// SwitchToUser unpacks architectural-details.
SwitchToUser unpacks architectural-details.
// SwitchToUser unpacks architectural - details .
func (c *vCPU) SwitchToUser(switchOpts ring0.SwitchOpts, info *linux.SignalInfo) (hostarch.AccessType, error) {
	if regs := switchOpts.Registers; !ring0.IsCanonical(regs.Pc) {
		return nonCanonical(regs.Pc, int32(unix.SIGSEGV), info)
	} else if !ring0.IsCanonical(regs.Sp) {
		return nonCanonical(regs.Sp, int32(unix.SIGSEGV), info)
	}
	if c.PCIDs != nil {
		var requireFlushPCID bool 
		switchOpts.UserASID, requireFlushPCID = c.PCIDs.Assign(switchOpts.PageTables)
		switchOpts.Flush = switchOpts.Flush || requireFlushPCID
	}
	var vector ring0.Vector
	ttbr0App := switchOpts.PageTables.TTBR0_EL1(false, 0)
	c.SetTtbr0App(uintptr(ttbr0App))
	appRegs := switchOpts.Registers
	c.SetAppAddr(ring0.KernelStartAddress | uintptr(unsafe.Pointer(appRegs)))
	entersyscall()
	bluepill(c)
	vector = c.CPU.SwitchToUser(switchOpts)
	exitsyscall()
	switch vector {
	case ring0.Syscall:
		return hostarch.NoAccess, nil
	case ring0.PageFault:
		return c.fault(int32(unix.SIGSEGV), info)
	case ring0.El0ErrNMI:
		return c.fault(int32(unix.SIGBUS), info)
	case ring0.Vector(bounce): 
		return hostarch.NoAccess, platform.ErrContextInterrupt
	case ring0.El0SyncUndef:
		return c.fault(int32(unix.SIGILL), info)
	case ring0.El0SyncDbg:
		*info = linux.SignalInfo{
			Signo: int32(unix.SIGTRAP),
			Code:  1, 
		}
		info.SetAddr(switchOpts.Registers.Pc) 
		return hostarch.AccessType{}, platform.ErrContextSignal
	case ring0.El0SyncSpPc:
		*info = linux.SignalInfo{
			Signo: int32(unix.SIGBUS),
			Code:  2, 
		}
		return hostarch.NoAccess, platform.ErrContextSignal
	case ring0.El0SyncSys,
		ring0.El0SyncWfx:
		return hostarch.NoAccess, nil 
	default:
		panic(fmt.Sprintf("unexpected vector: 0x%x", vector))
	}
}
func ( c * vCPU ) SwitchToUser ( switchOpts ring0 . SwitchOpts , info * linux . SignalInfo ) ( hostarch . AccessType , error ) { if regs := switchOpts . Registers ; ! ring0 . IsCanonical ( regs . Pc ) { return nonCanonical ( regs . Pc , int32 ( unix . SIGSEGV ) , info ) } else if ! ring0 . IsCanonical ( regs . Sp ) { return nonCanonical ( regs . Sp , int32 ( unix . SIGSEGV ) , info ) } if c . PCIDs != nil { var requireFlushPCID bool switchOpts . UserASID , requireFlushPCID = c . PCIDs . Assign ( switchOpts . PageTables ) switchOpts . Flush = switchOpts . Flush || requireFlushPCID } var vector ring0 . Vector ttbr0App := switchOpts . PageTables . TTBR0_EL1 ( false , 0 ) c . SetTtbr0App ( uintptr ( ttbr0App ) ) appRegs := switchOpts . Registers c . SetAppAddr ( ring0 . KernelStartAddress | uintptr ( unsafe . Pointer ( appRegs ) ) ) entersyscall ( ) bluepill ( c ) vector = c . CPU . SwitchToUser ( switchOpts ) exitsyscall ( ) switch vector { case ring0 . Syscall : return hostarch . NoAccess , nil case ring0 . PageFault : return c . fault ( int32 ( unix . SIGSEGV ) , info ) case ring0 . El0ErrNMI : return c . fault ( int32 ( unix . SIGBUS ) , info ) case ring0 . Vector ( bounce ) : return hostarch . NoAccess , platform . ErrContextInterrupt case ring0 . El0SyncUndef : return c . fault ( int32 ( unix . SIGILL ) , info ) case ring0 . El0SyncDbg : * info = linux . SignalInfo { Signo : int32 ( unix . SIGTRAP ) , Code : 1 , } info . SetAddr ( switchOpts . Registers . Pc ) return hostarch . AccessType { } , platform . ErrContextSignal case ring0 . El0SyncSpPc : * info = linux . SignalInfo { Signo : int32 ( unix . SIGBUS ) , Code : 2 , } return hostarch . NoAccess , platform . ErrContextSignal case ring0 . El0SyncSys , ring0 . El0SyncWfx : return hostarch . NoAccess , nil default : panic ( fmt . Sprintf ( " " , vector ) ) } }
SwitchToUser unpacks architectural-details.
SwitchToUser unpacks architectural - details .
// Check for canonical addresses. // Assign PCIDs. // Force a flush? // Full context-switch supporting for Arm64. // The Arm64 user-mode execution state consists of: // x0-x30 // PC, SP, PSTATE // V0-V31: 32 128-bit registers for floating point, and simd // FPSR, FPCR // TPIDR_EL0, used for TLS // Fast path: system call executed. // ring0.VirtualizationException. // TRAP_BRKPT (breakpoint). // Include address. // BUS_ADRERR (physical address does not exist). // skip for now.