diff --git a/xen/arch/riscv/Makefile b/xen/arch/riscv/Makefile index 1eb9ab090b..caa1aac5b2 100644 --- a/xen/arch/riscv/Makefile +++ b/xen/arch/riscv/Makefile @@ -1,5 +1,6 @@ obj-y += aplic.o obj-y += cpufeature.o +obj-y += domain.o obj-$(CONFIG_EARLY_PRINTK) += early_printk.o obj-y += entry.o obj-y += imsic.o diff --git a/xen/arch/riscv/domain.c b/xen/arch/riscv/domain.c new file mode 100644 index 0000000000..b60320b90d --- /dev/null +++ b/xen/arch/riscv/domain.c @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include + +static void continue_new_vcpu(struct vcpu *prev) +{ + BUG_ON("unimplemented\n"); +} + +int arch_vcpu_create(struct vcpu *v) +{ + int rc; + void *stack = vzalloc(STACK_SIZE); + + if ( !stack ) + return -ENOMEM; + + v->arch.cpu_info = stack + STACK_SIZE - sizeof(*v->arch.cpu_info); + + v->arch.xen_saved_context.sp = (register_t)v->arch.cpu_info; + v->arch.xen_saved_context.ra = (register_t)continue_new_vcpu; + + /* Idle VCPUs don't need the rest of this setup */ + if ( is_idle_vcpu(v) ) + return 0; + + /* + * As the vtimer and interrupt controller (IC) are not yet implemented, + * return an error. + * + * TODO: Drop this once the vtimer and IC are implemented. + */ + rc = -EOPNOTSUPP; + goto fail; + + return rc; + + fail: + arch_vcpu_destroy(v); + return rc; +} + +void arch_vcpu_destroy(struct vcpu *v) +{ + vfree((void *)&v->arch.cpu_info[1] - STACK_SIZE); +} + +static void __init __maybe_unused build_assertions(void) +{ + /* + * Enforce the requirement documented in struct cpu_info that + * guest_cpu_user_regs must be the first field. + */ + BUILD_BUG_ON(offsetof(struct cpu_info, guest_cpu_user_regs)); +} diff --git a/xen/arch/riscv/include/asm/config.h b/xen/arch/riscv/include/asm/config.h index 1e08d3bf78..0613de008b 100644 --- a/xen/arch/riscv/include/asm/config.h +++ b/xen/arch/riscv/include/asm/config.h @@ -143,7 +143,7 @@ #define SMP_CACHE_BYTES (1 << 6) -#define STACK_SIZE PAGE_SIZE +#define STACK_SIZE (PAGE_SIZE << 3) #define IDENT_AREA_SIZE 64 diff --git a/xen/arch/riscv/include/asm/current.h b/xen/arch/riscv/include/asm/current.h index 0c3ea70c2e..58c9f1506b 100644 --- a/xen/arch/riscv/include/asm/current.h +++ b/xen/arch/riscv/include/asm/current.h @@ -21,6 +21,12 @@ struct pcpu_info { /* tp points to one of these */ extern struct pcpu_info pcpu_info[NR_CPUS]; +/* Per-VCPU state that lives at the top of the stack */ +struct cpu_info { + /* This should be the first member. */ + struct cpu_user_regs guest_cpu_user_regs; +}; + #define set_processor_id(id) do { \ tp->processor_id = (id); \ } while (0) diff --git a/xen/arch/riscv/include/asm/domain.h b/xen/arch/riscv/include/asm/domain.h index 316e7c6c84..f78f145258 100644 --- a/xen/arch/riscv/include/asm/domain.h +++ b/xen/arch/riscv/include/asm/domain.h @@ -24,6 +24,30 @@ struct arch_vcpu_io { struct arch_vcpu { struct vcpu_vmid vmid; + + /* + * Callee saved registers for Xen's state used to switch from + * prev's stack to the next's stack during context switch. + */ + struct + { + register_t s0; + register_t s1; + register_t s2; + register_t s3; + register_t s4; + register_t s5; + register_t s6; + register_t s7; + register_t s8; + register_t s9; + register_t s10; + register_t s11; + register_t sp; + register_t ra; + } xen_saved_context; + + struct cpu_info *cpu_info; }; struct paging_domain { diff --git a/xen/arch/riscv/stubs.c b/xen/arch/riscv/stubs.c index d071c8b86d..daadff0138 100644 --- a/xen/arch/riscv/stubs.c +++ b/xen/arch/riscv/stubs.c @@ -116,16 +116,6 @@ void dump_pageframe_info(struct domain *d) BUG_ON("unimplemented"); } -int arch_vcpu_create(struct vcpu *v) -{ - BUG_ON("unimplemented"); -} - -void arch_vcpu_destroy(struct vcpu *v) -{ - BUG_ON("unimplemented"); -} - int arch_sanitise_domain_config(struct xen_domctl_createdomain *config) { BUG_ON("unimplemented");