SBI Debug Console Extension Proposal (Draft v3)


Anup Patel
 

Hi All,

Based on feedback, below is the updated draft proposal of the
SBI Debug Console Extension ...

The motivations behind this proposal is as follows:
1) There is no new SBI extension replacing the legacy SBI v0.1
putchar() and getchar() calls. These legacy SBI v0.1 calls are
now disabled by default in Linux and will be eventually deprecated.
We need a replacement at least for the SBI v0.1 putchar() which
is widely used for early prints in various OSes and Bootloaders.
2) The OS-A Platforms (or SEE) specification need to mandate
a particular type of UART (8250, ns16550, or SiFive) as a standard
way for boot-time early prints in supervisor-mode software. Using
SBI debug console extension, the OS-A Platforms (or SEE)
specifications don't need to mandate any type of UART.
3) The legacy SBI v0.1 putchar() only supports printing one
character at a time. For some of the hypervisors (particularly KVM),
SBI based early prints (i.e. earlycon=sbi) is slow because each
SBI v0.1 putchar() trap will be forwarded to the KVM user-space
(KVMTOOL or QEMU).

In other words, the SBI debug console extension defines a standard
way for boot-time early prints in supervisor-mode software.

We have completed the proof-of-concept implementation of this
SBI extension proposal. Refer, "riscv_sbi_dbcn_v1" branch in the
following repos:
https://github.com/avpatel/opensbi.git
https://github.com/avpatel/linux.git
https://github.com/avpatel/kvmtool.git

Please review it and provide your feedback.

Regards,
Anup

SBI Debug Console Extension (EID #0x4442434E "DBCN")
====================================================

The debug console extension defines a generic mechanism for boot
time early prints from supervisor-mode software which allows users
to catch boot-time issues in supervisor-mode software.

This extension replaces the legacy console putchar (EID #0x01)
extension with following improvements:
1) It follows the new calling convention defined by the SBI v1.0
(or higher) specification.
2) It allows supervisor software to print multiple characters
in a single SBI call.

Some of the functions defined by this SBI extension have physical
memory as parameters for input and/or output. This physical memory
parameter MUST satisfy following requirements:
1) The SBI implementation MUST check that the supervisor-mode
software is allowed to read and write the specified physical
memory on the calling HART.
2) The SBI implementation MUST access the specified physical
memory using the PMA attribute.
Note: If the supervisor-mode software access the same physical
memory using memory type different from PMA then a loss of
coherence or unexpected memory ordering may occur and the
invoking software should follow the rules and sequences defined
in the RISC-V Svpbmt specification to prevent the loss of
coherence and memory ordering.

If the underlying physical console has extra bits for error checking
(or correction) then these extra bits should be handled by the SBI
implementation.

Function: Console Puts (FID #0)
-------------------------------

struct sbiret sbi_debug_console_puts(unsigned long addr_lo,
unsigned long addr_hi,
unsigned long num_chars)

Print a specified input string on the debug console.

The physical base address and size of the string to be printed is
derived from parameters as follows:
1) `addr_lo` parameter specifies the lower XLEN bits of the string
physical base address.
2) `addr_hi` parameter specifies the string physical base address
right shifted by XLEN.
3) `num_chars` parameter specifies the size of the string as the
number of characters (or bytes).

This is a blocking SBI call and will only return after printing all
characters of the string.

Errors:
SBI_SUCCESS - Characters printed successfully.
SBI_ERR_INVALID_ADDRESS - The string pointed by `addr_lo`, `addr_hi`,
and `num_chars` parameters is not accessible
to supervisor-mode.
SBI_ERR_FAILED - Failed to print characters due to I/O errors.


Heinrich Schuchardt
 

