summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorleyfoon.tan <leyfoon.tan@starfivetech.com>2024-01-17 06:40:24 +0300
committerleyfoon.tan <leyfoon.tan@starfivetech.com>2024-01-17 06:40:24 +0300
commit47450656d5d697f02885c8705eae604d3baaee3f (patch)
tree44f9e992f84c7d60f396f7d9e6e124856154187d
parent7cbc059d3374bda04199750691accd2fa2044e9a (diff)
parent30387e227506433af5072cebac0727751a7e87e1 (diff)
downloadlinux-47450656d5d697f02885c8705eae604d3baaee3f.tar.xz
Merge branch 'starfive-6.6.10-dubhe-Add-Dubhe70' into 'starfive-6.6.10-dubhe'
arch: riscv: starfive: Add Dubhe70 support See merge request starfive-tech/linux!246
-rw-r--r--Documentation/devicetree/bindings/riscv/cpus.yaml1
-rw-r--r--arch/riscv/boot/dts/starfive/Makefile1
-rwxr-xr-xarch/riscv/boot/dts/starfive/dubhe.dtsi10
-rw-r--r--arch/riscv/boot/dts/starfive/dubhe70.dtsi48
-rw-r--r--arch/riscv/boot/dts/starfive/dubhe70_fpga.dts5
-rw-r--r--arch/riscv/errata/starfive/errata.c38
-rw-r--r--arch/riscv/include/asm/cpufeature.h1
-rw-r--r--arch/riscv/include/asm/csr.h18
-rw-r--r--arch/riscv/include/asm/errata_list.h2
-rw-r--r--arch/riscv/include/asm/hwcap.h18
-rw-r--r--arch/riscv/include/asm/kvm_host.h18
-rw-r--r--arch/riscv/include/uapi/asm/kvm.h11
-rw-r--r--arch/riscv/kernel/cpufeature.c12
-rw-r--r--arch/riscv/kernel/setup.c4
-rw-r--r--arch/riscv/kernel/smpboot.c4
-rw-r--r--arch/riscv/kvm/vcpu.c78
-rw-r--r--arch/riscv/kvm/vcpu_onereg.c72
-rw-r--r--tools/perf/pmu-events/arch/riscv/mapfile.csv3
-rw-r--r--tools/perf/pmu-events/arch/riscv/starfive/dubhe-80/firmware.json68
-rw-r--r--tools/perf/pmu-events/arch/riscv/starfive/dubhe-90/common.json172
20 files changed, 380 insertions, 204 deletions
diff --git a/Documentation/devicetree/bindings/riscv/cpus.yaml b/Documentation/devicetree/bindings/riscv/cpus.yaml
index a1c105e2fcf7..6ef8cf448823 100644
--- a/Documentation/devicetree/bindings/riscv/cpus.yaml
+++ b/Documentation/devicetree/bindings/riscv/cpus.yaml
@@ -47,6 +47,7 @@ properties:
- sifive,u74-mc
- thead,c906
- thead,c910
+ - starfive,dubhe-70
- starfive,dubhe-80
- starfive,dubhe-90
- const: riscv
diff --git a/arch/riscv/boot/dts/starfive/Makefile b/arch/riscv/boot/dts/starfive/Makefile
index a8a97301e8fa..aab2781fbc76 100644
--- a/arch/riscv/boot/dts/starfive/Makefile
+++ b/arch/riscv/boot/dts/starfive/Makefile
@@ -14,3 +14,4 @@ dtb-$(CONFIG_ARCH_STARFIVE) += jh7110-starfive-visionfive-2-v1.3b.dtb
dtb-$(CONFIG_ARCH_STARFIVE) += dubhe90_fpga.dtb
dtb-$(CONFIG_ARCH_STARFIVE) += dubhe90_fpga_dual.dtb
dtb-$(CONFIG_ARCH_STARFIVE) += dubhe80_fpga.dtb
+dtb-$(CONFIG_ARCH_STARFIVE) += dubhe70_fpga.dtb
diff --git a/arch/riscv/boot/dts/starfive/dubhe.dtsi b/arch/riscv/boot/dts/starfive/dubhe.dtsi
index 580eea819f4d..5ec30a7d9423 100755
--- a/arch/riscv/boot/dts/starfive/dubhe.dtsi
+++ b/arch/riscv/boot/dts/starfive/dubhe.dtsi
@@ -17,7 +17,10 @@
mmu-type = "riscv,sv48";
next-level-cache = <&l2_cache>;
reg = <0x0>;
- riscv,isa = "rv64imafdcbh_sscofpmf";
+ riscv,isa = "rv64imafdcbh";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "b", "h",
+ "zicntr", "zicsr", "zifencei", "zihpm", "sscofpmf";
tlb-split;
cpu0_intc: interrupt-controller {
@@ -33,7 +36,10 @@
mmu-type = "riscv,sv48";
next-level-cache = <&l2_cache>;
reg = <0x1>;
- riscv,isa = "rv64imafdcbh_sscofpmf";
+ riscv,isa = "rv64imafdcbh";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "b", "h",
+ "zicntr", "zicsr", "zifencei", "zihpm", "sscofpmf";
tlb-split;
cpu1_intc: interrupt-controller {
diff --git a/arch/riscv/boot/dts/starfive/dubhe70.dtsi b/arch/riscv/boot/dts/starfive/dubhe70.dtsi
new file mode 100644
index 000000000000..8060e0f2ad5b
--- /dev/null
+++ b/arch/riscv/boot/dts/starfive/dubhe70.dtsi
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/* Copyright (c) 2023 StarFive Technology Co., Ltd. */
+
+#include "dubhe.dtsi"
+
+&cpu0 {
+ compatible = "starfive,dubhe-70", "riscv";
+ riscv,isa = "rv64imafdcbh";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "b", "h", "zicbom",
+ "zicboz", "zicntr", "zicond", "zicsr", "zifencei",
+ "zihintpause", "zihpm", "svinval", "svnapot", "svpbmt",
+ "sscofpmf";
+ riscv,cbom-block-size = <64>;
+ riscv,cboz-block-size = <64>;
+ d-cache-block-size = <64>;
+ d-cache-sets = <512>;
+ d-cache-size = <32768>;
+ d-tlb-sets = <1>;
+ d-tlb-size = <16>;
+ i-cache-block-size = <64>;
+ i-cache-sets = <512>;
+ i-cache-size = <32768>;
+ i-tlb-sets = <1>;
+ i-tlb-size = <24>;
+};
+
+&cpu1 {
+ compatible = "starfive,dubhe-70", "riscv";
+ riscv,isa = "rv64imafdcbh";
+ riscv,isa-base = "rv64i";
+ riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "b", "h", "zicbom",
+ "zicboz", "zicntr", "zicond", "zicsr", "zifencei",
+ "zihintpause", "zihpm", "svinval", "svnapot", "svpbmt",
+ "sscofpmf";
+ riscv,cbom-block-size = <64>;
+ riscv,cboz-block-size = <64>;
+ d-cache-block-size = <64>;
+ d-cache-sets = <512>;
+ d-cache-size = <32768>;
+ d-tlb-sets = <1>;
+ d-tlb-size = <16>;
+ i-cache-block-size = <64>;
+ i-cache-sets = <512>;
+ i-cache-size = <32768>;
+ i-tlb-sets = <1>;
+ i-tlb-size = <24>;
+};
diff --git a/arch/riscv/boot/dts/starfive/dubhe70_fpga.dts b/arch/riscv/boot/dts/starfive/dubhe70_fpga.dts
new file mode 100644
index 000000000000..a4e9ea608cb8
--- /dev/null
+++ b/arch/riscv/boot/dts/starfive/dubhe70_fpga.dts
@@ -0,0 +1,5 @@
+// SPDX-License-Identifier: (GPL-2.0 OR MIT)
+/* Copyright (c) 2023 StarFive Technology Co., Ltd. */
+
+#include "dubhe70.dtsi"
+#include "dubhe_fpga_common.dtsi"
diff --git a/arch/riscv/errata/starfive/errata.c b/arch/riscv/errata/starfive/errata.c
index b7e757207d54..c774ec16d87d 100644
--- a/arch/riscv/errata/starfive/errata.c
+++ b/arch/riscv/errata/starfive/errata.c
@@ -23,26 +23,45 @@
#define STARFIVE_DUBHE80_MARCHID 0x80000000DB000080UL
#define STARFIVE_DUBHE80_MIMPID 0x0000000020230831UL
-static bool errata_probe_cmo(unsigned int stage, unsigned long arch_id,
- unsigned long impid)
+#define STARFIVE_DUBHE70_MARCHID 0x80000000DB000070UL
+#define STARFIVE_DUBHE70_MIMPID 0x0000000020240131UL
+
+DEFINE_STATIC_KEY_FALSE(bypass_envcfg_csr_key);
+
+static void errata_probe_cmo(unsigned int stage, unsigned long arch_id,
+ unsigned long impid)
{
if (!IS_ENABLED(CONFIG_ERRATA_STARFIVE_CMO))
- return false;
+ return;
if (arch_id == STARFIVE_DUBHE90_MARCHID) {
if (impid > STARFIVE_DUBHE90_MIMPID)
- return false;
+ return;
}
if (arch_id == STARFIVE_DUBHE80_MARCHID) {
if (impid > STARFIVE_DUBHE80_MIMPID)
- return false;
+ return;
}
riscv_cbom_block_size = L1_CACHE_BYTES;
riscv_noncoherent_supported();
+}
+
+static void errata_bypass_envcfg_csr(unsigned int stage, unsigned long arch_id,
+ unsigned long impid)
+{
+ if (arch_id == STARFIVE_DUBHE90_MARCHID) {
+ if (impid > STARFIVE_DUBHE90_MIMPID)
+ return;
+ }
- return true;
+ if (arch_id == STARFIVE_DUBHE80_MARCHID) {
+ if (impid > STARFIVE_DUBHE80_MIMPID)
+ return;
+ }
+
+ static_branch_enable(&bypass_envcfg_csr_key);
}
void starfive_errata_patch_func(struct alt_entry *begin,
@@ -51,6 +70,11 @@ void starfive_errata_patch_func(struct alt_entry *begin,
unsigned long impid,
unsigned int stage)
{
- if (stage == RISCV_ALTERNATIVES_BOOT)
+ if (archid == STARFIVE_DUBHE70_MARCHID)
+ return;
+
+ if (stage == RISCV_ALTERNATIVES_BOOT) {
errata_probe_cmo(stage, archid, impid);
+ errata_bypass_envcfg_csr(stage, archid, impid);
+ }
}
diff --git a/arch/riscv/include/asm/cpufeature.h b/arch/riscv/include/asm/cpufeature.h
index d0345bd659c9..13b7d35648a9 100644
--- a/arch/riscv/include/asm/cpufeature.h
+++ b/arch/riscv/include/asm/cpufeature.h
@@ -31,5 +31,6 @@ DECLARE_PER_CPU(long, misaligned_access_speed);
extern struct riscv_isainfo hart_isa[NR_CPUS];
void check_unaligned_access(int cpu);
+void riscv_user_isa_enable(void);
#endif
diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h
index 777cb8299551..306a19a5509c 100644
--- a/arch/riscv/include/asm/csr.h
+++ b/arch/riscv/include/asm/csr.h
@@ -203,6 +203,18 @@
#define ENVCFG_CBIE_INV _AC(0x3, UL)
#define ENVCFG_FIOM _AC(0x1, UL)
+/* Smstateen bits */
+#define SMSTATEEN0_AIA_IMSIC_SHIFT 58
+#define SMSTATEEN0_AIA_IMSIC (_ULL(1) << SMSTATEEN0_AIA_IMSIC_SHIFT)
+#define SMSTATEEN0_AIA_SHIFT 59
+#define SMSTATEEN0_AIA (_ULL(1) << SMSTATEEN0_AIA_SHIFT)
+#define SMSTATEEN0_AIA_ISEL_SHIFT 60
+#define SMSTATEEN0_AIA_ISEL (_ULL(1) << SMSTATEEN0_AIA_ISEL_SHIFT)
+#define SMSTATEEN0_HSENVCFG_SHIFT 62
+#define SMSTATEEN0_HSENVCFG (_ULL(1) << SMSTATEEN0_HSENVCFG_SHIFT)
+#define SMSTATEEN0_SSTATEEN0_SHIFT 63
+#define SMSTATEEN0_SSTATEEN0 (_ULL(1) << SMSTATEEN0_SSTATEEN0_SHIFT)
+
/* symbolic CSR names: */
#define CSR_CYCLE 0xc00
#define CSR_TIME 0xc01
@@ -275,6 +287,8 @@
#define CSR_SIE 0x104
#define CSR_STVEC 0x105
#define CSR_SCOUNTEREN 0x106
+#define CSR_SENVCFG 0x10a
+#define CSR_SSTATEEN0 0x10c
#define CSR_SSCRATCH 0x140
#define CSR_SEPC 0x141
#define CSR_SCAUSE 0x142
@@ -349,6 +363,10 @@
#define CSR_VSIEH 0x214
#define CSR_VSIPH 0x254
+/* Hypervisor stateen CSRs */
+#define CSR_HSTATEEN0 0x60c
+#define CSR_HSTATEEN0H 0x61c
+
#define CSR_MSTATUS 0x300
#define CSR_MISA 0x301
#define CSR_MIDELEG 0x303
diff --git a/arch/riscv/include/asm/errata_list.h b/arch/riscv/include/asm/errata_list.h
index 6267b6407b6e..6bbb4bf643c0 100644
--- a/arch/riscv/include/asm/errata_list.h
+++ b/arch/riscv/include/asm/errata_list.h
@@ -164,6 +164,8 @@ asm volatile(ALTERNATIVE( \
: "=r" (__ovl) : \
: "memory")
+DECLARE_STATIC_KEY_FALSE(bypass_envcfg_csr_key);
+
#endif /* __ASSEMBLY__ */
#endif
diff --git a/arch/riscv/include/asm/hwcap.h b/arch/riscv/include/asm/hwcap.h
index b7b58258f6c7..fe6656af967a 100644
--- a/arch/riscv/include/asm/hwcap.h
+++ b/arch/riscv/include/asm/hwcap.h
@@ -58,6 +58,8 @@
#define RISCV_ISA_EXT_ZICSR 40
#define RISCV_ISA_EXT_ZIFENCEI 41
#define RISCV_ISA_EXT_ZIHPM 42
+#define RISCV_ISA_EXT_SMSTATEEN 43
+#define RISCV_ISA_EXT_ZICOND 44
#define RISCV_ISA_EXT_MAX 64
@@ -70,6 +72,7 @@
#ifndef __ASSEMBLY__
#include <linux/jump_label.h>
+#include <asm/cpufeature.h>
unsigned long riscv_get_elf_hwcap(void);
@@ -137,6 +140,21 @@ l_yes:
return true;
}
+static __always_inline bool riscv_cpu_has_extension_likely(int cpu, const unsigned long ext)
+{
+ if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE) && riscv_has_extension_likely(ext))
+ return true;
+
+ return __riscv_isa_extension_available(hart_isa[cpu].isa, ext);
+}
+
+static __always_inline bool riscv_cpu_has_extension_unlikely(int cpu, const unsigned long ext)
+{
+ if (IS_ENABLED(CONFIG_RISCV_ALTERNATIVE) && riscv_has_extension_unlikely(ext))
+ return true;
+
+ return __riscv_isa_extension_available(hart_isa[cpu].isa, ext);
+}
#endif
#endif /* _ASM_RISCV_HWCAP_H */
diff --git a/arch/riscv/include/asm/kvm_host.h b/arch/riscv/include/asm/kvm_host.h
index 1ebf20dfbaa6..0eefd9c991ae 100644
--- a/arch/riscv/include/asm/kvm_host.h
+++ b/arch/riscv/include/asm/kvm_host.h
@@ -162,6 +162,16 @@ struct kvm_vcpu_csr {
unsigned long hvip;
unsigned long vsatp;
unsigned long scounteren;
+ unsigned long senvcfg;
+};
+
+struct kvm_vcpu_config {
+ u64 henvcfg;
+ u64 hstateen0;
+};
+
+struct kvm_vcpu_smstateen_csr {
+ unsigned long sstateen0;
};
struct kvm_vcpu_arch {
@@ -183,6 +193,8 @@ struct kvm_vcpu_arch {
unsigned long host_sscratch;
unsigned long host_stvec;
unsigned long host_scounteren;
+ unsigned long host_senvcfg;
+ unsigned long host_sstateen0;
/* CPU context of Host */
struct kvm_cpu_context host_context;
@@ -193,6 +205,9 @@ struct kvm_vcpu_arch {
/* CPU CSR context of Guest VCPU */
struct kvm_vcpu_csr guest_csr;
+ /* CPU Smstateen CSR context of Guest VCPU */
+ struct kvm_vcpu_smstateen_csr smstateen_csr;
+
/* CPU context upon Guest VCPU reset */
struct kvm_cpu_context guest_reset_context;
@@ -244,6 +259,9 @@ struct kvm_vcpu_arch {
/* Performance monitoring context */
struct kvm_pmu pmu_context;
+
+ /* 'static' configurations which are set only once */
+ struct kvm_vcpu_config cfg;
};
static inline void kvm_arch_sync_events(struct kvm *kvm) {}
diff --git a/arch/riscv/include/uapi/asm/kvm.h b/arch/riscv/include/uapi/asm/kvm.h
index 992c5e407104..917d8cc2489e 100644
--- a/arch/riscv/include/uapi/asm/kvm.h
+++ b/arch/riscv/include/uapi/asm/kvm.h
@@ -80,6 +80,7 @@ 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 */
@@ -93,6 +94,11 @@ 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;
@@ -131,6 +137,8 @@ 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,
};
@@ -178,10 +186,13 @@ 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/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
index 1cfbba65d11a..a7ef18dabcd8 100644
--- a/arch/riscv/kernel/cpufeature.c
+++ b/arch/riscv/kernel/cpufeature.c
@@ -93,10 +93,10 @@ static bool riscv_isa_extension_check(int id)
return true;
case RISCV_ISA_EXT_ZICBOZ:
if (!riscv_cboz_block_size) {
- pr_err("Zicboz detected in ISA string, but no cboz-block-size found\n");
+ pr_err("Zicboz detected in ISA string, disabling as no cboz-block-size found\n");
return false;
} else if (!is_power_of_2(riscv_cboz_block_size)) {
- pr_err("cboz-block-size present, but is not a power-of-2\n");
+ pr_err("Zicboz disabled as cboz-block-size present, but is not a power-of-2\n");
return false;
}
return true;
@@ -167,6 +167,7 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = {
__RISCV_ISA_EXT_DATA(zicbom, RISCV_ISA_EXT_ZICBOM),
__RISCV_ISA_EXT_DATA(zicboz, RISCV_ISA_EXT_ZICBOZ),
__RISCV_ISA_EXT_DATA(zicntr, RISCV_ISA_EXT_ZICNTR),
+ __RISCV_ISA_EXT_DATA(zicond, RISCV_ISA_EXT_ZICOND),
__RISCV_ISA_EXT_DATA(zicsr, RISCV_ISA_EXT_ZICSR),
__RISCV_ISA_EXT_DATA(zifencei, RISCV_ISA_EXT_ZIFENCEI),
__RISCV_ISA_EXT_DATA(zihintpause, RISCV_ISA_EXT_ZIHINTPAUSE),
@@ -175,6 +176,7 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = {
__RISCV_ISA_EXT_DATA(zbb, RISCV_ISA_EXT_ZBB),
__RISCV_ISA_EXT_DATA(zbs, RISCV_ISA_EXT_ZBS),
__RISCV_ISA_EXT_DATA(smaia, RISCV_ISA_EXT_SMAIA),
+ __RISCV_ISA_EXT_DATA(smstateen, RISCV_ISA_EXT_SMSTATEEN),
__RISCV_ISA_EXT_DATA(ssaia, RISCV_ISA_EXT_SSAIA),
__RISCV_ISA_EXT_DATA(sscofpmf, RISCV_ISA_EXT_SSCOFPMF),
__RISCV_ISA_EXT_DATA(sstc, RISCV_ISA_EXT_SSTC),
@@ -653,6 +655,12 @@ static int check_unaligned_access_boot_cpu(void)
arch_initcall(check_unaligned_access_boot_cpu);
+void riscv_user_isa_enable(void)
+{
+ if (riscv_cpu_has_extension_unlikely(smp_processor_id(), RISCV_ISA_EXT_ZICBOZ))
+ csr_set(CSR_SENVCFG, ENVCFG_CBZE);
+}
+
#ifdef CONFIG_RISCV_ALTERNATIVE
/*
* Alternative patch sites consider 48 bits when determining when to patch
diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c
index aac853ae4eb7..2a79d4ed2660 100644
--- a/arch/riscv/kernel/setup.c
+++ b/arch/riscv/kernel/setup.c
@@ -26,6 +26,7 @@
#include <asm/acpi.h>
#include <asm/alternative.h>
#include <asm/cacheflush.h>
+#include <asm/cpufeature.h>
#include <asm/cpu_ops.h>
#include <asm/early_ioremap.h>
#include <asm/pgtable.h>
@@ -301,10 +302,13 @@ void __init setup_arch(char **cmdline_p)
riscv_fill_hwcap();
init_rt_signal_env();
apply_boot_alternatives();
+
if (IS_ENABLED(CONFIG_RISCV_ISA_ZICBOM) &&
riscv_isa_extension_available(NULL, ZICBOM))
riscv_noncoherent_supported();
riscv_set_dma_cache_alignment();
+
+ riscv_user_isa_enable();
}
static int __init topology_init(void)
diff --git a/arch/riscv/kernel/smpboot.c b/arch/riscv/kernel/smpboot.c
index 1b8da4e40a4d..d1b0a6fc3adf 100644
--- a/arch/riscv/kernel/smpboot.c
+++ b/arch/riscv/kernel/smpboot.c
@@ -25,6 +25,8 @@
#include <linux/of.h>
#include <linux/sched/task_stack.h>
#include <linux/sched/mm.h>
+
+#include <asm/cpufeature.h>
#include <asm/cpu_ops.h>
#include <asm/cpufeature.h>
#include <asm/irq.h>
@@ -253,6 +255,8 @@ asmlinkage __visible void smp_callin(void)
elf_hwcap &= ~COMPAT_HWCAP_ISA_V;
}
+ riscv_user_isa_enable();
+
/*
* Remote TLB flushes are ignored while the CPU is offline, so emit
* a local TLB flush right now just in case.
diff --git a/arch/riscv/kvm/vcpu.c b/arch/riscv/kvm/vcpu.c
index 1ac6a8dbe0b8..8fe674a874dd 100644
--- a/arch/riscv/kvm/vcpu.c
+++ b/arch/riscv/kvm/vcpu.c
@@ -19,6 +19,7 @@
#include <linux/kvm_host.h>
#include <asm/csr.h>
#include <asm/cacheflush.h>
+#include <asm/errata_list.h>
#include <asm/kvm_vcpu_vector.h>
const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
@@ -471,33 +472,38 @@ int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
return -EINVAL;
}
-/*
-static void kvm_riscv_vcpu_update_config(const unsigned long *isa)
+static void kvm_riscv_vcpu_setup_config(struct kvm_vcpu *vcpu)
{
- u64 henvcfg = 0;
+ const unsigned long *isa = vcpu->arch.isa;
+ struct kvm_vcpu_config *cfg = &vcpu->arch.cfg;
if (riscv_isa_extension_available(isa, SVPBMT))
- henvcfg |= ENVCFG_PBMTE;
+ cfg->henvcfg |= ENVCFG_PBMTE;
if (riscv_isa_extension_available(isa, SSTC))
- henvcfg |= ENVCFG_STCE;
+ cfg->henvcfg |= ENVCFG_STCE;
if (riscv_isa_extension_available(isa, ZICBOM))
- henvcfg |= (ENVCFG_CBIE | ENVCFG_CBCFE);
+ cfg->henvcfg |= (ENVCFG_CBIE | ENVCFG_CBCFE);
if (riscv_isa_extension_available(isa, ZICBOZ))
- henvcfg |= ENVCFG_CBZE;
-
- csr_write(CSR_HENVCFG, henvcfg);
-#ifdef CONFIG_32BIT
- csr_write(CSR_HENVCFGH, henvcfg >> 32);
-#endif
+ cfg->henvcfg |= ENVCFG_CBZE;
+
+ if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN)) {
+ cfg->hstateen0 |= SMSTATEEN0_HSENVCFG;
+ if (riscv_isa_extension_available(isa, SSAIA))
+ cfg->hstateen0 |= SMSTATEEN0_AIA_IMSIC |
+ SMSTATEEN0_AIA |
+ SMSTATEEN0_AIA_ISEL;
+ if (riscv_isa_extension_available(isa, SMSTATEEN))
+ cfg->hstateen0 |= SMSTATEEN0_SSTATEEN0;
+ }
}
-*/
void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
{
struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
+ struct kvm_vcpu_config *cfg = &vcpu->arch.cfg;
csr_write(CSR_VSSTATUS, csr->vsstatus);
csr_write(CSR_VSIE, csr->vsie);
@@ -508,9 +514,16 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
csr_write(CSR_VSTVAL, csr->vstval);
csr_write(CSR_HVIP, csr->hvip);
csr_write(CSR_VSATP, csr->vsatp);
-
- /* Temporarily commented out while Dubhe is still using Hypervisor ISA v0.6 */
- /* kvm_riscv_vcpu_update_config(vcpu->arch.isa); */
+ if (!static_branch_unlikely(&bypass_envcfg_csr_key)) {
+ csr_write(CSR_HENVCFG, cfg->henvcfg);
+ if (IS_ENABLED(CONFIG_32BIT))
+ csr_write(CSR_HENVCFGH, cfg->henvcfg >> 32);
+ }
+ if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN)) {
+ csr_write(CSR_HSTATEEN0, cfg->hstateen0);
+ if (IS_ENABLED(CONFIG_32BIT))
+ csr_write(CSR_HSTATEEN0H, cfg->hstateen0 >> 32);
+ }
kvm_riscv_gstage_update_hgatp(vcpu);
@@ -609,6 +622,34 @@ static void kvm_riscv_update_hvip(struct kvm_vcpu *vcpu)
kvm_riscv_vcpu_aia_update_hvip(vcpu);
}
+static __always_inline void kvm_riscv_vcpu_swap_in_guest_state(struct kvm_vcpu *vcpu)
+{
+ struct kvm_vcpu_smstateen_csr *smcsr = &vcpu->arch.smstateen_csr;
+ struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
+ struct kvm_vcpu_config *cfg = &vcpu->arch.cfg;
+
+ if (!static_branch_unlikely(&bypass_envcfg_csr_key))
+ vcpu->arch.host_senvcfg = csr_swap(CSR_SENVCFG, csr->senvcfg);
+ if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN) &&
+ (cfg->hstateen0 & SMSTATEEN0_SSTATEEN0))
+ vcpu->arch.host_sstateen0 = csr_swap(CSR_SSTATEEN0,
+ smcsr->sstateen0);
+}
+
+static __always_inline void kvm_riscv_vcpu_swap_in_host_state(struct kvm_vcpu *vcpu)
+{
+ struct kvm_vcpu_smstateen_csr *smcsr = &vcpu->arch.smstateen_csr;
+ struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
+ struct kvm_vcpu_config *cfg = &vcpu->arch.cfg;
+
+ if (!static_branch_unlikely(&bypass_envcfg_csr_key))
+ csr->senvcfg = csr_swap(CSR_SENVCFG, vcpu->arch.host_senvcfg);
+ if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN) &&
+ (cfg->hstateen0 & SMSTATEEN0_SSTATEEN0))
+ smcsr->sstateen0 = csr_swap(CSR_SSTATEEN0,
+ vcpu->arch.host_sstateen0);
+}
+
/*
* Actually run the vCPU, entering an RCU extended quiescent state (EQS) while
* the vCPU is running.
@@ -618,10 +659,12 @@ static void kvm_riscv_update_hvip(struct kvm_vcpu *vcpu)
*/
static void noinstr kvm_riscv_vcpu_enter_exit(struct kvm_vcpu *vcpu)
{
+ kvm_riscv_vcpu_swap_in_guest_state(vcpu);
guest_state_enter_irqoff();
__kvm_riscv_switch_to(&vcpu->arch);
vcpu->arch.last_exit_cpu = vcpu->cpu;
guest_state_exit_irqoff();
+ kvm_riscv_vcpu_swap_in_host_state(vcpu);
}
int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
@@ -630,6 +673,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
struct kvm_cpu_trap trap;
struct kvm_run *run = vcpu->run;
+ if (!vcpu->arch.ran_atleast_once)
+ kvm_riscv_vcpu_setup_config(vcpu);
+
/* Mark this VCPU ran at least once */
vcpu->arch.ran_atleast_once = true;
diff --git a/arch/riscv/kvm/vcpu_onereg.c b/arch/riscv/kvm/vcpu_onereg.c
index b7e0e03c69b1..c6ebce6126b5 100644
--- a/arch/riscv/kvm/vcpu_onereg.c
+++ b/arch/riscv/kvm/vcpu_onereg.c
@@ -34,6 +34,7 @@ static const unsigned long kvm_isa_ext_arr[] = {
[KVM_RISCV_ISA_EXT_M] = RISCV_ISA_EXT_m,
[KVM_RISCV_ISA_EXT_V] = RISCV_ISA_EXT_v,
/* Multi letter extensions (alphabetically sorted) */
+ KVM_ISA_EXT_ARR(SMSTATEEN),
KVM_ISA_EXT_ARR(SSAIA),
KVM_ISA_EXT_ARR(SSTC),
KVM_ISA_EXT_ARR(SVINVAL),
@@ -45,6 +46,7 @@ static const unsigned long kvm_isa_ext_arr[] = {
KVM_ISA_EXT_ARR(ZICBOM),
KVM_ISA_EXT_ARR(ZICBOZ),
KVM_ISA_EXT_ARR(ZICNTR),
+ KVM_ISA_EXT_ARR(ZICOND),
KVM_ISA_EXT_ARR(ZICSR),
KVM_ISA_EXT_ARR(ZIFENCEI),
KVM_ISA_EXT_ARR(ZIHINTPAUSE),
@@ -80,11 +82,11 @@ static bool kvm_riscv_vcpu_isa_enable_allowed(unsigned long ext)
static bool kvm_riscv_vcpu_isa_disable_allowed(unsigned long ext)
{
switch (ext) {
+ /* Extensions which don't have any mechanism to disable */
case KVM_RISCV_ISA_EXT_A:
case KVM_RISCV_ISA_EXT_C:
case KVM_RISCV_ISA_EXT_I:
case KVM_RISCV_ISA_EXT_M:
- case KVM_RISCV_ISA_EXT_SSAIA:
case KVM_RISCV_ISA_EXT_SSTC:
case KVM_RISCV_ISA_EXT_SVINVAL:
case KVM_RISCV_ISA_EXT_SVNAPOT:
@@ -92,11 +94,15 @@ static bool kvm_riscv_vcpu_isa_disable_allowed(unsigned long ext)
case KVM_RISCV_ISA_EXT_ZBB:
case KVM_RISCV_ISA_EXT_ZBS:
case KVM_RISCV_ISA_EXT_ZICNTR:
+ case KVM_RISCV_ISA_EXT_ZICOND:
case KVM_RISCV_ISA_EXT_ZICSR:
case KVM_RISCV_ISA_EXT_ZIFENCEI:
case KVM_RISCV_ISA_EXT_ZIHINTPAUSE:
case KVM_RISCV_ISA_EXT_ZIHPM:
return false;
+ /* Extensions which can be disabled using Smstateen */
+ case KVM_RISCV_ISA_EXT_SSAIA:
+ return riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN);
default:
break;
}
@@ -378,6 +384,34 @@ static int kvm_riscv_vcpu_general_set_csr(struct kvm_vcpu *vcpu,
return 0;
}
+static inline int kvm_riscv_vcpu_smstateen_set_csr(struct kvm_vcpu *vcpu,
+ unsigned long reg_num,
+ unsigned long reg_val)
+{
+ struct kvm_vcpu_smstateen_csr *csr = &vcpu->arch.smstateen_csr;
+
+ if (reg_num >= sizeof(struct kvm_riscv_smstateen_csr) /
+ sizeof(unsigned long))
+ return -EINVAL;
+
+ ((unsigned long *)csr)[reg_num] = reg_val;
+ return 0;
+}
+
+static int kvm_riscv_vcpu_smstateen_get_csr(struct kvm_vcpu *vcpu,
+ unsigned long reg_num,
+ unsigned long *out_val)
+{
+ struct kvm_vcpu_smstateen_csr *csr = &vcpu->arch.smstateen_csr;
+
+ if (reg_num >= sizeof(struct kvm_riscv_smstateen_csr) /
+ sizeof(unsigned long))
+ return -EINVAL;
+
+ *out_val = ((unsigned long *)csr)[reg_num];
+ return 0;
+}
+
static int kvm_riscv_vcpu_get_reg_csr(struct kvm_vcpu *vcpu,
const struct kvm_one_reg *reg)
{
@@ -401,6 +435,12 @@ static int kvm_riscv_vcpu_get_reg_csr(struct kvm_vcpu *vcpu,
case KVM_REG_RISCV_CSR_AIA:
rc = kvm_riscv_vcpu_aia_get_csr(vcpu, reg_num, &reg_val);
break;
+ case KVM_REG_RISCV_CSR_SMSTATEEN:
+ rc = -EINVAL;
+ if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN))
+ rc = kvm_riscv_vcpu_smstateen_get_csr(vcpu, reg_num,
+ &reg_val);
+ break;
default:
rc = -ENOENT;
break;
@@ -440,6 +480,12 @@ static int kvm_riscv_vcpu_set_reg_csr(struct kvm_vcpu *vcpu,
case KVM_REG_RISCV_CSR_AIA:
rc = kvm_riscv_vcpu_aia_set_csr(vcpu, reg_num, reg_val);
break;
+ case KVM_REG_RISCV_CSR_SMSTATEEN:
+ rc = -EINVAL;
+ if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN))
+ rc = kvm_riscv_vcpu_smstateen_set_csr(vcpu, reg_num,
+ reg_val);
+break;
default:
rc = -ENOENT;
break;
@@ -696,6 +742,8 @@ static inline unsigned long num_csr_regs(const struct kvm_vcpu *vcpu)
if (riscv_isa_extension_available(vcpu->arch.isa, SSAIA))
n += sizeof(struct kvm_riscv_aia_csr) / sizeof(unsigned long);
+ if (riscv_isa_extension_available(vcpu->arch.isa, SMSTATEEN))
+ n += sizeof(struct kvm_riscv_smstateen_csr) / sizeof(unsigned long);
return n;
}
@@ -704,7 +752,7 @@ static int copy_csr_reg_indices(const struct kvm_vcpu *vcpu,
u64 __user *uindices)
{
int n1 = sizeof(struct kvm_riscv_csr) / sizeof(unsigned long);
- int n2 = 0;
+ int n2 = 0, n3 = 0;
/* copy general csr regs */
for (int i = 0; i < n1; i++) {
@@ -738,7 +786,25 @@ static int copy_csr_reg_indices(const struct kvm_vcpu *vcpu,
}
}
- return n1 + n2;
+ /* copy Smstateen csr regs */
+ if (riscv_isa_extension_available(vcpu->arch.isa, SMSTATEEN)) {
+ n3 = sizeof(struct kvm_riscv_smstateen_csr) / sizeof(unsigned long);
+
+ for (int i = 0; i < n3; i++) {
+ u64 size = IS_ENABLED(CONFIG_32BIT) ?
+ KVM_REG_SIZE_U32 : KVM_REG_SIZE_U64;
+ u64 reg = KVM_REG_RISCV | size | KVM_REG_RISCV_CSR |
+ KVM_REG_RISCV_CSR_SMSTATEEN | i;
+
+ if (uindices) {
+ if (put_user(reg, uindices))
+ return -EFAULT;
+ uindices++;
+ }
+ }
+ }
+
+ return n1 + n2 + n3;
}
static inline unsigned long num_timer_regs(void)
diff --git a/tools/perf/pmu-events/arch/riscv/mapfile.csv b/tools/perf/pmu-events/arch/riscv/mapfile.csv
index 3a7ec0293b7f..8310a80a5986 100644
--- a/tools/perf/pmu-events/arch/riscv/mapfile.csv
+++ b/tools/perf/pmu-events/arch/riscv/mapfile.csv
@@ -15,5 +15,4 @@
#
#MVENDORID-MARCHID-MIMPID,Version,Filename,EventType
0x489-0x8000000000000007-0x[[:xdigit:]]+,v1,sifive/u74,core
-0x67e80902023,v1,starfive/dubhe-90,core
-0x67e80802023,v1,starfive/dubhe-80,core
+0x67e-0x80000000db0000[789]0-0x[[:xdigit:]]+,v1,starfive/dubhe-80,core
diff --git a/tools/perf/pmu-events/arch/riscv/starfive/dubhe-80/firmware.json b/tools/perf/pmu-events/arch/riscv/starfive/dubhe-80/firmware.json
new file mode 100644
index 000000000000..37079ebe9316
--- /dev/null
+++ b/tools/perf/pmu-events/arch/riscv/starfive/dubhe-80/firmware.json
@@ -0,0 +1,68 @@
+[
+ {
+ "ArchStdEvent": "FW_MISALIGNED_LOAD"
+ },
+ {
+ "ArchStdEvent": "FW_MISALIGNED_STORE"
+ },
+ {
+ "ArchStdEvent": "FW_ACCESS_LOAD"
+ },
+ {
+ "ArchStdEvent": "FW_ACCESS_STORE"
+ },
+ {
+ "ArchStdEvent": "FW_ILLEGAL_INSN"
+ },
+ {
+ "ArchStdEvent": "FW_SET_TIMER"
+ },
+ {
+ "ArchStdEvent": "FW_IPI_SENT"
+ },
+ {
+ "ArchStdEvent": "FW_IPI_RECEIVED"
+ },
+ {
+ "ArchStdEvent": "FW_FENCE_I_SENT"
+ },
+ {
+ "ArchStdEvent": "FW_FENCE_I_RECEIVED"
+ },
+ {
+ "ArchStdEvent": "FW_SFENCE_VMA_SENT"
+ },
+ {
+ "ArchStdEvent": "FW_SFENCE_VMA_RECEIVED"
+ },
+ {
+ "ArchStdEvent": "FW_SFENCE_VMA_RECEIVED"
+ },
+ {
+ "ArchStdEvent": "FW_SFENCE_VMA_ASID_RECEIVED"
+ },
+ {
+ "ArchStdEvent": "FW_HFENCE_GVMA_SENT"
+ },
+ {
+ "ArchStdEvent": "FW_HFENCE_GVMA_RECEIVED"
+ },
+ {
+ "ArchStdEvent": "FW_HFENCE_GVMA_VMID_SENT"
+ },
+ {
+ "ArchStdEvent": "FW_HFENCE_GVMA_VMID_RECEIVED"
+ },
+ {
+ "ArchStdEvent": "FW_HFENCE_VVMA_SENT"
+ },
+ {
+ "ArchStdEvent": "FW_HFENCE_VVMA_RECEIVED"
+ },
+ {
+ "ArchStdEvent": "FW_HFENCE_VVMA_ASID_SENT"
+ },
+ {
+ "ArchStdEvent": "FW_HFENCE_VVMA_ASID_RECEIVED"
+ }
+] \ No newline at end of file
diff --git a/tools/perf/pmu-events/arch/riscv/starfive/dubhe-90/common.json b/tools/perf/pmu-events/arch/riscv/starfive/dubhe-90/common.json
deleted file mode 100644
index 9026e6653c86..000000000000
--- a/tools/perf/pmu-events/arch/riscv/starfive/dubhe-90/common.json
+++ /dev/null
@@ -1,172 +0,0 @@
-[
- {
- "EventName": "ACCESS_MMU_STLB",
- "EventCode": "0x1",
- "BriefDescription": "access MMU STLB"
- },
- {
- "EventName": "MISS_MMU_STLB",
- "EventCode": "0x2",
- "BriefDescription": "miss MMU STLB"
- },
- {
- "EventName": "ACCESS_MMU_PTE_C",
- "EventCode": "0x3",
- "BriefDescription": "access MMU PTE-Cache"
- },
- {
- "EventName": "MISS_MMU_PTE_C",
- "EventCode": "0x4",
- "BriefDescription": "miss MMU PTE-Cache"
- },
- {
- "EventName": "ROB_FLUSH",
- "EventCode": "0x5",
- "BriefDescription": "ROB flush (all kinds of exceptions)"
- },
- {
- "EventName": "BTB_PREDICTION_MISS",
- "EventCode": "0x6",
- "BriefDescription": "BTB prediction miss"
- },
- {
- "EventName": "ITLB_MISS",
- "EventCode": "0x7",
- "BriefDescription": "ITLB miss"
- },
- {
- "EventName": "SYNC_DEL_FETCH_G",
- "EventCode": "0x8",
- "BriefDescription": "SYNC delivery a fetch-group"
- },
- {
- "EventName": "ICACHE_MISS",
- "EventCode": "0x9",
- "BriefDescription": "ICache miss"
- },
- {
- "EventName": "BPU_BR_RETIRE",
- "EventCode": "0xA",
- "BriefDescription": "condition branch instruction retire"
- },
- {
- "EventName": "BPU_BR_MISS",
- "EventCode": "0xB",
- "BriefDescription": "condition branch instruction miss"
- },
- {
- "EventName": "RET_INS_RETIRE",
- "EventCode": "0xC",
- "BriefDescription": "return instruction retire"
- },
- {
- "EventName": "RET_INS_MISS",
- "EventCode": "0xD",
- "BriefDescription": "return instruction miss"
- },
- {
- "EventName": "INDIRECT_JR_MISS",
- "EventCode": "0xE",
- "BriefDescription": "indirect JR instruction miss (inlcude without target)"
- },
- {
- "EventName": "IBUF_VAL_ID_NORDY",
- "EventCode": "0xF",
- "BriefDescription": "IBUF valid while ID not ready"
- },
- {
- "EventName": "IBUF_NOVAL_ID_RDY",
- "EventCode": "0x10",
- "BriefDescription": "IBUF not valid while ID ready"
- },
- {
- "EventName": "REN_INT_PHY_REG_NORDY",
- "EventCode": "0x11",
- "BriefDescription": "REN integer physical register file is not ready"
- },
- {
- "EventName": "REN_FP_PHY_REG_NORDY",
- "EventCode": "0x12",
- "BriefDescription": "REN floating point physical register file is not ready"
- },
- {
- "EventName": "REN_CP_NORDY",
- "EventCode": "0x13",
- "BriefDescription": "REN checkpoint is not ready"
- },
- {
- "EventName": "DEC_VAL_ROB_NORDY",
- "EventCode": "0x14",
- "BriefDescription": "DEC is valid and ROB is not ready"
- },
- {
- "EventName": "OOD_FLUSH_LS_DEP",
- "EventCode": "0x15",
- "BriefDescription": "out of order flush due to load/store dependency"
- },
- {
- "EventName": "BRU_RET_IJR_INS",
- "EventCode": "0x16",
- "BriefDescription": "BRU retire an IJR instruction"
- },
- {
- "EventName": "ACCESS_DTLB",
- "EventCode": "0x17",
- "BriefDescription": "access DTLB"
- },
- {
- "EventName": "MISS_DTLB",
- "EventCode": "0x18",
- "BriefDescription": "miss DTLB"
- },
- {
- "EventName": "LOAD_INS_DCACHE",
- "EventCode": "0x19",
- "BriefDescription": "load instruction access DCache"
- },
- {
- "EventName": "LOAD_INS_MISS_DCACHE",
- "EventCode": "0x1A",
- "BriefDescription": "load instruction miss DCache"
- },
- {
- "EventName": "STORE_INS_DCACHE",
- "EventCode": "0x1B",
- "BriefDescription": "store/amo instruction access DCache"
- },
- {
- "EventName": "STORE_INS_MISS_DCACHE",
- "EventCode": "0x1C",
- "BriefDescription": "store/amo instruction miss DCache"
- },
- {
- "EventName": "LOAD_SCACHE",
- "EventCode": "0x1D",
- "BriefDescription": "load access SCache"
- },
- {
- "EventName": "STORE_SCACHE",
- "EventCode": "0x1E",
- "BriefDescription": "store access SCache"
- },
- {
- "EventName": "LOAD_MISS_SCACHE",
- "EventCode": "0x1F",
- "BriefDescription": "load miss SCache"
- },
- {
- "EventName": "STORE_MISS_SCACHE",
- "EventCode": "0x20",
- "BriefDescription": "store miss SCache"
- },
- {
- "EventName": "L2C_PF_REQ",
- "EventCode": "0x21",
- "BriefDescription": "L2C data-prefetcher request"
- },
- {
- "EventName": "L2C_PF_HIT",
- "EventCode": "0x22",
- "BriefDescription": "L2C data-prefetcher hit"
- }
-] \ No newline at end of file