[PATCH v2 6/9] lib: sbi_domain_context: add slwid to per-domain S-mode context

Yu-Chien Peter Lin peter.lin at sifive.com
Fri Oct 23 01:10:25 PDT 2026


Hi Radim,

On Fri, Oct 16, 2026 at 05:08:14PM +0000, Radim Krcmar wrote:
> 2026-08-17T17:05:00+08:00, Yu-Chien Peter Lin <peter.lin at sifive.com>:
> > slwid is the S-mode CSR that controls U-mode's World ID. Since
> > each domain may run different U-mode workloads with different
> > WID isolation requirements, slwid must be part of the per-domain
> > S-mode context.
> >
> > Signed-off-by: Yu-Chien Peter Lin <peter.lin at sifive.com>
> > ---
> > diff --git a/lib/sbi/sbi_domain_context.c b/lib/sbi/sbi_domain_context.c
> > @@ -145,6 +147,17 @@ 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_SSWID)) {
> > +		/*
> > +		 * Temporarily enable Sswid so slwid is accessible for
> > +		 * swap. The target domain's mwiddeleg is restored by
> > +		 * sbi_hart_protection_reconfigure() below.
> > +		 */
> > +		csr_write(CSR_MWIDDELEG, ~0UL);
> > +		if (csr_read(CSR_MWIDDELEG))
> 
> The slow verification isn't necessary on each switch -- either check the
> hart capabilities during initialization and mask widdeleg from DT, or
> just trust the DT.
> We know what we've written to mwiddeleg for the current domain, so we
> could just read it from context.
> 
> > +			ctx->slwid = csr_swap(CSR_SLWID, dom_ctx->slwid);
> > +		csr_write(CSR_MWIDDELEG, 0);
> 
> Setting mwiddeleg to 0 is dangerous, because the specification isn't
> clear whether zeroing mwiddleg and hence disabling Sslwid preserves
> slwid CSR.  In any case, there is no reason to write 0 here, because we
> can be writing the correct mwiddeleg.
> 
> To optimize a bit, I think we only need 2 CSR accesses to handle
> delegation:
> 
>   if (ctx->mwiddeleg) {
>     ctx->slwid = csr_swap(CSR_SLWID, dom_ctx->slwid);
>     csr_write(CSR_MWIDDELEG, dom_ctx->mwiddeleg);
>   } else if (dom_ctx->mwiddeleg) {
>     csr_write(CSR_MWIDDELEG, dom_ctx->mwiddeleg);
>     csr_write(CSR_SLWID, dom_ctx->slwid);
>   }
> 
> Feel free to keep mwiddeleg write in sbi_hart_protection_reconfigure,
> but then please consider moving the slwid logic there as well.
> The current split seems suboptimal.

You are right. The mwiddeleg=0 write indeed does not guarantee
that slwid is preserved while Sswid is disabled. So my sequence
was unsafe.

There is no perfectly clean implementation either way, so I would
like to optimize for matching the configure/reconfigure semantics
of sbi_hart_protection, which I think map well onto "build up" and
"tear down" the WID isolation of a domain, including enabling and
disabling the Sswid capability.

Concretely, I plan to:
- Remove slwid from struct hart_context and stop touching mwiddeleg in
  sbi_domain_context.c entirely. slwid is an S-mode CSR, but its accessibility
  is gated by the M-mode mwiddeleg CSR, so saving and restoring it requires
  the mwiddeleg life cycle managed by sbi_hart_worlds.c
- Cache slwid as per-domain, per-hart state in sbi_hart_worlds.c using
  sbi_domain_data.

The downside is that this split means mwiddeleg is written twice per
domain switch (zeroed in unconfigure(), then set in configure()),
rather than the one CSR access your version achieves. But this shouldn't
introduce noticeable performance impact.

I will soon post the PATCHv3, happy to discuss more there!

> 
> Thanks.



More information about the opensbi mailing list