On 7/25/22 06:34, Anup Patel wrote:
Hi All,
Based on feedback, below is the updated draft proposal of the
SBI Debug Console Extension ...
The motivations behind this proposal is as follows:
1) There is no new SBI extension replacing the legacy SBI v0.1
putchar() and getchar() calls. These legacy SBI v0.1 calls are
now disabled by default in Linux and will be eventually deprecated.
We need a replacement at least for the SBI v0.1 putchar() which
is widely used for early prints in various OSes and Bootloaders.
2) The OS-A Platforms (or SEE) specification need to mandate
a particular type of UART (8250, ns16550, or SiFive) as a standard
way for boot-time early prints in supervisor-mode software. Using
SBI debug console extension, the OS-A Platforms (or SEE)
specifications don't need to mandate any type of UART.
3) The legacy SBI v0.1 putchar() only supports printing one
character at a time. For some of the hypervisors (particularly KVM),
SBI based early prints (i.e. earlycon=sbi) is slow because each
SBI v0.1 putchar() trap will be forwarded to the KVM user-space
(KVMTOOL or QEMU).
In other words, the SBI debug console extension defines a standard
way for boot-time early prints in supervisor-mode software.
We have completed the proof-of-concept implementation of this
SBI extension proposal. Refer, "riscv_sbi_dbcn_v1" branch in the
following repos:
https://github.com/avpatel/opensbi.git
https://github.com/avpatel/linux.git
https://github.com/avpatel/kvmtool.git
Please review it and provide your feedback.
Regards,
Anup
SBI Debug Console Extension (EID #0x4442434E "DBCN")
====================================================
The debug console extension defines a generic mechanism for boot
time early prints from supervisor-mode software which allows users
to catch boot-time issues in supervisor-mode software.
This extension replaces the legacy console putchar (EID #0x01)
extension with following improvements:
1) It follows the new calling convention defined by the SBI v1.0
(or higher) specification.
2) It allows supervisor software to print multiple characters
in a single SBI call.
Some of the functions defined by this SBI extension have physical
memory as parameters for input and/or output. This physical memory
parameter MUST satisfy following requirements:
1) The SBI implementation MUST check that the supervisor-mode
software is allowed to read and write the specified physical
memory on the calling HART.
2) The SBI implementation MUST access the specified physical
memory using the PMA attribute.
Note: If the supervisor-mode software access the same physical
memory using memory type different from PMA then a loss of
coherence or unexpected memory ordering may occur and the
invoking software should follow the rules and sequences defined
in the RISC-V Svpbmt specification to prevent the loss of
coherence and memory ordering.
If the underlying physical console has extra bits for error checking
(or correction) then these extra bits should be handled by the SBI
implementation.
Function: Console Puts (FID #0)
-------------------------------
struct sbiret sbi_debug_console_puts(unsigned long addr_lo,
unsigned long addr_hi,
unsigned long num_chars)
Print a specified input string on the debug console.
The physical base address and size of the string to be printed is
derived from parameters as follows:
1) `addr_lo` parameter specifies the lower XLEN bits of the string
physical base address.
2) `addr_hi` parameter specifies the string physical base address
right shifted by XLEN.
3) `num_chars` parameter specifies the size of the string as the
number of characters (or bytes).
This is a blocking SBI call and will only return after printing all
characters of the string.
Errors:
SBI_SUCCESS - Characters printed successfully.
SBI_ERR_INVALID_ADDRESS - The string pointed by `addr_lo`, `addr_hi`,
and `num_chars` parameters is not accessible
to supervisor-mode.
We should also cover the case that only a part of the memory area is accessible by S-mode.

%s/accessible/entirely accessible/

It is unclear if the SBI is obliged to check S-mode accessibility. The specification should explicitly make this check either obligatory or optional. For security reasons the check should be obligatory on systems where accessibility can be restricted.

Otherwise the specification looks fine to me.

Best regards

Heinrich

SBI_ERR_FAILED - Failed to print characters due to I/O errors.


Anup Patel
 

On Mon, Jul 25, 2022 at 11:37 AM Heinrich Schuchardt
<heinrich.schuchardt@...> wrote:

On 7/25/22 06:34, Anup Patel wrote:
Hi All,

Based on feedback, below is the updated draft proposal of the
SBI Debug Console Extension ...

The motivations behind this proposal is as follows:
1) There is no new SBI extension replacing the legacy SBI v0.1
putchar() and getchar() calls. These legacy SBI v0.1 calls are
now disabled by default in Linux and will be eventually deprecated.
We need a replacement at least for the SBI v0.1 putchar() which
is widely used for early prints in various OSes and Bootloaders.
2) The OS-A Platforms (or SEE) specification need to mandate
a particular type of UART (8250, ns16550, or SiFive) as a standard
way for boot-time early prints in supervisor-mode software. Using
SBI debug console extension, the OS-A Platforms (or SEE)
specifications don't need to mandate any type of UART.
3) The legacy SBI v0.1 putchar() only supports printing one
character at a time. For some of the hypervisors (particularly KVM),
SBI based early prints (i.e. earlycon=sbi) is slow because each
SBI v0.1 putchar() trap will be forwarded to the KVM user-space
(KVMTOOL or QEMU).

