[PATCH v1 1/3] xen/riscv: introduce struct arch_vcpu

Oleksii Kurochko posted 3 patches 6 days, 14 hours ago
[PATCH v1 1/3] xen/riscv: introduce struct arch_vcpu
Posted by Oleksii Kurochko 6 days, 14 hours ago
Introdce struct arch_vcpu to hold RISC-V vCPU-specific state.

The structure contains:
  - Guest-visible CSR state, used to save and restore vCPU execution
    state across context switches. hstatus isn't added here as it is
    already part of cpu_user_regs struct.
  - Callee-saved registers 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
After the first execution of __context_switch(), RA naturally points to
the instruction following the call site, and the remaining callee-saved
registers contain the Xen register state at the time of the switch.

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
Changes in V3:
 - Drop gp from struct {...} xen_saved_context as it ought to be stable accross
   Xen so there is no need to be saved/restored and, also, it shouldn't be
   preserved across calls according to RISC-V ABI.
 - Update the comment above struct {...} xen_saved_context to make it more
   clear.
 - Drop CSRs and VCSRS comments in arch_vcpu as it is clear what kind of CSR
   it is based on the name.
 - Drop __cacheline_aligned for struct arch_vcpu as proper measurements can't
   be made now so it is hard to prove that the attribute really boost
   performance.
---
Changes in v2:
 - Drop hstatus from struct arch_vcpu as it is stored in struct cpu_user_regs
   which will be stored on top of vCPU's stack.
 - Drop the comment above ra in xen_saved_context struct as it is potentially
   misleading.
---
 xen/arch/riscv/include/asm/domain.h | 49 +++++++++++++++++++++++++++++
 1 file changed, 49 insertions(+)

diff --git a/xen/arch/riscv/include/asm/domain.h b/xen/arch/riscv/include/asm/domain.h
index 316e7c6c8448..cca39effc1ba 100644
--- a/xen/arch/riscv/include/asm/domain.h
+++ b/xen/arch/riscv/include/asm/domain.h
@@ -24,6 +24,55 @@ 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;
+
+    register_t hedeleg;
+    register_t hideleg;
+    register_t hvip;
+    register_t hip;
+    register_t hie;
+    register_t hgeie;
+    register_t henvcfg;
+    register_t hcounteren;
+    register_t htimedelta;
+    register_t htval;
+    register_t htinst;
+    register_t hstateen0;
+#ifdef CONFIG_RISCV_32
+    register_t henvcfgh;
+    register_t htimedeltah;
+#endif
+
+    register_t vsstatus;
+    register_t vsip;
+    register_t vsie;
+    register_t vstvec;
+    register_t vsscratch;
+    register_t vscause;
+    register_t vstval;
+    register_t vsatp;
+    register_t vsepc;
 };
 
 struct paging_domain {
-- 
2.52.0


Re: [PATCH v1 1/3] xen/riscv: introduce struct arch_vcpu
Posted by Jan Beulich 6 days, 13 hours ago
On 02.02.2026 13:57, Oleksii Kurochko wrote:
> --- a/xen/arch/riscv/include/asm/domain.h
> +++ b/xen/arch/riscv/include/asm/domain.h
> @@ -24,6 +24,55 @@ struct arch_vcpu_io {
>  
>  struct arch_vcpu {
>      struct vcpu_vmid vmid;

Nit: This being already here contradicts the title saying "introduce".

> +
> +    /*
> +     * 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;
> +
> +    register_t hedeleg;
> +    register_t hideleg;
> +    register_t hvip;
> +    register_t hip;
> +    register_t hie;
> +    register_t hgeie;
> +    register_t henvcfg;
> +    register_t hcounteren;
> +    register_t htimedelta;
> +    register_t htval;
> +    register_t htinst;
> +    register_t hstateen0;
> +#ifdef CONFIG_RISCV_32
> +    register_t henvcfgh;
> +    register_t htimedeltah;
> +#endif

When you add these right away, any reason other high-half registers aren't added
as well? HVIP (above) and VSIE / VSIP at the very least have such counterparts,
iirc.

> +    register_t vsstatus;
> +    register_t vsip;
> +    register_t vsie;
> +    register_t vstvec;
> +    register_t vsscratch;
> +    register_t vscause;
> +    register_t vstval;
> +    register_t vsatp;
> +    register_t vsepc;
>  };

What I'm generally concerned of: With the registers all being put here in one go,
without any of them actually being used in this patch, it'll likely be harder to
track that they're saved / restored / initialized correctly (once uses appear).

Jan
Re: [PATCH v1 1/3] xen/riscv: introduce struct arch_vcpu
Posted by Oleksii Kurochko 5 days, 18 hours ago
On 2/2/26 3:08 PM, Jan Beulich wrote:
> On 02.02.2026 13:57, Oleksii Kurochko wrote:
>> --- a/xen/arch/riscv/include/asm/domain.h
>> +++ b/xen/arch/riscv/include/asm/domain.h
>> @@ -24,6 +24,55 @@ struct arch_vcpu_io {
>>   
>>   struct arch_vcpu {
>>       struct vcpu_vmid vmid;
> Nit: This being already here contradicts the title saying "introduce".

I'll update then the commit message.

>
>> +
>> +    /*
>> +     * 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;
>> +
>> +    register_t hedeleg;
>> +    register_t hideleg;
>> +    register_t hvip;
>> +    register_t hip;
>> +    register_t hie;
>> +    register_t hgeie;
>> +    register_t henvcfg;
>> +    register_t hcounteren;
>> +    register_t htimedelta;
>> +    register_t htval;
>> +    register_t htinst;
>> +    register_t hstateen0;
>> +#ifdef CONFIG_RISCV_32
>> +    register_t henvcfgh;
>> +    register_t htimedeltah;
>> +#endif
> When you add these right away, any reason other high-half registers aren't added
> as well? HVIP (above) and VSIE / VSIP at the very least have such counterparts,
> iirc.

No specific reason. It was added early in the RISC-V port when I was considering
supporting RV32, but as you know I later decided to focus only on RV64, at least
for now. Therefore, it seems better to drop this `#ifdef` from the `arch_vcpu`
structure and re-introduce when RV32 support will be added.

>
>> +    register_t vsstatus;
>> +    register_t vsip;
>> +    register_t vsie;
>> +    register_t vstvec;
>> +    register_t vsscratch;
>> +    register_t vscause;
>> +    register_t vstval;
>> +    register_t vsatp;
>> +    register_t vsepc;
>>   };
> What I'm generally concerned of: With the registers all being put here in one go,
> without any of them actually being used in this patch, it'll likely be harder to
> track that they're saved / restored / initialized correctly (once uses appear).

Then if it will really better I'll introduce in this patch series only vsatp register
as it is used in the further patches. (or even will just introduce vsatp in Patch 3)

I will keep the patch [1] separately in the patch series with introduction of vtimer
things and drop only an introduction of vsatp there.

[1] https://lore.kernel.org/xen-devel/cover.1769099883.git.oleksii.kurochko@gmail.com/T/#ma33af3ff4b2b033f86aa964902ebcab8705fd114

~ Oleksii