Ejemplo n.º 1
0
void cpu_check_irqs(CPUSPARCState *env)
{
    CPUState *cs;
    uint32_t pil = env->pil_in |
                  (env->softint & ~(SOFTINT_TIMER | SOFTINT_STIMER));

    /* TT_IVEC has a higher priority (16) than TT_EXTINT (31..17) */
    if (env->ivec_status & 0x20) {
        return;
    }
    cs = CPU(sparc_env_get_cpu(env));
    /* check if TM or SM in SOFTINT are set
       setting these also causes interrupt 14 */
    if (env->softint & (SOFTINT_TIMER | SOFTINT_STIMER)) {
        pil |= 1 << 14;
    }

    /* The bit corresponding to psrpil is (1<< psrpil), the next bit
       is (2 << psrpil). */
    if (pil < (2 << env->psrpil)){
        if (cs->interrupt_request & CPU_INTERRUPT_HARD) {
            CPUIRQ_DPRINTF("Reset CPU IRQ (current interrupt %x)\n",
                           env->interrupt_index);
            env->interrupt_index = 0;
            cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
        }
        return;
    }

    if (cpu_interrupts_enabled(env)) {

        unsigned int i;

        for (i = 15; i > env->psrpil; i--) {
            if (pil & (1 << i)) {
                int old_interrupt = env->interrupt_index;
                int new_interrupt = TT_EXTINT | i;

                if (unlikely(env->tl > 0 && cpu_tsptr(env)->tt > new_interrupt
                  && ((cpu_tsptr(env)->tt & 0x1f0) == TT_EXTINT))) {
                    CPUIRQ_DPRINTF("Not setting CPU IRQ: TL=%d "
                                   "current %x >= pending %x\n",
                                   env->tl, cpu_tsptr(env)->tt, new_interrupt);
                } else if (old_interrupt != new_interrupt) {
                    env->interrupt_index = new_interrupt;
                    CPUIRQ_DPRINTF("Set CPU IRQ %d old=%x new=%x\n", i,
                                   old_interrupt, new_interrupt);
                    cpu_interrupt(cs, CPU_INTERRUPT_HARD);
                }
                break;
            }
        }
    } else if (cs->interrupt_request & CPU_INTERRUPT_HARD) {
        CPUIRQ_DPRINTF("Interrupts disabled, pil=%08x pil_in=%08x softint=%08x "
                       "current interrupt %x\n",
                       pil, env->pil_in, env->softint, env->interrupt_index);
        env->interrupt_index = 0;
        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
    }
}
Ejemplo n.º 2
0
static void cpu_set_ivec_irq(void *opaque, int irq, int level)
{
    SPARCCPU *cpu = opaque;
    CPUSPARCState *env = &cpu->env;
    CPUState *cs;

    if (level) {
        if (!(env->ivec_status & 0x20)) {
            CPUIRQ_DPRINTF("Raise IVEC IRQ %d\n", irq);
            cs = CPU(cpu);
            cs->halted = 0;
            env->interrupt_index = TT_IVEC;
            env->ivec_status |= 0x20;
            env->ivec_data[0] = (0x1f << 6) | irq;
            env->ivec_data[1] = 0;
            env->ivec_data[2] = 0;
            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
        }
    } else {
        if (env->ivec_status & 0x20) {
            CPUIRQ_DPRINTF("Lower IVEC IRQ %d\n", irq);
            cs = CPU(cpu);
            env->ivec_status &= ~0x20;
            cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
        }
    }
}
Ejemplo n.º 3
0
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) {
                    CPUIRQ_DPRINTF("Set CPU IRQ %d\n", i);
                    cpu_interrupt(env, CPU_INTERRUPT_HARD);
                }
                break;
            }
        }
    } else if (!pil && (env->interrupt_index & ~15) == TT_EXTINT) {
        CPUIRQ_DPRINTF("Reset CPU IRQ %d\n", env->interrupt_index & 15);
        env->interrupt_index = 0;
        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
    }
}
Ejemplo n.º 4
0
Archivo: sun4m.c Proyecto: Fantu/qemu
void cpu_check_irqs(CPUSPARCState *env)
{
    CPUState *cs;

    if (env->pil_in && (env->interrupt_index == 0 ||
                        (env->interrupt_index & ~15) == TT_EXTINT)) {
        unsigned int i;

        for (i = 15; i > 0; i--) {
            if (env->pil_in & (1 << i)) {
                int old_interrupt = env->interrupt_index;

                env->interrupt_index = TT_EXTINT | i;
                if (old_interrupt != env->interrupt_index) {
                    cs = CPU(sparc_env_get_cpu(env));
                    trace_sun4m_cpu_interrupt(i);
                    cpu_interrupt(cs, CPU_INTERRUPT_HARD);
                }
                break;
            }
        }
    } else if (!env->pil_in && (env->interrupt_index & ~15) == TT_EXTINT) {
        cs = CPU(sparc_env_get_cpu(env));
        trace_sun4m_cpu_reset_interrupt(env->interrupt_index & 15);
        env->interrupt_index = 0;
        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
    }
}
Ejemplo n.º 5
0
static void leon3_set_pil_in(void *opaque, uint32_t pil_in)
{
    CPUSPARCState *env = (CPUSPARCState *)opaque;

    assert(env != NULL);

    env->pil_in = pil_in;

    if (env->pil_in && (env->interrupt_index == 0 ||
                        (env->interrupt_index & ~15) == TT_EXTINT)) {
        unsigned int i;

        for (i = 15; i > 0; i--) {
            if (env->pil_in & (1 << i)) {
                int old_interrupt = env->interrupt_index;

                env->interrupt_index = TT_EXTINT | i;
                if (old_interrupt != env->interrupt_index) {
                    trace_leon3_set_irq(i);
                    cpu_interrupt(env, CPU_INTERRUPT_HARD);
                }
                break;
            }
        }
    } else if (!env->pil_in && (env->interrupt_index & ~15) == TT_EXTINT) {
        trace_leon3_reset_irq(env->interrupt_index & 15);
        env->interrupt_index = 0;
        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
    }
}
Ejemplo n.º 6
0
static void cpu_riscv_irq_request(void *opaque, int irq, int level)
{
    /* These are not the same irq numbers visible to the emulated processor. */
    RISCVCPU *cpu = opaque;
    CPURISCVState *env = &cpu->env;
    CPUState *cs = CPU(cpu);

    /* current irqs:
       4: Host Interrupt. mfromhost should have a nonzero value
       3: Machine Timer. MIP_MTIP should have already been set
       2, 1, 0: Interrupts triggered by the CPU. At least one of
       MIP_STIP, MIP_SSIP, MIP_MSIP should already be set */
    if (unlikely(!(irq < 5 && irq >= 0))) {
        printf("IRQNO: %d\n", irq);
        fprintf(stderr, "Unused IRQ was raised.\n");
        exit(1);
    }

    if (level) {
        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
    } else {
        if (!env->mip && !env->mfromhost) {
            /* no interrupts pending, no host interrupt for HTIF, reset */
            cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
        }
    }
}
Ejemplo n.º 7
0
void sparc64_cpu_set_ivec_irq(void *opaque, int irq, int level)
{
    SPARCCPU *cpu = opaque;
    CPUSPARCState *env = &cpu->env;
    CPUState *cs;

    if (level) {
        if (!(env->ivec_status & 0x20)) {
            trace_sparc64_cpu_ivec_raise_irq(irq);
            cs = CPU(cpu);
            cs->halted = 0;
            env->interrupt_index = TT_IVEC;
            env->ivec_status |= 0x20;
            env->ivec_data[0] = (0x1f << 6) | irq;
            env->ivec_data[1] = 0;
            env->ivec_data[2] = 0;
            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
        }
    } else {
        if (env->ivec_status & 0x20) {
            trace_sparc64_cpu_ivec_lower_irq(irq);
            cs = CPU(cpu);
            env->ivec_status &= ~0x20;
            cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
        }
    }
}
Ejemplo n.º 8
0
static void cpu_mips_irq_request(void *opaque, int irq, int level)
{
    MIPSCPU *cpu = opaque;
    CPUMIPSState *env = &cpu->env;
    CPUState *cs = CPU(cpu);

    if (irq < 0 || irq > 7)
        return;

    if (level) {
        env->CP0_Cause |= 1 << (irq + CP0Ca_IP);

        if (kvm_enabled() && irq == 2) {
            kvm_mips_set_interrupt(cpu, irq, level);
        }

    } else {
        env->CP0_Cause &= ~(1 << (irq + CP0Ca_IP));
        if (kvm_enabled() && irq == 2) {
            kvm_mips_set_interrupt(cpu, irq, level);
        }
    }

    if (env->CP0_Cause & CP0Ca_IP_mask) {
        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
    } else {
        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
    }
}
Ejemplo n.º 9
0
static void cpu_irq_handler(void *opaque, int irq, int level)
{
    CPULM32State *env = opaque;

    if (level) {
        cpu_interrupt(env, CPU_INTERRUPT_HARD);
    } else {
        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
    }
}
Ejemplo n.º 10
0
void sh_intc_toggle_source(struct intc_source *source,
			   int enable_adj, int assert_adj)
{
    int enable_changed = 0;
    int pending_changed = 0;
    int old_pending;

    if ((source->enable_count == source->enable_max) && (enable_adj == -1))
        enable_changed = -1;

    source->enable_count += enable_adj;

    if (source->enable_count == source->enable_max)
        enable_changed = 1;

    source->asserted += assert_adj;

    old_pending = source->pending;
    source->pending = source->asserted &&
      (source->enable_count == source->enable_max);

    if (old_pending != source->pending)
        pending_changed = 1;

    if (pending_changed) {
        CPUState *cpu = CPU(sh_env_get_cpu(first_cpu));
        if (source->pending) {
            source->parent->pending++;
            if (source->parent->pending == 1) {
                cpu_interrupt(cpu, CPU_INTERRUPT_HARD);
            }
        } else {
            source->parent->pending--;
            if (source->parent->pending == 0) {
                cpu_reset_interrupt(cpu, CPU_INTERRUPT_HARD);
            }
	}
    }

  if (enable_changed || assert_adj || pending_changed) {
#ifdef DEBUG_INTC_SOURCES
            printf("sh_intc: (%d/%d/%d/%d) interrupt source 0x%x %s%s%s\n",
		   source->parent->pending,
		   source->asserted,
		   source->enable_count,
		   source->enable_max,
		   source->vect,
		   source->asserted ? "asserted " :
		   assert_adj ? "deasserted" : "",
		   enable_changed == 1 ? "enabled " :
		   enable_changed == -1 ? "disabled " : "",
		   source->pending ? "pending" : "");
#endif
  }
}
Ejemplo n.º 11
0
/* Called when one of DRIR or DIM changes.  */
static void cpu_irq_change(CPUState *env, uint64_t req)
{
    /* If there are any non-masked interrupts, tell the cpu.  */
    if (env) {
        if (req) {
            cpu_interrupt(env, CPU_INTERRUPT_HARD);
        } else {
            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
        }
    }
}
Ejemplo n.º 12
0
static void cpu_irq_handler(void *opaque, int irq, int level)
{
    LM32CPU *cpu = opaque;
    CPUState *cs = CPU(cpu);

    if (level) {
        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
    } else {
        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
    }
}
Ejemplo n.º 13
0
static void puv3_intc_cpu_handler(void *opaque, int irq, int level)
{
    CPUUniCore32State *env = opaque;

    assert(irq == 0);
    if (level) {
        cpu_interrupt(env, CPU_INTERRUPT_HARD);
    } else {
        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
    }
}
Ejemplo n.º 14
0
/* Called when one of DRIR or DIM changes.  */
static void cpu_irq_change(AlphaCPU *cpu, uint64_t req)
{
    /* If there are any non-masked interrupts, tell the cpu.  */
    if (cpu != NULL) {
        CPUState *cs = CPU(cpu);
        if (req) {
            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
        } else {
            cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
        }
    }
}
Ejemplo n.º 15
0
Archivo: puv3.c Proyecto: 8tab/qemu
static void puv3_intc_cpu_handler(void *opaque, int irq, int level)
{
    UniCore32CPU *cpu = opaque;
    CPUState *cs = CPU(cpu);

    assert(irq == 0);
    if (level) {
        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
    } else {
        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
    }
}
Ejemplo n.º 16
0
static void microblaze_cpu_set_irq(void *opaque, int irq, int level)
{
    MicroBlazeCPU *cpu = opaque;
    CPUState *cs = CPU(cpu);
    int type = irq ? CPU_INTERRUPT_NMI : CPU_INTERRUPT_HARD;

    if (level) {
        cpu_interrupt(cs, type);
    } else {
        cpu_reset_interrupt(cs, type);
    }
}
Ejemplo n.º 17
0
static void arm_pic_cpu_handler(void *opaque, int irq, int level)
{
    arm_pic_cpu_state *s = (arm_pic_cpu_state *)opaque;
    switch (irq) {
    case ARM_PIC_CPU_IRQ:
        if (level)
            cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
        else
            cpu_reset_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
        break;
    case ARM_PIC_CPU_FIQ:
        if (level)
            cpu_interrupt(s->cpu_env, CPU_INTERRUPT_FIQ);
        else
            cpu_reset_interrupt(s->cpu_env, CPU_INTERRUPT_FIQ);
        break;
    default:
        cpu_abort(s->cpu_env, "arm_pic_cpu_handler: Bad interrput line %d\n",
                  irq);
    }
}
Ejemplo n.º 18
0
/* Raise IRQ to CPU if necessary. It must be called every time the active
   IRQ may change */
