Skip to content

Commit

Permalink
From patchwork series 377241
Browse files Browse the repository at this point in the history
  • Loading branch information
Fox Snowpatch committed Oct 12, 2023
1 parent b8b05bc commit 314eef1
Show file tree
Hide file tree
Showing 12 changed files with 188 additions and 33 deletions.
1 change: 1 addition & 0 deletions arch/riscv/configs/defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_8250_DW=y
CONFIG_SERIAL_OF_PLATFORM=y
CONFIG_SERIAL_SH_SCI=y
CONFIG_SERIAL_EARLYCON_RISCV_SBI=y
CONFIG_VIRTIO_CONSOLE=y
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_VIRTIO=y
Expand Down
1 change: 1 addition & 0 deletions arch/riscv/configs/rv32_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ CONFIG_INPUT_MOUSEDEV=y
CONFIG_SERIAL_8250=y
CONFIG_SERIAL_8250_CONSOLE=y
CONFIG_SERIAL_OF_PLATFORM=y
CONFIG_SERIAL_EARLYCON_RISCV_SBI=y
CONFIG_VIRTIO_CONSOLE=y
CONFIG_HW_RANDOM=y
CONFIG_HW_RANDOM_VIRTIO=y
Expand Down
7 changes: 6 additions & 1 deletion arch/riscv/include/asm/kvm_vcpu_sbi.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

#define KVM_SBI_IMPID 3

#define KVM_SBI_VERSION_MAJOR 1
#define KVM_SBI_VERSION_MAJOR 2
#define KVM_SBI_VERSION_MINOR 0

