Add software and timer interrupt support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5299 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
d3ae49bcf7
commit
9d92659858
64
hw/sun4u.c
64
hw/sun4u.c
@ -33,6 +33,15 @@
|
||||
#include "firmware_abi.h"
|
||||
#include "fw_cfg.h"
|
||||
|
||||
//#define DEBUG_IRQ
|
||||
|
||||
#ifdef DEBUG_IRQ
|
||||
#define DPRINTF(fmt, args...) \
|
||||
do { printf("CPUIRQ: " fmt , ##args); } while (0)
|
||||
#else
|
||||
#define DPRINTF(fmt, args...)
|
||||
#endif
|
||||
|
||||
#define KERNEL_LOAD_ADDR 0x00404000
|
||||
#define CMDLINE_ADDR 0x003ff000
|
||||
#define INITRD_LOAD_ADDR 0x00300000
|
||||
@ -47,6 +56,8 @@
|
||||
#define MAX_IDE_BUS 2
|
||||
#define BIOS_CFG_IOPORT 0x510
|
||||
|
||||
#define MAX_PILS 16
|
||||
|
||||
struct hwdef {
|
||||
const char * const default_cpu_model;
|
||||
uint16_t machine_id;
|
||||
@ -201,6 +212,50 @@ void irq_info(void)
|
||||
{
|
||||
}
|
||||
|
||||
void cpu_check_irqs(CPUState *env)
|
||||
{
|
||||
uint32_t pil = env->pil_in | (env->softint & ~SOFTINT_TIMER) |
|
||||
((env->softint & SOFTINT_TIMER) << 14);
|
||||
|
||||
if (pil && (env->interrupt_index == 0 ||
|
||||
(env->interrupt_index & ~15) == TT_EXTINT)) {
|
||||
unsigned int i;
|
||||
|
||||
for (i = 15; i > 0; i--) {
|
||||
if (pil & (1 << i)) {
|
||||
int old_interrupt = env->interrupt_index;
|
||||
|
||||
env->interrupt_index = TT_EXTINT | i;
|
||||
if (old_interrupt != env->interrupt_index) {
|
||||
DPRINTF("Set CPU IRQ %d\n", i);
|
||||
cpu_interrupt(env, CPU_INTERRUPT_HARD);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (!pil && (env->interrupt_index & ~15) == TT_EXTINT) {
|
||||
DPRINTF("Reset CPU IRQ %d\n", env->interrupt_index & 15);
|
||||
env->interrupt_index = 0;
|
||||
cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
|
||||
}
|
||||
}
|
||||
|
||||
static void cpu_set_irq(void *opaque, int irq, int level)
|
||||
{
|
||||
CPUState *env = opaque;
|
||||
|
||||
if (level) {
|
||||
DPRINTF("Raise CPU IRQ %d\n", irq);
|
||||
env->halted = 0;
|
||||
env->pil_in |= 1 << irq;
|
||||
cpu_check_irqs(env);
|
||||
} else {
|
||||
DPRINTF("Lower CPU IRQ %d\n", irq);
|
||||
env->pil_in &= ~(1 << irq);
|
||||
cpu_check_irqs(env);
|
||||
}
|
||||
}
|
||||
|
||||
void qemu_system_powerdown(void)
|
||||
{
|
||||
}
|
||||
@ -222,6 +277,7 @@ static void tick_irq(void *opaque)
|
||||
{
|
||||
CPUState *env = opaque;
|
||||
|
||||
env->softint |= SOFTINT_TIMER;
|
||||
cpu_interrupt(env, CPU_INTERRUPT_TIMER);
|
||||
}
|
||||
|
||||
@ -229,6 +285,7 @@ static void stick_irq(void *opaque)
|
||||
{
|
||||
CPUState *env = opaque;
|
||||
|
||||
env->softint |= SOFTINT_TIMER;
|
||||
cpu_interrupt(env, CPU_INTERRUPT_TIMER);
|
||||
}
|
||||
|
||||
@ -236,13 +293,10 @@ static void hstick_irq(void *opaque)
|
||||
{
|
||||
CPUState *env = opaque;
|
||||
|
||||
env->softint |= SOFTINT_TIMER;
|
||||
cpu_interrupt(env, CPU_INTERRUPT_TIMER);
|
||||
}
|
||||
|
||||
static void dummy_cpu_set_irq(void *opaque, int irq, int level)
|
||||
{
|
||||
}
|
||||
|
||||
static const int ide_iobase[2] = { 0x1f0, 0x170 };
|
||||
static const int ide_iobase2[2] = { 0x3f6, 0x376 };
|
||||
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,
|
||||
pci_nic_init(pci_bus, &nd_table[i], -1);
|
||||
}
|
||||
|
||||
irq = qemu_allocate_irqs(dummy_cpu_set_irq, NULL, 32);
|
||||
irq = qemu_allocate_irqs(cpu_set_irq, env, MAX_PILS);
|
||||
if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) {
|
||||
fprintf(stderr, "qemu: too many IDE bus\n");
|
||||
exit(1);
|
||||
|
@ -329,6 +329,8 @@ typedef struct CPUSPARCState {
|
||||
/* UA 2005 hyperprivileged registers */
|
||||
uint64_t hpstate, htstate[MAXTL_MAX], hintp, htba, hver, hstick_cmpr, ssr;
|
||||
void *hstick; // UA 2005
|
||||
uint32_t softint;
|
||||
#define SOFTINT_TIMER 1
|
||||
#endif
|
||||
sparc_def_t *def;
|
||||
} CPUSPARCState;
|
||||
|
@ -31,6 +31,9 @@ DEF_HELPER(target_ulong, helper_cas_asi, (target_ulong addr, \
|
||||
DEF_HELPER(target_ulong, helper_casx_asi, (target_ulong addr, \
|
||||
target_ulong val1, \
|
||||
target_ulong val2, uint32_t asi))
|
||||
DEF_HELPER(void, helper_set_softint, (uint64_t value))
|
||||
DEF_HELPER(void, helper_clear_softint, (uint64_t value))
|
||||
DEF_HELPER(void, helper_write_softint, (uint64_t value))
|
||||
DEF_HELPER(void, helper_tick_set_count, (void *opaque, uint64_t count))
|
||||
DEF_HELPER(uint64_t, helper_tick_get_count, (void *opaque))
|
||||
DEF_HELPER(void, helper_tick_set_limit, (void *opaque, uint64_t limit))
|
||||
|
@ -2671,6 +2671,21 @@ void helper_retry(void)
|
||||
env->tl--;
|
||||
env->tsptr = &env->ts[env->tl & MAXTL_MASK];
|
||||
}
|
||||
|
||||
void helper_set_softint(uint64_t value)
|
||||
{
|
||||
env->softint |= (uint32_t)value;
|
||||
}
|
||||
|
||||
void helper_clear_softint(uint64_t value)
|
||||
{
|
||||
env->softint &= (uint32_t)~value;
|
||||
}
|
||||
|
||||
void helper_write_softint(uint64_t value)
|
||||
{
|
||||
env->softint = (uint32_t)value;
|
||||
}
|
||||
#endif
|
||||
|
||||
void helper_flush(target_ulong addr)
|
||||
|
@ -49,7 +49,7 @@ static TCGv cpu_cond, cpu_src1, cpu_src2, cpu_dst, cpu_addr, cpu_val;
|
||||
#ifdef TARGET_SPARC64
|
||||
static TCGv cpu_xcc, cpu_asi, cpu_fprs, cpu_gsr;
|
||||
static TCGv cpu_tick_cmpr, cpu_stick_cmpr, cpu_hstick_cmpr;
|
||||
static TCGv cpu_hintp, cpu_htba, cpu_hver, cpu_ssr, cpu_ver;
|
||||
static TCGv cpu_hintp, cpu_htba, cpu_hver, cpu_ssr, cpu_ver, cpu_softint;
|
||||
#else
|
||||
static TCGv cpu_wim;
|
||||
#endif
|
||||
@ -2102,6 +2102,10 @@ static void disas_sparc_insn(DisasContext * dc)
|
||||
goto jmp_insn;
|
||||
gen_movl_TN_reg(rd, cpu_gsr);
|
||||
break;
|
||||
case 0x16: /* Softint */
|
||||
tcg_gen_ext_i32_tl(cpu_dst, cpu_softint);
|
||||
gen_movl_TN_reg(rd, cpu_dst);
|
||||
break;
|
||||
case 0x17: /* Tick compare */
|
||||
gen_movl_TN_reg(rd, cpu_tick_cmpr);
|
||||
break;
|
||||
@ -2126,7 +2130,6 @@ static void disas_sparc_insn(DisasContext * dc)
|
||||
case 0x12: /* Dispatch Control */
|
||||
case 0x14: /* Softint set, WO */
|
||||
case 0x15: /* Softint clear, WO */
|
||||
case 0x16: /* Softint write */
|
||||
#endif
|
||||
default:
|
||||
goto illegal_insn;
|
||||
@ -3233,6 +3236,27 @@ static void disas_sparc_insn(DisasContext * dc)
|
||||
goto jmp_insn;
|
||||
tcg_gen_xor_tl(cpu_gsr, cpu_src1, cpu_src2);
|
||||
break;
|
||||
case 0x14: /* Softint set */
|
||||
if (!supervisor(dc))
|
||||
goto illegal_insn;
|
||||
tcg_gen_xor_tl(cpu_tmp64, cpu_src1, cpu_src2);
|
||||
tcg_gen_helper_0_1(helper_set_softint,
|
||||
cpu_tmp64);
|
||||
break;
|
||||
case 0x15: /* Softint clear */
|
||||
if (!supervisor(dc))
|
||||
goto illegal_insn;
|
||||
tcg_gen_xor_tl(cpu_tmp64, cpu_src1, cpu_src2);
|
||||
tcg_gen_helper_0_1(helper_clear_softint,
|
||||
cpu_tmp64);
|
||||
break;
|
||||
case 0x16: /* Softint write */
|
||||
if (!supervisor(dc))
|
||||
goto illegal_insn;
|
||||
tcg_gen_xor_tl(cpu_tmp64, cpu_src1, cpu_src2);
|
||||
tcg_gen_helper_0_1(helper_write_softint,
|
||||
cpu_tmp64);
|
||||
break;
|
||||
case 0x17: /* Tick compare */
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
if (!supervisor(dc))
|
||||
@ -3292,9 +3316,6 @@ static void disas_sparc_insn(DisasContext * dc)
|
||||
case 0x11: /* Performance Instrumentation
|
||||
Counter */
|
||||
case 0x12: /* Dispatch Control */
|
||||
case 0x14: /* Softint set */
|
||||
case 0x15: /* Softint clear */
|
||||
case 0x16: /* Softint write */
|
||||
#endif
|
||||
default:
|
||||
goto illegal_insn;
|
||||
@ -4952,6 +4973,9 @@ void gen_intermediate_code_init(CPUSPARCState *env)
|
||||
offsetof(CPUState, ssr), "ssr");
|
||||
cpu_ver = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
|
||||
offsetof(CPUState, version), "ver");
|
||||
cpu_softint = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
|
||||
offsetof(CPUState, softint),
|
||||
"softint");
|
||||
#else
|
||||
cpu_wim = tcg_global_mem_new(TCG_TYPE_I32,
|
||||
TCG_AREG0, offsetof(CPUState, wim),
|
||||
|
Loading…
Reference in New Issue
Block a user