Svade and Svadu extensions represent two schemes for managing the PTE A/D
bit. When the PTE A/D bits need to be set, Svade extension intdicates that
a related page fault will be raised. In contrast, the Svadu extension
supports hardware updating of PTE A/D bits. This series enables Svade and
Svadu extensions for both host and guest OS.
Regrading the mailing thread[1], we have 4 possible combinations of
these extensions in the device tree, the default hardware behavior for
these possibilities are:
1. Neither svade nor svadu in DT: default to svade.
2. Only svade in DT: use svade.
3. Only svadu in DT: use svadu.
4. Both svade and svadu in DT: default to svade.
The Svade extension is mandatory and the Svadu extension is optional in
RVA23 profile. Platforms want to take the advantage of Svadu can choose
3. Those are aware of the profile can choose 4, and Linux won't get the
benefit of svadu until the SBI FWFT extension is available.
[1] https://lore.kernel.org/linux-kernel/20240527-e9845c06619bca5cd285098c@orel/T/#m29644eb88e241ec282df4ccd5199514e913b06ee
---
v5:
- remove all Acked-by and Reviewed-by (Conor, Andrew)
- add Svade support
- update the arch_has_hw_pte_young() in PATCH1
- update the dtbinding in PATCH2 (Alexandre, Andrew)
- check the availibility of Svadu for Guest/VM based on
arch_has_hw_pte_young() in PATCH3
v4:
- fix 32bit kernel build error in PATCH1 (Conor)
- update the status of Svadu extension to ratified in PATCH2
- add the PATCH4 to suporrt SBI_FWFT_PTE_AD_HW_UPDATING for guest OS
- update the PATCH1 and PATCH3 to integrate with FWFT extension
- rebase PATCH5 on the lastest get-reg-list test (Andrew)
v3:
- fix the control bit name to ADUE in PATCH1 and PATCH3
- update get-reg-list in PATCH4
v2:
- add Co-developed-by: in PATCH1
- use riscv_has_extension_unlikely() to runtime patch the branch in PATCH1
- update dt-binding
Yong-Xuan Wang (4):
RISC-V: Add Svade and Svadu Extensions Support
dt-bindings: riscv: Add Svade and Svadu Entries
RISC-V: KVM: Add Svade and Svadu Extensions Support for Guest/VM
KVM: riscv: selftests: Add Svade and Svadu Extension to get-reg-list
test
.../devicetree/bindings/riscv/extensions.yaml | 30 +++++++++++++++++++
arch/riscv/Kconfig | 1 +
arch/riscv/include/asm/csr.h | 1 +
arch/riscv/include/asm/hwcap.h | 2 ++
arch/riscv/include/asm/pgtable.h | 14 ++++++++-
arch/riscv/include/uapi/asm/kvm.h | 2 ++
arch/riscv/kernel/cpufeature.c | 2 ++
arch/riscv/kvm/vcpu.c | 6 ++++
arch/riscv/kvm/vcpu_onereg.c | 6 ++++
.../selftests/kvm/riscv/get-reg-list.c | 8 +++++
10 files changed, 71 insertions(+), 1 deletion(-)
--
2.17.1
Update the get-reg-list test to test the Svade and Svadu Extensions are
available for guest OS.
Signed-off-by: Yong-Xuan Wang <[email protected]>
---
tools/testing/selftests/kvm/riscv/get-reg-list.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/tools/testing/selftests/kvm/riscv/get-reg-list.c b/tools/testing/selftests/kvm/riscv/get-reg-list.c
index 222198dd6d04..1d32351ad55e 100644
--- a/tools/testing/selftests/kvm/riscv/get-reg-list.c
+++ b/tools/testing/selftests/kvm/riscv/get-reg-list.c
@@ -45,6 +45,8 @@ bool filter_reg(__u64 reg)
case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_SSAIA:
case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_SSCOFPMF:
case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_SSTC:
+ case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_SVADE:
+ case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_SVADU:
case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_SVINVAL:
case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_SVNAPOT:
case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_SVPBMT:
@@ -411,6 +413,8 @@ static const char *isa_ext_single_id_to_str(__u64 reg_off)
KVM_ISA_EXT_ARR(SSAIA),
KVM_ISA_EXT_ARR(SSCOFPMF),
KVM_ISA_EXT_ARR(SSTC),
+ KVM_ISA_EXT_ARR(SVADE),
+ KVM_ISA_EXT_ARR(SVADU),
KVM_ISA_EXT_ARR(SVINVAL),
KVM_ISA_EXT_ARR(SVNAPOT),
KVM_ISA_EXT_ARR(SVPBMT),
@@ -935,6 +939,8 @@ KVM_ISA_EXT_SIMPLE_CONFIG(h, H);
KVM_ISA_EXT_SUBLIST_CONFIG(smstateen, SMSTATEEN);
KVM_ISA_EXT_SIMPLE_CONFIG(sscofpmf, SSCOFPMF);
KVM_ISA_EXT_SIMPLE_CONFIG(sstc, SSTC);
+KVM_ISA_EXT_SIMPLE_CONFIG(svade, SVADE);
+KVM_ISA_EXT_SIMPLE_CONFIG(svadu, SVADU);
KVM_ISA_EXT_SIMPLE_CONFIG(svinval, SVINVAL);
KVM_ISA_EXT_SIMPLE_CONFIG(svnapot, SVNAPOT);
KVM_ISA_EXT_SIMPLE_CONFIG(svpbmt, SVPBMT);
@@ -991,6 +997,8 @@ struct vcpu_reg_list *vcpu_configs[] = {
&config_smstateen,
&config_sscofpmf,
&config_sstc,
+ &config_svade,
+ &config_svadu,
&config_svinval,
&config_svnapot,
&config_svpbmt,
--
2.17.1
We extend the KVM ISA extension ONE_REG interface to allow VMM tools to
detect and enable Svade and Svadu extensions for Guest/VM. Since the
henvcfg.ADUE is read-only zero if the menvcfg.ADUE is zero, the Svadu
extension is available for Guest/VM only when arch_has_hw_pte_young()
is true.
Signed-off-by: Yong-Xuan Wang <[email protected]>
---
arch/riscv/include/uapi/asm/kvm.h | 2 ++
arch/riscv/kvm/vcpu.c | 6 ++++++
arch/riscv/kvm/vcpu_onereg.c | 6 ++++++
3 files changed, 14 insertions(+)
diff --git a/arch/riscv/include/uapi/asm/kvm.h b/arch/riscv/include/uapi/asm/kvm.h
index e878e7cc3978..a5e0c35d7e9a 100644
--- a/arch/riscv/include/uapi/asm/kvm.h
+++ b/arch/riscv/include/uapi/asm/kvm.h
@@ -168,6 +168,8 @@ enum KVM_RISCV_ISA_EXT_ID {
KVM_RISCV_ISA_EXT_ZTSO,
KVM_RISCV_ISA_EXT_ZACAS,
KVM_RISCV_ISA_EXT_SSCOFPMF,
+ KVM_RISCV_ISA_EXT_SVADE,
+ KVM_RISCV_ISA_EXT_SVADU,
KVM_RISCV_ISA_EXT_MAX,
};
diff --git a/arch/riscv/kvm/vcpu.c b/arch/riscv/kvm/vcpu.c
index 17e21df36cc1..21edd60c4756 100644
--- a/arch/riscv/kvm/vcpu.c
+++ b/arch/riscv/kvm/vcpu.c
@@ -540,6 +540,12 @@ static void kvm_riscv_vcpu_setup_config(struct kvm_vcpu *vcpu)
if (riscv_isa_extension_available(isa, ZICBOZ))
cfg->henvcfg |= ENVCFG_CBZE;
+ if (riscv_isa_extension_available(isa, SVADU))
+ cfg->henvcfg |= ENVCFG_ADUE;
+
+ if (riscv_isa_extension_available(isa, SVADE))
+ cfg->henvcfg &= ~ENVCFG_ADUE;
+
if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN)) {
cfg->hstateen0 |= SMSTATEEN0_HSENVCFG;
if (riscv_isa_extension_available(isa, SSAIA))
diff --git a/arch/riscv/kvm/vcpu_onereg.c b/arch/riscv/kvm/vcpu_onereg.c
index c676275ea0a0..06e930f1e206 100644
--- a/arch/riscv/kvm/vcpu_onereg.c
+++ b/arch/riscv/kvm/vcpu_onereg.c
@@ -15,6 +15,7 @@
#include <asm/cacheflush.h>
#include <asm/cpufeature.h>
#include <asm/kvm_vcpu_vector.h>
+#include <asm/pgtable.h>
#include <asm/vector.h>
#define KVM_RISCV_BASE_ISA_MASK GENMASK(25, 0)
@@ -38,6 +39,8 @@ static const unsigned long kvm_isa_ext_arr[] = {
KVM_ISA_EXT_ARR(SSAIA),
KVM_ISA_EXT_ARR(SSCOFPMF),
KVM_ISA_EXT_ARR(SSTC),
+ KVM_ISA_EXT_ARR(SVADE),
+ KVM_ISA_EXT_ARR(SVADU),
KVM_ISA_EXT_ARR(SVINVAL),
KVM_ISA_EXT_ARR(SVNAPOT),
KVM_ISA_EXT_ARR(SVPBMT),
@@ -105,6 +108,9 @@ static bool kvm_riscv_vcpu_isa_enable_allowed(unsigned long ext)
return __riscv_isa_extension_available(NULL, RISCV_ISA_EXT_SSAIA);
case KVM_RISCV_ISA_EXT_V:
return riscv_v_vstate_ctrl_user_allowed();
+ case KVM_RISCV_ISA_EXT_SVADU:
+ /* The henvcfg.ADUE is read-only zero if menvcfg.ADUE is zero. */
+ return arch_has_hw_pte_young();
default:
break;
}
--
2.17.1
Svade and Svadu extensions represent two schemes for managing the PTE A/D
bits. When the PTE A/D bits need to be set, Svade extension intdicates
that a related page fault will be raised. In contrast, the Svadu extension
supports hardware updating of PTE A/D bits. Since the Svade extension is
mandatory and the Svadu extension is optional in RVA23 profile, by default
the M-mode firmware will enable the Svadu extension in the menvcfg CSR
when only Svadu is present in DT.
This patch detects Svade and Svadu extensions from DT and adds
arch_has_hw_pte_young() to enable optimization in MGLRU and
__wp_page_copy_user() when we have the PTE A/D bits hardware updating
support.
Co-developed-by: Jinyu Tang <[email protected]>
Signed-off-by: Jinyu Tang <[email protected]>
Signed-off-by: Yong-Xuan Wang <[email protected]>
---
arch/riscv/Kconfig | 1 +
arch/riscv/include/asm/csr.h | 1 +
arch/riscv/include/asm/hwcap.h | 2 ++
arch/riscv/include/asm/pgtable.h | 14 +++++++++++++-
arch/riscv/kernel/cpufeature.c | 2 ++
5 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index b94176e25be1..dbfe2be99bf9 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -36,6 +36,7 @@ config RISCV
select ARCH_HAS_PMEM_API
select ARCH_HAS_PREPARE_SYNC_CORE_CMD
select ARCH_HAS_PTE_SPECIAL
+ select ARCH_HAS_HW_PTE_YOUNG
select ARCH_HAS_SET_DIRECT_MAP if MMU
select ARCH_HAS_SET_MEMORY if MMU
select ARCH_HAS_STRICT_KERNEL_RWX if MMU && !XIP_KERNEL
diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h
index 25966995da04..524cd4131c71 100644
--- a/arch/riscv/include/asm/csr.h
+++ b/arch/riscv/include/asm/csr.h
@@ -195,6 +195,7 @@
/* xENVCFG flags */
#define ENVCFG_STCE (_AC(1, ULL) << 63)
#define ENVCFG_PBMTE (_AC(1, ULL) << 62)
+#define ENVCFG_ADUE (_AC(1, ULL) << 61)
#define ENVCFG_CBZE (_AC(1, UL) << 7)
#define ENVCFG_CBCFE (_AC(1, UL) << 6)
#define ENVCFG_CBIE_SHIFT 4
diff --git a/arch/riscv/include/asm/hwcap.h b/arch/riscv/include/asm/hwcap.h
index e17d0078a651..35d7aa49785d 100644
--- a/arch/riscv/include/asm/hwcap.h
+++ b/arch/riscv/include/asm/hwcap.h
@@ -81,6 +81,8 @@
#define RISCV_ISA_EXT_ZTSO 72
#define RISCV_ISA_EXT_ZACAS 73
#define RISCV_ISA_EXT_XANDESPMU 74
+#define RISCV_ISA_EXT_SVADE 75
+#define RISCV_ISA_EXT_SVADU 76
#define RISCV_ISA_EXT_XLINUXENVCFG 127
diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
index aad8b8ca51f1..7287ea4a6160 100644
--- a/arch/riscv/include/asm/pgtable.h
+++ b/arch/riscv/include/asm/pgtable.h
@@ -120,6 +120,7 @@
#include <asm/tlbflush.h>
#include <linux/mm_types.h>
#include <asm/compat.h>
+#include <asm/cpufeature.h>
#define __page_val_to_pfn(_val) (((_val) & _PAGE_PFN_MASK) >> _PAGE_PFN_SHIFT)
@@ -288,7 +289,6 @@ static inline pte_t pud_pte(pud_t pud)
}
#ifdef CONFIG_RISCV_ISA_SVNAPOT
-#include <asm/cpufeature.h>
static __always_inline bool has_svnapot(void)
{
@@ -624,6 +624,18 @@ static inline pgprot_t pgprot_writecombine(pgprot_t _prot)
return __pgprot(prot);
}
+/*
+ * Both Svade and Svadu control the hardware behavior when the PTE A/D bits need to be set. By
+ * default the M-mode firmware enables the hardware updating scheme when only Svadu is present in
+ * DT.
+ */
+#define arch_has_hw_pte_young arch_has_hw_pte_young
+static inline bool arch_has_hw_pte_young(void)
+{
+ return riscv_has_extension_unlikely(RISCV_ISA_EXT_SVADU) &&
+ !riscv_has_extension_likely(RISCV_ISA_EXT_SVADE);
+}
+
/*
* THP functions
*/
diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
index 5ef48cb20ee1..58565798cea0 100644
--- a/arch/riscv/kernel/cpufeature.c
+++ b/arch/riscv/kernel/cpufeature.c
@@ -301,6 +301,8 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = {
__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),
+ __RISCV_ISA_EXT_DATA(svade, RISCV_ISA_EXT_SVADE),
+ __RISCV_ISA_EXT_DATA(svadu, RISCV_ISA_EXT_SVADU),
__RISCV_ISA_EXT_DATA(svinval, RISCV_ISA_EXT_SVINVAL),
__RISCV_ISA_EXT_DATA(svnapot, RISCV_ISA_EXT_SVNAPOT),
__RISCV_ISA_EXT_DATA(svpbmt, RISCV_ISA_EXT_SVPBMT),
--
2.17.1
Add entries for the Svade and Svadu extensions to the riscv,isa-extensions
property.
Signed-off-by: Yong-Xuan Wang <[email protected]>
---
.../devicetree/bindings/riscv/extensions.yaml | 30 +++++++++++++++++++
1 file changed, 30 insertions(+)
diff --git a/Documentation/devicetree/bindings/riscv/extensions.yaml b/Documentation/devicetree/bindings/riscv/extensions.yaml
index 468c646247aa..1e30988826b9 100644
--- a/Documentation/devicetree/bindings/riscv/extensions.yaml
+++ b/Documentation/devicetree/bindings/riscv/extensions.yaml
@@ -153,6 +153,36 @@ properties:
ratified at commit 3f9ed34 ("Add ability to manually trigger
workflow. (#2)") of riscv-time-compare.
+ - const: svade
+ description: |
+ The standard Svade supervisor-level extension for raising page-fault
+ exceptions when PTE A/D bits need be set as ratified in the 20240213
+ version of the privileged ISA specification.
+
+ Both Svade and Svadu extensions control the hardware behavior when
+ the PTE A/D bits need to be set. The default behavior for the four
+ possible combinations of these extensions in the device tree are:
+ 1. Neither svade nor svadu in DT: default to svade.
+ 2. Only svade in DT: use svade.
+ 3. Only svadu in DT: use svadu.
+ 4. Both svade and svadu in DT: default to svade (Linux can switch to
+ svadu once the SBI FWFT extension is available).
+
+ - const: svadu
+ description: |
+ The standard Svadu supervisor-level extension for hardware updating
+ of PTE A/D bits as ratified at commit c1abccf ("Merge pull request
+ #25 from ved-rivos/ratified") of riscv-svadu.
+
+ Both Svade and Svadu extensions control the hardware behavior when
+ the PTE A/D bits need to be set. The default behavior for the four
+ possible combinations of these extensions in the device tree are:
+ 1. Neither svade nor svadu in DT: default to svade.
+ 2. Only svade in DT: use svade.
+ 3. Only svadu in DT: use svadu.
+ 4. Both svade and svadu in DT: default to svade (Linux can switch to
+ svadu once the SBI FWFT extension is available).
+
- const: svinval
description:
The standard Svinval supervisor-level extension for fine-grained
--
2.17.1
On Wed, Jun 05, 2024 at 08:15:08PM +0800, Yong-Xuan Wang wrote:
> Add entries for the Svade and Svadu extensions to the riscv,isa-extensions
> property.
>
> Signed-off-by: Yong-Xuan Wang <[email protected]>
> ---
> .../devicetree/bindings/riscv/extensions.yaml | 30 +++++++++++++++++++
> 1 file changed, 30 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/riscv/extensions.yaml b/Documentation/devicetree/bindings/riscv/extensions.yaml
> index 468c646247aa..1e30988826b9 100644
> --- a/Documentation/devicetree/bindings/riscv/extensions.yaml
> +++ b/Documentation/devicetree/bindings/riscv/extensions.yaml
> @@ -153,6 +153,36 @@ properties:
> ratified at commit 3f9ed34 ("Add ability to manually trigger
> workflow. (#2)") of riscv-time-compare.
>
> + - const: svade
> + description: |
> + The standard Svade supervisor-level extension for raising page-fault
> + exceptions when PTE A/D bits need be set as ratified in the 20240213
> + version of the privileged ISA specification.
> +
> + Both Svade and Svadu extensions control the hardware behavior when
> + the PTE A/D bits need to be set. The default behavior for the four
> + possible combinations of these extensions in the device tree are:
> + 1. Neither svade nor svadu in DT: default to svade.
I think this needs to be expanded on, as to why nothing means svade.
> + 2. Only svade in DT: use svade.
That's a statement of the obvious, right?
> + 3. Only svadu in DT: use svadu.
This is not relevant for Svade.
> + 4. Both svade and svadu in DT: default to svade (Linux can switch to
> + svadu once the SBI FWFT extension is available).
"The privilege level to which this devicetree has been provided can switch to
Svadu if the SBI FWFT extension is available".
> + - const: svadu
> + description: |
> + The standard Svadu supervisor-level extension for hardware updating
> + of PTE A/D bits as ratified at commit c1abccf ("Merge pull request
> + #25 from ved-rivos/ratified") of riscv-svadu.
> +
> + Both Svade and Svadu extensions control the hardware behavior when
> + the PTE A/D bits need to be set. The default behavior for the four
> + possible combinations of these extensions in the device tree are:
@Anup/Drew/Alex, are we missing some wording in here about it only being
valid to have Svadu in isolation if the provider of the devicetree has
actually turned on Svadu? The binding says "the default behaviour", but
it is not the "default" behaviour, the behaviour is a must AFAICT. If
you set Svadu in isolation, you /must/ have turned it on. If you set
Svadu and Svade, you must have Svadu turned off?
> + 1. Neither svade nor svadu in DT: default to svade.
> + 2. Only svade in DT: use svade.
These two are not relevant to Svadu, I'd leave them out.
> + 3. Only svadu in DT: use svadu.
Again, statement of the obvious?
> + 4. Both svade and svadu in DT: default to svade (Linux can switch to
> + svadu once the SBI FWFT extension is available).
Same here as in the Svade entry.
Thanks,
Conor.