github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/ring0/kernel_arm64.go (about)

     1  // Copyright 2019 The gVisor Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // +build arm64
    16  
    17  package ring0
    18  
    19  // HaltAndResume halts execution and point the pointer to the resume function.
    20  //go:nosplit
    21  func HaltAndResume()
    22  
    23  // HaltEl1SvcAndResume calls Hooks.KernelSyscall and resume.
    24  //go:nosplit
    25  func HaltEl1SvcAndResume()
    26  
    27  // HaltEl1ExceptionAndResume calls Hooks.KernelException and resume.
    28  //go:nosplit
    29  func HaltEl1ExceptionAndResume()
    30  
    31  // init initializes architecture-specific state.
    32  func (k *Kernel) init(maxCPUs int) {
    33  }
    34  
    35  // init initializes architecture-specific state.
    36  func (c *CPU) init(cpuID int) {
    37  	// Set the kernel stack pointer(virtual address).
    38  	c.registers.Sp = uint64(c.StackTop())
    39  
    40  }
    41  
    42  // StackTop returns the kernel's stack address.
    43  //
    44  //go:nosplit
    45  func (c *CPU) StackTop() uint64 {
    46  	return uint64(kernelAddr(&c.stack[0])) + uint64(len(c.stack))
    47  }
    48  
    49  // IsCanonical indicates whether addr is canonical per the arm64 spec.
    50  //
    51  //go:nosplit
    52  func IsCanonical(addr uint64) bool {
    53  	return addr <= 0x0000ffffffffffff || addr > 0xffff000000000000
    54  }
    55  
    56  // SwitchToUser performs an eret.
    57  //
    58  // The return value is the exception vector.
    59  //
    60  // +checkescape:all
    61  //
    62  //go:nosplit
    63  func (c *CPU) SwitchToUser(switchOpts SwitchOpts) (vector Vector) {
    64  	storeAppASID(uintptr(switchOpts.UserASID))
    65  	storeEl0Fpstate(switchOpts.FloatingPointState.BytePointer())
    66  
    67  	if switchOpts.Flush {
    68  		LocalFlushTlbByASID(uintptr(switchOpts.UserASID))
    69  	}
    70  
    71  	regs := switchOpts.Registers
    72  
    73  	regs.Pstate &= ^uint64(PsrFlagsClear)
    74  	regs.Pstate |= UserFlagsSet
    75  
    76  	fpDisableTrap := CPACREL1()
    77  	if fpDisableTrap != 0 {
    78  		FPSIMDEnableTrap()
    79  	}
    80  
    81  	kernelExitToEl0()
    82  
    83  	fpDisableTrap = CPACREL1()
    84  	if fpDisableTrap != 0 {
    85  		SaveFloatingPoint(switchOpts.FloatingPointState.BytePointer())
    86  	}
    87  
    88  	vector = c.vecCode
    89  
    90  	return
    91  }
    92  
    93  // RestoreKernelFPState restores the Sentry floating point state.
    94  //
    95  //go:nosplit
    96  func RestoreKernelFPState() {
    97  }