:p
atchew
Login
Introduce the vSBI framework to handle extension ecall instruction calls from a guest. In this patch series, support is added for only a few extensions and FIDs, just enough to boot the first guest domains and obtain logs from them. This keeps the patch series independent from other ongoing work. It was decided to start with support for the Legacy Extension, as it is still supported by Linux (so we may need it anyway), and because some of its FIDs require less functionality to implement at this stage compared to the more modern extensions. CI tests: https://gitlab.com/xen-project/people/olkur/xen/-/pipelines/2228014400 --- Changes in v3: - Address a comments from v2. --- Changes in v2: - Address a comments from v1. --- Oleksii Kurochko (3): xen/riscv: introduce vSBI extension framework xen/riscv: add RISC-V legacy SBI extension support for guests xen/riscv: add RISC-V virtual SBI base extension support for guests xen/arch/riscv/Makefile | 1 + xen/arch/riscv/entry.S | 6 ++ xen/arch/riscv/include/asm/processor.h | 1 + xen/arch/riscv/include/asm/sbi.h | 21 ++++++- xen/arch/riscv/include/asm/vsbi.h | 31 ++++++++++ xen/arch/riscv/riscv64/asm-offsets.c | 1 + xen/arch/riscv/setup.c | 3 + xen/arch/riscv/traps.c | 8 +++ xen/arch/riscv/vsbi/Makefile | 3 + xen/arch/riscv/vsbi/base-extension.c | 78 ++++++++++++++++++++++++++ xen/arch/riscv/vsbi/core.c | 57 +++++++++++++++++++ xen/arch/riscv/vsbi/legacy-extension.c | 64 +++++++++++++++++++++ xen/arch/riscv/xen.lds.S | 7 +++ 13 files changed, 279 insertions(+), 2 deletions(-) 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/base-extension.c create mode 100644 xen/arch/riscv/vsbi/core.c create mode 100644 xen/arch/riscv/vsbi/legacy-extension.c -- 2.52.0
This commit introduces support for handling virtual SBI extensions in Xen. The changes include: - Added new vsbi/core.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. Also, add storing/restoring of hstatus register in handle_trap(). - Introduce vsbi_find_extension() to check if vsbi extension is supported by Xen. For now it is called only inside vsbi/core.c, but in future it is going to be called from other files. - Introduce check_vsbi_ext_ranges() to check if there EIDs ranges overlapping between extensions. 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. Note: All EIDs are printed in the format #%#lx and all FIDs in #%lu, as the SBI spec uses these formats. Printing them this way makes it easier to search for them in the SBI spec. Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com> --- Changes in v3: - Declare ext inside for() in vsbi_find_extension(). - Use gprintk() instead of printk(). - Drop `vcpu` argument for vsbi_handle_ecall() and ->handlers() as current is always used. - Correct commit message: s/#%#lu/#%lu. --- Changes in v2: - s/struct regs/struct cpu_user_regs. - s/handle/handler. - Drop extid_ prefix inside VSBI_EXT_START(). - use BUG_ON() instead of panic to be sure that CAUSE_VIRTUAL_SUPERVISOR_ECALL comes from VS-mode. - s/ext_id/eid for vsbi_find_extension(). - Add the comment above VSBI_EXT_START about [start,end] range. - Drop check "&& ext->handler" in vsbi_handle_ecall() as it isn't be so that handler() isn't provided. - s/vsbi.c/core.c - s/vsbi_ext/ext for local variable inside vsbi_find_extension(). - Update the commit message: add a note about FID and EID printing formats, add some information about vsbo_find_extension() function, and add info about check_vsbi_ext_ranges(). - Introduce check_vsbi_ext_ranges() to be sure that there is no overlapping in EIDs range(s). - Add storing/restoring of hstatus register in handle_trap()[entry.S]. --- xen/arch/riscv/Makefile | 1 + xen/arch/riscv/entry.S | 6 +++ xen/arch/riscv/include/asm/processor.h | 1 + xen/arch/riscv/include/asm/vsbi.h | 31 ++++++++++++++ xen/arch/riscv/riscv64/asm-offsets.c | 1 + xen/arch/riscv/setup.c | 3 ++ xen/arch/riscv/traps.c | 8 ++++ xen/arch/riscv/vsbi/Makefile | 1 + xen/arch/riscv/vsbi/core.c | 57 ++++++++++++++++++++++++++ xen/arch/riscv/xen.lds.S | 7 ++++ 10 files changed, 116 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/core.c diff --git a/xen/arch/riscv/Makefile b/xen/arch/riscv/Makefile index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/riscv/Makefile +++ b/xen/arch/riscv/Makefile @@ -XXX,XX +XXX,XX @@ obj-y += time.o obj-y += traps.o obj-y += vmid.o obj-y += vm_event.o +obj-y += vsbi/ $(TARGET): $(TARGET)-syms $(OBJCOPY) -O binary -S $< $@ diff --git a/xen/arch/riscv/entry.S b/xen/arch/riscv/entry.S index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/riscv/entry.S +++ b/xen/arch/riscv/entry.S @@ -XXX,XX +XXX,XX @@ save_to_stack: csrr t0, CSR_SSTATUS REG_S t0, CPU_USER_REGS_SSTATUS(sp) + csrr t0, CSR_HSTATUS + REG_S t0, CPU_USER_REGS_HSTATUS(sp) + mv a0, sp call do_trap restore_registers: /* Restore stack_cpu_regs */ + REG_L t0, CPU_USER_REGS_HSTATUS(sp) + csrw CSR_HSTATUS, t0 + REG_L t0, CPU_USER_REGS_SEPC(sp) csrw CSR_SEPC, t0 REG_L t0, CPU_USER_REGS_SSTATUS(sp) diff --git a/xen/arch/riscv/include/asm/processor.h b/xen/arch/riscv/include/asm/processor.h index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/riscv/include/asm/processor.h +++ b/xen/arch/riscv/include/asm/processor.h @@ -XXX,XX +XXX,XX @@ 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 XXXXXXX..XXXXXXX --- /dev/null +++ b/xen/arch/riscv/include/asm/vsbi.h @@ -XXX,XX +XXX,XX @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef ASM_RISCV_VSBI_H +#define ASM_RISCV_VSBI_H + +struct cpu_user_regs; + +struct vsbi_ext { + const char *name; + unsigned long eid_start; + unsigned long eid_end; + int (*handler)(unsigned long eid, unsigned long fid, + struct cpu_user_regs *regs); +}; + +/* Ranges (start and end) are inclusive within an extension */ +#define VSBI_EXT(ext, start, end, handle) \ +static const struct vsbi_ext vsbi_ext_##ext __used \ +__section(".vsbi.exts") = { \ + .name = #ext, \ + .eid_start = start, \ + .eid_end = end, \ + .handler = handle, \ +}; + +void vsbi_handle_ecall(struct cpu_user_regs *regs); +const struct vsbi_ext *vsbi_find_extension(unsigned long eid); + +void check_vsbi_ext_ranges(void); + +#endif diff --git a/xen/arch/riscv/riscv64/asm-offsets.c b/xen/arch/riscv/riscv64/asm-offsets.c index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/riscv/riscv64/asm-offsets.c +++ b/xen/arch/riscv/riscv64/asm-offsets.c @@ -XXX,XX +XXX,XX @@ void asm_offsets(void) OFFSET(CPU_USER_REGS_T6, struct cpu_user_regs, t6); OFFSET(CPU_USER_REGS_SEPC, struct cpu_user_regs, sepc); OFFSET(CPU_USER_REGS_SSTATUS, struct cpu_user_regs, sstatus); + OFFSET(CPU_USER_REGS_HSTATUS, struct cpu_user_regs, hstatus); OFFSET(CPU_USER_REGS_PREGS, struct cpu_user_regs, pregs); BLANK(); DEFINE(PCPU_INFO_SIZE, sizeof(struct pcpu_info)); diff --git a/xen/arch/riscv/setup.c b/xen/arch/riscv/setup.c index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/riscv/setup.c +++ b/xen/arch/riscv/setup.c @@ -XXX,XX +XXX,XX @@ #include <asm/sbi.h> #include <asm/setup.h> #include <asm/traps.h> +#include <asm/vsbi.h> /* Xen stack for bringing up the first CPU. */ unsigned char __initdata cpu0_boot_stack[STACK_SIZE] @@ -XXX,XX +XXX,XX @@ void __init noreturn start_xen(unsigned long bootcpu_id, end_boot_allocator(); + check_vsbi_ext_ranges(); + /* * The memory subsystem has been initialized, we can now switch from * early_boot -> boot. diff --git a/xen/arch/riscv/traps.c b/xen/arch/riscv/traps.c index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/riscv/traps.c +++ b/xen/arch/riscv/traps.c @@ -XXX,XX +XXX,XX @@ #include <asm/processor.h> #include <asm/riscv_encoding.h> #include <asm/traps.h> +#include <asm/vsbi.h> /* * Initialize the trap handling. @@ -XXX,XX +XXX,XX @@ void do_trap(struct cpu_user_regs *cpu_regs) switch ( cause ) { + case CAUSE_VIRTUAL_SUPERVISOR_ECALL: + /* CAUSE_VIRTUAL_SUPERVISOR_ECALL should come from VS-mode */ + BUG_ON(!(cpu_regs->hstatus & HSTATUS_SPV)); + + vsbi_handle_ecall(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 XXXXXXX..XXXXXXX --- /dev/null +++ b/xen/arch/riscv/vsbi/Makefile @@ -0,0 +1 @@ +obj-y += core.o diff --git a/xen/arch/riscv/vsbi/core.c b/xen/arch/riscv/vsbi/core.c new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/xen/arch/riscv/vsbi/core.c @@ -XXX,XX +XXX,XX @@ +/* 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[]; + +void __init check_vsbi_ext_ranges(void) +{ + for ( const struct vsbi_ext *a = _svsbi_exts; a != _evsbi_exts; a++ ) + for ( const struct vsbi_ext *b = a + 1; b != _evsbi_exts; b++ ) + if ( !(a->eid_end < b->eid_start || b->eid_end < a->eid_start) ) + panic("EID range overlap detected: " + "%s:[#%#lx..#%#lx] vs %s:[#%#lx..#%#lx]\n", + a->name, a->eid_start, a->eid_end, + b->name, b->eid_start, b->eid_end); +} + +const struct vsbi_ext *vsbi_find_extension(unsigned long eid) +{ + for ( const struct vsbi_ext *ext = _svsbi_exts; + ext != _evsbi_exts; + ext++ ) + if ( (eid >= ext->eid_start) && (eid <= ext->eid_end) ) + return ext; + + return NULL; +} + +void vsbi_handle_ecall(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 ) + ret = ext->handler(eid, fid, regs); + else + { + gprintk(XENLOG_ERR, "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 XXXXXXX..XXXXXXX 100644 --- a/xen/arch/riscv/xen.lds.S +++ b/xen/arch/riscv/xen.lds.S @@ -XXX,XX +XXX,XX @@ SECTIONS __note_gnu_build_id_end = .; } :note :text #endif + + . = ALIGN(POINTER_ALIGN); + DECL_SECTION(.vsbi.exts) { + _svsbi_exts = .; + *(.vsbi.exts) + _evsbi_exts = .; + } :text _erodata = .; /* End of read-only data */ . = ALIGN(PAGE_SIZE); -- 2.52.0
This commit adds support for legacy SBI extensions (version 0.1) in Xen for guest domains. The changes include: 1. Define all legacy SBI extension IDs (0x0 to 0x8) for better clarity and completeness. 2. Implement handling of legacy SBI extensions, starting with support for SBI_EXT_0_1_CONSOLE_PUTCHAR. SBI_EXT_0_1_CONSOLE_GETCHAR is marked as not supported as legacy SBI console related stuff is expected to be used only for early debugging of guest. The implementation uses the existing virtual SBI framework to handle legacy SBI ecalls, ensuring compatibility with older SBI specifications in RISC-V guests. Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com> --- Changes in v3: - s/vsbi_print_line/vsbi_print_char. - s/cd/currd in vsbi_print_char(). - Drop a cast of regs->a0 when vsbi_print_line() is called. - Use current instead of `vcpu` argument as it was dropped from vsbi_base_ecall_handler() prototype. --- Changes in v2: - s/vsbi-legacy-extension.*/legacy-extension.* - Correct padding for SBI_EXT_0_1_* macros. - Set ret = SBI_ERR_NOT_SUPPORTED; in the case of vsbi_legacy_ecall_handler() instead of regs->a0 = ... as regs->a0 will be overwritten in vsbi_handle_ecall(). - Use domain_crash() instead of panic() in vsbi_legacy_ecall_handler() and add TODO. - Use newly introduced VSBI_EXT macros instead of VSBI_EXT_{START,END}. - Introduce vsbi_print_line() and use it instead of plain printk() in the handler of SBI_EXT_0_1_CONSOLE_PUTCHAR. --- xen/arch/riscv/include/asm/sbi.h | 11 ++++- xen/arch/riscv/vsbi/Makefile | 1 + xen/arch/riscv/vsbi/legacy-extension.c | 64 ++++++++++++++++++++++++++ 3 files changed, 74 insertions(+), 2 deletions(-) create mode 100644 xen/arch/riscv/vsbi/legacy-extension.c diff --git a/xen/arch/riscv/include/asm/sbi.h b/xen/arch/riscv/include/asm/sbi.h index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/riscv/include/asm/sbi.h +++ b/xen/arch/riscv/include/asm/sbi.h @@ -XXX,XX +XXX,XX @@ #include <xen/cpumask.h> -#define SBI_EXT_0_1_CONSOLE_PUTCHAR 0x1 -#define SBI_EXT_0_1_SHUTDOWN 0x8 +#define SBI_EXT_0_1_SET_TIMER 0x0 +#define SBI_EXT_0_1_CONSOLE_PUTCHAR 0x1 +#define SBI_EXT_0_1_CONSOLE_GETCHAR 0x2 +#define SBI_EXT_0_1_CLEAR_IPI 0x3 +#define SBI_EXT_0_1_SEND_IPI 0x4 +#define SBI_EXT_0_1_REMOTE_FENCE_I 0x5 +#define SBI_EXT_0_1_REMOTE_SFENCE_VMA 0x6 +#define SBI_EXT_0_1_REMOTE_SFENCE_VMA_ASID 0x7 +#define SBI_EXT_0_1_SHUTDOWN 0x8 #define SBI_EXT_BASE 0x10 #define SBI_EXT_RFENCE 0x52464E43 diff --git a/xen/arch/riscv/vsbi/Makefile b/xen/arch/riscv/vsbi/Makefile index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/riscv/vsbi/Makefile +++ b/xen/arch/riscv/vsbi/Makefile @@ -1 +1,2 @@ obj-y += core.o +obj-y += legacy-extension.o diff --git a/xen/arch/riscv/vsbi/legacy-extension.c b/xen/arch/riscv/vsbi/legacy-extension.c new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/xen/arch/riscv/vsbi/legacy-extension.c @@ -XXX,XX +XXX,XX @@ + +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <xen/console.h> +#include <xen/lib.h> +#include <xen/sched.h> + +#include <asm/processor.h> +#include <asm/vsbi.h> + +static void vsbi_print_char(char c) +{ + struct domain *currd = current->domain; + struct domain_console *cons = currd->console; + + if ( !is_console_printable(c) ) + return; + + spin_lock(&cons->lock); + ASSERT(cons->idx < ARRAY_SIZE(cons->buf)); + if ( c != '\n' ) + cons->buf[cons->idx++] = c; + if ( (cons->idx == (ARRAY_SIZE(cons->buf) - 1)) || (c == '\n') ) + { + cons->buf[cons->idx] = '\0'; + guest_printk(currd, XENLOG_G_DEBUG "%s\n", cons->buf); + cons->idx = 0; + } + spin_unlock(&cons->lock); +} + +static int vsbi_legacy_ecall_handler(unsigned long eid, unsigned long fid, + struct cpu_user_regs *regs) +{ + int ret = 0; + + switch ( eid ) + { + case SBI_EXT_0_1_CONSOLE_PUTCHAR: + vsbi_print_char(regs->a0); + break; + + case SBI_EXT_0_1_CONSOLE_GETCHAR: + ret = SBI_ERR_NOT_SUPPORTED; + break; + + default: + /* + * TODO: domain_crash() is acceptable here while things are still under + * development. + * It shouldn't stay like this in the end though: guests should not + * be punished like this for something Xen hasn't implemented. + */ + domain_crash(current->domain, + "%s: Unsupported ecall: FID: #%lx, EID: #%lx\n", + __func__, fid, eid); + break; + } + + return ret; +} + +VSBI_EXT(legacy, SBI_EXT_0_1_SET_TIMER, SBI_EXT_0_1_SHUTDOWN, + vsbi_legacy_ecall_handler); -- 2.52.0
Add support of virtual SBI base extension calls for RISC-V guests, delegating hardware-specific queries to the underlying SBI and handling version and firmware ID queries directly. The changes include: 1. Define new SBI base extension function IDs (SBI_EXT_BASE_GET_MVENDORID, SBI_EXT_BASE_GET_MARCHID, SBI_EXT_BASE_GET_MIMPID). 2. Introduce XEN_SBI_VER_MAJOR, XEN_SBI_VER_MINOR for imeplenataion of SBI_EXT_BASE_GET_SPEC_VERSION. 4. Introduce SBI_XEN_IMPID to implement SBI_EXT_BASE_GET_IMP_ID. 5. Implement handling of SBI base extension functions, including version, firmware ID, and machine-specific queries. Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com> --- Changes in v3: - s/XEN_SBI_IMPID/SBI_XEN_IMPID - Add ASSERT(eid == SBI_EXT_BASE) in vsbi_base_ecall_handler(). - Fix code style for switch/case. - Use current instead of `vcpu` argument as it was dropped from vsbi_base_ecall_handler() prototype. - Add comments for define-s XEN_SBI_VER_{MAJOR, MINOR} and SBI_XEN_IMPID. --- Changes in v2: - s/vsbi-base-extension.*/base-extension.* - Introduce VCPU_SBI_IMPID, XEN_SBI_VER_MINOR and XEN_SBI_VER_MAJOR. - Return VCPU_SBI_IMPID in the case of SBI_EXT_BASE_GET_IMP_ID. - Return Xen version in the case of SBI_EXT_BASE_GET_IMP_VERSION. - Use domain_crash() instead of panic() for default case. - For SBI_EXT_BASE_GET_{MVENDORID,MARCHID,MIMPID} abd SBI_EXT_BASE_PROBE_EXT add handling of a domain is h/w or not. --- xen/arch/riscv/include/asm/sbi.h | 10 ++++ xen/arch/riscv/vsbi/Makefile | 1 + xen/arch/riscv/vsbi/base-extension.c | 78 ++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+) create mode 100644 xen/arch/riscv/vsbi/base-extension.c diff --git a/xen/arch/riscv/include/asm/sbi.h b/xen/arch/riscv/include/asm/sbi.h index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/riscv/include/asm/sbi.h +++ b/xen/arch/riscv/include/asm/sbi.h @@ -XXX,XX +XXX,XX @@ #include <xen/cpumask.h> +/* Xen-controlled SBI version reported to guests */ +#define XEN_SBI_VER_MAJOR 0 +#define XEN_SBI_VER_MINOR 2 + +/* SBI-defined implementation ID */ +#define SBI_XEN_IMPID 7 + #define SBI_EXT_0_1_SET_TIMER 0x0 #define SBI_EXT_0_1_CONSOLE_PUTCHAR 0x1 #define SBI_EXT_0_1_CONSOLE_GETCHAR 0x2 @@ -XXX,XX +XXX,XX @@ #define SBI_EXT_BASE_GET_IMP_ID 0x1 #define SBI_EXT_BASE_GET_IMP_VERSION 0x2 #define SBI_EXT_BASE_PROBE_EXT 0x3 +#define SBI_EXT_BASE_GET_MVENDORID 0x4 +#define SBI_EXT_BASE_GET_MARCHID 0x5 +#define SBI_EXT_BASE_GET_MIMPID 0x6 /* SBI function IDs for RFENCE extension */ #define SBI_EXT_RFENCE_REMOTE_FENCE_I 0x0 diff --git a/xen/arch/riscv/vsbi/Makefile b/xen/arch/riscv/vsbi/Makefile index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/riscv/vsbi/Makefile +++ b/xen/arch/riscv/vsbi/Makefile @@ -XXX,XX +XXX,XX @@ +obj-y += base-extension.o obj-y += core.o obj-y += legacy-extension.o diff --git a/xen/arch/riscv/vsbi/base-extension.c b/xen/arch/riscv/vsbi/base-extension.c new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/xen/arch/riscv/vsbi/base-extension.c @@ -XXX,XX +XXX,XX @@ + +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <xen/lib.h> +#include <xen/sched.h> +#include <xen/version.h> + +#include <asm/processor.h> +#include <asm/sbi.h> +#include <asm/vsbi.h> + +static int vsbi_base_ecall_handler(unsigned long eid, unsigned long fid, + struct cpu_user_regs *regs) +{ + int ret = 0; + struct sbiret sbi_ret; + + ASSERT(eid == SBI_EXT_BASE); + + switch ( fid ) + { + case SBI_EXT_BASE_GET_SPEC_VERSION: + regs->a1 = MASK_INSR(XEN_SBI_VER_MAJOR, SBI_SPEC_VERSION_MAJOR_MASK) | + XEN_SBI_VER_MINOR; + break; + + case SBI_EXT_BASE_GET_IMP_ID: + regs->a1 = SBI_XEN_IMPID; + break; + + case SBI_EXT_BASE_GET_IMP_VERSION: + regs->a1 = (xen_major_version() << 16) | xen_minor_version(); + break; + + case SBI_EXT_BASE_GET_MVENDORID: + case SBI_EXT_BASE_GET_MARCHID: + case SBI_EXT_BASE_GET_MIMPID: + if ( is_hardware_domain(current->domain) ) + { + sbi_ret = sbi_ecall(SBI_EXT_BASE, fid, 0, 0, 0, 0, 0, 0); + ret = sbi_ret.error; + regs->a1 = sbi_ret.value; + } + else + /* + * vSBI should present a consistent, virtualized view to guests. + * In particular, DomU-visible data must remain stable across + * migration and must not expose hardware-specific details. + * + * These register(s) must be readable in any implementation, + * but a value of 0 can be returned to indicate the field + * is not implemented. + */ + regs->a1 = 0; + + break; + + case SBI_EXT_BASE_PROBE_EXT: + regs->a1 = vsbi_find_extension(regs->a0) ? 1 : 0; + break; + + default: + /* + * TODO: domain_crash() is acceptable here while things are still under + * development. + * It shouldn't stay like this in the end though: guests should not + * be punished like this for something Xen hasn't implemented. + */ + domain_crash(current->domain, + "%s: Unsupported ecall: FID: #%lx, EID: #%lx\n", + __func__, fid, eid); + break; + } + + return ret; +} + +VSBI_EXT(base, SBI_EXT_BASE, SBI_EXT_BASE, vsbi_base_ecall_handler) -- 2.52.0
Introduce the vSBI framework to handle extension ecall instruction calls from a guest. In this patch series, support is added for only a few extensions and FIDs, just enough to boot the first guest domains and obtain logs from them. This keeps the patch series independent from other ongoing work. It was decided to start with support for the Legacy Extension, as it is still supported by Linux (so we may need it anyway), and because some of its FIDs require less functionality to implement at this stage compared to the more modern extensions. CI tests: https://gitlab.com/xen-project/people/olkur/xen/-/pipelines/2238071752 --- Changes in v4: - First to patches were merged to staging. - Address comments for the last patch. --- Changes in v3: - Address a comments from v2. --- Changes in v2: - Address a comments from v1. --- Oleksii Kurochko (1): xen/riscv: add RISC-V virtual SBI base extension support for guests xen/arch/riscv/include/asm/sbi.h | 6 ++ xen/arch/riscv/vsbi/Makefile | 1 + xen/arch/riscv/vsbi/base-extension.c | 82 ++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+) create mode 100644 xen/arch/riscv/vsbi/base-extension.c -- 2.52.0
Add support of virtual SBI base extension calls for RISC-V guests, delegating hardware-specific queries to the underlying SBI and handling version and firmware ID queries directly. The changes include: 1. Define new SBI base extension function IDs (SBI_EXT_BASE_GET_MVENDORID, SBI_EXT_BASE_GET_MARCHID, SBI_EXT_BASE_GET_MIMPID). 2. Introduce XEN_SBI_VER_MAJOR, XEN_SBI_VER_MINOR for imeplenataion of SBI_EXT_BASE_GET_SPEC_VERSION. 4. Introduce SBI_XEN_IMPID to implement SBI_EXT_BASE_GET_IMP_ID. 5. Implement handling of SBI base extension functions, including version, firmware ID, and machine-specific queries. Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com> --- Changes in v4: - Move definition of XEN_SBI_VER_{MAJOR, MINOR} to base-extension.c. - Correct string format for FID: s/#%#lx/#%lu. - Print first EID then FID (as vsbi/core.c code does). --- Changes in v3: - s/XEN_SBI_IMPID/SBI_XEN_IMPID - Add ASSERT(eid == SBI_EXT_BASE) in vsbi_base_ecall_handler(). - Fix code style for switch/case. - Use current instead of `vcpu` argument as it was dropped from vsbi_base_ecall_handler() prototype. - Add comments for define-s XEN_SBI_VER_{MAJOR, MINOR} and SBI_XEN_IMPID. --- Changes in v2: - s/vsbi-base-extension.*/base-extension.* - Introduce VCPU_SBI_IMPID, XEN_SBI_VER_MINOR and XEN_SBI_VER_MAJOR. - Return VCPU_SBI_IMPID in the case of SBI_EXT_BASE_GET_IMP_ID. - Return Xen version in the case of SBI_EXT_BASE_GET_IMP_VERSION. - Use domain_crash() instead of panic() for default case. - For SBI_EXT_BASE_GET_{MVENDORID,MARCHID,MIMPID} abd SBI_EXT_BASE_PROBE_EXT add handling of a domain is h/w or not. --- xen/arch/riscv/include/asm/sbi.h | 6 ++ xen/arch/riscv/vsbi/Makefile | 1 + xen/arch/riscv/vsbi/base-extension.c | 82 ++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+) create mode 100644 xen/arch/riscv/vsbi/base-extension.c diff --git a/xen/arch/riscv/include/asm/sbi.h b/xen/arch/riscv/include/asm/sbi.h index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/riscv/include/asm/sbi.h +++ b/xen/arch/riscv/include/asm/sbi.h @@ -XXX,XX +XXX,XX @@ #include <xen/cpumask.h> +/* SBI-defined implementation ID */ +#define SBI_XEN_IMPID 7 + #define SBI_EXT_0_1_SET_TIMER 0x0 #define SBI_EXT_0_1_CONSOLE_PUTCHAR 0x1 #define SBI_EXT_0_1_CONSOLE_GETCHAR 0x2 @@ -XXX,XX +XXX,XX @@ #define SBI_EXT_BASE_GET_IMP_ID 0x1 #define SBI_EXT_BASE_GET_IMP_VERSION 0x2 #define SBI_EXT_BASE_PROBE_EXT 0x3 +#define SBI_EXT_BASE_GET_MVENDORID 0x4 +#define SBI_EXT_BASE_GET_MARCHID 0x5 +#define SBI_EXT_BASE_GET_MIMPID 0x6 /* SBI function IDs for RFENCE extension */ #define SBI_EXT_RFENCE_REMOTE_FENCE_I 0x0 diff --git a/xen/arch/riscv/vsbi/Makefile b/xen/arch/riscv/vsbi/Makefile index XXXXXXX..XXXXXXX 100644 --- a/xen/arch/riscv/vsbi/Makefile +++ b/xen/arch/riscv/vsbi/Makefile @@ -XXX,XX +XXX,XX @@ +obj-y += base-extension.o obj-y += core.o obj-y += legacy-extension.o diff --git a/xen/arch/riscv/vsbi/base-extension.c b/xen/arch/riscv/vsbi/base-extension.c new file mode 100644 index XXXXXXX..XXXXXXX --- /dev/null +++ b/xen/arch/riscv/vsbi/base-extension.c @@ -XXX,XX +XXX,XX @@ + +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <xen/lib.h> +#include <xen/sched.h> +#include <xen/version.h> + +#include <asm/processor.h> +#include <asm/sbi.h> +#include <asm/vsbi.h> + +/* Xen-controlled SBI version reported to guests */ +#define XEN_SBI_VER_MAJOR 0 +#define XEN_SBI_VER_MINOR 2 + +static int vsbi_base_ecall_handler(unsigned long eid, unsigned long fid, + struct cpu_user_regs *regs) +{ + int ret = 0; + struct sbiret sbi_ret; + + ASSERT(eid == SBI_EXT_BASE); + + switch ( fid ) + { + case SBI_EXT_BASE_GET_SPEC_VERSION: + regs->a1 = MASK_INSR(XEN_SBI_VER_MAJOR, SBI_SPEC_VERSION_MAJOR_MASK) | + XEN_SBI_VER_MINOR; + break; + + case SBI_EXT_BASE_GET_IMP_ID: + regs->a1 = SBI_XEN_IMPID; + break; + + case SBI_EXT_BASE_GET_IMP_VERSION: + regs->a1 = (xen_major_version() << 16) | xen_minor_version(); + break; + + case SBI_EXT_BASE_GET_MVENDORID: + case SBI_EXT_BASE_GET_MARCHID: + case SBI_EXT_BASE_GET_MIMPID: + if ( is_hardware_domain(current->domain) ) + { + sbi_ret = sbi_ecall(SBI_EXT_BASE, fid, 0, 0, 0, 0, 0, 0); + ret = sbi_ret.error; + regs->a1 = sbi_ret.value; + } + else + /* + * vSBI should present a consistent, virtualized view to guests. + * In particular, DomU-visible data must remain stable across + * migration and must not expose hardware-specific details. + * + * These register(s) must be readable in any implementation, + * but a value of 0 can be returned to indicate the field + * is not implemented. + */ + regs->a1 = 0; + + break; + + case SBI_EXT_BASE_PROBE_EXT: + regs->a1 = vsbi_find_extension(regs->a0) ? 1 : 0; + break; + + default: + /* + * TODO: domain_crash() is acceptable here while things are still under + * development. + * It shouldn't stay like this in the end though: guests should not + * be punished like this for something Xen hasn't implemented. + */ + domain_crash(current->domain, + "%s: Unsupported ecall: EID: #%#lx FID: #%lu\n", + __func__, eid, fid); + break; + } + + return ret; +} + +VSBI_EXT(base, SBI_EXT_BASE, SBI_EXT_BASE, vsbi_base_ecall_handler) -- 2.52.0