[PATCH v1 2/3] xen/riscv: add RISC-V legacy SBI extension support for guests

Oleksii Kurochko posted 3 patches 1 week, 5 days ago
[PATCH v1 2/3] xen/riscv: add RISC-V legacy SBI extension support for guests
Posted by Oleksii Kurochko 1 week, 5 days ago
This commit adds support for legacy SBI extensions (version 0.1) in Xen
for guest domains.

The changes include:
1. Define all legacy SBI extension IDs (0x0 to 0x8) for better clarity and
   completeness.
2. Implement handling of legacy SBI extensions, starting with support for
   SBI_EXT_0_1_CONSOLE_{PUT,GET}CHAR.

The implementation uses the existing virtual SBI framework to handle legacy
SBI ecalls, ensuring compatibility with older SBI specifications in
RISC-V guests.

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
 xen/arch/riscv/include/asm/sbi.h            | 11 ++++--
 xen/arch/riscv/vsbi/Makefile                |  1 +
 xen/arch/riscv/vsbi/vsbi-legacy-extension.c | 37 +++++++++++++++++++++
 3 files changed, 47 insertions(+), 2 deletions(-)
 create mode 100644 xen/arch/riscv/vsbi/vsbi-legacy-extension.c

diff --git a/xen/arch/riscv/include/asm/sbi.h b/xen/arch/riscv/include/asm/sbi.h
index ade24a572d..e7d5d707b1 100644
--- a/xen/arch/riscv/include/asm/sbi.h
+++ b/xen/arch/riscv/include/asm/sbi.h
@@ -14,8 +14,15 @@
 
 #include <xen/cpumask.h>
 
-#define SBI_EXT_0_1_CONSOLE_PUTCHAR		0x1
-#define SBI_EXT_0_1_SHUTDOWN			0x8
+#define SBI_EXT_0_1_SET_TIMER           0x0
+#define SBI_EXT_0_1_CONSOLE_PUTCHAR     0x1
+#define SBI_EXT_0_1_CONSOLE_GETCHAR     0x2
+#define SBI_EXT_0_1_CLEAR_IPI           0x3
+#define SBI_EXT_0_1_SEND_IPI            0x4
+#define SBI_EXT_0_1_REMOTE_FENCE_I      0x5
+#define SBI_EXT_0_1_REMOTE_SFENCE_VMA   0x6
+#define SBI_EXT_0_1_REMOTE_SFENCE_VMA_ASID  0x7
+#define SBI_EXT_0_1_SHUTDOWN            0x8
 
 #define SBI_EXT_BASE                    0x10
 #define SBI_EXT_RFENCE                  0x52464E43
diff --git a/xen/arch/riscv/vsbi/Makefile b/xen/arch/riscv/vsbi/Makefile
index 574c8ff78d..4da625db9a 100644
--- a/xen/arch/riscv/vsbi/Makefile
+++ b/xen/arch/riscv/vsbi/Makefile
@@ -1 +1,2 @@
 obj-y += vsbi.o
