2019-04-29 21:25:05 +00:00
|
|
|
// Copyright 2018 The gVisor Authors.
|
2018-04-27 17:37:02 +00:00
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
|
|
|
// +build i386 amd64
|
|
|
|
|
|
|
|
package ring0
|
|
|
|
|
|
|
|
import (
|
2019-06-13 23:49:09 +00:00
|
|
|
"gvisor.dev/gvisor/pkg/cpuid"
|
2018-04-27 17:37:02 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// Useful bits.
|
|
|
|
const (
|
|
|
|
_CR0_PE = 1 << 0
|
|
|
|
_CR0_ET = 1 << 4
|
2018-06-09 00:50:55 +00:00
|
|
|
_CR0_AM = 1 << 18
|
2018-04-27 17:37:02 +00:00
|
|
|
_CR0_PG = 1 << 31
|
|
|
|
|
|
|
|
_CR4_PSE = 1 << 4
|
|
|
|
_CR4_PAE = 1 << 5
|
|
|
|
_CR4_PGE = 1 << 7
|
|
|
|
_CR4_OSFXSR = 1 << 9
|
|
|
|
_CR4_OSXMMEXCPT = 1 << 10
|
|
|
|
_CR4_FSGSBASE = 1 << 16
|
|
|
|
_CR4_PCIDE = 1 << 17
|
|
|
|
_CR4_OSXSAVE = 1 << 18
|
|
|
|
_CR4_SMEP = 1 << 20
|
|
|
|
|
|
|
|
_RFLAGS_AC = 1 << 18
|
|
|
|
_RFLAGS_NT = 1 << 14
|
|
|
|
_RFLAGS_IOPL = 3 << 12
|
|
|
|
_RFLAGS_DF = 1 << 10
|
|
|
|
_RFLAGS_IF = 1 << 9
|
|
|
|
_RFLAGS_STEP = 1 << 8
|
|
|
|
_RFLAGS_RESERVED = 1 << 1
|
|
|
|
|
|
|
|
_EFER_SCE = 0x001
|
|
|
|
_EFER_LME = 0x100
|
2018-05-02 05:17:13 +00:00
|
|
|
_EFER_LMA = 0x400
|
2018-04-27 17:37:02 +00:00
|
|
|
_EFER_NX = 0x800
|
|
|
|
|
2018-07-17 05:02:03 +00:00
|
|
|
_MSR_STAR = 0xc0000081
|
|
|
|
_MSR_LSTAR = 0xc0000082
|
|
|
|
_MSR_CSTAR = 0xc0000083
|
|
|
|
_MSR_SYSCALL_MASK = 0xc0000084
|
|
|
|
_MSR_PLATFORM_INFO = 0xce
|
|
|
|
_MSR_MISC_FEATURES = 0x140
|
|
|
|
|
|
|
|
_PLATFORM_INFO_CPUID_FAULT = 1 << 31
|
|
|
|
|
|
|
|
_MISC_FEATURE_CPUID_TRAP = 0x1
|
2018-04-27 17:37:02 +00:00
|
|
|
)
|
|
|
|
|
2018-06-09 00:50:55 +00:00
|
|
|
const (
|
|
|
|
// KernelFlagsSet should always be set in the kernel.
|
|
|
|
KernelFlagsSet = _RFLAGS_RESERVED
|
|
|
|
|
|
|
|
// UserFlagsSet are always set in userspace.
|
|
|
|
UserFlagsSet = _RFLAGS_RESERVED | _RFLAGS_IF
|
|
|
|
|
|
|
|
// KernelFlagsClear should always be clear in the kernel.
|
|
|
|
KernelFlagsClear = _RFLAGS_STEP | _RFLAGS_IF | _RFLAGS_IOPL | _RFLAGS_AC | _RFLAGS_NT
|
|
|
|
|
|
|
|
// UserFlagsClear are always cleared in userspace.
|
|
|
|
UserFlagsClear = _RFLAGS_NT | _RFLAGS_IOPL
|
|
|
|
)
|
|
|
|
|
2018-04-27 17:37:02 +00:00
|
|
|
// Vector is an exception vector.
|
|
|
|
type Vector uintptr
|
|
|
|
|
|
|
|
// Exception vectors.
|
|
|
|
const (
|
|
|
|
DivideByZero Vector = iota
|
|
|
|
Debug
|
|
|
|
NMI
|
|
|
|
Breakpoint
|
|
|
|
Overflow
|
|
|
|
BoundRangeExceeded
|
|
|
|
InvalidOpcode
|
|
|
|
DeviceNotAvailable
|
|
|
|
DoubleFault
|
|
|
|
CoprocessorSegmentOverrun
|
|
|
|
InvalidTSS
|
|
|
|
SegmentNotPresent
|
|
|
|
StackSegmentFault
|
|
|
|
GeneralProtectionFault
|
|
|
|
PageFault
|
|
|
|
_
|
|
|
|
X87FloatingPointException
|
|
|
|
AlignmentCheck
|
|
|
|
MachineCheck
|
|
|
|
SIMDFloatingPointException
|
|
|
|
VirtualizationException
|
|
|
|
SecurityException = 0x1e
|
|
|
|
SyscallInt80 = 0x80
|
|
|
|
_NR_INTERRUPTS = SyscallInt80 + 1
|
|
|
|
)
|
|
|
|
|
|
|
|
// System call vectors.
|
|
|
|
const (
|
|
|
|
Syscall Vector = _NR_INTERRUPTS
|
|
|
|
)
|
|
|
|
|
|
|
|
// VirtualAddressBits returns the number bits available for virtual addresses.
|
|
|
|
//
|
|
|
|
// Note that sign-extension semantics apply to the highest order bit.
|
|
|
|
//
|
2019-04-29 21:03:04 +00:00
|
|
|
// FIXME(b/69382326): This should use the cpuid passed to Init.
|
2018-04-27 17:37:02 +00:00
|
|
|
func VirtualAddressBits() uint32 {
|
|
|
|
ax, _, _, _ := cpuid.HostID(0x80000008, 0)
|
|
|
|
return (ax >> 8) & 0xff
|
|
|
|
}
|
|
|
|
|
|
|
|
// PhysicalAddressBits returns the number of bits available for physical addresses.
|
|
|
|
//
|
2019-04-29 21:03:04 +00:00
|
|
|
// FIXME(b/69382326): This should use the cpuid passed to Init.
|
2018-04-27 17:37:02 +00:00
|
|
|
func PhysicalAddressBits() uint32 {
|
|
|
|
ax, _, _, _ := cpuid.HostID(0x80000008, 0)
|
|
|
|
return ax & 0xff
|
|
|
|
}
|
|
|
|
|
|
|
|
// Selector is a segment Selector.
|
|
|
|
type Selector uint16
|
|
|
|
|
|
|
|
// SegmentDescriptor is a segment descriptor.
|
|
|
|
type SegmentDescriptor struct {
|
|
|
|
bits [2]uint32
|
|
|
|
}
|
|
|
|
|
|
|
|
// descriptorTable is a collection of descriptors.
|
|
|
|
type descriptorTable [32]SegmentDescriptor
|
|
|
|
|
|
|
|
// SegmentDescriptorFlags are typed flags within a descriptor.
|
|
|
|
type SegmentDescriptorFlags uint32
|
|
|
|
|
|
|
|
// SegmentDescriptorFlag declarations.
|
|
|
|
const (
|
|
|
|
SegmentDescriptorAccess SegmentDescriptorFlags = 1 << 8 // Access bit (always set).
|
|
|
|
SegmentDescriptorWrite = 1 << 9 // Write permission.
|
|
|
|
SegmentDescriptorExpandDown = 1 << 10 // Grows down, not used.
|
|
|
|
SegmentDescriptorExecute = 1 << 11 // Execute permission.
|
|
|
|
SegmentDescriptorSystem = 1 << 12 // Zero => system, 1 => user code/data.
|
|
|
|
SegmentDescriptorPresent = 1 << 15 // Present.
|
|
|
|
SegmentDescriptorAVL = 1 << 20 // Available.
|
|
|
|
SegmentDescriptorLong = 1 << 21 // Long mode.
|
|
|
|
SegmentDescriptorDB = 1 << 22 // 16 or 32-bit.
|
|
|
|
SegmentDescriptorG = 1 << 23 // Granularity: page or byte.
|
|
|
|
)
|
|
|
|
|
|
|
|
// Base returns the descriptor's base linear address.
|
|
|
|
func (d *SegmentDescriptor) Base() uint32 {
|
|
|
|
return d.bits[1]&0xFF000000 | (d.bits[1]&0x000000FF)<<16 | d.bits[0]>>16
|
|
|
|
}
|
|
|
|
|
|
|
|
// Limit returns the descriptor size.
|
|
|
|
func (d *SegmentDescriptor) Limit() uint32 {
|
|
|
|
l := d.bits[0]&0xFFFF | d.bits[1]&0xF0000
|
|
|
|
if d.bits[1]&uint32(SegmentDescriptorG) != 0 {
|
|
|
|
l <<= 12
|
|
|
|
l |= 0xFFF
|
|
|
|
}
|
|
|
|
return l
|
|
|
|
}
|
|
|
|
|
|
|
|
// Flags returns descriptor flags.
|
|
|
|
func (d *SegmentDescriptor) Flags() SegmentDescriptorFlags {
|
|
|
|
return SegmentDescriptorFlags(d.bits[1] & 0x00F09F00)
|
|
|
|
}
|
|
|
|
|
|
|
|
// DPL returns the descriptor privilege level.
|
|
|
|
func (d *SegmentDescriptor) DPL() int {
|
|
|
|
return int((d.bits[1] >> 13) & 3)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *SegmentDescriptor) setNull() {
|
|
|
|
d.bits[0] = 0
|
|
|
|
d.bits[1] = 0
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *SegmentDescriptor) set(base, limit uint32, dpl int, flags SegmentDescriptorFlags) {
|
|
|
|
flags |= SegmentDescriptorPresent
|
|
|
|
if limit>>12 != 0 {
|
|
|
|
limit >>= 12
|
|
|
|
flags |= SegmentDescriptorG
|
|
|
|
}
|
|
|
|
d.bits[0] = base<<16 | limit&0xFFFF
|
|
|
|
d.bits[1] = base&0xFF000000 | (base>>16)&0xFF | limit&0x000F0000 | uint32(flags) | uint32(dpl)<<13
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *SegmentDescriptor) setCode32(base, limit uint32, dpl int) {
|
|
|
|
d.set(base, limit, dpl,
|
|
|
|
SegmentDescriptorDB|
|
|
|
|
SegmentDescriptorExecute|
|
|
|
|
SegmentDescriptorSystem)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *SegmentDescriptor) setCode64(base, limit uint32, dpl int) {
|
|
|
|
d.set(base, limit, dpl,
|
|
|
|
SegmentDescriptorG|
|
|
|
|
SegmentDescriptorLong|
|
|
|
|
SegmentDescriptorExecute|
|
|
|
|
SegmentDescriptorSystem)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (d *SegmentDescriptor) setData(base, limit uint32, dpl int) {
|
|
|
|
d.set(base, limit, dpl,
|
|
|
|
SegmentDescriptorWrite|
|
|
|
|
SegmentDescriptorSystem)
|
|
|
|
}
|
|
|
|
|
|
|
|
// setHi is only used for the TSS segment, which is magically 64-bits.
|
|
|
|
func (d *SegmentDescriptor) setHi(base uint32) {
|
|
|
|
d.bits[0] = base
|
|
|
|
d.bits[1] = 0
|
|
|
|
}
|
|
|
|
|
|
|
|
// Gate64 is a 64-bit task, trap, or interrupt gate.
|
|
|
|
type Gate64 struct {
|
|
|
|
bits [4]uint32
|
|
|
|
}
|
|
|
|
|
|
|
|
// idt64 is a 64-bit interrupt descriptor table.
|
|
|
|
type idt64 [_NR_INTERRUPTS]Gate64
|
|
|
|
|
|
|
|
func (g *Gate64) setInterrupt(cs Selector, rip uint64, dpl int, ist int) {
|
|
|
|
g.bits[0] = uint32(cs)<<16 | uint32(rip)&0xFFFF
|
|
|
|
g.bits[1] = uint32(rip)&0xFFFF0000 | SegmentDescriptorPresent | uint32(dpl)<<13 | 14<<8 | uint32(ist)&0x7
|
|
|
|
g.bits[2] = uint32(rip >> 32)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (g *Gate64) setTrap(cs Selector, rip uint64, dpl int, ist int) {
|
|
|
|
g.setInterrupt(cs, rip, dpl, ist)
|
|
|
|
g.bits[1] |= 1 << 8
|
|
|
|
}
|
|
|
|
|
|
|
|
// TaskState64 is a 64-bit task state structure.
|
|
|
|
type TaskState64 struct {
|
|
|
|
_ uint32
|
|
|
|
rsp0Lo, rsp0Hi uint32
|
|
|
|
rsp1Lo, rsp1Hi uint32
|
|
|
|
rsp2Lo, rsp2Hi uint32
|
|
|
|
_ [2]uint32
|
|
|
|
ist1Lo, ist1Hi uint32
|
|
|
|
ist2Lo, ist2Hi uint32
|
|
|
|
ist3Lo, ist3Hi uint32
|
|
|
|
ist4Lo, ist4Hi uint32
|
|
|
|
ist5Lo, ist5Hi uint32
|
|
|
|
ist6Lo, ist6Hi uint32
|
|
|
|
ist7Lo, ist7Hi uint32
|
|
|
|
_ [2]uint32
|
|
|
|
_ uint16
|
|
|
|
ioPerm uint16
|
|
|
|
}
|