github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/pkg/sentry/platform/kvm/kvm_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  // +build amd64
    16  
    17  package kvm
    18  
    19  import (
    20  	"github.com/SagerNet/gvisor/pkg/cpuid"
    21  	"github.com/SagerNet/gvisor/pkg/ring0"
    22  )
    23  
    24  // userRegs represents KVM user registers.
    25  //
    26  // This mirrors kvm_regs.
    27  type userRegs struct {
    28  	RAX    uint64
    29  	RBX    uint64
    30  	RCX    uint64
    31  	RDX    uint64
    32  	RSI    uint64
    33  	RDI    uint64
    34  	RSP    uint64
    35  	RBP    uint64
    36  	R8     uint64
    37  	R9     uint64
    38  	R10    uint64
    39  	R11    uint64
    40  	R12    uint64
    41  	R13    uint64
    42  	R14    uint64
    43  	R15    uint64
    44  	RIP    uint64
    45  	RFLAGS uint64
    46  }
    47  
    48  // systemRegs represents KVM system registers.
    49  //
    50  // This mirrors kvm_sregs.
    51  type systemRegs struct {
    52  	CS              segment
    53  	DS              segment
    54  	ES              segment
    55  	FS              segment
    56  	GS              segment
    57  	SS              segment
    58  	TR              segment
    59  	LDT             segment
    60  	GDT             descriptor
    61  	IDT             descriptor
    62  	CR0             uint64
    63  	CR2             uint64
    64  	CR3             uint64
    65  	CR4             uint64
    66  	CR8             uint64
    67  	EFER            uint64
    68  	apicBase        uint64
    69  	interruptBitmap [(_KVM_NR_INTERRUPTS + 63) / 64]uint64
    70  }
    71  
    72  // segment is the expanded form of a segment register.
    73  //
    74  // This mirrors kvm_segment.
    75  type segment struct {
    76  	base     uint64
    77  	limit    uint32
    78  	selector uint16
    79  	typ      uint8
    80  	present  uint8
    81  	DPL      uint8
    82  	DB       uint8
    83  	S        uint8
    84  	L        uint8
    85  	G        uint8
    86  	AVL      uint8
    87  	unusable uint8
    88  	_        uint8
    89  }
    90  
    91  // Clear clears the segment and marks it unusable.
    92  func (s *segment) Clear() {
    93  	*s = segment{unusable: 1}
    94  }
    95  
    96  // selector is a segment selector.
    97  type selector uint16
    98  
    99  // tobool is a simple helper.
   100  func tobool(x ring0.SegmentDescriptorFlags) uint8 {
   101  	if x != 0 {
   102  		return 1
   103  	}
   104  	return 0
   105  }
   106  
   107  // Load loads the segment described by d into the segment s.
   108  //
   109  // The argument sel is recorded as the segment selector index.
   110  func (s *segment) Load(d *ring0.SegmentDescriptor, sel ring0.Selector) {
   111  	flag := d.Flags()
   112  	if flag&ring0.SegmentDescriptorPresent == 0 {
   113  		s.Clear()
   114  		return
   115  	}
   116  	s.base = uint64(d.Base())
   117  	s.limit = d.Limit()
   118  	s.typ = uint8((flag>>8)&0xF) | 1
   119  	s.S = tobool(flag & ring0.SegmentDescriptorSystem)
   120  	s.DPL = uint8(d.DPL())
   121  	s.present = tobool(flag & ring0.SegmentDescriptorPresent)
   122  	s.AVL = tobool(flag & ring0.SegmentDescriptorAVL)
   123  	s.L = tobool(flag & ring0.SegmentDescriptorLong)
   124  	s.DB = tobool(flag & ring0.SegmentDescriptorDB)
   125  	s.G = tobool(flag & ring0.SegmentDescriptorG)
   126  	if s.L != 0 {
   127  		s.limit = 0xffffffff
   128  	}
   129  	s.unusable = 0
   130  	s.selector = uint16(sel)
   131  }
   132  
   133  // descriptor describes a region of physical memory.
   134  //
   135  // It corresponds to the pseudo-descriptor used in the x86 LGDT and LIDT
   136  // instructions, and mirrors kvm_dtable.
   137  type descriptor struct {
   138  	base  uint64
   139  	limit uint16
   140  	_     [3]uint16
   141  }
   142  
   143  // modelControlRegister is an MSR entry.
   144  //
   145  // This mirrors kvm_msr_entry.
   146  type modelControlRegister struct {
   147  	index uint32
   148  	_     uint32
   149  	data  uint64
   150  }
   151  
   152  // modelControlRegisers is a collection of MSRs.
   153  //
   154  // This mirrors kvm_msrs.
   155  type modelControlRegisters struct {
   156  	nmsrs   uint32
   157  	_       uint32
   158  	entries [16]modelControlRegister
   159  }
   160  
   161  // cpuidEntry is a single CPUID entry.
   162  //
   163  // This mirrors kvm_cpuid_entry2.
   164  type cpuidEntry struct {
   165  	function uint32
   166  	index    uint32
   167  	flags    uint32
   168  	eax      uint32
   169  	ebx      uint32
   170  	ecx      uint32
   171  	edx      uint32
   172  	_        [3]uint32
   173  }
   174  
   175  // cpuidEntries is a collection of CPUID entries.
   176  //
   177  // This mirrors kvm_cpuid2.
   178  type cpuidEntries struct {
   179  	nr      uint32
   180  	_       uint32
   181  	entries [_KVM_NR_CPUID_ENTRIES]cpuidEntry
   182  }
   183  
   184  // updateGlobalOnce does global initialization. It has to be called only once.
   185  func updateGlobalOnce(fd int) error {
   186  	physicalInit()
   187  	err := updateSystemValues(int(fd))
   188  	ring0.Init(cpuid.HostFeatureSet())
   189  	return err
   190  }