+obj-y += vsbi-legacy-extension.o
diff --git a/xen/arch/riscv/vsbi/vsbi-legacy-extension.c b/xen/arch/riscv/vsbi/vsbi-legacy-extension.c
new file mode 100644
index 0000000000..39d65931b1
--- /dev/null
+++ b/xen/arch/riscv/vsbi/vsbi-legacy-extension.c
@@ -0,0 +1,37 @@
+
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <xen/lib.h>
+#include <xen/sched.h>
+
+#include <asm/processor.h>
+#include <asm/vsbi.h>
+
+static int vsbi_legacy_ecall_handler(struct vcpu *vcpu, unsigned long eid,
+                                     unsigned long fid,
+                                     struct cpu_user_regs *regs)
+{
+    int ret = 0;
+
+    switch ( eid )
+    {
+    case SBI_EXT_0_1_CONSOLE_PUTCHAR:
+        printk("%c", (char)regs->a0);
+        break;
+
+    case SBI_EXT_0_1_CONSOLE_GETCHAR:
+        regs->a0 = SBI_ERR_NOT_SUPPORTED;
+        break;
+
+    default:
+        panic("%s: Unsupported ecall: FID: #%lx, EID: #%lx\n",
+              __func__, fid, eid);
+		break;
+    }
+
+    return ret;
+}
+
+VSBI_EXT_START(legacy, SBI_EXT_0_1_SET_TIMER, SBI_EXT_0_1_SHUTDOWN,
+               vsbi_legacy_ecall_handler)
+VSBI_EXT_END
-- 
2.52.0
Re: [PATCH v1 2/3] xen/riscv: add RISC-V legacy SBI extension support for guests
Posted by Jan Beulich 5 days, 15 hours ago
On 01.12.2025 11:24, Oleksii Kurochko wrote:
> --- a/xen/arch/riscv/include/asm/sbi.h
> +++ b/xen/arch/riscv/include/asm/sbi.h
> @@ -14,8 +14,15 @@
>  
>  #include <xen/cpumask.h>
>  
> -#define SBI_EXT_0_1_CONSOLE_PUTCHAR		0x1
> -#define SBI_EXT_0_1_SHUTDOWN			0x8
> +#define SBI_EXT_0_1_SET_TIMER           0x0
> +#define SBI_EXT_0_1_CONSOLE_PUTCHAR     0x1

Why the padding adjustment when ...

> +#define SBI_EXT_0_1_CONSOLE_GETCHAR     0x2
> +#define SBI_EXT_0_1_CLEAR_IPI           0x3
> +#define SBI_EXT_0_1_SEND_IPI            0x4
> +#define SBI_EXT_0_1_REMOTE_FENCE_I      0x5
> +#define SBI_EXT_0_1_REMOTE_SFENCE_VMA   0x6
> +#define SBI_EXT_0_1_REMOTE_SFENCE_VMA_ASID  0x7

... you immediately have one that doesn't fit?

> --- a/xen/arch/riscv/vsbi/Makefile
> +++ b/xen/arch/riscv/vsbi/Makefile
> @@ -1 +1,2 @@
>  obj-y += vsbi.o
> +obj-y += vsbi-legacy-extension.o

No vsbi- prefixes please underneath vsbi/.

