github.com/ttpreport/gvisor-ligolo@v0.0.0-20240123134145-a858404967ba/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 // Copies of global variables, stored in CPU so that they can be used by 141 // syscall and exception handlers (in the upper address space). 142 hasXSAVE bool 143 hasXSAVEOPT bool 144 } 145 146 // ErrorCode returns the last error code. 147 // 148 // The returned boolean indicates whether the error code corresponds to the 149 // last user error or not. If it does not, then fault information must be 150 // ignored. This is generally the result of a kernel fault while servicing a 151 // user fault. 152 // 153 //go:nosplit 154 func (c *CPU) ErrorCode() (value uintptr, user bool) { 155 return c.errorCode, c.errorType != 0 156 } 157 158 // ClearErrorCode resets the error code. 159 // 160 //go:nosplit 161 func (c *CPU) ClearErrorCode() { 162 c.errorCode = 0 // No code. 163 c.errorType = 1 // User mode. 164 } 165 166 // Vector returns the vector of the last exception. 167 // 168 //go:nosplit 169 func (c *CPU) Vector() uintptr { 170 return c.vector 171 } 172 173 // FaultAddr returns the last fault address. 174 // 175 //go:nosplit 176 func (c *CPU) FaultAddr() uintptr { 177 return c.faultAddr 178 } 179 180 // SwitchArchOpts are embedded in SwitchOpts. 181 type SwitchArchOpts struct { 182 // UserPCID indicates that the application PCID to be used on switch, 183 // assuming that PCIDs are supported. 184 // 185 // Per pagetables_x86.go, a zero PCID implies a flush. 186 UserPCID uint16 187 188 // KernelPCID indicates that the kernel PCID to be used on return, 189 // assuming that PCIDs are supported. 190 // 191 // Per pagetables_x86.go, a zero PCID implies a flush. 192 KernelPCID uint16 193 } 194 195 func init() { 196 KernelCodeSegment.setCode64(0, 0, 0) 197 KernelDataSegment.setData(0, 0xffffffff, 0) 198 UserCodeSegment32.setCode64(0, 0, 3) 199 UserDataSegment.setData(0, 0xffffffff, 3) 200 UserCodeSegment64.setCode64(0, 0, 3) 201 }