Skip to content

Commit 951df4e

Browse files
Merge patch series "RISC-V SBI debug console extension support"
Anup Patel <[email protected]> says: The SBI v2.0 specification is now frozen. The SBI v2.0 specification defines SBI debug console (DBCN) extension which replaces the legacy SBI v0.1 functions sbi_console_putchar() and sbi_console_getchar(). (Refer v2.0-rc5 at https://github.com/riscv-non-isa/riscv-sbi-doc/releases) This series adds support for SBI debug console (DBCN) extension in Linux RISC-V. To try these patches with KVM RISC-V, use KVMTOOL from the riscv_zbx_zicntr_smstateen_condops_v1 branch at: https://github.com/avpatel/kvmtool.git * b4-shazam-merge: RISC-V: Enable SBI based earlycon support tty: Add SBI debug console support to HVC SBI driver tty/serial: Add RISC-V SBI debug console based earlycon RISC-V: Add SBI debug console helper routines RISC-V: Add stubs for sbi_console_putchar/getchar() Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Palmer Dabbelt <[email protected]>
2 parents 4dc4af9 + 50942ad commit 951df4e

File tree

7 files changed

+133
-12
lines changed

7 files changed

+133
-12
lines changed

arch/riscv/configs/defconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ CONFIG_SERIAL_8250_CONSOLE=y
149149
CONFIG_SERIAL_8250_DW=y
150150
CONFIG_SERIAL_OF_PLATFORM=y
151151
CONFIG_SERIAL_SH_SCI=y
152+
CONFIG_SERIAL_EARLYCON_RISCV_SBI=y
152153
CONFIG_VIRTIO_CONSOLE=y
153154
CONFIG_HW_RANDOM=y
154155
CONFIG_HW_RANDOM_VIRTIO=y

arch/riscv/include/asm/sbi.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,8 +280,13 @@ struct sbiret sbi_ecall(int ext, int fid, unsigned long arg0,
280280
unsigned long arg3, unsigned long arg4,
281281
unsigned long arg5);
282282

283+
#ifdef CONFIG_RISCV_SBI_V01
283284
void sbi_console_putchar(int ch);
284285
int sbi_console_getchar(void);
286+
#else
287+
static inline void sbi_console_putchar(int ch) { }
288+
static inline int sbi_console_getchar(void) { return -ENOENT; }
289+
#endif
285290
long sbi_get_mvendorid(void);
286291
long sbi_get_marchid(void);
287292
long sbi_get_mimpid(void);
@@ -338,6 +343,11 @@ static inline unsigned long sbi_mk_version(unsigned long major,
338343
}
339344

340345
int sbi_err_map_linux_errno(int err);
346+
347+
extern bool sbi_debug_console_available;
348+
int sbi_debug_console_write(const char *bytes, unsigned int num_bytes);
349+
int sbi_debug_console_read(char *bytes, unsigned int num_bytes);
350+
341351
#else /* CONFIG_RISCV_SBI */
342352
static inline int sbi_remote_fence_i(const struct cpumask *cpu_mask) { return -1; }
343353
static inline void sbi_init(void) {}

arch/riscv/kernel/sbi.c

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include <linux/bits.h>
99
#include <linux/init.h>
10+
#include <linux/mm.h>
1011
#include <linux/pm.h>
1112
#include <linux/reboot.h>
1213
#include <asm/sbi.h>
@@ -571,6 +572,66 @@ long sbi_get_mimpid(void)
571572
}
572573
EXPORT_SYMBOL_GPL(sbi_get_mimpid);
573574

575+
bool sbi_debug_console_available;
576+
577+
int sbi_debug_console_write(const char *bytes, unsigned int num_bytes)
578+
{
579+
phys_addr_t base_addr;
580+
struct sbiret ret;
581+
582+
if (!sbi_debug_console_available)
583+
return -EOPNOTSUPP;
584+
585+
if (is_vmalloc_addr(bytes))
586+
base_addr = page_to_phys(vmalloc_to_page(bytes)) +
587+
offset_in_page(bytes);
588+
else
589+
base_addr = __pa(bytes);
590+
if (PAGE_SIZE < (offset_in_page(bytes) + num_bytes))
591+
num_bytes = PAGE_SIZE - offset_in_page(bytes);
592+
593+
if (IS_ENABLED(CONFIG_32BIT))
594+
ret = sbi_ecall(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_WRITE,
595+
num_bytes, lower_32_bits(base_addr),
596+
upper_32_bits(base_addr), 0, 0, 0);
597+
else
598+
ret = sbi_ecall(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_WRITE,
599+
num_bytes, base_addr, 0, 0, 0, 0);
600+
601+
if (ret.error == SBI_ERR_FAILURE)
602+
return -EIO;
603+
return ret.error ? sbi_err_map_linux_errno(ret.error) : ret.value;
604+
}
605+
606+
int sbi_debug_console_read(char *bytes, unsigned int num_bytes)
607+
{
608+
phys_addr_t base_addr;
609+
struct sbiret ret;
610+
611+
if (!sbi_debug_console_available)
612+
return -EOPNOTSUPP;
613+
614+
if (is_vmalloc_addr(bytes))
615+
base_addr = page_to_phys(vmalloc_to_page(bytes)) +
616+
offset_in_page(bytes);
617+
else
618+
base_addr = __pa(bytes);
619+
if (PAGE_SIZE < (offset_in_page(bytes) + num_bytes))
620+
num_bytes = PAGE_SIZE - offset_in_page(bytes);
621+
622+
if (IS_ENABLED(CONFIG_32BIT))
623+
ret = sbi_ecall(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_READ,
624+
num_bytes, lower_32_bits(base_addr),
625+
upper_32_bits(base_addr), 0, 0, 0);
626+
else
627+
ret = sbi_ecall(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_READ,
628+
num_bytes, base_addr, 0, 0, 0, 0);
629+
630+
if (ret.error == SBI_ERR_FAILURE)
631+
return -EIO;
632+
return ret.error ? sbi_err_map_linux_errno(ret.error) : ret.value;
633+
}
634+
574635
void __init sbi_init(void)
575636
{
576637
int ret;
@@ -612,6 +673,11 @@ void __init sbi_init(void)
612673
sbi_srst_reboot_nb.priority = 192;
613674
register_restart_handler(&sbi_srst_reboot_nb);
614675
}
676+
if ((sbi_spec_version >= sbi_mk_version(2, 0)) &&
677+
(sbi_probe_extension(SBI_EXT_DBCN) > 0)) {
678+
pr_info("SBI DBCN extension detected\n");
679+
sbi_debug_console_available = true;
680+
}
615681
} else {
616682
__sbi_set_timer = __sbi_set_timer_v01;
617683
__sbi_send_ipi = __sbi_send_ipi_v01;

drivers/tty/hvc/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ config HVC_DCC_SERIALIZE_SMP
108108

109109
config HVC_RISCV_SBI
110110
bool "RISC-V SBI console support"
111-
depends on RISCV_SBI_V01
111+
depends on RISCV_SBI
112112
select HVC_DRIVER
113113
help
114114
This enables support for console output via RISC-V SBI calls, which

drivers/tty/hvc/hvc_riscv_sbi.c

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,21 +39,44 @@ static int hvc_sbi_tty_get(uint32_t vtermno, char *buf, int count)
3939
return i;
4040
}
4141