In other words, the SBI debug console extension defines a standard
way for boot-time early prints in supervisor-mode software.

We have completed the proof-of-concept implementation of this
SBI extension proposal. Refer, "riscv_sbi_dbcn_v1" branch in the
following repos:
https://github.com/avpatel/opensbi.git
https://github.com/avpatel/linux.git
https://github.com/avpatel/kvmtool.git

Please review it and provide your feedback.

Regards,
Anup

SBI Debug Console Extension (EID #0x4442434E "DBCN")
====================================================

The debug console extension defines a generic mechanism for boot
time early prints from supervisor-mode software which allows users
to catch boot-time issues in supervisor-mode software.

This extension replaces the legacy console putchar (EID #0x01)
extension with following improvements:
1) It follows the new calling convention defined by the SBI v1.0
(or higher) specification.
2) It allows supervisor software to print multiple characters
in a single SBI call.

Some of the functions defined by this SBI extension have physical
memory as parameters for input and/or output. This physical memory
parameter MUST satisfy following requirements:
1) The SBI implementation MUST check that the supervisor-mode
software is allowed to read and write the specified physical
memory on the calling HART.
2) The SBI implementation MUST access the specified physical
memory using the PMA attribute.
Note: If the supervisor-mode software access the same physical
memory using memory type different from PMA then a loss of
coherence or unexpected memory ordering may occur and the
invoking software should follow the rules and sequences defined
in the RISC-V Svpbmt specification to prevent the loss of
coherence and memory ordering.

If the underlying physical console has extra bits for error checking
(or correction) then these extra bits should be handled by the SBI
implementation.

Function: Console Puts (FID #0)
-------------------------------

struct sbiret sbi_debug_console_puts(unsigned long addr_lo,
unsigned long addr_hi,
unsigned long num_chars)

Print a specified input string on the debug console.

The physical base address and size of the string to be printed is
derived from parameters as follows:
1) `addr_lo` parameter specifies the lower XLEN bits of the string
physical base address.
2) `addr_hi` parameter specifies the string physical base address
right shifted by XLEN.
3) `num_chars` parameter specifies the size of the string as the
number of characters (or bytes).

This is a blocking SBI call and will only return after printing all
characters of the string.

Errors:
SBI_SUCCESS - Characters printed successfully.
SBI_ERR_INVALID_ADDRESS - The string pointed by `addr_lo`, `addr_hi`,
and `num_chars` parameters is not accessible
to supervisor-mode.
We should also cover the case that only a part of the memory area is
accessible by S-mode.

%s/accessible/entirely accessible/
Okay, I will update the text.


It is unclear if the SBI is obliged to check S-mode accessibility. The
specification should explicitly make this check either obligatory or
optional. For security reasons the check should be obligatory on systems
where accessibility can be restricted.
Yes, the accessibility check on physical address parameters is very
important for SBI implementation (M-mode firmware, Hypervisors) to
ensure that supervisor-mode does not provide rouge/inaccessible
address to print from.

For example, a system might have been partitioned into multiple
domains so software running in one domain cannot pass a physical
address belonging to another domain.

Regards,
Anup


Otherwise the specification looks fine to me.

Best regards

Heinrich

SBI_ERR_FAILED - Failed to print characters due to I/O errors.


Darius Rad
 

On Mon, Jul 25, 2022 at 10:04:52AM +0530, Anup Patel wrote:

Function: Console Puts (FID #0)
-------------------------------

struct sbiret sbi_debug_console_puts(unsigned long addr_lo,
unsigned long addr_hi,
unsigned long num_chars)

Print a specified input string on the debug console.

The physical base address and size of the string to be printed is
derived from parameters as follows:
1) `addr_lo` parameter specifies the lower XLEN bits of the string
physical base address.
2) `addr_hi` parameter specifies the string physical base address
right shifted by XLEN.
It is really necessary to have two long parameters for a physical address
on RV64? Clearly this is necessary for RV32, where the maximum physical
address is greater than XLEN, but that is not the case for RV64.

