github.com/MerlinKodo/gvisor@v0.0.0-20231110090155-957f62ecf90e/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 "github.com/MerlinKodo/gvisor/pkg/ring0" 22 "github.com/MerlinKodo/gvisor/pkg/sentry/arch" 23 "golang.org/x/sys/unix" 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 }