[kvm-unit-tests PATCH v2 5/8] riscv: Prefer SBI DBCN console with UART fallback
Xiang W
wangxiang at iscas.ac.cn
Thu Nov 5 00:20:32 PST 2026
CONFIG_SBI_CONSOLE already routes output through SBI DBCN, but console
setup still always went through the UART init path. uart0_init_fdt()
could skip a missing UART while uart0_init_acpi() aborted, so EFI/ACPI
guests without a described MMIO UART could not print.
Probe SBI_EXT_DBCN first. When it is available, use
SBI_EXT_DBCN_CONSOLE_WRITE and skip UART setup. Otherwise fall back to
the existing FDT or ACPI UART path. This keeps a UART fallback (as
required by the server platform spec on ACPI systems) while allowing
pure SBI-console environments to boot without an MMIO UART.
Rename the lock from uart_lock to console_lock since it now protects
both console backends.
Signed-off-by: Xiang W <wangxiang at iscas.ac.cn>
---
lib/riscv/io.c | 41 ++++++++++++++++++++++++-----------------
1 file changed, 24 insertions(+), 17 deletions(-)
diff --git a/lib/riscv/io.c b/lib/riscv/io.c
index b1163404..af38a540 100644
--- a/lib/riscv/io.c
+++ b/lib/riscv/io.c
@@ -28,7 +28,10 @@
static volatile u8 *uart0_base = UART_EARLY_BASE;
static u32 uart0_reg_width = 1;
static u32 uart0_reg_shift;
-static struct spinlock uart_lock;
+static struct spinlock console_lock;
+#ifdef CONFIG_SBI_CONSOLE
+static bool has_dbcn;
+#endif
static u32 uart0_read(u32 num)
{
@@ -71,16 +74,11 @@ static void uart0_init_fdt(void)
break;
}
-#ifdef CONFIG_SBI_CONSOLE
- uart0_base = NULL;
- return;
-#else
if (ret) {
printf("%s: Compatible uart not found in the device tree, aborting...\n",
__func__);
abort();
}
-#endif
} else {
const fdt32_t *val;
int len;
@@ -107,6 +105,12 @@ static void uart0_init_acpi(void)
void io_init(void)
{
+#ifdef CONFIG_SBI_CONSOLE
+ if (sbi_probe(SBI_EXT_DBCN)) {
+ has_dbcn = true;
+ return;
+ }
+#endif
if (dt_available())
uart0_init_fdt();
else
@@ -119,38 +123,41 @@ void io_init(void)
}
}
-void sbi_puts(const char *s);
-void sbi_puts(const char *s)
+#ifdef CONFIG_SBI_CONSOLE
+static void sbi_puts(const char *s)
{
phys_addr_t addr = virt_to_phys((void *)s);
unsigned long hi = upper_32_bits(addr);
unsigned long lo = lower_32_bits(addr);
- spin_lock(&uart_lock);
+ spin_lock(&console_lock);
sbi_ecall(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_WRITE, strlen(s), lo, hi, 0, 0, 0);
- spin_unlock(&uart_lock);
+ spin_unlock(&console_lock);
}
+#endif
-void uart0_puts(const char *s);
-void uart0_puts(const char *s)
+static void uart0_puts(const char *s)
{
assert(uart0_base);
- spin_lock(&uart_lock);
+ spin_lock(&console_lock);
while (*s) {
while (!(uart0_read(UART_LSR_OFFSET) & UART_LSR_THRE))
;
uart0_write(0, *s++);
}
- spin_unlock(&uart_lock);
+ spin_unlock(&console_lock);
}
void puts(const char *s)
{
#ifdef CONFIG_SBI_CONSOLE
- sbi_puts(s);
-#else
- uart0_puts(s);
+ if (has_dbcn) {
+ sbi_puts(s);
+ return;
+ }
#endif
+
+ uart0_puts(s);
}
/*
--
2.47.3
More information about the kvm-riscv
mailing list