> --- /dev/null
> +++ b/xen/arch/riscv/vsbi/vsbi-legacy-extension.c
> @@ -0,0 +1,37 @@
> +
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +
> +#include <xen/lib.h>
> +#include <xen/sched.h>
> +
> +#include <asm/processor.h>
> +#include <asm/vsbi.h>
> +
> +static int vsbi_legacy_ecall_handler(struct vcpu *vcpu, unsigned long eid,
> +                                     unsigned long fid,
> +                                     struct cpu_user_regs *regs)
> +{
> +    int ret = 0;
> +
> +    switch ( eid )
> +    {
> +    case SBI_EXT_0_1_CONSOLE_PUTCHAR:
> +        printk("%c", (char)regs->a0);

This is guest output, so shouldn't use plain printk().

> +        break;
> +
> +    case SBI_EXT_0_1_CONSOLE_GETCHAR:
> +        regs->a0 = SBI_ERR_NOT_SUPPORTED;

This will be overwritten with the return value you pass to the caller (i.e. 0),
by that caller (i.e. vsbi_handle_ecall()).

> +        break;
> +
> +    default:
> +        panic("%s: Unsupported ecall: FID: #%lx, EID: #%lx\n",
> +              __func__, fid, eid);

Please don't. domain_crash() may be okay to use here, but crashing the hypervisor
because of unexpected guest input isn't okay.

> +		break;

Bad indentation.

Jan
Re: [PATCH v1 2/3] xen/riscv: add RISC-V legacy SBI extension support for guests
Posted by Oleksii Kurochko 2 days, 19 hours ago
On 12/8/25 4:05 PM, Jan Beulich wrote:
> On 01.12.2025 11:24, Oleksii Kurochko wrote:
>> --- a/xen/arch/riscv/include/asm/sbi.h
>> +++ b/xen/arch/riscv/include/asm/sbi.h
>> @@ -14,8 +14,15 @@
>>   
>>   #include <xen/cpumask.h>
>>   
>> -#define SBI_EXT_0_1_CONSOLE_PUTCHAR		0x1
>> -#define SBI_EXT_0_1_SHUTDOWN			0x8
>> +#define SBI_EXT_0_1_SET_TIMER           0x0
>> +#define SBI_EXT_0_1_CONSOLE_PUTCHAR     0x1
> Why the padding adjustment when ...
>
>> +#define SBI_EXT_0_1_CONSOLE_GETCHAR     0x2
>> +#define SBI_EXT_0_1_CLEAR_IPI           0x3
>> +#define SBI_EXT_0_1_SEND_IPI            0x4
>> +#define SBI_EXT_0_1_REMOTE_FENCE_I      0x5
>> +#define SBI_EXT_0_1_REMOTE_SFENCE_VMA   0x6
>> +#define SBI_EXT_0_1_REMOTE_SFENCE_VMA_ASID  0x7
> ... you immediately have one that doesn't fit?

IDK, the padding adjustment shouldn't be done in this way.
I will correct it.

>> --- /dev/null
>> +++ b/xen/arch/riscv/vsbi/vsbi-legacy-extension.c
>> @@ -0,0 +1,37 @@
>> +
>> +/* SPDX-License-Identifier: GPL-2.0-only */
>> +
>> +#include <xen/lib.h>
>> +#include <xen/sched.h>
>> +
>> +#include <asm/processor.h>
>> +#include <asm/vsbi.h>
>> +
>> +static int vsbi_legacy_ecall_handler(struct vcpu *vcpu, unsigned long eid,
>> +                                     unsigned long fid,
>> +                                     struct cpu_user_regs *regs)
>> +{
>> +    int ret = 0;
>> +
>> +    switch ( eid )
>> +    {
>> +    case SBI_EXT_0_1_CONSOLE_PUTCHAR:
>> +        printk("%c", (char)regs->a0);
> This is guest output, so shouldn't use plain printk().

I think that I don't know what should be used instead. Could you suggest me something
or point to the code in other arch-s?

Or do you mean that guest_printk() should be used?

>> +        break;
>> +
>> +    case SBI_EXT_0_1_CONSOLE_GETCHAR:
>> +        regs->a0 = SBI_ERR_NOT_SUPPORTED;
> This will be overwritten with the return value you pass to the caller (i.e. 0),
> by that caller (i.e. vsbi_handle_ecall()).

Oh, thanks. It should be "ret = SBI_ERR_NOT_SUPPORTED;" here.


>
>> +        break;
>> +
>> +    default:
>> +        panic("%s: Unsupported ecall: FID: #%lx, EID: #%lx\n",
>> +              __func__, fid, eid);
> Please don't. domain_crash() may be okay to use here, but crashing the hypervisor
> because of unexpected guest input isn't okay.

|domain_crash()| is better. I also considered just returning|SBI_ERR_NOT_SUPPORTED|,
but it wasn’t too convenient for debugging which FID/EID the guest was called,
so I started using|panic()| instead.

Thanks.

~ Oleksii


Re: [PATCH v1 2/3] xen/riscv: add RISC-V legacy SBI extension support for guests
Posted by Jan Beulich 2 days, 19 hours ago
On 11.12.2025 11:29, Oleksii Kurochko wrote:
> On 12/8/25 4:05 PM, Jan Beulich wrote:
>> On 01.12.2025 11:24, Oleksii Kurochko wrote:
>>> --- /dev/null
>>> +++ b/xen/arch/riscv/vsbi/vsbi-legacy-extension.c
>>> @@ -0,0 +1,37 @@
>>> +
>>> +/* SPDX-License-Identifier: GPL-2.0-only */
>>> +
>>> +#include <xen/lib.h>
>>> +#include <xen/sched.h>
>>> +
>>> +#include <asm/processor.h>
>>> +#include <asm/vsbi.h>
>>> +
>>> +static int vsbi_legacy_ecall_handler(struct vcpu *vcpu, unsigned long eid,
>>> +                                     unsigned long fid,
>>> +                                     struct cpu_user_regs *regs)
>>> +{
>>> +    int ret = 0;
>>> +
>>> +    switch ( eid )
>>> +    {
>>> +    case SBI_EXT_0_1_CONSOLE_PUTCHAR:
>>> +        printk("%c", (char)regs->a0);
>> This is guest output, so shouldn't use plain printk().
> 
> I think that I don't know what should be used instead. Could you suggest me something
> or point to the code in other arch-s?
> 
> Or do you mean that guest_printk() should be used?

No direct replacement will do what you want, as they all prefix something to the
string passed (which isn't what you want). You may need to buffer characters and
emit them in batches (full lines unless overly long). For x86 see hvm_print_line(),
but I think Arm also has something like this.

>>> +    default:
>>> +        panic("%s: Unsupported ecall: FID: #%lx, EID: #%lx\n",
>>> +              __func__, fid, eid);
>> Please don't. domain_crash() may be okay to use here, but crashing the hypervisor
>> because of unexpected guest input isn't okay.
> 
> |domain_crash()| is better. I also considered just returning|SBI_ERR_NOT_SUPPORTED|,
> but it wasn’t too convenient for debugging which FID/EID the guest was called,
> so I started using|panic()| instead.

FTAOD - domain_crash() is acceptable here while things are still under development.
It shouldn't stay like this in the end though: Guests should not be punished like
this for something Xen hasn't implemented.

Jan

Re: [PATCH v1 2/3] xen/riscv: add RISC-V legacy SBI extension support for guests
Posted by Oleksii Kurochko 2 days, 17 hours ago
On 12/11/25 12:02 PM, Jan Beulich wrote:
> On 11.12.2025 11:29, Oleksii Kurochko wrote:
>> On 12/8/25 4:05 PM, Jan Beulich wrote:
>>> On 01.12.2025 11:24, Oleksii Kurochko wrote:
>>>> --- /dev/null
>>>> +++ b/xen/arch/riscv/vsbi/vsbi-legacy-extension.c
>>>> @@ -0,0 +1,37 @@
>>>> +
>>>> +/* SPDX-License-Identifier: GPL-2.0-only */
>>>> +
>>>> +#include <xen/lib.h>
>>>> +#include <xen/sched.h>
>>>> +
>>>> +#include <asm/processor.h>
>>>> +#include <asm/vsbi.h>
>>>> +
>>>> +static int vsbi_legacy_ecall_handler(struct vcpu *vcpu, unsigned long eid,
>>>> +                                     unsigned long fid,
>>>> +                                     struct cpu_user_regs *regs)
>>>> +{
>>>> +    int ret = 0;
>>>> +
>>>> +    switch ( eid )
>>>> +    {
>>>> +    case SBI_EXT_0_1_CONSOLE_PUTCHAR:
>>>> +        printk("%c", (char)regs->a0);
>>> This is guest output, so shouldn't use plain printk().
>> I think that I don't know what should be used instead. Could you suggest me something
>> or point to the code in other arch-s?
>>
>> Or do you mean that guest_printk() should be used?
> No direct replacement will do what you want, as they all prefix something to the
> string passed (which isn't what you want). You may need to buffer characters and
> emit them in batches (full lines unless overly long). For x86 see hvm_print_line(),
> but I think Arm also has something like this.

I don’t recall anything like that for ARM. The only thing related to character
buffering that I remember is in vpl011_write_data_xen()
(https://elixir.bootlin.com/xen/v4.21.0/source/xen/arch/arm/vpl011.c#L76), but it
does not use the buf declared in struct domain_console. Instead, it provides a
separate structure for vpl011:
     struct vpl011_xen_backend {
         char in[SBSA_UART_FIFO_SIZE];
         char out[SBSA_UART_OUT_BUF_SIZE];
         XENCONS_RING_IDX in_cons, in_prod;
         XENCONS_RING_IDX out_prod;
     };

I don’t see that ARM uses struct domain_console.

By the way, I can’t find a counterpart of hvm_print_line() for reading a character(s).
Is domain_console->buf intended to be used only for writing characters?


>
>>>> +    default:
>>>> +        panic("%s: Unsupported ecall: FID: #%lx, EID: #%lx\n",
>>>> +              __func__, fid, eid);
>>> Please don't. domain_crash() may be okay to use here, but crashing the hypervisor
>>> because of unexpected guest input isn't okay.
>> |domain_crash()| is better. I also considered just returning|SBI_ERR_NOT_SUPPORTED|,
>> but it wasn’t too convenient for debugging which FID/EID the guest was called,
>> so I started using|panic()| instead.
> FTAOD - domain_crash() is acceptable here while things are still under development.
> It shouldn't stay like this in the end though: Guests should not be punished like
> this for something Xen hasn't implemented.

Agree, I will create a task in my Xen's repo to not forget to drop panic()/domain_crash().

~ Oleksii


Re: [PATCH v1 2/3] xen/riscv: add RISC-V legacy SBI extension support for guests
Posted by Jan Beulich 2 days, 16 hours ago
On 11.12.2025 13:52, Oleksii Kurochko wrote:
> On 12/11/25 12:02 PM, Jan Beulich wrote:
>> On 11.12.2025 11:29, Oleksii Kurochko wrote:
>>> On 12/8/25 4:05 PM, Jan Beulich wrote:
>>>> On 01.12.2025 11:24, Oleksii Kurochko wrote:
>>>>> --- /dev/null
>>>>> +++ b/xen/arch/riscv/vsbi/vsbi-legacy-extension.c
>>>>> @@ -0,0 +1,37 @@
>>>>> +
>>>>> +/* SPDX-License-Identifier: GPL-2.0-only */
>>>>> +
>>>>> +#include <xen/lib.h>
>>>>> +#include <xen/sched.h>
>>>>> +
>>>>> +#include <asm/processor.h>
>>>>> +#include <asm/vsbi.h>
>>>>> +
>>>>> +static int vsbi_legacy_ecall_handler(struct vcpu *vcpu, unsigned long eid,
>>>>> +                                     unsigned long fid,
>>>>> +                                     struct cpu_user_regs *regs)
>>>>> +{
>>>>> +    int ret = 0;
>>>>> +
>>>>> +    switch ( eid )
>>>>> +    {
>>>>> +    case SBI_EXT_0_1_CONSOLE_PUTCHAR:
>>>>> +        printk("%c", (char)regs->a0);
>>>> This is guest output, so shouldn't use plain printk().
>>> I think that I don't know what should be used instead. Could you suggest me something
>>> or point to the code in other arch-s?
>>>
>>> Or do you mean that guest_printk() should be used?
>> No direct replacement will do what you want, as they all prefix something to the
>> string passed (which isn't what you want). You may need to buffer characters and
>> emit them in batches (full lines unless overly long). For x86 see hvm_print_line(),
>> but I think Arm also has something like this.
> 
> I don’t recall anything like that for ARM. The only thing related to character
> buffering that I remember is in vpl011_write_data_xen()
> (https://elixir.bootlin.com/xen/v4.21.0/source/xen/arch/arm/vpl011.c#L76), but it
> does not use the buf declared in struct domain_console. Instead, it provides a
> separate structure for vpl011:
>      struct vpl011_xen_backend {
>          char in[SBSA_UART_FIFO_SIZE];
>          char out[SBSA_UART_OUT_BUF_SIZE];
>          XENCONS_RING_IDX in_cons, in_prod;
>          XENCONS_RING_IDX out_prod;
>      };
> 
> I don’t see that ARM uses struct domain_console.
> 
> By the way, I can’t find a counterpart of hvm_print_line() for reading a character(s).
> Is domain_console->buf intended to be used only for writing characters?

I don't think there's any particular intention, but of course you can use it
only for one of the two.

Jan