enum kvm_riscv_sbi_ext_status {
Expand All @@ -35,6 +35,9 @@ struct kvm_vcpu_sbi_return {
struct kvm_vcpu_sbi_extension {
unsigned long extid_start;
unsigned long extid_end;

bool default_unavail;

/**
* SBI extension handler. It can be defined for a given extension or group of
* extension. But it should always return linux error codes rather than SBI
Expand All @@ -59,6 +62,7 @@ int kvm_riscv_vcpu_get_reg_sbi_ext(struct kvm_vcpu *vcpu,
const struct kvm_vcpu_sbi_extension *kvm_vcpu_sbi_find_ext(
struct kvm_vcpu *vcpu, unsigned long extid);
int kvm_riscv_vcpu_sbi_ecall(struct kvm_vcpu *vcpu, struct kvm_run *run);
void kvm_riscv_vcpu_sbi_init(struct kvm_vcpu *vcpu);

#ifdef CONFIG_RISCV_SBI_V01
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_v01;
Expand All @@ -69,6 +73,7 @@ extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_ipi;
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_rfence;
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_srst;
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_hsm;
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_dbcn;
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_experimental;
extern const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_vendor;

Expand Down
12 changes: 12 additions & 0 deletions arch/riscv/include/asm/sbi.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ enum sbi_ext_id {
SBI_EXT_HSM = 0x48534D,
SBI_EXT_SRST = 0x53525354,
SBI_EXT_PMU = 0x504D55,
SBI_EXT_DBCN = 0x4442434E,

/* Experimentals extensions must lie within this range */
SBI_EXT_EXPERIMENTAL_START = 0x08000000,
Expand Down Expand Up @@ -236,6 +237,12 @@ enum sbi_pmu_ctr_type {
/* Flags defined for counter stop function */
#define SBI_PMU_STOP_FLAG_RESET (1 << 0)

enum sbi_ext_dbcn_fid {
SBI_EXT_DBCN_CONSOLE_WRITE = 0,
SBI_EXT_DBCN_CONSOLE_READ = 1,
SBI_EXT_DBCN_CONSOLE_WRITE_BYTE = 2,
};

#define SBI_SPEC_VERSION_DEFAULT 0x1
#define SBI_SPEC_VERSION_MAJOR_SHIFT 24
#define SBI_SPEC_VERSION_MAJOR_MASK 0x7f
Expand Down Expand Up @@ -264,8 +271,13 @@ struct sbiret sbi_ecall(int ext, int fid, unsigned long arg0,
unsigned long arg3, unsigned long arg4,
unsigned long arg5);

#ifdef CONFIG_RISCV_SBI_V01
void sbi_console_putchar(int ch);
int sbi_console_getchar(void);
#else
static inline void sbi_console_putchar(int ch) { }
static inline int sbi_console_getchar(void) { return -1; }
#endif
long sbi_get_mvendorid(void);
long sbi_get_marchid(void);
long sbi_get_mimpid(void);
Expand Down
1 change: 1 addition & 0 deletions arch/riscv/include/uapi/asm/kvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ enum KVM_RISCV_SBI_EXT_ID {
KVM_RISCV_SBI_EXT_PMU,
KVM_RISCV_SBI_EXT_EXPERIMENTAL,
KVM_RISCV_SBI_EXT_VENDOR,
KVM_RISCV_SBI_EXT_DBCN,
KVM_RISCV_SBI_EXT_MAX,
};

Expand Down
6 changes: 6 additions & 0 deletions arch/riscv/kvm/vcpu.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,12 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
if (rc)
return rc;

/*
* Setup SBI extensions
* NOTE: This must be the last thing to be initialized.
*/
kvm_riscv_vcpu_sbi_init(vcpu);

/* Reset VCPU */
kvm_riscv_reset_vcpu(vcpu);

Expand Down
49 changes: 30 additions & 19 deletions arch/riscv/kvm/vcpu_sbi.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ static const struct kvm_riscv_sbi_extension_entry sbi_ext[] = {
.ext_idx = KVM_RISCV_SBI_EXT_PMU,
.ext_ptr = &vcpu_sbi_ext_pmu,
},
{
.ext_idx = KVM_RISCV_SBI_EXT_DBCN,
.ext_ptr = &vcpu_sbi_ext_dbcn,
},
{
.ext_idx = KVM_RISCV_SBI_EXT_EXPERIMENTAL,
.ext_ptr = &vcpu_sbi_ext_experimental,
Expand Down Expand Up @@ -155,14 +159,8 @@ static int riscv_vcpu_set_sbi_ext_single(struct kvm_vcpu *vcpu,
if (!sext)
return -ENOENT;

/*
* We can't set the extension status to available here, since it may
* have a probe() function which needs to confirm availability first,
* but it may be too early to call that here. We can set the status to
* unavailable, though.
*/
if (!reg_val)
scontext->ext_status[sext->ext_idx] =
scontext->ext_status[sext->ext_idx] = (reg_val) ?
KVM_RISCV_SBI_EXT_AVAILABLE :
KVM_RISCV_SBI_EXT_UNAVAILABLE;

return 0;
Expand Down Expand Up @@ -337,18 +335,8 @@ const struct kvm_vcpu_sbi_extension *kvm_vcpu_sbi_find_ext(
scontext->ext_status[entry->ext_idx] ==
KVM_RISCV_SBI_EXT_AVAILABLE)
return ext;
if (scontext->ext_status[entry->ext_idx] ==
KVM_RISCV_SBI_EXT_UNAVAILABLE)
return NULL;
if (ext->probe && !ext->probe(vcpu)) {
scontext->ext_status[entry->ext_idx] =
KVM_RISCV_SBI_EXT_UNAVAILABLE;
return NULL;
}

scontext->ext_status[entry->ext_idx] =
KVM_RISCV_SBI_EXT_AVAILABLE;
return ext;
return NULL;
}
}

Expand Down Expand Up @@ -419,3 +407,26 @@ int kvm_riscv_vcpu_sbi_ecall(struct kvm_vcpu *vcpu, struct kvm_run *run)

return ret;
}

void kvm_riscv_vcpu_sbi_init(struct kvm_vcpu *vcpu)
{
struct kvm_vcpu_sbi_context *scontext = &vcpu->arch.sbi_context;
const struct kvm_riscv_sbi_extension_entry *entry;
const struct kvm_vcpu_sbi_extension *ext;
int i;

for (i = 0; i < ARRAY_SIZE(sbi_ext); i++) {
entry = &sbi_ext[i];
ext = entry->ext_ptr;

if (ext->probe && !ext->probe(vcpu)) {
scontext->ext_status[entry->ext_idx] =
KVM_RISCV_SBI_EXT_UNAVAILABLE;
continue;
}

scontext->ext_status[entry->ext_idx] = ext->default_unavail ?
KVM_RISCV_SBI_EXT_UNAVAILABLE :
KVM_RISCV_SBI_EXT_AVAILABLE;
}
}
32 changes: 32 additions & 0 deletions arch/riscv/kvm/vcpu_sbi_replace.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,3 +175,35 @@ const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_srst = {
.extid_end = SBI_EXT_SRST,
.handler = kvm_sbi_ext_srst_handler,
};

static int kvm_sbi_ext_dbcn_handler(struct kvm_vcpu *vcpu,
struct kvm_run *run,
struct kvm_vcpu_sbi_return *retdata)
{
struct kvm_cpu_context *cp = &vcpu->arch.guest_context;
unsigned long funcid = cp->a6;

switch (funcid) {
case SBI_EXT_DBCN_CONSOLE_WRITE:
case SBI_EXT_DBCN_CONSOLE_READ:
case SBI_EXT_DBCN_CONSOLE_WRITE_BYTE:
/*
* The SBI debug console functions are unconditionally
* forwarded to the userspace.
*/
kvm_riscv_vcpu_sbi_forward(vcpu, run);
retdata->uexit = true;
break;
default:
retdata->err_val = SBI_ERR_NOT_SUPPORTED;
}

return 0;
}

const struct kvm_vcpu_sbi_extension vcpu_sbi_ext_dbcn = {
.extid_start = SBI_EXT_DBCN,
.extid_end = SBI_EXT_DBCN,
.default_unavail = true,
.handler = kvm_sbi_ext_dbcn_handler,
};
2 changes: 1 addition & 1 deletion drivers/tty/hvc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ config HVC_DCC_SERIALIZE_SMP

config HVC_RISCV_SBI
bool "RISC-V SBI console support"
depends on RISCV_SBI_V01
depends on RISCV_SBI
select HVC_DRIVER
help
This enables support for console output via RISC-V SBI calls, which
Expand Down
76 changes: 69 additions & 7 deletions drivers/tty/hvc/hvc_riscv_sbi.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,21 +39,83 @@ static int hvc_sbi_tty_get(uint32_t vtermno, char *buf, int count)
return i;
}

static const struct hv_ops hvc_sbi_ops = {
static const struct hv_ops hvc_sbi_v01_ops = {
.get_chars = hvc_sbi_tty_get,
.put_chars = hvc_sbi_tty_put,
};

static int __init hvc_sbi_init(void)
static int hvc_sbi_dbcn_tty_put(uint32_t vtermno, const char *buf, int count)
{
return PTR_ERR_OR_ZERO(hvc_alloc(0, 0, &hvc_sbi_ops, 16));
phys_addr_t pa;
struct sbiret ret;

if (is_vmalloc_addr(buf))
pa = page_to_phys(vmalloc_to_page(buf)) + offset_in_page(buf);
else
pa = __pa(buf);

if (IS_ENABLED(CONFIG_32BIT))
ret = sbi_ecall(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_WRITE,
count, lower_32_bits(pa), upper_32_bits(pa),
0, 0, 0);
else
ret = sbi_ecall(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_WRITE,
count, pa, 0, 0, 0, 0);
if (ret.error)
return 0;

return count;
}
device_initcall(hvc_sbi_init);

static int __init hvc_sbi_console_init(void)
static int hvc_sbi_dbcn_tty_get(uint32_t vtermno, char *buf, int count)
{
hvc_instantiate(0, 0, &hvc_sbi_ops);
phys_addr_t pa;
struct sbiret ret;

if (is_vmalloc_addr(buf))
pa = page_to_phys(vmalloc_to_page(buf)) + offset_in_page(buf);
else
pa = __pa(buf);

if (IS_ENABLED(CONFIG_32BIT))
ret = sbi_ecall(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_READ,
count, lower_32_bits(pa), upper_32_bits(pa),
0, 0, 0);
else
ret = sbi_ecall(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_READ,
count, pa, 0, 0, 0, 0);
if (ret.error)
return 0;

return ret.value;
}

static const struct hv_ops hvc_sbi_dbcn_ops = {
.put_chars = hvc_sbi_dbcn_tty_put,
.get_chars = hvc_sbi_dbcn_tty_get,
};

static int __init hvc_sbi_init(void)
{
int err;

if ((sbi_spec_version >= sbi_mk_version(2, 0)) &&
(sbi_probe_extension(SBI_EXT_DBCN) > 0)) {
err = PTR_ERR_OR_ZERO(hvc_alloc(0, 0, &hvc_sbi_dbcn_ops, 16));
if (err)
return err;
hvc_instantiate(0, 0, &hvc_sbi_dbcn_ops);
} else {
if (IS_ENABLED(CONFIG_RISCV_SBI_V01)) {
err = PTR_ERR_OR_ZERO(hvc_alloc(0, 0, &hvc_sbi_v01_ops, 16));
if (err)
return err;
hvc_instantiate(0, 0, &hvc_sbi_v01_ops);
} else {
return -ENODEV;
}
}

return 0;
}
console_initcall(hvc_sbi_console_init);
device_initcall(hvc_sbi_init);
2 changes: 1 addition & 1 deletion drivers/tty/serial/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ config SERIAL_EARLYCON_SEMIHOST

config SERIAL_EARLYCON_RISCV_SBI
bool "Early console using RISC-V SBI"
depends on RISCV_SBI_V01
depends on RISCV_SBI
select SERIAL_CORE
select SERIAL_CORE_CONSOLE
select SERIAL_EARLYCON
Expand Down
32 changes: 28 additions & 4 deletions drivers/tty/serial/earlycon-riscv-sbi.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,41 @@ static void sbi_putc(struct uart_port *port, unsigned char c)
sbi_console_putchar(c);
}

static void sbi_console_write(struct console *con,
const char *s, unsigned n)
static void sbi_0_1_console_write(struct console *con,
const char *s, unsigned int n)
{
struct earlycon_device *dev = con->data;
uart_console_write(&dev->port, s, n, sbi_putc);
}

static void sbi_dbcn_console_write(struct console *con,
const char *s, unsigned int n)
{
phys_addr_t pa = __pa(s);

if (IS_ENABLED(CONFIG_32BIT))
sbi_ecall(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_WRITE,
n, lower_32_bits(pa), upper_32_bits(pa), 0, 0, 0);
else
sbi_ecall(SBI_EXT_DBCN, SBI_EXT_DBCN_CONSOLE_WRITE,
n, pa, 0, 0, 0, 0);
}

static int __init early_sbi_setup(struct earlycon_device *device,
const char *opt)
{
device->con->write = sbi_console_write;
return 0;
int ret = 0;

if ((sbi_spec_version >= sbi_mk_version(2, 0)) &&
(sbi_probe_extension(SBI_EXT_DBCN) > 0)) {
device->con->write = sbi_dbcn_console_write;
} else {
if (IS_ENABLED(CONFIG_RISCV_SBI_V01))
device->con->write = sbi_0_1_console_write;
else
ret = -ENODEV;
}

return ret;
}
EARLYCON_DECLARE(sbi, early_sbi_setup);

0 comments on commit 314eef1

Please sign in to comment.