Skip to content

Commit

Permalink
target/riscv: Add HS-mode virtual interrupt and IRQ filtering support.
Browse files Browse the repository at this point in the history
This change adds support for inserting virtual interrupts from HS-mode
into VS-mode using hvien and hvip csrs. This also allows for IRQ filtering
from HS-mode.

Also, the spec doesn't mandate the interrupt to be actually supported
in hardware. Which allows HS-mode to assert virtual interrupts to VS-mode
that have no connection to any real interrupt events.

This is defined as part of the AIA specification [0], "6.3.2 Virtual
interrupts for VS level".

[0]: https://github.com/riscv/riscv-aia/releases/download/1.0/riscv-interrupts-1.0.pdf

Signed-off-by: Rajnesh Kanwal <rkanwal@rivosinc.com>
Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Message-ID: <20231016111736.28721-7-rkanwal@rivosinc.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
  • Loading branch information
rajnesh-kanwal authored and alistair23 committed Nov 7, 2023
1 parent 1697837 commit 40336d5
Show file tree
Hide file tree
Showing 5 changed files with 236 additions and 32 deletions.
3 changes: 2 additions & 1 deletion target/riscv/cpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -814,7 +814,8 @@ static bool riscv_cpu_has_work(CPUState *cs)
* mode and delegation registers, but respect individual enables
*/
return riscv_cpu_all_pending(env) != 0 ||
riscv_cpu_sirq_pending(env) != RISCV_EXCP_NONE;
riscv_cpu_sirq_pending(env) != RISCV_EXCP_NONE ||
riscv_cpu_vsirq_pending(env) != RISCV_EXCP_NONE;
#else
return true;
#endif
Expand Down
14 changes: 14 additions & 0 deletions target/riscv/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,12 @@ struct CPUArchState {
*/
uint64_t sie;

/*
* When hideleg[i]=0 and hvien[i]=1, vsie[i] is no more
* alias of sie[i] (mie[i]) and needs to be maintained separatly.
*/
uint64_t vsie;

target_ulong satp; /* since: priv-1.10.0 */
target_ulong stval;
target_ulong medeleg;
Expand Down Expand Up @@ -242,6 +248,14 @@ struct CPUArchState {
target_ulong hgeie;
target_ulong hgeip;
uint64_t htimedelta;
uint64_t hvien;

/*
* Bits VSSIP, VSTIP and VSEIP in hvip are maintained in mip. Other bits
* from 0:12 are reserved. Bits 13:63 are not aliased and must be separately
* maintain in hvip.
*/
uint64_t hvip;

/* Hypervisor controlled virtual interrupt priorities */
target_ulong hvictl;
Expand Down
48 changes: 37 additions & 11 deletions target/riscv/cpu_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -377,8 +377,9 @@ static int riscv_cpu_pending_to_irq(CPURISCVState *env,
}

/*
* Doesn't report interrupts inserted using mvip from M-mode firmware. Those
* are returned in riscv_cpu_sirq_pending().
* Doesn't report interrupts inserted using mvip from M-mode firmware or
* using hvip bits 13:63 from HS-mode. Those are returned in
* riscv_cpu_sirq_pending() and riscv_cpu_vsirq_pending().
*/
uint64_t riscv_cpu_all_pending(CPURISCVState *env)
{
Expand Down Expand Up @@ -410,16 +411,23 @@ int riscv_cpu_sirq_pending(CPURISCVState *env)

int riscv_cpu_vsirq_pending(CPURISCVState *env)
{
uint64_t irqs = riscv_cpu_all_pending(env) & env->mideleg &
(MIP_VSSIP | MIP_VSTIP | MIP_VSEIP);
uint64_t irqs = riscv_cpu_all_pending(env) & env->mideleg & env->hideleg;
uint64_t irqs_f_vs = env->hvip & env->hvien & ~env->hideleg & env->vsie;
uint64_t vsbits;

/* Bring VS-level bits to correct position */
vsbits = irqs & VS_MODE_INTERRUPTS;
irqs &= ~VS_MODE_INTERRUPTS;
irqs |= vsbits >> 1;

return riscv_cpu_pending_to_irq(env, IRQ_S_EXT, IPRIO_DEFAULT_S,
irqs >> 1, env->hviprio);
(irqs | irqs_f_vs), env->hviprio);
}

static int riscv_cpu_local_irq_pending(CPURISCVState *env)
{
uint64_t irqs, pending, mie, hsie, vsie, irqs_f;
uint64_t irqs, pending, mie, hsie, vsie, irqs_f, irqs_f_vs;
uint64_t vsbits, irq_delegated;
int virq;

/* Determine interrupt enable state of all privilege modes */
Expand Down Expand Up @@ -456,12 +464,26 @@ static int riscv_cpu_local_irq_pending(CPURISCVState *env)
irqs, env->siprio);
}

/* Check for virtual VS-mode interrupts. */
irqs_f_vs = env->hvip & env->hvien & ~env->hideleg & env->vsie;

/* Check VS-mode interrupts */
irqs = pending & env->mideleg & env->hideleg & -vsie;
irq_delegated = pending & env->mideleg & env->hideleg;

/* Bring VS-level bits to correct position */
vsbits = irq_delegated & VS_MODE_INTERRUPTS;
irq_delegated &= ~VS_MODE_INTERRUPTS;
irq_delegated |= vsbits >> 1;

irqs = (irq_delegated | irqs_f_vs) & -vsie;
if (irqs) {
virq = riscv_cpu_pending_to_irq(env, IRQ_S_EXT, IPRIO_DEFAULT_S,
irqs >> 1, env->hviprio);
return (virq <= 0) ? virq : virq + 1;
irqs, env->hviprio);
if (virq <= 0 || (virq > 12 && virq <= 63)) {
return virq;
} else {
return virq + 1;
}
}

/* Indicate no pending interrupt */
Expand Down Expand Up @@ -638,6 +660,7 @@ void riscv_cpu_interrupt(CPURISCVState *env)
if (env->virt_enabled) {
gein = get_field(env->hstatus, HSTATUS_VGEIN);
vsgein = (env->hgeip & (1ULL << gein)) ? MIP_VSEIP : 0;
irqf = env->hvien & env->hvip & env->vsie;
} else {
irqf = env->mvien & env->mvip & env->sie;
}
Expand Down Expand Up @@ -1623,6 +1646,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
uint64_t deleg = async ? env->mideleg : env->medeleg;
bool s_injected = env->mvip & (1 << cause) & env->mvien &&
!(env->mip & (1 << cause));
bool vs_injected = env->hvip & (1 << cause) & env->hvien &&
!(env->mip & (1 << cause));
target_ulong tval = 0;
target_ulong tinst = 0;
target_ulong htval = 0;
Expand Down Expand Up @@ -1712,12 +1737,13 @@ void riscv_cpu_do_interrupt(CPUState *cs)
riscv_cpu_get_trap_name(cause, async));

if (env->priv <= PRV_S && cause < 64 &&
(((deleg >> cause) & 1) || s_injected)) {
(((deleg >> cause) & 1) || s_injected || vs_injected)) {
/* handle the trap in S-mode */
if (riscv_has_ext(env, RVH)) {
uint64_t hdeleg = async ? env->hideleg : env->hedeleg;

if (env->virt_enabled && ((hdeleg >> cause) & 1)) {
if (env->virt_enabled &&
(((hdeleg >> cause) & 1) || vs_injected)) {
/* Trap to VS mode */
/*
* See if we need to adjust cause. Yes if its VS mode interrupt
Expand Down

0 comments on commit 40336d5

Please sign in to comment.