diff mbox series

[RFC,6/7] riscv: kvm: add SBI FWFT support for SBI_FWFT_DOUBLE_TRAP_ENABLE

Message ID 20240418142701.1493091-7-cleger@rivosinc.com (mailing list archive)
State New, archived
Headers show
Series riscv: Add support for Ssdbltrp extension | expand

Commit Message

Clément Léger April 18, 2024, 2:26 p.m. UTC
Add support in KVM SBI FWFT extension to allow VS-mode to request double
trap enabling. Double traps can then be generated by VS-mode, allowing
M-mode to redirect them to S-mode.

Signed-off-by: Clément Léger <cleger@rivosinc.com>
---
 arch/riscv/include/asm/csr.h               |  1 +
 arch/riscv/include/asm/kvm_vcpu_sbi_fwft.h |  2 +-
 arch/riscv/kvm/vcpu_sbi_fwft.c             | 41 ++++++++++++++++++++++
 3 files changed, 43 insertions(+), 1 deletion(-)

Comments

Deepak Gupta April 27, 2024, 1:17 a.m. UTC | #1
On Thu, Apr 18, 2024 at 04:26:45PM +0200, Clément Léger wrote:
>Add support in KVM SBI FWFT extension to allow VS-mode to request double
>trap enabling. Double traps can then be generated by VS-mode, allowing
>M-mode to redirect them to S-mode.
>
>Signed-off-by: Clément Léger <cleger@rivosinc.com>
>---
> arch/riscv/include/asm/csr.h               |  1 +
> arch/riscv/include/asm/kvm_vcpu_sbi_fwft.h |  2 +-
> arch/riscv/kvm/vcpu_sbi_fwft.c             | 41 ++++++++++++++++++++++
> 3 files changed, 43 insertions(+), 1 deletion(-)
>
>diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h
>index 905cdf894a57..ee1b73655bec 100644
>--- a/arch/riscv/include/asm/csr.h
>+++ b/arch/riscv/include/asm/csr.h
>@@ -196,6 +196,7 @@
> /* xENVCFG flags */
> #define ENVCFG_STCE			(_AC(1, ULL) << 63)
> #define ENVCFG_PBMTE			(_AC(1, ULL) << 62)
>+#define ENVCFG_DTE			(_AC(1, ULL) << 59)
> #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/kvm_vcpu_sbi_fwft.h b/arch/riscv/include/asm/kvm_vcpu_sbi_fwft.h
>index 7dc1b80c7e6c..a9e20d655126 100644
>--- a/arch/riscv/include/asm/kvm_vcpu_sbi_fwft.h
>+++ b/arch/riscv/include/asm/kvm_vcpu_sbi_fwft.h
>@@ -11,7 +11,7 @@
>
> #include <asm/sbi.h>
>
>-#define KVM_SBI_FWFT_FEATURE_COUNT	1
>+#define KVM_SBI_FWFT_FEATURE_COUNT	2
>
> struct kvm_sbi_fwft_config;
> struct kvm_vcpu;
>diff --git a/arch/riscv/kvm/vcpu_sbi_fwft.c b/arch/riscv/kvm/vcpu_sbi_fwft.c
>index b9b7f8fa6d22..9e8e397eb02f 100644
>--- a/arch/riscv/kvm/vcpu_sbi_fwft.c
>+++ b/arch/riscv/kvm/vcpu_sbi_fwft.c
>@@ -9,10 +9,19 @@
> #include <linux/errno.h>
> #include <linux/err.h>
> #include <linux/kvm_host.h>
>+#include <linux/riscv_dbltrp.h>
> #include <asm/sbi.h>
> #include <asm/kvm_vcpu_sbi.h>
> #include <asm/kvm_vcpu_sbi_fwft.h>
>
>+#ifdef CONFIG_32BIT
>+# define CSR_HENVCFG_DBLTRP	CSR_HENVCFGH
>+# define DBLTRP_DTE	(ENVCFG_DTE >> 32)
>+#else
>+# define CSR_HENVCFG_DBLTRP	CSR_HENVCFG
>+# define DBLTRP_DTE	ENVCFG_DTE
>+#endif
>+
> #define MIS_DELEG (1UL << EXC_LOAD_MISALIGNED | 1UL << EXC_STORE_MISALIGNED)
>
> static int kvm_sbi_fwft_set_misaligned_delegation(struct kvm_vcpu *vcpu,
>@@ -36,6 +45,33 @@ static int kvm_sbi_fwft_get_misaligned_delegation(struct kvm_vcpu *vcpu,
> 	return SBI_SUCCESS;
> }
>
>+static int kvm_sbi_fwft_set_double_trap(struct kvm_vcpu *vcpu,
>+					struct kvm_sbi_fwft_config *conf,
>+					unsigned long value)
>+{
>+	if (!riscv_double_trap_enabled())
>+		return SBI_ERR_NOT_SUPPORTED;

Why its required to check whether host has enabled double trap for itself ?
It's orthogonal to guest asking hypervisor to enable double trap.

Probably you need a check here whether underlying FW supports handling double
trap.

Am I missing something here?

>+
>+	if (value)
>+		csr_set(CSR_HENVCFG_DBLTRP, DBLTRP_DTE);
>+	else
>+		csr_clear(CSR_HENVCFG_DBLTRP, DBLTRP_DTE);

I think vcpu->arch.cfg has `henvcfg` field. Can we reflect it there as well so that current
`henvcfg` copy in vcpu arch specifci config is consistent? Otherwise it'll be lost when vCPU
is scheduled out and later scheduled back in (on vcpu load)

Furthermore, lets not do feature specific alias names for CSR.

Instead let's keep consistent 64bit image of henvcfg in vcpu->arch.cfg.

And whenever it's time to pick up the setting, pick up logic either perform the writes in
henvcfg. And if required it'll perform henvcfgh too (as `kvm_arch_vcpu_load` already does)

>+
>+	return SBI_SUCCESS;
>+}
>+
>+static int kvm_sbi_fwft_get_double_trap(struct kvm_vcpu *vcpu,
>+					struct kvm_sbi_fwft_config *conf,
>+					unsigned long *value)
>+{
>+	if (!riscv_double_trap_enabled())
>+		return SBI_ERR_NOT_SUPPORTED;
>+
>+	*value = (csr_read(CSR_HENVCFG_DBLTRP) & DBLTRP_DTE) != 0;
>+
>+	return SBI_SUCCESS;
>+}
>+
> static struct kvm_sbi_fwft_config *
> kvm_sbi_fwft_get_config(struct kvm_vcpu *vcpu, enum sbi_fwft_feature_t feature)
> {
>@@ -111,6 +147,11 @@ static const struct kvm_sbi_fwft_feature features[] = {
> 		.id = SBI_FWFT_MISALIGNED_DELEG,
> 		.set = kvm_sbi_fwft_set_misaligned_delegation,
> 		.get = kvm_sbi_fwft_get_misaligned_delegation,
>+	},
>+	{
>+		.id = SBI_FWFT_DOUBLE_TRAP_ENABLE,
>+		.set = kvm_sbi_fwft_set_double_trap,
>+		.get = kvm_sbi_fwft_get_double_trap,
> 	}
> };
>
>-- 
>2.43.0
>
>
Deepak Gupta April 27, 2024, 3:36 p.m. UTC | #2
On Fri, Apr 26, 2024 at 06:17:08PM -0700, Deepak Gupta wrote:
>On Thu, Apr 18, 2024 at 04:26:45PM +0200, Clément Léger wrote:
>>Add support in KVM SBI FWFT extension to allow VS-mode to request double
>>trap enabling. Double traps can then be generated by VS-mode, allowing
>>M-mode to redirect them to S-mode.
>>
>>Signed-off-by: Clément Léger <cleger@rivosinc.com>
>>---
>>arch/riscv/include/asm/csr.h               |  1 +
>>arch/riscv/include/asm/kvm_vcpu_sbi_fwft.h |  2 +-
>>arch/riscv/kvm/vcpu_sbi_fwft.c             | 41 ++++++++++++++++++++++
>>3 files changed, 43 insertions(+), 1 deletion(-)
>>
>>diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h
>>index 905cdf894a57..ee1b73655bec 100644
>>--- a/arch/riscv/include/asm/csr.h
>>+++ b/arch/riscv/include/asm/csr.h
>>@@ -196,6 +196,7 @@
>>/* xENVCFG flags */
>>#define ENVCFG_STCE			(_AC(1, ULL) << 63)
>>#define ENVCFG_PBMTE			(_AC(1, ULL) << 62)
>>+#define ENVCFG_DTE			(_AC(1, ULL) << 59)
>>#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/kvm_vcpu_sbi_fwft.h b/arch/riscv/include/asm/kvm_vcpu_sbi_fwft.h
>>index 7dc1b80c7e6c..a9e20d655126 100644
>>--- a/arch/riscv/include/asm/kvm_vcpu_sbi_fwft.h
>>+++ b/arch/riscv/include/asm/kvm_vcpu_sbi_fwft.h
>>@@ -11,7 +11,7 @@
>>
>>#include <asm/sbi.h>
>>
>>-#define KVM_SBI_FWFT_FEATURE_COUNT	1
>>+#define KVM_SBI_FWFT_FEATURE_COUNT	2
>>
>>struct kvm_sbi_fwft_config;
>>struct kvm_vcpu;
>>diff --git a/arch/riscv/kvm/vcpu_sbi_fwft.c b/arch/riscv/kvm/vcpu_sbi_fwft.c
>>index b9b7f8fa6d22..9e8e397eb02f 100644
>>--- a/arch/riscv/kvm/vcpu_sbi_fwft.c
>>+++ b/arch/riscv/kvm/vcpu_sbi_fwft.c
>>@@ -9,10 +9,19 @@
>>#include <linux/errno.h>
>>#include <linux/err.h>
>>#include <linux/kvm_host.h>
>>+#include <linux/riscv_dbltrp.h>
>>#include <asm/sbi.h>
>>#include <asm/kvm_vcpu_sbi.h>
>>#include <asm/kvm_vcpu_sbi_fwft.h>
>>
>>+#ifdef CONFIG_32BIT
>>+# define CSR_HENVCFG_DBLTRP	CSR_HENVCFGH
>>+# define DBLTRP_DTE	(ENVCFG_DTE >> 32)
>>+#else
>>+# define CSR_HENVCFG_DBLTRP	CSR_HENVCFG
>>+# define DBLTRP_DTE	ENVCFG_DTE
>>+#endif
>>+
>>#define MIS_DELEG (1UL << EXC_LOAD_MISALIGNED | 1UL << EXC_STORE_MISALIGNED)
>>
>>static int kvm_sbi_fwft_set_misaligned_delegation(struct kvm_vcpu *vcpu,
>>@@ -36,6 +45,33 @@ static int kvm_sbi_fwft_get_misaligned_delegation(struct kvm_vcpu *vcpu,
>>	return SBI_SUCCESS;
>>}
>>
>>+static int kvm_sbi_fwft_set_double_trap(struct kvm_vcpu *vcpu,
>>+					struct kvm_sbi_fwft_config *conf,
>>+					unsigned long value)
>>+{
>>+	if (!riscv_double_trap_enabled())
>>+		return SBI_ERR_NOT_SUPPORTED;
>
>Why its required to check whether host has enabled double trap for itself ?
>It's orthogonal to guest asking hypervisor to enable double trap.
>
>Probably you need a check here whether underlying FW supports handling double
>trap.
>
>Am I missing something here?
>

On this I am indeed missing that menvcfg.DTE has to be 1 for any less priv.
So, nevermind on this comment. Sorry about that.
Clément Léger May 14, 2024, 9:43 a.m. UTC | #3
On 27/04/2024 03:17, Deepak Gupta wrote:
> On Thu, Apr 18, 2024 at 04:26:45PM +0200, Clément Léger wrote:
>> Add support in KVM SBI FWFT extension to allow VS-mode to request double
>> trap enabling. Double traps can then be generated by VS-mode, allowing
>> M-mode to redirect them to S-mode.
>>
>> Signed-off-by: Clément Léger <cleger@rivosinc.com>
>> ---
>> arch/riscv/include/asm/csr.h               |  1 +
>> arch/riscv/include/asm/kvm_vcpu_sbi_fwft.h |  2 +-
>> arch/riscv/kvm/vcpu_sbi_fwft.c             | 41 ++++++++++++++++++++++
>> 3 files changed, 43 insertions(+), 1 deletion(-)
>>
>> diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h
>> index 905cdf894a57..ee1b73655bec 100644
>> --- a/arch/riscv/include/asm/csr.h
>> +++ b/arch/riscv/include/asm/csr.h
>> @@ -196,6 +196,7 @@
>> /* xENVCFG flags */
>> #define ENVCFG_STCE            (_AC(1, ULL) << 63)
>> #define ENVCFG_PBMTE            (_AC(1, ULL) << 62)
>> +#define ENVCFG_DTE            (_AC(1, ULL) << 59)
>> #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/kvm_vcpu_sbi_fwft.h
>> b/arch/riscv/include/asm/kvm_vcpu_sbi_fwft.h
>> index 7dc1b80c7e6c..a9e20d655126 100644
>> --- a/arch/riscv/include/asm/kvm_vcpu_sbi_fwft.h
>> +++ b/arch/riscv/include/asm/kvm_vcpu_sbi_fwft.h
>> @@ -11,7 +11,7 @@
>>
>> #include <asm/sbi.h>
>>
>> -#define KVM_SBI_FWFT_FEATURE_COUNT    1
>> +#define KVM_SBI_FWFT_FEATURE_COUNT    2
>>
>> struct kvm_sbi_fwft_config;
>> struct kvm_vcpu;
>> diff --git a/arch/riscv/kvm/vcpu_sbi_fwft.c
>> b/arch/riscv/kvm/vcpu_sbi_fwft.c
>> index b9b7f8fa6d22..9e8e397eb02f 100644
>> --- a/arch/riscv/kvm/vcpu_sbi_fwft.c
>> +++ b/arch/riscv/kvm/vcpu_sbi_fwft.c
>> @@ -9,10 +9,19 @@
>> #include <linux/errno.h>
>> #include <linux/err.h>
>> #include <linux/kvm_host.h>
>> +#include <linux/riscv_dbltrp.h>
>> #include <asm/sbi.h>
>> #include <asm/kvm_vcpu_sbi.h>
>> #include <asm/kvm_vcpu_sbi_fwft.h>
>>
>> +#ifdef CONFIG_32BIT
>> +# define CSR_HENVCFG_DBLTRP    CSR_HENVCFGH
>> +# define DBLTRP_DTE    (ENVCFG_DTE >> 32)
>> +#else
>> +# define CSR_HENVCFG_DBLTRP    CSR_HENVCFG
>> +# define DBLTRP_DTE    ENVCFG_DTE
>> +#endif
>> +
>> #define MIS_DELEG (1UL << EXC_LOAD_MISALIGNED | 1UL <<
>> EXC_STORE_MISALIGNED)
>>
>> static int kvm_sbi_fwft_set_misaligned_delegation(struct kvm_vcpu *vcpu,
>> @@ -36,6 +45,33 @@ static int
>> kvm_sbi_fwft_get_misaligned_delegation(struct kvm_vcpu *vcpu,
>>     return SBI_SUCCESS;
>> }
>>
>> +static int kvm_sbi_fwft_set_double_trap(struct kvm_vcpu *vcpu,
>> +                    struct kvm_sbi_fwft_config *conf,
>> +                    unsigned long value)
>> +{
>> +    if (!riscv_double_trap_enabled())
>> +        return SBI_ERR_NOT_SUPPORTED;
> 
> Why its required to check whether host has enabled double trap for itself ?
> It's orthogonal to guest asking hypervisor to enable double trap.

Hi Deepak,

Indeed, as you saw, henvcfg.DTE needs menvcfg.DTE to be enabled in order
to be usable.

> 
> Probably you need a check here whether underlying FW supports handling
> double
> trap.
> 
> Am I missing something here?
> 
>> +
>> +    if (value)
>> +        csr_set(CSR_HENVCFG_DBLTRP, DBLTRP_DTE);
>> +    else
>> +        csr_clear(CSR_HENVCFG_DBLTRP, DBLTRP_DTE);
> 
> I think vcpu->arch.cfg has `henvcfg` field. Can we reflect it there as
> well so that current
> `henvcfg` copy in vcpu arch specifci config is consistent? Otherwise
> it'll be lost when vCPU
> is scheduled out and later scheduled back in (on vcpu load)

henvcfg is restored when loading the vpcu (kvm_arch_vcpu_load()) and
saved when the CPU is put (kvm_arch_vcpu_put()). But I just saw that
this change is included in the next patch. Should have been this one ,
I'll fix that.


> 
> Furthermore, lets not do feature specific alias names for CSR.
> 
> Instead let's keep consistent 64bit image of henvcfg in vcpu->arch.cfg.
> 
> And whenever it's time to pick up the setting, pick up logic either
> perform the writes in
> henvcfg. And if required it'll perform henvcfgh too (as
> `kvm_arch_vcpu_load` already does)

I don't have a strong opinion on that point so if you think it really is
better, I'll switch to that.

Thanks,

Clément

> 
>> +
>> +    return SBI_SUCCESS;
>> +}
>> +
>> +static int kvm_sbi_fwft_get_double_trap(struct kvm_vcpu *vcpu,
>> +                    struct kvm_sbi_fwft_config *conf,
>> +                    unsigned long *value)
>> +{
>> +    if (!riscv_double_trap_enabled())
>> +        return SBI_ERR_NOT_SUPPORTED;
>> +
>> +    *value = (csr_read(CSR_HENVCFG_DBLTRP) & DBLTRP_DTE) != 0;
>> +
>> +    return SBI_SUCCESS;
>> +}
>> +
>> static struct kvm_sbi_fwft_config *
>> kvm_sbi_fwft_get_config(struct kvm_vcpu *vcpu, enum sbi_fwft_feature_t
>> feature)
>> {
>> @@ -111,6 +147,11 @@ static const struct kvm_sbi_fwft_feature
>> features[] = {
>>         .id = SBI_FWFT_MISALIGNED_DELEG,
>>         .set = kvm_sbi_fwft_set_misaligned_delegation,
>>         .get = kvm_sbi_fwft_get_misaligned_delegation,
>> +    },
>> +    {
>> +        .id = SBI_FWFT_DOUBLE_TRAP_ENABLE,
>> +        .set = kvm_sbi_fwft_set_double_trap,
>> +        .get = kvm_sbi_fwft_get_double_trap,
>>     }
>> };
>>
>> -- 
>> 2.43.0
>>
>>
Deepak Gupta May 14, 2024, 4:05 p.m. UTC | #4
On Tue, May 14, 2024 at 11:43:15AM +0200, Clément Léger wrote:
>
>
>On 27/04/2024 03:17, Deepak Gupta wrote:
>> On Thu, Apr 18, 2024 at 04:26:45PM +0200, Clément Léger wrote:
>>> Add support in KVM SBI FWFT extension to allow VS-mode to request double
>>> trap enabling. Double traps can then be generated by VS-mode, allowing
>>> M-mode to redirect them to S-mode.
>>>
>>
>>> +
>>> +    if (value)
>>> +        csr_set(CSR_HENVCFG_DBLTRP, DBLTRP_DTE);
>>> +    else
>>> +        csr_clear(CSR_HENVCFG_DBLTRP, DBLTRP_DTE);
>>
>> I think vcpu->arch.cfg has `henvcfg` field. Can we reflect it there as
>> well so that current
>> `henvcfg` copy in vcpu arch specifci config is consistent? Otherwise
>> it'll be lost when vCPU
>> is scheduled out and later scheduled back in (on vcpu load)
>
>henvcfg is restored when loading the vpcu (kvm_arch_vcpu_load()) and
>saved when the CPU is put (kvm_arch_vcpu_put()). But I just saw that
>this change is included in the next patch. Should have been this one ,
>I'll fix that.
>
>
>>
>> Furthermore, lets not do feature specific alias names for CSR.
>>
>> Instead let's keep consistent 64bit image of henvcfg in vcpu->arch.cfg.
>>
>> And whenever it's time to pick up the setting, pick up logic either
>> perform the writes in
>> henvcfg. And if required it'll perform henvcfgh too (as
>> `kvm_arch_vcpu_load` already does)
>
>I don't have a strong opinion on that point so if you think it really is
>better, I'll switch to that.

Thanks.

>
>Thanks,
>
>Clément
>
>>
>>> +
>>> +    return SBI_SUCCESS;
>>> +}
>>> +
>>> +static int kvm_sbi_fwft_get_double_trap(struct kvm_vcpu *vcpu,
>>> +                    struct kvm_sbi_fwft_config *conf,
>>> +                    unsigned long *value)
>>> +{
>>> +    if (!riscv_double_trap_enabled())
>>> +        return SBI_ERR_NOT_SUPPORTED;
>>> +
>>> +    *value = (csr_read(CSR_HENVCFG_DBLTRP) & DBLTRP_DTE) != 0;
>>> +
>>> +    return SBI_SUCCESS;
>>> +}
>>> +
>>> static struct kvm_sbi_fwft_config *
>>> kvm_sbi_fwft_get_config(struct kvm_vcpu *vcpu, enum sbi_fwft_feature_t
>>> feature)
>>> {
>>> @@ -111,6 +147,11 @@ static const struct kvm_sbi_fwft_feature
>>> features[] = {
>>>         .id = SBI_FWFT_MISALIGNED_DELEG,
>>>         .set = kvm_sbi_fwft_set_misaligned_delegation,
>>>         .get = kvm_sbi_fwft_get_misaligned_delegation,
>>> +    },
>>> +    {
>>> +        .id = SBI_FWFT_DOUBLE_TRAP_ENABLE,
>>> +        .set = kvm_sbi_fwft_set_double_trap,
>>> +        .get = kvm_sbi_fwft_get_double_trap,
>>>     }
>>> };
>>>
>>> -- 
>>> 2.43.0
>>>
>>>
diff mbox series

