[RFC PATCH v3 2/6] lib: sbi: Preserve Sstc timer state across domain switches

Samuel Holland samuel.holland at sifive.com
Thu Nov 5 06:47:11 PST 2026


(sorry for the duplicate mail -- I didn't see v3 because it was wasn't a
separate thread, since you sent it as a reply to v2)

On 2026-11-04 10:43 PM, Theodorus Wensan Februanto wrote:
> The Sstc extension provides a supervisor timer comparison register.
> Without preserving this value, another domain can replace the
> previous domain's timer deadline.
> 
> Keep a per-domain timer comparison value and initialize new domains
> to a future deadline to avoid immediate timer interrupts.
> 
> Link: https://github.com/riscv-software-src/opensbi/issues/433
> Signed-off-by: Theodorus Wensan Februanto <theodoruswensanfebruanto025 at gmail.com>
> ---
>  include/sbi/riscv_encoding.h |  2 ++
>  lib/sbi/sbi_domain_context.c | 15 +++++++++++++++
>  2 files changed, 17 insertions(+)
> 
> diff --git a/include/sbi/riscv_encoding.h b/include/sbi/riscv_encoding.h
> index ffe7666c..60a0c39e 100644
> --- a/include/sbi/riscv_encoding.h
> +++ b/include/sbi/riscv_encoding.h
> @@ -448,6 +448,8 @@
>  #define CSR_VSCAUSE			0x242
>  #define CSR_VSTVAL			0x243
>  #define CSR_VSIP			0x244
> +#define CSR_VSTIMECMP		0x24D
> +#define CSR_VSTIMECMPH		0x25D
>  #define CSR_VSATP			0x280
>  
>  /* Virtual Interrupts and Interrupt Priorities (H-extension with AIA) */
> diff --git a/lib/sbi/sbi_domain_context.c b/lib/sbi/sbi_domain_context.c
> index c34d4cbb..d2490483 100644
> --- a/lib/sbi/sbi_domain_context.c
> +++ b/lib/sbi/sbi_domain_context.c
> @@ -57,6 +57,11 @@ struct hart_context_hext {
>  	unsigned long vsatp;
>  };
>  
> +struct hart_context_sstc {
> +	u64 stimecmp;
> +	u64 vstimecmp;
> +};
> +
>  /** Context representation for a hart within a domain */
>  struct hart_context {
>  	/** Trap-related states such as GPRs, mepc, and mstatus */
> @@ -88,6 +93,7 @@ struct hart_context {
>  	unsigned long senvcfg;
>  	/** Supervisor resource management configuration register */
>  	unsigned long srmcfg;
> +	struct hart_context_sstc sstc;
>  
>  	/** Float context state */
>  	struct sbi_fp_context fp_ctx;
> @@ -259,6 +265,12 @@ static int switch_to_next_domain_context(struct hart_context *ctx,
>  		ctx->senvcfg	= csr_swap(CSR_SENVCFG, dom_ctx->senvcfg);
>  	if (sbi_hart_has_extension(scratch, SBI_HART_EXT_SSQOSID))
>  		ctx->srmcfg	= csr_swap(CSR_SRMCFG, dom_ctx->srmcfg);
> +	if (sbi_hart_has_extension(scratch, SBI_HART_EXT_SSTC)) {
> +		ctx->sstc.stimecmp = csr_swap64(CSR_STIMECMP, dom_ctx->sstc.stimecmp);
> +		if (misa_extension('H'))
> +			ctx->sstc.vstimecmp = csr_swap64(CSR_VSTIMECMP,
> +						 dom_ctx->sstc.vstimecmp);
> +	}

This is not sufficient if the timer interrupt should ever trigger a domain
switch. OpenSBI needs to register a timer event for at least the earlier of the
outgoing domain's stimecmp/vstimecmp+htimedelta so it knows when that domain's
timer interrupt should be pending.

Regards,
Samuel

>  
>  	/* Eager context switch for float */
>  	if (sbi_hart_has_extension(scratch, SBI_HART_EXT_F) ||
> @@ -320,6 +332,9 @@ static int hart_context_init(u32 hartindex)
>  		if (!ctx)
>  			return SBI_ENOMEM;
>  
> +		ctx->sstc.stimecmp = ~0ULL;
> +		ctx->sstc.vstimecmp = ~0ULL;
> +
>  		if (sbi_hart_has_extension(sbi_scratch_thishart_ptr(),
>  					   SBI_HART_EXT_V)) {
>  			vec_size = sbi_vector_context_size();




More information about the opensbi mailing list