mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
xen/riscv: implement arch_vcpu_{create,destroy}()
Introduce architecture-specific functions to create and destroy VCPUs.
Note that arch_vcpu_create() currently returns -EOPNOTSUPP, as the virtual
timer and interrupt controller are not yet implemented.
Add callee-saved registers to struct arch_vcpu which are used to preserve
Xen’s own execution context when switching between vCPU stacks.
It is going to be used in the following way (pseudocode):
context_switch(prev_vcpu, next_vcpu):
...
/* Switch from previous stack to the next stack. */
__context_switch(prev_vcpu, next_vcpu);
...
schedule_tail(prev_vcpu):
Save and restore vCPU's CSRs.
The Xen-saved context allows __context_switch() to switch execution
from the previous vCPU’s stack to the next vCPU’s stack and later resume
execution on the original stack when switching back.
During vCPU creation, the Xen-saved context is going to be initialized
with:
- SP pointing to the newly allocated vCPU stack.
- RA pointing to a helper that performs final vCPU setup before
transferring control to the guest.
As part of this change, add continue_new_vcpu(), which will be used after
the first context_switch() of a new vCPU. Since this functionality is not
yet implemented, continue_new_vcpu() is currently provided as a stub.
The prev argument is going to be set by RISC-V ABI (prev will be stored in
a0) when __context_swtich() will be introduced and called from
context_switch().
Update the STACK_SIZE definition.
Introduce struct cpu_info to store per-vCPU state that lives at the top
of the vCPU's stack.
Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
This commit is contained in:
1 parent
ebf99a1627
commit
ad535118f0
6 files changed
+90
-11
No files matched your search
@@ -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
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#include <xen/init.h>
|
||||
#include <xen/mm.h>
|
||||
#include <xen/sched.h>
|
||||
#include <xen/vmap.h>
|
||||
|
||||
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));
|
||||
}
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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");
|
||||
|
||||