qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: How does qemu detect the completion of interrupt execution?


From: Duo jia
Subject: Re: How does qemu detect the completion of interrupt execution?
Date: Thu, 2 Sep 2021 10:17:52 +0800

  Hi,
   thank you for your response.
   As you say
 "End of interrupt handling is entirely dependent on what the
guest hardware being emulated is. Usually the guest software
will indicate "interrupt handled" back to the interrupt
controller (perhaps by writing a register; depends on the
interrupt controller), and the interrupt controller will
then look at what the next highest priority pending interrupt
is and signal that back to the CPU, or do nothing if there's
no new interrupt. So the second interrupt will automatically
be taken and handled once the first one has finished,
as a result of this interrupt controller and guest OS
interaction."
I agree with that. I has try some method, But Still have some problems.

Q1:
My guest(target) cpu seem don't have a   "interrupt handled" , And I don't know How/When to program the  " interrupt controller"   to check the second interrupt when the first over.

Q2:
Also I found the new problem(maybe bug) , when first interrupt  not over, the second interrupt may occure, this case Interrupt nesting ,if I check Interrupt flag in the code,the second interrupt losed。

I don't know the interrupt mechanism of qemu very well. If you have any suggestions, I am very happy to receive them.

this is my code:

/* set irq for device */
static void stm8_cpu_set_irq(void *opaque, int irq, int level)
{
    //printf("%s\n",__func__);
    STM8CPU *cpu = opaque;
    CPUSTM8State *env = &cpu->env;
    CPUState *cs = CPU(cpu);
    uint64_t mask = (1ull << irq);

    //printf("irq:%d , level:%d\n",irq,level);
    if (level) {
        env->intsrc |= mask;
        cpu_interrupt(cs, CPU_INTERRUPT_HARD);
    } else {
        env->intsrc &= ~mask;
        if (env->intsrc == 0) {
            cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
        }
    }
}

bool stm8_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
{
    //printf("%s\n",__func__);
    CPUClass *cpu_cc = CPU_GET_CLASS(cs);
    STM8CPU *cpu = STM8_CPU(cs);
    CPUSTM8State *env = &cpu->env;
    int idx = -1;

    /* Check interrupt */
    if (!cpu_interrupts_enabled(env)){
        qemu_log_mask(LOG_GUEST_ERROR,"[CPU] cpu_interrupts_enabled = false.\n");
        //return false; 
    }
    if (interrupt_request & CPU_INTERRUPT_RESET)
    {
        idx = 0;
        cs->interrupt_request &= ~CPU_INTERRUPT_RESET;
    }
    if (interrupt_request & CPU_INTERRUPT_HARD) {
        if(env->intsrc != 0){
            idx = ctz32(env->intsrc);
            env->intsrc &= ~(1<<idx);

            cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
            /* Map interrupt */
            idx = EXCP_INT(idx);
        }
    }
    if (idx >= 0) {
        cs->exception_index = idx;
        cpu_cc->do_interrupt(cs);
        return true;
    }
    return false;
}
 




Peter Maydell <peter.maydell@linaro.org> 于2021年8月6日周五 下午6:16写道:
On Fri, 6 Aug 2021 at 07:24, Duo jia <jiaduo19920301@gmail.com> wrote:
> I am simulating a device. When an interrupt occurs, another interrupt
> comes, and the second interrupt will not be triggered because the
> first interrupt has not yet finished.
>
> I want to know whether qemu can detect whether the interrupt has been
> executed, will there be a callback here?
> Or how can I deal with this situation?

End of interrupt handling is entirely dependent on what the
guest hardware being emulated is. Usually the guest software
will indicate "interrupt handled" back to the interrupt
controller (perhaps by writing a register; depends on the
interrupt controller), and the interrupt controller will
then look at what the next highest priority pending interrupt
is and signal that back to the CPU, or do nothing if there's
no new interrupt. So the second interrupt will automatically
be taken and handled once the first one has finished,
as a result of this interrupt controller and guest OS
interaction.

The original device usually doesn't get told when this
happens, and it doesn't need to know. For example, one common
form of device interrupt is level-triggered. Here the device
has some condition (perhaps "FIFO full") that causes an
interrupt. So it raises its outbound IRQ line when the FIFO
is full, and it doesn't lower it again until whatever the
device specification says is the condition (eg when the
guest reads from the FIFO, or if the guest writes to some
'clear interrupt' register on the device). It's the job of
the guest software to make sure that when it gets an interrupt
from the device that it handles it such that the device has
been satisfied and lowered the interrupt.

More rarely, some devices are specified to pulse their interrupt
line when a condition occurs.

In summary, you need to look at the specification of the device
you're emulating to find out when and how it is supposed to
raise or lower its interrupt line. ("I didn't get a second
interrupt" bugs might also be caused by bugs in the interrupt
controller or in the guest software device driver -- if you're
just using an existing known-to-work QEMU interrupt controller
model and a known-to-work device driver and OS, then the
bug is very likely in your device model. If you're also
writing the OS device driver at the same time then the bug
could be there instead.)

-- PMM

reply via email to

[Prev in Thread] Current Thread [Next in Thread]