github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/pkg/sentry/platform/kvm/bluepill_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 kvm
    19  
    20  import (
    21  	"golang.org/x/sys/unix"
    22  	"github.com/nicocha30/gvisor-ligolo/pkg/ring0"
    23  	"github.com/nicocha30/gvisor-ligolo/pkg/sentry/arch"
    24  )
    25  
    26  var (
    27  	// The action for bluepillSignal is changed by sigaction().
    28  	bluepillSignal = unix.SIGILL
    29  )
    30  
    31  // getTLS returns the value of TPIDR_EL0 register.
    32  //
    33  //go:nosplit
    34  func getTLS() (value uint64)
    35  
    36  // setTLS writes the TPIDR_EL0 value.
    37  //
    38  //go:nosplit
    39  func setTLS(value uint64)
    40  
    41  // bluepillArchEnter is called during bluepillEnter.
    42  //
    43  //go:nosplit
    44  func bluepillArchEnter(context *arch.SignalContext64) (c *vCPU) {
    45  	c = vCPUPtr(uintptr(context.Regs[8]))
    46  	regs := c.CPU.Registers()
    47  	regs.Regs = context.Regs
    48  	regs.Sp = context.Sp
    49  	regs.Pc = context.Pc
    50  	regs.Pstate = context.Pstate
    51  	regs.Pstate &^= uint64(ring0.PsrFlagsClear)
    52  	regs.Pstate |= ring0.KernelFlagsSet
    53  	regs.TPIDR_EL0 = getTLS()
    54  
    55  	return
    56  }
    57  
    58  // bluepillArchExit is called during bluepillEnter.
    59  //
    60  //go:nosplit
    61  func bluepillArchExit(c *vCPU, context *arch.SignalContext64) {
    62  	regs := c.CPU.Registers()
    63  	context.Regs = regs.Regs
    64  	context.Sp = regs.Sp
    65  	context.Pc = regs.Pc
    66  	context.Pstate = regs.Pstate
    67  	context.Pstate &^= uint64(ring0.PsrFlagsClear)
    68  	context.Pstate |= ring0.UserFlagsSet
    69  	setTLS(regs.TPIDR_EL0)
    70  
    71  	lazyVfp := c.GetLazyVFP()
    72  	if lazyVfp != 0 {
    73  		fpsimd := fpsimdPtr(c.FloatingPointState().BytePointer()) // escapes: no
    74  		context.Fpsimd64.Fpsr = fpsimd.Fpsr
    75  		context.Fpsimd64.Fpcr = fpsimd.Fpcr
    76  		context.Fpsimd64.Vregs = fpsimd.Vregs
    77  	}
    78  }
    79  
    80  // KernelSyscall handles kernel syscalls.
    81  //
    82  // +checkescape:all
    83  //
    84  //go:nosplit
    85  func (c *vCPU) KernelSyscall() {
    86  	regs := c.Registers()
    87  	if regs.Regs[8] != ^uint64(0) {
    88  		regs.Pc -= 4 // Rewind.
    89  	}
    90  
    91  	fpDisableTrap := ring0.CPACREL1()
    92  	if fpDisableTrap != 0 {
    93  		fpsimd := fpsimdPtr(c.FloatingPointState().BytePointer()) // escapes: no
    94  		fpcr := ring0.GetFPCR()
    95  		fpsr := ring0.GetFPSR()
    96  		fpsimd.Fpcr = uint32(fpcr)
    97  		fpsimd.Fpsr = uint32(fpsr)
    98  		ring0.SaveVRegs(c.FloatingPointState().BytePointer()) // escapes: no
    99  	}
   100  
   101  	ring0.Halt()
   102  }
   103  
   104  // KernelException handles kernel exceptions.
   105  //
   106  // +checkescape:all
   107  //
   108  //go:nosplit
   109  func (c *vCPU) KernelException(vector ring0.Vector) {
   110  	regs := c.Registers()
   111  	if vector == ring0.Vector(bounce) {
   112  		regs.Pc = 0
   113  	}
   114  
   115  	fpDisableTrap := ring0.CPACREL1()
   116  	if fpDisableTrap != 0 {
   117  		fpsimd := fpsimdPtr(c.FloatingPointState().BytePointer()) // escapes: no
   118  		fpcr := ring0.GetFPCR()
   119  		fpsr := ring0.GetFPSR()
   120  		fpsimd.Fpcr = uint32(fpcr)
   121  		fpsimd.Fpsr = uint32(fpsr)
   122  		ring0.SaveVRegs(c.FloatingPointState().BytePointer()) // escapes: no
   123  	}
   124  
   125  	ring0.Halt()
   126  }
   127  
   128  // hltSanityCheck verifies the current state to detect obvious corruption.
   129  //
   130  //go:nosplit
   131  func (c *vCPU) hltSanityCheck() {
   132  }