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  }