Commit 9d92659858e5dfad56148586f5d2351178223979

Authored by blueswir1
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
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),