Commit 9d92659858e5dfad56148586f5d2351178223979
1 parent
d3ae49bc
Add software and timer interrupt support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5299 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
5 changed files
with
108 additions
and
10 deletions
hw/sun4u.c
@@ -33,6 +33,15 @@ | @@ -33,6 +33,15 @@ | ||
33 | #include "firmware_abi.h" | 33 | #include "firmware_abi.h" |
34 | #include "fw_cfg.h" | 34 | #include "fw_cfg.h" |
35 | 35 | ||
36 | +//#define DEBUG_IRQ | ||
37 | + | ||
38 | +#ifdef DEBUG_IRQ | ||
39 | +#define DPRINTF(fmt, args...) \ | ||
40 | + do { printf("CPUIRQ: " fmt , ##args); } while (0) | ||
41 | +#else | ||
42 | +#define DPRINTF(fmt, args...) | ||
43 | +#endif | ||
44 | + | ||
36 | #define KERNEL_LOAD_ADDR 0x00404000 | 45 | #define KERNEL_LOAD_ADDR 0x00404000 |
37 | #define CMDLINE_ADDR 0x003ff000 | 46 | #define CMDLINE_ADDR 0x003ff000 |
38 | #define INITRD_LOAD_ADDR 0x00300000 | 47 | #define INITRD_LOAD_ADDR 0x00300000 |
@@ -47,6 +56,8 @@ | @@ -47,6 +56,8 @@ | ||
47 | #define MAX_IDE_BUS 2 | 56 | #define MAX_IDE_BUS 2 |
48 | #define BIOS_CFG_IOPORT 0x510 | 57 | #define BIOS_CFG_IOPORT 0x510 |
49 | 58 | ||
59 | +#define MAX_PILS 16 | ||
60 | + | ||
50 | struct hwdef { | 61 | struct hwdef { |
51 | const char * const default_cpu_model; | 62 | const char * const default_cpu_model; |
52 | uint16_t machine_id; | 63 | uint16_t machine_id; |
@@ -201,6 +212,50 @@ void irq_info(void) | @@ -201,6 +212,50 @@ void irq_info(void) | ||
201 | { | 212 | { |
202 | } | 213 | } |
203 | 214 | ||
215 | +void cpu_check_irqs(CPUState *env) | ||
216 | +{ | ||
217 | + uint32_t pil = env->pil_in | (env->softint & ~SOFTINT_TIMER) | | ||
218 | + ((env->softint & SOFTINT_TIMER) << 14); | ||
219 | + | ||
220 | + if (pil && (env->interrupt_index == 0 || | ||
221 | + (env->interrupt_index & ~15) == TT_EXTINT)) { | ||
222 | + unsigned int i; | ||
223 | + | ||
224 | + for (i = 15; i > 0; i--) { | ||
225 | + if (pil & (1 << i)) { | ||
226 | + int old_interrupt = env->interrupt_index; | ||
227 | + | ||
228 | + env->interrupt_index = TT_EXTINT | i; | ||
229 | + if (old_interrupt != env->interrupt_index) { | ||
230 | + DPRINTF("Set CPU IRQ %d\n", i); | ||
231 | + cpu_interrupt(env, CPU_INTERRUPT_HARD); | ||
232 | + } | ||
233 | + break; | ||
234 | + } | ||
235 | + } | ||
236 | + } else if (!pil && (env->interrupt_index & ~15) == TT_EXTINT) { | ||
237 | + DPRINTF("Reset CPU IRQ %d\n", env->interrupt_index & 15); | ||
238 | + env->interrupt_index = 0; | ||
239 | + cpu_reset_interrupt(env, CPU_INTERRUPT_HARD); | ||
240 | + } | ||
241 | +} | ||
242 | + | ||
243 | +static void cpu_set_irq(void *opaque, int irq, int level) | ||
244 | +{ | ||
245 | + CPUState *env = opaque; | ||
246 | + | ||
247 | + if (level) { | ||
248 | + DPRINTF("Raise CPU IRQ %d\n", irq); | ||
249 | + env->halted = 0; | ||
250 | + env->pil_in |= 1 << irq; | ||
251 | + cpu_check_irqs(env); | ||
252 | + } else { | ||
253 | + DPRINTF("Lower CPU IRQ %d\n", irq); | ||
254 | + env->pil_in &= ~(1 << irq); | ||
255 | + cpu_check_irqs(env); | ||
256 | + } | ||
257 | +} | ||
258 | + | ||
204 | void qemu_system_powerdown(void) | 259 | void qemu_system_powerdown(void) |
205 | { | 260 | { |
206 | } | 261 | } |
@@ -222,6 +277,7 @@ static void tick_irq(void *opaque) | @@ -222,6 +277,7 @@ static void tick_irq(void *opaque) | ||
222 | { | 277 | { |
223 | CPUState *env = opaque; | 278 | CPUState *env = opaque; |
224 | 279 | ||
280 | + env->softint |= SOFTINT_TIMER; | ||
225 | cpu_interrupt(env, CPU_INTERRUPT_TIMER); | 281 | cpu_interrupt(env, CPU_INTERRUPT_TIMER); |
226 | } | 282 | } |
227 | 283 | ||
@@ -229,6 +285,7 @@ static void stick_irq(void *opaque) | @@ -229,6 +285,7 @@ static void stick_irq(void *opaque) | ||
229 | { | 285 | { |
230 | CPUState *env = opaque; | 286 | CPUState *env = opaque; |
231 | 287 | ||
288 | + env->softint |= SOFTINT_TIMER; | ||
232 | cpu_interrupt(env, CPU_INTERRUPT_TIMER); | 289 | cpu_interrupt(env, CPU_INTERRUPT_TIMER); |
233 | } | 290 | } |
234 | 291 | ||
@@ -236,13 +293,10 @@ static void hstick_irq(void *opaque) | @@ -236,13 +293,10 @@ static void hstick_irq(void *opaque) | ||
236 | { | 293 | { |
237 | CPUState *env = opaque; | 294 | CPUState *env = opaque; |
238 | 295 | ||
296 | + env->softint |= SOFTINT_TIMER; | ||
239 | cpu_interrupt(env, CPU_INTERRUPT_TIMER); | 297 | cpu_interrupt(env, CPU_INTERRUPT_TIMER); |
240 | } | 298 | } |
241 | 299 | ||
242 | -static void dummy_cpu_set_irq(void *opaque, int irq, int level) | ||
243 | -{ | ||
244 | -} | ||
245 | - | ||
246 | static const int ide_iobase[2] = { 0x1f0, 0x170 }; | 300 | static const int ide_iobase[2] = { 0x1f0, 0x170 }; |
247 | static const int ide_iobase2[2] = { 0x3f6, 0x376 }; | 301 | static const int ide_iobase2[2] = { 0x3f6, 0x376 }; |
248 | static const int ide_irq[2] = { 14, 15 }; | 302 | static const int ide_irq[2] = { 14, 15 }; |
@@ -383,7 +437,7 @@ static void sun4uv_init(ram_addr_t RAM_size, int vga_ram_size, | @@ -383,7 +437,7 @@ static void sun4uv_init(ram_addr_t RAM_size, int vga_ram_size, | ||
383 | pci_nic_init(pci_bus, &nd_table[i], -1); | 437 | pci_nic_init(pci_bus, &nd_table[i], -1); |
384 | } | 438 | } |
385 | 439 | ||
386 | - irq = qemu_allocate_irqs(dummy_cpu_set_irq, NULL, 32); | 440 | + irq = qemu_allocate_irqs(cpu_set_irq, env, MAX_PILS); |
387 | if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) { | 441 | if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) { |
388 | fprintf(stderr, "qemu: too many IDE bus\n"); | 442 | fprintf(stderr, "qemu: too many IDE bus\n"); |
389 | exit(1); | 443 | exit(1); |
target-sparc/cpu.h
@@ -329,6 +329,8 @@ typedef struct CPUSPARCState { | @@ -329,6 +329,8 @@ typedef struct CPUSPARCState { | ||
329 | /* UA 2005 hyperprivileged registers */ | 329 | /* UA 2005 hyperprivileged registers */ |
330 | uint64_t hpstate, htstate[MAXTL_MAX], hintp, htba, hver, hstick_cmpr, ssr; | 330 | uint64_t hpstate, htstate[MAXTL_MAX], hintp, htba, hver, hstick_cmpr, ssr; |
331 | void *hstick; // UA 2005 | 331 | void *hstick; // UA 2005 |
332 | + uint32_t softint; | ||
333 | +#define SOFTINT_TIMER 1 | ||
332 | #endif | 334 | #endif |
333 | sparc_def_t *def; | 335 | sparc_def_t *def; |
334 | } CPUSPARCState; | 336 | } CPUSPARCState; |
target-sparc/helper.h
@@ -31,6 +31,9 @@ DEF_HELPER(target_ulong, helper_cas_asi, (target_ulong addr, \ | @@ -31,6 +31,9 @@ DEF_HELPER(target_ulong, helper_cas_asi, (target_ulong addr, \ | ||
31 | DEF_HELPER(target_ulong, helper_casx_asi, (target_ulong addr, \ | 31 | DEF_HELPER(target_ulong, helper_casx_asi, (target_ulong addr, \ |
32 | target_ulong val1, \ | 32 | target_ulong val1, \ |
33 | target_ulong val2, uint32_t asi)) | 33 | target_ulong val2, uint32_t asi)) |
34 | +DEF_HELPER(void, helper_set_softint, (uint64_t value)) | ||
35 | +DEF_HELPER(void, helper_clear_softint, (uint64_t value)) | ||
36 | +DEF_HELPER(void, helper_write_softint, (uint64_t value)) | ||
34 | DEF_HELPER(void, helper_tick_set_count, (void *opaque, uint64_t count)) | 37 | DEF_HELPER(void, helper_tick_set_count, (void *opaque, uint64_t count)) |
35 | DEF_HELPER(uint64_t, helper_tick_get_count, (void *opaque)) | 38 | DEF_HELPER(uint64_t, helper_tick_get_count, (void *opaque)) |
36 | DEF_HELPER(void, helper_tick_set_limit, (void *opaque, uint64_t limit)) | 39 | DEF_HELPER(void, helper_tick_set_limit, (void *opaque, uint64_t limit)) |
target-sparc/op_helper.c
@@ -2671,6 +2671,21 @@ void helper_retry(void) | @@ -2671,6 +2671,21 @@ void helper_retry(void) | ||
2671 | env->tl--; | 2671 | env->tl--; |
2672 | env->tsptr = &env->ts[env->tl & MAXTL_MASK]; | 2672 | env->tsptr = &env->ts[env->tl & MAXTL_MASK]; |
2673 | } | 2673 | } |
2674 | + | ||
2675 | +void helper_set_softint(uint64_t value) | ||
2676 | +{ | ||
2677 | + env->softint |= (uint32_t)value; | ||
2678 | +} | ||
2679 | + | ||
2680 | +void helper_clear_softint(uint64_t value) | ||
2681 | +{ | ||
2682 | + env->softint &= (uint32_t)~value; | ||
2683 | +} | ||
2684 | + | ||
2685 | +void helper_write_softint(uint64_t value) | ||
2686 | +{ | ||
2687 | + env->softint = (uint32_t)value; | ||
2688 | +} | ||
2674 | #endif | 2689 | #endif |
2675 | 2690 | ||
2676 | void helper_flush(target_ulong addr) | 2691 | void helper_flush(target_ulong addr) |
target-sparc/translate.c
@@ -49,7 +49,7 @@ static TCGv cpu_cond, cpu_src1, cpu_src2, cpu_dst, cpu_addr, cpu_val; | @@ -49,7 +49,7 @@ static TCGv cpu_cond, cpu_src1, cpu_src2, cpu_dst, cpu_addr, cpu_val; | ||
49 | #ifdef TARGET_SPARC64 | 49 | #ifdef TARGET_SPARC64 |
50 | static TCGv cpu_xcc, cpu_asi, cpu_fprs, cpu_gsr; | 50 | static TCGv cpu_xcc, cpu_asi, cpu_fprs, cpu_gsr; |
51 | static TCGv cpu_tick_cmpr, cpu_stick_cmpr, cpu_hstick_cmpr; | 51 | static TCGv cpu_tick_cmpr, cpu_stick_cmpr, cpu_hstick_cmpr; |
52 | -static TCGv cpu_hintp, cpu_htba, cpu_hver, cpu_ssr, cpu_ver; | 52 | +static TCGv cpu_hintp, cpu_htba, cpu_hver, cpu_ssr, cpu_ver, cpu_softint; |
53 | #else | 53 | #else |
54 | static TCGv cpu_wim; | 54 | static TCGv cpu_wim; |
55 | #endif | 55 | #endif |
@@ -2102,6 +2102,10 @@ static void disas_sparc_insn(DisasContext * dc) | @@ -2102,6 +2102,10 @@ static void disas_sparc_insn(DisasContext * dc) | ||
2102 | goto jmp_insn; | 2102 | goto jmp_insn; |
2103 | gen_movl_TN_reg(rd, cpu_gsr); | 2103 | gen_movl_TN_reg(rd, cpu_gsr); |
2104 | break; | 2104 | break; |
2105 | + case 0x16: /* Softint */ | ||
2106 | + tcg_gen_ext_i32_tl(cpu_dst, cpu_softint); | ||
2107 | + gen_movl_TN_reg(rd, cpu_dst); | ||
2108 | + break; | ||
2105 | case 0x17: /* Tick compare */ | 2109 | case 0x17: /* Tick compare */ |
2106 | gen_movl_TN_reg(rd, cpu_tick_cmpr); | 2110 | gen_movl_TN_reg(rd, cpu_tick_cmpr); |
2107 | break; | 2111 | break; |
@@ -2126,7 +2130,6 @@ static void disas_sparc_insn(DisasContext * dc) | @@ -2126,7 +2130,6 @@ static void disas_sparc_insn(DisasContext * dc) | ||
2126 | case 0x12: /* Dispatch Control */ | 2130 | case 0x12: /* Dispatch Control */ |
2127 | case 0x14: /* Softint set, WO */ | 2131 | case 0x14: /* Softint set, WO */ |
2128 | case 0x15: /* Softint clear, WO */ | 2132 | case 0x15: /* Softint clear, WO */ |
2129 | - case 0x16: /* Softint write */ | ||
2130 | #endif | 2133 | #endif |
2131 | default: | 2134 | default: |
2132 | goto illegal_insn; | 2135 | goto illegal_insn; |
@@ -3233,6 +3236,27 @@ static void disas_sparc_insn(DisasContext * dc) | @@ -3233,6 +3236,27 @@ static void disas_sparc_insn(DisasContext * dc) | ||
3233 | goto jmp_insn; | 3236 | goto jmp_insn; |
3234 | tcg_gen_xor_tl(cpu_gsr, cpu_src1, cpu_src2); | 3237 | tcg_gen_xor_tl(cpu_gsr, cpu_src1, cpu_src2); |
3235 | break; | 3238 | break; |
3239 | + case 0x14: /* Softint set */ | ||
3240 | + if (!supervisor(dc)) | ||
3241 | + goto illegal_insn; | ||
3242 | + tcg_gen_xor_tl(cpu_tmp64, cpu_src1, cpu_src2); | ||
3243 | + tcg_gen_helper_0_1(helper_set_softint, | ||
3244 | + cpu_tmp64); | ||
3245 | + break; | ||
3246 | + case 0x15: /* Softint clear */ | ||
3247 | + if (!supervisor(dc)) | ||
3248 | + goto illegal_insn; | ||
3249 | + tcg_gen_xor_tl(cpu_tmp64, cpu_src1, cpu_src2); | ||
3250 | + tcg_gen_helper_0_1(helper_clear_softint, | ||
3251 | + cpu_tmp64); | ||
3252 | + break; | ||
3253 | + case 0x16: /* Softint write */ | ||
3254 | + if (!supervisor(dc)) | ||
3255 | + goto illegal_insn; | ||
3256 | + tcg_gen_xor_tl(cpu_tmp64, cpu_src1, cpu_src2); | ||
3257 | + tcg_gen_helper_0_1(helper_write_softint, | ||
3258 | + cpu_tmp64); | ||
3259 | + break; | ||
3236 | case 0x17: /* Tick compare */ | 3260 | case 0x17: /* Tick compare */ |
3237 | #if !defined(CONFIG_USER_ONLY) | 3261 | #if !defined(CONFIG_USER_ONLY) |
3238 | if (!supervisor(dc)) | 3262 | if (!supervisor(dc)) |
@@ -3292,9 +3316,6 @@ static void disas_sparc_insn(DisasContext * dc) | @@ -3292,9 +3316,6 @@ static void disas_sparc_insn(DisasContext * dc) | ||
3292 | case 0x11: /* Performance Instrumentation | 3316 | case 0x11: /* Performance Instrumentation |
3293 | Counter */ | 3317 | Counter */ |
3294 | case 0x12: /* Dispatch Control */ | 3318 | case 0x12: /* Dispatch Control */ |
3295 | - case 0x14: /* Softint set */ | ||
3296 | - case 0x15: /* Softint clear */ | ||
3297 | - case 0x16: /* Softint write */ | ||
3298 | #endif | 3319 | #endif |
3299 | default: | 3320 | default: |
3300 | goto illegal_insn; | 3321 | goto illegal_insn; |
@@ -4952,6 +4973,9 @@ void gen_intermediate_code_init(CPUSPARCState *env) | @@ -4952,6 +4973,9 @@ void gen_intermediate_code_init(CPUSPARCState *env) | ||
4952 | offsetof(CPUState, ssr), "ssr"); | 4973 | offsetof(CPUState, ssr), "ssr"); |
4953 | cpu_ver = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0, | 4974 | cpu_ver = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0, |
4954 | offsetof(CPUState, version), "ver"); | 4975 | offsetof(CPUState, version), "ver"); |
4976 | + cpu_softint = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0, | ||
4977 | + offsetof(CPUState, softint), | ||
4978 | + "softint"); | ||
4955 | #else | 4979 | #else |
4956 | cpu_wim = tcg_global_mem_new(TCG_TYPE_I32, | 4980 | cpu_wim = tcg_global_mem_new(TCG_TYPE_I32, |
4957 | TCG_AREG0, offsetof(CPUState, wim), | 4981 | TCG_AREG0, offsetof(CPUState, wim), |