[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH v2 1/2] target/riscv: fix VS interrupts forwarding to HS
From: |
Alistair Francis |
Subject: |
Re: [PATCH v2 1/2] target/riscv: fix VS interrupts forwarding to HS |
Date: |
Wed, 27 Oct 2021 13:24:14 +1000 |
On Wed, Oct 27, 2021 at 12:53 AM Jose Martins <josemartins90@gmail.com> wrote:
>
> VS interrupts (2, 6, 10) were not correctly forwarded to hs-mode when
> not delegated in hideleg (which was not being taken into account). This
> was mainly because hs level sie was not always considered enabled when
> it should. The spec states that "Interrupts for higher-privilege modes,
> y>x, are always globally enabled regardless of the setting of the global
> yIE bit for the higher-privilege mode." and also "For purposes of
> interrupt global enables, HS-mode is considered more privileged than
> VS-mode, and VS-mode is considered more privileged than VU-mode". Also,
> vs-level interrupts were not being taken into account unless V=1, but
> should be unless delegated.
>
> Finally, there is no need for a special case for to handle vs interrupts
> as the current privilege level, the state of the global ie and of the
> delegation registers should be enough to route all interrupts to the
> appropriate privilege level in riscv_cpu_do_interrupt.
>
> Signed-off-by: Jose Martins <josemartins90@gmail.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Alistair
> ---
> target/riscv/cpu_helper.c | 28 ++++++++--------------------
> 1 file changed, 8 insertions(+), 20 deletions(-)
>
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 968cb8046f..55db004fea 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -38,36 +38,24 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
> #ifndef CONFIG_USER_ONLY
> static int riscv_cpu_local_irq_pending(CPURISCVState *env)
> {
> - target_ulong irqs;
> + target_ulong virt_enabled = riscv_cpu_virt_enabled(env);
>
> target_ulong mstatus_mie = get_field(env->mstatus, MSTATUS_MIE);
> target_ulong mstatus_sie = get_field(env->mstatus, MSTATUS_SIE);
> - target_ulong hs_mstatus_sie = get_field(env->mstatus_hs, MSTATUS_SIE);
>
> - target_ulong pending = env->mip & env->mie &
> - ~(MIP_VSSIP | MIP_VSTIP | MIP_VSEIP);
> - target_ulong vspending = (env->mip & env->mie &
> - (MIP_VSSIP | MIP_VSTIP | MIP_VSEIP));
> + target_ulong pending = env->mip & env->mie;
>
> target_ulong mie = env->priv < PRV_M ||
> (env->priv == PRV_M && mstatus_mie);
> target_ulong sie = env->priv < PRV_S ||
> (env->priv == PRV_S && mstatus_sie);
> - target_ulong hs_sie = env->priv < PRV_S ||
> - (env->priv == PRV_S && hs_mstatus_sie);
> + target_ulong hsie = virt_enabled || sie;
> + target_ulong vsie = virt_enabled && sie;
>
> - if (riscv_cpu_virt_enabled(env)) {
> - target_ulong pending_hs_irq = pending & -hs_sie;
> -
> - if (pending_hs_irq) {
> - riscv_cpu_set_force_hs_excep(env, FORCE_HS_EXCEP);
> - return ctz64(pending_hs_irq);
> - }
> -
> - pending = vspending;
> - }
> -
> - irqs = (pending & ~env->mideleg & -mie) | (pending & env->mideleg &
> -sie);
> + target_ulong irqs =
> + (pending & ~env->mideleg & -mie) |
> + (pending & env->mideleg & ~env->hideleg & -hsie) |
> + (pending & env->mideleg & env->hideleg & -vsie);
>
> if (irqs) {
> return ctz64(irqs); /* since non-zero */
> --
> 2.33.1
>
>