[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [RFC PATCH v9 06/23] target/arm: Add support for Non-maskable Interr
From: |
Jinjie Ruan |
Subject: |
Re: [RFC PATCH v9 06/23] target/arm: Add support for Non-maskable Interrupt |
Date: |
Fri, 22 Mar 2024 13:05:06 +0800 |
User-agent: |
Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:102.0) Gecko/20100101 Thunderbird/102.2.0 |
On 2024/3/22 2:28, Peter Maydell wrote:
> On Thu, 21 Mar 2024 at 15:46, Peter Maydell <peter.maydell@linaro.org> wrote:
>> Something somewhere needs to implement "if SCTLR_ELx.NMI is 0 then
>> we don't take EXCP_VINMI etc but instead (maybe) EXCP_VIRQ etc".
>> At the moment nothing does that:
>> * arm_cpu_update_vinmi() doesn't look at the NMI bit before
>> deciding whether to set CPU_INTERRUPT_VINMI
>> * in arm_excp_unmasked() if NMI is 0 then allIntMask takes its
>> default value of false and so arm_excp_unmasked() returns true,
>> so VINMI is not masked
>> * arm_cpu_exec_interrupt() doesn't look at the NMI bit before
>> deciding whether to check the CPU_INTERRUPT_VINMI bit in interrupt_request
>>
>> So even if SCTLR_ELx.NMI is 0 we'll still try to take a VINMI
>> if it's set up in the HCR_EL2 bits.
>>
>> However we do this the required behaviour is that if NMI is 0
>> then it is as if the interrupt doesn't have superpriority and
>> it falls back to being handled as an ordinary IRQ, VIRQ, VFIQ etc.
>> I think the best place to do this is probably here in
>> arm_cpu_exec_interrupt() -- if SCTLR_ELx.NMI isn't set then
>> treat the VFNMI bit like VFIQ, the VINMI bit like VIRQ, and
>> the NMI bit like IRQ.
>
> Folding in something like this I think will work:
>
> diff --git a/target/arm/cpu.c b/target/arm/cpu.c
> index 91c2896de0f..797ae3eb805 100644
> --- a/target/arm/cpu.c
> +++ b/target/arm/cpu.c
> @@ -837,7 +837,8 @@ static bool arm_cpu_exec_interrupt(CPUState *cs,
> int interrupt_request)
>
> /* The prioritization of interrupts is IMPLEMENTATION DEFINED. */
>
> - if (cpu_isar_feature(aa64_nmi, env_archcpu(env))) {
> + if (cpu_isar_feature(aa64_nmi, env_archcpu(env)) &&
> + (arm_sctlr(env, cur_el) & SCTLR_NMI)) {
> if (interrupt_request & CPU_INTERRUPT_NMI) {
> excp_idx = EXCP_NMI;
> target_el = arm_phys_excp_target_el(cs, excp_idx, cur_el,
> secure);
> @@ -862,7 +863,22 @@ static bool arm_cpu_exec_interrupt(CPUState *cs,
> int interrupt_request)
> goto found;
> }
> }
> + } else {
> + /*
> + * NMI disabled: interrupts with superpriority are handled
> + * as if they didn't have it
> + */
> + if (interrupt_request & CPU_INTERRUPT_NMI) {
> + interrupt_request |= CPU_INTERRUPT_HARD;
The CPU_INTERRUPT_NMI and CPU_INTERRUPT_HARD are set simultaneously,
should the CPU_INTERRUPT_NMI be cleared?
> + }
> + if (interrupt_request & CPU_INTERRUPT_VINMI) {
> + interrupt_request |= CPU_INTERRUPT_VIRQ;
> + }
> + if (interrupt_request & CPU_INTERRUPT_VFNMI) {
> + interrupt_request |= CPU_INTERRUPT_VFIQ;
> + }
> }> +
> if (interrupt_request & CPU_INTERRUPT_FIQ) {
> excp_idx = EXCP_FIQ;
> target_el = arm_phys_excp_target_el(cs, excp_idx, cur_el, secure);
>
>
>> What semantics do we intend for the VINMI/VFNMI bits in interrupt_request
>> and for the incoming IRQ, FIQ, NMI lines? The GIC spec suggests
>> (but doesn't mandate) that NMI could be signalled by asserting
>> both NMI and IRQ, and plain IRQ by asserting just IRQ (table 4-6
>> in the GIC spec). I think the GIC changes in this patchset assert
>> only the NMI line for an IRQNMI, and not both NMI and IRQ. That's OK
>> and I think makes more sense for QEMU than signalling both lines,
>> but it's not the same as what we wind up doing with the handling
>> of the HCR_EL2 bits in these functions, because you don't change
>> the existing arm_cpu_update_virq() so that it only sets the
>> CPU_INTERRUPT_VIRQ bit if this is a VIRQ and not a VIRQNMI.
>> So if the guest sets HCR_EL2.VI and HCRX_EL2.VINMI then
>> arm_cpu_update_virq() will say "this is a VIRQ" and also
>> arm_cpu_update_vinmi() will say "This is a VINMI" and so both bits
>> get set in the interrupt_request field.
>>
>> I think the fix for this is probably to have arm_cpu_update_virq()
>> and arm_cpu_update_vfiq() check that this is not a VINMI/VFNMI,
>> so we only set 1 bit in interrupt_request, not 2.
>
> And for this a change like:
>
> diff --git a/target/arm/cpu.c b/target/arm/cpu.c
> index 03a48a41366..91c2896de0f 100644
> --- a/target/arm/cpu.c
> +++ b/target/arm/cpu.c
> @@ -926,7 +926,8 @@ void arm_cpu_update_virq(ARMCPU *cpu)
> CPUARMState *env = &cpu->env;
> CPUState *cs = CPU(cpu);
>
> - bool new_state = (env->cp15.hcr_el2 & HCR_VI) ||
> + bool new_state = ((arm_hcr_el2_eff(env) & HCR_VI) &&
> + !(arm_hcrx_el2_eff(env) & HCRX_VINMI)) ||
> (env->irq_line_state & CPU_INTERRUPT_VIRQ);
>
> if (new_state != ((cs->interrupt_request & CPU_INTERRUPT_VIRQ) != 0)) {
> @@ -947,7 +948,8 @@ void arm_cpu_update_vfiq(ARMCPU *cpu)
> CPUARMState *env = &cpu->env;
> CPUState *cs = CPU(cpu);
>
> - bool new_state = (env->cp15.hcr_el2 & HCR_VF) ||
> + bool new_state = ((arm_hcr_el2_eff(env) & HCR_VF) &&
> + !(arm_hcrx_el2_eff(env) & HCRX_VFNMI)) ||
> (env->irq_line_state & CPU_INTERRUPT_VFIQ);
>
> if (new_state != ((cs->interrupt_request & CPU_INTERRUPT_VFIQ) != 0)) {
>
>
> thanks
> -- PMM
- [RFC PATCH v9 02/23] target/arm: Add PSTATE.ALLINT, (continued)
- [RFC PATCH v9 02/23] target/arm: Add PSTATE.ALLINT, Jinjie Ruan, 2024/03/21
- [RFC PATCH v9 01/23] target/arm: Handle HCR_EL2 accesses for bits introduced with FEAT_NMI, Jinjie Ruan, 2024/03/21
- [RFC PATCH v9 03/23] target/arm: Add support for FEAT_NMI, Non-maskable Interrupt, Jinjie Ruan, 2024/03/21
- [RFC PATCH v9 04/23] target/arm: Implement ALLINT MSR (immediate), Jinjie Ruan, 2024/03/21
- [RFC PATCH v9 08/23] target/arm: Handle IS/FS in ISR_EL1 for NMI, VINMI and VFNMI, Jinjie Ruan, 2024/03/21
- [RFC PATCH v9 07/23] target/arm: Add support for NMI in arm_phys_excp_target_el(), Jinjie Ruan, 2024/03/21
- [RFC PATCH v9 06/23] target/arm: Add support for Non-maskable Interrupt, Jinjie Ruan, 2024/03/21
- Re: [RFC PATCH v9 06/23] target/arm: Add support for Non-maskable Interrupt, Jinjie Ruan, 2024/03/21
- Re: [RFC PATCH v9 06/23] target/arm: Add support for Non-maskable Interrupt, Peter Maydell, 2024/03/22
[RFC PATCH v9 10/23] hw/arm/virt: Wire NMI and VINMI irq lines from GIC to CPU, Jinjie Ruan, 2024/03/21
[RFC PATCH v9 12/23] target/arm: Handle NMI in arm_cpu_do_interrupt_aarch64(), Jinjie Ruan, 2024/03/21
[RFC PATCH v9 05/23] target/arm: Support MSR access to ALLINT, Jinjie Ruan, 2024/03/21
[RFC PATCH v9 09/23] target/arm: Handle PSTATE.ALLINT on taking an exception, Jinjie Ruan, 2024/03/21
[RFC PATCH v9 11/23] hw/intc/arm_gicv3: Add external IRQ lines for NMI, Jinjie Ruan, 2024/03/21
[RFC PATCH v9 13/23] hw/intc/arm_gicv3: Add irq superpriority information, Jinjie Ruan, 2024/03/21
[RFC PATCH v9 16/23] hw/intc: Enable FEAT_GICv3_NMI Feature, Jinjie Ruan, 2024/03/21