void cpu_mips_update_irq(CPUState *env)
{
    if ((env->CP0_Status & (1 << CP0St_IE)) &&
        !(env->CP0_Status & (1 << CP0St_EXL)) &&
        !(env->CP0_Status & (1 << CP0St_ERL)) &&
        !(env->hflags & MIPS_HFLAG_DM)) {
        if ((env->CP0_Status & env->CP0_Cause & CP0Ca_IP_mask) &&
            !(env->interrupt_request & CPU_INTERRUPT_HARD)) {
            cpu_interrupt(env, CPU_INTERRUPT_HARD);
	}
    } else
        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
}
Ejemplo n.º 19
0
void cpu_check_irqs(CPUState *env)
{
    uint32_t pil = env->pil_in |
                  (env->softint & ~(SOFTINT_TIMER | SOFTINT_STIMER));

    /* check if TM or SM in SOFTINT are set
       setting these also causes interrupt 14 */
    if (env->softint & (SOFTINT_TIMER | SOFTINT_STIMER)) {
        pil |= 1 << 14;
    }

    if (!pil) {
        if (env->interrupt_request & CPU_INTERRUPT_HARD) {
            CPUIRQ_DPRINTF("Reset CPU IRQ (current interrupt %x)\n",
                           env->interrupt_index);
            env->interrupt_index = 0;
            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
        }
        return;
    }

    if (cpu_interrupts_enabled(env)) {

        unsigned int i;

        for (i = 15; i > env->psrpil; i--) {
            if (pil & (1 << i)) {
                int old_interrupt = env->interrupt_index;
                int new_interrupt = TT_EXTINT | i;

                if (env->tl > 0 && cpu_tsptr(env)->tt > new_interrupt) {
                    CPUIRQ_DPRINTF("Not setting CPU IRQ: TL=%d "
                                   "current %x >= pending %x\n",
                                   env->tl, cpu_tsptr(env)->tt, new_interrupt);
                } else if (old_interrupt != new_interrupt) {
                    env->interrupt_index = new_interrupt;
                    CPUIRQ_DPRINTF("Set CPU IRQ %d old=%x new=%x\n", i,
                                   old_interrupt, new_interrupt);
                    cpu_interrupt(env, CPU_INTERRUPT_HARD);
                }
                break;
            }
        }
    } else {
        CPUIRQ_DPRINTF("Interrupts disabled, pil=%08x pil_in=%08x softint=%08x "
                       "current interrupt %x\n",
                       pil, env->pil_in, env->softint, env->interrupt_index);
    }
}
Ejemplo n.º 20
0
/* Input 0 is IRQ and input 1 is FIQ.  */
static void arm_pic_cpu_handler(void *opaque, int irq, int level)
{
    ARMCPU *cpu = opaque;
    CPUState *cs = CPU(cpu);

    switch (irq) {
    case ARM_PIC_CPU_IRQ:
        if (level) {
            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
        } else {
            cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
        }
        break;
    case ARM_PIC_CPU_FIQ:
        if (level) {
            cpu_interrupt(cs, CPU_INTERRUPT_FIQ);
        } else {
            cpu_reset_interrupt(cs, CPU_INTERRUPT_FIQ);
        }
        break;
    default:
        hw_error("arm_pic_cpu_handler: Bad interrupt line %d\n", irq);
    }
}
Ejemplo n.º 21
0
static void pic_irq_request(void *opaque, int irq, int level)
{
    CPUState *env = first_cpu;

    DPRINTF("pic_irqs: %s irq %d\n", level? "raise" : "lower", irq);
    if (env->apic_state) {
        while (env) {
            if (apic_accept_pic_intr(env->apic_state)) {
                apic_deliver_pic_intr(env->apic_state, level);
            }
            env = env->next_cpu;
        }
    } else {
        if (level)
            cpu_interrupt(env, CPU_INTERRUPT_HARD);
        else
            cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
    }
}
Ejemplo n.º 22
0
void cpu_check_irqs(CPUState *env)
{
    if (env->pil_in && (env->interrupt_index == 0 ||
                        (env->interrupt_index & ~15) == TT_EXTINT)) {
        unsigned int i;

        for (i = 15; i > 0; i--) {
            if (env->pil_in & (1 << i)) {
                int old_interrupt = env->interrupt_index;

                env->interrupt_index = TT_EXTINT | i;
                if (old_interrupt != env->interrupt_index)
                    cpu_interrupt(env, CPU_INTERRUPT_HARD);
                break;
            }
        }
    } else if (!env->pil_in && (env->interrupt_index & ~15) == TT_EXTINT) {
        env->interrupt_index = 0;
        cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
    }
}
Ejemplo n.º 23
0
void check_interrupts(CPUXtensaState *env)
{
    int minlevel = xtensa_get_cintlevel(env);
    uint32_t int_set_enabled = env->sregs[INTSET] & env->sregs[INTENABLE];
    int level;

    /* If the CPU is halted advance CCOUNT according to the vm_clock time
     * elapsed since the moment when it was advanced last time.
     */
    if (env->halted) {
        int64_t now = qemu_get_clock_ns(vm_clock);

        xtensa_advance_ccount(env,
                muldiv64(now - env->halt_clock,
                    env->config->clock_freq_khz, 1000000));
        env->halt_clock = now;
    }
    for (level = env->config->nlevel; level > minlevel; --level) {
        if (env->config->level_mask[level] & int_set_enabled) {
            env->pending_irq_level = level;
            cpu_interrupt(env, CPU_INTERRUPT_HARD);
            qemu_log_mask(CPU_LOG_INT,
                    "%s level = %d, cintlevel = %d, "
                    "pc = %08x, a0 = %08x, ps = %08x, "
                    "intset = %08x, intenable = %08x, "
                    "ccount = %08x\n",
                    __func__, level, xtensa_get_cintlevel(env),
                    env->pc, env->regs[0], env->sregs[PS],
                    env->sregs[INTSET], env->sregs[INTENABLE],
                    env->sregs[CCOUNT]);
            return;
        }
    }
    env->pending_irq_level = 0;
    cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
}
Ejemplo n.º 24
0
static void cchip_write(void *opaque, hwaddr addr,
                        uint64_t v32, unsigned size)
{
    TyphoonState *s = opaque;
    CPUState *cpu_single_cpu = CPU(alpha_env_get_cpu(cpu_single_env));
    uint64_t val, oldval, newval;

    if (addr & 4) {
        val = v32 << 32 | s->latch_tmp;
        addr ^= 4;
    } else {
        s->latch_tmp = v32;
        return;
    }

    switch (addr) {
    case 0x0000:
        /* CSC: Cchip System Configuration Register.  */
        /* All sorts of data here; nothing relevant RW.  */
        break;

    case 0x0040:
        /* MTR: Memory Timing Register.  */
        /* All sorts of stuff related to real DRAM.  */
        break;

    case 0x0080:
        /* MISC: Miscellaneous Register.  */
        newval = oldval = s->cchip.misc;
        newval &= ~(val & 0x10000ff0);     /* W1C fields */
        if (val & 0x100000) {
            newval &= ~0xff0000ull;        /* ACL clears ABT and ABW */
        } else {
            newval |= val & 0x00f00000;    /* ABT field is W1S */
            if ((newval & 0xf0000) == 0) {
                newval |= val & 0xf0000;   /* ABW field is W1S iff zero */
            }
        }
        newval |= (val & 0xf000) >> 4;     /* IPREQ field sets IPINTR.  */

        newval &= ~0xf0000000000ull;       /* WO and RW fields */
        newval |= val & 0xf0000000000ull;
        s->cchip.misc = newval;

        /* Pass on changes to IPI and ITI state.  */
        if ((newval ^ oldval) & 0xff0) {
            int i;
            for (i = 0; i < 4; ++i) {
                AlphaCPU *cpu = s->cchip.cpu[i];
                if (cpu != NULL) {
                    CPUState *cs = CPU(cpu);
                    /* IPI can be either cleared or set by the write.  */
                    if (newval & (1 << (i + 8))) {
                        cpu_interrupt(cs, CPU_INTERRUPT_SMP);
                    } else {
                        cpu_reset_interrupt(cs, CPU_INTERRUPT_SMP);
                    }

                    /* ITI can only be cleared by the write.  */
                    if ((newval & (1 << (i + 4))) == 0) {
                        cpu_reset_interrupt(cs, CPU_INTERRUPT_TIMER);
                    }
                }
            }
        }
        break;

    case 0x00c0:
        /* MPD: Memory Presence Detect Register.  */
        break;

    case 0x0100: /* AAR0 */
    case 0x0140: /* AAR1 */
    case 0x0180: /* AAR2 */
    case 0x01c0: /* AAR3 */
        /* AAR: Array Address Register.  */
        /* All sorts of information about DRAM.  */
        break;

    case 0x0200: /* DIM0 */
        /* DIM: Device Interrupt Mask Register, CPU0.  */
        s->cchip.dim[0] = val;
        cpu_irq_change(s->cchip.cpu[0], val & s->cchip.drir);
        break;
    case 0x0240: /* DIM1 */
        /* DIM: Device Interrupt Mask Register, CPU1.  */
        s->cchip.dim[0] = val;
        cpu_irq_change(s->cchip.cpu[1], val & s->cchip.drir);
        break;

    case 0x0280: /* DIR0 (RO) */
    case 0x02c0: /* DIR1 (RO) */
    case 0x0300: /* DRIR (RO) */
        break;

    case 0x0340:
        /* PRBEN: Probe Enable Register.  */
        break;

    case 0x0380: /* IIC0 */
        s->cchip.iic[0] = val & 0xffffff;
        break;
    case 0x03c0: /* IIC1 */
        s->cchip.iic[1] = val & 0xffffff;
        break;

    case 0x0400: /* MPR0 */
    case 0x0440: /* MPR1 */
    case 0x0480: /* MPR2 */
    case 0x04c0: /* MPR3 */
        /* MPR: Memory Programming Register.  */
        break;

    case 0x0580:
        /* TTR: TIGbus Timing Register.  */
        /* All sorts of stuff related to interrupt delivery timings.  */
        break;
    case 0x05c0:
        /* TDR: TIGbug Device Timing Register.  */
        break;

    case 0x0600:
        /* DIM2: Device Interrupt Mask Register, CPU2.  */
        s->cchip.dim[2] = val;
        cpu_irq_change(s->cchip.cpu[2], val & s->cchip.drir);
        break;
    case 0x0640:
        /* DIM3: Device Interrupt Mask Register, CPU3.  */
        s->cchip.dim[3] = val;
        cpu_irq_change(s->cchip.cpu[3], val & s->cchip.drir);
        break;

    case 0x0680: /* DIR2 (RO) */
    case 0x06c0: /* DIR3 (RO) */
        break;

    case 0x0700: /* IIC2 */
        s->cchip.iic[2] = val & 0xffffff;
        break;
    case 0x0740: /* IIC3 */
        s->cchip.iic[3] = val & 0xffffff;
        break;

    case 0x0780:
        /* PWR: Power Management Control.   */
        break;
    
    case 0x0c00: /* CMONCTLA */
    case 0x0c40: /* CMONCTLB */
    case 0x0c80: /* CMONCNT01 */
    case 0x0cc0: /* CMONCNT23 */
        break;

    default:
        cpu_unassigned_access(cpu_single_cpu, addr, true, false, 0, size);
        return;
    }
}
Ejemplo n.º 25
0
void cpu_check_irqs(CPUSPARCState *env)
{
    CPUState *cs;
    uint32_t pil = env->pil_in |
                  (env->softint & ~(SOFTINT_TIMER | SOFTINT_STIMER));

    /* We should be holding the BQL before we mess with IRQs */
    g_assert(qemu_mutex_iothread_locked());

    /* TT_IVEC has a higher priority (16) than TT_EXTINT (31..17) */
    if (env->ivec_status & 0x20) {
        return;
    }
    cs = CPU(sparc_env_get_cpu(env));
    /* check if TM or SM in SOFTINT are set
       setting these also causes interrupt 14 */
    if (env->softint & (SOFTINT_TIMER | SOFTINT_STIMER)) {
        pil |= 1 << 14;
    }

    /* The bit corresponding to psrpil is (1<< psrpil), the next bit
       is (2 << psrpil). */
    if (pil < (2 << env->psrpil)) {
        if (cs->interrupt_request & CPU_INTERRUPT_HARD) {
            trace_sparc64_cpu_check_irqs_reset_irq(env->interrupt_index);
            env->interrupt_index = 0;
            cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
        }
        return;
    }

    if (cpu_interrupts_enabled(env)) {

        unsigned int i;

        for (i = 15; i > env->psrpil; i--) {
            if (pil & (1 << i)) {
                int old_interrupt = env->interrupt_index;
                int new_interrupt = TT_EXTINT | i;

                if (unlikely(env->tl > 0 && cpu_tsptr(env)->tt > new_interrupt
                  && ((cpu_tsptr(env)->tt & 0x1f0) == TT_EXTINT))) {
                    trace_sparc64_cpu_check_irqs_noset_irq(env->tl,
                                                      cpu_tsptr(env)->tt,
                                                      new_interrupt);
                } else if (old_interrupt != new_interrupt) {
                    env->interrupt_index = new_interrupt;
                    trace_sparc64_cpu_check_irqs_set_irq(i, old_interrupt,
                                                         new_interrupt);
                    cpu_interrupt(cs, CPU_INTERRUPT_HARD);
                }
                break;
            }
        }
    } else if (cs->interrupt_request & CPU_INTERRUPT_HARD) {
        trace_sparc64_cpu_check_irqs_disabled(pil, env->pil_in, env->softint,
                                              env->interrupt_index);
        env->interrupt_index = 0;
        cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
    }
}