This commit introduces support for handling virtual SBI extensions in Xen. The changes include: - Added new vsbi.c and vsbi.h files to implement virtual SBI extension handling. - Modified traps.c to handle CAUSE_VIRTUAL_SUPERVISOR_ECALL by calling vsbi_handle_ecall() when the trap originates from VS-mode. - Updated xen.lds.S to include a new .vsbi.exts section for virtual SBI extension data. - Updated Makefile to include the new vsbi/ directory in the build. - Add hstatus register to struct cpu_user_regs as it is needed for a check that CAUSE_VIRTUAL_SUPERVISOR_ECALL happens from VS-mode.
The implementation allows for registration and handling of SBI extensions via a new vsbi_ext structure and ".vsbi.exts" section, enabling extensible virtual SBI support for RISC-V guests. Signed-off-by: Oleksii Kurochko <[email protected]> --- xen/arch/riscv/Makefile | 1 + xen/arch/riscv/include/asm/processor.h | 1 + xen/arch/riscv/include/asm/vsbi.h | 31 +++++++++++++++++ xen/arch/riscv/traps.c | 8 +++++ xen/arch/riscv/vsbi/Makefile | 1 + xen/arch/riscv/vsbi/vsbi.c | 46 ++++++++++++++++++++++++++ xen/arch/riscv/xen.lds.S | 7 ++++ 7 files changed, 95 insertions(+) create mode 100644 xen/arch/riscv/include/asm/vsbi.h create mode 100644 xen/arch/riscv/vsbi/Makefile create mode 100644 xen/arch/riscv/vsbi/vsbi.c diff --git a/xen/arch/riscv/Makefile b/xen/arch/riscv/Makefile index e2b8aa42c8..7bfe7024ef 100644 --- a/xen/arch/riscv/Makefile +++ b/xen/arch/riscv/Makefile @@ -17,6 +17,7 @@ obj-y += stubs.o obj-y += time.o obj-y += traps.o obj-y += vm_event.o +obj-y += vsbi/ $(TARGET): $(TARGET)-syms $(OBJCOPY) -O binary -S $< $@ diff --git a/xen/arch/riscv/include/asm/processor.h b/xen/arch/riscv/include/asm/processor.h index 39696fb58d..79d02c3dd2 100644 --- a/xen/arch/riscv/include/asm/processor.h +++ b/xen/arch/riscv/include/asm/processor.h @@ -49,6 +49,7 @@ struct cpu_user_regs unsigned long t6; unsigned long sepc; unsigned long sstatus; + unsigned long hstatus; /* pointer to previous stack_cpu_regs */ unsigned long pregs; }; diff --git a/xen/arch/riscv/include/asm/vsbi.h b/xen/arch/riscv/include/asm/vsbi.h new file mode 100644 index 0000000000..984e7acf7b --- /dev/null +++ b/xen/arch/riscv/include/asm/vsbi.h @@ -0,0 +1,31 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef ASM_RISCV_VSBI_H +#define ASM_RISCV_VSBI_H + +struct regs; +struct vcpu; + +struct vsbi_ext { + const char *name; + unsigned long eid_start; + unsigned long eid_end; + int (*handle)(struct vcpu *vcpu, unsigned long eid, + unsigned long fid, struct cpu_user_regs *regs); +}; + +#define VSBI_EXT_START(ext, extid_start, extid_end, extid_handle) \ +static const struct vsbi_ext vsbi_ext_##ext __used \ +__section(".vsbi.exts") = { \ + .name = #ext, \ + .eid_start = extid_start, \ + .eid_end = extid_end, \ + .handle = extid_handle, + +#define VSBI_EXT_END \ +}; + +void vsbi_handle_ecall(struct vcpu *vcpu, struct cpu_user_regs *regs); +const struct vsbi_ext *vsbi_find_extension(unsigned long ext_id); + +#endif diff --git a/xen/arch/riscv/traps.c b/xen/arch/riscv/traps.c index f061004d83..dfe1a5a112 100644 --- a/xen/arch/riscv/traps.c +++ b/xen/arch/riscv/traps.c @@ -15,6 +15,7 @@ #include <asm/processor.h> #include <asm/riscv_encoding.h> #include <asm/traps.h> +#include <asm/vsbi.h> /* * Initialize the trap handling. @@ -114,6 +115,13 @@ void do_trap(struct cpu_user_regs *cpu_regs) switch ( cause ) { + case CAUSE_VIRTUAL_SUPERVISOR_ECALL: + if ( !(cpu_regs->hstatus & HSTATUS_SPV) ) + panic("CAUSE_VIRTUAL_SUPERVISOR_ECALL came not from VS-mode\n"); + + vsbi_handle_ecall(current, cpu_regs); + break; + case CAUSE_ILLEGAL_INSTRUCTION: if ( do_bug_frame(cpu_regs, pc) >= 0 ) { diff --git a/xen/arch/riscv/vsbi/Makefile b/xen/arch/riscv/vsbi/Makefile new file mode 100644 index 0000000000..574c8ff78d --- /dev/null +++ b/xen/arch/riscv/vsbi/Makefile @@ -0,0 +1 @@ +obj-y += vsbi.o diff --git a/xen/arch/riscv/vsbi/vsbi.c b/xen/arch/riscv/vsbi/vsbi.c new file mode 100644 index 0000000000..cd119ce0d6 --- /dev/null +++ b/xen/arch/riscv/vsbi/vsbi.c @@ -0,0 +1,46 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <xen/sched.h> + +#include <asm/processor.h> +#include <asm/sbi.h> +#include <asm/vsbi.h> + +extern const struct vsbi_ext _svsbi_exts[], _evsbi_exts[]; + +const struct vsbi_ext *vsbi_find_extension(unsigned long ext_id) +{ + const struct vsbi_ext *vsbi_ext; + + for ( vsbi_ext = _svsbi_exts; vsbi_ext != _evsbi_exts; vsbi_ext++ ) + if ( ext_id >= vsbi_ext->eid_start && + ext_id <= vsbi_ext->eid_end ) + return vsbi_ext; + + return NULL; +} + +void vsbi_handle_ecall(struct vcpu *vcpu, struct cpu_user_regs *regs) +{ + const unsigned long eid = regs->a7; + const unsigned long fid = regs->a6; + const struct vsbi_ext *ext = vsbi_find_extension(eid); + int ret; + + if ( ext && ext->handle ) + ret = ext->handle(vcpu, eid, fid, regs); + else + { + printk("Unsupported Guest SBI EID #%#lx, FID #%lu\n", eid, regs->a1); + ret = SBI_ERR_NOT_SUPPORTED; + } + + /* + * The ecall instruction is not part of the RISC-V C extension (compressed + * instructions), so it is always 4 bytes long. Therefore, it is safe to + * use a fixed length of 4 bytes instead of reading guest memory to + * determine the instruction length. + */ + regs->sepc += 4; + regs->a0 = ret; +} diff --git a/xen/arch/riscv/xen.lds.S b/xen/arch/riscv/xen.lds.S index edcadff90b..2967f00ac5 100644 --- a/xen/arch/riscv/xen.lds.S +++ b/xen/arch/riscv/xen.lds.S @@ -91,6 +91,13 @@ SECTIONS DT_DEV_INFO /* Devicetree based device info */ + . = ALIGN(POINTER_ALIGN); + DECL_SECTION(.vsbi.exts) { + _svsbi_exts = .; + *(.vsbi.exts) + _evsbi_exts = .; + } :text + . = ALIGN(PAGE_SIZE); /* Init code and data */ __init_begin = .; .init.text : { -- 2.52.0
