:p
atchew
Login
The following changes since commit 9468484fe904ab4691de6d9c34616667f377ceac: Merge tag 'block-pull-request' of https://gitlab.com/stefanha/qemu into staging (2024-01-09 10:32:23 +0000) are available in the Git repository at: https://github.com/alistair23/qemu.git tags/pull-riscv-to-apply-20240110 for you to fetch changes up to 71b76da33a1558bcd59100188f5753737ef6fa21: target/riscv: Ensure mideleg is set correctly on reset (2024-01-10 18:47:47 +1000) ---------------------------------------------------------------- RISC-V PR for 9.0 * Make vector whole-register move (vmv) depend on vtype register * Fix th.dcache.cval1 priviledge check * Don't allow write mstatus_vs without RVV * Use hwaddr instead of target_ulong for RV32 * Fix machine IDs QOM getters\ * Fix KVM reg id sizes * ACPI: Enable AIA, PLIC and update RHCT * Fix the interrupts-extended property format of PLIC * Add support for Zacas extension * Add amocas.[w,d,q] instructions * Document acpi parameter of virt machine * RVA22 profiles support * Remove group setting of KVM AIA if the machine only has 1 socket * Add RVV CSRs to KVM * sifive_u: Update S-mode U-Boot image build instructions * Upgrade OpenSBI from v1.3.1 to v1.4 * pmp: Ignore writes when RW=01 and MML=0 * Assert that the CSR numbers will be correct * Don't adjust vscause for exceptions * Ensure mideleg is set correctly on reset ---------------------------------------------------------------- Alistair Francis (3): target/riscv: Assert that the CSR numbers will be correct target/riscv: Don't adjust vscause for exceptions target/riscv: Ensure mideleg is set correctly on reset Bin Meng (2): docs/system/riscv: sifive_u: Update S-mode U-Boot image build instructions roms/opensbi: Upgrade from v1.3.1 to v1.4 Daniel Henrique Barboza (36): target/riscv/cpu.c: fix machine IDs getters target/riscv/kvm: change KVM_REG_RISCV_FP_F to u32 target/riscv/kvm: change KVM_REG_RISCV_FP_D to u64 target/riscv/kvm: change timer regs size to u64 target/riscv/kvm: add RISCV_CONFIG_REG() target/riscv/kvm: rename riscv_reg_id() to riscv_reg_id_ulong() target/riscv: create TYPE_RISCV_VENDOR_CPU target/riscv/tcg: do not use "!generic" CPU checks target/riscv/tcg: update priv_ver on user_set extensions target/riscv: add rv64i CPU target/riscv: add zicbop extension flag target/riscv/tcg: add 'zic64b' support riscv-qmp-cmds.c: expose named features in cpu_model_expansion target/riscv: add rva22u64 profile definition target/riscv/kvm: add 'rva22u64' flag as unavailable target/riscv/tcg: add user flag for profile support target/riscv/tcg: add MISA user options hash target/riscv/tcg: add riscv_cpu_write_misa_bit() target/riscv/tcg: handle profile MISA bits target/riscv/tcg: add hash table insert helpers target/riscv/tcg: honor user choice for G MISA bits target/riscv/tcg: validate profiles during finalize riscv-qmp-cmds.c: add profile flags in cpu-model-expansion target/riscv: add 'rva22u64' CPU target/riscv: implement svade target/riscv: add priv ver restriction to profiles target/riscv/cpu.c: finalize satp_mode earlier target/riscv/cpu.c: add riscv_cpu_is_32bit() target/riscv: add satp_mode profile support target/riscv: add 'parent' in profile description target/riscv: add RVA22S64 profile target/riscv: add rva22s64 cpu linux-headers: Update to Linux v6.7-rc5 linux-headers: riscv: add ptrace.h target/riscv/kvm: do PR_RISCV_V_SET_CONTROL during realize() target/riscv/kvm: add RVV and Vector CSR regs Heinrich Schuchardt (1): docs/system/riscv: document acpi parameter of virt machine Ivan Klokov (2): target/riscv/pmp: Use hwaddr instead of target_ulong for RV32 target/riscv: pmp: Ignore writes when RW=01 and MML=0 LIU Zhiwei (2): target/riscv: Fix th.dcache.cval1 priviledge check target/riscv: Not allow write mstatus_vs without RVV Max Chou (2): target/riscv: Add vill check for whole vector register move instructions target/riscv: The whole vector register move instructions depend on vsew Rob Bradford (1): disas/riscv: Add amocas.[w,d,q] instructions Sunil V L (13): hw/arm/virt-acpi-build.c: Migrate fw_cfg creation to common location hw/arm/virt-acpi-build.c: Migrate virtio creation to common location hw/i386/acpi-microvm.c: Use common function to add virtio in DSDT hw/riscv: virt: Make few IMSIC macros and functions public hw/riscv/virt-acpi-build.c: Add AIA support in RINTC hw/riscv/virt-acpi-build.c: Add IMSIC in the MADT hw/riscv/virt-acpi-build.c: Add APLIC in the MADT hw/riscv/virt-acpi-build.c: Add CMO information in RHCT hw/riscv/virt-acpi-build.c: Add MMU node in RHCT hw/pci-host/gpex: Define properties for MMIO ranges hw/riscv/virt: Update GPEX MMIO related properties hw/riscv/virt-acpi-build.c: Add IO controllers and devices hw/riscv/virt-acpi-build.c: Add PLIC in MADT Weiwei Li (1): target/riscv: Add support for Zacas extension Yong-Xuan Wang (2): hw/riscv/virt.c: fix the interrupts-extended property format of PLIC target/riscv/kvm.c: remove group setting of KVM AIA if the machine only has 1 socket docs/system/riscv/sifive_u.rst | 33 +- docs/system/riscv/virt.rst | 5 + include/hw/nvram/fw_cfg_acpi.h | 15 + include/hw/pci-host/gpex.h | 28 +- include/hw/riscv/virt.h | 26 ++ include/hw/virtio/virtio-acpi.h | 16 + include/standard-headers/drm/drm_fourcc.h | 2 + include/standard-headers/linux/pci_regs.h | 24 +- include/standard-headers/linux/vhost_types.h | 7 + include/standard-headers/linux/virtio_config.h | 5 + include/standard-headers/linux/virtio_pci.h | 11 + linux-headers/asm-arm64/kvm.h | 32 ++ linux-headers/asm-generic/unistd.h | 14 +- linux-headers/asm-loongarch/bitsperlong.h | 1 + linux-headers/asm-loongarch/kvm.h | 108 ++++++ linux-headers/asm-loongarch/mman.h | 1 + linux-headers/asm-loongarch/unistd.h | 5 + linux-headers/asm-mips/unistd_n32.h | 4 + linux-headers/asm-mips/unistd_n64.h | 4 + linux-headers/asm-mips/unistd_o32.h | 4 + linux-headers/asm-powerpc/unistd_32.h | 4 + linux-headers/asm-powerpc/unistd_64.h | 4 + linux-headers/asm-riscv/kvm.h | 12 + linux-headers/asm-riscv/ptrace.h | 132 +++++++ linux-headers/asm-s390/unistd_32.h | 4 + linux-headers/asm-s390/unistd_64.h | 4 + linux-headers/asm-x86/unistd_32.h | 4 + linux-headers/asm-x86/unistd_64.h | 3 + linux-headers/asm-x86/unistd_x32.h | 3 + linux-headers/linux/iommufd.h | 180 +++++++++- linux-headers/linux/kvm.h | 11 + linux-headers/linux/psp-sev.h | 1 + linux-headers/linux/stddef.h | 9 +- linux-headers/linux/userfaultfd.h | 9 +- linux-headers/linux/vfio.h | 47 ++- linux-headers/linux/vhost.h | 8 + target/riscv/cpu-qom.h | 5 + target/riscv/cpu.h | 18 + target/riscv/cpu_cfg.h | 5 + target/riscv/pmp.h | 8 +- target/riscv/insn32.decode | 6 + disas/riscv.c | 9 + hw/arm/virt-acpi-build.c | 51 +-- hw/i386/acpi-microvm.c | 15 +- hw/nvram/fw_cfg-acpi.c | 23 ++ hw/pci-host/gpex-acpi.c | 13 + hw/pci-host/gpex.c | 12 + hw/riscv/virt-acpi-build.c | 323 ++++++++++++++++-- hw/riscv/virt.c | 124 +++---- hw/virtio/virtio-acpi.c | 33 ++ target/riscv/cpu.c | 223 ++++++++++-- target/riscv/cpu_helper.c | 4 +- target/riscv/csr.c | 10 +- target/riscv/kvm/kvm-cpu.c | 250 ++++++++++---- target/riscv/pmp.c | 28 +- target/riscv/riscv-qmp-cmds.c | 44 ++- target/riscv/tcg/tcg-cpu.c | 455 ++++++++++++++++++++++--- target/riscv/translate.c | 1 + target/riscv/insn_trans/trans_rvv.c.inc | 8 +- target/riscv/insn_trans/trans_rvzacas.c.inc | 150 ++++++++ target/riscv/insn_trans/trans_xthead.c.inc | 2 +- hw/nvram/meson.build | 1 + hw/riscv/Kconfig | 1 + hw/virtio/meson.build | 1 + pc-bios/opensbi-riscv32-generic-fw_dynamic.bin | Bin 135376 -> 267416 bytes pc-bios/opensbi-riscv64-generic-fw_dynamic.bin | Bin 138368 -> 270808 bytes roms/opensbi | 2 +- scripts/update-linux-headers.sh | 3 + 68 files changed, 2248 insertions(+), 360 deletions(-) create mode 100644 include/hw/nvram/fw_cfg_acpi.h create mode 100644 include/hw/virtio/virtio-acpi.h create mode 100644 linux-headers/asm-loongarch/bitsperlong.h create mode 100644 linux-headers/asm-loongarch/kvm.h create mode 100644 linux-headers/asm-loongarch/mman.h create mode 100644 linux-headers/asm-loongarch/unistd.h create mode 100644 linux-headers/asm-riscv/ptrace.h create mode 100644 hw/nvram/fw_cfg-acpi.c create mode 100644 hw/virtio/virtio-acpi.c create mode 100644 target/riscv/insn_trans/trans_rvzacas.c.inc
From: Max Chou <max.chou@sifive.com> The ratified version of RISC-V V spec section 16.6 says that `The instructions operate as if EEW=SEW`. So the whole vector register move instructions depend on the vtype register that means the whole vector register move instructions should raise an illegal-instruction exception when vtype.vill=1. Signed-off-by: Max Chou <max.chou@sifive.com> Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Message-ID: <20231129170400.21251-2-max.chou@sifive.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/insn_trans/trans_rvv.c.inc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 bool trans_vcompress_vm(DisasContext *s, arg_r *a) } /* - * Whole Vector Register Move Instructions ignore vtype and vl setting. - * Thus, we don't need to check vill bit. (Section 16.6) + * Whole Vector Register Move Instructions depend on vtype register(vsew). + * Thus, we need to check vill bit. (Section 16.6) */ #define GEN_VMV_WHOLE_TRANS(NAME, LEN) \ static bool trans_##NAME(DisasContext *s, arg_##NAME * a) \ { \ if (require_rvv(s) && \ + vext_check_isa_ill(s) && \ QEMU_IS_ALIGNED(a->rd, LEN) && \ QEMU_IS_ALIGNED(a->rs2, LEN)) { \ uint32_t maxsz = (s->cfg_ptr->vlen >> 3) * LEN; \ -- 2.43.0
From: Max Chou <max.chou@sifive.com> The RISC-V v spec 16.6 section says that the whole vector register move instructions operate as if EEW=SEW. So it should depends on the vsew field of vtype register. Signed-off-by: Max Chou <max.chou@sifive.com> Acked-by: Richard Henderson <richard.henderson@linaro.org> Message-ID: <20231129170400.21251-3-max.chou@sifive.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/insn_trans/trans_rvv.c.inc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 bool trans_##NAME(DisasContext *s, arg_##NAME * a) \ QEMU_IS_ALIGNED(a->rs2, LEN)) { \ uint32_t maxsz = (s->cfg_ptr->vlen >> 3) * LEN; \ if (s->vstart_eq_zero) { \ - /* EEW = 8 */ \ - tcg_gen_gvec_mov(MO_8, vreg_ofs(s, a->rd), \ + tcg_gen_gvec_mov(s->sew, vreg_ofs(s, a->rd), \ vreg_ofs(s, a->rs2), maxsz, maxsz); \ mark_vs_dirty(s); \ } else { \ -- 2.43.0
From: LIU Zhiwei <zhiwei_liu@linux.alibaba.com> According to the specification, the th.dcache.cvall1 can be executed under all priviledges. The specification about xtheadcmo located in, https://github.com/T-head-Semi/thead-extension-spec/blob/master/xtheadcmo/dcache_cval1.adoc Signed-off-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Christoph Muellner <christoph.muellner@vrull.eu> Message-ID: <20231208094315.177-1-zhiwei_liu@linux.alibaba.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/insn_trans/trans_xthead.c.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/riscv/insn_trans/trans_xthead.c.inc b/target/riscv/insn_trans/trans_xthead.c.inc index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/insn_trans/trans_xthead.c.inc +++ b/target/riscv/insn_trans/trans_xthead.c.inc @@ -XXX,XX +XXX,XX @@ NOP_PRIVCHECK(th_dcache_csw, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS) NOP_PRIVCHECK(th_dcache_cisw, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS) NOP_PRIVCHECK(th_dcache_isw, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS) NOP_PRIVCHECK(th_dcache_cpal1, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS) -NOP_PRIVCHECK(th_dcache_cval1, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS) +NOP_PRIVCHECK(th_dcache_cval1, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MSU) NOP_PRIVCHECK(th_icache_iall, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS) NOP_PRIVCHECK(th_icache_ialls, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS) -- 2.43.0
From: LIU Zhiwei <zhiwei_liu@linux.alibaba.com> If CPU does not implement the Vector extension, it usually means mstatus vs hardwire to zero. So we should not allow write a non-zero value to this field. Signed-off-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20231215023313.1708-1-zhiwei_liu@linux.alibaba.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/csr.c | 5 ++++- 1 file changed, 4 insertions(+), 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_mstatus(CPURISCVState *env, int csrno, mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE | MSTATUS_SPP | MSTATUS_MPRV | MSTATUS_SUM | MSTATUS_MPP | MSTATUS_MXR | MSTATUS_TVM | MSTATUS_TSR | - MSTATUS_TW | MSTATUS_VS; + MSTATUS_TW; if (riscv_has_ext(env, RVF)) { mask |= MSTATUS_FS; } + if (riscv_has_ext(env, RVV)) { + mask |= MSTATUS_VS; + } if (xl != MXL_RV32 || env->debugger) { if (riscv_has_ext(env, RVH)) { -- 2.43.0
From: Ivan Klokov <ivan.klokov@syntacore.com> The Sv32 page-based virtual-memory scheme described in RISCV privileged spec Section 5.3 supports 34-bit physical addresses for RV32, so the PMP scheme must support addresses wider than XLEN for RV32. However, PMP address register format is still 32 bit wide. Signed-off-by: Ivan Klokov <ivan.klokov@syntacore.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20231123091214.20312-1-ivan.klokov@syntacore.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/pmp.h | 8 ++++---- target/riscv/pmp.c | 26 ++++++++++++-------------- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/target/riscv/pmp.h b/target/riscv/pmp.h index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/pmp.h +++ b/target/riscv/pmp.h @@ -XXX,XX +XXX,XX @@ typedef struct { } pmp_entry_t; typedef struct { - target_ulong sa; - target_ulong ea; + hwaddr sa; + hwaddr ea; } pmp_addr_t; typedef struct { @@ -XXX,XX +XXX,XX @@ target_ulong mseccfg_csr_read(CPURISCVState *env); void pmpaddr_csr_write(CPURISCVState *env, uint32_t addr_index, target_ulong val); target_ulong pmpaddr_csr_read(CPURISCVState *env, uint32_t addr_index); -bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr, +bool pmp_hart_has_privs(CPURISCVState *env, hwaddr addr, target_ulong size, pmp_priv_t privs, pmp_priv_t *allowed_privs, target_ulong mode); -target_ulong pmp_get_tlb_size(CPURISCVState *env, target_ulong addr); +target_ulong pmp_get_tlb_size(CPURISCVState *env, hwaddr addr); void pmp_update_rule_addr(CPURISCVState *env, uint32_t pmp_index); void pmp_update_rule_nums(CPURISCVState *env); uint32_t pmp_get_num_rules(CPURISCVState *env); 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 @@ void pmp_unlock_entries(CPURISCVState *env) } } -static void pmp_decode_napot(target_ulong a, target_ulong *sa, - target_ulong *ea) +static void pmp_decode_napot(hwaddr a, hwaddr *sa, hwaddr *ea) { /* * aaaa...aaa0 8-byte NAPOT range @@ -XXX,XX +XXX,XX @@ 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; - target_ulong sa = 0u; - target_ulong ea = 0u; + hwaddr sa = 0u; + hwaddr ea = 0u; if (pmp_index >= 1u) { prev_addr = env->pmp_state.pmp[pmp_index - 1].addr_reg; @@ -XXX,XX +XXX,XX @@ void pmp_update_rule_nums(CPURISCVState *env) } } -static int pmp_is_in_range(CPURISCVState *env, int pmp_index, - target_ulong addr) +static int pmp_is_in_range(CPURISCVState *env, int pmp_index, hwaddr addr) { int result = 0; @@ -XXX,XX +XXX,XX @@ static bool pmp_hart_has_privs_default(CPURISCVState *env, pmp_priv_t privs, * Return true if a pmp rule match or default match * Return false if no match */ -bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr, +bool pmp_hart_has_privs(CPURISCVState *env, hwaddr addr, target_ulong size, pmp_priv_t privs, pmp_priv_t *allowed_privs, target_ulong mode) { int i = 0; int pmp_size = 0; - target_ulong s = 0; - target_ulong e = 0; + hwaddr s = 0; + hwaddr e = 0; /* Short cut if no rules */ if (0 == pmp_get_num_rules(env)) { @@ -XXX,XX +XXX,XX @@ target_ulong mseccfg_csr_read(CPURISCVState *env) * To avoid this we return a size of 1 (which means no caching) if the PMP * region only covers partial of the TLB page. */ -target_ulong pmp_get_tlb_size(CPURISCVState *env, target_ulong addr) +target_ulong pmp_get_tlb_size(CPURISCVState *env, hwaddr addr) { - target_ulong pmp_sa; - target_ulong pmp_ea; - target_ulong tlb_sa = addr & ~(TARGET_PAGE_SIZE - 1); - target_ulong tlb_ea = tlb_sa + TARGET_PAGE_SIZE - 1; + hwaddr pmp_sa; + hwaddr pmp_ea; + hwaddr tlb_sa = addr & ~(TARGET_PAGE_SIZE - 1); + hwaddr tlb_ea = tlb_sa + TARGET_PAGE_SIZE - 1; int i; /* -- 2.43.0
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> mvendorid is an uint32 property, mimpid/marchid are uint64 properties. But their getters are returning bools. The reason this went under the radar for this long is because we have no code using the getters. The problem can be seem via the 'qom-get' API though. Launching QEMU with the 'veyron-v1' CPU, a model with: VEYRON_V1_MVENDORID: 0x61f (1567) VEYRON_V1_MIMPID: 0x111 (273) VEYRON_V1_MARCHID: 0x8000000000010000 (9223372036854841344) This is what the API returns when retrieving these properties: (qemu) qom-get /machine/soc0/harts[0] mvendorid true (qemu) qom-get /machine/soc0/harts[0] mimpid true (qemu) qom-get /machine/soc0/harts[0] marchid true After this patch: (qemu) qom-get /machine/soc0/harts[0] mvendorid 1567 (qemu) qom-get /machine/soc0/harts[0] mimpid 273 (qemu) qom-get /machine/soc0/harts[0] marchid 9223372036854841344 Fixes: 1e34150045 ("target/riscv/cpu.c: restrict 'mvendorid' value") Fixes: a1863ad368 ("target/riscv/cpu.c: restrict 'mimpid' value") Fixes: d6a427e2c0 ("target/riscv/cpu.c: restrict 'marchid' value") Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-ID: <20231211170732.2541368-1-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 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 cpu_set_mvendorid(Object *obj, Visitor *v, const char *name, static void cpu_get_mvendorid(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { - bool value = RISCV_CPU(obj)->cfg.mvendorid; + uint32_t value = RISCV_CPU(obj)->cfg.mvendorid; - visit_type_bool(v, name, &value, errp); + visit_type_uint32(v, name, &value, errp); } static void cpu_set_mimpid(Object *obj, Visitor *v, const char *name, @@ -XXX,XX +XXX,XX @@ static void cpu_set_mimpid(Object *obj, Visitor *v, const char *name, static void cpu_get_mimpid(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { - bool value = RISCV_CPU(obj)->cfg.mimpid; + uint64_t value = RISCV_CPU(obj)->cfg.mimpid; - visit_type_bool(v, name, &value, errp); + visit_type_uint64(v, name, &value, errp); } static void cpu_set_marchid(Object *obj, Visitor *v, const char *name, @@ -XXX,XX +XXX,XX @@ static void cpu_set_marchid(Object *obj, Visitor *v, const char *name, static void cpu_get_marchid(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { - bool value = RISCV_CPU(obj)->cfg.marchid; + uint64_t value = RISCV_CPU(obj)->cfg.marchid; - visit_type_bool(v, name, &value, errp); + visit_type_uint64(v, name, &value, errp); } static void riscv_cpu_class_init(ObjectClass *c, void *data) -- 2.43.0
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> KVM_REG_RISCV_FP_F regs have u32 size according to the API, but by using kvm_riscv_reg_id() in RISCV_FP_F_REG() we're returning u64 sizes when running with TARGET_RISCV64. The most likely reason why no one noticed this is because we're not implementing kvm_cpu_synchronize_state() in RISC-V yet. Create a new helper that returns a KVM ID with u32 size and use it in RISCV_FP_F_REG(). Reported-by: Andrew Jones <ajones@ventanamicro.com> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Message-ID: <20231208183835.2411523-2-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/kvm/kvm-cpu.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 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 uint64_t kvm_riscv_reg_id(CPURISCVState *env, uint64_t type, return id; } +static uint64_t kvm_riscv_reg_id_u32(uint64_t type, uint64_t idx) +{ + return KVM_REG_RISCV | KVM_REG_SIZE_U32 | type | idx; +} + #define RISCV_CORE_REG(env, name) kvm_riscv_reg_id(env, KVM_REG_RISCV_CORE, \ KVM_REG_RISCV_CORE_REG(name)) @@ -XXX,XX +XXX,XX @@ static uint64_t kvm_riscv_reg_id(CPURISCVState *env, uint64_t type, #define RISCV_TIMER_REG(env, name) kvm_riscv_reg_id(env, KVM_REG_RISCV_TIMER, \ KVM_REG_RISCV_TIMER_REG(name)) -#define RISCV_FP_F_REG(env, idx) kvm_riscv_reg_id(env, KVM_REG_RISCV_FP_F, idx) +#define RISCV_FP_F_REG(idx) kvm_riscv_reg_id_u32(KVM_REG_RISCV_FP_F, idx) #define RISCV_FP_D_REG(env, idx) kvm_riscv_reg_id(env, KVM_REG_RISCV_FP_D, idx) @@ -XXX,XX +XXX,XX @@ static int kvm_riscv_get_regs_fp(CPUState *cs) if (riscv_has_ext(env, RVF)) { uint32_t reg; for (i = 0; i < 32; i++) { - ret = kvm_get_one_reg(cs, RISCV_FP_F_REG(env, i), ®); + ret = kvm_get_one_reg(cs, RISCV_FP_F_REG(i), ®); if (ret) { return ret; } @@ -XXX,XX +XXX,XX @@ static int kvm_riscv_put_regs_fp(CPUState *cs) uint32_t reg; for (i = 0; i < 32; i++) { reg = env->fpr[i]; - ret = kvm_set_one_reg(cs, RISCV_FP_F_REG(env, i), ®); + ret = kvm_set_one_reg(cs, RISCV_FP_F_REG(i), ®); if (ret) { return ret; } -- 2.43.0
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> KVM_REG_RISCV_FP_D regs are always u64 size. Using kvm_riscv_reg_id() in RISCV_FP_D_REG() ends up encoding the wrong size if we're running with TARGET_RISCV32. Create a new helper that returns a KVM ID with u64 size and use it with RISCV_FP_D_REG(). Reported-by: Andrew Jones <ajones@ventanamicro.com> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Message-ID: <20231208183835.2411523-3-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/kvm/kvm-cpu.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 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 uint64_t kvm_riscv_reg_id_u32(uint64_t type, uint64_t idx) return KVM_REG_RISCV | KVM_REG_SIZE_U32 | type | idx; } +static uint64_t kvm_riscv_reg_id_u64(uint64_t type, uint64_t idx) +{ + return KVM_REG_RISCV | KVM_REG_SIZE_U64 | type | idx; +} + #define RISCV_CORE_REG(env, name) kvm_riscv_reg_id(env, KVM_REG_RISCV_CORE, \ KVM_REG_RISCV_CORE_REG(name)) @@ -XXX,XX +XXX,XX @@ static uint64_t kvm_riscv_reg_id_u32(uint64_t type, uint64_t idx) #define RISCV_FP_F_REG(idx) kvm_riscv_reg_id_u32(KVM_REG_RISCV_FP_F, idx) -#define RISCV_FP_D_REG(env, idx) kvm_riscv_reg_id(env, KVM_REG_RISCV_FP_D, idx) +#define RISCV_FP_D_REG(idx) kvm_riscv_reg_id_u64(KVM_REG_RISCV_FP_D, idx) #define KVM_RISCV_GET_CSR(cs, env, csr, reg) \ do { \ @@ -XXX,XX +XXX,XX @@ static int kvm_riscv_get_regs_fp(CPUState *cs) if (riscv_has_ext(env, RVD)) { uint64_t reg; for (i = 0; i < 32; i++) { - ret = kvm_get_one_reg(cs, RISCV_FP_D_REG(env, i), ®); + ret = kvm_get_one_reg(cs, RISCV_FP_D_REG(i), ®); if (ret) { return ret; } @@ -XXX,XX +XXX,XX @@ static int kvm_riscv_put_regs_fp(CPUState *cs) uint64_t reg; for (i = 0; i < 32; i++) { reg = env->fpr[i]; - ret = kvm_set_one_reg(cs, RISCV_FP_D_REG(env, i), ®); + ret = kvm_set_one_reg(cs, RISCV_FP_D_REG(i), ®); if (ret) { return ret; } -- 2.43.0
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> KVM_REG_RISCV_TIMER regs are always u64 according to the KVM API, but at this moment we'll return u32 regs if we're running a RISCV32 target. Use the kvm_riscv_reg_id_u64() helper in RISCV_TIMER_REG() to fix it. Reported-by: Andrew Jones <ajones@ventanamicro.com> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Message-ID: <20231208183835.2411523-4-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/kvm/kvm-cpu.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 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 uint64_t kvm_riscv_reg_id_u64(uint64_t type, uint64_t idx) #define RISCV_CSR_REG(env, name) kvm_riscv_reg_id(env, KVM_REG_RISCV_CSR, \ KVM_REG_RISCV_CSR_REG(name)) -#define RISCV_TIMER_REG(env, name) kvm_riscv_reg_id(env, KVM_REG_RISCV_TIMER, \ +#define RISCV_TIMER_REG(name) kvm_riscv_reg_id_u64(KVM_REG_RISCV_TIMER, \ KVM_REG_RISCV_TIMER_REG(name)) #define RISCV_FP_F_REG(idx) kvm_riscv_reg_id_u32(KVM_REG_RISCV_FP_F, idx) @@ -XXX,XX +XXX,XX @@ static uint64_t kvm_riscv_reg_id_u64(uint64_t type, uint64_t idx) } \ } while (0) -#define KVM_RISCV_GET_TIMER(cs, env, name, reg) \ +#define KVM_RISCV_GET_TIMER(cs, name, reg) \ do { \ - int ret = kvm_get_one_reg(cs, RISCV_TIMER_REG(env, name), ®); \ + int ret = kvm_get_one_reg(cs, RISCV_TIMER_REG(name), ®); \ if (ret) { \ abort(); \ } \ } while (0) -#define KVM_RISCV_SET_TIMER(cs, env, name, reg) \ +#define KVM_RISCV_SET_TIMER(cs, name, reg) \ do { \ - int ret = kvm_set_one_reg(cs, RISCV_TIMER_REG(env, name), ®); \ + int ret = kvm_set_one_reg(cs, RISCV_TIMER_REG(name), ®); \ if (ret) { \ abort(); \ } \ @@ -XXX,XX +XXX,XX @@ static void kvm_riscv_get_regs_timer(CPUState *cs) return; } - KVM_RISCV_GET_TIMER(cs, env, time, env->kvm_timer_time); - KVM_RISCV_GET_TIMER(cs, env, compare, env->kvm_timer_compare); - KVM_RISCV_GET_TIMER(cs, env, state, env->kvm_timer_state); - KVM_RISCV_GET_TIMER(cs, env, frequency, env->kvm_timer_frequency); + KVM_RISCV_GET_TIMER(cs, time, env->kvm_timer_time); + KVM_RISCV_GET_TIMER(cs, compare, env->kvm_timer_compare); + KVM_RISCV_GET_TIMER(cs, state, env->kvm_timer_state); + KVM_RISCV_GET_TIMER(cs, frequency, env->kvm_timer_frequency); env->kvm_timer_dirty = true; } @@ -XXX,XX +XXX,XX @@ static void kvm_riscv_put_regs_timer(CPUState *cs) return; } - KVM_RISCV_SET_TIMER(cs, env, time, env->kvm_timer_time); - KVM_RISCV_SET_TIMER(cs, env, compare, env->kvm_timer_compare); + KVM_RISCV_SET_TIMER(cs, time, env->kvm_timer_time); + KVM_RISCV_SET_TIMER(cs, compare, env->kvm_timer_compare); /* * To set register of RISCV_TIMER_REG(state) will occur a error from KVM @@ -XXX,XX +XXX,XX @@ static void kvm_riscv_put_regs_timer(CPUState *cs) * TODO If KVM changes, adapt here. */ if (env->kvm_timer_state) { - KVM_RISCV_SET_TIMER(cs, env, state, env->kvm_timer_state); + KVM_RISCV_SET_TIMER(cs, state, env->kvm_timer_state); } /* @@ -XXX,XX +XXX,XX @@ static void kvm_riscv_put_regs_timer(CPUState *cs) * during the migration. */ if (migration_is_running(migrate_get_current()->state)) { - KVM_RISCV_GET_TIMER(cs, env, frequency, reg); + KVM_RISCV_GET_TIMER(cs, frequency, reg); if (reg != env->kvm_timer_frequency) { error_report("Dst Hosts timer frequency != Src Hosts"); } -- 2.43.0
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Create a RISCV_CONFIG_REG() macro, similar to what other regs use, to hide away some of the boilerplate. Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Message-ID: <20231208183835.2411523-5-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/kvm/kvm-cpu.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 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 uint64_t kvm_riscv_reg_id_u64(uint64_t type, uint64_t idx) #define RISCV_CSR_REG(env, name) kvm_riscv_reg_id(env, KVM_REG_RISCV_CSR, \ KVM_REG_RISCV_CSR_REG(name)) +#define RISCV_CONFIG_REG(env, name) \ + kvm_riscv_reg_id(env, KVM_REG_RISCV_CONFIG, \ + KVM_REG_RISCV_CONFIG_REG(name)) + #define RISCV_TIMER_REG(name) kvm_riscv_reg_id_u64(KVM_REG_RISCV_TIMER, \ KVM_REG_RISCV_TIMER_REG(name)) @@ -XXX,XX +XXX,XX @@ static void kvm_riscv_init_machine_ids(RISCVCPU *cpu, KVMScratchCPU *kvmcpu) struct kvm_one_reg reg; int ret; - reg.id = kvm_riscv_reg_id(env, KVM_REG_RISCV_CONFIG, - KVM_REG_RISCV_CONFIG_REG(mvendorid)); + reg.id = RISCV_CONFIG_REG(env, mvendorid); reg.addr = (uint64_t)&cpu->cfg.mvendorid; ret = ioctl(kvmcpu->cpufd, KVM_GET_ONE_REG, ®); if (ret != 0) { error_report("Unable to retrieve mvendorid from host, error %d", ret); } - reg.id = kvm_riscv_reg_id(env, KVM_REG_RISCV_CONFIG, - KVM_REG_RISCV_CONFIG_REG(marchid)); + reg.id = RISCV_CONFIG_REG(env, marchid); reg.addr = (uint64_t)&cpu->cfg.marchid; ret = ioctl(kvmcpu->cpufd, KVM_GET_ONE_REG, ®); if (ret != 0) { error_report("Unable to retrieve marchid from host, error %d", ret); } - reg.id = kvm_riscv_reg_id(env, KVM_REG_RISCV_CONFIG, - KVM_REG_RISCV_CONFIG_REG(mimpid)); + reg.id = RISCV_CONFIG_REG(env, mimpid); reg.addr = (uint64_t)&cpu->cfg.mimpid; ret = ioctl(kvmcpu->cpufd, KVM_GET_ONE_REG, ®); if (ret != 0) { @@ -XXX,XX +XXX,XX @@ static void kvm_riscv_init_misa_ext_mask(RISCVCPU *cpu, struct kvm_one_reg reg; int ret; - reg.id = kvm_riscv_reg_id(env, KVM_REG_RISCV_CONFIG, - KVM_REG_RISCV_CONFIG_REG(isa)); + reg.id = RISCV_CONFIG_REG(env, isa); reg.addr = (uint64_t)&env->misa_ext_mask; ret = ioctl(kvmcpu->cpufd, KVM_GET_ONE_REG, ®); @@ -XXX,XX +XXX,XX @@ static int kvm_vcpu_set_machine_ids(RISCVCPU *cpu, CPUState *cs) uint64_t id; int ret; - id = kvm_riscv_reg_id(env, KVM_REG_RISCV_CONFIG, - KVM_REG_RISCV_CONFIG_REG(mvendorid)); + id = RISCV_CONFIG_REG(env, mvendorid); /* * cfg.mvendorid is an uint32 but a target_ulong will * be written. Assign it to a target_ulong var to avoid @@ -XXX,XX +XXX,XX @@ static int kvm_vcpu_set_machine_ids(RISCVCPU *cpu, CPUState *cs) return ret; } - id = kvm_riscv_reg_id(env, KVM_REG_RISCV_CONFIG, - KVM_REG_RISCV_CONFIG_REG(marchid)); + id = RISCV_CONFIG_REG(env, marchid); ret = kvm_set_one_reg(cs, id, &cpu->cfg.marchid); if (ret != 0) { return ret; } - id = kvm_riscv_reg_id(env, KVM_REG_RISCV_CONFIG, - KVM_REG_RISCV_CONFIG_REG(mimpid)); + id = RISCV_CONFIG_REG(env, mimpid); ret = kvm_set_one_reg(cs, id, &cpu->cfg.mimpid); return ret; -- 2.43.0
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> kvm_riscv_reg_id() returns an id encoded with an ulong size, i.e. an u32 size when running TARGET_RISCV32 and u64 when running TARGET_RISCV64. Rename it to kvm_riscv_reg_id_ulong() to enhance code readability. It'll be in line with the existing kvm_riscv_reg_id_<size>() helpers. Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Message-ID: <20231208183835.2411523-6-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/kvm/kvm-cpu.c | 40 ++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 19 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 @@ void riscv_kvm_aplic_request(void *opaque, int irq, int level) static bool cap_has_mp_state; -static uint64_t kvm_riscv_reg_id(CPURISCVState *env, uint64_t type, +static uint64_t kvm_riscv_reg_id_ulong(CPURISCVState *env, uint64_t type, uint64_t idx) { uint64_t id = KVM_REG_RISCV | type | idx; @@ -XXX,XX +XXX,XX @@ static uint64_t kvm_riscv_reg_id_u64(uint64_t type, uint64_t idx) return KVM_REG_RISCV | KVM_REG_SIZE_U64 | type | idx; } -#define RISCV_CORE_REG(env, name) kvm_riscv_reg_id(env, KVM_REG_RISCV_CORE, \ - KVM_REG_RISCV_CORE_REG(name)) +#define RISCV_CORE_REG(env, name) \ + kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_CORE, \ + KVM_REG_RISCV_CORE_REG(name)) -#define RISCV_CSR_REG(env, name) kvm_riscv_reg_id(env, KVM_REG_RISCV_CSR, \ - KVM_REG_RISCV_CSR_REG(name)) +#define RISCV_CSR_REG(env, name) \ + kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_CSR, \ + KVM_REG_RISCV_CSR_REG(name)) #define RISCV_CONFIG_REG(env, name) \ - kvm_riscv_reg_id(env, KVM_REG_RISCV_CONFIG, \ - KVM_REG_RISCV_CONFIG_REG(name)) + kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_CONFIG, \ + KVM_REG_RISCV_CONFIG_REG(name)) #define RISCV_TIMER_REG(name) kvm_riscv_reg_id_u64(KVM_REG_RISCV_TIMER, \ KVM_REG_RISCV_TIMER_REG(name)) @@ -XXX,XX +XXX,XX @@ static void kvm_riscv_update_cpu_misa_ext(RISCVCPU *cpu, CPUState *cs) /* If we're here we're going to disable the MISA bit */ reg = 0; - id = kvm_riscv_reg_id(env, KVM_REG_RISCV_ISA_EXT, - misa_cfg->kvm_reg_id); + id = kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_ISA_EXT, + misa_cfg->kvm_reg_id); ret = kvm_set_one_reg(cs, id, ®); if (ret != 0) { /* @@ -XXX,XX +XXX,XX @@ static void kvm_riscv_update_cpu_cfg_isa_ext(RISCVCPU *cpu, CPUState *cs) continue; } - id = kvm_riscv_reg_id(env, KVM_REG_RISCV_ISA_EXT, - multi_ext_cfg->kvm_reg_id); + id = kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_ISA_EXT, + multi_ext_cfg->kvm_reg_id); reg = kvm_cpu_cfg_get(cpu, multi_ext_cfg); ret = kvm_set_one_reg(cs, id, ®); if (ret != 0) { @@ -XXX,XX +XXX,XX @@ static int kvm_riscv_get_regs_core(CPUState *cs) env->pc = reg; for (i = 1; i < 32; i++) { - uint64_t id = kvm_riscv_reg_id(env, KVM_REG_RISCV_CORE, i); + uint64_t id = kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_CORE, i); ret = kvm_get_one_reg(cs, id, ®); if (ret) { return ret; @@ -XXX,XX +XXX,XX @@ static int kvm_riscv_put_regs_core(CPUState *cs) } for (i = 1; i < 32; i++) { - uint64_t id = kvm_riscv_reg_id(env, KVM_REG_RISCV_CORE, i); + uint64_t id = kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_CORE, i); reg = env->gpr[i]; ret = kvm_set_one_reg(cs, id, ®); if (ret) { @@ -XXX,XX +XXX,XX @@ static void kvm_riscv_read_cbomz_blksize(RISCVCPU *cpu, KVMScratchCPU *kvmcpu, struct kvm_one_reg reg; int ret; - reg.id = kvm_riscv_reg_id(env, KVM_REG_RISCV_CONFIG, - cbomz_cfg->kvm_reg_id); + reg.id = kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_CONFIG, + cbomz_cfg->kvm_reg_id); reg.addr = (uint64_t)kvmconfig_get_cfg_addr(cpu, cbomz_cfg); ret = ioctl(kvmcpu->cpufd, KVM_GET_ONE_REG, ®); if (ret != 0) { @@ -XXX,XX +XXX,XX @@ static void kvm_riscv_read_multiext_legacy(RISCVCPU *cpu, KVMCPUConfig *multi_ext_cfg = &kvm_multi_ext_cfgs[i]; struct kvm_one_reg reg; - reg.id = kvm_riscv_reg_id(env, KVM_REG_RISCV_ISA_EXT, - multi_ext_cfg->kvm_reg_id); + reg.id = kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_ISA_EXT, + multi_ext_cfg->kvm_reg_id); reg.addr = (uint64_t)&val; ret = ioctl(kvmcpu->cpufd, KVM_GET_ONE_REG, ®); if (ret != 0) { @@ -XXX,XX +XXX,XX @@ static void kvm_riscv_init_multiext_cfg(RISCVCPU *cpu, KVMScratchCPU *kvmcpu) for (i = 0; i < ARRAY_SIZE(kvm_multi_ext_cfgs); i++) { multi_ext_cfg = &kvm_multi_ext_cfgs[i]; - reg_id = kvm_riscv_reg_id(&cpu->env, KVM_REG_RISCV_ISA_EXT, - multi_ext_cfg->kvm_reg_id); + reg_id = kvm_riscv_reg_id_ulong(&cpu->env, KVM_REG_RISCV_ISA_EXT, + multi_ext_cfg->kvm_reg_id); reg_search = bsearch(®_id, reglist->reg, reglist->n, sizeof(uint64_t), uint64_cmp); if (!reg_search) { -- 2.43.0
From: Sunil V L <sunilvl@ventanamicro.com> RISC-V also needs to use the same code to create fw_cfg in DSDT. So, avoid code duplication by moving the code in arm and riscv to a device specific file. Suggested-by: Igor Mammedov <imammedo@redhat.com> Signed-off-by: Sunil V L <sunilvl@ventanamicro.com> Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Message-ID: <20231218150247.466427-2-sunilvl@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- include/hw/nvram/fw_cfg_acpi.h | 15 +++++++++++++++ hw/arm/virt-acpi-build.c | 19 ++----------------- hw/nvram/fw_cfg-acpi.c | 23 +++++++++++++++++++++++ hw/riscv/virt-acpi-build.c | 19 ++----------------- hw/nvram/meson.build | 1 + 5 files changed, 43 insertions(+), 34 deletions(-) create mode 100644 include/hw/nvram/fw_cfg_acpi.h create mode 100644 hw/nvram/fw_cfg-acpi.c diff --git a/include/hw/nvram/fw_cfg_acpi.h b/include/hw/nvram/fw_cfg_acpi.h new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/include/hw/nvram/fw_cfg_acpi.h @@ -XXX,XX +XXX,XX @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * ACPI support for fw_cfg + * + */ + +#ifndef FW_CFG_ACPI_H +#define FW_CFG_ACPI_H + +#include "qemu/osdep.h" +#include "exec/hwaddr.h" + +void fw_cfg_acpi_dsdt_add(Aml *scope, const MemMapEntry *fw_cfg_memmap); + +#endif diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -XXX,XX +XXX,XX @@ #include "target/arm/cpu.h" #include "hw/acpi/acpi-defs.h" #include "hw/acpi/acpi.h" -#include "hw/nvram/fw_cfg.h" +#include "hw/nvram/fw_cfg_acpi.h" #include "hw/acpi/bios-linker-loader.h" #include "hw/acpi/aml-build.h" #include "hw/acpi/utils.h" @@ -XXX,XX +XXX,XX @@ static void acpi_dsdt_add_uart(Aml *scope, const MemMapEntry *uart_memmap, aml_append(scope, dev); } -static void acpi_dsdt_add_fw_cfg(Aml *scope, const MemMapEntry *fw_cfg_memmap) -{ - Aml *dev = aml_device("FWCF"); - aml_append(dev, aml_name_decl("_HID", aml_string("QEMU0002"))); - /* device present, functioning, decoding, not shown in UI */ - aml_append(dev, aml_name_decl("_STA", aml_int(0xB))); - aml_append(dev, aml_name_decl("_CCA", aml_int(1))); - - Aml *crs = aml_resource_template(); - aml_append(crs, aml_memory32_fixed(fw_cfg_memmap->base, - fw_cfg_memmap->size, AML_READ_WRITE)); - aml_append(dev, aml_name_decl("_CRS", crs)); - aml_append(scope, dev); -} - static void acpi_dsdt_add_flash(Aml *scope, const MemMapEntry *flash_memmap) { Aml *dev, *crs; @@ -XXX,XX +XXX,XX @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) if (vmc->acpi_expose_flash) { acpi_dsdt_add_flash(scope, &memmap[VIRT_FLASH]); } - acpi_dsdt_add_fw_cfg(scope, &memmap[VIRT_FW_CFG]); + fw_cfg_acpi_dsdt_add(scope, &memmap[VIRT_FW_CFG]); acpi_dsdt_add_virtio(scope, &memmap[VIRT_MMIO], (irqmap[VIRT_MMIO] + ARM_SPI_BASE), NUM_VIRTIO_TRANSPORTS); acpi_dsdt_add_pci(scope, memmap, irqmap[VIRT_PCIE] + ARM_SPI_BASE, vms); diff --git a/hw/nvram/fw_cfg-acpi.c b/hw/nvram/fw_cfg-acpi.c new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/hw/nvram/fw_cfg-acpi.c @@ -XXX,XX +XXX,XX @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Add fw_cfg device in DSDT + * + */ + +#include "hw/nvram/fw_cfg_acpi.h" +#include "hw/acpi/aml-build.h" + +void fw_cfg_acpi_dsdt_add(Aml *scope, const MemMapEntry *fw_cfg_memmap) +{ + Aml *dev = aml_device("FWCF"); + aml_append(dev, aml_name_decl("_HID", aml_string("QEMU0002"))); + /* device present, functioning, decoding, not shown in UI */ + aml_append(dev, aml_name_decl("_STA", aml_int(0xB))); + aml_append(dev, aml_name_decl("_CCA", aml_int(1))); + + Aml *crs = aml_resource_template(); + aml_append(crs, aml_memory32_fixed(fw_cfg_memmap->base, + fw_cfg_memmap->size, AML_READ_WRITE)); + aml_append(dev, aml_name_decl("_CRS", crs)); + aml_append(scope, dev); +} 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 @@ #include "hw/acpi/acpi.h" #include "hw/acpi/aml-build.h" #include "hw/acpi/utils.h" +#include "hw/nvram/fw_cfg_acpi.h" #include "qapi/error.h" #include "qemu/error-report.h" #include "sysemu/reset.h" @@ -XXX,XX +XXX,XX @@ static void acpi_dsdt_add_cpus(Aml *scope, RISCVVirtState *s) } } -static void acpi_dsdt_add_fw_cfg(Aml *scope, const MemMapEntry *fw_cfg_memmap) -{ - Aml *dev = aml_device("FWCF"); - aml_append(dev, aml_name_decl("_HID", aml_string("QEMU0002"))); - - /* device present, functioning, decoding, not shown in UI */ - aml_append(dev, aml_name_decl("_STA", aml_int(0xB))); - aml_append(dev, aml_name_decl("_CCA", aml_int(1))); - - Aml *crs = aml_resource_template(); - aml_append(crs, aml_memory32_fixed(fw_cfg_memmap->base, - fw_cfg_memmap->size, AML_READ_WRITE)); - aml_append(dev, aml_name_decl("_CRS", crs)); - aml_append(scope, dev); -} - /* RHCT Node[N] starts at offset 56 */ #define RHCT_NODE_ARRAY_OFFSET 56 @@ -XXX,XX +XXX,XX @@ static void build_dsdt(GArray *table_data, scope = aml_scope("\\_SB"); acpi_dsdt_add_cpus(scope, s); - acpi_dsdt_add_fw_cfg(scope, &memmap[VIRT_FW_CFG]); + fw_cfg_acpi_dsdt_add(scope, &memmap[VIRT_FW_CFG]); aml_append(dsdt, scope); diff --git a/hw/nvram/meson.build b/hw/nvram/meson.build index XXXXXXX..XXXXXXX 100644 --- a/hw/nvram/meson.build +++ b/hw/nvram/meson.build @@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_XLNX_EFUSE_ZYNQMP', if_true: files( system_ss.add(when: 'CONFIG_XLNX_BBRAM', if_true: files('xlnx-bbram.c')) specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr_nvram.c')) +specific_ss.add(when: 'CONFIG_ACPI', if_true: files('fw_cfg-acpi.c')) -- 2.43.0
From: Sunil V L <sunilvl@ventanamicro.com> RISC-V also needs to create the virtio in DSDT in the same way as ARM. So, instead of duplicating the code, move this function to the device specific file which is common across architectures. Suggested-by: Igor Mammedov <imammedo@redhat.com> Signed-off-by: Sunil V L <sunilvl@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Message-ID: <20231218150247.466427-3-sunilvl@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- include/hw/virtio/virtio-acpi.h | 16 ++++++++++++++++ hw/arm/virt-acpi-build.c | 32 ++++---------------------------- hw/virtio/virtio-acpi.c | 33 +++++++++++++++++++++++++++++++++ hw/virtio/meson.build | 1 + 4 files changed, 54 insertions(+), 28 deletions(-) create mode 100644 include/hw/virtio/virtio-acpi.h create mode 100644 hw/virtio/virtio-acpi.c diff --git a/include/hw/virtio/virtio-acpi.h b/include/hw/virtio/virtio-acpi.h new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/include/hw/virtio/virtio-acpi.h @@ -XXX,XX +XXX,XX @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * ACPI support for virtio + */ + +#ifndef VIRTIO_ACPI_H +#define VIRTIO_ACPI_H + +#include "qemu/osdep.h" +#include "exec/hwaddr.h" + +void virtio_acpi_dsdt_add(Aml *scope, const hwaddr virtio_mmio_base, + const hwaddr virtio_mmio_size, uint32_t mmio_irq, + long int start_index, int num); + +#endif diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index XXXXXXX..XXXXXXX 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -XXX,XX +XXX,XX @@ #include "migration/vmstate.h" #include "hw/acpi/ghes.h" #include "hw/acpi/viot.h" +#include "hw/virtio/virtio-acpi.h" #define ARM_SPI_BASE 32 @@ -XXX,XX +XXX,XX @@ static void acpi_dsdt_add_flash(Aml *scope, const MemMapEntry *flash_memmap) aml_append(scope, dev); } -static void acpi_dsdt_add_virtio(Aml *scope, - const MemMapEntry *virtio_mmio_memmap, - uint32_t mmio_irq, int num) -{ - hwaddr base = virtio_mmio_memmap->base; - hwaddr size = virtio_mmio_memmap->size; - int i; - - for (i = 0; i < num; i++) { - uint32_t irq = mmio_irq + i; - Aml *dev = aml_device("VR%02u", i); - aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0005"))); - aml_append(dev, aml_name_decl("_UID", aml_int(i))); - aml_append(dev, aml_name_decl("_CCA", aml_int(1))); - - Aml *crs = aml_resource_template(); - aml_append(crs, aml_memory32_fixed(base, size, AML_READ_WRITE)); - aml_append(crs, - aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, - AML_EXCLUSIVE, &irq, 1)); - aml_append(dev, aml_name_decl("_CRS", crs)); - aml_append(scope, dev); - base += size; - } -} - static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap, uint32_t irq, VirtMachineState *vms) { @@ -XXX,XX +XXX,XX @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) acpi_dsdt_add_flash(scope, &memmap[VIRT_FLASH]); } fw_cfg_acpi_dsdt_add(scope, &memmap[VIRT_FW_CFG]); - acpi_dsdt_add_virtio(scope, &memmap[VIRT_MMIO], - (irqmap[VIRT_MMIO] + ARM_SPI_BASE), NUM_VIRTIO_TRANSPORTS); + virtio_acpi_dsdt_add(scope, memmap[VIRT_MMIO].base, memmap[VIRT_MMIO].size, + (irqmap[VIRT_MMIO] + ARM_SPI_BASE), + 0, NUM_VIRTIO_TRANSPORTS); acpi_dsdt_add_pci(scope, memmap, irqmap[VIRT_PCIE] + ARM_SPI_BASE, vms); if (vms->acpi_dev) { build_ged_aml(scope, "\\_SB."GED_DEVICE, diff --git a/hw/virtio/virtio-acpi.c b/hw/virtio/virtio-acpi.c new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/hw/virtio/virtio-acpi.c @@ -XXX,XX +XXX,XX @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * virtio ACPI Support + * + */ + +#include "hw/virtio/virtio-acpi.h" +#include "hw/acpi/aml-build.h" + +void virtio_acpi_dsdt_add(Aml *scope, const hwaddr base, const hwaddr size, + uint32_t mmio_irq, long int start_index, int num) +{ + hwaddr virtio_base = base; + uint32_t irq = mmio_irq; + long int i; + + for (i = start_index; i < start_index + num; i++) { + Aml *dev = aml_device("VR%02u", (unsigned)i); + aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0005"))); + aml_append(dev, aml_name_decl("_UID", aml_int(i))); + aml_append(dev, aml_name_decl("_CCA", aml_int(1))); + + Aml *crs = aml_resource_template(); + aml_append(crs, aml_memory32_fixed(virtio_base, size, AML_READ_WRITE)); + aml_append(crs, + aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, + AML_EXCLUSIVE, &irq, 1)); + aml_append(dev, aml_name_decl("_CRS", crs)); + aml_append(scope, dev); + virtio_base += size; + irq++; + } +} diff --git a/hw/virtio/meson.build b/hw/virtio/meson.build index XXXXXXX..XXXXXXX 100644 --- a/hw/virtio/meson.build +++ b/hw/virtio/meson.build @@ -XXX,XX +XXX,XX @@ system_ss.add(when: 'CONFIG_VIRTIO', if_false: files('virtio-stub.c')) system_ss.add(files('virtio-hmp-cmds.c')) specific_ss.add_all(when: 'CONFIG_VIRTIO', if_true: specific_virtio_ss) +system_ss.add(when: 'CONFIG_ACPI', if_true: files('virtio-acpi.c')) -- 2.43.0
From: Sunil V L <sunilvl@ventanamicro.com> With common function to add virtio in DSDT created now, update microvm code also to use it instead of duplicate code. Suggested-by: Andrew Jones <ajones@ventanamicro.com> Signed-off-by: Sunil V L <sunilvl@ventanamicro.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Message-ID: <20231218150247.466427-4-sunilvl@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/i386/acpi-microvm.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/hw/i386/acpi-microvm.c b/hw/i386/acpi-microvm.c index XXXXXXX..XXXXXXX 100644 --- a/hw/i386/acpi-microvm.c +++ b/hw/i386/acpi-microvm.c @@ -XXX,XX +XXX,XX @@ #include "hw/pci/pci.h" #include "hw/pci/pcie_host.h" #include "hw/usb/xhci.h" +#include "hw/virtio/virtio-acpi.h" #include "hw/virtio/virtio-mmio.h" #include "hw/input/i8042.h" @@ -XXX,XX +XXX,XX @@ static void acpi_dsdt_add_virtio(Aml *scope, uint32_t irq = mms->virtio_irq_base + index; hwaddr base = VIRTIO_MMIO_BASE + index * 512; hwaddr size = 512; - - Aml *dev = aml_device("VR%02u", (unsigned)index); - aml_append(dev, aml_name_decl("_HID", aml_string("LNRO0005"))); - aml_append(dev, aml_name_decl("_UID", aml_int(index))); - aml_append(dev, aml_name_decl("_CCA", aml_int(1))); - - Aml *crs = aml_resource_template(); - aml_append(crs, aml_memory32_fixed(base, size, AML_READ_WRITE)); - aml_append(crs, - aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, - AML_EXCLUSIVE, &irq, 1)); - aml_append(dev, aml_name_decl("_CRS", crs)); - aml_append(scope, dev); + virtio_acpi_dsdt_add(scope, base, size, irq, index, 1); } } } -- 2.43.0
From: Sunil V L <sunilvl@ventanamicro.com> Some macros and static function related to IMSIC are defined in virt.c. They are required in virt-acpi-build.c. So, make them public. Signed-off-by: Sunil V L <sunilvl@ventanamicro.com> Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Message-ID: <20231218150247.466427-5-sunilvl@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- include/hw/riscv/virt.h | 25 +++++++++++++++++++++++++ hw/riscv/virt.c | 25 +------------------------ 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/riscv/virt.h +++ b/include/hw/riscv/virt.h @@ -XXX,XX +XXX,XX @@ #include "hw/riscv/riscv_hart.h" #include "hw/sysbus.h" #include "hw/block/flash.h" +#include "hw/intc/riscv_imsic.h" #define VIRT_CPUS_MAX_BITS 9 #define VIRT_CPUS_MAX (1 << VIRT_CPUS_MAX_BITS) @@ -XXX,XX +XXX,XX @@ enum { bool virt_is_acpi_enabled(RISCVVirtState *s); void virt_acpi_setup(RISCVVirtState *vms); +uint32_t imsic_num_bits(uint32_t count); + +/* + * The virt machine physical address space used by some of the devices + * namely ACLINT, PLIC, APLIC, and IMSIC depend on number of Sockets, + * number of CPUs, and number of IMSIC guest files. + * + * Various limits defined by VIRT_SOCKETS_MAX_BITS, VIRT_CPUS_MAX_BITS, + * and VIRT_IRQCHIP_MAX_GUESTS_BITS are tuned for maximum utilization + * of virt machine physical address space. + */ + +#define VIRT_IMSIC_GROUP_MAX_SIZE (1U << IMSIC_MMIO_GROUP_MIN_SHIFT) +#if VIRT_IMSIC_GROUP_MAX_SIZE < \ + IMSIC_GROUP_SIZE(VIRT_CPUS_MAX_BITS, VIRT_IRQCHIP_MAX_GUESTS_BITS) +#error "Can't accomodate single IMSIC group in address space" +#endif + +#define VIRT_IMSIC_MAX_SIZE (VIRT_SOCKETS_MAX * \ + VIRT_IMSIC_GROUP_MAX_SIZE) +#if 0x4000000 < VIRT_IMSIC_MAX_SIZE +#error "Can't accomodate all IMSIC groups in address space" +#endif + #endif 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 "kvm/kvm_riscv.h" #include "hw/intc/riscv_aclint.h" #include "hw/intc/riscv_aplic.h" -#include "hw/intc/riscv_imsic.h" #include "hw/intc/sifive_plic.h" #include "hw/misc/sifive_test.h" #include "hw/platform-bus.h" @@ -XXX,XX +XXX,XX @@ #include "hw/acpi/aml-build.h" #include "qapi/qapi-visit-common.h" -/* - * The virt machine physical address space used by some of the devices - * namely ACLINT, PLIC, APLIC, and IMSIC depend on number of Sockets, - * number of CPUs, and number of IMSIC guest files. - * - * Various limits defined by VIRT_SOCKETS_MAX_BITS, VIRT_CPUS_MAX_BITS, - * and VIRT_IRQCHIP_MAX_GUESTS_BITS are tuned for maximum utilization - * of virt machine physical address space. - */ - -#define VIRT_IMSIC_GROUP_MAX_SIZE (1U << IMSIC_MMIO_GROUP_MIN_SHIFT) -#if VIRT_IMSIC_GROUP_MAX_SIZE < \ - IMSIC_GROUP_SIZE(VIRT_CPUS_MAX_BITS, VIRT_IRQCHIP_MAX_GUESTS_BITS) -#error "Can't accommodate single IMSIC group in address space" -#endif - -#define VIRT_IMSIC_MAX_SIZE (VIRT_SOCKETS_MAX * \ - VIRT_IMSIC_GROUP_MAX_SIZE) -#if 0x4000000 < VIRT_IMSIC_MAX_SIZE -#error "Can't accommodate all IMSIC groups in address space" -#endif - /* KVM AIA only supports APLIC MSI. APLIC Wired is always emulated by QEMU. */ static bool virt_use_kvm_aia(RISCVVirtState *s) { @@ -XXX,XX +XXX,XX @@ static void create_fdt_socket_plic(RISCVVirtState *s, g_free(plic_cells); } -static uint32_t imsic_num_bits(uint32_t count) +uint32_t imsic_num_bits(uint32_t count) { uint32_t ret = 0; -- 2.43.0
From: Sunil V L <sunilvl@ventanamicro.com> Update the RINTC structure in MADT with AIA related fields. Signed-off-by: Sunil V L <sunilvl@ventanamicro.com> Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Message-ID: <20231218150247.466427-6-sunilvl@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/riscv/virt-acpi-build.c | 43 ++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) 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 @@ #include "hw/intc/riscv_aclint.h" #define ACPI_BUILD_TABLE_SIZE 0x20000 +#define ACPI_BUILD_INTC_ID(socket, index) ((socket << 24) | (index)) typedef struct AcpiBuildState { /* Copy of table in RAM (for patching) */ @@ -XXX,XX +XXX,XX @@ static void acpi_align_size(GArray *blob, unsigned align) static void riscv_acpi_madt_add_rintc(uint32_t uid, const CPUArchIdList *arch_ids, - GArray *entry) + GArray *entry, + RISCVVirtState *s) { + uint8_t guest_index_bits = imsic_num_bits(s->aia_guests + 1); uint64_t hart_id = arch_ids->cpus[uid].arch_id; + uint32_t imsic_size, local_cpu_id, socket_id; + uint64_t imsic_socket_addr, imsic_addr; + MachineState *ms = MACHINE(s); + socket_id = arch_ids->cpus[uid].props.node_id; + local_cpu_id = (arch_ids->cpus[uid].arch_id - + riscv_socket_first_hartid(ms, socket_id)) % + riscv_socket_hart_count(ms, socket_id); + imsic_socket_addr = s->memmap[VIRT_IMSIC_S].base + + (socket_id * VIRT_IMSIC_GROUP_MAX_SIZE); + imsic_size = IMSIC_HART_SIZE(guest_index_bits); + imsic_addr = imsic_socket_addr + local_cpu_id * imsic_size; build_append_int_noprefix(entry, 0x18, 1); /* Type */ - build_append_int_noprefix(entry, 20, 1); /* Length */ + build_append_int_noprefix(entry, 36, 1); /* Length */ build_append_int_noprefix(entry, 1, 1); /* Version */ build_append_int_noprefix(entry, 0, 1); /* Reserved */ build_append_int_noprefix(entry, 0x1, 4); /* Flags */ build_append_int_noprefix(entry, hart_id, 8); /* Hart ID */ build_append_int_noprefix(entry, uid, 4); /* ACPI Processor UID */ + /* External Interrupt Controller ID */ + if (s->aia_type == VIRT_AIA_TYPE_APLIC) { + build_append_int_noprefix(entry, + ACPI_BUILD_INTC_ID( + arch_ids->cpus[uid].props.node_id, + local_cpu_id), + 4); + } else { + build_append_int_noprefix(entry, 0, 4); + } + + if (s->aia_type == VIRT_AIA_TYPE_APLIC_IMSIC) { + /* IMSIC Base address */ + build_append_int_noprefix(entry, imsic_addr, 8); + /* IMSIC Size */ + build_append_int_noprefix(entry, imsic_size, 4); + } else { + build_append_int_noprefix(entry, 0, 8); + build_append_int_noprefix(entry, 0, 4); + } } static void acpi_dsdt_add_cpus(Aml *scope, RISCVVirtState *s) @@ -XXX,XX +XXX,XX @@ static void acpi_dsdt_add_cpus(Aml *scope, RISCVVirtState *s) aml_int(arch_ids->cpus[i].arch_id))); /* build _MAT object */ - riscv_acpi_madt_add_rintc(i, arch_ids, madt_buf); + riscv_acpi_madt_add_rintc(i, arch_ids, madt_buf, s); aml_append(dev, aml_name_decl("_MAT", aml_buffer(madt_buf->len, (uint8_t *)madt_buf->data))); @@ -XXX,XX +XXX,XX @@ static void build_dsdt(GArray *table_data, * 5.2.12 Multiple APIC Description Table (MADT) * REF: https://github.com/riscv-non-isa/riscv-acpi/issues/15 * https://drive.google.com/file/d/1R6k4MshhN3WTT-hwqAquu5nX6xSEqK2l/view + * https://drive.google.com/file/d/1oMGPyOD58JaPgMl1pKasT-VKsIKia7zR/view */ static void build_madt(GArray *table_data, BIOSLinker *linker, @@ -XXX,XX +XXX,XX @@ static void build_madt(GArray *table_data, /* RISC-V Local INTC structures per HART */ for (int i = 0; i < arch_ids->len; i++) { - riscv_acpi_madt_add_rintc(i, arch_ids, table_data); + riscv_acpi_madt_add_rintc(i, arch_ids, table_data, s); } acpi_table_end(linker, &table); -- 2.43.0
From: Sunil V L <sunilvl@ventanamicro.com> Add IMSIC structure in MADT when IMSIC is configured. Signed-off-by: Sunil V L <sunilvl@ventanamicro.com> Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Message-ID: <20231218150247.466427-7-sunilvl@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/riscv/virt-acpi-build.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) 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_madt(GArray *table_data, MachineClass *mc = MACHINE_GET_CLASS(s); MachineState *ms = MACHINE(s); const CPUArchIdList *arch_ids = mc->possible_cpu_arch_ids(ms); + uint8_t group_index_bits = imsic_num_bits(riscv_socket_count(ms)); + uint8_t guest_index_bits = imsic_num_bits(s->aia_guests + 1); + uint16_t imsic_max_hart_per_socket = 0; + uint8_t hart_index_bits; + uint8_t socket; + + for (socket = 0; socket < riscv_socket_count(ms); socket++) { + if (imsic_max_hart_per_socket < s->soc[socket].num_harts) { + imsic_max_hart_per_socket = s->soc[socket].num_harts; + } + } + + hart_index_bits = imsic_num_bits(imsic_max_hart_per_socket); AcpiTable table = { .sig = "APIC", .rev = 6, .oem_id = s->oem_id, .oem_table_id = s->oem_table_id }; @@ -XXX,XX +XXX,XX @@ static void build_madt(GArray *table_data, riscv_acpi_madt_add_rintc(i, arch_ids, table_data, s); } + /* IMSIC */ + if (s->aia_type == VIRT_AIA_TYPE_APLIC_IMSIC) { + /* IMSIC */ + build_append_int_noprefix(table_data, 0x19, 1); /* Type */ + build_append_int_noprefix(table_data, 16, 1); /* Length */ + build_append_int_noprefix(table_data, 1, 1); /* Version */ + build_append_int_noprefix(table_data, 0, 1); /* Reserved */ + build_append_int_noprefix(table_data, 0, 4); /* Flags */ + /* Number of supervisor mode Interrupt Identities */ + build_append_int_noprefix(table_data, VIRT_IRQCHIP_NUM_MSIS, 2); + /* Number of guest mode Interrupt Identities */ + build_append_int_noprefix(table_data, VIRT_IRQCHIP_NUM_MSIS, 2); + /* Guest Index Bits */ + build_append_int_noprefix(table_data, guest_index_bits, 1); + /* Hart Index Bits */ + build_append_int_noprefix(table_data, hart_index_bits, 1); + /* Group Index Bits */ + build_append_int_noprefix(table_data, group_index_bits, 1); + /* Group Index Shift */ + build_append_int_noprefix(table_data, IMSIC_MMIO_GROUP_MIN_SHIFT, 1); + } + acpi_table_end(linker, &table); } -- 2.43.0
From: Sunil V L <sunilvl@ventanamicro.com> Add APLIC structures for each socket in the MADT when system is configured with APLIC as the external wired interrupt controller. Signed-off-by: Sunil V L <sunilvl@ventanamicro.com> Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Message-ID: <20231218150247.466427-8-sunilvl@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/riscv/virt-acpi-build.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) 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_madt(GArray *table_data, uint8_t guest_index_bits = imsic_num_bits(s->aia_guests + 1); uint16_t imsic_max_hart_per_socket = 0; uint8_t hart_index_bits; + uint64_t aplic_addr; + uint32_t gsi_base; uint8_t socket; for (socket = 0; socket < riscv_socket_count(ms); socket++) { @@ -XXX,XX +XXX,XX @@ static void build_madt(GArray *table_data, build_append_int_noprefix(table_data, IMSIC_MMIO_GROUP_MIN_SHIFT, 1); } + if (s->aia_type != VIRT_AIA_TYPE_NONE) { + /* APLICs */ + for (socket = 0; socket < riscv_socket_count(ms); socket++) { + aplic_addr = s->memmap[VIRT_APLIC_S].base + + s->memmap[VIRT_APLIC_S].size * socket; + gsi_base = VIRT_IRQCHIP_NUM_SOURCES * socket; + build_append_int_noprefix(table_data, 0x1A, 1); /* Type */ + build_append_int_noprefix(table_data, 36, 1); /* Length */ + build_append_int_noprefix(table_data, 1, 1); /* Version */ + build_append_int_noprefix(table_data, socket, 1); /* APLIC ID */ + build_append_int_noprefix(table_data, 0, 4); /* Flags */ + build_append_int_noprefix(table_data, 0, 8); /* Hardware ID */ + /* Number of IDCs */ + if (s->aia_type == VIRT_AIA_TYPE_APLIC) { + build_append_int_noprefix(table_data, + s->soc[socket].num_harts, + 2); + } else { + build_append_int_noprefix(table_data, 0, 2); + } + /* Total External Interrupt Sources Supported */ + build_append_int_noprefix(table_data, VIRT_IRQCHIP_NUM_SOURCES, 2); + /* Global System Interrupt Base */ + build_append_int_noprefix(table_data, gsi_base, 4); + /* APLIC Address */ + build_append_int_noprefix(table_data, aplic_addr, 8); + /* APLIC size */ + build_append_int_noprefix(table_data, + s->memmap[VIRT_APLIC_S].size, 4); + } + } + acpi_table_end(linker, &table); } -- 2.43.0
From: Sunil V L <sunilvl@ventanamicro.com> When CMO related extensions like Zicboz, Zicbom and Zicbop are enabled, the block size for those extensions need to be communicated via CMO node in RHCT. Add CMO node in RHCT if any of those CMO extensions are detected. Signed-off-by: Sunil V L <sunilvl@ventanamicro.com> Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Message-ID: <20231218150247.466427-9-sunilvl@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/riscv/virt-acpi-build.c | 64 +++++++++++++++++++++++++++++++++----- 1 file changed, 56 insertions(+), 8 deletions(-) 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 acpi_dsdt_add_cpus(Aml *scope, RISCVVirtState *s) * 5.2.36 RISC-V Hart Capabilities Table (RHCT) * REF: https://github.com/riscv-non-isa/riscv-acpi/issues/16 * https://drive.google.com/file/d/1nP3nFiH4jkPMp6COOxP6123DCZKR-tia/view + * https://drive.google.com/file/d/1sKbOa8m1UZw1JkquZYe3F1zQBN1xXsaf/view */ static void build_rhct(GArray *table_data, BIOSLinker *linker, @@ -XXX,XX +XXX,XX @@ static void build_rhct(GArray *table_data, MachineState *ms = MACHINE(s); const CPUArchIdList *arch_ids = mc->possible_cpu_arch_ids(ms); size_t len, aligned_len; - uint32_t isa_offset, num_rhct_nodes; - RISCVCPU *cpu; + uint32_t isa_offset, num_rhct_nodes, cmo_offset = 0; + RISCVCPU *cpu = &s->soc[0].harts[0]; char *isa; AcpiTable table = { .sig = "RHCT", .rev = 1, .oem_id = s->oem_id, @@ -XXX,XX +XXX,XX @@ static void build_rhct(GArray *table_data, /* ISA + N hart info */ num_rhct_nodes = 1 + ms->smp.cpus; + if (cpu->cfg.ext_zicbom || cpu->cfg.ext_zicboz) { + num_rhct_nodes++; + } /* Number of RHCT nodes*/ build_append_int_noprefix(table_data, num_rhct_nodes, 4); @@ -XXX,XX +XXX,XX @@ static void build_rhct(GArray *table_data, isa_offset = table_data->len - table.table_offset; build_append_int_noprefix(table_data, 0, 2); /* Type 0 */ - cpu = &s->soc[0].harts[0]; isa = riscv_isa_string(cpu); len = 8 + strlen(isa) + 1; aligned_len = (len % 2) ? (len + 1) : len; @@ -XXX,XX +XXX,XX @@ static void build_rhct(GArray *table_data, build_append_int_noprefix(table_data, 0x0, 1); /* Optional Padding */ } + /* CMO node */ + if (cpu->cfg.ext_zicbom || cpu->cfg.ext_zicboz) { + cmo_offset = table_data->len - table.table_offset; + build_append_int_noprefix(table_data, 1, 2); /* Type */ + build_append_int_noprefix(table_data, 10, 2); /* Length */ + build_append_int_noprefix(table_data, 0x1, 2); /* Revision */ + build_append_int_noprefix(table_data, 0, 1); /* Reserved */ + + /* CBOM block size */ + if (cpu->cfg.cbom_blocksize) { + build_append_int_noprefix(table_data, + __builtin_ctz(cpu->cfg.cbom_blocksize), + 1); + } else { + build_append_int_noprefix(table_data, 0, 1); + } + + /* CBOP block size */ + build_append_int_noprefix(table_data, 0, 1); + + /* CBOZ block size */ + if (cpu->cfg.cboz_blocksize) { + build_append_int_noprefix(table_data, + __builtin_ctz(cpu->cfg.cboz_blocksize), + 1); + } else { + build_append_int_noprefix(table_data, 0, 1); + } + } + /* Hart Info Node */ for (int i = 0; i < arch_ids->len; i++) { + len = 16; + int num_offsets = 1; build_append_int_noprefix(table_data, 0xFFFF, 2); /* Type */ - build_append_int_noprefix(table_data, 16, 2); /* Length */ - build_append_int_noprefix(table_data, 0x1, 2); /* Revision */ - build_append_int_noprefix(table_data, 1, 2); /* Number of offsets */ - build_append_int_noprefix(table_data, i, 4); /* ACPI Processor UID */ - build_append_int_noprefix(table_data, isa_offset, 4); /* Offsets[0] */ + + /* Length */ + if (cmo_offset) { + len += 4; + num_offsets++; + } + + build_append_int_noprefix(table_data, len, 2); + build_append_int_noprefix(table_data, 0x1, 2); /* Revision */ + /* Number of offsets */ + build_append_int_noprefix(table_data, num_offsets, 2); + build_append_int_noprefix(table_data, i, 4); /* ACPI Processor UID */ + + /* Offsets */ + build_append_int_noprefix(table_data, isa_offset, 4); + if (cmo_offset) { + build_append_int_noprefix(table_data, cmo_offset, 4); + } } acpi_table_end(linker, &table); -- 2.43.0
From: Sunil V L <sunilvl@ventanamicro.com> MMU type information is available via MMU node in RHCT. Add this node in RHCT. Signed-off-by: Sunil V L <sunilvl@ventanamicro.com> Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Message-ID: <20231218150247.466427-10-sunilvl@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/riscv/virt-acpi-build.c | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 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_rhct(GArray *table_data, size_t len, aligned_len; uint32_t isa_offset, num_rhct_nodes, cmo_offset = 0; RISCVCPU *cpu = &s->soc[0].harts[0]; + uint32_t mmu_offset = 0; + uint8_t satp_mode_max; char *isa; AcpiTable table = { .sig = "RHCT", .rev = 1, .oem_id = s->oem_id, @@ -XXX,XX +XXX,XX @@ static void build_rhct(GArray *table_data, num_rhct_nodes++; } + if (cpu->cfg.satp_mode.supported != 0) { + num_rhct_nodes++; + } + /* Number of RHCT nodes*/ build_append_int_noprefix(table_data, num_rhct_nodes, 4); @@ -XXX,XX +XXX,XX @@ static void build_rhct(GArray *table_data, } } + /* MMU node structure */ + if (cpu->cfg.satp_mode.supported != 0) { + satp_mode_max = satp_mode_max_from_map(cpu->cfg.satp_mode.map); + mmu_offset = table_data->len - table.table_offset; + build_append_int_noprefix(table_data, 2, 2); /* Type */ + build_append_int_noprefix(table_data, 8, 2); /* Length */ + build_append_int_noprefix(table_data, 0x1, 2); /* Revision */ + build_append_int_noprefix(table_data, 0, 1); /* Reserved */ + /* MMU Type */ + if (satp_mode_max == VM_1_10_SV57) { + build_append_int_noprefix(table_data, 2, 1); /* Sv57 */ + } else if (satp_mode_max == VM_1_10_SV48) { + build_append_int_noprefix(table_data, 1, 1); /* Sv48 */ + } else if (satp_mode_max == VM_1_10_SV39) { + build_append_int_noprefix(table_data, 0, 1); /* Sv39 */ + } else { + assert(1); + } + } + /* Hart Info Node */ for (int i = 0; i < arch_ids->len; i++) { len = 16; @@ -XXX,XX +XXX,XX @@ static void build_rhct(GArray *table_data, num_offsets++; } + if (mmu_offset) { + len += 4; + num_offsets++; + } + build_append_int_noprefix(table_data, len, 2); build_append_int_noprefix(table_data, 0x1, 2); /* Revision */ /* Number of offsets */ build_append_int_noprefix(table_data, num_offsets, 2); build_append_int_noprefix(table_data, i, 4); /* ACPI Processor UID */ - /* Offsets */ build_append_int_noprefix(table_data, isa_offset, 4); if (cmo_offset) { build_append_int_noprefix(table_data, cmo_offset, 4); } + + if (mmu_offset) { + build_append_int_noprefix(table_data, mmu_offset, 4); + } } acpi_table_end(linker, &table); -- 2.43.0
From: Sunil V L <sunilvl@ventanamicro.com> ACPI DSDT generator needs information like ECAM range, PIO range, 32-bit and 64-bit PCI MMIO range etc related to the PCI host bridge. Instead of making these values machine specific, create properties for the GPEX host bridge with default value 0. During initialization, the firmware can initialize these properties with correct values for the platform. This basically allows DSDT generator code independent of the machine specific memory map accesses. Suggested-by: Igor Mammedov <imammedo@redhat.com> Signed-off-by: Sunil V L <sunilvl@ventanamicro.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Message-ID: <20231218150247.466427-11-sunilvl@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- include/hw/pci-host/gpex.h | 28 ++++++++++++++++++++-------- hw/pci-host/gpex-acpi.c | 13 +++++++++++++ hw/pci-host/gpex.c | 12 ++++++++++++ 3 files changed, 45 insertions(+), 8 deletions(-) diff --git a/include/hw/pci-host/gpex.h b/include/hw/pci-host/gpex.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/pci-host/gpex.h +++ b/include/hw/pci-host/gpex.h @@ -XXX,XX +XXX,XX @@ struct GPEXRootState { /*< public >*/ }; +struct GPEXConfig { + MemMapEntry ecam; + MemMapEntry mmio32; + MemMapEntry mmio64; + MemMapEntry pio; + int irq; + PCIBus *bus; +}; + struct GPEXHost { /*< private >*/ PCIExpressHost parent_obj; @@ -XXX,XX +XXX,XX @@ struct GPEXHost { int irq_num[GPEX_NUM_IRQS]; bool allow_unmapped_accesses; -}; -struct GPEXConfig { - MemMapEntry ecam; - MemMapEntry mmio32; - MemMapEntry mmio64; - MemMapEntry pio; - int irq; - PCIBus *bus; + struct GPEXConfig gpex_cfg; }; int gpex_set_irq_num(GPEXHost *s, int index, int gsi); void acpi_dsdt_add_gpex(Aml *scope, struct GPEXConfig *cfg); +void acpi_dsdt_add_gpex_host(Aml *scope, uint32_t irq); + +#define PCI_HOST_PIO_BASE "x-pio-base" +#define PCI_HOST_PIO_SIZE "x-pio-size" +#define PCI_HOST_ECAM_BASE "x-ecam-base" +#define PCI_HOST_ECAM_SIZE "x-ecam-size" +#define PCI_HOST_BELOW_4G_MMIO_BASE "x-below-4g-mmio-base" +#define PCI_HOST_BELOW_4G_MMIO_SIZE "x-below-4g-mmio-size" +#define PCI_HOST_ABOVE_4G_MMIO_BASE "x-above-4g-mmio-base" +#define PCI_HOST_ABOVE_4G_MMIO_SIZE "x-above-4g-mmio-size" #endif /* HW_GPEX_H */ diff --git a/hw/pci-host/gpex-acpi.c b/hw/pci-host/gpex-acpi.c index XXXXXXX..XXXXXXX 100644 --- a/hw/pci-host/gpex-acpi.c +++ b/hw/pci-host/gpex-acpi.c @@ -XXX,XX +XXX,XX @@ void acpi_dsdt_add_gpex(Aml *scope, struct GPEXConfig *cfg) crs_range_set_free(&crs_range_set); } + +void acpi_dsdt_add_gpex_host(Aml *scope, uint32_t irq) +{ + bool ambig; + Object *obj = object_resolve_path_type("", TYPE_GPEX_HOST, &ambig); + + if (!obj || ambig) { + return; + } + + GPEX_HOST(obj)->gpex_cfg.irq = irq; + acpi_dsdt_add_gpex(scope, &GPEX_HOST(obj)->gpex_cfg); +} diff --git a/hw/pci-host/gpex.c b/hw/pci-host/gpex.c index XXXXXXX..XXXXXXX 100644 --- a/hw/pci-host/gpex.c +++ b/hw/pci-host/gpex.c @@ -XXX,XX +XXX,XX @@ static Property gpex_host_properties[] = { */ DEFINE_PROP_BOOL("allow-unmapped-accesses", GPEXHost, allow_unmapped_accesses, true), + DEFINE_PROP_UINT64(PCI_HOST_ECAM_BASE, GPEXHost, gpex_cfg.ecam.base, 0), + DEFINE_PROP_SIZE(PCI_HOST_ECAM_SIZE, GPEXHost, gpex_cfg.ecam.size, 0), + DEFINE_PROP_UINT64(PCI_HOST_PIO_BASE, GPEXHost, gpex_cfg.pio.base, 0), + DEFINE_PROP_SIZE(PCI_HOST_PIO_SIZE, GPEXHost, gpex_cfg.pio.size, 0), + DEFINE_PROP_UINT64(PCI_HOST_BELOW_4G_MMIO_BASE, GPEXHost, + gpex_cfg.mmio32.base, 0), + DEFINE_PROP_SIZE(PCI_HOST_BELOW_4G_MMIO_SIZE, GPEXHost, + gpex_cfg.mmio32.size, 0), + DEFINE_PROP_UINT64(PCI_HOST_ABOVE_4G_MMIO_BASE, GPEXHost, + gpex_cfg.mmio64.base, 0), + DEFINE_PROP_SIZE(PCI_HOST_ABOVE_4G_MMIO_SIZE, GPEXHost, + gpex_cfg.mmio64.size, 0), DEFINE_PROP_END_OF_LIST(), }; -- 2.43.0
From: Sunil V L <sunilvl@ventanamicro.com> Update the GPEX host bridge properties related to MMIO ranges with values set for the virt machine. Suggested-by: Igor Mammedov <imammedo@redhat.com> Signed-off-by: Sunil V L <sunilvl@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Message-ID: <20231218150247.466427-12-sunilvl@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- include/hw/riscv/virt.h | 1 + hw/riscv/virt.c | 47 ++++++++++++++++++++++++++++------------- 2 files changed, 33 insertions(+), 15 deletions(-) diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h index XXXXXXX..XXXXXXX 100644 --- a/include/hw/riscv/virt.h +++ b/include/hw/riscv/virt.h @@ -XXX,XX +XXX,XX @@ struct RISCVVirtState { char *oem_table_id; OnOffAuto acpi; const MemMapEntry *memmap; + struct GPEXHost *gpex_host; }; enum { 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(RISCVVirtState *s, const MemMapEntry *memmap) } static inline DeviceState *gpex_pcie_init(MemoryRegion *sys_mem, - hwaddr ecam_base, hwaddr ecam_size, - hwaddr mmio_base, hwaddr mmio_size, - hwaddr high_mmio_base, - hwaddr high_mmio_size, - hwaddr pio_base, - DeviceState *irqchip) + DeviceState *irqchip, + RISCVVirtState *s) { DeviceState *dev; MemoryRegion *ecam_alias, *ecam_reg; MemoryRegion *mmio_alias, *high_mmio_alias, *mmio_reg; + hwaddr ecam_base = s->memmap[VIRT_PCIE_ECAM].base; + hwaddr ecam_size = s->memmap[VIRT_PCIE_ECAM].size; + hwaddr mmio_base = s->memmap[VIRT_PCIE_MMIO].base; + hwaddr mmio_size = s->memmap[VIRT_PCIE_MMIO].size; + hwaddr high_mmio_base = virt_high_pcie_memmap.base; + hwaddr high_mmio_size = virt_high_pcie_memmap.size; + hwaddr pio_base = s->memmap[VIRT_PCIE_PIO].base; + hwaddr pio_size = s->memmap[VIRT_PCIE_PIO].size; qemu_irq irq; int i; dev = qdev_new(TYPE_GPEX_HOST); + /* Set GPEX object properties for the virt machine */ + object_property_set_uint(OBJECT(GPEX_HOST(dev)), PCI_HOST_ECAM_BASE, + ecam_base, NULL); + object_property_set_int(OBJECT(GPEX_HOST(dev)), PCI_HOST_ECAM_SIZE, + ecam_size, NULL); + object_property_set_uint(OBJECT(GPEX_HOST(dev)), + PCI_HOST_BELOW_4G_MMIO_BASE, + mmio_base, NULL); + object_property_set_int(OBJECT(GPEX_HOST(dev)), PCI_HOST_BELOW_4G_MMIO_SIZE, + mmio_size, NULL); + object_property_set_uint(OBJECT(GPEX_HOST(dev)), + PCI_HOST_ABOVE_4G_MMIO_BASE, + high_mmio_base, NULL); + object_property_set_int(OBJECT(GPEX_HOST(dev)), PCI_HOST_ABOVE_4G_MMIO_SIZE, + high_mmio_size, NULL); + object_property_set_uint(OBJECT(GPEX_HOST(dev)), PCI_HOST_PIO_BASE, + pio_base, NULL); + object_property_set_int(OBJECT(GPEX_HOST(dev)), PCI_HOST_PIO_SIZE, + pio_size, NULL); + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); ecam_alias = g_new0(MemoryRegion, 1); @@ -XXX,XX +XXX,XX @@ static inline DeviceState *gpex_pcie_init(MemoryRegion *sys_mem, gpex_set_irq_num(GPEX_HOST(dev), i, PCIE_IRQ + i); } + GPEX_HOST(dev)->gpex_cfg.bus = PCI_HOST_BRIDGE(GPEX_HOST(dev))->bus; return dev; } @@ -XXX,XX +XXX,XX @@ static void virt_machine_init(MachineState *machine) qdev_get_gpio_in(virtio_irqchip, VIRTIO_IRQ + i)); } - gpex_pcie_init(system_memory, - memmap[VIRT_PCIE_ECAM].base, - memmap[VIRT_PCIE_ECAM].size, - memmap[VIRT_PCIE_MMIO].base, - memmap[VIRT_PCIE_MMIO].size, - virt_high_pcie_memmap.base, - virt_high_pcie_memmap.size, - memmap[VIRT_PCIE_PIO].base, - pcie_irqchip); + gpex_pcie_init(system_memory, pcie_irqchip, s); create_platform_bus(s, mmio_irqchip); -- 2.43.0
From: Sunil V L <sunilvl@ventanamicro.com> Add basic IO controllers and devices like PCI, VirtIO and UART in the ACPI namespace. Signed-off-by: Sunil V L <sunilvl@ventanamicro.com> Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Message-ID: <20231218150247.466427-13-sunilvl@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/riscv/virt-acpi-build.c | 79 ++++++++++++++++++++++++++++++++++++-- hw/riscv/Kconfig | 1 + 2 files changed, 76 insertions(+), 4 deletions(-) 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 @@ #include "hw/acpi/acpi-defs.h" #include "hw/acpi/acpi.h" #include "hw/acpi/aml-build.h" +#include "hw/acpi/pci.h" #include "hw/acpi/utils.h" +#include "hw/intc/riscv_aclint.h" #include "hw/nvram/fw_cfg_acpi.h" +#include "hw/pci-host/gpex.h" +#include "hw/riscv/virt.h" +#include "hw/riscv/numa.h" +#include "hw/virtio/virtio-acpi.h" +#include "migration/vmstate.h" #include "qapi/error.h" #include "qemu/error-report.h" #include "sysemu/reset.h" -#include "migration/vmstate.h" -#include "hw/riscv/virt.h" -#include "hw/riscv/numa.h" -#include "hw/intc/riscv_aclint.h" #define ACPI_BUILD_TABLE_SIZE 0x20000 #define ACPI_BUILD_INTC_ID(socket, index) ((socket << 24) | (index)) @@ -XXX,XX +XXX,XX @@ static void acpi_dsdt_add_cpus(Aml *scope, RISCVVirtState *s) } } +static void +acpi_dsdt_add_uart(Aml *scope, const MemMapEntry *uart_memmap, + uint32_t uart_irq) +{ + Aml *dev = aml_device("COM0"); + aml_append(dev, aml_name_decl("_HID", aml_string("PNP0501"))); + aml_append(dev, aml_name_decl("_UID", aml_int(0))); + + Aml *crs = aml_resource_template(); + aml_append(crs, aml_memory32_fixed(uart_memmap->base, + uart_memmap->size, AML_READ_WRITE)); + aml_append(crs, + aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH, + AML_EXCLUSIVE, &uart_irq, 1)); + aml_append(dev, aml_name_decl("_CRS", crs)); + + Aml *pkg = aml_package(2); + aml_append(pkg, aml_string("clock-frequency")); + aml_append(pkg, aml_int(3686400)); + + Aml *UUID = aml_touuid("DAFFD814-6EBA-4D8C-8A91-BC9BBF4AA301"); + + Aml *pkg1 = aml_package(1); + aml_append(pkg1, pkg); + + Aml *package = aml_package(2); + aml_append(package, UUID); + aml_append(package, pkg1); + + aml_append(dev, aml_name_decl("_DSD", package)); + aml_append(scope, dev); +} + /* RHCT Node[N] starts at offset 56 */ #define RHCT_NODE_ARRAY_OFFSET 56 @@ -XXX,XX +XXX,XX @@ static void build_dsdt(GArray *table_data, RISCVVirtState *s) { Aml *scope, *dsdt; + MachineState *ms = MACHINE(s); + uint8_t socket_count; const MemMapEntry *memmap = s->memmap; AcpiTable table = { .sig = "DSDT", .rev = 2, .oem_id = s->oem_id, .oem_table_id = s->oem_table_id }; @@ -XXX,XX +XXX,XX @@ static void build_dsdt(GArray *table_data, fw_cfg_acpi_dsdt_add(scope, &memmap[VIRT_FW_CFG]); + socket_count = riscv_socket_count(ms); + + acpi_dsdt_add_uart(scope, &memmap[VIRT_UART0], UART0_IRQ); + + if (socket_count == 1) { + virtio_acpi_dsdt_add(scope, memmap[VIRT_VIRTIO].base, + memmap[VIRT_VIRTIO].size, + VIRTIO_IRQ, 0, VIRTIO_COUNT); + acpi_dsdt_add_gpex_host(scope, PCIE_IRQ); + } else if (socket_count == 2) { + virtio_acpi_dsdt_add(scope, memmap[VIRT_VIRTIO].base, + memmap[VIRT_VIRTIO].size, + VIRTIO_IRQ + VIRT_IRQCHIP_NUM_SOURCES, 0, + VIRTIO_COUNT); + acpi_dsdt_add_gpex_host(scope, PCIE_IRQ + VIRT_IRQCHIP_NUM_SOURCES); + } else { + virtio_acpi_dsdt_add(scope, memmap[VIRT_VIRTIO].base, + memmap[VIRT_VIRTIO].size, + VIRTIO_IRQ + VIRT_IRQCHIP_NUM_SOURCES, 0, + VIRTIO_COUNT); + acpi_dsdt_add_gpex_host(scope, PCIE_IRQ + VIRT_IRQCHIP_NUM_SOURCES * 2); + } + aml_append(dsdt, scope); /* copy AML table into ACPI tables blob and patch header there */ @@ -XXX,XX +XXX,XX @@ static void virt_acpi_build(RISCVVirtState *s, AcpiBuildTables *tables) acpi_add_table(table_offsets, tables_blob); build_rhct(tables_blob, tables->linker, s); + acpi_add_table(table_offsets, tables_blob); + { + AcpiMcfgInfo mcfg = { + .base = s->memmap[VIRT_PCIE_MMIO].base, + .size = s->memmap[VIRT_PCIE_MMIO].size, + }; + build_mcfg(tables_blob, tables->linker, &mcfg, s->oem_id, + s->oem_table_id); + } + /* XSDT is pointed to by RSDP */ xsdt = tables_blob->len; build_xsdt(tables_blob, tables->linker, table_offsets, s->oem_id, diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index XXXXXXX..XXXXXXX 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -XXX,XX +XXX,XX @@ config RISCV_VIRT select FW_CFG_DMA select PLATFORM_BUS select ACPI + select ACPI_PCI config SHAKTI_C bool -- 2.43.0
From: Sunil V L <sunilvl@ventanamicro.com> Add PLIC structures for each socket in the MADT when system is configured with PLIC as the external interrupt controller. Signed-off-by: Haibo Xu <haibo1.xu@intel.com> Signed-off-by: Sunil V L <sunilvl@ventanamicro.com> Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Message-ID: <20231218150247.466427-14-sunilvl@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/riscv/virt-acpi-build.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) 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 riscv_acpi_madt_add_rintc(uint32_t uid, arch_ids->cpus[uid].props.node_id, local_cpu_id), 4); + } else if (s->aia_type == VIRT_AIA_TYPE_NONE) { + build_append_int_noprefix(entry, + ACPI_BUILD_INTC_ID( + arch_ids->cpus[uid].props.node_id, + 2 * local_cpu_id + 1), + 4); } else { build_append_int_noprefix(entry, 0, 4); } @@ -XXX,XX +XXX,XX @@ static void build_madt(GArray *table_data, build_append_int_noprefix(table_data, s->memmap[VIRT_APLIC_S].size, 4); } + } else { + /* PLICs */ + for (socket = 0; socket < riscv_socket_count(ms); socket++) { + aplic_addr = s->memmap[VIRT_PLIC].base + + s->memmap[VIRT_PLIC].size * socket; + gsi_base = VIRT_IRQCHIP_NUM_SOURCES * socket; + build_append_int_noprefix(table_data, 0x1B, 1); /* Type */ + build_append_int_noprefix(table_data, 36, 1); /* Length */ + build_append_int_noprefix(table_data, 1, 1); /* Version */ + build_append_int_noprefix(table_data, socket, 1); /* PLIC ID */ + build_append_int_noprefix(table_data, 0, 8); /* Hardware ID */ + /* Total External Interrupt Sources Supported */ + build_append_int_noprefix(table_data, + VIRT_IRQCHIP_NUM_SOURCES - 1, 2); + build_append_int_noprefix(table_data, 0, 2); /* Max Priority */ + build_append_int_noprefix(table_data, 0, 4); /* Flags */ + /* PLIC Size */ + build_append_int_noprefix(table_data, s->memmap[VIRT_PLIC].size, 4); + /* PLIC Address */ + build_append_int_noprefix(table_data, aplic_addr, 8); + /* Global System Interrupt Vector Base */ + build_append_int_noprefix(table_data, gsi_base, 4); + } } acpi_table_end(linker, &table); -- 2.43.0
From: Yong-Xuan Wang <yongxuan.wang@sifive.com> The interrupts-extended property of PLIC only has 2 * hart number fields when KVM enabled, copy 4 * hart number fields to fdt will expose some uninitialized value. In this patch, I also refactor the code about the setting of interrupts-extended property of PLIC for improved readability. Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com> Reviewed-by: Jim Shu <jim.shu@sifive.com> Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Message-ID: <20231218090543.22353-1-yongxuan.wang@sifive.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- hw/riscv/virt.c | 47 +++++++++++++++++++++++++++-------------------- 1 file changed, 27 insertions(+), 20 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_socket_plic(RISCVVirtState *s, "sifive,plic-1.0.0", "riscv,plic0" }; - if (kvm_enabled()) { - plic_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2); - } else { - plic_cells = g_new0(uint32_t, s->soc[socket].num_harts * 4); - } - - for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) { - if (kvm_enabled()) { - plic_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]); - plic_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_S_EXT); - } else { - plic_cells[cpu * 4 + 0] = cpu_to_be32(intc_phandles[cpu]); - plic_cells[cpu * 4 + 1] = cpu_to_be32(IRQ_M_EXT); - plic_cells[cpu * 4 + 2] = cpu_to_be32(intc_phandles[cpu]); - plic_cells[cpu * 4 + 3] = cpu_to_be32(IRQ_S_EXT); - } - } - plic_phandles[socket] = (*phandle)++; plic_addr = memmap[VIRT_PLIC].base + (memmap[VIRT_PLIC].size * socket); plic_name = g_strdup_printf("/soc/plic@%lx", plic_addr); @@ -XXX,XX +XXX,XX @@ static void create_fdt_socket_plic(RISCVVirtState *s, (char **)&plic_compat, ARRAY_SIZE(plic_compat)); qemu_fdt_setprop(ms->fdt, plic_name, "interrupt-controller", NULL, 0); - qemu_fdt_setprop(ms->fdt, plic_name, "interrupts-extended", - plic_cells, s->soc[socket].num_harts * sizeof(uint32_t) * 4); + + if (kvm_enabled()) { + plic_cells = g_new0(uint32_t, s->soc[socket].num_harts * 2); + + for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) { + plic_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]); + plic_cells[cpu * 2 + 1] = cpu_to_be32(IRQ_S_EXT); + } + + qemu_fdt_setprop(ms->fdt, plic_name, "interrupts-extended", + plic_cells, + s->soc[socket].num_harts * sizeof(uint32_t) * 2); + } else { + plic_cells = g_new0(uint32_t, s->soc[socket].num_harts * 4); + + for (cpu = 0; cpu < s->soc[socket].num_harts; cpu++) { + plic_cells[cpu * 4 + 0] = cpu_to_be32(intc_phandles[cpu]); + plic_cells[cpu * 4 + 1] = cpu_to_be32(IRQ_M_EXT); + plic_cells[cpu * 4 + 2] = cpu_to_be32(intc_phandles[cpu]); + plic_cells[cpu * 4 + 3] = cpu_to_be32(IRQ_S_EXT); + } + + qemu_fdt_setprop(ms->fdt, plic_name, "interrupts-extended", + plic_cells, + s->soc[socket].num_harts * sizeof(uint32_t) * 4); + } + qemu_fdt_setprop_cells(ms->fdt, plic_name, "reg", 0x0, plic_addr, 0x0, memmap[VIRT_PLIC].size); qemu_fdt_setprop_cell(ms->fdt, plic_name, "riscv,ndev", -- 2.43.0
From: Weiwei Li <liweiwei@iscas.ac.cn> Add support for amocas.w/d/q instructions which are part of the ratified Zacas extension: https://github.com/riscv/riscv-zacas Signed-off-by: Weiwei Li <liweiwei@iscas.ac.cn> Signed-off-by: Junqiang Wang <wangjunqiang@iscas.ac.cn> Signed-off-by: Rob Bradford <rbradford@rivosinc.com> Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Message-ID: <20231207153842.32401-2-rbradford@rivosinc.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu_cfg.h | 1 + target/riscv/insn32.decode | 6 + target/riscv/cpu.c | 2 + target/riscv/tcg/tcg-cpu.c | 5 + target/riscv/translate.c | 1 + target/riscv/insn_trans/trans_rvzacas.c.inc | 150 ++++++++++++++++++++ 6 files changed, 165 insertions(+) create mode 100644 target/riscv/insn_trans/trans_rvzacas.c.inc diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu_cfg.h +++ b/target/riscv/cpu_cfg.h @@ -XXX,XX +XXX,XX @@ struct RISCVCPUConfig { bool ext_svnapot; bool ext_svpbmt; bool ext_zdinx; + bool ext_zacas; bool ext_zawrs; bool ext_zfa; bool ext_zfbfmin; diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/insn32.decode +++ b/target/riscv/insn32.decode @@ -XXX,XX +XXX,XX @@ vgmul_vv 101000 1 ..... 10001 010 ..... 1110111 @r2_vm_1 vsm4k_vi 100001 1 ..... ..... 010 ..... 1110111 @r_vm_1 vsm4r_vv 101000 1 ..... 10000 010 ..... 1110111 @r2_vm_1 vsm4r_vs 101001 1 ..... 10000 010 ..... 1110111 @r2_vm_1 + +# *** RV32 Zacas Standard Extension *** +amocas_w 00101 . . ..... ..... 010 ..... 0101111 @atom_st +amocas_d 00101 . . ..... ..... 011 ..... 0101111 @atom_st +# *** RV64 Zacas Standard Extension *** +amocas_q 00101 . . ..... ..... 100 ..... 0101111 @atom_st 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(zihintpause, PRIV_VERSION_1_10_0, ext_zihintpause), ISA_EXT_DATA_ENTRY(zihpm, PRIV_VERSION_1_12_0, ext_zihpm), ISA_EXT_DATA_ENTRY(zmmul, PRIV_VERSION_1_12_0, ext_zmmul), + ISA_EXT_DATA_ENTRY(zacas, PRIV_VERSION_1_12_0, ext_zacas), ISA_EXT_DATA_ENTRY(zawrs, PRIV_VERSION_1_12_0, ext_zawrs), ISA_EXT_DATA_ENTRY(zfa, PRIV_VERSION_1_12_0, ext_zfa), ISA_EXT_DATA_ENTRY(zfbfmin, PRIV_VERSION_1_12_0, ext_zfbfmin), @@ -XXX,XX +XXX,XX @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = { 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("zacas", ext_zacas, false), MULTI_EXT_CFG_BOOL("zawrs", ext_zawrs, true), MULTI_EXT_CFG_BOOL("zfa", ext_zfa, true), MULTI_EXT_CFG_BOOL("zfh", ext_zfh, false), 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 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp) return; } + if ((cpu->cfg.ext_zacas) && !riscv_has_ext(env, RVA)) { + error_setg(errp, "Zacas extension requires A extension"); + return; + } + if ((cpu->cfg.ext_zawrs) && !riscv_has_ext(env, RVA)) { error_setg(errp, "Zawrs extension requires A extension"); return; diff --git a/target/riscv/translate.c b/target/riscv/translate.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -XXX,XX +XXX,XX @@ static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc) #include "insn_trans/trans_rvv.c.inc" #include "insn_trans/trans_rvb.c.inc" #include "insn_trans/trans_rvzicond.c.inc" +#include "insn_trans/trans_rvzacas.c.inc" #include "insn_trans/trans_rvzawrs.c.inc" #include "insn_trans/trans_rvzicbo.c.inc" #include "insn_trans/trans_rvzfa.c.inc" diff --git a/target/riscv/insn_trans/trans_rvzacas.c.inc b/target/riscv/insn_trans/trans_rvzacas.c.inc new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/target/riscv/insn_trans/trans_rvzacas.c.inc @@ -XXX,XX +XXX,XX @@ +/* + * RISC-V translation routines for the RV64 Zacas Standard Extension. + * + * Copyright (c) 2020-2023 PLCT Lab + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2 or later, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#define REQUIRE_ZACAS(ctx) do { \ + if (!ctx->cfg_ptr->ext_zacas) { \ + return false; \ + } \ +} while (0) + +static bool gen_cmpxchg(DisasContext *ctx, arg_atomic *a, MemOp mop) +{ + TCGv dest = get_gpr(ctx, a->rd, EXT_NONE); + TCGv src1 = get_address(ctx, a->rs1, 0); + TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE); + + decode_save_opc(ctx); + tcg_gen_atomic_cmpxchg_tl(dest, src1, dest, src2, ctx->mem_idx, mop); + + gen_set_gpr(ctx, a->rd, dest); + return true; +} + +static bool trans_amocas_w(DisasContext *ctx, arg_amocas_w *a) +{ + REQUIRE_ZACAS(ctx); + return gen_cmpxchg(ctx, a, MO_ALIGN | MO_TESL); +} + +static TCGv_i64 get_gpr_pair(DisasContext *ctx, int reg_num) +{ + TCGv_i64 t; + + assert(get_ol(ctx) == MXL_RV32); + + if (reg_num == 0) { + return tcg_constant_i64(0); + } + + t = tcg_temp_new_i64(); + tcg_gen_concat_tl_i64(t, cpu_gpr[reg_num], cpu_gpr[reg_num + 1]); + return t; +} + +static void gen_set_gpr_pair(DisasContext *ctx, int reg_num, TCGv_i64 t) +{ + assert(get_ol(ctx) == MXL_RV32); + + if (reg_num != 0) { +#ifdef TARGET_RISCV32 + tcg_gen_extr_i64_i32(cpu_gpr[reg_num], cpu_gpr[reg_num + 1], t); +#else + tcg_gen_ext32s_i64(cpu_gpr[reg_num], t); + tcg_gen_sari_i64(cpu_gpr[reg_num + 1], t, 32); +#endif + + if (get_xl_max(ctx) == MXL_RV128) { + tcg_gen_sari_tl(cpu_gprh[reg_num], cpu_gpr[reg_num], 63); + tcg_gen_sari_tl(cpu_gprh[reg_num + 1], cpu_gpr[reg_num + 1], 63); + } + } +} + +static bool gen_cmpxchg64(DisasContext *ctx, arg_atomic *a, MemOp mop) +{ + /* + * Encodings with odd numbered registers specified in rs2 and rd are + * reserved. + */ + if ((a->rs2 | a->rd) & 1) { + return false; + } + + TCGv_i64 dest = get_gpr_pair(ctx, a->rd); + TCGv src1 = get_address(ctx, a->rs1, 0); + TCGv_i64 src2 = get_gpr_pair(ctx, a->rs2); + + decode_save_opc(ctx); + tcg_gen_atomic_cmpxchg_i64(dest, src1, dest, src2, ctx->mem_idx, mop); + + gen_set_gpr_pair(ctx, a->rd, dest); + return true; +} + +static bool trans_amocas_d(DisasContext *ctx, arg_amocas_d *a) +{ + REQUIRE_ZACAS(ctx); + switch (get_ol(ctx)) { + case MXL_RV32: + return gen_cmpxchg64(ctx, a, MO_ALIGN | MO_TEUQ); + case MXL_RV64: + case MXL_RV128: + return gen_cmpxchg(ctx, a, MO_ALIGN | MO_TEUQ); + default: + g_assert_not_reached(); + } +} + +static bool trans_amocas_q(DisasContext *ctx, arg_amocas_q *a) +{ + REQUIRE_ZACAS(ctx); + REQUIRE_64BIT(ctx); + + /* + * Encodings with odd numbered registers specified in rs2 and rd are + * reserved. + */ + if ((a->rs2 | a->rd) & 1) { + return false; + } + +#ifdef TARGET_RISCV64 + TCGv_i128 dest = tcg_temp_new_i128(); + TCGv src1 = get_address(ctx, a->rs1, 0); + TCGv_i128 src2 = tcg_temp_new_i128(); + TCGv_i64 src2l = get_gpr(ctx, a->rs2, EXT_NONE); + TCGv_i64 src2h = get_gpr(ctx, a->rs2 == 0 ? 0 : a->rs2 + 1, EXT_NONE); + TCGv_i64 destl = get_gpr(ctx, a->rd, EXT_NONE); + TCGv_i64 desth = get_gpr(ctx, a->rd == 0 ? 0 : a->rd + 1, EXT_NONE); + + tcg_gen_concat_i64_i128(src2, src2l, src2h); + tcg_gen_concat_i64_i128(dest, destl, desth); + decode_save_opc(ctx); + tcg_gen_atomic_cmpxchg_i128(dest, src1, dest, src2, ctx->mem_idx, + (MO_ALIGN | MO_TEUO)); + + tcg_gen_extr_i128_i64(destl, desth, dest); + + if (a->rd != 0) { + gen_set_gpr(ctx, a->rd, destl); + gen_set_gpr(ctx, a->rd + 1, desth); + } +#endif + + return true; +} -- 2.43.0
From: Rob Bradford <rbradford@rivosinc.com> Signed-off-by: Rob Bradford <rbradford@rivosinc.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Message-ID: <20231207153842.32401-3-rbradford@rivosinc.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- disas/riscv.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/disas/riscv.c b/disas/riscv.c index XXXXXXX..XXXXXXX 100644 --- a/disas/riscv.c +++ b/disas/riscv.c @@ -XXX,XX +XXX,XX @@ typedef enum { rv_op_vwsll_vv = 872, rv_op_vwsll_vx = 873, rv_op_vwsll_vi = 874, + rv_op_amocas_w = 875, + rv_op_amocas_d = 876, + rv_op_amocas_q = 877, } rv_op; /* register names */ @@ -XXX,XX +XXX,XX @@ const rv_opcode_data rvi_opcode_data[] = { { "vwsll.vv", rv_codec_v_r, rv_fmt_vd_vs2_vs1_vm, NULL, 0, 0, 0 }, { "vwsll.vx", rv_codec_v_r, rv_fmt_vd_vs2_rs1_vm, NULL, 0, 0, 0 }, { "vwsll.vi", rv_codec_v_i, rv_fmt_vd_vs2_uimm_vm, NULL, 0, 0, 0 }, + { "amocas.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, + { "amocas.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, + { "amocas.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, }; /* CSR names */ @@ -XXX,XX +XXX,XX @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) case 34: op = rv_op_amoxor_w; break; case 35: op = rv_op_amoxor_d; break; case 36: op = rv_op_amoxor_q; break; + case 42: op = rv_op_amocas_w; break; + case 43: op = rv_op_amocas_d; break; + case 44: op = rv_op_amocas_q; break; case 66: op = rv_op_amoor_w; break; case 67: op = rv_op_amoor_d; break; case 68: op = rv_op_amoor_q; break; -- 2.43.0
From: Heinrich Schuchardt <heinrich.schuchardt@canonical.com> Since QEMU v8.0.0 the RISC-V virt machine has a switch to disable ACPI table generation. Add it to the documentation. Fixes: 168b8c29cedb ("hw/riscv/virt: Add a switch to disable ACPI") Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com> Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Sunil V L <sunilvl@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20231220193436.25909-1-heinrich.schuchardt@canonical.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- docs/system/riscv/virt.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/system/riscv/virt.rst b/docs/system/riscv/virt.rst index XXXXXXX..XXXXXXX 100644 --- a/docs/system/riscv/virt.rst +++ b/docs/system/riscv/virt.rst @@ -XXX,XX +XXX,XX @@ The following machine-specific options are supported: SiFive CLINT. When not specified, this option is assumed to be "off". This option is restricted to the TCG accelerator. +- acpi=[on|off|auto] + + When this option is "on" (which is the default), ACPI tables are generated and + exposed as firmware tables etc/acpi/rsdp and etc/acpi/tables. + - aia=[none|aplic|aplic-imsic] This option allows selecting interrupt controller defined by the AIA -- 2.43.0
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> We want to add a new CPU type for bare CPUs that will inherit specific traits of the 2 existing types: - it will allow for extensions to be enabled/disabled, like generic CPUs; - it will NOT inherit defaults, like vendor CPUs. We can make this conditions met by adding an explicit type for the existing vendor CPUs and change the existing logic to not imply that "not generic" means vendor CPUs. Let's add the "vendor" CPU type first. Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20231218125334.37184-2-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu-qom.h | 1 + target/riscv/cpu.c | 30 +++++++++++++++++++++--------- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu-qom.h +++ b/target/riscv/cpu-qom.h @@ -XXX,XX +XXX,XX @@ #define TYPE_RISCV_CPU "riscv-cpu" #define TYPE_RISCV_DYNAMIC_CPU "riscv-dynamic-cpu" +#define TYPE_RISCV_VENDOR_CPU "riscv-vendor-cpu" #define RISCV_CPU_TYPE_SUFFIX "-" TYPE_RISCV_CPU #define RISCV_CPU_TYPE_NAME(name) (name RISCV_CPU_TYPE_SUFFIX) 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_isa_string(RISCVCPU *cpu) .instance_init = initfn \ } +#define DEFINE_VENDOR_CPU(type_name, initfn) \ + { \ + .name = type_name, \ + .parent = TYPE_RISCV_VENDOR_CPU, \ + .instance_init = initfn \ + } + static const TypeInfo riscv_cpu_type_infos[] = { { .name = TYPE_RISCV_CPU, @@ -XXX,XX +XXX,XX @@ static const TypeInfo riscv_cpu_type_infos[] = { .parent = TYPE_RISCV_CPU, .abstract = true, }, + { + .name = TYPE_RISCV_VENDOR_CPU, + .parent = TYPE_RISCV_CPU, + .abstract = true, + }, DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY, riscv_any_cpu_init), DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX, riscv_max_cpu_init), #if defined(TARGET_RISCV32) DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE32, rv32_base_cpu_init), - DEFINE_CPU(TYPE_RISCV_CPU_IBEX, rv32_ibex_cpu_init), - DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E31, rv32_sifive_e_cpu_init), - DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E34, rv32_imafcu_nommu_cpu_init), - DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U34, rv32_sifive_u_cpu_init), + DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_IBEX, rv32_ibex_cpu_init), + DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_E31, rv32_sifive_e_cpu_init), + DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_E34, rv32_imafcu_nommu_cpu_init), + DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_U34, rv32_sifive_u_cpu_init), #elif defined(TARGET_RISCV64) DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE64, rv64_base_cpu_init), - DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E51, rv64_sifive_e_cpu_init), - DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U54, rv64_sifive_u_cpu_init), - DEFINE_CPU(TYPE_RISCV_CPU_SHAKTI_C, rv64_sifive_u_cpu_init), - DEFINE_CPU(TYPE_RISCV_CPU_THEAD_C906, rv64_thead_c906_cpu_init), - DEFINE_CPU(TYPE_RISCV_CPU_VEYRON_V1, rv64_veyron_v1_cpu_init), + DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_E51, rv64_sifive_e_cpu_init), + DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_U54, rv64_sifive_u_cpu_init), + DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SHAKTI_C, rv64_sifive_u_cpu_init), + DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_THEAD_C906, rv64_thead_c906_cpu_init), + DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_VEYRON_V1, rv64_veyron_v1_cpu_init), DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE128, rv128_base_cpu_init), #endif }; -- 2.43.0
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Our current logic in get/setters of MISA and multi-letter extensions works because we have only 2 CPU types, generic and vendor, and by using "!generic" we're implying that we're talking about vendor CPUs. When adding a third CPU type this logic will break so let's handle it beforehand. In set_misa_ext_cfg() and set_multi_ext_cfg(), check for "vendor" cpu instead of "not generic". The "generic CPU" checks remaining are from riscv_cpu_add_misa_properties() and cpu_add_multi_ext_prop() before applying default values for the extensions. This leaves us with: - vendor CPUs will not allow extension enablement, all other CPUs will; - generic CPUs will inherit default values for extensions, all others won't. And now we can add a new, third CPU type, that will allow extensions to be enabled and will not inherit defaults, without changing the existing logic. Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20231218125334.37184-3-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/tcg/tcg-cpu.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 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 bool riscv_cpu_is_generic(Object *cpu_obj) return object_dynamic_cast(cpu_obj, TYPE_RISCV_DYNAMIC_CPU) != NULL; } +static bool riscv_cpu_is_vendor(Object *cpu_obj) +{ + return object_dynamic_cast(cpu_obj, TYPE_RISCV_VENDOR_CPU) != NULL; +} + /* * We'll get here via the following path: * @@ -XXX,XX +XXX,XX @@ static void cpu_set_misa_ext_cfg(Object *obj, Visitor *v, const char *name, target_ulong misa_bit = misa_ext_cfg->misa_bit; RISCVCPU *cpu = RISCV_CPU(obj); CPURISCVState *env = &cpu->env; - bool generic_cpu = riscv_cpu_is_generic(obj); + bool vendor_cpu = riscv_cpu_is_vendor(obj); bool prev_val, value; if (!visit_type_bool(v, name, &value, errp)) { @@ -XXX,XX +XXX,XX @@ static void cpu_set_misa_ext_cfg(Object *obj, Visitor *v, const char *name, } if (value) { - if (!generic_cpu) { + if (vendor_cpu) { g_autofree char *cpuname = riscv_cpu_get_name(cpu); error_setg(errp, "'%s' CPU does not allow enabling extensions", cpuname); @@ -XXX,XX +XXX,XX @@ static void cpu_set_multi_ext_cfg(Object *obj, Visitor *v, const char *name, { const RISCVCPUMultiExtConfig *multi_ext_cfg = opaque; RISCVCPU *cpu = RISCV_CPU(obj); - bool generic_cpu = riscv_cpu_is_generic(obj); + bool vendor_cpu = riscv_cpu_is_vendor(obj); bool prev_val, value; if (!visit_type_bool(v, name, &value, errp)) { @@ -XXX,XX +XXX,XX @@ static void cpu_set_multi_ext_cfg(Object *obj, Visitor *v, const char *name, return; } - if (value && !generic_cpu) { + if (value && vendor_cpu) { g_autofree char *cpuname = riscv_cpu_get_name(cpu); error_setg(errp, "'%s' CPU does not allow enabling extensions", cpuname); -- 2.43.0
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> We'll add a new bare CPU type that won't have any default priv_ver. This means that the CPU will default to priv_ver = 0, i.e. 1.10.0. At the same we'll allow these CPUs to enable extensions at will, but then, if the extension has a priv_ver newer than 1.10, we'll end up disabling it. Users will then need to manually set priv_ver to something other than 1.10 to enable the extensions they want, which is not ideal. Change the setter() of extensions to allow user enabled extensions to bump the priv_ver of the CPU. This will make it convenient for users to enable extensions for CPUs that doesn't set a default priv_ver. This change does not affect any existing CPU: vendor CPUs does not allow extensions to be enabled, and generic CPUs are already set to priv_ver LATEST. Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20231218125334.37184-4-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/tcg/tcg-cpu.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 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 int cpu_cfg_ext_get_min_version(uint32_t ext_offset) g_assert_not_reached(); } +static void cpu_bump_multi_ext_priv_ver(CPURISCVState *env, + uint32_t ext_offset) +{ + int ext_priv_ver; + + if (env->priv_ver == PRIV_VERSION_LATEST) { + return; + } + + ext_priv_ver = cpu_cfg_ext_get_min_version(ext_offset); + + if (env->priv_ver < ext_priv_ver) { + /* + * Note: the 'priv_spec' command line option, if present, + * will take precedence over this priv_ver bump. + */ + env->priv_ver = ext_priv_ver; + } +} + static void cpu_cfg_ext_auto_update(RISCVCPU *cpu, uint32_t ext_offset, bool value) { @@ -XXX,XX +XXX,XX @@ static void cpu_set_misa_ext_cfg(Object *obj, Visitor *v, const char *name, return; } + if (misa_bit == RVH && env->priv_ver < PRIV_VERSION_1_12_0) { + /* + * Note: the 'priv_spec' command line option, if present, + * will take precedence over this priv_ver bump. + */ + env->priv_ver = PRIV_VERSION_1_12_0; + } + env->misa_ext |= misa_bit; env->misa_ext_mask |= misa_bit; } else { @@ -XXX,XX +XXX,XX @@ static void cpu_set_multi_ext_cfg(Object *obj, Visitor *v, const char *name, return; } + if (value) { + cpu_bump_multi_ext_priv_ver(&cpu->env, multi_ext_cfg->offset); + } + isa_ext_update_enabled(cpu, multi_ext_cfg->offset, value); } -- 2.43.0
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> We don't have any form of a 'bare bones' CPU. rv64, our default CPUs, comes with a lot of defaults. This is fine for most regular uses but it's not suitable when more control of what is actually loaded in the CPU is required. A bare-bones CPU would be annoying to deal with if not by profile support, a way to load a multitude of extensions with a single flag. Profile support is going to be implemented shortly, so let's add a CPU for it. The new 'rv64i' CPU will have only RVI loaded. It is inspired in the profile specification that dictates, for RVA22U64 [1]: "RVA22U64 Mandatory Base RV64I is the mandatory base ISA for RVA22U64" And so it seems that RV64I is the mandatory base ISA for all profiles listed in [1], making it an ideal CPU to use with profile support. rv64i is a CPU of type TYPE_RISCV_BARE_CPU. It has a mix of features from pre-existent CPUs: - it allows extensions to be enabled, like generic CPUs; - it will not inherit extension defaults, like vendor CPUs. This is the minimum extension set to boot OpenSBI and buildroot using rv64i: ./build/qemu-system-riscv64 -nographic -M virt \ -cpu rv64i,sv39=true,g=true,c=true,s=true,u=true Our minimal riscv,isa in this case will be: # cat /proc/device-tree/cpus/cpu@0/riscv,isa rv64imafdc_zicntr_zicsr_zifencei_zihpm_zca_zcd# [1] https://github.com/riscv/riscv-profiles/blob/main/profiles.adoc Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20231218125334.37184-5-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu-qom.h | 2 ++ target/riscv/cpu.c | 46 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu-qom.h +++ b/target/riscv/cpu-qom.h @@ -XXX,XX +XXX,XX @@ #define TYPE_RISCV_CPU "riscv-cpu" #define TYPE_RISCV_DYNAMIC_CPU "riscv-dynamic-cpu" #define TYPE_RISCV_VENDOR_CPU "riscv-vendor-cpu" +#define TYPE_RISCV_BARE_CPU "riscv-bare-cpu" #define RISCV_CPU_TYPE_SUFFIX "-" TYPE_RISCV_CPU #define RISCV_CPU_TYPE_NAME(name) (name RISCV_CPU_TYPE_SUFFIX) @@ -XXX,XX +XXX,XX @@ #define TYPE_RISCV_CPU_BASE32 RISCV_CPU_TYPE_NAME("rv32") #define TYPE_RISCV_CPU_BASE64 RISCV_CPU_TYPE_NAME("rv64") #define TYPE_RISCV_CPU_BASE128 RISCV_CPU_TYPE_NAME("x-rv128") +#define TYPE_RISCV_CPU_RV64I RISCV_CPU_TYPE_NAME("rv64i") #define TYPE_RISCV_CPU_IBEX RISCV_CPU_TYPE_NAME("lowrisc-ibex") #define TYPE_RISCV_CPU_SHAKTI_C RISCV_CPU_TYPE_NAME("shakti-c") #define TYPE_RISCV_CPU_SIFIVE_E31 RISCV_CPU_TYPE_NAME("sifive-e31") 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_max_supported(RISCVCPU *cpu, /* Set the satp mode to the max supported */ static void set_satp_mode_default_map(RISCVCPU *cpu) { + /* + * Bare CPUs do not default to the max available. + * Users must set a valid satp_mode in the command + * line. + */ + if (object_dynamic_cast(OBJECT(cpu), TYPE_RISCV_BARE_CPU) != NULL) { + warn_report("No satp mode set. Defaulting to 'bare'"); + cpu->cfg.satp_mode.map = (1 << VM_1_10_MBARE); + return; + } + cpu->cfg.satp_mode.map = cpu->cfg.satp_mode.supported; } #endif @@ -XXX,XX +XXX,XX @@ static void rv128_base_cpu_init(Object *obj) set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV57); #endif } + +static void rv64i_bare_cpu_init(Object *obj) +{ + CPURISCVState *env = &RISCV_CPU(obj)->env; + riscv_cpu_set_misa(env, MXL_RV64, RVI); + + /* Remove the defaults from the parent class */ + RISCV_CPU(obj)->cfg.ext_zicntr = false; + RISCV_CPU(obj)->cfg.ext_zihpm = false; + + /* Set to QEMU's first supported priv version */ + env->priv_ver = PRIV_VERSION_1_10_0; + + /* + * Support all available satp_mode settings. The default + * value will be set to MBARE if the user doesn't set + * satp_mode manually (see set_satp_mode_default()). + */ +#ifndef CONFIG_USER_ONLY + set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV64); +#endif +} #else static void rv32_base_cpu_init(Object *obj) { @@ -XXX,XX +XXX,XX @@ char *riscv_isa_string(RISCVCPU *cpu) .instance_init = initfn \ } +#define DEFINE_BARE_CPU(type_name, initfn) \ + { \ + .name = type_name, \ + .parent = TYPE_RISCV_BARE_CPU, \ + .instance_init = initfn \ + } + static const TypeInfo riscv_cpu_type_infos[] = { { .name = TYPE_RISCV_CPU, @@ -XXX,XX +XXX,XX @@ static const TypeInfo riscv_cpu_type_infos[] = { .parent = TYPE_RISCV_CPU, .abstract = true, }, + { + .name = TYPE_RISCV_BARE_CPU, + .parent = TYPE_RISCV_CPU, + .abstract = true, + }, DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY, riscv_any_cpu_init), DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX, riscv_max_cpu_init), #if defined(TARGET_RISCV32) @@ -XXX,XX +XXX,XX @@ static const TypeInfo riscv_cpu_type_infos[] = { DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_THEAD_C906, rv64_thead_c906_cpu_init), DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_VEYRON_V1, rv64_veyron_v1_cpu_init), DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE128, rv128_base_cpu_init), + DEFINE_BARE_CPU(TYPE_RISCV_CPU_RV64I, rv64i_bare_cpu_init), #endif }; -- 2.43.0
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> QEMU already implements zicbom (Cache Block Management Operations) and zicboz (Cache Block Zero Operations). Commit 59cb29d6a5 ("target/riscv: add Zicbop cbo.prefetch{i, r, m} placeholder") added placeholders for what would be the instructions for zicbop (Cache Block Prefetch Operations), which are now no-ops. The RVA22U64 profile mandates zicbop, which means that applications that run with this profile might expect zicbop to be present in the riscv,isa DT and might behave badly if it's absent. Adding zicbop as an extension will make our future RVA22U64 implementation more in line with what userspace expects and, if/when cache block prefetch operations became relevant to QEMU, we already have the extension flag to turn then on/off as needed. Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20231218125334.37184-6-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu_cfg.h | 2 ++ hw/riscv/virt.c | 5 +++++ target/riscv/cpu.c | 3 +++ 3 files changed, 10 insertions(+) diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu_cfg.h +++ b/target/riscv/cpu_cfg.h @@ -XXX,XX +XXX,XX @@ struct RISCVCPUConfig { bool ext_zicntr; bool ext_zicsr; bool ext_zicbom; + bool ext_zicbop; bool ext_zicboz; bool ext_zicond; bool ext_zihintntl; @@ -XXX,XX +XXX,XX @@ struct RISCVCPUConfig { uint16_t vlen; uint16_t elen; uint16_t cbom_blocksize; + uint16_t cbop_blocksize; uint16_t cboz_blocksize; bool mmu; bool pmp; 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_socket_cpus(RISCVVirtState *s, int socket, cpu_ptr->cfg.cboz_blocksize); } + if (cpu_ptr->cfg.ext_zicbop) { + qemu_fdt_setprop_cell(ms->fdt, cpu_name, "riscv,cbop-block-size", + cpu_ptr->cfg.cbop_blocksize); + } + qemu_fdt_setprop_string(ms->fdt, cpu_name, "compatible", "riscv"); qemu_fdt_setprop_string(ms->fdt, cpu_name, "status", "okay"); qemu_fdt_setprop_cell(ms->fdt, cpu_name, "reg", 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, */ const RISCVIsaExtData isa_edata_arr[] = { 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(zicond, PRIV_VERSION_1_12_0, ext_zicond), ISA_EXT_DATA_ENTRY(zicntr, PRIV_VERSION_1_12_0, ext_zicntr), @@ -XXX,XX +XXX,XX @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = { 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), @@ -XXX,XX +XXX,XX @@ Property riscv_cpu_options[] = { DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64), DEFINE_PROP_UINT16("cbom_blocksize", RISCVCPU, cfg.cbom_blocksize, 64), + DEFINE_PROP_UINT16("cbop_blocksize", RISCVCPU, cfg.cbop_blocksize, 64), DEFINE_PROP_UINT16("cboz_blocksize", RISCVCPU, cfg.cboz_blocksize, 64), DEFINE_PROP_END_OF_LIST(), -- 2.43.0
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> zic64b is defined in the RVA22U64 profile [1] as a named feature for "Cache blocks must be 64 bytes in size, naturally aligned in the address space". It's a fantasy name for 64 bytes cache blocks. The RVA22U64 profile mandates this feature, meaning that applications using this profile expects 64 bytes cache blocks. To make the upcoming RVA22U64 implementation complete, we'll zic64b as a 'named feature', not a regular extension. This means that: - it won't be exposed to users; - it won't be written in riscv,isa. This will be extended to other named extensions in the future, so we're creating some common boilerplate for them as well. zic64b is default to 'true' since we're already using 64 bytes blocks. If any cache block size (cbo{m,p,z}_blocksize) is changed to something different than 64, zic64b is set to 'false'. Our profile implementation will then be able to check the current state of zic64b and take the appropriate action (e.g. throw a warning). [1] https://github.com/riscv/riscv-profiles/releases/download/v1.0/profiles.pdf Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20231218125334.37184-7-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.h | 1 + target/riscv/cpu_cfg.h | 1 + target/riscv/cpu.c | 6 ++++++ target/riscv/tcg/tcg-cpu.c | 26 ++++++++++++++++++++++++++ 4 files changed, 34 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 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[]; extern const RISCVCPUMultiExtConfig riscv_cpu_deprecated_exts[]; extern Property riscv_cpu_options[]; diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu_cfg.h +++ b/target/riscv/cpu_cfg.h @@ -XXX,XX +XXX,XX @@ struct RISCVCPUConfig { bool ext_smepmp; bool rvv_ta_all_1s; bool rvv_ma_all_1s; + bool zic64b; uint32_t mvendorid; uint64_t marchid; 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[] = { DEFINE_PROP_END_OF_LIST(), }; +const RISCVCPUMultiExtConfig riscv_cpu_named_features[] = { + MULTI_EXT_CFG_BOOL("zic64b", zic64b, true), + + DEFINE_PROP_END_OF_LIST(), +}; + /* Deprecated entries marked for future removal */ const RISCVCPUMultiExtConfig riscv_cpu_deprecated_exts[] = { MULTI_EXT_CFG_BOOL("Zifencei", ext_zifencei, true), 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) 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 cpu_bump_multi_ext_priv_ver(CPURISCVState *env, uint32_t ext_offset) { @@ -XXX,XX +XXX,XX @@ static void cpu_bump_multi_ext_priv_ver(CPURISCVState *env, return; } + if (cpu_cfg_offset_is_named_feat(ext_offset)) { + return; + } + ext_priv_ver = cpu_cfg_ext_get_min_version(ext_offset); if (env->priv_ver < ext_priv_ver) { @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu) } } +static void riscv_cpu_update_named_features(RISCVCPU *cpu) +{ + cpu->cfg.zic64b = cpu->cfg.cbom_blocksize == 64 && + cpu->cfg.cbop_blocksize == 64 && + cpu->cfg.cboz_blocksize == 64; +} + /* * Check consistency between chosen extensions while setting * cpu->cfg accordingly. @@ -XXX,XX +XXX,XX @@ void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp) return; } + riscv_cpu_update_named_features(cpu); + if (cpu->cfg.ext_smepmp && !cpu->cfg.pmp) { /* * Enhanced PMP should only be available -- 2.43.0
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Named features (zic64b the sole example at this moment) aren't expose to users, thus we need another way to expose them. Go through each named feature, get its boolean value, do the needed conversions (bool to qbool, qbool to QObject) and add it to output dict. Another adjustment is needed: named features are evaluated during finalize(), so riscv_cpu_finalize_features() needs to be mandatory regardless of whether we have an input dict or not. Otherwise zic64b will always return 'false', which is incorrect: the default values of cache blocksizes ([cbom/cbop/cboz]_blocksize) are set to 64, satisfying the conditions for zic64b. Here's an API usage example after this patch: $ ./build/qemu-system-riscv64 -S -M virt -display none -qmp tcp:localhost:1234,server,wait=off $ ./scripts/qmp/qmp-shell localhost:1234 Welcome to the QMP low-level shell! Connected to QEMU 8.1.50 (QEMU) query-cpu-model-expansion type=full model={"name":"rv64"} {"return": {"model": {"name": "rv64", "props": {... "zic64b": true, ...}}}} zic64b is set to 'true', as expected, since all cache sizes are 64 bytes by default. If we change one of the cache blocksizes, zic64b is returned as 'false': (QEMU) query-cpu-model-expansion type=full model={"name":"rv64","props":{"cbom_blocksize":128}} {"return": {"model": {"name": "rv64", "props": {... "zic64b": false, ...}}}} Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20231218125334.37184-8-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/riscv-qmp-cmds.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) 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 "qapi/error.h" #include "qapi/qapi-commands-machine-target.h" +#include "qapi/qmp/qbool.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qerror.h" #include "qapi/qobject-input-visitor.h" @@ -XXX,XX +XXX,XX @@ static void riscv_obj_add_multiext_props(Object *obj, QDict *qdict_out, } } +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); + } +} + static void riscv_cpuobj_validate_qdict_in(Object *obj, QObject *props, const QDict *qdict_in, Error **errp) @@ -XXX,XX +XXX,XX @@ static void riscv_cpuobj_validate_qdict_in(Object *obj, QObject *props, goto err; } - riscv_cpu_finalize_features(RISCV_CPU(obj), &local_err); - if (local_err) { - goto err; - } - visit_end_struct(visitor, NULL); err: @@ -XXX,XX +XXX,XX @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type, } } + riscv_cpu_finalize_features(RISCV_CPU(obj), &local_err); + if (local_err) { + error_propagate(errp, local_err); + object_unref(obj); + return NULL; + } + expansion_info = g_new0(CpuModelExpansionInfo, 1); expansion_info->model = g_malloc0(sizeof(*expansion_info->model)); expansion_info->model->name = g_strdup(model->name); @@ -XXX,XX +XXX,XX @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type, 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); /* Add our CPU boolean options too */ riscv_obj_add_qdict_prop(obj, qdict_out, "mmu"); -- 2.43.0
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> The rva22U64 profile, described in: https://github.com/riscv/riscv-profiles/blob/main/profiles.adoc#rva22-profiles Contains a set of CPU extensions aimed for 64-bit userspace applications. Enabling this set to be enabled via a single user flag makes it convenient to enable a predictable set of features for the CPU, giving users more predicability when running/testing their workloads. QEMU implements all possible extensions of this profile. All the so called 'synthetic extensions' described in the profile that are cache related are ignored/assumed enabled (Za64rs, Zic64b, Ziccif, Ziccrse, Ziccamoa, Zicclsm) since we do not implement a cache model. An abstraction called RISCVCPUProfile is created to store the profile. 'ext_offsets' contains mandatory extensions that QEMU supports. Same thing with the 'misa_ext' mask. Optional extensions must be enabled manually in the command line if desired. The design here is to use the common target/riscv/cpu.c file to store the profile declaration and export it to the accelerator files. Each accelerator is then responsible to expose it (or not) to users and how to enable the extensions. Next patches will implement the profile for TCG and KVM. Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Message-ID: <20231218125334.37184-9-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.h | 12 ++++++++++++ target/riscv/cpu.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 44 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 @@ const char *riscv_get_misa_ext_description(uint32_t bit); #define CPU_CFG_OFFSET(_prop) offsetof(struct RISCVCPUConfig, _prop) +typedef struct riscv_cpu_profile { + const char *name; + uint32_t misa_ext; + bool enabled; + bool user_set; + const int32_t ext_offsets[]; +} RISCVCPUProfile; + +#define RISCV_PROFILE_EXT_LIST_END -1 + +extern RISCVCPUProfile *riscv_profiles[]; + /* Privileged specification version */ enum { PRIV_VERSION_1_10_0 = 0, 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 @@ Property riscv_cpu_options[] = { DEFINE_PROP_END_OF_LIST(), }; +/* + * RVA22U64 defines some 'named features' or 'synthetic extensions' + * that are cache related: Za64rs, Zic64b, Ziccif, Ziccrse, Ziccamoa + * and Zicclsm. We do not implement caching in QEMU so we'll consider + * all these named features as always enabled. + * + * There's no riscv,isa update for them (nor for zic64b, despite it + * having a cfg offset) at this moment. + */ +static RISCVCPUProfile RVA22U64 = { + .name = "rva22u64", + .misa_ext = RVI | RVM | RVA | RVF | RVD | RVC | RVU, + .ext_offsets = { + CPU_CFG_OFFSET(ext_zicsr), CPU_CFG_OFFSET(ext_zihintpause), + CPU_CFG_OFFSET(ext_zba), CPU_CFG_OFFSET(ext_zbb), + CPU_CFG_OFFSET(ext_zbs), CPU_CFG_OFFSET(ext_zfhmin), + CPU_CFG_OFFSET(ext_zkt), CPU_CFG_OFFSET(ext_zicntr), + CPU_CFG_OFFSET(ext_zihpm), CPU_CFG_OFFSET(ext_zicbom), + CPU_CFG_OFFSET(ext_zicbop), CPU_CFG_OFFSET(ext_zicboz), + + /* mandatory named features for this profile */ + CPU_CFG_OFFSET(zic64b), + + RISCV_PROFILE_EXT_LIST_END + } +}; + +RISCVCPUProfile *riscv_profiles[] = { + &RVA22U64, + NULL, +}; + static Property riscv_cpu_properties[] = { DEFINE_PROP_BOOL("debug", RISCVCPU, cfg.debug, true), -- 2.43.0
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> KVM does not have the means to support enabling the rva22u64 profile. The main reasons are: - we're missing support for some mandatory rva22u64 extensions in the KVM module; - we can't make promises about enabling a profile since it all depends on host support in the end. We'll revisit this decision in the future if needed. For now mark the 'rva22u64' profile as unavailable when running a KVM CPU: $ qemu-system-riscv64 -machine virt,accel=kvm -cpu rv64,rva22u64=true qemu-system-riscv64: can't apply global rv64-riscv-cpu.rva22u64=true: 'rva22u64' is not available with KVM Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Message-ID: <20231218125334.37184-10-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/kvm/kvm-cpu.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) 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 cpu_set_cfg_unavailable(Object *obj, Visitor *v, } if (value) { - error_setg(errp, "extension %s is not available with KVM", + error_setg(errp, "'%s' is not available with KVM", propname); } } @@ -XXX,XX +XXX,XX @@ static void kvm_riscv_add_cpu_user_properties(Object *cpu_obj) 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); + + /* We don't have the needed KVM support for profiles */ + for (i = 0; riscv_profiles[i] != NULL; i++) { + riscv_cpu_add_kvm_unavail_prop(cpu_obj, riscv_profiles[i]->name); + } } static int kvm_riscv_get_regs_core(CPUState *cs) -- 2.43.0
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> The TCG emulation implements all the extensions described in the RVA22U64 profile, both mandatory and optional. The mandatory extensions will be enabled via the profile flag. We'll leave the optional extensions to be enabled by hand. Given that this is the first profile we're implementing in TCG we'll need some ground work first: - all profiles declared in riscv_profiles[] will be exposed to users. TCG is the main accelerator we're considering when adding profile support in QEMU, so for now it's safe to assume that all profiles in riscv_profiles[] will be relevant to TCG; - we'll not support user profile settings for vendor CPUs. The flags will still be exposed but users won't be able to change them; - profile support, albeit available for all non-vendor CPUs, will be based on top of the new 'rv64i' CPU. Setting a profile to 'true' means enable all mandatory extensions of this profile, setting it to 'false' will disable all mandatory profile extensions of the CPU, which will obliterate preset defaults. This is not a problem for a bare CPU like rv64i but it can allow for silly scenarios when using other CPUs. E.g. an user can do "-cpu rv64,rva22u64=false" and have a bunch of default rv64 extensions disabled. The recommended way of using profiles is the rv64i CPU, but users are free to experiment. For now we'll handle multi-letter extensions only. MISA extensions need additional steps that we'll take care later. At this point we can boot a Linux buildroot using rva22u64 using the following options: -cpu rv64i,rva22u64=true,sv39=true,g=true,c=true,s=true Note that being an usermode/application profile we still need to explicitly set 's=true' to enable Supervisor mode to boot Linux. Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20231218125334.37184-11-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/tcg/tcg-cpu.c | 80 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 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 bool cpu_cfg_offset_is_named_feat(uint32_t ext_offset) return false; } +static void riscv_cpu_enable_named_feat(RISCVCPU *cpu, uint32_t feat_offset) +{ + switch (feat_offset) { + case CPU_CFG_OFFSET(zic64b): + cpu->cfg.cbom_blocksize = 64; + cpu->cfg.cbop_blocksize = 64; + cpu->cfg.cboz_blocksize = 64; + break; + default: + g_assert_not_reached(); + } +} + static void cpu_bump_multi_ext_priv_ver(CPURISCVState *env, uint32_t ext_offset) { @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_add_misa_properties(Object *cpu_obj) } } +static void cpu_set_profile(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + RISCVCPUProfile *profile = opaque; + RISCVCPU *cpu = RISCV_CPU(obj); + bool value; + int i, ext_offset; + + if (riscv_cpu_is_vendor(obj)) { + error_setg(errp, "Profile %s is not available for vendor CPUs", + profile->name); + return; + } + + if (cpu->env.misa_mxl != MXL_RV64) { + error_setg(errp, "Profile %s only available for 64 bit CPUs", + profile->name); + return; + } + + if (!visit_type_bool(v, name, &value, errp)) { + return; + } + + profile->user_set = true; + profile->enabled = value; + + for (i = 0; profile->ext_offsets[i] != RISCV_PROFILE_EXT_LIST_END; i++) { + 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); + } + + g_hash_table_insert(multi_ext_user_opts, + GUINT_TO_POINTER(ext_offset), + (gpointer)profile->enabled); + isa_ext_update_enabled(cpu, ext_offset, profile->enabled); + } +} + +static void cpu_get_profile(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + RISCVCPUProfile *profile = opaque; + bool value = profile->enabled; + + visit_type_bool(v, name, &value, errp); +} + +static void riscv_cpu_add_profiles(Object *cpu_obj) +{ + for (int i = 0; riscv_profiles[i] != NULL; i++) { + const RISCVCPUProfile *profile = riscv_profiles[i]; + + object_property_add(cpu_obj, profile->name, "bool", + cpu_get_profile, cpu_set_profile, + NULL, (void *)profile); + } +} + static bool cpu_ext_is_deprecated(const char *ext_name) { return isupper(ext_name[0]); @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_add_user_properties(Object *obj) riscv_cpu_add_multiext_prop_array(obj, riscv_cpu_deprecated_exts); + riscv_cpu_add_profiles(obj); + for (Property *prop = riscv_cpu_options; prop && prop->name; prop++) { qdev_property_add_static(DEVICE(obj), prop); } -- 2.43.0
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> We already track user choice for multi-letter extensions because we needed to honor user choice when enabling/disabling extensions during realize(). We refrained from adding the same mechanism for MISA extensions since we didn't need it. Profile support requires tne need to check for user choice for MISA extensions, so let's add the corresponding hash now. It works like the existing multi-letter hash (multi_ext_user_opts) but tracking MISA bits options in the cpu_set_misa_ext_cfg() callback. Note that we can't re-use the same hash from multi-letter extensions because that hash uses cpu->cfg offsets as keys, while for MISA extensions we're using MISA bits as keys. After adding the user hash in cpu_set_misa_ext_cfg(), setting default values with object_property_set_bool() in add_misa_properties() will end up marking the user choice hash with them. Set the default value manually to avoid it. Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Message-ID: <20231218125334.37184-12-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/tcg/tcg-cpu.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) 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 @@ /* Hash that stores user set extensions */ static GHashTable *multi_ext_user_opts; +static GHashTable *misa_ext_user_opts; static bool cpu_cfg_ext_is_user_set(uint32_t ext_offset) { @@ -XXX,XX +XXX,XX @@ static void cpu_set_misa_ext_cfg(Object *obj, Visitor *v, const char *name, return; } + g_hash_table_insert(misa_ext_user_opts, + GUINT_TO_POINTER(misa_bit), + (gpointer)value); + prev_val = env->misa_ext & misa_bit; if (value == prev_val) { @@ -XXX,XX +XXX,XX @@ static const RISCVCPUMisaExtConfig misa_ext_cfgs[] = { */ static void riscv_cpu_add_misa_properties(Object *cpu_obj) { + CPURISCVState *env = &RISCV_CPU(cpu_obj)->env; bool use_def_vals = riscv_cpu_is_generic(cpu_obj); int i; @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_add_misa_properties(Object *cpu_obj) NULL, (void *)misa_cfg); object_property_set_description(cpu_obj, name, desc); if (use_def_vals) { - object_property_set_bool(cpu_obj, name, misa_cfg->enabled, NULL); + if (misa_cfg->enabled) { + env->misa_ext |= bit; + env->misa_ext_mask |= bit; + } else { + env->misa_ext &= ~bit; + env->misa_ext_mask &= ~bit; + } } } } @@ -XXX,XX +XXX,XX @@ static void tcg_cpu_instance_init(CPUState *cs) RISCVCPU *cpu = RISCV_CPU(cs); Object *obj = OBJECT(cpu); + misa_ext_user_opts = g_hash_table_new(NULL, g_direct_equal); multi_ext_user_opts = g_hash_table_new(NULL, g_direct_equal); riscv_cpu_add_user_properties(obj); -- 2.43.0
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> We have two instances of the setting/clearing a MISA bit from env->misa_ext and env->misa_ext_mask pattern. And the next patch will end up adding one more. Create a helper to avoid code repetition. Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Message-ID: <20231218125334.37184-13-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/tcg/tcg-cpu.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 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 bool cpu_cfg_ext_is_user_set(uint32_t ext_offset) GUINT_TO_POINTER(ext_offset)); } +static void riscv_cpu_write_misa_bit(RISCVCPU *cpu, uint32_t bit, + bool enabled) +{ + CPURISCVState *env = &cpu->env; + + if (enabled) { + env->misa_ext |= bit; + env->misa_ext_mask |= bit; + } else { + env->misa_ext &= ~bit; + env->misa_ext_mask &= ~bit; + } +} + static void riscv_cpu_synchronize_from_tb(CPUState *cs, const TranslationBlock *tb) { @@ -XXX,XX +XXX,XX @@ static void cpu_set_misa_ext_cfg(Object *obj, Visitor *v, const char *name, */ env->priv_ver = PRIV_VERSION_1_12_0; } - - env->misa_ext |= misa_bit; - env->misa_ext_mask |= misa_bit; - } else { - env->misa_ext &= ~misa_bit; - env->misa_ext_mask &= ~misa_bit; } + + riscv_cpu_write_misa_bit(cpu, misa_bit, value); } static void cpu_get_misa_ext_cfg(Object *obj, Visitor *v, const char *name, @@ -XXX,XX +XXX,XX @@ static const RISCVCPUMisaExtConfig misa_ext_cfgs[] = { */ static void riscv_cpu_add_misa_properties(Object *cpu_obj) { - CPURISCVState *env = &RISCV_CPU(cpu_obj)->env; bool use_def_vals = riscv_cpu_is_generic(cpu_obj); int i; @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_add_misa_properties(Object *cpu_obj) NULL, (void *)misa_cfg); object_property_set_description(cpu_obj, name, desc); if (use_def_vals) { - if (misa_cfg->enabled) { - env->misa_ext |= bit; - env->misa_ext_mask |= bit; - } else { - env->misa_ext &= ~bit; - env->misa_ext_mask &= ~bit; - } + riscv_cpu_write_misa_bit(RISCV_CPU(cpu_obj), bit, + misa_cfg->enabled); } } } -- 2.43.0
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> The profile support is handling multi-letter extensions only. Let's add support for MISA bits as well. We'll go through every known MISA bit. If the profile doesn't declare the bit as mandatory, ignore it. Otherwise, set the bit in env->misa_ext and env->misa_ext_mask. Now that we're setting profile MISA bits, one can use the rv64i CPU to boot Linux using the following options: -cpu rv64i,rva22u64=true,rv39=true,s=true,zifencei=true In the near future, when rva22s64 (where, 's', 'zifencei' and sv39 are mandatory), is implemented, rv64i will be able to boot Linux loading rva22s64 and no additional flags. Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20231218125334.37184-14-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/tcg/tcg-cpu.c | 21 +++++++++++++++++++++ 1 file changed, 21 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 cpu_set_profile(Object *obj, Visitor *v, const char *name, profile->user_set = true; profile->enabled = value; + for (i = 0; misa_bits[i] != 0; i++) { + uint32_t bit = misa_bits[i]; + + if (!(profile->misa_ext & bit)) { + continue; + } + + if (bit == RVI && !profile->enabled) { + /* + * Disabling profiles will not disable the base + * ISA RV64I. + */ + continue; + } + + g_hash_table_insert(misa_ext_user_opts, + GUINT_TO_POINTER(bit), + (gpointer)value); + riscv_cpu_write_misa_bit(cpu, bit, profile->enabled); + } + for (i = 0; profile->ext_offsets[i] != RISCV_PROFILE_EXT_LIST_END; i++) { ext_offset = profile->ext_offsets[i]; -- 2.43.0
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Previous patches added several g_hash_table_insert() patterns. Add two helpers, one for each user hash, to make the code cleaner. Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20231218125334.37184-15-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/tcg/tcg-cpu.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 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 bool cpu_cfg_ext_is_user_set(uint32_t ext_offset) GUINT_TO_POINTER(ext_offset)); } +static void cpu_cfg_ext_add_user_opt(uint32_t ext_offset, bool value) +{ + g_hash_table_insert(multi_ext_user_opts, GUINT_TO_POINTER(ext_offset), + (gpointer)value); +} + +static void cpu_misa_ext_add_user_opt(uint32_t bit, bool value) +{ + g_hash_table_insert(misa_ext_user_opts, GUINT_TO_POINTER(bit), + (gpointer)value); +} + static void riscv_cpu_write_misa_bit(RISCVCPU *cpu, uint32_t bit, bool enabled) { @@ -XXX,XX +XXX,XX @@ static void cpu_set_misa_ext_cfg(Object *obj, Visitor *v, const char *name, return; } - g_hash_table_insert(misa_ext_user_opts, - GUINT_TO_POINTER(misa_bit), - (gpointer)value); + cpu_misa_ext_add_user_opt(misa_bit, value); prev_val = env->misa_ext & misa_bit; @@ -XXX,XX +XXX,XX @@ static void cpu_set_profile(Object *obj, Visitor *v, const char *name, continue; } - g_hash_table_insert(misa_ext_user_opts, - GUINT_TO_POINTER(bit), - (gpointer)value); + cpu_misa_ext_add_user_opt(bit, profile->enabled); riscv_cpu_write_misa_bit(cpu, bit, profile->enabled); } @@ -XXX,XX +XXX,XX @@ static void cpu_set_profile(Object *obj, Visitor *v, const char *name, cpu_bump_multi_ext_priv_ver(&cpu->env, ext_offset); } - g_hash_table_insert(multi_ext_user_opts, - GUINT_TO_POINTER(ext_offset), - (gpointer)profile->enabled); + cpu_cfg_ext_add_user_opt(ext_offset, profile->enabled); isa_ext_update_enabled(cpu, ext_offset, profile->enabled); } } @@ -XXX,XX +XXX,XX @@ static void cpu_set_multi_ext_cfg(Object *obj, Visitor *v, const char *name, multi_ext_cfg->name, lower); } - g_hash_table_insert(multi_ext_user_opts, - GUINT_TO_POINTER(multi_ext_cfg->offset), - (gpointer)value); + cpu_cfg_ext_add_user_opt(multi_ext_cfg->offset, value); prev_val = isa_ext_is_enabled(cpu, multi_ext_cfg->offset); -- 2.43.0
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> RVG behaves like a profile: a single flag enables a set of bits. Right now we're considering user choice when handling RVG and zicsr/zifencei and ignoring user choice on MISA bits. We'll add user warnings for profiles when the user disables its mandatory extensions in the next patch. We'll do the same thing with RVG now to keep consistency between RVG and profile handling. First and foremost, create a new RVG only helper to avoid clogging riscv_cpu_validate_set_extensions(). We do not want to annoy users with RVG warnings like we did in the past (see 9b9741c38f), thus we'll only warn if RVG was user set and the user disabled a RVG extension in the command line. For every RVG MISA bit (IMAFD), zicsr and zifencei, the logic then becomes: - if enabled, do nothing; - if disabled and not user set, enable it; - if disabled and user set, throw a warning that it's a RVG mandatory extension. This same logic will be used for profiles in the next patch. Note that this is a behavior change, where we would error out if the user disabled either zicsr or zifencei. As long as users are explicitly disabling things in the command line we'll let them have a go at it, at least in this step. We'll error out later in the validation if needed. Other notable changes from the previous RVG code: - use riscv_cpu_write_misa_bit() instead of manually updating both env->misa_ext and env->misa_ext_mask; - set zicsr and zifencei directly. We're already checking if they were user set and priv version will never fail for these extensions, making cpu_cfg_ext_auto_update() redundant. Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20231218125334.37184-16-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/tcg/tcg-cpu.c | 73 +++++++++++++++++++++++++------------- 1 file changed, 48 insertions(+), 25 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 bool cpu_cfg_ext_is_user_set(uint32_t ext_offset) GUINT_TO_POINTER(ext_offset)); } +static bool cpu_misa_ext_is_user_set(uint32_t misa_bit) +{ + return g_hash_table_contains(misa_ext_user_opts, + GUINT_TO_POINTER(misa_bit)); +} + static void cpu_cfg_ext_add_user_opt(uint32_t ext_offset, bool value) { g_hash_table_insert(multi_ext_user_opts, GUINT_TO_POINTER(ext_offset), @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_update_named_features(RISCVCPU *cpu) cpu->cfg.cboz_blocksize == 64; } +static void riscv_cpu_validate_g(RISCVCPU *cpu) +{ + const char *warn_msg = "RVG mandates disabled extension %s"; + uint32_t g_misa_bits[] = {RVI, RVM, RVA, RVF, RVD}; + bool send_warn = cpu_misa_ext_is_user_set(RVG); + + for (int i = 0; i < ARRAY_SIZE(g_misa_bits); i++) { + uint32_t bit = g_misa_bits[i]; + + if (riscv_has_ext(&cpu->env, bit)) { + continue; + } + + if (!cpu_misa_ext_is_user_set(bit)) { + riscv_cpu_write_misa_bit(cpu, bit, true); + continue; + } + + if (send_warn) { + warn_report(warn_msg, riscv_get_misa_ext_name(bit)); + } + } + + if (!cpu->cfg.ext_zicsr) { + if (!cpu_cfg_ext_is_user_set(CPU_CFG_OFFSET(ext_zicsr))) { + cpu->cfg.ext_zicsr = true; + } else if (send_warn) { + warn_report(warn_msg, "zicsr"); + } + } + + if (!cpu->cfg.ext_zifencei) { + if (!cpu_cfg_ext_is_user_set(CPU_CFG_OFFSET(ext_zifencei))) { + cpu->cfg.ext_zifencei = true; + } else if (send_warn) { + warn_report(warn_msg, "zifencei"); + } + } +} + /* * Check consistency between chosen extensions while setting * cpu->cfg accordingly. @@ -XXX,XX +XXX,XX @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp) CPURISCVState *env = &cpu->env; Error *local_err = NULL; - /* Do some ISA extension error checking */ - if (riscv_has_ext(env, RVG) && - !(riscv_has_ext(env, RVI) && riscv_has_ext(env, RVM) && - riscv_has_ext(env, RVA) && riscv_has_ext(env, RVF) && - riscv_has_ext(env, RVD) && - cpu->cfg.ext_zicsr && cpu->cfg.ext_zifencei)) { - - if (cpu_cfg_ext_is_user_set(CPU_CFG_OFFSET(ext_zicsr)) && - !cpu->cfg.ext_zicsr) { - error_setg(errp, "RVG requires Zicsr but user set Zicsr to false"); - return; - } - - if (cpu_cfg_ext_is_user_set(CPU_CFG_OFFSET(ext_zifencei)) && - !cpu->cfg.ext_zifencei) { - error_setg(errp, "RVG requires Zifencei but user set " - "Zifencei to false"); - return; - } - - cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zicsr), true); - cpu_cfg_ext_auto_update(cpu, CPU_CFG_OFFSET(ext_zifencei), true); - - env->misa_ext |= RVI | RVM | RVA | RVF | RVD; - env->misa_ext_mask |= RVI | RVM | RVA | RVF | RVD; + if (riscv_has_ext(env, RVG)) { + riscv_cpu_validate_g(cpu); } if (riscv_has_ext(env, RVI) && riscv_has_ext(env, RVE)) { -- 2.43.0
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Enabling a profile and then disabling some of its mandatory extensions is a valid use. It can be useful for debugging and testing. But the common expected use of enabling a profile is to enable all its mandatory extensions. Add an user warning when mandatory extensions from an enabled profile are disabled in the command line. We're also going to disable the profile flag in this case since the profile must include all the mandatory extensions. This flag can be exposed by QMP to indicate the actual profile state after the CPU is realized. After this patch, this will throw warnings: -cpu rv64,rva22u64=true,zihintpause=false,zicbom=false,zicboz=false qemu-system-riscv64: warning: Profile rva22u64 mandates disabled extension zihintpause qemu-system-riscv64: warning: Profile rva22u64 mandates disabled extension zicbom qemu-system-riscv64: warning: Profile rva22u64 mandates disabled extension zicboz Note that the following will NOT throw warnings because the profile is being enabled last, hence all its mandatory extensions will be enabled: -cpu rv64,zihintpause=false,zicbom=false,zicboz=false,rva22u64=true Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20231218125334.37184-17-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/tcg/tcg-cpu.c | 69 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 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 int cpu_cfg_ext_get_min_version(uint32_t ext_offset) g_assert_not_reached(); } +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++) { + if (edata->ext_enable_offset == ext_offset) { + return edata->name; + } + } + + for (feat = riscv_cpu_named_features; feat->name != NULL; feat++) { + if (feat->offset == ext_offset) { + return feat->name; + } + } + + g_assert_not_reached(); +} + static bool cpu_cfg_offset_is_named_feat(uint32_t ext_offset) { const RISCVCPUMultiExtConfig *feat; @@ -XXX,XX +XXX,XX @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp) riscv_cpu_disable_priv_spec_isa_exts(cpu); } +static void riscv_cpu_validate_profile(RISCVCPU *cpu, + RISCVCPUProfile *profile) +{ + const char *warn_msg = "Profile %s mandates disabled extension %s"; + bool send_warn = profile->user_set && profile->enabled; + bool profile_impl = true; + int i; + + for (i = 0; misa_bits[i] != 0; i++) { + uint32_t bit = misa_bits[i]; + + if (!(profile->misa_ext & bit)) { + continue; + } + + if (!riscv_has_ext(&cpu->env, bit)) { + profile_impl = false; + + if (send_warn) { + warn_report(warn_msg, profile->name, + riscv_get_misa_ext_name(bit)); + } + } + } + + for (i = 0; profile->ext_offsets[i] != RISCV_PROFILE_EXT_LIST_END; i++) { + int ext_offset = profile->ext_offsets[i]; + + if (!isa_ext_is_enabled(cpu, ext_offset)) { + profile_impl = false; + + if (send_warn) { + warn_report(warn_msg, profile->name, + cpu_cfg_ext_get_name(ext_offset)); + } + } + } + + profile->enabled = profile_impl; +} + +static void riscv_cpu_validate_profiles(RISCVCPU *cpu) +{ + for (int i = 0; riscv_profiles[i] != NULL; i++) { + riscv_cpu_validate_profile(cpu, riscv_profiles[i]); + } +} + 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_update_named_features(cpu); + riscv_cpu_validate_profiles(cpu); if (cpu->cfg.ext_smepmp && !cpu->cfg.pmp) { /* -- 2.43.0
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Expose all profile flags for all CPUs when executing query-cpu-model-expansion. This will allow callers to quickly determine if a certain profile is implemented by a given CPU. This includes vendor CPUs - the fact that they don't have profile user flags doesn't mean that they don't implement the profile. After this change it's possible to quickly determine if our stock CPUs implement the existing rva22u64 profile. Here's a few examples: $ ./build/qemu-system-riscv64 -S -M virt -display none -qmp tcp:localhost:1234,server,wait=off $ ./scripts/qmp/qmp-shell localhost:1234 Welcome to the QMP low-level shell! Connected to QEMU 8.1.50 - As expected, the 'max' CPU implements the rva22u64 profile. (QEMU) query-cpu-model-expansion type=full model={"name":"max"} {"return": {"model": {"name": "rv64", "props": {... "rva22u64": true, ...}}}} - rv64 is missing "zba", "zbb", "zbs", "zkt" and "zfhmin": query-cpu-model-expansion type=full model={"name":"rv64"} {"return": {"model": {"name": "rv64", "props": {... "rva22u64": false, ...}}}} query-cpu-model-expansion type=full model={"name":"rv64", "props":{"zba":true,"zbb":true,"zbs":true,"zkt":true,"zfhmin":true}} {"return": {"model": {"name": "rv64", "props": {... "rva22u64": true, ...}}}} We have no vendor CPUs that supports rva22u64 (veyron-v1 is the closest - it is missing just 'zkt'). In short, aside from the 'max' CPU, we have no CPUs that supports rva22u64 by default. Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20231218125334.37184-18-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/riscv-qmp-cmds.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) 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_named_feats_qdict(Object *obj, QDict *qdict_out) } } +static void riscv_obj_add_profiles_qdict(Object *obj, QDict *qdict_out) +{ + RISCVCPUProfile *profile; + QObject *value; + + for (int i = 0; riscv_profiles[i] != NULL; i++) { + profile = riscv_profiles[i]; + value = QOBJECT(qbool_from_bool(profile->enabled)); + + qdict_put_obj(qdict_out, profile->name, value); + } +} + static void riscv_cpuobj_validate_qdict_in(Object *obj, QObject *props, const QDict *qdict_in, Error **errp) @@ -XXX,XX +XXX,XX @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type, 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_profiles_qdict(obj, qdict_out); /* Add our CPU boolean options too */ riscv_obj_add_qdict_prop(obj, qdict_out, "mmu"); -- 2.43.0
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> This CPU was suggested by Alistair [1] and others during the profile design discussions. It consists of the bare 'rv64i' CPU with rva22u64 enabled by default, like an alias of '-cpu rv64i,rva22u64=true'. Users now have an even easier way of consuming this user-mode profile by doing '-cpu rva22u64'. Extensions can be enabled/disabled at will on top of it. We can boot Linux with this "user-mode" CPU by doing: -cpu rva22u64,sv39=true,s=true,zifencei=true [1] https://lore.kernel.org/qemu-riscv/CAKmqyKP7xzZ9Sx=-Lbx2Ob0qCfB7Z+JO944FQ2TQ+49mqo0q_Q@mail.gmail.com/ Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20231218125334.37184-19-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu-qom.h | 1 + target/riscv/cpu.c | 17 +++++++++++++++++ target/riscv/tcg/tcg-cpu.c | 9 +++++++++ 3 files changed, 27 insertions(+) diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu-qom.h +++ b/target/riscv/cpu-qom.h @@ -XXX,XX +XXX,XX @@ #define TYPE_RISCV_CPU_BASE64 RISCV_CPU_TYPE_NAME("rv64") #define TYPE_RISCV_CPU_BASE128 RISCV_CPU_TYPE_NAME("x-rv128") #define TYPE_RISCV_CPU_RV64I RISCV_CPU_TYPE_NAME("rv64i") +#define TYPE_RISCV_CPU_RVA22U64 RISCV_CPU_TYPE_NAME("rva22u64") #define TYPE_RISCV_CPU_IBEX RISCV_CPU_TYPE_NAME("lowrisc-ibex") #define TYPE_RISCV_CPU_SHAKTI_C RISCV_CPU_TYPE_NAME("shakti-c") #define TYPE_RISCV_CPU_SIFIVE_E31 RISCV_CPU_TYPE_NAME("sifive-e31") 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 Property riscv_cpu_properties[] = { DEFINE_PROP_END_OF_LIST(), }; +#if defined(TARGET_RISCV64) +static void rva22u64_profile_cpu_init(Object *obj) +{ + rv64i_bare_cpu_init(obj); + + RVA22U64.enabled = true; +} +#endif + static const gchar *riscv_gdb_arch_name(CPUState *cs) { RISCVCPU *cpu = RISCV_CPU(cs); @@ -XXX,XX +XXX,XX @@ char *riscv_isa_string(RISCVCPU *cpu) .instance_init = initfn \ } +#define DEFINE_PROFILE_CPU(type_name, initfn) \ + { \ + .name = type_name, \ + .parent = TYPE_RISCV_BARE_CPU, \ + .instance_init = initfn \ + } + static const TypeInfo riscv_cpu_type_infos[] = { { .name = TYPE_RISCV_CPU, @@ -XXX,XX +XXX,XX @@ static const TypeInfo riscv_cpu_type_infos[] = { DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_VEYRON_V1, rv64_veyron_v1_cpu_init), DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE128, rv128_base_cpu_init), DEFINE_BARE_CPU(TYPE_RISCV_CPU_RV64I, rv64i_bare_cpu_init), + DEFINE_PROFILE_CPU(TYPE_RISCV_CPU_RVA22U64, rva22u64_profile_cpu_init), #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 @@ static void riscv_cpu_add_profiles(Object *cpu_obj) object_property_add(cpu_obj, profile->name, "bool", cpu_get_profile, cpu_set_profile, NULL, (void *)profile); + + /* + * CPUs might enable a profile right from the start. + * Enable its mandatory extensions right away in this + * case. + */ + if (profile->enabled) { + object_property_set_bool(cpu_obj, profile->name, true, NULL); + } } } -- 2.43.0
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> 'svade' is a RVA22S64 profile requirement, a profile we're going to add shortly. It is a named feature (i.e. not a formal extension, not defined in riscv,isa DT at this moment) defined in [1] as: "Page-fault exceptions are raised when a page is accessed when A bit is clear, or written when D bit is clear.". As far as the spec goes, 'svade' is one of the two distinct modes of handling PTE_A and PTE_D. The other way, i.e. update PTE_A/PTE_D when they're cleared, is defined by the 'svadu' extension. Checking cpu_helper.c, get_physical_address(), we can verify that QEMU is compliant with that: we will update PTE_A/PTE_D if 'svadu' is enabled, or throw a page-fault exception if 'svadu' isn't enabled. So, as far as we're concerned, 'svade' translates to 'svadu must be disabled'. We'll implement it like 'zic64b': an internal flag that profiles can enable. The flag will not be exposed to users. [1] https://github.com/riscv/riscv-profiles/blob/main/profiles.adoc Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20231218125334.37184-20-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu_cfg.h | 1 + target/riscv/cpu.c | 1 + target/riscv/tcg/tcg-cpu.c | 5 +++++ 3 files changed, 7 insertions(+) diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu_cfg.h +++ b/target/riscv/cpu_cfg.h @@ -XXX,XX +XXX,XX @@ struct RISCVCPUConfig { bool ext_smepmp; bool rvv_ta_all_1s; bool rvv_ma_all_1s; + bool svade; bool zic64b; uint32_t mvendorid; 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[] = { }; const RISCVCPUMultiExtConfig riscv_cpu_named_features[] = { + MULTI_EXT_CFG_BOOL("svade", svade, true), MULTI_EXT_CFG_BOOL("zic64b", zic64b, true), DEFINE_PROP_END_OF_LIST(), 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_named_feat(RISCVCPU *cpu, uint32_t feat_offset) cpu->cfg.cbop_blocksize = 64; cpu->cfg.cboz_blocksize = 64; break; + case CPU_CFG_OFFSET(svade): + cpu->cfg.ext_svadu = false; + break; default: g_assert_not_reached(); } @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_update_named_features(RISCVCPU *cpu) cpu->cfg.zic64b = cpu->cfg.cbom_blocksize == 64 && cpu->cfg.cbop_blocksize == 64 && cpu->cfg.cboz_blocksize == 64; + + cpu->cfg.svade = !cpu->cfg.ext_svadu; } static void riscv_cpu_validate_g(RISCVCPU *cpu) -- 2.43.0
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Some profiles, like RVA22S64, has a priv_spec requirement. Make this requirement explicit for all profiles. We'll validate this requirement finalize() time and, in case the user chooses an incompatible priv_spec while activating a profile, a warning will be shown. Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20231218125334.37184-21-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.h | 2 ++ target/riscv/cpu.c | 1 + target/riscv/tcg/tcg-cpu.c | 31 +++++++++++++++++++++++++++++++ 3 files changed, 34 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 riscv_cpu_profile { uint32_t misa_ext; bool enabled; bool user_set; + int priv_spec; const int32_t ext_offsets[]; } RISCVCPUProfile; #define RISCV_PROFILE_EXT_LIST_END -1 +#define RISCV_PROFILE_ATTR_UNUSED -1 extern RISCVCPUProfile *riscv_profiles[]; 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 @@ Property riscv_cpu_options[] = { static RISCVCPUProfile RVA22U64 = { .name = "rva22u64", .misa_ext = RVI | RVM | RVA | RVF | RVD | RVC | RVU, + .priv_spec = RISCV_PROFILE_ATTR_UNUSED, .ext_offsets = { CPU_CFG_OFFSET(ext_zicsr), CPU_CFG_OFFSET(ext_zihintpause), CPU_CFG_OFFSET(ext_zba), CPU_CFG_OFFSET(ext_zbb), 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_write_misa_bit(RISCVCPU *cpu, uint32_t bit, } } +static const char *cpu_priv_ver_to_str(int priv_ver) +{ + switch (priv_ver) { + case PRIV_VERSION_1_10_0: + return "v1.10.0"; + case PRIV_VERSION_1_11_0: + return "v1.11.0"; + case PRIV_VERSION_1_12_0: + return "v1.12.0"; + } + + g_assert_not_reached(); +} + static void riscv_cpu_synchronize_from_tb(CPUState *cs, const TranslationBlock *tb) { @@ -XXX,XX +XXX,XX @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp) static void riscv_cpu_validate_profile(RISCVCPU *cpu, RISCVCPUProfile *profile) { + CPURISCVState *env = &cpu->env; const char *warn_msg = "Profile %s mandates disabled extension %s"; bool send_warn = profile->user_set && profile->enabled; bool profile_impl = true; int i; + if (profile->priv_spec != RISCV_PROFILE_ATTR_UNUSED && + profile->priv_spec != env->priv_ver) { + profile_impl = false; + + if (send_warn) { + warn_report("Profile %s requires priv spec %s, " + "but priv ver %s was set", profile->name, + cpu_priv_ver_to_str(profile->priv_spec), + cpu_priv_ver_to_str(env->priv_ver)); + } + } + for (i = 0; misa_bits[i] != 0; i++) { uint32_t bit = misa_bits[i]; @@ -XXX,XX +XXX,XX @@ static void cpu_set_profile(Object *obj, Visitor *v, const char *name, profile->user_set = true; profile->enabled = value; + if (profile->enabled) { + cpu->env.priv_ver = profile->priv_spec; + } + for (i = 0; misa_bits[i] != 0; i++) { uint32_t bit = misa_bits[i]; -- 2.43.0
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Profiles will need to validate satp_mode during their own finalize methods. This will occur inside riscv_tcg_cpu_finalize_features() for TCG. Given that satp_mode does not have any pre-req from the accelerator finalize() method, it's safe to finalize it earlier. Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20231218125334.37184-22-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.c | 16 ++++++++-------- 1 file changed, 8 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 @@ void riscv_cpu_finalize_features(RISCVCPU *cpu, Error **errp) { Error *local_err = NULL; +#ifndef CONFIG_USER_ONLY + riscv_cpu_satp_mode_finalize(cpu, &local_err); + if (local_err != NULL) { + error_propagate(errp, local_err); + return; + } +#endif + /* * KVM accel does not have a specialized finalize() * callback because its extensions are validated @@ -XXX,XX +XXX,XX @@ void riscv_cpu_finalize_features(RISCVCPU *cpu, Error **errp) return; } } - -#ifndef CONFIG_USER_ONLY - riscv_cpu_satp_mode_finalize(cpu, &local_err); - if (local_err != NULL) { - error_propagate(errp, local_err); - return; - } -#endif } static void riscv_cpu_realize(DeviceState *dev, Error **errp) -- 2.43.0
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Next patch will need to retrieve if a given RISCVCPU is 32 or 64 bit. The existing helper riscv_is_32bit() (hw/riscv/boot.c) will always check the first CPU of a given hart array, not any given CPU. Create a helper to retrieve the info for any given CPU, not the first CPU of the hart array. The helper is using the same 32 bit check that riscv_cpu_satp_mode_finalize() was doing. Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20231218125334.37184-23-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.h | 1 + target/riscv/cpu.c | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) 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 cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc, uint64_t *cs_base, uint32_t *pflags); void riscv_cpu_update_mask(CPURISCVState *env); +bool riscv_cpu_is_32bit(RISCVCPU *cpu); RISCVException riscv_csrrw(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 @@ const uint32_t misa_bits[] = {RVI, RVE, RVM, RVA, RVF, RVD, RVV, #define BYTE(x) (x) #endif +bool riscv_cpu_is_32bit(RISCVCPU *cpu) +{ + return riscv_cpu_mxl(&cpu->env) == MXL_RV32; +} + #define ISA_EXT_DATA_ENTRY(_name, _min_ver, _prop) \ {#_name, _min_ver, CPU_CFG_OFFSET(_prop)} @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info) #ifndef CONFIG_USER_ONLY static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp) { - bool rv32 = riscv_cpu_mxl(&cpu->env) == MXL_RV32; + bool rv32 = riscv_cpu_is_32bit(cpu); uint8_t satp_mode_map_max, satp_mode_supported_max; /* The CPU wants the OS to decide which satp mode to use */ -- 2.43.0
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> 'satp_mode' is a requirement for supervisor profiles like RVA22S64. User-mode/application profiles like RVA22U64 doesn't care. Add 'satp_mode' to the profile description. If a profile requires it, set it during cpu_set_profile(). We'll also check it during finalize() to validate if the running config implements the profile. Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20231218125334.37184-24-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.h | 1 + target/riscv/cpu.c | 1 + target/riscv/tcg/tcg-cpu.c | 40 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 42 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 riscv_cpu_profile { bool enabled; bool user_set; int priv_spec; + int satp_mode; const int32_t ext_offsets[]; } RISCVCPUProfile; 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 RISCVCPUProfile RVA22U64 = { .name = "rva22u64", .misa_ext = RVI | RVM | RVA | RVF | RVD | RVC | RVU, .priv_spec = RISCV_PROFILE_ATTR_UNUSED, + .satp_mode = RISCV_PROFILE_ATTR_UNUSED, .ext_offsets = { CPU_CFG_OFFSET(ext_zicsr), CPU_CFG_OFFSET(ext_zihintpause), CPU_CFG_OFFSET(ext_zba), CPU_CFG_OFFSET(ext_zbb), 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 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp) riscv_cpu_disable_priv_spec_isa_exts(cpu); } +#ifndef CONFIG_USER_ONLY +static bool riscv_cpu_validate_profile_satp(RISCVCPU *cpu, + RISCVCPUProfile *profile, + bool send_warn) +{ + int satp_max = satp_mode_max_from_map(cpu->cfg.satp_mode.supported); + + if (profile->satp_mode > satp_max) { + if (send_warn) { + bool is_32bit = riscv_cpu_is_32bit(cpu); + const char *req_satp = satp_mode_str(profile->satp_mode, is_32bit); + const char *cur_satp = satp_mode_str(satp_max, is_32bit); + + warn_report("Profile %s requires satp mode %s, " + "but satp mode %s was set", profile->name, + req_satp, cur_satp); + } + + return false; + } + + return true; +} +#endif + static void riscv_cpu_validate_profile(RISCVCPU *cpu, RISCVCPUProfile *profile) { @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_validate_profile(RISCVCPU *cpu, bool profile_impl = true; int i; +#ifndef CONFIG_USER_ONLY + if (profile->satp_mode != RISCV_PROFILE_ATTR_UNUSED) { + profile_impl = riscv_cpu_validate_profile_satp(cpu, profile, + send_warn); + } +#endif + if (profile->priv_spec != RISCV_PROFILE_ATTR_UNUSED && profile->priv_spec != env->priv_ver) { profile_impl = false; @@ -XXX,XX +XXX,XX @@ static void cpu_set_profile(Object *obj, Visitor *v, const char *name, cpu->env.priv_ver = profile->priv_spec; } +#ifndef CONFIG_USER_ONLY + if (profile->satp_mode != RISCV_PROFILE_ATTR_UNUSED) { + const char *satp_prop = satp_mode_str(profile->satp_mode, + riscv_cpu_is_32bit(cpu)); + object_property_set_bool(obj, satp_prop, profile->enabled, NULL); + } +#endif + for (i = 0; misa_bits[i] != 0; i++) { uint32_t bit = misa_bits[i]; -- 2.43.0
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Certain S-mode profiles, like RVA22S64 and RVA23S64, mandate all the mandatory extensions of their respective U-mode profiles. RVA22S64 includes all mandatory extensions of RVA22U64, and the same happens with RVA23 profiles. Add a 'parent' field to allow profiles to enable other profiles. This will allow us to describe S-mode profiles by specifying their parent U-mode profile, then adding just the S-mode specific extensions. We're naming the field 'parent' to consider the possibility of other uses (e.g. a s-mode profile including a previous s-mode profile) in the future. Suggested-by: Andrew Jones <ajones@ventanamicro.com> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20231218125334.37184-25-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.h | 1 + target/riscv/cpu.c | 1 + target/riscv/tcg/tcg-cpu.c | 14 +++++++++++++- 3 files changed, 15 insertions(+), 1 deletion(-) 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 @@ const char *riscv_get_misa_ext_description(uint32_t bit); #define CPU_CFG_OFFSET(_prop) offsetof(struct RISCVCPUConfig, _prop) typedef struct riscv_cpu_profile { + struct riscv_cpu_profile *parent; const char *name; uint32_t misa_ext; bool enabled; 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 @@ Property riscv_cpu_options[] = { * having a cfg offset) at this moment. */ static RISCVCPUProfile RVA22U64 = { + .parent = NULL, .name = "rva22u64", .misa_ext = RVI | RVM | RVA | RVF | RVD | RVC | RVU, .priv_spec = RISCV_PROFILE_ATTR_UNUSED, 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_validate_profile(RISCVCPU *cpu, CPURISCVState *env = &cpu->env; const char *warn_msg = "Profile %s mandates disabled extension %s"; bool send_warn = profile->user_set && profile->enabled; - bool profile_impl = true; + bool parent_enabled, profile_impl = true; int i; #ifndef CONFIG_USER_ONLY @@ -XXX,XX +XXX,XX @@ static void riscv_cpu_validate_profile(RISCVCPU *cpu, } profile->enabled = profile_impl; + + if (profile->parent != NULL) { + parent_enabled = object_property_get_bool(OBJECT(cpu), + profile->parent->name, + NULL); + profile->enabled = profile->enabled && parent_enabled; + } } static void riscv_cpu_validate_profiles(RISCVCPU *cpu) @@ -XXX,XX +XXX,XX @@ static void cpu_set_profile(Object *obj, Visitor *v, const char *name, profile->user_set = true; profile->enabled = value; + if (profile->parent != NULL) { + object_property_set_bool(obj, profile->parent->name, + profile->enabled, NULL); + } + if (profile->enabled) { cpu->env.priv_ver = profile->priv_spec; } -- 2.43.0
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> The RVA22S64 profile consists of the following: - all mandatory extensions of RVA22U64; - priv spec v1.12.0; - satp mode sv39; - Ssccptr, a cache related named feature that we're assuming always enable since we don't implement a cache; - Other named features already implemented: Sstvecd, Sstvala, Sscounterenw; - the new Svade named feature that was recently added. Most of the work is already done, so this patch is enough to implement the profile. After this patch, the 'rva22s64' user flag alone can be used with the rva64i CPU to boot Linux: -cpu rv64i,rva22s64=true This is the /proc/cpuinfo with this profile enabled: # cat /proc/cpuinfo processor : 0 hart : 0 isa : rv64imafdc_zicbom_zicbop_zicboz_zicntr_zicsr_zifencei_zihintpause_zihpm_zfhmin_zca_zcd_zba_zbb_zbs_zkt_svinval_svpbmt mmu : sv39 Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20231218125334.37184-26-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) 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 RISCVCPUProfile RVA22U64 = { } }; +/* + * As with RVA22U64, RVA22S64 also defines 'named features'. + * + * Cache related features that we consider enabled since we don't + * implement cache: Ssccptr + * + * Other named features that we already implement: Sstvecd, Sstvala, + * Sscounterenw + * + * Named features that we need to enable: svade + * + * The remaining features/extensions comes from RVA22U64. + */ +static RISCVCPUProfile RVA22S64 = { + .parent = &RVA22U64, + .name = "rva22s64", + .misa_ext = RVS, + .priv_spec = PRIV_VERSION_1_12_0, + .satp_mode = VM_1_10_SV39, + .ext_offsets = { + /* rva22s64 exts */ + CPU_CFG_OFFSET(ext_zifencei), CPU_CFG_OFFSET(ext_svpbmt), + CPU_CFG_OFFSET(ext_svinval), + + /* rva22s64 named features */ + CPU_CFG_OFFSET(svade), + + RISCV_PROFILE_EXT_LIST_END + } +}; + RISCVCPUProfile *riscv_profiles[] = { &RVA22U64, + &RVA22S64, NULL, }; -- 2.43.0
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Add a new profile CPU 'rva22s64' to work as an alias of -cpu rv64i,rva22s64 Like the existing rva22u64 CPU already does with the RVA22U64 profile. Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Andrew Jones <ajones@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20231218125334.37184-27-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu-qom.h | 1 + target/riscv/cpu.c | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu-qom.h +++ b/target/riscv/cpu-qom.h @@ -XXX,XX +XXX,XX @@ #define TYPE_RISCV_CPU_BASE128 RISCV_CPU_TYPE_NAME("x-rv128") #define TYPE_RISCV_CPU_RV64I RISCV_CPU_TYPE_NAME("rv64i") #define TYPE_RISCV_CPU_RVA22U64 RISCV_CPU_TYPE_NAME("rva22u64") +#define TYPE_RISCV_CPU_RVA22S64 RISCV_CPU_TYPE_NAME("rva22s64") #define TYPE_RISCV_CPU_IBEX RISCV_CPU_TYPE_NAME("lowrisc-ibex") #define TYPE_RISCV_CPU_SHAKTI_C RISCV_CPU_TYPE_NAME("shakti-c") #define TYPE_RISCV_CPU_SIFIVE_E31 RISCV_CPU_TYPE_NAME("sifive-e31") 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 rva22u64_profile_cpu_init(Object *obj) RVA22U64.enabled = true; } + +static void rva22s64_profile_cpu_init(Object *obj) +{ + rv64i_bare_cpu_init(obj); + + RVA22S64.enabled = true; +} #endif static const gchar *riscv_gdb_arch_name(CPUState *cs) @@ -XXX,XX +XXX,XX @@ static const TypeInfo riscv_cpu_type_infos[] = { DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE128, rv128_base_cpu_init), DEFINE_BARE_CPU(TYPE_RISCV_CPU_RV64I, rv64i_bare_cpu_init), DEFINE_PROFILE_CPU(TYPE_RISCV_CPU_RVA22U64, rva22u64_profile_cpu_init), + DEFINE_PROFILE_CPU(TYPE_RISCV_CPU_RVA22S64, rva22s64_profile_cpu_init), #endif }; -- 2.43.0
From: Yong-Xuan Wang <yongxuan.wang@sifive.com> The emulated AIA within the Linux kernel restores the HART index of the IMSICs according to the configured AIA settings. During this process, the group setting is used only when the machine partitions harts into groups. It's unnecessary to set the group configuration if the machine has only one socket, as its address space might not contain the group shift. Signed-off-by: Yong-Xuan Wang <yongxuan.wang@sifive.com> Reviewed-by: Jim Shu <jim.shu@sifive.com> Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Message-ID: <20231218090543.22353-2-yongxuan.wang@sifive.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/kvm/kvm-cpu.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 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 @@ void kvm_riscv_aia_create(MachineState *machine, uint64_t group_shift, exit(1); } - socket_bits = find_last_bit(&socket_count, BITS_PER_LONG) + 1; - ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG, - KVM_DEV_RISCV_AIA_CONFIG_GROUP_BITS, - &socket_bits, true, NULL); - if (ret < 0) { - error_report("KVM AIA: failed to set group_bits"); - exit(1); - } - ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG, - KVM_DEV_RISCV_AIA_CONFIG_GROUP_SHIFT, - &group_shift, true, NULL); - if (ret < 0) { - error_report("KVM AIA: failed to set group_shift"); - exit(1); + if (socket_count > 1) { + socket_bits = find_last_bit(&socket_count, BITS_PER_LONG) + 1; + ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG, + KVM_DEV_RISCV_AIA_CONFIG_GROUP_BITS, + &socket_bits, true, NULL); + if (ret < 0) { + error_report("KVM AIA: failed to set group_bits"); + exit(1); + } + + ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG, + KVM_DEV_RISCV_AIA_CONFIG_GROUP_SHIFT, + &group_shift, true, NULL); + if (ret < 0) { + error_report("KVM AIA: failed to set group_shift"); + exit(1); + } } guest_bits = guest_num == 0 ? 0 : -- 2.43.0
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> We'll add a new RISC-V linux-header file, but first let's update all headers. Headers for 'asm-loongarch' were added in this update. Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20231218204321.75757-2-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- include/standard-headers/drm/drm_fourcc.h | 2 + include/standard-headers/linux/pci_regs.h | 24 ++- include/standard-headers/linux/vhost_types.h | 7 + .../standard-headers/linux/virtio_config.h | 5 + include/standard-headers/linux/virtio_pci.h | 11 ++ linux-headers/asm-arm64/kvm.h | 32 ++++ linux-headers/asm-generic/unistd.h | 14 +- linux-headers/asm-loongarch/bitsperlong.h | 1 + linux-headers/asm-loongarch/kvm.h | 108 +++++++++++ linux-headers/asm-loongarch/mman.h | 1 + linux-headers/asm-loongarch/unistd.h | 5 + linux-headers/asm-mips/unistd_n32.h | 4 + linux-headers/asm-mips/unistd_n64.h | 4 + linux-headers/asm-mips/unistd_o32.h | 4 + linux-headers/asm-powerpc/unistd_32.h | 4 + linux-headers/asm-powerpc/unistd_64.h | 4 + linux-headers/asm-riscv/kvm.h | 12 ++ linux-headers/asm-s390/unistd_32.h | 4 + linux-headers/asm-s390/unistd_64.h | 4 + linux-headers/asm-x86/unistd_32.h | 4 + linux-headers/asm-x86/unistd_64.h | 3 + linux-headers/asm-x86/unistd_x32.h | 3 + linux-headers/linux/iommufd.h | 180 +++++++++++++++++- linux-headers/linux/kvm.h | 11 ++ linux-headers/linux/psp-sev.h | 1 + linux-headers/linux/stddef.h | 9 +- linux-headers/linux/userfaultfd.h | 9 +- linux-headers/linux/vfio.h | 47 +++-- linux-headers/linux/vhost.h | 8 + 29 files changed, 498 insertions(+), 27 deletions(-) create mode 100644 linux-headers/asm-loongarch/bitsperlong.h create mode 100644 linux-headers/asm-loongarch/kvm.h create mode 100644 linux-headers/asm-loongarch/mman.h create mode 100644 linux-headers/asm-loongarch/unistd.h diff --git a/include/standard-headers/drm/drm_fourcc.h b/include/standard-headers/drm/drm_fourcc.h index XXXXXXX..XXXXXXX 100644 --- a/include/standard-headers/drm/drm_fourcc.h +++ b/include/standard-headers/drm/drm_fourcc.h @@ -XXX,XX +XXX,XX @@ extern "C" { * index 1 = Cr:Cb plane, [39:0] Cr1:Cb1:Cr0:Cb0 little endian */ #define DRM_FORMAT_NV15 fourcc_code('N', 'V', '1', '5') /* 2x2 subsampled Cr:Cb plane */ +#define DRM_FORMAT_NV20 fourcc_code('N', 'V', '2', '0') /* 2x1 subsampled Cr:Cb plane */ +#define DRM_FORMAT_NV30 fourcc_code('N', 'V', '3', '0') /* non-subsampled Cr:Cb plane */ /* * 2 plane YCbCr MSB aligned diff --git a/include/standard-headers/linux/pci_regs.h b/include/standard-headers/linux/pci_regs.h index XXXXXXX..XXXXXXX 100644 --- a/include/standard-headers/linux/pci_regs.h +++ b/include/standard-headers/linux/pci_regs.h @@ -XXX,XX +XXX,XX @@ #define PCI_HEADER_TYPE_NORMAL 0 #define PCI_HEADER_TYPE_BRIDGE 1 #define PCI_HEADER_TYPE_CARDBUS 2 +#define PCI_HEADER_TYPE_MFD 0x80 /* Multi-Function Device (possible) */ #define PCI_BIST 0x0f /* 8 bits */ #define PCI_BIST_CODE_MASK 0x0f /* Return result */ @@ -XXX,XX +XXX,XX @@ #define PCI_EXP_RTCAP 0x1e /* Root Capabilities */ #define PCI_EXP_RTCAP_CRSVIS 0x0001 /* CRS Software Visibility capability */ #define PCI_EXP_RTSTA 0x20 /* Root Status */ +#define PCI_EXP_RTSTA_PME_RQ_ID 0x0000ffff /* PME Requester ID */ #define PCI_EXP_RTSTA_PME 0x00010000 /* PME status */ #define PCI_EXP_RTSTA_PENDING 0x00020000 /* PME pending */ /* @@ -XXX,XX +XXX,XX @@ /* Process Address Space ID */ #define PCI_PASID_CAP 0x04 /* PASID feature register */ -#define PCI_PASID_CAP_EXEC 0x02 /* Exec permissions Supported */ -#define PCI_PASID_CAP_PRIV 0x04 /* Privilege Mode Supported */ +#define PCI_PASID_CAP_EXEC 0x0002 /* Exec permissions Supported */ +#define PCI_PASID_CAP_PRIV 0x0004 /* Privilege Mode Supported */ +#define PCI_PASID_CAP_WIDTH 0x1f00 #define PCI_PASID_CTRL 0x06 /* PASID control register */ -#define PCI_PASID_CTRL_ENABLE 0x01 /* Enable bit */ -#define PCI_PASID_CTRL_EXEC 0x02 /* Exec permissions Enable */ -#define PCI_PASID_CTRL_PRIV 0x04 /* Privilege Mode Enable */ +#define PCI_PASID_CTRL_ENABLE 0x0001 /* Enable bit */ +#define PCI_PASID_CTRL_EXEC 0x0002 /* Exec permissions Enable */ +#define PCI_PASID_CTRL_PRIV 0x0004 /* Privilege Mode Enable */ #define PCI_EXT_CAP_PASID_SIZEOF 8 /* Single Root I/O Virtualization */ @@ -XXX,XX +XXX,XX @@ #define PCI_LTR_VALUE_MASK 0x000003ff #define PCI_LTR_SCALE_MASK 0x00001c00 #define PCI_LTR_SCALE_SHIFT 10 +#define PCI_LTR_NOSNOOP_VALUE 0x03ff0000 /* Max No-Snoop Latency Value */ +#define PCI_LTR_NOSNOOP_SCALE 0x1c000000 /* Scale for Max Value */ #define PCI_EXT_CAP_LTR_SIZEOF 8 /* Access Control Service */ @@ -XXX,XX +XXX,XX @@ #define PCI_EXP_DPC_STATUS 0x08 /* DPC Status */ #define PCI_EXP_DPC_STATUS_TRIGGER 0x0001 /* Trigger Status */ #define PCI_EXP_DPC_STATUS_TRIGGER_RSN 0x0006 /* Trigger Reason */ +#define PCI_EXP_DPC_STATUS_TRIGGER_RSN_UNCOR 0x0000 /* Uncorrectable error */ +#define PCI_EXP_DPC_STATUS_TRIGGER_RSN_NFE 0x0002 /* Rcvd ERR_NONFATAL */ +#define PCI_EXP_DPC_STATUS_TRIGGER_RSN_FE 0x0004 /* Rcvd ERR_FATAL */ +#define PCI_EXP_DPC_STATUS_TRIGGER_RSN_IN_EXT 0x0006 /* Reason in Trig Reason Extension field */ #define PCI_EXP_DPC_STATUS_INTERRUPT 0x0008 /* Interrupt Status */ #define PCI_EXP_DPC_RP_BUSY 0x0010 /* Root Port Busy */ #define PCI_EXP_DPC_STATUS_TRIGGER_RSN_EXT 0x0060 /* Trig Reason Extension */ +#define PCI_EXP_DPC_STATUS_TRIGGER_RSN_RP_PIO 0x0000 /* RP PIO error */ +#define PCI_EXP_DPC_STATUS_TRIGGER_RSN_SW_TRIGGER 0x0020 /* DPC SW Trigger bit */ +#define PCI_EXP_DPC_RP_PIO_FEP 0x1f00 /* RP PIO First Err Ptr */ #define PCI_EXP_DPC_SOURCE_ID 0x0A /* DPC Source Identifier */ @@ -XXX,XX +XXX,XX @@ #define PCI_L1SS_CTL1_LTR_L12_TH_VALUE 0x03ff0000 /* LTR_L1.2_THRESHOLD_Value */ #define PCI_L1SS_CTL1_LTR_L12_TH_SCALE 0xe0000000 /* LTR_L1.2_THRESHOLD_Scale */ #define PCI_L1SS_CTL2 0x0c /* Control 2 Register */ +#define PCI_L1SS_CTL2_T_PWR_ON_SCALE 0x00000003 /* T_POWER_ON Scale */ +#define PCI_L1SS_CTL2_T_PWR_ON_VALUE 0x000000f8 /* T_POWER_ON Value */ /* Designated Vendor-Specific (DVSEC, PCI_EXT_CAP_ID_DVSEC) */ #define PCI_DVSEC_HEADER1 0x4 /* Designated Vendor-Specific Header1 */ diff --git a/include/standard-headers/linux/vhost_types.h b/include/standard-headers/linux/vhost_types.h index XXXXXXX..XXXXXXX 100644 --- a/include/standard-headers/linux/vhost_types.h +++ b/include/standard-headers/linux/vhost_types.h @@ -XXX,XX +XXX,XX @@ struct vhost_vdpa_iova_range { * DRIVER_OK */ #define VHOST_BACKEND_F_ENABLE_AFTER_DRIVER_OK 0x6 +/* Device may expose the virtqueue's descriptor area, driver area and + * device area to a different group for ASID binding than where its + * buffers may reside. Requires VHOST_BACKEND_F_IOTLB_ASID. + */ +#define VHOST_BACKEND_F_DESC_ASID 0x7 +/* IOTLB don't flush memory mapping across device reset */ +#define VHOST_BACKEND_F_IOTLB_PERSIST 0x8 #endif diff --git a/include/standard-headers/linux/virtio_config.h b/include/standard-headers/linux/virtio_config.h index XXXXXXX..XXXXXXX 100644 --- a/include/standard-headers/linux/virtio_config.h +++ b/include/standard-headers/linux/virtio_config.h @@ -XXX,XX +XXX,XX @@ */ #define VIRTIO_F_NOTIFICATION_DATA 38 +/* This feature indicates that the driver uses the data provided by the device + * as a virtqueue identifier in available buffer notifications. + */ +#define VIRTIO_F_NOTIF_CONFIG_DATA 39 + /* * This feature indicates that the driver can reset a queue individually. */ diff --git a/include/standard-headers/linux/virtio_pci.h b/include/standard-headers/linux/virtio_pci.h index XXXXXXX..XXXXXXX 100644 --- a/include/standard-headers/linux/virtio_pci.h +++ b/include/standard-headers/linux/virtio_pci.h @@ -XXX,XX +XXX,XX @@ struct virtio_pci_common_cfg { uint32_t queue_used_hi; /* read-write */ }; +/* + * Warning: do not use sizeof on this: use offsetofend for + * specific fields you need. + */ +struct virtio_pci_modern_common_cfg { + struct virtio_pci_common_cfg cfg; + + uint16_t queue_notify_data; /* read-write */ + uint16_t queue_reset; /* read-write */ +}; + /* Fields in VIRTIO_PCI_CAP_PCI_CFG: */ struct virtio_pci_cfg_cap { struct virtio_pci_cap cap; diff --git a/linux-headers/asm-arm64/kvm.h b/linux-headers/asm-arm64/kvm.h index XXXXXXX..XXXXXXX 100644 --- a/linux-headers/asm-arm64/kvm.h +++ b/linux-headers/asm-arm64/kvm.h @@ -XXX,XX +XXX,XX @@ struct kvm_smccc_filter { #define KVM_HYPERCALL_EXIT_SMC (1U << 0) #define KVM_HYPERCALL_EXIT_16BIT (1U << 1) +/* + * Get feature ID registers userspace writable mask. + * + * From DDI0487J.a, D19.2.66 ("ID_AA64MMFR2_EL1, AArch64 Memory Model + * Feature Register 2"): + * + * "The Feature ID space is defined as the System register space in + * AArch64 with op0==3, op1=={0, 1, 3}, CRn==0, CRm=={0-7}, + * op2=={0-7}." + * + * This covers all currently known R/O registers that indicate + * anything useful feature wise, including the ID registers. + * + * If we ever need to introduce a new range, it will be described as + * such in the range field. + */ +#define KVM_ARM_FEATURE_ID_RANGE_IDX(op0, op1, crn, crm, op2) \ + ({ \ + __u64 __op1 = (op1) & 3; \ + __op1 -= (__op1 == 3); \ + (__op1 << 6 | ((crm) & 7) << 3 | (op2)); \ + }) + +#define KVM_ARM_FEATURE_ID_RANGE 0 +#define KVM_ARM_FEATURE_ID_RANGE_SIZE (3 * 8 * 8) + +struct reg_mask_range { + __u64 addr; /* Pointer to mask array */ + __u32 range; /* Requested range */ + __u32 reserved[13]; +}; + #endif #endif /* __ARM_KVM_H__ */ diff --git a/linux-headers/asm-generic/unistd.h b/linux-headers/asm-generic/unistd.h index XXXXXXX..XXXXXXX 100644 --- a/linux-headers/asm-generic/unistd.h +++ b/linux-headers/asm-generic/unistd.h @@ -XXX,XX +XXX,XX @@ __SYSCALL(__NR_fremovexattr, sys_fremovexattr) #define __NR_getcwd 17 __SYSCALL(__NR_getcwd, sys_getcwd) #define __NR_lookup_dcookie 18 -__SC_COMP(__NR_lookup_dcookie, sys_lookup_dcookie, compat_sys_lookup_dcookie) +__SYSCALL(__NR_lookup_dcookie, sys_ni_syscall) #define __NR_eventfd2 19 __SYSCALL(__NR_eventfd2, sys_eventfd2) #define __NR_epoll_create1 20 @@ -XXX,XX +XXX,XX @@ __SYSCALL(__NR_process_mrelease, sys_process_mrelease) __SYSCALL(__NR_futex_waitv, sys_futex_waitv) #define __NR_set_mempolicy_home_node 450 __SYSCALL(__NR_set_mempolicy_home_node, sys_set_mempolicy_home_node) - #define __NR_cachestat 451 __SYSCALL(__NR_cachestat, sys_cachestat) - #define __NR_fchmodat2 452 __SYSCALL(__NR_fchmodat2, sys_fchmodat2) +#define __NR_map_shadow_stack 453 +__SYSCALL(__NR_map_shadow_stack, sys_map_shadow_stack) +#define __NR_futex_wake 454 +__SYSCALL(__NR_futex_wake, sys_futex_wake) +#define __NR_futex_wait 455 +__SYSCALL(__NR_futex_wait, sys_futex_wait) +#define __NR_futex_requeue 456 +__SYSCALL(__NR_futex_requeue, sys_futex_requeue) #undef __NR_syscalls -#define __NR_syscalls 453 +#define __NR_syscalls 457 /* * 32 bit systems traditionally used different diff --git a/linux-headers/asm-loongarch/bitsperlong.h b/linux-headers/asm-loongarch/bitsperlong.h new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/linux-headers/asm-loongarch/bitsperlong.h @@ -0,0 +1 @@ +#include <asm-generic/bitsperlong.h> diff --git a/linux-headers/asm-loongarch/kvm.h b/linux-headers/asm-loongarch/kvm.h new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/linux-headers/asm-loongarch/kvm.h @@ -XXX,XX +XXX,XX @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * Copyright (C) 2020-2023 Loongson Technology Corporation Limited + */ + +#ifndef __UAPI_ASM_LOONGARCH_KVM_H +#define __UAPI_ASM_LOONGARCH_KVM_H + +#include <linux/types.h> + +/* + * KVM LoongArch specific structures and definitions. + * + * Some parts derived from the x86 version of this file. + */ + +#define __KVM_HAVE_READONLY_MEM + +#define KVM_COALESCED_MMIO_PAGE_OFFSET 1 +#define KVM_DIRTY_LOG_PAGE_OFFSET 64 + +/* + * for KVM_GET_REGS and KVM_SET_REGS + */ +struct kvm_regs { + /* out (KVM_GET_REGS) / in (KVM_SET_REGS) */ + __u64 gpr[32]; + __u64 pc; +}; + +/* + * for KVM_GET_FPU and KVM_SET_FPU + */ +struct kvm_fpu { + __u32 fcsr; + __u64 fcc; /* 8x8 */ + struct kvm_fpureg { + __u64 val64[4]; + } fpr[32]; +}; + +/* + * For LoongArch, we use KVM_SET_ONE_REG and KVM_GET_ONE_REG to access various + * registers. The id field is broken down as follows: + * + * bits[63..52] - As per linux/kvm.h + * bits[51..32] - Must be zero. + * bits[31..16] - Register set. + * + * Register set = 0: GP registers from kvm_regs (see definitions below). + * + * Register set = 1: CSR registers. + * + * Register set = 2: KVM specific registers (see definitions below). + * + * Register set = 3: FPU / SIMD registers (see definitions below). + * + * Other sets registers may be added in the future. Each set would + * have its own identifier in bits[31..16]. + */ + +#define KVM_REG_LOONGARCH_GPR (KVM_REG_LOONGARCH | 0x00000ULL) +#define KVM_REG_LOONGARCH_CSR (KVM_REG_LOONGARCH | 0x10000ULL) +#define KVM_REG_LOONGARCH_KVM (KVM_REG_LOONGARCH | 0x20000ULL) +#define KVM_REG_LOONGARCH_FPSIMD (KVM_REG_LOONGARCH | 0x30000ULL) +#define KVM_REG_LOONGARCH_CPUCFG (KVM_REG_LOONGARCH | 0x40000ULL) +#define KVM_REG_LOONGARCH_MASK (KVM_REG_LOONGARCH | 0x70000ULL) +#define KVM_CSR_IDX_MASK 0x7fff +#define KVM_CPUCFG_IDX_MASK 0x7fff + +/* + * KVM_REG_LOONGARCH_KVM - KVM specific control registers. + */ + +#define KVM_REG_LOONGARCH_COUNTER (KVM_REG_LOONGARCH_KVM | KVM_REG_SIZE_U64 | 1) +#define KVM_REG_LOONGARCH_VCPU_RESET (KVM_REG_LOONGARCH_KVM | KVM_REG_SIZE_U64 | 2) + +#define LOONGARCH_REG_SHIFT 3 +#define LOONGARCH_REG_64(TYPE, REG) (TYPE | KVM_REG_SIZE_U64 | (REG << LOONGARCH_REG_SHIFT)) +#define KVM_IOC_CSRID(REG) LOONGARCH_REG_64(KVM_REG_LOONGARCH_CSR, REG) +#define KVM_IOC_CPUCFG(REG) LOONGARCH_REG_64(KVM_REG_LOONGARCH_CPUCFG, REG) + +struct kvm_debug_exit_arch { +}; + +/* for KVM_SET_GUEST_DEBUG */ +struct kvm_guest_debug_arch { +}; + +/* definition of registers in kvm_run */ +struct kvm_sync_regs { +}; + +/* dummy definition */ +struct kvm_sregs { +}; + +struct kvm_iocsr_entry { + __u32 addr; + __u32 pad; + __u64 data; +}; + +#define KVM_NR_IRQCHIPS 1 +#define KVM_IRQCHIP_NUM_PINS 64 +#define KVM_MAX_CORES 256 + +#endif /* __UAPI_ASM_LOONGARCH_KVM_H */ diff --git a/linux-headers/asm-loongarch/mman.h b/linux-headers/asm-loongarch/mman.h new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/linux-headers/asm-loongarch/mman.h @@ -0,0 +1 @@ +#include <asm-generic/mman.h> diff --git a/linux-headers/asm-loongarch/unistd.h b/linux-headers/asm-loongarch/unistd.h new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/linux-headers/asm-loongarch/unistd.h @@ -XXX,XX +XXX,XX @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#define __ARCH_WANT_SYS_CLONE +#define __ARCH_WANT_SYS_CLONE3 + +#include <asm-generic/unistd.h> diff --git a/linux-headers/asm-mips/unistd_n32.h b/linux-headers/asm-mips/unistd_n32.h index XXXXXXX..XXXXXXX 100644 --- a/linux-headers/asm-mips/unistd_n32.h +++ b/linux-headers/asm-mips/unistd_n32.h @@ -XXX,XX +XXX,XX @@ #define __NR_set_mempolicy_home_node (__NR_Linux + 450) #define __NR_cachestat (__NR_Linux + 451) #define __NR_fchmodat2 (__NR_Linux + 452) +#define __NR_map_shadow_stack (__NR_Linux + 453) +#define __NR_futex_wake (__NR_Linux + 454) +#define __NR_futex_wait (__NR_Linux + 455) +#define __NR_futex_requeue (__NR_Linux + 456) #endif /* _ASM_UNISTD_N32_H */ diff --git a/linux-headers/asm-mips/unistd_n64.h b/linux-headers/asm-mips/unistd_n64.h index XXXXXXX..XXXXXXX 100644 --- a/linux-headers/asm-mips/unistd_n64.h +++ b/linux-headers/asm-mips/unistd_n64.h @@ -XXX,XX +XXX,XX @@ #define __NR_set_mempolicy_home_node (__NR_Linux + 450) #define __NR_cachestat (__NR_Linux + 451) #define __NR_fchmodat2 (__NR_Linux + 452) +#define __NR_map_shadow_stack (__NR_Linux + 453) +#define __NR_futex_wake (__NR_Linux + 454) +#define __NR_futex_wait (__NR_Linux + 455) +#define __NR_futex_requeue (__NR_Linux + 456) #endif /* _ASM_UNISTD_N64_H */ diff --git a/linux-headers/asm-mips/unistd_o32.h b/linux-headers/asm-mips/unistd_o32.h index XXXXXXX..XXXXXXX 100644 --- a/linux-headers/asm-mips/unistd_o32.h +++ b/linux-headers/asm-mips/unistd_o32.h @@ -XXX,XX +XXX,XX @@ #define __NR_set_mempolicy_home_node (__NR_Linux + 450) #define __NR_cachestat (__NR_Linux + 451) #define __NR_fchmodat2 (__NR_Linux + 452) +#define __NR_map_shadow_stack (__NR_Linux + 453) +#define __NR_futex_wake (__NR_Linux + 454) +#define __NR_futex_wait (__NR_Linux + 455) +#define __NR_futex_requeue (__NR_Linux + 456) #endif /* _ASM_UNISTD_O32_H */ diff --git a/linux-headers/asm-powerpc/unistd_32.h b/linux-headers/asm-powerpc/unistd_32.h index XXXXXXX..XXXXXXX 100644 --- a/linux-headers/asm-powerpc/unistd_32.h +++ b/linux-headers/asm-powerpc/unistd_32.h @@ -XXX,XX +XXX,XX @@ #define __NR_set_mempolicy_home_node 450 #define __NR_cachestat 451 #define __NR_fchmodat2 452 +#define __NR_map_shadow_stack 453 +#define __NR_futex_wake 454 +#define __NR_futex_wait 455 +#define __NR_futex_requeue 456 #endif /* _ASM_UNISTD_32_H */ diff --git a/linux-headers/asm-powerpc/unistd_64.h b/linux-headers/asm-powerpc/unistd_64.h index XXXXXXX..XXXXXXX 100644 --- a/linux-headers/asm-powerpc/unistd_64.h +++ b/linux-headers/asm-powerpc/unistd_64.h @@ -XXX,XX +XXX,XX @@ #define __NR_set_mempolicy_home_node 450 #define __NR_cachestat 451 #define __NR_fchmodat2 452 +#define __NR_map_shadow_stack 453 +#define __NR_futex_wake 454 +#define __NR_futex_wait 455 +#define __NR_futex_requeue 456 #endif /* _ASM_UNISTD_64_H */ diff --git a/linux-headers/asm-riscv/kvm.h b/linux-headers/asm-riscv/kvm.h index XXXXXXX..XXXXXXX 100644 --- a/linux-headers/asm-riscv/kvm.h +++ b/linux-headers/asm-riscv/kvm.h @@ -XXX,XX +XXX,XX @@ struct kvm_riscv_csr { unsigned long sip; unsigned long satp; unsigned long scounteren; + unsigned long senvcfg; }; /* AIA CSR registers for KVM_GET_ONE_REG and KVM_SET_ONE_REG */ @@ -XXX,XX +XXX,XX @@ struct kvm_riscv_aia_csr { unsigned long iprio2h; }; +/* Smstateen CSR for KVM_GET_ONE_REG and KVM_SET_ONE_REG */ +struct kvm_riscv_smstateen_csr { + unsigned long sstateen0; +}; + /* TIMER registers for KVM_GET_ONE_REG and KVM_SET_ONE_REG */ struct kvm_riscv_timer { __u64 frequency; @@ -XXX,XX +XXX,XX @@ enum KVM_RISCV_ISA_EXT_ID { KVM_RISCV_ISA_EXT_ZICSR, KVM_RISCV_ISA_EXT_ZIFENCEI, KVM_RISCV_ISA_EXT_ZIHPM, + KVM_RISCV_ISA_EXT_SMSTATEEN, + KVM_RISCV_ISA_EXT_ZICOND, KVM_RISCV_ISA_EXT_MAX, }; @@ -XXX,XX +XXX,XX @@ enum KVM_RISCV_SBI_EXT_ID { KVM_RISCV_SBI_EXT_PMU, KVM_RISCV_SBI_EXT_EXPERIMENTAL, KVM_RISCV_SBI_EXT_VENDOR, + KVM_RISCV_SBI_EXT_DBCN, KVM_RISCV_SBI_EXT_MAX, }; @@ -XXX,XX +XXX,XX @@ enum KVM_RISCV_SBI_EXT_ID { #define KVM_REG_RISCV_CSR (0x03 << KVM_REG_RISCV_TYPE_SHIFT) #define KVM_REG_RISCV_CSR_GENERAL (0x0 << KVM_REG_RISCV_SUBTYPE_SHIFT) #define KVM_REG_RISCV_CSR_AIA (0x1 << KVM_REG_RISCV_SUBTYPE_SHIFT) +#define KVM_REG_RISCV_CSR_SMSTATEEN (0x2 << KVM_REG_RISCV_SUBTYPE_SHIFT) #define KVM_REG_RISCV_CSR_REG(name) \ (offsetof(struct kvm_riscv_csr, name) / sizeof(unsigned long)) #define KVM_REG_RISCV_CSR_AIA_REG(name) \ (offsetof(struct kvm_riscv_aia_csr, name) / sizeof(unsigned long)) +#define KVM_REG_RISCV_CSR_SMSTATEEN_REG(name) \ + (offsetof(struct kvm_riscv_smstateen_csr, name) / sizeof(unsigned long)) /* Timer registers are mapped as type 4 */ #define KVM_REG_RISCV_TIMER (0x04 << KVM_REG_RISCV_TYPE_SHIFT) diff --git a/linux-headers/asm-s390/unistd_32.h b/linux-headers/asm-s390/unistd_32.h index XXXXXXX..XXXXXXX 100644 --- a/linux-headers/asm-s390/unistd_32.h +++ b/linux-headers/asm-s390/unistd_32.h @@ -XXX,XX +XXX,XX @@ #define __NR_set_mempolicy_home_node 450 #define __NR_cachestat 451 #define __NR_fchmodat2 452 +#define __NR_map_shadow_stack 453 +#define __NR_futex_wake 454 +#define __NR_futex_wait 455 +#define __NR_futex_requeue 456 #endif /* _ASM_S390_UNISTD_32_H */ diff --git a/linux-headers/asm-s390/unistd_64.h b/linux-headers/asm-s390/unistd_64.h index XXXXXXX..XXXXXXX 100644 --- a/linux-headers/asm-s390/unistd_64.h +++ b/linux-headers/asm-s390/unistd_64.h @@ -XXX,XX +XXX,XX @@ #define __NR_set_mempolicy_home_node 450 #define __NR_cachestat 451 #define __NR_fchmodat2 452 +#define __NR_map_shadow_stack 453 +#define __NR_futex_wake 454 +#define __NR_futex_wait 455 +#define __NR_futex_requeue 456 #endif /* _ASM_S390_UNISTD_64_H */ diff --git a/linux-headers/asm-x86/unistd_32.h b/linux-headers/asm-x86/unistd_32.h index XXXXXXX..XXXXXXX 100644 --- a/linux-headers/asm-x86/unistd_32.h +++ b/linux-headers/asm-x86/unistd_32.h @@ -XXX,XX +XXX,XX @@ #define __NR_set_mempolicy_home_node 450 #define __NR_cachestat 451 #define __NR_fchmodat2 452 +#define __NR_map_shadow_stack 453 +#define __NR_futex_wake 454 +#define __NR_futex_wait 455 +#define __NR_futex_requeue 456 #endif /* _ASM_UNISTD_32_H */ diff --git a/linux-headers/asm-x86/unistd_64.h b/linux-headers/asm-x86/unistd_64.h index XXXXXXX..XXXXXXX 100644 --- a/linux-headers/asm-x86/unistd_64.h +++ b/linux-headers/asm-x86/unistd_64.h @@ -XXX,XX +XXX,XX @@ #define __NR_cachestat 451 #define __NR_fchmodat2 452 #define __NR_map_shadow_stack 453 +#define __NR_futex_wake 454 +#define __NR_futex_wait 455 +#define __NR_futex_requeue 456 #endif /* _ASM_UNISTD_64_H */ diff --git a/linux-headers/asm-x86/unistd_x32.h b/linux-headers/asm-x86/unistd_x32.h index XXXXXXX..XXXXXXX 100644 --- a/linux-headers/asm-x86/unistd_x32.h +++ b/linux-headers/asm-x86/unistd_x32.h @@ -XXX,XX +XXX,XX @@ #define __NR_set_mempolicy_home_node (__X32_SYSCALL_BIT + 450) #define __NR_cachestat (__X32_SYSCALL_BIT + 451) #define __NR_fchmodat2 (__X32_SYSCALL_BIT + 452) +#define __NR_futex_wake (__X32_SYSCALL_BIT + 454) +#define __NR_futex_wait (__X32_SYSCALL_BIT + 455) +#define __NR_futex_requeue (__X32_SYSCALL_BIT + 456) #define __NR_rt_sigaction (__X32_SYSCALL_BIT + 512) #define __NR_rt_sigreturn (__X32_SYSCALL_BIT + 513) #define __NR_ioctl (__X32_SYSCALL_BIT + 514) diff --git a/linux-headers/linux/iommufd.h b/linux-headers/linux/iommufd.h index XXXXXXX..XXXXXXX 100644 --- a/linux-headers/linux/iommufd.h +++ b/linux-headers/linux/iommufd.h @@ -XXX,XX +XXX,XX @@ enum { IOMMUFD_CMD_VFIO_IOAS, IOMMUFD_CMD_HWPT_ALLOC, IOMMUFD_CMD_GET_HW_INFO, + IOMMUFD_CMD_HWPT_SET_DIRTY_TRACKING, + IOMMUFD_CMD_HWPT_GET_DIRTY_BITMAP, }; /** @@ -XXX,XX +XXX,XX @@ struct iommu_vfio_ioas { }; #define IOMMU_VFIO_IOAS _IO(IOMMUFD_TYPE, IOMMUFD_CMD_VFIO_IOAS) +/** + * enum iommufd_hwpt_alloc_flags - Flags for HWPT allocation + * @IOMMU_HWPT_ALLOC_NEST_PARENT: If set, allocate a HWPT that can serve as + * the parent HWPT in a nesting configuration. + * @IOMMU_HWPT_ALLOC_DIRTY_TRACKING: Dirty tracking support for device IOMMU is + * enforced on device attachment + */ +enum iommufd_hwpt_alloc_flags { + IOMMU_HWPT_ALLOC_NEST_PARENT = 1 << 0, + IOMMU_HWPT_ALLOC_DIRTY_TRACKING = 1 << 1, +}; + +/** + * enum iommu_hwpt_vtd_s1_flags - Intel VT-d stage-1 page table + * entry attributes + * @IOMMU_VTD_S1_SRE: Supervisor request + * @IOMMU_VTD_S1_EAFE: Extended access enable + * @IOMMU_VTD_S1_WPE: Write protect enable + */ +enum iommu_hwpt_vtd_s1_flags { + IOMMU_VTD_S1_SRE = 1 << 0, + IOMMU_VTD_S1_EAFE = 1 << 1, + IOMMU_VTD_S1_WPE = 1 << 2, +}; + +/** + * struct iommu_hwpt_vtd_s1 - Intel VT-d stage-1 page table + * info (IOMMU_HWPT_DATA_VTD_S1) + * @flags: Combination of enum iommu_hwpt_vtd_s1_flags + * @pgtbl_addr: The base address of the stage-1 page table. + * @addr_width: The address width of the stage-1 page table + * @__reserved: Must be 0 + */ +struct iommu_hwpt_vtd_s1 { + __aligned_u64 flags; + __aligned_u64 pgtbl_addr; + __u32 addr_width; + __u32 __reserved; +}; + +/** + * enum iommu_hwpt_data_type - IOMMU HWPT Data Type + * @IOMMU_HWPT_DATA_NONE: no data + * @IOMMU_HWPT_DATA_VTD_S1: Intel VT-d stage-1 page table + */ +enum iommu_hwpt_data_type { + IOMMU_HWPT_DATA_NONE, + IOMMU_HWPT_DATA_VTD_S1, +}; + /** * struct iommu_hwpt_alloc - ioctl(IOMMU_HWPT_ALLOC) * @size: sizeof(struct iommu_hwpt_alloc) - * @flags: Must be 0 + * @flags: Combination of enum iommufd_hwpt_alloc_flags * @dev_id: The device to allocate this HWPT for - * @pt_id: The IOAS to connect this HWPT to + * @pt_id: The IOAS or HWPT to connect this HWPT to * @out_hwpt_id: The ID of the new HWPT * @__reserved: Must be 0 + * @data_type: One of enum iommu_hwpt_data_type + * @data_len: Length of the type specific data + * @data_uptr: User pointer to the type specific data * * Explicitly allocate a hardware page table object. This is the same object * type that is returned by iommufd_device_attach() and represents the * underlying iommu driver's iommu_domain kernel object. * - * A HWPT will be created with the IOVA mappings from the given IOAS. + * A kernel-managed HWPT will be created with the mappings from the given + * IOAS via the @pt_id. The @data_type for this allocation must be set to + * IOMMU_HWPT_DATA_NONE. The HWPT can be allocated as a parent HWPT for a + * nesting configuration by passing IOMMU_HWPT_ALLOC_NEST_PARENT via @flags. + * + * A user-managed nested HWPT will be created from a given parent HWPT via + * @pt_id, in which the parent HWPT must be allocated previously via the + * same ioctl from a given IOAS (@pt_id). In this case, the @data_type + * must be set to a pre-defined type corresponding to an I/O page table + * type supported by the underlying IOMMU hardware. + * + * If the @data_type is set to IOMMU_HWPT_DATA_NONE, @data_len and + * @data_uptr should be zero. Otherwise, both @data_len and @data_uptr + * must be given. */ struct iommu_hwpt_alloc { __u32 size; @@ -XXX,XX +XXX,XX @@ struct iommu_hwpt_alloc { __u32 pt_id; __u32 out_hwpt_id; __u32 __reserved; + __u32 data_type; + __u32 data_len; + __aligned_u64 data_uptr; }; #define IOMMU_HWPT_ALLOC _IO(IOMMUFD_TYPE, IOMMUFD_CMD_HWPT_ALLOC) +/** + * enum iommu_hw_info_vtd_flags - Flags for VT-d hw_info + * @IOMMU_HW_INFO_VTD_ERRATA_772415_SPR17: If set, disallow read-only mappings + * on a nested_parent domain. + * https://www.intel.com/content/www/us/en/content-details/772415/content-details.html + */ +enum iommu_hw_info_vtd_flags { + IOMMU_HW_INFO_VTD_ERRATA_772415_SPR17 = 1 << 0, +}; + /** * struct iommu_hw_info_vtd - Intel VT-d hardware information * - * @flags: Must be 0 + * @flags: Combination of enum iommu_hw_info_vtd_flags * @__reserved: Must be 0 * * @cap_reg: Value of Intel VT-d capability register defined in VT-d spec @@ -XXX,XX +XXX,XX @@ enum iommu_hw_info_type { IOMMU_HW_INFO_TYPE_INTEL_VTD, }; +/** + * enum iommufd_hw_capabilities + * @IOMMU_HW_CAP_DIRTY_TRACKING: IOMMU hardware support for dirty tracking + * If available, it means the following APIs + * are supported: + * + * IOMMU_HWPT_GET_DIRTY_BITMAP + * IOMMU_HWPT_SET_DIRTY_TRACKING + * + */ +enum iommufd_hw_capabilities { + IOMMU_HW_CAP_DIRTY_TRACKING = 1 << 0, +}; + /** * struct iommu_hw_info - ioctl(IOMMU_GET_HW_INFO) * @size: sizeof(struct iommu_hw_info) @@ -XXX,XX +XXX,XX @@ enum iommu_hw_info_type { * the iommu type specific hardware information data * @out_data_type: Output the iommu hardware info type as defined in the enum * iommu_hw_info_type. + * @out_capabilities: Output the generic iommu capability info type as defined + * in the enum iommu_hw_capabilities. * @__reserved: Must be 0 * * Query an iommu type specific hardware information data from an iommu behind @@ -XXX,XX +XXX,XX @@ struct iommu_hw_info { __aligned_u64 data_uptr; __u32 out_data_type; __u32 __reserved; + __aligned_u64 out_capabilities; }; #define IOMMU_GET_HW_INFO _IO(IOMMUFD_TYPE, IOMMUFD_CMD_GET_HW_INFO) + +/* + * enum iommufd_hwpt_set_dirty_tracking_flags - Flags for steering dirty + * tracking + * @IOMMU_HWPT_DIRTY_TRACKING_ENABLE: Enable dirty tracking + */ +enum iommufd_hwpt_set_dirty_tracking_flags { + IOMMU_HWPT_DIRTY_TRACKING_ENABLE = 1, +}; + +/** + * struct iommu_hwpt_set_dirty_tracking - ioctl(IOMMU_HWPT_SET_DIRTY_TRACKING) + * @size: sizeof(struct iommu_hwpt_set_dirty_tracking) + * @flags: Combination of enum iommufd_hwpt_set_dirty_tracking_flags + * @hwpt_id: HW pagetable ID that represents the IOMMU domain + * @__reserved: Must be 0 + * + * Toggle dirty tracking on an HW pagetable. + */ +struct iommu_hwpt_set_dirty_tracking { + __u32 size; + __u32 flags; + __u32 hwpt_id; + __u32 __reserved; +}; +#define IOMMU_HWPT_SET_DIRTY_TRACKING _IO(IOMMUFD_TYPE, \ + IOMMUFD_CMD_HWPT_SET_DIRTY_TRACKING) + +/** + * enum iommufd_hwpt_get_dirty_bitmap_flags - Flags for getting dirty bits + * @IOMMU_HWPT_GET_DIRTY_BITMAP_NO_CLEAR: Just read the PTEs without clearing + * any dirty bits metadata. This flag + * can be passed in the expectation + * where the next operation is an unmap + * of the same IOVA range. + * + */ +enum iommufd_hwpt_get_dirty_bitmap_flags { + IOMMU_HWPT_GET_DIRTY_BITMAP_NO_CLEAR = 1, +}; + +/** + * struct iommu_hwpt_get_dirty_bitmap - ioctl(IOMMU_HWPT_GET_DIRTY_BITMAP) + * @size: sizeof(struct iommu_hwpt_get_dirty_bitmap) + * @hwpt_id: HW pagetable ID that represents the IOMMU domain + * @flags: Combination of enum iommufd_hwpt_get_dirty_bitmap_flags + * @__reserved: Must be 0 + * @iova: base IOVA of the bitmap first bit + * @length: IOVA range size + * @page_size: page size granularity of each bit in the bitmap + * @data: bitmap where to set the dirty bits. The bitmap bits each + * represent a page_size which you deviate from an arbitrary iova. + * + * Checking a given IOVA is dirty: + * + * data[(iova / page_size) / 64] & (1ULL << ((iova / page_size) % 64)) + * + * Walk the IOMMU pagetables for a given IOVA range to return a bitmap + * with the dirty IOVAs. In doing so it will also by default clear any + * dirty bit metadata set in the IOPTE. + */ +struct iommu_hwpt_get_dirty_bitmap { + __u32 size; + __u32 hwpt_id; + __u32 flags; + __u32 __reserved; + __aligned_u64 iova; + __aligned_u64 length; + __aligned_u64 page_size; + __aligned_u64 data; +}; +#define IOMMU_HWPT_GET_DIRTY_BITMAP _IO(IOMMUFD_TYPE, \ + IOMMUFD_CMD_HWPT_GET_DIRTY_BITMAP) + #endif diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h index XXXXXXX..XXXXXXX 100644 --- a/linux-headers/linux/kvm.h +++ b/linux-headers/linux/kvm.h @@ -XXX,XX +XXX,XX @@ struct kvm_xen_exit { #define KVM_EXIT_RISCV_SBI 35 #define KVM_EXIT_RISCV_CSR 36 #define KVM_EXIT_NOTIFY 37 +#define KVM_EXIT_LOONGARCH_IOCSR 38 /* For KVM_EXIT_INTERNAL_ERROR */ /* Emulate instruction failed. */ @@ -XXX,XX +XXX,XX @@ struct kvm_run { __u32 len; __u8 is_write; } mmio; + /* KVM_EXIT_LOONGARCH_IOCSR */ + struct { + __u64 phys_addr; + __u8 data[8]; + __u32 len; + __u8 is_write; + } iocsr_io; /* KVM_EXIT_HYPERCALL */ struct { __u64 nr; @@ -XXX,XX +XXX,XX @@ struct kvm_ppc_resize_hpt { #define KVM_CAP_COUNTER_OFFSET 227 #define KVM_CAP_ARM_EAGER_SPLIT_CHUNK_SIZE 228 #define KVM_CAP_ARM_SUPPORTED_BLOCK_SIZES 229 +#define KVM_CAP_ARM_SUPPORTED_REG_MASK_RANGES 230 #ifdef KVM_CAP_IRQ_ROUTING @@ -XXX,XX +XXX,XX @@ struct kvm_dirty_tlb { #define KVM_REG_ARM64 0x6000000000000000ULL #define KVM_REG_MIPS 0x7000000000000000ULL #define KVM_REG_RISCV 0x8000000000000000ULL +#define KVM_REG_LOONGARCH 0x9000000000000000ULL #define KVM_REG_SIZE_SHIFT 52 #define KVM_REG_SIZE_MASK 0x00f0000000000000ULL @@ -XXX,XX +XXX,XX @@ struct kvm_s390_ucas_mapping { #define KVM_ARM_MTE_COPY_TAGS _IOR(KVMIO, 0xb4, struct kvm_arm_copy_mte_tags) /* Available with KVM_CAP_COUNTER_OFFSET */ #define KVM_ARM_SET_COUNTER_OFFSET _IOW(KVMIO, 0xb5, struct kvm_arm_counter_offset) +#define KVM_ARM_GET_REG_WRITABLE_MASKS _IOR(KVMIO, 0xb6, struct reg_mask_range) /* ioctl for vm fd */ #define KVM_CREATE_DEVICE _IOWR(KVMIO, 0xe0, struct kvm_create_device) diff --git a/linux-headers/linux/psp-sev.h b/linux-headers/linux/psp-sev.h index XXXXXXX..XXXXXXX 100644 --- a/linux-headers/linux/psp-sev.h +++ b/linux-headers/linux/psp-sev.h @@ -XXX,XX +XXX,XX @@ typedef enum { SEV_RET_INVALID_PARAM, SEV_RET_RESOURCE_LIMIT, SEV_RET_SECURE_DATA_INVALID, + SEV_RET_INVALID_KEY = 0x27, SEV_RET_MAX, } sev_ret_code; diff --git a/linux-headers/linux/stddef.h b/linux-headers/linux/stddef.h index XXXXXXX..XXXXXXX 100644 --- a/linux-headers/linux/stddef.h +++ b/linux-headers/linux/stddef.h @@ -XXX,XX +XXX,XX @@ union { \ struct { MEMBERS } ATTRS; \ struct TAG { MEMBERS } ATTRS NAME; \ - } + } ATTRS +#ifdef __cplusplus +/* sizeof(struct{}) is 1 in C++, not 0, can't use C version of the macro. */ +#define __DECLARE_FLEX_ARRAY(T, member) \ + T member[0] +#else /** * __DECLARE_FLEX_ARRAY() - Declare a flexible array usable in a union * @@ -XXX,XX +XXX,XX @@ #ifndef __counted_by #define __counted_by(m) #endif + +#endif /* _LINUX_STDDEF_H */ diff --git a/linux-headers/linux/userfaultfd.h b/linux-headers/linux/userfaultfd.h index XXXXXXX..XXXXXXX 100644 --- a/linux-headers/linux/userfaultfd.h +++ b/linux-headers/linux/userfaultfd.h @@ -XXX,XX +XXX,XX @@ UFFD_FEATURE_EXACT_ADDRESS | \ UFFD_FEATURE_WP_HUGETLBFS_SHMEM | \ UFFD_FEATURE_WP_UNPOPULATED | \ - UFFD_FEATURE_POISON) + UFFD_FEATURE_POISON | \ + UFFD_FEATURE_WP_ASYNC) #define UFFD_API_IOCTLS \ ((__u64)1 << _UFFDIO_REGISTER | \ (__u64)1 << _UFFDIO_UNREGISTER | \ @@ -XXX,XX +XXX,XX @@ struct uffdio_api { * (i.e. empty ptes). This will be the default behavior for shmem * & hugetlbfs, so this flag only affects anonymous memory behavior * when userfault write-protection mode is registered. + * + * UFFD_FEATURE_WP_ASYNC indicates that userfaultfd write-protection + * asynchronous mode is supported in which the write fault is + * automatically resolved and write-protection is un-set. + * It implies UFFD_FEATURE_WP_UNPOPULATED. */ #define UFFD_FEATURE_PAGEFAULT_FLAG_WP (1<<0) #define UFFD_FEATURE_EVENT_FORK (1<<1) @@ -XXX,XX +XXX,XX @@ struct uffdio_api { #define UFFD_FEATURE_WP_HUGETLBFS_SHMEM (1<<12) #define UFFD_FEATURE_WP_UNPOPULATED (1<<13) #define UFFD_FEATURE_POISON (1<<14) +#define UFFD_FEATURE_WP_ASYNC (1<<15) __u64 features; __u64 ioctls; diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h index XXXXXXX..XXXXXXX 100644 --- a/linux-headers/linux/vfio.h +++ b/linux-headers/linux/vfio.h @@ -XXX,XX +XXX,XX @@ struct vfio_region_info { #define VFIO_REGION_INFO_FLAG_CAPS (1 << 3) /* Info supports caps */ __u32 index; /* Region index */ __u32 cap_offset; /* Offset within info struct of first cap */ - __u64 size; /* Region size (bytes) */ - __u64 offset; /* Region offset from start of device fd */ + __aligned_u64 size; /* Region size (bytes) */ + __aligned_u64 offset; /* Region offset from start of device fd */ }; #define VFIO_DEVICE_GET_REGION_INFO _IO(VFIO_TYPE, VFIO_BASE + 8) @@ -XXX,XX +XXX,XX @@ struct vfio_region_info { #define VFIO_REGION_INFO_CAP_SPARSE_MMAP 1 struct vfio_region_sparse_mmap_area { - __u64 offset; /* Offset of mmap'able area within region */ - __u64 size; /* Size of mmap'able area */ + __aligned_u64 offset; /* Offset of mmap'able area within region */ + __aligned_u64 size; /* Size of mmap'able area */ }; struct vfio_region_info_cap_sparse_mmap { @@ -XXX,XX +XXX,XX @@ struct vfio_device_migration_info { VFIO_DEVICE_STATE_V1_RESUMING) __u32 reserved; - __u64 pending_bytes; - __u64 data_offset; - __u64 data_size; + __aligned_u64 pending_bytes; + __aligned_u64 data_offset; + __aligned_u64 data_size; }; /* @@ -XXX,XX +XXX,XX @@ struct vfio_device_migration_info { struct vfio_region_info_cap_nvlink2_ssatgt { struct vfio_info_cap_header header; - __u64 tgt; + __aligned_u64 tgt; }; /* @@ -XXX,XX +XXX,XX @@ struct vfio_device_gfx_plane_info { __u32 drm_plane_type; /* type of plane: DRM_PLANE_TYPE_* */ /* out */ __u32 drm_format; /* drm format of plane */ - __u64 drm_format_mod; /* tiled mode */ + __aligned_u64 drm_format_mod; /* tiled mode */ __u32 width; /* width of plane */ __u32 height; /* height of plane */ __u32 stride; /* stride of plane */ @@ -XXX,XX +XXX,XX @@ struct vfio_device_gfx_plane_info { __u32 region_index; /* region index */ __u32 dmabuf_id; /* dma-buf id */ }; + __u32 reserved; }; #define VFIO_DEVICE_QUERY_GFX_PLANE _IO(VFIO_TYPE, VFIO_BASE + 14) @@ -XXX,XX +XXX,XX @@ struct vfio_device_ioeventfd { #define VFIO_DEVICE_IOEVENTFD_32 (1 << 2) /* 4-byte write */ #define VFIO_DEVICE_IOEVENTFD_64 (1 << 3) /* 8-byte write */ #define VFIO_DEVICE_IOEVENTFD_SIZE_MASK (0xf) - __u64 offset; /* device fd offset of write */ - __u64 data; /* data to be written */ + __aligned_u64 offset; /* device fd offset of write */ + __aligned_u64 data; /* data to be written */ __s32 fd; /* -1 for de-assignment */ + __u32 reserved; }; #define VFIO_DEVICE_IOEVENTFD _IO(VFIO_TYPE, VFIO_BASE + 16) @@ -XXX,XX +XXX,XX @@ struct vfio_device_feature_mig_data_size { #define VFIO_DEVICE_FEATURE_MIG_DATA_SIZE 9 +/** + * Upon VFIO_DEVICE_FEATURE_SET, set or clear the BUS mastering for the device + * based on the operation specified in op flag. + * + * The functionality is incorporated for devices that needs bus master control, + * but the in-band device interface lacks the support. Consequently, it is not + * applicable to PCI devices, as bus master control for PCI devices is managed + * in-band through the configuration space. At present, this feature is supported + * only for CDX devices. + * When the device's BUS MASTER setting is configured as CLEAR, it will result in + * blocking all incoming DMA requests from the device. On the other hand, configuring + * the device's BUS MASTER setting as SET (enable) will grant the device the + * capability to perform DMA to the host memory. + */ +struct vfio_device_feature_bus_master { + __u32 op; +#define VFIO_DEVICE_FEATURE_CLEAR_MASTER 0 /* Clear Bus Master */ +#define VFIO_DEVICE_FEATURE_SET_MASTER 1 /* Set Bus Master */ +}; +#define VFIO_DEVICE_FEATURE_BUS_MASTER 10 + /* -------- API for Type1 VFIO IOMMU -------- */ /** @@ -XXX,XX +XXX,XX @@ struct vfio_iommu_type1_info { __u32 flags; #define VFIO_IOMMU_INFO_PGSIZES (1 << 0) /* supported page sizes info */ #define VFIO_IOMMU_INFO_CAPS (1 << 1) /* Info supports caps */ - __u64 iova_pgsizes; /* Bitmap of supported page sizes */ + __aligned_u64 iova_pgsizes; /* Bitmap of supported page sizes */ __u32 cap_offset; /* Offset within info struct of first cap */ __u32 pad; }; diff --git a/linux-headers/linux/vhost.h b/linux-headers/linux/vhost.h index XXXXXXX..XXXXXXX 100644 --- a/linux-headers/linux/vhost.h +++ b/linux-headers/linux/vhost.h @@ -XXX,XX +XXX,XX @@ */ #define VHOST_VDPA_RESUME _IO(VHOST_VIRTIO, 0x7E) +/* Get the group for the descriptor table including driver & device areas + * of a virtqueue: read index, write group in num. + * The virtqueue index is stored in the index field of vhost_vring_state. + * The group ID of the descriptor table for this specific virtqueue + * is returned via num field of vhost_vring_state. + */ +#define VHOST_VDPA_GET_VRING_DESC_GROUP _IOWR(VHOST_VIRTIO, 0x7F, \ + struct vhost_vring_state) #endif -- 2.43.0
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> KVM vector support for RISC-V requires the linux-header ptrace.h. Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20231218204321.75757-3-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- linux-headers/asm-riscv/ptrace.h | 132 +++++++++++++++++++++++++++++++ scripts/update-linux-headers.sh | 3 + 2 files changed, 135 insertions(+) create mode 100644 linux-headers/asm-riscv/ptrace.h diff --git a/linux-headers/asm-riscv/ptrace.h b/linux-headers/asm-riscv/ptrace.h new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/linux-headers/asm-riscv/ptrace.h @@ -XXX,XX +XXX,XX @@ +/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ +/* + * Copyright (C) 2012 Regents of the University of California + */ + +#ifndef _ASM_RISCV_PTRACE_H +#define _ASM_RISCV_PTRACE_H + +#ifndef __ASSEMBLY__ + +#include <linux/types.h> + +#define PTRACE_GETFDPIC 33 + +#define PTRACE_GETFDPIC_EXEC 0 +#define PTRACE_GETFDPIC_INTERP 1 + +/* + * User-mode register state for core dumps, ptrace, sigcontext + * + * This decouples struct pt_regs from the userspace ABI. + * struct user_regs_struct must form a prefix of struct pt_regs. + */ +struct user_regs_struct { + unsigned long pc; + unsigned long ra; + unsigned long sp; + unsigned long gp; + unsigned long tp; + unsigned long t0; + unsigned long t1; + unsigned long t2; + unsigned long s0; + unsigned long s1; + unsigned long a0; + unsigned long a1; + unsigned long a2; + unsigned long a3; + unsigned long a4; + unsigned long a5; + unsigned long a6; + unsigned long a7; + unsigned long s2; + unsigned long s3; + unsigned long s4; + unsigned long s5; + unsigned long s6; + unsigned long s7; + unsigned long s8; + unsigned long s9; + unsigned long s10; + unsigned long s11; + unsigned long t3; + unsigned long t4; + unsigned long t5; + unsigned long t6; +}; + +struct __riscv_f_ext_state { + __u32 f[32]; + __u32 fcsr; +}; + +struct __riscv_d_ext_state { + __u64 f[32]; + __u32 fcsr; +}; + +struct __riscv_q_ext_state { + __u64 f[64] __attribute__((aligned(16))); + __u32 fcsr; + /* + * Reserved for expansion of sigcontext structure. Currently zeroed + * upon signal, and must be zero upon sigreturn. + */ + __u32 reserved[3]; +}; + +struct __riscv_ctx_hdr { + __u32 magic; + __u32 size; +}; + +struct __riscv_extra_ext_header { + __u32 __padding[129] __attribute__((aligned(16))); + /* + * Reserved for expansion of sigcontext structure. Currently zeroed + * upon signal, and must be zero upon sigreturn. + */ + __u32 reserved; + struct __riscv_ctx_hdr hdr; +}; + +union __riscv_fp_state { + struct __riscv_f_ext_state f; + struct __riscv_d_ext_state d; + struct __riscv_q_ext_state q; +}; + +struct __riscv_v_ext_state { + unsigned long vstart; + unsigned long vl; + unsigned long vtype; + unsigned long vcsr; + unsigned long vlenb; + void *datap; + /* + * In signal handler, datap will be set a correct user stack offset + * and vector registers will be copied to the address of datap + * pointer. + */ +}; + +struct __riscv_v_regset_state { + unsigned long vstart; + unsigned long vl; + unsigned long vtype; + unsigned long vcsr; + unsigned long vlenb; + char vreg[]; +}; + +/* + * According to spec: The number of bits in a single vector register, + * VLEN >= ELEN, which must be a power of 2, and must be no greater than + * 2^16 = 65536bits = 8192bytes + */ +#define RISCV_MAX_VLENB (8192) + +#endif /* __ASSEMBLY__ */ + +#endif /* _ASM_RISCV_PTRACE_H */ diff --git a/scripts/update-linux-headers.sh b/scripts/update-linux-headers.sh index XXXXXXX..XXXXXXX 100755 --- a/scripts/update-linux-headers.sh +++ b/scripts/update-linux-headers.sh @@ -XXX,XX +XXX,XX @@ for arch in $ARCHLIST; do cp_portable "$tmpdir/bootparam.h" \ "$output/include/standard-headers/asm-$arch" fi + if [ $arch = riscv ]; then + cp "$tmpdir/include/asm/ptrace.h" "$output/linux-headers/asm-riscv/" + fi done rm -rf "$output/linux-headers/linux" -- 2.43.0
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Linux RISC-V vector documentation (Document/arch/riscv/vector.rst) mandates a prctl() in order to allow an userspace thread to use the Vector extension from the host. This is something to be done in realize() time, after init(), when we already decided whether we're using RVV or not. We don't have a realize() callback for KVM yet, so add kvm_cpu_realize() and enable RVV for the thread via PR_RISCV_V_SET_CONTROL. Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20231218204321.75757-4-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/kvm/kvm-cpu.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 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 @@ #include "qemu/osdep.h" #include <sys/ioctl.h> +#include <sys/prctl.h> #include <linux/kvm.h> @@ -XXX,XX +XXX,XX @@ #include "sysemu/runstate.h" #include "hw/riscv/numa.h" +#define PR_RISCV_V_SET_CONTROL 69 +#define PR_RISCV_V_VSTATE_CTRL_ON 2 + void riscv_kvm_aplic_request(void *opaque, int irq, int level) { kvm_set_irq(kvm_state, irq, !!level); @@ -XXX,XX +XXX,XX @@ static void kvm_cpu_instance_init(CPUState *cs) } } +/* + * We'll get here via the following path: + * + * riscv_cpu_realize() + * -> cpu_exec_realizefn() + * -> kvm_cpu_realize() (via accel_cpu_common_realize()) + */ +static bool kvm_cpu_realize(CPUState *cs, Error **errp) +{ + RISCVCPU *cpu = RISCV_CPU(cs); + int ret; + + if (riscv_has_ext(&cpu->env, RVV)) { + ret = prctl(PR_RISCV_V_SET_CONTROL, PR_RISCV_V_VSTATE_CTRL_ON); + if (ret) { + error_setg(errp, "Error in prctl PR_RISCV_V_SET_CONTROL, code: %s", + strerrorname_np(errno)); + return false; + } + } + + return true; +} + static void kvm_cpu_accel_class_init(ObjectClass *oc, void *data) { AccelCPUClass *acc = ACCEL_CPU_CLASS(oc); acc->cpu_instance_init = kvm_cpu_instance_init; + acc->cpu_target_realize = kvm_cpu_realize; } static const TypeInfo kvm_cpu_accel_type_info = { -- 2.43.0
From: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Add support for RVV and Vector CSR KVM regs vstart, vl and vtype. Support for vregs[] requires KVM side changes and an extra reg (vlenb) and will be added later. Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20231218204321.75757-5-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/kvm/kvm-cpu.c | 74 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 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 uint64_t kvm_riscv_reg_id_u64(uint64_t type, uint64_t idx) #define RISCV_FP_D_REG(idx) kvm_riscv_reg_id_u64(KVM_REG_RISCV_FP_D, idx) +#define RISCV_VECTOR_CSR_REG(env, name) \ + kvm_riscv_reg_id_ulong(env, KVM_REG_RISCV_VECTOR, \ + KVM_REG_RISCV_VECTOR_CSR_REG(name)) + #define KVM_RISCV_GET_CSR(cs, env, csr, reg) \ do { \ int _ret = kvm_get_one_reg(cs, RISCV_CSR_REG(env, csr), ®); \ @@ -XXX,XX +XXX,XX @@ static KVMCPUConfig kvm_misa_ext_cfgs[] = { KVM_MISA_CFG(RVH, KVM_RISCV_ISA_EXT_H), KVM_MISA_CFG(RVI, KVM_RISCV_ISA_EXT_I), KVM_MISA_CFG(RVM, KVM_RISCV_ISA_EXT_M), + KVM_MISA_CFG(RVV, KVM_RISCV_ISA_EXT_V), }; static void kvm_cpu_get_misa_ext_cfg(Object *obj, Visitor *v, @@ -XXX,XX +XXX,XX @@ static void kvm_riscv_put_regs_timer(CPUState *cs) env->kvm_timer_dirty = false; } +static int kvm_riscv_get_regs_vector(CPUState *cs) +{ + CPURISCVState *env = &RISCV_CPU(cs)->env; + target_ulong reg; + int ret = 0; + + if (!riscv_has_ext(env, RVV)) { + return 0; + } + + ret = kvm_get_one_reg(cs, RISCV_VECTOR_CSR_REG(env, vstart), ®); + if (ret) { + return ret; + } + env->vstart = reg; + + ret = kvm_get_one_reg(cs, RISCV_VECTOR_CSR_REG(env, vl), ®); + if (ret) { + return ret; + } + env->vl = reg; + + ret = kvm_get_one_reg(cs, RISCV_VECTOR_CSR_REG(env, vtype), ®); + if (ret) { + return ret; + } + env->vtype = reg; + + return 0; +} + +static int kvm_riscv_put_regs_vector(CPUState *cs) +{ + CPURISCVState *env = &RISCV_CPU(cs)->env; + target_ulong reg; + int ret = 0; + + if (!riscv_has_ext(env, RVV)) { + return 0; + } + + reg = env->vstart; + ret = kvm_set_one_reg(cs, RISCV_VECTOR_CSR_REG(env, vstart), ®); + if (ret) { + return ret; + } + + reg = env->vl; + ret = kvm_set_one_reg(cs, RISCV_VECTOR_CSR_REG(env, vl), ®); + if (ret) { + return ret; + } + + reg = env->vtype; + ret = kvm_set_one_reg(cs, RISCV_VECTOR_CSR_REG(env, vtype), ®); + + return ret; +} + typedef struct KVMScratchCPU { int kvmfd; int vmfd; @@ -XXX,XX +XXX,XX @@ int kvm_arch_get_registers(CPUState *cs) return ret; } + ret = kvm_riscv_get_regs_vector(cs); + if (ret) { + return ret; + } + return ret; } @@ -XXX,XX +XXX,XX @@ int kvm_arch_put_registers(CPUState *cs, int level) return ret; } + ret = kvm_riscv_put_regs_vector(cs); + if (ret) { + return ret; + } + if (KVM_PUT_RESET_STATE == level) { RISCVCPU *cpu = RISCV_CPU(cs); if (cs->cpu_index == 0) { -- 2.43.0
From: Bin Meng <bmeng@tinylab.org> Currently, the documentation outlines the process for building the S-mode U-Boot image using `make menuconfig` and manual actions within the menuconfig UI. However, this approach is fragile due to Kconfig options potentially changing across different releases. For example, CONFIG_OF_PRIOR_STAGE has been replaced by CONFIG_BOARD since v2022.01 release, and CONFIG_TEXT_BASE has been moved to the 'General setup' menu from the 'Boot options' menu in v2024.01 release. This update aims to make the S-mode U-Boot image build instructions future-proof. It leverages the 'config' script provided in the U-Boot source tree to edit the .config file, followed by a `make olddefconfig`. Validated with U-Boot v2024.01 release. Signed-off-by: Bin Meng <bmeng@tinylab.org> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20240104071523.273702-1-bmeng@tinylab.org> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- docs/system/riscv/sifive_u.rst | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/docs/system/riscv/sifive_u.rst b/docs/system/riscv/sifive_u.rst index XXXXXXX..XXXXXXX 100644 --- a/docs/system/riscv/sifive_u.rst +++ b/docs/system/riscv/sifive_u.rst @@ -XXX,XX +XXX,XX @@ command line options with ``qemu-system-riscv32``. Running U-Boot -------------- -U-Boot mainline v2021.07 release is tested at the time of writing. To build a +U-Boot mainline v2024.01 release is tested at the time of writing. To build a U-Boot mainline bootloader that can be booted by the ``sifive_u`` machine, use the sifive_unleashed_defconfig with similar commands as described above for Linux: @@ -XXX,XX +XXX,XX @@ configuration of U-Boot: $ export CROSS_COMPILE=riscv64-linux- $ make sifive_unleashed_defconfig - $ make menuconfig - -then manually select the following configuration: - - * Device Tree Control ---> Provider of DTB for DT Control ---> Prior Stage bootloader DTB - -and unselect the following configuration: - - * Library routines ---> Allow access to binman information in the device tree + $ ./scripts/config --enable OF_BOARD + $ ./scripts/config --disable BINMAN_FDT + $ ./scripts/config --disable SPL + $ make olddefconfig This changes U-Boot to use the QEMU generated device tree blob, and bypass running the U-Boot SPL stage. @@ -XXX,XX +XXX,XX @@ It's possible to create a 32-bit U-Boot S-mode image as well. $ export CROSS_COMPILE=riscv64-linux- $ make sifive_unleashed_defconfig - $ make menuconfig - -then manually update the following configuration in U-Boot: - - * Device Tree Control ---> Provider of DTB for DT Control ---> Prior Stage bootloader DTB - * RISC-V architecture ---> Base ISA ---> RV32I - * Boot options ---> Boot images ---> Text Base ---> 0x80400000 - -and unselect the following configuration: - - * Library routines ---> Allow access to binman information in the device tree + $ ./scripts/config --disable ARCH_RV64I + $ ./scripts/config --enable ARCH_RV32I + $ ./scripts/config --set-val TEXT_BASE 0x80400000 + $ ./scripts/config --enable OF_BOARD + $ ./scripts/config --disable BINMAN_FDT + $ ./scripts/config --disable SPL + $ make olddefconfig Use the same command line options to boot the 32-bit U-Boot S-mode image: -- 2.43.0
From: Bin Meng <bmeng@tinylab.org> Upgrade OpenSBI from v1.3.1 to v1.4 and the pre-built bios images. The v1.4 release includes the following commits: 1a398d9 lib: sbi: Add Zicntr as a HART ISA extension 669089c lib: sbi: Add Zihpm as a HART ISA extension 72b9c8f lib: sbi: Alphabetically sort HART ISA extensions 5359fc6 lib: sbi: Rename hart_pmu_get_allowed_bits() function 976895c lib: sbi: Fix Priv spec version for [m|s]counteren and mcountinhibit CSRs 6053917 lib: sbi: Fix how print gets flags 35ef182 lib: sbi: print not fill '0' when left-aligned 40dac06 lib: sbi: Add '+' flags for print 458fa74 lib: sbi: Add ' ' '\'' flags for print 05cbb6e lib: sbi: implifying the parameters of printi fe08281 lib: sbi: print add 'o' type c6ee5ae lib: sbi: Fix printi 3b6fcdd lib: sbi: Simplify prints cc89fa7 lib: sbi: Fix printc ff43168 lib: sbi: Fix timing of clearing tbuf a73982d lib: sbi: Fix missing '\0' when buffer szie equal 1 ea6533a lib: utils/gpio: Fix RV32 compile error for designware GPIO driver c3b98c6 include: sbi: Add macro definitions for mseccfg CSR 1c099c4 lib: sbi: Add functions to manipulate PMP entries 6c202c5 include: sbi: Add Smepmp specific access flags for PMP entries cbcfc7b lib: sbi: Add smepmp in hart extensions d72f5f1 lib: utils: Add detection of Smepmp from ISA string in FDT 4a42a23 lib: sbi: Grant SU R/W/X permissions to whole memory f3fdd04 lib: sbi: Change the order of PMP initialization 5dd8db5 lib: sbi: Add support for Smepmp 6e44ef6 lib: sbi: Add functions to map/unmap shared memory 0ad8660 lib: sbi: Map/Unmap debug console shared memory buffers 057eb10 lib: utils/gpio: Fix RV32 compile error for designware GPIO driver 0e2111e libfdt: fix SPDX license identifiers e05a9cf lib: sbi: Update system suspend to spec 5e20d25 include: sbi: fix CSR define of mseccfg 44c5151 include: sbi_utils: Remove driver pointer from struct i2c_adapter 14a35b0 lib: utils/regmap: Add generic regmap access library 8e97275 lib: utils/regmap: Add simple FDT based regmap framework f21d8f7 lib: utils/regmap: Add simple FDT based syscon regmap driver 4a344a9 lib: utils/reset: Add syscon based reboot and poweroff c2e6027 lib: utils/reset: Remove SiFive Test reset driver f536e0b gitignore: allow gitignore to ignore most dot file c744ed7 lib: sbi_pmu: Enable noncontigous hpm event and counters 6259b2e lib: utils/fdt: Fix fdt_parse_isa_extensions() implementation f46a564 lib: sbi: Fix typo for finding fixed event counter 94197a8 fw_base.S: Fix assembler error with clang 16+ c104c60 lib: sbi: Add support for smcntrpmf 7aabeee Makefile: Fix grep warning e7e73aa platform: generic: allwinner: correct mhpmevent count ee1f83c lib: sbi_pmu: remove mhpm_count field in hart feature a9cffd6 firmware: payload: test: Change to SBI v2.0 DBCN ecalls b20bd47 lib: sbi: improve the definition of SBI_IPI_EVENT_MAX 664692f lib: sbi_pmu: ensure update hpm counter before starting counting c9a296d platform: generic: allwinner: fix OF process for T-HEAD c9xx pmu 901d3d7 lib: sbi_pmu: keep overflow interrupt of stopped hpm counter disabled cacfba3 platform: Allow platforms to specify the size of tlb fifo 5bd9694 lib: sbi: alloc tlb fifo by sbi_malloc 130e65d lib: sbi: Implement SET_FS_DIRTY() to make sure the mstatus FS dirty is set d1e4dff lib: sbi: Introduce HART index in sbi_scratch e6125c3 lib: sbi: Remove sbi_platform_hart_index/invalid() functions 296e70d lib: sbi: Extend sbi_hartmask to support both hartid and hartindex e632cd7 lib: sbi: Use sbi_scratch_last_hartindex() in remote TLB managment 78c667b lib: sbi: Prefer hartindex over hartid in IPI framework 22d6ff8 lib: sbi: Remove sbi_scratch_last_hartid() macro 112daa2 lib: sbi: Maximize the use of HART index in sbi_domain 9560fb3 include: sbi: Remove sbi_hartmask_for_each_hart() macro b8fb96e include: sbi_domain: Fix permission test macros bff27c1 lib: sbi: Factor-out Smepmp configuration as separate function 5240d31 lib: sbi: Don't clear mseccfg.MML bit in sbi_hart_smepmp_configure() 2b51a9d lib: sbi: Fix pmp_flags for Smepmp read-only shared region 73aea28 lib: sbi: Populate M-only Smepmp entries before setting mseccfg.MML e8bc162 lib: utils/serial: Add shared regions for serial drivers b7e9d34 lib: utils/regmap: Mark syscon region as shared read-write 3669153 platform: generic: thead: fix stale TLB entries for th1520/sg2042 de525ac firmware: Remove ALIGN in .rela.dyn in linker script 2a6d725 firmware: Remove handling of R_RISCV_{32,64} 6ed125a Makefile: Add --exclude-libs ALL to avoid .dynsym e21901d doc: Fix fw_payload.md a125423 lib: utils/serial: Ensure proper allocation of PMP entries for uart8250 d36709f lib: utils: timer/ipi: Update memregion flags for PLMT and PLICSW 8197c2f lib: sbi: fix sbi_domain_get_assigned_hartmask() 9da30f6 lib: utils/fdt: simplify dt_parse_isa_extensions 942aca2 lib: utils: Simplify SET_ISA_EXT_MAP() f831b93 lib: sbi_pmu: check for index overflows d891cae gpio/starfive: redundant readl() call e8114c6 docs: platform: update platform_requirements.md 3632f2b lib: sbi: Add support for mconfigptr ec0559e lib: sbi_misaligned_ldst: Fix handling of C.SWSP and C.SDSP cbdd869 include: sbi: Change spec version to 2.0 5d0ed1b lib: sbi: simplify sanitize_domain() c1a6987 platform: generic: thead: move to thead c9xx header to vendor specific postion 8e941e7 platform: generic: thead: separate implement of T-HEAD c9xx pmu 492d9b1 platform: generic: thead: separate implement of T-HEAD c9xx errata 3e21b96 platform: generic: thead: initialize PMU by default in thead generic platform a140a4e lib: sbi: Correctly limit flushes to a single ASID/VMID 88ae718 platform: generic: thead: improve tlb flush errata 52fd64b platform: Uses hart count as the default size of tlb info 07f2ccd lib: utils/serial: Optimize semihosting_putc implementation fccdf41 firmware: fw_base.S: Fix boot hart status synchronization d1e0f7f utils/reset: Remove fdt_reset_thead 896d2c9 lib: utils/timer: Allow ACLINT MTIMER driver to setup quirks accafb1 lib: utils/timer: mtimer: add separate T-Head C9xx CLINT mtimer compatible 98bc25f lib: utils/ipi: mswi: add separate T-Head C9xx CLINT mswi compatible 5b2f55d lib: sbi: separate the swap operation of domain region 3b03cdd lib: sbi: Add regions merging when sanitizing domain region 2bfdb9e platform: generic: Add Sophgo sg2042 platform support 280f7ae include: sbi: macros for mseccfg.sseed and .useed efcac33 lib: sbi: Add Zkr in hart extensions 6e5b0cf lib: sbi: enable seed access in S-mode 6602e11 lib: sbi: change sbi_hart_features.extensions as an array 3aaed4f lib: sbi: Make console_puts/console_putc interchangeable dc0bb19 lib: utils/serial: remove semihosting_putc 16bb930 lib: sbi: Fix PMP granularity handling in sbi_hart_map_saddr() 574b9c8 lib: sbi_pmu: avoid buffer overflow 791704c lib: utils/irqchip: Avoid redundant writes to APLIC CLRIE register f520256 lib: sbi: Allow relaxed MMIO writes in device ipi_send() callback b70d628 lib: sbi: Allow relaxed MMIO writes in device ipi_clear() callback bd74931 lib: ipi: Adjust Andes PLICSW to single-bit-per-hart scheme 291403f sbi: sbi_pmu: Improve sbi_pmu_init() error handling 090fa99 lib: sbi: Add XAndesPMU in hart extensions a48f2cf sbi: sbi_pmu: Add hw_counter_filter_mode() to pmu device 51ec60c platform: include: andes45: Add PMU related CSR defines effd89a platform: generic: Introduce pmu_init() platform override 1b9e743 platform: andes: Add Andes custom PMU support 2e50c24 platform: andes: Enable Andes PMU for AE350 535c661 platform: rzfive: Enable Andes PMU for RZ/Five 0b3262e lib: utils: fdt_fixup: Allow preserving PMU properties 009ae4e platform: andes: Factor out is_andes() helper 0308f93 lib: utils: fdt_pmu: Make the fdt_pmu_evt_select table global variable e19d419 lib: utils: fdt_pmu: Do not iterate over the fdt_pmu_evt_select table d162009 docs: pmu: Add Andes PMU node example 6b9a849 lib: sbi: Remove xchg/cmpxchg implemented via lr/sc 11bf49b lib: sbi: Fix __atomic_op_bit_ord and comments 8839869 lib: sbi: Replace __atomic_op_bit_ord with __atomic intrinsics 07419ec lib: sbi: Prevent redundant sbi_ipi_process 93da66b lib: sbi_hart: Store PMP granularity as log base 2 ee72517 lib: sbi_pmu: Add PMU snapshot definitions 11a0ba5 lib: sbi_pmu: Fix the counter info function 0696810 firmware: fix section types a25fc74 lib: sbi_hsm: Put the resume_pending hart in the interruptible hart mask 87aa306 platform: recalculate heap size to support new tlb entry number a2e254e lib: sbi: skip wait_for_coldboot when coolboot done 6112d58 lib: utils/fdt: Allow to use reg-names when parsing ACLINT 35cba92 lib: sbi_tlb: Check tlb_range_flush_limit only once per request a894187 lib: sbi_ipi: Do not ignore errors from sbi_ipi_send() 446fa65 lib: sbi_ipi: Process self-IPIs in sbi_ipi_send() 2707250 lib: sbi_ipi: Drop unnecessary ipi_process check 925ce14 lib: sbi: Simplify the initialization of root_hmask in sbi_domain_init 2c8be56 lib: sbi: Improve the code of privilege mode and extensions detection 056fe6f lib: sbi: Refactor the code for enable extensions in menvfg CSR 776770d lib: sbi: Using one array to define the name of extensions 3daac8f lib: sbi: Detect extensions from the ISA string in DT 416ceb3 lib: sbi_tlb: Reduce size of struct sbi_tlb_info 80169b2 platform: generic: Fine tune fw_platform_calculate_heap_size() cdebae2 lib: utils/irqchip: Add shared MMIO region for PLIC in root domain 3284bea lib: sbi: Allow ecall handlers to directly update register state 5a57e8c lib: sbi: Remove the SBI_ETRAP error code 2b80b92 lib: sbi: Do not enter OpenSBI with mseccfg.MML == 1 63e09ad lib: sbi: Fix shift bug in sbi_system_reset ba29293 lib: utils/timer: mtimer: only use regname for aclint bbd065d lib: sbi: Detect Zicntr extension only based on traps a2b255b include: Bump-up version to 1.4 Signed-off-by: Bin Meng <bmeng@tinylab.org> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-Id: <20240102151153.133896-1-bmeng@tinylab.org> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- .../opensbi-riscv32-generic-fw_dynamic.bin | Bin 135376 -> 267416 bytes .../opensbi-riscv64-generic-fw_dynamic.bin | Bin 138368 -> 270808 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 057eb10b6d523540012e6947d5c9f63e95244e94 +Subproject commit a2b255b88918715173942f2c5e1f97ac9e90c877 -- 2.43.0
From: Ivan Klokov <ivan.klokov@syntacore.com> This patch changes behavior on writing RW=01 to pmpcfg with MML=0. RWX filed is form of collective WARL with the combination of pmpcfg.RW=01 remains reserved for future standard use. According to definition of WARL writing the CSR has no other side effect. But current implementation change architectural state and change system behavior. After writing we will get unreadable-unwriteble region regardless on the previous state. On the other side WARL said that we should read legal value and nothing says about what we should write. Current behavior change system state regardless of whether we read this register or not. Fixes: ac66f2f0 ("target/riscv: pmp: Ignore writes when RW=01") Signed-off-by: Ivan Klokov <ivan.klokov@syntacore.com> Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20231220153205.11072-1-ivan.klokov@syntacore.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/pmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 bool pmp_write_cfg(CPURISCVState *env, uint32_t pmp_index, uint8_t val) /* If !mseccfg.MML then ignore writes with encoding RW=01 */ if ((val & PMP_WRITE) && !(val & PMP_READ) && !MSECCFG_MML_ISSET(env)) { - val &= ~(PMP_WRITE | PMP_READ); + return false; } env->pmp_state.pmp[pmp_index].cfg_reg = val; pmp_update_rule_addr(env, pmp_index); -- 2.43.0
From: Alistair Francis <alistair23@gmail.com> The CSRs will always be between either CSR_MHPMCOUNTER3 and CSR_MHPMCOUNTER31 or CSR_MHPMCOUNTER3H and CSR_MHPMCOUNTER31H. So although ctr_index can't be negative, Coverity doesn't know this and it isn't obvious to human readers either. Let's add an assert to ensure that Coverity knows the values will be within range. To simplify the code let's also change the RV32 adjustment. Fixes: Coverity CID 1523910 Signed-off-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Message-ID: <20240108001328.280222-2-alistair.francis@wdc.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/csr.c | 5 ++++- 1 file changed, 4 insertions(+), 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 mctr(CPURISCVState *env, int csrno) if ((riscv_cpu_mxl(env) == MXL_RV32) && csrno >= CSR_MCYCLEH) { /* Offset for RV32 mhpmcounternh counters */ - base_csrno += 0x80; + csrno -= 0x80; } + + g_assert(csrno >= CSR_MHPMCOUNTER3 && csrno <= CSR_MHPMCOUNTER31); + ctr_index = csrno - base_csrno; if ((BIT(ctr_index) & pmu_avail_ctrs >> 3) == 0) { /* The PMU is not enabled or counter is out of range */ -- 2.43.0
From: Alistair Francis <alistair23@gmail.com> We have been incorrectly adjusting both the interrupt and exception cause when using the hypervisor extension and trapping to VS-mode. This patch changes the conditional to ensure we only adjust the cause for interrupts and not exceptions. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1708 Signed-off-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Message-ID: <20240108001328.280222-3-alistair.francis@wdc.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu_helper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index XXXXXXX..XXXXXXX 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -XXX,XX +XXX,XX @@ void riscv_cpu_do_interrupt(CPUState *cs) * See if we need to adjust cause. Yes if its VS mode interrupt * no if hypervisor has delegated one of hs mode's interrupt */ - if (cause == IRQ_VS_TIMER || cause == IRQ_VS_SOFT || - cause == IRQ_VS_EXT) { + if (async && (cause == IRQ_VS_TIMER || cause == IRQ_VS_SOFT || + cause == IRQ_VS_EXT)) { cause = cause - 1; } write_gva = false; -- 2.43.0
From: Alistair Francis <alistair23@gmail.com> Bits 10, 6, 2 and 12 of mideleg are read only 1 when the Hypervisor is enabled. We currently only set them on accesses to mideleg, but they aren't correctly set on reset. Let's ensure they are always the correct value. Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1617 Signed-off-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com> Message-ID: <20240108001328.280222-4-alistair.francis@wdc.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com> --- target/riscv/cpu.c | 8 ++++++++ 1 file changed, 8 insertions(+) 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) /* mmte is supposed to have pm.current hardwired to 1 */ env->mmte |= (EXT_STATUS_INITIAL | MMTE_M_PM_CURRENT); + /* + * Bits 10, 6, 2 and 12 of mideleg are read only 1 when the Hypervisor + * extension is enabled. + */ + if (riscv_has_ext(env, RVH)) { + env->mideleg |= HS_MODE_INTERRUPTS; + } + /* * Clear mseccfg and unlock all the PMP entries upon reset. * This is allowed as per the priv and smepmp specifications -- 2.43.0
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