42-
static const struct hv_ops hvc_sbi_ops = {
42+
static const struct hv_ops hvc_sbi_v01_ops = {
4343
.get_chars = hvc_sbi_tty_get,
4444
.put_chars = hvc_sbi_tty_put,
4545
};
4646

47-
static int __init hvc_sbi_init(void)
47+
static int hvc_sbi_dbcn_tty_put(uint32_t vtermno, const char *buf, int count)
4848
{
49-
return PTR_ERR_OR_ZERO(hvc_alloc(0, 0, &hvc_sbi_ops, 16));
49+
return sbi_debug_console_write(buf, count);
5050
}
51-
device_initcall(hvc_sbi_init);
5251

53-
static int __init hvc_sbi_console_init(void)
52+
static int hvc_sbi_dbcn_tty_get(uint32_t vtermno, char *buf, int count)
5453
{
55-
hvc_instantiate(0, 0, &hvc_sbi_ops);
54+
return sbi_debug_console_read(buf, count);
55+
}
56+
57+
static const struct hv_ops hvc_sbi_dbcn_ops = {
58+
.put_chars = hvc_sbi_dbcn_tty_put,
59+
.get_chars = hvc_sbi_dbcn_tty_get,
60+
};
61+
62+
static int __init hvc_sbi_init(void)
63+
{
64+
int err;
65+
66+
if (sbi_debug_console_available) {
67+
err = PTR_ERR_OR_ZERO(hvc_alloc(0, 0, &hvc_sbi_dbcn_ops, 256));
68+
if (err)
69+
return err;
70+
hvc_instantiate(0, 0, &hvc_sbi_dbcn_ops);
71+
} else if (IS_ENABLED(CONFIG_RISCV_SBI_V01)) {
72+
err = PTR_ERR_OR_ZERO(hvc_alloc(0, 0, &hvc_sbi_v01_ops, 256));
73+
if (err)
74+
return err;
75+
hvc_instantiate(0, 0, &hvc_sbi_v01_ops);
76+
} else {
77+
return -ENODEV;
78+
}
5679

5780
return 0;
5881
}
59-
console_initcall(hvc_sbi_console_init);
82+
device_initcall(hvc_sbi_init);

drivers/tty/serial/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ config SERIAL_EARLYCON_SEMIHOST
8787

8888
config SERIAL_EARLYCON_RISCV_SBI
8989
bool "Early console using RISC-V SBI"
90-
depends on RISCV_SBI_V01
90+
depends on RISCV_SBI
9191
select SERIAL_CORE
9292
select SERIAL_CORE_CONSOLE
9393
select SERIAL_EARLYCON

drivers/tty/serial/earlycon-riscv-sbi.c

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,38 @@ static void sbi_putc(struct uart_port *port, unsigned char c)
1515
sbi_console_putchar(c);
1616
}
1717

18-
static void sbi_console_write(struct console *con,
19-
const char *s, unsigned n)
18+
static void sbi_0_1_console_write(struct console *con,
19+
const char *s, unsigned int n)
2020
{
2121
struct earlycon_device *dev = con->data;
2222
uart_console_write(&dev->port, s, n, sbi_putc);
2323
}
2424

25+
static void sbi_dbcn_console_write(struct console *con,
26+
const char *s, unsigned int n)
27+
{
28+
int ret;
29+
30+
while (n) {
31+
ret = sbi_debug_console_write(s, n);
32+
if (ret < 0)
33+
break;
34+
35+
s += ret;
36+
n -= ret;
37+
}
38+
}
39+
2540
static int __init early_sbi_setup(struct earlycon_device *device,
2641
const char *opt)
2742
{
28-
device->con->write = sbi_console_write;
43+
if (sbi_debug_console_available)
44+
device->con->write = sbi_dbcn_console_write;
45+
else if (IS_ENABLED(CONFIG_RISCV_SBI_V01))
46+
device->con->write = sbi_0_1_console_write;
47+
else
48+
return -ENODEV;
49+
2950
return 0;
3051
}
3152
EARLYCON_DECLARE(sbi, early_sbi_setup);

0 commit comments

Comments
 (0)