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 | 33 | #include "firmware_abi.h" |
34 | 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 | 45 | #define KERNEL_LOAD_ADDR 0x00404000 |
37 | 46 | #define CMDLINE_ADDR 0x003ff000 |
38 | 47 | #define INITRD_LOAD_ADDR 0x00300000 |
... | ... | @@ -47,6 +56,8 @@ |
47 | 56 | #define MAX_IDE_BUS 2 |
48 | 57 | #define BIOS_CFG_IOPORT 0x510 |
49 | 58 | |
59 | +#define MAX_PILS 16 | |
60 | + | |
50 | 61 | struct hwdef { |
51 | 62 | const char * const default_cpu_model; |
52 | 63 | uint16_t machine_id; |
... | ... | @@ -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 | 259 | void qemu_system_powerdown(void) |
205 | 260 | { |
206 | 261 | } |
... | ... | @@ -222,6 +277,7 @@ static void tick_irq(void *opaque) |
222 | 277 | { |
223 | 278 | CPUState *env = opaque; |
224 | 279 | |
280 | + env->softint |= SOFTINT_TIMER; | |
225 | 281 | cpu_interrupt(env, CPU_INTERRUPT_TIMER); |
226 | 282 | } |
227 | 283 | |
... | ... | @@ -229,6 +285,7 @@ static void stick_irq(void *opaque) |
229 | 285 | { |
230 | 286 | CPUState *env = opaque; |
231 | 287 | |
288 | + env->softint |= SOFTINT_TIMER; | |
232 | 289 | cpu_interrupt(env, CPU_INTERRUPT_TIMER); |
233 | 290 | } |
234 | 291 | |
... | ... | @@ -236,13 +293,10 @@ static void hstick_irq(void *opaque) |
236 | 293 | { |
237 | 294 | CPUState *env = opaque; |
238 | 295 | |
296 | + env->softint |= SOFTINT_TIMER; | |
239 | 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 | 300 | static const int ide_iobase[2] = { 0x1f0, 0x170 }; |
247 | 301 | static const int ide_iobase2[2] = { 0x3f6, 0x376 }; |
248 | 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 | 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 | 441 | if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) { |
388 | 442 | fprintf(stderr, "qemu: too many IDE bus\n"); |
389 | 443 | exit(1); | ... | ... |
target-sparc/cpu.h
... | ... | @@ -329,6 +329,8 @@ typedef struct CPUSPARCState { |
329 | 329 | /* UA 2005 hyperprivileged registers */ |
330 | 330 | uint64_t hpstate, htstate[MAXTL_MAX], hintp, htba, hver, hstick_cmpr, ssr; |
331 | 331 | void *hstick; // UA 2005 |
332 | + uint32_t softint; | |
333 | +#define SOFTINT_TIMER 1 | |
332 | 334 | #endif |
333 | 335 | sparc_def_t *def; |
334 | 336 | } CPUSPARCState; | ... | ... |
target-sparc/helper.h
... | ... | @@ -31,6 +31,9 @@ DEF_HELPER(target_ulong, helper_cas_asi, (target_ulong addr, \ |
31 | 31 | DEF_HELPER(target_ulong, helper_casx_asi, (target_ulong addr, \ |
32 | 32 | target_ulong val1, \ |
33 | 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 | 37 | DEF_HELPER(void, helper_tick_set_count, (void *opaque, uint64_t count)) |
35 | 38 | DEF_HELPER(uint64_t, helper_tick_get_count, (void *opaque)) |
36 | 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 | 2671 | env->tl--; |
2672 | 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 | 2689 | #endif |
2675 | 2690 | |
2676 | 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 | 49 | #ifdef TARGET_SPARC64 |
50 | 50 | static TCGv cpu_xcc, cpu_asi, cpu_fprs, cpu_gsr; |
51 | 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 | 53 | #else |
54 | 54 | static TCGv cpu_wim; |
55 | 55 | #endif |
... | ... | @@ -2102,6 +2102,10 @@ static void disas_sparc_insn(DisasContext * dc) |
2102 | 2102 | goto jmp_insn; |
2103 | 2103 | gen_movl_TN_reg(rd, cpu_gsr); |
2104 | 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 | 2109 | case 0x17: /* Tick compare */ |
2106 | 2110 | gen_movl_TN_reg(rd, cpu_tick_cmpr); |
2107 | 2111 | break; |
... | ... | @@ -2126,7 +2130,6 @@ static void disas_sparc_insn(DisasContext * dc) |
2126 | 2130 | case 0x12: /* Dispatch Control */ |
2127 | 2131 | case 0x14: /* Softint set, WO */ |
2128 | 2132 | case 0x15: /* Softint clear, WO */ |
2129 | - case 0x16: /* Softint write */ | |
2130 | 2133 | #endif |
2131 | 2134 | default: |
2132 | 2135 | goto illegal_insn; |
... | ... | @@ -3233,6 +3236,27 @@ static void disas_sparc_insn(DisasContext * dc) |
3233 | 3236 | goto jmp_insn; |
3234 | 3237 | tcg_gen_xor_tl(cpu_gsr, cpu_src1, cpu_src2); |
3235 | 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 | 3260 | case 0x17: /* Tick compare */ |
3237 | 3261 | #if !defined(CONFIG_USER_ONLY) |
3238 | 3262 | if (!supervisor(dc)) |
... | ... | @@ -3292,9 +3316,6 @@ static void disas_sparc_insn(DisasContext * dc) |
3292 | 3316 | case 0x11: /* Performance Instrumentation |
3293 | 3317 | Counter */ |
3294 | 3318 | case 0x12: /* Dispatch Control */ |
3295 | - case 0x14: /* Softint set */ | |
3296 | - case 0x15: /* Softint clear */ | |
3297 | - case 0x16: /* Softint write */ | |
3298 | 3319 | #endif |
3299 | 3320 | default: |
3300 | 3321 | goto illegal_insn; |
... | ... | @@ -4952,6 +4973,9 @@ void gen_intermediate_code_init(CPUSPARCState *env) |
4952 | 4973 | offsetof(CPUState, ssr), "ssr"); |
4953 | 4974 | cpu_ver = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0, |
4954 | 4975 | offsetof(CPUState, version), "ver"); |
4976 | + cpu_softint = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0, | |
4977 | + offsetof(CPUState, softint), | |
4978 | + "softint"); | |
4955 | 4979 | #else |
4956 | 4980 | cpu_wim = tcg_global_mem_new(TCG_TYPE_I32, |
4957 | 4981 | TCG_AREG0, offsetof(CPUState, wim), | ... | ... |