:p
atchew
Login
From: Alistair Francis <alistair.francis@wdc.com> The following changes since commit f5a2438405d4ae8b62de7c9b39fac0b2155ee544: Merge tag 'pull-qapi-2026-05-21' of https://repo.or.cz/qemu/armbru into staging (2026-05-21 09:00:22 -0400) are available in the Git repository at: https://github.com/alistair23/qemu.git tags/pull-riscv-to-apply-20260522 for you to fetch changes up to b7d87fb10d53a918e9c4a3dfe1fb06ce42c52526: hw/riscv: riscv-iommu: Re-process command queue after clearing CMD_ILL (2026-05-22 09:59:21 +1000) ---------------------------------------------------------------- RISC-V PR for 11.1. * Remove spike as default machine * Deprecate the shakti_c machine * Set MISA.[C|X] based on the selected extensions * Update Maintainers for OpenSBI Firmware * Update OpenSBI to v1.8.1 * Avoid RISCVCPU copy in PMU FDT setup * A collection of specification compliance improvements * Fix Svnapot 64KB pages * Handle source overlap of vector widening reduction instructions * Check interrupt in SiFive UART after txctrl register is written * Fix medeleg[11] read-only zero bit for M-mode ECALL * Fix tail handling for vmv.s.x and vfmv.s.f * Update the local AIA interrupt mask * Add KVM support for Zicbop and BFloat16 extensions * Fix the IOMMU FSC SV32 capability check * Avoid caching PCI device IDs in the IOMMU * Implement Microchip mpfs ioscb PLLs and sysreg clock dividers * Remove the internal CPU riscv_cpu_* arrays * Fix IOCOUNTINH.CY toggle detection * Fix the read of pmpaddr(0-63) CSRs * Make hpmcounterh return the upper 32-bits * Minor fixes and enhancements of RISC-V AIA devices * Re-process IOMMU command queue after clearing CMD_ILL ---------------------------------------------------------------- Abhigyan Kumar (1): target/riscv: Fix medeleg[11] read-only zero bit for M-mode ECALL Alistair Francis (4): target/riscv: Remove spike as default machine target/riscv: Deprecate the shakti_c machine MAINTAINERS: Maintain OpenSBI Firmware target/riscv: Update the local interrupt mask Andrew Jones (1): hw/riscv/riscv-iommu: Fix Svnapot 64KB pages Anton Blanchard (1): target/riscv: rvv: Handle source overlap of vector widening reduction instructions Chengbo Gao (1): hw/riscv/riscv-iommu: Avoid caching PCI device IDs Daniel Henrique Barboza (16): roms/opensbi: Update to v1.8.1 target/riscv/cpu.c: add xlrbr isa_edata_arr[] entry target/riscv/cpu.c: fix smctr/ssctr isa_edata_arr[] order target/riscv: make riscv-qmp-cmds use isa_data_arr[] target/riscv/tcg: treat all exts equally in cpu_disable_priv_spec_isa_exts target/riscv/tcg: use only isa_edata_arr[] in cpu_cfg_ext_get_name() target/riscv/cpu.c: remove riscv_cpu_enable_named_feat() target/riscv: remove riscv_cpu_named_features[] target/riscv/tcg: use isa_edata_arr[] in riscv_cpu_update_misa_x() target/riscv/kvm: use isa_edata_arr[] for unavailable props target/riscv/tcg: use isa_edata_arr[] to enable max exts target/riscv/tcg: use cfg_offset as cpu_set_multi_ext cb opaque target/riscv: do not set defaults in cpu prop callback target/riscv/tcg: use isa_edata_arr[] to create user props target/riscv/cpu: remove riscv_cpu_* arrays target/riscv/csr.c: fix read of pmpaddr(0-63) CSRs Fangyu Yu (1): hw/riscv/riscv-iommu: Fix IOCOUNTINH.CY toggle detection Frank Chang (3): target/riscv: Update MISA.C for Zc* extensions target/riscv: Update MISA.X for non-standard extensions hw/char: Check interrupt after txctrl register is written Guenter Roeck (1): hw: misc: Implement Microchip mpfs ioscb PLLs and sysreg clock dividers Jay Chang (1): hw/riscv: riscv-iommu: Re-process command queue after clearing CMD_ILL Jim Shu (4): hw/intc: riscv_aplic: Fix level trigger IRQ in direct delivery mode hw/intc: riscv_aplic: Add reset API to APLIC hw/intc: riscv_imsic: Add reset API to IMSIC hw/intc: riscv_aplic: add trace events of APLIC read/write function Mohamed Ayman (1): riscv: virt: avoid RISCVCPU copy in PMU FDT setup Portia Stephens (1): target/riscv: Make hpmcounterh return the upper 32-bits Zishun Yi (9): target/riscv: Allow mseccfg access based on ext_zicfilp target/riscv: add Zvknha as an implied extension for Zvknhb target/riscv: Remove unconditional MENVCFG_CDE from mask target/riscv: Fix missing CDE check for scountinhibit target/riscv/pmp: Fix integer overflow in TOR and NA4 address computation target/riscv: Add mseccfg to VMStateDescription target/riscv: clear mseccfg on reset for all dependent extensions hw/riscv/riscv-iommu: fix FSC SV32 capability check hw/riscv/virt-acpi-build: Fix off-by-one error in RIMT ID mapping Zongmin Zhou (2): target/riscv/kvm: add KVM support for Zicbop extension target/riscv/kvm: Add BFloat16 extensions support chen.zhongyao@zte.com.cn (1): target/riscv: Fix tail handling for vmv.s.x and vfmv.s.f MAINTAINERS | 2 + docs/about/deprecated.rst | 21 +- docs/about/removed-features.rst | 14 ++ include/hw/misc/mchp_pfsoc_ioscb.h | 2 + target/riscv/cpu.h | 13 +- target/riscv/helper.h | 4 + hw/char/sifive_uart.c | 1 + hw/intc/riscv_aplic.c | 116 ++++++--- hw/intc/riscv_imsic.c | 19 ++ hw/misc/mchp_pfsoc_ioscb.c | 47 +++- hw/misc/mchp_pfsoc_sysreg.c | 13 + hw/riscv/riscv-iommu-hpm.c | 3 +- hw/riscv/riscv-iommu.c | 96 ++++++-- hw/riscv/shakti_c.c | 1 + hw/riscv/spike.c | 1 - hw/riscv/virt-acpi-build.c | 3 +- hw/riscv/virt.c | 4 +- target/riscv/cpu.c | 327 +++++++++---------------- target/riscv/csr.c | 36 ++- target/riscv/kvm/kvm-cpu.c | 62 +++-- target/riscv/machine.c | 20 ++ target/riscv/pmp.c | 4 +- target/riscv/riscv-qmp-cmds.c | 30 +-- target/riscv/tcg/tcg-cpu.c | 192 +++++++-------- target/riscv/vector_helper.c | 18 ++ target/riscv/insn_trans/trans_rvv.c.inc | 45 ++-- hw/intc/trace-events | 4 + pc-bios/opensbi-riscv32-generic-fw_dynamic.bin | Bin 268752 -> 270384 bytes pc-bios/opensbi-riscv64-generic-fw_dynamic.bin | Bin 273048 -> 275928 bytes roms/opensbi | 2 +- 30 files changed, 613 insertions(+), 487 deletions(-)
From: Alistair Francis <alistair.francis@wdc.com> In QEMU 10.0 we deprecated the default spike machine, let's finally remove spike as the default and require users to specify the machine. Signed-off-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com> Message-ID: <20260430052218.771358-2-alistair.francis@wdc.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- docs/about/deprecated.rst | 18 ------------------ docs/about/removed-features.rst | 14 ++++++++++++++ hw/riscv/spike.c | 1 - 3 files changed, 14 insertions(+), 19 deletions(-) diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index XXXXXXX..XXXXXXX 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -XXX,XX +XXX,XX @@ better reflects the way this property affects all random data within the device tree blob, not just the ``kaslr-seed`` node. -RISC-V default machine option (since 10.0) -'''''''''''''''''''''''''''''''''''''''''' - -RISC-V defines ``spike`` as the default machine if no machine option is -given in the command line. This happens because ``spike`` is the first -RISC-V machine implemented in QEMU and setting it as default was -convenient at that time. Now we have 7 riscv64 and 6 riscv32 machines -and having ``spike`` as a default is no longer justified. This default -will also promote situations where users think they're running ``virt`` -(the most used RISC-V machine type in 10.0) when in fact they're -running ``spike``. - -Removing the default machine option forces users to always set the machine -they want to use and avoids confusion. Existing users of the ``spike`` -machine must ensure that they're setting the ``spike`` machine in the -command line (``-M spike``). - - Backend options --------------- diff --git a/docs/about/removed-features.rst b/docs/about/removed-features.rst index XXXXXXX..XXXXXXX 100644 --- a/docs/about/removed-features.rst +++ b/docs/about/removed-features.rst @@ -XXX,XX +XXX,XX @@ firmware is available to boot it. It can be replaced by the ``ast2700fc``, another multi-SoC machine based on the newer AST2700 SoCs which are excepted to receive better support in the future. +RISC-V default machine (removed in 11.1) +'''''''''''''''''''''''''''''''''''''''' + +RISC-V used to define ``spike`` as the default machine if no machine option +was given via the command line. This happend because ``spike`` was the first +RISC-V machine implemented in QEMU and setting it as default was +convenient at that time. Now we have 7 riscv64 and 6 riscv32 machines +and having ``spike`` as a default is no longer justified. + +The default machine option has been removed, forcing users to always set the +machine they want to use to avoid confusion. Existing users of the ``spike`` +machine must ensure that they're setting the ``spike`` machine in the +command line (``-M spike``). + linux-user mode CPUs -------------------- diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/spike.c +++ b/hw/riscv/spike.c @@ -XXX,XX +XXX,XX @@ static void spike_machine_class_init(ObjectClass *oc, const void *data) mc->desc = "RISC-V Spike board"; mc->init = spike_board_init; mc->max_cpus = SPIKE_CPUS_MAX; - mc->is_default = true; mc->default_cpu_type = TYPE_RISCV_CPU_BASE; mc->possible_cpu_arch_ids = riscv_numa_possible_cpu_arch_ids; mc->cpu_index_to_instance_props = riscv_numa_cpu_index_to_props; -- 2.53.0
From: Alistair Francis <alistair.francis@wdc.com> The RISC-V shakti_c machine hasn't had meaningful contributions since 2021 and is currently unmaintained. The machine is scheduled to be removed as it appears to have no users. Signed-off-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com> Message-ID: <20260430052218.771358-3-alistair.francis@wdc.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- docs/about/deprecated.rst | 7 +++++++ hw/riscv/shakti_c.c | 1 + 2 files changed, 8 insertions(+) diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index XXXXXXX..XXXXXXX 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -XXX,XX +XXX,XX @@ deprecated; use the new name ``dtb-randomness`` instead. The new name better reflects the way this property affects all random data within the device tree blob, not just the ``kaslr-seed`` node. +RISC-V Shakti machine (since 11.1) +'''''''''''''''''''''''''''''''''' + +The RISC-V ``shakti_c`` machine hasn't had meaningful contributions since 2021 +and is currently unmaintained. The machine is scheduled to be removed as it +appears to have no users. + Backend options --------------- diff --git a/hw/riscv/shakti_c.c b/hw/riscv/shakti_c.c index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/shakti_c.c +++ b/hw/riscv/shakti_c.c @@ -XXX,XX +XXX,XX @@ static void shakti_c_machine_class_init(ObjectClass *klass, const void *data) mc->init = shakti_c_machine_state_init; mc->default_cpu_type = TYPE_RISCV_CPU_SHAKTI_C; mc->valid_cpu_types = valid_cpu_types; + mc->deprecation_reason = "Currently unmaintained with no known users"; mc->default_ram_id = "riscv.shakti.c.ram"; } -- 2.53.0
From: Frank Chang <frank.chang@sifive.com> MISA.C is set if the following extensions are selected: * Zca and not F. * Zca, Zcf and F (but not D) is specified (RV32 only). * Zca, Zcf and Zcd if D is specified (RV32 only). * Zca, Zcd if D is specified (RV64 only). Therefore, MISA.C must be set according to the Zc* extension rules. Warn the user if RVC is explicitly disabled but MISA.C is required by the rules above. Signed-off-by: Frank Chang <frank.chang@sifive.com> Reviewed-by: Max Chou <max.chou@sifive.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260424050509.3935180-2-frank.chang@sifive.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/tcg/tcg-cpu.c | 39 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_enable_implied_rules(RISCVCPU *cpu) } } +/* + * MISA.C is set if the following extensions are selected: + * - Zca and not F. + * - Zca, Zcf and F (but not D) is specified on RV32. + * - Zca, Zcf and Zcd if D is specified on RV32. + * - Zca, Zcd if D is specified on RV64. + */ +static void riscv_cpu_update_misa_c(RISCVCPU *cpu) +{ + CPURISCVState *env = &cpu->env; + bool set_misa_c = false; + + if (riscv_has_ext(env, RVC)) { + return; + } + + if (cpu->cfg.ext_zca && !riscv_has_ext(env, RVF)) { + set_misa_c = true; + } else if (riscv_cpu_mxl(env) == MXL_RV32 && + cpu->cfg.ext_zca && cpu->cfg.ext_zcf && + (riscv_has_ext(env, RVD) ? cpu->cfg.ext_zcd : + riscv_has_ext(env, RVF))) { + set_misa_c = true; + } else if (riscv_cpu_mxl(env) == MXL_RV64 && + cpu->cfg.ext_zca && cpu->cfg.ext_zcd) { + set_misa_c = true; + } + + if (set_misa_c) { + if (cpu_misa_ext_is_user_set(RVC)) { + warn_report("RVC mandated by Zca/Zcf/Zcd extensions"); + return; + } + + riscv_cpu_set_misa_ext(env, env->misa_ext | RVC); + } +} + void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp) { CPURISCVState *env = &cpu->env; @@ -XXX,XX +XXX,XX @@ void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp) riscv_cpu_init_implied_exts_rules(); riscv_cpu_enable_implied_rules(cpu); + riscv_cpu_update_misa_c(cpu); riscv_cpu_validate_misa_priv(env, &local_err); if (local_err != NULL) { -- 2.53.0
From: Frank Chang <frank.chang@sifive.com> MISA.X is set if there are any non-standard extensions. We should set MISA.X when any of the vendor extensions is enabled. Signed-off-by: Frank Chang <frank.chang@sifive.com> Reviewed-by: Max Chou <max.chou@sifive.com> Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260424050509.3935180-3-frank.chang@sifive.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.h | 1 + target/riscv/tcg/tcg-cpu.c | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -XXX,XX +XXX,XX @@ typedef struct CPUArchState CPURISCVState; #define RVH RV('H') #define RVG RV('G') #define RVB RV('B') +#define RVX RV('X') extern const uint32_t misa_bits[]; const char *riscv_get_misa_ext_name(uint32_t bit); diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_update_misa_c(RISCVCPU *cpu) } } +/* MISA.X is set when any of the non-standard extensions is enabled. */ +static void riscv_cpu_update_misa_x(RISCVCPU *cpu) +{ + CPURISCVState *env = &cpu->env; + const RISCVCPUMultiExtConfig *arr = riscv_cpu_vendor_exts; + + for (int i = 0; arr[i].name != NULL; i++) { + if (isa_ext_is_enabled(cpu, arr[i].offset)) { + riscv_cpu_set_misa_ext(env, env->misa_ext | RVX); + break; + } + } +} + void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp) { CPURISCVState *env = &cpu->env; @@ -XXX,XX +XXX,XX @@ void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp) riscv_cpu_init_implied_exts_rules(); riscv_cpu_enable_implied_rules(cpu); riscv_cpu_update_misa_c(cpu); + riscv_cpu_update_misa_x(cpu); riscv_cpu_validate_misa_priv(env, &local_err); if (local_err != NULL) { -- 2.53.0
From: Alistair Francis <alistair.francis@wdc.com> Mark the OpenSBI Firmware as maintained by me (Alistair Francis) and add Daniel Henrique Barboza as a reviewer. Signed-off-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-ID: <20260506234243.1873782-1-alistair.francis@wdc.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index XXXXXXX..XXXXXXX 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -XXX,XX +XXX,XX @@ S: Supported F: hw/i386/amd_iommu* OpenSBI Firmware +M: Alistair Francis <Alistair.Francis@wdc.com> +R: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> L: qemu-riscv@nongnu.org S: Supported F: pc-bios/opensbi-* -- 2.53.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Update OpenSBI and the pre-built opensbi32 and opensbi64 images to version 1.8.1. We're going for the intermediate/bug fix release 1.8.1 directly due to a PMP related fix that was impacting QEMU profile CPUs. Changelog for v1.8.1: * Typo fix in comments of sbi_hartindex_to_hartid() * Fix hart protection abstraction for platforms without PMP Changelog for v1.8 includes, among other things: - IPI device ratings - SiFive CLINT v2 support - SiFive PL2 cache controller driver - SiFive Extensible Cache (EC) driver - SiFive TMC0 based HSM driver - SiFive SMC0 based system suspend driver - MPXY RPMI mailbox driver for voltage service group - MPXY RPMI mailbox driver for device power service group - MPXY RPMI mailbox driver for performance service group Check out the full release log at [1] for more info. [1] https://github.com/riscv-software-src/opensbi/releases/tag/v1.8 Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260108160825.171794-1-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- .../opensbi-riscv32-generic-fw_dynamic.bin | Bin 268752 -> 270384 bytes .../opensbi-riscv64-generic-fw_dynamic.bin | Bin 273048 -> 275928 bytes roms/opensbi | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) diff --git a/pc-bios/opensbi-riscv32-generic-fw_dynamic.bin b/pc-bios/opensbi-riscv32-generic-fw_dynamic.bin index XXXXXXX..XXXXXXX 100644 Binary files a/pc-bios/opensbi-riscv32-generic-fw_dynamic.bin and b/pc-bios/opensbi-riscv32-generic-fw_dynamic.bin differ diff --git a/pc-bios/opensbi-riscv64-generic-fw_dynamic.bin b/pc-bios/opensbi-riscv64-generic-fw_dynamic.bin index XXXXXXX..XXXXXXX 100644 Binary files a/pc-bios/opensbi-riscv64-generic-fw_dynamic.bin and b/pc-bios/opensbi-riscv64-generic-fw_dynamic.bin differ diff --git a/roms/opensbi b/roms/opensbi index XXXXXXX..XXXXXXX 160000 --- a/roms/opensbi +++ b/roms/opensbi @@ -1 +1 @@ -Subproject commit a32a91069119e7a5aa31e6bc51d5e00860be3d80 +Subproject commit 74434f255873d74e56cc50aa762d1caf24c099f8 -- 2.53.0
From: Mohamed Ayman <mohamedaymanworkspace@gmail.com> Use a pointer to the hart instead of copying RISCVCPU when passing pmu_avail_ctrs to riscv_pmu_generate_fdt_node(). Signed-off-by: Mohamed Ayman <mohamedaymanworkspace@gmail.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260503180252.1122776-1-mohamedaymanworkspace@gmail.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/riscv/virt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -XXX,XX +XXX,XX @@ static void create_fdt_pmu(RISCVVirtState *s) { g_autofree char *pmu_name = g_strdup_printf("/pmu"); MachineState *ms = MACHINE(s); - RISCVCPU hart = s->soc[0].harts[0]; + RISCVCPU *hart = &s->soc[0].harts[0]; qemu_fdt_add_subnode(ms->fdt, pmu_name); qemu_fdt_setprop_string(ms->fdt, pmu_name, "compatible", "riscv,pmu"); - riscv_pmu_generate_fdt_node(ms->fdt, hart.pmu_avail_ctrs, pmu_name); + riscv_pmu_generate_fdt_node(ms->fdt, hart->pmu_avail_ctrs, pmu_name); } static void create_fdt_sockets(RISCVVirtState *s, -- 2.53.0
From: Zishun Yi <vulab@iscas.ac.cn> The Zicfilp extension adds the MLPE field to the mseccfg CSR. According to the RISC-V Privileged Specification, mseccfg exists if any extension that adds a field to it is implemented. Currently, the `have_mseccfg()` predicate function checks for Smepmp, Zkr, and Smmpm, but misses Zicfilp. As a result, if a CPU is configured with `zicfilp=true` but without the other extensions, accessing the mseccfg CSR will incorrectly raise an illegal instruction exception. This patch adds the missing check for `ext_zicfilp` to ensure the CSR is properly accessible when the Zicfilp extension is enabled. This issue was discovered and reported by SpecHunter, an AI-driven architecture specification analysis tool. Link: https://github.com/yizishun/rv-isa-sec/blob/master/output/riscv-isa-manual/pr-2561/qemu.txt Signed-off-by: Zishun Yi <vulab@iscas.ac.cn> Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260511072705.3015986-1-vulab@iscas.ac.cn> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/csr.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -XXX,XX +XXX,XX @@ static RISCVException have_mseccfg(CPURISCVState *env, int csrno) if (riscv_cpu_cfg(env)->ext_smmpm) { return RISCV_EXCP_NONE; } + if (riscv_cpu_cfg(env)->ext_zicfilp) { + return RISCV_EXCP_NONE; + } return RISCV_EXCP_ILLEGAL_INST; } -- 2.53.0
From: Andrew Jones <andrew.jones@oss.qualcomm.com> The Svnapot extension encodes a 64KB leaf PTE by setting PTE_N and storing bits [3:0] of the PPN as a NAPOT size indicator. The IOMMU model wasn't checking PTE_N and therefore was using the raw (NAPOT- encoded) PPN directly in the physical address, yielding an address 32 KB above the correct base. Fix both riscv_iommu_spa_fetch() and pdt_memory_read() by mirroring the Svnapot handling already present in target/riscv/cpu_helper.c: napot_bits = ctz64(ppn) + 1 /* 4 for 64KB */ napot_mask = (1 << napot_bits) - 1 /* 0xF */ phys_base = PPN_PHYS(ppn & ~napot_mask) page_offset = addr & (PPN_PHYS(napot_mask) | (TARGET_PAGE_SIZE - 1)) The spec only defines napot_bits == 4 (64KB); any other value is treated as a reserved encoding. This is a fix, rather than new feature support, because the spec says "IOMMU implementations must support the Svnapot standard extension for NAPOT Translation Contiguity." Fixes: 0c54acb8243d ("hw/riscv: add RISC-V IOMMU base emulation") Cc: qemu-stable@nongnu.org Signed-off-by: Andrew Jones <andrew.jones@oss.qualcomm.com> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Nutty Liu <nutty.liu@hotmail.com> Reviewed-by: Tomasz Jeznach <tjeznach@rivosinc.com> Message-ID: <20260508205129.377032-1-andrew.jones@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/riscv/riscv-iommu.c | 44 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/riscv-iommu.c +++ b/hw/riscv/riscv-iommu.c @@ -XXX,XX +XXX,XX @@ static bool riscv_iommu_msi_check(RISCVIOMMUState *s, RISCVIOMMUContext *ctx, return true; } +/* Returns the NAPOT page mask, or 0 for reserved encodings. */ +static hwaddr riscv_iommu_napot_page_mask(hwaddr ppn, hwaddr addr, hwaddr *out) +{ + int napot_bits = ctz64(ppn) + 1; + hwaddr napot_mask, page_mask; + + /* The spec only defines 64KB (napot_bits == 4) */ + if (napot_bits != 4) { + return 0; + } + + napot_mask = (1ULL << napot_bits) - 1; + page_mask = PPN_PHYS(napot_mask) | (TARGET_PAGE_SIZE - 1); + + *out = PPN_PHYS(ppn & ~napot_mask) | (addr & page_mask); + + return page_mask; +} + /* * RISCV IOMMU Address Translation Lookup - Page Table Walk * @@ -XXX,XX +XXX,XX @@ static int riscv_iommu_spa_fetch(RISCVIOMMUState *s, RISCVIOMMUContext *ctx, } else { /* Leaf PTE, translation completed. */ sc[pass].step = sc[pass].levels; - base = PPN_PHYS(ppn) | (addr & ((1ULL << va_skip) - 1)); - /* Update address mask based on smallest translation granularity */ - iotlb->addr_mask &= (1ULL << va_skip) - 1; + + if (pte & PTE_N) { + hwaddr mask = riscv_iommu_napot_page_mask(ppn, addr, &base); + + if (!mask) { + break; + } + iotlb->addr_mask &= mask; + } else { + base = PPN_PHYS(ppn) | (addr & ((1ULL << va_skip) - 1)); + /* Update address mask based on smallest translation granularity */ + iotlb->addr_mask &= (1ULL << va_skip) - 1; + } + /* Continue with S-Stage translation? */ if (pass && sc[0].step != sc[0].levels) { pass = S_STAGE; @@ -XXX,XX +XXX,XX @@ static MemTxResult pdt_memory_read(RISCVIOMMUState *s, return MEMTX_ACCESS_ERROR; /* Misaligned PPN */ } else { /* Leaf PTE, translation completed. */ - base = PPN_PHYS(ppn) | (addr & ((1ULL << va_skip) - 1)); + if (pte & PTE_N) { + if (!riscv_iommu_napot_page_mask(ppn, addr, &base)) { + return MEMTX_ACCESS_ERROR; + } + } else { + base = PPN_PHYS(ppn) | (addr & ((1ULL << va_skip) - 1)); + } break; } -- 2.53.0
From: Anton Blanchard <antonb@tenstorrent.com> Widening reductions read vs2 as a vector of SEW elements and vs1[0] as a scalar of 2*SEW. The ISA does not allow the same vector register to be read with different EEWs, so they must not overlap. vs1 is read as a scalar from element 0, so it is treated as a single vector register (independent of LMUL) when checking overlap. Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3208 Signed-off-by: Anton Blanchard <antonb@tenstorrent.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260417080328.31918-1-antonb@tenstorrent.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/insn_trans/trans_rvv.c.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -XXX,XX +XXX,XX @@ GEN_OPIVV_TRANS(vredxor_vs, reduction_check) static bool reduction_widen_check(DisasContext *s, arg_rmrr *a) { return reduction_check(s, a) && (s->sew < MO_64) && + !is_overlapped(a->rs1, 1, a->rs2, 1 << MAX(s->lmul, 0)) && ((s->sew + 1) <= (s->cfg_ptr->elen >> 4)); } -- 2.53.0
From: Frank Chang <frank.chang@sifive.com> It's possible that the transmit watermark level (txctrl.txcnt) is updated when the user writes to txctrl register, which may decrease the transmit watermark level to less than the number of entries in the transmit FIFO. In such a case, the interrupt should be raised so we need to call sifive_uart_update_irq() to check and update interrupt when txctrl register is written. Otherwise, the interrupt will have to be delayed until next TX FIFO transmission is processed. Suggested-by: Chao Liu <chao.liu.zevorn@gmail.com> Signed-off-by: Frank Chang <frank.chang@sifive.com> Reviewed-by: Jim Shu <jim.shu@sifive.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260513030503.3665414-1-frank.chang@sifive.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/char/sifive_uart.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/char/sifive_uart.c b/hw/char/sifive_uart.c index XXXXXXX..XXXXXXX 100644 --- a/hw/char/sifive_uart.c +++ b/hw/char/sifive_uart.c @@ -XXX,XX +XXX,XX @@ sifive_uart_write(void *opaque, hwaddr addr, if (SIFIVE_UART_TXEN(s->txctrl) && !fifo8_is_empty(&s->tx_fifo)) { sifive_uart_trigger_tx_fifo(s); } + sifive_uart_update_irq(s); return; case SIFIVE_UART_RXCTRL: s->rxctrl = val64; -- 2.53.0
From: Abhigyan Kumar <314abh@gmail.com> RISC-V Privileged Specification 3.1.8 (Machine Trap Delegation Registers (medeleg and mideleg)) mentions: "For exceptions that cannot occur in less privileged modes, the corresponding medeleg bits should be read-only zero. In particular, medeleg[11] is read-only zero." QEMU incorrectly included RISCV_EXCP_M_ECALL in DELEGABLE_EXCPS. It allowed the 11th bit to be written and read as set. Fixed by removing it from the DELEGABLE_EXCPS mask, adhering to the specification. Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3438 Signed-off-by: Abhigyan Kumar <314abh@gmail.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260427060849.749179-2-314abh@gmail.com> [ Changes by AF: - Remove comment ] Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/csr.c | 1 - 1 file changed, 1 deletion(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -XXX,XX +XXX,XX @@ static const uint64_t all_ints = M_MODE_INTERRUPTS | S_MODE_INTERRUPTS | (1ULL << (RISCV_EXCP_U_ECALL)) | \ (1ULL << (RISCV_EXCP_S_ECALL)) | \ (1ULL << (RISCV_EXCP_VS_ECALL)) | \ - (1ULL << (RISCV_EXCP_M_ECALL)) | \ (1ULL << (RISCV_EXCP_INST_PAGE_FAULT)) | \ (1ULL << (RISCV_EXCP_LOAD_PAGE_FAULT)) | \ (1ULL << (RISCV_EXCP_STORE_PAGE_FAULT)) | \ -- 2.53.0
From: "chen.zhongyao@zte.com.cn" <chen.zhongyao@zte.com.cn> The risc-v vector spec defines vmv.s.x and vfmv.s.f as writing element 0 of the destination register while the remaining destination elements follow the current tail policy. When QEMU runs with rvv_ta_all_1s enabled, those elements must therefore become all 1s. QEMU handled both instructions as translation-time special cases that directly wrote vd[0] and skipped the usual tail processing. As a result, vmv.s.x and vfmv.s.f left the remaining destination elements unchanged instead of applying the configured tail policy. Fix this by routing both instructions through a helper that writes vd[0] and then treats the rest of the destination register as tail, reusing the existing agnostic-element fill logic. Signed-off-by: Zhongyao Chen <chen.zhongyao@zte.com.cn> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <202605061005.646A537u037157@mse-fl1.zte.com.cn> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/helper.h | 4 +++ target/riscv/vector_helper.c | 18 ++++++++++ target/riscv/insn_trans/trans_rvv.c.inc | 44 ++++++++----------------- 3 files changed, 36 insertions(+), 30 deletions(-) diff --git a/target/riscv/helper.h b/target/riscv/helper.h index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/helper.h +++ b/target/riscv/helper.h @@ -XXX,XX +XXX,XX @@ DEF_HELPER_4(vmv_v_x_b, void, ptr, i64, env, i32) DEF_HELPER_4(vmv_v_x_h, void, ptr, i64, env, i32) DEF_HELPER_4(vmv_v_x_w, void, ptr, i64, env, i32) DEF_HELPER_4(vmv_v_x_d, void, ptr, i64, env, i32) +DEF_HELPER_4(vset_velem0_b, void, ptr, i64, env, i32) +DEF_HELPER_4(vset_velem0_h, void, ptr, i64, env, i32) +DEF_HELPER_4(vset_velem0_w, void, ptr, i64, env, i32) +DEF_HELPER_4(vset_velem0_d, void, ptr, i64, env, i32) DEF_HELPER_6(vsaddu_vv_b, void, ptr, ptr, ptr, ptr, env, i32) DEF_HELPER_6(vsaddu_vv_h, void, ptr, ptr, ptr, ptr, env, i32) diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/vector_helper.c +++ b/target/riscv/vector_helper.c @@ -XXX,XX +XXX,XX @@ GEN_VEXT_VMV_VX(vmv_v_x_h, int16_t, H2) GEN_VEXT_VMV_VX(vmv_v_x_w, int32_t, H4) GEN_VEXT_VMV_VX(vmv_v_x_d, int64_t, H8) +#define GEN_VEXT_SET_VELEM0(NAME, ETYPE, H) \ +void HELPER(NAME)(void *vd, uint64_t s1, CPURISCVState *env, \ + uint32_t desc) \ +{ \ + uint32_t esz = sizeof(ETYPE); \ + uint32_t vlenb = riscv_cpu_cfg(env)->vlenb; \ + uint32_t vta = vext_vta(desc); \ + \ + *((ETYPE *)vd + H(0)) = (ETYPE)s1; \ + /* Treat every element past vd[0] as tail for scalar-to-vector moves. */ \ + vext_set_elems_1s(vd, vta, esz, vlenb); \ +} + +GEN_VEXT_SET_VELEM0(vset_velem0_b, int8_t, H1) +GEN_VEXT_SET_VELEM0(vset_velem0_h, int16_t, H2) +GEN_VEXT_SET_VELEM0(vset_velem0_w, int32_t, H4) +GEN_VEXT_SET_VELEM0(vset_velem0_d, int64_t, H8) + #define GEN_VEXT_VMERGE_VV(NAME, ETYPE, H) \ void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \ CPURISCVState *env, uint32_t desc) \ diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -XXX,XX +XXX,XX @@ static void vec_element_loadi(DisasContext *s, TCGv_i64 dest, load_element(dest, tcg_env, endian_ofs(s, vreg, idx), s->sew, sign); } -/* Integer Scalar Move Instruction */ +typedef void gen_helper_vset_velem0(TCGv_ptr, TCGv_i64, TCGv_env, TCGv_i32); -static void store_element(TCGv_i64 val, TCGv_ptr base, - int ofs, int sew) +static void vec_element_storei_tail(DisasContext *s, int vreg, TCGv_i64 val) { - switch (sew) { - case MO_8: - tcg_gen_st8_i64(val, base, ofs); - break; - case MO_16: - tcg_gen_st16_i64(val, base, ofs); - break; - case MO_32: - tcg_gen_st32_i64(val, base, ofs); - break; - case MO_64: - tcg_gen_st_i64(val, base, ofs); - break; - default: - g_assert_not_reached(); - } -} + static gen_helper_vset_velem0 * const fns[4] = { + gen_helper_vset_velem0_b, gen_helper_vset_velem0_h, + gen_helper_vset_velem0_w, gen_helper_vset_velem0_d, + }; + TCGv_ptr dest = tcg_temp_new_ptr(); + uint32_t data = FIELD_DP32(0, VDATA, VTA, s->vta); + TCGv_i32 desc = tcg_constant_i32(simd_desc(s->cfg_ptr->vlenb, + s->cfg_ptr->vlenb, data)); -/* - * Store vreg[idx] = val. - * The index must be in range of VLMAX. - */ -static void vec_element_storei(DisasContext *s, int vreg, - int idx, TCGv_i64 val) -{ - store_element(val, tcg_env, endian_ofs(s, vreg, idx), s->sew); + tcg_gen_addi_ptr(dest, tcg_env, vreg_ofs(s, vreg)); + fns[s->sew](dest, val, tcg_env, desc); } /* vmv.x.s rd, vs2 # x[rd] = vs2[0] */ @@ -XXX,XX +XXX,XX @@ static bool trans_vmv_s_x(DisasContext *s, arg_vmv_s_x *a) */ s1 = get_gpr(s, a->rs1, EXT_NONE); tcg_gen_ext_tl_i64(t1, s1); - vec_element_storei(s, a->rd, 0, t1); + vec_element_storei_tail(s, a->rd, t1); gen_set_label(over); tcg_gen_movi_tl(cpu_vstart, 0); finalize_rvv_inst(s); @@ -XXX,XX +XXX,XX @@ static bool trans_vfmv_s_f(DisasContext *s, arg_vfmv_s_f *a) t1 = tcg_temp_new_i64(); do_nanbox(s, t1, cpu_fpr[a->rs1]); - vec_element_storei(s, a->rd, 0, t1); + vec_element_storei_tail(s, a->rd, t1); gen_set_label(over); tcg_gen_movi_tl(cpu_vstart, 0); -- 2.53.0
From: Zishun Yi <vulab@iscas.ac.cn> The RISC-V unpriv specification (zvk.adoc) states that "Zvknhb implies Zvknha". This means that enabling Zvknhb should automatically enable Zvknha. Add Zvknha to ZVKNHB_IMPLIED to ensure the dependency is correctly enforced. This issue was discovered and reported by SpecHunter, an AI-driven architecture specification analysis tool. Link:https://github.com/yizishun/rv-isa-sec/blob/master/output/riscv-isa-manual/pr-2635/qemu.txt Signed-off-by: Zishun Yi <vulab@iscas.ac.cn> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Message-ID: <20260511051736.2916225-1-vulab@iscas.ac.cn> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -XXX,XX +XXX,XX @@ static RISCVCPUImpliedExtsRule ZVKNG_IMPLIED = { static RISCVCPUImpliedExtsRule ZVKNHB_IMPLIED = { .ext = CPU_CFG_OFFSET(ext_zvknhb), .implied_multi_exts = { - CPU_CFG_OFFSET(ext_zve64x), + CPU_CFG_OFFSET(ext_zve64x), CPU_CFG_OFFSET(ext_zvknha), RISCV_IMPLIED_EXTS_RULE_END }, -- 2.53.0
From: Zishun Yi <vulab@iscas.ac.cn> Currently, the MENVCFG_CDE (Counter Delegation Enable) bit is unconditionally included in the base write mask for CSR_MENVCFG. This make the subsequent conditional check `(cfg->ext_smcdeleg ? MENVCFG_CDE : 0)` completely ineffective, as a bitwise OR cannot clear a bit that is already set. Fix this by removing MENVCFG_CDE from the initial base mask. The bit will now only be writable when explicitly granted by the `ext_smcdeleg` configuration. This issue was discovered and reported by SpecHunter, an AI-driven architecture specification analysis tool. Link: https://github.com/yizishun/rv-isa-sec/blob/master/output/riscv-isa-manual/pr-2601/qemu.txt Signed-off-by: Zishun Yi <vulab@iscas.ac.cn> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Message-ID: <20260511040534.2862443-1-vulab@iscas.ac.cn> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- 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 XXXXXXX..XXXXXXX 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -XXX,XX +XXX,XX @@ static RISCVException write_menvcfg(CPURISCVState *env, int csrno, { const RISCVCPUConfig *cfg = riscv_cpu_cfg(env); uint64_t mask = MENVCFG_FIOM | MENVCFG_CBIE | MENVCFG_CBCFE | - MENVCFG_CBZE | MENVCFG_CDE; + MENVCFG_CBZE; bool stce_changed = false; if (riscv_cpu_mxl(env) == MXL_RV64) { -- 2.53.0
From: Zishun Yi <vulab@iscas.ac.cn> According to the RISC-V smcdeleg specification: "When menvcfg.CDE=0, attempts to access scountinhibit raise an illegal-instruction exception." The current implementation of scountinhibit_pred() only checks the hardware extensions (ext_ssccfg, ext_smcdeleg) and virtualization status, but completely misses the runtime environment configuration check (menvcfg.CDE). This allows S-mode to access scountinhibit even when the M-mode has explicitly disabled counter delegation. This issue was discovered by the SpecHunter tool (https://github.com/yizishun/rv-isa-sec/blob/master/output/riscv-isa-manual/pr-2571/qemu.txt). Fixes: 6247dc2ef70b ("target/riscv: Add counter delegation/configuration support") Signed-off-by: Zishun Yi <vulab@iscas.ac.cn> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Message-ID: <20260508174917.371667-1-vulab@iscas.ac.cn> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/csr.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -XXX,XX +XXX,XX @@ static RISCVException scountinhibit_pred(CPURISCVState *env, int csrno) return RISCV_EXCP_ILLEGAL_INST; } + if (!get_field(env->menvcfg, MENVCFG_CDE)) { + return RISCV_EXCP_ILLEGAL_INST; + } + if (env->virt_enabled) { return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; } -- 2.53.0
From: Zishun Yi <vulab@iscas.ac.cn> According to the RISC-V Privileged Manual: "The Sv32 page-based virtual-memory scheme described in sv32 supports 34-bit physical addresses for RV32, so the PMP scheme must support addresses wider than XLEN for RV32." However, the current QEMU implementation uses `target_ulong` (which resolves to `uint32_t` on RV32) for PMP address variables. When shifting these addresses left (e.g., `this_addr << 2`), an integer overflow occurs, truncating the high bits of the 34-bit physical address. Fix this issue by changing the types of PMP address variables (`this_addr` and `prev_addr`) to `hwaddr`. This issue was discovered and reported by SpecHunter, an AI-driven architecture specification analysis tool. Link: https://github.com/yizishun/rv-isa-sec/blob/master/output/riscv-isa-manual/pr-2472/qemu.txt Signed-off-by: Zishun Yi <vulab@iscas.ac.cn> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Message-ID: <20260511102627.3120140-1-vulab@iscas.ac.cn> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/pmp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/pmp.c +++ b/target/riscv/pmp.c @@ -XXX,XX +XXX,XX @@ static void pmp_decode_napot(hwaddr a, hwaddr *sa, hwaddr *ea) void pmp_update_rule_addr(CPURISCVState *env, uint32_t pmp_index) { uint8_t this_cfg = env->pmp_state.pmp[pmp_index].cfg_reg; - target_ulong this_addr = env->pmp_state.pmp[pmp_index].addr_reg; - target_ulong prev_addr = 0u; + hwaddr this_addr = env->pmp_state.pmp[pmp_index].addr_reg; + hwaddr prev_addr = 0u; hwaddr sa = 0u; hwaddr ea = 0u; int g = pmp_get_granularity_g(env); -- 2.53.0
From: Zishun Yi <vulab@iscas.ac.cn> Currently, the Machine Security Configuration Register (mseccfg) was missing from the live migration state. This omission causes the register to be reset to zero on the destination host after migration. Fixed by adding vmstate_mseccfg subsection This vulnerability was discovered and reported by SpecHunter, an AI-driven architecture specification analysis tool. Link: https://github.com/yizishun/rv-isa-sec/blob/a22e4459cd026ae970791dfbd9cfe5d110fbd46b/output/riscv-isa-manual/pr-1879/qemu.txt#L121 Signed-off-by: Zishun Yi <vulab@iscas.ac.cn> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260511124828.3210477-1-vulab@iscas.ac.cn> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/machine.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/target/riscv/machine.c b/target/riscv/machine.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_sstc = { } }; +static bool mseccfg_needed(void *opaque) +{ + RISCVCPU *cpu = opaque; + + return cpu->cfg.ext_smepmp || cpu->cfg.ext_zkr + || cpu->cfg.ext_smmpm || cpu->cfg.ext_zicfilp; +} + +static const VMStateDescription vmstate_mseccfg = { + .name = "cpu/mseccfg", + .version_id = 1, + .minimum_version_id = 1, + .needed = mseccfg_needed, + .fields = (const VMStateField[]) { + VMSTATE_UINTTL(env.mseccfg, RISCVCPU), + VMSTATE_END_OF_LIST() + } +}; + const VMStateDescription vmstate_riscv_cpu = { .name = "cpu", .version_id = 11, @@ -XXX,XX +XXX,XX @@ const VMStateDescription vmstate_riscv_cpu = { &vmstate_ssp, &vmstate_ctr, &vmstate_sstc, + &vmstate_mseccfg, NULL } }; -- 2.53.0
From: Alistair Francis <alistair.francis@wdc.com> The RISC-V spec describes bits 0-15 as standard fixed interrupts. The AIA spec on the other hand describes bits 0-12 as standard fixed interrupts. This conflict causes issues for us as we don't dynamically determine if AIA is enabled when setting the *delegable_ints consts. This means currently we incorrectly treat the LCOFIP bit as delegable, even if AIA is disabled, which is incorrect (see the issues mentioned below). The AIA spec indicates that implementations can determine which bits of 13-63 in mvien are writable, so let's just make it bits 15-63 to match the main spec. Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3133 Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3134 Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3135 Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3138 Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3140 Signed-off-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Message-ID: <20260513051841.1671987-1-alistair.francis@wdc.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/csr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -XXX,XX +XXX,XX @@ static RISCVException write_stimecmph(CPURISCVState *env, int csrno, #define VSTOPI_NUM_SRCS 5 /* - * All core local interrupts except the fixed ones 0:12. This macro is for + * All core local interrupts except the fixed ones 0:15. This macro is for * virtual interrupts logic so please don't change this to avoid messing up * the whole support, For reference see AIA spec: `5.3 Interrupt filtering and * virtual interrupts for supervisor level` and `6.3.2 Virtual interrupts for * VS level`. */ -#define LOCAL_INTERRUPTS (~0x1FFFULL) +#define LOCAL_INTERRUPTS (~0xFFFFULL) static const uint64_t delegable_ints = S_MODE_INTERRUPTS | VS_MODE_INTERRUPTS | MIP_LCOFIP; -- 2.53.0
From: Zishun Yi <vulab@iscas.ac.cn> Currently, the `mseccfg` CSR is only cleared to 0 during reset if the `ext_smepmp` is enabled. However, this register is now shared by several other extensions such as `zkr`, `smmpm`, and `zicfilp`. Fix by clearing `mseccfg` if any dependent extension is present, and adjusting the relevant comments. This vulnerability was discovered and reported by SpecHunter, an AI-driven architecture specification analysis tool. Link: https://github.com/yizishun/rv-isa-sec/blob/master/output/riscv-svvptc/pr-134/qemu.txt Signed-off-by: Zishun Yi <vulab@iscas.ac.cn> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Message-ID: <20260512052240.330815-1-vulab@iscas.ac.cn> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_reset_hold(Object *obj, ResetType type) /* * Clear mseccfg and unlock all the PMP entries upon reset. - * This is allowed as per the priv and smepmp specifications - * and is needed to clear stale entries across reboots. + * This is required as per the priv, smepmp, and other security + * extension specifications that share this CSR, and is needed + * to clear stale entries across reboots. */ - if (riscv_cpu_cfg(env)->ext_smepmp) { + if (riscv_cpu_cfg(env)->ext_smepmp || + riscv_cpu_cfg(env)->ext_zkr || + riscv_cpu_cfg(env)->ext_smmpm || + riscv_cpu_cfg(env)->ext_zicfilp) { env->mseccfg = 0; } -- 2.53.0
From: Zongmin Zhou <zhouzongmin@kylinos.cn> When the Zicbop extension is available expose it to the KVM guest. Also read and validate cbop_blocksize from the host via KVM interface. Signed-off-by: Zongmin Zhou <zhouzongmin@kylinos.cn> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Message-ID: <9e388aa9984ea9d3d0c85e1630c9195023938952.1778653159.git.zhouzongmin@kylinos.cn> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/kvm/kvm-cpu.c | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/kvm/kvm-cpu.c +++ b/target/riscv/kvm/kvm-cpu.c @@ -XXX,XX +XXX,XX @@ static void kvm_cpu_csr_set_u64(RISCVCPU *cpu, KVMCPUConfig *csr_cfg, static KVMCPUConfig kvm_multi_ext_cfgs[] = { KVM_EXT_CFG("zicbom", ext_zicbom, KVM_RISCV_ISA_EXT_ZICBOM), + KVM_EXT_CFG("zicbop", ext_zicbop, KVM_RISCV_ISA_EXT_ZICBOP), KVM_EXT_CFG("zicboz", ext_zicboz, KVM_RISCV_ISA_EXT_ZICBOZ), KVM_EXT_CFG("ziccrse", ext_ziccrse, KVM_RISCV_ISA_EXT_ZICCRSE), KVM_EXT_CFG("zicntr", ext_zicntr, KVM_RISCV_ISA_EXT_ZICNTR), @@ -XXX,XX +XXX,XX @@ static KVMCPUConfig kvm_cboz_blocksize = { .kvm_reg_id = KVM_REG_RISCV_CONFIG_REG(zicboz_block_size) }; +static KVMCPUConfig kvm_cbop_blocksize = { + .name = "cbop_blocksize", + .offset = CPU_CFG_OFFSET(cbop_blocksize), + .kvm_reg_id = KVM_REG_RISCV_CONFIG_REG(zicbop_block_size) +}; + static KVMCPUConfig kvm_v_vlenb = { .name = "vlenb", .offset = CPU_CFG_OFFSET(vlenb), @@ -XXX,XX +XXX,XX @@ static void kvm_riscv_init_cfg(RISCVCPU *cpu, KVMScratchCPU *kvmcpu) kvm_riscv_read_cbomz_blksize(cpu, kvmcpu, &kvm_cbom_blocksize); } + if (cpu->cfg.ext_zicbop) { + kvm_riscv_read_cbomz_blksize(cpu, kvmcpu, &kvm_cbop_blocksize); + } + if (cpu->cfg.ext_zicboz) { kvm_riscv_read_cbomz_blksize(cpu, kvmcpu, &kvm_cboz_blocksize); } @@ -XXX,XX +XXX,XX @@ void riscv_kvm_cpu_finalize_features(RISCVCPU *cpu, Error **errp) int ret; /* short-circuit without spinning the scratch CPU */ - if (!cpu->cfg.ext_zicbom && !cpu->cfg.ext_zicboz && - !riscv_has_ext(env, RVV)) { + if (!cpu->cfg.ext_zicbom && !cpu->cfg.ext_zicbop && + !cpu->cfg.ext_zicboz && !riscv_has_ext(env, RVV)) { return; } @@ -XXX,XX +XXX,XX @@ void riscv_kvm_cpu_finalize_features(RISCVCPU *cpu, Error **errp) } } + if (cpu->cfg.ext_zicbop && + riscv_cpu_option_set(kvm_cbop_blocksize.name)) { + + reg.id = KVM_RISCV_REG_ID_ULONG(KVM_REG_RISCV_CONFIG, + kvm_cbop_blocksize.kvm_reg_id); + reg.addr = (uint64_t)&val; + ret = ioctl(kvmcpu.cpufd, KVM_GET_ONE_REG, ®); + if (ret != 0) { + error_setg_errno(errp, errno, "Unable to read cbop_blocksize"); + return; + } + + if (cpu->cfg.cbop_blocksize != val) { + error_setg(errp, "Unable to set cbop_blocksize to a different " + "value than the host (%lu)", val); + return; + } + } + /* Users are setting vlen, not vlenb */ if (riscv_has_ext(env, RVV) && riscv_cpu_option_set("vlen")) { if (!kvm_v_vlenb.supported) { -- 2.53.0
From: Zongmin Zhou <zhouzongmin@kylinos.cn> Expose the BFloat16 extensions (Zfbfmin, Zvfbfmin, Zvfbfwma) to KVM guests when available in hardware. Signed-off-by: Zongmin Zhou <zhouzongmin@kylinos.cn> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Message-ID: <1258febb0eeb4ee286eb88f70b077a7f1ece507f.1778653159.git.zhouzongmin@kylinos.cn> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/kvm/kvm-cpu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/kvm/kvm-cpu.c +++ b/target/riscv/kvm/kvm-cpu.c @@ -XXX,XX +XXX,XX @@ static KVMCPUConfig kvm_multi_ext_cfgs[] = { KVM_EXT_CFG("zacas", ext_zacas, KVM_RISCV_ISA_EXT_ZACAS), KVM_EXT_CFG("zawrs", ext_zawrs, KVM_RISCV_ISA_EXT_ZAWRS), KVM_EXT_CFG("zfa", ext_zfa, KVM_RISCV_ISA_EXT_ZFA), + KVM_EXT_CFG("zfbfmin", ext_zfbfmin, KVM_RISCV_ISA_EXT_ZFBFMIN), KVM_EXT_CFG("zfh", ext_zfh, KVM_RISCV_ISA_EXT_ZFH), KVM_EXT_CFG("zfhmin", ext_zfhmin, KVM_RISCV_ISA_EXT_ZFHMIN), KVM_EXT_CFG("zba", ext_zba, KVM_RISCV_ISA_EXT_ZBA), @@ -XXX,XX +XXX,XX @@ static KVMCPUConfig kvm_multi_ext_cfgs[] = { KVM_EXT_CFG("zvbc", ext_zvbc, KVM_RISCV_ISA_EXT_ZVBC), KVM_EXT_CFG("zvfh", ext_zvfh, KVM_RISCV_ISA_EXT_ZVFH), KVM_EXT_CFG("zvfhmin", ext_zvfhmin, KVM_RISCV_ISA_EXT_ZVFHMIN), + KVM_EXT_CFG("zvfbfmin", ext_zvfbfmin, KVM_RISCV_ISA_EXT_ZVFBFMIN), + KVM_EXT_CFG("zvfbfwma", ext_zvfbfwma, KVM_RISCV_ISA_EXT_ZVFBFWMA), KVM_EXT_CFG("zvkb", ext_zvkb, KVM_RISCV_ISA_EXT_ZVKB), KVM_EXT_CFG("zvkg", ext_zvkg, KVM_RISCV_ISA_EXT_ZVKG), KVM_EXT_CFG("zvkned", ext_zvkned, KVM_RISCV_ISA_EXT_ZVKNED), -- 2.53.0
From: Zishun Yi <vulab@iscas.ac.cn> Fix a mode-to-capability comparison error in riscv_iommu_validate_device_ctx. The code was comparing fsc_mode (a value) against a capability bitmask, making the SV32 support check ineffective. This issue was discovered and reported by SpecHunter, an AI-driven architecture specification analysis tool. Link: https://github.com/yizishun/rv-isa-sec/blob/master/output/riscv-iommu/pr-694/qemu.txt Signed-off-by: Zishun Yi <vulab@iscas.ac.cn> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Message-ID: <20260511080904.3049446-1-vulab@iscas.ac.cn> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/riscv/riscv-iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/riscv-iommu.c +++ b/hw/riscv/riscv-iommu.c @@ -XXX,XX +XXX,XX @@ static bool riscv_iommu_validate_device_ctx(RISCVIOMMUState *s, } if (ctx->tc & RISCV_IOMMU_DC_TC_SXL) { - if (fsc_mode == RISCV_IOMMU_CAP_SV32 && + if (fsc_mode == RISCV_IOMMU_DC_FSC_IOSATP_MODE_SV32 && !(s->cap & RISCV_IOMMU_CAP_SV32)) { return false; } -- 2.53.0
From: Chengbo Gao <gaochengbo@bosc.ac.cn> PCI bus numbers may still be unassigned when QEMU initializes a PCI device's bus-master address space. For devices behind bridges, pci_bus_num() can return 0 at that point because the guest has not yet programmed the bridge Secondary Bus Number register. The RISC-V IOMMU currently stores a fixed device_id in RISCVIOMMUSpace when the address space is created. If the guest later enumerates the device on a non-zero bus, DMA translation still uses the stale device_id and may look up the wrong device context in the DDT. Store the stable PCIBus pointer and devfn in RISCVIOMMUSpace instead, and compute the device_id from the current bus number when it is needed. This keeps DMA translation and ATS invalidation in sync with guest PCI bus enumeration. Signed-off-by: Chengbo Gao <gaochengbo@bosc.ac.cn> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Message-ID: <20260514020637.2819308-1-gaochengbo@bosc.ac.cn> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/riscv/riscv-iommu.c | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/riscv-iommu.c +++ b/hw/riscv/riscv-iommu.c @@ -XXX,XX +XXX,XX @@ struct RISCVIOMMUSpace { IOMMUMemoryRegion iova_mr; /* IOVA memory region for attached device */ AddressSpace iova_as; /* IOVA address space for attached device */ RISCVIOMMUState *iommu; /* Managing IOMMU device state */ - uint32_t devid; /* Requester identifier, AKA device_id */ + PCIBus *bus; /* PCI bus of the requester */ + uint8_t devfn; /* Requester identifier, AKA device_id */ bool notifier; /* IOMMU unmap notifier enabled */ QLIST_ENTRY(RISCVIOMMUSpace) list; }; @@ -XXX,XX +XXX,XX @@ struct RISCVIOMMUEntry { /* IOMMU index for transactions without process_id specified. */ #define RISCV_IOMMU_NOPROCID 0 +static uint32_t riscv_iommu_space_devid(RISCVIOMMUSpace *as) +{ + uint32_t devid = PCI_BUILD_BDF(pci_bus_num(as->bus), as->devfn); + + /* FIXME: PCIe bus remapping for attached endpoints. */ + devid |= as->iommu->bus << 8; + return devid; +} + static uint8_t riscv_iommu_get_icvec_vector(uint32_t icvec, uint32_t vec_type) { switch (vec_type) { @@ -XXX,XX +XXX,XX @@ static void riscv_iommu_ctx_put(RISCVIOMMUState *s, void *ref) } /* Find or allocate address space for a given device */ -static AddressSpace *riscv_iommu_space(RISCVIOMMUState *s, uint32_t devid) +static AddressSpace *riscv_iommu_space(RISCVIOMMUState *s, PCIBus *bus, + int devfn) { RISCVIOMMUSpace *as; - /* FIXME: PCIe bus remapping for attached endpoints. */ - devid |= s->bus << 8; - QLIST_FOREACH(as, &s->spaces, list) { - if (as->devid == devid) { + if (as->bus == bus && as->devfn == devfn) { break; } } @@ -XXX,XX +XXX,XX @@ static AddressSpace *riscv_iommu_space(RISCVIOMMUState *s, uint32_t devid) as = g_new0(RISCVIOMMUSpace, 1); as->iommu = s; - as->devid = devid; + as->bus = bus; + as->devfn = devfn; snprintf(name, sizeof(name), "riscv-iommu-%04x:%02x.%d-iova", - PCI_BUS_NUM(as->devid), PCI_SLOT(as->devid), PCI_FUNC(as->devid)); + pci_bus_num(bus), PCI_SLOT(devfn), PCI_FUNC(devfn)); /* IOVA address space, untranslated addresses */ memory_region_init_iommu(&as->iova_mr, sizeof(as->iova_mr), @@ -XXX,XX +XXX,XX @@ static AddressSpace *riscv_iommu_space(RISCVIOMMUState *s, uint32_t devid) QLIST_INSERT_HEAD(&s->spaces, as, list); - trace_riscv_iommu_new(s->parent_obj.id, PCI_BUS_NUM(as->devid), - PCI_SLOT(as->devid), PCI_FUNC(as->devid)); + trace_riscv_iommu_new(s->parent_obj.id, pci_bus_num(bus), + PCI_SLOT(devfn), PCI_FUNC(devfn)); } return &as->iova_as; } @@ -XXX,XX +XXX,XX @@ static void riscv_iommu_ats(RISCVIOMMUState *s, pid = get_field(cmd->dword0, RISCV_IOMMU_CMD_ATS_PID); QLIST_FOREACH(as, &s->spaces, list) { - if (as->devid == devid) { + if (riscv_iommu_space_devid(as) == devid) { break; } } @@ -XXX,XX +XXX,XX @@ static IOMMUTLBEntry riscv_iommu_memory_region_translate( .addr_mask = ~0ULL, .perm = flag, }; + uint32_t devid = riscv_iommu_space_devid(as); - ctx = riscv_iommu_ctx(as->iommu, as->devid, iommu_idx, &ref); + ctx = riscv_iommu_ctx(as->iommu, devid, iommu_idx, &ref); if (ctx == NULL) { /* Translation disabled or invalid. */ iotlb.addr_mask = 0; @@ -XXX,XX +XXX,XX @@ static IOMMUTLBEntry riscv_iommu_memory_region_translate( } /* Trace all dma translations with original access flags. */ - trace_riscv_iommu_dma(as->iommu->parent_obj.id, PCI_BUS_NUM(as->devid), - PCI_SLOT(as->devid), PCI_FUNC(as->devid), iommu_idx, + trace_riscv_iommu_dma(as->iommu->parent_obj.id, PCI_BUS_NUM(devid), + PCI_SLOT(devid), PCI_FUNC(devid), iommu_idx, IOMMU_FLAG_STR[flag & IOMMU_RW], iotlb.iova, iotlb.translated_addr); @@ -XXX,XX +XXX,XX @@ static AddressSpace *riscv_iommu_find_as(PCIBus *bus, void *opaque, int devfn) /* Find first matching IOMMU */ while (s != NULL && as == NULL) { - as = riscv_iommu_space(s, PCI_BUILD_BDF(pci_bus_num(bus), devfn)); + as = riscv_iommu_space(s, bus, devfn); s = s->iommus.le_next; } -- 2.53.0
From: Guenter Roeck <linux@roeck-us.net> Minimal clock register configuration required to boot Linux without backtraces in the clock code. Signed-off-by: Guenter Roeck <linux@roeck-us.net> Signed-off-by: Conor Dooley <conor.dooley@microchip.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260514-reference-overhand-749149e36a88@spud> [ Changes by AF: - Fixup checkpatch errors ] Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- include/hw/misc/mchp_pfsoc_ioscb.h | 2 ++ hw/misc/mchp_pfsoc_ioscb.c | 47 +++++++++++++++++++++++++++++- hw/misc/mchp_pfsoc_sysreg.c | 13 +++++++++ 3 files changed, 61 insertions(+), 1 deletion(-) diff --git a/include/hw/misc/mchp_pfsoc_ioscb.h b/include/hw/misc/mchp_pfsoc_ioscb.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/misc/mchp_pfsoc_ioscb.h +++ b/include/hw/misc/mchp_pfsoc_ioscb.h @@ -XXX,XX +XXX,XX @@ typedef struct MchpPfSoCIoscbState { MemoryRegion mailbox; MemoryRegion cfg; MemoryRegion ccc; + MemoryRegion pll_nw_0; + MemoryRegion pll_nw_1; MemoryRegion pll_mss; MemoryRegion cfm_mss; MemoryRegion pll_ddr; diff --git a/hw/misc/mchp_pfsoc_ioscb.c b/hw/misc/mchp_pfsoc_ioscb.c index XXXXXXX..XXXXXXX 100644 --- a/hw/misc/mchp_pfsoc_ioscb.c +++ b/hw/misc/mchp_pfsoc_ioscb.c @@ -XXX,XX +XXX,XX @@ #define IOSCB_MAILBOX_BASE 0x07020800 #define IOSCB_CFG_BASE 0x07080000 #define IOSCB_CCC_BASE 0x08000000 +#define IOSCB_PLL_NW0_BASE 0x08100000 +#define IOSCB_PLL_NW1_BASE 0x08200000 #define IOSCB_PLL_MSS_BASE 0x0E001000 #define IOSCB_CFM_MSS_BASE 0x0E002000 #define IOSCB_PLL_DDR_BASE 0x0E010000 @@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps mchp_pfsoc_dummy_ops = { /* All PLL modules in IOSCB have the same register layout */ #define PLL_CTRL 0x04 +#define PLL_REF_FB 0x08 +#define PLL_DIV_0_1 0x10 +#define PLL_DIV_2_3 0x14 +#define PLL_CTRL2 0x18 +#define PLL_CAL 0x1c +#define PLL_PHADJ 0x20 +#define SSCG_REG_0 0x24 +#define SSCG_REG_1 0x28 +#define SSCG_REG_2 0x2c +#define SSCG_REG_3 0x30 static uint64_t mchp_pfsoc_pll_read(void *opaque, hwaddr offset, unsigned size) @@ -XXX,XX +XXX,XX @@ static uint64_t mchp_pfsoc_pll_read(void *opaque, hwaddr offset, /* PLL is locked */ val = BIT(25); break; + case PLL_DIV_0_1: + case PLL_DIV_2_3: + val = 0x01000100; /* return valid post divider values */ + break; + case PLL_CTRL2: + val = 0x00001110; + break; + case PLL_REF_FB: + val = 0x00000100; /* RFDIV := 1 */ + break; + case SSCG_REG_2: + val = 0x00000001; /* INTIN := 1 */ + break; + case PLL_PHADJ: + val = 0x00000401; + break; default: qemu_log_mask(LOG_UNIMP, "%s: unimplemented device read " "(size %d, offset 0x%" HWADDR_PRIx ")\n", @@ -XXX,XX +XXX,XX @@ static uint64_t mchp_pfsoc_pll_read(void *opaque, hwaddr offset, return val; } +static void mchp_pfsoc_pll_write(void *opaque, hwaddr offset, + uint64_t value, unsigned size) +{ + qemu_log_mask(LOG_UNIMP, "%s: unimplemented device write " + "(size %d, value 0x%" PRIx64 + ", offset 0x%" HWADDR_PRIx ")\n", + __func__, size, value, offset); +} + static const MemoryRegionOps mchp_pfsoc_pll_ops = { .read = mchp_pfsoc_pll_read, - .write = mchp_pfsoc_dummy_write, + .write = mchp_pfsoc_pll_write, .endianness = DEVICE_LITTLE_ENDIAN, }; @@ -XXX,XX +XXX,XX @@ static void mchp_pfsoc_ioscb_realize(DeviceState *dev, Error **errp) "mchp.pfsoc.ioscb.ccc", IOSCB_CCC_REG_SIZE); memory_region_add_subregion(&s->container, IOSCB_CCC_BASE, &s->ccc); + memory_region_init_io(&s->pll_nw_0, OBJECT(s), &mchp_pfsoc_pll_ops, s, + "mchp.pfsoc.ioscb.pll_nw_0", IOSCB_SUBMOD_REG_SIZE); + memory_region_add_subregion(&s->container, IOSCB_PLL_NW0_BASE, &s->pll_nw_0); + + memory_region_init_io(&s->pll_nw_1, OBJECT(s), &mchp_pfsoc_pll_ops, s, + "mchp.pfsoc.ioscb.pll_nw_1", IOSCB_SUBMOD_REG_SIZE); + memory_region_add_subregion(&s->container, IOSCB_PLL_NW1_BASE, &s->pll_nw_1); + memory_region_init_io(&s->pll_mss, OBJECT(s), &mchp_pfsoc_pll_ops, s, "mchp.pfsoc.ioscb.pll_mss", IOSCB_SUBMOD_REG_SIZE); memory_region_add_subregion(&s->container, IOSCB_PLL_MSS_BASE, &s->pll_mss); diff --git a/hw/misc/mchp_pfsoc_sysreg.c b/hw/misc/mchp_pfsoc_sysreg.c index XXXXXXX..XXXXXXX 100644 --- a/hw/misc/mchp_pfsoc_sysreg.c +++ b/hw/misc/mchp_pfsoc_sysreg.c @@ -XXX,XX +XXX,XX @@ #include "hw/misc/mchp_pfsoc_sysreg.h" #include "system/runstate.h" +#define CLOCK_CONFIG_CR 0x8 +#define RTC_CLOCK_CR 0xc #define MSS_RESET_CR 0x18 #define ENVM_CR 0xb8 #define MESSAGE_INT 0x118c @@ -XXX,XX +XXX,XX @@ static uint64_t mchp_pfsoc_sysreg_read(void *opaque, hwaddr offset, uint32_t val = 0; switch (offset) { + case CLOCK_CONFIG_CR: + /* Icicle kit reference design cpu/axi/ahb divider setting */ + val = 0x24; + break; + case RTC_CLOCK_CR: + /* + * Bit 16 enables the RTC clock, 0x7d is the required divider + * setting for a 125 MHz reference. + */ + val = BIT(16) | 0x7d; + break; case ENVM_CR: /* Indicate the eNVM is running at the configured divider rate */ val = BIT(6); -- 2.53.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> The entry was missing from isa_edata_arr[]. Fixes: 32bbab666 ("target/riscv: add draft RISC-V Zbr ext as xbr0p93") Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260512032926.1978818-2-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -XXX,XX +XXX,XX @@ const RISCVIsaExtData isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(svrsw60t59b, PRIV_VERSION_1_13_0, ext_svrsw60t59b), ISA_EXT_DATA_ENTRY(svukte, PRIV_VERSION_1_13_0, ext_svukte), ISA_EXT_DATA_ENTRY(svvptc, PRIV_VERSION_1_13_0, ext_svvptc), + ISA_EXT_DATA_ENTRY(xlrbr, PRIV_VERSION_1_13_0, ext_xlrbr), ISA_EXT_DATA_ENTRY(xmipscbop, PRIV_VERSION_1_12_0, ext_xmipscbop), ISA_EXT_DATA_ENTRY(xmipscmov, PRIV_VERSION_1_12_0, ext_xmipscmov), ISA_EXT_DATA_ENTRY(xmipslsp, PRIV_VERSION_1_12_0, ext_xmipslsp), -- 2.53.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Noticed when realizing that 'svadu' was too far apart from 'svade'. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260512032926.1978818-3-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -XXX,XX +XXX,XX @@ const RISCVIsaExtData isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(smcdeleg, PRIV_VERSION_1_13_0, ext_smcdeleg), ISA_EXT_DATA_ENTRY(smcntrpmf, PRIV_VERSION_1_12_0, ext_smcntrpmf), ISA_EXT_DATA_ENTRY(smcsrind, PRIV_VERSION_1_13_0, ext_smcsrind), + ISA_EXT_DATA_ENTRY(smctr, PRIV_VERSION_1_12_0, ext_smctr), ISA_EXT_DATA_ENTRY(smdbltrp, PRIV_VERSION_1_13_0, ext_smdbltrp), ISA_EXT_DATA_ENTRY(smepmp, PRIV_VERSION_1_12_0, ext_smepmp), ISA_EXT_DATA_ENTRY(smpmpmt, PRIV_VERSION_1_12_0, ext_smpmpmt), @@ -XXX,XX +XXX,XX @@ const RISCVIsaExtData isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(sscofpmf, PRIV_VERSION_1_12_0, ext_sscofpmf), ISA_EXT_DATA_ENTRY(sscounterenw, PRIV_VERSION_1_12_0, has_priv_1_12), ISA_EXT_DATA_ENTRY(sscsrind, PRIV_VERSION_1_12_0, ext_sscsrind), + ISA_EXT_DATA_ENTRY(ssctr, PRIV_VERSION_1_12_0, ext_ssctr), ISA_EXT_DATA_ENTRY(ssdbltrp, PRIV_VERSION_1_13_0, ext_ssdbltrp), ISA_EXT_DATA_ENTRY(ssnpm, PRIV_VERSION_1_13_0, ext_ssnpm), ISA_EXT_DATA_ENTRY(sspm, PRIV_VERSION_1_13_0, ext_sspm), @@ -XXX,XX +XXX,XX @@ const RISCVIsaExtData isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(ssu64xl, PRIV_VERSION_1_12_0, has_priv_1_12), ISA_EXT_DATA_ENTRY(supm, PRIV_VERSION_1_13_0, ext_supm), ISA_EXT_DATA_ENTRY(svade, PRIV_VERSION_1_11_0, ext_svade), - ISA_EXT_DATA_ENTRY(smctr, PRIV_VERSION_1_12_0, ext_smctr), - ISA_EXT_DATA_ENTRY(ssctr, PRIV_VERSION_1_12_0, ext_ssctr), ISA_EXT_DATA_ENTRY(svadu, PRIV_VERSION_1_12_0, ext_svadu), ISA_EXT_DATA_ENTRY(svinval, PRIV_VERSION_1_12_0, ext_svinval), ISA_EXT_DATA_ENTRY(svnapot, PRIV_VERSION_1_12_0, ext_svnapot), -- 2.53.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> We want to reduce the usage of the riscv_cpu_* arrays in target/riscv/cpu.c, centering everything in isa_edata_arr[] instead, to reduce data duplication and make our lives a bit easier when adding new extensions. To do that we'll have to make isa_edata_arr[] do what the other arrays are currently doing, not breaking existing semantics in the process. The riscv_cpu_* arrays have a few exclusive uses: - set default extensions for rv32 and rv64; - create user CPU properties; - misc uses around tcg-cpu.c and kvm-cpu.c. We'll slowly make isa_edata_arr[] supersede these arrays. Start by adding a new 'prop_name' field in RISCVIsaExtData. This field is needed because not all extensions have properties and not all properties match the riscv,isa string name. Create two additional macros and reclassify existing isa_edata_arr[] entries as follows: - ISA_EXT_DATA_ENTRY creates an entry where prop_name == riscv,isa. Most of our regular extensions fall into this category; - ISA_EXPERIMENTAL_EXT_DATA_ENTRY: same as above but add a "x-" to the prop name, i.e. prop_name == "x-" + riscv,isa; - ISA_INTERNAL_EXT_DATA_ENTRY: used to declared internal extensions. By 'internal' we mean users/management can't set them on or off. With these new macros we can start our simplification by changing riscv-qmp-cmds to use isa_edata_arr[]. We'll just scroll through it once and gather what we need. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260512032926.1978818-4-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.h | 1 + target/riscv/cpu.c | 60 +++++++++++++++++++++++------------ target/riscv/riscv-qmp-cmds.c | 30 ++++-------------- 3 files changed, 47 insertions(+), 44 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -XXX,XX +XXX,XX @@ extern const RISCVCPUMultiExtConfig riscv_cpu_named_features[]; typedef struct isa_ext_data { const char *name; + const char *prop_name; int min_version; int ext_enable_offset; } RISCVIsaExtData; diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_cfg_merge(RISCVCPUConfig *dest, const RISCVCPUConfig *src) #include "cpu_cfg_fields.h.inc" } +/* Use this for regular user facing extensions */ #define ISA_EXT_DATA_ENTRY(_name, _min_ver, _prop) \ - {#_name, _min_ver, CPU_CFG_OFFSET(_prop)} + {#_name, #_name, _min_ver, CPU_CFG_OFFSET(_prop)} + +/* + * Same as above but for experimental extensions. We'll add a + * "x-" right after "_name" when creating the user property. + */ +#define ISA_EXPERIMENTAL_EXT_DATA_ENTRY(_name, _min_ver, _prop) \ + {#_name, "x-" #_name, _min_ver, CPU_CFG_OFFSET(_prop)} + +/* + * Internal extensions are extensions we will declare in the + * riscv,isa DT but they don't have an user property, i.e. + * users/management can't enable/disable them. + */ +#define ISA_INTERNAL_EXT_DATA_ENTRY(_name, _min_ver, _prop) \ + {#_name, NULL, _min_ver, CPU_CFG_OFFSET(_prop)} /* * Here are the ordering rules of extension naming defined by RISC-V @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_cfg_merge(RISCVCPUConfig *dest, const RISCVCPUConfig *src) * instead. */ const RISCVIsaExtData isa_edata_arr[] = { - ISA_EXT_DATA_ENTRY(zic64b, PRIV_VERSION_1_12_0, ext_zic64b), + ISA_INTERNAL_EXT_DATA_ENTRY(zic64b, PRIV_VERSION_1_12_0, ext_zic64b), ISA_EXT_DATA_ENTRY(zicbom, PRIV_VERSION_1_12_0, ext_zicbom), ISA_EXT_DATA_ENTRY(zicbop, PRIV_VERSION_1_12_0, ext_zicbop), ISA_EXT_DATA_ENTRY(zicboz, PRIV_VERSION_1_12_0, ext_zicboz), - ISA_EXT_DATA_ENTRY(ziccamoa, PRIV_VERSION_1_11_0, has_priv_1_11), - ISA_EXT_DATA_ENTRY(ziccif, PRIV_VERSION_1_11_0, has_priv_1_11), - ISA_EXT_DATA_ENTRY(zicclsm, PRIV_VERSION_1_11_0, has_priv_1_11), + ISA_INTERNAL_EXT_DATA_ENTRY(ziccamoa, PRIV_VERSION_1_11_0, has_priv_1_11), + ISA_INTERNAL_EXT_DATA_ENTRY(ziccif, PRIV_VERSION_1_11_0, has_priv_1_11), + ISA_INTERNAL_EXT_DATA_ENTRY(zicclsm, PRIV_VERSION_1_11_0, has_priv_1_11), ISA_EXT_DATA_ENTRY(ziccrse, PRIV_VERSION_1_11_0, ext_ziccrse), ISA_EXT_DATA_ENTRY(zicfilp, PRIV_VERSION_1_12_0, ext_zicfilp), ISA_EXT_DATA_ENTRY(zicfiss, PRIV_VERSION_1_13_0, ext_zicfiss), @@ -XXX,XX +XXX,XX @@ const RISCVIsaExtData isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(zilsd, PRIV_VERSION_1_12_0, ext_zilsd), ISA_EXT_DATA_ENTRY(zimop, PRIV_VERSION_1_13_0, ext_zimop), ISA_EXT_DATA_ENTRY(zmmul, PRIV_VERSION_1_12_0, ext_zmmul), - ISA_EXT_DATA_ENTRY(za64rs, PRIV_VERSION_1_12_0, has_priv_1_12), + ISA_INTERNAL_EXT_DATA_ENTRY(za64rs, PRIV_VERSION_1_12_0, has_priv_1_12), ISA_EXT_DATA_ENTRY(zaamo, PRIV_VERSION_1_12_0, ext_zaamo), ISA_EXT_DATA_ENTRY(zabha, PRIV_VERSION_1_13_0, ext_zabha), ISA_EXT_DATA_ENTRY(zacas, PRIV_VERSION_1_12_0, ext_zacas), @@ -XXX,XX +XXX,XX @@ const RISCVIsaExtData isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(zhinx, PRIV_VERSION_1_12_0, ext_zhinx), ISA_EXT_DATA_ENTRY(zhinxmin, PRIV_VERSION_1_12_0, ext_zhinxmin), ISA_EXT_DATA_ENTRY(sdtrig, PRIV_VERSION_1_12_0, debug), - ISA_EXT_DATA_ENTRY(shcounterenw, PRIV_VERSION_1_12_0, has_priv_1_12), - ISA_EXT_DATA_ENTRY(sha, PRIV_VERSION_1_12_0, ext_sha), - ISA_EXT_DATA_ENTRY(shgatpa, PRIV_VERSION_1_12_0, has_priv_1_12), - ISA_EXT_DATA_ENTRY(shtvala, PRIV_VERSION_1_12_0, has_priv_1_12), - ISA_EXT_DATA_ENTRY(shvsatpa, PRIV_VERSION_1_12_0, has_priv_1_12), - ISA_EXT_DATA_ENTRY(shvstvala, PRIV_VERSION_1_12_0, has_priv_1_12), - ISA_EXT_DATA_ENTRY(shvstvecd, PRIV_VERSION_1_12_0, has_priv_1_12), + ISA_INTERNAL_EXT_DATA_ENTRY(shcounterenw, PRIV_VERSION_1_12_0, + has_priv_1_12), + ISA_INTERNAL_EXT_DATA_ENTRY(sha, PRIV_VERSION_1_12_0, ext_sha), + ISA_INTERNAL_EXT_DATA_ENTRY(shgatpa, PRIV_VERSION_1_12_0, has_priv_1_12), + ISA_INTERNAL_EXT_DATA_ENTRY(shtvala, PRIV_VERSION_1_12_0, has_priv_1_12), + ISA_INTERNAL_EXT_DATA_ENTRY(shvsatpa, PRIV_VERSION_1_12_0, has_priv_1_12), + ISA_INTERNAL_EXT_DATA_ENTRY(shvstvala, PRIV_VERSION_1_12_0, has_priv_1_12), + ISA_INTERNAL_EXT_DATA_ENTRY(shvstvecd, PRIV_VERSION_1_12_0, has_priv_1_12), ISA_EXT_DATA_ENTRY(smaia, PRIV_VERSION_1_12_0, ext_smaia), ISA_EXT_DATA_ENTRY(smcdeleg, PRIV_VERSION_1_13_0, ext_smcdeleg), ISA_EXT_DATA_ENTRY(smcntrpmf, PRIV_VERSION_1_12_0, ext_smcntrpmf), @@ -XXX,XX +XXX,XX @@ const RISCVIsaExtData isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(smstateen, PRIV_VERSION_1_12_0, ext_smstateen), ISA_EXT_DATA_ENTRY(ssaia, PRIV_VERSION_1_12_0, ext_ssaia), ISA_EXT_DATA_ENTRY(ssccfg, PRIV_VERSION_1_13_0, ext_ssccfg), - ISA_EXT_DATA_ENTRY(ssccptr, PRIV_VERSION_1_11_0, has_priv_1_11), + ISA_INTERNAL_EXT_DATA_ENTRY(ssccptr, PRIV_VERSION_1_11_0, has_priv_1_11), ISA_EXT_DATA_ENTRY(sscofpmf, PRIV_VERSION_1_12_0, ext_sscofpmf), - ISA_EXT_DATA_ENTRY(sscounterenw, PRIV_VERSION_1_12_0, has_priv_1_12), + ISA_INTERNAL_EXT_DATA_ENTRY(sscounterenw, PRIV_VERSION_1_12_0, + has_priv_1_12), ISA_EXT_DATA_ENTRY(sscsrind, PRIV_VERSION_1_12_0, ext_sscsrind), ISA_EXT_DATA_ENTRY(ssctr, PRIV_VERSION_1_12_0, ext_ssctr), ISA_EXT_DATA_ENTRY(ssdbltrp, PRIV_VERSION_1_13_0, ext_ssdbltrp), ISA_EXT_DATA_ENTRY(ssnpm, PRIV_VERSION_1_13_0, ext_ssnpm), ISA_EXT_DATA_ENTRY(sspm, PRIV_VERSION_1_13_0, ext_sspm), - ISA_EXT_DATA_ENTRY(ssstateen, PRIV_VERSION_1_12_0, ext_ssstateen), - ISA_EXT_DATA_ENTRY(ssstrict, PRIV_VERSION_1_12_0, has_priv_1_12), + ISA_INTERNAL_EXT_DATA_ENTRY(ssstateen, PRIV_VERSION_1_12_0, ext_ssstateen), + ISA_INTERNAL_EXT_DATA_ENTRY(ssstrict, PRIV_VERSION_1_12_0, has_priv_1_12), ISA_EXT_DATA_ENTRY(sstc, PRIV_VERSION_1_12_0, ext_sstc), - ISA_EXT_DATA_ENTRY(sstvala, PRIV_VERSION_1_12_0, has_priv_1_12), - ISA_EXT_DATA_ENTRY(sstvecd, PRIV_VERSION_1_12_0, has_priv_1_12), - ISA_EXT_DATA_ENTRY(ssu64xl, PRIV_VERSION_1_12_0, has_priv_1_12), + ISA_INTERNAL_EXT_DATA_ENTRY(sstvala, PRIV_VERSION_1_12_0, has_priv_1_12), + ISA_INTERNAL_EXT_DATA_ENTRY(sstvecd, PRIV_VERSION_1_12_0, has_priv_1_12), + ISA_INTERNAL_EXT_DATA_ENTRY(ssu64xl, PRIV_VERSION_1_12_0, has_priv_1_12), ISA_EXT_DATA_ENTRY(supm, PRIV_VERSION_1_13_0, ext_supm), ISA_EXT_DATA_ENTRY(svade, PRIV_VERSION_1_11_0, ext_svade), ISA_EXT_DATA_ENTRY(svadu, PRIV_VERSION_1_12_0, ext_svadu), @@ -XXX,XX +XXX,XX @@ const RISCVIsaExtData isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(svnapot, PRIV_VERSION_1_12_0, ext_svnapot), ISA_EXT_DATA_ENTRY(svpbmt, PRIV_VERSION_1_12_0, ext_svpbmt), ISA_EXT_DATA_ENTRY(svrsw60t59b, PRIV_VERSION_1_13_0, ext_svrsw60t59b), - ISA_EXT_DATA_ENTRY(svukte, PRIV_VERSION_1_13_0, ext_svukte), + ISA_EXPERIMENTAL_EXT_DATA_ENTRY(svukte, PRIV_VERSION_1_13_0, ext_svukte), ISA_EXT_DATA_ENTRY(svvptc, PRIV_VERSION_1_13_0, ext_svvptc), ISA_EXT_DATA_ENTRY(xlrbr, PRIV_VERSION_1_13_0, ext_xlrbr), ISA_EXT_DATA_ENTRY(xmipscbop, PRIV_VERSION_1_12_0, ext_xmipscbop), diff --git a/target/riscv/riscv-qmp-cmds.c b/target/riscv/riscv-qmp-cmds.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/riscv-qmp-cmds.c +++ b/target/riscv/riscv-qmp-cmds.c @@ -XXX,XX +XXX,XX @@ static void riscv_obj_add_qdict_prop(Object *obj, QDict *qdict_out, } } -static void riscv_obj_add_multiext_props(Object *obj, QDict *qdict_out, - const RISCVCPUMultiExtConfig *arr) +static void riscv_obj_add_multiext_props(Object *obj, QDict *qdict_out) { - for (int i = 0; arr[i].name != NULL; i++) { - riscv_obj_add_qdict_prop(obj, qdict_out, arr[i].name); - } -} + const RISCVIsaExtData *edata; -static void riscv_obj_add_named_feats_qdict(Object *obj, QDict *qdict_out) -{ - const RISCVCPUMultiExtConfig *named_cfg; - RISCVCPU *cpu = RISCV_CPU(obj); - QObject *value; - bool flag_val; - - for (int i = 0; riscv_cpu_named_features[i].name != NULL; i++) { - named_cfg = &riscv_cpu_named_features[i]; - flag_val = isa_ext_is_enabled(cpu, named_cfg->offset); - value = QOBJECT(qbool_from_bool(flag_val)); - - qdict_put_obj(qdict_out, named_cfg->name, value); + for (edata = isa_edata_arr; edata && edata->name; edata++) { + if (edata->prop_name) { + riscv_obj_add_qdict_prop(obj, qdict_out, edata->prop_name); + } } } @@ -XXX,XX +XXX,XX @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type, qdict_out = qdict_new(); - riscv_obj_add_multiext_props(obj, qdict_out, riscv_cpu_extensions); - riscv_obj_add_multiext_props(obj, qdict_out, riscv_cpu_experimental_exts); - riscv_obj_add_multiext_props(obj, qdict_out, riscv_cpu_vendor_exts); - riscv_obj_add_named_feats_qdict(obj, qdict_out); + riscv_obj_add_multiext_props(obj, qdict_out); riscv_obj_add_profiles_qdict(obj, qdict_out); /* Add our CPU boolean options too */ -- 2.53.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Commit 7e4f75cadf ("target/riscv/tcg: hide warn for named feats when disabling via priv_ver") changed the design of disable_priv_spec_isa_exts to not warn when disabling what we were calling "named features" at that time. Back in that time we were adding RVA22 profile support and we were dealing with a RVI innovation: named features. These can be define as cute names for pre-existing behavior/parameters, e.g. 'zic64b' means all cache blocks must have 64 bytes. They do get inserted in the riscv,isa but they are not "real" extensions because users shouldn't be setting them in the command line, or so we thought back then, and we attempted to model that by calling it "named features". This didn't age that well: ziccrse is a so called named feature as far as TCG goes, but then KVM had to treat it as a regular extension that can be user set and we made an exception: ziccrse is a named feature that is user set by KVM. "Named features" are regular extensions that might or might not be user set, and might or might not warrant special handling during realize() by setting other parameters. And we'll being treating them as such, which will culminate in the end of riscv_cpu_named_features[] array in the end. This reverts commit 7e4f75cadf44ee67809c7ca82645a289a5268966. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260512032926.1978818-5-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/tcg/tcg-cpu.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu) } isa_ext_update_enabled(cpu, edata->ext_enable_offset, false); - - /* - * Do not show user warnings for named features that users - * can't enable/disable in the command line. See commit - * 68c9e54bea for more info. - */ - if (cpu_cfg_offset_is_named_feat(edata->ext_enable_offset)) { - continue; - } #ifndef CONFIG_USER_ONLY warn_report("disabling %s extension for hart 0x%" PRIx64 " because privilege spec version does not match", @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_update_named_features(RISCVCPU *cpu) cpu->cfg.has_priv_1_13 = true; } + /* zic64b is 1.12 or later */ cpu->cfg.ext_zic64b = cpu->cfg.cbom_blocksize == 64 && cpu->cfg.cbop_blocksize == 64 && - cpu->cfg.cboz_blocksize == 64; + cpu->cfg.cboz_blocksize == 64 && + cpu->cfg.has_priv_1_12; cpu->cfg.ext_ssstateen = cpu->cfg.ext_smstateen; -- 2.53.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> We're using both isa_edata_arr[] and riscv_cpu_named_features[] to find an extension name based on a cfg offset. This is reminiscent of a past where isa_edata_arr[] didn't include entries for internal extensions. At this point we can use just isa_edata_arr[]. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260512032926.1978818-6-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/tcg/tcg-cpu.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -XXX,XX +XXX,XX @@ static int cpu_cfg_ext_get_min_version(uint32_t ext_offset) static const char *cpu_cfg_ext_get_name(uint32_t ext_offset) { - const RISCVCPUMultiExtConfig *feat; const RISCVIsaExtData *edata; for (edata = isa_edata_arr; edata->name != NULL; edata++) { @@ -XXX,XX +XXX,XX @@ static const char *cpu_cfg_ext_get_name(uint32_t ext_offset) } } - for (feat = riscv_cpu_named_features; feat->name != NULL; feat++) { - if (feat->offset == ext_offset) { - return feat->name; - } - } - g_assert_not_reached(); } -- 2.53.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Deprecate riscv_cpu_enable_named_feat() by creating implied rules for 'sha' and 'ssstateen'. 'zic64' is always true given that our default block size is set to 64. With this change we homogeneize extension handling when enabling profiles. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260512032926.1978818-7-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.c | 25 ++++++++++++++++++++++-- target/riscv/tcg/tcg-cpu.c | 40 -------------------------------------- 2 files changed, 23 insertions(+), 42 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -XXX,XX +XXX,XX @@ static RISCVCPUImpliedExtsRule ZVKSG_IMPLIED = { }, }; +static RISCVCPUImpliedExtsRule SHA_IMPLIED = { + .ext = CPU_CFG_OFFSET(ext_sha), + .implied_misa_exts = RVH, + .implied_multi_exts = { + CPU_CFG_OFFSET(ext_smstateen), + CPU_CFG_OFFSET(ext_ssstateen), + + RISCV_IMPLIED_EXTS_RULE_END + }, +}; + static RISCVCPUImpliedExtsRule SSCFG_IMPLIED = { .ext = CPU_CFG_OFFSET(ext_ssccfg), .implied_multi_exts = { @@ -XXX,XX +XXX,XX @@ static RISCVCPUImpliedExtsRule SSCTR_IMPLIED = { }, }; +static RISCVCPUImpliedExtsRule SSSTATEEN_IMPLIED = { + .ext = CPU_CFG_OFFSET(ext_ssstateen), + .implied_multi_exts = { + CPU_CFG_OFFSET(ext_smstateen), + + RISCV_IMPLIED_EXTS_RULE_END + }, +}; + static RISCVCPUImpliedExtsRule ZVFBFA_IMPLIED = { .ext = CPU_CFG_OFFSET(ext_zvfbfa), .implied_multi_exts = { @@ -XXX,XX +XXX,XX @@ RISCVCPUImpliedExtsRule *riscv_multi_ext_implied_rules[] = { &ZVFBFA_IMPLIED, &ZVFBFMIN_IMPLIED, &ZVFBFWMA_IMPLIED, &ZVFH_IMPLIED, &ZVFHMIN_IMPLIED, &ZVKN_IMPLIED, &ZVKNC_IMPLIED, &ZVKNG_IMPLIED, &ZVKNHB_IMPLIED, - &ZVKS_IMPLIED, &ZVKSC_IMPLIED, &ZVKSG_IMPLIED, &SSCFG_IMPLIED, - &SUPM_IMPLIED, &SSPM_IMPLIED, &SMCTR_IMPLIED, &SSCTR_IMPLIED, + &ZVKS_IMPLIED, &ZVKSC_IMPLIED, &ZVKSG_IMPLIED, &SHA_IMPLIED, + &SSCFG_IMPLIED, &SUPM_IMPLIED, &SSPM_IMPLIED, &SMCTR_IMPLIED, + &SSCTR_IMPLIED, &SSSTATEEN_IMPLIED, NULL }; diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -XXX,XX +XXX,XX @@ static const char *cpu_cfg_ext_get_name(uint32_t ext_offset) g_assert_not_reached(); } -static bool cpu_cfg_offset_is_named_feat(uint32_t ext_offset) -{ - const RISCVCPUMultiExtConfig *feat; - - for (feat = riscv_cpu_named_features; feat->name != NULL; feat++) { - if (feat->offset == ext_offset) { - return true; - } - } - - return false; -} - -static void riscv_cpu_enable_named_feat(RISCVCPU *cpu, uint32_t feat_offset) -{ - /* - * All other named features are already enabled - * in riscv_tcg_cpu_instance_init(). - */ - switch (feat_offset) { - case CPU_CFG_OFFSET(ext_zic64b): - cpu->cfg.cbom_blocksize = 64; - cpu->cfg.cbop_blocksize = 64; - cpu->cfg.cboz_blocksize = 64; - break; - case CPU_CFG_OFFSET(ext_sha): - if (!cpu_misa_ext_is_user_set(RVH)) { - riscv_cpu_write_misa_bit(cpu, RVH, true); - } - /* fallthrough */ - case CPU_CFG_OFFSET(ext_ssstateen): - cpu->cfg.ext_smstateen = true; - break; - } -} - static void cpu_bump_multi_ext_priv_ver(CPURISCVState *env, uint32_t ext_offset) { @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_set_profile(RISCVCPU *cpu, ext_offset = profile->ext_offsets[i]; if (profile->enabled) { - if (cpu_cfg_offset_is_named_feat(ext_offset)) { - riscv_cpu_enable_named_feat(cpu, ext_offset); - } - cpu_bump_multi_ext_priv_ver(&cpu->env, ext_offset); } -- 2.53.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> This array has no uses left. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260512032926.1978818-8-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.h | 1 - target/riscv/cpu.c | 26 -------------------------- target/riscv/tcg/tcg-cpu.c | 4 ++-- 3 files changed, 2 insertions(+), 29 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -XXX,XX +XXX,XX @@ typedef struct RISCVCPUMultiExtConfig { extern const RISCVCPUMultiExtConfig riscv_cpu_extensions[]; extern const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[]; extern const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[]; -extern const RISCVCPUMultiExtConfig riscv_cpu_named_features[]; typedef struct isa_ext_data { const char *name; diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -XXX,XX +XXX,XX @@ const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[] = { { }, }; -/* - * 'Named features' is the name we give to extensions that we - * don't want to expose to users. They are either immutable - * (always enabled/disable) or they'll vary depending on - * the resulting CPU state. - * - * Some of them are always enabled depending on priv version - * of the CPU and are declared directly in isa_edata_arr[]. - * The ones listed here have special checks during finalize() - * time and require their own flags like regular extensions. - * See riscv_cpu_update_named_features() for more info. - */ -const RISCVCPUMultiExtConfig riscv_cpu_named_features[] = { - MULTI_EXT_CFG_BOOL("zic64b", ext_zic64b, true), - MULTI_EXT_CFG_BOOL("ssstateen", ext_ssstateen, true), - MULTI_EXT_CFG_BOOL("sha", ext_sha, true), - - /* - * 'ziccrse' has its own flag because the KVM driver - * wants to enable/disable it on its own accord. - */ - MULTI_EXT_CFG_BOOL("ziccrse", ext_ziccrse, true), - - { }, -}; - static void cpu_set_prop_err(RISCVCPU *cpu, const char *propname, Error **errp) { diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu) } } -static void riscv_cpu_update_named_features(RISCVCPU *cpu) +static void riscv_cpu_update_cfg(RISCVCPU *cpu) { if (cpu->env.priv_ver >= PRIV_VERSION_1_11_0) { cpu->cfg.has_priv_1_11 = true; @@ -XXX,XX +XXX,XX @@ void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp) return; } - riscv_cpu_update_named_features(cpu); + riscv_cpu_update_cfg(cpu); riscv_cpu_validate_profiles(cpu); if (cpu->cfg.ext_smepmp && !cpu->cfg.pmp) { -- 2.53.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> The non-standard extensions, in this particular function the vendor extensions, are all riscv,isa names that starts with 'x'. In theory this is a bit slower than using riscv_cpu_vendor_exts (isa_edata_arr is longer) but riscv_cpu_update_misa_x() is executed only once during finalize(), i.e. not a hot path. We're accepting a tiny performance hit as as a tradeoff for the code simplication we'll have later by removing all riscv_cpu_* arrays. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260512032926.1978818-9-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/tcg/tcg-cpu.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_update_misa_c(RISCVCPU *cpu) static void riscv_cpu_update_misa_x(RISCVCPU *cpu) { CPURISCVState *env = &cpu->env; - const RISCVCPUMultiExtConfig *arr = riscv_cpu_vendor_exts; + const RISCVIsaExtData *edata; - for (int i = 0; arr[i].name != NULL; i++) { - if (isa_ext_is_enabled(cpu, arr[i].offset)) { + for (edata = isa_edata_arr; edata && edata->name; edata++) { + if (edata->name[0] == 'x' + && isa_ext_is_enabled(cpu, edata->ext_enable_offset)) { riscv_cpu_set_misa_ext(env, env->misa_ext | RVX); break; } -- 2.53.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Use isa_edata_arr[] directly instead of going through 3 different arrays to populate the unavailable KVM properties. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260512032926.1978818-10-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/kvm/kvm-cpu.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/kvm/kvm-cpu.c +++ b/target/riscv/kvm/kvm-cpu.c @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_add_kvm_unavail_prop(Object *obj, const char *prop_name) NULL, (void *)prop_name); } -static void riscv_cpu_add_kvm_unavail_prop_array(Object *obj, - const RISCVCPUMultiExtConfig *array) -{ - const RISCVCPUMultiExtConfig *prop; - - g_assert(array); - - for (prop = array; prop && prop->name; prop++) { - riscv_cpu_add_kvm_unavail_prop(obj, prop->name); - } -} - static void kvm_riscv_add_cpu_user_properties(Object *cpu_obj) { + const RISCVIsaExtData *edata; int i; riscv_add_satp_mode_properties(cpu_obj); @@ -XXX,XX +XXX,XX @@ static void kvm_riscv_add_cpu_user_properties(Object *cpu_obj) NULL, multi_cfg); } - riscv_cpu_add_kvm_unavail_prop_array(cpu_obj, riscv_cpu_extensions); - riscv_cpu_add_kvm_unavail_prop_array(cpu_obj, riscv_cpu_vendor_exts); - riscv_cpu_add_kvm_unavail_prop_array(cpu_obj, riscv_cpu_experimental_exts); + /* + * Mark all isa_edata_arr properties that collides with + * a KVM property as unavailable. + */ + for (edata = isa_edata_arr; edata && edata->name; edata++) { + if (edata->prop_name) { + riscv_cpu_add_kvm_unavail_prop(cpu_obj, edata->prop_name); + } + } /* We don't have the needed KVM support for profiles */ for (i = 0; riscv_profiles[i] != NULL; i++) { -- 2.53.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Use isa_edata_arr[] to enable all feasible extensions. Filter experimental and vendor extensions by checking if the riscv,isa or the prop name starts with 'x'. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260512032926.1978818-11-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/tcg/tcg-cpu.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -XXX,XX +XXX,XX @@ static void riscv_init_max_cpu_extensions(Object *obj) { RISCVCPU *cpu = RISCV_CPU(obj); CPURISCVState *env = &cpu->env; - const RISCVCPUMultiExtConfig *prop; + const RISCVIsaExtData *edata; /* Enable RVG and RVV that are disabled by default */ riscv_cpu_set_misa_ext(env, env->misa_ext | RVB | RVG | RVV); - for (prop = riscv_cpu_extensions; prop && prop->name; prop++) { - isa_ext_update_enabled(cpu, prop->offset, true); + for (edata = isa_edata_arr; edata && edata->name; edata++) { + if (edata->name[0] == 'x' + || (edata->prop_name && edata->prop_name[0] == 'x')) { + continue; + } + + isa_ext_update_enabled(cpu, edata->ext_enable_offset, true); } /* -- 2.53.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> The cpu_get_multi_ext_cfg/cpu_set_multi_ext_cfg callbacks are using a RISCVCPUMultiExtConfig pointer as opaque, but internally we're just using multi_ext_cfg->offset. Use multi_ext_cfg->offset as opaque instead. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260512032926.1978818-12-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/tcg/tcg-cpu.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_add_profiles(Object *cpu_obj) static void cpu_set_multi_ext_cfg(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { - const RISCVCPUMultiExtConfig *multi_ext_cfg = opaque; RISCVCPU *cpu = RISCV_CPU(obj); + uint32_t cfg_offset = *(uint32_t *)opaque; bool vendor_cpu = riscv_cpu_is_vendor(obj); bool prev_val, value; @@ -XXX,XX +XXX,XX @@ static void cpu_set_multi_ext_cfg(Object *obj, Visitor *v, const char *name, return; } - cpu_cfg_ext_add_user_opt(multi_ext_cfg->offset, value); + cpu_cfg_ext_add_user_opt(cfg_offset, value); - prev_val = isa_ext_is_enabled(cpu, multi_ext_cfg->offset); + prev_val = isa_ext_is_enabled(cpu, cfg_offset); if (value == prev_val) { return; @@ -XXX,XX +XXX,XX @@ static void cpu_set_multi_ext_cfg(Object *obj, Visitor *v, const char *name, } if (value) { - cpu_bump_multi_ext_priv_ver(&cpu->env, multi_ext_cfg->offset); + cpu_bump_multi_ext_priv_ver(&cpu->env, cfg_offset); } - isa_ext_update_enabled(cpu, multi_ext_cfg->offset, value); + isa_ext_update_enabled(cpu, cfg_offset, value); } static void cpu_get_multi_ext_cfg(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { - const RISCVCPUMultiExtConfig *multi_ext_cfg = opaque; - bool value = isa_ext_is_enabled(RISCV_CPU(obj), multi_ext_cfg->offset); + uint32_t cfg_offset = *(uint32_t *)opaque; + bool value = isa_ext_is_enabled(RISCV_CPU(obj), cfg_offset); visit_type_bool(v, name, &value, errp); } @@ -XXX,XX +XXX,XX @@ static void cpu_add_multi_ext_prop(Object *cpu_obj, object_property_add(cpu_obj, multi_cfg->name, "bool", cpu_get_multi_ext_cfg, cpu_set_multi_ext_cfg, - NULL, (void *)multi_cfg); + NULL, (void *)&multi_cfg->offset); if (!generic_cpu) { return; -- 2.53.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Do not rely on riscv_cpu_* arrays to set rv32/rv64 CPU defaults - add them to the CPU definition like we do with all other CPUs (aside from 'max'). Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260512032926.1978818-13-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.c | 40 ++++++++++++++++++++++++++++++++++++++ target/riscv/tcg/tcg-cpu.c | 14 ------------- 2 files changed, 40 insertions(+), 14 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -XXX,XX +XXX,XX @@ static const TypeInfo riscv_cpu_type_infos[] = { DEFINE_RISCV_CPU(TYPE_RISCV_CPU_BASE32, TYPE_RISCV_DYNAMIC_CPU, .cfg.max_satp_mode = VM_1_10_SV32, .misa_mxl_max = MXL_RV32, + + /* Default extensions as of QEMU 11.1. */ + .cfg.ext_zicbom = true, + .cfg.ext_zicbop = true, + .cfg.ext_zicboz = true, + .cfg.ext_zicntr = true, + .cfg.ext_zicsr = true, + .cfg.ext_zifencei = true, + .cfg.ext_zihintntl = true, + .cfg.ext_zihintpause = true, + .cfg.ext_zihpm = true, + .cfg.ext_zawrs = true, + .cfg.ext_zfa = true, + .cfg.ext_zba = true, + .cfg.ext_zbb = true, + .cfg.ext_zbc = true, + .cfg.ext_zbs = true, + .cfg.ext_sstc = true, + .cfg.ext_svadu = true, + .cfg.ext_svvptc = true, ), DEFINE_RISCV_CPU(TYPE_RISCV_CPU_IBEX, TYPE_RISCV_VENDOR_CPU, @@ -XXX,XX +XXX,XX @@ static const TypeInfo riscv_cpu_type_infos[] = { DEFINE_RISCV_CPU(TYPE_RISCV_CPU_BASE64, TYPE_RISCV_DYNAMIC_CPU, .cfg.max_satp_mode = VM_1_10_SV57, .misa_mxl_max = MXL_RV64, + + /* Default extensions as of QEMU 11.1. */ + .cfg.ext_zicbom = true, + .cfg.ext_zicbop = true, + .cfg.ext_zicboz = true, + .cfg.ext_zicntr = true, + .cfg.ext_zicsr = true, + .cfg.ext_zifencei = true, + .cfg.ext_zihintntl = true, + .cfg.ext_zihintpause = true, + .cfg.ext_zihpm = true, + .cfg.ext_zawrs = true, + .cfg.ext_zfa = true, + .cfg.ext_zba = true, + .cfg.ext_zbb = true, + .cfg.ext_zbc = true, + .cfg.ext_zbs = true, + .cfg.ext_sstc = true, + .cfg.ext_svadu = true, + .cfg.ext_svvptc = true, ), DEFINE_RISCV_CPU(TYPE_RISCV_CPU_SIFIVE_E51, TYPE_RISCV_CPU_SIFIVE_E, diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -XXX,XX +XXX,XX @@ static void cpu_get_multi_ext_cfg(Object *obj, Visitor *v, const char *name, static void cpu_add_multi_ext_prop(Object *cpu_obj, const RISCVCPUMultiExtConfig *multi_cfg) { - bool generic_cpu = riscv_cpu_is_generic(cpu_obj); - object_property_add(cpu_obj, multi_cfg->name, "bool", cpu_get_multi_ext_cfg, cpu_set_multi_ext_cfg, NULL, (void *)&multi_cfg->offset); - - if (!generic_cpu) { - return; - } - - /* - * Set def val directly instead of using - * object_property_set_bool() to save the set() - * callback hash for user inputs. - */ - isa_ext_update_enabled(RISCV_CPU(cpu_obj), multi_cfg->offset, - multi_cfg->enabled); } static void riscv_cpu_add_multiext_prop_array(Object *obj, -- 2.53.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> This change has been done twice now: one in riscv-qmp-cmds, another in the KVM. We're now ready to do it for TCG. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260512032926.1978818-14-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/tcg/tcg-cpu.c | 34 ++++++++++------------------------ 1 file changed, 10 insertions(+), 24 deletions(-) diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -XXX,XX +XXX,XX @@ static void cpu_get_multi_ext_cfg(Object *obj, Visitor *v, const char *name, visit_type_bool(v, name, &value, errp); } -static void cpu_add_multi_ext_prop(Object *cpu_obj, - const RISCVCPUMultiExtConfig *multi_cfg) -{ - object_property_add(cpu_obj, multi_cfg->name, "bool", - cpu_get_multi_ext_cfg, - cpu_set_multi_ext_cfg, - NULL, (void *)&multi_cfg->offset); -} - -static void riscv_cpu_add_multiext_prop_array(Object *obj, - const RISCVCPUMultiExtConfig *array) -{ - const RISCVCPUMultiExtConfig *prop; - - g_assert(array); - - for (prop = array; prop && prop->name; prop++) { - cpu_add_multi_ext_prop(obj, prop); - } -} - /* * Add CPU properties with user-facing flags. * @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_add_multiext_prop_array(Object *obj, */ static void riscv_cpu_add_user_properties(Object *obj) { + const RISCVIsaExtData *edata; + #ifndef CONFIG_USER_ONLY riscv_add_satp_mode_properties(obj); #endif riscv_cpu_add_misa_properties(obj); - riscv_cpu_add_multiext_prop_array(obj, riscv_cpu_extensions); - riscv_cpu_add_multiext_prop_array(obj, riscv_cpu_vendor_exts); - riscv_cpu_add_multiext_prop_array(obj, riscv_cpu_experimental_exts); + for (edata = isa_edata_arr; edata && edata->name; edata++) { + if (edata->prop_name) { + object_property_add(obj, edata->prop_name, "bool", + cpu_get_multi_ext_cfg, + cpu_set_multi_ext_cfg, + NULL, (void *)&edata->ext_enable_offset); + } + } riscv_cpu_add_profiles(obj); } -- 2.53.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> There is no more uses left for these arrays. isa_edata_arr[] is doing everything we need, making our lives a little easier when adding new extensions. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260512032926.1978818-15-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.h | 10 --- target/riscv/cpu.c | 159 --------------------------------------------- 2 files changed, 169 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -XXX,XX +XXX,XX @@ bool isa_ext_is_enabled(RISCVCPU *cpu, uint32_t ext_offset); void riscv_cpu_set_misa_ext(CPURISCVState *env, uint32_t ext); bool riscv_cpu_is_vendor(Object *cpu_obj); -typedef struct RISCVCPUMultiExtConfig { - const char *name; - uint32_t offset; - bool enabled; -} RISCVCPUMultiExtConfig; - -extern const RISCVCPUMultiExtConfig riscv_cpu_extensions[]; -extern const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[]; -extern const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[]; - typedef struct isa_ext_data { const char *name; const char *prop_name; diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -XXX,XX +XXX,XX @@ const char *riscv_get_misa_ext_description(uint32_t bit) return val; } -#define MULTI_EXT_CFG_BOOL(_name, _prop, _defval) \ - {.name = _name, .offset = CPU_CFG_OFFSET(_prop), \ - .enabled = _defval} - -const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = { - /* Defaults for standard extensions */ - MULTI_EXT_CFG_BOOL("sscofpmf", ext_sscofpmf, false), - MULTI_EXT_CFG_BOOL("smcntrpmf", ext_smcntrpmf, false), - MULTI_EXT_CFG_BOOL("smcsrind", ext_smcsrind, false), - MULTI_EXT_CFG_BOOL("smcdeleg", ext_smcdeleg, false), - MULTI_EXT_CFG_BOOL("sscsrind", ext_sscsrind, false), - MULTI_EXT_CFG_BOOL("ssccfg", ext_ssccfg, false), - MULTI_EXT_CFG_BOOL("smctr", ext_smctr, false), - MULTI_EXT_CFG_BOOL("ssctr", ext_ssctr, false), - MULTI_EXT_CFG_BOOL("zifencei", ext_zifencei, true), - MULTI_EXT_CFG_BOOL("zicfilp", ext_zicfilp, false), - MULTI_EXT_CFG_BOOL("zicfiss", ext_zicfiss, false), - MULTI_EXT_CFG_BOOL("zicsr", ext_zicsr, true), - MULTI_EXT_CFG_BOOL("zihintntl", ext_zihintntl, true), - MULTI_EXT_CFG_BOOL("zihintpause", ext_zihintpause, true), - MULTI_EXT_CFG_BOOL("zimop", ext_zimop, false), - MULTI_EXT_CFG_BOOL("zcmop", ext_zcmop, false), - MULTI_EXT_CFG_BOOL("zacas", ext_zacas, false), - MULTI_EXT_CFG_BOOL("zama16b", ext_zama16b, false), - MULTI_EXT_CFG_BOOL("zabha", ext_zabha, false), - MULTI_EXT_CFG_BOOL("zaamo", ext_zaamo, false), - MULTI_EXT_CFG_BOOL("zalasr", ext_zalasr, false), - MULTI_EXT_CFG_BOOL("zalrsc", ext_zalrsc, false), - MULTI_EXT_CFG_BOOL("zawrs", ext_zawrs, true), - MULTI_EXT_CFG_BOOL("zfa", ext_zfa, true), - MULTI_EXT_CFG_BOOL("zfbfmin", ext_zfbfmin, false), - MULTI_EXT_CFG_BOOL("zfh", ext_zfh, false), - MULTI_EXT_CFG_BOOL("zfhmin", ext_zfhmin, false), - MULTI_EXT_CFG_BOOL("zve32f", ext_zve32f, false), - MULTI_EXT_CFG_BOOL("zve32x", ext_zve32x, false), - MULTI_EXT_CFG_BOOL("zve64f", ext_zve64f, false), - MULTI_EXT_CFG_BOOL("zve64d", ext_zve64d, false), - MULTI_EXT_CFG_BOOL("zve64x", ext_zve64x, false), - MULTI_EXT_CFG_BOOL("zvfbfa", ext_zvfbfa, false), - MULTI_EXT_CFG_BOOL("zvfbfmin", ext_zvfbfmin, false), - MULTI_EXT_CFG_BOOL("zvfbfwma", ext_zvfbfwma, false), - MULTI_EXT_CFG_BOOL("zvfh", ext_zvfh, false), - MULTI_EXT_CFG_BOOL("zvfhmin", ext_zvfhmin, false), - MULTI_EXT_CFG_BOOL("sstc", ext_sstc, true), - MULTI_EXT_CFG_BOOL("ssnpm", ext_ssnpm, false), - MULTI_EXT_CFG_BOOL("sspm", ext_sspm, false), - MULTI_EXT_CFG_BOOL("supm", ext_supm, false), - - MULTI_EXT_CFG_BOOL("smaia", ext_smaia, false), - MULTI_EXT_CFG_BOOL("smdbltrp", ext_smdbltrp, false), - MULTI_EXT_CFG_BOOL("smepmp", ext_smepmp, false), - MULTI_EXT_CFG_BOOL("smpmpmt", ext_smpmpmt, false), - MULTI_EXT_CFG_BOOL("smrnmi", ext_smrnmi, false), - MULTI_EXT_CFG_BOOL("smmpm", ext_smmpm, false), - MULTI_EXT_CFG_BOOL("smnpm", ext_smnpm, false), - MULTI_EXT_CFG_BOOL("smstateen", ext_smstateen, false), - MULTI_EXT_CFG_BOOL("ssaia", ext_ssaia, false), - MULTI_EXT_CFG_BOOL("ssdbltrp", ext_ssdbltrp, false), - MULTI_EXT_CFG_BOOL("svade", ext_svade, false), - MULTI_EXT_CFG_BOOL("svadu", ext_svadu, true), - MULTI_EXT_CFG_BOOL("svinval", ext_svinval, false), - MULTI_EXT_CFG_BOOL("svnapot", ext_svnapot, false), - MULTI_EXT_CFG_BOOL("svpbmt", ext_svpbmt, false), - MULTI_EXT_CFG_BOOL("svrsw60t59b", ext_svrsw60t59b, false), - MULTI_EXT_CFG_BOOL("svvptc", ext_svvptc, true), - - MULTI_EXT_CFG_BOOL("zicntr", ext_zicntr, true), - MULTI_EXT_CFG_BOOL("zihpm", ext_zihpm, true), - MULTI_EXT_CFG_BOOL("zilsd", ext_zilsd, false), - - MULTI_EXT_CFG_BOOL("zba", ext_zba, true), - MULTI_EXT_CFG_BOOL("zbb", ext_zbb, true), - MULTI_EXT_CFG_BOOL("zbc", ext_zbc, true), - MULTI_EXT_CFG_BOOL("zbkb", ext_zbkb, false), - MULTI_EXT_CFG_BOOL("zbkc", ext_zbkc, false), - MULTI_EXT_CFG_BOOL("zbkx", ext_zbkx, false), - MULTI_EXT_CFG_BOOL("zbs", ext_zbs, true), - MULTI_EXT_CFG_BOOL("zk", ext_zk, false), - MULTI_EXT_CFG_BOOL("zkn", ext_zkn, false), - MULTI_EXT_CFG_BOOL("zknd", ext_zknd, false), - MULTI_EXT_CFG_BOOL("zkne", ext_zkne, false), - MULTI_EXT_CFG_BOOL("zknh", ext_zknh, false), - MULTI_EXT_CFG_BOOL("zkr", ext_zkr, false), - MULTI_EXT_CFG_BOOL("zks", ext_zks, false), - MULTI_EXT_CFG_BOOL("zksed", ext_zksed, false), - MULTI_EXT_CFG_BOOL("zksh", ext_zksh, false), - MULTI_EXT_CFG_BOOL("zkt", ext_zkt, false), - MULTI_EXT_CFG_BOOL("ztso", ext_ztso, false), - - MULTI_EXT_CFG_BOOL("zdinx", ext_zdinx, false), - MULTI_EXT_CFG_BOOL("zfinx", ext_zfinx, false), - MULTI_EXT_CFG_BOOL("zhinx", ext_zhinx, false), - MULTI_EXT_CFG_BOOL("zhinxmin", ext_zhinxmin, false), - - MULTI_EXT_CFG_BOOL("zicbom", ext_zicbom, true), - MULTI_EXT_CFG_BOOL("zicbop", ext_zicbop, true), - MULTI_EXT_CFG_BOOL("zicboz", ext_zicboz, true), - - MULTI_EXT_CFG_BOOL("zmmul", ext_zmmul, false), - - MULTI_EXT_CFG_BOOL("zca", ext_zca, false), - MULTI_EXT_CFG_BOOL("zcb", ext_zcb, false), - MULTI_EXT_CFG_BOOL("zcd", ext_zcd, false), - MULTI_EXT_CFG_BOOL("zce", ext_zce, false), - MULTI_EXT_CFG_BOOL("zcf", ext_zcf, false), - MULTI_EXT_CFG_BOOL("zcmp", ext_zcmp, false), - MULTI_EXT_CFG_BOOL("zcmt", ext_zcmt, false), - MULTI_EXT_CFG_BOOL("zicond", ext_zicond, false), - MULTI_EXT_CFG_BOOL("zclsd", ext_zclsd, false), - - /* Vector cryptography extensions */ - MULTI_EXT_CFG_BOOL("zvbb", ext_zvbb, false), - MULTI_EXT_CFG_BOOL("zvbc", ext_zvbc, false), - MULTI_EXT_CFG_BOOL("zvkb", ext_zvkb, false), - MULTI_EXT_CFG_BOOL("zvkg", ext_zvkg, false), - MULTI_EXT_CFG_BOOL("zvkned", ext_zvkned, false), - MULTI_EXT_CFG_BOOL("zvknha", ext_zvknha, false), - MULTI_EXT_CFG_BOOL("zvknhb", ext_zvknhb, false), - MULTI_EXT_CFG_BOOL("zvksed", ext_zvksed, false), - MULTI_EXT_CFG_BOOL("zvksh", ext_zvksh, false), - MULTI_EXT_CFG_BOOL("zvkt", ext_zvkt, false), - MULTI_EXT_CFG_BOOL("zvkn", ext_zvkn, false), - MULTI_EXT_CFG_BOOL("zvknc", ext_zvknc, false), - MULTI_EXT_CFG_BOOL("zvkng", ext_zvkng, false), - MULTI_EXT_CFG_BOOL("zvks", ext_zvks, false), - MULTI_EXT_CFG_BOOL("zvksc", ext_zvksc, false), - MULTI_EXT_CFG_BOOL("zvksg", ext_zvksg, false), - - { }, -}; - -const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[] = { - MULTI_EXT_CFG_BOOL("xtheadba", ext_xtheadba, false), - MULTI_EXT_CFG_BOOL("xtheadbb", ext_xtheadbb, false), - MULTI_EXT_CFG_BOOL("xtheadbs", ext_xtheadbs, false), - MULTI_EXT_CFG_BOOL("xtheadcmo", ext_xtheadcmo, false), - MULTI_EXT_CFG_BOOL("xtheadcondmov", ext_xtheadcondmov, false), - MULTI_EXT_CFG_BOOL("xtheadfmemidx", ext_xtheadfmemidx, false), - MULTI_EXT_CFG_BOOL("xtheadfmv", ext_xtheadfmv, false), - MULTI_EXT_CFG_BOOL("xtheadmac", ext_xtheadmac, false), - MULTI_EXT_CFG_BOOL("xtheadmemidx", ext_xtheadmemidx, false), - MULTI_EXT_CFG_BOOL("xtheadmempair", ext_xtheadmempair, false), - MULTI_EXT_CFG_BOOL("xtheadsync", ext_xtheadsync, false), - MULTI_EXT_CFG_BOOL("xventanacondops", ext_XVentanaCondOps, false), - MULTI_EXT_CFG_BOOL("xmipscbop", ext_xmipscbop, false), - MULTI_EXT_CFG_BOOL("xmipscmov", ext_xmipscmov, false), - MULTI_EXT_CFG_BOOL("xmipslsp", ext_xmipslsp, false), - MULTI_EXT_CFG_BOOL("xlrbr", ext_xlrbr, false), - - { }, -}; - -/* These are experimental so mark with 'x-' */ -const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[] = { - MULTI_EXT_CFG_BOOL("x-svukte", ext_svukte, false), - - { }, -}; - static void cpu_set_prop_err(RISCVCPU *cpu, const char *propname, Error **errp) { -- 2.53.0
From: Fangyu Yu <fangyu.yu@linux.alibaba.com> Fix IOCOUNTINH.CY toggle detection by comparing normalized CY bit rather than XORing whole register with boolean. Fixes: 2cf2a6c027ba ("hw/riscv/riscv-iommu: add IOCOUNTINH mmio writes") Signed-off-by: Fangyu Yu <fangyu.yu@linux.alibaba.com> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Nutty Liu <nutty.liu@hotmail.com> Message-ID: <20260509074941.99295-1-fangyu.yu@linux.alibaba.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/riscv/riscv-iommu-hpm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/riscv/riscv-iommu-hpm.c b/hw/riscv/riscv-iommu-hpm.c index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/riscv-iommu-hpm.c +++ b/hw/riscv/riscv-iommu-hpm.c @@ -XXX,XX +XXX,XX @@ void riscv_iommu_process_iocntinh_cy(RISCVIOMMUState *s, bool prev_cy_inh) s, RISCV_IOMMU_REG_IOCOUNTINH); /* We only need to process CY bit toggle. */ - if (!(inhibit ^ prev_cy_inh)) { + bool cy_inh = !!(inhibit & RISCV_IOMMU_IOCOUNTINH_CY); + if (cy_inh == prev_cy_inh) { return; } -- 2.53.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> The priv spec defines, for RV64, that the upper 10 bits of pmpaddr0-pmpaddr63 are WARL and are supposed to be cleared. After this patch, using the bug reproducer in [1], writing ffffffffffffffff in pmpaddr0 and reading it back now results in 003fffffffffffff. Here's the 'diff -cp' dump before and after this change: *************** IN: *** 5272,5278 **** pmpcfg10 0000000000000000 pmpcfg12 0000000000000000 pmpcfg14 0000000000000000 ! pmpaddr0 ffffffffffffffff pmpaddr1 0000000000000000 pmpaddr2 0000000000000000 pmpaddr3 0000000000000000 Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260514123342.2139464-1-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/csr.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -XXX,XX +XXX,XX @@ static RISCVException read_pmpaddr(CPURISCVState *env, int csrno, target_ulong *val) { *val = pmpaddr_csr_read(env, csrno - CSR_PMPADDR0); + + /* + * For RV64, bits 54-63 of the address registers + * PMPAADDR(0-63) is a WARL zero field (priv spec, + * section "Physical Memory Protection CSRs"). + * + * We'll have to add an annoying TARGET_RISCV64 gate + * here to avoid complaints about masking bits 0-53 + * of a potential 32 bit target_ulong '*var'. + */ +#ifdef TARGET_RISCV64 + if (env->misa_mxl == MXL_RV64 + && csrno >= CSR_PMPADDR0 && csrno <= CSR_PMPADDR63) { + target_ulong read_mask = MAKE_64BIT_MASK(0, 54); + *val &= read_mask; + } +#endif return RISCV_EXCP_NONE; } -- 2.53.0
From: Zishun Yi <vulab@iscas.ac.cn> In build_rimt(), the calculation of `num_ids` for the ID mapping array incorrectly uses the same formula (`0xffff - s->pci_iommu_bdf`) for both System IOMMU and PCI IOMMU topologies. For a System IOMMU, `s->pci_iommu_bdf` is 0. This results in a `num_ids` value of 0xffff. Since the source ID base starts at 0, the mapping only covers Requester IDs from 0 to 0xfffe. The final valid PCI Requester ID (0xffff) is erroneously omitted from the RIMT table. Fix this by decoupling the `num_ids` calculation. For System IOMMUs, explicitly set `num_ids` to 0x10000 to cover the entire PCI Requester ID space. This issue was discovered and reported by SpecHunter, an AI-driven architecture specification analysis tool. Link: https://github.com/yizishun/rv-isa-sec/blob/c78dacf66c8acd677b3538c837fde310bb71a97b/output/riscv-server-platform/pr-102/qemu.txt#L32 Signed-off-by: Zishun Yi <vulab@iscas.ac.cn> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260512062310.348208-1-vulab@iscas.ac.cn> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/riscv/virt-acpi-build.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/riscv/virt-acpi-build.c b/hw/riscv/virt-acpi-build.c index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/virt-acpi-build.c +++ b/hw/riscv/virt-acpi-build.c @@ -XXX,XX +XXX,XX @@ static void build_rimt(GArray *table_data, BIOSLinker *linker, range = &g_array_index(iommu_idmaps, AcpiRimtIdMapping, i); if (virt_is_iommu_sys_enabled(s)) { range->source_id_base = 0; + range->num_ids = 0x10000; } else { range->source_id_base = s->pci_iommu_bdf + 1; + range->num_ids = 0xffff - s->pci_iommu_bdf; } - range->num_ids = 0xffff - s->pci_iommu_bdf; build_rimt_id_mapping(table_data, range->source_id_base, range->num_ids, iommu_offset); } -- 2.53.0
From: Portia Stephens <portias@oss.tenstorrent.com> The counter value was not being bitshifted for a hpmcounterh read resulting in hpmcounterh returning the bottom 32-bits. Fixes: cfc96df65e01 ("target/riscv: Remove upper_half from riscv_pmu_ctr_get_fixed_counters_val") Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3498 Cc: qemu-stable@nongnu.org Signed-off-by: Portia Stephens <portias@oss.tenstorrent.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260519043352.3685866-1-stephensportia@gmail.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/csr.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -XXX,XX +XXX,XX @@ RISCVException riscv_pmu_read_ctr(CPURISCVState *env, target_ulong *val, */ if (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) || riscv_pmu_ctr_monitor_instructions(env, ctr_idx)) { - *val = riscv_pmu_ctr_get_fixed_counters_val(env, ctr_idx) - - ctr_prev + ctr_val; + uint64_t cntr = riscv_pmu_ctr_get_fixed_counters_val(env, ctr_idx) - + ctr_prev + ctr_val; + *val = extract64(cntr, start, length); } else { *val = ctr_val; } -- 2.53.0
From: Jim Shu <jim.shu@sifive.com> According to the AIA spec ch4.7 ("Precise effects on interrupt-pending bits"), pending bit of APLIC should be set/cleared whenever the rectified input value is high/low in the both level-trigger mode and direct delivery mode. Currently, QEMU APLIC only clears the pending bit when interrupt is claimed in APLIC, but not clears it when the rectified input value is low. (e.g. IRQ source signal is low in the LEVEL_HIGH/Level1 mode). The software may receive an additional IRQ if the peripheral triggers one after the software clears the APLIC IRQ but before it clears the peripheral's IRQ. Thus, we also clear the pending bit via the rectified input value in the level-trigger mode. This change doesn't affect MSI delivery mode. Calling riscv_aplic_msi_irq_update() when IRQ pending is low will do nothing. Signed-off-by: Jim Shu <jim.shu@sifive.com> Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Message-ID: <20260428160103.3551125-2-jim.shu@sifive.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/intc/riscv_aplic.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c index XXXXXXX..XXXXXXX 100644 --- a/hw/intc/riscv_aplic.c +++ b/hw/intc/riscv_aplic.c @@ -XXX,XX +XXX,XX @@ static void riscv_aplic_request(void *opaque, int irq, int level) } break; case APLIC_SOURCECFG_SM_LEVEL_HIGH: - if ((level > 0) && !(state & APLIC_ISTATE_PENDING)) { - riscv_aplic_set_pending_raw(aplic, irq, true); + if ((level > 0) != !!(state & APLIC_ISTATE_PENDING)) { + riscv_aplic_set_pending_raw(aplic, irq, level > 0); update = true; } break; case APLIC_SOURCECFG_SM_LEVEL_LOW: - if ((level <= 0) && !(state & APLIC_ISTATE_PENDING)) { - riscv_aplic_set_pending_raw(aplic, irq, true); + if ((level <= 0) != !!(state & APLIC_ISTATE_PENDING)) { + riscv_aplic_set_pending_raw(aplic, irq, level <= 0); update = true; } break; -- 2.53.0
From: Jim Shu <jim.shu@sifive.com> Clearing APLIC registers and qemu_irq in the reset function Signed-off-by: Jim Shu <jim.shu@sifive.com> Signed-off-by: Fea.Wang <fea.wang@sifive.com> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Message-ID: <20260428160103.3551125-3-jim.shu@sifive.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/intc/riscv_aplic.c | 45 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c index XXXXXXX..XXXXXXX 100644 --- a/hw/intc/riscv_aplic.c +++ b/hw/intc/riscv_aplic.c @@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps riscv_aplic_ops = { } }; +static void riscv_aplic_reset_enter(Object *obj, ResetType type) +{ + RISCVAPLICState *aplic = RISCV_APLIC(obj); + int i; + + aplic->domaincfg = 0; + memset(aplic->sourcecfg, 0, sizeof(uint32_t) * aplic->num_irqs); + memset(aplic->target, 0, sizeof(uint32_t) * aplic->num_irqs); + if (!aplic->msimode) { + for (i = 0; i < aplic->num_irqs; i++) { + aplic->target[i] = 1; + } + } + + for (i = 0; i < aplic->num_irqs ; i++) { + riscv_aplic_set_enabled_raw(aplic, i, false); + } + + /* Need to unlock [ms]msicfgaddrh.L */ + aplic->mmsicfgaddr = 0; + aplic->mmsicfgaddrH = 0; + aplic->smsicfgaddr = 0; + aplic->smsicfgaddrH = 0; + + if (!aplic->msimode) { + /* Reset IDC registers only in non-MSI mode */ + for (i = 0; i < aplic->num_harts; i++) { + aplic->idelivery[i] = 0; + aplic->iforce[i] = 0; + aplic->ithreshold[i] = 0; + } + + for (i = 0; i < aplic->num_harts; i++) { + qemu_irq_lower(aplic->external_irqs[i]); + } + } +} + static void riscv_aplic_realize(DeviceState *dev, Error **errp) { uint32_t i; @@ -XXX,XX +XXX,XX @@ static void riscv_aplic_realize(DeviceState *dev, Error **errp) aplic->sourcecfg = g_new0(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++) { - aplic->target[i] = 1; - } - } aplic->idelivery = g_new0(uint32_t, aplic->num_harts); aplic->iforce = g_new0(uint32_t, aplic->num_harts); aplic->ithreshold = g_new0(uint32_t, aplic->num_harts); @@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_riscv_aplic = { static void riscv_aplic_class_init(ObjectClass *klass, const void *data) { DeviceClass *dc = DEVICE_CLASS(klass); + ResettableClass *rc = RESETTABLE_CLASS(klass); device_class_set_props(dc, riscv_aplic_properties); dc->realize = riscv_aplic_realize; + rc->phases.enter = riscv_aplic_reset_enter; dc->vmsd = &vmstate_riscv_aplic; } -- 2.53.0
From: Jim Shu <jim.shu@sifive.com> Clearing IMSIC registers and qemu_irq in the reset function Signed-off-by: Jim Shu <jim.shu@sifive.com> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Message-ID: <20260428160103.3551125-4-jim.shu@sifive.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/intc/riscv_imsic.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/hw/intc/riscv_imsic.c b/hw/intc/riscv_imsic.c index XXXXXXX..XXXXXXX 100644 --- a/hw/intc/riscv_imsic.c +++ b/hw/intc/riscv_imsic.c @@ -XXX,XX +XXX,XX @@ static const MemoryRegionOps riscv_imsic_ops = { } }; +static void riscv_imsic_reset_enter(Object *obj, ResetType type) +{ + RISCVIMSICState *imsic = RISCV_IMSIC(obj); + int i; + + memset(imsic->eidelivery, 0, sizeof(uint32_t) * imsic->num_pages); + memset(imsic->eithreshold, 0, sizeof(uint32_t) * imsic->num_pages); + + for (i = 0; i < imsic->num_eistate; i++) { + imsic->eistate[i] &= ~IMSIC_EISTATE_ENABLED; + } + + for (i = 0; i < imsic->num_pages; i++) { + qemu_irq_lower(imsic->external_irqs[i]); + } +} + static void riscv_imsic_realize(DeviceState *dev, Error **errp) { RISCVIMSICState *imsic = RISCV_IMSIC(dev); @@ -XXX,XX +XXX,XX @@ static const VMStateDescription vmstate_riscv_imsic = { static void riscv_imsic_class_init(ObjectClass *klass, const void *data) { DeviceClass *dc = DEVICE_CLASS(klass); + ResettableClass *rc = RESETTABLE_CLASS(klass); device_class_set_props(dc, riscv_imsic_properties); dc->realize = riscv_imsic_realize; + rc->phases.enter = riscv_imsic_reset_enter; dc->vmsd = &vmstate_riscv_imsic; } -- 2.53.0
From: Jim Shu <jim.shu@sifive.com> Add the trace events for APLIC read/write functions. Signed-off-by: Jim Shu <jim.shu@sifive.com> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Message-ID: <20260428160103.3551125-5-jim.shu@sifive.com> [ Changes by AF: - Init val to zero to avoid uninitialised build errors ] Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/intc/riscv_aplic.c | 63 ++++++++++++++++++++++++++----------------- hw/intc/trace-events | 4 +++ 2 files changed, 42 insertions(+), 25 deletions(-) diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c index XXXXXXX..XXXXXXX 100644 --- a/hw/intc/riscv_aplic.c +++ b/hw/intc/riscv_aplic.c @@ -XXX,XX +XXX,XX @@ #include "system/tcg.h" #include "kvm/kvm_riscv.h" #include "migration/vmstate.h" +#include "trace.h" #define APLIC_MAX_IDC (1UL << 14) #define APLIC_MAX_SOURCE 1024 @@ -XXX,XX +XXX,XX @@ static void riscv_aplic_request(void *opaque, int irq, int level) static uint64_t riscv_aplic_read(void *opaque, hwaddr addr, unsigned size) { uint32_t irq, word, idc; + uint64_t val = 0; RISCVAPLICState *aplic = opaque; /* Reads must be 4 byte words */ @@ -XXX,XX +XXX,XX @@ static uint64_t riscv_aplic_read(void *opaque, hwaddr addr, unsigned size) } if (addr == APLIC_DOMAINCFG) { - return APLIC_DOMAINCFG_RDONLY | aplic->domaincfg | - (aplic->msimode ? APLIC_DOMAINCFG_DM : 0); + val = APLIC_DOMAINCFG_RDONLY | aplic->domaincfg | + (aplic->msimode ? APLIC_DOMAINCFG_DM : 0); } else if ((APLIC_SOURCECFG_BASE <= addr) && (addr < (APLIC_SOURCECFG_BASE + (aplic->num_irqs - 1) * 4))) { irq = ((addr - APLIC_SOURCECFG_BASE) >> 2) + 1; - return aplic->sourcecfg[irq]; + val = aplic->sourcecfg[irq]; } else if (aplic->mmode && aplic->msimode && (addr == APLIC_MMSICFGADDR)) { - return aplic->mmsicfgaddr; + val = aplic->mmsicfgaddr; } else if (aplic->mmode && aplic->msimode && (addr == APLIC_MMSICFGADDRH)) { - return aplic->mmsicfgaddrH; + val = aplic->mmsicfgaddrH; } else if (aplic->mmode && aplic->msimode && (addr == APLIC_SMSICFGADDR)) { /* @@ -XXX,XX +XXX,XX @@ static uint64_t riscv_aplic_read(void *opaque, hwaddr addr, unsigned size) * only zero in at least one of the supervisor-level child * domains). */ - return (aplic->num_children) ? aplic->smsicfgaddr : 0; + val = (aplic->num_children) ? aplic->smsicfgaddr : 0; } else if (aplic->mmode && aplic->msimode && (addr == APLIC_SMSICFGADDRH)) { - return (aplic->num_children) ? aplic->smsicfgaddrH : 0; + val = (aplic->num_children) ? aplic->smsicfgaddrH : 0; } else if ((APLIC_SETIP_BASE <= addr) && (addr < (APLIC_SETIP_BASE + aplic->bitfield_words * 4))) { word = (addr - APLIC_SETIP_BASE) >> 2; - return riscv_aplic_read_pending_word(aplic, word); + val = riscv_aplic_read_pending_word(aplic, word); } else if (addr == APLIC_SETIPNUM) { - return 0; + val = 0; } else if ((APLIC_CLRIP_BASE <= addr) && (addr < (APLIC_CLRIP_BASE + aplic->bitfield_words * 4))) { word = (addr - APLIC_CLRIP_BASE) >> 2; - return riscv_aplic_read_input_word(aplic, word); + val = riscv_aplic_read_input_word(aplic, word); } else if (addr == APLIC_CLRIPNUM) { - return 0; + val = 0; } else if ((APLIC_SETIE_BASE <= addr) && (addr < (APLIC_SETIE_BASE + aplic->bitfield_words * 4))) { word = (addr - APLIC_SETIE_BASE) >> 2; - return riscv_aplic_read_enabled_word(aplic, word); + val = riscv_aplic_read_enabled_word(aplic, word); } else if (addr == APLIC_SETIENUM) { - return 0; + val = 0; } else if ((APLIC_CLRIE_BASE <= addr) && (addr < (APLIC_CLRIE_BASE + aplic->bitfield_words * 4))) { - return 0; + val = 0; } else if (addr == APLIC_CLRIENUM) { - return 0; + val = 0; } else if (addr == APLIC_SETIPNUM_LE) { - return 0; + val = 0; } else if (addr == APLIC_SETIPNUM_BE) { - return 0; + val = 0; } else if (addr == APLIC_GENMSI) { - return (aplic->msimode) ? aplic->genmsi : 0; + val = (aplic->msimode) ? aplic->genmsi : 0; } else if ((APLIC_TARGET_BASE <= addr) && (addr < (APLIC_TARGET_BASE + (aplic->num_irqs - 1) * 4))) { irq = ((addr - APLIC_TARGET_BASE) >> 2) + 1; if (!riscv_aplic_source_active(aplic, irq)) { - return 0; + val = 0; + } else { + val = aplic->target[irq]; } - return aplic->target[irq]; } else if (!aplic->msimode && (APLIC_IDC_BASE <= addr) && (addr < (APLIC_IDC_BASE + aplic->num_harts * APLIC_IDC_SIZE))) { idc = (addr - APLIC_IDC_BASE) / APLIC_IDC_SIZE; switch (addr - (APLIC_IDC_BASE + idc * APLIC_IDC_SIZE)) { case APLIC_IDC_IDELIVERY: - return aplic->idelivery[idc]; + val = aplic->idelivery[idc]; + break; case APLIC_IDC_IFORCE: - return aplic->iforce[idc]; + val = aplic->iforce[idc]; + break; case APLIC_IDC_ITHRESHOLD: - return aplic->ithreshold[idc]; + val = aplic->ithreshold[idc]; + break; case APLIC_IDC_TOPI: - return riscv_aplic_idc_topi(aplic, idc); + val = riscv_aplic_idc_topi(aplic, idc); + break; case APLIC_IDC_CLAIMI: - return riscv_aplic_idc_claimi(aplic, idc); + val = riscv_aplic_idc_claimi(aplic, idc); + break; default: goto err; }; } + trace_riscv_aplic_read(addr, size, val); + return val; + err: qemu_log_mask(LOG_GUEST_ERROR, "%s: Invalid register read 0x%" HWADDR_PRIx "\n", @@ -XXX,XX +XXX,XX @@ static void riscv_aplic_write(void *opaque, hwaddr addr, uint64_t value, goto err; } + trace_riscv_aplic_write(addr, size, value); + if (addr == APLIC_DOMAINCFG) { /* Only IE bit writable at the moment */ value &= APLIC_DOMAINCFG_IE; diff --git a/hw/intc/trace-events b/hw/intc/trace-events index XXXXXXX..XXXXXXX 100644 --- a/hw/intc/trace-events +++ b/hw/intc/trace-events @@ -XXX,XX +XXX,XX @@ loongarch_msi_set_irq(int irq_num) "set msi irq %d" loongarch_extioi_setirq(int irq, int level) "set extirq irq %d level %d" loongarch_extioi_readw(uint64_t addr, uint64_t val) "addr: 0x%"PRIx64 "val: 0x%" PRIx64 loongarch_extioi_writew(uint64_t addr, uint64_t val) "addr: 0x%"PRIx64 "val: 0x%" PRIx64 + +# riscv_aplic.c +riscv_aplic_read(uint64_t offset, unsigned size, uint64_t value) "offset: 0x%" PRIx64 ", size: %u, value: 0x%" PRIx64 +riscv_aplic_write(uint64_t offset, unsigned size, uint64_t value) "offset: 0x%" PRIx64 ", size: %u, value: 0x%" PRIx64 -- 2.53.0
From: Jay Chang <jay.chang@sifive.com> When software clears CMD_ILL or CQMF error bits by writing 1 to CQCSR, the IOMMU should re-check the command queue and continue processing pending commands if head != tail. Per RISC-V IOMMU specification : If command-queue access leads to a memory fault then the command-queue-memory-fault bit is set to 1 and the commandqueue stalls until this bit is cleared. To re-enable command processing, software should clear this bit by writing 1. Signed-off-by: Jay Chang <jay.chang@sifive.com> Reviewed-by: Frank Chang <frank.chang@sifive.com> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Nutty Liu <nutty.liu@hotmail.com> Message-ID: <20260518070143.8405-1-jay.chang@sifive.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/riscv/riscv-iommu.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/riscv-iommu.c +++ b/hw/riscv/riscv-iommu.c @@ -XXX,XX +XXX,XX @@ static void riscv_iommu_process_cq_control(RISCVIOMMUState *s) } riscv_iommu_reg_mod32(s, RISCV_IOMMU_REG_CQCSR, ctrl_set, ctrl_clr); + + /* + * After clearing error bits (CMD_ILL, CQMF), if queue is still active, + * re-process pending command. + */ + ctrl_set = riscv_iommu_reg_get32(s, RISCV_IOMMU_REG_CQCSR); + if ((ctrl_set & RISCV_IOMMU_CQCSR_CQON) && + !(ctrl_set & (RISCV_IOMMU_CQCSR_CMD_ILL | RISCV_IOMMU_CQCSR_CQMF))) { + riscv_iommu_process_cq_tail(s); + } } static void riscv_iommu_process_fq_control(RISCVIOMMUState *s) -- 2.53.0
From: Alistair Francis <alistair.francis@wdc.com> The following changes since commit f893c46c3931b3684d235d221bf8b7844ddbf1d7: Merge tag 'qemu-openbios-20260707' of https://github.com/mcayland/qemu into staging (2026-07-08 16:01:29 +0200) are available in the Git repository at: https://github.com/alistair23/qemu.git tags/pull-riscv-to-apply-20260710 for you to fetch changes up to ec7d32428757d5813935cbe099449f6201980d80: tests: update SPCR loongarch64 and riscv64 test data (2026-07-09 16:21:52 +1000) ---------------------------------------------------------------- RISC-V PR for 11.1 * Fix IOMMU fault type for spa_fetch() faults * Check IOMMU for reserved PTE bits * Fault when IOMMU !PTE_U and no priv access * Fault IOMMU for non-user PTE in G_STAGE * Check IOMMU reserved MSI PTE basic bits * Record fault on IOMMU-generated MSI write * Move RISC-V TCG files and fix --disable-tcg * Check for misaligned IOMMU IOHGATP_PPN * Update IOMMU ioval2 when faulting in spa_fetch() * Forbid IOMMU GATE/SADE if caps.AMO_HWADD is zero * Set IOMMU ftype and iova in riscv_iommu_ctx() * Check PCIe DOE mailbox length for overflows * Add extensions after v7.1-rc4 update * Remove job building OpenSBI firmware binaries * Correct ACPI field sequence in SPCR table ---------------------------------------------------------------- Alistair Francis (1): hw/pci/pcie_doe: Check mailbox length for overflows Bin Meng (1): gitlab-ci: Remove job building OpenSBI firmware binaries Daniel Henrique Barboza (32): hw/riscv/riscv-iommu.c: fix fault type for spa_fetch() faults hw/riscv/riscv-iommu.c: check for reserved PTE bits hw/riscv/riscv-iommu.c: fault when !PTE_U and no priv access hw/riscv/riscv-iommu.c: fault for non-user PTE in G_STAGE hw/riscv/riscv-iommu.c: check reserved MSI PTE basic bits hw/riscv/riscv-iommu-sys.c: record fault on IOMMU-generated MSI write target/riscv: move valid_vm_* satp arrays to cpu.c hw/riscv, target/riscv: move pmu fdt function to fdt-common.c target/riscv: move TCG only files to tcg subdir target/riscv/machine.c: do not migrate pmp state with kvm target/riscv: move pmp files to tcg subdir target/riscv: tidy up riscv_sysemu_ops target/riscv: move debug.h to tcg subdir target/riscv: remove csr.h from kvm-cpu.c target/riscv: move csr.h to tcg subdir target/riscv: move custom_csrs logic to tcg-cpu.c target/riscv: move riscv_cpu_set_nmi() to tcg-cpu.c target/riscv: move some irq helpers to cpu.c target/riscv: move riscv_cpu_claim_interrupts to cpu.c target/riscv/cpu.c: handle TCG bits of riscv_cpu_dump_state target/riscv: gate riscv_cpu_update_mip with tcg_enabled() target/riscv/cpu.c: filter TCG only bits in riscv_cpu_reset_hold() hw/riscv/riscv_hart.c isolate tcg only bits target/riscv/gdbstub.c: isolate TCG only checks target/riscv: move riscv_cpu_set_rdtime_fn to riscv_aclint target/riscv/tcg: remove unused riscv_cpu_get_geilen() target/riscv: move riscv_cpu_set_geilen() to riscv-imsic target/riscv: move riscv_cpu_set_aia_ireg_rmw_cb() to riscv_imsic hw/riscv/riscv-iommu.c: check for misaligned IOHGATP_PPN hw/riscv/riscv-iommu.c: update ioval2 when faulting in spa_fetch() hw/riscv/riscv-iommu: forbid GATE/SADE if caps.AMO_HWADD is zero hw/riscv/riscv-iommu.c: set ftype and iova in riscv_iommu_ctx() Heinrich Schuchardt (3): tests: allow differences in SPCR hw/acpi: correct field sequence in SPCR table tests: update SPCR loongarch64 and riscv64 test data Wang Yechao (1): target/riscv/kvm: add extensions after v7.1-rc4 update Zephyr Li (2): target/riscv: Remove unused tcg/tcg.h include gitlab-ci.d/crossbuilds: add riscv64 KVM-only build job MAINTAINERS | 2 - hw/riscv/riscv-iommu-bits.h | 1 + hw/riscv/riscv-iommu.h | 1 + include/hw/riscv/fdt-common.h | 1 + target/riscv/cpu.h | 24 +- target/riscv/{ => tcg}/csr.h | 6 +- target/riscv/{ => tcg}/debug.h | 0 target/riscv/{ => tcg}/pmp.h | 0 target/riscv/{ => tcg}/pmu.h | 0 target/riscv/{ => tcg}/vector_internals.h | 0 tests/qtest/libqos/qos-riscv-iommu.h | 4 +- hw/acpi/aml-build.c | 4 +- hw/intc/riscv_aclint.c | 8 + hw/intc/riscv_imsic.c | 24 ++ hw/pci/pcie_doe.c | 27 +- hw/riscv/fdt-common.c | 52 ++++ hw/riscv/riscv-iommu-sys.c | 16 +- hw/riscv/riscv-iommu.c | 117 +++++++- hw/riscv/riscv_hart.c | 8 +- hw/riscv/tt_atlantis.c | 1 - hw/riscv/virt.c | 1 - target/riscv/cpu.c | 318 ++++++++++++++++++--- target/riscv/gdbstub.c | 10 +- target/riscv/kvm/kvm-cpu.c | 4 +- target/riscv/machine.c | 15 +- target/riscv/monitor.c | 4 +- target/riscv/riscv-qmp-cmds.c | 2 +- target/riscv/{ => tcg}/bitmanip_helper.c | 0 target/riscv/{ => tcg}/cpu_helper.c | 253 +--------------- target/riscv/{ => tcg}/crypto_helper.c | 0 target/riscv/{ => tcg}/csr.c | 45 +-- target/riscv/{ => tcg}/debug.c | 2 +- target/riscv/{ => tcg}/fpu_helper.c | 0 target/riscv/{ => tcg}/m128_helper.c | 0 target/riscv/{ => tcg}/mips_csr.c | 2 +- target/riscv/{ => tcg}/op_helper.c | 2 +- target/riscv/{ => tcg}/pmp.c | 2 +- target/riscv/{ => tcg}/pmu.c | 52 ---- target/riscv/tcg/tcg-cpu.c | 30 +- target/riscv/{ => tcg}/th_csr.c | 2 +- target/riscv/{ => tcg}/translate.c | 0 target/riscv/{ => tcg}/vcrypto_helper.c | 0 target/riscv/{ => tcg}/vector_helper.c | 0 target/riscv/{ => tcg}/vector_internals.c | 0 target/riscv/{ => tcg}/zce_helper.c | 0 target/riscv/time_helper.c | 33 ++- .../{ => tcg}/insn_trans/trans_privileged.c.inc | 0 target/riscv/{ => tcg}/insn_trans/trans_rva.c.inc | 0 target/riscv/{ => tcg}/insn_trans/trans_rvb.c.inc | 0 .../riscv/{ => tcg}/insn_trans/trans_rvbf16.c.inc | 0 target/riscv/{ => tcg}/insn_trans/trans_rvd.c.inc | 0 target/riscv/{ => tcg}/insn_trans/trans_rvf.c.inc | 0 target/riscv/{ => tcg}/insn_trans/trans_rvh.c.inc | 0 target/riscv/{ => tcg}/insn_trans/trans_rvi.c.inc | 0 target/riscv/{ => tcg}/insn_trans/trans_rvk.c.inc | 0 target/riscv/{ => tcg}/insn_trans/trans_rvm.c.inc | 0 target/riscv/{ => tcg}/insn_trans/trans_rvv.c.inc | 0 target/riscv/{ => tcg}/insn_trans/trans_rvvk.c.inc | 0 .../riscv/{ => tcg}/insn_trans/trans_rvzabha.c.inc | 0 .../riscv/{ => tcg}/insn_trans/trans_rvzacas.c.inc | 0 .../{ => tcg}/insn_trans/trans_rvzalasr.c.inc | 0 .../riscv/{ => tcg}/insn_trans/trans_rvzawrs.c.inc | 0 .../riscv/{ => tcg}/insn_trans/trans_rvzce.c.inc | 0 .../riscv/{ => tcg}/insn_trans/trans_rvzcmop.c.inc | 0 .../riscv/{ => tcg}/insn_trans/trans_rvzfa.c.inc | 0 .../riscv/{ => tcg}/insn_trans/trans_rvzfh.c.inc | 0 .../riscv/{ => tcg}/insn_trans/trans_rvzicbo.c.inc | 0 .../{ => tcg}/insn_trans/trans_rvzicfiss.c.inc | 0 .../{ => tcg}/insn_trans/trans_rvzicond.c.inc | 0 .../riscv/{ => tcg}/insn_trans/trans_rvzimop.c.inc | 0 .../riscv/{ => tcg}/insn_trans/trans_svinval.c.inc | 0 .../riscv/{ => tcg}/insn_trans/trans_xlrbr.c.inc | 0 .../riscv/{ => tcg}/insn_trans/trans_xmips.c.inc | 0 .../riscv/{ => tcg}/insn_trans/trans_xthead.c.inc | 0 .../insn_trans/trans_xventanacondops.c.inc | 0 .../riscv/{ => tcg}/insn_trans/trans_zilsd.c.inc | 0 .gitlab-ci.d/crossbuilds.yml | 8 + .gitlab-ci.d/opensbi.yml | 88 ------ .gitlab-ci.d/opensbi/Dockerfile | 34 --- .gitlab-ci.d/qemu-project.yml | 1 - target/riscv/meson.build | 17 -- target/riscv/tcg/meson.build | 31 +- tests/data/acpi/loongarch64/virt/SPCR | Bin 80 -> 80 bytes tests/data/acpi/riscv64/virt/SPCR | Bin 90 -> 90 bytes 84 files changed, 666 insertions(+), 586 deletions(-) rename target/riscv/{ => tcg}/csr.h (96%) rename target/riscv/{ => tcg}/debug.h (100%) rename target/riscv/{ => tcg}/pmp.h (100%) rename target/riscv/{ => tcg}/pmu.h (100%) rename target/riscv/{ => tcg}/vector_internals.h (100%) rename target/riscv/{ => tcg}/bitmanip_helper.c (100%) rename target/riscv/{ => tcg}/cpu_helper.c (92%) rename target/riscv/{ => tcg}/crypto_helper.c (100%) rename target/riscv/{ => tcg}/csr.c (99%) rename target/riscv/{ => tcg}/debug.c (99%) rename target/riscv/{ => tcg}/fpu_helper.c (100%) rename target/riscv/{ => tcg}/m128_helper.c (100%) rename target/riscv/{ => tcg}/mips_csr.c (99%) rename target/riscv/{ => tcg}/op_helper.c (99%) rename target/riscv/{ => tcg}/pmp.c (99%) rename target/riscv/{ => tcg}/pmu.c (86%) rename target/riscv/{ => tcg}/th_csr.c (99%) rename target/riscv/{ => tcg}/translate.c (100%) rename target/riscv/{ => tcg}/vcrypto_helper.c (100%) rename target/riscv/{ => tcg}/vector_helper.c (100%) rename target/riscv/{ => tcg}/vector_internals.c (100%) rename target/riscv/{ => tcg}/zce_helper.c (100%) rename target/riscv/{ => tcg}/insn_trans/trans_privileged.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rva.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvb.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvbf16.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvd.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvf.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvh.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvi.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvk.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvm.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvv.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvvk.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvzabha.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvzacas.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvzalasr.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvzawrs.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvzce.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvzcmop.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvzfa.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvzfh.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvzicbo.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvzicfiss.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvzicond.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvzimop.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_svinval.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_xlrbr.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_xmips.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_xthead.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_xventanacondops.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_zilsd.c.inc (100%) delete mode 100644 .gitlab-ci.d/opensbi.yml delete mode 100644 .gitlab-ci.d/opensbi/Dockerfile
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Under certain circunstances, like the one described in [1] and [2], a read operation that faults will be logged as a write fault instead, and vice-versa, if they happen after the translation phase in riscv_iommu_spa_fetch(). The first problem is that we're overwriting iotlb->perm with PTE flags, so an IOMMU_RO access flag can be overwritten by whatever flags the PTE has. This will cause the wrong fault type to be thrown at the end of the function in case a fault happens. To solve the iotlb->perm overwrite we'll bit_and the original iotlb->perm access flags with the PTE access flags, preserving the original access type. So a IOMMU_RO access in a R+W PTE will result in a IOMMU_RO perm. Second, the resulting fault is received by riscv_iommu_translate(), which will then report the fault. To do that we require a transaction type (ttype). We're prioritizing checking "perm & IOMMU_RW" to set a UADDR_WR ttype, and then checking "perm & IOMMU_RO" to set UADDR_RD ttype. The issue with that is IOMMU_RO=1 and IOMMU_RW=3, thus checking "perm & IOMMU_RW" for a write then "perm & IOMMU_RO" for a read will cause the read fault to always be diagnosed as write. Make the iotlb->perm matches more strict: "perm & IOMMU_RW" must be exactly IOMMU_RW, ensuring that 'perm' has both flags. Then we can check perm & IOMMU_WO and perm & IOMMU_RO without worrying about overlapping with the RW flag. [1] https://gitlab.com/qemu-project/qemu/-/work_items/3557 [2] https://gitlab.com/qemu-project/qemu/-/work_items/3577 Fixes: 69a9ae4836 ("hw/riscv/riscv-iommu: add ATS support") Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3557 Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3577 Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260701124034.552271-1-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/riscv/riscv-iommu.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/riscv-iommu.c +++ b/hw/riscv/riscv-iommu.c @@ -XXX,XX +XXX,XX @@ static hwaddr riscv_iommu_napot_page_mask(hwaddr ppn, hwaddr addr, hwaddr *out) static int riscv_iommu_spa_fetch(RISCVIOMMUState *s, RISCVIOMMUContext *ctx, IOMMUTLBEntry *iotlb) { + IOMMUAccessFlags pte_perm; dma_addr_t addr, base; uint64_t satp, gatp, pte; bool en_s, en_g; @@ -XXX,XX +XXX,XX @@ static int riscv_iommu_spa_fetch(RISCVIOMMUState *s, RISCVIOMMUContext *ctx, } /* Translation phase completed (GPA or SPA) */ iotlb->translated_addr = base; - iotlb->perm = (pte & PTE_W) ? ((pte & PTE_R) ? IOMMU_RW : IOMMU_WO) - : IOMMU_RO; + + /* + * Do a bit_and between the PTE bits and the original + * request flags to determine the exact permission we + * need, i.e. if the original request is RO and the + * PTE has RW flags the actual perm is RO. + */ + pte_perm = (pte & PTE_W) ? ((pte & PTE_R) ? IOMMU_RW : IOMMU_WO) + : IOMMU_RO; + iotlb->perm &= pte_perm; /* Check MSI GPA address match */ if (pass == S_STAGE && (iotlb->perm & IOMMU_WO) && @@ -XXX,XX +XXX,XX @@ done: if (fault) { unsigned ttype = RISCV_IOMMU_FQ_TTYPE_PCIE_ATS_REQ; - if (iotlb->perm & IOMMU_RW) { + if ((iotlb->perm & IOMMU_RW) == IOMMU_RW + || iotlb->perm & IOMMU_WO) { ttype = RISCV_IOMMU_FQ_TTYPE_UADDR_WR; } else if (iotlb->perm & IOMMU_RO) { ttype = RISCV_IOMMU_FQ_TTYPE_UADDR_RD; -- 2.54.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> We need to fault if reserved PTE bits (60:54) are set. Fixes: 0c54acb8243d ("hw/riscv: add RISC-V IOMMU base emulation") Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3554 Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Nutty Liu <nutty.liu@hotmail.com> Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com> Message-ID: <20260701121111.537654-2-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/riscv/riscv-iommu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/riscv-iommu.c +++ b/hw/riscv/riscv-iommu.c @@ -XXX,XX +XXX,XX @@ static int riscv_iommu_spa_fetch(RISCVIOMMUState *s, RISCVIOMMUContext *ctx, if (!(pte & PTE_V)) { break; /* Invalid PTE */ + } else if (pte & PTE_RESERVED(false)) { + break; /* Reserved PTE bits set */ } else if (!(pte & (PTE_R | PTE_W | PTE_X))) { base = PPN_PHYS(ppn); /* Inner PTE, continue walking */ } else if ((pte & (PTE_R | PTE_W | PTE_X)) == PTE_W) { -- 2.54.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> All IOMMU accesses are assumed to be user mode unless told otherwise, i.e. we have a process_id. In case we have a non-user mode leaf PTE (PTE_U isn't set) and we are running in user mode, we need to throw a fault. This also reflects on qos-riscv-iommu tests: the tests always run in user mode so our PTEs must have PTE_U (bit 0x10) set. Fixes: 0c54acb8243d ("hw/riscv: add RISC-V IOMMU base emulation") Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3553 Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Nutty Liu <nutty.liu@hotmail.com> Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com> Message-ID: <20260701121111.537654-3-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- tests/qtest/libqos/qos-riscv-iommu.h | 4 ++-- hw/riscv/riscv-iommu.c | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/qtest/libqos/qos-riscv-iommu.h b/tests/qtest/libqos/qos-riscv-iommu.h index XXXXXXX..XXXXXXX 100644 --- a/tests/qtest/libqos/qos-riscv-iommu.h +++ b/tests/qtest/libqos/qos-riscv-iommu.h @@ -XXX,XX +XXX,XX @@ * PTE masks for RISC-V IOMMU page tables. * Values match PTE_V, PTE_R, PTE_W, PTE_A, PTE_D in target/riscv/cpu_bits.h */ -#define QRIOMMU_NON_LEAF_PTE_MASK 0x001 /* PTE_V */ -#define QRIOMMU_LEAF_PTE_RW_MASK 0x0c7 /* V|R|W|A|D */ +#define QRIOMMU_NON_LEAF_PTE_MASK 0x011 /* PTE_V | PTE_U */ +#define QRIOMMU_LEAF_PTE_RW_MASK 0x0d7 /* V | R | W | A | D | PTE_U */ #define QRIOMMU_PTE_PPN_MASK 0x003ffffffffffc00ull /* Address-space base offset for test tables */ diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/riscv-iommu.c +++ b/hw/riscv/riscv-iommu.c @@ -XXX,XX +XXX,XX @@ static int riscv_iommu_spa_fetch(RISCVIOMMUState *s, RISCVIOMMUContext *ctx, G_STAGE = 1, } pass; MemTxResult ret; + bool pv = !!ctx->process_id; satp = get_field(ctx->satp, RISCV_IOMMU_ATP_MODE_FIELD); gatp = get_field(ctx->gatp, RISCV_IOMMU_ATP_MODE_FIELD); @@ -XXX,XX +XXX,XX @@ static int riscv_iommu_spa_fetch(RISCVIOMMUState *s, RISCVIOMMUContext *ctx, break; /* Invalid PTE */ } else if (pte & PTE_RESERVED(false)) { break; /* Reserved PTE bits set */ + } else if (!(pte & PTE_U) && !pv) { + /* + * All accesses are assumed to be User mode unless + * process_id is valid (pv). In case we have a + * non-user mode PTE and !pv we need to fault. + */ + break; } else if (!(pte & (PTE_R | PTE_W | PTE_X))) { base = PPN_PHYS(ppn); /* Inner PTE, continue walking */ } else if ((pte & (PTE_R | PTE_W | PTE_X)) == PTE_W) { -- 2.54.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> riscv-iommu spec 1.0 says: "When checking the U bit in a second-stage PTE, the transaction is treated as not requesting supervisor privilege." We need to *always* fault in case we're on G_STAGE and PTE_U is cleared since we can't be on supervisor mode at this point. Fixes: 0c54acb8243d ("hw/riscv: add RISC-V IOMMU base emulation") Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3555 Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Message-ID: <20260701121111.537654-4-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/riscv/riscv-iommu.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/riscv-iommu.c +++ b/hw/riscv/riscv-iommu.c @@ -XXX,XX +XXX,XX @@ static int riscv_iommu_spa_fetch(RISCVIOMMUState *s, RISCVIOMMUContext *ctx, break; /* Access bit not set */ } else if ((iotlb->perm & IOMMU_WO) && !ade && !(pte & PTE_D)) { break; /* Dirty bit not set */ + } else if (pass == G_STAGE && !(pte & PTE_U)) { + /* + * riscv-iommu spec 1.0: "When checking the U bit in a + * second-stage PTE, the transaction is treated as + * not requesting supervisor privilege." + * + * I.e. we need to fault if this is a non-user PTE since + * we are always in user mode at this point. + */ + break; } else { /* Leaf PTE, translation completed. */ sc[pass].step = sc[pass].levels; -- 2.54.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> We need to throw an MSI_MISCONFIGURED error when any of the reserved PTE bits (first doubleword only) are set. Fixes: Fixes: 0c54acb8243d ("hw/riscv: add RISC-V IOMMU base emulation") Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3563 Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Nutty Liu <nutty.liu@hotmail.com> Message-ID: <20260629125719.679626-1-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/riscv/riscv-iommu.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/riscv-iommu.c +++ b/hw/riscv/riscv-iommu.c @@ -XXX,XX +XXX,XX @@ static MemTxResult riscv_iommu_msi_write(RISCVIOMMUState *s, switch (get_field(pte[0], RISCV_IOMMU_MSI_PTE_M)) { case RISCV_IOMMU_MSI_PTE_M_BASIC: + /* + * riscv-iommu spec MSI PTE basic translate mode: + * "When an MSI PTE has fields V = 1, C = 0, and M = 3 + * (basic translate mode), the PTE's complete format is: + * First doubleword: bit 63 C, = 0 + * bits 53:10 PPN + * bits 2:1 M, = 3 + * bit 0 V, = 1 + * All other bits of the first doubleword are reserved + * and must be set to zeros by software. The second + * doubleword is ignored by an IOMMU so is free for + * software to use." + * + * In other words, bits 62:54 and 9:3 of pte[0] are reserved. + */ + if (pte[0] & (GENMASK_ULL(62, 54) | GENMASK_ULL(9, 3))) { + res = MEMTX_DECODE_ERROR; + cause = RISCV_IOMMU_FQ_CAUSE_MSI_MISCONFIGURED; + goto err; + } + /* MSI Pass-through mode */ addr = PPN_PHYS(get_field(pte[0], RISCV_IOMMU_MSI_PTE_PPN)); -- 2.54.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> The riscv-iommu spec requires that the IOMMU records its own generated MSI write faults. Fixes: 01c1caa9d1 ("hw/riscv/virt.c, riscv-iommu-sys.c: add MSIx support") Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3572 Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Nutty Liu <nutty.liu@hotmail.com> Message-ID: <20260629165954.1018123-1-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/riscv/riscv-iommu.h | 1 + hw/riscv/riscv-iommu-sys.c | 16 +++++++++++++++- hw/riscv/riscv-iommu.c | 3 +-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/hw/riscv/riscv-iommu.h b/hw/riscv/riscv-iommu.h index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/riscv-iommu.h +++ b/hw/riscv/riscv-iommu.h @@ -XXX,XX +XXX,XX @@ void riscv_iommu_pci_setup_iommu(RISCVIOMMUState *iommu, PCIBus *bus, void riscv_iommu_set_cap_igs(RISCVIOMMUState *s, riscv_iommu_igs_mode mode); void riscv_iommu_reset(RISCVIOMMUState *s); void riscv_iommu_notify(RISCVIOMMUState *s, int vec_type); +void riscv_iommu_fault(RISCVIOMMUState *s, struct riscv_iommu_fq_record *ev); typedef struct RISCVIOMMUContext RISCVIOMMUContext; /* Device translation context state. */ diff --git a/hw/riscv/riscv-iommu-sys.c b/hw/riscv/riscv-iommu-sys.c index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/riscv-iommu-sys.c +++ b/hw/riscv/riscv-iommu-sys.c @@ -XXX,XX +XXX,XX @@ #include "qemu/host-utils.h" #include "qemu/module.h" #include "qom/object.h" +#include "target/riscv/cpu_bits.h" #include "trace.h" #include "riscv-iommu.h" @@ -XXX,XX +XXX,XX @@ static void riscv_iommu_sysdev_send_MSI(RISCVIOMMUStateSys *s, address_space_stl_le(&address_space_memory, msi_addr, msi_data, MEMTXATTRS_UNSPECIFIED, &result); - trace_riscv_iommu_sys_msi_sent(vector, msi_addr, msi_data, result); + + if (result == MEMTX_OK) { + trace_riscv_iommu_sys_msi_sent(vector, msi_addr, msi_data, result); + } else { + /* Record an access fault error in the fault queue */ + struct riscv_iommu_fq_record ev = { 0 }; + RISCVIOMMUState *iommu = &s->iommu; + + ev.hdr = set_field(ev.hdr, RISCV_IOMMU_FQ_HDR_CAUSE, + RISCV_IOMMU_FQ_CAUSE_MSI_WR_FAULT); + ev.hdr = set_field(ev.hdr, RISCV_IOMMU_FQ_HDR_TTYPE, + RISCV_IOMMU_FQ_TTYPE_UADDR_WR); + riscv_iommu_fault(iommu, &ev); + } } static void riscv_iommu_sysdev_notify(RISCVIOMMUState *iommu, diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/riscv-iommu.c +++ b/hw/riscv/riscv-iommu.c @@ -XXX,XX +XXX,XX @@ void riscv_iommu_notify(RISCVIOMMUState *s, int vec_type) } } -static void riscv_iommu_fault(RISCVIOMMUState *s, - struct riscv_iommu_fq_record *ev) +void riscv_iommu_fault(RISCVIOMMUState *s, struct riscv_iommu_fq_record *ev) { uint32_t ctrl = riscv_iommu_reg_get32(s, RISCV_IOMMU_REG_FQCSR); uint32_t head = riscv_iommu_reg_get32(s, RISCV_IOMMU_REG_FQH) & s->fq_mask; -- 2.54.0
From: Zephyr Li <fritchleybohrer@gmail.com> Signed-off-by: Zephyr Li <fritchleybohrer@gmail.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com> Message-ID: <20260703180538.3346781-2-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.c | 1 - 1 file changed, 1 deletion(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -XXX,XX +XXX,XX @@ #include "system/tcg.h" #include "kvm/kvm_riscv.h" #include "tcg/tcg-cpu.h" -#include "tcg/tcg.h" #if !defined(CONFIG_USER_ONLY) #include "target/riscv/debug.h" #endif -- 2.54.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> These satp arrays are used internally in both csr.c and in cpu.c. csr.c is going to be moved to the TCG subdir in the next patch, and we want the satp logic to be available for KVM with --disable-tcg builds. Move these arrays to cpu.c to keep them available for KVM with --disable-tcg. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Message-ID: <20260703180538.3346781-3-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.h | 2 -- target/riscv/csr.h | 3 +++ target/riscv/cpu.c | 13 +++++++++++++ target/riscv/csr.c | 12 ------------ 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -XXX,XX +XXX,XX @@ void riscv_cpu_finalize_features(RISCVCPU *cpu, Error **errp); void riscv_add_satp_mode_properties(Object *obj); bool riscv_cpu_accelerator_compatible(RISCVCPU *cpu); -extern const bool valid_vm_1_10_32[], valid_vm_1_10_64[]; - void riscv_cpu_register_gdb_regs_for_features(CPUState *cs); const char *satp_mode_str(uint8_t satp_mode, bool is_32_bit); diff --git a/target/riscv/csr.h b/target/riscv/csr.h index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/csr.h +++ b/target/riscv/csr.h @@ -XXX,XX +XXX,XX @@ enum { CSR_TABLE_SIZE = 0x1000 }; +/* valid_vm_* arrays are shared with KVM via cpu.c */ +extern const bool valid_vm_1_10_32[], valid_vm_1_10_64[]; + /* CSR function table */ extern riscv_csr_operations csr_ops[CSR_TABLE_SIZE]; diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -XXX,XX +XXX,XX @@ const uint32_t misa_bits[] = {RVI, RVE, RVM, RVA, RVF, RVD, RVV, #define BYTE(x) (x) #endif +/* SATP bits that are shared between TCG and KVM */ +const bool valid_vm_1_10_32[16] = { + [VM_1_10_MBARE] = true, + [VM_1_10_SV32] = true +}; + +const bool valid_vm_1_10_64[16] = { + [VM_1_10_MBARE] = true, + [VM_1_10_SV39] = true, + [VM_1_10_SV48] = true, + [VM_1_10_SV57] = true +}; + bool riscv_cpu_is_32bit(RISCVCPU *cpu) { return riscv_cpu_mxl(&cpu->env) == MXL_RV32; diff --git a/target/riscv/csr.c b/target/riscv/csr.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -XXX,XX +XXX,XX @@ static const uint64_t hvien_writable_mask = LOCAL_INTERRUPTS; static const uint64_t vsip_writable_mask = MIP_VSSIP | LOCAL_INTERRUPTS; -const bool valid_vm_1_10_32[16] = { - [VM_1_10_MBARE] = true, - [VM_1_10_SV32] = true -}; - -const bool valid_vm_1_10_64[16] = { - [VM_1_10_MBARE] = true, - [VM_1_10_SV39] = true, - [VM_1_10_SV48] = true, - [VM_1_10_SV57] = true -}; - /* Machine Information Registers */ static RISCVException read_zero(CPURISCVState *env, int csrno, target_ulong *val) -- 2.54.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> riscv_pmu_generate_fdt_node() can be moved to fdt_common.c since it has no PMU TCG internals. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Message-ID: <20260703180538.3346781-4-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- include/hw/riscv/fdt-common.h | 1 + hw/riscv/fdt-common.c | 52 +++++++++++++++++++++++++++++++++++ hw/riscv/tt_atlantis.c | 1 - hw/riscv/virt.c | 1 - target/riscv/pmu.c | 52 ----------------------------------- 5 files changed, 53 insertions(+), 54 deletions(-) diff --git a/include/hw/riscv/fdt-common.h b/include/hw/riscv/fdt-common.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/riscv/fdt-common.h +++ b/include/hw/riscv/fdt-common.h @@ -XXX,XX +XXX,XX @@ void create_fdt_plic(void *fdt, hwaddr addr, uint64_t size, uint32_t addr_cells, uint32_t *plic_cells, uint32_t cells_size, uint32_t ndev_sources, bool numa_enabled, int socket); +void riscv_pmu_generate_fdt_node(void *fdt, uint32_t cmask, char *pmu_name); #endif diff --git a/hw/riscv/fdt-common.c b/hw/riscv/fdt-common.c index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/fdt-common.c +++ b/hw/riscv/fdt-common.c @@ -XXX,XX +XXX,XX @@ void create_fdt_plic(void *fdt, hwaddr addr, uint64_t size, } qemu_fdt_setprop_cell(fdt, nodename, "phandle", plic_phandle); } + +/* + * To keep it simple, any event can be mapped to any programmable counters in + * QEMU. The generic cycle & instruction count events can also be monitored + * using programmable counters. In that case, mcycle & minstret must continue + * to provide the correct value as well. Heterogeneous PMU per hart is not + * supported yet. Thus, number of counters are same across all harts. + */ +void riscv_pmu_generate_fdt_node(void *fdt, uint32_t cmask, char *pmu_name) +{ + uint32_t fdt_event_ctr_map[15] = {}; + + /* + * The event encoding is specified in the SBI specification + * Event idx is a 20bits wide number encoded as follows: + * event_idx[19:16] = type + * event_idx[15:0] = code + * The code field in cache events are encoded as follows: + * event_idx.code[15:3] = cache_id + * event_idx.code[2:1] = op_id + * event_idx.code[0:0] = result_id + */ + + /* SBI_PMU_HW_CPU_CYCLES: 0x01 : type(0x00) */ + fdt_event_ctr_map[0] = cpu_to_be32(0x00000001); + fdt_event_ctr_map[1] = cpu_to_be32(0x00000001); + fdt_event_ctr_map[2] = cpu_to_be32(cmask | 1 << 0); + + /* SBI_PMU_HW_INSTRUCTIONS: 0x02 : type(0x00) */ + fdt_event_ctr_map[3] = cpu_to_be32(0x00000002); + fdt_event_ctr_map[4] = cpu_to_be32(0x00000002); + fdt_event_ctr_map[5] = cpu_to_be32(cmask | 1 << 2); + + /* SBI_PMU_HW_CACHE_DTLB : 0x03 READ : 0x00 MISS : 0x00 type(0x01) */ + fdt_event_ctr_map[6] = cpu_to_be32(0x00010019); + fdt_event_ctr_map[7] = cpu_to_be32(0x00010019); + fdt_event_ctr_map[8] = cpu_to_be32(cmask); + + /* SBI_PMU_HW_CACHE_DTLB : 0x03 WRITE : 0x01 MISS : 0x00 type(0x01) */ + fdt_event_ctr_map[9] = cpu_to_be32(0x0001001B); + fdt_event_ctr_map[10] = cpu_to_be32(0x0001001B); + fdt_event_ctr_map[11] = cpu_to_be32(cmask); + + /* SBI_PMU_HW_CACHE_ITLB : 0x04 READ : 0x00 MISS : 0x00 type(0x01) */ + fdt_event_ctr_map[12] = cpu_to_be32(0x00010021); + fdt_event_ctr_map[13] = cpu_to_be32(0x00010021); + fdt_event_ctr_map[14] = cpu_to_be32(cmask); + + /* This a OpenSBI specific DT property documented in OpenSBI docs */ + qemu_fdt_setprop(fdt, pmu_name, "riscv,event-to-mhpmcounters", + fdt_event_ctr_map, sizeof(fdt_event_ctr_map)); +} diff --git a/hw/riscv/tt_atlantis.c b/hw/riscv/tt_atlantis.c index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/tt_atlantis.c +++ b/hw/riscv/tt_atlantis.c @@ -XXX,XX +XXX,XX @@ #include "hw/core/sysbus.h" #include "target/riscv/cpu.h" -#include "target/riscv/pmu.h" #include "hw/riscv/boot.h" #include "hw/riscv/fdt-common.h" diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -XXX,XX +XXX,XX @@ #include "hw/char/serial-mm.h" #include "target/riscv/cpu.h" #include "hw/core/sysbus-fdt.h" -#include "target/riscv/pmu.h" #include "hw/riscv/riscv_hart.h" #include "hw/riscv/iommu.h" #include "hw/riscv/riscv-iommu-bits.h" diff --git a/target/riscv/pmu.c b/target/riscv/pmu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/pmu.c +++ b/target/riscv/pmu.c @@ -XXX,XX +XXX,XX @@ #define RISCV_TIMEBASE_FREQ 1000000000 /* 1Ghz */ -/* - * To keep it simple, any event can be mapped to any programmable counters in - * QEMU. The generic cycle & instruction count events can also be monitored - * using programmable counters. In that case, mcycle & minstret must continue - * to provide the correct value as well. Heterogeneous PMU per hart is not - * supported yet. Thus, number of counters are same across all harts. - */ -void riscv_pmu_generate_fdt_node(void *fdt, uint32_t cmask, char *pmu_name) -{ - uint32_t fdt_event_ctr_map[15] = {}; - - /* - * The event encoding is specified in the SBI specification - * Event idx is a 20bits wide number encoded as follows: - * event_idx[19:16] = type - * event_idx[15:0] = code - * The code field in cache events are encoded as follows: - * event_idx.code[15:3] = cache_id - * event_idx.code[2:1] = op_id - * event_idx.code[0:0] = result_id - */ - - /* SBI_PMU_HW_CPU_CYCLES: 0x01 : type(0x00) */ - fdt_event_ctr_map[0] = cpu_to_be32(0x00000001); - fdt_event_ctr_map[1] = cpu_to_be32(0x00000001); - fdt_event_ctr_map[2] = cpu_to_be32(cmask | 1 << 0); - - /* SBI_PMU_HW_INSTRUCTIONS: 0x02 : type(0x00) */ - fdt_event_ctr_map[3] = cpu_to_be32(0x00000002); - fdt_event_ctr_map[4] = cpu_to_be32(0x00000002); - fdt_event_ctr_map[5] = cpu_to_be32(cmask | 1 << 2); - - /* SBI_PMU_HW_CACHE_DTLB : 0x03 READ : 0x00 MISS : 0x00 type(0x01) */ - fdt_event_ctr_map[6] = cpu_to_be32(0x00010019); - fdt_event_ctr_map[7] = cpu_to_be32(0x00010019); - fdt_event_ctr_map[8] = cpu_to_be32(cmask); - - /* SBI_PMU_HW_CACHE_DTLB : 0x03 WRITE : 0x01 MISS : 0x00 type(0x01) */ - fdt_event_ctr_map[9] = cpu_to_be32(0x0001001B); - fdt_event_ctr_map[10] = cpu_to_be32(0x0001001B); - fdt_event_ctr_map[11] = cpu_to_be32(cmask); - - /* SBI_PMU_HW_CACHE_ITLB : 0x04 READ : 0x00 MISS : 0x00 type(0x01) */ - fdt_event_ctr_map[12] = cpu_to_be32(0x00010021); - fdt_event_ctr_map[13] = cpu_to_be32(0x00010021); - fdt_event_ctr_map[14] = cpu_to_be32(cmask); - - /* This a OpenSBI specific DT property documented in OpenSBI docs */ - qemu_fdt_setprop(fdt, pmu_name, "riscv,event-to-mhpmcounters", - fdt_event_ctr_map, sizeof(fdt_event_ctr_map)); -} - static bool riscv_pmu_counter_valid(RISCVCPU *cpu, uint32_t ctr_idx) { if (ctr_idx < 3 || ctr_idx >= RV_MAX_MHPMCOUNTERS || -- 2.54.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> We have *way* too much TCG-only code hanging around in target/riscv, where ideally we would have things that are shared between accelerators. We'll follow the example of other targets like i386 and loongarch and move everything to the tcg subir. This will not only cleanup target/riscv but it will also expose what is common code but it's buried inside a TCG helper. We're leaving some stuff behind because these require a little more case to not end up breaking KVM. We'll take care of them next. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com> Message-ID: <20260703180538.3346781-5-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/{ => tcg}/pmu.h | 0 target/riscv/{ => tcg}/vector_internals.h | 0 target/riscv/{ => tcg}/bitmanip_helper.c | 0 target/riscv/{ => tcg}/cpu_helper.c | 0 target/riscv/{ => tcg}/crypto_helper.c | 0 target/riscv/{ => tcg}/csr.c | 0 target/riscv/{ => tcg}/debug.c | 0 target/riscv/{ => tcg}/fpu_helper.c | 0 target/riscv/{ => tcg}/m128_helper.c | 0 target/riscv/{ => tcg}/mips_csr.c | 0 target/riscv/{ => tcg}/op_helper.c | 0 target/riscv/{ => tcg}/pmu.c | 0 target/riscv/{ => tcg}/th_csr.c | 0 target/riscv/{ => tcg}/translate.c | 0 target/riscv/{ => tcg}/vcrypto_helper.c | 0 target/riscv/{ => tcg}/vector_helper.c | 0 target/riscv/{ => tcg}/vector_internals.c | 0 target/riscv/{ => tcg}/zce_helper.c | 0 .../insn_trans/trans_privileged.c.inc | 0 .../{ => tcg}/insn_trans/trans_rva.c.inc | 0 .../{ => tcg}/insn_trans/trans_rvb.c.inc | 0 .../{ => tcg}/insn_trans/trans_rvbf16.c.inc | 0 .../{ => tcg}/insn_trans/trans_rvd.c.inc | 0 .../{ => tcg}/insn_trans/trans_rvf.c.inc | 0 .../{ => tcg}/insn_trans/trans_rvh.c.inc | 0 .../{ => tcg}/insn_trans/trans_rvi.c.inc | 0 .../{ => tcg}/insn_trans/trans_rvk.c.inc | 0 .../{ => tcg}/insn_trans/trans_rvm.c.inc | 0 .../{ => tcg}/insn_trans/trans_rvv.c.inc | 0 .../{ => tcg}/insn_trans/trans_rvvk.c.inc | 0 .../{ => tcg}/insn_trans/trans_rvzabha.c.inc | 0 .../{ => tcg}/insn_trans/trans_rvzacas.c.inc | 0 .../{ => tcg}/insn_trans/trans_rvzalasr.c.inc | 0 .../{ => tcg}/insn_trans/trans_rvzawrs.c.inc | 0 .../{ => tcg}/insn_trans/trans_rvzce.c.inc | 0 .../{ => tcg}/insn_trans/trans_rvzcmop.c.inc | 0 .../{ => tcg}/insn_trans/trans_rvzfa.c.inc | 0 .../{ => tcg}/insn_trans/trans_rvzfh.c.inc | 0 .../{ => tcg}/insn_trans/trans_rvzicbo.c.inc | 0 .../insn_trans/trans_rvzicfiss.c.inc | 0 .../{ => tcg}/insn_trans/trans_rvzicond.c.inc | 0 .../{ => tcg}/insn_trans/trans_rvzimop.c.inc | 0 .../{ => tcg}/insn_trans/trans_svinval.c.inc | 0 .../{ => tcg}/insn_trans/trans_xlrbr.c.inc | 0 .../{ => tcg}/insn_trans/trans_xmips.c.inc | 0 .../{ => tcg}/insn_trans/trans_xthead.c.inc | 0 .../insn_trans/trans_xventanacondops.c.inc | 0 .../{ => tcg}/insn_trans/trans_zilsd.c.inc | 0 target/riscv/meson.build | 16 ---------- target/riscv/tcg/meson.build | 30 +++++++++++++++++-- 50 files changed, 28 insertions(+), 18 deletions(-) rename target/riscv/{ => tcg}/pmu.h (100%) rename target/riscv/{ => tcg}/vector_internals.h (100%) rename target/riscv/{ => tcg}/bitmanip_helper.c (100%) rename target/riscv/{ => tcg}/cpu_helper.c (100%) rename target/riscv/{ => tcg}/crypto_helper.c (100%) rename target/riscv/{ => tcg}/csr.c (100%) rename target/riscv/{ => tcg}/debug.c (100%) rename target/riscv/{ => tcg}/fpu_helper.c (100%) rename target/riscv/{ => tcg}/m128_helper.c (100%) rename target/riscv/{ => tcg}/mips_csr.c (100%) rename target/riscv/{ => tcg}/op_helper.c (100%) rename target/riscv/{ => tcg}/pmu.c (100%) rename target/riscv/{ => tcg}/th_csr.c (100%) rename target/riscv/{ => tcg}/translate.c (100%) rename target/riscv/{ => tcg}/vcrypto_helper.c (100%) rename target/riscv/{ => tcg}/vector_helper.c (100%) rename target/riscv/{ => tcg}/vector_internals.c (100%) rename target/riscv/{ => tcg}/zce_helper.c (100%) rename target/riscv/{ => tcg}/insn_trans/trans_privileged.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rva.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvb.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvbf16.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvd.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvf.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvh.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvi.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvk.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvm.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvv.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvvk.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvzabha.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvzacas.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvzalasr.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvzawrs.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvzce.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvzcmop.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvzfa.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvzfh.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvzicbo.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvzicfiss.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvzicond.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_rvzimop.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_svinval.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_xlrbr.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_xmips.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_xthead.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_xventanacondops.c.inc (100%) rename target/riscv/{ => tcg}/insn_trans/trans_zilsd.c.inc (100%) diff --git a/target/riscv/pmu.h b/target/riscv/tcg/pmu.h similarity index 100% rename from target/riscv/pmu.h rename to target/riscv/tcg/pmu.h diff --git a/target/riscv/vector_internals.h b/target/riscv/tcg/vector_internals.h similarity index 100% rename from target/riscv/vector_internals.h rename to target/riscv/tcg/vector_internals.h diff --git a/target/riscv/bitmanip_helper.c b/target/riscv/tcg/bitmanip_helper.c similarity index 100% rename from target/riscv/bitmanip_helper.c rename to target/riscv/tcg/bitmanip_helper.c diff --git a/target/riscv/cpu_helper.c b/target/riscv/tcg/cpu_helper.c similarity index 100% rename from target/riscv/cpu_helper.c rename to target/riscv/tcg/cpu_helper.c diff --git a/target/riscv/crypto_helper.c b/target/riscv/tcg/crypto_helper.c similarity index 100% rename from target/riscv/crypto_helper.c rename to target/riscv/tcg/crypto_helper.c diff --git a/target/riscv/csr.c b/target/riscv/tcg/csr.c similarity index 100% rename from target/riscv/csr.c rename to target/riscv/tcg/csr.c diff --git a/target/riscv/debug.c b/target/riscv/tcg/debug.c similarity index 100% rename from target/riscv/debug.c rename to target/riscv/tcg/debug.c diff --git a/target/riscv/fpu_helper.c b/target/riscv/tcg/fpu_helper.c similarity index 100% rename from target/riscv/fpu_helper.c rename to target/riscv/tcg/fpu_helper.c diff --git a/target/riscv/m128_helper.c b/target/riscv/tcg/m128_helper.c similarity index 100% rename from target/riscv/m128_helper.c rename to target/riscv/tcg/m128_helper.c diff --git a/target/riscv/mips_csr.c b/target/riscv/tcg/mips_csr.c similarity index 100% rename from target/riscv/mips_csr.c rename to target/riscv/tcg/mips_csr.c diff --git a/target/riscv/op_helper.c b/target/riscv/tcg/op_helper.c similarity index 100% rename from target/riscv/op_helper.c rename to target/riscv/tcg/op_helper.c diff --git a/target/riscv/pmu.c b/target/riscv/tcg/pmu.c similarity index 100% rename from target/riscv/pmu.c rename to target/riscv/tcg/pmu.c diff --git a/target/riscv/th_csr.c b/target/riscv/tcg/th_csr.c similarity index 100% rename from target/riscv/th_csr.c rename to target/riscv/tcg/th_csr.c diff --git a/target/riscv/translate.c b/target/riscv/tcg/translate.c similarity index 100% rename from target/riscv/translate.c rename to target/riscv/tcg/translate.c diff --git a/target/riscv/vcrypto_helper.c b/target/riscv/tcg/vcrypto_helper.c similarity index 100% rename from target/riscv/vcrypto_helper.c rename to target/riscv/tcg/vcrypto_helper.c diff --git a/target/riscv/vector_helper.c b/target/riscv/tcg/vector_helper.c similarity index 100% rename from target/riscv/vector_helper.c rename to target/riscv/tcg/vector_helper.c diff --git a/target/riscv/vector_internals.c b/target/riscv/tcg/vector_internals.c similarity index 100% rename from target/riscv/vector_internals.c rename to target/riscv/tcg/vector_internals.c diff --git a/target/riscv/zce_helper.c b/target/riscv/tcg/zce_helper.c similarity index 100% rename from target/riscv/zce_helper.c rename to target/riscv/tcg/zce_helper.c diff --git a/target/riscv/insn_trans/trans_privileged.c.inc b/target/riscv/tcg/insn_trans/trans_privileged.c.inc similarity index 100% rename from target/riscv/insn_trans/trans_privileged.c.inc rename to target/riscv/tcg/insn_trans/trans_privileged.c.inc diff --git a/target/riscv/insn_trans/trans_rva.c.inc b/target/riscv/tcg/insn_trans/trans_rva.c.inc similarity index 100% rename from target/riscv/insn_trans/trans_rva.c.inc rename to target/riscv/tcg/insn_trans/trans_rva.c.inc diff --git a/target/riscv/insn_trans/trans_rvb.c.inc b/target/riscv/tcg/insn_trans/trans_rvb.c.inc similarity index 100% rename from target/riscv/insn_trans/trans_rvb.c.inc rename to target/riscv/tcg/insn_trans/trans_rvb.c.inc diff --git a/target/riscv/insn_trans/trans_rvbf16.c.inc b/target/riscv/tcg/insn_trans/trans_rvbf16.c.inc similarity index 100% rename from target/riscv/insn_trans/trans_rvbf16.c.inc rename to target/riscv/tcg/insn_trans/trans_rvbf16.c.inc diff --git a/target/riscv/insn_trans/trans_rvd.c.inc b/target/riscv/tcg/insn_trans/trans_rvd.c.inc similarity index 100% rename from target/riscv/insn_trans/trans_rvd.c.inc rename to target/riscv/tcg/insn_trans/trans_rvd.c.inc diff --git a/target/riscv/insn_trans/trans_rvf.c.inc b/target/riscv/tcg/insn_trans/trans_rvf.c.inc similarity index 100% rename from target/riscv/insn_trans/trans_rvf.c.inc rename to target/riscv/tcg/insn_trans/trans_rvf.c.inc diff --git a/target/riscv/insn_trans/trans_rvh.c.inc b/target/riscv/tcg/insn_trans/trans_rvh.c.inc similarity index 100% rename from target/riscv/insn_trans/trans_rvh.c.inc rename to target/riscv/tcg/insn_trans/trans_rvh.c.inc diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/tcg/insn_trans/trans_rvi.c.inc similarity index 100% rename from target/riscv/insn_trans/trans_rvi.c.inc rename to target/riscv/tcg/insn_trans/trans_rvi.c.inc diff --git a/target/riscv/insn_trans/trans_rvk.c.inc b/target/riscv/tcg/insn_trans/trans_rvk.c.inc similarity index 100% rename from target/riscv/insn_trans/trans_rvk.c.inc rename to target/riscv/tcg/insn_trans/trans_rvk.c.inc diff --git a/target/riscv/insn_trans/trans_rvm.c.inc b/target/riscv/tcg/insn_trans/trans_rvm.c.inc similarity index 100% rename from target/riscv/insn_trans/trans_rvm.c.inc rename to target/riscv/tcg/insn_trans/trans_rvm.c.inc diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/tcg/insn_trans/trans_rvv.c.inc similarity index 100% rename from target/riscv/insn_trans/trans_rvv.c.inc rename to target/riscv/tcg/insn_trans/trans_rvv.c.inc diff --git a/target/riscv/insn_trans/trans_rvvk.c.inc b/target/riscv/tcg/insn_trans/trans_rvvk.c.inc similarity index 100% rename from target/riscv/insn_trans/trans_rvvk.c.inc rename to target/riscv/tcg/insn_trans/trans_rvvk.c.inc diff --git a/target/riscv/insn_trans/trans_rvzabha.c.inc b/target/riscv/tcg/insn_trans/trans_rvzabha.c.inc similarity index 100% rename from target/riscv/insn_trans/trans_rvzabha.c.inc rename to target/riscv/tcg/insn_trans/trans_rvzabha.c.inc diff --git a/target/riscv/insn_trans/trans_rvzacas.c.inc b/target/riscv/tcg/insn_trans/trans_rvzacas.c.inc similarity index 100% rename from target/riscv/insn_trans/trans_rvzacas.c.inc rename to target/riscv/tcg/insn_trans/trans_rvzacas.c.inc diff --git a/target/riscv/insn_trans/trans_rvzalasr.c.inc b/target/riscv/tcg/insn_trans/trans_rvzalasr.c.inc similarity index 100% rename from target/riscv/insn_trans/trans_rvzalasr.c.inc rename to target/riscv/tcg/insn_trans/trans_rvzalasr.c.inc diff --git a/target/riscv/insn_trans/trans_rvzawrs.c.inc b/target/riscv/tcg/insn_trans/trans_rvzawrs.c.inc similarity index 100% rename from target/riscv/insn_trans/trans_rvzawrs.c.inc rename to target/riscv/tcg/insn_trans/trans_rvzawrs.c.inc diff --git a/target/riscv/insn_trans/trans_rvzce.c.inc b/target/riscv/tcg/insn_trans/trans_rvzce.c.inc similarity index 100% rename from target/riscv/insn_trans/trans_rvzce.c.inc rename to target/riscv/tcg/insn_trans/trans_rvzce.c.inc diff --git a/target/riscv/insn_trans/trans_rvzcmop.c.inc b/target/riscv/tcg/insn_trans/trans_rvzcmop.c.inc similarity index 100% rename from target/riscv/insn_trans/trans_rvzcmop.c.inc rename to target/riscv/tcg/insn_trans/trans_rvzcmop.c.inc diff --git a/target/riscv/insn_trans/trans_rvzfa.c.inc b/target/riscv/tcg/insn_trans/trans_rvzfa.c.inc similarity index 100% rename from target/riscv/insn_trans/trans_rvzfa.c.inc rename to target/riscv/tcg/insn_trans/trans_rvzfa.c.inc diff --git a/target/riscv/insn_trans/trans_rvzfh.c.inc b/target/riscv/tcg/insn_trans/trans_rvzfh.c.inc similarity index 100% rename from target/riscv/insn_trans/trans_rvzfh.c.inc rename to target/riscv/tcg/insn_trans/trans_rvzfh.c.inc diff --git a/target/riscv/insn_trans/trans_rvzicbo.c.inc b/target/riscv/tcg/insn_trans/trans_rvzicbo.c.inc similarity index 100% rename from target/riscv/insn_trans/trans_rvzicbo.c.inc rename to target/riscv/tcg/insn_trans/trans_rvzicbo.c.inc diff --git a/target/riscv/insn_trans/trans_rvzicfiss.c.inc b/target/riscv/tcg/insn_trans/trans_rvzicfiss.c.inc similarity index 100% rename from target/riscv/insn_trans/trans_rvzicfiss.c.inc rename to target/riscv/tcg/insn_trans/trans_rvzicfiss.c.inc diff --git a/target/riscv/insn_trans/trans_rvzicond.c.inc b/target/riscv/tcg/insn_trans/trans_rvzicond.c.inc similarity index 100% rename from target/riscv/insn_trans/trans_rvzicond.c.inc rename to target/riscv/tcg/insn_trans/trans_rvzicond.c.inc diff --git a/target/riscv/insn_trans/trans_rvzimop.c.inc b/target/riscv/tcg/insn_trans/trans_rvzimop.c.inc similarity index 100% rename from target/riscv/insn_trans/trans_rvzimop.c.inc rename to target/riscv/tcg/insn_trans/trans_rvzimop.c.inc diff --git a/target/riscv/insn_trans/trans_svinval.c.inc b/target/riscv/tcg/insn_trans/trans_svinval.c.inc similarity index 100% rename from target/riscv/insn_trans/trans_svinval.c.inc rename to target/riscv/tcg/insn_trans/trans_svinval.c.inc diff --git a/target/riscv/insn_trans/trans_xlrbr.c.inc b/target/riscv/tcg/insn_trans/trans_xlrbr.c.inc similarity index 100% rename from target/riscv/insn_trans/trans_xlrbr.c.inc rename to target/riscv/tcg/insn_trans/trans_xlrbr.c.inc diff --git a/target/riscv/insn_trans/trans_xmips.c.inc b/target/riscv/tcg/insn_trans/trans_xmips.c.inc similarity index 100% rename from target/riscv/insn_trans/trans_xmips.c.inc rename to target/riscv/tcg/insn_trans/trans_xmips.c.inc diff --git a/target/riscv/insn_trans/trans_xthead.c.inc b/target/riscv/tcg/insn_trans/trans_xthead.c.inc similarity index 100% rename from target/riscv/insn_trans/trans_xthead.c.inc rename to target/riscv/tcg/insn_trans/trans_xthead.c.inc diff --git a/target/riscv/insn_trans/trans_xventanacondops.c.inc b/target/riscv/tcg/insn_trans/trans_xventanacondops.c.inc similarity index 100% rename from target/riscv/insn_trans/trans_xventanacondops.c.inc rename to target/riscv/tcg/insn_trans/trans_xventanacondops.c.inc diff --git a/target/riscv/insn_trans/trans_zilsd.c.inc b/target/riscv/tcg/insn_trans/trans_zilsd.c.inc similarity index 100% rename from target/riscv/insn_trans/trans_zilsd.c.inc rename to target/riscv/tcg/insn_trans/trans_zilsd.c.inc diff --git a/target/riscv/meson.build b/target/riscv/meson.build index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/meson.build +++ b/target/riscv/meson.build @@ -XXX,XX +XXX,XX @@ riscv_ss.add(when: 'CONFIG_ARM_COMPATIBLE_SEMIHOSTING', riscv_ss.add(files( 'cpu.c', - 'cpu_helper.c', - 'csr.c', - 'fpu_helper.c', 'gdbstub.c', - 'op_helper.c', - 'vector_helper.c', - 'vector_internals.c', - 'bitmanip_helper.c', - 'translate.c', - 'm128_helper.c', - 'crypto_helper.c', - 'zce_helper.c', - 'vcrypto_helper.c' )) riscv_system_ss = ss.source_set() riscv_system_ss.add(files( 'arch_dump.c', 'pmp.c', - 'debug.c', 'monitor.c', 'machine.c', - 'mips_csr.c', - 'pmu.c', - 'th_csr.c', 'time_helper.c', 'riscv-qmp-cmds.c', )) diff --git a/target/riscv/tcg/meson.build b/target/riscv/tcg/meson.build index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/meson.build +++ b/target/riscv/tcg/meson.build @@ -XXX,XX +XXX,XX @@ -riscv_ss.add(when: 'CONFIG_TCG', if_true: files( - 'tcg-cpu.c')) +if 'CONFIG_TCG' not in config_all_accel + subdir_done() +endif + +riscv_ss.add(files( + 'bitmanip_helper.c', + 'cpu_helper.c', + 'csr.c', + 'crypto_helper.c', + 'fpu_helper.c', + 'm128_helper.c', + 'op_helper.c', + 'translate.c', + 'tcg-cpu.c', + 'vcrypto_helper.c', + 'vector_helper.c', + 'vector_internals.c', + 'zce_helper.c')) + + +riscv_system_ss.add(files( + 'debug.c', + 'mips_csr.c', + 'pmu.c', + 'th_csr.c', +)) + + -- 2.54.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> The PMP emulation isn't present in the KVM driver. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260703180538.3346781-6-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/machine.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/target/riscv/machine.c b/target/riscv/machine.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -XXX,XX +XXX,XX @@ #include "cpu.h" #include "qemu/error-report.h" #include "system/kvm.h" +#include "system/tcg.h" #include "migration/cpu.h" #include "exec/icount.h" #include "target/riscv/debug.h" @@ -XXX,XX +XXX,XX @@ static bool pmp_needed(void *opaque) { RISCVCPU *cpu = opaque; - return cpu->cfg.pmp; + if (kvm_enabled()) { + return false; + } + + return tcg_enabled() && cpu->cfg.pmp; } static int pmp_post_load(void *opaque, int version_id) { +#ifdef CONFIG_TCG RISCVCPU *cpu = opaque; CPURISCVState *env = &cpu->env; - int i; uint8_t pmp_regions = riscv_cpu_cfg(env)->pmp_regions; - for (i = 0; i < pmp_regions; i++) { + for (int i = 0; i < pmp_regions; i++) { pmp_update_rule_addr(env, i); } pmp_update_rule_nums(env); - +#endif return 0; } -- 2.54.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> A trivial header change is required too. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com> Message-ID: <20260703180538.3346781-7-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.h | 2 +- target/riscv/{ => tcg}/pmp.h | 0 target/riscv/{ => tcg}/pmp.c | 0 target/riscv/meson.build | 1 - target/riscv/tcg/meson.build | 1 + 5 files changed, 2 insertions(+), 2 deletions(-) rename target/riscv/{ => tcg}/pmp.h (100%) rename target/riscv/{ => tcg}/pmp.c (100%) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -XXX,XX +XXX,XX @@ extern RISCVCPUImpliedExtsRule *riscv_multi_ext_implied_rules[]; #define MMU_USER_IDX 3 #if !defined(CONFIG_USER_ONLY) -#include "pmp.h" +#include "tcg/pmp.h" #endif #define RV_VLEN_MAX 1024 diff --git a/target/riscv/pmp.h b/target/riscv/tcg/pmp.h similarity index 100% rename from target/riscv/pmp.h rename to target/riscv/tcg/pmp.h diff --git a/target/riscv/pmp.c b/target/riscv/tcg/pmp.c similarity index 100% rename from target/riscv/pmp.c rename to target/riscv/tcg/pmp.c diff --git a/target/riscv/meson.build b/target/riscv/meson.build index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/meson.build +++ b/target/riscv/meson.build @@ -XXX,XX +XXX,XX @@ riscv_ss.add(files( riscv_system_ss = ss.source_set() riscv_system_ss.add(files( 'arch_dump.c', - 'pmp.c', 'monitor.c', 'machine.c', 'time_helper.c', diff --git a/target/riscv/tcg/meson.build b/target/riscv/tcg/meson.build index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/meson.build +++ b/target/riscv/tcg/meson.build @@ -XXX,XX +XXX,XX @@ riscv_ss.add(files( riscv_system_ss.add(files( 'debug.c', 'mips_csr.c', + 'pmp.c', 'pmu.c', 'th_csr.c', )) -- 2.54.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> monitor_get_register at this moment has a TCG exclusive implementation for RISC-V, even though the callback is supposed to be arch independent. Until we address how KVM is going to implement it we need to filter it out in cpu.c. Same goes for get_phys_addr_debug - it has a TCG only implementation and KVM can't use it for now. It would also need to be filtered out, but since we're at it, let's convert it to the newer 'translate_for_debug' API too. Same restrictions apply. Suggested-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Message-ID: <20260703180538.3346781-8-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.h | 3 ++- target/riscv/cpu.c | 6 ++++-- target/riscv/monitor.c | 2 ++ target/riscv/tcg/cpu_helper.c | 14 ++++++++++---- 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -XXX,XX +XXX,XX @@ void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, MMUAccessType access_type, int mmu_idx, MemTxAttrs attrs, MemTxResult response, uintptr_t retaddr); -hwaddr riscv_cpu_get_phys_addr_debug(CPUState *cpu, vaddr addr); +bool riscv_cpu_translate_for_debug(CPUState *cs, vaddr addr, + TranslateForDebugResult *result); bool riscv_cpu_exec_interrupt(CPUState *cs, int interrupt_request); void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env); int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts); diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -XXX,XX +XXX,XX @@ static int64_t riscv_get_arch_id(CPUState *cs) static const struct SysemuCPUOps riscv_sysemu_ops = { .has_work = riscv_cpu_has_work, - .get_phys_addr_debug = riscv_cpu_get_phys_addr_debug, .write_elf64_note = riscv_cpu_write_elf64_note, .write_elf32_note = riscv_cpu_write_elf32_note, - .monitor_get_register = riscv_monitor_get_register_legacy, .legacy_vmsd = &vmstate_riscv_cpu, +#ifdef CONFIG_TCG + .translate_for_debug = riscv_cpu_translate_for_debug, + .monitor_get_register = riscv_monitor_get_register_legacy, +#endif }; #endif diff --git a/target/riscv/monitor.c b/target/riscv/monitor.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/monitor.c +++ b/target/riscv/monitor.c @@ -XXX,XX +XXX,XX @@ void hmp_info_mem(Monitor *mon, const QDict *qdict) mem_info_svxx(mon, env); } +#ifdef CONFIG_TCG static bool reg_is_ulong_integer(CPURISCVState *env, const char *name, target_ulong *val, bool is_gprh) { @@ -XXX,XX +XXX,XX @@ int riscv_monitor_get_register_legacy(CPUState *cs, const char *name, return -EINVAL; } +#endif diff --git a/target/riscv/tcg/cpu_helper.c b/target/riscv/tcg/cpu_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/cpu_helper.c +++ b/target/riscv/tcg/cpu_helper.c @@ -XXX,XX +XXX,XX @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address, env->two_stage_indirect_lookup = two_stage_indirect; } -hwaddr riscv_cpu_get_phys_addr_debug(CPUState *cs, vaddr addr) +bool riscv_cpu_translate_for_debug(CPUState *cs, vaddr addr, + TranslateForDebugResult *result) { RISCVCPU *cpu = RISCV_CPU(cs); CPURISCVState *env = &cpu->env; @@ -XXX,XX +XXX,XX @@ hwaddr riscv_cpu_get_phys_addr_debug(CPUState *cs, vaddr addr) if (get_physical_address(env, &phys_addr, &prot, addr, NULL, 0, mmu_idx, true, env->virt_enabled, true, false)) { - return -1; + return false; } if (env->virt_enabled) { if (get_physical_address(env, &phys_addr, &prot, phys_addr, NULL, 0, MMUIdx_U, false, true, true, false)) { - return -1; + return false; } } - return phys_addr; + *result = (TranslateForDebugResult) { + .physaddr = phys_addr, + .lg_page_size = TARGET_PAGE_BITS, + .attrs.debug = 1, + }; + return true; } void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, -- 2.54.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> riscv_trigger_* APIs are TCG only. Wrap the usages we have of them in cpu.c with CONFIG_TCG. After that we can move the header to the tcg subdir. This will be enough to get this out of the way for the --disable-tcg build. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260703180538.3346781-9-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/{ => tcg}/debug.h | 0 target/riscv/cpu.c | 8 +++++--- target/riscv/machine.c | 2 +- target/riscv/tcg/cpu_helper.c | 2 +- target/riscv/tcg/csr.c | 2 +- target/riscv/tcg/debug.c | 2 +- target/riscv/tcg/tcg-cpu.c | 2 +- 7 files changed, 10 insertions(+), 8 deletions(-) rename target/riscv/{ => tcg}/debug.h (100%) diff --git a/target/riscv/debug.h b/target/riscv/tcg/debug.h similarity index 100% rename from target/riscv/debug.h rename to target/riscv/tcg/debug.h diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -XXX,XX +XXX,XX @@ #include "kvm/kvm_riscv.h" #include "tcg/tcg-cpu.h" #if !defined(CONFIG_USER_ONLY) -#include "target/riscv/debug.h" +#include "target/riscv/tcg/debug.h" #endif /* RISC-V CPU definitions */ @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_reset_hold(Object *obj, ResetType type) env->vill = true; #ifndef CONFIG_USER_ONLY +#ifdef CONFIG_TCG if (cpu->cfg.debug) { riscv_trigger_reset_hold(env); } +#endif if (cpu->cfg.ext_smrnmi) { env->rnmip = 0; @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) riscv_cpu_register_gdb_regs_for_features(cs); -#ifndef CONFIG_USER_ONLY +#if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY) if (cpu->cfg.debug) { riscv_trigger_realize(&cpu->env); } @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) static void riscv_cpu_unrealize(DeviceState *dev) { RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev); -#ifndef CONFIG_USER_ONLY +#if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY) RISCVCPU *cpu = RISCV_CPU(dev); if (cpu->cfg.debug) { diff --git a/target/riscv/machine.c b/target/riscv/machine.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -XXX,XX +XXX,XX @@ #include "system/tcg.h" #include "migration/cpu.h" #include "exec/icount.h" -#include "target/riscv/debug.h" +#include "target/riscv/tcg/debug.h" #include "hw/riscv/machines-qom.h" static bool pmp_needed(void *opaque) diff --git a/target/riscv/tcg/cpu_helper.c b/target/riscv/tcg/cpu_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/cpu_helper.c +++ b/target/riscv/tcg/cpu_helper.c @@ -XXX,XX +XXX,XX @@ #include "semihosting/common-semi.h" #include "exec/icount.h" #include "cpu_bits.h" -#include "target/riscv/debug.h" +#include "target/riscv/tcg/debug.h" #include "pmp.h" #include "qemu/plugin.h" diff --git a/target/riscv/tcg/csr.c b/target/riscv/tcg/csr.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/csr.c +++ b/target/riscv/tcg/csr.c @@ -XXX,XX +XXX,XX @@ #include "tcg/insn-start-words.h" #include "internals.h" #if !defined(CONFIG_USER_ONLY) -#include "target/riscv/debug.h" +#include "target/riscv/tcg/debug.h" #endif /* CSR function table public API */ diff --git a/target/riscv/tcg/debug.c b/target/riscv/tcg/debug.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/debug.c +++ b/target/riscv/tcg/debug.c @@ -XXX,XX +XXX,XX @@ #include "qapi/error.h" #include "qemu/error-report.h" #include "cpu.h" -#include "target/riscv/debug.h" +#include "target/riscv/tcg/debug.h" #include "trace.h" #include "exec/helper-proto.h" #include "exec/watchpoint.h" diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -XXX,XX +XXX,XX @@ #include "hw/core/boards.h" #include "system/tcg.h" #include "exec/icount.h" -#include "target/riscv/debug.h" +#include "target/riscv/tcg/debug.h" #endif /* Hash that stores user set extensions */ -- 2.54.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Move riscv_new_csr_seed from csr.c to cpu.c since this function is shared with KVM. With that we can remove the csr.h from kvm-cpu.c. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260703180538.3346781-10-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.h | 3 ++- target/riscv/csr.h | 3 --- target/riscv/cpu.c | 30 ++++++++++++++++++++++++++++++ target/riscv/kvm/kvm-cpu.c | 1 - target/riscv/tcg/csr.c | 29 ----------------------------- 5 files changed, 32 insertions(+), 34 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -XXX,XX +XXX,XX @@ void riscv_add_satp_mode_properties(Object *obj); bool riscv_cpu_accelerator_compatible(RISCVCPU *cpu); void riscv_cpu_register_gdb_regs_for_features(CPUState *cs); - +target_ulong riscv_new_csr_seed(target_ulong new_value, + target_ulong write_mask); const char *satp_mode_str(uint8_t satp_mode, bool is_32_bit); const char *priv_spec_to_str(int priv_version); diff --git a/target/riscv/csr.h b/target/riscv/csr.h index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/csr.h +++ b/target/riscv/csr.h @@ -XXX,XX +XXX,XX @@ #include "exec/target_long.h" #include "cpu_bits.h" -target_ulong riscv_new_csr_seed(target_ulong new_value, - target_ulong write_mask); - RISCVException riscv_csrr(CPURISCVState *env, int csrno, target_ulong *ret_value); diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -XXX,XX +XXX,XX @@ #include "qemu/qemu-print.h" #include "qemu/ctype.h" #include "qemu/log.h" +#include "qemu/guest-random.h" #include "cpu.h" #include "cpu_vendorid.h" #include "target/riscv/csr.h" @@ -XXX,XX +XXX,XX @@ static void riscv_register_custom_csrs(RISCVCPU *cpu, const RISCVCSR *csr_list) } #endif +/* Used by csr.c and the KVM driver */ +target_ulong riscv_new_csr_seed(target_ulong new_value, + target_ulong write_mask) +{ + uint16_t random_v; + Error *random_e = NULL; + int random_r; + target_ulong rval; + + random_r = qemu_guest_getrandom(&random_v, 2, &random_e); + if (unlikely(random_r < 0)) { + /* + * Failed, for unknown reasons in the crypto subsystem. + * The best we can do is log the reason and return a + * failure indication to the guest. There is no reason + * we know to expect the failure to be transitory, so + * indicate DEAD to avoid having the guest spin on WAIT. + */ + qemu_log_mask(LOG_UNIMP, "%s: Crypto failure: %s", + __func__, error_get_pretty(random_e)); + error_free(random_e); + rval = SEED_OPST_DEAD; + } else { + rval = random_v | SEED_OPST_ES16; + } + + return rval; +} + static ObjectClass *riscv_cpu_class_by_name(const char *cpu_model) { ObjectClass *oc; diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/kvm/kvm-cpu.c +++ b/target/riscv/kvm/kvm-cpu.c @@ -XXX,XX +XXX,XX @@ #include "system/kvm.h" #include "system/kvm_int.h" #include "cpu.h" -#include "target/riscv/csr.h" #include "trace.h" #include "accel/accel-cpu-target.h" #include "hw/pci/pci.h" diff --git a/target/riscv/tcg/csr.c b/target/riscv/tcg/csr.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/csr.c +++ b/target/riscv/tcg/csr.c @@ -XXX,XX +XXX,XX @@ #include "exec/icount.h" #include "accel/tcg/cpu-loop.h" #include "accel/tcg/getpc.h" -#include "qemu/guest-random.h" #include "qapi/error.h" #include "tcg/insn-start-words.h" #include "internals.h" @@ -XXX,XX +XXX,XX @@ static RISCVException write_mnstatus(CPURISCVState *env, int csrno, #endif /* Crypto Extension */ -target_ulong riscv_new_csr_seed(target_ulong new_value, - target_ulong write_mask) -{ - uint16_t random_v; - Error *random_e = NULL; - int random_r; - target_ulong rval; - - random_r = qemu_guest_getrandom(&random_v, 2, &random_e); - if (unlikely(random_r < 0)) { - /* - * Failed, for unknown reasons in the crypto subsystem. - * The best we can do is log the reason and return a - * failure indication to the guest. There is no reason - * we know to expect the failure to be transitory, so - * indicate DEAD to avoid having the guest spin on WAIT. - */ - qemu_log_mask(LOG_UNIMP, "%s: Crypto failure: %s", - __func__, error_get_pretty(random_e)); - error_free(random_e); - rval = SEED_OPST_DEAD; - } else { - rval = random_v | SEED_OPST_ES16; - } - - return rval; -} - static RISCVException rmw_seed(CPURISCVState *env, int csrno, target_ulong *ret_value, target_ulong new_value, -- 2.54.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> After KVM is no longer reliant on csr.h move it to the TGC only land. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260703180538.3346781-11-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/{ => tcg}/csr.h | 0 target/riscv/cpu.c | 2 +- target/riscv/gdbstub.c | 2 +- target/riscv/monitor.c | 2 +- target/riscv/riscv-qmp-cmds.c | 2 +- target/riscv/tcg/csr.c | 2 +- target/riscv/tcg/mips_csr.c | 2 +- target/riscv/tcg/op_helper.c | 2 +- target/riscv/tcg/pmp.c | 2 +- target/riscv/tcg/th_csr.c | 2 +- 10 files changed, 9 insertions(+), 9 deletions(-) rename target/riscv/{ => tcg}/csr.h (100%) diff --git a/target/riscv/csr.h b/target/riscv/tcg/csr.h similarity index 100% rename from target/riscv/csr.h rename to target/riscv/tcg/csr.h diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -XXX,XX +XXX,XX @@ #include "qemu/guest-random.h" #include "cpu.h" #include "cpu_vendorid.h" -#include "target/riscv/csr.h" +#include "target/riscv/tcg/csr.h" #include "internals.h" #include "qapi/error.h" #include "qapi/visitor.h" diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/gdbstub.c +++ b/target/riscv/gdbstub.c @@ -XXX,XX +XXX,XX @@ #include "gdbstub/helpers.h" #include "cpu.h" #include "internals.h" -#include "target/riscv/csr.h" +#include "target/riscv/tcg/csr.h" struct TypeSize { const char *gdb_type; diff --git a/target/riscv/monitor.c b/target/riscv/monitor.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/monitor.c +++ b/target/riscv/monitor.c @@ -XXX,XX +XXX,XX @@ #include "qemu/ctype.h" #include "qemu/qemu-print.h" #include "cpu.h" -#include "target/riscv/csr.h" +#include "target/riscv/tcg/csr.h" #include "cpu_bits.h" #include "monitor/monitor.h" #include "monitor/hmp.h" diff --git a/target/riscv/riscv-qmp-cmds.c b/target/riscv/riscv-qmp-cmds.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/riscv-qmp-cmds.c +++ b/target/riscv/riscv-qmp-cmds.c @@ -XXX,XX +XXX,XX @@ #include "system/tcg.h" #include "cpu-qom.h" #include "cpu.h" -#include "target/riscv/csr.h" +#include "target/riscv/tcg/csr.h" static void riscv_cpu_add_definition(gpointer data, gpointer user_data) { diff --git a/target/riscv/tcg/csr.c b/target/riscv/tcg/csr.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/csr.c +++ b/target/riscv/tcg/csr.c @@ -XXX,XX +XXX,XX @@ #include "qemu/log.h" #include "qemu/timer.h" #include "cpu.h" -#include "target/riscv/csr.h" +#include "target/riscv/tcg/csr.h" #include "tcg/tcg-cpu.h" #include "pmu.h" #include "time_helper.h" diff --git a/target/riscv/tcg/mips_csr.c b/target/riscv/tcg/mips_csr.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/mips_csr.c +++ b/target/riscv/tcg/mips_csr.c @@ -XXX,XX +XXX,XX @@ #include "qemu/osdep.h" #include "cpu.h" #include "cpu_vendorid.h" -#include "target/riscv/csr.h" +#include "target/riscv/tcg/csr.h" /* Static MIPS CSR state storage */ static struct { diff --git a/target/riscv/tcg/op_helper.c b/target/riscv/tcg/op_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/op_helper.c +++ b/target/riscv/tcg/op_helper.c @@ -XXX,XX +XXX,XX @@ #include "qemu/osdep.h" #include "cpu.h" -#include "target/riscv/csr.h" +#include "target/riscv/tcg/csr.h" #include "internals.h" #include "exec/cputlb.h" #include "accel/tcg/cpu-ldst.h" diff --git a/target/riscv/tcg/pmp.c b/target/riscv/tcg/pmp.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/pmp.c +++ b/target/riscv/tcg/pmp.c @@ -XXX,XX +XXX,XX @@ #include "qemu/log.h" #include "qapi/error.h" #include "cpu.h" -#include "target/riscv/csr.h" +#include "target/riscv/tcg/csr.h" #include "trace.h" #include "exec/cputlb.h" #include "exec/page-protection.h" diff --git a/target/riscv/tcg/th_csr.c b/target/riscv/tcg/th_csr.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/th_csr.c +++ b/target/riscv/tcg/th_csr.c @@ -XXX,XX +XXX,XX @@ #include "qemu/osdep.h" #include "cpu.h" #include "cpu_vendorid.h" -#include "target/riscv/csr.h" +#include "target/riscv/tcg/csr.h" /* Extended M-mode control registers of T-Head */ #define CSR_TH_MXSTATUS 0x7c0 -- 2.54.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> We have a couple of CPUs that has a set of custom CSRs that uses TCG specific APIs. Move the related code to tcg-cpu.c and do not set .custom_csrs if we're not in a TCG build. What we'll end up doing, sooner or later, is punting all these CPUs to tcg-cpu.c since they're all TCG specific and KVM has nothing to do with them. Another time. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260703180538.3346781-12-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.h | 2 ++ target/riscv/cpu.c | 26 +++++--------------------- target/riscv/tcg/tcg-cpu.c | 21 +++++++++++++++++++++ 3 files changed, 28 insertions(+), 21 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -XXX,XX +XXX,XX @@ typedef struct RISCVCPUDef { int32_t vext_spec; RISCVCPUConfig cfg; bool bare; +#if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY) const RISCVCSR *custom_csrs; +#endif /* This is just a setter for env->num_triggers. */ uint32_t num_triggers; } RISCVCPUDef; diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -XXX,XX +XXX,XX @@ static void set_satp_mode_default_map(RISCVCPU *cpu) } #endif -#ifndef CONFIG_USER_ONLY -static void riscv_register_custom_csrs(RISCVCPU *cpu, const RISCVCSR *csr_list) -{ - for (size_t i = 0; csr_list[i].csr_ops.name; i++) { - int csrno = csr_list[i].csrno; - const riscv_csr_operations *csr_ops = &csr_list[i].csr_ops; - if (!csr_list[i].insertion_test || csr_list[i].insertion_test(cpu)) { - riscv_set_csr_ops(csrno, csr_ops); - } - } -} -#endif - /* Used by csr.c and the KVM driver */ target_ulong riscv_new_csr_seed(target_ulong new_value, target_ulong write_mask) @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_init(Object *obj) if (mcc->def->vext_spec != RISCV_PROFILE_ATTR_UNUSED) { cpu->env.vext_ver = mcc->def->vext_spec; } -#ifndef CONFIG_USER_ONLY - if (mcc->def->custom_csrs) { - riscv_register_custom_csrs(cpu, mcc->def->custom_csrs); - } -#endif accel_cpu_instance_init(CPU(obj)); } @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_class_base_init(ObjectClass *c, const void *data) riscv_cpu_cfg_merge(&mcc->def->cfg, &def->cfg); +#if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY) if (def->custom_csrs) { assert(!mcc->def->custom_csrs); mcc->def->custom_csrs = def->custom_csrs; } +#endif } if (!object_class_is_abstract(c)) { @@ -XXX,XX +XXX,XX @@ static const TypeInfo riscv_cpu_type_infos[] = { .cfg.mvendorid = THEAD_VENDOR_ID, .cfg.max_satp_mode = VM_1_10_SV39, -#ifndef CONFIG_USER_ONLY +#if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY) .custom_csrs = th_csr_list, #endif ), @@ -XXX,XX +XXX,XX @@ static const TypeInfo riscv_cpu_type_infos[] = { .cfg.marchid = 0x8d143000, .cfg.mvendorid = THEAD_VENDOR_ID, -#ifndef CONFIG_USER_ONLY +#if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY) .custom_csrs = th_csr_list, #endif ), @@ -XXX,XX +XXX,XX @@ static const TypeInfo riscv_cpu_type_infos[] = { .cfg.ext_xmipscmov = true, .cfg.marchid = 0x8000000000000201, .cfg.mvendorid = MIPS_VENDOR_ID, -#ifndef CONFIG_USER_ONLY +#if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY) .custom_csrs = mips_csr_list, #endif ), diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -XXX,XX +XXX,XX @@ #include "system/tcg.h" #include "exec/icount.h" #include "target/riscv/tcg/debug.h" +#include "target/riscv/tcg/csr.h" #endif /* Hash that stores user set extensions */ @@ -XXX,XX +XXX,XX @@ static bool riscv_cpu_has_max_extensions(Object *cpu_obj) return object_dynamic_cast(cpu_obj, TYPE_RISCV_CPU_MAX) != NULL; } +#ifndef CONFIG_USER_ONLY +static void riscv_register_custom_csrs(RISCVCPU *cpu, const RISCVCSR *csr_list) +{ + for (size_t i = 0; csr_list[i].csr_ops.name; i++) { + int csrno = csr_list[i].csrno; + const riscv_csr_operations *csr_ops = &csr_list[i].csr_ops; + if (!csr_list[i].insertion_test || csr_list[i].insertion_test(cpu)) { + riscv_set_csr_ops(csrno, csr_ops); + } + } +} +#endif + static void riscv_tcg_cpu_instance_init(CPUState *cs) { RISCVCPU *cpu = RISCV_CPU(cs); Object *obj = OBJECT(cpu); +#ifndef CONFIG_USER_ONLY + RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(obj); + + if (mcc->def->custom_csrs) { + riscv_register_custom_csrs(cpu, mcc->def->custom_csrs); + } +#endif misa_ext_user_opts = g_hash_table_new(NULL, g_direct_equal); multi_ext_user_opts = g_hash_table_new(NULL, g_direct_equal); -- 2.54.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> This function is related to Smrnmi and non-masked interrupts, firing up interrupts via env->rnmip from riscv_cpu_local_irq_pending(). This is all TCG only code. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260703180538.3346781-13-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.c | 8 -------- target/riscv/tcg/tcg-cpu.c | 7 +++++++ 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_set_irq(void *opaque, int irq, int level) g_assert_not_reached(); } } - -static void riscv_cpu_set_nmi(void *opaque, int irq, int level) -{ - riscv_cpu_set_rnmi(RISCV_CPU(opaque), irq, level); -} #endif /* CONFIG_USER_ONLY */ static bool riscv_cpu_is_dynamic(Object *cpu_obj) @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_init(Object *obj) #ifndef CONFIG_USER_ONLY qdev_init_gpio_in(DEVICE(obj), riscv_cpu_set_irq, IRQ_LOCAL_MAX + IRQ_LOCAL_GUEST_MAX); - qdev_init_gpio_in_named(DEVICE(cpu), riscv_cpu_set_nmi, - "riscv.cpu.rnmi", RNMI_MAX); - if (mcc->def->num_triggers) { env->num_triggers = mcc->def->num_triggers; } diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -XXX,XX +XXX,XX @@ static void riscv_register_custom_csrs(RISCVCPU *cpu, const RISCVCSR *csr_list) } } } + +static inline void riscv_cpu_set_nmi(void *opaque, int irq, int level) +{ + riscv_cpu_set_rnmi(RISCV_CPU(opaque), irq, level); +} #endif static void riscv_tcg_cpu_instance_init(CPUState *cs) @@ -XXX,XX +XXX,XX @@ static void riscv_tcg_cpu_instance_init(CPUState *cs) if (mcc->def->custom_csrs) { riscv_register_custom_csrs(cpu, mcc->def->custom_csrs); } + qdev_init_gpio_in_named(DEVICE(cpu), riscv_cpu_set_nmi, + "riscv.cpu.rnmi", RNMI_MAX); #endif misa_ext_user_opts = g_hash_table_new(NULL, g_direct_equal); -- 2.54.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> riscv_cpu_has_work() uses a handful of irq pending functions from cpu_helper.c. There is a very high possibility that KVM doesn't need the current implermentation of has_work(), but the common accel code needs an implementation of this callback (see cpu_exec_class_post_init) otherwise the KVM driver won't initialize. Move the relevant irq helpers to cpu.c to allow KVM to keep using the current has_work implementation, allowing --disable-tcg to work. We'll circle it back to evaluate a proper KVM implementation for it in a later date. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260703180538.3346781-14-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.h | 5 + target/riscv/cpu.c | 187 ++++++++++++++++++++++++++++++++++ target/riscv/tcg/cpu_helper.c | 187 ---------------------------------- 3 files changed, 192 insertions(+), 187 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -XXX,XX +XXX,XX @@ uint64_t riscv_cpu_all_pending(CPURISCVState *env); int riscv_cpu_mirq_pending(CPURISCVState *env); int riscv_cpu_sirq_pending(CPURISCVState *env); int riscv_cpu_vsirq_pending(CPURISCVState *env); +int riscv_cpu_pending_to_irq(CPURISCVState *env, + int extirq, unsigned int extirq_def_prio, + uint64_t pending, uint8_t *iprio); + + bool riscv_cpu_fp_enabled(CPURISCVState *env); uint8_t riscv_cpu_get_geilen(CPURISCVState *env); void riscv_cpu_set_geilen(CPURISCVState *env, uint8_t geilen); diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -XXX,XX +XXX,XX @@ static vaddr riscv_cpu_get_pc(CPUState *cs) } #ifndef CONFIG_USER_ONLY +/* + * Default priorities of local interrupts are defined in the + * RISC-V Advanced Interrupt Architecture specification. + * + * ---------------------------------------------------------------- + * Default | + * Priority | Major Interrupt Numbers + * ---------------------------------------------------------------- + * 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) + * | + * | 39, 19, 38, 37, 18, 36, + * Lowest | 35, 17, 34, 33, 16, 32 + * ---------------------------------------------------------------- + */ +static const uint8_t default_iprio[64] = { + /* 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] = IPRIO_DEFAULT_UPPER + 3, + [22] = IPRIO_DEFAULT_UPPER + 4, + [44] = IPRIO_DEFAULT_UPPER + 5, + + [43] = IPRIO_DEFAULT_UPPER + 6, + [21] = IPRIO_DEFAULT_UPPER + 7, + [42] = IPRIO_DEFAULT_UPPER + 8, + [41] = IPRIO_DEFAULT_UPPER + 9, + [20] = IPRIO_DEFAULT_UPPER + 10, + [40] = IPRIO_DEFAULT_UPPER + 11, + + [11] = IPRIO_DEFAULT_M, + [3] = IPRIO_DEFAULT_M + 1, + [7] = IPRIO_DEFAULT_M + 2, + + [9] = IPRIO_DEFAULT_S, + [1] = IPRIO_DEFAULT_S + 1, + [5] = IPRIO_DEFAULT_S + 2, + + [12] = IPRIO_DEFAULT_SGEXT, + + [10] = IPRIO_DEFAULT_VS, + [2] = IPRIO_DEFAULT_VS + 1, + [6] = IPRIO_DEFAULT_VS + 2, + + [39] = IPRIO_DEFAULT_LOWER, + [19] = IPRIO_DEFAULT_LOWER + 1, + [38] = IPRIO_DEFAULT_LOWER + 2, + [37] = IPRIO_DEFAULT_LOWER + 3, + [18] = IPRIO_DEFAULT_LOWER + 4, + [36] = IPRIO_DEFAULT_LOWER + 5, + + [35] = IPRIO_DEFAULT_LOWER + 6, + [17] = IPRIO_DEFAULT_LOWER + 7, + [34] = IPRIO_DEFAULT_LOWER + 8, + [33] = IPRIO_DEFAULT_LOWER + 9, + [16] = IPRIO_DEFAULT_LOWER + 10, + [32] = IPRIO_DEFAULT_LOWER + 11, +}; + +uint8_t riscv_cpu_default_priority(int irq) +{ + if (irq < 0 || irq > 63) { + return IPRIO_MMAXIPRIO; + } + + return default_iprio[irq] ? default_iprio[irq] : IPRIO_MMAXIPRIO; +}; + +int riscv_cpu_pending_to_irq(CPURISCVState *env, + int extirq, unsigned int extirq_def_prio, + uint64_t pending, uint8_t *iprio) +{ + int irq, best_irq = RISCV_EXCP_NONE; + unsigned int prio, best_prio = UINT_MAX; + + if (!pending) { + return RISCV_EXCP_NONE; + } + + irq = ctz64(pending); + if (!((extirq == IRQ_M_EXT) ? riscv_cpu_cfg(env)->ext_smaia : + riscv_cpu_cfg(env)->ext_ssaia)) { + return irq; + } + + pending = pending >> irq; + while (pending) { + prio = iprio[irq]; + if (!prio) { + if (irq == extirq) { + prio = extirq_def_prio; + } else { + prio = (riscv_cpu_default_priority(irq) < extirq_def_prio) ? + 1 : IPRIO_MMAXIPRIO; + } + } + if ((pending & 0x1) && (prio <= best_prio)) { + best_irq = irq; + best_prio = prio; + } + irq++; + pending = pending >> 1; + } + + return best_irq; +} + +/* + * Doesn't report interrupts inserted using mvip from M-mode firmware or + * using hvip bits 13:63 from HS-mode. Those are returned in + * riscv_cpu_sirq_pending() and riscv_cpu_vsirq_pending(). + */ +uint64_t riscv_cpu_all_pending(CPURISCVState *env) +{ + uint32_t gein = get_field(env->hstatus, HSTATUS_VGEIN); + uint64_t vsgein = (env->hgeip & (1ULL << gein)) ? MIP_VSEIP : 0; + uint64_t vstip = (env->vstime_irq) ? MIP_VSTIP : 0; + + return (env->mip | vsgein | vstip) & env->mie; +} + +int riscv_cpu_mirq_pending(CPURISCVState *env) +{ + uint64_t irqs = riscv_cpu_all_pending(env) & ~env->mideleg & + ~(MIP_SGEIP | MIP_VSSIP | MIP_VSTIP | MIP_VSEIP); + + return riscv_cpu_pending_to_irq(env, IRQ_M_EXT, IPRIO_DEFAULT_M, + irqs, env->miprio); +} + +int riscv_cpu_sirq_pending(CPURISCVState *env) +{ + uint64_t irqs = riscv_cpu_all_pending(env) & env->mideleg & ~env->hideleg; + uint64_t irqs_f = env->mvip & env->mvien & ~env->mideleg & env->sie; + + return riscv_cpu_pending_to_irq(env, IRQ_S_EXT, IPRIO_DEFAULT_S, + irqs | irqs_f, env->siprio); +} + +int riscv_cpu_vsirq_pending(CPURISCVState *env) +{ + uint64_t irqs = riscv_cpu_all_pending(env) & env->mideleg & env->hideleg; + uint64_t irqs_f_vs = env->hvip & env->hvien & ~env->hideleg & env->vsie; + uint64_t vsbits; + + /* Bring VS-level bits to correct position */ + vsbits = irqs & VS_MODE_INTERRUPTS; + irqs &= ~VS_MODE_INTERRUPTS; + irqs |= vsbits >> 1; + + return riscv_cpu_pending_to_irq(env, IRQ_S_EXT, IPRIO_DEFAULT_S, + (irqs | irqs_f_vs), env->hviprio); +} + bool riscv_cpu_has_work(CPUState *cs) { RISCVCPU *cpu = RISCV_CPU(cs); diff --git a/target/riscv/tcg/cpu_helper.c b/target/riscv/tcg/cpu_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/cpu_helper.c +++ b/target/riscv/tcg/cpu_helper.c @@ -XXX,XX +XXX,XX @@ int riscv_cpu_hviprio_index2irq(int index, int *out_irq, int *out_rdzero) return 0; } -/* - * Default priorities of local interrupts are defined in the - * RISC-V Advanced Interrupt Architecture specification. - * - * ---------------------------------------------------------------- - * Default | - * Priority | Major Interrupt Numbers - * ---------------------------------------------------------------- - * 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) - * | - * | 39, 19, 38, 37, 18, 36, - * Lowest | 35, 17, 34, 33, 16, 32 - * ---------------------------------------------------------------- - */ -static const uint8_t default_iprio[64] = { - /* 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] = IPRIO_DEFAULT_UPPER + 3, - [22] = IPRIO_DEFAULT_UPPER + 4, - [44] = IPRIO_DEFAULT_UPPER + 5, - - [43] = IPRIO_DEFAULT_UPPER + 6, - [21] = IPRIO_DEFAULT_UPPER + 7, - [42] = IPRIO_DEFAULT_UPPER + 8, - [41] = IPRIO_DEFAULT_UPPER + 9, - [20] = IPRIO_DEFAULT_UPPER + 10, - [40] = IPRIO_DEFAULT_UPPER + 11, - - [11] = IPRIO_DEFAULT_M, - [3] = IPRIO_DEFAULT_M + 1, - [7] = IPRIO_DEFAULT_M + 2, - - [9] = IPRIO_DEFAULT_S, - [1] = IPRIO_DEFAULT_S + 1, - [5] = IPRIO_DEFAULT_S + 2, - - [12] = IPRIO_DEFAULT_SGEXT, - - [10] = IPRIO_DEFAULT_VS, - [2] = IPRIO_DEFAULT_VS + 1, - [6] = IPRIO_DEFAULT_VS + 2, - - [39] = IPRIO_DEFAULT_LOWER, - [19] = IPRIO_DEFAULT_LOWER + 1, - [38] = IPRIO_DEFAULT_LOWER + 2, - [37] = IPRIO_DEFAULT_LOWER + 3, - [18] = IPRIO_DEFAULT_LOWER + 4, - [36] = IPRIO_DEFAULT_LOWER + 5, - - [35] = IPRIO_DEFAULT_LOWER + 6, - [17] = IPRIO_DEFAULT_LOWER + 7, - [34] = IPRIO_DEFAULT_LOWER + 8, - [33] = IPRIO_DEFAULT_LOWER + 9, - [16] = IPRIO_DEFAULT_LOWER + 10, - [32] = IPRIO_DEFAULT_LOWER + 11, -}; - -uint8_t riscv_cpu_default_priority(int irq) -{ - if (irq < 0 || irq > 63) { - return IPRIO_MMAXIPRIO; - } - - return default_iprio[irq] ? default_iprio[irq] : IPRIO_MMAXIPRIO; -}; - -static int riscv_cpu_pending_to_irq(CPURISCVState *env, - int extirq, unsigned int extirq_def_prio, - uint64_t pending, uint8_t *iprio) -{ - int irq, best_irq = RISCV_EXCP_NONE; - unsigned int prio, best_prio = UINT_MAX; - - if (!pending) { - return RISCV_EXCP_NONE; - } - - irq = ctz64(pending); - if (!((extirq == IRQ_M_EXT) ? riscv_cpu_cfg(env)->ext_smaia : - riscv_cpu_cfg(env)->ext_ssaia)) { - return irq; - } - - pending = pending >> irq; - while (pending) { - prio = iprio[irq]; - if (!prio) { - if (irq == extirq) { - prio = extirq_def_prio; - } else { - prio = (riscv_cpu_default_priority(irq) < extirq_def_prio) ? - 1 : IPRIO_MMAXIPRIO; - } - } - if ((pending & 0x1) && (prio <= best_prio)) { - best_irq = irq; - best_prio = prio; - } - irq++; - pending = pending >> 1; - } - - return best_irq; -} - -/* - * Doesn't report interrupts inserted using mvip from M-mode firmware or - * using hvip bits 13:63 from HS-mode. Those are returned in - * riscv_cpu_sirq_pending() and riscv_cpu_vsirq_pending(). - */ -uint64_t riscv_cpu_all_pending(CPURISCVState *env) -{ - uint32_t gein = get_field(env->hstatus, HSTATUS_VGEIN); - uint64_t vsgein = (env->hgeip & (1ULL << gein)) ? MIP_VSEIP : 0; - uint64_t vstip = (env->vstime_irq) ? MIP_VSTIP : 0; - - return (env->mip | vsgein | vstip) & env->mie; -} - -int riscv_cpu_mirq_pending(CPURISCVState *env) -{ - uint64_t irqs = riscv_cpu_all_pending(env) & ~env->mideleg & - ~(MIP_SGEIP | MIP_VSSIP | MIP_VSTIP | MIP_VSEIP); - - return riscv_cpu_pending_to_irq(env, IRQ_M_EXT, IPRIO_DEFAULT_M, - irqs, env->miprio); -} - -int riscv_cpu_sirq_pending(CPURISCVState *env) -{ - uint64_t irqs = riscv_cpu_all_pending(env) & env->mideleg & ~env->hideleg; - uint64_t irqs_f = env->mvip & env->mvien & ~env->mideleg & env->sie; - - return riscv_cpu_pending_to_irq(env, IRQ_S_EXT, IPRIO_DEFAULT_S, - irqs | irqs_f, env->siprio); -} - -int riscv_cpu_vsirq_pending(CPURISCVState *env) -{ - uint64_t irqs = riscv_cpu_all_pending(env) & env->mideleg & env->hideleg; - uint64_t irqs_f_vs = env->hvip & env->hvien & ~env->hideleg & env->vsie; - uint64_t vsbits; - - /* Bring VS-level bits to correct position */ - vsbits = irqs & VS_MODE_INTERRUPTS; - irqs &= ~VS_MODE_INTERRUPTS; - irqs |= vsbits >> 1; - - return riscv_cpu_pending_to_irq(env, IRQ_S_EXT, IPRIO_DEFAULT_S, - (irqs | irqs_f_vs), env->hviprio); -} - static int riscv_cpu_local_irq_pending(CPURISCVState *env) { uint64_t irqs, pending, mie, hsie, vsie, irqs_f, irqs_f_vs; -- 2.54.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> The function is used by hw/intc/ files that KVM cares about like riscv_aplic.c. Move it to cpu.c to be accessible for --disable-tcg builds. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260703180538.3346781-15-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.c | 14 ++++++++++++++ target/riscv/tcg/cpu_helper.c | 11 ----------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -XXX,XX +XXX,XX @@ target_ulong riscv_new_csr_seed(target_ulong new_value, return rval; } +#ifndef CONFIG_USER_ONLY +/* Used by lots of folks in hw/intc */ +int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts) +{ + CPURISCVState *env = &cpu->env; + if (env->miclaim & interrupts) { + return -1; + } else { + env->miclaim |= interrupts; + return 0; + } +} +#endif + static ObjectClass *riscv_cpu_class_by_name(const char *cpu_model) { ObjectClass *oc; diff --git a/target/riscv/tcg/cpu_helper.c b/target/riscv/tcg/cpu_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/cpu_helper.c +++ b/target/riscv/tcg/cpu_helper.c @@ -XXX,XX +XXX,XX @@ void riscv_cpu_set_rnmi(RISCVCPU *cpu, uint32_t irq, bool level) } } -int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts) -{ - CPURISCVState *env = &cpu->env; - if (env->miclaim & interrupts) { - return -1; - } else { - env->miclaim |= interrupts; - return 0; - } -} - void riscv_cpu_interrupt(CPURISCVState *env) { uint64_t gein, vsgein = 0, vstip = 0, irqf = 0; -- 2.54.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> riscv_dump_csr() is a TCG only function but we'll have to implement it at some capacity for KVM eventually, therefore put it under a CONFIG_TCG ifdef while making a note that this function is unimplemented in KVM. The csr_ops array is also TCG specific, thus the for loop inside dump_state that iterates it is also TCG only business. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Message-ID: <20260703180538.3346781-16-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -XXX,XX +XXX,XX @@ char *riscv_cpu_get_name(RISCVCPU *cpu) return cpu_model_from_type(typename); } +/* Note: this function needs a KVM implementation. */ static void riscv_dump_csr(CPURISCVState *env, int csrno, FILE *f) { +#ifdef CONFIG_TCG target_ulong val = 0; RISCVException res = riscv_csrrw_debug(env, csrno, &val, 0, 0); @@ -XXX,XX +XXX,XX @@ static void riscv_dump_csr(CPURISCVState *env, int csrno, FILE *f) qemu_fprintf(f, " %-13s " TARGET_FMT_lx "\n", csr_ops[csrno].name, val); } +#endif } #if !defined(CONFIG_USER_ONLY) @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags) } #endif qemu_fprintf(f, " %-13s %" PRIx64 "\n", "pc", env->pc); -#ifndef CONFIG_USER_ONLY +#if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY) for (i = 0; i < ARRAY_SIZE(csr_ops); i++) { int csrno = i; -- 2.54.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> riscv_cpu_update_mip() is a TCG only call. Its KVM equivalent is kvm_riscv_set_irq(). cpu.c gates the KVM only function with a kvm_enabled() check, making it unavailable for TCG only builds. We need to do the same for riscv_cpu_update_mip() otherwise a KVM only build will fail because it doesn't know what this function is. Use tcg_enabled() for the couple of riscv_cpu_update_mip() calls we have unguarded in cpu.c. We have way more calls to deal with in time_helper.c which isn't using kvm_riscv_set_irq() at all, so create a riscv_accel_set_irq() local helper that will choose whether to use the KVM or TCG API. The reason we're going through all this hassle in time_helper.c is because hw/int/riscv_aclint.c uses it, and if we don't do something about we won't have riscv_aclint working for KVM. Whether this is a real problem or not and we should remove aclint support for KVM is question for another day. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260703180538.3346781-17-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.c | 19 ++++++++++++++----- target/riscv/time_helper.c | 33 +++++++++++++++++++++++++-------- 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_set_irq(void *opaque, int irq, int level) case IRQ_M_EXT: if (kvm_enabled()) { kvm_riscv_set_irq(cpu, irq, level); - } else { + } + + if (tcg_enabled()) { riscv_cpu_update_mip(env, 1 << irq, BOOL_TO_MASK(level)); } break; case IRQ_S_EXT: if (kvm_enabled()) { kvm_riscv_set_irq(cpu, irq, level); - } else { + } + + if (tcg_enabled()) { env->external_seip = level; riscv_cpu_update_mip(env, 1 << irq, BOOL_TO_MASK(level | env->software_seip)); @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_set_irq(void *opaque, int irq, int level) env->hgeip |= 1ULL << irq; } - /* Update mip.SGEIP bit */ - riscv_cpu_update_mip(env, MIP_SGEIP, - BOOL_TO_MASK(!!(env->hgeie & env->hgeip))); + if (kvm_enabled()) { + kvm_riscv_set_irq(cpu, irq, level); + } + if (tcg_enabled()) { + /* Update mip.SGEIP bit */ + riscv_cpu_update_mip(env, MIP_SGEIP, + BOOL_TO_MASK(!!(env->hgeie & env->hgeip))); + } } else { g_assert_not_reached(); } diff --git a/target/riscv/time_helper.c b/target/riscv/time_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/time_helper.c +++ b/target/riscv/time_helper.c @@ -XXX,XX +XXX,XX @@ #include "cpu_bits.h" #include "time_helper.h" #include "hw/intc/riscv_aclint.h" +#include "kvm/kvm_riscv.h" +#include "system/kvm.h" +#include "system/tcg.h" + +static void riscv_accel_set_irq(RISCVCPU *cpu, int irq, int level) +{ + if (kvm_enabled()) { + kvm_riscv_set_irq(cpu, irq, level); + } + + if (tcg_enabled()) { + riscv_cpu_update_mip(&cpu->env, irq, level); + } +} + static void riscv_vstimer_cb(void *opaque) { RISCVCPU *cpu = opaque; CPURISCVState *env = &cpu->env; env->vstime_irq = 1; - riscv_cpu_update_mip(env, 0, BOOL_TO_MASK(1)); + riscv_accel_set_irq(cpu, 0, BOOL_TO_MASK(1)); } static void riscv_stimer_cb(void *opaque) { RISCVCPU *cpu = opaque; - riscv_cpu_update_mip(&cpu->env, MIP_STIP, BOOL_TO_MASK(1)); + riscv_accel_set_irq(cpu, MIP_STIP, BOOL_TO_MASK(1)); } /* @@ -XXX,XX +XXX,XX @@ void riscv_timer_write_timecmp(CPURISCVState *env, QEMUTimer *timer, RISCVAclintMTimerState *mtimer = env->rdtime_fn_arg; uint32_t timebase_freq; uint64_t rtc_r; + RISCVCPU *cpu; if (!riscv_cpu_cfg(env)->ext_sstc || !env->rdtime_fn || !env->rdtime_fn_arg || !get_field(env->menvcfg, MENVCFG_STCE)) { @@ -XXX,XX +XXX,XX @@ void riscv_timer_write_timecmp(CPURISCVState *env, QEMUTimer *timer, timebase_freq = mtimer->timebase_freq; rtc_r = env->rdtime_fn(env->rdtime_fn_arg) + delta; + cpu = env_archcpu(env); if (timecmp <= rtc_r) { /* @@ -XXX,XX +XXX,XX @@ void riscv_timer_write_timecmp(CPURISCVState *env, QEMUTimer *timer, */ if (timer_irq == MIP_VSTIP) { env->vstime_irq = 1; - riscv_cpu_update_mip(env, 0, BOOL_TO_MASK(1)); + riscv_accel_set_irq(cpu, 0, BOOL_TO_MASK(1)); } else { - riscv_cpu_update_mip(env, MIP_STIP, BOOL_TO_MASK(1)); + riscv_accel_set_irq(cpu, MIP_STIP, BOOL_TO_MASK(1)); } return; } @@ -XXX,XX +XXX,XX @@ void riscv_timer_write_timecmp(CPURISCVState *env, QEMUTimer *timer, /* Clear the [VS|S]TIP bit in mip */ if (timer_irq == MIP_VSTIP) { env->vstime_irq = 0; - riscv_cpu_update_mip(env, 0, BOOL_TO_MASK(0)); + riscv_accel_set_irq(cpu, 0, BOOL_TO_MASK(0)); } else { - riscv_cpu_update_mip(env, timer_irq, BOOL_TO_MASK(0)); + riscv_accel_set_irq(cpu, timer_irq, BOOL_TO_MASK(0)); } /* @@ -XXX,XX +XXX,XX @@ static void riscv_timer_disable_timecmp(CPURISCVState *env, QEMUTimer *timer, { /* Disable S-mode Timer IRQ and HW-based STIP */ if ((timer_irq == MIP_STIP) && !get_field(env->menvcfg, MENVCFG_STCE)) { - riscv_cpu_update_mip(env, timer_irq, BOOL_TO_MASK(0)); + riscv_accel_set_irq(env_archcpu(env), timer_irq, BOOL_TO_MASK(0)); timer_del(timer); return; } @@ -XXX,XX +XXX,XX @@ static void riscv_timer_disable_timecmp(CPURISCVState *env, QEMUTimer *timer, (!get_field(env->menvcfg, MENVCFG_STCE) || !get_field(env->henvcfg, HENVCFG_STCE))) { env->vstime_irq = 0; - riscv_cpu_update_mip(env, 0, BOOL_TO_MASK(0)); + riscv_accel_set_irq(env_archcpu(env), 0, BOOL_TO_MASK(0)); timer_del(timer); return; } -- 2.54.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> We have a lot of TCG only initialization in the common cpu_reset_hold callback that prevents --disable-tcg to work. Put a CONFIG_TCG ifdef around those bits to make the build work. Eventually we'll create a TCG specific reset function in tcg-cpu.c but for now this suffices. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260703180538.3346781-18-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -XXX,XX +XXX,XX @@ bool riscv_cpu_has_work(CPUState *cs) static void riscv_cpu_reset_hold(Object *obj, ResetType type) { -#ifndef CONFIG_USER_ONLY - uint8_t iprio; - int i, irq, rdzero; -#endif CPUState *cs = CPU(obj); RISCVCPU *cpu = RISCV_CPU(cs); RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(obj); @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_reset_hold(Object *obj, ResetType type) MENVCFG_ADUE : 0); env->henvcfg = 0; +#ifdef CONFIG_TCG + uint8_t iprio; + int i, irq, rdzero; + /* Initialized default priorities of local interrupts. */ for (i = 0; i < ARRAY_SIZE(env->miprio); i++) { iprio = riscv_cpu_default_priority(i); @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_reset_hold(Object *obj, ResetType type) } pmp_unlock_entries(env); +#endif /* ifdef CONFIG_TCG */ #else env->priv = PRV_U; env->senvcfg = 0; env->menvcfg = 0; -#endif +#endif /* !CONFIG_USER_ONLY */ /* on reset elp is clear */ env->elp = false; -- 2.54.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> riscv_cpu_register_csr_qtest_callback(), vcsr_call() and csr_qtest_callback() are all TCG only and are not available in --disable-tcg builds. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Message-ID: <20260703180538.3346781-19-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/riscv/riscv_hart.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/hw/riscv/riscv_hart.c b/hw/riscv/riscv_hart.c index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/riscv_hart.c +++ b/hw/riscv/riscv_hart.c @@ -XXX,XX +XXX,XX @@ static void riscv_harts_cpu_reset(void *opaque) cpu_reset(CPU(cpu)); } -#ifndef CONFIG_USER_ONLY +#if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY) static void csr_call(char *cmd, uint64_t cpu_num, int csrno, uint64_t *val) { RISCVCPU *cpu = RISCV_CPU(cpu_by_arch_id(cpu_num)); @@ -XXX,XX +XXX,XX @@ static void riscv_harts_realize(DeviceState *dev, Error **errp) s->harts = g_new0(RISCVCPU, s->num_harts); -#ifndef CONFIG_USER_ONLY - riscv_cpu_register_csr_qtest_callback(); +#if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY) + if (qtest_enabled()) { + riscv_cpu_register_csr_qtest_callback(); + } #endif for (n = 0; n < s->num_harts; n++) { -- 2.54.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> The following functions are TCG only and are broken, if they were ever usable in the first place, with KVM: - riscv_gdb_(get|se)t_csr - riscv_gdb_(get|set)_virtual - riscv_gen_dynamic_csr_feature Gate everything with TCG enabled to at least get them out of the way to enable --disable-tcg. As a note for the future: other archs have distincts gdbstub files for each accelerator. There's a strong case for RISC-V to do the same. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Message-ID: <20260703180538.3346781-20-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/gdbstub.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/gdbstub.c +++ b/target/riscv/gdbstub.c @@ -XXX,XX +XXX,XX @@ static int riscv_gdb_set_vector(CPUState *cs, uint8_t *mem_buf, int n) return 0; } +#ifdef CONFIG_TCG static int riscv_gdb_get_csr(CPUState *cs, GByteArray *buf, int n) { RISCVCPU *cpu = RISCV_CPU(cs); @@ -XXX,XX +XXX,XX @@ static GDBFeature *riscv_gen_dynamic_csr_feature(CPUState *cs, int base_reg) return &cpu->dyn_csr_feature; } +#endif /* CONFIG_TCG */ static GDBFeature *ricsv_gen_dynamic_vector_feature(CPUState *cs, int base_reg) { @@ -XXX,XX +XXX,XX @@ static GDBFeature *ricsv_gen_dynamic_vector_feature(CPUState *cs, int base_reg) void riscv_cpu_register_gdb_regs_for_features(CPUState *cs) { - RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cs); RISCVCPU *cpu = RISCV_CPU(cs); CPURISCVState *env = &cpu->env; if (env->misa_ext & RVD) { @@ -XXX,XX +XXX,XX @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs) riscv_gdb_set_vector, ricsv_gen_dynamic_vector_feature(cs, cs->gdb_num_regs)); } + +#ifdef CONFIG_TCG + RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cs); + switch (mcc->def->misa_mxl_max) { case MXL_RV32: gdb_register_coprocessor(cs, riscv_gdb_get_virtual, @@ -XXX,XX +XXX,XX @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs) gdb_register_coprocessor(cs, riscv_gdb_get_csr, riscv_gdb_set_csr, riscv_gen_dynamic_csr_feature(cs, cs->gdb_num_regs)); } +#endif } -- 2.54.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> There's no need for it to be in cpu_helper since riscv_aclint is the only caller. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260703180538.3346781-21-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.h | 2 -- hw/intc/riscv_aclint.c | 8 ++++++++ target/riscv/tcg/cpu_helper.c | 7 ------- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -XXX,XX +XXX,XX @@ uint64_t riscv_cpu_update_mip(CPURISCVState *env, uint64_t mask, void riscv_cpu_set_rnmi(RISCVCPU *cpu, uint32_t irq, bool level); void riscv_cpu_interrupt(CPURISCVState *env); #define BOOL_TO_MASK(x) (-!!(x)) /* helper for riscv_cpu_update_mip value */ -void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(void *), - void *arg); void riscv_cpu_set_aia_ireg_rmw_cb(CPURISCVState *env, privilege_mode_t priv, aia_ireg_rmw_fn rmw_fn, void *rmw_fn_arg); diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c index XXXXXXX..XXXXXXX 100644 --- a/hw/intc/riscv_aclint.c +++ b/hw/intc/riscv_aclint.c @@ -XXX,XX +XXX,XX @@ typedef struct riscv_aclint_mtimer_callback { int num; } riscv_aclint_mtimer_callback; +static void riscv_cpu_set_rdtime_fn(CPURISCVState *env, + uint64_t (*fn)(void *), + void *arg) +{ + env->rdtime_fn = fn; + env->rdtime_fn_arg = arg; +} + static uint64_t cpu_riscv_read_rtc_raw(uint32_t timebase_freq) { return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), diff --git a/target/riscv/tcg/cpu_helper.c b/target/riscv/tcg/cpu_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/cpu_helper.c +++ b/target/riscv/tcg/cpu_helper.c @@ -XXX,XX +XXX,XX @@ uint64_t riscv_cpu_update_mip(CPURISCVState *env, uint64_t mask, uint64_t value) return old; } -void riscv_cpu_set_rdtime_fn(CPURISCVState *env, uint64_t (*fn)(void *), - void *arg) -{ - env->rdtime_fn = fn; - env->rdtime_fn_arg = arg; -} - void riscv_cpu_set_aia_ireg_rmw_cb(CPURISCVState *env, privilege_mode_t priv, aia_ireg_rmw_fn rmw_fn, void *rmw_fn_arg) -- 2.54.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> No one uses it. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Message-ID: <20260703180538.3346781-22-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.h | 1 - target/riscv/tcg/cpu_helper.c | 9 --------- 2 files changed, 10 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -XXX,XX +XXX,XX @@ int riscv_cpu_pending_to_irq(CPURISCVState *env, bool riscv_cpu_fp_enabled(CPURISCVState *env); -uint8_t riscv_cpu_get_geilen(CPURISCVState *env); void riscv_cpu_set_geilen(CPURISCVState *env, uint8_t geilen); bool riscv_cpu_vector_enabled(CPURISCVState *env); void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable); diff --git a/target/riscv/tcg/cpu_helper.c b/target/riscv/tcg/cpu_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/cpu_helper.c +++ b/target/riscv/tcg/cpu_helper.c @@ -XXX,XX +XXX,XX @@ void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env) } } -uint8_t riscv_cpu_get_geilen(CPURISCVState *env) -{ - if (!riscv_has_ext(env, RVH)) { - return 0; - } - - return env->geilen; -} - void riscv_cpu_set_geilen(CPURISCVState *env, uint8_t geilen) { if (!riscv_has_ext(env, RVH)) { -- 2.54.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> riscv_imsic.c is the only caller. Having it sitting in the TCG only cpu_helper.c gets in the way of --disable-tcg for no good reason. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260703180538.3346781-23-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.h | 1 - hw/intc/riscv_imsic.c | 13 +++++++++++++ target/riscv/tcg/cpu_helper.c | 13 ------------- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -XXX,XX +XXX,XX @@ int riscv_cpu_pending_to_irq(CPURISCVState *env, bool riscv_cpu_fp_enabled(CPURISCVState *env); -void riscv_cpu_set_geilen(CPURISCVState *env, uint8_t geilen); bool riscv_cpu_vector_enabled(CPURISCVState *env); void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable); int riscv_env_mmu_index(CPURISCVState *env, bool ifetch); diff --git a/hw/intc/riscv_imsic.c b/hw/intc/riscv_imsic.c index XXXXXXX..XXXXXXX 100644 --- a/hw/intc/riscv_imsic.c +++ b/hw/intc/riscv_imsic.c @@ -XXX,XX +XXX,XX @@ #define IMSIC_EISTATE_ENPEND (IMSIC_EISTATE_ENABLED | \ IMSIC_EISTATE_PENDING) +static void riscv_cpu_set_geilen(CPURISCVState *env, uint8_t geilen) +{ + if (!riscv_has_ext(env, RVH)) { + return; + } + + if (geilen > (TARGET_LONG_BITS - 1)) { + return; + } + + env->geilen = geilen; +} + static uint32_t riscv_imsic_topei(RISCVIMSICState *imsic, uint32_t page) { uint32_t i, max_irq, base; diff --git a/target/riscv/tcg/cpu_helper.c b/target/riscv/tcg/cpu_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/cpu_helper.c +++ b/target/riscv/tcg/cpu_helper.c @@ -XXX,XX +XXX,XX @@ void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env) } } -void riscv_cpu_set_geilen(CPURISCVState *env, uint8_t geilen) -{ - if (!riscv_has_ext(env, RVH)) { - return; - } - - if (geilen > (TARGET_LONG_BITS - 1)) { - return; - } - - env->geilen = geilen; -} - void riscv_cpu_set_rnmi(RISCVCPU *cpu, uint32_t irq, bool level) { CPURISCVState *env = &cpu->env; -- 2.54.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> riscv_imsic.c is the only caller. Having it sitting in the TCG only cpu_helper.c gets in the way of --disable-tcg for no good reason. Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260703180538.3346781-24-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.h | 3 --- hw/intc/riscv_imsic.c | 11 +++++++++++ target/riscv/tcg/cpu_helper.c | 10 ---------- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -XXX,XX +XXX,XX @@ uint64_t riscv_cpu_update_mip(CPURISCVState *env, uint64_t mask, void riscv_cpu_set_rnmi(RISCVCPU *cpu, uint32_t irq, bool level); void riscv_cpu_interrupt(CPURISCVState *env); #define BOOL_TO_MASK(x) (-!!(x)) /* helper for riscv_cpu_update_mip value */ -void riscv_cpu_set_aia_ireg_rmw_cb(CPURISCVState *env, privilege_mode_t priv, - aia_ireg_rmw_fn rmw_fn, - void *rmw_fn_arg); RISCVException smstateen_acc_ok(CPURISCVState *env, int index, uint64_t bit); #endif /* !CONFIG_USER_ONLY */ diff --git a/hw/intc/riscv_imsic.c b/hw/intc/riscv_imsic.c index XXXXXXX..XXXXXXX 100644 --- a/hw/intc/riscv_imsic.c +++ b/hw/intc/riscv_imsic.c @@ -XXX,XX +XXX,XX @@ static void riscv_imsic_reset_enter(Object *obj, ResetType type) } } +static void riscv_cpu_set_aia_ireg_rmw_cb(CPURISCVState *env, + privilege_mode_t priv, + aia_ireg_rmw_fn rmw_fn, + void *rmw_fn_arg) +{ + if (priv <= PRV_M) { + env->aia_ireg_rmw_cb[priv] = rmw_fn; + env->aia_ireg_rmw_cb_arg[priv] = rmw_fn_arg; + } +} + static void riscv_imsic_realize(DeviceState *dev, Error **errp) { RISCVIMSICState *imsic = RISCV_IMSIC(dev); diff --git a/target/riscv/tcg/cpu_helper.c b/target/riscv/tcg/cpu_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/tcg/cpu_helper.c +++ b/target/riscv/tcg/cpu_helper.c @@ -XXX,XX +XXX,XX @@ uint64_t riscv_cpu_update_mip(CPURISCVState *env, uint64_t mask, uint64_t value) return old; } -void riscv_cpu_set_aia_ireg_rmw_cb(CPURISCVState *env, privilege_mode_t priv, - aia_ireg_rmw_fn rmw_fn, - void *rmw_fn_arg) -{ - if (priv <= PRV_M) { - env->aia_ireg_rmw_cb[priv] = rmw_fn; - env->aia_ireg_rmw_cb_arg[priv] = rmw_fn_arg; - } -} - static void riscv_ctr_freeze(CPURISCVState *env, uint64_t freeze_mask, bool virt) { -- 2.54.0
From: Zephyr Li <fritchleybohrer@gmail.com> Add CI coverage for a riscv64 --disable-tcg cross build. This ensures that RISC-V no-TCG/KVM-only builds keep working and prevents TCG-only code from being accidentally pulled into common RISC-V sources again. The cross_accel_build_job template enables KVM by default via --enable-${ACCEL:-kvm}, so the extra options only need to disable TCG. Signed-off-by: Zephyr Li <fritchleybohrer@gmail.com> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260703180538.3346781-25-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- .gitlab-ci.d/crossbuilds.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.gitlab-ci.d/crossbuilds.yml b/.gitlab-ci.d/crossbuilds.yml index XXXXXXX..XXXXXXX 100644 --- a/.gitlab-ci.d/crossbuilds.yml +++ b/.gitlab-ci.d/crossbuilds.yml @@ -XXX,XX +XXX,XX @@ cross-riscv64-user: variables: IMAGE: debian-riscv64-cross +cross-riscv64-kvm-only: + extends: .cross_accel_build_job + needs: + - job: riscv64-debian-cross-container + variables: + IMAGE: debian-riscv64-cross + EXTRA_CONFIGURE_OPTS: --disable-tcg --without-default-features + cross-s390x-system: extends: .cross_system_build_job needs: -- 2.54.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> We must check if IOHGATP_PPN is 16kb aligned for non-bare GATP modes. Fixes: 69a9ae4836 ("hw/riscv/riscv-iommu: add ATS support") Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3550 Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com> Reviewed-by: Nutty Liu <nutty.liu@hotmail.com> Message-ID: <20260702203616.1795588-2-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/riscv/riscv-iommu.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/riscv-iommu.c +++ b/hw/riscv/riscv-iommu.c @@ -XXX,XX +XXX,XX @@ static bool riscv_iommu_validate_device_ctx(RISCVIOMMUState *s, return false; } + if (gatp != RISCV_IOMMU_DC_IOHGATP_MODE_BARE) { + uint64_t iohgatp_ppn = get_field(ctx->gatp, + RISCV_IOMMU_DC_IOHGATP_PPN); + + /* + * One of the conditions for a misconfigured DDT entry + * according to the riscv-spec: "DC.iohgatp.MODE is not + * Bare and the root page table (address) determined by + * DC.iohgatp.PPN is not aligned to a 16-KiB boundary." + */ + if (PPN_PHYS(iohgatp_ppn) & ((1ULL << 14) - 1)) { + return false; + } + } + fsc_mode = get_field(ctx->satp, RISCV_IOMMU_DC_FSC_MODE); if (ctx->tc & RISCV_IOMMU_DC_TC_PDTV) { -- 2.54.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> riscv_iommu_translate(), the only caller of riscv_iommu_spa_fetch(), will use riscv_iommu_report_fault() for all faults it detects. And it will use iotlb->translated_addr as 'iotval2' every time. At this moment we're updating iotlb->translated_addr only after a translation step is completed, meaning any fault that occur before that will have a zeroed iotlb->translated_addr, and as a result iotval2 will also be zero later on. Keep iotlb->translated_addr updated with the latest translated addr we have. Fixes: 0c54acb8243d ("hw/riscv: add RISC-V IOMMU base emulation") Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3559 Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260702171202.1322493-1-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/riscv/riscv-iommu.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/riscv-iommu.c +++ b/hw/riscv/riscv-iommu.c @@ -XXX,XX +XXX,XX @@ static int riscv_iommu_spa_fetch(RISCVIOMMUState *s, RISCVIOMMUContext *ctx, } } while (1); + /* + * riscv_iommu_translate() will receive a fault and then call + * riscv_iommu_report_fault() using iotlb->translated_addr + * as iotval2. Update translated_addr it with the latest + * translated addr we have. + */ + iotlb->translated_addr = addr; + return (iotlb->perm & IOMMU_WO) ? (pass ? RISCV_IOMMU_FQ_CAUSE_WR_FAULT_VS : RISCV_IOMMU_FQ_CAUSE_WR_FAULT_S) : -- 2.54.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> When capabilities.AMO_HWADD isn't set, DC.tc.GADE and DC.tc.SADE are reserved bits and setting them throws a DDT_MISCONFIGURED error. Fixes: 0c54acb8243d ("hw/riscv: add RISC-V IOMMU base emulation") Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3549 Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Nutty Liu <nutty.liu@hotmail.com> Message-ID: <20260630172110.1866951-1-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/riscv/riscv-iommu-bits.h | 1 + hw/riscv/riscv-iommu.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/hw/riscv/riscv-iommu-bits.h b/hw/riscv/riscv-iommu-bits.h index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/riscv-iommu-bits.h +++ b/hw/riscv/riscv-iommu-bits.h @@ -XXX,XX +XXX,XX @@ struct riscv_iommu_pq_record { #define RISCV_IOMMU_CAP_SV57X4 BIT_ULL(19) #define RISCV_IOMMU_CAP_MSI_FLAT BIT_ULL(22) #define RISCV_IOMMU_CAP_MSI_MRIF BIT_ULL(23) +#define RISCV_IOMMU_CAP_AMO_HWAD BIT_ULL(24) #define RISCV_IOMMU_CAP_ATS BIT_ULL(25) #define RISCV_IOMMU_CAP_T2GPA BIT_ULL(26) #define RISCV_IOMMU_CAP_IGS GENMASK_ULL(29, 28) diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/riscv-iommu.c +++ b/hw/riscv/riscv-iommu.c @@ -XXX,XX +XXX,XX @@ static int riscv_iommu_spa_fetch(RISCVIOMMUState *s, RISCVIOMMUContext *ctx, const bool ade = ctx->tc & (pass ? RISCV_IOMMU_DC_TC_GADE : RISCV_IOMMU_DC_TC_SADE); + if (ade && !(s->cap & RISCV_IOMMU_CAP_AMO_HWAD)) { + /* GADE/SADE are reserved bits if AMO_HWAD is cleared. */ + return RISCV_IOMMU_FQ_CAUSE_DDT_MISCONFIGURED; + } + /* Address range check before first level lookup */ if (!sc[pass].step) { const uint64_t va_len = va_skip + va_bits; -- 2.54.0
From: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> We're hardcoding faulting type as READ, where it could very well be a write access, and we're not recording the faulting addr/iova. A note was added in the fault_type logic because I wasn't able to trivially handle a probable code repeitition it in this same patch. Something to do in a later date. Fixes: 0c54acb8243d ("hw/riscv: add RISC-V IOMMU base emulation") Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3564 Signed-off-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Message-ID: <20260701092241.307801-1-daniel.barboza@oss.qualcomm.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/riscv/riscv-iommu.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/riscv-iommu.c +++ b/hw/riscv/riscv-iommu.c @@ -XXX,XX +XXX,XX @@ static void riscv_iommu_ctx_inval(RISCVIOMMUState *s, GHFunc func, /* Find or allocate translation context for a given {device_id, process_id} */ static RISCVIOMMUContext *riscv_iommu_ctx(RISCVIOMMUState *s, unsigned devid, unsigned process_id, + IOMMUAccessFlags perm, uint64_t iova, void **ref) { GHashTable *ctx_cache; @@ -XXX,XX +XXX,XX @@ static RISCVIOMMUContext *riscv_iommu_ctx(RISCVIOMMUState *s, .process_id = process_id, }; unsigned mode = get_field(s->ddtp, RISCV_IOMMU_DDTP_MODE); + uint32_t fault_type; ctx_cache = g_hash_table_ref(s->ctx_cache); @@ -XXX,XX +XXX,XX @@ static RISCVIOMMUContext *riscv_iommu_ctx(RISCVIOMMUState *s, g_hash_table_unref(ctx_cache); *ref = NULL; - riscv_iommu_report_fault(s, ctx, RISCV_IOMMU_FQ_TTYPE_UADDR_RD, - fault, !!process_id, 0, 0); + /* + * TODO: (1) do we need to distinguish other fault types + * for ctx fetching and (2) evaluate putting the 'fault_type' + * logic inside riscv_iommu_report_fault() - there's at + * least one other place (end of riscv_iommu_translate()) + * that does something similar. + */ + if (perm & IOMMU_RO) { + fault_type = RISCV_IOMMU_FQ_TTYPE_UADDR_RD; + } else { + fault_type = RISCV_IOMMU_FQ_TTYPE_UADDR_WR; + } + + riscv_iommu_report_fault(s, ctx, fault_type, fault, + !!process_id, iova, 0); g_free(ctx); return NULL; @@ -XXX,XX +XXX,XX @@ static void riscv_iommu_process_dbg(RISCVIOMMUState *s) uint64_t ctrl = riscv_iommu_reg_get64(s, RISCV_IOMMU_REG_TR_REQ_CTL); unsigned devid = get_field(ctrl, RISCV_IOMMU_TR_REQ_CTL_DID); unsigned pid = get_field(ctrl, RISCV_IOMMU_TR_REQ_CTL_PID); + IOMMUAccessFlags perm = ctrl & RISCV_IOMMU_TR_REQ_CTL_NW + ? IOMMU_RO : IOMMU_RW; RISCVIOMMUContext *ctx; void *ref; @@ -XXX,XX +XXX,XX @@ static void riscv_iommu_process_dbg(RISCVIOMMUState *s) return; } - ctx = riscv_iommu_ctx(s, devid, pid, &ref); + ctx = riscv_iommu_ctx(s, devid, pid, perm, iova, &ref); if (ctx == NULL) { riscv_iommu_reg_set64(s, RISCV_IOMMU_REG_TR_RESPONSE, RISCV_IOMMU_TR_RESPONSE_FAULT | @@ -XXX,XX +XXX,XX @@ static void riscv_iommu_process_dbg(RISCVIOMMUState *s) } else { IOMMUTLBEntry iotlb = { .iova = iova, - .perm = ctrl & RISCV_IOMMU_TR_REQ_CTL_NW ? IOMMU_RO : IOMMU_RW, + .perm = perm, .addr_mask = ~0, .target_as = NULL, }; @@ -XXX,XX +XXX,XX @@ static MemTxResult riscv_iommu_trap_write(void *opaque, hwaddr addr, /* FIXME: PCIe bus remapping for attached endpoints. */ devid |= s->bus << 8; - ctx = riscv_iommu_ctx(s, devid, 0, &ref); + ctx = riscv_iommu_ctx(s, devid, 0, IOMMU_RW, addr, &ref); if (ctx == NULL) { res = MEMTX_ACCESS_ERROR; } else { @@ -XXX,XX +XXX,XX @@ static IOMMUTLBEntry riscv_iommu_memory_region_translate( }; uint32_t devid = riscv_iommu_space_devid(as); - ctx = riscv_iommu_ctx(as->iommu, devid, iommu_idx, &ref); + ctx = riscv_iommu_ctx(as->iommu, devid, iommu_idx, flag, addr, &ref); if (ctx == NULL) { /* Translation disabled or invalid. */ iotlb.addr_mask = 0; -- 2.54.0
From: Alistair Francis <alistair.francis@wdc.com> It was possible that a guest could overflow the `doe_cap->write_mbox` buffer by writing more then PCI_DOE_DW_SIZE_MAX dwords. `doe_cap->write_mbox_len` would continue to increment and there were no bounds checks on the length when offsetting into doe_cap->write_mbox. This patch adds a check and reports a guest error if we would overflow. On an overflow we also silenty discard the entire object as instructed to do in the PCIe spec when the length specified in the header (up to PCI_DOE_DW_SIZE_MAX dwords) doesn't match the length of the object. Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3679 Signed-off-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Reviewed-by: Tao Tang <tangtao1634@phytium.com.cn> Message-ID: <20260707020750.788960-1-alistair.francis@wdc.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/pci/pcie_doe.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/hw/pci/pcie_doe.c b/hw/pci/pcie_doe.c index XXXXXXX..XXXXXXX 100644 --- a/hw/pci/pcie_doe.c +++ b/hw/pci/pcie_doe.c @@ -XXX,XX +XXX,XX @@ static bool pcie_doe_discovery(DOECap *doe_cap) return true; } +static void pcie_doe_reset_write_mbox(DOECap *st) +{ + st->write_mbox_len = 0; + + memset(st->write_mbox, 0, PCI_DOE_DW_SIZE_MAX * DWORD_BYTE); +} + static void pcie_doe_reset_mbox(DOECap *st) { st->read_mbox_idx = 0; st->read_mbox_len = 0; - st->write_mbox_len = 0; memset(st->read_mbox, 0, PCI_DOE_DW_SIZE_MAX * DWORD_BYTE); - memset(st->write_mbox, 0, PCI_DOE_DW_SIZE_MAX * DWORD_BYTE); + + pcie_doe_reset_write_mbox(st); } void pcie_doe_init(PCIDevice *dev, DOECap *doe_cap, uint16_t offset, @@ -XXX,XX +XXX,XX @@ void pcie_doe_write_config(DOECap *doe_cap, if (size != DWORD_BYTE) { return; } - doe_cap->write_mbox[doe_cap->write_mbox_len] = val; - doe_cap->write_mbox_len++; + if (doe_cap->write_mbox_len < PCI_DOE_DW_SIZE_MAX) { + doe_cap->write_mbox[doe_cap->write_mbox_len] = val; + doe_cap->write_mbox_len++; + } else { + qemu_log_mask(LOG_GUEST_ERROR, + "Mailbox write length (%d) overflow\n", + doe_cap->write_mbox_len); + /* + * Too much data has been written, it can't + * "match the Length indicated in DOE Data Object Header 2" + * so we drop the entire object. + */ + pcie_doe_reset_write_mbox(doe_cap); + } break; case PCI_EXP_DOE_CAP: /* fallthrough */ -- 2.54.0
From: Wang Yechao <wang.yechao255@zte.com.cn> Expose zilsd, zclsd and zalasr. Signed-off-by: Wang Yechao <wang.yechao255@zte.com.cn> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260707072610.403595-1-wang.yechao255@zte.com.cn> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/kvm/kvm-cpu.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/kvm/kvm-cpu.c +++ b/target/riscv/kvm/kvm-cpu.c @@ -XXX,XX +XXX,XX @@ static KVMCPUConfig kvm_multi_ext_cfgs[] = { KVM_EXT_CFG("zihintntl", ext_zihintntl, KVM_RISCV_ISA_EXT_ZIHINTNTL), KVM_EXT_CFG("zihintpause", ext_zihintpause, KVM_RISCV_ISA_EXT_ZIHINTPAUSE), KVM_EXT_CFG("zihpm", ext_zihpm, KVM_RISCV_ISA_EXT_ZIHPM), + KVM_EXT_CFG("zilsd", ext_zilsd, KVM_RISCV_ISA_EXT_ZILSD), KVM_EXT_CFG("zimop", ext_zimop, KVM_RISCV_ISA_EXT_ZIMOP), KVM_EXT_CFG("zcmop", ext_zcmop, KVM_RISCV_ISA_EXT_ZCMOP), + KVM_EXT_CFG("zclsd", ext_zclsd, KVM_RISCV_ISA_EXT_ZCLSD), KVM_EXT_CFG("zabha", ext_zabha, KVM_RISCV_ISA_EXT_ZABHA), KVM_EXT_CFG("zacas", ext_zacas, KVM_RISCV_ISA_EXT_ZACAS), + KVM_EXT_CFG("zalasr", ext_zalasr, KVM_RISCV_ISA_EXT_ZALASR), KVM_EXT_CFG("zawrs", ext_zawrs, KVM_RISCV_ISA_EXT_ZAWRS), KVM_EXT_CFG("zfa", ext_zfa, KVM_RISCV_ISA_EXT_ZFA), KVM_EXT_CFG("zfbfmin", ext_zfbfmin, KVM_RISCV_ISA_EXT_ZFBFMIN), -- 2.54.0
From: Bin Meng <bin.meng@processmission.com> The OpenSBI firmware build job follows the same pattern as the EDK2 job [1] that was removed earlier [2]: it exists to produce firmware binaries from CI artifacts, but those outputs are not consumed by the tree. Remove the job definition and its project include to avoid maintaining bitrotting container and firmware build logic. [1] 71920809ceab ("gitlab-ci.yml: Add jobs to build EDK2 firmware binaries") [2] 690ceb71936f ("gitlab-ci: Remove job building EDK2 firmware binaries") Signed-off-by: Bin Meng <bin.meng@processmission.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com> Message-ID: <20260706161716.29488-1-bin.meng@processmission.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- MAINTAINERS | 2 - .gitlab-ci.d/opensbi.yml | 88 --------------------------------- .gitlab-ci.d/opensbi/Dockerfile | 34 ------------- .gitlab-ci.d/qemu-project.yml | 1 - 4 files changed, 125 deletions(-) delete mode 100644 .gitlab-ci.d/opensbi.yml delete mode 100644 .gitlab-ci.d/opensbi/Dockerfile diff --git a/MAINTAINERS b/MAINTAINERS index XXXXXXX..XXXXXXX 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -XXX,XX +XXX,XX @@ R: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> L: qemu-riscv@nongnu.org S: Supported F: pc-bios/opensbi-* -F: .gitlab-ci.d/opensbi.yml -F: .gitlab-ci.d/opensbi/ Clock framework M: Luc Michel <luc@lmichel.fr> diff --git a/.gitlab-ci.d/opensbi.yml b/.gitlab-ci.d/opensbi.yml deleted file mode 100644 index XXXXXXX..XXXXXXX --- a/.gitlab-ci.d/opensbi.yml +++ /dev/null @@ -XXX,XX +XXX,XX @@ -# All jobs needing docker-opensbi must use the same rules it uses. -.opensbi_job_rules: - rules: - # Forks don't get pipelines unless QEMU_CI=1 or QEMU_CI=2 is set - - if: '$QEMU_CI != "1" && $QEMU_CI != "2" && $CI_PROJECT_NAMESPACE != "qemu-project"' - when: never - - # In forks, if QEMU_CI=1 is set, then create manual job - # if any files affecting the build output are touched - - if: '$QEMU_CI == "1" && $CI_PROJECT_NAMESPACE != "qemu-project"' - changes: - - .gitlab-ci.d/opensbi.yml - - .gitlab-ci.d/opensbi/Dockerfile - - roms/opensbi/* - when: manual - - # In forks, if QEMU_CI=1 is set, then create manual job - # if the branch/tag starts with 'opensbi' - - if: '$QEMU_CI == "1" && $CI_PROJECT_NAMESPACE != "qemu-project" && $CI_COMMIT_REF_NAME =~ /^opensbi/' - when: manual - - # In forks, if QEMU_CI=1 is set, then create manual job - # if the last commit msg contains 'OpenSBI' (case insensitive) - - if: '$QEMU_CI == "1" && $CI_PROJECT_NAMESPACE != "qemu-project" && $CI_COMMIT_MESSAGE =~ /opensbi/i' - when: manual - - # Scheduled runs on mainline don't get pipelines except for the special Coverity job - - if: '$CI_PROJECT_NAMESPACE == $QEMU_CI_UPSTREAM && $CI_PIPELINE_SOURCE == "schedule"' - when: never - - # Run if any files affecting the build output are touched - - changes: - - .gitlab-ci.d/opensbi.yml - - .gitlab-ci.d/opensbi/Dockerfile - - roms/opensbi/* - when: on_success - - # Run if the branch/tag starts with 'opensbi' - - if: '$CI_COMMIT_REF_NAME =~ /^opensbi/' - when: on_success - - # Run if the last commit msg contains 'OpenSBI' (case insensitive) - - if: '$CI_COMMIT_MESSAGE =~ /opensbi/i' - when: on_success - -docker-opensbi: - extends: .opensbi_job_rules - stage: containers - image: docker:latest - services: - - docker:dind - variables: - GIT_DEPTH: 3 - IMAGE_TAG: $CI_REGISTRY_IMAGE:opensbi-cross-build - before_script: - - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY - - until docker info; do sleep 1; done - script: - - docker pull $IMAGE_TAG || true - - docker build --cache-from $IMAGE_TAG --tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA - --tag $IMAGE_TAG .gitlab-ci.d/opensbi - - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA - - docker push $IMAGE_TAG - -build-opensbi: - extends: .opensbi_job_rules - stage: build - needs: ['docker-opensbi'] - artifacts: - when: on_success - paths: # 'artifacts.zip' will contains the following files: - - pc-bios/opensbi-riscv32-generic-fw_dynamic.bin - - pc-bios/opensbi-riscv64-generic-fw_dynamic.bin - - opensbi32-generic-stdout.log - - opensbi32-generic-stderr.log - - opensbi64-generic-stdout.log - - opensbi64-generic-stderr.log - image: $CI_REGISTRY_IMAGE:opensbi-cross-build - variables: - GIT_DEPTH: 3 - script: # Clone the required submodules and build OpenSBI - - git submodule update --init roms/opensbi - - export JOBS=$(($(getconf _NPROCESSORS_ONLN) + 1)) - - echo "=== Using ${JOBS} simultaneous jobs ===" - - make -j${JOBS} -C roms/opensbi clean - - make -j${JOBS} -C roms opensbi32-generic 2>&1 1>opensbi32-generic-stdout.log | tee -a opensbi32-generic-stderr.log >&2 - - make -j${JOBS} -C roms/opensbi clean - - make -j${JOBS} -C roms opensbi64-generic 2>&1 1>opensbi64-generic-stdout.log | tee -a opensbi64-generic-stderr.log >&2 diff --git a/.gitlab-ci.d/opensbi/Dockerfile b/.gitlab-ci.d/opensbi/Dockerfile deleted file mode 100644 index XXXXXXX..XXXXXXX --- a/.gitlab-ci.d/opensbi/Dockerfile +++ /dev/null @@ -XXX,XX +XXX,XX @@ -# -# Docker image to cross-compile OpenSBI firmware binaries -# -FROM ubuntu:18.04 - -MAINTAINER Bin Meng <bmeng.cn@gmail.com> - -# Install packages required to build OpenSBI -RUN apt update \ - && \ - \ - DEBIAN_FRONTEND=noninteractive \ - apt install --assume-yes --no-install-recommends \ - build-essential \ - ca-certificates \ - git \ - make \ - python3 \ - wget \ - && \ - \ - rm -rf /var/lib/apt/lists/* - -# Manually install the kernel.org "Crosstool" based toolchains for gcc-8.3 -RUN wget -O - \ - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/8.3.0/x86_64-gcc-8.3.0-nolibc-riscv32-linux.tar.xz \ - | tar -C /opt -xJ -RUN wget -O - \ - https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/x86_64/8.3.0/x86_64-gcc-8.3.0-nolibc-riscv64-linux.tar.xz \ - | tar -C /opt -xJ - -# Export the toolchains to the system path -ENV PATH="/opt/gcc-8.3.0-nolibc/riscv32-linux/bin:${PATH}" -ENV PATH="/opt/gcc-8.3.0-nolibc/riscv64-linux/bin:${PATH}" diff --git a/.gitlab-ci.d/qemu-project.yml b/.gitlab-ci.d/qemu-project.yml index XXXXXXX..XXXXXXX 100644 --- a/.gitlab-ci.d/qemu-project.yml +++ b/.gitlab-ci.d/qemu-project.yml @@ -XXX,XX +XXX,XX @@ default: include: - local: '/.gitlab-ci.d/base.yml' - local: '/.gitlab-ci.d/stages.yml' - - local: '/.gitlab-ci.d/opensbi.yml' - local: '/.gitlab-ci.d/containers.yml' - local: '/.gitlab-ci.d/crossbuilds.yml' - local: '/.gitlab-ci.d/buildtest.yml' -- 2.54.0
From: Heinrich Schuchardt <heinrich.schuchardt@canonical.com> For easier bisection add the SPCR table to bios-tables-test-allowed-diff.h. Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260705063147.199732-2-heinrich.schuchardt@canonical.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- tests/qtest/bios-tables-test-allowed-diff.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index XXXXXXX..XXXXXXX 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h +++ b/tests/qtest/bios-tables-test-allowed-diff.h @@ -1 +1,3 @@ /* List of comma-separated changed AML files to ignore */ +"tests/data/acpi/loongarch64/virt/SPCR", +"tests/data/acpi/riscv64/virt/SPCR", -- 2.54.0
From: Heinrich Schuchardt <heinrich.schuchardt@canonical.com> On LoongArch and RISC-V invalid SPCR tables are created: Terminal Type : 00 Language : 03 The correct values are: Terminal Type : 03 Language : 00 This is due to commit 7dd0b070fa09 ("hw/arm/virt-acpi-build.c: Migrate SPCR creation to common location") that swapped the fields. See the specification of the table in https://learn.microsoft.com/en-us/windows-hardware/drivers/bringup/serial-port-console-redirection-table This page shows version 1.10. But the sequence of the fields was not changed since version 1.0. Our LoongArch and ARM code uses version 1.07 of the specification. Our RISC-V code uses version 1.10 of the specification. Fixes: 7dd0b070fa09 ("hw/arm/virt-acpi-build.c: Migrate SPCR creation to common location") Origin: https://lore.kernel.org/qemu-devel/20260326121947.51200-1-heinrich.schuchardt@canonical.com/T/#u Bug-Ubuntu: https://bugs.launchpad.net/ubuntu/+source/qemu/+bug/2146419 Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260705063147.199732-3-heinrich.schuchardt@canonical.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/acpi/aml-build.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c index XXXXXXX..XXXXXXX 100644 --- a/hw/acpi/aml-build.c +++ b/hw/acpi/aml-build.c @@ -XXX,XX +XXX,XX @@ void build_spcr(GArray *table_data, BIOSLinker *linker, build_append_int_noprefix(table_data, f->stop_bits, 1); /* Flow Control */ build_append_int_noprefix(table_data, f->flow_control, 1); - /* Language */ - build_append_int_noprefix(table_data, f->language, 1); /* Terminal Type */ build_append_int_noprefix(table_data, f->terminal_type, 1); + /* Language */ + build_append_int_noprefix(table_data, f->language, 1); /* PCI Device ID */ build_append_int_noprefix(table_data, f->pci_device_id, 2); /* PCI Vendor ID */ -- 2.54.0
From: Heinrich Schuchardt <heinrich.schuchardt@canonical.com> On LoongArch and RISC-V the SPCR test data contained: Terminal Type : 00 Language : 03 The corrected values are: Terminal Type : 03 Language : 00 See the specification of the table in https://learn.microsoft.com/en-us/windows-hardware/drivers/bringup/serial-port-console-redirection-table The ACPI table data was rebuilt with tests/data/acpi/rebuild-expected-aml.sh. Remove SPCR expections from tests/qtest/bios-tables-test-allowed-diff.h. Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20260705063147.199732-4-heinrich.schuchardt@canonical.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- tests/qtest/bios-tables-test-allowed-diff.h | 2 -- tests/data/acpi/loongarch64/virt/SPCR | Bin 80 -> 80 bytes tests/data/acpi/riscv64/virt/SPCR | Bin 90 -> 90 bytes 3 files changed, 2 deletions(-) diff --git a/tests/qtest/bios-tables-test-allowed-diff.h b/tests/qtest/bios-tables-test-allowed-diff.h index XXXXXXX..XXXXXXX 100644 --- a/tests/qtest/bios-tables-test-allowed-diff.h +++ b/tests/qtest/bios-tables-test-allowed-diff.h @@ -1,3 +1 @@ /* List of comma-separated changed AML files to ignore */ -"tests/data/acpi/loongarch64/virt/SPCR", -"tests/data/acpi/riscv64/virt/SPCR", diff --git a/tests/data/acpi/loongarch64/virt/SPCR b/tests/data/acpi/loongarch64/virt/SPCR index XXXXXXX..XXXXXXX 100644 Binary files a/tests/data/acpi/loongarch64/virt/SPCR and b/tests/data/acpi/loongarch64/virt/SPCR differ diff --git a/tests/data/acpi/riscv64/virt/SPCR b/tests/data/acpi/riscv64/virt/SPCR index XXXXXXX..XXXXXXX 100644 Binary files a/tests/data/acpi/riscv64/virt/SPCR and b/tests/data/acpi/riscv64/virt/SPCR differ -- 2.54.0