Patch

diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h
index 905cdf894a57..ee1b73655bec 100644
--- a/arch/riscv/include/asm/csr.h
+++ b/arch/riscv/include/asm/csr.h
@@ -196,6 +196,7 @@ 
 /* xENVCFG flags */
 #define ENVCFG_STCE			(_AC(1, ULL) << 63)
 #define ENVCFG_PBMTE			(_AC(1, ULL) << 62)
+#define ENVCFG_DTE			(_AC(1, ULL) << 59)
 #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/kvm_vcpu_sbi_fwft.h b/arch/riscv/include/asm/kvm_vcpu_sbi_fwft.h
index 7dc1b80c7e6c..a9e20d655126 100644
--- a/arch/riscv/include/asm/kvm_vcpu_sbi_fwft.h
+++ b/arch/riscv/include/asm/kvm_vcpu_sbi_fwft.h
@@ -11,7 +11,7 @@ 
 
 #include <asm/sbi.h>
 
-#define KVM_SBI_FWFT_FEATURE_COUNT	1
+#define KVM_SBI_FWFT_FEATURE_COUNT	2
 
 struct kvm_sbi_fwft_config;
 struct kvm_vcpu;
diff --git a/arch/riscv/kvm/vcpu_sbi_fwft.c b/arch/riscv/kvm/vcpu_sbi_fwft.c
index b9b7f8fa6d22..9e8e397eb02f 100644
--- a/arch/riscv/kvm/vcpu_sbi_fwft.c
+++ b/arch/riscv/kvm/vcpu_sbi_fwft.c
@@ -9,10 +9,19 @@ 
 #include <linux/errno.h>
 #include <linux/err.h>
 #include <linux/kvm_host.h>
