Skip to content

Commit

Permalink
RISC-V: Add SBI debug console helper routines
Browse files Browse the repository at this point in the history
Let us provide SBI debug console helper routines which can be
shared by serial/earlycon-riscv-sbi.c and hvc/hvc_riscv_sbi.c.

Signed-off-by: Anup Patel <apatel@ventanamicro.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Link: https://lore.kernel.org/r/20231124070905.1043092-3-apatel@ventanamicro.com
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
  • Loading branch information
Anup Patel authored and Palmer Dabbelt committed Jan 10, 2024
1 parent f503b16 commit f43fabf
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 0 deletions.
5 changes: 5 additions & 0 deletions arch/riscv/include/asm/sbi.h
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,11 @@ static inline unsigned long sbi_mk_version(unsigned long major,
}

int sbi_err_map_linux_errno(int err);

extern bool sbi_debug_console_available;
int sbi_debug_console_write(const char *bytes, unsigned int num_bytes);
int sbi_debug_console_read(char *bytes, unsigned int num_bytes);

#else /* CONFIG_RISCV_SBI */
static inline int sbi_remote_fence_i(const struct cpumask *cpu_mask) { return -1; }
static inline void sbi_init(void) {}
Expand Down
66 changes: 66 additions & 0 deletions arch/riscv/kernel/sbi.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <linux/bits.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/pm.h>
#include <linux/reboot.h>
#include <asm/sbi.h>
Expand Down Expand Up @@ -571,6 +572,66 @@ long sbi_get_mimpid(void)
}
EXPORT_SYMBOL_GPL(sbi_get_mimpid);

bool sbi_debug_console_available;

int sbi_debug_console_write(const char *bytes, unsigned int num_bytes)
{
phys_addr_t base_addr;
struct sbiret ret;

if (!sbi_debug_console_available)
return -EOPNOTSUPP;

if (is_vmalloc_addr(bytes))
base_addr = page_to_phys(vmalloc_to_page(bytes)) +
offset_in_page(bytes);
else
base_addr = __pa(bytes);
if (PAGE_SIZE < (offset_in_page(bytes) + num_bytes))
num_bytes = PAGE_SIZE - offset_in_page(bytes);

if (IS_ENABLED(CONFIG_32BIT))
ret = sbi_ecall(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_WRITE,
num_bytes, lower_32_bits(base_addr),
upper_32_bits(base_addr), 0, 0, 0);
else
ret = sbi_ecall(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_WRITE,
num_bytes, base_addr, 0, 0, 0, 0);

if (ret.error == SBI_ERR_FAILURE)
return -EIO;
return ret.error ? sbi_err_map_linux_errno(ret.error) : ret.value;
}

int sbi_debug_console_read(char *bytes, unsigned int num_bytes)
{
phys_addr_t base_addr;
struct sbiret ret;

if (!sbi_debug_console_available)
return -EOPNOTSUPP;

if (is_vmalloc_addr(bytes))
base_addr = page_to_phys(vmalloc_to_page(bytes)) +
offset_in_page(bytes);
else
base_addr = __pa(bytes);
if (PAGE_SIZE < (offset_in_page(bytes) + num_bytes))
num_bytes = PAGE_SIZE - offset_in_page(bytes);

if (IS_ENABLED(CONFIG_32BIT))
ret = sbi_ecall(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_READ,
num_bytes, lower_32_bits(base_addr),
upper_32_bits(base_addr), 0, 0, 0);
else
ret = sbi_ecall(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_READ,
num_bytes, base_addr, 0, 0, 0, 0);

if (ret.error == SBI_ERR_FAILURE)
return -EIO;
return ret.error ? sbi_err_map_linux_errno(ret.error) : ret.value;
}

void __init sbi_init(void)
{
int ret;
Expand Down Expand Up @@ -612,6 +673,11 @@ void __init sbi_init(void)
sbi_srst_reboot_nb.priority = 192;
register_restart_handler(&sbi_srst_reboot_nb);
}
if ((sbi_spec_version >= sbi_mk_version(2, 0)) &&
(sbi_probe_extension(SBI_EXT_DBCN) > 0)) {
pr_info("SBI DBCN extension detected\n");
sbi_debug_console_available = true;
}
} else {
__sbi_set_timer = __sbi_set_timer_v01;
__sbi_send_ipi = __sbi_send_ipi_v01;
Expand Down

0 comments on commit f43fabf

Please sign in to comment.