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), | ... | ... |