+#include <linux/riscv_dbltrp.h>
 #include <asm/sbi.h>
 #include <asm/kvm_vcpu_sbi.h>
 #include <asm/kvm_vcpu_sbi_fwft.h>
 
+#ifdef CONFIG_32BIT
+# define CSR_HENVCFG_DBLTRP	CSR_HENVCFGH
+# define DBLTRP_DTE	(ENVCFG_DTE >> 32)
+#else
+# define CSR_HENVCFG_DBLTRP	CSR_HENVCFG
+# define DBLTRP_DTE	ENVCFG_DTE
+#endif
+
 #define MIS_DELEG (1UL << EXC_LOAD_MISALIGNED | 1UL << EXC_STORE_MISALIGNED)
 
 static int kvm_sbi_fwft_set_misaligned_delegation(struct kvm_vcpu *vcpu,
@@ -36,6 +45,33 @@  static int kvm_sbi_fwft_get_misaligned_delegation(struct kvm_vcpu *vcpu,
 	return SBI_SUCCESS;
 }
 
+static int kvm_sbi_fwft_set_double_trap(struct kvm_vcpu *vcpu,
+					struct kvm_sbi_fwft_config *conf,
+					unsigned long value)
+{
+	if (!riscv_double_trap_enabled())
+		return SBI_ERR_NOT_SUPPORTED;
+
+	if (value)
+		csr_set(CSR_HENVCFG_DBLTRP, DBLTRP_DTE);
+	else
+		csr_clear(CSR_HENVCFG_DBLTRP, DBLTRP_DTE);
+
+	return SBI_SUCCESS;
+}
+
+static int kvm_sbi_fwft_get_double_trap(struct kvm_vcpu *vcpu,
+					struct kvm_sbi_fwft_config *conf,
+					unsigned long *value)
+{
+	if (!riscv_double_trap_enabled())
+		return SBI_ERR_NOT_SUPPORTED;
+
+	*value = (csr_read(CSR_HENVCFG_DBLTRP) & DBLTRP_DTE) != 0;
+
+	return SBI_SUCCESS;
+}
+
 static struct kvm_sbi_fwft_config *
 kvm_sbi_fwft_get_config(struct kvm_vcpu *vcpu, enum sbi_fwft_feature_t feature)
 {
@@ -111,6 +147,11 @@  static const struct kvm_sbi_fwft_feature features[] = {
 		.id = SBI_FWFT_MISALIGNED_DELEG,
 		.set = kvm_sbi_fwft_set_misaligned_delegation,
 		.get = kvm_sbi_fwft_get_misaligned_delegation,
+	},
+	{
+		.id = SBI_FWFT_DOUBLE_TRAP_ENABLE,
+		.set = kvm_sbi_fwft_set_double_trap,
+		.get = kvm_sbi_fwft_get_double_trap,
 	}
 };