gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/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  //go:build arm64
    16  // +build arm64
    17  
    18  package ring0
    19  
    20  // HaltAndResume halts execution and point the pointer to the resume function.
    21  //
    22  //go:nosplit
    23  func HaltAndResume()
    24  
    25  // HaltEl1SvcAndResume calls Hooks.KernelSyscall and resume.
    26  //
    27  //go:nosplit
    28  func HaltEl1SvcAndResume()
    29  
    30  // HaltEl1ExceptionAndResume calls Hooks.KernelException and resume.
    31  //
    32  //go:nosplit
    33  func HaltEl1ExceptionAndResume()
    34  
    35  // init initializes architecture-specific state.
    36  func (k *Kernel) init(maxCPUs int) {
    37  }
    38  
    39  // init initializes architecture-specific state.
    40  func (c *CPU) init(cpuID int) {
    41  	// Set the kernel stack pointer(virtual address).
    42  	c.registers.Sp = uint64(c.StackTop())
    43  
    44  }
    45  
    46  // StackTop returns the kernel's stack address.
    47  //
    48  //go:nosplit
    49  func (c *CPU) StackTop() uint64 {
    50  	return uint64(kernelAddr(&c.stack[0])) + uint64(len(c.stack))
    51  }
    52  
    53  // IsCanonical indicates whether addr is canonical per the arm64 spec.
    54  //
    55  //go:nosplit
    56  func IsCanonical(addr uint64) bool {
    57  	return addr <= 0x0000ffffffffffff || addr >= 0xffff000000000000
    58  }
    59  
    60  // SwitchToUser performs an eret.
    61  //
    62  // The return value is the exception vector.
    63  //
    64  // +checkescape:all
    65  //
    66  //go:nosplit
    67  func (c *CPU) SwitchToUser(switchOpts SwitchOpts) (vector Vector) {
    68  	storeAppASID(uintptr(switchOpts.UserASID))
    69  	storeEl0Fpstate(switchOpts.FloatingPointState.BytePointer())
    70  
    71  	if switchOpts.Flush {
    72  		LocalFlushTlbByASID(uintptr(switchOpts.UserASID))
    73  	}
    74  
    75  	regs := switchOpts.Registers
    76  
    77  	regs.Pstate &= ^uint64(PsrFlagsClear)
    78  	regs.Pstate |= UserFlagsSet
    79  
    80  	fpDisableTrap := CPACREL1()
    81  	if fpDisableTrap != 0 {
    82  		FPSIMDEnableTrap()
    83  	}
    84  
    85  	kernelExitToEl0()
    86  
    87  	fpDisableTrap = CPACREL1()
    88  	if fpDisableTrap != 0 {
    89  		SaveFloatingPoint(switchOpts.FloatingPointState.BytePointer())
    90  	}
    91  
    92  	vector = c.vecCode
    93  
    94  	return
    95  }