* [PATCH v4 01/18] riscv: add Firmware Feature (FWFT) SBI extensions definitions
2025-03-17 17:06 [PATCH v4 00/18] riscv: add SBI FWFT misaligned exception delegation support Clément Léger
@ 2025-03-17 17:06 ` Clément Léger
2025-03-17 17:06 ` [PATCH v4 02/18] riscv: sbi: add new SBI error mappings Clément Léger
` (16 subsequent siblings)
17 siblings, 0 replies; 28+ messages in thread
From: Clément Léger @ 2025-03-17 17:06 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Anup Patel, Atish Patra,
Shuah Khan, Jonathan Corbet, linux-riscv, linux-kernel, linux-doc,
kvm, kvm-riscv, linux-kselftest
Cc: Clément Léger, Samuel Holland, Andrew Jones,
Deepak Gupta
The Firmware Features extension (FWFT) was added as part of the SBI 3.0
specification. Add SBI definitions to use this extension.
Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Samuel Holland <samuel.holland@sifive.com>
Tested-by: Samuel Holland <samuel.holland@sifive.com>
Reviewed-by: Deepak Gupta <debug@rivosinc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
---
arch/riscv/include/asm/sbi.h | 33 +++++++++++++++++++++++++++++++++
1 file changed, 33 insertions(+)
diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h
index 3d250824178b..bb077d0c912f 100644
--- a/arch/riscv/include/asm/sbi.h
+++ b/arch/riscv/include/asm/sbi.h
@@ -35,6 +35,7 @@ enum sbi_ext_id {
SBI_EXT_DBCN = 0x4442434E,
SBI_EXT_STA = 0x535441,
SBI_EXT_NACL = 0x4E41434C,
+ SBI_EXT_FWFT = 0x46574654,
/* Experimentals extensions must lie within this range */
SBI_EXT_EXPERIMENTAL_START = 0x08000000,
@@ -402,6 +403,33 @@ enum sbi_ext_nacl_feature {
#define SBI_NACL_SHMEM_SRET_X(__i) ((__riscv_xlen / 8) * (__i))
#define SBI_NACL_SHMEM_SRET_X_LAST 31
+/* SBI function IDs for FW feature extension */
+#define SBI_EXT_FWFT_SET 0x0
+#define SBI_EXT_FWFT_GET 0x1
+
+enum sbi_fwft_feature_t {
+ SBI_FWFT_MISALIGNED_EXC_DELEG = 0x0,
+ SBI_FWFT_LANDING_PAD = 0x1,
+ SBI_FWFT_SHADOW_STACK = 0x2,
+ SBI_FWFT_DOUBLE_TRAP = 0x3,
+ SBI_FWFT_PTE_AD_HW_UPDATING = 0x4,
+ SBI_FWFT_POINTER_MASKING_PMLEN = 0x5,
+ SBI_FWFT_LOCAL_RESERVED_START = 0x6,
+ SBI_FWFT_LOCAL_RESERVED_END = 0x3fffffff,
+ SBI_FWFT_LOCAL_PLATFORM_START = 0x40000000,
+ SBI_FWFT_LOCAL_PLATFORM_END = 0x7fffffff,
+
+ SBI_FWFT_GLOBAL_RESERVED_START = 0x80000000,
+ SBI_FWFT_GLOBAL_RESERVED_END = 0xbfffffff,
+ SBI_FWFT_GLOBAL_PLATFORM_START = 0xc0000000,
+ SBI_FWFT_GLOBAL_PLATFORM_END = 0xffffffff,
+};
+
+#define SBI_FWFT_PLATFORM_FEATURE_BIT BIT(30)
+#define SBI_FWFT_GLOBAL_FEATURE_BIT BIT(31)
+
+#define SBI_FWFT_SET_FLAG_LOCK BIT(0)
+
/* SBI spec version fields */
#define SBI_SPEC_VERSION_DEFAULT 0x1
#define SBI_SPEC_VERSION_MAJOR_SHIFT 24
@@ -419,6 +447,11 @@ enum sbi_ext_nacl_feature {
#define SBI_ERR_ALREADY_STARTED -7
#define SBI_ERR_ALREADY_STOPPED -8
#define SBI_ERR_NO_SHMEM -9
+#define SBI_ERR_INVALID_STATE -10
+#define SBI_ERR_BAD_RANGE -11
+#define SBI_ERR_TIMEOUT -12
+#define SBI_ERR_IO -13
+#define SBI_ERR_DENIED_LOCKED -14
extern unsigned long sbi_spec_version;
struct sbiret {
--
2.47.2
^ permalink raw reply related [flat|nested] 28+ messages in thread* [PATCH v4 02/18] riscv: sbi: add new SBI error mappings
2025-03-17 17:06 [PATCH v4 00/18] riscv: add SBI FWFT misaligned exception delegation support Clément Léger
2025-03-17 17:06 ` [PATCH v4 01/18] riscv: add Firmware Feature (FWFT) SBI extensions definitions Clément Léger
@ 2025-03-17 17:06 ` Clément Léger
2025-03-22 12:06 ` Andrew Jones
2025-03-17 17:06 ` [PATCH v4 03/18] riscv: sbi: add FWFT extension interface Clément Léger
` (15 subsequent siblings)
17 siblings, 1 reply; 28+ messages in thread
From: Clément Léger @ 2025-03-17 17:06 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Anup Patel, Atish Patra,
Shuah Khan, Jonathan Corbet, linux-riscv, linux-kernel, linux-doc,
kvm, kvm-riscv, linux-kselftest
Cc: Clément Léger, Samuel Holland, Andrew Jones
A few new errors have been added with SBI V3.0, maps them as close as
possible to errno values.
Signed-off-by: Clément Léger <cleger@rivosinc.com>
---
arch/riscv/include/asm/sbi.h | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h
index bb077d0c912f..d11d22717b49 100644
--- a/arch/riscv/include/asm/sbi.h
+++ b/arch/riscv/include/asm/sbi.h
@@ -536,11 +536,20 @@ static inline int sbi_err_map_linux_errno(int err)
case SBI_SUCCESS:
return 0;
case SBI_ERR_DENIED:
+ case SBI_ERR_DENIED_LOCKED:
return -EPERM;
case SBI_ERR_INVALID_PARAM:
+ case SBI_ERR_INVALID_STATE:
+ case SBI_ERR_BAD_RANGE:
return -EINVAL;
case SBI_ERR_INVALID_ADDRESS:
return -EFAULT;
+ case SBI_ERR_NO_SHMEM:
+ return -ENOMEM;
+ case SBI_ERR_TIMEOUT:
+ return -ETIME;
+ case SBI_ERR_IO:
+ return -EIO;
case SBI_ERR_NOT_SUPPORTED:
case SBI_ERR_FAILURE:
default:
--
2.47.2
^ permalink raw reply related [flat|nested] 28+ messages in thread* Re: [PATCH v4 02/18] riscv: sbi: add new SBI error mappings
2025-03-17 17:06 ` [PATCH v4 02/18] riscv: sbi: add new SBI error mappings Clément Léger
@ 2025-03-22 12:06 ` Andrew Jones
2025-03-24 8:29 ` Clément Léger
0 siblings, 1 reply; 28+ messages in thread
From: Andrew Jones @ 2025-03-22 12:06 UTC (permalink / raw)
To: Clément Léger
Cc: Paul Walmsley, Palmer Dabbelt, Anup Patel, Atish Patra,
Shuah Khan, Jonathan Corbet, linux-riscv, linux-kernel, linux-doc,
kvm, kvm-riscv, linux-kselftest, Samuel Holland
On Mon, Mar 17, 2025 at 06:06:08PM +0100, Clément Léger wrote:
> A few new errors have been added with SBI V3.0, maps them as close as
> possible to errno values.
>
> Signed-off-by: Clément Léger <cleger@rivosinc.com>
> ---
> arch/riscv/include/asm/sbi.h | 9 +++++++++
> 1 file changed, 9 insertions(+)
>
> diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h
> index bb077d0c912f..d11d22717b49 100644
> --- a/arch/riscv/include/asm/sbi.h
> +++ b/arch/riscv/include/asm/sbi.h
> @@ -536,11 +536,20 @@ static inline int sbi_err_map_linux_errno(int err)
> case SBI_SUCCESS:
> return 0;
> case SBI_ERR_DENIED:
> + case SBI_ERR_DENIED_LOCKED:
> return -EPERM;
> case SBI_ERR_INVALID_PARAM:
> + case SBI_ERR_INVALID_STATE:
> + case SBI_ERR_BAD_RANGE:
> return -EINVAL;
> case SBI_ERR_INVALID_ADDRESS:
> return -EFAULT;
> + case SBI_ERR_NO_SHMEM:
> + return -ENOMEM;
> + case SBI_ERR_TIMEOUT:
> + return -ETIME;
> + case SBI_ERR_IO:
> + return -EIO;
> case SBI_ERR_NOT_SUPPORTED:
> case SBI_ERR_FAILURE:
> default:
> --
> 2.47.2
>
I'm not a huge fan sbi_err_map_linux_errno() since the mappings seem a bit
arbitrary, but if we're going to do it, then these look pretty good to me.
Only other thought I had was E2BIG for bad-range, but nah...
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Thanks,
drew
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v4 02/18] riscv: sbi: add new SBI error mappings
2025-03-22 12:06 ` Andrew Jones
@ 2025-03-24 8:29 ` Clément Léger
2025-03-24 8:38 ` Andrew Jones
0 siblings, 1 reply; 28+ messages in thread
From: Clément Léger @ 2025-03-24 8:29 UTC (permalink / raw)
To: Andrew Jones
Cc: Paul Walmsley, Palmer Dabbelt, Anup Patel, Atish Patra,
Shuah Khan, Jonathan Corbet, linux-riscv, linux-kernel, linux-doc,
kvm, kvm-riscv, linux-kselftest, Samuel Holland
On 22/03/2025 13:06, Andrew Jones wrote:
> On Mon, Mar 17, 2025 at 06:06:08PM +0100, Clément Léger wrote:
>> A few new errors have been added with SBI V3.0, maps them as close as
>> possible to errno values.
>>
>> Signed-off-by: Clément Léger <cleger@rivosinc.com>
>> ---
>> arch/riscv/include/asm/sbi.h | 9 +++++++++
>> 1 file changed, 9 insertions(+)
>>
>> diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h
>> index bb077d0c912f..d11d22717b49 100644
>> --- a/arch/riscv/include/asm/sbi.h
>> +++ b/arch/riscv/include/asm/sbi.h
>> @@ -536,11 +536,20 @@ static inline int sbi_err_map_linux_errno(int err)
>> case SBI_SUCCESS:
>> return 0;
>> case SBI_ERR_DENIED:
>> + case SBI_ERR_DENIED_LOCKED:
>> return -EPERM;
>> case SBI_ERR_INVALID_PARAM:
>> + case SBI_ERR_INVALID_STATE:
>> + case SBI_ERR_BAD_RANGE:
>> return -EINVAL;
>> case SBI_ERR_INVALID_ADDRESS:
>> return -EFAULT;
>> + case SBI_ERR_NO_SHMEM:
>> + return -ENOMEM;
>> + case SBI_ERR_TIMEOUT:
>> + return -ETIME;
>> + case SBI_ERR_IO:
>> + return -EIO;
>> case SBI_ERR_NOT_SUPPORTED:
>> case SBI_ERR_FAILURE:
>> default:
>> --
>> 2.47.2
>>
>
> I'm not a huge fan sbi_err_map_linux_errno() since the mappings seem a bit
> arbitrary, but if we're going to do it, then these look pretty good to me.
> Only other thought I had was E2BIG for bad-range, but nah...
Yeah I also think some mappings are a bit odd even though I skimmed
through the whole errno list to find the best possible mappings. I'd be
happy to find something better though.
Thanks,
Clément
>
> Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
>
> Thanks,
> drew
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v4 02/18] riscv: sbi: add new SBI error mappings
2025-03-24 8:29 ` Clément Léger
@ 2025-03-24 8:38 ` Andrew Jones
2025-03-24 8:40 ` Clément Léger
0 siblings, 1 reply; 28+ messages in thread
From: Andrew Jones @ 2025-03-24 8:38 UTC (permalink / raw)
To: Clément Léger
Cc: Paul Walmsley, Palmer Dabbelt, Anup Patel, Atish Patra,
Shuah Khan, Jonathan Corbet, linux-riscv, linux-kernel, linux-doc,
kvm, kvm-riscv, linux-kselftest, Samuel Holland
On Mon, Mar 24, 2025 at 09:29:33AM +0100, Clément Léger wrote:
>
>
> On 22/03/2025 13:06, Andrew Jones wrote:
> > On Mon, Mar 17, 2025 at 06:06:08PM +0100, Clément Léger wrote:
> >> A few new errors have been added with SBI V3.0, maps them as close as
> >> possible to errno values.
> >>
> >> Signed-off-by: Clément Léger <cleger@rivosinc.com>
> >> ---
> >> arch/riscv/include/asm/sbi.h | 9 +++++++++
> >> 1 file changed, 9 insertions(+)
> >>
> >> diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h
> >> index bb077d0c912f..d11d22717b49 100644
> >> --- a/arch/riscv/include/asm/sbi.h
> >> +++ b/arch/riscv/include/asm/sbi.h
> >> @@ -536,11 +536,20 @@ static inline int sbi_err_map_linux_errno(int err)
> >> case SBI_SUCCESS:
> >> return 0;
> >> case SBI_ERR_DENIED:
> >> + case SBI_ERR_DENIED_LOCKED:
> >> return -EPERM;
> >> case SBI_ERR_INVALID_PARAM:
> >> + case SBI_ERR_INVALID_STATE:
> >> + case SBI_ERR_BAD_RANGE:
> >> return -EINVAL;
> >> case SBI_ERR_INVALID_ADDRESS:
> >> return -EFAULT;
> >> + case SBI_ERR_NO_SHMEM:
> >> + return -ENOMEM;
> >> + case SBI_ERR_TIMEOUT:
> >> + return -ETIME;
> >> + case SBI_ERR_IO:
> >> + return -EIO;
> >> case SBI_ERR_NOT_SUPPORTED:
> >> case SBI_ERR_FAILURE:
> >> default:
> >> --
> >> 2.47.2
> >>
> >
> > I'm not a huge fan sbi_err_map_linux_errno() since the mappings seem a bit
> > arbitrary, but if we're going to do it, then these look pretty good to me.
> > Only other thought I had was E2BIG for bad-range, but nah...
Actually, I just recalled that there is an ERANGE, which would probably be
a better match for bad-range than EINVAL, but I'm not sure it matters much
anyway since this function doesn't promise 1-to-1 mappings.
Thanks,
drew
>
> Yeah I also think some mappings are a bit odd even though I skimmed
> through the whole errno list to find the best possible mappings. I'd be
> happy to find something better though.
>
> Thanks,
>
> Clément
>
> >
> > Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
> >
> > Thanks,
> > drew
>
^ permalink raw reply [flat|nested] 28+ messages in thread
* Re: [PATCH v4 02/18] riscv: sbi: add new SBI error mappings
2025-03-24 8:38 ` Andrew Jones
@ 2025-03-24 8:40 ` Clément Léger
0 siblings, 0 replies; 28+ messages in thread
From: Clément Léger @ 2025-03-24 8:40 UTC (permalink / raw)
To: Andrew Jones
Cc: Paul Walmsley, Palmer Dabbelt, Anup Patel, Atish Patra,
Shuah Khan, Jonathan Corbet, linux-riscv, linux-kernel, linux-doc,
kvm, kvm-riscv, linux-kselftest, Samuel Holland
On 24/03/2025 09:38, Andrew Jones wrote:
> On Mon, Mar 24, 2025 at 09:29:33AM +0100, Clément Léger wrote:
>>
>>
>> On 22/03/2025 13:06, Andrew Jones wrote:
>>> On Mon, Mar 17, 2025 at 06:06:08PM +0100, Clément Léger wrote:
>>>> A few new errors have been added with SBI V3.0, maps them as close as
>>>> possible to errno values.
>>>>
>>>> Signed-off-by: Clément Léger <cleger@rivosinc.com>
>>>> ---
>>>> arch/riscv/include/asm/sbi.h | 9 +++++++++
>>>> 1 file changed, 9 insertions(+)
>>>>
>>>> diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h
>>>> index bb077d0c912f..d11d22717b49 100644
>>>> --- a/arch/riscv/include/asm/sbi.h
>>>> +++ b/arch/riscv/include/asm/sbi.h
>>>> @@ -536,11 +536,20 @@ static inline int sbi_err_map_linux_errno(int err)
>>>> case SBI_SUCCESS:
>>>> return 0;
>>>> case SBI_ERR_DENIED:
>>>> + case SBI_ERR_DENIED_LOCKED:
>>>> return -EPERM;
>>>> case SBI_ERR_INVALID_PARAM:
>>>> + case SBI_ERR_INVALID_STATE:
>>>> + case SBI_ERR_BAD_RANGE:
>>>> return -EINVAL;
>>>> case SBI_ERR_INVALID_ADDRESS:
>>>> return -EFAULT;
>>>> + case SBI_ERR_NO_SHMEM:
>>>> + return -ENOMEM;
>>>> + case SBI_ERR_TIMEOUT:
>>>> + return -ETIME;
>>>> + case SBI_ERR_IO:
>>>> + return -EIO;
>>>> case SBI_ERR_NOT_SUPPORTED:
>>>> case SBI_ERR_FAILURE:
>>>> default:
>>>> --
>>>> 2.47.2
>>>>
>>>
>>> I'm not a huge fan sbi_err_map_linux_errno() since the mappings seem a bit
>>> arbitrary, but if we're going to do it, then these look pretty good to me.
>>> Only other thought I had was E2BIG for bad-range, but nah...
>
> Actually, I just recalled that there is an ERANGE, which would probably be
> a better match for bad-range than EINVAL, but I'm not sure it matters much
> anyway since this function doesn't promise 1-to-1 mappings.
Yes, but ERANGE description is actually "results are too large", but at
least it's name is more descriptive. Let's go with it.
>
> Thanks,
> drew
>
>>
>> Yeah I also think some mappings are a bit odd even though I skimmed
>> through the whole errno list to find the best possible mappings. I'd be
>> happy to find something better though.
>>
>> Thanks,
>>
>> Clément
>>
>>>
>>> Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
>>>
>>> Thanks,
>>> drew
>>
^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH v4 03/18] riscv: sbi: add FWFT extension interface
2025-03-17 17:06 [PATCH v4 00/18] riscv: add SBI FWFT misaligned exception delegation support Clément Léger
2025-03-17 17:06 ` [PATCH v4 01/18] riscv: add Firmware Feature (FWFT) SBI extensions definitions Clément Léger
2025-03-17 17:06 ` [PATCH v4 02/18] riscv: sbi: add new SBI error mappings Clément Léger
@ 2025-03-17 17:06 ` Clément Léger
2025-03-22 12:11 ` Andrew Jones
2025-03-17 17:06 ` [PATCH v4 04/18] riscv: sbi: add SBI FWFT extension calls Clément Léger
` (14 subsequent siblings)
17 siblings, 1 reply; 28+ messages in thread
From: Clément Léger @ 2025-03-17 17:06 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Anup Patel, Atish Patra,
Shuah Khan, Jonathan Corbet, linux-riscv, linux-kernel, linux-doc,
kvm, kvm-riscv, linux-kselftest
Cc: Clément Léger, Samuel Holland, Andrew Jones
This SBI extensions enables supervisor mode to control feature that are
under M-mode control (For instance, Svadu menvcfg ADUE bit, Ssdbltrp
DTE, etc). Add an interface to set local features for a specific cpu
mask as well as for the online cpu mask.
Signed-off-by: Clément Léger <cleger@rivosinc.com>
---
arch/riscv/include/asm/sbi.h | 20 +++++++++++
arch/riscv/kernel/sbi.c | 69 ++++++++++++++++++++++++++++++++++++
2 files changed, 89 insertions(+)
diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h
index d11d22717b49..1cecfa82c2e5 100644
--- a/arch/riscv/include/asm/sbi.h
+++ b/arch/riscv/include/asm/sbi.h
@@ -503,6 +503,26 @@ int sbi_remote_hfence_vvma_asid(const struct cpumask *cpu_mask,
unsigned long asid);
long sbi_probe_extension(int ext);
+int sbi_fwft_local_set_cpumask(const cpumask_t *mask, u32 feature,
+ unsigned long value, unsigned long flags);
+/**
+ * sbi_fwft_local_set() - Set a feature on all online cpus
+ * @feature: The feature to be set
+ * @value: The feature value to be set
+ * @flags: FWFT feature set flags
+ *
+ * Return: 0 on success, appropriate linux error code otherwise.
+ */
+ static inline int sbi_fwft_local_set(u32 feature, unsigned long value,
+ unsigned long flags)
+ {
+ return sbi_fwft_local_set_cpumask(cpu_online_mask, feature, value,
+ flags);
+ }
+
+int sbi_fwft_get(u32 feature, unsigned long *value);
+int sbi_fwft_set(u32 feature, unsigned long value, unsigned long flags);
+
/* Check if current SBI specification version is 0.1 or not */
static inline int sbi_spec_is_0_1(void)
{
diff --git a/arch/riscv/kernel/sbi.c b/arch/riscv/kernel/sbi.c
index 1989b8cade1b..d41a5642be24 100644
--- a/arch/riscv/kernel/sbi.c
+++ b/arch/riscv/kernel/sbi.c
@@ -299,6 +299,75 @@ static int __sbi_rfence_v02(int fid, const struct cpumask *cpu_mask,
return 0;
}
+/**
+ * sbi_fwft_get() - Get a feature for the local hart
+ * @feature: The feature ID to be set
+ * @value: Will contain the feature value on success
+ *
+ * Return: 0 on success, appropriate linux error code otherwise.
+ */
+int sbi_fwft_get(u32 feature, unsigned long *value)
+{
+ return -EOPNOTSUPP;
+}
+
+/**
+ * sbi_fwft_set() - Set a feature on the local hart
+ * @feature: The feature ID to be set
+ * @value: The feature value to be set
+ * @flags: FWFT feature set flags
+ *
+ * Return: 0 on success, appropriate linux error code otherwise.
+ */
+int sbi_fwft_set(u32 feature, unsigned long value, unsigned long flags)
+{
+ return -EOPNOTSUPP;
+}
+
+struct fwft_set_req {
+ u32 feature;
+ unsigned long value;
+ unsigned long flags;
+ atomic_t error;
+};
+
+static void cpu_sbi_fwft_set(void *arg)
+{
+ struct fwft_set_req *req = arg;
+ int ret;
+
+ ret = sbi_fwft_set(req->feature, req->value, req->flags);
+ if (ret)
+ atomic_set(&req->error, ret);
+}
+
+/**
+ * sbi_fwft_local_set() - Set a feature for the specified cpumask
+ * @mask: CPU mask of cpus that need the feature to be set
+ * @feature: The feature ID to be set
+ * @value: The feature value to be set
+ * @flags: FWFT feature set flags
+ *
+ * Return: 0 on success, appropriate linux error code otherwise.
+ */
+int sbi_fwft_local_set_cpumask(const cpumask_t *mask, u32 feature,
+ unsigned long value, unsigned long flags)
+{
+ struct fwft_set_req req = {
+ .feature = feature,
+ .value = value,
+ .flags = flags,
+ .error = ATOMIC_INIT(0),
+ };
+
+ if (feature & SBI_FWFT_GLOBAL_FEATURE_BIT)
+ return -EINVAL;
+
+ on_each_cpu_mask(mask, cpu_sbi_fwft_set, &req, 1);
+
+ return atomic_read(&req.error);
+}
+
/**
* sbi_set_timer() - Program the timer for next timer event.
* @stime_value: The value after which next timer event should fire.
--
2.47.2
^ permalink raw reply related [flat|nested] 28+ messages in thread* Re: [PATCH v4 03/18] riscv: sbi: add FWFT extension interface
2025-03-17 17:06 ` [PATCH v4 03/18] riscv: sbi: add FWFT extension interface Clément Léger
@ 2025-03-22 12:11 ` Andrew Jones
0 siblings, 0 replies; 28+ messages in thread
From: Andrew Jones @ 2025-03-22 12:11 UTC (permalink / raw)
To: Clément Léger
Cc: Paul Walmsley, Palmer Dabbelt, Anup Patel, Atish Patra,
Shuah Khan, Jonathan Corbet, linux-riscv, linux-kernel, linux-doc,
kvm, kvm-riscv, linux-kselftest, Samuel Holland
On Mon, Mar 17, 2025 at 06:06:09PM +0100, Clément Léger wrote:
> This SBI extensions enables supervisor mode to control feature that are
> under M-mode control (For instance, Svadu menvcfg ADUE bit, Ssdbltrp
> DTE, etc). Add an interface to set local features for a specific cpu
> mask as well as for the online cpu mask.
>
> Signed-off-by: Clément Léger <cleger@rivosinc.com>
> ---
> arch/riscv/include/asm/sbi.h | 20 +++++++++++
> arch/riscv/kernel/sbi.c | 69 ++++++++++++++++++++++++++++++++++++
> 2 files changed, 89 insertions(+)
>
> diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h
> index d11d22717b49..1cecfa82c2e5 100644
> --- a/arch/riscv/include/asm/sbi.h
> +++ b/arch/riscv/include/asm/sbi.h
> @@ -503,6 +503,26 @@ int sbi_remote_hfence_vvma_asid(const struct cpumask *cpu_mask,
> unsigned long asid);
> long sbi_probe_extension(int ext);
>
> +int sbi_fwft_local_set_cpumask(const cpumask_t *mask, u32 feature,
> + unsigned long value, unsigned long flags);
> +/**
> + * sbi_fwft_local_set() - Set a feature on all online cpus
> + * @feature: The feature to be set
> + * @value: The feature value to be set
> + * @flags: FWFT feature set flags
> + *
> + * Return: 0 on success, appropriate linux error code otherwise.
> + */
> + static inline int sbi_fwft_local_set(u32 feature, unsigned long value,
> + unsigned long flags)
> + {
> + return sbi_fwft_local_set_cpumask(cpu_online_mask, feature, value,
> + flags);
Let flags stick out. We have 100 chars.
> + }
> +
> +int sbi_fwft_get(u32 feature, unsigned long *value);
> +int sbi_fwft_set(u32 feature, unsigned long value, unsigned long flags);
> +
> /* Check if current SBI specification version is 0.1 or not */
> static inline int sbi_spec_is_0_1(void)
> {
> diff --git a/arch/riscv/kernel/sbi.c b/arch/riscv/kernel/sbi.c
> index 1989b8cade1b..d41a5642be24 100644
> --- a/arch/riscv/kernel/sbi.c
> +++ b/arch/riscv/kernel/sbi.c
> @@ -299,6 +299,75 @@ static int __sbi_rfence_v02(int fid, const struct cpumask *cpu_mask,
> return 0;
> }
>
> +/**
> + * sbi_fwft_get() - Get a feature for the local hart
> + * @feature: The feature ID to be set
> + * @value: Will contain the feature value on success
> + *
> + * Return: 0 on success, appropriate linux error code otherwise.
> + */
> +int sbi_fwft_get(u32 feature, unsigned long *value)
> +{
> + return -EOPNOTSUPP;
> +}
> +
> +/**
> + * sbi_fwft_set() - Set a feature on the local hart
> + * @feature: The feature ID to be set
> + * @value: The feature value to be set
> + * @flags: FWFT feature set flags
> + *
> + * Return: 0 on success, appropriate linux error code otherwise.
> + */
> +int sbi_fwft_set(u32 feature, unsigned long value, unsigned long flags)
> +{
> + return -EOPNOTSUPP;
> +}
> +
> +struct fwft_set_req {
> + u32 feature;
> + unsigned long value;
> + unsigned long flags;
> + atomic_t error;
> +};
> +
> +static void cpu_sbi_fwft_set(void *arg)
> +{
> + struct fwft_set_req *req = arg;
> + int ret;
> +
> + ret = sbi_fwft_set(req->feature, req->value, req->flags);
> + if (ret)
> + atomic_set(&req->error, ret);
> +}
> +
> +/**
> + * sbi_fwft_local_set() - Set a feature for the specified cpumask
sbi_fwft_local_set_cpumask
> + * @mask: CPU mask of cpus that need the feature to be set
> + * @feature: The feature ID to be set
> + * @value: The feature value to be set
> + * @flags: FWFT feature set flags
> + *
> + * Return: 0 on success, appropriate linux error code otherwise.
> + */
> +int sbi_fwft_local_set_cpumask(const cpumask_t *mask, u32 feature,
> + unsigned long value, unsigned long flags)
> +{
> + struct fwft_set_req req = {
> + .feature = feature,
> + .value = value,
> + .flags = flags,
> + .error = ATOMIC_INIT(0),
> + };
> +
> + if (feature & SBI_FWFT_GLOBAL_FEATURE_BIT)
> + return -EINVAL;
> +
> + on_each_cpu_mask(mask, cpu_sbi_fwft_set, &req, 1);
> +
> + return atomic_read(&req.error);
> +}
> +
> /**
> * sbi_set_timer() - Program the timer for next timer event.
> * @stime_value: The value after which next timer event should fire.
> --
> 2.47.2
>
Otherwise,
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH v4 04/18] riscv: sbi: add SBI FWFT extension calls
2025-03-17 17:06 [PATCH v4 00/18] riscv: add SBI FWFT misaligned exception delegation support Clément Léger
` (2 preceding siblings ...)
2025-03-17 17:06 ` [PATCH v4 03/18] riscv: sbi: add FWFT extension interface Clément Léger
@ 2025-03-17 17:06 ` Clément Léger
2025-03-22 12:14 ` Andrew Jones
2025-03-17 17:06 ` [PATCH v4 05/18] riscv: misaligned: request misaligned exception from SBI Clément Léger
` (13 subsequent siblings)
17 siblings, 1 reply; 28+ messages in thread
From: Clément Léger @ 2025-03-17 17:06 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Anup Patel, Atish Patra,
Shuah Khan, Jonathan Corbet, linux-riscv, linux-kernel, linux-doc,
kvm, kvm-riscv, linux-kselftest
Cc: Clément Léger, Samuel Holland, Andrew Jones
Add FWFT extension calls. This will be ratified in SBI V3.0 hence, it is
provided as a separate commit that can be left out if needed.
Signed-off-by: Clément Léger <cleger@rivosinc.com>
---
arch/riscv/kernel/sbi.c | 30 ++++++++++++++++++++++++++++--
1 file changed, 28 insertions(+), 2 deletions(-)
diff --git a/arch/riscv/kernel/sbi.c b/arch/riscv/kernel/sbi.c
index d41a5642be24..54d9ceb7b723 100644
--- a/arch/riscv/kernel/sbi.c
+++ b/arch/riscv/kernel/sbi.c
@@ -299,6 +299,8 @@ static int __sbi_rfence_v02(int fid, const struct cpumask *cpu_mask,
return 0;
}
+static bool sbi_fwft_supported;
+
/**
* sbi_fwft_get() - Get a feature for the local hart
* @feature: The feature ID to be set
@@ -308,7 +310,15 @@ static int __sbi_rfence_v02(int fid, const struct cpumask *cpu_mask,
*/
int sbi_fwft_get(u32 feature, unsigned long *value)
{
- return -EOPNOTSUPP;
+ struct sbiret ret;
+
+ if (!sbi_fwft_supported)
+ return -EOPNOTSUPP;
+
+ ret = sbi_ecall(SBI_EXT_FWFT, SBI_EXT_FWFT_GET,
+ feature, 0, 0, 0, 0, 0);
+
+ return sbi_err_map_linux_errno(ret.error);
}
/**
@@ -321,7 +331,15 @@ int sbi_fwft_get(u32 feature, unsigned long *value)
*/
int sbi_fwft_set(u32 feature, unsigned long value, unsigned long flags)
{
- return -EOPNOTSUPP;
+ struct sbiret ret;
+
+ if (!sbi_fwft_supported)
+ return -EOPNOTSUPP;
+
+ ret = sbi_ecall(SBI_EXT_FWFT, SBI_EXT_FWFT_SET,
+ feature, value, flags, 0, 0, 0);
+
+ return sbi_err_map_linux_errno(ret.error);
}
struct fwft_set_req {
@@ -360,6 +378,9 @@ int sbi_fwft_local_set_cpumask(const cpumask_t *mask, u32 feature,
.error = ATOMIC_INIT(0),
};
+ if (!sbi_fwft_supported)
+ return -EOPNOTSUPP;
+
if (feature & SBI_FWFT_GLOBAL_FEATURE_BIT)
return -EINVAL;
@@ -691,6 +712,11 @@ void __init sbi_init(void)
pr_info("SBI DBCN extension detected\n");
sbi_debug_console_available = true;
}
+ if ((sbi_spec_version >= sbi_mk_version(3, 0)) &&
+ (sbi_probe_extension(SBI_EXT_FWFT) > 0)) {
+ pr_info("SBI FWFT extension detected\n");
+ sbi_fwft_supported = true;
+ }
} else {
__sbi_set_timer = __sbi_set_timer_v01;
__sbi_send_ipi = __sbi_send_ipi_v01;
--
2.47.2
^ permalink raw reply related [flat|nested] 28+ messages in thread* Re: [PATCH v4 04/18] riscv: sbi: add SBI FWFT extension calls
2025-03-17 17:06 ` [PATCH v4 04/18] riscv: sbi: add SBI FWFT extension calls Clément Léger
@ 2025-03-22 12:14 ` Andrew Jones
2025-03-24 8:37 ` Clément Léger
0 siblings, 1 reply; 28+ messages in thread
From: Andrew Jones @ 2025-03-22 12:14 UTC (permalink / raw)
To: Clément Léger
Cc: Paul Walmsley, Palmer Dabbelt, Anup Patel, Atish Patra,
Shuah Khan, Jonathan Corbet, linux-riscv, linux-kernel, linux-doc,
kvm, kvm-riscv, linux-kselftest, Samuel Holland
On Mon, Mar 17, 2025 at 06:06:10PM +0100, Clément Léger wrote:
> Add FWFT extension calls. This will be ratified in SBI V3.0 hence, it is
> provided as a separate commit that can be left out if needed.
>
> Signed-off-by: Clément Léger <cleger@rivosinc.com>
> ---
> arch/riscv/kernel/sbi.c | 30 ++++++++++++++++++++++++++++--
> 1 file changed, 28 insertions(+), 2 deletions(-)
>
> diff --git a/arch/riscv/kernel/sbi.c b/arch/riscv/kernel/sbi.c
> index d41a5642be24..54d9ceb7b723 100644
> --- a/arch/riscv/kernel/sbi.c
> +++ b/arch/riscv/kernel/sbi.c
> @@ -299,6 +299,8 @@ static int __sbi_rfence_v02(int fid, const struct cpumask *cpu_mask,
> return 0;
> }
>
> +static bool sbi_fwft_supported;
> +
> /**
> * sbi_fwft_get() - Get a feature for the local hart
> * @feature: The feature ID to be set
> @@ -308,7 +310,15 @@ static int __sbi_rfence_v02(int fid, const struct cpumask *cpu_mask,
> */
> int sbi_fwft_get(u32 feature, unsigned long *value)
> {
> - return -EOPNOTSUPP;
> + struct sbiret ret;
> +
> + if (!sbi_fwft_supported)
> + return -EOPNOTSUPP;
> +
> + ret = sbi_ecall(SBI_EXT_FWFT, SBI_EXT_FWFT_GET,
> + feature, 0, 0, 0, 0, 0);
We're missing the
if (!ret)
*value = ret.value;
part.
> +
> + return sbi_err_map_linux_errno(ret.error);
> }
>
> /**
> @@ -321,7 +331,15 @@ int sbi_fwft_get(u32 feature, unsigned long *value)
> */
> int sbi_fwft_set(u32 feature, unsigned long value, unsigned long flags)
> {
> - return -EOPNOTSUPP;
> + struct sbiret ret;
> +
> + if (!sbi_fwft_supported)
> + return -EOPNOTSUPP;
> +
> + ret = sbi_ecall(SBI_EXT_FWFT, SBI_EXT_FWFT_SET,
> + feature, value, flags, 0, 0, 0);
> +
> + return sbi_err_map_linux_errno(ret.error);
> }
>
> struct fwft_set_req {
> @@ -360,6 +378,9 @@ int sbi_fwft_local_set_cpumask(const cpumask_t *mask, u32 feature,
> .error = ATOMIC_INIT(0),
> };
>
> + if (!sbi_fwft_supported)
> + return -EOPNOTSUPP;
> +
> if (feature & SBI_FWFT_GLOBAL_FEATURE_BIT)
> return -EINVAL;
>
> @@ -691,6 +712,11 @@ void __init sbi_init(void)
> pr_info("SBI DBCN extension detected\n");
> sbi_debug_console_available = true;
> }
> + if ((sbi_spec_version >= sbi_mk_version(3, 0)) &&
> + (sbi_probe_extension(SBI_EXT_FWFT) > 0)) {
> + pr_info("SBI FWFT extension detected\n");
> + sbi_fwft_supported = true;
> + }
> } else {
> __sbi_set_timer = __sbi_set_timer_v01;
> __sbi_send_ipi = __sbi_send_ipi_v01;
> --
> 2.47.2
>
Thanks,
drew
^ permalink raw reply [flat|nested] 28+ messages in thread* Re: [PATCH v4 04/18] riscv: sbi: add SBI FWFT extension calls
2025-03-22 12:14 ` Andrew Jones
@ 2025-03-24 8:37 ` Clément Léger
0 siblings, 0 replies; 28+ messages in thread
From: Clément Léger @ 2025-03-24 8:37 UTC (permalink / raw)
To: Andrew Jones
Cc: Paul Walmsley, Palmer Dabbelt, Anup Patel, Atish Patra,
Shuah Khan, Jonathan Corbet, linux-riscv, linux-kernel, linux-doc,
kvm, kvm-riscv, linux-kselftest, Samuel Holland
On 22/03/2025 13:14, Andrew Jones wrote:
> On Mon, Mar 17, 2025 at 06:06:10PM +0100, Clément Léger wrote:
>> Add FWFT extension calls. This will be ratified in SBI V3.0 hence, it is
>> provided as a separate commit that can be left out if needed.
>>
>> Signed-off-by: Clément Léger <cleger@rivosinc.com>
>> ---
>> arch/riscv/kernel/sbi.c | 30 ++++++++++++++++++++++++++++--
>> 1 file changed, 28 insertions(+), 2 deletions(-)
>>
>> diff --git a/arch/riscv/kernel/sbi.c b/arch/riscv/kernel/sbi.c
>> index d41a5642be24..54d9ceb7b723 100644
>> --- a/arch/riscv/kernel/sbi.c
>> +++ b/arch/riscv/kernel/sbi.c
>> @@ -299,6 +299,8 @@ static int __sbi_rfence_v02(int fid, const struct cpumask *cpu_mask,
>> return 0;
>> }
>>
>> +static bool sbi_fwft_supported;
>> +
>> /**
>> * sbi_fwft_get() - Get a feature for the local hart
>> * @feature: The feature ID to be set
>> @@ -308,7 +310,15 @@ static int __sbi_rfence_v02(int fid, const struct cpumask *cpu_mask,
>> */
>> int sbi_fwft_get(u32 feature, unsigned long *value)
>> {
>> - return -EOPNOTSUPP;
>> + struct sbiret ret;
>> +
>> + if (!sbi_fwft_supported)
>> + return -EOPNOTSUPP;
>> +
>> + ret = sbi_ecall(SBI_EXT_FWFT, SBI_EXT_FWFT_GET,
>> + feature, 0, 0, 0, 0, 0);
>
> We're missing the
>
> if (!ret)
> *value = ret.value;
>
> part.
Damn, and even worse it isn't used at all. I'll probably remove it
entirely and keep the strict minimum for this series.
Thanks,
Clément
>
>> +
>> + return sbi_err_map_linux_errno(ret.error);
>> }
>>
>> /**
>> @@ -321,7 +331,15 @@ int sbi_fwft_get(u32 feature, unsigned long *value)
>> */
>> int sbi_fwft_set(u32 feature, unsigned long value, unsigned long flags)
>> {
>> - return -EOPNOTSUPP;
>> + struct sbiret ret;
>> +
>> + if (!sbi_fwft_supported)
>> + return -EOPNOTSUPP;
>> +
>> + ret = sbi_ecall(SBI_EXT_FWFT, SBI_EXT_FWFT_SET,
>> + feature, value, flags, 0, 0, 0);
>> +
>> + return sbi_err_map_linux_errno(ret.error);
>> }
>>
>> struct fwft_set_req {
>> @@ -360,6 +378,9 @@ int sbi_fwft_local_set_cpumask(const cpumask_t *mask, u32 feature,
>> .error = ATOMIC_INIT(0),
>> };
>>
>> + if (!sbi_fwft_supported)
>> + return -EOPNOTSUPP;
>> +
>> if (feature & SBI_FWFT_GLOBAL_FEATURE_BIT)
>> return -EINVAL;
>>
>> @@ -691,6 +712,11 @@ void __init sbi_init(void)
>> pr_info("SBI DBCN extension detected\n");
>> sbi_debug_console_available = true;
>> }
>> + if ((sbi_spec_version >= sbi_mk_version(3, 0)) &&
>> + (sbi_probe_extension(SBI_EXT_FWFT) > 0)) {
>> + pr_info("SBI FWFT extension detected\n");
>> + sbi_fwft_supported = true;
>> + }
>> } else {
>> __sbi_set_timer = __sbi_set_timer_v01;
>> __sbi_send_ipi = __sbi_send_ipi_v01;
>> --
>> 2.47.2
>>
>
> Thanks,
> drew
^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH v4 05/18] riscv: misaligned: request misaligned exception from SBI
2025-03-17 17:06 [PATCH v4 00/18] riscv: add SBI FWFT misaligned exception delegation support Clément Léger
` (3 preceding siblings ...)
2025-03-17 17:06 ` [PATCH v4 04/18] riscv: sbi: add SBI FWFT extension calls Clément Léger
@ 2025-03-17 17:06 ` Clément Léger
2025-03-17 17:06 ` [PATCH v4 06/18] riscv: misaligned: use on_each_cpu() for scalar misaligned access probing Clément Léger
` (12 subsequent siblings)
17 siblings, 0 replies; 28+ messages in thread
From: Clément Léger @ 2025-03-17 17:06 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Anup Patel, Atish Patra,
Shuah Khan, Jonathan Corbet, linux-riscv, linux-kernel, linux-doc,
kvm, kvm-riscv, linux-kselftest
Cc: Clément Léger, Samuel Holland, Andrew Jones
Now that the kernel can handle misaligned accesses in S-mode, request
misaligned access exception delegation from SBI. This uses the FWFT SBI
extension defined in SBI version 3.0.
Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
---
arch/riscv/include/asm/cpufeature.h | 3 +-
arch/riscv/kernel/traps_misaligned.c | 77 +++++++++++++++++++++-
arch/riscv/kernel/unaligned_access_speed.c | 11 +++-
3 files changed, 86 insertions(+), 5 deletions(-)
diff --git a/arch/riscv/include/asm/cpufeature.h b/arch/riscv/include/asm/cpufeature.h
index 569140d6e639..ad7d26788e6a 100644
--- a/arch/riscv/include/asm/cpufeature.h
+++ b/arch/riscv/include/asm/cpufeature.h
@@ -64,8 +64,9 @@ void __init riscv_user_isa_enable(void);
_RISCV_ISA_EXT_DATA(_name, _id, _sub_exts, ARRAY_SIZE(_sub_exts), _validate)
bool check_unaligned_access_emulated_all_cpus(void);
+void unaligned_access_init(void);
+int cpu_online_unaligned_access_init(unsigned int cpu);
#if defined(CONFIG_RISCV_SCALAR_MISALIGNED)
-void check_unaligned_access_emulated(struct work_struct *work __always_unused);
void unaligned_emulation_finish(void);
bool unaligned_ctl_available(void);
DECLARE_PER_CPU(long, misaligned_access_speed);
diff --git a/arch/riscv/kernel/traps_misaligned.c b/arch/riscv/kernel/traps_misaligned.c
index 7cc108aed74e..fa7f100b95bd 100644
--- a/arch/riscv/kernel/traps_misaligned.c
+++ b/arch/riscv/kernel/traps_misaligned.c
@@ -16,6 +16,7 @@
#include <asm/entry-common.h>
#include <asm/hwprobe.h>
#include <asm/cpufeature.h>
+#include <asm/sbi.h>
#include <asm/vector.h>
#define INSN_MATCH_LB 0x3
@@ -635,7 +636,7 @@ bool check_vector_unaligned_access_emulated_all_cpus(void)
static bool unaligned_ctl __read_mostly;
-void check_unaligned_access_emulated(struct work_struct *work __always_unused)
+static void check_unaligned_access_emulated(struct work_struct *work __always_unused)
{
int cpu = smp_processor_id();
long *mas_ptr = per_cpu_ptr(&misaligned_access_speed, cpu);
@@ -646,6 +647,13 @@ void check_unaligned_access_emulated(struct work_struct *work __always_unused)
__asm__ __volatile__ (
" "REG_L" %[tmp], 1(%[ptr])\n"
: [tmp] "=r" (tmp_val) : [ptr] "r" (&tmp_var) : "memory");
+}
+
+static int cpu_online_check_unaligned_access_emulated(unsigned int cpu)
+{
+ long *mas_ptr = per_cpu_ptr(&misaligned_access_speed, cpu);
+
+ check_unaligned_access_emulated(NULL);
/*
* If unaligned_ctl is already set, this means that we detected that all
@@ -654,9 +662,10 @@ void check_unaligned_access_emulated(struct work_struct *work __always_unused)
*/
if (unlikely(unaligned_ctl && (*mas_ptr != RISCV_HWPROBE_MISALIGNED_SCALAR_EMULATED))) {
pr_crit("CPU misaligned accesses non homogeneous (expected all emulated)\n");
- while (true)
- cpu_relax();
+ return -EINVAL;
}
+
+ return 0;
}
bool check_unaligned_access_emulated_all_cpus(void)
@@ -688,4 +697,66 @@ bool check_unaligned_access_emulated_all_cpus(void)
{
return false;
}
+static int cpu_online_check_unaligned_access_emulated(unsigned int cpu)
+{
+ return 0;
+}
#endif
+
+#ifdef CONFIG_RISCV_SBI
+
+static bool misaligned_traps_delegated;
+
+static int cpu_online_sbi_unaligned_setup(unsigned int cpu)
+{
+ if (sbi_fwft_set(SBI_FWFT_MISALIGNED_EXC_DELEG, 1, 0) &&
+ misaligned_traps_delegated) {
+ pr_crit("Misaligned trap delegation non homogeneous (expected delegated)");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static void unaligned_sbi_request_delegation(void)
+{
+ int ret;
+
+ ret = sbi_fwft_local_set(SBI_FWFT_MISALIGNED_EXC_DELEG, 1, 0);
+ if (ret)
+ return;
+
+ misaligned_traps_delegated = true;
+ pr_info("SBI misaligned access exception delegation ok\n");
+ /*
+ * Note that we don't have to take any specific action here, if
+ * the delegation is successful, then
+ * check_unaligned_access_emulated() will verify that indeed the
+ * platform traps on misaligned accesses.
+ */
+}
+
+void unaligned_access_init(void)
+{
+ if (sbi_probe_extension(SBI_EXT_FWFT) > 0)
+ unaligned_sbi_request_delegation();
+}
+#else
+void unaligned_access_init(void) {}
+
+static int cpu_online_sbi_unaligned_setup(unsigned int cpu __always_unused)
+{
+ return 0;
+}
+#endif
+
+int cpu_online_unaligned_access_init(unsigned int cpu)
+{
+ int ret;
+
+ ret = cpu_online_sbi_unaligned_setup(cpu);
+ if (ret)
+ return ret;
+
+ return cpu_online_check_unaligned_access_emulated(cpu);
+}
diff --git a/arch/riscv/kernel/unaligned_access_speed.c b/arch/riscv/kernel/unaligned_access_speed.c
index 91f189cf1611..2f3aba073297 100644
--- a/arch/riscv/kernel/unaligned_access_speed.c
+++ b/arch/riscv/kernel/unaligned_access_speed.c
@@ -188,13 +188,20 @@ arch_initcall_sync(lock_and_set_unaligned_access_static_branch);
static int riscv_online_cpu(unsigned int cpu)
{
+ int ret;
static struct page *buf;
/* We are already set since the last check */
if (per_cpu(misaligned_access_speed, cpu) != RISCV_HWPROBE_MISALIGNED_SCALAR_UNKNOWN)
goto exit;
- check_unaligned_access_emulated(NULL);
+ ret = cpu_online_unaligned_access_init(cpu);
+ if (ret)
+ return ret;
+
+ if (per_cpu(misaligned_access_speed, cpu) == RISCV_HWPROBE_MISALIGNED_SCALAR_EMULATED)
+ goto exit;
+
buf = alloc_pages(GFP_KERNEL, MISALIGNED_BUFFER_ORDER);
if (!buf) {
pr_warn("Allocation failure, not measuring misaligned performance\n");
@@ -403,6 +410,8 @@ static int check_unaligned_access_all_cpus(void)
{
bool all_cpus_emulated, all_cpus_vec_unsupported;
+ unaligned_access_init();
+
all_cpus_emulated = check_unaligned_access_emulated_all_cpus();
all_cpus_vec_unsupported = check_vector_unaligned_access_emulated_all_cpus();
--
2.47.2
^ permalink raw reply related [flat|nested] 28+ messages in thread* [PATCH v4 06/18] riscv: misaligned: use on_each_cpu() for scalar misaligned access probing
2025-03-17 17:06 [PATCH v4 00/18] riscv: add SBI FWFT misaligned exception delegation support Clément Léger
` (4 preceding siblings ...)
2025-03-17 17:06 ` [PATCH v4 05/18] riscv: misaligned: request misaligned exception from SBI Clément Léger
@ 2025-03-17 17:06 ` Clément Léger
2025-03-17 17:06 ` [PATCH v4 07/18] riscv: misaligned: use correct CONFIG_ ifdef for misaligned_access_speed Clément Léger
` (11 subsequent siblings)
17 siblings, 0 replies; 28+ messages in thread
From: Clément Léger @ 2025-03-17 17:06 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Anup Patel, Atish Patra,
Shuah Khan, Jonathan Corbet, linux-riscv, linux-kernel, linux-doc,
kvm, kvm-riscv, linux-kselftest
Cc: Clément Léger, Samuel Holland, Andrew Jones
schedule_on_each_cpu() was used without any good reason while documented
as very slow. This call was in the boot path, so better use
on_each_cpu() for scalar misaligned checking. Vector misaligned check
still needs to use schedule_on_each_cpu() since it requires irqs to be
enabled but that's less of a problem since this code is ran in a kthread.
Add a comment to explicit that.
Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
---
arch/riscv/kernel/traps_misaligned.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/arch/riscv/kernel/traps_misaligned.c b/arch/riscv/kernel/traps_misaligned.c
index fa7f100b95bd..4584f2e1d39d 100644
--- a/arch/riscv/kernel/traps_misaligned.c
+++ b/arch/riscv/kernel/traps_misaligned.c
@@ -616,6 +616,10 @@ bool check_vector_unaligned_access_emulated_all_cpus(void)
return false;
}
+ /*
+ * While being documented as very slow, schedule_on_each_cpu() is used since
+ * kernel_vector_begin() expects irqs to be enabled or it will panic()
+ */
schedule_on_each_cpu(check_vector_unaligned_access_emulated);
for_each_online_cpu(cpu)
@@ -636,7 +640,7 @@ bool check_vector_unaligned_access_emulated_all_cpus(void)
static bool unaligned_ctl __read_mostly;
-static void check_unaligned_access_emulated(struct work_struct *work __always_unused)
+static void check_unaligned_access_emulated(void *arg __always_unused)
{
int cpu = smp_processor_id();
long *mas_ptr = per_cpu_ptr(&misaligned_access_speed, cpu);
@@ -677,7 +681,7 @@ bool check_unaligned_access_emulated_all_cpus(void)
* accesses emulated since tasks requesting such control can run on any
* CPU.
*/
- schedule_on_each_cpu(check_unaligned_access_emulated);
+ on_each_cpu(check_unaligned_access_emulated, NULL, 1);
for_each_online_cpu(cpu)
if (per_cpu(misaligned_access_speed, cpu)
--
2.47.2
^ permalink raw reply related [flat|nested] 28+ messages in thread* [PATCH v4 07/18] riscv: misaligned: use correct CONFIG_ ifdef for misaligned_access_speed
2025-03-17 17:06 [PATCH v4 00/18] riscv: add SBI FWFT misaligned exception delegation support Clément Léger
` (5 preceding siblings ...)
2025-03-17 17:06 ` [PATCH v4 06/18] riscv: misaligned: use on_each_cpu() for scalar misaligned access probing Clément Léger
@ 2025-03-17 17:06 ` Clément Léger
2025-03-17 17:06 ` [PATCH v4 08/18] riscv: misaligned: move emulated access uniformity check in a function Clément Léger
` (10 subsequent siblings)
17 siblings, 0 replies; 28+ messages in thread
From: Clément Léger @ 2025-03-17 17:06 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Anup Patel, Atish Patra,
Shuah Khan, Jonathan Corbet, linux-riscv, linux-kernel, linux-doc,
kvm, kvm-riscv, linux-kselftest
Cc: Clément Léger, Samuel Holland, Andrew Jones
misaligned_access_speed is defined under CONFIG_RISCV_SCALAR_MISALIGNED
but was used under CONFIG_RISCV_PROBE_UNALIGNED_ACCESS. Fix that by
using the correct config option.
Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
---
arch/riscv/kernel/traps_misaligned.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/riscv/kernel/traps_misaligned.c b/arch/riscv/kernel/traps_misaligned.c
index 4584f2e1d39d..8175b3449b73 100644
--- a/arch/riscv/kernel/traps_misaligned.c
+++ b/arch/riscv/kernel/traps_misaligned.c
@@ -362,7 +362,7 @@ static int handle_scalar_misaligned_load(struct pt_regs *regs)
perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, addr);
-#ifdef CONFIG_RISCV_PROBE_UNALIGNED_ACCESS
+#ifdef CONFIG_RISCV_SCALAR_MISALIGNED
*this_cpu_ptr(&misaligned_access_speed) = RISCV_HWPROBE_MISALIGNED_SCALAR_EMULATED;
#endif
--
2.47.2
^ permalink raw reply related [flat|nested] 28+ messages in thread* [PATCH v4 08/18] riscv: misaligned: move emulated access uniformity check in a function
2025-03-17 17:06 [PATCH v4 00/18] riscv: add SBI FWFT misaligned exception delegation support Clément Léger
` (6 preceding siblings ...)
2025-03-17 17:06 ` [PATCH v4 07/18] riscv: misaligned: use correct CONFIG_ ifdef for misaligned_access_speed Clément Léger
@ 2025-03-17 17:06 ` Clément Léger
2025-03-17 17:06 ` [PATCH v4 09/18] riscv: misaligned: add a function to check misalign trap delegability Clément Léger
` (9 subsequent siblings)
17 siblings, 0 replies; 28+ messages in thread
From: Clément Léger @ 2025-03-17 17:06 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Anup Patel, Atish Patra,
Shuah Khan, Jonathan Corbet, linux-riscv, linux-kernel, linux-doc,
kvm, kvm-riscv, linux-kselftest
Cc: Clément Léger, Samuel Holland, Andrew Jones
Split the code that check for the uniformity of misaligned accesses
performance on all cpus from check_unaligned_access_emulated_all_cpus()
to its own function which will be used for delegation check. No
functional changes intended.
Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
---
arch/riscv/kernel/traps_misaligned.c | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/arch/riscv/kernel/traps_misaligned.c b/arch/riscv/kernel/traps_misaligned.c
index 8175b3449b73..3c77fc78fe4f 100644
--- a/arch/riscv/kernel/traps_misaligned.c
+++ b/arch/riscv/kernel/traps_misaligned.c
@@ -672,10 +672,20 @@ static int cpu_online_check_unaligned_access_emulated(unsigned int cpu)
return 0;
}
-bool check_unaligned_access_emulated_all_cpus(void)
+static bool all_cpus_unaligned_scalar_access_emulated(void)
{
int cpu;
+ for_each_online_cpu(cpu)
+ if (per_cpu(misaligned_access_speed, cpu) !=
+ RISCV_HWPROBE_MISALIGNED_SCALAR_EMULATED)
+ return false;
+
+ return true;
+}
+
+bool check_unaligned_access_emulated_all_cpus(void)
+{
/*
* We can only support PR_UNALIGN controls if all CPUs have misaligned
* accesses emulated since tasks requesting such control can run on any
@@ -683,10 +693,8 @@ bool check_unaligned_access_emulated_all_cpus(void)
*/
on_each_cpu(check_unaligned_access_emulated, NULL, 1);
- for_each_online_cpu(cpu)
- if (per_cpu(misaligned_access_speed, cpu)
- != RISCV_HWPROBE_MISALIGNED_SCALAR_EMULATED)
- return false;
+ if (!all_cpus_unaligned_scalar_access_emulated())
+ return false;
unaligned_ctl = true;
return true;
--
2.47.2
^ permalink raw reply related [flat|nested] 28+ messages in thread* [PATCH v4 09/18] riscv: misaligned: add a function to check misalign trap delegability
2025-03-17 17:06 [PATCH v4 00/18] riscv: add SBI FWFT misaligned exception delegation support Clément Léger
` (7 preceding siblings ...)
2025-03-17 17:06 ` [PATCH v4 08/18] riscv: misaligned: move emulated access uniformity check in a function Clément Léger
@ 2025-03-17 17:06 ` Clément Léger
2025-03-17 17:06 ` [PATCH v4 10/18] riscv: misaligned: factorize trap handling Clément Léger
` (8 subsequent siblings)
17 siblings, 0 replies; 28+ messages in thread
From: Clément Léger @ 2025-03-17 17:06 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Anup Patel, Atish Patra,
Shuah Khan, Jonathan Corbet, linux-riscv, linux-kernel, linux-doc,
kvm, kvm-riscv, linux-kselftest
Cc: Clément Léger, Samuel Holland, Andrew Jones
Checking for the delegability of the misaligned access trap is needed
for the KVM FWFT extension implementation. Add a function to get the
delegability of the misaligned trap exception.
Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
---
arch/riscv/include/asm/cpufeature.h | 5 +++++
arch/riscv/kernel/traps_misaligned.c | 17 +++++++++++++++--
2 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/arch/riscv/include/asm/cpufeature.h b/arch/riscv/include/asm/cpufeature.h
index ad7d26788e6a..8b97cba99fc3 100644
--- a/arch/riscv/include/asm/cpufeature.h
+++ b/arch/riscv/include/asm/cpufeature.h
@@ -69,12 +69,17 @@ int cpu_online_unaligned_access_init(unsigned int cpu);
#if defined(CONFIG_RISCV_SCALAR_MISALIGNED)
void unaligned_emulation_finish(void);
bool unaligned_ctl_available(void);
+bool misaligned_traps_can_delegate(void);
DECLARE_PER_CPU(long, misaligned_access_speed);
#else
static inline bool unaligned_ctl_available(void)
{
return false;
}
+static inline bool misaligned_traps_can_delegate(void)
+{
+ return false;
+}
#endif
bool check_vector_unaligned_access_emulated_all_cpus(void);
diff --git a/arch/riscv/kernel/traps_misaligned.c b/arch/riscv/kernel/traps_misaligned.c
index 3c77fc78fe4f..0fb663ac200f 100644
--- a/arch/riscv/kernel/traps_misaligned.c
+++ b/arch/riscv/kernel/traps_misaligned.c
@@ -715,10 +715,10 @@ static int cpu_online_check_unaligned_access_emulated(unsigned int cpu)
}
#endif
-#ifdef CONFIG_RISCV_SBI
-
static bool misaligned_traps_delegated;
+#ifdef CONFIG_RISCV_SBI
+
static int cpu_online_sbi_unaligned_setup(unsigned int cpu)
{
if (sbi_fwft_set(SBI_FWFT_MISALIGNED_EXC_DELEG, 1, 0) &&
@@ -760,6 +760,7 @@ static int cpu_online_sbi_unaligned_setup(unsigned int cpu __always_unused)
{
return 0;
}
+
#endif
int cpu_online_unaligned_access_init(unsigned int cpu)
@@ -772,3 +773,15 @@ int cpu_online_unaligned_access_init(unsigned int cpu)
return cpu_online_check_unaligned_access_emulated(cpu);
}
+
+bool misaligned_traps_can_delegate(void)
+{
+ /*
+ * Either we successfully requested misaligned traps delegation for all
+ * CPUS or the SBI does not implemented FWFT extension but delegated the
+ * exception by default.
+ */
+ return misaligned_traps_delegated ||
+ all_cpus_unaligned_scalar_access_emulated();
+}
+EXPORT_SYMBOL_GPL(misaligned_traps_can_delegate);
--
2.47.2
^ permalink raw reply related [flat|nested] 28+ messages in thread* [PATCH v4 10/18] riscv: misaligned: factorize trap handling
2025-03-17 17:06 [PATCH v4 00/18] riscv: add SBI FWFT misaligned exception delegation support Clément Léger
` (8 preceding siblings ...)
2025-03-17 17:06 ` [PATCH v4 09/18] riscv: misaligned: add a function to check misalign trap delegability Clément Léger
@ 2025-03-17 17:06 ` Clément Léger
2025-03-17 17:06 ` [PATCH v4 11/18] riscv: misaligned: enable IRQs while handling misaligned accesses Clément Léger
` (7 subsequent siblings)
17 siblings, 0 replies; 28+ messages in thread
From: Clément Léger @ 2025-03-17 17:06 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Anup Patel, Atish Patra,
Shuah Khan, Jonathan Corbet, linux-riscv, linux-kernel, linux-doc,
kvm, kvm-riscv, linux-kselftest
Cc: Clément Léger, Samuel Holland, Andrew Jones
misaligned accesses traps are not nmi and should be treated as normal
one using irqentry_enter()/exit(). Since both load/store and user/kernel
should use almost the same path and that we are going to add some code
around that, factorize it.
Signed-off-by: Clément Léger <cleger@rivosinc.com>
---
arch/riscv/kernel/traps.c | 49 ++++++++++++++++-----------------------
1 file changed, 20 insertions(+), 29 deletions(-)
diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c
index 8ff8e8b36524..55d9f3450398 100644
--- a/arch/riscv/kernel/traps.c
+++ b/arch/riscv/kernel/traps.c
@@ -198,47 +198,38 @@ asmlinkage __visible __trap_section void do_trap_insn_illegal(struct pt_regs *re
DO_ERROR_INFO(do_trap_load_fault,
SIGSEGV, SEGV_ACCERR, "load access fault");
-asmlinkage __visible __trap_section void do_trap_load_misaligned(struct pt_regs *regs)
+enum misaligned_access_type {
+ MISALIGNED_STORE,
+ MISALIGNED_LOAD,
+};
+
+static void do_trap_misaligned(struct pt_regs *regs, enum misaligned_access_type type)
{
- if (user_mode(regs)) {
- irqentry_enter_from_user_mode(regs);
+ irqentry_state_t state = irqentry_enter(regs);
+ if (type == MISALIGNED_LOAD) {
if (handle_misaligned_load(regs))
do_trap_error(regs, SIGBUS, BUS_ADRALN, regs->epc,
- "Oops - load address misaligned");
-
- irqentry_exit_to_user_mode(regs);
+ "Oops - load address misaligned");
} else {
- irqentry_state_t state = irqentry_nmi_enter(regs);
-
- if (handle_misaligned_load(regs))
+ if (handle_misaligned_store(regs))
do_trap_error(regs, SIGBUS, BUS_ADRALN, regs->epc,
- "Oops - load address misaligned");
-
- irqentry_nmi_exit(regs, state);
+ "Oops - store (or AMO) address misaligned");
}
+
+ irqentry_exit(regs, state);
}
-asmlinkage __visible __trap_section void do_trap_store_misaligned(struct pt_regs *regs)
+asmlinkage __visible __trap_section void do_trap_load_misaligned(struct pt_regs *regs)
{
- if (user_mode(regs)) {
- irqentry_enter_from_user_mode(regs);
-
- if (handle_misaligned_store(regs))
- do_trap_error(regs, SIGBUS, BUS_ADRALN, regs->epc,
- "Oops - store (or AMO) address misaligned");
-
- irqentry_exit_to_user_mode(regs);
- } else {
- irqentry_state_t state = irqentry_nmi_enter(regs);
-
- if (handle_misaligned_store(regs))
- do_trap_error(regs, SIGBUS, BUS_ADRALN, regs->epc,
- "Oops - store (or AMO) address misaligned");
+ do_trap_misaligned(regs, MISALIGNED_LOAD);
+}
- irqentry_nmi_exit(regs, state);
- }
+asmlinkage __visible __trap_section void do_trap_store_misaligned(struct pt_regs *regs)
+{
+ do_trap_misaligned(regs, MISALIGNED_STORE);
}
+
DO_ERROR_INFO(do_trap_store_fault,
SIGSEGV, SEGV_ACCERR, "store (or AMO) access fault");
DO_ERROR_INFO(do_trap_ecall_s,
--
2.47.2
^ permalink raw reply related [flat|nested] 28+ messages in thread* [PATCH v4 11/18] riscv: misaligned: enable IRQs while handling misaligned accesses
2025-03-17 17:06 [PATCH v4 00/18] riscv: add SBI FWFT misaligned exception delegation support Clément Léger
` (9 preceding siblings ...)
2025-03-17 17:06 ` [PATCH v4 10/18] riscv: misaligned: factorize trap handling Clément Léger
@ 2025-03-17 17:06 ` Clément Léger
2025-03-17 17:06 ` [PATCH v4 12/18] riscv: misaligned: use get_user() instead of __get_user() Clément Léger
` (6 subsequent siblings)
17 siblings, 0 replies; 28+ messages in thread
From: Clément Léger @ 2025-03-17 17:06 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Anup Patel, Atish Patra,
Shuah Khan, Jonathan Corbet, linux-riscv, linux-kernel, linux-doc,
kvm, kvm-riscv, linux-kselftest
Cc: Clément Léger, Samuel Holland, Andrew Jones
We can safely reenable IRQs if they were enabled in the previous
context. This allows to access user memory that could potentially
trigger a page fault.
Signed-off-by: Clément Léger <cleger@rivosinc.com>
---
arch/riscv/kernel/traps.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c
index 55d9f3450398..3eecc2addc41 100644
--- a/arch/riscv/kernel/traps.c
+++ b/arch/riscv/kernel/traps.c
@@ -206,6 +206,11 @@ enum misaligned_access_type {
static void do_trap_misaligned(struct pt_regs *regs, enum misaligned_access_type type)
{
irqentry_state_t state = irqentry_enter(regs);
+ bool enable_irqs = !regs_irqs_disabled(regs);
+
+ /* Enable interrupts if they were enabled in the interrupted context. */
+ if (enable_irqs)
+ local_irq_enable();
if (type == MISALIGNED_LOAD) {
if (handle_misaligned_load(regs))
@@ -217,6 +222,9 @@ static void do_trap_misaligned(struct pt_regs *regs, enum misaligned_access_type
"Oops - store (or AMO) address misaligned");
}
+ if (enable_irqs)
+ local_irq_disable();
+
irqentry_exit(regs, state);
}
--
2.47.2
^ permalink raw reply related [flat|nested] 28+ messages in thread* [PATCH v4 12/18] riscv: misaligned: use get_user() instead of __get_user()
2025-03-17 17:06 [PATCH v4 00/18] riscv: add SBI FWFT misaligned exception delegation support Clément Léger
` (10 preceding siblings ...)
2025-03-17 17:06 ` [PATCH v4 11/18] riscv: misaligned: enable IRQs while handling misaligned accesses Clément Léger
@ 2025-03-17 17:06 ` Clément Léger
2025-03-17 17:06 ` [PATCH v4 13/18] Documentation/sysctl: add riscv to unaligned-trap supported archs Clément Léger
` (5 subsequent siblings)
17 siblings, 0 replies; 28+ messages in thread
From: Clément Léger @ 2025-03-17 17:06 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Anup Patel, Atish Patra,
Shuah Khan, Jonathan Corbet, linux-riscv, linux-kernel, linux-doc,
kvm, kvm-riscv, linux-kselftest
Cc: Clément Léger, Samuel Holland, Andrew Jones
Now that we can safely handle user memory accesses while in the
misaligned access handlers, use get_user() instead of __get_user() to
have user memory access checks.
Signed-off-by: Clément Léger <cleger@rivosinc.com>
---
arch/riscv/kernel/traps_misaligned.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/riscv/kernel/traps_misaligned.c b/arch/riscv/kernel/traps_misaligned.c
index 0fb663ac200f..90466a171f58 100644
--- a/arch/riscv/kernel/traps_misaligned.c
+++ b/arch/riscv/kernel/traps_misaligned.c
@@ -269,7 +269,7 @@ static unsigned long get_f32_rs(unsigned long insn, u8 fp_reg_offset,
int __ret; \
\
if (user_mode(regs)) { \
- __ret = __get_user(insn, (type __user *) insn_addr); \
+ __ret = get_user(insn, (type __user *) insn_addr); \
} else { \
insn = *(type *)insn_addr; \
__ret = 0; \
--
2.47.2
^ permalink raw reply related [flat|nested] 28+ messages in thread* [PATCH v4 13/18] Documentation/sysctl: add riscv to unaligned-trap supported archs
2025-03-17 17:06 [PATCH v4 00/18] riscv: add SBI FWFT misaligned exception delegation support Clément Léger
` (11 preceding siblings ...)
2025-03-17 17:06 ` [PATCH v4 12/18] riscv: misaligned: use get_user() instead of __get_user() Clément Léger
@ 2025-03-17 17:06 ` Clément Léger
2025-03-17 17:06 ` [PATCH v4 14/18] selftests: riscv: add misaligned access testing Clément Léger
` (4 subsequent siblings)
17 siblings, 0 replies; 28+ messages in thread
From: Clément Léger @ 2025-03-17 17:06 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Anup Patel, Atish Patra,
Shuah Khan, Jonathan Corbet, linux-riscv, linux-kernel, linux-doc,
kvm, kvm-riscv, linux-kselftest
Cc: Clément Léger, Samuel Holland, Andrew Jones
riscv supports the "unaligned-trap" sysctl variable, add it to the list
of supported architectures.
Signed-off-by: Clément Léger <cleger@rivosinc.com>
---
Documentation/admin-guide/sysctl/kernel.rst | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Documentation/admin-guide/sysctl/kernel.rst b/Documentation/admin-guide/sysctl/kernel.rst
index dd49a89a62d3..a38e91c4d92c 100644
--- a/Documentation/admin-guide/sysctl/kernel.rst
+++ b/Documentation/admin-guide/sysctl/kernel.rst
@@ -1595,8 +1595,8 @@ unaligned-trap
On architectures where unaligned accesses cause traps, and where this
feature is supported (``CONFIG_SYSCTL_ARCH_UNALIGN_ALLOW``; currently,
-``arc``, ``parisc`` and ``loongarch``), controls whether unaligned traps
-are caught and emulated (instead of failing).
+``arc``, ``parisc``, ``loongarch`` and ``riscv``), controls whether unaligned
+traps are caught and emulated (instead of failing).
= ========================================================
0 Do not emulate unaligned accesses.
--
2.47.2
^ permalink raw reply related [flat|nested] 28+ messages in thread* [PATCH v4 14/18] selftests: riscv: add misaligned access testing
2025-03-17 17:06 [PATCH v4 00/18] riscv: add SBI FWFT misaligned exception delegation support Clément Léger
` (12 preceding siblings ...)
2025-03-17 17:06 ` [PATCH v4 13/18] Documentation/sysctl: add riscv to unaligned-trap supported archs Clément Léger
@ 2025-03-17 17:06 ` Clément Léger
2025-03-17 17:06 ` [PATCH v4 15/18] RISC-V: KVM: add SBI extension init()/deinit() functions Clément Léger
` (3 subsequent siblings)
17 siblings, 0 replies; 28+ messages in thread
From: Clément Léger @ 2025-03-17 17:06 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Anup Patel, Atish Patra,
Shuah Khan, Jonathan Corbet, linux-riscv, linux-kernel, linux-doc,
kvm, kvm-riscv, linux-kselftest
Cc: Clément Léger, Samuel Holland, Andrew Jones
Now that the kernel can emulate misaligned access and control its
behavior, add a selftest for that. This selftest tests all the currently
emulated instruction (except for the RV32 compressed ones which are left
as a future exercise for a RV32 user). For the FPU instructions, all the
FPU registers are tested.
Signed-off-by: Clément Léger <cleger@rivosinc.com>
---
.../selftests/riscv/misaligned/.gitignore | 1 +
.../selftests/riscv/misaligned/Makefile | 12 +
.../selftests/riscv/misaligned/common.S | 33 +++
.../testing/selftests/riscv/misaligned/fpu.S | 180 +++++++++++++
tools/testing/selftests/riscv/misaligned/gp.S | 103 +++++++
.../selftests/riscv/misaligned/misaligned.c | 254 ++++++++++++++++++
6 files changed, 583 insertions(+)
create mode 100644 tools/testing/selftests/riscv/misaligned/.gitignore
create mode 100644 tools/testing/selftests/riscv/misaligned/Makefile
create mode 100644 tools/testing/selftests/riscv/misaligned/common.S
create mode 100644 tools/testing/selftests/riscv/misaligned/fpu.S
create mode 100644 tools/testing/selftests/riscv/misaligned/gp.S
create mode 100644 tools/testing/selftests/riscv/misaligned/misaligned.c
diff --git a/tools/testing/selftests/riscv/misaligned/.gitignore b/tools/testing/selftests/riscv/misaligned/.gitignore
new file mode 100644
index 000000000000..5eff15a1f981
--- /dev/null
+++ b/tools/testing/selftests/riscv/misaligned/.gitignore
@@ -0,0 +1 @@
+misaligned
diff --git a/tools/testing/selftests/riscv/misaligned/Makefile b/tools/testing/selftests/riscv/misaligned/Makefile
new file mode 100644
index 000000000000..1aa40110c50d
--- /dev/null
+++ b/tools/testing/selftests/riscv/misaligned/Makefile
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (C) 2021 ARM Limited
+# Originally tools/testing/arm64/abi/Makefile
+
+CFLAGS += -I$(top_srcdir)/tools/include
+
+TEST_GEN_PROGS := misaligned
+
+include ../../lib.mk
+
+$(OUTPUT)/misaligned: misaligned.c fpu.S gp.S
+ $(CC) -g3 -static -o$@ -march=rv64imafdc $(CFLAGS) $(LDFLAGS) $^
diff --git a/tools/testing/selftests/riscv/misaligned/common.S b/tools/testing/selftests/riscv/misaligned/common.S
new file mode 100644
index 000000000000..8fa00035bd5d
--- /dev/null
+++ b/tools/testing/selftests/riscv/misaligned/common.S
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2025 Rivos Inc.
+ *
+ * Authors:
+ * Clément Léger <cleger@rivosinc.com>
+ */
+
+.macro lb_sb temp, offset, src, dst
+ lb \temp, \offset(\src)
+ sb \temp, \offset(\dst)
+.endm
+
+.macro copy_long_to temp, src, dst
+ lb_sb \temp, 0, \src, \dst,
+ lb_sb \temp, 1, \src, \dst,
+ lb_sb \temp, 2, \src, \dst,
+ lb_sb \temp, 3, \src, \dst,
+ lb_sb \temp, 4, \src, \dst,
+ lb_sb \temp, 5, \src, \dst,
+ lb_sb \temp, 6, \src, \dst,
+ lb_sb \temp, 7, \src, \dst,
+.endm
+
+.macro sp_stack_prologue offset
+ addi sp, sp, -8
+ sub sp, sp, \offset
+.endm
+
+.macro sp_stack_epilogue offset
+ add sp, sp, \offset
+ addi sp, sp, 8
+.endm
diff --git a/tools/testing/selftests/riscv/misaligned/fpu.S b/tools/testing/selftests/riscv/misaligned/fpu.S
new file mode 100644
index 000000000000..d008bff58310
--- /dev/null
+++ b/tools/testing/selftests/riscv/misaligned/fpu.S
@@ -0,0 +1,180 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2025 Rivos Inc.
+ *
+ * Authors:
+ * Clément Léger <cleger@rivosinc.com>
+ */
+
+#include "common.S"
+
+#define CASE_ALIGN 4
+
+.macro fpu_load_inst fpreg, inst, precision, load_reg
+.align CASE_ALIGN
+ \inst \fpreg, 0(\load_reg)
+ fmv.\precision fa0, \fpreg
+ j 2f
+.endm
+
+#define flw(__fpreg) fpu_load_inst __fpreg, flw, s, s1
+#define fld(__fpreg) fpu_load_inst __fpreg, fld, d, s1
+#define c_flw(__fpreg) fpu_load_inst __fpreg, c.flw, s, s1
+#define c_fld(__fpreg) fpu_load_inst __fpreg, c.fld, d, s1
+#define c_fldsp(__fpreg) fpu_load_inst __fpreg, c.fldsp, d, sp
+
+.macro fpu_store_inst fpreg, inst, precision, store_reg
+.align CASE_ALIGN
+ fmv.\precision \fpreg, fa0
+ \inst \fpreg, 0(\store_reg)
+ j 2f
+.endm
+
+#define fsw(__fpreg) fpu_store_inst __fpreg, fsw, s, s1
+#define fsd(__fpreg) fpu_store_inst __fpreg, fsd, d, s1
+#define c_fsw(__fpreg) fpu_store_inst __fpreg, c.fsw, s, s1
+#define c_fsd(__fpreg) fpu_store_inst __fpreg, c.fsd, d, s1
+#define c_fsdsp(__fpreg) fpu_store_inst __fpreg, c.fsdsp, d, sp
+
+.macro fp_test_prologue
+ move s1, a1
+ /*
+ * Compute jump offset to store the correct FP register since we don't
+ * have indirect FP register access (or at least we don't use this
+ * extension so that works on all archs)
+ */
+ sll t0, a0, CASE_ALIGN
+ la t2, 1f
+ add t0, t0, t2
+ jr t0
+.align CASE_ALIGN
+1:
+.endm
+
+.macro fp_test_prologue_compressed
+ /* FP registers for compressed instructions starts from 8 to 16 */
+ addi a0, a0, -8
+ fp_test_prologue
+.endm
+
+#define fp_test_body_compressed(__inst_func) \
+ __inst_func(f8); \
+ __inst_func(f9); \
+ __inst_func(f10); \
+ __inst_func(f11); \
+ __inst_func(f12); \
+ __inst_func(f13); \
+ __inst_func(f14); \
+ __inst_func(f15); \
+2:
+
+#define fp_test_body(__inst_func) \
+ __inst_func(f0); \
+ __inst_func(f1); \
+ __inst_func(f2); \
+ __inst_func(f3); \
+ __inst_func(f4); \
+ __inst_func(f5); \
+ __inst_func(f6); \
+ __inst_func(f7); \
+ __inst_func(f8); \
+ __inst_func(f9); \
+ __inst_func(f10); \
+ __inst_func(f11); \
+ __inst_func(f12); \
+ __inst_func(f13); \
+ __inst_func(f14); \
+ __inst_func(f15); \
+ __inst_func(f16); \
+ __inst_func(f17); \
+ __inst_func(f18); \
+ __inst_func(f19); \
+ __inst_func(f20); \
+ __inst_func(f21); \
+ __inst_func(f22); \
+ __inst_func(f23); \
+ __inst_func(f24); \
+ __inst_func(f25); \
+ __inst_func(f26); \
+ __inst_func(f27); \
+ __inst_func(f28); \
+ __inst_func(f29); \
+ __inst_func(f30); \
+ __inst_func(f31); \
+2:
+.text
+
+#define __gen_test_inst(__inst, __suffix) \
+.global test_ ## __inst; \
+test_ ## __inst:; \
+ fp_test_prologue ## __suffix; \
+ fp_test_body ## __suffix(__inst); \
+ ret
+
+#define gen_test_inst_compressed(__inst) \
+ .option arch,+c; \
+ __gen_test_inst(c_ ## __inst, _compressed)
+
+#define gen_test_inst(__inst) \
+ .balign 16; \
+ .option push; \
+ .option arch,-c; \
+ __gen_test_inst(__inst, ); \
+ .option pop
+
+.macro fp_test_prologue_load_compressed_sp
+ copy_long_to t0, a1, sp
+.endm
+
+.macro fp_test_epilogue_load_compressed_sp
+.endm
+
+.macro fp_test_prologue_store_compressed_sp
+.endm
+
+.macro fp_test_epilogue_store_compressed_sp
+ copy_long_to t0, sp, a1
+.endm
+
+#define gen_inst_compressed_sp(__inst, __type) \
+ .global test_c_ ## __inst ## sp; \
+ test_c_ ## __inst ## sp:; \
+ sp_stack_prologue a2; \
+ fp_test_prologue_## __type ## _compressed_sp; \
+ fp_test_prologue_compressed; \
+ fp_test_body_compressed(c_ ## __inst ## sp); \
+ fp_test_epilogue_## __type ## _compressed_sp; \
+ sp_stack_epilogue a2; \
+ ret
+
+#define gen_test_load_compressed_sp(__inst) gen_inst_compressed_sp(__inst, load)
+#define gen_test_store_compressed_sp(__inst) gen_inst_compressed_sp(__inst, store)
+
+/*
+ * float_fsw_reg - Set a FP register from a register containing the value
+ * a0 = FP register index to be set
+ * a1 = addr where to store register value
+ * a2 = address offset
+ * a3 = value to be store
+ */
+gen_test_inst(fsw)
+
+/*
+ * float_flw_reg - Get a FP register value and return it
+ * a0 = FP register index to be retrieved
+ * a1 = addr to load register from
+ * a2 = address offset
+ */
+gen_test_inst(flw)
+
+gen_test_inst(fsd)
+#ifdef __riscv_compressed
+gen_test_inst_compressed(fsd)
+gen_test_store_compressed_sp(fsd)
+#endif
+
+gen_test_inst(fld)
+#ifdef __riscv_compressed
+gen_test_inst_compressed(fld)
+gen_test_load_compressed_sp(fld)
+#endif
diff --git a/tools/testing/selftests/riscv/misaligned/gp.S b/tools/testing/selftests/riscv/misaligned/gp.S
new file mode 100644
index 000000000000..f53f4c6d81dd
--- /dev/null
+++ b/tools/testing/selftests/riscv/misaligned/gp.S
@@ -0,0 +1,103 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2025 Rivos Inc.
+ *
+ * Authors:
+ * Clément Léger <cleger@rivosinc.com>
+ */
+
+#include "common.S"
+
+.text
+
+.macro __gen_test_inst inst, src_reg
+ \inst a2, 0(\src_reg)
+ move a0, a2
+.endm
+
+.macro gen_func_header func_name, rvc
+ .option arch,\rvc
+ .global test_\func_name
+ test_\func_name:
+.endm
+
+.macro gen_test_inst inst
+ .option push
+ gen_func_header \inst, -c
+ __gen_test_inst \inst, a0
+ .option pop
+ ret
+.endm
+
+.macro __gen_test_inst_c name, src_reg
+ .option push
+ gen_func_header c_\name, +c
+ __gen_test_inst c.\name, \src_reg
+ .option pop
+ ret
+.endm
+
+.macro gen_test_inst_c name
+ __gen_test_inst_c \name, a0
+.endm
+
+
+.macro gen_test_inst_load_c_sp name
+ .option push
+ gen_func_header c_\name\()sp, +c
+ sp_stack_prologue a1
+ copy_long_to t0, a0, sp
+ c.ldsp a0, 0(sp)
+ sp_stack_epilogue a1
+ .option pop
+ ret
+.endm
+
+.macro lb_sp_sb_a0 reg, offset
+ lb_sb \reg, \offset, sp, a0
+.endm
+
+.macro gen_test_inst_store_c_sp inst_name
+ .option push
+ gen_func_header c_\inst_name\()sp, +c
+ /* Misalign stack pointer */
+ sp_stack_prologue a1
+ /* Misalign access */
+ c.sdsp a2, 0(sp)
+ copy_long_to t0, sp, a0
+ sp_stack_epilogue a1
+ .option pop
+ ret
+.endm
+
+
+ /*
+ * a0 = addr to load from
+ * a1 = address offset
+ * a2 = value to be loaded
+ */
+gen_test_inst lh
+gen_test_inst lhu
+gen_test_inst lw
+gen_test_inst lwu
+gen_test_inst ld
+#ifdef __riscv_compressed
+gen_test_inst_c lw
+gen_test_inst_c ld
+gen_test_inst_load_c_sp ld
+#endif
+
+/*
+ * a0 = addr where to store value
+ * a1 = address offset
+ * a2 = value to be stored
+ */
+gen_test_inst sh
+gen_test_inst sw
+gen_test_inst sd
+#ifdef __riscv_compressed
+gen_test_inst_c sw
+gen_test_inst_c sd
+gen_test_inst_store_c_sp sd
+#endif
+
diff --git a/tools/testing/selftests/riscv/misaligned/misaligned.c b/tools/testing/selftests/riscv/misaligned/misaligned.c
new file mode 100644
index 000000000000..c66aa87ec03e
--- /dev/null
+++ b/tools/testing/selftests/riscv/misaligned/misaligned.c
@@ -0,0 +1,254 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2025 Rivos Inc.
+ *
+ * Authors:
+ * Clément Léger <cleger@rivosinc.com>
+ */
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <linux/ptrace.h>
+#include "../../kselftest_harness.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <float.h>
+#include <errno.h>
+#include <math.h>
+#include <string.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <ucontext.h>
+
+#include <sys/prctl.h>
+
+#define stringify(s) __stringify(s)
+#define __stringify(s) #s
+
+#define VAL16 0x1234
+#define VAL32 0xDEADBEEF
+#define VAL64 0x45674321D00DF789
+
+#define VAL_float 78951.234375
+#define VAL_double 567890.512396965789589290
+
+static bool float_equal(float a, float b)
+{
+ float scaled_epsilon;
+ float difference = fabsf(a - b);
+
+ // Scale to the largest value.
+ a = fabsf(a);
+ b = fabsf(b);
+ if (a > b)
+ scaled_epsilon = FLT_EPSILON * a;
+ else
+ scaled_epsilon = FLT_EPSILON * b;
+
+ return difference <= scaled_epsilon;
+}
+
+static bool double_equal(double a, double b)
+{
+ double scaled_epsilon;
+ double difference = fabsf(a - b);
+
+ // Scale to the largest value.
+ a = fabs(a);
+ b = fabs(b);
+ if (a > b)
+ scaled_epsilon = DBL_EPSILON * a;
+ else
+ scaled_epsilon = DBL_EPSILON * b;
+
+ return difference <= scaled_epsilon;
+}
+
+#define fpu_load_proto(__inst, __type) \
+extern __type test_ ## __inst(unsigned long fp_reg, void *addr, unsigned long offset, __type value)
+
+fpu_load_proto(flw, float);
+fpu_load_proto(fld, double);
+fpu_load_proto(c_flw, float);
+fpu_load_proto(c_fld, double);
+fpu_load_proto(c_fldsp, double);
+
+#define fpu_store_proto(__inst, __type) \
+extern void test_ ## __inst(unsigned long fp_reg, void *addr, unsigned long offset, __type value)
+
+fpu_store_proto(fsw, float);
+fpu_store_proto(fsd, double);
+fpu_store_proto(c_fsw, float);
+fpu_store_proto(c_fsd, double);
+fpu_store_proto(c_fsdsp, double);
+
+#define gp_load_proto(__inst, __type) \
+extern __type test_ ## __inst(void *addr, unsigned long offset, __type value)
+
+gp_load_proto(lh, uint16_t);
+gp_load_proto(lhu, uint16_t);
+gp_load_proto(lw, uint32_t);
+gp_load_proto(lwu, uint32_t);
+gp_load_proto(ld, uint64_t);
+gp_load_proto(c_lw, uint32_t);
+gp_load_proto(c_ld, uint64_t);
+gp_load_proto(c_ldsp, uint64_t);
+
+#define gp_store_proto(__inst, __type) \
+extern void test_ ## __inst(void *addr, unsigned long offset, __type value)
+
+gp_store_proto(sh, uint16_t);
+gp_store_proto(sw, uint32_t);
+gp_store_proto(sd, uint64_t);
+gp_store_proto(c_sw, uint32_t);
+gp_store_proto(c_sd, uint64_t);
+gp_store_proto(c_sdsp, uint64_t);
+
+#define TEST_GP_LOAD(__inst, __type_size) \
+TEST(gp_load_ ## __inst) \
+{ \
+ int offset, ret; \
+ uint8_t buf[16] __attribute__((aligned(16))); \
+ \
+ ret = prctl(PR_SET_UNALIGN, PR_UNALIGN_NOPRINT); \
+ ASSERT_EQ(ret, 0); \
+ \
+ for (offset = 1; offset < __type_size / 8; offset++) { \
+ uint ## __type_size ## _t val = VAL ## __type_size; \
+ uint ## __type_size ## _t *ptr = (uint ## __type_size ## _t *) (buf + offset); \
+ memcpy(ptr, &val, sizeof(val)); \
+ val = test_ ## __inst(ptr, offset, val); \
+ EXPECT_EQ(VAL ## __type_size, val); \
+ } \
+}
+
+TEST_GP_LOAD(lh, 16);
+TEST_GP_LOAD(lhu, 16);
+TEST_GP_LOAD(lw, 32);
+TEST_GP_LOAD(lwu, 32);
+TEST_GP_LOAD(ld, 64);
+#ifdef __riscv_compressed
+TEST_GP_LOAD(c_lw, 32);
+TEST_GP_LOAD(c_ld, 64);
+TEST_GP_LOAD(c_ldsp, 64);
+#endif
+
+#define TEST_GP_STORE(__inst, __type_size) \
+TEST(gp_load_ ## __inst) \
+{ \
+ int offset, ret; \
+ uint8_t buf[16] __attribute__((aligned(16))); \
+ \
+ ret = prctl(PR_SET_UNALIGN, PR_UNALIGN_NOPRINT); \
+ ASSERT_EQ(ret, 0); \
+ \
+ for (offset = 1; offset < __type_size / 8; offset++) { \
+ uint ## __type_size ## _t val = VAL ## __type_size; \
+ uint ## __type_size ## _t *ptr = (uint ## __type_size ## _t *) (buf + offset); \
+ memset(ptr, 0, sizeof(val)); \
+ test_ ## __inst(ptr, offset, val); \
+ memcpy(&val, ptr, sizeof(val)); \
+ EXPECT_EQ(VAL ## __type_size, val); \
+ } \
+}
+TEST_GP_STORE(sh, 16);
+TEST_GP_STORE(sw, 32);
+TEST_GP_STORE(sd, 64);
+#ifdef __riscv_compressed
+TEST_GP_STORE(c_sw, 32);
+TEST_GP_STORE(c_sd, 64);
+TEST_GP_STORE(c_sdsp, 64);
+#endif
+
+#define __TEST_FPU_LOAD(__type, __inst, __reg_start, __reg_end) \
+TEST(fpu_load_ ## __inst) \
+{ \
+ int i, ret, offset, fp_reg; \
+ uint8_t buf[16] __attribute__((aligned(16))); \
+ \
+ ret = prctl(PR_SET_UNALIGN, PR_UNALIGN_NOPRINT); \
+ ASSERT_EQ(ret, 0); \
+ \
+ for (fp_reg = __reg_start; fp_reg < __reg_end; fp_reg++) { \
+ for (offset = 1; offset < 4; offset++) { \
+ void *load_addr = (buf + offset); \
+ __type val = VAL_ ## __type ; \
+ \
+ memcpy(load_addr, &val, sizeof(val)); \
+ val = test_ ## __inst(fp_reg, load_addr, offset, val); \
+ EXPECT_TRUE(__type ##_equal(val, VAL_## __type)); \
+ } \
+ } \
+}
+#define TEST_FPU_LOAD(__type, __inst) \
+ __TEST_FPU_LOAD(__type, __inst, 0, 32)
+#define TEST_FPU_LOAD_COMPRESSED(__type, __inst) \
+ __TEST_FPU_LOAD(__type, __inst, 8, 16)
+
+TEST_FPU_LOAD(float, flw)
+TEST_FPU_LOAD(double, fld)
+#ifdef __riscv_compressed
+TEST_FPU_LOAD_COMPRESSED(double, c_fld)
+TEST_FPU_LOAD_COMPRESSED(double, c_fldsp)
+#endif
+
+#define __TEST_FPU_STORE(__type, __inst, __reg_start, __reg_end) \
+TEST(fpu_store_ ## __inst) \
+{ \
+ int i, ret, offset, fp_reg; \
+ uint8_t buf[16] __attribute__((aligned(16))); \
+ \
+ ret = prctl(PR_SET_UNALIGN, PR_UNALIGN_NOPRINT); \
+ ASSERT_EQ(ret, 0); \
+ \
+ for (fp_reg = __reg_start; fp_reg < __reg_end; fp_reg++) { \
+ for (offset = 1; offset < 4; offset++) { \
+ \
+ void *store_addr = (buf + offset); \
+ __type val = VAL_ ## __type ; \
+ \
+ test_ ## __inst(fp_reg, store_addr, offset, val); \
+ memcpy(&val, store_addr, sizeof(val)); \
+ EXPECT_TRUE(__type ## _equal(val, VAL_## __type)); \
+ } \
+ } \
+}
+#define TEST_FPU_STORE(__type, __inst) \
+ __TEST_FPU_STORE(__type, __inst, 0, 32)
+#define TEST_FPU_STORE_COMPRESSED(__type, __inst) \
+ __TEST_FPU_STORE(__type, __inst, 8, 16)
+
+TEST_FPU_STORE(float, fsw)
+TEST_FPU_STORE(double, fsd)
+#ifdef __riscv_compressed
+TEST_FPU_STORE_COMPRESSED(double, c_fsd)
+TEST_FPU_STORE_COMPRESSED(double, c_fsdsp)
+#endif
+
+TEST_SIGNAL(gen_sigbus, SIGBUS)
+{
+ uint32_t *ptr;
+ uint8_t buf[16] __attribute__((aligned(16)));
+ int ret;
+
+ ret = prctl(PR_SET_UNALIGN, PR_UNALIGN_SIGBUS);
+ ASSERT_EQ(ret, 0);
+
+ ptr = (uint32_t *)(buf + 1);
+ *ptr = 0xDEADBEEFULL;
+}
+
+int main(int argc, char **argv)
+{
+ int ret, val;
+
+ ret = prctl(PR_GET_UNALIGN, &val);
+ if (ret == -1 && errno == EINVAL)
+ ksft_exit_skip("SKIP GET_UNALIGN_CTL not supported\n");
+
+ exit(test_harness_run(argc, argv));
+}
--
2.47.2
^ permalink raw reply related [flat|nested] 28+ messages in thread* [PATCH v4 15/18] RISC-V: KVM: add SBI extension init()/deinit() functions
2025-03-17 17:06 [PATCH v4 00/18] riscv: add SBI FWFT misaligned exception delegation support Clément Léger
` (13 preceding siblings ...)
2025-03-17 17:06 ` [PATCH v4 14/18] selftests: riscv: add misaligned access testing Clément Léger
@ 2025-03-17 17:06 ` Clément Léger
2025-03-22 12:23 ` Andrew Jones
2025-03-17 17:06 ` [PATCH v4 16/18] RISC-V: KVM: add SBI extension reset callback Clément Léger
` (2 subsequent siblings)
17 siblings, 1 reply; 28+ messages in thread
From: Clément Léger @ 2025-03-17 17:06 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Anup Patel, Atish Patra,
Shuah Khan, Jonathan Corbet, linux-riscv, linux-kernel, linux-doc,
kvm, kvm-riscv, linux-kselftest
Cc: Clément Léger, Samuel Holland, Andrew Jones
The FWFT SBI extension will need to dynamically allocate memory and do
init time specific initialization. Add an init/deinit callbacks that
allows to do so.
Signed-off-by: Clément Léger <cleger@rivosinc.com>
---
arch/riscv/include/asm/kvm_vcpu_sbi.h | 9 +++++++++
arch/riscv/kvm/vcpu.c | 2 ++
arch/riscv/kvm/vcpu_sbi.c | 26 ++++++++++++++++++++++++++
3 files changed, 37 insertions(+)
diff --git a/arch/riscv/include/asm/kvm_vcpu_sbi.h b/arch/riscv/include/asm/kvm_vcpu_sbi.h
index 4ed6203cdd30..bcb90757b149 100644
--- a/arch/riscv/include/asm/kvm_vcpu_sbi.h
+++ b/arch/riscv/include/asm/kvm_vcpu_sbi.h
@@ -49,6 +49,14 @@ struct kvm_vcpu_sbi_extension {
/* Extension specific probe function */
unsigned long (*probe)(struct kvm_vcpu *vcpu);
+
+ /*
+ * Init/deinit function called once during VCPU init/destroy. These
+ * might be use if the SBI extensions need to allocate or do specific
+ * init time only configuration.
+ */
+ int (*init)(struct kvm_vcpu *vcpu);
+ void (*deinit)(struct kvm_vcpu *vcpu);
};
void kvm_riscv_vcpu_sbi_forward(struct kvm_vcpu *vcpu, struct kvm_run *run);
@@ -69,6 +77,7 @@ const struct kvm_vcpu_sbi_extension *kvm_vcpu_sbi_find_ext(
bool riscv_vcpu_supports_sbi_ext(struct kvm_vcpu *vcpu, int idx);
int kvm_riscv_vcpu_sbi_ecall(struct kvm_vcpu *vcpu, struct kvm_run *run);
void kvm_riscv_vcpu_sbi_init(struct kvm_vcpu *vcpu);
+void kvm_riscv_vcpu_sbi_deinit(struct kvm_vcpu *vcpu);
int kvm_riscv_vcpu_get_reg_sbi_sta(struct kvm_vcpu *vcpu, unsigned long reg_num,
unsigned long *reg_val);
diff --git a/arch/riscv/kvm/vcpu.c b/arch/riscv/kvm/vcpu.c
index 60d684c76c58..877bcc85c067 100644
--- a/arch/riscv/kvm/vcpu.c
+++ b/arch/riscv/kvm/vcpu.c
@@ -185,6 +185,8 @@ void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
{
+ kvm_riscv_vcpu_sbi_deinit(vcpu);
+
/* Cleanup VCPU AIA context */
kvm_riscv_vcpu_aia_deinit(vcpu);
diff --git a/arch/riscv/kvm/vcpu_sbi.c b/arch/riscv/kvm/vcpu_sbi.c
index d1c83a77735e..3139f171c20f 100644
--- a/arch/riscv/kvm/vcpu_sbi.c
+++ b/arch/riscv/kvm/vcpu_sbi.c
@@ -508,5 +508,31 @@ void kvm_riscv_vcpu_sbi_init(struct kvm_vcpu *vcpu)
scontext->ext_status[idx] = ext->default_disabled ?
KVM_RISCV_SBI_EXT_STATUS_DISABLED :
KVM_RISCV_SBI_EXT_STATUS_ENABLED;
+
+ if (ext->init && ext->init(vcpu) != 0)
+ scontext->ext_status[idx] = KVM_RISCV_SBI_EXT_STATUS_UNAVAILABLE;
+ }
+}
+
+void kvm_riscv_vcpu_sbi_deinit(struct kvm_vcpu *vcpu)
+{
+ struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context;
+ const struct kvm_riscv_sbi_extension_entry *entry;
+ const struct kvm_vcpu_sbi_extension *ext;
+ int idx, i;
+
+ for (i = 0; i < ARRAY_SIZE(sbi_ext); i++) {
+ entry = &sbi_ext[i];
+ ext = entry->ext_ptr;
+ idx = entry->ext_idx;
+
+ if (idx < 0 || idx >= ARRAY_SIZE(scontext->ext_status))
+ continue;
+
+ if (scontext->ext_status[idx] == KVM_RISCV_SBI_EXT_STATUS_UNAVAILABLE ||
+ !ext->deinit)
+ continue;
+
+ ext->deinit(vcpu);
}
}
--
2.47.2
^ permalink raw reply related [flat|nested] 28+ messages in thread* Re: [PATCH v4 15/18] RISC-V: KVM: add SBI extension init()/deinit() functions
2025-03-17 17:06 ` [PATCH v4 15/18] RISC-V: KVM: add SBI extension init()/deinit() functions Clément Léger
@ 2025-03-22 12:23 ` Andrew Jones
0 siblings, 0 replies; 28+ messages in thread
From: Andrew Jones @ 2025-03-22 12:23 UTC (permalink / raw)
To: Clément Léger
Cc: Paul Walmsley, Palmer Dabbelt, Anup Patel, Atish Patra,
Shuah Khan, Jonathan Corbet, linux-riscv, linux-kernel, linux-doc,
kvm, kvm-riscv, linux-kselftest, Samuel Holland
On Mon, Mar 17, 2025 at 06:06:21PM +0100, Clément Léger wrote:
> The FWFT SBI extension will need to dynamically allocate memory and do
> init time specific initialization. Add an init/deinit callbacks that
> allows to do so.
>
> Signed-off-by: Clément Léger <cleger@rivosinc.com>
> ---
> arch/riscv/include/asm/kvm_vcpu_sbi.h | 9 +++++++++
> arch/riscv/kvm/vcpu.c | 2 ++
> arch/riscv/kvm/vcpu_sbi.c | 26 ++++++++++++++++++++++++++
> 3 files changed, 37 insertions(+)
>
> diff --git a/arch/riscv/include/asm/kvm_vcpu_sbi.h b/arch/riscv/include/asm/kvm_vcpu_sbi.h
> index 4ed6203cdd30..bcb90757b149 100644
> --- a/arch/riscv/include/asm/kvm_vcpu_sbi.h
> +++ b/arch/riscv/include/asm/kvm_vcpu_sbi.h
> @@ -49,6 +49,14 @@ struct kvm_vcpu_sbi_extension {
>
> /* Extension specific probe function */
> unsigned long (*probe)(struct kvm_vcpu *vcpu);
> +
> + /*
> + * Init/deinit function called once during VCPU init/destroy. These
> + * might be use if the SBI extensions need to allocate or do specific
> + * init time only configuration.
> + */
> + int (*init)(struct kvm_vcpu *vcpu);
> + void (*deinit)(struct kvm_vcpu *vcpu);
> };
>
> void kvm_riscv_vcpu_sbi_forward(struct kvm_vcpu *vcpu, struct kvm_run *run);
> @@ -69,6 +77,7 @@ const struct kvm_vcpu_sbi_extension *kvm_vcpu_sbi_find_ext(
> bool riscv_vcpu_supports_sbi_ext(struct kvm_vcpu *vcpu, int idx);
> int kvm_riscv_vcpu_sbi_ecall(struct kvm_vcpu *vcpu, struct kvm_run *run);
> void kvm_riscv_vcpu_sbi_init(struct kvm_vcpu *vcpu);
> +void kvm_riscv_vcpu_sbi_deinit(struct kvm_vcpu *vcpu);
>
> int kvm_riscv_vcpu_get_reg_sbi_sta(struct kvm_vcpu *vcpu, unsigned long reg_num,
> unsigned long *reg_val);
> diff --git a/arch/riscv/kvm/vcpu.c b/arch/riscv/kvm/vcpu.c
> index 60d684c76c58..877bcc85c067 100644
> --- a/arch/riscv/kvm/vcpu.c
> +++ b/arch/riscv/kvm/vcpu.c
> @@ -185,6 +185,8 @@ void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
>
> void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
> {
> + kvm_riscv_vcpu_sbi_deinit(vcpu);
> +
> /* Cleanup VCPU AIA context */
> kvm_riscv_vcpu_aia_deinit(vcpu);
>
> diff --git a/arch/riscv/kvm/vcpu_sbi.c b/arch/riscv/kvm/vcpu_sbi.c
> index d1c83a77735e..3139f171c20f 100644
> --- a/arch/riscv/kvm/vcpu_sbi.c
> +++ b/arch/riscv/kvm/vcpu_sbi.c
> @@ -508,5 +508,31 @@ void kvm_riscv_vcpu_sbi_init(struct kvm_vcpu *vcpu)
> scontext->ext_status[idx] = ext->default_disabled ?
> KVM_RISCV_SBI_EXT_STATUS_DISABLED :
> KVM_RISCV_SBI_EXT_STATUS_ENABLED;
> +
> + if (ext->init && ext->init(vcpu) != 0)
> + scontext->ext_status[idx] = KVM_RISCV_SBI_EXT_STATUS_UNAVAILABLE;
> + }
> +}
> +
> +void kvm_riscv_vcpu_sbi_deinit(struct kvm_vcpu *vcpu)
> +{
> + struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context;
> + const struct kvm_riscv_sbi_extension_entry *entry;
> + const struct kvm_vcpu_sbi_extension *ext;
> + int idx, i;
> +
> + for (i = 0; i < ARRAY_SIZE(sbi_ext); i++) {
> + entry = &sbi_ext[i];
> + ext = entry->ext_ptr;
> + idx = entry->ext_idx;
> +
> + if (idx < 0 || idx >= ARRAY_SIZE(scontext->ext_status))
> + continue;
> +
> + if (scontext->ext_status[idx] == KVM_RISCV_SBI_EXT_STATUS_UNAVAILABLE ||
> + !ext->deinit)
> + continue;
> +
> + ext->deinit(vcpu);
> }
> }
> --
> 2.47.2
>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH v4 16/18] RISC-V: KVM: add SBI extension reset callback
2025-03-17 17:06 [PATCH v4 00/18] riscv: add SBI FWFT misaligned exception delegation support Clément Léger
` (14 preceding siblings ...)
2025-03-17 17:06 ` [PATCH v4 15/18] RISC-V: KVM: add SBI extension init()/deinit() functions Clément Léger
@ 2025-03-17 17:06 ` Clément Léger
2025-03-17 17:06 ` [PATCH v4 17/18] RISC-V: KVM: add support for FWFT SBI extension Clément Léger
2025-03-17 17:06 ` [PATCH v4 18/18] RISC-V: KVM: add support for SBI_FWFT_MISALIGNED_DELEG Clément Léger
17 siblings, 0 replies; 28+ messages in thread
From: Clément Léger @ 2025-03-17 17:06 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Anup Patel, Atish Patra,
Shuah Khan, Jonathan Corbet, linux-riscv, linux-kernel, linux-doc,
kvm, kvm-riscv, linux-kselftest
Cc: Clément Léger, Samuel Holland, Andrew Jones
Currently, only the STA extension needed a reset function but that's
going to be the case for FWFT as well. Add a reset callback that can be
implemented by SBI extensions.
Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
---
arch/riscv/include/asm/kvm_host.h | 1 -
arch/riscv/include/asm/kvm_vcpu_sbi.h | 2 ++
arch/riscv/kvm/vcpu.c | 2 +-
arch/riscv/kvm/vcpu_sbi.c | 24 ++++++++++++++++++++++++
arch/riscv/kvm/vcpu_sbi_sta.c | 3 ++-
5 files changed, 29 insertions(+), 3 deletions(-)
diff --git a/arch/riscv/include/asm/kvm_host.h b/arch/riscv/include/asm/kvm_host.h
index cc33e35cd628..bb93d2995ea2 100644
--- a/arch/riscv/include/asm/kvm_host.h
+++ b/arch/riscv/include/asm/kvm_host.h
@@ -409,7 +409,6 @@ void __kvm_riscv_vcpu_power_on(struct kvm_vcpu *vcpu);
void kvm_riscv_vcpu_power_on(struct kvm_vcpu *vcpu);
bool kvm_riscv_vcpu_stopped(struct kvm_vcpu *vcpu);
-void kvm_riscv_vcpu_sbi_sta_reset(struct kvm_vcpu *vcpu);
void kvm_riscv_vcpu_record_steal_time(struct kvm_vcpu *vcpu);
#endif /* __RISCV_KVM_HOST_H__ */
diff --git a/arch/riscv/include/asm/kvm_vcpu_sbi.h b/arch/riscv/include/asm/kvm_vcpu_sbi.h
index bcb90757b149..cb68b3a57c8f 100644
--- a/arch/riscv/include/asm/kvm_vcpu_sbi.h
+++ b/arch/riscv/include/asm/kvm_vcpu_sbi.h
@@ -57,6 +57,7 @@ struct kvm_vcpu_sbi_extension {
*/
int (*init)(struct kvm_vcpu *vcpu);
void (*deinit)(struct kvm_vcpu *vcpu);
+ void (*reset)(struct kvm_vcpu *vcpu);
};
void kvm_riscv_vcpu_sbi_forward(struct kvm_vcpu *vcpu, struct kvm_run *run);
@@ -78,6 +79,7 @@ bool riscv_vcpu_supports_sbi_ext(struct kvm_vcpu *vcpu, int idx);
int kvm_riscv_vcpu_sbi_ecall(struct kvm_vcpu *vcpu, struct kvm_run *run);
void kvm_riscv_vcpu_sbi_init(struct kvm_vcpu *vcpu);
void kvm_riscv_vcpu_sbi_deinit(struct kvm_vcpu *vcpu);
+void kvm_riscv_vcpu_sbi_reset(struct kvm_vcpu *vcpu);
int kvm_riscv_vcpu_get_reg_sbi_sta(struct kvm_vcpu *vcpu, unsigned long reg_num,
unsigned long *reg_val);
diff --git a/arch/riscv/kvm/vcpu.c b/arch/riscv/kvm/vcpu.c
index 877bcc85c067..542747e2c7f5 100644
--- a/arch/riscv/kvm/vcpu.c
+++ b/arch/riscv/kvm/vcpu.c
@@ -94,7 +94,7 @@ static void kvm_riscv_reset_vcpu(struct kvm_vcpu *vcpu)
vcpu->arch.hfence_tail = 0;
memset(vcpu->arch.hfence_queue, 0, sizeof(vcpu->arch.hfence_queue));
- kvm_riscv_vcpu_sbi_sta_reset(vcpu);
+ kvm_riscv_vcpu_sbi_reset(vcpu);
/* Reset the guest CSRs for hotplug usecase */
if (loaded)
diff --git a/arch/riscv/kvm/vcpu_sbi.c b/arch/riscv/kvm/vcpu_sbi.c
index 3139f171c20f..50be079b5528 100644
--- a/arch/riscv/kvm/vcpu_sbi.c
+++ b/arch/riscv/kvm/vcpu_sbi.c
@@ -536,3 +536,27 @@ void kvm_riscv_vcpu_sbi_deinit(struct kvm_vcpu *vcpu)
ext->deinit(vcpu);
}
}
+
+void kvm_riscv_vcpu_sbi_reset(struct kvm_vcpu *vcpu)
+{
+ struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context;
+ const struct kvm_riscv_sbi_extension_entry *entry;
+ const struct kvm_vcpu_sbi_extension *ext;
+ int idx, i;
+
+ for (i = 0; i < ARRAY_SIZE(sbi_ext); i++) {
+ entry = &sbi_ext[i];
+ ext = entry->ext_ptr;
+ idx = entry->ext_idx;
+
+ if (idx < 0 || idx >= ARRAY_SIZE(scontext->ext_status))
+ continue;
+
+ if (scontext->ext_status[idx] != KVM_RISCV_SBI_EXT_STATUS_ENABLED ||
+ !ext->reset)
+ continue;
+
+ ext->reset(vcpu);
+ }
+}
+
diff --git a/arch/riscv/kvm/vcpu_sbi_sta.c b/arch/riscv/kvm/vcpu_sbi_sta.c
index 5f35427114c1..cc6cb7c8f0e4 100644
--- a/arch/riscv/kvm/vcpu_sbi_sta.c
+++ b/arch/riscv/kvm/vcpu_sbi_sta.c
@@ -16,7 +16,7 @@
#include <asm/sbi.h>
#include <asm/uaccess.h>
-void kvm_riscv_vcpu_sbi_sta_reset(struct kvm_vcpu *vcpu)
+static void kvm_riscv_vcpu_sbi_sta_reset(struct kvm_vcpu *vcpu)
{
vcpu->arch.sta.shmem = INVALID_GPA;
vcpu->arch.sta.last_steal = 0;
@@ -156,6 +156,7 @@ const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_sta = {
.extid_end = SBI_EXT_STA,
.handler = kvm_sbi_ext_sta_handler,
.probe = kvm_sbi_ext_sta_probe,
+ .reset = kvm_riscv_vcpu_sbi_sta_reset,
};
int kvm_riscv_vcpu_get_reg_sbi_sta(struct kvm_vcpu *vcpu,
--
2.47.2
^ permalink raw reply related [flat|nested] 28+ messages in thread* [PATCH v4 17/18] RISC-V: KVM: add support for FWFT SBI extension
2025-03-17 17:06 [PATCH v4 00/18] riscv: add SBI FWFT misaligned exception delegation support Clément Léger
` (15 preceding siblings ...)
2025-03-17 17:06 ` [PATCH v4 16/18] RISC-V: KVM: add SBI extension reset callback Clément Léger
@ 2025-03-17 17:06 ` Clément Léger
2025-03-22 12:30 ` Andrew Jones
2025-03-17 17:06 ` [PATCH v4 18/18] RISC-V: KVM: add support for SBI_FWFT_MISALIGNED_DELEG Clément Léger
17 siblings, 1 reply; 28+ messages in thread
From: Clément Léger @ 2025-03-17 17:06 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Anup Patel, Atish Patra,
Shuah Khan, Jonathan Corbet, linux-riscv, linux-kernel, linux-doc,
kvm, kvm-riscv, linux-kselftest
Cc: Clément Léger, Samuel Holland, Andrew Jones
Add basic infrastructure to support the FWFT extension in KVM.
Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
---
arch/riscv/include/asm/kvm_host.h | 4 +
arch/riscv/include/asm/kvm_vcpu_sbi.h | 1 +
arch/riscv/include/asm/kvm_vcpu_sbi_fwft.h | 29 +++
arch/riscv/include/uapi/asm/kvm.h | 1 +
arch/riscv/kvm/Makefile | 1 +
arch/riscv/kvm/vcpu_sbi.c | 4 +
arch/riscv/kvm/vcpu_sbi_fwft.c | 216 +++++++++++++++++++++
7 files changed, 256 insertions(+)
create mode 100644 arch/riscv/include/asm/kvm_vcpu_sbi_fwft.h
create mode 100644 arch/riscv/kvm/vcpu_sbi_fwft.c
diff --git a/arch/riscv/include/asm/kvm_host.h b/arch/riscv/include/asm/kvm_host.h
index bb93d2995ea2..c0db61ba691a 100644
--- a/arch/riscv/include/asm/kvm_host.h
+++ b/arch/riscv/include/asm/kvm_host.h
@@ -19,6 +19,7 @@
#include <asm/kvm_vcpu_fp.h>
#include <asm/kvm_vcpu_insn.h>
#include <asm/kvm_vcpu_sbi.h>
+#include <asm/kvm_vcpu_sbi_fwft.h>
#include <asm/kvm_vcpu_timer.h>
#include <asm/kvm_vcpu_pmu.h>
@@ -281,6 +282,9 @@ struct kvm_vcpu_arch {
/* Performance monitoring context */
struct kvm_pmu pmu_context;
+ /* Firmware feature SBI extension context */
+ struct kvm_sbi_fwft fwft_context;
+
/* 'static' configurations which are set only once */
struct kvm_vcpu_config cfg;
diff --git a/arch/riscv/include/asm/kvm_vcpu_sbi.h b/arch/riscv/include/asm/kvm_vcpu_sbi.h
index cb68b3a57c8f..ffd03fed0c06 100644
--- a/arch/riscv/include/asm/kvm_vcpu_sbi.h
+++ b/arch/riscv/include/asm/kvm_vcpu_sbi.h
@@ -98,6 +98,7 @@ extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_hsm;
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_dbcn;
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_susp;
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_sta;
+extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_fwft;
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_experimental;
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_vendor;
diff --git a/arch/riscv/include/asm/kvm_vcpu_sbi_fwft.h b/arch/riscv/include/asm/kvm_vcpu_sbi_fwft.h
new file mode 100644
index 000000000000..9ba841355758
--- /dev/null
+++ b/arch/riscv/include/asm/kvm_vcpu_sbi_fwft.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2025 Rivos Inc.
+ *
+ * Authors:
+ * Clément Léger <cleger@rivosinc.com>
+ */
+
+#ifndef __KVM_VCPU_RISCV_FWFT_H
+#define __KVM_VCPU_RISCV_FWFT_H
+
+#include <asm/sbi.h>
+
+struct kvm_sbi_fwft_feature;
+
+struct kvm_sbi_fwft_config {
+ const struct kvm_sbi_fwft_feature *feature;
+ bool supported;
+ unsigned long flags;
+};
+
+/* FWFT data structure per vcpu */
+struct kvm_sbi_fwft {
+ struct kvm_sbi_fwft_config *configs;
+};
+
+#define vcpu_to_fwft(vcpu) (&(vcpu)->arch.fwft_context)
+
+#endif /* !__KVM_VCPU_RISCV_FWFT_H */
diff --git a/arch/riscv/include/uapi/asm/kvm.h b/arch/riscv/include/uapi/asm/kvm.h
index f06bc5efcd79..fa6eee1caf41 100644
--- a/arch/riscv/include/uapi/asm/kvm.h
+++ b/arch/riscv/include/uapi/asm/kvm.h
@@ -202,6 +202,7 @@ enum KVM_RISCV_SBI_EXT_ID {
KVM_RISCV_SBI_EXT_DBCN,
KVM_RISCV_SBI_EXT_STA,
KVM_RISCV_SBI_EXT_SUSP,
+ KVM_RISCV_SBI_EXT_FWFT,
KVM_RISCV_SBI_EXT_MAX,
};
diff --git a/arch/riscv/kvm/Makefile b/arch/riscv/kvm/Makefile
index 4e0bba91d284..06e2d52a9b88 100644
--- a/arch/riscv/kvm/Makefile
+++ b/arch/riscv/kvm/Makefile
@@ -26,6 +26,7 @@ kvm-y += vcpu_onereg.o
kvm-$(CONFIG_RISCV_PMU_SBI) += vcpu_pmu.o
kvm-y += vcpu_sbi.o
kvm-y += vcpu_sbi_base.o
+kvm-y += vcpu_sbi_fwft.o
kvm-y += vcpu_sbi_hsm.o
kvm-$(CONFIG_RISCV_PMU_SBI) += vcpu_sbi_pmu.o
kvm-y += vcpu_sbi_replace.o
diff --git a/arch/riscv/kvm/vcpu_sbi.c b/arch/riscv/kvm/vcpu_sbi.c
index 50be079b5528..0748810c0252 100644
--- a/arch/riscv/kvm/vcpu_sbi.c
+++ b/arch/riscv/kvm/vcpu_sbi.c
@@ -78,6 +78,10 @@ static const struct kvm_riscv_sbi_extension_entry sbi_ext[] = {
.ext_idx = KVM_RISCV_SBI_EXT_STA,
.ext_ptr = &vcpu_sbi_ext_sta,
},
+ {
+ .ext_idx = KVM_RISCV_SBI_EXT_FWFT,
+ .ext_ptr = &vcpu_sbi_ext_fwft,
+ },
{
.ext_idx = KVM_RISCV_SBI_EXT_EXPERIMENTAL,
.ext_ptr = &vcpu_sbi_ext_experimental,
diff --git a/arch/riscv/kvm/vcpu_sbi_fwft.c b/arch/riscv/kvm/vcpu_sbi_fwft.c
new file mode 100644
index 000000000000..8a7cfe1fe7a7
--- /dev/null
+++ b/arch/riscv/kvm/vcpu_sbi_fwft.c
@@ -0,0 +1,216 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2025 Rivos Inc.
+ *
+ * Authors:
+ * Clément Léger <cleger@rivosinc.com>
+ */
+
+#include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/kvm_host.h>
+#include <asm/cpufeature.h>
+#include <asm/sbi.h>
+#include <asm/kvm_vcpu_sbi.h>
+#include <asm/kvm_vcpu_sbi_fwft.h>
+
+struct kvm_sbi_fwft_feature {
+ /**
+ * @id: Feature ID
+ */
+ enum sbi_fwft_feature_t id;
+
+ /**
+ * @supported: Check if the feature is supported on the vcpu
+ *
+ * This callback is optional, if not provided the feature is assumed to
+ * be supported
+ */
+ bool (*supported)(struct kvm_vcpu *vcpu);
+
+ /**
+ * @set: Set the feature value
+ *
+ * Return SBI_SUCCESS on success or an SBI error (SBI_ERR_*)
+ *
+ * This callback is mandatory
+ */
+ long (*set)(struct kvm_vcpu *vcpu, struct kvm_sbi_fwft_config *conf, unsigned long value);
+
+ /**
+ * @get: Get the feature current value
+ *
+ * Return SBI_SUCCESS on success or an SBI error (SBI_ERR_*)
+ *
+ * This callback is mandatory
+ */
+ long (*get)(struct kvm_vcpu *vcpu, struct kvm_sbi_fwft_config *conf, unsigned long *value);
+};
+
+static const enum sbi_fwft_feature_t kvm_fwft_defined_features[] = {
+ SBI_FWFT_MISALIGNED_EXC_DELEG,
+ SBI_FWFT_LANDING_PAD,
+ SBI_FWFT_SHADOW_STACK,
+ SBI_FWFT_DOUBLE_TRAP,
+ SBI_FWFT_PTE_AD_HW_UPDATING,
+ SBI_FWFT_POINTER_MASKING_PMLEN,
+};
+
+static bool kvm_fwft_is_defined_feature(enum sbi_fwft_feature_t feature)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(kvm_fwft_defined_features); i++) {
+ if (kvm_fwft_defined_features[i] == feature)
+ return true;
+ }
+
+ return false;
+}
+
+static const struct kvm_sbi_fwft_feature features[] = {
+};
+
+static struct kvm_sbi_fwft_config *
+kvm_sbi_fwft_get_config(struct kvm_vcpu *vcpu, enum sbi_fwft_feature_t feature)
+{
+ int i;
+ struct kvm_sbi_fwft *fwft = vcpu_to_fwft(vcpu);
+
+ for (i = 0; i < ARRAY_SIZE(features); i++) {
+ if (fwft->configs[i].feature->id == feature)
+ return &fwft->configs[i];
+ }
+
+ return NULL;
+}
+
+static int kvm_fwft_get_feature(struct kvm_vcpu *vcpu, u32 feature,
+ struct kvm_sbi_fwft_config **conf)
+{
+ struct kvm_sbi_fwft_config *tconf;
+
+ tconf = kvm_sbi_fwft_get_config(vcpu, feature);
+ if (!tconf) {
+ if (kvm_fwft_is_defined_feature(feature))
+ return SBI_ERR_NOT_SUPPORTED;
+
+ return SBI_ERR_DENIED;
+ }
+
+ if (!tconf->supported)
+ return SBI_ERR_NOT_SUPPORTED;
+
+ *conf = tconf;
+
+ return SBI_SUCCESS;
+}
+
+static int kvm_sbi_fwft_set(struct kvm_vcpu *vcpu, u32 feature,
+ unsigned long value, unsigned long flags)
+{
+ int ret;
+ struct kvm_sbi_fwft_config *conf;
+
+ ret = kvm_fwft_get_feature(vcpu, feature, &conf);
+ if (ret)
+ return ret;
+
+ if ((flags & ~SBI_FWFT_SET_FLAG_LOCK) != 0)
+ return SBI_ERR_INVALID_PARAM;
+
+ if (conf->flags & SBI_FWFT_SET_FLAG_LOCK)
+ return SBI_ERR_DENIED_LOCKED;
+
+ conf->flags = flags;
+
+ return conf->feature->set(vcpu, conf, value);
+}
+
+static int kvm_sbi_fwft_get(struct kvm_vcpu *vcpu, unsigned long feature,
+ unsigned long *value)
+{
+ int ret;
+ struct kvm_sbi_fwft_config *conf;
+
+ ret = kvm_fwft_get_feature(vcpu, feature, &conf);
+ if (ret)
+ return ret;
+
+ return conf->feature->get(vcpu, conf, value);
+}
+
+static int kvm_sbi_ext_fwft_handler(struct kvm_vcpu *vcpu, struct kvm_run *run,
+ struct kvm_vcpu_sbi_return *retdata)
+{
+ int ret;
+ struct kvm_cpu_context *cp = &vcpu->arch.guest_context;
+ unsigned long funcid = cp->a6;
+
+ switch (funcid) {
+ case SBI_EXT_FWFT_SET:
+ ret = kvm_sbi_fwft_set(vcpu, cp->a0, cp->a1, cp->a2);
+ break;
+ case SBI_EXT_FWFT_GET:
+ ret = kvm_sbi_fwft_get(vcpu, cp->a0, &retdata->out_val);
+ break;
+ default:
+ ret = SBI_ERR_NOT_SUPPORTED;
+ break;
+ }
+
+ retdata->err_val = ret;
+
+ return 0;
+}
+
+static int kvm_sbi_ext_fwft_init(struct kvm_vcpu *vcpu)
+{
+ struct kvm_sbi_fwft *fwft = vcpu_to_fwft(vcpu);
+ const struct kvm_sbi_fwft_feature *feature;
+ struct kvm_sbi_fwft_config *conf;
+ int i;
+
+ fwft->configs = kcalloc(ARRAY_SIZE(features), sizeof(struct kvm_sbi_fwft_config),
+ GFP_KERNEL);
+ if (!fwft->configs)
+ return -ENOMEM;
+
+ for (i = 0; i < ARRAY_SIZE(features); i++) {
+ feature = &features[i];
+ conf = &fwft->configs[i];
+ if (feature->supported)
+ conf->supported = feature->supported(vcpu);
+ else
+ conf->supported = true;
+
+ conf->feature = feature;
+ }
+
+ return 0;
+}
+
+static void kvm_sbi_ext_fwft_deinit(struct kvm_vcpu *vcpu)
+{
+ struct kvm_sbi_fwft *fwft = vcpu_to_fwft(vcpu);
+
+ kfree(fwft->configs);
+}
+
+static void kvm_sbi_ext_fwft_reset(struct kvm_vcpu *vcpu)
+{
+ int i;
+ struct kvm_sbi_fwft *fwft = vcpu_to_fwft(vcpu);
+
+ for (i = 0; i < ARRAY_SIZE(features); i++)
+ fwft->configs[i].flags = 0;
+}
+
+const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_fwft = {
+ .extid_start = SBI_EXT_FWFT,
+ .extid_end = SBI_EXT_FWFT,
+ .handler = kvm_sbi_ext_fwft_handler,
+ .init = kvm_sbi_ext_fwft_init,
+ .deinit = kvm_sbi_ext_fwft_deinit,
+ .reset = kvm_sbi_ext_fwft_reset,
+};
--
2.47.2
^ permalink raw reply related [flat|nested] 28+ messages in thread* Re: [PATCH v4 17/18] RISC-V: KVM: add support for FWFT SBI extension
2025-03-17 17:06 ` [PATCH v4 17/18] RISC-V: KVM: add support for FWFT SBI extension Clément Léger
@ 2025-03-22 12:30 ` Andrew Jones
0 siblings, 0 replies; 28+ messages in thread
From: Andrew Jones @ 2025-03-22 12:30 UTC (permalink / raw)
To: Clément Léger
Cc: Paul Walmsley, Palmer Dabbelt, Anup Patel, Atish Patra,
Shuah Khan, Jonathan Corbet, linux-riscv, linux-kernel, linux-doc,
kvm, kvm-riscv, linux-kselftest, Samuel Holland
On Mon, Mar 17, 2025 at 06:06:23PM +0100, Clément Léger wrote:
> Add basic infrastructure to support the FWFT extension in KVM.
>
> Signed-off-by: Clément Léger <cleger@rivosinc.com>
> Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
> ---
> arch/riscv/include/asm/kvm_host.h | 4 +
> arch/riscv/include/asm/kvm_vcpu_sbi.h | 1 +
> arch/riscv/include/asm/kvm_vcpu_sbi_fwft.h | 29 +++
> arch/riscv/include/uapi/asm/kvm.h | 1 +
> arch/riscv/kvm/Makefile | 1 +
> arch/riscv/kvm/vcpu_sbi.c | 4 +
> arch/riscv/kvm/vcpu_sbi_fwft.c | 216 +++++++++++++++++++++
> 7 files changed, 256 insertions(+)
> create mode 100644 arch/riscv/include/asm/kvm_vcpu_sbi_fwft.h
> create mode 100644 arch/riscv/kvm/vcpu_sbi_fwft.c
>
> diff --git a/arch/riscv/include/asm/kvm_host.h b/arch/riscv/include/asm/kvm_host.h
> index bb93d2995ea2..c0db61ba691a 100644
> --- a/arch/riscv/include/asm/kvm_host.h
> +++ b/arch/riscv/include/asm/kvm_host.h
> @@ -19,6 +19,7 @@
> #include <asm/kvm_vcpu_fp.h>
> #include <asm/kvm_vcpu_insn.h>
> #include <asm/kvm_vcpu_sbi.h>
> +#include <asm/kvm_vcpu_sbi_fwft.h>
> #include <asm/kvm_vcpu_timer.h>
> #include <asm/kvm_vcpu_pmu.h>
>
> @@ -281,6 +282,9 @@ struct kvm_vcpu_arch {
> /* Performance monitoring context */
> struct kvm_pmu pmu_context;
>
> + /* Firmware feature SBI extension context */
> + struct kvm_sbi_fwft fwft_context;
> +
> /* 'static' configurations which are set only once */
> struct kvm_vcpu_config cfg;
>
> diff --git a/arch/riscv/include/asm/kvm_vcpu_sbi.h b/arch/riscv/include/asm/kvm_vcpu_sbi.h
> index cb68b3a57c8f..ffd03fed0c06 100644
> --- a/arch/riscv/include/asm/kvm_vcpu_sbi.h
> +++ b/arch/riscv/include/asm/kvm_vcpu_sbi.h
> @@ -98,6 +98,7 @@ extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_hsm;
> extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_dbcn;
> extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_susp;
> extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_sta;
> +extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_fwft;
> extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_experimental;
> extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_vendor;
>
> diff --git a/arch/riscv/include/asm/kvm_vcpu_sbi_fwft.h b/arch/riscv/include/asm/kvm_vcpu_sbi_fwft.h
> new file mode 100644
> index 000000000000..9ba841355758
> --- /dev/null
> +++ b/arch/riscv/include/asm/kvm_vcpu_sbi_fwft.h
> @@ -0,0 +1,29 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Copyright (c) 2025 Rivos Inc.
> + *
> + * Authors:
> + * Clément Léger <cleger@rivosinc.com>
> + */
> +
> +#ifndef __KVM_VCPU_RISCV_FWFT_H
> +#define __KVM_VCPU_RISCV_FWFT_H
> +
> +#include <asm/sbi.h>
> +
> +struct kvm_sbi_fwft_feature;
> +
> +struct kvm_sbi_fwft_config {
> + const struct kvm_sbi_fwft_feature *feature;
> + bool supported;
> + unsigned long flags;
> +};
> +
> +/* FWFT data structure per vcpu */
> +struct kvm_sbi_fwft {
> + struct kvm_sbi_fwft_config *configs;
> +};
> +
> +#define vcpu_to_fwft(vcpu) (&(vcpu)->arch.fwft_context)
> +
> +#endif /* !__KVM_VCPU_RISCV_FWFT_H */
> diff --git a/arch/riscv/include/uapi/asm/kvm.h b/arch/riscv/include/uapi/asm/kvm.h
> index f06bc5efcd79..fa6eee1caf41 100644
> --- a/arch/riscv/include/uapi/asm/kvm.h
> +++ b/arch/riscv/include/uapi/asm/kvm.h
> @@ -202,6 +202,7 @@ enum KVM_RISCV_SBI_EXT_ID {
> KVM_RISCV_SBI_EXT_DBCN,
> KVM_RISCV_SBI_EXT_STA,
> KVM_RISCV_SBI_EXT_SUSP,
> + KVM_RISCV_SBI_EXT_FWFT,
> KVM_RISCV_SBI_EXT_MAX,
> };
>
> diff --git a/arch/riscv/kvm/Makefile b/arch/riscv/kvm/Makefile
> index 4e0bba91d284..06e2d52a9b88 100644
> --- a/arch/riscv/kvm/Makefile
> +++ b/arch/riscv/kvm/Makefile
> @@ -26,6 +26,7 @@ kvm-y += vcpu_onereg.o
> kvm-$(CONFIG_RISCV_PMU_SBI) += vcpu_pmu.o
> kvm-y += vcpu_sbi.o
> kvm-y += vcpu_sbi_base.o
> +kvm-y += vcpu_sbi_fwft.o
> kvm-y += vcpu_sbi_hsm.o
> kvm-$(CONFIG_RISCV_PMU_SBI) += vcpu_sbi_pmu.o
> kvm-y += vcpu_sbi_replace.o
> diff --git a/arch/riscv/kvm/vcpu_sbi.c b/arch/riscv/kvm/vcpu_sbi.c
> index 50be079b5528..0748810c0252 100644
> --- a/arch/riscv/kvm/vcpu_sbi.c
> +++ b/arch/riscv/kvm/vcpu_sbi.c
> @@ -78,6 +78,10 @@ static const struct kvm_riscv_sbi_extension_entry sbi_ext[] = {
> .ext_idx = KVM_RISCV_SBI_EXT_STA,
> .ext_ptr = &vcpu_sbi_ext_sta,
> },
> + {
> + .ext_idx = KVM_RISCV_SBI_EXT_FWFT,
> + .ext_ptr = &vcpu_sbi_ext_fwft,
> + },
> {
> .ext_idx = KVM_RISCV_SBI_EXT_EXPERIMENTAL,
> .ext_ptr = &vcpu_sbi_ext_experimental,
> diff --git a/arch/riscv/kvm/vcpu_sbi_fwft.c b/arch/riscv/kvm/vcpu_sbi_fwft.c
> new file mode 100644
> index 000000000000..8a7cfe1fe7a7
> --- /dev/null
> +++ b/arch/riscv/kvm/vcpu_sbi_fwft.c
> @@ -0,0 +1,216 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Copyright (c) 2025 Rivos Inc.
> + *
> + * Authors:
> + * Clément Léger <cleger@rivosinc.com>
> + */
> +
> +#include <linux/errno.h>
> +#include <linux/err.h>
> +#include <linux/kvm_host.h>
> +#include <asm/cpufeature.h>
> +#include <asm/sbi.h>
> +#include <asm/kvm_vcpu_sbi.h>
> +#include <asm/kvm_vcpu_sbi_fwft.h>
> +
> +struct kvm_sbi_fwft_feature {
> + /**
> + * @id: Feature ID
> + */
> + enum sbi_fwft_feature_t id;
> +
> + /**
> + * @supported: Check if the feature is supported on the vcpu
> + *
> + * This callback is optional, if not provided the feature is assumed to
> + * be supported
> + */
> + bool (*supported)(struct kvm_vcpu *vcpu);
> +
> + /**
> + * @set: Set the feature value
> + *
> + * Return SBI_SUCCESS on success or an SBI error (SBI_ERR_*)
> + *
> + * This callback is mandatory
> + */
> + long (*set)(struct kvm_vcpu *vcpu, struct kvm_sbi_fwft_config *conf, unsigned long value);
> +
> + /**
> + * @get: Get the feature current value
> + *
> + * Return SBI_SUCCESS on success or an SBI error (SBI_ERR_*)
> + *
> + * This callback is mandatory
> + */
> + long (*get)(struct kvm_vcpu *vcpu, struct kvm_sbi_fwft_config *conf, unsigned long *value);
^
extra space here
Thanks,
drew
^ permalink raw reply [flat|nested] 28+ messages in thread
* [PATCH v4 18/18] RISC-V: KVM: add support for SBI_FWFT_MISALIGNED_DELEG
2025-03-17 17:06 [PATCH v4 00/18] riscv: add SBI FWFT misaligned exception delegation support Clément Léger
` (16 preceding siblings ...)
2025-03-17 17:06 ` [PATCH v4 17/18] RISC-V: KVM: add support for FWFT SBI extension Clément Léger
@ 2025-03-17 17:06 ` Clément Léger
17 siblings, 0 replies; 28+ messages in thread
From: Clément Léger @ 2025-03-17 17:06 UTC (permalink / raw)
To: Paul Walmsley, Palmer Dabbelt, Anup Patel, Atish Patra,
Shuah Khan, Jonathan Corbet, linux-riscv, linux-kernel, linux-doc,
kvm, kvm-riscv, linux-kselftest
Cc: Clément Léger, Samuel Holland, Andrew Jones,
Deepak Gupta
SBI_FWFT_MISALIGNED_DELEG needs hedeleg to be modified to delegate
misaligned load/store exceptions. Save and restore it during CPU
load/put.
Signed-off-by: Clément Léger <cleger@rivosinc.com>
Reviewed-by: Deepak Gupta <debug@rivosinc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
---
arch/riscv/kvm/vcpu.c | 3 +++
arch/riscv/kvm/vcpu_sbi_fwft.c | 36 ++++++++++++++++++++++++++++++++++
2 files changed, 39 insertions(+)
diff --git a/arch/riscv/kvm/vcpu.c b/arch/riscv/kvm/vcpu.c
index 542747e2c7f5..d98e379945c3 100644
--- a/arch/riscv/kvm/vcpu.c
+++ b/arch/riscv/kvm/vcpu.c
@@ -646,6 +646,7 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
{
void *nsh;
struct kvm_vcpu_csr *csr = &vcpu->arch.guest_csr;
+ struct kvm_vcpu_config *cfg = &vcpu->arch.cfg;
vcpu->cpu = -1;
@@ -671,6 +672,7 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
csr->vstval = nacl_csr_read(nsh, CSR_VSTVAL);
csr->hvip = nacl_csr_read(nsh, CSR_HVIP);
csr->vsatp = nacl_csr_read(nsh, CSR_VSATP);
+ cfg->hedeleg = nacl_csr_read(nsh, CSR_HEDELEG);
} else {
csr->vsstatus = csr_read(CSR_VSSTATUS);
csr->vsie = csr_read(CSR_VSIE);
@@ -681,6 +683,7 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
csr->vstval = csr_read(CSR_VSTVAL);
csr->hvip = csr_read(CSR_HVIP);
csr->vsatp = csr_read(CSR_VSATP);
+ cfg->hedeleg = csr_read(CSR_HEDELEG);
}
}
diff --git a/arch/riscv/kvm/vcpu_sbi_fwft.c b/arch/riscv/kvm/vcpu_sbi_fwft.c
index 8a7cfe1fe7a7..b0556d66e775 100644
--- a/arch/riscv/kvm/vcpu_sbi_fwft.c
+++ b/arch/riscv/kvm/vcpu_sbi_fwft.c
@@ -14,6 +14,8 @@
#include <asm/kvm_vcpu_sbi.h>
#include <asm/kvm_vcpu_sbi_fwft.h>
+#define MIS_DELEG (BIT_ULL(EXC_LOAD_MISALIGNED) | BIT_ULL(EXC_STORE_MISALIGNED))
+
struct kvm_sbi_fwft_feature {
/**
* @id: Feature ID
@@ -68,7 +70,41 @@ static bool kvm_fwft_is_defined_feature(enum sbi_fwft_feature_t feature)
return false;
}
+static bool kvm_sbi_fwft_misaligned_delegation_supported(struct kvm_vcpu *vcpu)
+{
+ return misaligned_traps_can_delegate();
+}
+
+static long kvm_sbi_fwft_set_misaligned_delegation(struct kvm_vcpu *vcpu,
+ struct kvm_sbi_fwft_config *conf,
+ unsigned long value)
+{
+ if (value == 1)
+ csr_set(CSR_HEDELEG, MIS_DELEG);
+ else if (value == 0)
+ csr_clear(CSR_HEDELEG, MIS_DELEG);
+ else
+ return SBI_ERR_INVALID_PARAM;
+
+ return SBI_SUCCESS;
+}
+
+static long kvm_sbi_fwft_get_misaligned_delegation(struct kvm_vcpu *vcpu,
+ struct kvm_sbi_fwft_config *conf,
+ unsigned long *value)
+{
+ *value = (csr_read(CSR_HEDELEG) & MIS_DELEG) != 0;
+
+ return SBI_SUCCESS;
+}
+
static const struct kvm_sbi_fwft_feature features[] = {
+ {
+ .id = SBI_FWFT_MISALIGNED_EXC_DELEG,
+ .supported = kvm_sbi_fwft_misaligned_delegation_supported,
+ .set = kvm_sbi_fwft_set_misaligned_delegation,
+ .get = kvm_sbi_fwft_get_misaligned_delegation,
+ },
};
static struct kvm_sbi_fwft_config *
--
2.47.2
^ permalink raw reply related [flat|nested] 28+ messages in thread