[PATCH 0/2] RISC-V APLIC fixes

2024-03-06 Thread Anup Patel
Few fixes for RISC-V APLIC discovered during Linux AIA patch reviews.

These patches can also be found in the apatel_aplic_fixes_v1 branch at:
https://github.com/avpatel/qemu.git

Anup Patel (2):
  hw/intc/riscv_aplic: Fix setipnum_le write emulation for APLIC
MSI-mode
  hw/intc/riscv_aplic: Fix in_clrip[x] read emulation

 hw/intc/riscv_aplic.c | 37 +++--
 1 file changed, 31 insertions(+), 6 deletions(-)

-- 
2.34.1




[PATCH 2/2] hw/intc/riscv_aplic: Fix in_clrip[x] read emulation

2024-03-06 Thread Anup Patel
The reads to in_clrip[x] registers return rectified input values of the
interrupt sources.

A rectified input value of an interrupt source is defined by the section
"4.5.2 Source configurations (sourcecfg[1]–sourcecfg[1023])" of the RISC-V
AIA specification as:
"rectified input value = (incoming wire value) XOR (source is inverted)"

Update the riscv_aplic_read_input_word() implementation to match the above.

Fixes: e8f79343cfc8 ("hw/intc: Add RISC-V AIA APLIC device emulation")
Signed-off-by: Anup Patel 
---
 hw/intc/riscv_aplic.c | 17 +++--
 1 file changed, 15 insertions(+), 2 deletions(-)

diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
index 775bb96164..6a7fbfa861 100644
--- a/hw/intc/riscv_aplic.c
+++ b/hw/intc/riscv_aplic.c
@@ -162,7 +162,7 @@ static bool is_kvm_aia(bool msimode)
 static uint32_t riscv_aplic_read_input_word(RISCVAPLICState *aplic,
 uint32_t word)
 {
-uint32_t i, irq, ret = 0;
+uint32_t i, irq, sourcecfg, sm, raw_input, irq_inverted, ret = 0;
 
 for (i = 0; i < 32; i++) {
 irq = word * 32 + i;
@@ -170,7 +170,20 @@ static uint32_t 
riscv_aplic_read_input_word(RISCVAPLICState *aplic,
 continue;
 }
 
-ret |= ((aplic->state[irq] & APLIC_ISTATE_INPUT) ? 1 : 0) << i;
+sourcecfg = aplic->sourcecfg[irq];
+if (sourcecfg & APLIC_SOURCECFG_D) {
+continue;
+}
+
+sm = sourcecfg & APLIC_SOURCECFG_SM_MASK;
+if (sm == APLIC_SOURCECFG_SM_INACTIVE) {
+continue;
+}
+
+raw_input = (aplic->state[irq] & APLIC_ISTATE_INPUT) ? 1 : 0;
+irq_inverted = (sm == APLIC_SOURCECFG_SM_LEVEL_LOW ||
+sm == APLIC_SOURCECFG_SM_EDGE_FALL) ? 1 : 0;
+ret |= (raw_input ^ irq_inverted) << i;
 }
 
 return ret;
-- 
2.34.1




[PATCH 1/2] hw/intc/riscv_aplic: Fix setipnum_le write emulation for APLIC MSI-mode

2024-03-06 Thread Anup Patel
The writes to setipnum_le register in APLIC MSI-mode have special
consideration for level-triggered interrupts as-per section "4.9.2
Special consideration for level-sensitive interrupt sources" of the
RISC-V AIA specification.

Particularly, the below text from the RISC-V specification defines
the behaviour of writes to setipnum_le for level-triggered interrupts:

"A second option is for the interrupt service routine to write the
APLIC’s source identity number for the interrupt to the domain’s
setipnum register just before exiting. This will cause the interrupt’s
pending bit to be set to one again if the source is still asserting
an interrupt, but not if the source is not asserting an interrupt."

Fix setipnum_le write emulation for APLIC MSI-mode by implementing
the above behaviour in riscv_aplic_set_pending() function.

Fixes: e8f79343cfc8 ("hw/intc: Add RISC-V AIA APLIC device emulation")
Signed-off-by: Anup Patel 
---
 hw/intc/riscv_aplic.c | 20 
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
index e98e258deb..775bb96164 100644
--- a/hw/intc/riscv_aplic.c
+++ b/hw/intc/riscv_aplic.c
@@ -218,13 +218,25 @@ static void riscv_aplic_set_pending(RISCVAPLICState 
*aplic,
 }
 
 sm = sourcecfg & APLIC_SOURCECFG_SM_MASK;
-if ((sm == APLIC_SOURCECFG_SM_INACTIVE) ||
-((!aplic->msimode || (aplic->msimode && !pending)) &&
- ((sm == APLIC_SOURCECFG_SM_LEVEL_HIGH) ||
-  (sm == APLIC_SOURCECFG_SM_LEVEL_LOW {
+if (sm == APLIC_SOURCECFG_SM_INACTIVE) {
 return;
 }
 
+if ((sm == APLIC_SOURCECFG_SM_LEVEL_HIGH) ||
+(sm == APLIC_SOURCECFG_SM_LEVEL_LOW)) {
+if (!aplic->msimode || (aplic->msimode && !pending)) {
+return;
+}
+if ((aplic->state[irq] & APLIC_ISTATE_INPUT) &&
+(sm == APLIC_SOURCECFG_SM_LEVEL_LOW)) {
+return;
+}
+if (!(aplic->state[irq] & APLIC_ISTATE_INPUT) &&
+(sm == APLIC_SOURCECFG_SM_LEVEL_HIGH)) {
+return;
+}
+}
+
 riscv_aplic_set_pending_raw(aplic, irq, pending);
 }
 
-- 
2.34.1




Re: [PATCH v3 0/2] Export debug triggers as an extension

2024-02-29 Thread Anup Patel
On Thu, Feb 29, 2024 at 8:42 PM Andrew Jones  wrote:
>
> On Thu, Feb 29, 2024 at 07:07:43PM +0530, Himanshu Chauhan wrote:
> > All the CPUs may or may not implement the debug triggers (sdtrig)
> > extension. The presence of it should be dynamically detectable.
> > This patch exports the debug triggers as an extension which
> > can be turned on or off by sdtrig= option. It is
> > turned on by default.
> >
> > "sdtrig" is concatenated to ISA string when it is enabled.
> > Like so:
> > rv64imafdch_zicbom_*_sdtrig_*_sstc_svadu
> >
> > Changes from v1:
> >- Replaced the debug property with ext_sdtrig
> >- Marked it experimenatal by naming it x-sdtrig
> >- x-sdtrig is added to ISA string
> >- Reversed the patch order
> >
> > Changes from v2:
> >- Mark debug property as deprecated and replace internally with sdtrig 
> > extension
>
> I'm getting lost in our discussions, but I thought we needed both in case
> a machine only implements debug 0.13, since sdtrig is at least 'more than'
> debug, even if backwards compatible (which I also wasn't sure was the
> case). If, OTOH, QEMU's debug implementation exactly implements sdtrig's
> specification, then I'm in favor of deprecating the 'debug' extension.

The QEMU's debug implementation aligns more with Sdtrig v1.0 specification
because we have mcontrol6 which was not present in debug 0.13

IMO, we should definitely depricate debug 0.13

Regards,
Anup

>
> Thanks,
> drew
>
>
> >- setting/unsetting debug property shows warning and sets/unsets 
> > ext_sdtrig
> >- sdtrig is added to ISA string as RISC-V debug specification is frozen
> >
> > Himanshu Chauhan (2):
> >   target/riscv: Mark debug property as deprecated
> >   target/riscv: Export sdtrig in ISA string
> >
> >  target/riscv/cpu.c| 38 +++---
> >  target/riscv/cpu_cfg.h|  2 +-
> >  target/riscv/cpu_helper.c |  2 +-
> >  target/riscv/csr.c|  2 +-
> >  target/riscv/machine.c|  2 +-
> >  5 files changed, 39 insertions(+), 7 deletions(-)
> >
> > --
> > 2.34.1
> >
> >
>



Re: Re: [PATCH 0/2] Export debug triggers as an extension

2024-02-04 Thread Anup Patel
On Mon, Feb 5, 2024 at 9:36 AM Alistair Francis  wrote:
>
> On Mon, Jan 22, 2024 at 7:16 PM Andrew Jones  wrote:
> >
> > On Mon, Jan 22, 2024 at 03:42:10PM +1000, Alistair Francis wrote:
> > > > > From memory the "debug" property is for the original debug spec:
> > > > > https://github.com/riscv/riscv-debug-spec/releases/tag/task_group_vote
> > > > >
> > > > > That was ratified and is an official extension. AFAIK this is what is
> > > > > in physical hardware as well.
> > > > >
> > > > > The actual PDF says draft though, I'm not sure what's going on there.
> > > > >
> > > > > The debug spec doesn't have a Z* name, so it's just "debug", at least
> > > > > AFAIK.
> > > > >
> > > > > "sdtrig" seems to be a new backwards-incompatible extension doing
> > > > > basically the same thing. What a mess
> > ...
> > > >
> > > > I've done a bit of digging and I agree things are quite messy. Here are
> > > > my discoveries:
> > > >
> > > > The debug option and the code for triggers was added in these commits:
> > > >
> > > > c9711bd778 target/riscv: cpu: Enable native debug feature
> > > > 38b4e781a4 target/riscv: machine: Add debug state description
> > > > b6092544fc target/riscv: csr: Hook debug CSR read/write
> > > > 1acdb3b013 target/riscv: cpu: Add a config option for native debug
> > > > 95799e36c1 target/riscv: Add initial support for the Sdtrig extension
> > > >
> > > > In March 2022 - since the commit refers to the Sdtrig extension name
> > > > and from the date this was an implementation not of the ratified 0.13
> > > > debug spec (which did not have Sdtrig as a separate extension) but
> > > > rather a version of the in development 1.0 debug spec.
> > >
> > > Yeah... We used the "stable" from master. That is our mistake there.
> > >
> > > I'm pretty sure we targeted the 0.13. The "Sdtrig" was only added in
> > > the v4 as the changelog says: "mention Sdtrig extension in the commit"
> > >
> > > >
> > > > It's not trivial to tell if it's closer to the ratified 0.13 version or
> > > > the (hopefully soon to be frozen) 1.0 version.
> > > >
> > > > As the only part of the debug specification to be implemented is the
> > > > triggers then effectively the debug option is x-sdtrig.
> > > >
> > > > I don't think there is any way for code running on the machine to
> > > > identify what version of the debug is implemented - the appropriate
> > > > register is only available for external debug. Once 1.0 is frozen then
> > > > the presence of Sdtrig isa string would indicate 1.0 trigger support is
> > > > available.
> > > >
> > > > According to JIRA - https://jira.riscv.org/browse/RVS-981 the debug
> > > > specification should freeze this month.
> > > >
> > > > How about considering this as a solution:
> > > >
> > > > - Add a new x-sdtrig option that defaults to false
> > > > - Deprecate debug option - but retain it with default on
> > >
> > > We can't deprecate a ratified spec. The 0.13 just seems to call it
> > > "debug" so that's what we are stuck with
> > >
> > > > - Add warning if triggers are used and x-sdtrig is not enabled
> > > > - Update the trigger implementation to match frozen spec
> > >
> > > We will need to support two versions, as there are two ratified specs.
> > >
> >
> > We'll likely want to be allowed to deprecate ratified extensions as riscv
> > evolves. Despite best intentions, extensions may be designed and ratified
> > which ultimately fail to be of much utility, and new extensions will
> > supersede old extensions. If QEMU keeps every extension it adds, then
> > we'll slow progress on new extensions by maintaining old extension code.
> > The old extensions will also bitrot or waste CI resources getting tested
> > for no reason.
>
> I agree that we might need to deprecate extensions.
>
> I'm not sure the debug extension is there though. The debug extension
> is used in current shipping hardware and has been ratified. The Sdtrig
> isn't even ratified yet
> (https://lists.riscv.org/g/tech-announce/message/320)

Is shipping real hardware OR ratification a requirement of
QEMU patch acceptance ?

Regards,
Anup

>
> Right now I feel that we should at least wait for hardware that
> supports Sdtrig to start to come out. Then we can look at deprecating
> debug. Deprecating it now seems a bit premature.
>
> Alistair
>
> >
> > I don't know the history of 'debug' and 'sdtrig', other than what I've
> > read above, but, to me, it looks like 'debug' might be one of the first
> > extensions which should be deprecated. Assuming we have a long enough
> > deprecation period, then I think it's always safe to attempt a
> > deprecation. If somebody shouts, then it can always be taken back off the
> > chopping block.
> >
> > Thanks,
> > drew
> >
>



Re: [PATCH v2 1/2] target/riscv: Convert sdtrig functionality from property to an extension

2024-01-18 Thread Anup Patel
On Wed, Jan 17, 2024 at 7:54 PM Himanshu Chauhan
 wrote:
>
> The debug trigger (sdtrig) capability is controlled using the debug property.
> The sdtrig is an ISA extension and should be treated so. The sdtrig extension
> may or may not be implemented in a system. Therefore, it must raise an illegal
> instruction exception when it is disabled and its CSRs are accessed.
>
> This patch removes the "debug" property and replaces it with ext_sdtrig 
> extension.
> It also raises an illegal instruction exception when the extension is 
> disabled and
> its CSRs are accessed.
>
> Signed-off-by: Himanshu Chauhan 
> ---
>  target/riscv/cpu.c| 7 +++
>  target/riscv/cpu_cfg.h| 2 +-
>  target/riscv/cpu_helper.c | 2 +-
>  target/riscv/csr.c| 2 +-
>  target/riscv/machine.c| 2 +-
>  5 files changed, 7 insertions(+), 8 deletions(-)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index b07a76ef6b..c770a7e506 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -909,7 +909,7 @@ static void riscv_cpu_reset_hold(Object *obj)
>  set_default_nan_mode(1, >fp_status);
>
>  #ifndef CONFIG_USER_ONLY
> -if (cpu->cfg.debug) {
> +if (cpu->cfg.ext_sdtrig) {
>  riscv_trigger_reset_hold(env);
>  }
>
> @@ -1068,7 +1068,7 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
> **errp)
>  riscv_cpu_register_gdb_regs_for_features(cs);
>
>  #ifndef CONFIG_USER_ONLY
> -if (cpu->cfg.debug) {
> +if (cpu->cfg.ext_sdtrig) {
>  riscv_trigger_realize(>env);
>  }
>  #endif
> @@ -1393,6 +1393,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[] = {
>
>  /* These are experimental so mark with 'x-' */
>  const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[] = {
> +MULTI_EXT_CFG_BOOL("x-sdtrig", ext_sdtrig, true),

Drop the "x-" because Sdtrig is already frozen and public review has started.

>  MULTI_EXT_CFG_BOOL("x-smaia", ext_smaia, false),
>  MULTI_EXT_CFG_BOOL("x-ssaia", ext_ssaia, false),
>
> @@ -1480,8 +1481,6 @@ Property riscv_cpu_options[] = {
>  };
>
>  static Property riscv_cpu_properties[] = {
> -DEFINE_PROP_BOOL("debug", RISCVCPU, cfg.debug, true),
> -
>  #ifndef CONFIG_USER_ONLY
>  DEFINE_PROP_UINT64("resetvec", RISCVCPU, env.resetvec, DEFAULT_RSTVEC),
>  #endif
> diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
> index f4605fb190..341ebf726a 100644
> --- a/target/riscv/cpu_cfg.h
> +++ b/target/riscv/cpu_cfg.h
> @@ -109,6 +109,7 @@ struct RISCVCPUConfig {
>  bool ext_zvfbfwma;
>  bool ext_zvfh;
>  bool ext_zvfhmin;
> +bool ext_sdtrig;
>  bool ext_smaia;
>  bool ext_ssaia;
>  bool ext_sscofpmf;
> @@ -145,7 +146,6 @@ struct RISCVCPUConfig {
>  uint16_t cboz_blocksize;
>  bool mmu;
>  bool pmp;
> -bool debug;
>  bool misa_w;
>
>  bool short_isa_string;
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index e7e23b34f4..3f7c2f1315 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -126,7 +126,7 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
>   ? EXT_STATUS_DIRTY : EXT_STATUS_DISABLED;
>  }
>
> -if (cpu->cfg.debug && !icount_enabled()) {
> +if (cpu->cfg.ext_sdtrig && !icount_enabled()) {
>  flags = FIELD_DP32(flags, TB_FLAGS, ITRIGGER, env->itrigger_enabled);
>  }
>  #endif
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index c50a33397c..8dbb49aa88 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -543,7 +543,7 @@ static RISCVException have_mseccfg(CPURISCVState *env, 
> int csrno)
>
>  static RISCVException debug(CPURISCVState *env, int csrno)
>  {
> -if (riscv_cpu_cfg(env)->debug) {
> +if (riscv_cpu_cfg(env)->ext_sdtrig) {
>  return RISCV_EXCP_NONE;
>  }
>
> diff --git a/target/riscv/machine.c b/target/riscv/machine.c
> index 72fe2374dc..8f9787a30f 100644
> --- a/target/riscv/machine.c
> +++ b/target/riscv/machine.c
> @@ -231,7 +231,7 @@ static bool debug_needed(void *opaque)
>  {
>  RISCVCPU *cpu = opaque;
>
> -return cpu->cfg.debug;
> +return cpu->cfg.ext_sdtrig;
>  }
>
>  static int debug_post_load(void *opaque, int version_id)
> --
> 2.34.1
>
>

Regards,
Anup



Re: [PATCH] hw/riscv: split RAM into low and high memory

2023-09-07 Thread Anup Patel
t; only 1 Gb of RAM
> > > (-m 1Gb). If I try with -m 1.1Gb I reproduce this error. This can be a
> > > validation of
> > > the guess I'm making here: Ubuntu is trying to fetch stuff (probably the
> > > fdt) from
> > > the gap between the memory areas.
> > >
> > > This change on top of this patch doesn't work either:
> > >
> > > $ git diff
> > > diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> > > index 8fbdc7220c..dfff48d849 100644
> > > --- a/hw/riscv/virt.c
> > > +++ b/hw/riscv/virt.c
> > > @@ -1335,9 +1335,16 @@ static void virt_machine_done(Notifier *notifier,
> > > void *data)
> > >   kernel_start_addr, true, NULL);
> > >  }
> > >
> > > -fdt_load_addr = riscv_compute_fdt_addr(memmap[VIRT_DRAM].base,
> > > +if (machine->ram_size < memmap[VIRT_DRAM].size) {
> > > +fdt_load_addr = riscv_compute_fdt_addr(memmap[VIRT_DRAM].base,
> > >     memmap[VIRT_DRAM].size,
> > > machine);
> > > +} else {
> > > +fdt_load_addr =
> > > riscv_compute_fdt_addr(memmap[VIRT_DRAM_HIGH].base,
> > > +   memmap[VIRT_DRAM_HIGH].size,
> > > +   machine);
> > > +}
> > > +
> > >
> > > This would put the fdt at the end of the HI RAM for guests with more
> > > than 1Gb of RAM.
> > > This change in fact makes the situation even worse, breaking setups that
> > > were working
> > > before with this patch.
> > >
> > > There's a chance that reducing the gap between the RAM banks can make
> > > Ubuntu work
> > > reliably again but now I'm a little cold feet with this change.
> > >
> > >
> > > I think we'll need some kernel/Opensbi folks to weight in here to see if
> > > there's a
> > > failsafe memory setup that won't break distros out there and allow your
> > > passthrough
> > > to work.
> > >
> > Hi Daniel,
> >
> > Do you know who we should talk to? I think it's not uncommon to have
> > seperated multi-range memory, the stack should support this configuration.
>
> @Palmer Dabbelt @Anup Patel any ideas?
>

Sparse memory and multiple memory banks are a reality and seen
on many platforms.

Based on my experience:
* Linux RISC-V already supports SPARSEMEM and multiple
  RAM banks.
* OpenSBI also handles multiple RAM banks nicely.
* U-Boot requires some kconfig option setting otherwise
   even U-Boot handles it fine.

Regards,
Anup



Re: [PATCH] hw/riscv: split RAM into low and high memory

2023-09-07 Thread Anup Patel
On Tue, Aug 1, 2023 at 4:16 AM Daniel Henrique Barboza
 wrote:
>
>
>
> On 7/30/23 22:53, Fei Wu wrote:
> > riscv virt platform's memory started at 0x8000 and
> > straddled the 4GiB boundary. Curiously enough, this choice
> > of a memory layout will prevent from launching a VM with
> > a bit more than 2000MiB and PCIe pass-thru on an x86 host, due
> > to identity mapping requirements for the MSI doorbell on x86,
> > and these (APIC/IOAPIC) live right below 4GiB.
> >
> > So just split the RAM range into two portions:
> > - 1 GiB range from 0x8000 to 0xc000.
> > - The remainder at 0x1
> >
> > ...leaving a hole between the ranges.
>
> I am afraid this breaks some existing distro setups, like Ubuntu. After this 
> patch
> this emulation stopped working:
>
> ~/work/qemu/build/qemu-system-riscv64 \
> -machine virt -nographic -m 8G -smp 8 \
> -kernel ./uboot-ubuntu/usr/lib/u-boot/qemu-riscv64_smode/uboot.elf \
> -drive file=snapshot.img,format=qcow2,if=virtio \
> -netdev bridge,id=bridge1,br=virbr0 -device 
> virtio-net-pci,netdev=bridge1
>
>
> This is basically a guest created via the official Canonical tutorial:
>
> https://wiki.ubuntu.com/RISC-V/QEMU
>
> The error being thrown:
>
> =
>
> Boot HART ID  : 4
> Boot HART Domain  : root
> Boot HART Priv Version: v1.12
> Boot HART Base ISA: rv64imafdch
> Boot HART ISA Extensions  : time,sstc
> Boot HART PMP Count   : 16
> Boot HART PMP Granularity : 4
> Boot HART PMP Address Bits: 54
> Boot HART MHPM Count  : 16
> Boot HART MIDELEG : 0x1666
> Boot HART MEDELEG : 0x00f0b509
>
>
> U-Boot 2022.07+dfsg-1ubuntu4.2 (Nov 24 2022 - 18:47:41 +)
>
> CPU:   
> rv64imafdch_zicbom_zicboz_zicsr_zifencei_zihintpause_zawrs_zfa_zca_zcd_zba_zbb_zbc_zbs_sstc_svadu
> Model: riscv-virtio,qemu
> DRAM:  Unhandled exception: Store/AMO access fault
> EPC: 802018b8 RA: 802126a0 TVAL: ff733f90
>
> Code: b823 06b2 bc23 06b2 b023 08b2 b423 08b2 (b823 08b2)
>
>
> resetting ...
> System reset not supported on this platform
> ### ERROR ### Please RESET the board ###
> QEMU 8.0.90 monitor - type 'help' for more infor
> =

Can you try again after setting CONFIG_NR_DRAM_BANKS=2 in
qemu-riscv64_smode_defconfig and qemu-riscv64_spl_defconfig ?

Regards,
Anup

>
>
> Based on the change made I can make an educated guess on what is going wrong.
> We have another board with a similar memory topology you're making here, the
> Microchip Polarfire (microchip_pfsoc.c). We were having some problems with 
> this
> board while trying to consolidate the boot process between all boards in
> hw/riscv/boot.c because of its non-continuous RAM bank. The full story can be
> read in the commit message of 4b402886ac89 ("hw/riscv: change 
> riscv_compute_fdt_addr()
> semantics") but the short version can be seen in riscv_compute_fdt_addr()
> from boot.c:
>
>   - if ram_start is less than 3072MiB, the FDT will be  put at the lowest 
> value
> between 3072 MiB and the end of that RAM bank;
>
> - if ram_start is higher than 3072 MiB the FDT will be put at the end of the
> RAM bank.
>
> So, after this patch, since riscv_compute_fdt_addr() is being used with the 
> now
> lower RAM bank, the fdt is being put in LOW_MEM - fdt_size for any setup that 
> has
> more than 1Gb RAM, and this breaks assumptions made by uboot and Ubuntu and 
> possibly
> others that are trying to retrieve the FDT from the gap that you created 
> between
> low and hi mem in this patch.
>
> In fact, this same Ubuntu guest I mentioned above will boot if I put only 1 
> Gb of RAM
> (-m 1Gb). If I try with -m 1.1Gb I reproduce this error. This can be a 
> validation of
> the guess I'm making here: Ubuntu is trying to fetch stuff (probably the fdt) 
> from
> the gap between the memory areas.
>
> This change on top of this patch doesn't work either:
>
> $ git diff
> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> index 8fbdc7220c..dfff48d849 100644
> --- a/hw/riscv/virt.c
> +++ b/hw/riscv/virt.c
> @@ -1335,9 +1335,16 @@ static void virt_machine_done(Notifier *notifier, void 
> *data)
>kernel_start_addr, true, NULL);
>   }
>
> -fdt_load_addr = riscv_compute_fdt_addr(memmap[VIRT_DRAM].base,
> +if (machine->ram_size < memmap[VIRT_DRAM].size) {
> +fdt_load_addr = riscv_compute_fdt_addr(memmap[VIRT_DRAM].base,
>  memmap[VIRT_DRAM].size,
>  machine);
> +} else {
> +fdt_load_addr = riscv_compute_fdt_addr(memmap[VIRT_DRAM_HIGH].base,
> +   memmap[VIRT_DRAM_HIGH].size,
> +   machine);
> +}
> +
>
>
> This would put the fdt at the end of the HI RAM for guests with more than 1Gb 
> of RAM.
> This change in fact makes the situation even worse, 

Re: Boot failure after QEMU's upgrade to OpenSBI v1.3 (was Re: [PATCH for-8.2 6/7] target/riscv: add 'max' CPU type)

2023-07-19 Thread Anup Patel
Hi Bin,

On Wed, Jul 19, 2023 at 9:15 PM Bin Meng  wrote:
>
> On Wed, Jul 19, 2023 at 11:22 PM Anup Patel  wrote:
> >
> > On Wed, Jul 19, 2023 at 3:23 PM Alistair Francis  
> > wrote:
> > >
> > > On Wed, Jul 19, 2023 at 3:39 PM Anup Patel  wrote:
> > > >
> > > > On Wed, Jul 19, 2023 at 7:03 AM Alistair Francis  
> > > > wrote:
> > > > >
> > > > > On Sat, Jul 15, 2023 at 7:14 PM Atish Patra  
> > > > > wrote:
> > > > > >
> > > > > > On Fri, Jul 14, 2023 at 5:29 AM Conor Dooley  
> > > > > > wrote:
> > > > > > >
> > > > > > > On Fri, Jul 14, 2023 at 11:19:34AM +0100, Conor Dooley wrote:
> > > > > > > > On Fri, Jul 14, 2023 at 10:00:19AM +0530, Anup Patel wrote:
> > > > > > > >
> > > > > > > > > > > OpenSBI v1.3
> > > > > > > > > > >_  _
> > > > > > > > > > >   / __ \  / |  _ \_   _|
> > > > > > > > > > >  | |  | |_ __   ___ _ __ | (___ | |_) || |
> > > > > > > > > > >  | |  | | '_ \ / _ \ '_ \ \___ \|  _ < | |
> > > > > > > > > > >  | |__| | |_) |  __/ | | |) | |_) || |_
> > > > > > > > > > >   \/| .__/ \___|_| |_|_/|___/_|
> > > > > > > > > > > | |
> > > > > > > > > > > |_|
> > > > > > > > > > >
> > > > > > > > > > > init_coldboot: ipi init failed (error -1009)
> > > > > > > > > > >
> > > > > > > > > > > Just to note, because we use our own firmware that 
> > > > > > > > > > > vendors in OpenSBI
> > > > > > > > > > > and compiles only a significantly cut down number of 
> > > > > > > > > > > files from it, we
> > > > > > > > > > > do not use the fw_dynamic etc flow on our hardware. As a 
> > > > > > > > > > > result, we have
> > > > > > > > > > > not tested v1.3, nor do we have any immediate plans to 
> > > > > > > > > > > change our
> > > > > > > > > > > platform firmware to vendor v1.3 either.
> > > > > > > > > > >
> > > > > > > > > > > I unless there's something obvious to you, it sounds like 
> > > > > > > > > > > I will need to
> > > > > > > > > > > go and bisect OpenSBI. That's a job for another day 
> > > > > > > > > > > though, given the
> > > > > > > > > > > time.
> > > > > > > > > > >
> > > > > > > > >
> > > > > > > > > The real issue is some CPU/HART DT nodes marked as disabled 
> > > > > > > > > in the
> > > > > > > > > DT passed to OpenSBI 1.3.
> > > > > > > > >
> > > > > > > > > This issue does not exist in any of the DTs generated by QEMU 
> > > > > > > > > but some
> > > > > > > > > of the DTs in the kernel (such as microchip and SiFive board 
> > > > > > > > > DTs) have
> > > > > > > > > the E-core disabled.
> > > > > > > > >
> > > > > > > > > I had discovered this issue in a totally different context 
> > > > > > > > > after the OpenSBI 1.3
> > > > > > > > > release happened. This issue is already fixed in the latest 
> > > > > > > > > OpenSBI by the
> > > > > > > > > following commit c6a35733b74aeff612398f274ed19a74f81d1f37 
> > > > > > > > > ("lib: utils:
> > > > > > > > > Fix sbi_hartid_to_scratch() usage in ACLINT drivers").
> > > > > > > >
> > > > > > > > Great, thanks Anup! I thought I had tested tip-of-tree too, but
> > > > > > > > obviously not.
> > > > > > > >
> > > > > > > > > I always assumed that Microchip h

Re: Boot failure after QEMU's upgrade to OpenSBI v1.3 (was Re: [PATCH for-8.2 6/7] target/riscv: add 'max' CPU type)

2023-07-19 Thread Anup Patel
On Wed, Jul 19, 2023 at 3:23 PM Alistair Francis  wrote:
>
> On Wed, Jul 19, 2023 at 3:39 PM Anup Patel  wrote:
> >
> > On Wed, Jul 19, 2023 at 7:03 AM Alistair Francis  
> > wrote:
> > >
> > > On Sat, Jul 15, 2023 at 7:14 PM Atish Patra  wrote:
> > > >
> > > > On Fri, Jul 14, 2023 at 5:29 AM Conor Dooley  wrote:
> > > > >
> > > > > On Fri, Jul 14, 2023 at 11:19:34AM +0100, Conor Dooley wrote:
> > > > > > On Fri, Jul 14, 2023 at 10:00:19AM +0530, Anup Patel wrote:
> > > > > >
> > > > > > > > > OpenSBI v1.3
> > > > > > > > >_  _
> > > > > > > > >   / __ \  / |  _ \_   _|
> > > > > > > > >  | |  | |_ __   ___ _ __ | (___ | |_) || |
> > > > > > > > >  | |  | | '_ \ / _ \ '_ \ \___ \|  _ < | |
> > > > > > > > >  | |__| | |_) |  __/ | | |) | |_) || |_
> > > > > > > > >   \/| .__/ \___|_| |_|_/|___/_|
> > > > > > > > > | |
> > > > > > > > > |_|
> > > > > > > > >
> > > > > > > > > init_coldboot: ipi init failed (error -1009)
> > > > > > > > >
> > > > > > > > > Just to note, because we use our own firmware that vendors in 
> > > > > > > > > OpenSBI
> > > > > > > > > and compiles only a significantly cut down number of files 
> > > > > > > > > from it, we
> > > > > > > > > do not use the fw_dynamic etc flow on our hardware. As a 
> > > > > > > > > result, we have
> > > > > > > > > not tested v1.3, nor do we have any immediate plans to change 
> > > > > > > > > our
> > > > > > > > > platform firmware to vendor v1.3 either.
> > > > > > > > >
> > > > > > > > > I unless there's something obvious to you, it sounds like I 
> > > > > > > > > will need to
> > > > > > > > > go and bisect OpenSBI. That's a job for another day though, 
> > > > > > > > > given the
> > > > > > > > > time.
> > > > > > > > >
> > > > > > >
> > > > > > > The real issue is some CPU/HART DT nodes marked as disabled in the
> > > > > > > DT passed to OpenSBI 1.3.
> > > > > > >
> > > > > > > This issue does not exist in any of the DTs generated by QEMU but 
> > > > > > > some
> > > > > > > of the DTs in the kernel (such as microchip and SiFive board DTs) 
> > > > > > > have
> > > > > > > the E-core disabled.
> > > > > > >
> > > > > > > I had discovered this issue in a totally different context after 
> > > > > > > the OpenSBI 1.3
> > > > > > > release happened. This issue is already fixed in the latest 
> > > > > > > OpenSBI by the
> > > > > > > following commit c6a35733b74aeff612398f274ed19a74f81d1f37 ("lib: 
> > > > > > > utils:
> > > > > > > Fix sbi_hartid_to_scratch() usage in ACLINT drivers").
> > > > > >
> > > > > > Great, thanks Anup! I thought I had tested tip-of-tree too, but
> > > > > > obviously not.
> > > > > >
> > > > > > > I always assumed that Microchip hss.bin is the preferred BIOS for 
> > > > > > > the
> > > > > > > QEMU microchip-icicle-kit machine but I guess that's not true.
> > > > > >
> > > > > > Unfortunately the HSS has not worked in QEMU for a long time, and 
> > > > > > while
> > > > > > I would love to fix it, but am pretty stretched for spare time to 
> > > > > > begin
> > > > > > with.
> > > > > > I usually just do direct kernel boots, which use the OpenSBI that 
> > > > > > comes
> > > > > > with QEMU, as I am sure you already know :)
> > > > > >
> > > > > > > At this point, you can either:
> > > > > > > 1) Use latest OpenSBI on QEMU microchip-ici

Re: Boot failure after QEMU's upgrade to OpenSBI v1.3 (was Re: [PATCH for-8.2 6/7] target/riscv: add 'max' CPU type)

2023-07-18 Thread Anup Patel
On Wed, Jul 19, 2023 at 7:03 AM Alistair Francis  wrote:
>
> On Sat, Jul 15, 2023 at 7:14 PM Atish Patra  wrote:
> >
> > On Fri, Jul 14, 2023 at 5:29 AM Conor Dooley  wrote:
> > >
> > > On Fri, Jul 14, 2023 at 11:19:34AM +0100, Conor Dooley wrote:
> > > > On Fri, Jul 14, 2023 at 10:00:19AM +0530, Anup Patel wrote:
> > > >
> > > > > > > OpenSBI v1.3
> > > > > > >_  _
> > > > > > >   / __ \  / |  _ \_   _|
> > > > > > >  | |  | |_ __   ___ _ __ | (___ | |_) || |
> > > > > > >  | |  | | '_ \ / _ \ '_ \ \___ \|  _ < | |
> > > > > > >  | |__| | |_) |  __/ | | |) | |_) || |_
> > > > > > >   \/| .__/ \___|_| |_|_/|___/_|
> > > > > > > | |
> > > > > > > |_|
> > > > > > >
> > > > > > > init_coldboot: ipi init failed (error -1009)
> > > > > > >
> > > > > > > Just to note, because we use our own firmware that vendors in 
> > > > > > > OpenSBI
> > > > > > > and compiles only a significantly cut down number of files from 
> > > > > > > it, we
> > > > > > > do not use the fw_dynamic etc flow on our hardware. As a result, 
> > > > > > > we have
> > > > > > > not tested v1.3, nor do we have any immediate plans to change our
> > > > > > > platform firmware to vendor v1.3 either.
> > > > > > >
> > > > > > > I unless there's something obvious to you, it sounds like I will 
> > > > > > > need to
> > > > > > > go and bisect OpenSBI. That's a job for another day though, given 
> > > > > > > the
> > > > > > > time.
> > > > > > >
> > > > >
> > > > > The real issue is some CPU/HART DT nodes marked as disabled in the
> > > > > DT passed to OpenSBI 1.3.
> > > > >
> > > > > This issue does not exist in any of the DTs generated by QEMU but some
> > > > > of the DTs in the kernel (such as microchip and SiFive board DTs) have
> > > > > the E-core disabled.
> > > > >
> > > > > I had discovered this issue in a totally different context after the 
> > > > > OpenSBI 1.3
> > > > > release happened. This issue is already fixed in the latest OpenSBI 
> > > > > by the
> > > > > following commit c6a35733b74aeff612398f274ed19a74f81d1f37 ("lib: 
> > > > > utils:
> > > > > Fix sbi_hartid_to_scratch() usage in ACLINT drivers").
> > > >
> > > > Great, thanks Anup! I thought I had tested tip-of-tree too, but
> > > > obviously not.
> > > >
> > > > > I always assumed that Microchip hss.bin is the preferred BIOS for the
> > > > > QEMU microchip-icicle-kit machine but I guess that's not true.
> > > >
> > > > Unfortunately the HSS has not worked in QEMU for a long time, and while
> > > > I would love to fix it, but am pretty stretched for spare time to begin
> > > > with.
> > > > I usually just do direct kernel boots, which use the OpenSBI that comes
> > > > with QEMU, as I am sure you already know :)
> > > >
> > > > > At this point, you can either:
> > > > > 1) Use latest OpenSBI on QEMU microchip-icicle-kit machine
> > >
> > > I forgot to reply to this point, wondering what should be done with
> > > QEMU. Bumping to v1.3 in QEMU introduces a regression here, regardless
> > > of whether I can go and build a fixed version of OpenSBI.
> > >
> > FYI: The no-map fix went in OpenSBI v1.3. Without the upgrade, any
> > user using the latest kernel (> v6.4)
> > may hit those random linear map related issues (in hibernation or EFI
> > booting path).
> >
> > There are three possible scenarios:
> >
> > 1. Upgrade to OpenSBI v1.3: Any user of microchip-icicle-kit machine
> > or sifive fu540 machine users
> > may hit this issue if the device tree has the disabled hart (e core).
> > 2. No upgrade to OpenSBI v1.2. Any user using hibernation or UEFI may
> > have issues [1]
> > 3. Include a non-release version OpenSBI in Qemu with the fix as an 
> > exception.
> >
> > #3 probably deviates from polic

Re: Boot failure after QEMU's upgrade to OpenSBI v1.3 (was Re: [PATCH for-8.2 6/7] target/riscv: add 'max' CPU type)

2023-07-14 Thread Anup Patel
On Fri, Jul 14, 2023 at 3:50 PM Conor Dooley  wrote:
>
> On Fri, Jul 14, 2023 at 10:00:19AM +0530, Anup Patel wrote:
>
> > > > OpenSBI v1.3
> > > >_  _
> > > >   / __ \  / |  _ \_   _|
> > > >  | |  | |_ __   ___ _ __ | (___ | |_) || |
> > > >  | |  | | '_ \ / _ \ '_ \ \___ \|  _ < | |
> > > >  | |__| | |_) |  __/ | | |) | |_) || |_
> > > >   \/| .__/ \___|_| |_|_/|___/_|
> > > > | |
> > > > |_|
> > > >
> > > > init_coldboot: ipi init failed (error -1009)
> > > >
> > > > Just to note, because we use our own firmware that vendors in OpenSBI
> > > > and compiles only a significantly cut down number of files from it, we
> > > > do not use the fw_dynamic etc flow on our hardware. As a result, we have
> > > > not tested v1.3, nor do we have any immediate plans to change our
> > > > platform firmware to vendor v1.3 either.
> > > >
> > > > I unless there's something obvious to you, it sounds like I will need to
> > > > go and bisect OpenSBI. That's a job for another day though, given the
> > > > time.
> > > >
> >
> > The real issue is some CPU/HART DT nodes marked as disabled in the
> > DT passed to OpenSBI 1.3.
> >
> > This issue does not exist in any of the DTs generated by QEMU but some
> > of the DTs in the kernel (such as microchip and SiFive board DTs) have
> > the E-core disabled.
> >
> > I had discovered this issue in a totally different context after the 
> > OpenSBI 1.3
> > release happened. This issue is already fixed in the latest OpenSBI by the
> > following commit c6a35733b74aeff612398f274ed19a74f81d1f37 ("lib: utils:
> > Fix sbi_hartid_to_scratch() usage in ACLINT drivers").
>
> Great, thanks Anup! I thought I had tested tip-of-tree too, but
> obviously not.
>
> > I always assumed that Microchip hss.bin is the preferred BIOS for the
> > QEMU microchip-icicle-kit machine but I guess that's not true.
>
> Unfortunately the HSS has not worked in QEMU for a long time, and while
> I would love to fix it, but am pretty stretched for spare time to begin
> with.
> I usually just do direct kernel boots, which use the OpenSBI that comes
> with QEMU, as I am sure you already know :)
>
> > At this point, you can either:
> > 1) Use latest OpenSBI on QEMU microchip-icicle-kit machine
>
> > 2) Ensure CPU0 DT node is enabled in DT when booting on QEMU
> > microchip-icicle-kit machine with OpenSBI 1.3
>
> Will OpenSBI disable it? If not, I think option 2) needs to be remove
> the DT node. I'll just use tip-of-tree myself & up to the

Current, FDT fixup code in OpenSBI will disable any CPU DT node
which satisfies any of the following:
1) CPU is not assigned to the current domain
2) CPU does not have "mmu-type" DT property

Regards,
Anup



Re: Boot failure after QEMU's upgrade to OpenSBI v1.3 (was Re: [PATCH for-8.2 6/7] target/riscv: add 'max' CPU type)

2023-07-13 Thread Anup Patel
On Fri, Jul 14, 2023 at 3:43 AM Conor Dooley  wrote:
>
> +CC OpenSBI Mailing list
>
> I've not yet had the chance to bisect this, so adding the OpenSBI folks
> to CC in case they might have an idea for what to try.
>
> And a question for you below Daniel.
>
> On Wed, Jul 12, 2023 at 11:14:21PM +0100, Conor Dooley wrote:
> > On Wed, Jul 12, 2023 at 06:39:28PM -0300, Daniel Henrique Barboza wrote:
> > > On 7/12/23 18:35, Conor Dooley wrote:
> > > > On Wed, Jul 12, 2023 at 06:09:10PM -0300, Daniel Henrique Barboza wrote:
> > > >
> > > > > It is intentional. Those default marchid/mimpid vals were derived 
> > > > > from the current
> > > > > QEMU version ID/build and didn't mean much.
> > > > >
> > > > > It is still possible to set them via "-cpu rv64,marchid=N,mimpid=N" 
> > > > > if needed when
> > > > > using the generic (rv64,rv32) CPUs. Vendor CPUs can't have their 
> > > > > machine IDs changed
> > > > > via command line.
> > > >
> > > > Sounds good, thanks. I did just now go and check icicle to see what it
> > > > would report & it does not boot. I'll go bisect...
> > >
> > > BTW how are you booting the icicle board nowadays? I remember you 
> > > mentioning about
> > > some changes in the FDT being required to boot and whatnot.
> >
> > I do direct kernel boots, as the HSS doesn't work anymore, and just lie
> > a bit to QEMU about how much DDR we have.
> > .PHONY: qemu-icicle
> > qemu-icicle:
> >   $(qemu) -M microchip-icicle-kit \
> >   -m 3G -smp 5 \
> >   -kernel $(vmlinux_bin) \
> >   -dtb $(icicle_dtb) \
> >   -initrd $(initramfs) \
> >   -display none -serial null \
> >   -serial stdio \
> >   -D qemu.log -d unimp
> >
> > The platform only supports 2 GiB of DDR, not 3, but if I pass 2 to QEMU
> > it thinks there's 1 GiB at 0x8000_ and 1 GiB at 0x10__. The
> > upstream devicetree (and current FPGA reference design) expects there to
> > be 1 GiB at 0x8000_ and 1 GiB at 0x10_4000_. If I lie to QEMU,
> > it thinks there is 1 GiB at 0x8000_ and 2 GiB at 0x10__, and
> > things just work. I prefer doing it this way than having to modify the
> > DT, it is a lot easier to explain to people this way.
> >
> > I've been meaning to work the support for the icicle & mpfs in QEMU, but
> > it just gets shunted down the priority list. I'd really like if a proper
> > boot flow would run in QEMU, which means fixing whatever broke the HSS,
> > but I've recently picked up maintainership of dt-binding stuff in Linux,
> > so I've unfortunately got even less time to try and work on it. Maybe
> > we'll get some new graduate in and I can make them suffer in my stead...
> >
> > > If it's not too hard I'll add it in my test scripts to keep it under 
> > > check. Perhaps
> > > we can even add it to QEMU testsuite.
> >
> > I don't think it really should be that bad, at least for the direct
> > kernel boot, which is what I mainly care about, since I use it fairly
> > often for debugging boot stuff in Linux.
> >
> > Anyways, aa903cf31391dd505b399627158f1292a6d19896 is the first bad commit:
> > commit aa903cf31391dd505b399627158f1292a6d19896
> > Author: Bin Meng 
> > Date:   Fri Jun 30 23:36:04 2023 +0800
> >
> > roms/opensbi: Upgrade from v1.2 to v1.3
> >
> > Upgrade OpenSBI from v1.2 to v1.3 and the pre-built bios images.
> >
> > And I see something like:
> > qemu//build/qemu-system-riscv64 -M microchip-icicle-kit \
> > -m 3G -smp 5 \
> > -kernel vmlinux.bin \
> > -dtb icicle.dtb \
> > -initrd initramfs.cpio.gz \
> > -display none -serial null \
> > -serial stdio \
> > -D qemu.log -d unimp
>
> > qemu-system-riscv64: warning: disabling zca extension for hart 
> > 0x because privilege spec version does not match
> > qemu-system-riscv64: warning: disabling zca extension for hart 
> > 0x0001 because privilege spec version does not match
> > qemu-system-riscv64: warning: disabling zcd extension for hart 
> > 0x0001 because privilege spec version does not match
> > qemu-system-riscv64: warning: disabling zca extension for hart 
> > 0x0002 because privilege spec version does not match
> > qemu-system-riscv64: warning: disabling zcd extension for hart 
> > 0x0002 because privilege spec version does not match
> > qemu-system-riscv64: warning: disabling zca extension for hart 
> > 0x0003 because privilege spec version does not match
> > qemu-system-riscv64: warning: disabling zcd extension for hart 
> > 0x0003 because privilege spec version does not match
> > qemu-system-riscv64: warning: disabling zca extension for hart 
> > 0x0004 because privilege spec version does not match
> > qemu-system-riscv64: warning: disabling zcd extension for hart 
> > 0x0004 because privilege spec version does not match
>
> Why am I seeing these warnings? Does the 

Re: Is it possible to boot a riscv32 guest on riscv64 host using KVM?

2023-06-27 Thread Anup Patel
On Mon, Jun 26, 2023 at 4:57 PM Philippe Mathieu-Daudé
 wrote:
>
> Hi,
>
> I'm working on a tree-wide accelerator refactor and want
> to run various configs to be sure I didn't broke anything.
>
> QEMU theoretically supports running a riscv32 guest using
> KVM on a riscv64 host, however the documentation I'm finding
> only refers to riscv64 guests:
> https://github.com/kvm-riscv/howto/wiki
>
> So I wonder, is this a valid / supported config? If so,
> do you mind helping me with pointing me to a guest image
> and its command line?

Currently, we only support running rv64 guest on rv64 host
and rv32 guest on rv32 host.

In the future, we might support running rv32 guest on rv64 host
but as of now we don't see a strong push for it.

Regards,
Anup

>
> Thanks,
>
> Phil.



Re: [PATCH] hw/intc: If mmsiaddrcfgh.L == 1, smsiaddrcfg and smsiaddrcfgh are read-only.

2023-06-11 Thread Anup Patel
On Fri, Jun 9, 2023 at 11:29 AM Tommy Wu  wrote:
>
> According to the `The RISC-V Advanced Interrupt Architecture`
> document, if register `mmsiaddrcfgh` of the domain has bit L set
> to one, then `smsiaddrcfg` and `smsiaddrcfgh` are locked as
> read-only alongside `mmsiaddrcfg` and `mmsiaddrcfgh`.
>
> Signed-off-by: Tommy Wu 
> Reviewed-by: Frank Chang 

Looks good to me.

Reviewed-by: Anup Patel 

> ---
>  hw/intc/riscv_aplic.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
> index afc5b54dbb..4bdc6a5d1a 100644
> --- a/hw/intc/riscv_aplic.c
> +++ b/hw/intc/riscv_aplic.c
> @@ -688,13 +688,13 @@ static void riscv_aplic_write(void *opaque, hwaddr 
> addr, uint64_t value,
>   * domains).
>   */
>  if (aplic->num_children &&
> -!(aplic->smsicfgaddrH & APLIC_xMSICFGADDRH_L)) {
> +!(aplic->mmsicfgaddrH & APLIC_xMSICFGADDRH_L)) {
>  aplic->smsicfgaddr = value;
>  }
>  } else if (aplic->mmode && aplic->msimode &&
> (addr == APLIC_SMSICFGADDRH)) {
>  if (aplic->num_children &&
> -!(aplic->smsicfgaddrH & APLIC_xMSICFGADDRH_L)) {
> +!(aplic->mmsicfgaddrH & APLIC_xMSICFGADDRH_L)) {
>  aplic->smsicfgaddrH = value & APLIC_xMSICFGADDRH_VALID_MASK;
>  }
>  } else if ((APLIC_SETIP_BASE <= addr) &&
> --
> 2.31.1
>



Re: [PATCH v5 0/3] hw/riscv/virt: pflash improvements

2023-05-30 Thread Anup Patel
On Fri, May 26, 2023 at 5:41 PM Sunil V L  wrote:
>
> This series improves the pflash usage in RISC-V virt machine with solutions to
> below issues.
>
> 1) Currently the first pflash is reserved for ROM/M-mode firmware code. But 
> S-mode
> payload firmware like EDK2 need both pflash devices to have separate code and 
> variable
> store so that OS distros can keep the FW code as read-only.
>
> The issue is reported at
> https://salsa.debian.org/qemu-team/edk2/-/commit/c345655a0149f64c5020bfc1e53c619ce60587f6
>
> 2) The latest way of using pflash devices in other architectures and libvirt
> is by using -blockdev and machine options. However, currently this method is
> not working in RISC-V.
>
> With above issues fixed, added documentation on how to use pflash devices
> in RISC-V virt machine.
>
> This patch series is based on Alistair's riscv-to-apply.next branch.
>
> Changes since v4:
> 1) Updated patch 2 to avoid accessing private field as per feedback 
> from Philippe.
> 2) Updated documentation patch to add read-only for ROM usage.
> 3) Rebased to latest riscv-to-apply.next branch and updated tags.
>
> Changes since v3:
> 1) Converted single patch to a series with a cover letter since there 
> are
>multiple patches now.
> 2) Added a new patch to enable pflash usage via -blockdev option.
> 3) Separated the documentation change into new patch and updated the
>documentation to mention only -blockdev option which seems to be 
> the
>recommended way of using pflash.
>
> Changes since v2:
> 1) Reverted v2 changes and used v1 approach so that pflash0 can be 
> used
>for code and pflash1 for variable store.
> 2) Rebased to latest riscv-to-apply.next branch.
> 3) Added documentation for pflash usage.
>
> Changes since v1:
> 1) Simplified the fix such that it doesn't break current EDK2.
>
> Sunil V L (3):
>   hw/riscv: virt: Assume M-mode FW in pflash0 only when "-bios none"
>   riscv/virt: Support using pflash via -blockdev option
>   docs/system: riscv: Add pflash usage details

In case of KVM guests, there is no M-mode so pflash0 will always
contain S-mode FW.

I suggest improving this series to consider KVM guests as well
such that the same EDK2 S-mode works for KVM and TCG guests.

Regards,
Anup

>
>  docs/system/riscv/virt.rst | 29 
>  hw/riscv/virt.c| 56 +++---
>  2 files changed, 51 insertions(+), 34 deletions(-)
>
> --
> 2.34.1
>
>



Re: [PATCH] hw/intc/riscv_aplic: Zero init APLIC internal state

2023-04-13 Thread Anup Patel
On Thu, Apr 13, 2023 at 7:04 PM Ivan Klokov  wrote:
>
> Since g_new is used to initialize the RISCVAPLICState->state structure,
> in some case we get behavior that is not as expected. This patch
> changes this to g_new0, which allows to initialize the APLIC in the correct 
> state.
>
> Signed-off-by: Ivan Klokov 

Looks good to me.

Reviewed-by: Anup Patel 

Regards,
Anup

> ---
>  hw/intc/riscv_aplic.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
> index cfd007e629..71591d44bf 100644
> --- a/hw/intc/riscv_aplic.c
> +++ b/hw/intc/riscv_aplic.c
> @@ -803,7 +803,7 @@ static void riscv_aplic_realize(DeviceState *dev, Error 
> **errp)
>
>  aplic->bitfield_words = (aplic->num_irqs + 31) >> 5;
>  aplic->sourcecfg = g_new0(uint32_t, aplic->num_irqs);
> -aplic->state = g_new(uint32_t, aplic->num_irqs);
> +aplic->state = g_new0(uint32_t, aplic->num_irqs);
>  aplic->target = g_new0(uint32_t, aplic->num_irqs);
>  if (!aplic->msimode) {
>  for (i = 0; i < aplic->num_irqs; i++) {
> --
> 2.34.1
>



Re: [PATCH v3 1/1] hw/riscv: Fix max size limit when put initrd to RAM

2023-03-13 Thread Anup Patel
On Mon, Mar 13, 2023 at 7:49 AM Hang Xu  wrote:
>
> Because the starting address of ram is not necessarily 0,
> the remaining free space in ram is
> ram_size - (start - ram_base) instead of ram_size-start.
>
> Signed-off-by: Hang Xu 

What happens in-case a platform has multiple RAM banks ?

Regards,
Anup

> ---
>  hw/riscv/boot.c| 19 +--
>  hw/riscv/microchip_pfsoc.c |  5 -
>  hw/riscv/opentitan.c   |  2 +-
>  hw/riscv/sifive_e.c|  2 +-
>  hw/riscv/sifive_u.c|  5 -
>  hw/riscv/spike.c   |  5 -
>  hw/riscv/virt.c|  5 -
>  include/hw/riscv/boot.h|  2 ++
>  8 files changed, 33 insertions(+), 12 deletions(-)
>
> diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
> index 52bf8e67de..cfbc376a82 100644
> --- a/hw/riscv/boot.c
> +++ b/hw/riscv/boot.c
> @@ -173,13 +173,14 @@ target_ulong riscv_load_firmware(const char 
> *firmware_filename,
>  exit(1);
>  }
>
> -static void riscv_load_initrd(MachineState *machine, uint64_t kernel_entry)
> +static void riscv_load_initrd(MachineState *machine, uint64_t kernel_entry,
> +  uint64_t ram_base, uint64_t ram_size)
>  {
>  const char *filename = machine->initrd_filename;
> -uint64_t mem_size = machine->ram_size;
>  void *fdt = machine->fdt;
>  hwaddr start, end;
>  ssize_t size;
> +uint64_t max_initrd;
>
>  g_assert(filename != NULL);
>
> @@ -193,12 +194,16 @@ static void riscv_load_initrd(MachineState *machine, 
> uint64_t kernel_entry)
>   * So for boards with less  than 256MB of RAM we put the initrd
>   * halfway into RAM, and for boards with 256MB of RAM or more we put
>   * the initrd at 128MB.
> + * A ram_size == 0, usually from a MemMapEntry[].size element,
> + * means that the RAM block goes all the way to ms->ram_size.
>   */
> -start = kernel_entry + MIN(mem_size / 2, 128 * MiB);
> +ram_size = ram_size ? MIN(machine->ram_size, ram_size) : 
> machine->ram_size;
> +start = kernel_entry + MIN(ram_size / 2, 128 * MiB);
> +max_initrd = ram_size - (start - ram_base);
>
> -size = load_ramdisk(filename, start, mem_size - start);
> +size = load_ramdisk(filename, start, max_initrd);
>  if (size == -1) {
> -size = load_image_targphys(filename, start, mem_size - start);
> +size = load_image_targphys(filename, start, max_initrd);
>  if (size == -1) {
>  error_report("could not load ramdisk '%s'", filename);
>  exit(1);
> @@ -217,6 +222,8 @@ target_ulong riscv_load_kernel(MachineState *machine,
> RISCVHartArrayState *harts,
> target_ulong kernel_start_addr,
> bool load_initrd,
> +   uint64_t ram_base,
> +   uint64_t ram_size,
> symbol_fn_t sym_cb)
>  {
>  const char *kernel_filename = machine->kernel_filename;
> @@ -263,7 +270,7 @@ out:
>  }
>
>  if (load_initrd && machine->initrd_filename) {
> -riscv_load_initrd(machine, kernel_entry);
> +riscv_load_initrd(machine, kernel_entry, ram_base, ram_size);
>  }
>
>  if (fdt && machine->kernel_cmdline && *machine->kernel_cmdline) {
> diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c
> index e81bbd12df..b42d90b89e 100644
> --- a/hw/riscv/microchip_pfsoc.c
> +++ b/hw/riscv/microchip_pfsoc.c
> @@ -630,7 +630,10 @@ static void 
> microchip_icicle_kit_machine_init(MachineState *machine)
>   firmware_end_addr);
>
>  kernel_entry = riscv_load_kernel(machine, >soc.u_cpus,
> - kernel_start_addr, true, NULL);
> + kernel_start_addr, true,
> + 
> memmap[MICROCHIP_PFSOC_DRAM_LO].base,
> + 
> memmap[MICROCHIP_PFSOC_DRAM_LO].size,
> + NULL);
>
>  /* Compute the fdt load address in dram */
>  fdt_load_addr = 
> riscv_compute_fdt_addr(memmap[MICROCHIP_PFSOC_DRAM_LO].base,
> diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c
> index b06944d382..bb663523d5 100644
> --- a/hw/riscv/opentitan.c
> +++ b/hw/riscv/opentitan.c
> @@ -103,7 +103,7 @@ static void opentitan_board_init(MachineState *machine)
>  if (machine->kernel_filename) {
>  riscv_load_kernel(machine, >soc.cpus,
>memmap[IBEX_DEV_RAM].base,
> -  false, NULL);
> +  false, 0, 0, NULL);
>  }
>  }
>
> diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
> index 04939b60c3..5b47d539a6 100644
> --- a/hw/riscv/sifive_e.c
> +++ b/hw/riscv/sifive_e.c
> @@ -116,7 +116,7 @@ static void sifive_e_machine_init(MachineState *machine)
>  if 

[PATCH v3 1/4] target/riscv: Update VS timer whenever htimedelta changes

2023-01-20 Thread Anup Patel
The htimedelta[h] CSR has impact on the VS timer comparison so we
should call riscv_timer_write_timecmp() whenever htimedelta changes.

Fixes: 3ec0fe18a31f ("target/riscv: Add vstimecmp suppor")
Signed-off-by: Anup Patel 
Reviewed-by: Alistair Francis 
---
 target/riscv/csr.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 62e6c4acbd..fa17d7770c 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -3045,6 +3045,8 @@ static RISCVException read_htimedelta(CPURISCVState *env, 
int csrno,
 static RISCVException write_htimedelta(CPURISCVState *env, int csrno,
target_ulong val)
 {
+RISCVCPU *cpu = env_archcpu(env);
+
 if (!env->rdtime_fn) {
 return RISCV_EXCP_ILLEGAL_INST;
 }
@@ -3054,6 +3056,12 @@ static RISCVException write_htimedelta(CPURISCVState 
*env, int csrno,
 } else {
 env->htimedelta = val;
 }
+
+if (cpu->cfg.ext_sstc && env->rdtime_fn) {
+riscv_timer_write_timecmp(cpu, env->vstimer, env->vstimecmp,
+  env->htimedelta, MIP_VSTIP);
+}
+
 return RISCV_EXCP_NONE;
 }
 
@@ -3071,11 +3079,19 @@ static RISCVException read_htimedeltah(CPURISCVState 
*env, int csrno,
 static RISCVException write_htimedeltah(CPURISCVState *env, int csrno,
 target_ulong val)
 {
+RISCVCPU *cpu = env_archcpu(env);
+
 if (!env->rdtime_fn) {
 return RISCV_EXCP_ILLEGAL_INST;
 }
 
 env->htimedelta = deposit64(env->htimedelta, 32, 32, (uint64_t)val);
+
+if (cpu->cfg.ext_sstc && env->rdtime_fn) {
+riscv_timer_write_timecmp(cpu, env->vstimer, env->vstimecmp,
+  env->htimedelta, MIP_VSTIP);
+}
+
 return RISCV_EXCP_NONE;
 }
 
-- 
2.34.1




[PATCH v3 2/4] target/riscv: Don't clear mask in riscv_cpu_update_mip() for VSTIP

2023-01-20 Thread Anup Patel
Instead of clearing mask in riscv_cpu_update_mip() for VSTIP, we
should call riscv_cpu_update_mip() with mask == 0 from timer_helper.c
for VSTIP.

Fixes: 3ec0fe18a31f ("target/riscv: Add vstimecmp suppor")
Signed-off-by: Anup Patel 
Reviewed-by: Alistair Francis 
---
 target/riscv/cpu_helper.c  |  2 --
 target/riscv/time_helper.c | 12 
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 8ea3442b4a..84f84b2bae 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -621,8 +621,6 @@ uint64_t riscv_cpu_update_mip(RISCVCPU *cpu, uint64_t mask, 
uint64_t value)
 vsgein = (env->hgeip & (1ULL << gein)) ? MIP_VSEIP : 0;
 }
 
-/* No need to update mip for VSTIP */
-mask = ((mask == MIP_VSTIP) && env->vstime_irq) ? 0 : mask;
 vstip = env->vstime_irq ? MIP_VSTIP : 0;
 
 QEMU_IOTHREAD_LOCK_GUARD();
diff --git a/target/riscv/time_helper.c b/target/riscv/time_helper.c
index 8cce667dfd..4fb2a471a9 100644
--- a/target/riscv/time_helper.c
+++ b/target/riscv/time_helper.c
@@ -27,7 +27,7 @@ static void riscv_vstimer_cb(void *opaque)
 RISCVCPU *cpu = opaque;
 CPURISCVState *env = >env;
 env->vstime_irq = 1;
-riscv_cpu_update_mip(cpu, MIP_VSTIP, BOOL_TO_MASK(1));
+riscv_cpu_update_mip(cpu, 0, BOOL_TO_MASK(1));
 }
 
 static void riscv_stimer_cb(void *opaque)
@@ -57,16 +57,20 @@ void riscv_timer_write_timecmp(RISCVCPU *cpu, QEMUTimer 
*timer,
  */
 if (timer_irq == MIP_VSTIP) {
 env->vstime_irq = 1;
+riscv_cpu_update_mip(cpu, 0, BOOL_TO_MASK(1));
+} else {
+riscv_cpu_update_mip(cpu, MIP_STIP, BOOL_TO_MASK(1));
 }
-riscv_cpu_update_mip(cpu, timer_irq, BOOL_TO_MASK(1));
 return;
 }
 
+/* Clear the [VS|S]TIP bit in mip */
 if (timer_irq == MIP_VSTIP) {
 env->vstime_irq = 0;
+riscv_cpu_update_mip(cpu, 0, BOOL_TO_MASK(0));
+} else {
+riscv_cpu_update_mip(cpu, timer_irq, BOOL_TO_MASK(0));
 }
-/* Clear the [V]STIP bit in mip */
-riscv_cpu_update_mip(cpu, timer_irq, BOOL_TO_MASK(0));
 
 /* otherwise, set up the future timer interrupt */
 diff = timecmp - rtc_r;
-- 
2.34.1




[PATCH v3 3/4] target/riscv: No need to re-start QEMU timer when timecmp == UINT64_MAX

2023-01-20 Thread Anup Patel
The time CSR will wrap-around immediately after reaching UINT64_MAX
so we don't need to re-start QEMU timer when timecmp == UINT64_MAX
in riscv_timer_write_timecmp().

Signed-off-by: Anup Patel 
Reviewed-by: Alistair Francis 
---
 target/riscv/time_helper.c | 24 
 1 file changed, 24 insertions(+)

diff --git a/target/riscv/time_helper.c b/target/riscv/time_helper.c
index 4fb2a471a9..b654f91af9 100644
--- a/target/riscv/time_helper.c
+++ b/target/riscv/time_helper.c
@@ -72,6 +72,30 @@ void riscv_timer_write_timecmp(RISCVCPU *cpu, QEMUTimer 
*timer,
 riscv_cpu_update_mip(cpu, timer_irq, BOOL_TO_MASK(0));
 }
 
+/*
+ * Sstc specification says the following about timer interrupt:
+ * "A supervisor timer interrupt becomes pending - as reflected in
+ * the STIP bit in the mip and sip registers - whenever time contains
+ * a value greater than or equal to stimecmp, treating the values
+ * as unsigned integers. Writes to stimecmp are guaranteed to be
+ * reflected in STIP eventually, but not necessarily immediately.
+ * The interrupt remains posted until stimecmp becomes greater
+ * than time - typically as a result of writing stimecmp."
+ *
+ * When timecmp = UINT64_MAX, the time CSR will eventually reach
+ * timecmp value but on next timer tick the time CSR will wrap-around
+ * and become zero which is less than UINT64_MAX. Now, the timer
+ * interrupt behaves like a level triggered interrupt so it will
+ * become 1 when time = timecmp = UINT64_MAX and next timer tick
+ * it will become 0 again because time = 0 < timecmp = UINT64_MAX.
+ *
+ * Based on above, we don't re-start the QEMU timer when timecmp
+ * equals UINT64_MAX.
+ */
+if (timecmp == UINT64_MAX) {
+return;
+}
+
 /* otherwise, set up the future timer interrupt */
 diff = timecmp - rtc_r;
 /* back to ns (note args switched in muldiv64) */
-- 
2.34.1




[PATCH v3 4/4] target/riscv: Ensure opcode is saved for all relevant instructions

2023-01-20 Thread Anup Patel
We should call decode_save_opc() for all relevant instructions which
can potentially generate a virtual instruction fault or a guest page
fault because generating transformed instruction upon guest page fault
expects opcode to be available. Without this, hypervisor will see
transformed instruction as zero in htinst CSR for guest MMIO emulation
which makes MMIO emulation in hypervisor slow and also breaks nested
virtualization.

Fixes: a9814e3e08d2 ("target/riscv: Minimize the calls to decode_save_opc")
Signed-off-by: Anup Patel 
---
 target/riscv/insn_trans/trans_rva.c.inc | 10 +++---
 target/riscv/insn_trans/trans_rvd.c.inc |  2 ++
 target/riscv/insn_trans/trans_rvf.c.inc |  2 ++
 target/riscv/insn_trans/trans_rvh.c.inc |  3 +++
 target/riscv/insn_trans/trans_rvi.c.inc |  2 ++
 target/riscv/insn_trans/trans_rvzfh.c.inc   |  2 ++
 target/riscv/insn_trans/trans_svinval.c.inc |  3 +++
 7 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/target/riscv/insn_trans/trans_rva.c.inc 
b/target/riscv/insn_trans/trans_rva.c.inc
index 45db82c9be..5f194a447b 100644
--- a/target/riscv/insn_trans/trans_rva.c.inc
+++ b/target/riscv/insn_trans/trans_rva.c.inc
@@ -20,8 +20,10 @@
 
 static bool gen_lr(DisasContext *ctx, arg_atomic *a, MemOp mop)
 {
-TCGv src1 = get_address(ctx, a->rs1, 0);
+TCGv src1;
 
+decode_save_opc(ctx);
+src1 = get_address(ctx, a->rs1, 0);
 if (a->rl) {
 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
 }
@@ -43,6 +45,7 @@ static bool gen_sc(DisasContext *ctx, arg_atomic *a, MemOp 
mop)
 TCGLabel *l1 = gen_new_label();
 TCGLabel *l2 = gen_new_label();
 
+decode_save_opc(ctx);
 src1 = get_address(ctx, a->rs1, 0);
 tcg_gen_brcond_tl(TCG_COND_NE, load_res, src1, l1);
 
@@ -81,9 +84,10 @@ static bool gen_amo(DisasContext *ctx, arg_atomic *a,
 MemOp mop)
 {
 TCGv dest = dest_gpr(ctx, a->rd);
-TCGv src1 = get_address(ctx, a->rs1, 0);
-TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
+TCGv src1, src2 = get_gpr(ctx, a->rs2, EXT_NONE);
 
+decode_save_opc(ctx);
+src1 = get_address(ctx, a->rs1, 0);
 func(dest, src1, src2, ctx->mem_idx, mop);
 
 gen_set_gpr(ctx, a->rd, dest);
diff --git a/target/riscv/insn_trans/trans_rvd.c.inc 
b/target/riscv/insn_trans/trans_rvd.c.inc
index 1397c1ce1c..6e3159b797 100644
--- a/target/riscv/insn_trans/trans_rvd.c.inc
+++ b/target/riscv/insn_trans/trans_rvd.c.inc
@@ -38,6 +38,7 @@ static bool trans_fld(DisasContext *ctx, arg_fld *a)
 REQUIRE_FPU;
 REQUIRE_EXT(ctx, RVD);
 
+decode_save_opc(ctx);
 addr = get_address(ctx, a->rs1, a->imm);
 tcg_gen_qemu_ld_i64(cpu_fpr[a->rd], addr, ctx->mem_idx, MO_TEUQ);
 
@@ -52,6 +53,7 @@ static bool trans_fsd(DisasContext *ctx, arg_fsd *a)
 REQUIRE_FPU;
 REQUIRE_EXT(ctx, RVD);
 
+decode_save_opc(ctx);
 addr = get_address(ctx, a->rs1, a->imm);
 tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], addr, ctx->mem_idx, MO_TEUQ);
 return true;
diff --git a/target/riscv/insn_trans/trans_rvf.c.inc 
b/target/riscv/insn_trans/trans_rvf.c.inc
index a1d3eb52ad..965e1f8d11 100644
--- a/target/riscv/insn_trans/trans_rvf.c.inc
+++ b/target/riscv/insn_trans/trans_rvf.c.inc
@@ -38,6 +38,7 @@ static bool trans_flw(DisasContext *ctx, arg_flw *a)
 REQUIRE_FPU;
 REQUIRE_EXT(ctx, RVF);
 
+decode_save_opc(ctx);
 addr = get_address(ctx, a->rs1, a->imm);
 dest = cpu_fpr[a->rd];
 tcg_gen_qemu_ld_i64(dest, addr, ctx->mem_idx, MO_TEUL);
@@ -54,6 +55,7 @@ static bool trans_fsw(DisasContext *ctx, arg_fsw *a)
 REQUIRE_FPU;
 REQUIRE_EXT(ctx, RVF);
 
+decode_save_opc(ctx);
 addr = get_address(ctx, a->rs1, a->imm);
 tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], addr, ctx->mem_idx, MO_TEUL);
 return true;
diff --git a/target/riscv/insn_trans/trans_rvh.c.inc 
b/target/riscv/insn_trans/trans_rvh.c.inc
index 4f8aecddc7..9248b48c36 100644
--- a/target/riscv/insn_trans/trans_rvh.c.inc
+++ b/target/riscv/insn_trans/trans_rvh.c.inc
@@ -36,6 +36,7 @@ static bool do_hlv(DisasContext *ctx, arg_r2 *a, MemOp mop)
 #ifdef CONFIG_USER_ONLY
 return false;
 #else
+decode_save_opc(ctx);
 if (check_access(ctx)) {
 TCGv dest = dest_gpr(ctx, a->rd);
 TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
@@ -82,6 +83,7 @@ static bool do_hsv(DisasContext *ctx, arg_r2_s *a, MemOp mop)
 #ifdef CONFIG_USER_ONLY
 return false;
 #else
+decode_save_opc(ctx);
 if (check_access(ctx)) {
 TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
 TCGv data = get_gpr(ctx, a->rs2, EXT_NONE);
@@ -135,6 +137,7 @@ static bool trans_hsv_d(DisasContext *ctx, arg_hsv_d *a)
 static bool do_hlvx(DisasContext *ctx, arg_r2 *a,
 void (*func)(TCGv, TCGv_env, TCGv))
 {
+decode_save_opc(ctx);
 if (check_access(ctx)) {
 TCGv dest = dest_gpr(ctx, a->rd);
 TCGv a

[PATCH v3 0/4] Nested virtualization fixes for QEMU

2023-01-20 Thread Anup Patel
This series mainly includes fixes discovered while developing nested
virtualization running on QEMU.

These patches can also be found in the riscv_nested_fixes_v3 branch at:
https://github.com/avpatel/qemu.git

Changes since v2:
 - Dropped PATCH1 since it is already merged
 - Rebased on latest riscv-to-apply.next branch of Alistair

Changes since v1:
 - Added Alistair's Reviewed-by tags to appropriate patches
 - Added detailed comment block in PATCH4

Anup Patel (4):
  target/riscv: Update VS timer whenever htimedelta changes
  target/riscv: Don't clear mask in riscv_cpu_update_mip() for VSTIP
  target/riscv: No need to re-start QEMU timer when timecmp ==
UINT64_MAX
  target/riscv: Ensure opcode is saved for all relevant instructions

 target/riscv/cpu_helper.c   |  2 --
 target/riscv/csr.c  | 16 +
 target/riscv/insn_trans/trans_rva.c.inc | 10 --
 target/riscv/insn_trans/trans_rvd.c.inc |  2 ++
 target/riscv/insn_trans/trans_rvf.c.inc |  2 ++
 target/riscv/insn_trans/trans_rvh.c.inc |  3 ++
 target/riscv/insn_trans/trans_rvi.c.inc |  2 ++
 target/riscv/insn_trans/trans_rvzfh.c.inc   |  2 ++
 target/riscv/insn_trans/trans_svinval.c.inc |  3 ++
 target/riscv/time_helper.c  | 36 ++---
 10 files changed, 69 insertions(+), 9 deletions(-)

-- 
2.34.1




Re: [PATCH v2 2/5] target/riscv: Update VS timer whenever htimedelta changes

2023-01-15 Thread Anup Patel
Hi Alistair,

On Tue, Jan 3, 2023 at 9:43 PM Anup Patel  wrote:
>
> Hi Alistair,
>
> On Wed, Dec 28, 2022 at 11:08 AM Alistair Francis  
> wrote:
> >
> > On Fri, Dec 23, 2022 at 11:14 PM Anup Patel  wrote:
> > >
> > > On Thu, Dec 15, 2022 at 8:55 AM Alistair Francis  
> > > wrote:
> > > >
> > > > On Mon, Dec 12, 2022 at 9:12 PM Anup Patel  
> > > > wrote:
> > > > >
> > > > > On Mon, Dec 12, 2022 at 11:23 AM Alistair Francis 
> > > > >  wrote:
> > > > > >
> > > > > > On Thu, Dec 8, 2022 at 6:41 PM Anup Patel  
> > > > > > wrote:
> > > > > > >
> > > > > > > On Thu, Dec 8, 2022 at 9:00 AM Alistair Francis 
> > > > > > >  wrote:
> > > > > > > >
> > > > > > > > On Tue, Nov 8, 2022 at 11:07 PM Anup Patel 
> > > > > > > >  wrote:
> > > > > > > > >
> > > > > > > > > The htimedelta[h] CSR has impact on the VS timer comparison 
> > > > > > > > > so we
> > > > > > > > > should call riscv_timer_write_timecmp() whenever htimedelta 
> > > > > > > > > changes.
> > > > > > > > >
> > > > > > > > > Fixes: 3ec0fe18a31f ("target/riscv: Add vstimecmp suppor")
> > > > > > > > > Signed-off-by: Anup Patel 
> > > > > > > > > Reviewed-by: Alistair Francis 
> > > > > > > >
> > > > > > > > This patch breaks my Xvisor test. When running OpenSBI and 
> > > > > > > > Xvisor like this:
> > > > > > > >
> > > > > > > > qemu-system-riscv64 -machine virt \
> > > > > > > > -m 1G -serial mon:stdio -serial null -nographic \
> > > > > > > > -append 'vmm.console=uart@1000 vmm.bootcmd="vfs mount 
> > > > > > > > initrd
> > > > > > > > /;vfs run /boot.xscript;vfs cat /system/banner.txt; guest kick 
> > > > > > > > guest0;
> > > > > > > > vserial bind guest0/uart0"' \
> > > > > > > > -smp 4 -d guest_errors \
> > > > > > > > -bios none \
> > > > > > > > -device 
> > > > > > > > loader,file=./images/qemuriscv64/vmm.bin,addr=0x8020 \
> > > > > > > > -kernel ./images/qemuriscv64/fw_jump.elf \
> > > > > > > > -initrd ./images/qemuriscv64/vmm-disk-linux.img -cpu 
> > > > > > > > rv64,h=true
> > > > > > > >
> > > > > > > > Running:
> > > > > > > >
> > > > > > > > Xvisor v0.3.0-129-gbc33f339 (Jan  1 1970 00:00:00)
> > > > > > > >
> > > > > > > > I see this failure:
> > > > > > > >
> > > > > > > > INIT: bootcmd:  guest kick guest0
> > > > > > > >
> > > > > > > > guest0: Kicked
> > > > > > > >
> > > > > > > > INIT: bootcmd:  vserial bind guest0/uart0
> > > > > > > >
> > > > > > > > [guest0/uart0] cpu_vcpu_stage2_map: 
> > > > > > > > guest_phys=0x3B9AC000
> > > > > > > > size=0x4096 map failed
> > > > > > > >
> > > > > > > > do_error: CPU3: VCPU=guest0/vcpu0 page fault failed (error -1)
> > > > > > > >
> > > > > > > >zero=0x  ra=0x80001B4E
> > > > > > > >
> > > > > > > >  sp=0x8001CF80  gp=0x
> > > > > > > >
> > > > > > > >  tp=0x  s0=0x8001CFB0
> > > > > > > >
> > > > > > > >  s1=0x  a0=0x10001048
> > > > > > > >
> > > > > > > >  a1=0x  a2=0x00989680
> > > > > > > >
> > > > > > > >  a3=0x3B9ACA00  a4=0x0048
> > > > > > > >
> > >

Re: [PATCH v2 2/5] target/riscv: Update VS timer whenever htimedelta changes

2023-01-03 Thread Anup Patel
Hi Alistair,

On Wed, Dec 28, 2022 at 11:08 AM Alistair Francis  wrote:
>
> On Fri, Dec 23, 2022 at 11:14 PM Anup Patel  wrote:
> >
> > On Thu, Dec 15, 2022 at 8:55 AM Alistair Francis  
> > wrote:
> > >
> > > On Mon, Dec 12, 2022 at 9:12 PM Anup Patel  
> > > wrote:
> > > >
> > > > On Mon, Dec 12, 2022 at 11:23 AM Alistair Francis 
> > > >  wrote:
> > > > >
> > > > > On Thu, Dec 8, 2022 at 6:41 PM Anup Patel  
> > > > > wrote:
> > > > > >
> > > > > > On Thu, Dec 8, 2022 at 9:00 AM Alistair Francis 
> > > > > >  wrote:
> > > > > > >
> > > > > > > On Tue, Nov 8, 2022 at 11:07 PM Anup Patel 
> > > > > > >  wrote:
> > > > > > > >
> > > > > > > > The htimedelta[h] CSR has impact on the VS timer comparison so 
> > > > > > > > we
> > > > > > > > should call riscv_timer_write_timecmp() whenever htimedelta 
> > > > > > > > changes.
> > > > > > > >
> > > > > > > > Fixes: 3ec0fe18a31f ("target/riscv: Add vstimecmp suppor")
> > > > > > > > Signed-off-by: Anup Patel 
> > > > > > > > Reviewed-by: Alistair Francis 
> > > > > > >
> > > > > > > This patch breaks my Xvisor test. When running OpenSBI and Xvisor 
> > > > > > > like this:
> > > > > > >
> > > > > > > qemu-system-riscv64 -machine virt \
> > > > > > > -m 1G -serial mon:stdio -serial null -nographic \
> > > > > > > -append 'vmm.console=uart@1000 vmm.bootcmd="vfs mount 
> > > > > > > initrd
> > > > > > > /;vfs run /boot.xscript;vfs cat /system/banner.txt; guest kick 
> > > > > > > guest0;
> > > > > > > vserial bind guest0/uart0"' \
> > > > > > > -smp 4 -d guest_errors \
> > > > > > > -bios none \
> > > > > > > -device 
> > > > > > > loader,file=./images/qemuriscv64/vmm.bin,addr=0x8020 \
> > > > > > > -kernel ./images/qemuriscv64/fw_jump.elf \
> > > > > > > -initrd ./images/qemuriscv64/vmm-disk-linux.img -cpu 
> > > > > > > rv64,h=true
> > > > > > >
> > > > > > > Running:
> > > > > > >
> > > > > > > Xvisor v0.3.0-129-gbc33f339 (Jan  1 1970 00:00:00)
> > > > > > >
> > > > > > > I see this failure:
> > > > > > >
> > > > > > > INIT: bootcmd:  guest kick guest0
> > > > > > >
> > > > > > > guest0: Kicked
> > > > > > >
> > > > > > > INIT: bootcmd:  vserial bind guest0/uart0
> > > > > > >
> > > > > > > [guest0/uart0] cpu_vcpu_stage2_map: guest_phys=0x3B9AC000
> > > > > > > size=0x4096 map failed
> > > > > > >
> > > > > > > do_error: CPU3: VCPU=guest0/vcpu0 page fault failed (error -1)
> > > > > > >
> > > > > > >zero=0x  ra=0x80001B4E
> > > > > > >
> > > > > > >  sp=0x8001CF80  gp=0x
> > > > > > >
> > > > > > >  tp=0x  s0=0x8001CFB0
> > > > > > >
> > > > > > >  s1=0x  a0=0x10001048
> > > > > > >
> > > > > > >  a1=0x  a2=0x00989680
> > > > > > >
> > > > > > >  a3=0x3B9ACA00  a4=0x0048
> > > > > > >
> > > > > > >  a5=0x  a6=0x00019000
> > > > > > >
> > > > > > >  a7=0x  s2=0x
> > > > > > >
> > > > > > >  s3=0x  s4=0x
> > > > > > >
> > > > > > >  s5=0x  s6=0x
> > > > > > >
> > > &g

Re: [PATCH v2 2/5] target/riscv: Update VS timer whenever htimedelta changes

2022-12-23 Thread Anup Patel
On Thu, Dec 15, 2022 at 8:55 AM Alistair Francis  wrote:
>
> On Mon, Dec 12, 2022 at 9:12 PM Anup Patel  wrote:
> >
> > On Mon, Dec 12, 2022 at 11:23 AM Alistair Francis  
> > wrote:
> > >
> > > On Thu, Dec 8, 2022 at 6:41 PM Anup Patel  wrote:
> > > >
> > > > On Thu, Dec 8, 2022 at 9:00 AM Alistair Francis  
> > > > wrote:
> > > > >
> > > > > On Tue, Nov 8, 2022 at 11:07 PM Anup Patel  
> > > > > wrote:
> > > > > >
> > > > > > The htimedelta[h] CSR has impact on the VS timer comparison so we
> > > > > > should call riscv_timer_write_timecmp() whenever htimedelta changes.
> > > > > >
> > > > > > Fixes: 3ec0fe18a31f ("target/riscv: Add vstimecmp suppor")
> > > > > > Signed-off-by: Anup Patel 
> > > > > > Reviewed-by: Alistair Francis 
> > > > >
> > > > > This patch breaks my Xvisor test. When running OpenSBI and Xvisor 
> > > > > like this:
> > > > >
> > > > > qemu-system-riscv64 -machine virt \
> > > > > -m 1G -serial mon:stdio -serial null -nographic \
> > > > > -append 'vmm.console=uart@1000 vmm.bootcmd="vfs mount initrd
> > > > > /;vfs run /boot.xscript;vfs cat /system/banner.txt; guest kick guest0;
> > > > > vserial bind guest0/uart0"' \
> > > > > -smp 4 -d guest_errors \
> > > > > -bios none \
> > > > > -device loader,file=./images/qemuriscv64/vmm.bin,addr=0x8020 \
> > > > > -kernel ./images/qemuriscv64/fw_jump.elf \
> > > > > -initrd ./images/qemuriscv64/vmm-disk-linux.img -cpu rv64,h=true
> > > > >
> > > > > Running:
> > > > >
> > > > > Xvisor v0.3.0-129-gbc33f339 (Jan  1 1970 00:00:00)
> > > > >
> > > > > I see this failure:
> > > > >
> > > > > INIT: bootcmd:  guest kick guest0
> > > > >
> > > > > guest0: Kicked
> > > > >
> > > > > INIT: bootcmd:  vserial bind guest0/uart0
> > > > >
> > > > > [guest0/uart0] cpu_vcpu_stage2_map: guest_phys=0x3B9AC000
> > > > > size=0x4096 map failed
> > > > >
> > > > > do_error: CPU3: VCPU=guest0/vcpu0 page fault failed (error -1)
> > > > >
> > > > >zero=0x  ra=0x80001B4E
> > > > >
> > > > >  sp=0x8001CF80  gp=0x
> > > > >
> > > > >  tp=0x  s0=0x8001CFB0
> > > > >
> > > > >  s1=0x  a0=0x10001048
> > > > >
> > > > >  a1=0x  a2=0x00989680
> > > > >
> > > > >  a3=0x3B9ACA00  a4=0x0048
> > > > >
> > > > >  a5=0x  a6=0x00019000
> > > > >
> > > > >  a7=0x  s2=0x
> > > > >
> > > > >  s3=0x  s4=0x
> > > > >
> > > > >  s5=0x  s6=0x
> > > > >
> > > > >  s7=0x  s8=0x
> > > > >
> > > > >  s9=0x s10=0x
> > > > >
> > > > > s11=0x  t0=0x4000
> > > > >
> > > > >  t1=0x0100  t2=0x
> > > > >
> > > > >  t3=0x  t4=0x
> > > > >
> > > > >  t5=0x  t6=0x
> > > > >
> > > > >sepc=0x80001918 sstatus=0x00024120
> > > > >
> > > > > hstatus=0x0002002001C0 sp_exec=0x10A64000
> > > > >
> > > > >  scause=0x0017   stval=0x3B9ACAF8
> > > > >
> > > > >   htval=0x0EE6B2BE  htinst=0x00D03021
> > > > >
> > > > > I have tried updating to 

Re: [PATCH 01/15] tests/avocado: add RISC-V opensbi boot test

2022-12-22 Thread Anup Patel
On Thu, Dec 22, 2022 at 6:27 PM Bin Meng  wrote:
>
> On Thu, Dec 22, 2022 at 6:47 PM Daniel Henrique Barboza
>  wrote:
> >
> >
> >
> > On 12/22/22 07:24, Bin Meng wrote:
> > > On Thu, Dec 22, 2022 at 2:29 AM Daniel Henrique Barboza
> > >  wrote:
> > >> This test is used to do a quick sanity check to ensure that we're able
> > >> to run the existing QEMU FW image.
> > >>
> > >> 'sifive_u', 'spike' and 'virt' riscv64 machines, and 'sifive_u' and
> > >> 'virt' 32 bit machines are able to run the default RISCV64_BIOS_BIN |
> > >> RISCV32_BIOS_BIN firmware with minimal options.
> > >>
> > >> Cc: Cleber Rosa 
> > >> Cc: Philippe Mathieu-Daudé 
> > >> Cc: Wainer dos Santos Moschetta 
> > >> Cc: Beraldo Leal 
> > >> Signed-off-by: Daniel Henrique Barboza 
> > >> ---
> > >>   tests/avocado/riscv_opensbi.py | 65 ++
> > >>   1 file changed, 65 insertions(+)
> > >>   create mode 100644 tests/avocado/riscv_opensbi.py
> > >>
> > >> diff --git a/tests/avocado/riscv_opensbi.py 
> > >> b/tests/avocado/riscv_opensbi.py
> > >> new file mode 100644
> > >> index 00..abc99ced30
> > >> --- /dev/null
> > >> +++ b/tests/avocado/riscv_opensbi.py
> > >> @@ -0,0 +1,65 @@
> > >> +# opensbi boot test for RISC-V machines
> > >> +#
> > >> +# Copyright (c) 2022, Ventana Micro
> > >> +#
> > >> +# This work is licensed under the terms of the GNU GPL, version 2 or
> > >> +# later.  See the COPYING file in the top-level directory.
> > >> +
> > >> +from avocado_qemu import QemuSystemTest
> > >> +from avocado_qemu import wait_for_console_pattern
> > >> +
> > >> +class RiscvOpensbi(QemuSystemTest):
> > >> +"""
> > >> +:avocado: tags=accel:tcg
> > >> +"""
> > >> +timeout = 5
> > >> +
> > >> +def test_riscv64_virt(self):
> > >> +"""
> > >> +:avocado: tags=arch:riscv64
> > >> +:avocado: tags=machine:virt
> > >> +"""
> > >> +self.vm.set_console()
> > >> +self.vm.launch()
> > >> +wait_for_console_pattern(self, 'Platform Name')
> > >> +wait_for_console_pattern(self, 'Boot HART MEDELEG')
> > >> +
> > >> +def test_riscv64_spike(self):
> > >> +"""
> > >> +:avocado: tags=arch:riscv64
> > >> +:avocado: tags=machine:spike
> > >> +"""
> > >> +self.vm.set_console()
> > >> +self.vm.launch()
> > >> +wait_for_console_pattern(self, 'Platform Name')
> > >> +wait_for_console_pattern(self, 'Boot HART MEDELEG')
> > >> +
> > >> +def test_riscv64_sifive_u(self):
> > >> +"""
> > >> +:avocado: tags=arch:riscv64
> > >> +:avocado: tags=machine:sifive_u
> > >> +"""
> > >> +self.vm.set_console()
> > >> +self.vm.launch()
> > >> +wait_for_console_pattern(self, 'Platform Name')
> > >> +wait_for_console_pattern(self, 'Boot HART MEDELEG')
> > >> +
> > >> +def test_riscv32_virt(self):
> > >> +"""
> > >> +:avocado: tags=arch:riscv32
> > >> +:avocado: tags=machine:virt
> > >> +"""
> > >> +self.vm.set_console()
> > >> +self.vm.launch()
> > >> +wait_for_console_pattern(self, 'Platform Name')
> > >> +wait_for_console_pattern(self, 'Boot HART MEDELEG')
> > > How about testing riscv32_spike too?
> >
> >
> > I didn't manage to make it work. This riscv64 spark command line boots 
> > opensbi:
> >
> >
> > $ ./qemu-system-riscv64 -nographic -display none -vga none -machine spike
> >
> > OpenSBI v1.1
> > _  _
> >/ __ \  / |  _ \_   _|
> >   | |  | |_ __   ___ _ __ | (___ | |_) || |
> >   | |  | | '_ \ / _ \ '_ \ \___ \|  _ < | |
> >   | |__| | |_) |  __/ | | |) | |_) || |_
> >\/| .__/ \___|_| |_|_/|/_|
> >  | |
> >  |_|
> >
> > (...)
> >
> > The same command line doesn't boot riscv32 spark:
> >
> > ./qemu-system-riscv32 -nographic -display none -vga none -machine spike
> > (--- hangs indefinitely ---)
> >
> > I debugged it a bit and, as far as boot code goes, it goes all the way and 
> > loads the
> > opensbi 32bit binary.
> >
> > After that I tried to found any command line example that boots spike with 
> > riscv32
> > bit and didn't find any.  So I gave up digging it further because I became 
> > unsure
> > about whether 32-bit spike works.
> >
> > If someone can verify that yes, 32-bit spike is supposed to work, then I 
> > believe it's
> > worth investigating why it's not the case ATM.
> >
>
> +Anup who might know if QEMU spike 32-bit machine works with opensbi
> 32-bit generic image.

We never got HTIF putc() working on QEMU RV32 Spike but it works
perfectly fine on QEMU RV64 Spike.

See below log of QEMU RV64 Spike ...

Regards,
Anup

anup@anup-ubuntu-vm:~/Work/riscv-test/opensbi$ qemu-system-riscv64 -M
spike -m 256M -nographic -bios
/home/anup/Work/riscv-test/opensbi/build/platform/generic/firmware/fw_payload.elf

OpenSBI v1.1-124-gb848d87
     

Re: [PATCH v2 2/5] target/riscv: Update VS timer whenever htimedelta changes

2022-12-12 Thread Anup Patel
On Mon, Dec 12, 2022 at 11:23 AM Alistair Francis  wrote:
>
> On Thu, Dec 8, 2022 at 6:41 PM Anup Patel  wrote:
> >
> > On Thu, Dec 8, 2022 at 9:00 AM Alistair Francis  
> > wrote:
> > >
> > > On Tue, Nov 8, 2022 at 11:07 PM Anup Patel  
> > > wrote:
> > > >
> > > > The htimedelta[h] CSR has impact on the VS timer comparison so we
> > > > should call riscv_timer_write_timecmp() whenever htimedelta changes.
> > > >
> > > > Fixes: 3ec0fe18a31f ("target/riscv: Add vstimecmp suppor")
> > > > Signed-off-by: Anup Patel 
> > > > Reviewed-by: Alistair Francis 
> > >
> > > This patch breaks my Xvisor test. When running OpenSBI and Xvisor like 
> > > this:
> > >
> > > qemu-system-riscv64 -machine virt \
> > > -m 1G -serial mon:stdio -serial null -nographic \
> > > -append 'vmm.console=uart@1000 vmm.bootcmd="vfs mount initrd
> > > /;vfs run /boot.xscript;vfs cat /system/banner.txt; guest kick guest0;
> > > vserial bind guest0/uart0"' \
> > > -smp 4 -d guest_errors \
> > > -bios none \
> > > -device loader,file=./images/qemuriscv64/vmm.bin,addr=0x8020 \
> > > -kernel ./images/qemuriscv64/fw_jump.elf \
> > > -initrd ./images/qemuriscv64/vmm-disk-linux.img -cpu rv64,h=true
> > >
> > > Running:
> > >
> > > Xvisor v0.3.0-129-gbc33f339 (Jan  1 1970 00:00:00)
> > >
> > > I see this failure:
> > >
> > > INIT: bootcmd:  guest kick guest0
> > >
> > > guest0: Kicked
> > >
> > > INIT: bootcmd:  vserial bind guest0/uart0
> > >
> > > [guest0/uart0] cpu_vcpu_stage2_map: guest_phys=0x3B9AC000
> > > size=0x4096 map failed
> > >
> > > do_error: CPU3: VCPU=guest0/vcpu0 page fault failed (error -1)
> > >
> > >zero=0x  ra=0x80001B4E
> > >
> > >  sp=0x8001CF80  gp=0x
> > >
> > >  tp=0x  s0=0x8001CFB0
> > >
> > >  s1=0x  a0=0x10001048
> > >
> > >  a1=0x  a2=0x00989680
> > >
> > >  a3=0x3B9ACA00  a4=0x0048
> > >
> > >  a5=0x  a6=0x00019000
> > >
> > >  a7=0x  s2=0x
> > >
> > >  s3=0x  s4=0x
> > >
> > >  s5=0x  s6=0x
> > >
> > >  s7=0x  s8=0x
> > >
> > >  s9=0x s10=0x
> > >
> > > s11=0x  t0=0x4000
> > >
> > >  t1=0x0100  t2=0x
> > >
> > >  t3=0x  t4=0x
> > >
> > >  t5=0x  t6=0x
> > >
> > >sepc=0x80001918 sstatus=0x00024120
> > >
> > > hstatus=0x0002002001C0 sp_exec=0x10A64000
> > >
> > >  scause=0x0017   stval=0x3B9ACAF8
> > >
> > >   htval=0x0EE6B2BE  htinst=0x00D03021
> > >
> > > I have tried updating to a newer Xvisor release, but with that I don't
> > > get any serial output.
> > >
> > > Can you help get the Xvisor tests back up and running?
> >
> > I tried the latest Xvisor-next (https://github.com/avpatel/xvisor-next)
> > with your QEMU riscv-to-apply.next branch and it works fine (both
> > with and without Sstc).
>
> Does it work with the latest release?

Yes, the latest Xvisor-next repo works for QEMU v7.2.0-rc4 and
your riscv-to-apply.next branch (commit 51bb9de2d188)

Regards,
Anup

>
> Alistair
>
> >
> > Here's the QEMU command which I use:
> >
> > qemu-system-riscv64 -M virt -m 512M -nographic \
> > -bios opensbi/build/platform/generic/firmware/fw_jump.bin \
> > -kernel ../xvisor-next/build/vmm.bin \
> > -initrd rbd_v64.img \
> > -append "vmm.bootcmd=\"vfs mount initrd /;vfs run /boot.xscript;vfs
> > cat /system/banner.txt\"" \
> > -smp 4
> >
> > Also, I will be releasing Xvisor-0.3.2 by the end of Dec 2022 so I
> > suggest using this upcoming release in your test.
> >
> > Regards,
> > Anup



Re: [PATCH v2 2/5] target/riscv: Update VS timer whenever htimedelta changes

2022-12-08 Thread Anup Patel
On Thu, Dec 8, 2022 at 9:00 AM Alistair Francis  wrote:
>
> On Tue, Nov 8, 2022 at 11:07 PM Anup Patel  wrote:
> >
> > The htimedelta[h] CSR has impact on the VS timer comparison so we
> > should call riscv_timer_write_timecmp() whenever htimedelta changes.
> >
> > Fixes: 3ec0fe18a31f ("target/riscv: Add vstimecmp suppor")
> > Signed-off-by: Anup Patel 
> > Reviewed-by: Alistair Francis 
>
> This patch breaks my Xvisor test. When running OpenSBI and Xvisor like this:
>
> qemu-system-riscv64 -machine virt \
> -m 1G -serial mon:stdio -serial null -nographic \
> -append 'vmm.console=uart@1000 vmm.bootcmd="vfs mount initrd
> /;vfs run /boot.xscript;vfs cat /system/banner.txt; guest kick guest0;
> vserial bind guest0/uart0"' \
> -smp 4 -d guest_errors \
> -bios none \
> -device loader,file=./images/qemuriscv64/vmm.bin,addr=0x8020 \
> -kernel ./images/qemuriscv64/fw_jump.elf \
> -initrd ./images/qemuriscv64/vmm-disk-linux.img -cpu rv64,h=true
>
> Running:
>
> Xvisor v0.3.0-129-gbc33f339 (Jan  1 1970 00:00:00)
>
> I see this failure:
>
> INIT: bootcmd:  guest kick guest0
>
> guest0: Kicked
>
> INIT: bootcmd:  vserial bind guest0/uart0
>
> [guest0/uart0] cpu_vcpu_stage2_map: guest_phys=0x3B9AC000
> size=0x4096 map failed
>
> do_error: CPU3: VCPU=guest0/vcpu0 page fault failed (error -1)
>
>zero=0x  ra=0x80001B4E
>
>  sp=0x8001CF80  gp=0x
>
>  tp=0x  s0=0x8001CFB0
>
>  s1=0x  a0=0x10001048
>
>  a1=0x  a2=0x00989680
>
>  a3=0x3B9ACA00  a4=0x0048
>
>  a5=0x  a6=0x00019000
>
>  a7=0x  s2=0x
>
>  s3=0x  s4=0x
>
>  s5=0x  s6=0x
>
>  s7=0x  s8=0x
>
>  s9=0x s10=0x
>
> s11=0x  t0=0x4000
>
>  t1=0x0100  t2=0x
>
>  t3=0x  t4=0x
>
>  t5=0x  t6=0x
>
>sepc=0x80001918 sstatus=0x00024120
>
> hstatus=0x0002002001C0 sp_exec=0x10A64000
>
>  scause=0x0017   stval=0x3B9ACAF8
>
>   htval=0x0EE6B2BE  htinst=0x00D03021
>
> I have tried updating to a newer Xvisor release, but with that I don't
> get any serial output.
>
> Can you help get the Xvisor tests back up and running?

I tried the latest Xvisor-next (https://github.com/avpatel/xvisor-next)
with your QEMU riscv-to-apply.next branch and it works fine (both
with and without Sstc).

Here's the QEMU command which I use:

qemu-system-riscv64 -M virt -m 512M -nographic \
-bios opensbi/build/platform/generic/firmware/fw_jump.bin \
-kernel ../xvisor-next/build/vmm.bin \
-initrd rbd_v64.img \
-append "vmm.bootcmd=\"vfs mount initrd /;vfs run /boot.xscript;vfs
cat /system/banner.txt\"" \
-smp 4

Also, I will be releasing Xvisor-0.3.2 by the end of Dec 2022 so I
suggest using this upcoming release in your test.

Regards,
Anup



Re: [PATCH v2 0/5] Nested virtualization fixes for QEMU

2022-11-20 Thread Anup Patel
Hi Alistair,

On Tue, Nov 8, 2022 at 6:27 PM Anup Patel  wrote:
>
> This series mainly includes fixes discovered while developing nested
> virtualization running on QEMU.
>
> These patches can also be found in the riscv_nested_fixes_v2 branch at:
> https://github.com/avpatel/qemu.git
>
> Changes since v1:
>  - Added Alistair's Reviewed-by tags to appropriate patches
>  - Added detailed comment block in PATCH4
>
> Anup Patel (5):
>   target/riscv: Typo fix in sstc() predicate
>   target/riscv: Update VS timer whenever htimedelta changes
>   target/riscv: Don't clear mask in riscv_cpu_update_mip() for VSTIP
>   target/riscv: No need to re-start QEMU timer when timecmp ==
> UINT64_MAX
>   target/riscv: Ensure opcode is saved for all relevant instructions

Friendly ping ?

Regards,
Anup

>
>  target/riscv/cpu_helper.c   |  2 --
>  target/riscv/csr.c  | 18 ++-
>  target/riscv/insn_trans/trans_rva.c.inc | 10 --
>  target/riscv/insn_trans/trans_rvd.c.inc |  2 ++
>  target/riscv/insn_trans/trans_rvf.c.inc |  2 ++
>  target/riscv/insn_trans/trans_rvh.c.inc |  3 ++
>  target/riscv/insn_trans/trans_rvi.c.inc |  2 ++
>  target/riscv/insn_trans/trans_rvzfh.c.inc   |  2 ++
>  target/riscv/insn_trans/trans_svinval.c.inc |  3 ++
>  target/riscv/time_helper.c  | 36 ++---
>  10 files changed, 70 insertions(+), 10 deletions(-)
>
> --
> 2.34.1
>



[PATCH v2 4/5] target/riscv: No need to re-start QEMU timer when timecmp == UINT64_MAX

2022-11-08 Thread Anup Patel
The time CSR will wrap-around immediately after reaching UINT64_MAX
so we don't need to re-start QEMU timer when timecmp == UINT64_MAX
in riscv_timer_write_timecmp().

Signed-off-by: Anup Patel 
Reviewed-by: Alistair Francis 
---
 target/riscv/time_helper.c | 24 
 1 file changed, 24 insertions(+)

diff --git a/target/riscv/time_helper.c b/target/riscv/time_helper.c
index 4fb2a471a9..b654f91af9 100644
--- a/target/riscv/time_helper.c
+++ b/target/riscv/time_helper.c
@@ -72,6 +72,30 @@ void riscv_timer_write_timecmp(RISCVCPU *cpu, QEMUTimer 
*timer,
 riscv_cpu_update_mip(cpu, timer_irq, BOOL_TO_MASK(0));
 }
 
+/*
+ * Sstc specification says the following about timer interrupt:
+ * "A supervisor timer interrupt becomes pending - as reflected in
+ * the STIP bit in the mip and sip registers - whenever time contains
+ * a value greater than or equal to stimecmp, treating the values
+ * as unsigned integers. Writes to stimecmp are guaranteed to be
+ * reflected in STIP eventually, but not necessarily immediately.
+ * The interrupt remains posted until stimecmp becomes greater
+ * than time - typically as a result of writing stimecmp."
+ *
+ * When timecmp = UINT64_MAX, the time CSR will eventually reach
+ * timecmp value but on next timer tick the time CSR will wrap-around
+ * and become zero which is less than UINT64_MAX. Now, the timer
+ * interrupt behaves like a level triggered interrupt so it will
+ * become 1 when time = timecmp = UINT64_MAX and next timer tick
+ * it will become 0 again because time = 0 < timecmp = UINT64_MAX.
+ *
+ * Based on above, we don't re-start the QEMU timer when timecmp
+ * equals UINT64_MAX.
+ */
+if (timecmp == UINT64_MAX) {
+return;
+}
+
 /* otherwise, set up the future timer interrupt */
 diff = timecmp - rtc_r;
 /* back to ns (note args switched in muldiv64) */
-- 
2.34.1




[PATCH v2 5/5] target/riscv: Ensure opcode is saved for all relevant instructions

2022-11-08 Thread Anup Patel
We should call decode_save_opc() for all relevant instructions which
can potentially generate a virtual instruction fault or a guest page
fault because generating transformed instruction upon guest page fault
expects opcode to be available. Without this, hypervisor will see
transformed instruction as zero in htinst CSR for guest MMIO emulation
which makes MMIO emulation in hypervisor slow and also breaks nested
virtualization.

Fixes: a9814e3e08d2 ("target/riscv: Minimize the calls to decode_save_opc")
Signed-off-by: Anup Patel 
---
 target/riscv/insn_trans/trans_rva.c.inc | 10 +++---
 target/riscv/insn_trans/trans_rvd.c.inc |  2 ++
 target/riscv/insn_trans/trans_rvf.c.inc |  2 ++
 target/riscv/insn_trans/trans_rvh.c.inc |  3 +++
 target/riscv/insn_trans/trans_rvi.c.inc |  2 ++
 target/riscv/insn_trans/trans_rvzfh.c.inc   |  2 ++
 target/riscv/insn_trans/trans_svinval.c.inc |  3 +++
 7 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/target/riscv/insn_trans/trans_rva.c.inc 
b/target/riscv/insn_trans/trans_rva.c.inc
index 45db82c9be..5f194a447b 100644
--- a/target/riscv/insn_trans/trans_rva.c.inc
+++ b/target/riscv/insn_trans/trans_rva.c.inc
@@ -20,8 +20,10 @@
 
 static bool gen_lr(DisasContext *ctx, arg_atomic *a, MemOp mop)
 {
-TCGv src1 = get_address(ctx, a->rs1, 0);
+TCGv src1;
 
+decode_save_opc(ctx);
+src1 = get_address(ctx, a->rs1, 0);
 if (a->rl) {
 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
 }
@@ -43,6 +45,7 @@ static bool gen_sc(DisasContext *ctx, arg_atomic *a, MemOp 
mop)
 TCGLabel *l1 = gen_new_label();
 TCGLabel *l2 = gen_new_label();
 
+decode_save_opc(ctx);
 src1 = get_address(ctx, a->rs1, 0);
 tcg_gen_brcond_tl(TCG_COND_NE, load_res, src1, l1);
 
@@ -81,9 +84,10 @@ static bool gen_amo(DisasContext *ctx, arg_atomic *a,
 MemOp mop)
 {
 TCGv dest = dest_gpr(ctx, a->rd);
-TCGv src1 = get_address(ctx, a->rs1, 0);
-TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
+TCGv src1, src2 = get_gpr(ctx, a->rs2, EXT_NONE);
 
+decode_save_opc(ctx);
+src1 = get_address(ctx, a->rs1, 0);
 func(dest, src1, src2, ctx->mem_idx, mop);
 
 gen_set_gpr(ctx, a->rd, dest);
diff --git a/target/riscv/insn_trans/trans_rvd.c.inc 
b/target/riscv/insn_trans/trans_rvd.c.inc
index 1397c1ce1c..6e3159b797 100644
--- a/target/riscv/insn_trans/trans_rvd.c.inc
+++ b/target/riscv/insn_trans/trans_rvd.c.inc
@@ -38,6 +38,7 @@ static bool trans_fld(DisasContext *ctx, arg_fld *a)
 REQUIRE_FPU;
 REQUIRE_EXT(ctx, RVD);
 
+decode_save_opc(ctx);
 addr = get_address(ctx, a->rs1, a->imm);
 tcg_gen_qemu_ld_i64(cpu_fpr[a->rd], addr, ctx->mem_idx, MO_TEUQ);
 
@@ -52,6 +53,7 @@ static bool trans_fsd(DisasContext *ctx, arg_fsd *a)
 REQUIRE_FPU;
 REQUIRE_EXT(ctx, RVD);
 
+decode_save_opc(ctx);
 addr = get_address(ctx, a->rs1, a->imm);
 tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], addr, ctx->mem_idx, MO_TEUQ);
 return true;
diff --git a/target/riscv/insn_trans/trans_rvf.c.inc 
b/target/riscv/insn_trans/trans_rvf.c.inc
index a1d3eb52ad..965e1f8d11 100644
--- a/target/riscv/insn_trans/trans_rvf.c.inc
+++ b/target/riscv/insn_trans/trans_rvf.c.inc
@@ -38,6 +38,7 @@ static bool trans_flw(DisasContext *ctx, arg_flw *a)
 REQUIRE_FPU;
 REQUIRE_EXT(ctx, RVF);
 
+decode_save_opc(ctx);
 addr = get_address(ctx, a->rs1, a->imm);
 dest = cpu_fpr[a->rd];
 tcg_gen_qemu_ld_i64(dest, addr, ctx->mem_idx, MO_TEUL);
@@ -54,6 +55,7 @@ static bool trans_fsw(DisasContext *ctx, arg_fsw *a)
 REQUIRE_FPU;
 REQUIRE_EXT(ctx, RVF);
 
+decode_save_opc(ctx);
 addr = get_address(ctx, a->rs1, a->imm);
 tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], addr, ctx->mem_idx, MO_TEUL);
 return true;
diff --git a/target/riscv/insn_trans/trans_rvh.c.inc 
b/target/riscv/insn_trans/trans_rvh.c.inc
index 4f8aecddc7..9248b48c36 100644
--- a/target/riscv/insn_trans/trans_rvh.c.inc
+++ b/target/riscv/insn_trans/trans_rvh.c.inc
@@ -36,6 +36,7 @@ static bool do_hlv(DisasContext *ctx, arg_r2 *a, MemOp mop)
 #ifdef CONFIG_USER_ONLY
 return false;
 #else
+decode_save_opc(ctx);
 if (check_access(ctx)) {
 TCGv dest = dest_gpr(ctx, a->rd);
 TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
@@ -82,6 +83,7 @@ static bool do_hsv(DisasContext *ctx, arg_r2_s *a, MemOp mop)
 #ifdef CONFIG_USER_ONLY
 return false;
 #else
+decode_save_opc(ctx);
 if (check_access(ctx)) {
 TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
 TCGv data = get_gpr(ctx, a->rs2, EXT_NONE);
@@ -135,6 +137,7 @@ static bool trans_hsv_d(DisasContext *ctx, arg_hsv_d *a)
 static bool do_hlvx(DisasContext *ctx, arg_r2 *a,
 void (*func)(TCGv, TCGv_env, TCGv))
 {
+decode_save_opc(ctx);
 if (check_access(ctx)) {
 TCGv dest = dest_gpr(ctx, a->rd);
 TCGv a

[PATCH v2 3/5] target/riscv: Don't clear mask in riscv_cpu_update_mip() for VSTIP

2022-11-08 Thread Anup Patel
Instead of clearing mask in riscv_cpu_update_mip() for VSTIP, we
should call riscv_cpu_update_mip() with mask == 0 from timer_helper.c
for VSTIP.

Fixes: 3ec0fe18a31f ("target/riscv: Add vstimecmp suppor")
Signed-off-by: Anup Patel 
Reviewed-by: Alistair Francis 
---
 target/riscv/cpu_helper.c  |  2 --
 target/riscv/time_helper.c | 12 
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 5d66246c2c..a403825e49 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -617,8 +617,6 @@ uint64_t riscv_cpu_update_mip(RISCVCPU *cpu, uint64_t mask, 
uint64_t value)
 vsgein = (env->hgeip & (1ULL << gein)) ? MIP_VSEIP : 0;
 }
 
-/* No need to update mip for VSTIP */
-mask = ((mask == MIP_VSTIP) && env->vstime_irq) ? 0 : mask;
 vstip = env->vstime_irq ? MIP_VSTIP : 0;
 
 if (!qemu_mutex_iothread_locked()) {
diff --git a/target/riscv/time_helper.c b/target/riscv/time_helper.c
index 8cce667dfd..4fb2a471a9 100644
--- a/target/riscv/time_helper.c
+++ b/target/riscv/time_helper.c
@@ -27,7 +27,7 @@ static void riscv_vstimer_cb(void *opaque)
 RISCVCPU *cpu = opaque;
 CPURISCVState *env = >env;
 env->vstime_irq = 1;
-riscv_cpu_update_mip(cpu, MIP_VSTIP, BOOL_TO_MASK(1));
+riscv_cpu_update_mip(cpu, 0, BOOL_TO_MASK(1));
 }
 
 static void riscv_stimer_cb(void *opaque)
@@ -57,16 +57,20 @@ void riscv_timer_write_timecmp(RISCVCPU *cpu, QEMUTimer 
*timer,
  */
 if (timer_irq == MIP_VSTIP) {
 env->vstime_irq = 1;
+riscv_cpu_update_mip(cpu, 0, BOOL_TO_MASK(1));
+} else {
+riscv_cpu_update_mip(cpu, MIP_STIP, BOOL_TO_MASK(1));
 }
-riscv_cpu_update_mip(cpu, timer_irq, BOOL_TO_MASK(1));
 return;
 }
 
+/* Clear the [VS|S]TIP bit in mip */
 if (timer_irq == MIP_VSTIP) {
 env->vstime_irq = 0;
+riscv_cpu_update_mip(cpu, 0, BOOL_TO_MASK(0));
+} else {
+riscv_cpu_update_mip(cpu, timer_irq, BOOL_TO_MASK(0));
 }
-/* Clear the [V]STIP bit in mip */
-riscv_cpu_update_mip(cpu, timer_irq, BOOL_TO_MASK(0));
 
 /* otherwise, set up the future timer interrupt */
 diff = timecmp - rtc_r;
-- 
2.34.1




[PATCH v2 1/5] target/riscv: Typo fix in sstc() predicate

2022-11-08 Thread Anup Patel
We should use "&&" instead of "&" when checking hcounteren.TM and
henvcfg.STCE bits.

Fixes: 3ec0fe18a31f ("target/riscv: Add vstimecmp suppor")
Signed-off-by: Anup Patel 
Reviewed-by: Alistair Francis 
---
 target/riscv/csr.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 5c9a7ee287..716f9d960e 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -838,7 +838,7 @@ static RISCVException sstc(CPURISCVState *env, int csrno)
 }
 
 if (riscv_cpu_virt_enabled(env)) {
-if (!(get_field(env->hcounteren, COUNTEREN_TM) &
+if (!(get_field(env->hcounteren, COUNTEREN_TM) &&
   get_field(env->henvcfg, HENVCFG_STCE))) {
 return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
 }
-- 
2.34.1




[PATCH v2 0/5] Nested virtualization fixes for QEMU

2022-11-08 Thread Anup Patel
This series mainly includes fixes discovered while developing nested
virtualization running on QEMU.

These patches can also be found in the riscv_nested_fixes_v2 branch at:
https://github.com/avpatel/qemu.git

Changes since v1:
 - Added Alistair's Reviewed-by tags to appropriate patches
 - Added detailed comment block in PATCH4

Anup Patel (5):
  target/riscv: Typo fix in sstc() predicate
  target/riscv: Update VS timer whenever htimedelta changes
  target/riscv: Don't clear mask in riscv_cpu_update_mip() for VSTIP
  target/riscv: No need to re-start QEMU timer when timecmp ==
UINT64_MAX
  target/riscv: Ensure opcode is saved for all relevant instructions

 target/riscv/cpu_helper.c   |  2 --
 target/riscv/csr.c  | 18 ++-
 target/riscv/insn_trans/trans_rva.c.inc | 10 --
 target/riscv/insn_trans/trans_rvd.c.inc |  2 ++
 target/riscv/insn_trans/trans_rvf.c.inc |  2 ++
 target/riscv/insn_trans/trans_rvh.c.inc |  3 ++
 target/riscv/insn_trans/trans_rvi.c.inc |  2 ++
 target/riscv/insn_trans/trans_rvzfh.c.inc   |  2 ++
 target/riscv/insn_trans/trans_svinval.c.inc |  3 ++
 target/riscv/time_helper.c  | 36 ++---
 10 files changed, 70 insertions(+), 10 deletions(-)

-- 
2.34.1




[PATCH v2 2/5] target/riscv: Update VS timer whenever htimedelta changes

2022-11-08 Thread Anup Patel
The htimedelta[h] CSR has impact on the VS timer comparison so we
should call riscv_timer_write_timecmp() whenever htimedelta changes.

Fixes: 3ec0fe18a31f ("target/riscv: Add vstimecmp suppor")
Signed-off-by: Anup Patel 
Reviewed-by: Alistair Francis 
---
 target/riscv/csr.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 716f9d960e..4b1a608260 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -2722,6 +2722,8 @@ static RISCVException read_htimedelta(CPURISCVState *env, 
int csrno,
 static RISCVException write_htimedelta(CPURISCVState *env, int csrno,
target_ulong val)
 {
+RISCVCPU *cpu = env_archcpu(env);
+
 if (!env->rdtime_fn) {
 return RISCV_EXCP_ILLEGAL_INST;
 }
@@ -2731,6 +2733,12 @@ static RISCVException write_htimedelta(CPURISCVState 
*env, int csrno,
 } else {
 env->htimedelta = val;
 }
+
+if (cpu->cfg.ext_sstc && env->rdtime_fn) {
+riscv_timer_write_timecmp(cpu, env->vstimer, env->vstimecmp,
+  env->htimedelta, MIP_VSTIP);
+}
+
 return RISCV_EXCP_NONE;
 }
 
@@ -2748,11 +2756,19 @@ static RISCVException read_htimedeltah(CPURISCVState 
*env, int csrno,
 static RISCVException write_htimedeltah(CPURISCVState *env, int csrno,
 target_ulong val)
 {
+RISCVCPU *cpu = env_archcpu(env);
+
 if (!env->rdtime_fn) {
 return RISCV_EXCP_ILLEGAL_INST;
 }
 
 env->htimedelta = deposit64(env->htimedelta, 32, 32, (uint64_t)val);
+
+if (cpu->cfg.ext_sstc && env->rdtime_fn) {
+riscv_timer_write_timecmp(cpu, env->vstimer, env->vstimecmp,
+  env->htimedelta, MIP_VSTIP);
+}
+
 return RISCV_EXCP_NONE;
 }
 
-- 
2.34.1




Re: [PATCH 4/5] target/riscv: No need to re-start QEMU timer when timecmp == UINT64_MAX

2022-11-06 Thread Anup Patel
On Wed, Nov 2, 2022 at 5:40 AM Alistair Francis  wrote:
>
> On Mon, Oct 31, 2022 at 1:49 PM Anup Patel  wrote:
> >
> > On Mon, Oct 31, 2022 at 6:25 AM Alistair Francis  
> > wrote:
> > >
> > > On Fri, Oct 28, 2022 at 2:53 AM Anup Patel  
> > > wrote:
> > > >
> > > > The time CSR will wrap-around immediately after reaching UINT64_MAX
> > > > so we don't need to re-start QEMU timer when timecmp == UINT64_MAX
> > > > in riscv_timer_write_timecmp().
> > >
> > > I'm not clear what this is fixing?
> > >
> > > If the guest sets a timer for UINT64_MAX shouldn't that still trigger
> > > an event at some point?
> >
> > Here's what Sstc says about timer interrupt using Sstc:
> > "A supervisor timer interrupt becomes pending - as reflected in the
> > STIP bit in the mip and sip registers - whenever time contains a
> > value greater than or equal to stimecmp, treating the values as
> > unsigned integers. Writes to stimecmp are guaranteed to be
> > reflected in STIP eventually, but not necessarily immediately.
> > The interrupt remains posted until stimecmp becomes greater
> > than time - typically as a result of writing stimecmp."
> >
> > When timecmp = UINT64_MAX, the time CSR will eventually reach
> > timecmp value but on next timer tick the time CSR will wrap-around
> > and become zero which is less than UINT64_MAX. Now, the timer
> > interrupt behaves like a level triggered interrupt so it will become 1
> > when time = timecmp = UINT64_MAX and next timer tick it will
> > become 0 again because time = 0 < timecmp = UINT64_MAX.
>
> Ah, I didn't realise this. Can you add this to the code comment and
> maybe add this description to the commit message. Otherwise:
>
> Reviewed-by: Alistair Francis 

Sure, I will add a detailed comment block in the code itself.

Thanks,
Anup

>
> Alistair
>
> >
> > This time CSR wrap-around comparison with timecmp is natural
> > to implement in HW but not straight forward in QEMU hence this
> > patch.
> >
> > Software can potentially use timecmp = UINT64_MAX as a way
> > to clear the timer interrupt and keep timer disabled instead of
> > enabling/disabling sie.STIP. This timecmp = UINT64_MAX helps:
> > 1) Linux RISC-V timer driver keep timer interrupt enable/disable
> > state in-sync with Linux interrupt subsystem.
> > 2) Reduce number of traps taken when emulating Sstc for the
> > "Nested Guest" (i.e. Guest running under some "Guest Hypervisor"
> > which in-turn runs under a "Host Hypervisor").
> >
> > In fact, the SBI set_timer() call also defines similar mechanism to
> > disable timer: "If the supervisor wishes to clear the timer interrupt
> > without scheduling the next timer event, it can either request a timer
> > interrupt infinitely far into the future (i.e., (uint64_t)-1), ...".
> >
> > Regards,
> > Anup
> >
> > >
> > > Alistair
> > >
> > > >
> > > > Signed-off-by: Anup Patel 
> > > > ---
> > > >  target/riscv/time_helper.c | 8 
> > > >  1 file changed, 8 insertions(+)
> > > >
> > > > diff --git a/target/riscv/time_helper.c b/target/riscv/time_helper.c
> > > > index 4fb2a471a9..1ee9f94813 100644
> > > > --- a/target/riscv/time_helper.c
> > > > +++ b/target/riscv/time_helper.c
> > > > @@ -72,6 +72,14 @@ void riscv_timer_write_timecmp(RISCVCPU *cpu, 
> > > > QEMUTimer *timer,
> > > >  riscv_cpu_update_mip(cpu, timer_irq, BOOL_TO_MASK(0));
> > > >  }
> > > >
> > > > +/*
> > > > + * Don't re-start the QEMU timer when timecmp == UINT64_MAX because
> > > > + * time CSR will wrap-around immediately after reaching UINT64_MAX.
> > > > + */
> > > > +if (timecmp == UINT64_MAX) {
> > > > +return;
> > > > +}
> > > > +
> > > >  /* otherwise, set up the future timer interrupt */
> > > >  diff = timecmp - rtc_r;
> > > >  /* back to ns (note args switched in muldiv64) */
> > > > --
> > > > 2.34.1
> > > >
> > > >



Re: [PATCH 4/5] target/riscv: No need to re-start QEMU timer when timecmp == UINT64_MAX

2022-10-30 Thread Anup Patel
On Mon, Oct 31, 2022 at 6:25 AM Alistair Francis  wrote:
>
> On Fri, Oct 28, 2022 at 2:53 AM Anup Patel  wrote:
> >
> > The time CSR will wrap-around immediately after reaching UINT64_MAX
> > so we don't need to re-start QEMU timer when timecmp == UINT64_MAX
> > in riscv_timer_write_timecmp().
>
> I'm not clear what this is fixing?
>
> If the guest sets a timer for UINT64_MAX shouldn't that still trigger
> an event at some point?

Here's what Sstc says about timer interrupt using Sstc:
"A supervisor timer interrupt becomes pending - as reflected in the
STIP bit in the mip and sip registers - whenever time contains a
value greater than or equal to stimecmp, treating the values as
unsigned integers. Writes to stimecmp are guaranteed to be
reflected in STIP eventually, but not necessarily immediately.
The interrupt remains posted until stimecmp becomes greater
than time - typically as a result of writing stimecmp."

When timecmp = UINT64_MAX, the time CSR will eventually reach
timecmp value but on next timer tick the time CSR will wrap-around
and become zero which is less than UINT64_MAX. Now, the timer
interrupt behaves like a level triggered interrupt so it will become 1
when time = timecmp = UINT64_MAX and next timer tick it will
become 0 again because time = 0 < timecmp = UINT64_MAX.

This time CSR wrap-around comparison with timecmp is natural
to implement in HW but not straight forward in QEMU hence this
patch.

Software can potentially use timecmp = UINT64_MAX as a way
to clear the timer interrupt and keep timer disabled instead of
enabling/disabling sie.STIP. This timecmp = UINT64_MAX helps:
1) Linux RISC-V timer driver keep timer interrupt enable/disable
state in-sync with Linux interrupt subsystem.
2) Reduce number of traps taken when emulating Sstc for the
"Nested Guest" (i.e. Guest running under some "Guest Hypervisor"
which in-turn runs under a "Host Hypervisor").

In fact, the SBI set_timer() call also defines similar mechanism to
disable timer: "If the supervisor wishes to clear the timer interrupt
without scheduling the next timer event, it can either request a timer
interrupt infinitely far into the future (i.e., (uint64_t)-1), ...".

Regards,
Anup

>
> Alistair
>
> >
> > Signed-off-by: Anup Patel 
> > ---
> >  target/riscv/time_helper.c | 8 
> >  1 file changed, 8 insertions(+)
> >
> > diff --git a/target/riscv/time_helper.c b/target/riscv/time_helper.c
> > index 4fb2a471a9..1ee9f94813 100644
> > --- a/target/riscv/time_helper.c
> > +++ b/target/riscv/time_helper.c
> > @@ -72,6 +72,14 @@ void riscv_timer_write_timecmp(RISCVCPU *cpu, QEMUTimer 
> > *timer,
> >  riscv_cpu_update_mip(cpu, timer_irq, BOOL_TO_MASK(0));
> >  }
> >
> > +/*
> > + * Don't re-start the QEMU timer when timecmp == UINT64_MAX because
> > + * time CSR will wrap-around immediately after reaching UINT64_MAX.
> > + */
> > +if (timecmp == UINT64_MAX) {
> > +return;
> > +}
> > +
> >  /* otherwise, set up the future timer interrupt */
> >  diff = timecmp - rtc_r;
> >  /* back to ns (note args switched in muldiv64) */
> > --
> > 2.34.1
> >
> >



[PATCH 2/5] target/riscv: Update VS timer whenever htimedelta changes

2022-10-27 Thread Anup Patel
The htimedelta[h] CSR has impact on the VS timer comparison so we
should call riscv_timer_write_timecmp() whenever htimedelta changes.

Fixes: 3ec0fe18a31f ("target/riscv: Add vstimecmp suppor")
Signed-off-by: Anup Patel 
---
 target/riscv/csr.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 716f9d960e..4b1a608260 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -2722,6 +2722,8 @@ static RISCVException read_htimedelta(CPURISCVState *env, 
int csrno,
 static RISCVException write_htimedelta(CPURISCVState *env, int csrno,
target_ulong val)
 {
+RISCVCPU *cpu = env_archcpu(env);
+
 if (!env->rdtime_fn) {
 return RISCV_EXCP_ILLEGAL_INST;
 }
@@ -2731,6 +2733,12 @@ static RISCVException write_htimedelta(CPURISCVState 
*env, int csrno,
 } else {
 env->htimedelta = val;
 }
+
+if (cpu->cfg.ext_sstc && env->rdtime_fn) {
+riscv_timer_write_timecmp(cpu, env->vstimer, env->vstimecmp,
+  env->htimedelta, MIP_VSTIP);
+}
+
 return RISCV_EXCP_NONE;
 }
 
@@ -2748,11 +2756,19 @@ static RISCVException read_htimedeltah(CPURISCVState 
*env, int csrno,
 static RISCVException write_htimedeltah(CPURISCVState *env, int csrno,
 target_ulong val)
 {
+RISCVCPU *cpu = env_archcpu(env);
+
 if (!env->rdtime_fn) {
 return RISCV_EXCP_ILLEGAL_INST;
 }
 
 env->htimedelta = deposit64(env->htimedelta, 32, 32, (uint64_t)val);
+
+if (cpu->cfg.ext_sstc && env->rdtime_fn) {
+riscv_timer_write_timecmp(cpu, env->vstimer, env->vstimecmp,
+  env->htimedelta, MIP_VSTIP);
+}
+
 return RISCV_EXCP_NONE;
 }
 
-- 
2.34.1




[PATCH 4/5] target/riscv: No need to re-start QEMU timer when timecmp == UINT64_MAX

2022-10-27 Thread Anup Patel
The time CSR will wrap-around immediately after reaching UINT64_MAX
so we don't need to re-start QEMU timer when timecmp == UINT64_MAX
in riscv_timer_write_timecmp().

Signed-off-by: Anup Patel 
---
 target/riscv/time_helper.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/target/riscv/time_helper.c b/target/riscv/time_helper.c
index 4fb2a471a9..1ee9f94813 100644
--- a/target/riscv/time_helper.c
+++ b/target/riscv/time_helper.c
@@ -72,6 +72,14 @@ void riscv_timer_write_timecmp(RISCVCPU *cpu, QEMUTimer 
*timer,
 riscv_cpu_update_mip(cpu, timer_irq, BOOL_TO_MASK(0));
 }
 
+/*
+ * Don't re-start the QEMU timer when timecmp == UINT64_MAX because
+ * time CSR will wrap-around immediately after reaching UINT64_MAX.
+ */
+if (timecmp == UINT64_MAX) {
+return;
+}
+
 /* otherwise, set up the future timer interrupt */
 diff = timecmp - rtc_r;
 /* back to ns (note args switched in muldiv64) */
-- 
2.34.1




[PATCH 3/5] target/riscv: Don't clear mask in riscv_cpu_update_mip() for VSTIP

2022-10-27 Thread Anup Patel
Instead of clearing mask in riscv_cpu_update_mip() for VSTIP, we
should call riscv_cpu_update_mip() with mask == 0 from timer_helper.c
for VSTIP.

Fixes: 3ec0fe18a31f ("target/riscv: Add vstimecmp suppor")
Signed-off-by: Anup Patel 
---
 target/riscv/cpu_helper.c  |  2 --
 target/riscv/time_helper.c | 12 
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 5d66246c2c..a403825e49 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -617,8 +617,6 @@ uint64_t riscv_cpu_update_mip(RISCVCPU *cpu, uint64_t mask, 
uint64_t value)
 vsgein = (env->hgeip & (1ULL << gein)) ? MIP_VSEIP : 0;
 }
 
-/* No need to update mip for VSTIP */
-mask = ((mask == MIP_VSTIP) && env->vstime_irq) ? 0 : mask;
 vstip = env->vstime_irq ? MIP_VSTIP : 0;
 
 if (!qemu_mutex_iothread_locked()) {
diff --git a/target/riscv/time_helper.c b/target/riscv/time_helper.c
index 8cce667dfd..4fb2a471a9 100644
--- a/target/riscv/time_helper.c
+++ b/target/riscv/time_helper.c
@@ -27,7 +27,7 @@ static void riscv_vstimer_cb(void *opaque)
 RISCVCPU *cpu = opaque;
 CPURISCVState *env = >env;
 env->vstime_irq = 1;
-riscv_cpu_update_mip(cpu, MIP_VSTIP, BOOL_TO_MASK(1));
+riscv_cpu_update_mip(cpu, 0, BOOL_TO_MASK(1));
 }
 
 static void riscv_stimer_cb(void *opaque)
@@ -57,16 +57,20 @@ void riscv_timer_write_timecmp(RISCVCPU *cpu, QEMUTimer 
*timer,
  */
 if (timer_irq == MIP_VSTIP) {
 env->vstime_irq = 1;
+riscv_cpu_update_mip(cpu, 0, BOOL_TO_MASK(1));
+} else {
+riscv_cpu_update_mip(cpu, MIP_STIP, BOOL_TO_MASK(1));
 }
-riscv_cpu_update_mip(cpu, timer_irq, BOOL_TO_MASK(1));
 return;
 }
 
+/* Clear the [VS|S]TIP bit in mip */
 if (timer_irq == MIP_VSTIP) {
 env->vstime_irq = 0;
+riscv_cpu_update_mip(cpu, 0, BOOL_TO_MASK(0));
+} else {
+riscv_cpu_update_mip(cpu, timer_irq, BOOL_TO_MASK(0));
 }
-/* Clear the [V]STIP bit in mip */
-riscv_cpu_update_mip(cpu, timer_irq, BOOL_TO_MASK(0));
 
 /* otherwise, set up the future timer interrupt */
 diff = timecmp - rtc_r;
-- 
2.34.1




[PATCH 1/5] target/riscv: Typo fix in sstc() predicate

2022-10-27 Thread Anup Patel
We should use "&&" instead of "&" when checking hcounteren.TM and
henvcfg.STCE bits.

Fixes: 3ec0fe18a31f ("target/riscv: Add vstimecmp suppor")
Signed-off-by: Anup Patel 
---
 target/riscv/csr.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 5c9a7ee287..716f9d960e 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -838,7 +838,7 @@ static RISCVException sstc(CPURISCVState *env, int csrno)
 }
 
 if (riscv_cpu_virt_enabled(env)) {
-if (!(get_field(env->hcounteren, COUNTEREN_TM) &
+if (!(get_field(env->hcounteren, COUNTEREN_TM) &&
   get_field(env->henvcfg, HENVCFG_STCE))) {
 return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
 }
-- 
2.34.1




[PATCH 5/5] target/riscv: Ensure opcode is saved for all relevant instructions

2022-10-27 Thread Anup Patel
We should call decode_save_opc() for all relevant instructions which
can potentially generate a virtual instruction fault or a guest page
fault because generating transformed instruction upon guest page fault
expects opcode to be available. Without this, hypervisor will see
transformed instruction as zero in htinst CSR for guest MMIO emulation
which makes MMIO emulation in hypervisor slow and also breaks nested
virtualization.

Fixes: a9814e3e08d2 ("target/riscv: Minimize the calls to decode_save_opc")
Signed-off-by: Anup Patel 
---
 target/riscv/insn_trans/trans_rva.c.inc | 10 +++---
 target/riscv/insn_trans/trans_rvd.c.inc |  2 ++
 target/riscv/insn_trans/trans_rvf.c.inc |  2 ++
 target/riscv/insn_trans/trans_rvh.c.inc |  3 +++
 target/riscv/insn_trans/trans_rvi.c.inc |  2 ++
 target/riscv/insn_trans/trans_rvzfh.c.inc   |  2 ++
 target/riscv/insn_trans/trans_svinval.c.inc |  3 +++
 7 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/target/riscv/insn_trans/trans_rva.c.inc 
b/target/riscv/insn_trans/trans_rva.c.inc
index 45db82c9be..5f194a447b 100644
--- a/target/riscv/insn_trans/trans_rva.c.inc
+++ b/target/riscv/insn_trans/trans_rva.c.inc
@@ -20,8 +20,10 @@
 
 static bool gen_lr(DisasContext *ctx, arg_atomic *a, MemOp mop)
 {
-TCGv src1 = get_address(ctx, a->rs1, 0);
+TCGv src1;
 
+decode_save_opc(ctx);
+src1 = get_address(ctx, a->rs1, 0);
 if (a->rl) {
 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
 }
@@ -43,6 +45,7 @@ static bool gen_sc(DisasContext *ctx, arg_atomic *a, MemOp 
mop)
 TCGLabel *l1 = gen_new_label();
 TCGLabel *l2 = gen_new_label();
 
+decode_save_opc(ctx);
 src1 = get_address(ctx, a->rs1, 0);
 tcg_gen_brcond_tl(TCG_COND_NE, load_res, src1, l1);
 
@@ -81,9 +84,10 @@ static bool gen_amo(DisasContext *ctx, arg_atomic *a,
 MemOp mop)
 {
 TCGv dest = dest_gpr(ctx, a->rd);
-TCGv src1 = get_address(ctx, a->rs1, 0);
-TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
+TCGv src1, src2 = get_gpr(ctx, a->rs2, EXT_NONE);
 
+decode_save_opc(ctx);
+src1 = get_address(ctx, a->rs1, 0);
 func(dest, src1, src2, ctx->mem_idx, mop);
 
 gen_set_gpr(ctx, a->rd, dest);
diff --git a/target/riscv/insn_trans/trans_rvd.c.inc 
b/target/riscv/insn_trans/trans_rvd.c.inc
index 1397c1ce1c..6e3159b797 100644
--- a/target/riscv/insn_trans/trans_rvd.c.inc
+++ b/target/riscv/insn_trans/trans_rvd.c.inc
@@ -38,6 +38,7 @@ static bool trans_fld(DisasContext *ctx, arg_fld *a)
 REQUIRE_FPU;
 REQUIRE_EXT(ctx, RVD);
 
+decode_save_opc(ctx);
 addr = get_address(ctx, a->rs1, a->imm);
 tcg_gen_qemu_ld_i64(cpu_fpr[a->rd], addr, ctx->mem_idx, MO_TEUQ);
 
@@ -52,6 +53,7 @@ static bool trans_fsd(DisasContext *ctx, arg_fsd *a)
 REQUIRE_FPU;
 REQUIRE_EXT(ctx, RVD);
 
+decode_save_opc(ctx);
 addr = get_address(ctx, a->rs1, a->imm);
 tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], addr, ctx->mem_idx, MO_TEUQ);
 return true;
diff --git a/target/riscv/insn_trans/trans_rvf.c.inc 
b/target/riscv/insn_trans/trans_rvf.c.inc
index a1d3eb52ad..965e1f8d11 100644
--- a/target/riscv/insn_trans/trans_rvf.c.inc
+++ b/target/riscv/insn_trans/trans_rvf.c.inc
@@ -38,6 +38,7 @@ static bool trans_flw(DisasContext *ctx, arg_flw *a)
 REQUIRE_FPU;
 REQUIRE_EXT(ctx, RVF);
 
+decode_save_opc(ctx);
 addr = get_address(ctx, a->rs1, a->imm);
 dest = cpu_fpr[a->rd];
 tcg_gen_qemu_ld_i64(dest, addr, ctx->mem_idx, MO_TEUL);
@@ -54,6 +55,7 @@ static bool trans_fsw(DisasContext *ctx, arg_fsw *a)
 REQUIRE_FPU;
 REQUIRE_EXT(ctx, RVF);
 
+decode_save_opc(ctx);
 addr = get_address(ctx, a->rs1, a->imm);
 tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], addr, ctx->mem_idx, MO_TEUL);
 return true;
diff --git a/target/riscv/insn_trans/trans_rvh.c.inc 
b/target/riscv/insn_trans/trans_rvh.c.inc
index 4f8aecddc7..9248b48c36 100644
--- a/target/riscv/insn_trans/trans_rvh.c.inc
+++ b/target/riscv/insn_trans/trans_rvh.c.inc
@@ -36,6 +36,7 @@ static bool do_hlv(DisasContext *ctx, arg_r2 *a, MemOp mop)
 #ifdef CONFIG_USER_ONLY
 return false;
 #else
+decode_save_opc(ctx);
 if (check_access(ctx)) {
 TCGv dest = dest_gpr(ctx, a->rd);
 TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
@@ -82,6 +83,7 @@ static bool do_hsv(DisasContext *ctx, arg_r2_s *a, MemOp mop)
 #ifdef CONFIG_USER_ONLY
 return false;
 #else
+decode_save_opc(ctx);
 if (check_access(ctx)) {
 TCGv addr = get_gpr(ctx, a->rs1, EXT_NONE);
 TCGv data = get_gpr(ctx, a->rs2, EXT_NONE);
@@ -135,6 +137,7 @@ static bool trans_hsv_d(DisasContext *ctx, arg_hsv_d *a)
 static bool do_hlvx(DisasContext *ctx, arg_r2 *a,
 void (*func)(TCGv, TCGv_env, TCGv))
 {
+decode_save_opc(ctx);
 if (check_access(ctx)) {
 TCGv dest = dest_gpr(ctx, a->rd);
 TCGv a

[PATCH 0/5] Nested virtualization fixes for QEMU

2022-10-27 Thread Anup Patel
This series mainly includes fixes discovered while developing nested
virtualization running on QEMU.

These patches can also be found in the riscv_nested_fixes_v1 branch at:
https://github.com/avpatel/qemu.git

Anup Patel (5):
  target/riscv: Typo fix in sstc() predicate
  target/riscv: Update VS timer whenever htimedelta changes
  target/riscv: Don't clear mask in riscv_cpu_update_mip() for VSTIP
  target/riscv: No need to re-start QEMU timer when timecmp ==
UINT64_MAX
  target/riscv: Ensure opcode is saved for all relevant instructions

 target/riscv/cpu_helper.c   |  2 --
 target/riscv/csr.c  | 18 +-
 target/riscv/insn_trans/trans_rva.c.inc | 10 +++---
 target/riscv/insn_trans/trans_rvd.c.inc |  2 ++
 target/riscv/insn_trans/trans_rvf.c.inc |  2 ++
 target/riscv/insn_trans/trans_rvh.c.inc |  3 +++
 target/riscv/insn_trans/trans_rvi.c.inc |  2 ++
 target/riscv/insn_trans/trans_rvzfh.c.inc   |  2 ++
 target/riscv/insn_trans/trans_svinval.c.inc |  3 +++
 target/riscv/time_helper.c  | 20 
 10 files changed, 54 insertions(+), 10 deletions(-)

-- 
2.34.1




[PATCH v3] target/riscv: Use official extension names for AIA CSRs

2022-08-19 Thread Anup Patel
The arch review of AIA spec is completed and we now have official
extension names for AIA: Smaia (M-mode AIA CSRs) and Ssaia (S-mode
AIA CSRs).

Refer, section 1.6 of the latest AIA v0.3.1 stable specification at
https://github.com/riscv/riscv-aia/releases/download/0.3.1-draft.32/riscv-interrupts-032.pdf)

Based on above, we update QEMU RISC-V to:
1) Have separate config options for Smaia and Ssaia extensions
   which replace RISCV_FEATURE_AIA in CPU features
2) Not generate AIA INTC compatible string in virt machine

Signed-off-by: Anup Patel 
Reviewed-by: Andrew Jones 
---
Changes since v2:
 - Use env_archcpu() to get RISCVCPU * from CPURISCVState *
Changes since v1:
 - Remove redundant "has_aia" parameter from riscv_cpu_pending_to_irq()
---
 hw/intc/riscv_imsic.c |  4 +++-
 hw/riscv/virt.c   | 13 ++---
 target/riscv/cpu.c|  9 -
 target/riscv/cpu.h|  4 ++--
 target/riscv/cpu_helper.c |  3 ++-
 target/riscv/csr.c| 24 ++--
 6 files changed, 31 insertions(+), 26 deletions(-)

diff --git a/hw/intc/riscv_imsic.c b/hw/intc/riscv_imsic.c
index 8615e4cc1d..4d4d5b50ca 100644
--- a/hw/intc/riscv_imsic.c
+++ b/hw/intc/riscv_imsic.c
@@ -344,9 +344,11 @@ static void riscv_imsic_realize(DeviceState *dev, Error 
**errp)
 
 /* Force select AIA feature and setup CSR read-modify-write callback */
 if (env) {
-riscv_set_feature(env, RISCV_FEATURE_AIA);
 if (!imsic->mmode) {
+rcpu->cfg.ext_ssaia = true;
 riscv_cpu_set_geilen(env, imsic->num_pages - 1);
+} else {
+rcpu->cfg.ext_smaia = true;
 }
 riscv_cpu_set_aia_ireg_rmw_fn(env, (imsic->mmode) ? PRV_M : PRV_S,
   riscv_imsic_rmw, imsic);
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index e779d399ae..b041b33afc 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -261,17 +261,8 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int 
socket,
 qemu_fdt_add_subnode(mc->fdt, intc_name);
 qemu_fdt_setprop_cell(mc->fdt, intc_name, "phandle",
 intc_phandles[cpu]);
-if (riscv_feature(>soc[socket].harts[cpu].env,
-  RISCV_FEATURE_AIA)) {
-static const char * const compat[2] = {
-"riscv,cpu-intc-aia", "riscv,cpu-intc"
-};
-qemu_fdt_setprop_string_array(mc->fdt, intc_name, "compatible",
-  (char **), ARRAY_SIZE(compat));
-} else {
-qemu_fdt_setprop_string(mc->fdt, intc_name, "compatible",
-"riscv,cpu-intc");
-}
+qemu_fdt_setprop_string(mc->fdt, intc_name, "compatible",
+"riscv,cpu-intc");
 qemu_fdt_setprop(mc->fdt, intc_name, "interrupt-controller", NULL, 0);
 qemu_fdt_setprop_cell(mc->fdt, intc_name, "#interrupt-cells", 1);
 
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index d3fbaa..3cf0c86661 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -101,6 +101,8 @@ static const struct isa_ext_data isa_edata_arr[] = {
 ISA_EXT_DATA_ENTRY(zve64f, true, PRIV_VERSION_1_12_0, ext_zve64f),
 ISA_EXT_DATA_ENTRY(zhinx, true, PRIV_VERSION_1_12_0, ext_zhinx),
 ISA_EXT_DATA_ENTRY(zhinxmin, true, PRIV_VERSION_1_12_0, ext_zhinxmin),
+ISA_EXT_DATA_ENTRY(smaia, true, PRIV_VERSION_1_12_0, ext_smaia),
+ISA_EXT_DATA_ENTRY(ssaia, true, PRIV_VERSION_1_12_0, ext_ssaia),
 ISA_EXT_DATA_ENTRY(sscofpmf, true, PRIV_VERSION_1_12_0, ext_sscofpmf),
 ISA_EXT_DATA_ENTRY(sstc, true, PRIV_VERSION_1_12_0, ext_sstc),
 ISA_EXT_DATA_ENTRY(svinval, true, PRIV_VERSION_1_12_0, ext_svinval),
@@ -669,10 +671,6 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 }
 }
 
-if (cpu->cfg.aia) {
-riscv_set_feature(env, RISCV_FEATURE_AIA);
-}
-
 if (cpu->cfg.debug) {
 riscv_set_feature(env, RISCV_FEATURE_DEBUG);
 }
@@ -1058,7 +1056,8 @@ static Property riscv_cpu_extensions[] = {
 DEFINE_PROP_BOOL("x-j", RISCVCPU, cfg.ext_j, false),
 /* ePMP 0.9.3 */
 DEFINE_PROP_BOOL("x-epmp", RISCVCPU, cfg.epmp, false),
-DEFINE_PROP_BOOL("x-aia", RISCVCPU, cfg.aia, false),
+DEFINE_PROP_BOOL("x-smaia", RISCVCPU, cfg.ext_smaia, false),
+DEFINE_PROP_BOOL("x-ssaia", RISCVCPU, cfg.ext_ssaia, false),
 
 DEFINE_PROP_END_OF_LIST(),
 };
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 42edfa4558..15cad73def 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -85,7 +85,6 @@ enum {
 RISCV_FEATURE_PMP,
 RISCV_FEATURE_EPMP,
 RISCV_FEATURE_MISA,
-RISCV_FEATURE_AIA,
 RISCV_FEATURE_DEBUG
 };
 
@@ -452,6 +451,8 @@ struct RISCVCPUConfig {
 bool ext_zve64f;
 b

Re: [PATCH v2] target/riscv: Use official extension names for AIA CSRs

2022-08-19 Thread Anup Patel
On Fri, Aug 19, 2022 at 8:40 PM Richard Henderson
 wrote:
>
> On 8/19/22 00:31, Anup Patel wrote:
> >   static int aia_hmode(CPURISCVState *env, int csrno)
> >   {
> > -if (!riscv_feature(env, RISCV_FEATURE_AIA)) {
> > +CPUState *cs = env_cpu(env);
> > +RISCVCPU *cpu = RISCV_CPU(cs);
>
> Better as
>
>  RISCVCPU *cpu = env_archcpu(env);

Okay, I will update.

Thanks,
Anup

>
>
> r~



[PATCH v2] target/riscv: Use official extension names for AIA CSRs

2022-08-19 Thread Anup Patel
The arch review of AIA spec is completed and we now have official
extension names for AIA: Smaia (M-mode AIA CSRs) and Ssaia (S-mode
AIA CSRs).

Refer, section 1.6 of the latest AIA v0.3.1 stable specification at
https://github.com/riscv/riscv-aia/releases/download/0.3.1-draft.32/riscv-interrupts-032.pdf)

Based on above, we update QEMU RISC-V to:
1) Have separate config options for Smaia and Ssaia extensions
   which replace RISCV_FEATURE_AIA in CPU features
2) Not generate AIA INTC compatible string in virt machine

Signed-off-by: Anup Patel 
Reviewed-by: Andrew Jones 
---
Changes since v1:
 - Remove redundant "has_aia" parameter from riscv_cpu_pending_to_irq()
---
 hw/intc/riscv_imsic.c |  4 +++-
 hw/riscv/virt.c   | 13 ++---
 target/riscv/cpu.c|  9 -
 target/riscv/cpu.h|  4 ++--
 target/riscv/cpu_helper.c |  4 +++-
 target/riscv/csr.c| 30 --
 6 files changed, 38 insertions(+), 26 deletions(-)

diff --git a/hw/intc/riscv_imsic.c b/hw/intc/riscv_imsic.c
index 8615e4cc1d..4d4d5b50ca 100644
--- a/hw/intc/riscv_imsic.c
+++ b/hw/intc/riscv_imsic.c
@@ -344,9 +344,11 @@ static void riscv_imsic_realize(DeviceState *dev, Error 
**errp)
 
 /* Force select AIA feature and setup CSR read-modify-write callback */
 if (env) {
-riscv_set_feature(env, RISCV_FEATURE_AIA);
 if (!imsic->mmode) {
+rcpu->cfg.ext_ssaia = true;
 riscv_cpu_set_geilen(env, imsic->num_pages - 1);
+} else {
+rcpu->cfg.ext_smaia = true;
 }
 riscv_cpu_set_aia_ireg_rmw_fn(env, (imsic->mmode) ? PRV_M : PRV_S,
   riscv_imsic_rmw, imsic);
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index e779d399ae..b041b33afc 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -261,17 +261,8 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int 
socket,
 qemu_fdt_add_subnode(mc->fdt, intc_name);
 qemu_fdt_setprop_cell(mc->fdt, intc_name, "phandle",
 intc_phandles[cpu]);
-if (riscv_feature(>soc[socket].harts[cpu].env,
-  RISCV_FEATURE_AIA)) {
-static const char * const compat[2] = {
-"riscv,cpu-intc-aia", "riscv,cpu-intc"
-};
-qemu_fdt_setprop_string_array(mc->fdt, intc_name, "compatible",
-  (char **), ARRAY_SIZE(compat));
-} else {
-qemu_fdt_setprop_string(mc->fdt, intc_name, "compatible",
-"riscv,cpu-intc");
-}
+qemu_fdt_setprop_string(mc->fdt, intc_name, "compatible",
+"riscv,cpu-intc");
 qemu_fdt_setprop(mc->fdt, intc_name, "interrupt-controller", NULL, 0);
 qemu_fdt_setprop_cell(mc->fdt, intc_name, "#interrupt-cells", 1);
 
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index d3fbaa..3cf0c86661 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -101,6 +101,8 @@ static const struct isa_ext_data isa_edata_arr[] = {
 ISA_EXT_DATA_ENTRY(zve64f, true, PRIV_VERSION_1_12_0, ext_zve64f),
 ISA_EXT_DATA_ENTRY(zhinx, true, PRIV_VERSION_1_12_0, ext_zhinx),
 ISA_EXT_DATA_ENTRY(zhinxmin, true, PRIV_VERSION_1_12_0, ext_zhinxmin),
+ISA_EXT_DATA_ENTRY(smaia, true, PRIV_VERSION_1_12_0, ext_smaia),
+ISA_EXT_DATA_ENTRY(ssaia, true, PRIV_VERSION_1_12_0, ext_ssaia),
 ISA_EXT_DATA_ENTRY(sscofpmf, true, PRIV_VERSION_1_12_0, ext_sscofpmf),
 ISA_EXT_DATA_ENTRY(sstc, true, PRIV_VERSION_1_12_0, ext_sstc),
 ISA_EXT_DATA_ENTRY(svinval, true, PRIV_VERSION_1_12_0, ext_svinval),
@@ -669,10 +671,6 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 }
 }
 
-if (cpu->cfg.aia) {
-riscv_set_feature(env, RISCV_FEATURE_AIA);
-}
-
 if (cpu->cfg.debug) {
 riscv_set_feature(env, RISCV_FEATURE_DEBUG);
 }
@@ -1058,7 +1056,8 @@ static Property riscv_cpu_extensions[] = {
 DEFINE_PROP_BOOL("x-j", RISCVCPU, cfg.ext_j, false),
 /* ePMP 0.9.3 */
 DEFINE_PROP_BOOL("x-epmp", RISCVCPU, cfg.epmp, false),
-DEFINE_PROP_BOOL("x-aia", RISCVCPU, cfg.aia, false),
+DEFINE_PROP_BOOL("x-smaia", RISCVCPU, cfg.ext_smaia, false),
+DEFINE_PROP_BOOL("x-ssaia", RISCVCPU, cfg.ext_ssaia, false),
 
 DEFINE_PROP_END_OF_LIST(),
 };
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 42edfa4558..15cad73def 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -85,7 +85,6 @@ enum {
 RISCV_FEATURE_PMP,
 RISCV_FEATURE_EPMP,
 RISCV_FEATURE_MISA,
-RISCV_FEATURE_AIA,
 RISCV_FEATURE_DEBUG
 };
 
@@ -452,6 +451,8 @@ struct RISCVCPUConfig {
 bool ext_zve64f;
 bool ext_zmmul;
 bool ext_sscofpmf;
+bool ext_smaia;
+bool ex

Re: [PATCH] target/riscv: Use official extension names for AIA CSRs

2022-08-18 Thread Anup Patel
On Fri, Aug 19, 2022 at 10:24 AM Weiwei Li  wrote:
>
>
> 在 2022/8/19 上午11:09, Anup Patel 写道:
> > The arch review of AIA spec is completed and we now have official
> > extension names for AIA: Smaia (M-mode AIA CSRs) and Ssaia (S-mode
> > AIA CSRs).
> >
> > Refer, section 1.6 of the latest AIA v0.3.1 stable specification at
> > https://github.com/riscv/riscv-aia/releases/download/0.3.1-draft.32/riscv-interrupts-032.pdf)
> >
> > Based on above, we update QEMU RISC-V to:
> > 1) Have separate config options for Smaia and Ssaia extensions
> > which replace RISCV_FEATURE_AIA in CPU features
> > 2) Not generate AIA INTC compatible string in virt machine
> >
> > Signed-off-by: Anup Patel 
> > Reviewed-by: Andrew Jones 
> > ---
> >   hw/intc/riscv_imsic.c |  4 +++-
> >   hw/riscv/virt.c   | 13 ++---
> >   target/riscv/cpu.c|  9 -
> >   target/riscv/cpu.h|  4 ++--
> >   target/riscv/cpu_helper.c | 30 ++
> >   target/riscv/csr.c| 30 --
> >   6 files changed, 57 insertions(+), 33 deletions(-)
> >
> > diff --git a/hw/intc/riscv_imsic.c b/hw/intc/riscv_imsic.c
> > index 8615e4cc1d..4d4d5b50ca 100644
> > --- a/hw/intc/riscv_imsic.c
> > +++ b/hw/intc/riscv_imsic.c
> > @@ -344,9 +344,11 @@ static void riscv_imsic_realize(DeviceState *dev, 
> > Error **errp)
> >
> >   /* Force select AIA feature and setup CSR read-modify-write callback 
> > */
> >   if (env) {
> > -riscv_set_feature(env, RISCV_FEATURE_AIA);
> >   if (!imsic->mmode) {
> > +rcpu->cfg.ext_ssaia = true;
> >   riscv_cpu_set_geilen(env, imsic->num_pages - 1);
> > +} else {
> > +rcpu->cfg.ext_smaia = true;
> >   }
> >   riscv_cpu_set_aia_ireg_rmw_fn(env, (imsic->mmode) ? PRV_M : PRV_S,
> > riscv_imsic_rmw, imsic);
> > diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> > index e779d399ae..b041b33afc 100644
> > --- a/hw/riscv/virt.c
> > +++ b/hw/riscv/virt.c
> > @@ -261,17 +261,8 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, 
> > int socket,
> >   qemu_fdt_add_subnode(mc->fdt, intc_name);
> >   qemu_fdt_setprop_cell(mc->fdt, intc_name, "phandle",
> >   intc_phandles[cpu]);
> > -if (riscv_feature(>soc[socket].harts[cpu].env,
> > -  RISCV_FEATURE_AIA)) {
> > -static const char * const compat[2] = {
> > -"riscv,cpu-intc-aia", "riscv,cpu-intc"
> > -};
> > -qemu_fdt_setprop_string_array(mc->fdt, intc_name, "compatible",
> > -  (char **), 
> > ARRAY_SIZE(compat));
> > -} else {
> > -qemu_fdt_setprop_string(mc->fdt, intc_name, "compatible",
> > -"riscv,cpu-intc");
> > -}
> > +qemu_fdt_setprop_string(mc->fdt, intc_name, "compatible",
> > +"riscv,cpu-intc");
> >   qemu_fdt_setprop(mc->fdt, intc_name, "interrupt-controller", 
> > NULL, 0);
> >   qemu_fdt_setprop_cell(mc->fdt, intc_name, "#interrupt-cells", 1);
> >
> > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> > index d3fbaa..3cf0c86661 100644
> > --- a/target/riscv/cpu.c
> > +++ b/target/riscv/cpu.c
> > @@ -101,6 +101,8 @@ static const struct isa_ext_data isa_edata_arr[] = {
> >   ISA_EXT_DATA_ENTRY(zve64f, true, PRIV_VERSION_1_12_0, ext_zve64f),
> >   ISA_EXT_DATA_ENTRY(zhinx, true, PRIV_VERSION_1_12_0, ext_zhinx),
> >   ISA_EXT_DATA_ENTRY(zhinxmin, true, PRIV_VERSION_1_12_0, ext_zhinxmin),
> > +ISA_EXT_DATA_ENTRY(smaia, true, PRIV_VERSION_1_12_0, ext_smaia),
> > +ISA_EXT_DATA_ENTRY(ssaia, true, PRIV_VERSION_1_12_0, ext_ssaia),
> >   ISA_EXT_DATA_ENTRY(sscofpmf, true, PRIV_VERSION_1_12_0, ext_sscofpmf),
> >   ISA_EXT_DATA_ENTRY(sstc, true, PRIV_VERSION_1_12_0, ext_sstc),
> >   ISA_EXT_DATA_ENTRY(svinval, true, PRIV_VERSION_1_12_0, ext_svinval),
> > @@ -669,10 +671,6 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
> > **errp)
> >   }
> >   }
> >
> > -if (cpu->cfg.aia) {
> > -riscv_set_feature(env, RISCV_FEATURE_AIA);
> > -}
> > -
> >   if (cpu->cfg.debug) {
> >   ri

[PATCH] target/riscv: Use official extension names for AIA CSRs

2022-08-18 Thread Anup Patel
The arch review of AIA spec is completed and we now have official
extension names for AIA: Smaia (M-mode AIA CSRs) and Ssaia (S-mode
AIA CSRs).

Refer, section 1.6 of the latest AIA v0.3.1 stable specification at
https://github.com/riscv/riscv-aia/releases/download/0.3.1-draft.32/riscv-interrupts-032.pdf)

Based on above, we update QEMU RISC-V to:
1) Have separate config options for Smaia and Ssaia extensions
   which replace RISCV_FEATURE_AIA in CPU features
2) Not generate AIA INTC compatible string in virt machine

Signed-off-by: Anup Patel 
Reviewed-by: Andrew Jones 
---
 hw/intc/riscv_imsic.c |  4 +++-
 hw/riscv/virt.c   | 13 ++---
 target/riscv/cpu.c|  9 -
 target/riscv/cpu.h|  4 ++--
 target/riscv/cpu_helper.c | 30 ++
 target/riscv/csr.c| 30 --
 6 files changed, 57 insertions(+), 33 deletions(-)

diff --git a/hw/intc/riscv_imsic.c b/hw/intc/riscv_imsic.c
index 8615e4cc1d..4d4d5b50ca 100644
--- a/hw/intc/riscv_imsic.c
+++ b/hw/intc/riscv_imsic.c
@@ -344,9 +344,11 @@ static void riscv_imsic_realize(DeviceState *dev, Error 
**errp)
 
 /* Force select AIA feature and setup CSR read-modify-write callback */
 if (env) {
-riscv_set_feature(env, RISCV_FEATURE_AIA);
 if (!imsic->mmode) {
+rcpu->cfg.ext_ssaia = true;
 riscv_cpu_set_geilen(env, imsic->num_pages - 1);
+} else {
+rcpu->cfg.ext_smaia = true;
 }
 riscv_cpu_set_aia_ireg_rmw_fn(env, (imsic->mmode) ? PRV_M : PRV_S,
   riscv_imsic_rmw, imsic);
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index e779d399ae..b041b33afc 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -261,17 +261,8 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int 
socket,
 qemu_fdt_add_subnode(mc->fdt, intc_name);
 qemu_fdt_setprop_cell(mc->fdt, intc_name, "phandle",
 intc_phandles[cpu]);
-if (riscv_feature(>soc[socket].harts[cpu].env,
-  RISCV_FEATURE_AIA)) {
-static const char * const compat[2] = {
-"riscv,cpu-intc-aia", "riscv,cpu-intc"
-};
-qemu_fdt_setprop_string_array(mc->fdt, intc_name, "compatible",
-  (char **), ARRAY_SIZE(compat));
-} else {
-qemu_fdt_setprop_string(mc->fdt, intc_name, "compatible",
-"riscv,cpu-intc");
-}
+qemu_fdt_setprop_string(mc->fdt, intc_name, "compatible",
+"riscv,cpu-intc");
 qemu_fdt_setprop(mc->fdt, intc_name, "interrupt-controller", NULL, 0);
 qemu_fdt_setprop_cell(mc->fdt, intc_name, "#interrupt-cells", 1);
 
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index d3fbaa..3cf0c86661 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -101,6 +101,8 @@ static const struct isa_ext_data isa_edata_arr[] = {
 ISA_EXT_DATA_ENTRY(zve64f, true, PRIV_VERSION_1_12_0, ext_zve64f),
 ISA_EXT_DATA_ENTRY(zhinx, true, PRIV_VERSION_1_12_0, ext_zhinx),
 ISA_EXT_DATA_ENTRY(zhinxmin, true, PRIV_VERSION_1_12_0, ext_zhinxmin),
+ISA_EXT_DATA_ENTRY(smaia, true, PRIV_VERSION_1_12_0, ext_smaia),
+ISA_EXT_DATA_ENTRY(ssaia, true, PRIV_VERSION_1_12_0, ext_ssaia),
 ISA_EXT_DATA_ENTRY(sscofpmf, true, PRIV_VERSION_1_12_0, ext_sscofpmf),
 ISA_EXT_DATA_ENTRY(sstc, true, PRIV_VERSION_1_12_0, ext_sstc),
 ISA_EXT_DATA_ENTRY(svinval, true, PRIV_VERSION_1_12_0, ext_svinval),
@@ -669,10 +671,6 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 }
 }
 
-if (cpu->cfg.aia) {
-riscv_set_feature(env, RISCV_FEATURE_AIA);
-}
-
 if (cpu->cfg.debug) {
 riscv_set_feature(env, RISCV_FEATURE_DEBUG);
 }
@@ -1058,7 +1056,8 @@ static Property riscv_cpu_extensions[] = {
 DEFINE_PROP_BOOL("x-j", RISCVCPU, cfg.ext_j, false),
 /* ePMP 0.9.3 */
 DEFINE_PROP_BOOL("x-epmp", RISCVCPU, cfg.epmp, false),
-DEFINE_PROP_BOOL("x-aia", RISCVCPU, cfg.aia, false),
+DEFINE_PROP_BOOL("x-smaia", RISCVCPU, cfg.ext_smaia, false),
+DEFINE_PROP_BOOL("x-ssaia", RISCVCPU, cfg.ext_ssaia, false),
 
 DEFINE_PROP_END_OF_LIST(),
 };
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 42edfa4558..15cad73def 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -85,7 +85,6 @@ enum {
 RISCV_FEATURE_PMP,
 RISCV_FEATURE_EPMP,
 RISCV_FEATURE_MISA,
-RISCV_FEATURE_AIA,
 RISCV_FEATURE_DEBUG
 };
 
@@ -452,6 +451,8 @@ struct RISCVCPUConfig {
 bool ext_zve64f;
 bool ext_zmmul;
 bool ext_sscofpmf;
+bool ext_smaia;
+bool ext_ssaia;
 bool rvv_ta_all_1s;
 bool rvv_ma_all_1s;
 
@@ -472,7 +473,6 @@

Re: [PATCH] target/riscv: Fix priority of csr related check in riscv_csrrw_check

2022-08-04 Thread Anup Patel
On Thu, Aug 4, 2022 at 5:59 PM Weiwei Li  wrote:
>
>
> 在 2022/8/4 上午11:38, Anup Patel 写道:
> > On Wed, Aug 3, 2022 at 6:16 PM Weiwei Li  wrote:
> >> Normally, riscv_csrrw_check is called when executing Zicsr instructions.
> >> And we can only do access control for existed CSRs. So the priority of
> >> CSR related check, from highest to lowest, should be as follows:
> >> 1) check whether Zicsr is supported: raise RISCV_EXCP_ILLEGAL_INST if not
> >> 2) check whether csr is existed: raise RISCV_EXCP_ILLEGAL_INST if not
> >> 3) do access control: raise RISCV_EXCP_ILLEGAL_INST or RISCV_EXCP_VIRT_
> >> INSTRUCTION_FAULT if not allowed
> >>
> >> The predicates contain parts of function of both 2) and 3), So they need
> >> to be placed in the middle of riscv_csrrw_check
> >>
> >> Signed-off-by: Weiwei Li 
> >> Signed-off-by: Junqiang Wang 
> >> ---
> >>   target/riscv/csr.c | 44 +---
> >>   1 file changed, 25 insertions(+), 19 deletions(-)
> >>
> >> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> >> index 0fb042b2fd..d81f466c80 100644
> >> --- a/target/riscv/csr.c
> >> +++ b/target/riscv/csr.c
> >> @@ -3270,6 +3270,30 @@ static inline RISCVException 
> >> riscv_csrrw_check(CPURISCVState *env,
> >>   /* check privileges and return RISCV_EXCP_ILLEGAL_INST if check 
> >> fails */
> >>   int read_only = get_field(csrno, 0xC00) == 3;
> >>   int csr_min_priv = csr_ops[csrno].min_priv_ver;
> >> +
> >> +/* ensure the CSR extension is enabled. */
> >> +if (!cpu->cfg.ext_icsr) {
> >> +return RISCV_EXCP_ILLEGAL_INST;
> >> +}
> >> +
> >> +if (env->priv_ver < csr_min_priv) {
> >> +return RISCV_EXCP_ILLEGAL_INST;
> > This line breaks nested virtualization because for nested virtualization
> > to work, the guest hypervisor accessing h and vs CSRs from
> > VS-mode should result in a virtual instruction trap not illegal
> > instruction trap.
> >
> > Regards,
> > Anup
>
> Do you mean "if (env->priv_ver < csr_min_priv)" ?

I got confused with the csr_min_priv name. This variable holds
min priv spec verison and not the privilege level required for
the CSR.

No issues with the "if (env->priv_ver < csr_min_priv)" check.

Regards,
Anup

>
> If so, I think illegal instruction trap is better, since the csr is not
> implemented(or existed) when
>
> env->priv_ver < csr_min_priv and virtual instruction trap is only raised
> for implemented csr access.
>
> Regards,
>
> Weiwei Li
>
> >> +}
> >> +
> >> +/* check predicate */
> >> +if (!csr_ops[csrno].predicate) {
> >> +return RISCV_EXCP_ILLEGAL_INST;
> >> +}
> >> +
> >> +if (write_mask && read_only) {
> >> +return RISCV_EXCP_ILLEGAL_INST;
> >> +}
> >> +
> >> +RISCVException ret = csr_ops[csrno].predicate(env, csrno);
> >> +if (ret != RISCV_EXCP_NONE) {
> >> +return ret;
> >> +}
> >> +
> >>   #if !defined(CONFIG_USER_ONLY)
> >>   int csr_priv, effective_priv = env->priv;
> >>
> >> @@ -3290,25 +3314,7 @@ static inline RISCVException 
> >> riscv_csrrw_check(CPURISCVState *env,
> >>   return RISCV_EXCP_ILLEGAL_INST;
> >>   }
> >>   #endif
> >> -if (write_mask && read_only) {
> >> -return RISCV_EXCP_ILLEGAL_INST;
> >> -}
> >> -
> >> -/* ensure the CSR extension is enabled. */
> >> -if (!cpu->cfg.ext_icsr) {
> >> -return RISCV_EXCP_ILLEGAL_INST;
> >> -}
> >> -
> >> -/* check predicate */
> >> -if (!csr_ops[csrno].predicate) {
> >> -return RISCV_EXCP_ILLEGAL_INST;
> >> -}
> >> -
> >> -if (env->priv_ver < csr_min_priv) {
> >> -return RISCV_EXCP_ILLEGAL_INST;
> >> -}
> >> -
> >> -return csr_ops[csrno].predicate(env, csrno);
> >> +return RISCV_EXCP_NONE;
> >>   }
> >>
> >>   static RISCVException riscv_csrrw_do64(CPURISCVState *env, int csrno,
> >> --
> >> 2.17.1
> >>
> >>
>



Re: [PATCH] target/riscv: Fix priority of csr related check in riscv_csrrw_check

2022-08-03 Thread Anup Patel
On Wed, Aug 3, 2022 at 6:16 PM Weiwei Li  wrote:
>
> Normally, riscv_csrrw_check is called when executing Zicsr instructions.
> And we can only do access control for existed CSRs. So the priority of
> CSR related check, from highest to lowest, should be as follows:
> 1) check whether Zicsr is supported: raise RISCV_EXCP_ILLEGAL_INST if not
> 2) check whether csr is existed: raise RISCV_EXCP_ILLEGAL_INST if not
> 3) do access control: raise RISCV_EXCP_ILLEGAL_INST or RISCV_EXCP_VIRT_
> INSTRUCTION_FAULT if not allowed
>
> The predicates contain parts of function of both 2) and 3), So they need
> to be placed in the middle of riscv_csrrw_check
>
> Signed-off-by: Weiwei Li 
> Signed-off-by: Junqiang Wang 
> ---
>  target/riscv/csr.c | 44 +---
>  1 file changed, 25 insertions(+), 19 deletions(-)
>
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index 0fb042b2fd..d81f466c80 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -3270,6 +3270,30 @@ static inline RISCVException 
> riscv_csrrw_check(CPURISCVState *env,
>  /* check privileges and return RISCV_EXCP_ILLEGAL_INST if check fails */
>  int read_only = get_field(csrno, 0xC00) == 3;
>  int csr_min_priv = csr_ops[csrno].min_priv_ver;
> +
> +/* ensure the CSR extension is enabled. */
> +if (!cpu->cfg.ext_icsr) {
> +return RISCV_EXCP_ILLEGAL_INST;
> +}
> +
> +if (env->priv_ver < csr_min_priv) {
> +return RISCV_EXCP_ILLEGAL_INST;

This line breaks nested virtualization because for nested virtualization
to work, the guest hypervisor accessing h and vs CSRs from
VS-mode should result in a virtual instruction trap not illegal
instruction trap.

Regards,
Anup

> +}
> +
> +/* check predicate */
> +if (!csr_ops[csrno].predicate) {
> +return RISCV_EXCP_ILLEGAL_INST;
> +}
> +
> +if (write_mask && read_only) {
> +return RISCV_EXCP_ILLEGAL_INST;
> +}
> +
> +RISCVException ret = csr_ops[csrno].predicate(env, csrno);
> +if (ret != RISCV_EXCP_NONE) {
> +return ret;
> +}
> +
>  #if !defined(CONFIG_USER_ONLY)
>  int csr_priv, effective_priv = env->priv;
>
> @@ -3290,25 +3314,7 @@ static inline RISCVException 
> riscv_csrrw_check(CPURISCVState *env,
>  return RISCV_EXCP_ILLEGAL_INST;
>  }
>  #endif
> -if (write_mask && read_only) {
> -return RISCV_EXCP_ILLEGAL_INST;
> -}
> -
> -/* ensure the CSR extension is enabled. */
> -if (!cpu->cfg.ext_icsr) {
> -return RISCV_EXCP_ILLEGAL_INST;
> -}
> -
> -/* check predicate */
> -if (!csr_ops[csrno].predicate) {
> -return RISCV_EXCP_ILLEGAL_INST;
> -}
> -
> -if (env->priv_ver < csr_min_priv) {
> -return RISCV_EXCP_ILLEGAL_INST;
> -}
> -
> -return csr_ops[csrno].predicate(env, csrno);
> +return RISCV_EXCP_NONE;
>  }
>
>  static RISCVException riscv_csrrw_do64(CPURISCVState *env, int csrno,
> --
> 2.17.1
>
>



Re: [PATCH] target/riscv: Ensure opcode is saved for every instruction

2022-07-26 Thread Anup Patel
On Wed, Jul 27, 2022 at 9:24 AM Richard Henderson
 wrote:
>
> On 7/26/22 20:25, Anup Patel wrote:
> > We should call decode_save_opc() for every decoded instruction
> > because generating transformed instruction upon guest page faults
> > expects opcode to be available. Without this, hypervisor sees
> > transformed instruction as zero in htinst CSR for guest MMIO
> > emulation which makes MMIO emulation in hypervisor slow and
> > also breaks nested virtualization.
>
> Then just add decode_save_opc to load/store insns, not everything including 
> plain
> arithmetic...

We will have to add for float load/store, atomics, and HLV/HSV as
well. Basically we end-up adding for everything except integer and
float arithmetic.

I see that decode_save_opc() only saves opcode in an array
through tcg_set_insn_start_param(). Which brings me to the
question about how much are we saving by distributing
decode_save_opc() calls ?

If we distribute decode_save_opc() calls then the code becomes
fragile for future changes and we will miss adding decode_save_opc()
for some new extensions.

Regards,
Anup

>
>
> r~
>
>
> >
> > Fixes: a9814e3e08d2 ("target/riscv: Minimize the calls to decode_save_opc")
> > Signed-off-by: Anup Patel 
> > ---
> >   target/riscv/insn_trans/trans_privileged.c.inc |  4 
> >   target/riscv/insn_trans/trans_rvh.c.inc|  2 --
> >   target/riscv/insn_trans/trans_rvi.c.inc|  2 --
> >   target/riscv/translate.c   | 10 --
> >   4 files changed, 4 insertions(+), 14 deletions(-)
> >
> > diff --git a/target/riscv/insn_trans/trans_privileged.c.inc 
> > b/target/riscv/insn_trans/trans_privileged.c.inc
> > index 46f96ad74d..53613682e8 100644
> > --- a/target/riscv/insn_trans/trans_privileged.c.inc
> > +++ b/target/riscv/insn_trans/trans_privileged.c.inc
> > @@ -75,7 +75,6 @@ static bool trans_sret(DisasContext *ctx, arg_sret *a)
> >   {
> >   #ifndef CONFIG_USER_ONLY
> >   if (has_ext(ctx, RVS)) {
> > -decode_save_opc(ctx);
> >   gen_helper_sret(cpu_pc, cpu_env);
> >   tcg_gen_exit_tb(NULL, 0); /* no chaining */
> >   ctx->base.is_jmp = DISAS_NORETURN;
> > @@ -91,7 +90,6 @@ static bool trans_sret(DisasContext *ctx, arg_sret *a)
> >   static bool trans_mret(DisasContext *ctx, arg_mret *a)
> >   {
> >   #ifndef CONFIG_USER_ONLY
> > -decode_save_opc(ctx);
> >   gen_helper_mret(cpu_pc, cpu_env);
> >   tcg_gen_exit_tb(NULL, 0); /* no chaining */
> >   ctx->base.is_jmp = DISAS_NORETURN;
> > @@ -104,7 +102,6 @@ static bool trans_mret(DisasContext *ctx, arg_mret *a)
> >   static bool trans_wfi(DisasContext *ctx, arg_wfi *a)
> >   {
> >   #ifndef CONFIG_USER_ONLY
> > -decode_save_opc(ctx);
> >   gen_set_pc_imm(ctx, ctx->pc_succ_insn);
> >   gen_helper_wfi(cpu_env);
> >   return true;
> > @@ -116,7 +113,6 @@ static bool trans_wfi(DisasContext *ctx, arg_wfi *a)
> >   static bool trans_sfence_vma(DisasContext *ctx, arg_sfence_vma *a)
> >   {
> >   #ifndef CONFIG_USER_ONLY
> > -decode_save_opc(ctx);
> >   gen_helper_tlb_flush(cpu_env);
> >   return true;
> >   #endif
> > diff --git a/target/riscv/insn_trans/trans_rvh.c.inc 
> > b/target/riscv/insn_trans/trans_rvh.c.inc
> > index 4f8aecddc7..cebcb3f8f6 100644
> > --- a/target/riscv/insn_trans/trans_rvh.c.inc
> > +++ b/target/riscv/insn_trans/trans_rvh.c.inc
> > @@ -169,7 +169,6 @@ static bool trans_hfence_gvma(DisasContext *ctx, 
> > arg_sfence_vma *a)
> >   {
> >   REQUIRE_EXT(ctx, RVH);
> >   #ifndef CONFIG_USER_ONLY
> > -decode_save_opc(ctx);
> >   gen_helper_hyp_gvma_tlb_flush(cpu_env);
> >   return true;
> >   #endif
> > @@ -180,7 +179,6 @@ static bool trans_hfence_vvma(DisasContext *ctx, 
> > arg_sfence_vma *a)
> >   {
> >   REQUIRE_EXT(ctx, RVH);
> >   #ifndef CONFIG_USER_ONLY
> > -decode_save_opc(ctx);
> >   gen_helper_hyp_tlb_flush(cpu_env);
> >   return true;
> >   #endif
> > diff --git a/target/riscv/insn_trans/trans_rvi.c.inc 
> > b/target/riscv/insn_trans/trans_rvi.c.inc
> > index c49dbec0eb..1f318ffbef 100644
> > --- a/target/riscv/insn_trans/trans_rvi.c.inc
> > +++ b/target/riscv/insn_trans/trans_rvi.c.inc
> > @@ -834,8 +834,6 @@ static bool trans_fence_i(DisasContext *ctx, 
> > arg_fence_i *a)
> >
> >   static bool do_csr_post(DisasContext *ctx)
> >   {
> > -/* The helper may raise ILLEGAL_INSN -- record binv for unwind. */
> 

[PATCH] target/riscv: Ensure opcode is saved for every instruction

2022-07-26 Thread Anup Patel
We should call decode_save_opc() for every decoded instruction
because generating transformed instruction upon guest page faults
expects opcode to be available. Without this, hypervisor sees
transformed instruction as zero in htinst CSR for guest MMIO
emulation which makes MMIO emulation in hypervisor slow and
also breaks nested virtualization.

Fixes: a9814e3e08d2 ("target/riscv: Minimize the calls to decode_save_opc")
Signed-off-by: Anup Patel 
---
 target/riscv/insn_trans/trans_privileged.c.inc |  4 
 target/riscv/insn_trans/trans_rvh.c.inc|  2 --
 target/riscv/insn_trans/trans_rvi.c.inc|  2 --
 target/riscv/translate.c   | 10 --
 4 files changed, 4 insertions(+), 14 deletions(-)

diff --git a/target/riscv/insn_trans/trans_privileged.c.inc 
b/target/riscv/insn_trans/trans_privileged.c.inc
index 46f96ad74d..53613682e8 100644
--- a/target/riscv/insn_trans/trans_privileged.c.inc
+++ b/target/riscv/insn_trans/trans_privileged.c.inc
@@ -75,7 +75,6 @@ static bool trans_sret(DisasContext *ctx, arg_sret *a)
 {
 #ifndef CONFIG_USER_ONLY
 if (has_ext(ctx, RVS)) {
-decode_save_opc(ctx);
 gen_helper_sret(cpu_pc, cpu_env);
 tcg_gen_exit_tb(NULL, 0); /* no chaining */
 ctx->base.is_jmp = DISAS_NORETURN;
@@ -91,7 +90,6 @@ static bool trans_sret(DisasContext *ctx, arg_sret *a)
 static bool trans_mret(DisasContext *ctx, arg_mret *a)
 {
 #ifndef CONFIG_USER_ONLY
-decode_save_opc(ctx);
 gen_helper_mret(cpu_pc, cpu_env);
 tcg_gen_exit_tb(NULL, 0); /* no chaining */
 ctx->base.is_jmp = DISAS_NORETURN;
@@ -104,7 +102,6 @@ static bool trans_mret(DisasContext *ctx, arg_mret *a)
 static bool trans_wfi(DisasContext *ctx, arg_wfi *a)
 {
 #ifndef CONFIG_USER_ONLY
-decode_save_opc(ctx);
 gen_set_pc_imm(ctx, ctx->pc_succ_insn);
 gen_helper_wfi(cpu_env);
 return true;
@@ -116,7 +113,6 @@ static bool trans_wfi(DisasContext *ctx, arg_wfi *a)
 static bool trans_sfence_vma(DisasContext *ctx, arg_sfence_vma *a)
 {
 #ifndef CONFIG_USER_ONLY
-decode_save_opc(ctx);
 gen_helper_tlb_flush(cpu_env);
 return true;
 #endif
diff --git a/target/riscv/insn_trans/trans_rvh.c.inc 
b/target/riscv/insn_trans/trans_rvh.c.inc
index 4f8aecddc7..cebcb3f8f6 100644
--- a/target/riscv/insn_trans/trans_rvh.c.inc
+++ b/target/riscv/insn_trans/trans_rvh.c.inc
@@ -169,7 +169,6 @@ static bool trans_hfence_gvma(DisasContext *ctx, 
arg_sfence_vma *a)
 {
 REQUIRE_EXT(ctx, RVH);
 #ifndef CONFIG_USER_ONLY
-decode_save_opc(ctx);
 gen_helper_hyp_gvma_tlb_flush(cpu_env);
 return true;
 #endif
@@ -180,7 +179,6 @@ static bool trans_hfence_vvma(DisasContext *ctx, 
arg_sfence_vma *a)
 {
 REQUIRE_EXT(ctx, RVH);
 #ifndef CONFIG_USER_ONLY
-decode_save_opc(ctx);
 gen_helper_hyp_tlb_flush(cpu_env);
 return true;
 #endif
diff --git a/target/riscv/insn_trans/trans_rvi.c.inc 
b/target/riscv/insn_trans/trans_rvi.c.inc
index c49dbec0eb..1f318ffbef 100644
--- a/target/riscv/insn_trans/trans_rvi.c.inc
+++ b/target/riscv/insn_trans/trans_rvi.c.inc
@@ -834,8 +834,6 @@ static bool trans_fence_i(DisasContext *ctx, arg_fence_i *a)
 
 static bool do_csr_post(DisasContext *ctx)
 {
-/* The helper may raise ILLEGAL_INSN -- record binv for unwind. */
-decode_save_opc(ctx);
 /* We may have changed important cpu state -- exit to main loop. */
 gen_set_pc_imm(ctx, ctx->pc_succ_insn);
 tcg_gen_exit_tb(NULL, 0);
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index a79d0cd95b..5425d19846 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -207,10 +207,10 @@ static void gen_check_nanbox_s(TCGv_i64 out, TCGv_i64 in)
 tcg_gen_movcond_i64(TCG_COND_GEU, out, in, t_max, in, t_nan);
 }
 
-static void decode_save_opc(DisasContext *ctx)
+static void decode_save_opc(DisasContext *ctx, target_ulong opc)
 {
 assert(ctx->insn_start != NULL);
-tcg_set_insn_start_param(ctx->insn_start, 1, ctx->opcode);
+tcg_set_insn_start_param(ctx->insn_start, 1, opc);
 ctx->insn_start = NULL;
 }
 
@@ -240,8 +240,6 @@ static void generate_exception(DisasContext *ctx, int excp)
 
 static void gen_exception_illegal(DisasContext *ctx)
 {
-tcg_gen_st_i32(tcg_constant_i32(ctx->opcode), cpu_env,
-   offsetof(CPURISCVState, bins));
 generate_exception(ctx, RISCV_EXCP_ILLEGAL_INST);
 }
 
@@ -643,8 +641,6 @@ static void gen_set_rm(DisasContext *ctx, int rm)
 return;
 }
 
-/* The helper may raise ILLEGAL_INSN -- record binv for unwind. */
-decode_save_opc(ctx);
 gen_helper_set_rounding_mode(cpu_env, tcg_constant_i32(rm));
 }
 
@@ -1055,6 +1051,7 @@ static void decode_opc(CPURISCVState *env, DisasContext 
*ctx, uint16_t opcode)
 
 /* Check for compressed insn */
 if (extract16(opcode, 0, 2) != 3) {
+decode_save_opc(ctx, opcode);
 if (!has_ext(ctx, RVC)) {
 gen_exception_illegal(ct

Re: [PATCH] target/riscv: Support SW update of PTE A/D bits and Ssptwad extension

2022-07-19 Thread Anup Patel
On Wed, Jul 20, 2022 at 5:02 AM Jim Shu  wrote:
>
> Hi Anup,
>
> Do you think it is OK if we only use ssptwad as a CPU option name
> but not a RISC-V extension? just like MMU and PMP options of RISC-V.
> (And we could change it to RISC-V extension in the future
> if Ssptwad becomes the formal RISC-V extension)
>
> Both HW/SW update schemes are already defined in RISC-V priv spec,
> so I think it's reasonable to implement them in QEMU. The only issue here is
> to choose a proper CPU option name to turn on/off HW update of A/D bits.

I am not saying that we should avoid implementing it in QEMU.

My suggestion is to differentiate HW optionalities from ISA extensions
in QEMU. For example, instead of referring to this as Ssptwad, we should
call it "hw_ptwad" or "opt_ptwad" and don't use the "ext_" prefix.

@Alistair Francis might have better suggestions on this ?

Regards,
Anup

>
> Regards,
> Jim Shu
>
> On Mon, Jul 18, 2022 at 12:02 PM Anup Patel  wrote:
>>
>> +Atish
>>
>> On Mon, Jul 18, 2022 at 9:23 AM Jim Shu  wrote:
>> >
>> > RISC-V priv spec v1.12 permits 2 PTE-update schemes of A/D-bit
>> > (Access/Dirty bit): HW update or SW update. RISC-V profile defines the
>> > extension name 'Ssptwad' for HW update to PTE A/D bits.
>> > https://github.com/riscv/riscv-profiles/blob/main/profiles.adoc
>>
>> The Ssptwad (even though used by profiles) is not a well defined RISC-V
>> ISA extension. Rather, Ssptwad is just a name used in profiles to represent
>> an optional feature.
>>
>> In fact, since it is not a well-defined ISA extension, QEMU cannot include
>> Ssptwad in the ISA string as well.
>>
>> I think for such optionalities which are not well-defined ISA extensions,
>> QEMU should treat it differently.
>>
>> Regards,
>> Anup
>>
>> >
>> > Current QEMU RISC-V implements HW update scheme, so this commit
>> > introduces SW update scheme to QEMU and uses the 'Ssptwad' extension
>> > as the CPU option to select 2 PTE-update schemes. QEMU RISC-V CPU still
>> > uses HW update scheme (ext_ssptwad=true) by default to keep the backward
>> > compatibility.
>> >
>> > SW update scheme implemention is based on priv spec v1.12:
>> > "When a virtual page is accessed and the A bit is clear, or is written
>> > and the D bit is clear, a page-fault exception (corresponding to the
>> > original access type) is raised."
>> >
>> > Signed-off-by: Jim Shu 
>> > Reviewed-by: Frank Chang 
>> > ---
>> >  target/riscv/cpu.c| 2 ++
>> >  target/riscv/cpu.h| 1 +
>> >  target/riscv/cpu_helper.c | 9 +
>> >  3 files changed, 12 insertions(+)
>> >
>> > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
>> > index 1bb3973806..1d38c1c1d2 100644
>> > --- a/target/riscv/cpu.c
>> > +++ b/target/riscv/cpu.c
>> > @@ -857,6 +857,7 @@ static void riscv_cpu_init(Object *obj)
>> >
>> >  cpu->cfg.ext_ifencei = true;
>> >  cpu->cfg.ext_icsr = true;
>> > +cpu->cfg.ext_ssptwad = true;
>> >  cpu->cfg.mmu = true;
>> >  cpu->cfg.pmp = true;
>> >
>> > @@ -900,6 +901,7 @@ static Property riscv_cpu_extensions[] = {
>> >  DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false),
>> >  DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false),
>> >  DEFINE_PROP_BOOL("svpbmt", RISCVCPU, cfg.ext_svpbmt, false),
>> > +DEFINE_PROP_BOOL("ssptwad", RISCVCPU, cfg.ext_ssptwad, true),
>> >
>> >  DEFINE_PROP_BOOL("zba", RISCVCPU, cfg.ext_zba, true),
>> >  DEFINE_PROP_BOOL("zbb", RISCVCPU, cfg.ext_zbb, true),
>> > diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
>> > index 5c7acc055a..2eee59af98 100644
>> > --- a/target/riscv/cpu.h
>> > +++ b/target/riscv/cpu.h
>> > @@ -433,6 +433,7 @@ struct RISCVCPUConfig {
>> >  bool ext_zve32f;
>> >  bool ext_zve64f;
>> >  bool ext_zmmul;
>> > +bool ext_ssptwad;
>> >  bool rvv_ta_all_1s;
>> >
>> >  uint32_t mvendorid;
>> > diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
>> > index 59b3680b1b..a8607c0d7b 100644
>> > --- a/target/riscv/cpu_helper.c
>> > +++ b/target/riscv/cpu_helper.c
>> > @@ -981,6 +981,15 @@ restart:
>> >
>> >  /* Page table updates need to be atomic with MTTCG enabled */
>> >  if (updated_pte != pte) {
>> > +if (!cpu->cfg.ext_ssptwad) {
>> > +/*
>> > + * If A/D bits are managed by SW, HW just raises the
>> > + * page fault exception corresponding to the original
>> > + * access type when A/D bits need to be updated.
>> > + */
>> > +return TRANSLATE_FAIL;
>> > +}
>> > +
>> >  /*
>> >   * - if accessed or dirty bits need updating, and the PTE 
>> > is
>> >   *   in RAM, then we do so atomically with a compare and 
>> > swap.
>> > --
>> > 2.17.1
>> >
>> >



Re: [PATCH] target/riscv: Support SW update of PTE A/D bits and Ssptwad extension

2022-07-17 Thread Anup Patel
+Atish

On Mon, Jul 18, 2022 at 9:23 AM Jim Shu  wrote:
>
> RISC-V priv spec v1.12 permits 2 PTE-update schemes of A/D-bit
> (Access/Dirty bit): HW update or SW update. RISC-V profile defines the
> extension name 'Ssptwad' for HW update to PTE A/D bits.
> https://github.com/riscv/riscv-profiles/blob/main/profiles.adoc

The Ssptwad (even though used by profiles) is not a well defined RISC-V
ISA extension. Rather, Ssptwad is just a name used in profiles to represent
an optional feature.

In fact, since it is not a well-defined ISA extension, QEMU cannot include
Ssptwad in the ISA string as well.

I think for such optionalities which are not well-defined ISA extensions,
QEMU should treat it differently.

Regards,
Anup

>
> Current QEMU RISC-V implements HW update scheme, so this commit
> introduces SW update scheme to QEMU and uses the 'Ssptwad' extension
> as the CPU option to select 2 PTE-update schemes. QEMU RISC-V CPU still
> uses HW update scheme (ext_ssptwad=true) by default to keep the backward
> compatibility.
>
> SW update scheme implemention is based on priv spec v1.12:
> "When a virtual page is accessed and the A bit is clear, or is written
> and the D bit is clear, a page-fault exception (corresponding to the
> original access type) is raised."
>
> Signed-off-by: Jim Shu 
> Reviewed-by: Frank Chang 
> ---
>  target/riscv/cpu.c| 2 ++
>  target/riscv/cpu.h| 1 +
>  target/riscv/cpu_helper.c | 9 +
>  3 files changed, 12 insertions(+)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 1bb3973806..1d38c1c1d2 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -857,6 +857,7 @@ static void riscv_cpu_init(Object *obj)
>
>  cpu->cfg.ext_ifencei = true;
>  cpu->cfg.ext_icsr = true;
> +cpu->cfg.ext_ssptwad = true;
>  cpu->cfg.mmu = true;
>  cpu->cfg.pmp = true;
>
> @@ -900,6 +901,7 @@ static Property riscv_cpu_extensions[] = {
>  DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false),
>  DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false),
>  DEFINE_PROP_BOOL("svpbmt", RISCVCPU, cfg.ext_svpbmt, false),
> +DEFINE_PROP_BOOL("ssptwad", RISCVCPU, cfg.ext_ssptwad, true),
>
>  DEFINE_PROP_BOOL("zba", RISCVCPU, cfg.ext_zba, true),
>  DEFINE_PROP_BOOL("zbb", RISCVCPU, cfg.ext_zbb, true),
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 5c7acc055a..2eee59af98 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -433,6 +433,7 @@ struct RISCVCPUConfig {
>  bool ext_zve32f;
>  bool ext_zve64f;
>  bool ext_zmmul;
> +bool ext_ssptwad;
>  bool rvv_ta_all_1s;
>
>  uint32_t mvendorid;
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 59b3680b1b..a8607c0d7b 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -981,6 +981,15 @@ restart:
>
>  /* Page table updates need to be atomic with MTTCG enabled */
>  if (updated_pte != pte) {
> +if (!cpu->cfg.ext_ssptwad) {
> +/*
> + * If A/D bits are managed by SW, HW just raises the
> + * page fault exception corresponding to the original
> + * access type when A/D bits need to be updated.
> + */
> +return TRANSLATE_FAIL;
> +}
> +
>  /*
>   * - if accessed or dirty bits need updating, and the PTE is
>   *   in RAM, then we do so atomically with a compare and 
> swap.
> --
> 2.17.1
>
>



Re: [PATCH v2 03/11] goldfish_rtc: Add endianness property

2022-07-03 Thread Anup Patel
On Mon, Jul 4, 2022 at 2:59 AM Stafford Horne  wrote:
>
> Add an endianness property to allow configuring the RTC as either
> native, little or big endian.
>
> Cc: Laurent Vivier 
> Signed-off-by: Stafford Horne 

Looks good to me.

Reviewed-by: Anup Patel 

Regards,
Anup

> ---
>  hw/rtc/goldfish_rtc.c | 46 ---
>  include/hw/rtc/goldfish_rtc.h |  2 ++
>  2 files changed, 39 insertions(+), 9 deletions(-)
>
> diff --git a/hw/rtc/goldfish_rtc.c b/hw/rtc/goldfish_rtc.c
> index 35e493be31..24f6587086 100644
> --- a/hw/rtc/goldfish_rtc.c
> +++ b/hw/rtc/goldfish_rtc.c
> @@ -216,14 +216,34 @@ static int goldfish_rtc_post_load(void *opaque, int 
> version_id)
>  return 0;
>  }
>
> -static const MemoryRegionOps goldfish_rtc_ops = {
> -.read = goldfish_rtc_read,
> -.write = goldfish_rtc_write,
> -.endianness = DEVICE_NATIVE_ENDIAN,
> -.valid = {
> -.min_access_size = 4,
> -.max_access_size = 4
> -}
> +static const MemoryRegionOps goldfish_rtc_ops[3] = {
> +[DEVICE_NATIVE_ENDIAN] = {
> +.read = goldfish_rtc_read,
> +.write = goldfish_rtc_write,
> +.endianness = DEVICE_NATIVE_ENDIAN,
> +.valid = {
> +.min_access_size = 4,
> +.max_access_size = 4
> +}
> +},
> +[DEVICE_LITTLE_ENDIAN] = {
> +.read = goldfish_rtc_read,
> +.write = goldfish_rtc_write,
> +.endianness = DEVICE_LITTLE_ENDIAN,
> +.valid = {
> +.min_access_size = 4,
> +.max_access_size = 4
> +}
> +},
> +[DEVICE_BIG_ENDIAN] = {
> +.read = goldfish_rtc_read,
> +.write = goldfish_rtc_write,
> +.endianness = DEVICE_BIG_ENDIAN,
> +.valid = {
> +.min_access_size = 4,
> +.max_access_size = 4
> +}
> +},
>  };
>
>  static const VMStateDescription goldfish_rtc_vmstate = {
> @@ -265,7 +285,8 @@ static void goldfish_rtc_realize(DeviceState *d, Error 
> **errp)
>  SysBusDevice *dev = SYS_BUS_DEVICE(d);
>  GoldfishRTCState *s = GOLDFISH_RTC(d);
>
> -memory_region_init_io(>iomem, OBJECT(s), _rtc_ops, s,
> +memory_region_init_io(>iomem, OBJECT(s),
> +  _rtc_ops[s->endianness], s,
>"goldfish_rtc", 0x24);
>  sysbus_init_mmio(dev, >iomem);
>
> @@ -274,10 +295,17 @@ static void goldfish_rtc_realize(DeviceState *d, Error 
> **errp)
>  s->timer = timer_new_ns(rtc_clock, goldfish_rtc_interrupt, s);
>  }
>
> +static Property goldfish_rtc_properties[] = {
> +DEFINE_PROP_UINT8("endianness", GoldfishRTCState, endianness,
> +  DEVICE_NATIVE_ENDIAN),
> +DEFINE_PROP_END_OF_LIST(),
> +};
> +
>  static void goldfish_rtc_class_init(ObjectClass *klass, void *data)
>  {
>  DeviceClass *dc = DEVICE_CLASS(klass);
>
> +device_class_set_props(dc, goldfish_rtc_properties);
>  dc->realize = goldfish_rtc_realize;
>  dc->reset = goldfish_rtc_reset;
>  dc->vmsd = _rtc_vmstate;
> diff --git a/include/hw/rtc/goldfish_rtc.h b/include/hw/rtc/goldfish_rtc.h
> index 79ca7daf5d..8e1aeb85e3 100644
> --- a/include/hw/rtc/goldfish_rtc.h
> +++ b/include/hw/rtc/goldfish_rtc.h
> @@ -42,6 +42,8 @@ struct GoldfishRTCState {
>  uint32_t irq_pending;
>  uint32_t irq_enabled;
>  uint32_t time_high;
> +
> +uint8_t endianness;
>  };
>
>  #endif
> --
> 2.36.1
>
>



Re: [PATCH v9 0/2] QEMU RISC-V nested virtualization fixes

2022-06-30 Thread Anup Patel
On Thu, Jun 30, 2022 at 11:42 AM Anup Patel  wrote:
>
> This series does fixes and improvements to have nested virtualization
> on QEMU RISC-V.
>
> These patches can also be found in riscv_nested_fixes_v9 branch at:
> https://github.com/avpatel/qemu.git
>
> The RISC-V nested virtualization was tested on QEMU RISC-V using
> Xvisor RISC-V which has required hypervisor support to run another
> hypervisor as Guest/VM.

Changes since v8:
 - Drop first two patches because Alistair has already taken care of it.
 - Include instruction immediate offset in "Addr. Offset" for PATCH1

Regards,
Anup

>
> Changes since v7:
>  - Improve tinst "Addr. Offset" in PATCH3
>
> Changes since v6:
>  - Droppred original PATCH1 and PATCH2 since these are already merged
>  - Added PATCH1 to revert dummy mcountinhibit CSR
>  - Added PATCH2 to fix minimum priv spec version for mcountinhibit CSR
>  - Fixed checkpatch error in PATCH3
>  - Fixed compile error in PATCH4
>
> Changes since v5:
>  - Correctly set "Addr. Offset" for misaligned load/store traps in PATCH3
>  - Use offsetof() instead of pointer in PATCH4
>
> Changes since v4:
>  - Updated commit description in PATCH1, PATCH2, and PATCH4
>  - Use "const" for local array in PATCH5
>
> Changes since v3:
>  - Updated PATCH3 to set special pseudoinstructions in htinst for
>guest page faults which result due to VS-stage page table walks
>  - Updated warning message in PATCH4
>
> Changes since v2:
>  - Dropped the patch which are already in Alistair's next branch
>  - Set "Addr. Offset" in the transformed instruction for PATCH3
>  - Print warning in riscv_cpu_realize() if we are disabling an
>extension due to privilege spec verions mismatch for PATCH4
>
> Changes since v1:
>  - Set write_gva to env->two_stage_lookup which ensures that for
>HS-mode to HS-mode trap write_gva is true only for HLV/HSV
>instructions
>  - Included "[PATCH 0/3] QEMU RISC-V priv spec version fixes"
>patches in this series for easy review
>  - Re-worked PATCH7 to force disable extensions if required
>priv spec version is not staisfied
>  - Added new PATCH8 to fix "aia=aplic-imsic" mode of virt machine
>
> Anup Patel (2):
>   target/riscv: Update [m|h]tinst CSR in riscv_cpu_do_interrupt()
>   target/riscv: Force disable extensions if priv spec version does not
> match
>
>  target/riscv/cpu.c| 150 ++-
>  target/riscv/cpu.h|   5 +
>  target/riscv/cpu_helper.c | 252 +-
>  target/riscv/instmap.h|  45 +++
>  4 files changed, 390 insertions(+), 62 deletions(-)
>
> --
> 2.34.1
>



[PATCH v9 0/2] QEMU RISC-V nested virtualization fixes

2022-06-30 Thread Anup Patel
This series does fixes and improvements to have nested virtualization
on QEMU RISC-V.

These patches can also be found in riscv_nested_fixes_v9 branch at:
https://github.com/avpatel/qemu.git

The RISC-V nested virtualization was tested on QEMU RISC-V using
Xvisor RISC-V which has required hypervisor support to run another
hypervisor as Guest/VM.

Changes since v7:
 - Improve tinst "Addr. Offset" in PATCH3

Changes since v6:
 - Droppred original PATCH1 and PATCH2 since these are already merged
 - Added PATCH1 to revert dummy mcountinhibit CSR
 - Added PATCH2 to fix minimum priv spec version for mcountinhibit CSR
 - Fixed checkpatch error in PATCH3
 - Fixed compile error in PATCH4

Changes since v5:
 - Correctly set "Addr. Offset" for misaligned load/store traps in PATCH3
 - Use offsetof() instead of pointer in PATCH4

Changes since v4:
 - Updated commit description in PATCH1, PATCH2, and PATCH4
 - Use "const" for local array in PATCH5

Changes since v3:
 - Updated PATCH3 to set special pseudoinstructions in htinst for
   guest page faults which result due to VS-stage page table walks
 - Updated warning message in PATCH4

Changes since v2:
 - Dropped the patch which are already in Alistair's next branch
 - Set "Addr. Offset" in the transformed instruction for PATCH3
 - Print warning in riscv_cpu_realize() if we are disabling an
   extension due to privilege spec verions mismatch for PATCH4

Changes since v1:
 - Set write_gva to env->two_stage_lookup which ensures that for
   HS-mode to HS-mode trap write_gva is true only for HLV/HSV
   instructions
 - Included "[PATCH 0/3] QEMU RISC-V priv spec version fixes"
   patches in this series for easy review
 - Re-worked PATCH7 to force disable extensions if required
   priv spec version is not staisfied
 - Added new PATCH8 to fix "aia=aplic-imsic" mode of virt machine

Anup Patel (2):
  target/riscv: Update [m|h]tinst CSR in riscv_cpu_do_interrupt()
  target/riscv: Force disable extensions if priv spec version does not
match

 target/riscv/cpu.c| 150 ++-
 target/riscv/cpu.h|   5 +
 target/riscv/cpu_helper.c | 252 +-
 target/riscv/instmap.h|  45 +++
 4 files changed, 390 insertions(+), 62 deletions(-)

-- 
2.34.1




[PATCH v9 2/2] target/riscv: Force disable extensions if priv spec version does not match

2022-06-30 Thread Anup Patel
We should disable extensions in riscv_cpu_realize() if minimum required
priv spec version is not satisfied. This also ensures that machines with
priv spec v1.11 (or lower) cannot enable H, V, and various multi-letter
extensions.

Fixes: a775398be2e9 ("target/riscv: Add isa extenstion strings to the device 
tree")
Reviewed-by: Alistair Francis 
Signed-off-by: Anup Patel 
Signed-off-by: Rahul Pathak 
---
 target/riscv/cpu.c | 150 -
 1 file changed, 94 insertions(+), 56 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 4e7ca6cd4a..9bc4ef0685 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -43,9 +43,82 @@ static const char riscv_single_letter_exts[] = "IEMAFDQCPVH";
 
 struct isa_ext_data {
 const char *name;
-bool enabled;
+bool multi_letter;
+int min_version;
+int ext_enable_offset;
 };
 
+#define ISA_EXT_DATA_ENTRY(_name, _m_letter, _min_ver, _prop) \
+{#_name, _m_letter, _min_ver, offsetof(struct RISCVCPUConfig, _prop)}
+
+/**
+ * Here are the ordering rules of extension naming defined by RISC-V
+ * specification :
+ * 1. All extensions should be separated from other multi-letter extensions
+ *by an underscore.
+ * 2. The first letter following the 'Z' conventionally indicates the most
+ *closely related alphabetical extension category, IMAFDQLCBKJTPVH.
+ *If multiple 'Z' extensions are named, they should be ordered first
+ *by category, then alphabetically within a category.
+ * 3. Standard supervisor-level extensions (starts with 'S') should be
+ *listed after standard unprivileged extensions.  If multiple
+ *supervisor-level extensions are listed, they should be ordered
+ *alphabetically.
+ * 4. Non-standard extensions (starts with 'X') must be listed after all
+ *standard extensions. They must be separated from other multi-letter
+ *extensions by an underscore.
+ */
+static const struct isa_ext_data isa_edata_arr[] = {
+ISA_EXT_DATA_ENTRY(h, false, PRIV_VERSION_1_12_0, ext_h),
+ISA_EXT_DATA_ENTRY(v, false, PRIV_VERSION_1_12_0, ext_v),
+ISA_EXT_DATA_ENTRY(zicsr, true, PRIV_VERSION_1_10_0, ext_icsr),
+ISA_EXT_DATA_ENTRY(zifencei, true, PRIV_VERSION_1_10_0, ext_ifencei),
+ISA_EXT_DATA_ENTRY(zfh, true, PRIV_VERSION_1_12_0, ext_zfh),
+ISA_EXT_DATA_ENTRY(zfhmin, true, PRIV_VERSION_1_12_0, ext_zfhmin),
+ISA_EXT_DATA_ENTRY(zfinx, true, PRIV_VERSION_1_12_0, ext_zfinx),
+ISA_EXT_DATA_ENTRY(zdinx, true, PRIV_VERSION_1_12_0, ext_zdinx),
+ISA_EXT_DATA_ENTRY(zba, true, PRIV_VERSION_1_12_0, ext_zba),
+ISA_EXT_DATA_ENTRY(zbb, true, PRIV_VERSION_1_12_0, ext_zbb),
+ISA_EXT_DATA_ENTRY(zbc, true, PRIV_VERSION_1_12_0, ext_zbc),
+ISA_EXT_DATA_ENTRY(zbkb, true, PRIV_VERSION_1_12_0, ext_zbkb),
+ISA_EXT_DATA_ENTRY(zbkc, true, PRIV_VERSION_1_12_0, ext_zbkc),
+ISA_EXT_DATA_ENTRY(zbkx, true, PRIV_VERSION_1_12_0, ext_zbkx),
+ISA_EXT_DATA_ENTRY(zbs, true, PRIV_VERSION_1_12_0, ext_zbs),
+ISA_EXT_DATA_ENTRY(zk, true, PRIV_VERSION_1_12_0, ext_zk),
+ISA_EXT_DATA_ENTRY(zkn, true, PRIV_VERSION_1_12_0, ext_zkn),
+ISA_EXT_DATA_ENTRY(zknd, true, PRIV_VERSION_1_12_0, ext_zknd),
+ISA_EXT_DATA_ENTRY(zkne, true, PRIV_VERSION_1_12_0, ext_zkne),
+ISA_EXT_DATA_ENTRY(zknh, true, PRIV_VERSION_1_12_0, ext_zknh),
+ISA_EXT_DATA_ENTRY(zkr, true, PRIV_VERSION_1_12_0, ext_zkr),
+ISA_EXT_DATA_ENTRY(zks, true, PRIV_VERSION_1_12_0, ext_zks),
+ISA_EXT_DATA_ENTRY(zksed, true, PRIV_VERSION_1_12_0, ext_zksed),
+ISA_EXT_DATA_ENTRY(zksh, true, PRIV_VERSION_1_12_0, ext_zksh),
+ISA_EXT_DATA_ENTRY(zkt, true, PRIV_VERSION_1_12_0, ext_zkt),
+ISA_EXT_DATA_ENTRY(zve32f, true, PRIV_VERSION_1_12_0, ext_zve32f),
+ISA_EXT_DATA_ENTRY(zve64f, true, PRIV_VERSION_1_12_0, ext_zve64f),
+ISA_EXT_DATA_ENTRY(zhinx, true, PRIV_VERSION_1_12_0, ext_zhinx),
+ISA_EXT_DATA_ENTRY(zhinxmin, true, PRIV_VERSION_1_12_0, ext_zhinxmin),
+ISA_EXT_DATA_ENTRY(svinval, true, PRIV_VERSION_1_12_0, ext_svinval),
+ISA_EXT_DATA_ENTRY(svnapot, true, PRIV_VERSION_1_12_0, ext_svnapot),
+ISA_EXT_DATA_ENTRY(svpbmt, true, PRIV_VERSION_1_12_0, ext_svpbmt),
+};
+
+static bool isa_ext_is_enabled(RISCVCPU *cpu,
+   const struct isa_ext_data *edata)
+{
+bool *ext_enabled = (void *)>cfg + edata->ext_enable_offset;
+
+return *ext_enabled;
+}
+
+static void isa_ext_update_enabled(RISCVCPU *cpu,
+   const struct isa_ext_data *edata, bool en)
+{
+bool *ext_enabled = (void *)>cfg + edata->ext_enable_offset;
+
+*ext_enabled = en;
+}
+
 const char * const riscv_int_regnames[] = {
   "x0/zero", "x1/ra",  "x2/sp",  "x3/gp",  "x4/tp",  "x5/t0",   "x6/t1",
   "x7/t2",   "x8/s0",  "x9/s1",  "x10/a0", "x11/a1", "x12/a2",  "x13/a3

[PATCH v9 1/2] target/riscv: Update [m|h]tinst CSR in riscv_cpu_do_interrupt()

2022-06-30 Thread Anup Patel
We should write transformed instruction encoding of the trapped
instruction in [m|h]tinst CSR at time of taking trap as defined
by the RISC-V privileged specification v1.12.

Reviewed-by: Alistair Francis 
Signed-off-by: Anup Patel 
---
 target/riscv/cpu.h|   5 +
 target/riscv/cpu_helper.c | 252 +-
 target/riscv/instmap.h|  45 +++
 3 files changed, 296 insertions(+), 6 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 5c7acc055a..ffb1a18873 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -285,6 +285,11 @@ struct CPUArchState {
 /* Signals whether the current exception occurred with two-stage address
translation active. */
 bool two_stage_lookup;
+/*
+ * Signals whether the current exception occurred while doing two-stage
+ * address translation for the VS-stage page table walk.
+ */
+bool two_stage_indirect_lookup;
 
 target_ulong scounteren;
 target_ulong mcounteren;
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index be28615e23..c59cfddac2 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -22,6 +22,7 @@
 #include "qemu/main-loop.h"
 #include "cpu.h"
 #include "exec/exec-all.h"
+#include "instmap.h"
 #include "tcg/tcg-op.h"
 #include "trace.h"
 #include "semihosting/common-semi.h"
@@ -1057,7 +1058,8 @@ restart:
 
 static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
 MMUAccessType access_type, bool pmp_violation,
-bool first_stage, bool two_stage)
+bool first_stage, bool two_stage,
+bool two_stage_indirect)
 {
 CPUState *cs = env_cpu(env);
 int page_fault_exceptions, vm;
@@ -1107,6 +1109,7 @@ static void raise_mmu_exception(CPURISCVState *env, 
target_ulong address,
 }
 env->badaddr = address;
 env->two_stage_lookup = two_stage;
+env->two_stage_indirect_lookup = two_stage_indirect;
 }
 
 hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
@@ -1152,6 +1155,7 @@ void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr 
physaddr,
 env->badaddr = addr;
 env->two_stage_lookup = riscv_cpu_virt_enabled(env) ||
 riscv_cpu_two_stage_lookup(mmu_idx);
+env->two_stage_indirect_lookup = false;
 cpu_loop_exit_restore(cs, retaddr);
 }
 
@@ -1177,6 +1181,7 @@ void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr 
addr,
 env->badaddr = addr;
 env->two_stage_lookup = riscv_cpu_virt_enabled(env) ||
 riscv_cpu_two_stage_lookup(mmu_idx);
+env->two_stage_indirect_lookup = false;
 cpu_loop_exit_restore(cs, retaddr);
 }
 
@@ -1192,6 +1197,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int 
size,
 bool pmp_violation = false;
 bool first_stage_error = true;
 bool two_stage_lookup = false;
+bool two_stage_indirect_error = false;
 int ret = TRANSLATE_FAIL;
 int mode = mmu_idx;
 /* default TLB page size */
@@ -1229,6 +1235,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int 
size,
  */
 if (ret == TRANSLATE_G_STAGE_FAIL) {
 first_stage_error = false;
+two_stage_indirect_error = true;
 access_type = MMU_DATA_LOAD;
 }
 
@@ -1312,12 +1319,218 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, 
int size,
 raise_mmu_exception(env, address, access_type, pmp_violation,
 first_stage_error,
 riscv_cpu_virt_enabled(env) ||
-riscv_cpu_two_stage_lookup(mmu_idx));
+riscv_cpu_two_stage_lookup(mmu_idx),
+two_stage_indirect_error);
 cpu_loop_exit_restore(cs, retaddr);
 }
 
 return true;
 }
+
+static target_ulong riscv_transformed_insn(CPURISCVState *env,
+   target_ulong insn,
+   target_ulong taddr)
+{
+target_ulong xinsn = 0;
+target_ulong access_rs1 = 0, access_imm = 0, access_size = 0;
+
+/*
+ * Only Quadrant 0 and Quadrant 2 of RVC instruction space need to
+ * be uncompressed. The Quadrant 1 of RVC instruction space need
+ * not be transformed because these instructions won't generate
+ * any load/store trap.
+ */
+
+if ((insn & 0x3) != 0x3) {
+/* Transform 16bit instruction into 32bit instruction */
+switch (GET_C_OP(insn)) {
+case OPC_RISC_C_OP_QUAD0: /* Quadrant 0 */
+switch (GET_C_FUNC(insn)) {
+case OPC_RISC_C_FUNC_FLD_LQ:
+if (riscv_cpu_xlen(env) != 128) { /* C.FLD (RV32/64) */
+xinsn = OPC_RISC_FLD;
+ 

Re: [PATCH v2] target/riscv: fix user-mode build issue because mhartid

2022-06-28 Thread Anup Patel
On Wed, Jun 29, 2022 at 9:27 AM Bin Meng  wrote:
>
> Hi Rahul,
>
> On Wed, Jun 29, 2022 at 10:07 AM Rahul Pathak  
> wrote:
> >
> > Hi Alistair
> >
> > My fix patch needs to be dropped since Anup took care of this issue
> > in his yesterdays series update in this patch -
> > [PATCH v8 4/4] target/riscv: Force disable extensions if priv spec
> > version does not match
>
> I don't understand. Each patch should keep bisectability.

The patches are already bisectable. There was a compile error until
v6 which was fixed in v7 by squashing this patch into PATCH4.

>
> This sounds like to me, that
> [PATCH v8 4/4] target/riscv: Force disable extensions if priv spec
> version does not match
>
> has an issue that it does 2 things: one is to fix this bug, and the
> other one is to force disable extensions.
>
> Which is not right.

The bug is fixed as a result of force disabling extensions which
don't match the priv spec version.

Regards,
Anup



[PATCH v8 2/4] target/riscv: Set minumum priv spec version for mcountinhibit

2022-06-28 Thread Anup Patel
The minimum priv spec versino for mcountinhibit to v1.11 so that it
is not available for v1.10 (or lower).

Fixes: eab4776b2bad ("target/riscv: Add support for hpmcounters/hpmevents")
Signed-off-by: Anup Patel 
---
 target/riscv/csr.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index d65318dcc6..f7bfd2eab5 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -3944,7 +3944,7 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
write_mhpmcounter },
 
 [CSR_MCOUNTINHIBIT]  = { "mcountinhibit",  any, read_mcountinhibit,
-write_mcountinhibit },
+   write_mcountinhibit, .min_priv_ver = PRIV_VERSION_1_11_0  },
 
 [CSR_MHPMEVENT3] = { "mhpmevent3", any,read_mhpmevent,
write_mhpmevent },
-- 
2.34.1




[PATCH v8 3/4] target/riscv: Update [m|h]tinst CSR in riscv_cpu_do_interrupt()

2022-06-28 Thread Anup Patel
We should write transformed instruction encoding of the trapped
instruction in [m|h]tinst CSR at time of taking trap as defined
by the RISC-V privileged specification v1.12.

Reviewed-by: Alistair Francis 
Signed-off-by: Anup Patel 
---
 target/riscv/cpu.h|   5 +
 target/riscv/cpu_helper.c | 235 +-
 target/riscv/instmap.h|  45 
 3 files changed, 279 insertions(+), 6 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 5c7acc055a..ffb1a18873 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -285,6 +285,11 @@ struct CPUArchState {
 /* Signals whether the current exception occurred with two-stage address
translation active. */
 bool two_stage_lookup;
+/*
+ * Signals whether the current exception occurred while doing two-stage
+ * address translation for the VS-stage page table walk.
+ */
+bool two_stage_indirect_lookup;
 
 target_ulong scounteren;
 target_ulong mcounteren;
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 4a6700c890..d11198f4f9 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -22,6 +22,7 @@
 #include "qemu/main-loop.h"
 #include "cpu.h"
 #include "exec/exec-all.h"
+#include "instmap.h"
 #include "tcg/tcg-op.h"
 #include "trace.h"
 #include "semihosting/common-semi.h"
@@ -1057,7 +1058,8 @@ restart:
 
 static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
 MMUAccessType access_type, bool pmp_violation,
-bool first_stage, bool two_stage)
+bool first_stage, bool two_stage,
+bool two_stage_indirect)
 {
 CPUState *cs = env_cpu(env);
 int page_fault_exceptions, vm;
@@ -1107,6 +1109,7 @@ static void raise_mmu_exception(CPURISCVState *env, 
target_ulong address,
 }
 env->badaddr = address;
 env->two_stage_lookup = two_stage;
+env->two_stage_indirect_lookup = two_stage_indirect;
 }
 
 hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
@@ -1152,6 +1155,7 @@ void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr 
physaddr,
 env->badaddr = addr;
 env->two_stage_lookup = riscv_cpu_virt_enabled(env) ||
 riscv_cpu_two_stage_lookup(mmu_idx);
+env->two_stage_indirect_lookup = false;
 cpu_loop_exit_restore(cs, retaddr);
 }
 
@@ -1177,6 +1181,7 @@ void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr 
addr,
 env->badaddr = addr;
 env->two_stage_lookup = riscv_cpu_virt_enabled(env) ||
 riscv_cpu_two_stage_lookup(mmu_idx);
+env->two_stage_indirect_lookup = false;
 cpu_loop_exit_restore(cs, retaddr);
 }
 
@@ -1192,6 +1197,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int 
size,
 bool pmp_violation = false;
 bool first_stage_error = true;
 bool two_stage_lookup = false;
+bool two_stage_indirect_error = false;
 int ret = TRANSLATE_FAIL;
 int mode = mmu_idx;
 /* default TLB page size */
@@ -1229,6 +1235,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int 
size,
  */
 if (ret == TRANSLATE_G_STAGE_FAIL) {
 first_stage_error = false;
+two_stage_indirect_error = true;
 access_type = MMU_DATA_LOAD;
 }
 
@@ -1312,12 +1319,201 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, 
int size,
 raise_mmu_exception(env, address, access_type, pmp_violation,
 first_stage_error,
 riscv_cpu_virt_enabled(env) ||
-riscv_cpu_two_stage_lookup(mmu_idx));
+riscv_cpu_two_stage_lookup(mmu_idx),
+two_stage_indirect_error);
 cpu_loop_exit_restore(cs, retaddr);
 }
 
 return true;
 }
+
+static target_ulong riscv_transformed_insn(CPURISCVState *env,
+   target_ulong insn,
+   target_ulong taddr)
+{
+target_ulong xinsn = 0, xinsn_access_rs1 = 0, xinsn_access_size = 0;
+
+/*
+ * Only Quadrant 0 and Quadrant 2 of RVC instruction space need to
+ * be uncompressed. The Quadrant 1 of RVC instruction space need
+ * not be transformed because these instructions won't generate
+ * any load/store trap.
+ */
+
+if ((insn & 0x3) != 0x3) {
+/* Transform 16bit instruction into 32bit instruction */
+switch (GET_C_OP(insn)) {
+case OPC_RISC_C_OP_QUAD0: /* Quadrant 0 */
+switch (GET_C_FUNC(insn)) {
+case OPC_RISC_C_FUNC_FLD_LQ:
+if (riscv_cpu_xlen(env) != 128) { /* C.FLD (RV32/64) */
+xinsn = OPC_RISC_FLD;
+   

[PATCH v8 0/4] QEMU RISC-V nested virtualization fixes

2022-06-28 Thread Anup Patel
This series does fixes and improvements to have nested virtualization
on QEMU RISC-V.

These patches can also be found in riscv_nested_fixes_v8 branch at:
https://github.com/avpatel/qemu.git

The RISC-V nested virtualization was tested on QEMU RISC-V using
Xvisor RISC-V which has required hypervisor support to run another
hypervisor as Guest/VM.

Changes since 7:
 - Improve tinst "Addr. Offset" in PATCH3

Changes since v6:
 - Droppred original PATCH1 and PATCH2 since these are already merged
 - Added PATCH1 to revert dummy mcountinhibit CSR
 - Added PATCH2 to fix minimum priv spec version for mcountinhibit CSR
 - Fixed checkpatch error in PATCH3
 - Fixed compile error in PATCH4

Changes since v5:
 - Correctly set "Addr. Offset" for misaligned load/store traps in PATCH3
 - Use offsetof() instead of pointer in PATCH4

Changes since v4:
 - Updated commit description in PATCH1, PATCH2, and PATCH4
 - Use "const" for local array in PATCH5

Changes since v3:
 - Updated PATCH3 to set special pseudoinstructions in htinst for
   guest page faults which result due to VS-stage page table walks
 - Updated warning message in PATCH4

Changes since v2:
 - Dropped the patch which are already in Alistair's next branch
 - Set "Addr. Offset" in the transformed instruction for PATCH3
 - Print warning in riscv_cpu_realize() if we are disabling an
   extension due to privilege spec verions mismatch for PATCH4

Changes since v1:
 - Set write_gva to env->two_stage_lookup which ensures that for
   HS-mode to HS-mode trap write_gva is true only for HLV/HSV
   instructions
 - Included "[PATCH 0/3] QEMU RISC-V priv spec version fixes"
   patches in this series for easy review
 - Re-worked PATCH7 to force disable extensions if required
   priv spec version is not staisfied
 - Added new PATCH8 to fix "aia=aplic-imsic" mode of virt machine

Anup Patel (4):
  Revert "target/riscv: Add dummy mcountinhibit CSR for priv spec v1.11
or higher"
  target/riscv: Set minumum priv spec version for mcountinhibit
  target/riscv: Update [m|h]tinst CSR in riscv_cpu_do_interrupt()
  target/riscv: Force disable extensions if priv spec version does not
match

 target/riscv/cpu.c| 150 +++-
 target/riscv/cpu.h|   5 +
 target/riscv/cpu_bits.h   |   3 -
 target/riscv/cpu_helper.c | 235 +-
 target/riscv/csr.c|   4 +-
 target/riscv/instmap.h|  45 
 6 files changed, 374 insertions(+), 68 deletions(-)

-- 
2.34.1




[PATCH v8 4/4] target/riscv: Force disable extensions if priv spec version does not match

2022-06-28 Thread Anup Patel
We should disable extensions in riscv_cpu_realize() if minimum required
priv spec version is not satisfied. This also ensures that machines with
priv spec v1.11 (or lower) cannot enable H, V, and various multi-letter
extensions.

Fixes: a775398be2e9 ("target/riscv: Add isa extenstion strings to the device 
tree")
Reviewed-by: Alistair Francis 
Signed-off-by: Anup Patel 
Signed-off-by: Rahul Pathak 
---
 target/riscv/cpu.c | 150 -
 1 file changed, 94 insertions(+), 56 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 4e7ca6cd4a..9bc4ef0685 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -43,9 +43,82 @@ static const char riscv_single_letter_exts[] = "IEMAFDQCPVH";
 
 struct isa_ext_data {
 const char *name;
-bool enabled;
+bool multi_letter;
+int min_version;
+int ext_enable_offset;
 };
 
+#define ISA_EXT_DATA_ENTRY(_name, _m_letter, _min_ver, _prop) \
+{#_name, _m_letter, _min_ver, offsetof(struct RISCVCPUConfig, _prop)}
+
+/**
+ * Here are the ordering rules of extension naming defined by RISC-V
+ * specification :
+ * 1. All extensions should be separated from other multi-letter extensions
+ *by an underscore.
+ * 2. The first letter following the 'Z' conventionally indicates the most
+ *closely related alphabetical extension category, IMAFDQLCBKJTPVH.
+ *If multiple 'Z' extensions are named, they should be ordered first
+ *by category, then alphabetically within a category.
+ * 3. Standard supervisor-level extensions (starts with 'S') should be
+ *listed after standard unprivileged extensions.  If multiple
+ *supervisor-level extensions are listed, they should be ordered
+ *alphabetically.
+ * 4. Non-standard extensions (starts with 'X') must be listed after all
+ *standard extensions. They must be separated from other multi-letter
+ *extensions by an underscore.
+ */
+static const struct isa_ext_data isa_edata_arr[] = {
+ISA_EXT_DATA_ENTRY(h, false, PRIV_VERSION_1_12_0, ext_h),
+ISA_EXT_DATA_ENTRY(v, false, PRIV_VERSION_1_12_0, ext_v),
+ISA_EXT_DATA_ENTRY(zicsr, true, PRIV_VERSION_1_10_0, ext_icsr),
+ISA_EXT_DATA_ENTRY(zifencei, true, PRIV_VERSION_1_10_0, ext_ifencei),
+ISA_EXT_DATA_ENTRY(zfh, true, PRIV_VERSION_1_12_0, ext_zfh),
+ISA_EXT_DATA_ENTRY(zfhmin, true, PRIV_VERSION_1_12_0, ext_zfhmin),
+ISA_EXT_DATA_ENTRY(zfinx, true, PRIV_VERSION_1_12_0, ext_zfinx),
+ISA_EXT_DATA_ENTRY(zdinx, true, PRIV_VERSION_1_12_0, ext_zdinx),
+ISA_EXT_DATA_ENTRY(zba, true, PRIV_VERSION_1_12_0, ext_zba),
+ISA_EXT_DATA_ENTRY(zbb, true, PRIV_VERSION_1_12_0, ext_zbb),
+ISA_EXT_DATA_ENTRY(zbc, true, PRIV_VERSION_1_12_0, ext_zbc),
+ISA_EXT_DATA_ENTRY(zbkb, true, PRIV_VERSION_1_12_0, ext_zbkb),
+ISA_EXT_DATA_ENTRY(zbkc, true, PRIV_VERSION_1_12_0, ext_zbkc),
+ISA_EXT_DATA_ENTRY(zbkx, true, PRIV_VERSION_1_12_0, ext_zbkx),
+ISA_EXT_DATA_ENTRY(zbs, true, PRIV_VERSION_1_12_0, ext_zbs),
+ISA_EXT_DATA_ENTRY(zk, true, PRIV_VERSION_1_12_0, ext_zk),
+ISA_EXT_DATA_ENTRY(zkn, true, PRIV_VERSION_1_12_0, ext_zkn),
+ISA_EXT_DATA_ENTRY(zknd, true, PRIV_VERSION_1_12_0, ext_zknd),
+ISA_EXT_DATA_ENTRY(zkne, true, PRIV_VERSION_1_12_0, ext_zkne),
+ISA_EXT_DATA_ENTRY(zknh, true, PRIV_VERSION_1_12_0, ext_zknh),
+ISA_EXT_DATA_ENTRY(zkr, true, PRIV_VERSION_1_12_0, ext_zkr),
+ISA_EXT_DATA_ENTRY(zks, true, PRIV_VERSION_1_12_0, ext_zks),
+ISA_EXT_DATA_ENTRY(zksed, true, PRIV_VERSION_1_12_0, ext_zksed),
+ISA_EXT_DATA_ENTRY(zksh, true, PRIV_VERSION_1_12_0, ext_zksh),
+ISA_EXT_DATA_ENTRY(zkt, true, PRIV_VERSION_1_12_0, ext_zkt),
+ISA_EXT_DATA_ENTRY(zve32f, true, PRIV_VERSION_1_12_0, ext_zve32f),
+ISA_EXT_DATA_ENTRY(zve64f, true, PRIV_VERSION_1_12_0, ext_zve64f),
+ISA_EXT_DATA_ENTRY(zhinx, true, PRIV_VERSION_1_12_0, ext_zhinx),
+ISA_EXT_DATA_ENTRY(zhinxmin, true, PRIV_VERSION_1_12_0, ext_zhinxmin),
+ISA_EXT_DATA_ENTRY(svinval, true, PRIV_VERSION_1_12_0, ext_svinval),
+ISA_EXT_DATA_ENTRY(svnapot, true, PRIV_VERSION_1_12_0, ext_svnapot),
+ISA_EXT_DATA_ENTRY(svpbmt, true, PRIV_VERSION_1_12_0, ext_svpbmt),
+};
+
+static bool isa_ext_is_enabled(RISCVCPU *cpu,
+   const struct isa_ext_data *edata)
+{
+bool *ext_enabled = (void *)>cfg + edata->ext_enable_offset;
+
+return *ext_enabled;
+}
+
+static void isa_ext_update_enabled(RISCVCPU *cpu,
+   const struct isa_ext_data *edata, bool en)
+{
+bool *ext_enabled = (void *)>cfg + edata->ext_enable_offset;
+
+*ext_enabled = en;
+}
+
 const char * const riscv_int_regnames[] = {
   "x0/zero", "x1/ra",  "x2/sp",  "x3/gp",  "x4/tp",  "x5/t0",   "x6/t1",
   "x7/t2",   "x8/s0",  "x9/s1",  "x10/a0", "x11/a1", "x12/a2",  "x13/a3

[PATCH v8 1/4] Revert "target/riscv: Add dummy mcountinhibit CSR for priv spec v1.11 or higher"

2022-06-28 Thread Anup Patel
This reverts commit 33cc1c0b69e457f5c526f64297353cba6f7bfdb4 because
commit eab4776b2badd4088a4f807c9bb3dc453c53dc23 already implements
proper mcountinhibit CSR emulation.

Signed-off-by: Anup Patel 
---
 target/riscv/cpu_bits.h | 3 ---
 target/riscv/csr.c  | 2 --
 2 files changed, 5 deletions(-)

diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 8724b45c08..b3f7fa7130 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -159,9 +159,6 @@
 #define CSR_MTVEC   0x305
 #define CSR_MCOUNTEREN  0x306
 
-/* Machine Counter Setup */
-#define CSR_MCOUNTINHIBIT   0x320
-
 /* 32-bit only */
 #define CSR_MSTATUSH0x310
 
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index b5734957cf..d65318dcc6 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -3642,8 +3642,6 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
 [CSR_MIE] = { "mie",any,   NULL,NULL,rmw_mie   
},
 [CSR_MTVEC]   = { "mtvec",  any,   read_mtvec,   write_mtvec   
},
 [CSR_MCOUNTEREN]  = { "mcounteren", any,   read_mcounteren,  
write_mcounteren  },
-[CSR_MCOUNTINHIBIT] = { "mcountinhibit", any, read_zero, write_ignore,
- .min_priv_ver = 
PRIV_VERSION_1_11_0 },
 
 [CSR_MSTATUSH]= { "mstatush",   any32, read_mstatush,
write_mstatush},
 
-- 
2.34.1




Re: [PATCH v6 3/4] target/riscv: Update [m|h]tinst CSR in riscv_cpu_do_interrupt()

2022-06-28 Thread Anup Patel
On Mon, Jun 27, 2022 at 10:25 PM dramforever  wrote:
>
> On 6/27/22 09:00, Alistair Francis wrote:
> > On Sat, Jun 11, 2022 at 6:06 PM Anup Patel  wrote:
> >> We should write transformed instruction encoding of the trapped
> >> instruction in [m|h]tinst CSR at time of taking trap as defined
> >> by the RISC-V privileged specification v1.12.
> >>
> >> Signed-off-by: Anup Patel 
> >> ---
> >>  target/riscv/cpu.h|   3 +
> >>  target/riscv/cpu_helper.c | 214 --
> >>  target/riscv/instmap.h|  45 
> >>  3 files changed, 256 insertions(+), 6 deletions(-)
> >>
> >> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> >> index 7d6397acdf..cac9e1876c 100644
> >> --- a/target/riscv/cpu.h
> >> +++ b/target/riscv/cpu.h
> >> @@ -271,6 +271,9 @@ struct CPUArchState {
> >>  /* Signals whether the current exception occurred with two-stage 
> >> address
> >> translation active. */
> >>  bool two_stage_lookup;
> >> +/* Signals whether the current exception occurred while doing 
> >> two-stage
> >> +   address translation for the VS-stage page table walk. */
> > Wrong comment style, otherwise
> >
> > Reviewed-by: Alistair Francis 
> >
> > I can fix this up when I apply the series (unless you need to spin a
> > new version)
> >
> > Alistair
>
> Hi Anup Patel and Alistair Francis,
>
> I still have some concerns about this patch. Can you please take a look
> before this goes to master?
>
> >> +bool two_stage_indirect_lookup;
> >>
> >>  target_ulong scounteren;
> >>  target_ulong mcounteren;
> >> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> >> index 4a6700c890..3c8ebecf84 100644
> >> --- a/target/riscv/cpu_helper.c
> >> +++ b/target/riscv/cpu_helper.c
> >> @@ -22,6 +22,7 @@
> >>  #include "qemu/main-loop.h"
> >>  #include "cpu.h"
> >>  #include "exec/exec-all.h"
> >> +#include "instmap.h"
> >>  #include "tcg/tcg-op.h"
> >>  #include "trace.h"
> >>  #include "semihosting/common-semi.h"
> >> @@ -1057,7 +1058,8 @@ restart:
> >>
> >>  static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
> >>  MMUAccessType access_type, bool 
> >> pmp_violation,
> >> -bool first_stage, bool two_stage)
> >> +bool first_stage, bool two_stage,
> >> +bool two_stage_indirect)
> >>  {
> >>  CPUState *cs = env_cpu(env);
> >>  int page_fault_exceptions, vm;
> >> @@ -1107,6 +1109,7 @@ static void raise_mmu_exception(CPURISCVState *env, 
> >> target_ulong address,
> >>  }
> >>  env->badaddr = address;
> >>  env->two_stage_lookup = two_stage;
> >> +env->two_stage_indirect_lookup = two_stage_indirect;
> >>  }
> >>
> >>  hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
> >> @@ -1152,6 +1155,7 @@ void riscv_cpu_do_transaction_failed(CPUState *cs, 
> >> hwaddr physaddr,
> >>  env->badaddr = addr;
> >>  env->two_stage_lookup = riscv_cpu_virt_enabled(env) ||
> >>  riscv_cpu_two_stage_lookup(mmu_idx);
> >> +env->two_stage_indirect_lookup = false;
> >>  cpu_loop_exit_restore(cs, retaddr);
> >>  }
> >>
> >> @@ -1177,6 +1181,7 @@ void riscv_cpu_do_unaligned_access(CPUState *cs, 
> >> vaddr addr,
> >>  env->badaddr = addr;
> >>  env->two_stage_lookup = riscv_cpu_virt_enabled(env) ||
> >>  riscv_cpu_two_stage_lookup(mmu_idx);
> >> +env->two_stage_indirect_lookup = false;
> >>  cpu_loop_exit_restore(cs, retaddr);
> >>  }
> >>
> >> @@ -1192,6 +1197,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, 
> >> int size,
> >>  bool pmp_violation = false;
> >>  bool first_stage_error = true;
> >>  bool two_stage_lookup = false;
> >> +bool two_stage_indirect_error = false;
> >>  int ret = TRANSLATE_FAIL;
> >>  int mode = mmu_idx;
> >>  /* default TLB page size */
> >> @@ -1229,6 +1235,7 @@ bool riscv_cpu_tlb_fi

[PATCH v7 2/4] target/riscv: Set minumum priv spec version for mcountinhibit

2022-06-28 Thread Anup Patel
The minimum priv spec versino for mcountinhibit to v1.11 so that it
is not available for v1.10 (or lower).

Fixes: eab4776b2bad ("target/riscv: Add support for hpmcounters/hpmevents")
Signed-off-by: Anup Patel 
---
 target/riscv/csr.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index d65318dcc6..f7bfd2eab5 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -3944,7 +3944,7 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
write_mhpmcounter },
 
 [CSR_MCOUNTINHIBIT]  = { "mcountinhibit",  any, read_mcountinhibit,
-write_mcountinhibit },
+   write_mcountinhibit, .min_priv_ver = PRIV_VERSION_1_11_0  },
 
 [CSR_MHPMEVENT3] = { "mhpmevent3", any,read_mhpmevent,
write_mhpmevent },
-- 
2.34.1




[PATCH v7 1/4] Revert "target/riscv: Add dummy mcountinhibit CSR for priv spec v1.11 or higher"

2022-06-28 Thread Anup Patel
This reverts commit 33cc1c0b69e457f5c526f64297353cba6f7bfdb4 because
commit eab4776b2badd4088a4f807c9bb3dc453c53dc23 already implements
proper mcountinhibit CSR emulation.

Signed-off-by: Anup Patel 
---
 target/riscv/cpu_bits.h | 3 ---
 target/riscv/csr.c  | 2 --
 2 files changed, 5 deletions(-)

diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 8724b45c08..b3f7fa7130 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -159,9 +159,6 @@
 #define CSR_MTVEC   0x305
 #define CSR_MCOUNTEREN  0x306
 
-/* Machine Counter Setup */
-#define CSR_MCOUNTINHIBIT   0x320
-
 /* 32-bit only */
 #define CSR_MSTATUSH0x310
 
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index b5734957cf..d65318dcc6 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -3642,8 +3642,6 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
 [CSR_MIE] = { "mie",any,   NULL,NULL,rmw_mie   
},
 [CSR_MTVEC]   = { "mtvec",  any,   read_mtvec,   write_mtvec   
},
 [CSR_MCOUNTEREN]  = { "mcounteren", any,   read_mcounteren,  
write_mcounteren  },
-[CSR_MCOUNTINHIBIT] = { "mcountinhibit", any, read_zero, write_ignore,
- .min_priv_ver = 
PRIV_VERSION_1_11_0 },
 
 [CSR_MSTATUSH]= { "mstatush",   any32, read_mstatush,
write_mstatush},
 
-- 
2.34.1




[PATCH v7 4/4] target/riscv: Force disable extensions if priv spec version does not match

2022-06-27 Thread Anup Patel
We should disable extensions in riscv_cpu_realize() if minimum required
priv spec version is not satisfied. This also ensures that machines with
priv spec v1.11 (or lower) cannot enable H, V, and various multi-letter
extensions.

Fixes: a775398be2e9 ("target/riscv: Add isa extenstion strings to the device 
tree")
Reviewed-by: Alistair Francis 
Signed-off-by: Anup Patel 
Signed-off-by: Rahul Pathak 
---
 target/riscv/cpu.c | 150 -
 1 file changed, 94 insertions(+), 56 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 4e7ca6cd4a..9bc4ef0685 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -43,9 +43,82 @@ static const char riscv_single_letter_exts[] = "IEMAFDQCPVH";
 
 struct isa_ext_data {
 const char *name;
-bool enabled;
+bool multi_letter;
+int min_version;
+int ext_enable_offset;
 };
 
+#define ISA_EXT_DATA_ENTRY(_name, _m_letter, _min_ver, _prop) \
+{#_name, _m_letter, _min_ver, offsetof(struct RISCVCPUConfig, _prop)}
+
+/**
+ * Here are the ordering rules of extension naming defined by RISC-V
+ * specification :
+ * 1. All extensions should be separated from other multi-letter extensions
+ *by an underscore.
+ * 2. The first letter following the 'Z' conventionally indicates the most
+ *closely related alphabetical extension category, IMAFDQLCBKJTPVH.
+ *If multiple 'Z' extensions are named, they should be ordered first
+ *by category, then alphabetically within a category.
+ * 3. Standard supervisor-level extensions (starts with 'S') should be
+ *listed after standard unprivileged extensions.  If multiple
+ *supervisor-level extensions are listed, they should be ordered
+ *alphabetically.
+ * 4. Non-standard extensions (starts with 'X') must be listed after all
+ *standard extensions. They must be separated from other multi-letter
+ *extensions by an underscore.
+ */
+static const struct isa_ext_data isa_edata_arr[] = {
+ISA_EXT_DATA_ENTRY(h, false, PRIV_VERSION_1_12_0, ext_h),
+ISA_EXT_DATA_ENTRY(v, false, PRIV_VERSION_1_12_0, ext_v),
+ISA_EXT_DATA_ENTRY(zicsr, true, PRIV_VERSION_1_10_0, ext_icsr),
+ISA_EXT_DATA_ENTRY(zifencei, true, PRIV_VERSION_1_10_0, ext_ifencei),
+ISA_EXT_DATA_ENTRY(zfh, true, PRIV_VERSION_1_12_0, ext_zfh),
+ISA_EXT_DATA_ENTRY(zfhmin, true, PRIV_VERSION_1_12_0, ext_zfhmin),
+ISA_EXT_DATA_ENTRY(zfinx, true, PRIV_VERSION_1_12_0, ext_zfinx),
+ISA_EXT_DATA_ENTRY(zdinx, true, PRIV_VERSION_1_12_0, ext_zdinx),
+ISA_EXT_DATA_ENTRY(zba, true, PRIV_VERSION_1_12_0, ext_zba),
+ISA_EXT_DATA_ENTRY(zbb, true, PRIV_VERSION_1_12_0, ext_zbb),
+ISA_EXT_DATA_ENTRY(zbc, true, PRIV_VERSION_1_12_0, ext_zbc),
+ISA_EXT_DATA_ENTRY(zbkb, true, PRIV_VERSION_1_12_0, ext_zbkb),
+ISA_EXT_DATA_ENTRY(zbkc, true, PRIV_VERSION_1_12_0, ext_zbkc),
+ISA_EXT_DATA_ENTRY(zbkx, true, PRIV_VERSION_1_12_0, ext_zbkx),
+ISA_EXT_DATA_ENTRY(zbs, true, PRIV_VERSION_1_12_0, ext_zbs),
+ISA_EXT_DATA_ENTRY(zk, true, PRIV_VERSION_1_12_0, ext_zk),
+ISA_EXT_DATA_ENTRY(zkn, true, PRIV_VERSION_1_12_0, ext_zkn),
+ISA_EXT_DATA_ENTRY(zknd, true, PRIV_VERSION_1_12_0, ext_zknd),
+ISA_EXT_DATA_ENTRY(zkne, true, PRIV_VERSION_1_12_0, ext_zkne),
+ISA_EXT_DATA_ENTRY(zknh, true, PRIV_VERSION_1_12_0, ext_zknh),
+ISA_EXT_DATA_ENTRY(zkr, true, PRIV_VERSION_1_12_0, ext_zkr),
+ISA_EXT_DATA_ENTRY(zks, true, PRIV_VERSION_1_12_0, ext_zks),
+ISA_EXT_DATA_ENTRY(zksed, true, PRIV_VERSION_1_12_0, ext_zksed),
+ISA_EXT_DATA_ENTRY(zksh, true, PRIV_VERSION_1_12_0, ext_zksh),
+ISA_EXT_DATA_ENTRY(zkt, true, PRIV_VERSION_1_12_0, ext_zkt),
+ISA_EXT_DATA_ENTRY(zve32f, true, PRIV_VERSION_1_12_0, ext_zve32f),
+ISA_EXT_DATA_ENTRY(zve64f, true, PRIV_VERSION_1_12_0, ext_zve64f),
+ISA_EXT_DATA_ENTRY(zhinx, true, PRIV_VERSION_1_12_0, ext_zhinx),
+ISA_EXT_DATA_ENTRY(zhinxmin, true, PRIV_VERSION_1_12_0, ext_zhinxmin),
+ISA_EXT_DATA_ENTRY(svinval, true, PRIV_VERSION_1_12_0, ext_svinval),
+ISA_EXT_DATA_ENTRY(svnapot, true, PRIV_VERSION_1_12_0, ext_svnapot),
+ISA_EXT_DATA_ENTRY(svpbmt, true, PRIV_VERSION_1_12_0, ext_svpbmt),
+};
+
+static bool isa_ext_is_enabled(RISCVCPU *cpu,
+   const struct isa_ext_data *edata)
+{
+bool *ext_enabled = (void *)>cfg + edata->ext_enable_offset;
+
+return *ext_enabled;
+}
+
+static void isa_ext_update_enabled(RISCVCPU *cpu,
+   const struct isa_ext_data *edata, bool en)
+{
+bool *ext_enabled = (void *)>cfg + edata->ext_enable_offset;
+
+*ext_enabled = en;
+}
+
 const char * const riscv_int_regnames[] = {
   "x0/zero", "x1/ra",  "x2/sp",  "x3/gp",  "x4/tp",  "x5/t0",   "x6/t1",
   "x7/t2",   "x8/s0",  "x9/s1",  "x10/a0", "x11/a1", "x12/a2",  "x13/a3

[PATCH v7 3/4] target/riscv: Update [m|h]tinst CSR in riscv_cpu_do_interrupt()

2022-06-27 Thread Anup Patel
We should write transformed instruction encoding of the trapped
instruction in [m|h]tinst CSR at time of taking trap as defined
by the RISC-V privileged specification v1.12.

Reviewed-by: Alistair Francis 
Signed-off-by: Anup Patel 
---
 target/riscv/cpu.h|   5 +
 target/riscv/cpu_helper.c | 214 --
 target/riscv/instmap.h|  45 
 3 files changed, 258 insertions(+), 6 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 5c7acc055a..ffb1a18873 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -285,6 +285,11 @@ struct CPUArchState {
 /* Signals whether the current exception occurred with two-stage address
translation active. */
 bool two_stage_lookup;
+/*
+ * Signals whether the current exception occurred while doing two-stage
+ * address translation for the VS-stage page table walk.
+ */
+bool two_stage_indirect_lookup;
 
 target_ulong scounteren;
 target_ulong mcounteren;
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 4a6700c890..d890670f29 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -22,6 +22,7 @@
 #include "qemu/main-loop.h"
 #include "cpu.h"
 #include "exec/exec-all.h"
+#include "instmap.h"
 #include "tcg/tcg-op.h"
 #include "trace.h"
 #include "semihosting/common-semi.h"
@@ -1057,7 +1058,8 @@ restart:
 
 static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
 MMUAccessType access_type, bool pmp_violation,
-bool first_stage, bool two_stage)
+bool first_stage, bool two_stage,
+bool two_stage_indirect)
 {
 CPUState *cs = env_cpu(env);
 int page_fault_exceptions, vm;
@@ -1107,6 +1109,7 @@ static void raise_mmu_exception(CPURISCVState *env, 
target_ulong address,
 }
 env->badaddr = address;
 env->two_stage_lookup = two_stage;
+env->two_stage_indirect_lookup = two_stage_indirect;
 }
 
 hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
@@ -1152,6 +1155,7 @@ void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr 
physaddr,
 env->badaddr = addr;
 env->two_stage_lookup = riscv_cpu_virt_enabled(env) ||
 riscv_cpu_two_stage_lookup(mmu_idx);
+env->two_stage_indirect_lookup = false;
 cpu_loop_exit_restore(cs, retaddr);
 }
 
@@ -1177,6 +1181,7 @@ void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr 
addr,
 env->badaddr = addr;
 env->two_stage_lookup = riscv_cpu_virt_enabled(env) ||
 riscv_cpu_two_stage_lookup(mmu_idx);
+env->two_stage_indirect_lookup = false;
 cpu_loop_exit_restore(cs, retaddr);
 }
 
@@ -1192,6 +1197,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int 
size,
 bool pmp_violation = false;
 bool first_stage_error = true;
 bool two_stage_lookup = false;
+bool two_stage_indirect_error = false;
 int ret = TRANSLATE_FAIL;
 int mode = mmu_idx;
 /* default TLB page size */
@@ -1229,6 +1235,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int 
size,
  */
 if (ret == TRANSLATE_G_STAGE_FAIL) {
 first_stage_error = false;
+two_stage_indirect_error = true;
 access_type = MMU_DATA_LOAD;
 }
 
@@ -1312,12 +1319,182 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, 
int size,
 raise_mmu_exception(env, address, access_type, pmp_violation,
 first_stage_error,
 riscv_cpu_virt_enabled(env) ||
-riscv_cpu_two_stage_lookup(mmu_idx));
+riscv_cpu_two_stage_lookup(mmu_idx),
+two_stage_indirect_error);
 cpu_loop_exit_restore(cs, retaddr);
 }
 
 return true;
 }
+
+static target_ulong riscv_transformed_insn(CPURISCVState *env,
+   target_ulong insn,
+   bool addr_offset_nonzero,
+   target_ulong taddr)
+{
+target_ulong xinsn = 0, xinsn_access_bits = 0;
+
+/*
+ * Only Quadrant 0 and Quadrant 2 of RVC instruction space need to
+ * be uncompressed. The Quadrant 1 of RVC instruction space need
+ * not be transformed because these instructions won't generate
+ * any load/store trap.
+ */
+
+if ((insn & 0x3) != 0x3) {
+/* Transform 16bit instruction into 32bit instruction */
+switch (GET_C_OP(insn)) {
+case OPC_RISC_C_OP_QUAD0: /* Quadrant 0 */
+switch (GET_C_FUNC(insn)) {
+case OPC_RISC_C_FUNC_FLD_LQ:
+if (riscv_cpu_xlen(env) != 128) { /* C.FLD (RV32/64) */

[PATCH v7 0/4] QEMU RISC-V nested virtualization fixes

2022-06-27 Thread Anup Patel
This series does fixes and improvements to have nested virtualization
on QEMU RISC-V.

These patches can also be found in riscv_nested_fixes_v7 branch at:
https://github.com/avpatel/qemu.git

The RISC-V nested virtualization was tested on QEMU RISC-V using
Xvisor RISC-V which has required hypervisor support to run another
hypervisor as Guest/VM.

Changes since v6:
 - Droppred original PATCH1 and PATCH2 since these are already merged
 - Added PATCH1 to revert dummy mcountinhibit CSR
 - Added PATCH2 to fix minimum priv spec version for mcountinhibit CSR
 - Fixed checkpatch error in PATCH3
 - Fixed compile error in PATCH4

Changes since v5:
 - Correctly set "Addr. Offset" for misaligned load/store traps in PATCH3
 - Use offsetof() instead of pointer in PATCH4

Changes since v4:
 - Updated commit description in PATCH1, PATCH2, and PATCH4
 - Use "const" for local array in PATCH5

Changes since v3:
 - Updated PATCH3 to set special pseudoinstructions in htinst for
   guest page faults which result due to VS-stage page table walks
 - Updated warning message in PATCH4

Changes since v2:
 - Dropped the patch which are already in Alistair's next branch
 - Set "Addr. Offset" in the transformed instruction for PATCH3
 - Print warning in riscv_cpu_realize() if we are disabling an
   extension due to privilege spec verions mismatch for PATCH4

Changes since v1:
 - Set write_gva to env->two_stage_lookup which ensures that for
   HS-mode to HS-mode trap write_gva is true only for HLV/HSV
   instructions
 - Included "[PATCH 0/3] QEMU RISC-V priv spec version fixes"
   patches in this series for easy review
 - Re-worked PATCH7 to force disable extensions if required
   priv spec version is not staisfied
 - Added new PATCH8 to fix "aia=aplic-imsic" mode of virt machine

Anup Patel (4):
  Revert "target/riscv: Add dummy mcountinhibit CSR for priv spec v1.11
or higher"
  target/riscv: Set minumum priv spec version for mcountinhibit
  target/riscv: Update [m|h]tinst CSR in riscv_cpu_do_interrupt()
  target/riscv: Force disable extensions if priv spec version does not
match

 target/riscv/cpu.c| 150 --
 target/riscv/cpu.h|   5 +
 target/riscv/cpu_bits.h   |   3 -
 target/riscv/cpu_helper.c | 214 --
 target/riscv/csr.c|   4 +-
 target/riscv/instmap.h|  45 
 6 files changed, 353 insertions(+), 68 deletions(-)

-- 
2.34.1




Re: [PATCH v6 4/4] target/riscv: Force disable extensions if priv spec version does not match

2022-06-27 Thread Anup Patel
On Tue, Jun 28, 2022 at 4:47 AM Alistair Francis  wrote:
>
> On Sat, Jun 11, 2022 at 6:07 PM Anup Patel  wrote:
> >
> > We should disable extensions in riscv_cpu_realize() if minimum required
> > priv spec version is not satisfied. This also ensures that machines with
> > priv spec v1.11 (or lower) cannot enable H, V, and various multi-letter
> > extensions.
> >
> > Fixes: a775398be2e9 ("target/riscv: Add isa extenstion strings to the 
> > device tree")
> > Signed-off-by: Anup Patel 
>
> This fails to build
>
> ../target/riscv/cpu.c: In function 'riscv_cpu_realize':
> ../target/riscv/cpu.c:641:66: error: 'CPURISCVState' {aka 'struct
> CPUArchState'} has no member named 'mhartid'
>   641 | isa_edata_arr[i].name, (unsigned
> long)env->mhartid);
>   |  ^~

I missed testing riscv64-linux-user build.

I will fix and quickly send v7.

Regards,
Anup

>
> Alistair
>
> > ---
> >  target/riscv/cpu.c | 144 +++--
> >  1 file changed, 88 insertions(+), 56 deletions(-)
> >
> > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> > index 8db0f0bd49..a17bc98662 100644
> > --- a/target/riscv/cpu.c
> > +++ b/target/riscv/cpu.c
> > @@ -43,9 +43,82 @@ static const char riscv_single_letter_exts[] = 
> > "IEMAFDQCPVH";
> >
> >  struct isa_ext_data {
> >  const char *name;
> > -bool enabled;
> > +bool multi_letter;
> > +int min_version;
> > +int ext_enable_offset;
> >  };
> >
> > +#define ISA_EXT_DATA_ENTRY(_name, _m_letter, _min_ver, _prop) \
> > +{#_name, _m_letter, _min_ver, offsetof(struct RISCVCPUConfig, _prop)}
> > +
> > +/**
> > + * Here are the ordering rules of extension naming defined by RISC-V
> > + * specification :
> > + * 1. All extensions should be separated from other multi-letter extensions
> > + *by an underscore.
> > + * 2. The first letter following the 'Z' conventionally indicates the most
> > + *closely related alphabetical extension category, IMAFDQLCBKJTPVH.
> > + *If multiple 'Z' extensions are named, they should be ordered first
> > + *by category, then alphabetically within a category.
> > + * 3. Standard supervisor-level extensions (starts with 'S') should be
> > + *listed after standard unprivileged extensions.  If multiple
> > + *supervisor-level extensions are listed, they should be ordered
> > + *alphabetically.
> > + * 4. Non-standard extensions (starts with 'X') must be listed after all
> > + *standard extensions. They must be separated from other multi-letter
> > + *extensions by an underscore.
> > + */
> > +static const struct isa_ext_data isa_edata_arr[] = {
> > +ISA_EXT_DATA_ENTRY(h, false, PRIV_VERSION_1_12_0, ext_h),
> > +ISA_EXT_DATA_ENTRY(v, false, PRIV_VERSION_1_12_0, ext_v),
> > +ISA_EXT_DATA_ENTRY(zicsr, true, PRIV_VERSION_1_10_0, ext_icsr),
> > +ISA_EXT_DATA_ENTRY(zifencei, true, PRIV_VERSION_1_10_0, ext_ifencei),
> > +ISA_EXT_DATA_ENTRY(zfh, true, PRIV_VERSION_1_12_0, ext_zfh),
> > +ISA_EXT_DATA_ENTRY(zfhmin, true, PRIV_VERSION_1_12_0, ext_zfhmin),
> > +ISA_EXT_DATA_ENTRY(zfinx, true, PRIV_VERSION_1_12_0, ext_zfinx),
> > +ISA_EXT_DATA_ENTRY(zdinx, true, PRIV_VERSION_1_12_0, ext_zdinx),
> > +ISA_EXT_DATA_ENTRY(zba, true, PRIV_VERSION_1_12_0, ext_zba),
> > +ISA_EXT_DATA_ENTRY(zbb, true, PRIV_VERSION_1_12_0, ext_zbb),
> > +ISA_EXT_DATA_ENTRY(zbc, true, PRIV_VERSION_1_12_0, ext_zbc),
> > +ISA_EXT_DATA_ENTRY(zbkb, true, PRIV_VERSION_1_12_0, ext_zbkb),
> > +ISA_EXT_DATA_ENTRY(zbkc, true, PRIV_VERSION_1_12_0, ext_zbkc),
> > +ISA_EXT_DATA_ENTRY(zbkx, true, PRIV_VERSION_1_12_0, ext_zbkx),
> > +ISA_EXT_DATA_ENTRY(zbs, true, PRIV_VERSION_1_12_0, ext_zbs),
> > +ISA_EXT_DATA_ENTRY(zk, true, PRIV_VERSION_1_12_0, ext_zk),
> > +ISA_EXT_DATA_ENTRY(zkn, true, PRIV_VERSION_1_12_0, ext_zkn),
> > +ISA_EXT_DATA_ENTRY(zknd, true, PRIV_VERSION_1_12_0, ext_zknd),
> > +ISA_EXT_DATA_ENTRY(zkne, true, PRIV_VERSION_1_12_0, ext_zkne),
> > +ISA_EXT_DATA_ENTRY(zknh, true, PRIV_VERSION_1_12_0, ext_zknh),
> > +ISA_EXT_DATA_ENTRY(zkr, true, PRIV_VERSION_1_12_0, ext_zkr),
> > +ISA_EXT_DATA_ENTRY(zks, true, PRIV_VERSION_1_12_0, ext_zks),
> > +ISA_EXT_DATA_ENTRY(zksed, true, PRIV_VERSION_1_12_0, ext_zksed),
> > +ISA_EXT_DATA_ENTRY(zksh, true, PRIV_VERSION_1_12_0, ext_zksh),
> > +ISA_EXT_DATA_ENTRY(zkt, true, PRIV_VERSION_1_12_0, ext

Re: [PATCH v5 3/4] target/riscv: Update [m|h]tinst CSR in riscv_cpu_do_interrupt()

2022-06-27 Thread Anup Patel
On Tue, Jun 28, 2022 at 4:48 AM Alistair Francis  wrote:
>
> On Thu, Jun 9, 2022 at 1:31 PM Anup Patel  wrote:
> >
> > We should write transformed instruction encoding of the trapped
> > instruction in [m|h]tinst CSR at time of taking trap as defined
> > by the RISC-V privileged specification v1.12.
> >
> > Signed-off-by: Anup Patel 
>
> This fails to pass checkpatch
>
> ERROR: suspect code indent for conditional statements (13, 17)
> #257: FILE: target/riscv/cpu_helper.c:1480:
> + if (MASK_OP_SYSTEM(insn) == OPC_RISC_HLVHSV) {
> + xinsn = insn;
>
> total: 1 errors, 0 warnings, 389 lines checked

Okay, I will quickly send v7.

Regards,
Anup

>
> Alistair
>
> > ---
> >  target/riscv/cpu.h|   3 +
> >  target/riscv/cpu_helper.c | 231 +-
> >  target/riscv/instmap.h|  43 +++
> >  3 files changed, 271 insertions(+), 6 deletions(-)
> >
> > diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> > index 194a58d760..11726e9031 100644
> > --- a/target/riscv/cpu.h
> > +++ b/target/riscv/cpu.h
> > @@ -271,6 +271,9 @@ struct CPUArchState {
> >  /* Signals whether the current exception occurred with two-stage 
> > address
> > translation active. */
> >  bool two_stage_lookup;
> > +/* Signals whether the current exception occurred while doing two-stage
> > +   address translation for the VS-stage page table walk. */
> > +bool two_stage_indirect_lookup;
> >
> >  target_ulong scounteren;
> >  target_ulong mcounteren;
> > diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> > index 16c6045459..62a6762617 100644
> > --- a/target/riscv/cpu_helper.c
> > +++ b/target/riscv/cpu_helper.c
> > @@ -22,6 +22,7 @@
> >  #include "qemu/main-loop.h"
> >  #include "cpu.h"
> >  #include "exec/exec-all.h"
> > +#include "instmap.h"
> >  #include "tcg/tcg-op.h"
> >  #include "trace.h"
> >  #include "semihosting/common-semi.h"
> > @@ -1055,7 +1056,8 @@ restart:
> >
> >  static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
> >  MMUAccessType access_type, bool 
> > pmp_violation,
> > -bool first_stage, bool two_stage)
> > +bool first_stage, bool two_stage,
> > +bool two_stage_indirect)
> >  {
> >  CPUState *cs = env_cpu(env);
> >  int page_fault_exceptions, vm;
> > @@ -1105,6 +1107,7 @@ static void raise_mmu_exception(CPURISCVState *env, 
> > target_ulong address,
> >  }
> >  env->badaddr = address;
> >  env->two_stage_lookup = two_stage;
> > +env->two_stage_indirect_lookup = two_stage_indirect;
> >  }
> >
> >  hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
> > @@ -1150,6 +1153,7 @@ void riscv_cpu_do_transaction_failed(CPUState *cs, 
> > hwaddr physaddr,
> >  env->badaddr = addr;
> >  env->two_stage_lookup = riscv_cpu_virt_enabled(env) ||
> >  riscv_cpu_two_stage_lookup(mmu_idx);
> > +env->two_stage_indirect_lookup = false;
> >  cpu_loop_exit_restore(cs, retaddr);
> >  }
> >
> > @@ -1175,6 +1179,7 @@ void riscv_cpu_do_unaligned_access(CPUState *cs, 
> > vaddr addr,
> >  env->badaddr = addr;
> >  env->two_stage_lookup = riscv_cpu_virt_enabled(env) ||
> >  riscv_cpu_two_stage_lookup(mmu_idx);
> > +env->two_stage_indirect_lookup = false;
> >  cpu_loop_exit_restore(cs, retaddr);
> >  }
> >
> > @@ -1190,6 +1195,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, 
> > int size,
> >  bool pmp_violation = false;
> >  bool first_stage_error = true;
> >  bool two_stage_lookup = false;
> > +bool two_stage_indirect_error = false;
> >  int ret = TRANSLATE_FAIL;
> >  int mode = mmu_idx;
> >  /* default TLB page size */
> > @@ -1227,6 +1233,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, 
> > int size,
> >   */
> >  if (ret == TRANSLATE_G_STAGE_FAIL) {
> >  first_stage_error = false;
> > +two_stage_indirect_error = true;
> >  access_type = MMU_DATA_LOAD;
> >  }
> >
> > @@ -1310,12 +1317,207 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr 
> > addre

Re: [PATCH v5 2/3] target/riscv: Add stimecmp support

2022-06-15 Thread Anup Patel
On Thu, Jun 16, 2022 at 8:08 AM Alistair Francis  wrote:
>
> On Thu, Jun 16, 2022 at 4:21 AM Atish Kumar Patra  wrote:
> >
> > On Wed, Jun 8, 2022 at 12:19 AM Alistair Francis  
> > wrote:
> > >
> > > On Mon, Jun 6, 2022 at 2:23 AM Atish Patra  wrote:
> > > >
> > > > On Thu, Jun 2, 2022 at 12:02 AM Alistair Francis  
> > > > wrote:
> > > > >
> > > > > On Wed, Jun 1, 2022 at 4:16 AM Atish Patra  
> > > > > wrote:
> > > > > >
> > > > > > stimecmp allows the supervisor mode to update stimecmp CSR directly
> > > > > > to program the next timer interrupt. This CSR is part of the Sstc
> > > > > > extension which was ratified recently.
> > > > > >
> > > > > > Signed-off-by: Atish Patra 
> > > > > > ---
> > > > > >  target/riscv/cpu.c |  8 
> > > > > >  target/riscv/cpu.h |  5 ++
> > > > > >  target/riscv/cpu_bits.h|  4 ++
> > > > > >  target/riscv/csr.c | 81 +++
> > > > > >  target/riscv/machine.c |  1 +
> > > > > >  target/riscv/meson.build   |  3 +-
> > > > > >  target/riscv/time_helper.c | 98 
> > > > > > ++
> > > > > >  target/riscv/time_helper.h | 30 
> > > > > >  8 files changed, 229 insertions(+), 1 deletion(-)
> > > > > >  create mode 100644 target/riscv/time_helper.c
> > > > > >  create mode 100644 target/riscv/time_helper.h
> > > > > >
> > > > > > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> > > > > > index 19f4e8294042..d58dd2f857a7 100644
> > > > > > --- a/target/riscv/cpu.c
> > > > > > +++ b/target/riscv/cpu.c
> > > > > > @@ -23,6 +23,7 @@
> > > > > >  #include "qemu/log.h"
> > > > > >  #include "cpu.h"
> > > > > >  #include "internals.h"
> > > > > > +#include "time_helper.h"
> > > > > >  #include "exec/exec-all.h"
> > > > > >  #include "qapi/error.h"
> > > > > >  #include "qemu/error-report.h"
> > > > > > @@ -779,7 +780,12 @@ static void riscv_cpu_init(Object *obj)
> > > > > >  #ifndef CONFIG_USER_ONLY
> > > > > >  qdev_init_gpio_in(DEVICE(cpu), riscv_cpu_set_irq,
> > > > > >IRQ_LOCAL_MAX + IRQ_LOCAL_GUEST_MAX);
> > > > > > +
> > > > > > +if (cpu->cfg.ext_sstc) {
> > > > > > +riscv_timer_init(cpu);
> > > > > > +}
> > > > > >  #endif /* CONFIG_USER_ONLY */
> > > > > > +
> > > > > >  }
> > > > > >
> > > > > >  static Property riscv_cpu_properties[] = {
> > > > > > @@ -806,6 +812,7 @@ static Property riscv_cpu_properties[] = {
> > > > > >  DEFINE_PROP_BOOL("mmu", RISCVCPU, cfg.mmu, true),
> > > > > >  DEFINE_PROP_BOOL("pmp", RISCVCPU, cfg.pmp, true),
> > > > > >  DEFINE_PROP_BOOL("debug", RISCVCPU, cfg.debug, true),
> > > > > > +DEFINE_PROP_BOOL("sstc", RISCVCPU, cfg.ext_sstc, true),
> > > > >
> > > > > Do we want this enabled by default?
> > > > >
> > > >
> > > > sstc extension will result in performance improvements as it avoids
> > > > the SBI calls & interrupt forwarding
> > > > path. That's why I think it should be enabled by default.
> > > >
> > > > > >
> > > > > >  DEFINE_PROP_STRING("priv_spec", RISCVCPU, cfg.priv_spec),
> > > > > >  DEFINE_PROP_STRING("vext_spec", RISCVCPU, cfg.vext_spec),
> > > > > > @@ -965,6 +972,7 @@ static void riscv_isa_string_ext(RISCVCPU *cpu, 
> > > > > > char **isa_str, int max_str_len)
> > > > > >  ISA_EDATA_ENTRY(zbs, ext_zbs),
> > > > > >  ISA_EDATA_ENTRY(zve32f, ext_zve32f),
> > > > > >  ISA_EDATA_ENTRY(zve64f, ext_zve64f),
> > > > > > +ISA_EDATA_ENTRY(sstc, ext_sstc),
> > > > > >  ISA_EDATA_ENTRY(svinval, ext_svinval),
> > > > > >  ISA_EDATA_ENTRY(svnapot, ext_svnapot),
> > > > > >  ISA_EDATA_ENTRY(svpbmt, ext_svpbmt),
> > > > > > diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> > > > > > index 1119d5201066..9a5e02f217ba 100644
> > > > > > --- a/target/riscv/cpu.h
> > > > > > +++ b/target/riscv/cpu.h
> > > > > > @@ -276,6 +276,9 @@ struct CPUArchState {
> > > > > >  uint64_t mfromhost;
> > > > > >  uint64_t mtohost;
> > > > > >
> > > > > > +/* Sstc CSRs */
> > > > > > +uint64_t stimecmp;
> > > > > > +
> > > > > >  /* physical memory protection */
> > > > > >  pmp_table_t pmp_state;
> > > > > >  target_ulong mseccfg;
> > > > > > @@ -329,6 +332,7 @@ struct CPUArchState {
> > > > > >  float_status fp_status;
> > > > > >
> > > > > >  /* Fields from here on are preserved across CPU reset. */
> > > > > > +QEMUTimer *stimer; /* Internal timer for S-mode interrupt */
> > > > > >
> > > > > >  hwaddr kernel_addr;
> > > > > >  hwaddr fdt_addr;
> > > > > > @@ -379,6 +383,7 @@ struct RISCVCPUConfig {
> > > > > >  bool ext_counters;
> > > > > >  bool ext_ifencei;
> > > > > >  bool ext_icsr;
> > > > > > +bool ext_sstc;
> > > > > >  bool ext_svinval;
> > > > > >  bool ext_svnapot;
> > > > > >  bool ext_svpbmt;
> > > > > > diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> > > > > > index 4e5b630f5965..29d0e4a1be01 100644
> > > > > > --- 

[PATCH 1/2] target/riscv: Remove CSRs that set/clear an IMSIC interrupt file bits

2022-06-15 Thread Anup Patel
Based on architecture review committee feedback, the [m|s|vs]seteienum,
[m|s|vs]clreienum, [m|s|vs]seteipnum, and [m|s|vs]clreipnum CSRs are
removed in the latest AIA draft v0.3.0 specification.
(Refer, https://github.com/riscv/riscv-aia/releases/tag/0.3.0-draft.31)

These CSRs were mostly for software convenience and software can always
use [m|s|vs]iselect and [m|s|vs]ireg CSRs to update the IMSIC interrupt
file bits.

We update the IMSIC CSR emulation as-per above to match the latest AIA
draft specification.

Signed-off-by: Anup Patel 
---
 target/riscv/cpu_bits.h |  24 +--
 target/riscv/csr.c  | 150 +---
 2 files changed, 6 insertions(+), 168 deletions(-)

diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 4a55c6a709..01608f86e5 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -177,14 +177,8 @@
 #define CSR_MIREG   0x351
 
 /* Machine-Level Interrupts (AIA) */
-#define CSR_MTOPI   0xfb0
-
-/* Machine-Level IMSIC Interface (AIA) */
-#define CSR_MSETEIPNUM  0x358
-#define CSR_MCLREIPNUM  0x359
-#define CSR_MSETEIENUM  0x35a
-#define CSR_MCLREIENUM  0x35b
 #define CSR_MTOPEI  0x35c
+#define CSR_MTOPI   0xfb0
 
 /* Virtual Interrupts for Supervisor Level (AIA) */
 #define CSR_MVIEN   0x308
@@ -224,14 +218,8 @@
 #define CSR_SIREG   0x151
 
 /* Supervisor-Level Interrupts (AIA) */
-#define CSR_STOPI   0xdb0
-
-/* Supervisor-Level IMSIC Interface (AIA) */
-#define CSR_SSETEIPNUM  0x158
-#define CSR_SCLREIPNUM  0x159
-#define CSR_SSETEIENUM  0x15a
-#define CSR_SCLREIENUM  0x15b
 #define CSR_STOPEI  0x15c
+#define CSR_STOPI   0xdb0
 
 /* Supervisor-Level High-Half CSRs (AIA) */
 #define CSR_SIEH0x114
@@ -282,14 +270,8 @@
 #define CSR_VSIREG  0x251
 
 /* VS-Level Interrupts (H-extension with AIA) */
-#define CSR_VSTOPI  0xeb0
-
-/* VS-Level IMSIC Interface (H-extension with AIA) */
-#define CSR_VSSETEIPNUM 0x258
-#define CSR_VSCLREIPNUM 0x259
-#define CSR_VSSETEIENUM 0x25a
-#define CSR_VSCLREIENUM 0x25b
 #define CSR_VSTOPEI 0x25c
+#define CSR_VSTOPI  0xeb0
 
 /* Hypervisor and VS-Level High-Half CSRs (H-extension with AIA) */
 #define CSR_HIDELEGH0x613
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 409a209f14..a4890ebc70 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -1040,14 +1040,6 @@ static int aia_xlate_vs_csrno(CPURISCVState *env, int 
csrno)
 return CSR_VSISELECT;
 case CSR_SIREG:
 return CSR_VSIREG;
-case CSR_SSETEIPNUM:
-return CSR_VSSETEIPNUM;
-case CSR_SCLREIPNUM:
-return CSR_VSCLREIPNUM;
-case CSR_SSETEIENUM:
-return CSR_VSSETEIENUM;
-case CSR_SCLREIENUM:
-return CSR_VSCLREIENUM;
 case CSR_STOPEI:
 return CSR_VSTOPEI;
 default:
@@ -1202,124 +1194,6 @@ done:
 return RISCV_EXCP_NONE;
 }
 
-static int rmw_xsetclreinum(CPURISCVState *env, int csrno, target_ulong *val,
-target_ulong new_val, target_ulong wr_mask)
-{
-int ret = -EINVAL;
-bool set, pend, virt;
-target_ulong priv, isel, vgein, xlen, nval, wmask;
-
-/* Translate CSR number for VS-mode */
-csrno = aia_xlate_vs_csrno(env, csrno);
-
-/* Decode register details from CSR number */
-virt = set = pend = false;
-switch (csrno) {
-case CSR_MSETEIPNUM:
-priv = PRV_M;
-set = true;
-pend = true;
-break;
-case CSR_MCLREIPNUM:
-priv = PRV_M;
-pend = true;
-break;
-case CSR_MSETEIENUM:
-priv = PRV_M;
-set = true;
-break;
-case CSR_MCLREIENUM:
-priv = PRV_M;
-break;
-case CSR_SSETEIPNUM:
-priv = PRV_S;
-set = true;
-pend = true;
-break;
-case CSR_SCLREIPNUM:
-priv = PRV_S;
-pend = true;
-break;
-case CSR_SSETEIENUM:
-priv = PRV_S;
-set = true;
-break;
-case CSR_SCLREIENUM:
-priv = PRV_S;
-break;
-case CSR_VSSETEIPNUM:
-priv = PRV_S;
-virt = true;
-set = true;
-pend = true;
-break;
-case CSR_VSCLREIPNUM:
-priv = PRV_S;
-virt = true;
-pend = true;
-break;
-case CSR_VSSETEIENUM:
-priv = PRV_S;
-virt = true;
-set = true;
-break;
-case CSR_VSCLREIENUM:
-priv = PRV_S;
-virt = true;
-break;
-default:
- goto done;
-};
-
-/* IMSIC CSRs only available when machine implements IMSIC. */
-if (!env->aia_ireg_rmw_fn[priv]) {
-goto done;
-}
-
-/* Find the selected guest interrupt file */
-vgein = (virt) ? get_field(env->hstatus, HSTATUS_VGEIN) : 0;
-
-/* Selected guest interrupt file should be valid */
-if (virt && (!vgein 

[PATCH 2/2] target/riscv: Update default priority table for local interrupts

2022-06-15 Thread Anup Patel
The latest AIA draft v0.3.0 defines a relatively simpler scheme for
default priority assignments where:
1) local interrupts 24 to 31 and 48 to 63 are reserved for custom use
   and have implementation specific default priority.
2) remaining local interrupts 0 to 23 and 32 to 47 have a recommended
   (not mandatory) priority assignments.

We update the default priority table and hviprio mapping as-per above.

Signed-off-by: Anup Patel 
---
 target/riscv/cpu_bits.h   |   2 +-
 target/riscv/cpu_helper.c | 134 ++
 2 files changed, 66 insertions(+), 70 deletions(-)

diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 01608f86e5..63ba867379 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -773,7 +773,7 @@ typedef enum RISCVException {
 #define IPRIO_IRQ_BITS 8
 #define IPRIO_MMAXIPRIO255
 #define IPRIO_DEFAULT_UPPER4
-#define IPRIO_DEFAULT_MIDDLE   (IPRIO_DEFAULT_UPPER + 24)
+#define IPRIO_DEFAULT_MIDDLE   (IPRIO_DEFAULT_UPPER + 12)
 #define IPRIO_DEFAULT_MIPRIO_DEFAULT_MIDDLE
 #define IPRIO_DEFAULT_S(IPRIO_DEFAULT_M + 3)
 #define IPRIO_DEFAULT_SGEXT(IPRIO_DEFAULT_S + 3)
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 3c8ebecf84..063a1403db 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -169,17 +169,17 @@ void riscv_cpu_update_mask(CPURISCVState *env)
  * 14 "
  * 15 "
  * 16 "
- * 18 Debug/trace interrupt
- * 20 (Reserved interrupt)
+ * 17 "
+ * 18 "
+ * 19 "
+ * 20 "
+ * 21 "
  * 22 "
- * 24 "
- * 26 "
- * 28 "
- * 30 (Reserved for standard reporting of bus or system errors)
+ * 23 "
  */
 
 static const int hviprio_index2irq[] = {
-0, 1, 4, 5, 8, 13, 14, 15, 16, 18, 20, 22, 24, 26, 28, 30 };
+0, 1, 4, 5, 8, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 };
 static const int hviprio_index2rdzero[] = {
 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 
@@ -208,50 +208,60 @@ int riscv_cpu_hviprio_index2irq(int index, int *out_irq, 
int *out_rdzero)
  *  Default  |
  *  Priority | Major Interrupt Numbers
  * 
- *  Highest  | 63 (3f), 62 (3e), 31 (1f), 30 (1e), 61 (3d), 60 (3c),
- *   | 59 (3b), 58 (3a), 29 (1d), 28 (1c), 57 (39), 56 (38),
- *   | 55 (37), 54 (36), 27 (1b), 26 (1a), 53 (35), 52 (34),
- *   | 51 (33), 50 (32), 25 (19), 24 (18), 49 (31), 48 (30)
+ *  Highest  | 47, 23, 46, 45, 22, 44,
+ *   | 43, 21, 42, 41, 20, 40
  *   |
  *   | 11 (0b),  3 (03),  7 (07)
  *   |  9 (09),  1 (01),  5 (05)
  *   | 12 (0c)
  *   | 10 (0a),  2 (02),  6 (06)
  *   |
- *   | 47 (2f), 46 (2e), 23 (17), 22 (16), 45 (2d), 44 (2c),
- *   | 43 (2b), 42 (2a), 21 (15), 20 (14), 41 (29), 40 (28),
- *   | 39 (27), 38 (26), 19 (13), 18 (12), 37 (25), 36 (24),
- *  Lowest   | 35 (23), 34 (22), 17 (11), 16 (10), 33 (21), 32 (20)
+ *   | 39, 19, 38, 37, 18, 36,
+ *  Lowest   | 35, 17, 34, 33, 16, 32
  * 
  */
 static const uint8_t default_iprio[64] = {
- [63] = IPRIO_DEFAULT_UPPER,
- [62] = IPRIO_DEFAULT_UPPER + 1,
- [31] = IPRIO_DEFAULT_UPPER + 2,
- [30] = IPRIO_DEFAULT_UPPER + 3,
- [61] = IPRIO_DEFAULT_UPPER + 4,
- [60] = IPRIO_DEFAULT_UPPER + 5,
-
- [59] = IPRIO_DEFAULT_UPPER + 6,
- [58] = IPRIO_DEFAULT_UPPER + 7,
- [29] = IPRIO_DEFAULT_UPPER + 8,
- [28] = IPRIO_DEFAULT_UPPER + 9,
- [57] = IPRIO_DEFAULT_UPPER + 10,
- [56] = IPRIO_DEFAULT_UPPER + 11,
-
- [55] = IPRIO_DEFAULT_UPPER + 12,
- [54] = IPRIO_DEFAULT_UPPER + 13,
- [27] = IPRIO_DEFAULT_UPPER + 14,
- [26] = IPRIO_DEFAULT_UPPER + 15,
- [53] = IPRIO_DEFAULT_UPPER + 16,
- [52] = IPRIO_DEFAULT_UPPER + 17,
-
- [51] = IPRIO_DEFAULT_UPPER + 18,
- [50] = IPRIO_DEFAULT_UPPER + 19,
- [25] = IPRIO_DEFAULT_UPPER + 20,
- [24] = IPRIO_DEFAULT_UPPER + 21,
- [49] = IPRIO_DEFAULT_UPPER + 22,
- [48] = IPRIO_DEFAULT_UPPER + 23,
+ /* Custom interrupts 48 to 63 */
+ [63] = IPRIO_MMAXIPRIO,
+ [62] = IPRIO_MMAXIPRIO,
+ [61] = IPRIO_MMAXIPRIO,
+ [60] = IPRIO_MMAXIPRIO,
+ [59] = IPRIO_MMAXIPRIO,
+ [58] = IPRIO_MMAXIPRIO,
+ [57] = IPRIO_MMAXIPRIO,
+ [56] = IPRIO_MMAXIPRIO,
+ [55] = IPRIO_MMAXIPRIO,
+ [54] = IPRIO_MMAXIPRIO,
+ [53] = IPRIO_MMAXIPRIO,
+ [52] = IPRIO_MMAXIPRIO,
+ [51] = IPRIO_MMAXIPRIO,
+ [50] = IPRIO_MMAXIPRIO,
+ [49] = IPRIO_MMAXIPRIO,
+ [48] = IPRIO_MMAXIPRIO,
+
+ /* Custom interrupts 24 to 31 */
+ [31] = IPRIO_MMAXIPRIO,
+ [30] = IPRIO_MMAXIPRIO,
+ [29] = IPRIO_MMAXIPRIO,
+ [28] = IPRIO_MMAXIPRIO,
+ [27] = IPRIO_MMAXIPRIO,
+ [26] = IPRIO_MMAXIPRIO,
+ [25] = IPRIO_MMAXIPRIO,
+ [24] = IPRIO_MMAXIPRIO,
+
+ [47] = IPRIO_DEFAULT_UPPER,
+ [23] = IPRIO_DEFAULT_UPPER + 1,
+ [46] = IPRIO_DEFAULT_UPPER + 2,
+ [45] =

[PATCH 0/2] AIA draft v0.3.0 support for QEMU RISC-V

2022-06-15 Thread Anup Patel
The latest AIA draft v0.3.0 addresses comments from the architecture
review committee.
(Refer, https://github.com/riscv/riscv-aia/releases/tag/0.3.0-draft.31)

There are primarily two changes:
1) Removing various [m|s|vs]seteienum, [m|s|vs]clreienum, [m|s|vs]seteipnum,
   and [m|s|vs]clrei;num CSRs because these CSRs were mostly for software
   convienence.
2) Simplifying the default priority assignment for local interrupts

These patches can also be found in riscv_aia_update_v1 branch at:
https://github.com/avpatel/qemu.git

Corresponding changes in OpenSBI and Linux were small and these can be
found at:
 riscv_aia_update_v1 branch of https://github.com/avpatel/opensbi.git
 riscv_aia_v1 branch of https://github.com/avpatel/linux.git

Anup Patel (2):
  target/riscv: Remove CSRs that set/clear an IMSIC interrupt file bits
  target/riscv: Update default priority table for local interrupts

 target/riscv/cpu_bits.h   |  26 +--
 target/riscv/cpu_helper.c | 134 +-
 target/riscv/csr.c| 150 +-
 3 files changed, 72 insertions(+), 238 deletions(-)

-- 
2.34.1




[PATCH v6 0/4] QEMU RISC-V nested virtualization fixes

2022-06-11 Thread Anup Patel
This series does fixes and improvements to have nested virtualization
on QEMU RISC-V.

These patches can also be found in riscv_nested_fixes_v6 branch at:
https://github.com/avpatel/qemu.git

The RISC-V nested virtualization was tested on QEMU RISC-V using
Xvisor RISC-V which has required hypervisor support to run another
hypervisor as Guest/VM.

Changes since v5:
 - Correctly set "Addr. Offset" for misaligned load/store traps in PATCH3
 - Use offsetof() instead of pointer in PATCH4

Changes since v4:
 - Updated commit description in PATCH1, PATCH2, and PATCH4
 - Use "const" for local array in PATCH5

Changes since v3:
 - Updated PATCH3 to set special pseudoinstructions in htinst for
   guest page faults which result due to VS-stage page table walks
 - Updated warning message in PATCH4

Changes since v2:
 - Dropped the patch which are already in Alistair's next branch
 - Set "Addr. Offset" in the transformed instruction for PATCH3
 - Print warning in riscv_cpu_realize() if we are disabling an
   extension due to privilege spec verions mismatch for PATCH4

Changes since v1:
 - Set write_gva to env->two_stage_lookup which ensures that for
   HS-mode to HS-mode trap write_gva is true only for HLV/HSV
   instructions
 - Included "[PATCH 0/3] QEMU RISC-V priv spec version fixes"
   patches in this series for easy review
 - Re-worked PATCH7 to force disable extensions if required
   priv spec version is not staisfied
 - Added new PATCH8 to fix "aia=aplic-imsic" mode of virt machine

Anup Patel (4):
  target/riscv: Don't force update priv spec version to latest
  target/riscv: Add dummy mcountinhibit CSR for priv spec v1.11 or
higher
  target/riscv: Update [m|h]tinst CSR in riscv_cpu_do_interrupt()
  target/riscv: Force disable extensions if priv spec version does not
match

 target/riscv/cpu.c| 154 ---
 target/riscv/cpu.h|   3 +
 target/riscv/cpu_bits.h   |   3 +
 target/riscv/cpu_helper.c | 214 --
 target/riscv/csr.c|   2 +
 target/riscv/instmap.h|  45 
 6 files changed, 356 insertions(+), 65 deletions(-)

-- 
2.34.1




[PATCH v6 1/4] target/riscv: Don't force update priv spec version to latest

2022-06-11 Thread Anup Patel
The riscv_cpu_realize() sets priv spec version to v1.12 when it is
when "env->priv_ver == 0" (i.e. default v1.10) because the enum
value of priv spec v1.10 is zero.

Due to above issue, the sifive_u machine will see priv spec v1.12
instead of priv spec v1.10.

To fix this issue, we set latest priv spec version (i.e. v1.12)
for base rv64/rv32 cpu and riscv_cpu_realize() will override priv
spec version only when "cpu->cfg.priv_spec != NULL".

Fixes: 7100fe6c2441 ("target/riscv: Enable privileged spec version 1.12")
Signed-off-by: Anup Patel 
Reviewed-by: Frank Chang 
Reviewed-by: Alistair Francis 
Reviewed-by: Atish Patra 
Reviewed-by: Bin Meng 
---
 target/riscv/cpu.c | 12 
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 05e6521351..8db0f0bd49 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -173,6 +173,8 @@ static void rv64_base_cpu_init(Object *obj)
 /* We set this in the realise function */
 set_misa(env, MXL_RV64, 0);
 register_cpu_props(DEVICE(obj));
+/* Set latest version of privileged specification */
+set_priv_version(env, PRIV_VERSION_1_12_0);
 }
 
 static void rv64_sifive_u_cpu_init(Object *obj)
@@ -204,6 +206,8 @@ static void rv128_base_cpu_init(Object *obj)
 /* We set this in the realise function */
 set_misa(env, MXL_RV128, 0);
 register_cpu_props(DEVICE(obj));
+/* Set latest version of privileged specification */
+set_priv_version(env, PRIV_VERSION_1_12_0);
 }
 #else
 static void rv32_base_cpu_init(Object *obj)
@@ -212,6 +216,8 @@ static void rv32_base_cpu_init(Object *obj)
 /* We set this in the realise function */
 set_misa(env, MXL_RV32, 0);
 register_cpu_props(DEVICE(obj));
+/* Set latest version of privileged specification */
+set_priv_version(env, PRIV_VERSION_1_12_0);
 }
 
 static void rv32_sifive_u_cpu_init(Object *obj)
@@ -524,7 +530,7 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 CPURISCVState *env = >env;
 RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev);
 CPUClass *cc = CPU_CLASS(mcc);
-int priv_version = 0;
+int priv_version = -1;
 Error *local_err = NULL;
 
 cpu_exec_realizefn(cs, _err);
@@ -548,10 +554,8 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 }
 }
 
-if (priv_version) {
+if (priv_version >= PRIV_VERSION_1_10_0) {
 set_priv_version(env, priv_version);
-} else if (!env->priv_ver) {
-set_priv_version(env, PRIV_VERSION_1_12_0);
 }
 
 if (cpu->cfg.mmu) {
-- 
2.34.1




[PATCH v6 2/4] target/riscv: Add dummy mcountinhibit CSR for priv spec v1.11 or higher

2022-06-11 Thread Anup Patel
The mcountinhibit CSR is mandatory for priv spec v1.11 or higher. For
implementation that don't want to implement can simply have a dummy
mcountinhibit which is always zero.

Fixes: a4b2fa433125 ("target/riscv: Introduce privilege version field in the 
CSR ops.")
Signed-off-by: Anup Patel 
Reviewed-by: Frank Chang 
Reviewed-by: Alistair Francis 
Reviewed-by: Bin Meng 
---
 target/riscv/cpu_bits.h | 3 +++
 target/riscv/csr.c  | 2 ++
 2 files changed, 5 insertions(+)

diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 4d04b20d06..4a55c6a709 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -159,6 +159,9 @@
 #define CSR_MTVEC   0x305
 #define CSR_MCOUNTEREN  0x306
 
+/* Machine Counter Setup */
+#define CSR_MCOUNTINHIBIT   0x320
+
 /* 32-bit only */
 #define CSR_MSTATUSH0x310
 
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 6dbe9b541f..409a209f14 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -3391,6 +3391,8 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
 [CSR_MIE] = { "mie",any,   NULL,NULL,rmw_mie   
},
 [CSR_MTVEC]   = { "mtvec",  any,   read_mtvec,   write_mtvec   
},
 [CSR_MCOUNTEREN]  = { "mcounteren", any,   read_mcounteren,  
write_mcounteren  },
+[CSR_MCOUNTINHIBIT] = { "mcountinhibit", any, read_zero, write_ignore,
+ .min_priv_ver = 
PRIV_VERSION_1_11_0 },
 
 [CSR_MSTATUSH]= { "mstatush",   any32, read_mstatush,
write_mstatush},
 
-- 
2.34.1




[PATCH v6 4/4] target/riscv: Force disable extensions if priv spec version does not match

2022-06-11 Thread Anup Patel
We should disable extensions in riscv_cpu_realize() if minimum required
priv spec version is not satisfied. This also ensures that machines with
priv spec v1.11 (or lower) cannot enable H, V, and various multi-letter
extensions.

Fixes: a775398be2e9 ("target/riscv: Add isa extenstion strings to the device 
tree")
Signed-off-by: Anup Patel 
---
 target/riscv/cpu.c | 144 +++--
 1 file changed, 88 insertions(+), 56 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 8db0f0bd49..a17bc98662 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -43,9 +43,82 @@ static const char riscv_single_letter_exts[] = "IEMAFDQCPVH";
 
 struct isa_ext_data {
 const char *name;
-bool enabled;
+bool multi_letter;
+int min_version;
+int ext_enable_offset;
 };
 
+#define ISA_EXT_DATA_ENTRY(_name, _m_letter, _min_ver, _prop) \
+{#_name, _m_letter, _min_ver, offsetof(struct RISCVCPUConfig, _prop)}
+
+/**
+ * Here are the ordering rules of extension naming defined by RISC-V
+ * specification :
+ * 1. All extensions should be separated from other multi-letter extensions
+ *by an underscore.
+ * 2. The first letter following the 'Z' conventionally indicates the most
+ *closely related alphabetical extension category, IMAFDQLCBKJTPVH.
+ *If multiple 'Z' extensions are named, they should be ordered first
+ *by category, then alphabetically within a category.
+ * 3. Standard supervisor-level extensions (starts with 'S') should be
+ *listed after standard unprivileged extensions.  If multiple
+ *supervisor-level extensions are listed, they should be ordered
+ *alphabetically.
+ * 4. Non-standard extensions (starts with 'X') must be listed after all
+ *standard extensions. They must be separated from other multi-letter
+ *extensions by an underscore.
+ */
+static const struct isa_ext_data isa_edata_arr[] = {
+ISA_EXT_DATA_ENTRY(h, false, PRIV_VERSION_1_12_0, ext_h),
+ISA_EXT_DATA_ENTRY(v, false, PRIV_VERSION_1_12_0, ext_v),
+ISA_EXT_DATA_ENTRY(zicsr, true, PRIV_VERSION_1_10_0, ext_icsr),
+ISA_EXT_DATA_ENTRY(zifencei, true, PRIV_VERSION_1_10_0, ext_ifencei),
+ISA_EXT_DATA_ENTRY(zfh, true, PRIV_VERSION_1_12_0, ext_zfh),
+ISA_EXT_DATA_ENTRY(zfhmin, true, PRIV_VERSION_1_12_0, ext_zfhmin),
+ISA_EXT_DATA_ENTRY(zfinx, true, PRIV_VERSION_1_12_0, ext_zfinx),
+ISA_EXT_DATA_ENTRY(zdinx, true, PRIV_VERSION_1_12_0, ext_zdinx),
+ISA_EXT_DATA_ENTRY(zba, true, PRIV_VERSION_1_12_0, ext_zba),
+ISA_EXT_DATA_ENTRY(zbb, true, PRIV_VERSION_1_12_0, ext_zbb),
+ISA_EXT_DATA_ENTRY(zbc, true, PRIV_VERSION_1_12_0, ext_zbc),
+ISA_EXT_DATA_ENTRY(zbkb, true, PRIV_VERSION_1_12_0, ext_zbkb),
+ISA_EXT_DATA_ENTRY(zbkc, true, PRIV_VERSION_1_12_0, ext_zbkc),
+ISA_EXT_DATA_ENTRY(zbkx, true, PRIV_VERSION_1_12_0, ext_zbkx),
+ISA_EXT_DATA_ENTRY(zbs, true, PRIV_VERSION_1_12_0, ext_zbs),
+ISA_EXT_DATA_ENTRY(zk, true, PRIV_VERSION_1_12_0, ext_zk),
+ISA_EXT_DATA_ENTRY(zkn, true, PRIV_VERSION_1_12_0, ext_zkn),
+ISA_EXT_DATA_ENTRY(zknd, true, PRIV_VERSION_1_12_0, ext_zknd),
+ISA_EXT_DATA_ENTRY(zkne, true, PRIV_VERSION_1_12_0, ext_zkne),
+ISA_EXT_DATA_ENTRY(zknh, true, PRIV_VERSION_1_12_0, ext_zknh),
+ISA_EXT_DATA_ENTRY(zkr, true, PRIV_VERSION_1_12_0, ext_zkr),
+ISA_EXT_DATA_ENTRY(zks, true, PRIV_VERSION_1_12_0, ext_zks),
+ISA_EXT_DATA_ENTRY(zksed, true, PRIV_VERSION_1_12_0, ext_zksed),
+ISA_EXT_DATA_ENTRY(zksh, true, PRIV_VERSION_1_12_0, ext_zksh),
+ISA_EXT_DATA_ENTRY(zkt, true, PRIV_VERSION_1_12_0, ext_zkt),
+ISA_EXT_DATA_ENTRY(zve32f, true, PRIV_VERSION_1_12_0, ext_zve32f),
+ISA_EXT_DATA_ENTRY(zve64f, true, PRIV_VERSION_1_12_0, ext_zve64f),
+ISA_EXT_DATA_ENTRY(zhinx, true, PRIV_VERSION_1_12_0, ext_zhinx),
+ISA_EXT_DATA_ENTRY(zhinxmin, true, PRIV_VERSION_1_12_0, ext_zhinxmin),
+ISA_EXT_DATA_ENTRY(svinval, true, PRIV_VERSION_1_12_0, ext_svinval),
+ISA_EXT_DATA_ENTRY(svnapot, true, PRIV_VERSION_1_12_0, ext_svnapot),
+ISA_EXT_DATA_ENTRY(svpbmt, true, PRIV_VERSION_1_12_0, ext_svpbmt),
+};
+
+static bool isa_ext_is_enabled(RISCVCPU *cpu,
+   const struct isa_ext_data *edata)
+{
+bool *ext_enabled = (void *)>cfg + edata->ext_enable_offset;
+
+return *ext_enabled;
+}
+
+static void isa_ext_update_enabled(RISCVCPU *cpu,
+   const struct isa_ext_data *edata, bool en)
+{
+bool *ext_enabled = (void *)>cfg + edata->ext_enable_offset;
+
+*ext_enabled = en;
+}
+
 const char * const riscv_int_regnames[] = {
   "x0/zero", "x1/ra",  "x2/sp",  "x3/gp",  "x4/tp",  "x5/t0",   "x6/t1",
   "x7/t2",   "x8/s0",  "x9/s1",  "x10/a0", "x11/a1", "x12/a2",  "x13/a3",
@@ -530,7 +603,7 @@ static void riscv_cpu_realize(De

[PATCH v6 3/4] target/riscv: Update [m|h]tinst CSR in riscv_cpu_do_interrupt()

2022-06-11 Thread Anup Patel
We should write transformed instruction encoding of the trapped
instruction in [m|h]tinst CSR at time of taking trap as defined
by the RISC-V privileged specification v1.12.

Signed-off-by: Anup Patel 
---
 target/riscv/cpu.h|   3 +
 target/riscv/cpu_helper.c | 214 --
 target/riscv/instmap.h|  45 
 3 files changed, 256 insertions(+), 6 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 7d6397acdf..cac9e1876c 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -271,6 +271,9 @@ struct CPUArchState {
 /* Signals whether the current exception occurred with two-stage address
translation active. */
 bool two_stage_lookup;
+/* Signals whether the current exception occurred while doing two-stage
+   address translation for the VS-stage page table walk. */
+bool two_stage_indirect_lookup;
 
 target_ulong scounteren;
 target_ulong mcounteren;
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 4a6700c890..3c8ebecf84 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -22,6 +22,7 @@
 #include "qemu/main-loop.h"
 #include "cpu.h"
 #include "exec/exec-all.h"
+#include "instmap.h"
 #include "tcg/tcg-op.h"
 #include "trace.h"
 #include "semihosting/common-semi.h"
@@ -1057,7 +1058,8 @@ restart:
 
 static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
 MMUAccessType access_type, bool pmp_violation,
-bool first_stage, bool two_stage)
+bool first_stage, bool two_stage,
+bool two_stage_indirect)
 {
 CPUState *cs = env_cpu(env);
 int page_fault_exceptions, vm;
@@ -1107,6 +1109,7 @@ static void raise_mmu_exception(CPURISCVState *env, 
target_ulong address,
 }
 env->badaddr = address;
 env->two_stage_lookup = two_stage;
+env->two_stage_indirect_lookup = two_stage_indirect;
 }
 
 hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
@@ -1152,6 +1155,7 @@ void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr 
physaddr,
 env->badaddr = addr;
 env->two_stage_lookup = riscv_cpu_virt_enabled(env) ||
 riscv_cpu_two_stage_lookup(mmu_idx);
+env->two_stage_indirect_lookup = false;
 cpu_loop_exit_restore(cs, retaddr);
 }
 
@@ -1177,6 +1181,7 @@ void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr 
addr,
 env->badaddr = addr;
 env->two_stage_lookup = riscv_cpu_virt_enabled(env) ||
 riscv_cpu_two_stage_lookup(mmu_idx);
+env->two_stage_indirect_lookup = false;
 cpu_loop_exit_restore(cs, retaddr);
 }
 
@@ -1192,6 +1197,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int 
size,
 bool pmp_violation = false;
 bool first_stage_error = true;
 bool two_stage_lookup = false;
+bool two_stage_indirect_error = false;
 int ret = TRANSLATE_FAIL;
 int mode = mmu_idx;
 /* default TLB page size */
@@ -1229,6 +1235,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int 
size,
  */
 if (ret == TRANSLATE_G_STAGE_FAIL) {
 first_stage_error = false;
+two_stage_indirect_error = true;
 access_type = MMU_DATA_LOAD;
 }
 
@@ -1312,12 +1319,182 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, 
int size,
 raise_mmu_exception(env, address, access_type, pmp_violation,
 first_stage_error,
 riscv_cpu_virt_enabled(env) ||
-riscv_cpu_two_stage_lookup(mmu_idx));
+riscv_cpu_two_stage_lookup(mmu_idx),
+two_stage_indirect_error);
 cpu_loop_exit_restore(cs, retaddr);
 }
 
 return true;
 }
+
+static target_ulong riscv_transformed_insn(CPURISCVState *env,
+   target_ulong insn,
+   bool addr_offset_nonzero,
+   target_ulong taddr)
+{
+target_ulong xinsn = 0, xinsn_access_bits = 0;
+
+/*
+ * Only Quadrant 0 and Quadrant 2 of RVC instruction space need to
+ * be uncompressed. The Quadrant 1 of RVC instruction space need
+ * not be transformed because these instructions won't generate
+ * any load/store trap.
+ */
+
+if ((insn & 0x3) != 0x3) {
+/* Transform 16bit instruction into 32bit instruction */
+switch (GET_C_OP(insn)) {
+case OPC_RISC_C_OP_QUAD0: /* Quadrant 0 */
+switch (GET_C_FUNC(insn)) {
+case OPC_RISC_C_FUNC_FLD_LQ:
+if (riscv_cpu_xlen(env) != 128) { /* C.FLD (RV32/64) */
+xinsn = OPC_RISC_FLD;
+  

Re: [PATCH v5 3/4] target/riscv: Update [m|h]tinst CSR in riscv_cpu_do_interrupt()

2022-06-10 Thread Anup Patel
On Fri, Jun 10, 2022 at 5:20 PM dramforever  wrote:
>
> >
> >> In addition, the various V-extension vector load/store instructions do not 
> >> have
> >> defined transformations, so they should show up in [m|h]tinst as all zeros.
> > Okay, I will update.
> Just a clarification/suggestion: It might be easier to only write non-zero for
> instructions with currently defined transformation. Writing zero is always
> legal, but writing an undefined transformed instruction is not.
> >>> @@ -1355,18 +1558,31 @@ void riscv_cpu_do_interrupt(CPUState *cs)
> >>>  if (!async) {
> >>>  /* set tval to badaddr for traps with address information */
> >>>  switch (cause) {
> >>> -case RISCV_EXCP_INST_GUEST_PAGE_FAULT:
> >>>  case RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT:
> >>>  case RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT:
> >>> -case RISCV_EXCP_INST_ADDR_MIS:
> >>> -case RISCV_EXCP_INST_ACCESS_FAULT:
> >>>  case RISCV_EXCP_LOAD_ADDR_MIS:
> >>>  case RISCV_EXCP_STORE_AMO_ADDR_MIS:
> >>>  case RISCV_EXCP_LOAD_ACCESS_FAULT:
> >>>  case RISCV_EXCP_STORE_AMO_ACCESS_FAULT:
> >>> -case RISCV_EXCP_INST_PAGE_FAULT:
> >>>  case RISCV_EXCP_LOAD_PAGE_FAULT:
> >>>  case RISCV_EXCP_STORE_PAGE_FAULT:
> >>> +write_gva = env->two_stage_lookup;
> >>> +tval = env->badaddr;
> >>> +if (env->two_stage_indirect_lookup) {
> >>> +/*
> >>> + * special pseudoinstruction for G-stage fault taken 
> >>> while
> >>> + * doing VS-stage page table walk.
> >>> + */
> >>> +tinst = (riscv_cpu_xlen(env) == 32) ? 0x2000 : 
> >>> 0x3000;
> >>> +} else {
> >>> +/* transformed instruction for all other load/store 
> >>> faults */
> >>> +tinst = riscv_transformed_insn(env, env->bins);
> >>> +}
> >>> +break;
> >>> +case RISCV_EXCP_INST_GUEST_PAGE_FAULT:
> >>> +case RISCV_EXCP_INST_ADDR_MIS:
> >>> +case RISCV_EXCP_INST_ACCESS_FAULT:
> >>> +case RISCV_EXCP_INST_PAGE_FAULT:
> >>>  write_gva = env->two_stage_lookup;
> >>>  tval = env->badaddr;
> >>>  break;
> >> Instruction guest-page faults should set [m|h]tinst to one of the
> >> pseudoinstructions if env->two_stage_lookup is true. Otherwise it should 
> >> set
> >> [m|h]tinst to zero.
> >>
> >> In any case, as this seems to be one of the first implementations of
> >> [m|h]tinst, it might be worthwhile to confirm with the spec authors and 
> >> clarify
> >> any unclear bits before this gets released.
> > This is already handled because tinst is initialized to zero.
>
> If an instruction guest-page fault occurs due to a G-stage fault while doing
> VS-stage page table walk, i.e. env->two_stage_indirect_lookup is true (I had
> mistakenly wrote env->two_stage_lookup earlier), and the faulting guest
> physical address (env->guest_phys_fault_addr) is written to mtval2/htval,
> [m|h]tinst must be a pseudoinstruction and not zero. This case is not handled
> in the v5 patch.

The v5 patch is writing pseudoinstruction in [m|h]tinst when
env->two_stage_indirect_lookup is true.

Regards,
Anup



Re: [PATCH v5 3/4] target/riscv: Update [m|h]tinst CSR in riscv_cpu_do_interrupt()

2022-06-10 Thread Anup Patel
On Fri, Jun 10, 2022 at 3:00 PM dramforever  wrote:
>
> Hi Anup Patel,
>
> I think there are some misunderstandings of the privileged spec with regards 
> to
> [m|h]tinst handling. Here are some possible issues I've found:
>
> > +case OPC_RISC_C_FUNC_FLD_LQ:
> > +if (riscv_cpu_xlen(env) != 128) { /* C.FLD (RV32/64) */
> > +xinsn = OPC_RISC_FLD;
> > +xinsn = SET_RD(xinsn, GET_C_RS2S(insn));
> > +xinsn = SET_RS1(xinsn, GET_C_RS1S(insn));
> > +xinsn = SET_I_IMM(xinsn, GET_C_LD_IMM(insn));
> > +xinsn_has_addr_offset = true;
> > +}
> > +break;
>
> The privileged spec requires that 'for basic loads and stores, the
> transformations replace the instruction’s immediate offset fields with zero',
> so this SET_I_IMM() line isn't necessary. Similarly for all the compressed
> instruction cases, the SET_I_IMM() and SET_S_IMM() calls are all unnecessary.

Sure, I will update.

>
> > +} else {
> > +/* No need to transform 32bit (or wider) instructions */
> > +xinsn = insn;
>
> For AMO, lr, sc, and hypervisor load/store instructions, this is fine. But as
> above, 32-bit integer load/store instructions and floating point load/store
> instructions need have their immediate fields cleared to zero.

Okay, I will update.

>
> In addition, the various V-extension vector load/store instructions do not 
> have
> defined transformations, so they should show up in [m|h]tinst as all zeros.

Okay, I will update.

>
> > +if (xinsn_has_addr_offset) {
> > +/*
> > + * The "Addr. Offset" field in transformed instruction is non-zero
> > + * only for misaligned load/store traps which are very unlikely on
> > + * QEMU so for now always set "Addr. Offset" to zero.
> > + */
> > +xinsn = SET_RS1(xinsn, 0);
> > +}
>
> There seems to be two misconceptions here:
>
> Firstly, QEMU *does* raise address misaligned exceptions for misaligned atomic
> accesses.
>
> However, if I understood correctly, the address misaligned exceptions are
> irrelevant here because 'Addr. Offset' is only non-zero for a misaligned
> accesses that faults but *not* due to an address misaligned exception.
>
> For example, if an ld instruction reads 8 bytes starting from 0xa00ffe, and 
> the
> page 0xa0 to 0xa00fff is mapped, but 0xa01000 to 0xa01fff is not, a load
> page fault is raised with [m|s]tval = 0xa01000, while the original virtual
> address of the access is 0xa00ffe. The 'Addr. Offset' in this case is 2, i.e.
> the difference calculated with (0xa01000 - 0xa00ffe). This means that we *do*
> have to set 'Addr. Offset' *because* we handle some misaligned load/store
> instructions.

Well, I am aware of how "Addr. Offset" field is set but I was not aware that
QEMU generates misaligned exception in a specific case (i.e. misaligned
atomic).

I will update this patch to

>
> > @@ -1355,18 +1558,31 @@ void riscv_cpu_do_interrupt(CPUState *cs)
> >  if (!async) {
> >  /* set tval to badaddr for traps with address information */
> >  switch (cause) {
> > -case RISCV_EXCP_INST_GUEST_PAGE_FAULT:
> >  case RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT:
> >  case RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT:
> > -case RISCV_EXCP_INST_ADDR_MIS:
> > -case RISCV_EXCP_INST_ACCESS_FAULT:
> >  case RISCV_EXCP_LOAD_ADDR_MIS:
> >  case RISCV_EXCP_STORE_AMO_ADDR_MIS:
> >  case RISCV_EXCP_LOAD_ACCESS_FAULT:
> >  case RISCV_EXCP_STORE_AMO_ACCESS_FAULT:
> > -case RISCV_EXCP_INST_PAGE_FAULT:
> >  case RISCV_EXCP_LOAD_PAGE_FAULT:
> >  case RISCV_EXCP_STORE_PAGE_FAULT:
> > +write_gva = env->two_stage_lookup;
> > +tval = env->badaddr;
> > +if (env->two_stage_indirect_lookup) {
> > +/*
> > + * special pseudoinstruction for G-stage fault taken while
> > + * doing VS-stage page table walk.
> > + */
> > +tinst = (riscv_cpu_xlen(env) == 32) ? 0x2000 : 
> > 0x3000;
> > +} else {
> > +/* transformed instruction for all other load/store faults 
> > */
> > +tinst = riscv_transformed_insn(env, env->bins);
> > +}
> > +break;
> > +case RISCV_EXCP_INST_GUEST_PAGE_FAULT:
> > +case RISCV_EXCP_INST_A

Re: [PATCH v4 4/4] target/riscv: Force disable extensions if priv spec version does not match

2022-06-09 Thread Anup Patel
On Thu, Jun 9, 2022 at 7:28 PM Richard Henderson
 wrote:
>
> On 6/8/22 20:16, Anup Patel wrote:
> > On Wed, Jun 8, 2022 at 10:23 PM Richard Henderson
> >  wrote:
> >>
> >> On 6/8/22 09:14, Anup Patel wrote:
> >>> +struct isa_ext_data isa_edata_arr[] = {
> >>
> >> static const?
> >
> > Using const is fine but we can't use "static const" because
> > the "struct isa_ext_data" has a pointer to ext_xyz which
> > is different for each CPU.
>
> Ah, I see.  Perhaps better to use offsetof then -- the data structure is not 
> small...

I agree. Using offsetof() is a much better approach.

Thanks,
Anup

>
>
> r~



[PATCH v5 4/4] target/riscv: Force disable extensions if priv spec version does not match

2022-06-08 Thread Anup Patel
We should disable extensions in riscv_cpu_realize() if minimum required
priv spec version is not satisfied. This also ensures that machines with
priv spec v1.11 (or lower) cannot enable H, V, and various multi-letter
extensions.

Fixes: a775398be2e9 ("target/riscv: Add isa extenstion strings to the device 
tree")
Signed-off-by: Anup Patel 
---
 target/riscv/cpu.c | 57 ++
 1 file changed, 52 insertions(+), 5 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 9f9c27a3f5..e7eb65d708 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -43,9 +43,13 @@ static const char riscv_single_letter_exts[] = "IEMAFDQCPVH";
 
 struct isa_ext_data {
 const char *name;
-bool enabled;
+int min_version;
+bool *enabled;
 };
 
+#define ISA_EDATA_ENTRY(name, prop) {#name, PRIV_VERSION_1_10_0, 
>cfg.prop}
+#define ISA_EDATA_ENTRY2(name, min_ver, prop) {#name, min_ver, >cfg.prop}
+
 const char * const riscv_int_regnames[] = {
   "x0/zero", "x1/ra",  "x2/sp",  "x3/gp",  "x4/tp",  "x5/t0",   "x6/t1",
   "x7/t2",   "x8/s0",  "x9/s1",  "x10/a0", "x11/a1", "x12/a2",  "x13/a3",
@@ -513,8 +517,42 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 CPURISCVState *env = >env;
 RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev);
 CPUClass *cc = CPU_CLASS(mcc);
-int priv_version = -1;
+int i, priv_version = -1;
 Error *local_err = NULL;
+const struct isa_ext_data isa_edata_arr[] = {
+ISA_EDATA_ENTRY2(h, PRIV_VERSION_1_12_0, ext_h),
+ISA_EDATA_ENTRY2(v, PRIV_VERSION_1_12_0, ext_v),
+ISA_EDATA_ENTRY2(zicsr, PRIV_VERSION_1_10_0, ext_icsr),
+ISA_EDATA_ENTRY2(zifencei, PRIV_VERSION_1_10_0, ext_ifencei),
+ISA_EDATA_ENTRY2(zfh, PRIV_VERSION_1_12_0, ext_zfh),
+ISA_EDATA_ENTRY2(zfhmin, PRIV_VERSION_1_12_0, ext_zfhmin),
+ISA_EDATA_ENTRY2(zfinx, PRIV_VERSION_1_12_0, ext_zfinx),
+ISA_EDATA_ENTRY2(zdinx, PRIV_VERSION_1_12_0, ext_zdinx),
+ISA_EDATA_ENTRY2(zba, PRIV_VERSION_1_12_0, ext_zba),
+ISA_EDATA_ENTRY2(zbb, PRIV_VERSION_1_12_0, ext_zbb),
+ISA_EDATA_ENTRY2(zbc, PRIV_VERSION_1_12_0, ext_zbc),
+ISA_EDATA_ENTRY2(zbkb, PRIV_VERSION_1_12_0, ext_zbkb),
+ISA_EDATA_ENTRY2(zbkc, PRIV_VERSION_1_12_0, ext_zbkc),
+ISA_EDATA_ENTRY2(zbkx, PRIV_VERSION_1_12_0, ext_zbkx),
+ISA_EDATA_ENTRY2(zbs, PRIV_VERSION_1_12_0, ext_zbs),
+ISA_EDATA_ENTRY2(zk, PRIV_VERSION_1_12_0, ext_zk),
+ISA_EDATA_ENTRY2(zkn, PRIV_VERSION_1_12_0, ext_zkn),
+ISA_EDATA_ENTRY2(zknd, PRIV_VERSION_1_12_0, ext_zknd),
+ISA_EDATA_ENTRY2(zkne, PRIV_VERSION_1_12_0, ext_zkne),
+ISA_EDATA_ENTRY2(zknh, PRIV_VERSION_1_12_0, ext_zknh),
+ISA_EDATA_ENTRY2(zkr, PRIV_VERSION_1_12_0, ext_zkr),
+ISA_EDATA_ENTRY2(zks, PRIV_VERSION_1_12_0, ext_zks),
+ISA_EDATA_ENTRY2(zksed, PRIV_VERSION_1_12_0, ext_zksed),
+ISA_EDATA_ENTRY2(zksh, PRIV_VERSION_1_12_0, ext_zksh),
+ISA_EDATA_ENTRY2(zkt, PRIV_VERSION_1_12_0, ext_zkt),
+ISA_EDATA_ENTRY2(zve32f, PRIV_VERSION_1_12_0, ext_zve32f),
+ISA_EDATA_ENTRY2(zve64f, PRIV_VERSION_1_12_0, ext_zve64f),
+ISA_EDATA_ENTRY2(zhinx, PRIV_VERSION_1_12_0, ext_zhinx),
+ISA_EDATA_ENTRY2(zhinxmin, PRIV_VERSION_1_12_0, ext_zhinxmin),
+ISA_EDATA_ENTRY2(svinval, PRIV_VERSION_1_12_0, ext_svinval),
+ISA_EDATA_ENTRY2(svnapot, PRIV_VERSION_1_12_0, ext_svnapot),
+ISA_EDATA_ENTRY2(svpbmt, PRIV_VERSION_1_12_0, ext_svpbmt),
+};
 
 cpu_exec_realizefn(cs, _err);
 if (local_err != NULL) {
@@ -541,6 +579,17 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 set_priv_version(env, priv_version);
 }
 
+/* Force disable extensions if priv spec version does not match */
+for (i = 0; i < ARRAY_SIZE(isa_edata_arr); i++) {
+if (*isa_edata_arr[i].enabled &&
+(env->priv_ver < isa_edata_arr[i].min_version)) {
+*isa_edata_arr[i].enabled = false;
+warn_report("disabling %s extension for hart 0x%lx because "
+"privilege spec version does not match",
+isa_edata_arr[i].name, (unsigned long)env->mhartid);
+}
+}
+
 if (cpu->cfg.mmu) {
 riscv_set_feature(env, RISCV_FEATURE_MMU);
 }
@@ -1011,8 +1060,6 @@ static void riscv_cpu_class_init(ObjectClass *c, void 
*data)
 device_class_set_props(dc, riscv_cpu_properties);
 }
 
-#define ISA_EDATA_ENTRY(name, prop) {#name, cpu->cfg.prop}
-
 static void riscv_isa_string_ext(RISCVCPU *cpu, char **isa_str, int 
max_str_len)
 {
 char *old = *isa_str;
@@ -1071,7 +1118,7 @@ static void riscv_isa_string_ext(RISCVCPU *cpu, c

[PATCH v5 3/4] target/riscv: Update [m|h]tinst CSR in riscv_cpu_do_interrupt()

2022-06-08 Thread Anup Patel
We should write transformed instruction encoding of the trapped
instruction in [m|h]tinst CSR at time of taking trap as defined
by the RISC-V privileged specification v1.12.

Signed-off-by: Anup Patel 
---
 target/riscv/cpu.h|   3 +
 target/riscv/cpu_helper.c | 231 +-
 target/riscv/instmap.h|  43 +++
 3 files changed, 271 insertions(+), 6 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 194a58d760..11726e9031 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -271,6 +271,9 @@ struct CPUArchState {
 /* Signals whether the current exception occurred with two-stage address
translation active. */
 bool two_stage_lookup;
+/* Signals whether the current exception occurred while doing two-stage
+   address translation for the VS-stage page table walk. */
+bool two_stage_indirect_lookup;
 
 target_ulong scounteren;
 target_ulong mcounteren;
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 16c6045459..62a6762617 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -22,6 +22,7 @@
 #include "qemu/main-loop.h"
 #include "cpu.h"
 #include "exec/exec-all.h"
+#include "instmap.h"
 #include "tcg/tcg-op.h"
 #include "trace.h"
 #include "semihosting/common-semi.h"
@@ -1055,7 +1056,8 @@ restart:
 
 static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
 MMUAccessType access_type, bool pmp_violation,
-bool first_stage, bool two_stage)
+bool first_stage, bool two_stage,
+bool two_stage_indirect)
 {
 CPUState *cs = env_cpu(env);
 int page_fault_exceptions, vm;
@@ -1105,6 +1107,7 @@ static void raise_mmu_exception(CPURISCVState *env, 
target_ulong address,
 }
 env->badaddr = address;
 env->two_stage_lookup = two_stage;
+env->two_stage_indirect_lookup = two_stage_indirect;
 }
 
 hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
@@ -1150,6 +1153,7 @@ void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr 
physaddr,
 env->badaddr = addr;
 env->two_stage_lookup = riscv_cpu_virt_enabled(env) ||
 riscv_cpu_two_stage_lookup(mmu_idx);
+env->two_stage_indirect_lookup = false;
 cpu_loop_exit_restore(cs, retaddr);
 }
 
@@ -1175,6 +1179,7 @@ void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr 
addr,
 env->badaddr = addr;
 env->two_stage_lookup = riscv_cpu_virt_enabled(env) ||
 riscv_cpu_two_stage_lookup(mmu_idx);
+env->two_stage_indirect_lookup = false;
 cpu_loop_exit_restore(cs, retaddr);
 }
 
@@ -1190,6 +1195,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int 
size,
 bool pmp_violation = false;
 bool first_stage_error = true;
 bool two_stage_lookup = false;
+bool two_stage_indirect_error = false;
 int ret = TRANSLATE_FAIL;
 int mode = mmu_idx;
 /* default TLB page size */
@@ -1227,6 +1233,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int 
size,
  */
 if (ret == TRANSLATE_G_STAGE_FAIL) {
 first_stage_error = false;
+two_stage_indirect_error = true;
 access_type = MMU_DATA_LOAD;
 }
 
@@ -1310,12 +1317,207 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, 
int size,
 raise_mmu_exception(env, address, access_type, pmp_violation,
 first_stage_error,
 riscv_cpu_virt_enabled(env) ||
-riscv_cpu_two_stage_lookup(mmu_idx));
+riscv_cpu_two_stage_lookup(mmu_idx),
+two_stage_indirect_error);
 cpu_loop_exit_restore(cs, retaddr);
 }
 
 return true;
 }
+
+static target_ulong riscv_transformed_insn(CPURISCVState *env,
+   target_ulong insn)
+{
+bool xinsn_has_addr_offset = false;
+target_ulong xinsn = 0;
+
+/*
+ * Only Quadrant 0 and Quadrant 2 of RVC instruction space need to
+ * be uncompressed. The Quadrant 1 of RVC instruction space need
+ * not be transformed because these instructions won't generate
+ * any load/store trap.
+ */
+
+if ((insn & 0x3) != 0x3) {
+/* Transform 16bit instruction into 32bit instruction */
+switch (GET_C_OP(insn)) {
+case OPC_RISC_C_OP_QUAD0: /* Quadrant 0 */
+switch (GET_C_FUNC(insn)) {
+case OPC_RISC_C_FUNC_FLD_LQ:
+if (riscv_cpu_xlen(env) != 128) { /* C.FLD (RV32/64) */
+xinsn = OPC_RISC_FLD;
+xinsn = SET_RD(xinsn, GET_C_RS2S(insn));
+xinsn = SET_RS1(xinsn, GET_C_RS1S(insn));
+  

[PATCH v5 0/4] QEMU RISC-V nested virtualization fixes

2022-06-08 Thread Anup Patel
This series does fixes and improvements to have nested virtualization
on QEMU RISC-V.

These patches can also be found in riscv_nested_fixes_v5 branch at:
https://github.com/avpatel/qemu.git

The RISC-V nested virtualization was tested on QEMU RISC-V using
Xvisor RISC-V which has required hypervisor support to run another
hypervisor as Guest/VM.

Changes since 4:
 - Updated commit description in PATCH1, PATCH2, and PATCH4
 - Use "const" for local array in PATCH5

Changes since v3:
 - Updated PATCH3 to set special pseudoinstructions in htinst for
   guest page faults which result due to VS-stage page table walks
 - Updated warning message in PATCH4

Changes since v2:
 - Dropped the patch which are already in Alistair's next branch
 - Set "Addr. Offset" in the transformed instruction for PATCH3
 - Print warning in riscv_cpu_realize() if we are disabling an
   extension due to privilege spec verions mismatch for PATCH4

Changes since v1:
 - Set write_gva to env->two_stage_lookup which ensures that for
   HS-mode to HS-mode trap write_gva is true only for HLV/HSV
   instructions
 - Included "[PATCH 0/3] QEMU RISC-V priv spec version fixes"
   patches in this series for easy review
 - Re-worked PATCH7 to force disable extensions if required
   priv spec version is not staisfied
 - Added new PATCH8 to fix "aia=aplic-imsic" mode of virt machine

Anup Patel (4):
  target/riscv: Don't force update priv spec version to latest
  target/riscv: Add dummy mcountinhibit CSR for priv spec v1.11 or
higher
  target/riscv: Update [m|h]tinst CSR in riscv_cpu_do_interrupt()
  target/riscv: Force disable extensions if priv spec version does not
match

 target/riscv/cpu.c|  65 +--
 target/riscv/cpu.h|   3 +
 target/riscv/cpu_bits.h   |   3 +
 target/riscv/cpu_helper.c | 231 +-
 target/riscv/csr.c|   2 +
 target/riscv/instmap.h|  43 +++
 6 files changed, 333 insertions(+), 14 deletions(-)

-- 
2.34.1




[PATCH v5 1/4] target/riscv: Don't force update priv spec version to latest

2022-06-08 Thread Anup Patel
The riscv_cpu_realize() sets priv spec version to v1.12 when it is
when "env->priv_ver == 0" (i.e. default v1.10) because the enum
value of priv spec v1.10 is zero.

Due to above issue, the sifive_u machine will see priv spec v1.12
instead of priv spec v1.10.

To fix this issue, we set latest priv spec version (i.e. v1.12)
for base rv64/rv32 cpu and riscv_cpu_realize() will override priv
spec version only when "cpu->cfg.priv_spec != NULL".

Fixes: 7100fe6c2441 ("target/riscv: Enable privileged spec version 1.12")
Signed-off-by: Anup Patel 
Reviewed-by: Frank Chang 
Reviewed-by: Alistair Francis 
Reviewed-by: Atish Patra 
Reviewed-by: Bin Meng 
---
 target/riscv/cpu.c | 10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 0497af45cc..9f9c27a3f5 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -169,6 +169,8 @@ static void rv64_base_cpu_init(Object *obj)
 CPURISCVState *env = _CPU(obj)->env;
 /* We set this in the realise function */
 set_misa(env, MXL_RV64, 0);
+/* Set latest version of privileged specification */
+set_priv_version(env, PRIV_VERSION_1_12_0);
 }
 
 static void rv64_sifive_u_cpu_init(Object *obj)
@@ -204,6 +206,8 @@ static void rv32_base_cpu_init(Object *obj)
 CPURISCVState *env = _CPU(obj)->env;
 /* We set this in the realise function */
 set_misa(env, MXL_RV32, 0);
+/* Set latest version of privileged specification */
+set_priv_version(env, PRIV_VERSION_1_12_0);
 }
 
 static void rv32_sifive_u_cpu_init(Object *obj)
@@ -509,7 +513,7 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 CPURISCVState *env = >env;
 RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev);
 CPUClass *cc = CPU_CLASS(mcc);
-int priv_version = 0;
+int priv_version = -1;
 Error *local_err = NULL;
 
 cpu_exec_realizefn(cs, _err);
@@ -533,10 +537,8 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 }
 }
 
-if (priv_version) {
+if (priv_version >= PRIV_VERSION_1_10_0) {
 set_priv_version(env, priv_version);
-} else if (!env->priv_ver) {
-set_priv_version(env, PRIV_VERSION_1_12_0);
 }
 
 if (cpu->cfg.mmu) {
-- 
2.34.1




[PATCH v5 2/4] target/riscv: Add dummy mcountinhibit CSR for priv spec v1.11 or higher

2022-06-08 Thread Anup Patel
The mcountinhibit CSR is mandatory for priv spec v1.11 or higher. For
implementation that don't want to implement can simply have a dummy
mcountinhibit which is always zero.

Fixes: a4b2fa433125 ("target/riscv: Introduce privilege version field in the 
CSR ops.")
Signed-off-by: Anup Patel 
Reviewed-by: Frank Chang 
Reviewed-by: Alistair Francis 
Reviewed-by: Bin Meng 
---
 target/riscv/cpu_bits.h | 3 +++
 target/riscv/csr.c  | 2 ++
 2 files changed, 5 insertions(+)

diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 4d04b20d06..4a55c6a709 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -159,6 +159,9 @@
 #define CSR_MTVEC   0x305
 #define CSR_MCOUNTEREN  0x306
 
+/* Machine Counter Setup */
+#define CSR_MCOUNTINHIBIT   0x320
+
 /* 32-bit only */
 #define CSR_MSTATUSH0x310
 
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 6dbe9b541f..409a209f14 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -3391,6 +3391,8 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
 [CSR_MIE] = { "mie",any,   NULL,NULL,rmw_mie   
},
 [CSR_MTVEC]   = { "mtvec",  any,   read_mtvec,   write_mtvec   
},
 [CSR_MCOUNTEREN]  = { "mcounteren", any,   read_mcounteren,  
write_mcounteren  },
+[CSR_MCOUNTINHIBIT] = { "mcountinhibit", any, read_zero, write_ignore,
+ .min_priv_ver = 
PRIV_VERSION_1_11_0 },
 
 [CSR_MSTATUSH]= { "mstatush",   any32, read_mstatush,
write_mstatush},
 
-- 
2.34.1




Re: [PATCH v4 4/4] target/riscv: Force disable extensions if priv spec version does not match

2022-06-08 Thread Anup Patel
On Wed, Jun 8, 2022 at 10:23 PM Richard Henderson
 wrote:
>
> On 6/8/22 09:14, Anup Patel wrote:
> > +struct isa_ext_data isa_edata_arr[] = {
>
> static const?

Using const is fine but we can't use "static const" because
the "struct isa_ext_data" has a pointer to ext_xyz which
is different for each CPU.

Regards,
Anup

>
>
> r~



[PATCH v4 4/4] target/riscv: Force disable extensions if priv spec version does not match

2022-06-08 Thread Anup Patel
We should disable extensions in riscv_cpu_realize() if minimum required
priv spec version is not satisfied. This also ensures that machines with
priv spec v1.11 (or lower) cannot enable H, V, and various multi-letter
extensions.

Fixes: a775398be2e ("target/riscv: Add isa extenstion strings to the
device tree")
Signed-off-by: Anup Patel 
---
 target/riscv/cpu.c | 57 ++
 1 file changed, 52 insertions(+), 5 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 9f9c27a3f5..953ba2e445 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -43,9 +43,13 @@ static const char riscv_single_letter_exts[] = "IEMAFDQCPVH";
 
 struct isa_ext_data {
 const char *name;
-bool enabled;
+int min_version;
+bool *enabled;
 };
 
+#define ISA_EDATA_ENTRY(name, prop) {#name, PRIV_VERSION_1_10_0, 
>cfg.prop}
+#define ISA_EDATA_ENTRY2(name, min_ver, prop) {#name, min_ver, >cfg.prop}
+
 const char * const riscv_int_regnames[] = {
   "x0/zero", "x1/ra",  "x2/sp",  "x3/gp",  "x4/tp",  "x5/t0",   "x6/t1",
   "x7/t2",   "x8/s0",  "x9/s1",  "x10/a0", "x11/a1", "x12/a2",  "x13/a3",
@@ -513,8 +517,42 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 CPURISCVState *env = >env;
 RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev);
 CPUClass *cc = CPU_CLASS(mcc);
-int priv_version = -1;
+int i, priv_version = -1;
 Error *local_err = NULL;
+struct isa_ext_data isa_edata_arr[] = {
+ISA_EDATA_ENTRY2(h, PRIV_VERSION_1_12_0, ext_h),
+ISA_EDATA_ENTRY2(v, PRIV_VERSION_1_12_0, ext_v),
+ISA_EDATA_ENTRY2(zicsr, PRIV_VERSION_1_10_0, ext_icsr),
+ISA_EDATA_ENTRY2(zifencei, PRIV_VERSION_1_10_0, ext_ifencei),
+ISA_EDATA_ENTRY2(zfh, PRIV_VERSION_1_12_0, ext_zfh),
+ISA_EDATA_ENTRY2(zfhmin, PRIV_VERSION_1_12_0, ext_zfhmin),
+ISA_EDATA_ENTRY2(zfinx, PRIV_VERSION_1_12_0, ext_zfinx),
+ISA_EDATA_ENTRY2(zdinx, PRIV_VERSION_1_12_0, ext_zdinx),
+ISA_EDATA_ENTRY2(zba, PRIV_VERSION_1_12_0, ext_zba),
+ISA_EDATA_ENTRY2(zbb, PRIV_VERSION_1_12_0, ext_zbb),
+ISA_EDATA_ENTRY2(zbc, PRIV_VERSION_1_12_0, ext_zbc),
+ISA_EDATA_ENTRY2(zbkb, PRIV_VERSION_1_12_0, ext_zbkb),
+ISA_EDATA_ENTRY2(zbkc, PRIV_VERSION_1_12_0, ext_zbkc),
+ISA_EDATA_ENTRY2(zbkx, PRIV_VERSION_1_12_0, ext_zbkx),
+ISA_EDATA_ENTRY2(zbs, PRIV_VERSION_1_12_0, ext_zbs),
+ISA_EDATA_ENTRY2(zk, PRIV_VERSION_1_12_0, ext_zk),
+ISA_EDATA_ENTRY2(zkn, PRIV_VERSION_1_12_0, ext_zkn),
+ISA_EDATA_ENTRY2(zknd, PRIV_VERSION_1_12_0, ext_zknd),
+ISA_EDATA_ENTRY2(zkne, PRIV_VERSION_1_12_0, ext_zkne),
+ISA_EDATA_ENTRY2(zknh, PRIV_VERSION_1_12_0, ext_zknh),
+ISA_EDATA_ENTRY2(zkr, PRIV_VERSION_1_12_0, ext_zkr),
+ISA_EDATA_ENTRY2(zks, PRIV_VERSION_1_12_0, ext_zks),
+ISA_EDATA_ENTRY2(zksed, PRIV_VERSION_1_12_0, ext_zksed),
+ISA_EDATA_ENTRY2(zksh, PRIV_VERSION_1_12_0, ext_zksh),
+ISA_EDATA_ENTRY2(zkt, PRIV_VERSION_1_12_0, ext_zkt),
+ISA_EDATA_ENTRY2(zve32f, PRIV_VERSION_1_12_0, ext_zve32f),
+ISA_EDATA_ENTRY2(zve64f, PRIV_VERSION_1_12_0, ext_zve64f),
+ISA_EDATA_ENTRY2(zhinx, PRIV_VERSION_1_12_0, ext_zhinx),
+ISA_EDATA_ENTRY2(zhinxmin, PRIV_VERSION_1_12_0, ext_zhinxmin),
+ISA_EDATA_ENTRY2(svinval, PRIV_VERSION_1_12_0, ext_svinval),
+ISA_EDATA_ENTRY2(svnapot, PRIV_VERSION_1_12_0, ext_svnapot),
+ISA_EDATA_ENTRY2(svpbmt, PRIV_VERSION_1_12_0, ext_svpbmt),
+};
 
 cpu_exec_realizefn(cs, _err);
 if (local_err != NULL) {
@@ -541,6 +579,17 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 set_priv_version(env, priv_version);
 }
 
+/* Force disable extensions if priv spec version does not match */
+for (i = 0; i < ARRAY_SIZE(isa_edata_arr); i++) {
+if (*isa_edata_arr[i].enabled &&
+(env->priv_ver < isa_edata_arr[i].min_version)) {
+*isa_edata_arr[i].enabled = false;
+warn_report("disabling %s extension for hart 0x%lx because "
+"privilege spec version does not match",
+isa_edata_arr[i].name, (unsigned long)env->mhartid);
+}
+}
+
 if (cpu->cfg.mmu) {
 riscv_set_feature(env, RISCV_FEATURE_MMU);
 }
@@ -1011,8 +1060,6 @@ static void riscv_cpu_class_init(ObjectClass *c, void 
*data)
 device_class_set_props(dc, riscv_cpu_properties);
 }
 
-#define ISA_EDATA_ENTRY(name, prop) {#name, cpu->cfg.prop}
-
 static void riscv_isa_string_ext(RISCVCPU *cpu, char **isa_str, int 
max_str_len)
 {
 char *old = *isa_str;
@@ -1071,7 +1118,7 @@ static void riscv_isa_string_ext(RISCVCPU *cpu, char 
**isa_str, int ma

[PATCH v4 3/4] target/riscv: Update [m|h]tinst CSR in riscv_cpu_do_interrupt()

2022-06-08 Thread Anup Patel
We should write transformed instruction encoding of the trapped
instruction in [m|h]tinst CSR at time of taking trap as defined
by the RISC-V privileged specification v1.12.

Signed-off-by: Anup Patel 
---
 target/riscv/cpu.h|   3 +
 target/riscv/cpu_helper.c | 231 +-
 target/riscv/instmap.h|  43 +++
 3 files changed, 271 insertions(+), 6 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 194a58d760..11726e9031 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -271,6 +271,9 @@ struct CPUArchState {
 /* Signals whether the current exception occurred with two-stage address
translation active. */
 bool two_stage_lookup;
+/* Signals whether the current exception occurred while doing two-stage
+   address translation for the VS-stage page table walk. */
+bool two_stage_indirect_lookup;
 
 target_ulong scounteren;
 target_ulong mcounteren;
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 16c6045459..62a6762617 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -22,6 +22,7 @@
 #include "qemu/main-loop.h"
 #include "cpu.h"
 #include "exec/exec-all.h"
+#include "instmap.h"
 #include "tcg/tcg-op.h"
 #include "trace.h"
 #include "semihosting/common-semi.h"
@@ -1055,7 +1056,8 @@ restart:
 
 static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
 MMUAccessType access_type, bool pmp_violation,
-bool first_stage, bool two_stage)
+bool first_stage, bool two_stage,
+bool two_stage_indirect)
 {
 CPUState *cs = env_cpu(env);
 int page_fault_exceptions, vm;
@@ -1105,6 +1107,7 @@ static void raise_mmu_exception(CPURISCVState *env, 
target_ulong address,
 }
 env->badaddr = address;
 env->two_stage_lookup = two_stage;
+env->two_stage_indirect_lookup = two_stage_indirect;
 }
 
 hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
@@ -1150,6 +1153,7 @@ void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr 
physaddr,
 env->badaddr = addr;
 env->two_stage_lookup = riscv_cpu_virt_enabled(env) ||
 riscv_cpu_two_stage_lookup(mmu_idx);
+env->two_stage_indirect_lookup = false;
 cpu_loop_exit_restore(cs, retaddr);
 }
 
@@ -1175,6 +1179,7 @@ void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr 
addr,
 env->badaddr = addr;
 env->two_stage_lookup = riscv_cpu_virt_enabled(env) ||
 riscv_cpu_two_stage_lookup(mmu_idx);
+env->two_stage_indirect_lookup = false;
 cpu_loop_exit_restore(cs, retaddr);
 }
 
@@ -1190,6 +1195,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int 
size,
 bool pmp_violation = false;
 bool first_stage_error = true;
 bool two_stage_lookup = false;
+bool two_stage_indirect_error = false;
 int ret = TRANSLATE_FAIL;
 int mode = mmu_idx;
 /* default TLB page size */
@@ -1227,6 +1233,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int 
size,
  */
 if (ret == TRANSLATE_G_STAGE_FAIL) {
 first_stage_error = false;
+two_stage_indirect_error = true;
 access_type = MMU_DATA_LOAD;
 }
 
@@ -1310,12 +1317,207 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, 
int size,
 raise_mmu_exception(env, address, access_type, pmp_violation,
 first_stage_error,
 riscv_cpu_virt_enabled(env) ||
-riscv_cpu_two_stage_lookup(mmu_idx));
+riscv_cpu_two_stage_lookup(mmu_idx),
+two_stage_indirect_error);
 cpu_loop_exit_restore(cs, retaddr);
 }
 
 return true;
 }
+
+static target_ulong riscv_transformed_insn(CPURISCVState *env,
+   target_ulong insn)
+{
+bool xinsn_has_addr_offset = false;
+target_ulong xinsn = 0;
+
+/*
+ * Only Quadrant 0 and Quadrant 2 of RVC instruction space need to
+ * be uncompressed. The Quadrant 1 of RVC instruction space need
+ * not be transformed because these instructions won't generate
+ * any load/store trap.
+ */
+
+if ((insn & 0x3) != 0x3) {
+/* Transform 16bit instruction into 32bit instruction */
+switch (GET_C_OP(insn)) {
+case OPC_RISC_C_OP_QUAD0: /* Quadrant 0 */
+switch (GET_C_FUNC(insn)) {
+case OPC_RISC_C_FUNC_FLD_LQ:
+if (riscv_cpu_xlen(env) != 128) { /* C.FLD (RV32/64) */
+xinsn = OPC_RISC_FLD;
+xinsn = SET_RD(xinsn, GET_C_RS2S(insn));
+xinsn = SET_RS1(xinsn, GET_C_RS1S(insn));
+  

[PATCH v4 0/4] QEMU RISC-V nested virtualization fixes

2022-06-08 Thread Anup Patel
This series does fixes and improvements to have nested virtualization
on QEMU RISC-V.

These patches can also be found in riscv_nested_fixes_v4 branch at:
https://github.com/avpatel/qemu.git

The RISC-V nested virtualization was tested on QEMU RISC-V using
Xvisor RISC-V which has required hypervisor support to run another
hypervisor as Guest/VM.

Changes since v3:
 - Updated PATCH3 to set special pseudoinstructions in htinst for
   guest page faults which result due to VS-stage page table walks
 - Updated warning message in PATCH4

Changes since v2:
 - Dropped the patch which are already in Alistair's next branch
 - Set "Addr. Offset" in the transformed instruction for PATCH3
 - Print warning in riscv_cpu_realize() if we are disabling an
   extension due to privilege spec verions mismatch for PATCH4

Changes since v1:
 - Set write_gva to env->two_stage_lookup which ensures that for
   HS-mode to HS-mode trap write_gva is true only for HLV/HSV
   instructions
 - Included "[PATCH 0/3] QEMU RISC-V priv spec version fixes"
   patches in this series for easy review
 - Re-worked PATCH7 to force disable extensions if required
   priv spec version is not staisfied
 - Added new PATCH8 to fix "aia=aplic-imsic" mode of virt machine

Anup Patel (4):
  target/riscv: Don't force update priv spec version to latest
  target/riscv: Add dummy mcountinhibit CSR for priv spec v1.11 or
higher
  target/riscv: Update [m|h]tinst CSR in riscv_cpu_do_interrupt()
  target/riscv: Force disable extensions if priv spec version does not
match

 target/riscv/cpu.c|  65 +--
 target/riscv/cpu.h|   3 +
 target/riscv/cpu_bits.h   |   3 +
 target/riscv/cpu_helper.c | 231 +-
 target/riscv/csr.c|   2 +
 target/riscv/instmap.h|  43 +++
 6 files changed, 333 insertions(+), 14 deletions(-)

-- 
2.34.1




[PATCH v4 2/4] target/riscv: Add dummy mcountinhibit CSR for priv spec v1.11 or higher

2022-06-08 Thread Anup Patel
The mcountinhibit CSR is mandatory for priv spec v1.11 or higher. For
implementation that don't want to implement can simply have a dummy
mcountinhibit which always zero.

Fixes: a4b2fa433125 ("target/riscv: Introduce privilege version field in
the CSR ops.")
Signed-off-by: Anup Patel 
Reviewed-by: Frank Chang 
Reviewed-by: Alistair Francis 
---
 target/riscv/cpu_bits.h | 3 +++
 target/riscv/csr.c  | 2 ++
 2 files changed, 5 insertions(+)

diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 4d04b20d06..4a55c6a709 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -159,6 +159,9 @@
 #define CSR_MTVEC   0x305
 #define CSR_MCOUNTEREN  0x306
 
+/* Machine Counter Setup */
+#define CSR_MCOUNTINHIBIT   0x320
+
 /* 32-bit only */
 #define CSR_MSTATUSH0x310
 
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 6dbe9b541f..409a209f14 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -3391,6 +3391,8 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
 [CSR_MIE] = { "mie",any,   NULL,NULL,rmw_mie   
},
 [CSR_MTVEC]   = { "mtvec",  any,   read_mtvec,   write_mtvec   
},
 [CSR_MCOUNTEREN]  = { "mcounteren", any,   read_mcounteren,  
write_mcounteren  },
+[CSR_MCOUNTINHIBIT] = { "mcountinhibit", any, read_zero, write_ignore,
+ .min_priv_ver = 
PRIV_VERSION_1_11_0 },
 
 [CSR_MSTATUSH]= { "mstatush",   any32, read_mstatush,
write_mstatush},
 
-- 
2.34.1




[PATCH v4 1/4] target/riscv: Don't force update priv spec version to latest

2022-06-08 Thread Anup Patel
The riscv_cpu_realize() sets priv spec verion to v1.12 when it is
when "env->priv_ver == 0" (i.e. default v1.10) because the enum
value of priv spec v1.10 is zero.

Due to above issue, the sifive_u machine will see priv spec v1.12
instead of priv spec v1.10.

To fix this issue, we set latest priv spec version (i.e. v1.12)
for base rv64/rv32 cpu and riscv_cpu_realize() will override priv
spec version only when "cpu->cfg.priv_spec != NULL".

Fixes: 7100fe6c2441 ("target/riscv: Enable privileged spec version 1.12")
Signed-off-by: Anup Patel 
Reviewed-by: Frank Chang 
Reviewed-by: Alistair Francis 
Reviewed-by: Atish Patra 
---
 target/riscv/cpu.c | 10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 0497af45cc..9f9c27a3f5 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -169,6 +169,8 @@ static void rv64_base_cpu_init(Object *obj)
 CPURISCVState *env = _CPU(obj)->env;
 /* We set this in the realise function */
 set_misa(env, MXL_RV64, 0);
+/* Set latest version of privileged specification */
+set_priv_version(env, PRIV_VERSION_1_12_0);
 }
 
 static void rv64_sifive_u_cpu_init(Object *obj)
@@ -204,6 +206,8 @@ static void rv32_base_cpu_init(Object *obj)
 CPURISCVState *env = _CPU(obj)->env;
 /* We set this in the realise function */
 set_misa(env, MXL_RV32, 0);
+/* Set latest version of privileged specification */
+set_priv_version(env, PRIV_VERSION_1_12_0);
 }
 
 static void rv32_sifive_u_cpu_init(Object *obj)
@@ -509,7 +513,7 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 CPURISCVState *env = >env;
 RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev);
 CPUClass *cc = CPU_CLASS(mcc);
-int priv_version = 0;
+int priv_version = -1;
 Error *local_err = NULL;
 
 cpu_exec_realizefn(cs, _err);
@@ -533,10 +537,8 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
**errp)
 }
 }
 
-if (priv_version) {
+if (priv_version >= PRIV_VERSION_1_10_0) {
 set_priv_version(env, priv_version);
-} else if (!env->priv_ver) {
-set_priv_version(env, PRIV_VERSION_1_12_0);
 }
 
 if (cpu->cfg.mmu) {
-- 
2.34.1




Re: [PATCH v3 3/4] target/riscv: Update [m|h]tinst CSR in riscv_cpu_do_interrupt()

2022-06-06 Thread Anup Patel
On Tue, Jun 7, 2022 at 8:31 AM Anup Patel  wrote:
>
> On Mon, Jun 6, 2022 at 7:23 AM Alistair Francis  wrote:
> >
> > On Mon, Jun 6, 2022 at 11:48 AM Alistair Francis  
> > wrote:
> > >
> > > On Thu, May 26, 2022 at 8:12 PM Anup Patel  
> > > wrote:
> > > >
> > > > We should write transformed instruction encoding of the trapped
> > > > instruction in [m|h]tinst CSR at time of taking trap as defined
> > > > by the RISC-V privileged specification v1.12.
> > > >
> > > > Signed-off-by: Anup Patel 
> > >
> > > Reviewed-by: Alistair Francis 
> >
> > Whoops, I thought there was another patch. This doesn't seem to
> > implemented the guest-page fault pseudoinstructions which can be
> > generated while doing VS-stage translation
>
> I did not understand. Which guest-page fault pseudo-instructions ?

Nevermind, I see what you meant. Let me check.

Regards,
Anup

>
> Regards,
> Anup
>
> >
> > Alistair
> >
> > >
> > > Alistair
> > >
> > > > ---
> > > >  target/riscv/cpu_helper.c | 210 +-
> > > >  target/riscv/instmap.h|  43 
> > > >  2 files changed, 249 insertions(+), 4 deletions(-)
> > > >
> > > > diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> > > > index d99fac9d2d..2a2b6776fb 100644
> > > > --- a/target/riscv/cpu_helper.c
> > > > +++ b/target/riscv/cpu_helper.c
> > > > @@ -22,6 +22,7 @@
> > > >  #include "qemu/main-loop.h"
> > > >  #include "cpu.h"
> > > >  #include "exec/exec-all.h"
> > > > +#include "instmap.h"
> > > >  #include "tcg/tcg-op.h"
> > > >  #include "trace.h"
> > > >  #include "semihosting/common-semi.h"
> > > > @@ -1316,6 +1317,200 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr 
> > > > address, int size,
> > > >
> > > >  return true;
> > > >  }
> > > > +
> > > > +static target_ulong riscv_transformed_insn(CPURISCVState *env,
> > > > +   target_ulong insn)
> > > > +{
> > > > +bool xinsn_has_addr_offset = false;
> > > > +target_ulong xinsn = 0;
> > > > +
> > > > +/*
> > > > + * Only Quadrant 0 and Quadrant 2 of RVC instruction space need to
> > > > + * be uncompressed. The Quadrant 1 of RVC instruction space need
> > > > + * not be transformed because these instructions won't generate
> > > > + * any load/store trap.
> > > > + */
> > > > +
> > > > +if ((insn & 0x3) != 0x3) {
> > > > +/* Transform 16bit instruction into 32bit instruction */
> > > > +switch (GET_C_OP(insn)) {
> > > > +case OPC_RISC_C_OP_QUAD0: /* Quadrant 0 */
> > > > +switch (GET_C_FUNC(insn)) {
> > > > +case OPC_RISC_C_FUNC_FLD_LQ:
> > > > +if (riscv_cpu_xlen(env) != 128) { /* C.FLD (RV32/64) */
> > > > +xinsn = OPC_RISC_FLD;
> > > > +xinsn = SET_RD(xinsn, GET_C_RS2S(insn));
> > > > +xinsn = SET_RS1(xinsn, GET_C_RS1S(insn));
> > > > +xinsn = SET_I_IMM(xinsn, GET_C_LD_IMM(insn));
> > > > +xinsn_has_addr_offset = true;
> > > > +}
> > > > +break;
> > > > +case OPC_RISC_C_FUNC_LW: /* C.LW */
> > > > +xinsn = OPC_RISC_LW;
> > > > +xinsn = SET_RD(xinsn, GET_C_RS2S(insn));
> > > > +xinsn = SET_RS1(xinsn, GET_C_RS1S(insn));
> > > > +xinsn = SET_I_IMM(xinsn, GET_C_LW_IMM(insn));
> > > > +xinsn_has_addr_offset = true;
> > > > +break;
> > > > +case OPC_RISC_C_FUNC_FLW_LD:
> > > > +if (riscv_cpu_xlen(env) == 32) { /* C.FLW (RV32) */
> > > > +xinsn = OPC_RISC_FLW;
> > > > +xinsn = SET_RD(xinsn, GET_C_RS2S(insn));
> > > > +xinsn = SET_RS1(xinsn, GET_C_RS1S(insn));
> > > > +xinsn = SET_I_IMM(xinsn, GET_C_LW_IMM(insn));
> > >

Re: [PATCH v3 4/4] target/riscv: Force disable extensions if priv spec version does not match

2022-06-06 Thread Anup Patel
On Mon, Jun 6, 2022 at 7:25 AM Alistair Francis  wrote:
>
> On Thu, May 26, 2022 at 8:09 PM Anup Patel  wrote:
> >
> > We should disable extensions in riscv_cpu_realize() if minimum required
> > priv spec version is not satisfied. This also ensures that machines with
> > priv spec v1.11 (or lower) cannot enable H, V, and various multi-letter
> > extensions.
> >
> > Fixes: a775398be2e ("target/riscv: Add isa extenstion strings to the
> > device tree")
> > Signed-off-by: Anup Patel 
> > ---
> >  target/riscv/cpu.c | 56 +-
> >  1 file changed, 51 insertions(+), 5 deletions(-)
> >
> > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> > index b086eb25da..e6e878ceb3 100644
> > --- a/target/riscv/cpu.c
> > +++ b/target/riscv/cpu.c
> > @@ -43,9 +43,13 @@ static const char riscv_single_letter_exts[] = 
> > "IEMAFDQCPVH";
> >
> >  struct isa_ext_data {
> >  const char *name;
> > -bool enabled;
> > +int min_version;
> > +bool *enabled;
> >  };
> >
> > +#define ISA_EDATA_ENTRY(name, prop) {#name, PRIV_VERSION_1_10_0, 
> > >cfg.prop}
> > +#define ISA_EDATA_ENTRY2(name, min_ver, prop) {#name, min_ver, 
> > >cfg.prop}
> > +
> >  const char * const riscv_int_regnames[] = {
> >"x0/zero", "x1/ra",  "x2/sp",  "x3/gp",  "x4/tp",  "x5/t0",   "x6/t1",
> >"x7/t2",   "x8/s0",  "x9/s1",  "x10/a0", "x11/a1", "x12/a2",  "x13/a3",
> > @@ -513,8 +517,42 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
> > **errp)
> >  CPURISCVState *env = >env;
> >  RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev);
> >  CPUClass *cc = CPU_CLASS(mcc);
> > -int priv_version = -1;
> > +int i, priv_version = -1;
> >  Error *local_err = NULL;
> > +struct isa_ext_data isa_edata_arr[] = {
> > +ISA_EDATA_ENTRY2(h, PRIV_VERSION_1_12_0, ext_h),
> > +ISA_EDATA_ENTRY2(v, PRIV_VERSION_1_12_0, ext_v),
> > +ISA_EDATA_ENTRY2(zicsr, PRIV_VERSION_1_10_0, ext_icsr),
> > +ISA_EDATA_ENTRY2(zifencei, PRIV_VERSION_1_10_0, ext_ifencei),
> > +ISA_EDATA_ENTRY2(zfh, PRIV_VERSION_1_12_0, ext_zfh),
> > +ISA_EDATA_ENTRY2(zfhmin, PRIV_VERSION_1_12_0, ext_zfhmin),
> > +ISA_EDATA_ENTRY2(zfinx, PRIV_VERSION_1_12_0, ext_zfinx),
> > +ISA_EDATA_ENTRY2(zdinx, PRIV_VERSION_1_12_0, ext_zdinx),
> > +ISA_EDATA_ENTRY2(zba, PRIV_VERSION_1_12_0, ext_zba),
> > +ISA_EDATA_ENTRY2(zbb, PRIV_VERSION_1_12_0, ext_zbb),
> > +ISA_EDATA_ENTRY2(zbc, PRIV_VERSION_1_12_0, ext_zbc),
> > +ISA_EDATA_ENTRY2(zbkb, PRIV_VERSION_1_12_0, ext_zbkb),
> > +ISA_EDATA_ENTRY2(zbkc, PRIV_VERSION_1_12_0, ext_zbkc),
> > +ISA_EDATA_ENTRY2(zbkx, PRIV_VERSION_1_12_0, ext_zbkx),
> > +ISA_EDATA_ENTRY2(zbs, PRIV_VERSION_1_12_0, ext_zbs),
> > +ISA_EDATA_ENTRY2(zk, PRIV_VERSION_1_12_0, ext_zk),
> > +ISA_EDATA_ENTRY2(zkn, PRIV_VERSION_1_12_0, ext_zkn),
> > +ISA_EDATA_ENTRY2(zknd, PRIV_VERSION_1_12_0, ext_zknd),
> > +ISA_EDATA_ENTRY2(zkne, PRIV_VERSION_1_12_0, ext_zkne),
> > +ISA_EDATA_ENTRY2(zknh, PRIV_VERSION_1_12_0, ext_zknh),
> > +ISA_EDATA_ENTRY2(zkr, PRIV_VERSION_1_12_0, ext_zkr),
> > +ISA_EDATA_ENTRY2(zks, PRIV_VERSION_1_12_0, ext_zks),
> > +ISA_EDATA_ENTRY2(zksed, PRIV_VERSION_1_12_0, ext_zksed),
> > +ISA_EDATA_ENTRY2(zksh, PRIV_VERSION_1_12_0, ext_zksh),
> > +ISA_EDATA_ENTRY2(zkt, PRIV_VERSION_1_12_0, ext_zkt),
> > +ISA_EDATA_ENTRY2(zve32f, PRIV_VERSION_1_12_0, ext_zve32f),
> > +ISA_EDATA_ENTRY2(zve64f, PRIV_VERSION_1_12_0, ext_zve64f),
> > +ISA_EDATA_ENTRY2(zhinx, PRIV_VERSION_1_12_0, ext_zhinx),
> > +ISA_EDATA_ENTRY2(zhinxmin, PRIV_VERSION_1_12_0, ext_zhinxmin),
> > +ISA_EDATA_ENTRY2(svinval, PRIV_VERSION_1_12_0, ext_svinval),
> > +ISA_EDATA_ENTRY2(svnapot, PRIV_VERSION_1_12_0, ext_svnapot),
> > +ISA_EDATA_ENTRY2(svpbmt, PRIV_VERSION_1_12_0, ext_svpbmt),
> > +};
> >
> >  cpu_exec_realizefn(cs, _err);
> >  if (local_err != NULL) {
> > @@ -541,6 +579,16 @@ static void riscv_cpu_realize(DeviceState *dev, Error 
> > **errp)
> >  set_priv_version(env, priv_version);
> >  }
> >
> > +/* Force disable extensions if priv spec version does not match */
> >

Re: [PATCH v3 3/4] target/riscv: Update [m|h]tinst CSR in riscv_cpu_do_interrupt()

2022-06-06 Thread Anup Patel
On Mon, Jun 6, 2022 at 7:23 AM Alistair Francis  wrote:
>
> On Mon, Jun 6, 2022 at 11:48 AM Alistair Francis  wrote:
> >
> > On Thu, May 26, 2022 at 8:12 PM Anup Patel  wrote:
> > >
> > > We should write transformed instruction encoding of the trapped
> > > instruction in [m|h]tinst CSR at time of taking trap as defined
> > > by the RISC-V privileged specification v1.12.
> > >
> > > Signed-off-by: Anup Patel 
> >
> > Reviewed-by: Alistair Francis 
>
> Whoops, I thought there was another patch. This doesn't seem to
> implemented the guest-page fault pseudoinstructions which can be
> generated while doing VS-stage translation

I did not understand. Which guest-page fault pseudo-instructions ?

Regards,
Anup

>
> Alistair
>
> >
> > Alistair
> >
> > > ---
> > >  target/riscv/cpu_helper.c | 210 +-
> > >  target/riscv/instmap.h|  43 
> > >  2 files changed, 249 insertions(+), 4 deletions(-)
> > >
> > > diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> > > index d99fac9d2d..2a2b6776fb 100644
> > > --- a/target/riscv/cpu_helper.c
> > > +++ b/target/riscv/cpu_helper.c
> > > @@ -22,6 +22,7 @@
> > >  #include "qemu/main-loop.h"
> > >  #include "cpu.h"
> > >  #include "exec/exec-all.h"
> > > +#include "instmap.h"
> > >  #include "tcg/tcg-op.h"
> > >  #include "trace.h"
> > >  #include "semihosting/common-semi.h"
> > > @@ -1316,6 +1317,200 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr 
> > > address, int size,
> > >
> > >  return true;
> > >  }
> > > +
> > > +static target_ulong riscv_transformed_insn(CPURISCVState *env,
> > > +   target_ulong insn)
> > > +{
> > > +bool xinsn_has_addr_offset = false;
> > > +target_ulong xinsn = 0;
> > > +
> > > +/*
> > > + * Only Quadrant 0 and Quadrant 2 of RVC instruction space need to
> > > + * be uncompressed. The Quadrant 1 of RVC instruction space need
> > > + * not be transformed because these instructions won't generate
> > > + * any load/store trap.
> > > + */
> > > +
> > > +if ((insn & 0x3) != 0x3) {
> > > +/* Transform 16bit instruction into 32bit instruction */
> > > +switch (GET_C_OP(insn)) {
> > > +case OPC_RISC_C_OP_QUAD0: /* Quadrant 0 */
> > > +switch (GET_C_FUNC(insn)) {
> > > +case OPC_RISC_C_FUNC_FLD_LQ:
> > > +if (riscv_cpu_xlen(env) != 128) { /* C.FLD (RV32/64) */
> > > +xinsn = OPC_RISC_FLD;
> > > +xinsn = SET_RD(xinsn, GET_C_RS2S(insn));
> > > +xinsn = SET_RS1(xinsn, GET_C_RS1S(insn));
> > > +xinsn = SET_I_IMM(xinsn, GET_C_LD_IMM(insn));
> > > +xinsn_has_addr_offset = true;
> > > +}
> > > +break;
> > > +case OPC_RISC_C_FUNC_LW: /* C.LW */
> > > +xinsn = OPC_RISC_LW;
> > > +xinsn = SET_RD(xinsn, GET_C_RS2S(insn));
> > > +xinsn = SET_RS1(xinsn, GET_C_RS1S(insn));
> > > +xinsn = SET_I_IMM(xinsn, GET_C_LW_IMM(insn));
> > > +xinsn_has_addr_offset = true;
> > > +break;
> > > +case OPC_RISC_C_FUNC_FLW_LD:
> > > +if (riscv_cpu_xlen(env) == 32) { /* C.FLW (RV32) */
> > > +xinsn = OPC_RISC_FLW;
> > > +xinsn = SET_RD(xinsn, GET_C_RS2S(insn));
> > > +xinsn = SET_RS1(xinsn, GET_C_RS1S(insn));
> > > +xinsn = SET_I_IMM(xinsn, GET_C_LW_IMM(insn));
> > > +xinsn_has_addr_offset = true;
> > > +} else { /* C.LD (RV64/RV128) */
> > > +xinsn = OPC_RISC_LD;
> > > +xinsn = SET_RD(xinsn, GET_C_RS2S(insn));
> > > +xinsn = SET_RS1(xinsn, GET_C_RS1S(insn));
> > > +xinsn = SET_I_IMM(xinsn, GET_C_LD_IMM(insn));
> > > +xinsn_has_addr_offset = true;
> > > +}
> > > +break;
> > > +case OPC_RISC_C_FUNC_FSD_SQ:
&

  1   2   3   4   5   6   7   >