Port-sparc64 archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: sun4v trap table



Don't look at the Solaris, Illuminos, or Linux kernels.  They use a 
completely different trap and address space model from NetBSD.

User and kernel are not mapped into the same address space.

Trap levels above 0 are only used during trap dispatch.  The kernel runs 
at TL0.

The different window spill and fill handlers have to do with which address 
space a particular register window is mapped to.  The fill/spill normal 
use the currnt active context. The other ones use and ASI to always use 
the user TLB context.

When traping into the kernel, the CPU is set to kernel mode and the 
primary context set to 0 {nucleus), so the TLB uses kernel mappings, 
and %otherwin is set to the number of user stack frames.  For the spills, 
if %otherwin is not 0 it traps to the the handler that dumps the stack 
frame to the user address space, otherwise it goes to the active address 
space.

If there are traps during trap handling Solaris and Linux will try to 
return to the trap handler that faultes.  The NetBSD code will unwind the 
trap state completely.

Remember, sun4u can use all 4 trap levels.  sun4v can only use 2 because 
the other 2 are reserved for the hypervisor.  On sun4v the hypervisor and 
LDOMs are always active, whether configured or not.

Eduardo

On Mon, 6 Oct 2025, Sad Clouds wrote:

> On Mon, 06 Oct 2025 17:34:42 +1100
> matthew green <mrg%eterna23.net@localhost> wrote:
> 
> > include/psl.h:264:#define WSTATE_USER    022
> > include/psl.h:263:#define WSTATE_KERN    026
> > 
> > since they both seem to set OTHER bits, which means that 4:2 in the
> > trap type will always be 2?  so always uses SPILLBOTH()?  i think i
> > am still missing something here...
> 
> Looking at Illumos/Solaris: src/uts/sparc/v9/sys/privregs.h
> 
> /*
>  * Window State Register (WSTATE)
>  *
>  *   |------------|
>  *   |OTHER|NORMAL|
>  *   |-----|------|
>  *    5	  3 2    0
>  */
> #define	WSTATE_BAD	0	/* unused */
> #define	WSTATE_U32	1	/* 32b stack */
> #define	WSTATE_U64	2	/* 64b stack */
> #define	WSTATE_CLEAN32	3	/* cleanwin workaround, 32b stack */
> #define	WSTATE_CLEAN64	4	/* cleanwin workaround, 64b stack */
> #define	WSTATE_K32	5	/* priv 32b stack */
> #define	WSTATE_K64	6	/* priv 64b stack */
> #define	WSTATE_KMIX	7	/* priv mixed stack */
> 
> #define	WSTATE_CLEAN_OFFSET	2
> #define	WSTATE_SHIFT	3	/* normal-to-other shift */
> #define	WSTATE_MASK	7	/* mask for each set */
> #define	WSTATE(o, n)	(((o) << WSTATE_SHIFT) | (n))
> 
> #define	WSTATE_USER32	WSTATE(WSTATE_BAD, WSTATE_U32)
> #define	WSTATE_USER64	WSTATE(WSTATE_BAD, WSTATE_U64)
> #define	WSTATE_KERN	WSTATE(WSTATE_U32, WSTATE_K64)
> 
> 
> This results in WSTATE.OTHER=0 and WSTATE.NORMAL=0-7. Unlike NetBSD,
> only WSTATE_KERN results in WSTATE.OTHER>0.
> 
> WSTATE.NORMAL=0 is unused, so I guess they may use it like a NULL
> pointer to catch uninitialised WSTATE register?
> 


Home | Main Index | Thread Index | Old Index