On Mon, May 22, 2023 at 6:18 PM Daniel Henrique Barboza <dbarb...@ventanamicro.com> wrote: > > > > On 5/18/23 08:38, Rajnesh Kanwal wrote: > > 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-RC4/riscv-interrupts-1.0-RC4.pdf > > > > Signed-off-by: Rajnesh Kanwal <rkan...@rivosinc.com> > > --- > > target/riscv/cpu.c | 3 +- > > target/riscv/cpu.h | 14 +++ > > target/riscv/cpu_helper.c | 48 +++++++--- > > target/riscv/csr.c | 196 ++++++++++++++++++++++++++++++++++---- > > target/riscv/machine.c | 3 + > > 5 files changed, 234 insertions(+), 30 deletions(-) > > > > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c > > index 9557194a21..c2b05d4c37 100644 > > --- a/target/riscv/cpu.c > > +++ b/target/riscv/cpu.c > > @@ -713,7 +713,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 > > diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h > > index 07cf656471..3e10eee38f 100644 > > --- a/target/riscv/cpu.h > > +++ b/target/riscv/cpu.h > > @@ -196,6 +196,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; > > @@ -230,6 +236,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; > > diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c > > index 681b4ae811..80bdd4cf5a 100644 > > --- a/target/riscv/cpu_helper.c > > +++ b/target/riscv/cpu_helper.c > > @@ -366,8 +366,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) > > { > > @@ -399,16 +400,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 */ > > @@ -445,12 +453,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 */ > > @@ -625,6 +647,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; > > } > > @@ -1620,6 +1643,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; > > @@ -1711,12 +1736,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 > > diff --git a/target/riscv/csr.c b/target/riscv/csr.c > > index c1ca065a81..1929d5fa7b 100644 > > --- a/target/riscv/csr.c > > +++ b/target/riscv/csr.c > > @@ -30,6 +30,11 @@ > > #include "qemu/guest-random.h" > > #include "qapi/error.h" > > > > + > > +static RISCVException rmw_hvip64(CPURISCVState *env, int csrno, > > + uint64_t *ret_val, > > + uint64_t new_val, uint64_t wr_mask); > > + > > This forward declaration breaks qemu linux-user build: > > > [2/26] Compiling C object libqemu-riscv32-linux-user.fa.p/target_riscv_csr.c.o > FAILED: libqemu-riscv32-linux-user.fa.p/target_riscv_csr.c.o > cc -m64 -mcx16 -Ilibqemu-riscv32-linux-user.fa.p -I. -I.. -Itarget/riscv > -I../target/riscv -I../common-user/host/x86_64 > -I../linux-user/include/host/x86_64 -I../linux-user/include -Ilinux-user > -I../linux-user -I../linux-user/riscv -Iqapi -Itrace -Iui -Iui/shader > -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include > -I/usr/include/sysprof-4 -fdiagnostics-color=auto -Wall -Winvalid-pch -Werror > -std=gnu11 -O2 -g -isystem /home/danielhb/work/qemu/linux-headers -isystem > linux-headers -iquote . -iquote /home/danielhb/work/qemu -iquote > /home/danielhb/work/qemu/include -iquote /home/danielhb/work/qemu/tcg/i386 > -pthread -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE > -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -fno-strict-aliasing -fno-common > -fwrapv -Wundef -Wwrite-strings -Wmissing-prototypes -Wstrict-prototypes > -Wredundant-decls -Wold-style-declaration -Wold-style-definition > -Wtype-limits -Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers > -Wempty-body -Wnested-externs -Wendif-labels -Wexpansion-to-defined > -Wimplicit-fallthrough=2 -Wmissing-format-attribute -Wno-missing-include-dirs > -Wno-shift-negative-value -Wno-psabi -fstack-protector-strong -fPIE > -isystem../linux-headers -isystemlinux-headers -DNEED_CPU_H > '-DCONFIG_TARGET="riscv32-linux-user-config-target.h"' > '-DCONFIG_DEVICES="riscv32-linux-user-config-devices.h"' -MD -MQ > libqemu-riscv32-linux-user.fa.p/target_riscv_csr.c.o -MF > libqemu-riscv32-linux-user.fa.p/target_riscv_csr.c.o.d -o > libqemu-riscv32-linux-user.fa.p/target_riscv_csr.c.o -c ../target/riscv/csr.c > ../target/riscv/csr.c:34:23: error: ‘rmw_hvip64’ declared ‘static’ but never > defined [-Werror=unused-function] > 34 | static RISCVException rmw_hvip64(CPURISCVState *env, int csrno, > | ^~~~~~~~~~ > cc1: all warnings being treated as errors > > > > It's not clear in the code but rmw_vsip64() is inside a huge "#if > defined(CONFIG_USER_ONLY)" > block that starts at line 775. > > Putting "rmw_hvip64" forward declaration right before rmw_vsip64() is enough > to fix it. > > > Thanks, > > > Daniel
Thanks Daniel. I have fixed both issues related to linux-user build failure in v2. https://lore.kernel.org/all/20230526162308.22892-1-rkan...@rivosinc.com/ -Rajnesh > > > > /* CSR function table public API */ > > void riscv_get_csr_ops(int csrno, riscv_csr_operations *ops) > > { > > @@ -1176,6 +1181,8 @@ static const target_ulong sip_writable_mask = > > SIP_SSIP | LOCAL_INTERRUPTS; > > static const target_ulong hip_writable_mask = MIP_VSSIP; > > static const target_ulong hvip_writable_mask = MIP_VSSIP | MIP_VSTIP | > > MIP_VSEIP | LOCAL_INTERRUPTS; > > +static const target_ulong hvien_writable_mask = LOCAL_INTERRUPTS; > > + > > static const target_ulong vsip_writable_mask = MIP_VSSIP | > > LOCAL_INTERRUPTS; > > > > const bool valid_vm_1_10_32[16] = { > > @@ -2584,16 +2591,36 @@ static RISCVException rmw_vsie64(CPURISCVState > > *env, int csrno, > > uint64_t *ret_val, > > uint64_t new_val, uint64_t wr_mask) > > { > > + uint64_t alias_mask = (LOCAL_INTERRUPTS | VS_MODE_INTERRUPTS) & > > + env->hideleg; > > + uint64_t nalias_mask = LOCAL_INTERRUPTS & (~env->hideleg & env->hvien); > > + uint64_t rval, rval_vs, vsbits; > > + uint64_t wr_mask_vsie; > > + uint64_t wr_mask_mie; > > RISCVException ret; > > - uint64_t rval, mask = env->hideleg & VS_MODE_INTERRUPTS; > > > > /* Bring VS-level bits to correct position */ > > - new_val = (new_val & (VS_MODE_INTERRUPTS >> 1)) << 1; > > - wr_mask = (wr_mask & (VS_MODE_INTERRUPTS >> 1)) << 1; > > + vsbits = new_val & (VS_MODE_INTERRUPTS >> 1); > > + new_val &= ~(VS_MODE_INTERRUPTS >> 1); > > + new_val |= vsbits << 1; > > + > > + vsbits = wr_mask & (VS_MODE_INTERRUPTS >> 1); > > + wr_mask &= ~(VS_MODE_INTERRUPTS >> 1); > > + wr_mask |= vsbits << 1; > > + > > + wr_mask_mie = wr_mask & alias_mask; > > + wr_mask_vsie = wr_mask & nalias_mask; > > + > > + ret = rmw_mie64(env, csrno, &rval, new_val, wr_mask_mie); > > + > > + rval_vs = env->vsie & nalias_mask; > > + env->vsie = (env->vsie & ~wr_mask_vsie) | (new_val & wr_mask_vsie); > > > > - ret = rmw_mie64(env, csrno, &rval, new_val, wr_mask & mask); > > if (ret_val) { > > - *ret_val = (rval & mask) >> 1; > > + rval &= alias_mask; > > + vsbits = rval & VS_MODE_INTERRUPTS; > > + rval &= ~VS_MODE_INTERRUPTS; > > + *ret_val = rval | (vsbits >> 1) | rval_vs; > > } > > > > return ret; > > @@ -2812,15 +2839,26 @@ static RISCVException rmw_vsip64(CPURISCVState > > *env, int csrno, > > { > > RISCVException ret; > > uint64_t rval, mask = env->hideleg & VS_MODE_INTERRUPTS; > > + uint64_t vsbits; > > > > - /* Bring VS-level bits to correct position */ > > - new_val = (new_val & (VS_MODE_INTERRUPTS >> 1)) << 1; > > - wr_mask = (wr_mask & (VS_MODE_INTERRUPTS >> 1)) << 1; > > + /* Add virtualized bits into vsip mask. */ > > + mask |= env->hvien & ~env->hideleg; > > > > - ret = rmw_mip64(env, csrno, &rval, new_val, > > - wr_mask & mask & vsip_writable_mask); > > + /* Bring VS-level bits to correct position */ > > + vsbits = new_val & (VS_MODE_INTERRUPTS >> 1); > > + new_val &= ~(VS_MODE_INTERRUPTS >> 1); > > + new_val |= vsbits << 1; > > + vsbits = wr_mask & (VS_MODE_INTERRUPTS >> 1); > > + wr_mask &= ~(VS_MODE_INTERRUPTS >> 1); > > + wr_mask |= vsbits << 1; > > + > > + ret = rmw_hvip64(env, csrno, &rval, new_val, > > + wr_mask & mask & vsip_writable_mask); > > if (ret_val) { > > - *ret_val = (rval & mask) >> 1; > > + rval &= mask; > > + vsbits = rval & VS_MODE_INTERRUPTS; > > + rval &= ~VS_MODE_INTERRUPTS; > > + *ret_val = rval | (vsbits >> 1); > > } > > > > return ret; > > @@ -3112,6 +3150,52 @@ static RISCVException write_hedeleg(CPURISCVState > > *env, int csrno, > > return RISCV_EXCP_NONE; > > } > > > > +static RISCVException rmw_hvien64(CPURISCVState *env, int csrno, > > + uint64_t *ret_val, > > + uint64_t new_val, uint64_t wr_mask) > > +{ > > + uint64_t mask = wr_mask & hvien_writable_mask; > > + > > + if (ret_val) { > > + *ret_val = env->hvien; > > + } > > + > > + env->hvien = (env->hvien & ~mask) | (new_val & mask); > > + > > + return RISCV_EXCP_NONE; > > +} > > + > > +static RISCVException rmw_hvien(CPURISCVState *env, int csrno, > > + target_ulong *ret_val, > > + target_ulong new_val, target_ulong wr_mask) > > +{ > > + uint64_t rval; > > + RISCVException ret; > > + > > + ret = rmw_hvien64(env, csrno, &rval, new_val, wr_mask); > > + if (ret_val) { > > + *ret_val = rval; > > + } > > + > > + return ret; > > +} > > + > > +static RISCVException rmw_hvienh(CPURISCVState *env, int csrno, > > + target_ulong *ret_val, > > + target_ulong new_val, target_ulong > > wr_mask) > > +{ > > + uint64_t rval; > > + RISCVException ret; > > + > > + ret = rmw_hvien64(env, csrno, &rval, > > + ((uint64_t)new_val) << 32, ((uint64_t)wr_mask) << 32); > > + if (ret_val) { > > + *ret_val = rval >> 32; > > + } > > + > > + return ret; > > +} > > + > > static RISCVException rmw_hideleg64(CPURISCVState *env, int csrno, > > uint64_t *ret_val, > > uint64_t new_val, uint64_t wr_mask) > > @@ -3157,16 +3241,94 @@ static RISCVException rmw_hidelegh(CPURISCVState > > *env, int csrno, > > return ret; > > } > > > > +/* > > + * The function is written for two use-cases: > > + * 1- To access hvip csr as is for HS-mode access. > > + * 2- To access vsip as a combination of hvip, and mip for vs-mode. > > + * > > + * Both report bits 2, 6, 10 and 13:63. > > + * vsip needs to be read-only zero when both hideleg[i] and > > + * hvien[i] are zero. > > + */ > > static RISCVException rmw_hvip64(CPURISCVState *env, int csrno, > > uint64_t *ret_val, > > uint64_t new_val, uint64_t wr_mask) > > { > > RISCVException ret; > > + uint64_t old_hvip; > > + uint64_t ret_mip; > > + > > + /* > > + * For bits 10, 6 and 2, vsip[i] is an alias of hip[i]. These bits are > > + * present in hip, hvip and mip. Where mip[i] is alias of hip[i] and > > hvip[i] > > + * is OR'ed in hip[i] to inject virtual interrupts from hypervisor. > > These > > + * bits are actually being maintained in mip so we read them from > > there. > > + * This way we have a single source of truth and allows for easier > > + * implementation. > > + * > > + * For bits 13:63 we have: > > + * > > + * hideleg[i] hvien[i] > > + * 0 0 No delegation. vsip[i] readonly zero. > > + * 0 1 vsip[i] is alias of hvip[i], sip bypassed. > > + * 1 X vsip[i] is alias of sip[i], hvip bypassed. > > + * > > + * alias_mask denotes the bits that come from sip (mip here given we > > + * maintain all bits there). nalias_mask denotes bits that come from > > + * hvip. > > + */ > > + uint64_t alias_mask = (env->hideleg | ~env->hvien) | > > VS_MODE_INTERRUPTS; > > + uint64_t nalias_mask = (~env->hideleg & env->hvien); > > + uint64_t wr_mask_hvip; > > + uint64_t wr_mask_mip; > > + > > + /* > > + * Both alias and non-alias mask remain same for vsip except: > > + * 1- For VS* bits if they are zero in hideleg. > > + * 2- For 13:63 bits if they are zero in both hideleg and hvien. > > + */ > > + if (csrno == CSR_VSIP) { > > + /* zero-out VS* bits that are not delegated to VS mode. */ > > + alias_mask &= (env->hideleg | ~VS_MODE_INTERRUPTS); > > + > > + /* > > + * zero-out 13:63 bits that are zero in both hideleg and hvien. > > + * nalias_mask mask can not contain any VS* bits so only second > > + * condition applies on it. > > + */ > > + nalias_mask &= (env->hideleg | env->hvien); > > + alias_mask &= (env->hideleg | env->hvien); > > + } > > + > > + wr_mask_hvip = wr_mask & nalias_mask & hvip_writable_mask; > > + wr_mask_mip = wr_mask & alias_mask & hvip_writable_mask; > > + > > + /* Aliased bits, bits 10, 6, 2 need to come from mip. */ > > + ret = rmw_mip64(env, csrno, &ret_mip, new_val, wr_mask_mip); > > + if (ret != RISCV_EXCP_NONE) { > > + return ret; > > + } > > + > > + old_hvip = env->hvip; > > + > > + if (wr_mask_hvip) { > > + env->hvip = (env->hvip & ~wr_mask_hvip) | (new_val & wr_mask_hvip); > > + > > + /* > > + * Given hvip is separate source from mip, we need to trigger > > interrupt > > + * from here separately. Normally this happen from > > riscv_cpu_update_mip. > > + */ > > + riscv_cpu_interrupt(env); > > + } > > > > - ret = rmw_mip64(env, csrno, ret_val, new_val, > > - wr_mask & hvip_writable_mask); > > if (ret_val) { > > - *ret_val &= VS_MODE_INTERRUPTS; > > + /* Only take VS* bits from mip. */ > > + ret_mip &= alias_mask; > > + > > + /* Take in non-delegated 13:63 bits from hvip. */ > > + old_hvip &= nalias_mask; > > + > > + *ret_val = ret_mip | old_hvip; > > } > > > > return ret; > > @@ -4527,14 +4689,13 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { > > .min_priv_ver = PRIV_VERSION_1_12_0 > > }, > > > > /* Virtual Interrupts and Interrupt Priorities (H-extension with AIA) > > */ > > - [CSR_HVIEN] = { "hvien", aia_hmode, read_zero, > > write_ignore }, > > + [CSR_HVIEN] = { "hvien", aia_hmode, NULL, NULL, rmw_hvien > > }, > > [CSR_HVICTL] = { "hvictl", aia_hmode, read_hvictl, > > write_hvictl > > }, > > [CSR_HVIPRIO1] = { "hviprio1", aia_hmode, read_hviprio1, > > write_hviprio1 > > }, > > [CSR_HVIPRIO2] = { "hviprio2", aia_hmode, read_hviprio2, > > write_hviprio2 > > }, > > - > > /* > > * VS-Level Window to Indirectly Accessed Registers (H-extension with > > AIA) > > */ > > @@ -4549,8 +4710,7 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { > > /* Hypervisor and VS-Level High-Half CSRs (H-extension with AIA) */ > > [CSR_HIDELEGH] = { "hidelegh", aia_hmode32, NULL, NULL, > > rmw_hidelegh > > }, > > - [CSR_HVIENH] = { "hvienh", aia_hmode32, read_zero, > > - write_ignore > > }, > > + [CSR_HVIENH] = { "hvienh", aia_hmode32, NULL, NULL, > > rmw_hvienh }, > > [CSR_HVIPH] = { "hviph", aia_hmode32, NULL, NULL, > > rmw_hviph }, > > [CSR_HVIPRIO1H] = { "hviprio1h", aia_hmode32, read_hviprio1h, > > write_hviprio1h > > }, > > diff --git a/target/riscv/machine.c b/target/riscv/machine.c > > index dd7bdbb691..3fff230a1c 100644 > > --- a/target/riscv/machine.c > > +++ b/target/riscv/machine.c > > @@ -92,6 +92,8 @@ static const VMStateDescription vmstate_hyper = { > > VMSTATE_UINTTL(env.hgatp, RISCVCPU), > > VMSTATE_UINTTL(env.hgeie, RISCVCPU), > > VMSTATE_UINTTL(env.hgeip, RISCVCPU), > > + VMSTATE_UINT64(env.hvien, RISCVCPU), > > + VMSTATE_UINT64(env.hvip, RISCVCPU), > > VMSTATE_UINT64(env.htimedelta, RISCVCPU), > > VMSTATE_UINT64(env.vstimecmp, RISCVCPU), > > > > @@ -106,6 +108,7 @@ static const VMStateDescription vmstate_hyper = { > > VMSTATE_UINTTL(env.vstval, RISCVCPU), > > VMSTATE_UINTTL(env.vsatp, RISCVCPU), > > VMSTATE_UINTTL(env.vsiselect, RISCVCPU), > > + VMSTATE_UINT64(env.vsie, RISCVCPU), > > > > VMSTATE_UINTTL(env.mtval2, RISCVCPU), > > VMSTATE_UINTTL(env.mtinst, RISCVCPU),