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 }