github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/arch/arch_aarch64.go (about) 1 // Copyright 2020 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 arch 18 19 import ( 20 "fmt" 21 "io" 22 23 "github.com/SagerNet/gvisor/pkg/abi/linux" 24 "github.com/SagerNet/gvisor/pkg/cpuid" 25 "github.com/SagerNet/gvisor/pkg/errors/linuxerr" 26 "github.com/SagerNet/gvisor/pkg/log" 27 "github.com/SagerNet/gvisor/pkg/sentry/arch/fpu" 28 rpb "github.com/SagerNet/gvisor/pkg/sentry/arch/registers_go_proto" 29 "github.com/SagerNet/gvisor/pkg/syserror" 30 ) 31 32 // Registers represents the CPU registers for this architecture. 33 // 34 // +stateify savable 35 type Registers struct { 36 linux.PtraceRegs 37 38 // TPIDR_EL0 is the EL0 Read/Write Software Thread ID Register. 39 TPIDR_EL0 uint64 40 } 41 42 const ( 43 // SyscallWidth is the width of insturctions. 44 SyscallWidth = 4 45 ) 46 47 // ARMTrapFlag is the mask for the trap flag. 48 const ARMTrapFlag = uint64(1) << 21 49 50 // State contains the common architecture bits for aarch64 (the build tag of this 51 // file ensures it's only built on aarch64). 52 // 53 // +stateify savable 54 type State struct { 55 // The system registers. 56 Regs Registers 57 58 // Our floating point state. 59 fpState fpu.State `state:"wait"` 60 61 // FeatureSet is a pointer to the currently active feature set. 62 FeatureSet *cpuid.FeatureSet 63 64 // OrigR0 stores the value of register R0. 65 OrigR0 uint64 66 } 67 68 // Proto returns a protobuf representation of the system registers in State. 69 func (s State) Proto() *rpb.Registers { 70 regs := &rpb.ARM64Registers{ 71 R0: s.Regs.Regs[0], 72 R1: s.Regs.Regs[1], 73 R2: s.Regs.Regs[2], 74 R3: s.Regs.Regs[3], 75 R4: s.Regs.Regs[4], 76 R5: s.Regs.Regs[5], 77 R6: s.Regs.Regs[6], 78 R7: s.Regs.Regs[7], 79 R8: s.Regs.Regs[8], 80 R9: s.Regs.Regs[9], 81 R10: s.Regs.Regs[10], 82 R11: s.Regs.Regs[11], 83 R12: s.Regs.Regs[12], 84 R13: s.Regs.Regs[13], 85 R14: s.Regs.Regs[14], 86 R15: s.Regs.Regs[15], 87 R16: s.Regs.Regs[16], 88 R17: s.Regs.Regs[17], 89 R18: s.Regs.Regs[18], 90 R19: s.Regs.Regs[19], 91 R20: s.Regs.Regs[20], 92 R21: s.Regs.Regs[21], 93 R22: s.Regs.Regs[22], 94 R23: s.Regs.Regs[23], 95 R24: s.Regs.Regs[24], 96 R25: s.Regs.Regs[25], 97 R26: s.Regs.Regs[26], 98 R27: s.Regs.Regs[27], 99 R28: s.Regs.Regs[28], 100 R29: s.Regs.Regs[29], 101 R30: s.Regs.Regs[30], 102 Sp: s.Regs.Sp, 103 Pc: s.Regs.Pc, 104 Pstate: s.Regs.Pstate, 105 Tls: s.Regs.TPIDR_EL0, 106 } 107 return &rpb.Registers{Arch: &rpb.Registers_Arm64{Arm64: regs}} 108 } 109 110 // Fork creates and returns an identical copy of the state. 111 func (s *State) Fork() State { 112 return State{ 113 Regs: s.Regs, 114 fpState: s.fpState.Fork(), 115 FeatureSet: s.FeatureSet, 116 OrigR0: s.OrigR0, 117 } 118 } 119 120 // StateData implements Context.StateData. 121 func (s *State) StateData() *State { 122 return s 123 } 124 125 // CPUIDEmulate emulates a cpuid instruction. 126 func (s *State) CPUIDEmulate(l log.Logger) { 127 // TODO(github.com/SagerNet/issue/1255): cpuid is not supported. 128 } 129 130 // SingleStep implements Context.SingleStep. 131 func (s *State) SingleStep() bool { 132 return false 133 } 134 135 // SetSingleStep enables single stepping. 136 func (s *State) SetSingleStep() { 137 // Set the trap flag. 138 // TODO(github.com/SagerNet/issue/1239): ptrace single-step is not supported. 139 } 140 141 // ClearSingleStep enables single stepping. 142 func (s *State) ClearSingleStep() { 143 // Clear the trap flag. 144 // TODO(github.com/SagerNet/issue/1239): ptrace single-step is not supported. 145 } 146 147 // RegisterMap returns a map of all registers. 148 func (s *State) RegisterMap() (map[string]uintptr, error) { 149 return map[string]uintptr{ 150 "R0": uintptr(s.Regs.Regs[0]), 151 "R1": uintptr(s.Regs.Regs[1]), 152 "R2": uintptr(s.Regs.Regs[2]), 153 "R3": uintptr(s.Regs.Regs[3]), 154 "R4": uintptr(s.Regs.Regs[4]), 155 "R5": uintptr(s.Regs.Regs[5]), 156 "R6": uintptr(s.Regs.Regs[6]), 157 "R7": uintptr(s.Regs.Regs[7]), 158 "R8": uintptr(s.Regs.Regs[8]), 159 "R9": uintptr(s.Regs.Regs[9]), 160 "R10": uintptr(s.Regs.Regs[10]), 161 "R11": uintptr(s.Regs.Regs[11]), 162 "R12": uintptr(s.Regs.Regs[12]), 163 "R13": uintptr(s.Regs.Regs[13]), 164 "R14": uintptr(s.Regs.Regs[14]), 165 "R15": uintptr(s.Regs.Regs[15]), 166 "R16": uintptr(s.Regs.Regs[16]), 167 "R17": uintptr(s.Regs.Regs[17]), 168 "R18": uintptr(s.Regs.Regs[18]), 169 "R19": uintptr(s.Regs.Regs[19]), 170 "R20": uintptr(s.Regs.Regs[20]), 171 "R21": uintptr(s.Regs.Regs[21]), 172 "R22": uintptr(s.Regs.Regs[22]), 173 "R23": uintptr(s.Regs.Regs[23]), 174 "R24": uintptr(s.Regs.Regs[24]), 175 "R25": uintptr(s.Regs.Regs[25]), 176 "R26": uintptr(s.Regs.Regs[26]), 177 "R27": uintptr(s.Regs.Regs[27]), 178 "R28": uintptr(s.Regs.Regs[28]), 179 "R29": uintptr(s.Regs.Regs[29]), 180 "R30": uintptr(s.Regs.Regs[30]), 181 "Sp": uintptr(s.Regs.Sp), 182 "Pc": uintptr(s.Regs.Pc), 183 "Pstate": uintptr(s.Regs.Pstate), 184 "Tls": uintptr(s.Regs.TPIDR_EL0), 185 }, nil 186 } 187 188 // PtraceGetRegs implements Context.PtraceGetRegs. 189 func (s *State) PtraceGetRegs(dst io.Writer) (int, error) { 190 regs := s.ptraceGetRegs() 191 n, err := regs.WriteTo(dst) 192 return int(n), err 193 } 194 195 func (s *State) ptraceGetRegs() Registers { 196 return s.Regs 197 } 198 199 var ptraceRegistersSize = (*linux.PtraceRegs)(nil).SizeBytes() 200 201 // PtraceSetRegs implements Context.PtraceSetRegs. 202 func (s *State) PtraceSetRegs(src io.Reader) (int, error) { 203 var regs Registers 204 buf := make([]byte, ptraceRegistersSize) 205 if _, err := io.ReadFull(src, buf); err != nil { 206 return 0, err 207 } 208 regs.UnmarshalUnsafe(buf) 209 s.Regs = regs 210 return ptraceRegistersSize, nil 211 } 212 213 // PtraceGetFPRegs implements Context.PtraceGetFPRegs. 214 func (s *State) PtraceGetFPRegs(dst io.Writer) (int, error) { 215 // TODO(github.com/SagerNet/issue/1238): floating-point is not supported. 216 return 0, nil 217 } 218 219 // PtraceSetFPRegs implements Context.PtraceSetFPRegs. 220 func (s *State) PtraceSetFPRegs(src io.Reader) (int, error) { 221 // TODO(github.com/SagerNet/issue/1238): floating-point is not supported. 222 return 0, nil 223 } 224 225 // Register sets defined in include/uapi/linux/elf.h. 226 const ( 227 _NT_PRSTATUS = 1 228 _NT_PRFPREG = 2 229 _NT_ARM_TLS = 0x401 230 ) 231 232 // PtraceGetRegSet implements Context.PtraceGetRegSet. 233 func (s *State) PtraceGetRegSet(regset uintptr, dst io.Writer, maxlen int) (int, error) { 234 switch regset { 235 case _NT_PRSTATUS: 236 if maxlen < ptraceRegistersSize { 237 return 0, syserror.EFAULT 238 } 239 return s.PtraceGetRegs(dst) 240 default: 241 return 0, linuxerr.EINVAL 242 } 243 } 244 245 // PtraceSetRegSet implements Context.PtraceSetRegSet. 246 func (s *State) PtraceSetRegSet(regset uintptr, src io.Reader, maxlen int) (int, error) { 247 switch regset { 248 case _NT_PRSTATUS: 249 if maxlen < ptraceRegistersSize { 250 return 0, syserror.EFAULT 251 } 252 return s.PtraceSetRegs(src) 253 default: 254 return 0, linuxerr.EINVAL 255 } 256 } 257 258 // FullRestore indicates whether a full restore is required. 259 func (s *State) FullRestore() bool { 260 return false 261 } 262 263 // New returns a new architecture context. 264 func New(arch Arch, fs *cpuid.FeatureSet) Context { 265 switch arch { 266 case ARM64: 267 return &context64{ 268 State{ 269 fpState: fpu.NewState(), 270 FeatureSet: fs, 271 }, 272 []fpu.State(nil), 273 } 274 } 275 panic(fmt.Sprintf("unknown architecture %v", arch)) 276 }