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:
Oleksii Kurochko authored and Jan Beulich committed 2026-02-18 10:16:34 +01:00
1 parent ebf99a1627
commit ad535118f0
6 files changed
+90 -11

No files matched your search

+1
View File
@@ -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
+58
View File
@@ -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));
}
+1 -1
View File
@@ -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
+6
View File
@@ -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
View File
@@ -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 {
-10
View File
@@ -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");
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.