Port-sparc64 archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: sun4v trap table
On Fri, 10 Oct 2025, Sad Clouds wrote:
> On Thu, 9 Oct 2025 18:53:48 +0000 (UTC)
> Eduardo Horvath <eeh%NetBSD.org@localhost> wrote:
>
> >
> > Don't look at the Solaris, Illuminos, or Linux kernels. They use a
> > completely different trap and address space model from NetBSD.
> >
> Maybe ddb (which itself relies on traps) cannot stop at breakpoints in
> trap handlers?
You can't use DDB on trap code. That's what TRAPTRACE is for.
>
> > 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.
> >
>
> I'm confused about how the transition between Trap Levels (TLs)
> happens. Hardware documentation gives this table for sun4v TLs usage:
>
> TL Exec Mode Usage
> ---------------------------------------------------------------------------
> 0 Nonprivileged Normal execution
> 1 Privileged System calls; interrupt handlers; instruction emulation
> 2 Privileged Window spill/fill handler
> 3 Hyperprivileged Real address TLB miss handler
> 4 Hyperprivileged Reserved for error handling
> 5 Hyperprivileged RED_state handler
Ignore that. Those are just guidelines.
Trap levels are determined by the %tl register, Whenever a trap is taken
it is inremented. Trap returns decrement it.
I beleive the hypervisor trap levels are entered through a hypercall. But
once again, ignore all that. Unlike x86 or ARM, consider all of the
hypervisor operation as just part of the H/W.
> So let's assume a user process makes a function call which results in a
> window spill trap. The user process is running at TL=0, but the
> documentation states that TLs are incremented sequentially, so how does
> it get to TL=2 as stated in the table above? It would be running at TL=1.
That is misleading. Window trap handlers run at TL=1 unless they occur
during trap processing when the CPU is already at TL=1.
>
> When I look at NetBSD sun4u spill trap handlers, these are virtually
> the same for TL=0 and TL>0. I assume the "supervisor mode" is a synonym
> for the "nucleus mode".
Nucleus mode always uses TLB context 0.
>
> /* Traps from TL=0 -- traps from user mode */
> TABLE(uspill):
> SPILL64(uspill8,ASI_AIUS) ! 0x080 spill_0_normal -- used to save user windows in user mode
> SPILL32(uspill4,ASI_AIUS) ! 0x084 spill_1_normal
> SPILLBOTH(uspill8,uspill4,ASI_AIUS) ! 0x088 spill_2_normal
> UTRAP(0x08c); TA32 ! 0x08c spill_3_normal
> TABLE(kspill):
> SPILL64(kspill8,ASI_N) ! 0x090 spill_4_normal -- used to save supervisor windows
> SPILL32(kspill4,ASI_N) ! 0x094 spill_5_normal
> SPILLBOTH(kspill8,kspill4,ASI_N) ! 0x098 spill_6_normal
> UTRAP(0x09c); TA32 ! 0x09c spill_7_normal
> TABLE(uspillk):
> SPILL64(uspillk8,ASI_AIUS) ! 0x0a0 spill_0_other -- used to save user windows in supervisor mode
> SPILL32(uspillk4,ASI_AIUS) ! 0x0a4 spill_1_other
> SPILLBOTH(uspillk8,uspillk4,ASI_AIUS) ! 0x0a8 spill_2_other
> ...
> /* Traps from TL>0 -- traps from supervisor mode */
> TABLE(uspill):
> SPILL64(1,ASI_AIUS) ! 0x080 spill_0_normal -- used to save user windows
> SPILL32(2,ASI_AIUS) ! 0x084 spill_1_normal
> SPILLBOTH(1b,2b,ASI_AIUS) ! 0x088 spill_2_normal
> UTRAP(0x08c); TA32 ! 0x08c spill_3_normal
> TABLE(kspill):
> SPILL64(1,ASI_N) ! 0x090 spill_4_normal -- used to save supervisor windows
> SPILL32(2,ASI_N) ! 0x094 spill_5_normal
> SPILLBOTH(1b,2b,ASI_N) ! 0x098 spill_6_normal
> UTRAP(0x09c); TA32 ! 0x09c spill_7_normal
> TABLE(uspillk):
> SPILL64(1,ASI_AIUS) ! 0x0a0 spill_0_other -- used to save user windows in nucleus mode
> SPILL32(2,ASI_AIUS) ! 0x0a4 spill_1_other
> SPILLBOTH(1b,2b,ASI_AIUS) ! 0x0a8 spill_2_other
> ...
>
> So how do they differ between various TLs?
>
> When TL=0:
> uspill: spill windows when in user address space?
>
> kspill: spill windows when in kernel address space?
>
> uspillk: spill windows for user space process when in kernel space?
> When would this happen? User process making a syscall which
> then results in that syscall running in kernel address space
> but needing to spill windows for user process?
>
> When TL>1:
> These are the same, so when would these traps occur? Are these nested
> traps, e.g. a user process causes a trap (syscall, pagefault, etc)
> which then causes another trap related to window spill?
The comments there originally came from the v9 manual and are probably a
bit misleading.
What this comes down to are two things:
Is the stack frame 32-bit or 64-bit or do you need to figure that out in
the trap handler from the stack pointer?
Does the stack frame need to be saved to the user address space or kernel
address space?
The fist is determined by the macro, the second by the ASI.
In SPARC v7 there was only one trap level and you are not allowed to take
a trap in a trap handler or you get a watchdog reset. So window trap
handlers had to make sure the destination was mapped in the MMU before
accessing stack frame memory.
In v8 you can take a trap while handling a trap so you don't need to check
MMU mappings before spilling a window, You just take a TL>0 MMU trap.
TL=0 traps happen during normal execution. TL>0 traps happenwhile already
taking a trap, say a window spill causes a MMU miss, They are usually
triggerd by a savewin instruction in a trap hander that needs to enter the
kernel and do something.
Solaris will typically be executing user code, take a window spill trap,
then take a MMU miss trap, return to the MMU miss trap, then return to
userland.
NetBSD will take a window trap, then a MMU miss trap, clean up the whole
mess and directly return to userland.
Eduardo
Home |
Main Index |
Thread Index |
Old Index