Why not use long long, which is 8 bytes on both RV32 and RV64 (on the
respective ABIs, that is)? Or use a different function signature for RV32
and RV64, with two parameters for the former and one for the latter?

3) `num_chars` parameter specifies the size of the string as the
number of characters (or bytes).
// darius


Anup Patel
 

On Mon, Jul 25, 2022 at 5:11 PM Darius Rad <darius@...> wrote:

On Mon, Jul 25, 2022 at 10:04:52AM +0530, Anup Patel wrote:

Function: Console Puts (FID #0)
-------------------------------

struct sbiret sbi_debug_console_puts(unsigned long addr_lo,
unsigned long addr_hi,
unsigned long num_chars)

Print a specified input string on the debug console.

The physical base address and size of the string to be printed is
derived from parameters as follows:
1) `addr_lo` parameter specifies the lower XLEN bits of the string
physical base address.
2) `addr_hi` parameter specifies the string physical base address
right shifted by XLEN.
It is really necessary to have two long parameters for a physical address
on RV64? Clearly this is necessary for RV32, where the maximum physical
address is greater than XLEN, but that is not the case for RV64.

Why not use long long, which is 8 bytes on both RV32 and RV64 (on the
respective ABIs, that is)? Or use a different function signature for RV32
and RV64, with two parameters for the former and one for the latter?
For SBI spec, we have avoided separate function signatures for RV32
and RV64 so better to prefer other options.

If we want to combine "addr_lo" and "addr_hi" into one parameter then
uint64_t is better and consistent with other parts of SBI spec as well.

Regards,
Anup


3) `num_chars` parameter specifies the size of the string as the
number of characters (or bytes).
// darius


洛佳 Luo Jia
 

Hi Group,

I have an idea on addr_lo and addr_hi combination. What will happen if we ask supervisor to provide the
string address in a probable virtual address? In this way the supervisor won't need to convert it to physical
address, and we can save one argument for future designs to refer to. If machine mode firmware need to
read the supervisor accesible address, it uses mstatus.TVM bit to achieve this. By this way the machine
accesses the string parameter the same way the supervisor does.

Considering difference of physical and virtual address spacees (e.g. on RV32 Sv32 has 34-bit physical address),
if the supervisor does not use virtual memory, it only reads lower 32 bit of physical address, which is the
same limit of how machine mode firmware would read the memory.

By this way we have `usize` as parameter:

fn debug_console_print(supervisor_address: usize, length_bytes: usize) -> SbiRet { ... }

... other than combining different parts to form the final address.

Luo Jia


Anup Patel
 

Hi,

On Wed, Aug 3, 2022 at 1:27 PM 洛佳 Luo Jia <me@...> wrote:

Hi Group,

I have an idea on addr_lo and addr_hi combination. What will happen if we ask supervisor to provide the
string address in a probable virtual address? In this way the supervisor won't need to convert it to physical
address, and we can save one argument for future designs to refer to. If machine mode firmware need to
read the supervisor accesible address, it uses mstatus.TVM bit to achieve this. By this way the machine
accesses the string parameter the same way the supervisor does.

Considering difference of physical and virtual address spacees (e.g. on RV32 Sv32 has 34-bit physical address),
if the supervisor does not use virtual memory, it only reads lower 32 bit of physical address, which is the
same limit of how machine mode firmware would read the memory.

By this way we have `usize` as parameter:

fn debug_console_print(supervisor_address: usize, length_bytes: usize) -> SbiRet { ... }
There are two major issues in passing virtual address of string:

1) A rogue supervisor software can pass a virtual address mapped to a
physical address not accessible to it.
2) To access a string by virtual address, the SBI implementation (M-mode
firmware and hypervisors) end-up using unpriv load/store instructions.
These unpriv load/store instructions can potentially trap for hypervisor
because the guest OS can swap-out pages while the hypervisor is
trying to access it. Further in-case of nested virtualization, the unpriv
load/store instructions always trap to the host hypervisor so accessing
string by virtual address becomes extremely slow for guest hypervisor.

Due to the above reasons, we avoid using virtual addresses as
parameters in newer SBI calls for SBI v0.2 (higher).

Regards,
Anup


... other than combining different parts to form the final address.

Luo Jia