gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/pkg/ring0/defs_amd64.go (about)

     1  // Copyright 2018 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 amd64
    16  // +build amd64
    17  
    18  package ring0
    19  
    20  var (
    21  	// VirtualAddressBits is the number of bits available in the virtual
    22  	// address space.
    23  	//
    24  	// Initialized by ring0.Init.
    25  	VirtualAddressBits uintptr
    26  
    27  	// PhysicalAddressBits is the number of bits available in the physical
    28  	// address space.
    29  	//
    30  	// Initialized by ring0.Init.
    31  	PhysicalAddressBits uintptr
    32  
    33  	// UserspaceSize is the total size of userspace.
    34  	//
    35  	// Initialized by ring0.Init.
    36  	UserspaceSize uintptr
    37  
    38  	// MaximumUserAddress is the largest possible user address.
    39  	//
    40  	// Initialized by ring0.Init.
    41  	MaximumUserAddress uintptr
    42  
    43  	// KernelStartAddress is the starting kernel address.
    44  	//
    45  	// Initialized by ring0.Init.
    46  	KernelStartAddress uintptr
    47  )
    48  
    49  // Segment indices and Selectors.
    50  const (
    51  	// Index into GDT array.
    52  	_          = iota // Null descriptor first.
    53  	_                 // Reserved (Linux is kernel 32).
    54  	segKcode          // Kernel code (64-bit).
    55  	segKdata          // Kernel data.
    56  	segUcode32        // User code (32-bit).
    57  	segUdata          // User data.
    58  	segUcode64        // User code (64-bit).
    59  	segTss            // Task segment descriptor.
    60  	segTssHi          // Upper bits for TSS.
    61  	segLast           // Last segment (terminal, not included).
    62  )
    63  
    64  // Selectors.
    65  const (
    66  	Kcode   Selector = segKcode << 3
    67  	Kdata   Selector = segKdata << 3
    68  	Ucode32 Selector = (segUcode32 << 3) | 3
    69  	Udata   Selector = (segUdata << 3) | 3
    70  	Ucode64 Selector = (segUcode64 << 3) | 3
    71  	Tss     Selector = segTss << 3
    72  )
    73  
    74  // Standard segments.
    75  var (
    76  	UserCodeSegment32 SegmentDescriptor
    77  	UserDataSegment   SegmentDescriptor
    78  	UserCodeSegment64 SegmentDescriptor
    79  	KernelCodeSegment SegmentDescriptor
    80  	KernelDataSegment SegmentDescriptor
    81  )
    82  
    83  // KernelArchState contains architecture-specific state.
    84  type KernelArchState struct {
    85  	// cpuEntries is array of kernelEntry for all cpus.
    86  	cpuEntries []kernelEntry
    87  
    88  	// globalIDT is our set of interrupt gates.
    89  	globalIDT *idt64
    90  }
    91  
    92  // kernelEntry contains minimal CPU-specific arch state
    93  // that can be mapped at the upper of the address space.
    94  // Malicious APP might steal info from it via CPU bugs.
    95  type kernelEntry struct {
    96  	// stack is the stack used for interrupts on this CPU.
    97  	stack [256]byte
    98  
    99  	// scratch space for temporary usage.
   100  	scratch0 uint64
   101  
   102  	// stackTop is the top of the stack.
   103  	stackTop uint64
   104  
   105  	// cpuSelf is back reference to CPU.
   106  	cpuSelf *CPU
   107  
   108  	// kernelCR3 is the cr3 used for sentry kernel.
   109  	kernelCR3 uintptr
   110  
   111  	// gdt is the CPU's descriptor table.
   112  	gdt descriptorTable
   113  
   114  	// tss is the CPU's task state.
   115  	tss TaskState64
   116  }
   117  
   118  // CPUArchState contains CPU-specific arch state.
   119  type CPUArchState struct {
   120  	// errorCode is the error code from the last exception.
   121  	errorCode uintptr
   122  
   123  	// errorType indicates the type of error code here, it is always set
   124  	// along with the errorCode value above.
   125  	//
   126  	// It will either by 1, which indicates a user error, or 0 indicating a
   127  	// kernel error. If the error code below returns false (kernel error),
   128  	// then it cannot provide relevant information about the last
   129  	// exception.
   130  	errorType uintptr
   131  
   132  	// vector is the vector of the last exception.
   133  	vector uintptr
   134  
   135  	// faultAddr is the value of the cr2 register.
   136  	faultAddr uintptr
   137  
   138  	*kernelEntry
   139  
   140  	appGsBase uint64
   141  
   142  	// Copies of global variables, stored in CPU so that they can be used by
   143  	// syscall and exception handlers (in the upper address space).
   144  	hasXSAVE    bool
   145  	hasXSAVEOPT bool
   146  	hasFSGSBASE bool
   147  }
   148  
   149  // ErrorCode returns the last error code.
   150  //
   151  // The returned boolean indicates whether the error code corresponds to the
   152  // last user error or not. If it does not, then fault information must be
   153  // ignored. This is generally the result of a kernel fault while servicing a
   154  // user fault.
   155  //
   156  //go:nosplit
   157  func (c *CPU) ErrorCode() (value uintptr, user bool) {
   158  	return c.errorCode, c.errorType != 0
   159  }
   160  
   161  // ClearErrorCode resets the error code.
   162  //
   163  //go:nosplit
   164  func (c *CPU) ClearErrorCode() {
   165  	c.errorCode = 0 // No code.
   166  	c.errorType = 1 // User mode.
   167  }
   168  
   169  // Vector returns the vector of the last exception.
   170  //
   171  //go:nosplit
   172  func (c *CPU) Vector() uintptr {
   173  	return c.vector
   174  }
   175  
   176  // FaultAddr returns the last fault address.
   177  //
   178  //go:nosplit
   179  func (c *CPU) FaultAddr() uintptr {
   180  	return c.faultAddr
   181  }
   182  
   183  // SwitchArchOpts are embedded in SwitchOpts.
   184  type SwitchArchOpts struct {
   185  	// UserPCID indicates that the application PCID to be used on switch,
   186  	// assuming that PCIDs are supported.
   187  	//
   188  	// Per pagetables_x86.go, a zero PCID implies a flush.
   189  	UserPCID uint16
   190  
   191  	// KernelPCID indicates that the kernel PCID to be used on return,
   192  	// assuming that PCIDs are supported.
   193  	//
   194  	// Per pagetables_x86.go, a zero PCID implies a flush.
   195  	KernelPCID uint16
   196  }
   197  
   198  func init() {
   199  	KernelCodeSegment.setCode64(0, 0, 0)
   200  	KernelDataSegment.setData(0, 0xffffffff, 0)
   201  	UserCodeSegment32.setCode64(0, 0, 3)
   202  	UserDataSegment.setData(0, 0xffffffff, 3)
   203  	UserCodeSegment64.setCode64(0, 0, 3)
   204  }