summaryrefslogtreecommitdiffhomepage
path: root/pkg/sentry/platform
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/sentry/platform')
-rw-r--r--pkg/sentry/platform/BUILD22
-rw-r--r--pkg/sentry/platform/interrupt/BUILD19
-rw-r--r--pkg/sentry/platform/interrupt/interrupt_state_autogen.go3
-rw-r--r--pkg/sentry/platform/interrupt/interrupt_test.go99
-rw-r--r--pkg/sentry/platform/kvm/BUILD95
-rw-r--r--pkg/sentry/platform/kvm/bluepill_impl_amd64.s (renamed from pkg/sentry/platform/kvm/bluepill_amd64.s)70
-rw-r--r--pkg/sentry/platform/kvm/kvm_amd64_state_autogen.go7
-rw-r--r--pkg/sentry/platform/kvm/kvm_amd64_test.go51
-rw-r--r--pkg/sentry/platform/kvm/kvm_amd64_unsafe_state_autogen.go7
-rw-r--r--pkg/sentry/platform/kvm/kvm_arm64_state_autogen.go7
-rw-r--r--pkg/sentry/platform/kvm/kvm_arm64_test.go31
-rw-r--r--pkg/sentry/platform/kvm/kvm_arm64_unsafe_state_autogen.go7
-rw-r--r--pkg/sentry/platform/kvm/kvm_state_autogen.go3
-rw-r--r--pkg/sentry/platform/kvm/kvm_test.go527
-rw-r--r--pkg/sentry/platform/kvm/kvm_unsafe_state_autogen.go8
-rw-r--r--pkg/sentry/platform/kvm/testutil/BUILD17
-rw-r--r--pkg/sentry/platform/kvm/testutil/testutil.go72
-rw-r--r--pkg/sentry/platform/kvm/testutil/testutil_amd64.go139
-rw-r--r--pkg/sentry/platform/kvm/testutil/testutil_amd64.s98
-rw-r--r--pkg/sentry/platform/kvm/testutil/testutil_arm64.go69
-rw-r--r--pkg/sentry/platform/kvm/testutil/testutil_arm64.s134
-rw-r--r--pkg/sentry/platform/kvm/virtual_map_test.go93
-rw-r--r--pkg/sentry/platform/platform_state_autogen.go3
-rw-r--r--pkg/sentry/platform/ptrace/BUILD40
-rw-r--r--pkg/sentry/platform/ptrace/ptrace_amd64_state_autogen.go5
-rw-r--r--pkg/sentry/platform/ptrace/ptrace_arm64_state_autogen.go5
-rw-r--r--pkg/sentry/platform/ptrace/ptrace_arm64_unsafe_state_autogen.go5
-rw-r--r--pkg/sentry/platform/ptrace/ptrace_linux_state_autogen.go5
-rw-r--r--pkg/sentry/platform/ptrace/ptrace_linux_unsafe_state_autogen.go6
-rw-r--r--pkg/sentry/platform/ptrace/ptrace_state_autogen.go3
-rw-r--r--pkg/sentry/platform/ptrace/ptrace_unsafe_state_autogen.go6
31 files changed, 150 insertions, 1506 deletions
diff --git a/pkg/sentry/platform/BUILD b/pkg/sentry/platform/BUILD
deleted file mode 100644
index db7d55ef2..000000000
--- a/pkg/sentry/platform/BUILD
+++ /dev/null
@@ -1,22 +0,0 @@
-load("//tools:defs.bzl", "go_library")
-
-package(licenses = ["notice"])
-
-go_library(
- name = "platform",
- srcs = [
- "context.go",
- "mmap_min_addr.go",
- "platform.go",
- ],
- visibility = ["//pkg/sentry:internal"],
- deps = [
- "//pkg/abi/linux",
- "//pkg/context",
- "//pkg/seccomp",
- "//pkg/sentry/arch",
- "//pkg/sentry/hostmm",
- "//pkg/sentry/memmap",
- "//pkg/usermem",
- ],
-)
diff --git a/pkg/sentry/platform/interrupt/BUILD b/pkg/sentry/platform/interrupt/BUILD
deleted file mode 100644
index 83b385f14..000000000
--- a/pkg/sentry/platform/interrupt/BUILD
+++ /dev/null
@@ -1,19 +0,0 @@
-load("//tools:defs.bzl", "go_library", "go_test")
-
-package(licenses = ["notice"])
-
-go_library(
- name = "interrupt",
- srcs = [
- "interrupt.go",
- ],
- visibility = ["//pkg/sentry:internal"],
- deps = ["//pkg/sync"],
-)
-
-go_test(
- name = "interrupt_test",
- size = "small",
- srcs = ["interrupt_test.go"],
- library = ":interrupt",
-)
diff --git a/pkg/sentry/platform/interrupt/interrupt_state_autogen.go b/pkg/sentry/platform/interrupt/interrupt_state_autogen.go
new file mode 100644
index 000000000..1336e5f01
--- /dev/null
+++ b/pkg/sentry/platform/interrupt/interrupt_state_autogen.go
@@ -0,0 +1,3 @@
+// automatically generated by stateify.
+
+package interrupt
diff --git a/pkg/sentry/platform/interrupt/interrupt_test.go b/pkg/sentry/platform/interrupt/interrupt_test.go
deleted file mode 100644
index 0ecdf6e7a..000000000
--- a/pkg/sentry/platform/interrupt/interrupt_test.go
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// 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.
-
-package interrupt
-
-import (
- "testing"
-)
-
-type countingReceiver struct {
- interrupts int
-}
-
-// NotifyInterrupt implements Receiver.NotifyInterrupt.
-func (r *countingReceiver) NotifyInterrupt() {
- r.interrupts++
-}
-
-func TestSingleInterruptBeforeEnable(t *testing.T) {
- var (
- f Forwarder
- r countingReceiver
- )
- f.NotifyInterrupt()
- // The interrupt should cause the first Enable to fail.
- if f.Enable(&r) {
- f.Disable()
- t.Fatalf("Enable: got true, wanted false")
- }
- // The failing Enable "acknowledges" the interrupt, allowing future Enables
- // to succeed.
- if !f.Enable(&r) {
- t.Fatalf("Enable: got false, wanted true")
- }
- f.Disable()
-}
-
-func TestMultipleInterruptsBeforeEnable(t *testing.T) {
- var (
- f Forwarder
- r countingReceiver
- )
- f.NotifyInterrupt()
- f.NotifyInterrupt()
- // The interrupts should cause the first Enable to fail.
- if f.Enable(&r) {
- f.Disable()
- t.Fatalf("Enable: got true, wanted false")
- }
- // Interrupts are deduplicated while the Forwarder is disabled, so the
- // failing Enable "acknowledges" all interrupts, allowing future Enables to
- // succeed.
- if !f.Enable(&r) {
- t.Fatalf("Enable: got false, wanted true")
- }
- f.Disable()
-}
-
-func TestSingleInterruptAfterEnable(t *testing.T) {
- var (
- f Forwarder
- r countingReceiver
- )
- if !f.Enable(&r) {
- t.Fatalf("Enable: got false, wanted true")
- }
- defer f.Disable()
- f.NotifyInterrupt()
- if r.interrupts != 1 {
- t.Errorf("interrupts: got %d, wanted 1", r.interrupts)
- }
-}
-
-func TestMultipleInterruptsAfterEnable(t *testing.T) {
- var (
- f Forwarder
- r countingReceiver
- )
- if !f.Enable(&r) {
- t.Fatalf("Enable: got false, wanted true")
- }
- defer f.Disable()
- f.NotifyInterrupt()
- f.NotifyInterrupt()
- if r.interrupts != 2 {
- t.Errorf("interrupts: got %d, wanted 2", r.interrupts)
- }
-}
diff --git a/pkg/sentry/platform/kvm/BUILD b/pkg/sentry/platform/kvm/BUILD
deleted file mode 100644
index 4f9e781af..000000000
--- a/pkg/sentry/platform/kvm/BUILD
+++ /dev/null
@@ -1,95 +0,0 @@
-load("//tools:defs.bzl", "go_library", "go_test")
-
-package(licenses = ["notice"])
-
-go_library(
- name = "kvm",
- srcs = [
- "address_space.go",
- "bluepill.go",
- "bluepill_allocator.go",
- "bluepill_amd64.go",
- "bluepill_amd64_unsafe.go",
- "bluepill_arm64.go",
- "bluepill_arm64.s",
- "bluepill_arm64_unsafe.go",
- "bluepill_fault.go",
- "bluepill_impl_amd64.s",
- "bluepill_unsafe.go",
- "context.go",
- "filters_amd64.go",
- "filters_arm64.go",
- "kvm.go",
- "kvm_amd64.go",
- "kvm_amd64_unsafe.go",
- "kvm_arm64.go",
- "kvm_arm64_unsafe.go",
- "kvm_const.go",
- "kvm_const_arm64.go",
- "machine.go",
- "machine_amd64.go",
- "machine_amd64_unsafe.go",
- "machine_arm64.go",
- "machine_arm64_unsafe.go",
- "machine_unsafe.go",
- "physical_map.go",
- "physical_map_amd64.go",
- "physical_map_arm64.go",
- "virtual_map.go",
- ],
- visibility = ["//pkg/sentry:internal"],
- deps = [
- "//pkg/abi/linux",
- "//pkg/atomicbitops",
- "//pkg/context",
- "//pkg/cpuid",
- "//pkg/log",
- "//pkg/procid",
- "//pkg/ring0",
- "//pkg/ring0/pagetables",
- "//pkg/safecopy",
- "//pkg/seccomp",
- "//pkg/sentry/arch",
- "//pkg/sentry/memmap",
- "//pkg/sentry/platform",
- "//pkg/sentry/platform/interrupt",
- "//pkg/sentry/time",
- "//pkg/sync",
- "//pkg/usermem",
- "@org_golang_x_sys//unix:go_default_library",
- ],
-)
-
-go_test(
- name = "kvm_test",
- srcs = [
- "kvm_amd64_test.go",
- "kvm_arm64_test.go",
- "kvm_test.go",
- "virtual_map_test.go",
- ],
- library = ":kvm",
- tags = [
- "manual",
- "nogotsan",
- "requires-kvm",
- ],
- deps = [
- "//pkg/ring0",
- "//pkg/ring0/pagetables",
- "//pkg/sentry/arch",
- "//pkg/sentry/platform",
- "//pkg/sentry/platform/kvm/testutil",
- "//pkg/sentry/time",
- "//pkg/usermem",
- "@org_golang_x_sys//unix:go_default_library",
- ],
-)
-
-genrule(
- name = "bluepill_impl_amd64",
- srcs = ["bluepill_amd64.s"],
- outs = ["bluepill_impl_amd64.s"],
- cmd = "(echo -e '// build +amd64\\n' && $(location //pkg/ring0/gen_offsets) && cat $(SRCS)) > $@",
- tools = ["//pkg/ring0/gen_offsets"],
-)
diff --git a/pkg/sentry/platform/kvm/bluepill_amd64.s b/pkg/sentry/platform/kvm/bluepill_impl_amd64.s
index 025ea93b5..2bbf06b18 100644
--- a/pkg/sentry/platform/kvm/bluepill_amd64.s
+++ b/pkg/sentry/platform/kvm/bluepill_impl_amd64.s
@@ -1,3 +1,73 @@
+// build +amd64
+
+// Automatically generated, do not edit.
+
+// CPU offsets.
+#define CPU_REGISTERS 0x28
+#define CPU_ERROR_CODE 0x10
+#define CPU_ERROR_TYPE 0x18
+#define CPU_ENTRY 0x20
+
+// CPU entry offsets.
+#define ENTRY_SCRATCH0 0x100
+#define ENTRY_STACK_TOP 0x108
+#define ENTRY_CPU_SELF 0x110
+#define ENTRY_KERNEL_CR3 0x118
+
+// Bits.
+#define _RFLAGS_IF 0x200
+#define _RFLAGS_IOPL0 0x1000
+#define _KERNEL_FLAGS 0x02
+
+// Vectors.
+#define DivideByZero 0x00
+#define Debug 0x01
+#define NMI 0x02
+#define Breakpoint 0x03
+#define Overflow 0x04
+#define BoundRangeExceeded 0x05
+#define InvalidOpcode 0x06
+#define DeviceNotAvailable 0x07
+#define DoubleFault 0x08
+#define CoprocessorSegmentOverrun 0x09
+#define InvalidTSS 0x0a
+#define SegmentNotPresent 0x0b
+#define StackSegmentFault 0x0c
+#define GeneralProtectionFault 0x0d
+#define PageFault 0x0e
+#define X87FloatingPointException 0x10
+#define AlignmentCheck 0x11
+#define MachineCheck 0x12
+#define SIMDFloatingPointException 0x13
+#define VirtualizationException 0x14
+#define SecurityException 0x1e
+#define SyscallInt80 0x80
+#define Syscall 0x100
+
+// Ptrace registers.
+#define PTRACE_R15 0x00
+#define PTRACE_R14 0x08
+#define PTRACE_R13 0x10
+#define PTRACE_R12 0x18
+#define PTRACE_RBP 0x20
+#define PTRACE_RBX 0x28
+#define PTRACE_R11 0x30
+#define PTRACE_R10 0x38
+#define PTRACE_R9 0x40
+#define PTRACE_R8 0x48
+#define PTRACE_RAX 0x50
+#define PTRACE_RCX 0x58
+#define PTRACE_RDX 0x60
+#define PTRACE_RSI 0x68
+#define PTRACE_RDI 0x70
+#define PTRACE_ORIGRAX 0x78
+#define PTRACE_RIP 0x80
+#define PTRACE_CS 0x88
+#define PTRACE_FLAGS 0x90
+#define PTRACE_RSP 0x98
+#define PTRACE_SS 0xa0
+#define PTRACE_FS 0xa8
+#define PTRACE_GS 0xb0
// Copyright 2018 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/pkg/sentry/platform/kvm/kvm_amd64_state_autogen.go b/pkg/sentry/platform/kvm/kvm_amd64_state_autogen.go
new file mode 100644
index 000000000..a69cbee8b
--- /dev/null
+++ b/pkg/sentry/platform/kvm/kvm_amd64_state_autogen.go
@@ -0,0 +1,7 @@
+// automatically generated by stateify.
+
+// +build amd64
+// +build amd64
+// +build amd64
+
+package kvm
diff --git a/pkg/sentry/platform/kvm/kvm_amd64_test.go b/pkg/sentry/platform/kvm/kvm_amd64_test.go
deleted file mode 100644
index 76fc594a0..000000000
--- a/pkg/sentry/platform/kvm/kvm_amd64_test.go
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2020 The gVisor Authors.
-//
-// 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 amd64
-
-package kvm
-
-import (
- "testing"
-
- "gvisor.dev/gvisor/pkg/ring0"
- "gvisor.dev/gvisor/pkg/ring0/pagetables"
- "gvisor.dev/gvisor/pkg/sentry/arch"
- "gvisor.dev/gvisor/pkg/sentry/platform"
- "gvisor.dev/gvisor/pkg/sentry/platform/kvm/testutil"
-)
-
-func TestSegments(t *testing.T) {
- applicationTest(t, true, testutil.TwiddleSegments, func(c *vCPU, regs *arch.Registers, pt *pagetables.PageTables) bool {
- testutil.SetTestSegments(regs)
- for {
- var si arch.SignalInfo
- if _, err := c.SwitchToUser(ring0.SwitchOpts{
- Registers: regs,
- FloatingPointState: dummyFPState,
- PageTables: pt,
- FullRestore: true,
- }, &si); err == platform.ErrContextInterrupt {
- continue // Retry.
- } else if err != nil {
- t.Errorf("application segment check with full restore got unexpected error: %v", err)
- }
- if err := testutil.CheckTestSegments(regs); err != nil {
- t.Errorf("application segment check with full restore failed: %v", err)
- }
- break // Done.
- }
- return false
- })
-}
diff --git a/pkg/sentry/platform/kvm/kvm_amd64_unsafe_state_autogen.go b/pkg/sentry/platform/kvm/kvm_amd64_unsafe_state_autogen.go
new file mode 100644
index 000000000..a69cbee8b
--- /dev/null
+++ b/pkg/sentry/platform/kvm/kvm_amd64_unsafe_state_autogen.go
@@ -0,0 +1,7 @@
+// automatically generated by stateify.
+
+// +build amd64
+// +build amd64
+// +build amd64
+
+package kvm
diff --git a/pkg/sentry/platform/kvm/kvm_arm64_state_autogen.go b/pkg/sentry/platform/kvm/kvm_arm64_state_autogen.go
new file mode 100644
index 000000000..90183b764
--- /dev/null
+++ b/pkg/sentry/platform/kvm/kvm_arm64_state_autogen.go
@@ -0,0 +1,7 @@
+// automatically generated by stateify.
+
+// +build arm64
+// +build arm64
+// +build arm64
+
+package kvm
diff --git a/pkg/sentry/platform/kvm/kvm_arm64_test.go b/pkg/sentry/platform/kvm/kvm_arm64_test.go
deleted file mode 100644
index 0e3d84d95..000000000
--- a/pkg/sentry/platform/kvm/kvm_arm64_test.go
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2020 The gVisor Authors.
-//
-// 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 arm64
-
-package kvm
-
-import (
- "testing"
-
- "gvisor.dev/gvisor/pkg/sentry/platform/kvm/testutil"
-)
-
-func TestKernelTLS(t *testing.T) {
- bluepillTest(t, func(c *vCPU) {
- if !testutil.TLSWorks() {
- t.Errorf("tls does not work, and it should!")
- }
- })
-}
diff --git a/pkg/sentry/platform/kvm/kvm_arm64_unsafe_state_autogen.go b/pkg/sentry/platform/kvm/kvm_arm64_unsafe_state_autogen.go
new file mode 100644
index 000000000..90183b764
--- /dev/null
+++ b/pkg/sentry/platform/kvm/kvm_arm64_unsafe_state_autogen.go
@@ -0,0 +1,7 @@
+// automatically generated by stateify.
+
+// +build arm64
+// +build arm64
+// +build arm64
+
+package kvm
diff --git a/pkg/sentry/platform/kvm/kvm_state_autogen.go b/pkg/sentry/platform/kvm/kvm_state_autogen.go
new file mode 100644
index 000000000..8d85b96d0
--- /dev/null
+++ b/pkg/sentry/platform/kvm/kvm_state_autogen.go
@@ -0,0 +1,3 @@
+// automatically generated by stateify.
+
+package kvm
diff --git a/pkg/sentry/platform/kvm/kvm_test.go b/pkg/sentry/platform/kvm/kvm_test.go
deleted file mode 100644
index 6243b9a04..000000000
--- a/pkg/sentry/platform/kvm/kvm_test.go
+++ /dev/null
@@ -1,527 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// 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.
-
-package kvm
-
-import (
- "math/rand"
- "reflect"
- "sync/atomic"
- "testing"
- "time"
-
- "golang.org/x/sys/unix"
- "gvisor.dev/gvisor/pkg/ring0"
- "gvisor.dev/gvisor/pkg/ring0/pagetables"
- "gvisor.dev/gvisor/pkg/sentry/arch"
- "gvisor.dev/gvisor/pkg/sentry/platform"
- "gvisor.dev/gvisor/pkg/sentry/platform/kvm/testutil"
- ktime "gvisor.dev/gvisor/pkg/sentry/time"
- "gvisor.dev/gvisor/pkg/usermem"
-)
-
-var dummyFPState = (*byte)(arch.NewFloatingPointData())
-
-type testHarness interface {
- Errorf(format string, args ...interface{})
- Fatalf(format string, args ...interface{})
-}
-
-func kvmTest(t testHarness, setup func(*KVM), fn func(*vCPU) bool) {
- // Create the machine.
- deviceFile, err := OpenDevice()
- if err != nil {
- t.Fatalf("error opening device file: %v", err)
- }
- k, err := New(deviceFile)
- if err != nil {
- t.Fatalf("error creating KVM instance: %v", err)
- }
- defer k.machine.Destroy()
-
- // Call additional setup.
- if setup != nil {
- setup(k)
- }
-
- var c *vCPU // For recovery.
- defer func() {
- redpill()
- if c != nil {
- k.machine.Put(c)
- }
- }()
- for {
- c = k.machine.Get()
- if !fn(c) {
- break
- }
-
- // We put the vCPU here and clear the value so that the
- // deferred recovery will not re-put it above.
- k.machine.Put(c)
- c = nil
- }
-}
-
-func bluepillTest(t testHarness, fn func(*vCPU)) {
- kvmTest(t, nil, func(c *vCPU) bool {
- bluepill(c)
- fn(c)
- return false
- })
-}
-
-func TestKernelSyscall(t *testing.T) {
- bluepillTest(t, func(c *vCPU) {
- redpill() // Leave guest mode.
- if got := atomic.LoadUint32(&c.state); got != vCPUUser {
- t.Errorf("vCPU not in ready state: got %v", got)
- }
- })
-}
-
-func hostFault() {
- defer func() {
- recover()
- }()
- var foo *int
- *foo = 0
-}
-
-func TestKernelFault(t *testing.T) {
- hostFault() // Ensure recovery works.
- bluepillTest(t, func(c *vCPU) {
- hostFault()
- if got := atomic.LoadUint32(&c.state); got != vCPUUser {
- t.Errorf("vCPU not in ready state: got %v", got)
- }
- })
-}
-
-func TestKernelFloatingPoint(t *testing.T) {
- bluepillTest(t, func(c *vCPU) {
- if !testutil.FloatingPointWorks() {
- t.Errorf("floating point does not work, and it should!")
- }
- })
-}
-
-func applicationTest(t testHarness, useHostMappings bool, target func(), fn func(*vCPU, *arch.Registers, *pagetables.PageTables) bool) {
- // Initialize registers & page tables.
- var (
- regs arch.Registers
- pt *pagetables.PageTables
- )
- testutil.SetTestTarget(&regs, target)
-
- kvmTest(t, func(k *KVM) {
- // Create new page tables.
- as, _, err := k.NewAddressSpace(nil /* invalidator */)
- if err != nil {
- t.Fatalf("can't create new address space: %v", err)
- }
- pt = as.(*addressSpace).pageTables
-
- if useHostMappings {
- // Apply the physical mappings to these page tables.
- // (This is normally dangerous, since they point to
- // physical pages that may not exist. This shouldn't be
- // done for regular user code, but is fine for test
- // purposes.)
- applyPhysicalRegions(func(pr physicalRegion) bool {
- pt.Map(usermem.Addr(pr.virtual), pr.length, pagetables.MapOpts{
- AccessType: usermem.AnyAccess,
- User: true,
- }, pr.physical)
- return true // Keep iterating.
- })
- }
- }, func(c *vCPU) bool {
- // Invoke the function with the extra data.
- return fn(c, &regs, pt)
- })
-}
-
-func TestApplicationSyscall(t *testing.T) {
- applicationTest(t, true, testutil.SyscallLoop, func(c *vCPU, regs *arch.Registers, pt *pagetables.PageTables) bool {
- var si arch.SignalInfo
- if _, err := c.SwitchToUser(ring0.SwitchOpts{
- Registers: regs,
- FloatingPointState: dummyFPState,
- PageTables: pt,
- FullRestore: true,
- }, &si); err == platform.ErrContextInterrupt {
- return true // Retry.
- } else if err != nil {
- t.Errorf("application syscall with full restore failed: %v", err)
- }
- return false
- })
- applicationTest(t, true, testutil.SyscallLoop, func(c *vCPU, regs *arch.Registers, pt *pagetables.PageTables) bool {
- var si arch.SignalInfo
- if _, err := c.SwitchToUser(ring0.SwitchOpts{
- Registers: regs,
- FloatingPointState: dummyFPState,
- PageTables: pt,
- }, &si); err == platform.ErrContextInterrupt {
- return true // Retry.
- } else if err != nil {
- t.Errorf("application syscall with partial restore failed: %v", err)
- }
- return false
- })
-}
-
-func TestApplicationFault(t *testing.T) {
- applicationTest(t, true, testutil.Touch, func(c *vCPU, regs *arch.Registers, pt *pagetables.PageTables) bool {
- testutil.SetTouchTarget(regs, nil) // Cause fault.
- var si arch.SignalInfo
- if _, err := c.SwitchToUser(ring0.SwitchOpts{
- Registers: regs,
- FloatingPointState: dummyFPState,
- PageTables: pt,
- FullRestore: true,
- }, &si); err == platform.ErrContextInterrupt {
- return true // Retry.
- } else if err != platform.ErrContextSignal || si.Signo != int32(unix.SIGSEGV) {
- t.Errorf("application fault with full restore got (%v, %v), expected (%v, SIGSEGV)", err, si, platform.ErrContextSignal)
- }
- return false
- })
- applicationTest(t, true, testutil.Touch, func(c *vCPU, regs *arch.Registers, pt *pagetables.PageTables) bool {
- testutil.SetTouchTarget(regs, nil) // Cause fault.
- var si arch.SignalInfo
- if _, err := c.SwitchToUser(ring0.SwitchOpts{
- Registers: regs,
- FloatingPointState: dummyFPState,
- PageTables: pt,
- }, &si); err == platform.ErrContextInterrupt {
- return true // Retry.
- } else if err != platform.ErrContextSignal || si.Signo != int32(unix.SIGSEGV) {
- t.Errorf("application fault with partial restore got (%v, %v), expected (%v, SIGSEGV)", err, si, platform.ErrContextSignal)
- }
- return false
- })
-}
-
-func TestRegistersSyscall(t *testing.T) {
- applicationTest(t, true, testutil.TwiddleRegsSyscall, func(c *vCPU, regs *arch.Registers, pt *pagetables.PageTables) bool {
- testutil.SetTestRegs(regs) // Fill values for all registers.
- for {
- var si arch.SignalInfo
- if _, err := c.SwitchToUser(ring0.SwitchOpts{
- Registers: regs,
- FloatingPointState: dummyFPState,
- PageTables: pt,
- }, &si); err == platform.ErrContextInterrupt {
- continue // Retry.
- } else if err != nil {
- t.Errorf("application register check with partial restore got unexpected error: %v", err)
- }
- if err := testutil.CheckTestRegs(regs, false); err != nil {
- t.Errorf("application register check with partial restore failed: %v", err)
- }
- break // Done.
- }
- return false
- })
-}
-
-func TestRegistersFault(t *testing.T) {
- applicationTest(t, true, testutil.TwiddleRegsFault, func(c *vCPU, regs *arch.Registers, pt *pagetables.PageTables) bool {
- testutil.SetTestRegs(regs) // Fill values for all registers.
- for {
- var si arch.SignalInfo
- if _, err := c.SwitchToUser(ring0.SwitchOpts{
- Registers: regs,
- FloatingPointState: dummyFPState,
- PageTables: pt,
- FullRestore: true,
- }, &si); err == platform.ErrContextInterrupt {
- continue // Retry.
- } else if err != platform.ErrContextSignal || si.Signo != int32(unix.SIGSEGV) {
- t.Errorf("application register check with full restore got unexpected error: %v", err)
- }
- if err := testutil.CheckTestRegs(regs, true); err != nil {
- t.Errorf("application register check with full restore failed: %v", err)
- }
- break // Done.
- }
- return false
- })
-}
-
-func TestBounce(t *testing.T) {
- applicationTest(t, true, testutil.SpinLoop, func(c *vCPU, regs *arch.Registers, pt *pagetables.PageTables) bool {
- go func() {
- time.Sleep(time.Millisecond)
- c.BounceToKernel()
- }()
- var si arch.SignalInfo
- if _, err := c.SwitchToUser(ring0.SwitchOpts{
- Registers: regs,
- FloatingPointState: dummyFPState,
- PageTables: pt,
- }, &si); err != platform.ErrContextInterrupt {
- t.Errorf("application partial restore: got %v, wanted %v", err, platform.ErrContextInterrupt)
- }
- return false
- })
- applicationTest(t, true, testutil.SpinLoop, func(c *vCPU, regs *arch.Registers, pt *pagetables.PageTables) bool {
- go func() {
- time.Sleep(time.Millisecond)
- c.BounceToKernel()
- }()
- var si arch.SignalInfo
- if _, err := c.SwitchToUser(ring0.SwitchOpts{
- Registers: regs,
- FloatingPointState: dummyFPState,
- PageTables: pt,
- FullRestore: true,
- }, &si); err != platform.ErrContextInterrupt {
- t.Errorf("application full restore: got %v, wanted %v", err, platform.ErrContextInterrupt)
- }
- return false
- })
-}
-
-func TestBounceStress(t *testing.T) {
- applicationTest(t, true, testutil.SpinLoop, func(c *vCPU, regs *arch.Registers, pt *pagetables.PageTables) bool {
- randomSleep := func() {
- // O(hundreds of microseconds) is appropriate to ensure
- // different overlaps and different schedules.
- if n := rand.Intn(1000); n > 100 {
- time.Sleep(time.Duration(n) * time.Microsecond)
- }
- }
- for i := 0; i < 1000; i++ {
- // Start an asynchronously executing goroutine that
- // calls Bounce at pseudo-random point in time.
- // This should wind up calling Bounce when the
- // kernel is in various stages of the switch.
- go func() {
- randomSleep()
- c.BounceToKernel()
- }()
- randomSleep()
- var si arch.SignalInfo
- if _, err := c.SwitchToUser(ring0.SwitchOpts{
- Registers: regs,
- FloatingPointState: dummyFPState,
- PageTables: pt,
- }, &si); err != platform.ErrContextInterrupt {
- t.Errorf("application partial restore: got %v, wanted %v", err, platform.ErrContextInterrupt)
- }
- c.unlock()
- randomSleep()
- c.lock()
- }
- return false
- })
-}
-
-func TestInvalidate(t *testing.T) {
- var data uintptr // Used below.
- applicationTest(t, true, testutil.Touch, func(c *vCPU, regs *arch.Registers, pt *pagetables.PageTables) bool {
- testutil.SetTouchTarget(regs, &data) // Read legitimate value.
- for {
- var si arch.SignalInfo
- if _, err := c.SwitchToUser(ring0.SwitchOpts{
- Registers: regs,
- FloatingPointState: dummyFPState,
- PageTables: pt,
- }, &si); err == platform.ErrContextInterrupt {
- continue // Retry.
- } else if err != nil {
- t.Errorf("application partial restore: got %v, wanted nil", err)
- }
- break // Done.
- }
- // Unmap the page containing data & invalidate.
- pt.Unmap(usermem.Addr(reflect.ValueOf(&data).Pointer() & ^uintptr(usermem.PageSize-1)), usermem.PageSize)
- for {
- var si arch.SignalInfo
- if _, err := c.SwitchToUser(ring0.SwitchOpts{
- Registers: regs,
- FloatingPointState: dummyFPState,
- PageTables: pt,
- Flush: true,
- }, &si); err == platform.ErrContextInterrupt {
- continue // Retry.
- } else if err != platform.ErrContextSignal {
- t.Errorf("application partial restore: got %v, wanted %v", err, platform.ErrContextSignal)
- }
- break // Success.
- }
- return false
- })
-}
-
-// IsFault returns true iff the given signal represents a fault.
-func IsFault(err error, si *arch.SignalInfo) bool {
- return err == platform.ErrContextSignal && si.Signo == int32(unix.SIGSEGV)
-}
-
-func TestEmptyAddressSpace(t *testing.T) {
- applicationTest(t, false, testutil.SyscallLoop, func(c *vCPU, regs *arch.Registers, pt *pagetables.PageTables) bool {
- var si arch.SignalInfo
- if _, err := c.SwitchToUser(ring0.SwitchOpts{
- Registers: regs,
- FloatingPointState: dummyFPState,
- PageTables: pt,
- }, &si); err == platform.ErrContextInterrupt {
- return true // Retry.
- } else if !IsFault(err, &si) {
- t.Errorf("first fault with partial restore failed got %v", err)
- t.Logf("registers: %#v", &regs)
- }
- return false
- })
- applicationTest(t, false, testutil.SyscallLoop, func(c *vCPU, regs *arch.Registers, pt *pagetables.PageTables) bool {
- var si arch.SignalInfo
- if _, err := c.SwitchToUser(ring0.SwitchOpts{
- Registers: regs,
- FloatingPointState: dummyFPState,
- PageTables: pt,
- FullRestore: true,
- }, &si); err == platform.ErrContextInterrupt {
- return true // Retry.
- } else if !IsFault(err, &si) {
- t.Errorf("first fault with full restore failed got %v", err)
- t.Logf("registers: %#v", &regs)
- }
- return false
- })
-}
-
-func TestWrongVCPU(t *testing.T) {
- kvmTest(t, nil, func(c1 *vCPU) bool {
- kvmTest(t, nil, func(c2 *vCPU) bool {
- // Basic test, one then the other.
- bluepill(c1)
- bluepill(c2)
- if c1.guestExits == 0 {
- // Check: vCPU1 will exit due to redpill() in bluepill(c2).
- // Don't allow the test to proceed if this fails.
- t.Fatalf("wrong vCPU#1 exits: vCPU1=%+v,vCPU2=%+v", c1, c2)
- }
-
- // Alternate vCPUs; we expect to need to trigger the
- // wrong vCPU path on each switch.
- for i := 0; i < 100; i++ {
- bluepill(c1)
- bluepill(c2)
- }
- if count := c1.guestExits; count < 90 {
- t.Errorf("wrong vCPU#1 exits: vCPU1=%+v,vCPU2=%+v", c1, c2)
- }
- if count := c2.guestExits; count < 90 {
- t.Errorf("wrong vCPU#2 exits: vCPU1=%+v,vCPU2=%+v", c1, c2)
- }
- return false
- })
- return false
- })
- kvmTest(t, nil, func(c1 *vCPU) bool {
- kvmTest(t, nil, func(c2 *vCPU) bool {
- bluepill(c1)
- bluepill(c2)
- return false
- })
- return false
- })
-}
-
-func TestRdtsc(t *testing.T) {
- var i int // Iteration count.
- kvmTest(t, nil, func(c *vCPU) bool {
- start := ktime.Rdtsc()
- bluepill(c)
- guest := ktime.Rdtsc()
- redpill()
- end := ktime.Rdtsc()
- if start > guest || guest > end {
- t.Errorf("inconsistent time: start=%d, guest=%d, end=%d", start, guest, end)
- }
- i++
- return i < 100
- })
-}
-
-func BenchmarkApplicationSyscall(b *testing.B) {
- var (
- i int // Iteration includes machine.Get() / machine.Put().
- a int // Count for ErrContextInterrupt.
- )
- applicationTest(b, true, testutil.SyscallLoop, func(c *vCPU, regs *arch.Registers, pt *pagetables.PageTables) bool {
- var si arch.SignalInfo
- if _, err := c.SwitchToUser(ring0.SwitchOpts{
- Registers: regs,
- FloatingPointState: dummyFPState,
- PageTables: pt,
- }, &si); err == platform.ErrContextInterrupt {
- a++
- return true // Ignore.
- } else if err != nil {
- b.Fatalf("benchmark failed: %v", err)
- }
- i++
- return i < b.N
- })
- if a != 0 {
- b.Logf("ErrContextInterrupt occurred %d times (in %d iterations).", a, a+i)
- }
-}
-
-func BenchmarkKernelSyscall(b *testing.B) {
- // Note that the target passed here is irrelevant, we never execute SwitchToUser.
- applicationTest(b, true, testutil.Getpid, func(c *vCPU, regs *arch.Registers, pt *pagetables.PageTables) bool {
- // iteration does not include machine.Get() / machine.Put().
- for i := 0; i < b.N; i++ {
- testutil.Getpid()
- }
- return false
- })
-}
-
-func BenchmarkWorldSwitchToUserRoundtrip(b *testing.B) {
- // see BenchmarkApplicationSyscall.
- var (
- i int
- a int
- )
- applicationTest(b, true, testutil.SyscallLoop, func(c *vCPU, regs *arch.Registers, pt *pagetables.PageTables) bool {
- var si arch.SignalInfo
- if _, err := c.SwitchToUser(ring0.SwitchOpts{
- Registers: regs,
- FloatingPointState: dummyFPState,
- PageTables: pt,
- }, &si); err == platform.ErrContextInterrupt {
- a++
- return true // Ignore.
- } else if err != nil {
- b.Fatalf("benchmark failed: %v", err)
- }
- // This will intentionally cause the world switch. By executing
- // a host syscall here, we force the transition between guest
- // and host mode.
- testutil.Getpid()
- i++
- return i < b.N
- })
- if a != 0 {
- b.Logf("ErrContextInterrupt occurred %d times (in %d iterations).", a, a+i)
- }
-}
diff --git a/pkg/sentry/platform/kvm/kvm_unsafe_state_autogen.go b/pkg/sentry/platform/kvm/kvm_unsafe_state_autogen.go
new file mode 100644
index 000000000..a6d639a63
--- /dev/null
+++ b/pkg/sentry/platform/kvm/kvm_unsafe_state_autogen.go
@@ -0,0 +1,8 @@
+// automatically generated by stateify.
+
+// +build go1.12
+// +build !go1.18
+// +build go1.12
+// +build !go1.18
+
+package kvm
diff --git a/pkg/sentry/platform/kvm/testutil/BUILD b/pkg/sentry/platform/kvm/testutil/BUILD
deleted file mode 100644
index f7feb8683..000000000
--- a/pkg/sentry/platform/kvm/testutil/BUILD
+++ /dev/null
@@ -1,17 +0,0 @@
-load("//tools:defs.bzl", "go_library")
-
-package(licenses = ["notice"])
-
-go_library(
- name = "testutil",
- testonly = 1,
- srcs = [
- "testutil.go",
- "testutil_amd64.go",
- "testutil_amd64.s",
- "testutil_arm64.go",
- "testutil_arm64.s",
- ],
- visibility = ["//pkg/sentry/platform/kvm:__pkg__"],
- deps = ["//pkg/sentry/arch"],
-)
diff --git a/pkg/sentry/platform/kvm/testutil/testutil.go b/pkg/sentry/platform/kvm/testutil/testutil.go
deleted file mode 100644
index 5c1efa0fd..000000000
--- a/pkg/sentry/platform/kvm/testutil/testutil.go
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// 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.
-
-// Package testutil provides common assembly stubs for testing.
-package testutil
-
-import (
- "fmt"
- "strings"
-)
-
-// Getpid executes a trivial system call.
-func Getpid()
-
-// Touch touches the value in the first register.
-func Touch()
-
-// SyscallLoop executes a syscall and loops.
-func SyscallLoop()
-
-// SpinLoop spins on the CPU.
-func SpinLoop()
-
-// HaltLoop immediately halts and loops.
-func HaltLoop()
-
-// TwiddleRegsFault twiddles registers then faults.
-func TwiddleRegsFault()
-
-// TwiddleRegsSyscall twiddles registers then executes a syscall.
-func TwiddleRegsSyscall()
-
-// FloatingPointWorks is a floating point test.
-//
-// It returns true or false.
-func FloatingPointWorks() bool
-
-// RegisterMismatchError is used for checking registers.
-type RegisterMismatchError []string
-
-// Error returns a human-readable error.
-func (r RegisterMismatchError) Error() string {
- return strings.Join([]string(r), ";")
-}
-
-// addRegisterMisatch allows simple chaining of register mismatches.
-func addRegisterMismatch(err error, reg string, got, expected interface{}) error {
- errStr := fmt.Sprintf("%s got %08x, expected %08x", reg, got, expected)
- switch r := err.(type) {
- case nil:
- // Return a new register mismatch.
- return RegisterMismatchError{errStr}
- case RegisterMismatchError:
- // Append the error.
- r = append(r, errStr)
- return r
- default:
- // Leave as is.
- return err
- }
-}
diff --git a/pkg/sentry/platform/kvm/testutil/testutil_amd64.go b/pkg/sentry/platform/kvm/testutil/testutil_amd64.go
deleted file mode 100644
index 8048eedec..000000000
--- a/pkg/sentry/platform/kvm/testutil/testutil_amd64.go
+++ /dev/null
@@ -1,139 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// 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 amd64
-
-package testutil
-
-import (
- "reflect"
-
- "gvisor.dev/gvisor/pkg/sentry/arch"
-)
-
-// TwiddleSegments reads segments into known registers.
-func TwiddleSegments()
-
-// SetTestTarget sets the rip appropriately.
-func SetTestTarget(regs *arch.Registers, fn func()) {
- regs.Rip = uint64(reflect.ValueOf(fn).Pointer())
-}
-
-// SetTouchTarget sets rax appropriately.
-func SetTouchTarget(regs *arch.Registers, target *uintptr) {
- if target != nil {
- regs.Rax = uint64(reflect.ValueOf(target).Pointer())
- } else {
- regs.Rax = 0
- }
-}
-
-// RewindSyscall rewinds a syscall RIP.
-func RewindSyscall(regs *arch.Registers) {
- regs.Rip -= 2
-}
-
-// SetTestRegs initializes registers to known values.
-func SetTestRegs(regs *arch.Registers) {
- regs.R15 = 0x15
- regs.R14 = 0x14
- regs.R13 = 0x13
- regs.R12 = 0x12
- regs.Rbp = 0xb9
- regs.Rbx = 0xb4
- regs.R11 = 0x11
- regs.R10 = 0x10
- regs.R9 = 0x09
- regs.R8 = 0x08
- regs.Rax = 0x44
- regs.Rcx = 0xc4
- regs.Rdx = 0xd4
- regs.Rsi = 0x51
- regs.Rdi = 0xd1
- regs.Rsp = 0x59
-}
-
-// CheckTestRegs checks that registers were twiddled per TwiddleRegs.
-func CheckTestRegs(regs *arch.Registers, full bool) (err error) {
- if need := ^uint64(0x15); regs.R15 != need {
- err = addRegisterMismatch(err, "R15", regs.R15, need)
- }
- if need := ^uint64(0x14); regs.R14 != need {
- err = addRegisterMismatch(err, "R14", regs.R14, need)
- }
- if need := ^uint64(0x13); regs.R13 != need {
- err = addRegisterMismatch(err, "R13", regs.R13, need)
- }
- if need := ^uint64(0x12); regs.R12 != need {
- err = addRegisterMismatch(err, "R12", regs.R12, need)
- }
- if need := ^uint64(0xb9); regs.Rbp != need {
- err = addRegisterMismatch(err, "Rbp", regs.Rbp, need)
- }
- if need := ^uint64(0xb4); regs.Rbx != need {
- err = addRegisterMismatch(err, "Rbx", regs.Rbx, need)
- }
- if need := ^uint64(0x10); regs.R10 != need {
- err = addRegisterMismatch(err, "R10", regs.R10, need)
- }
- if need := ^uint64(0x09); regs.R9 != need {
- err = addRegisterMismatch(err, "R9", regs.R9, need)
- }
- if need := ^uint64(0x08); regs.R8 != need {
- err = addRegisterMismatch(err, "R8", regs.R8, need)
- }
- if need := ^uint64(0x44); regs.Rax != need {
- err = addRegisterMismatch(err, "Rax", regs.Rax, need)
- }
- if need := ^uint64(0xd4); regs.Rdx != need {
- err = addRegisterMismatch(err, "Rdx", regs.Rdx, need)
- }
- if need := ^uint64(0x51); regs.Rsi != need {
- err = addRegisterMismatch(err, "Rsi", regs.Rsi, need)
- }
- if need := ^uint64(0xd1); regs.Rdi != need {
- err = addRegisterMismatch(err, "Rdi", regs.Rdi, need)
- }
- if need := ^uint64(0x59); regs.Rsp != need {
- err = addRegisterMismatch(err, "Rsp", regs.Rsp, need)
- }
- // Rcx & R11 are ignored if !full is set.
- if need := ^uint64(0x11); full && regs.R11 != need {
- err = addRegisterMismatch(err, "R11", regs.R11, need)
- }
- if need := ^uint64(0xc4); full && regs.Rcx != need {
- err = addRegisterMismatch(err, "Rcx", regs.Rcx, need)
- }
- return
-}
-
-var fsData uint64 = 0x55
-var gsData uint64 = 0x85
-
-// SetTestSegments initializes segments to known values.
-func SetTestSegments(regs *arch.Registers) {
- regs.Fs_base = uint64(reflect.ValueOf(&fsData).Pointer())
- regs.Gs_base = uint64(reflect.ValueOf(&gsData).Pointer())
-}
-
-// CheckTestSegments checks that registers were twiddled per TwiddleSegments.
-func CheckTestSegments(regs *arch.Registers) (err error) {
- if regs.Rax != fsData {
- err = addRegisterMismatch(err, "Rax", regs.Rax, fsData)
- }
- if regs.Rbx != gsData {
- err = addRegisterMismatch(err, "Rbx", regs.Rcx, gsData)
- }
- return
-}
diff --git a/pkg/sentry/platform/kvm/testutil/testutil_amd64.s b/pkg/sentry/platform/kvm/testutil/testutil_amd64.s
deleted file mode 100644
index 491ec0c2a..000000000
--- a/pkg/sentry/platform/kvm/testutil/testutil_amd64.s
+++ /dev/null
@@ -1,98 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// 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 amd64
-
-// test_util_amd64.s provides AMD64 test functions.
-
-#include "funcdata.h"
-#include "textflag.h"
-
-TEXT ·Getpid(SB),NOSPLIT,$0
- NO_LOCAL_POINTERS
- MOVQ $39, AX // getpid
- SYSCALL
- RET
-
-TEXT ·Touch(SB),NOSPLIT,$0
-start:
- MOVQ 0(AX), BX // deref AX
- MOVQ $39, AX // getpid
- SYSCALL
- JMP start
-
-TEXT ·HaltLoop(SB),NOSPLIT,$0
-start:
- HLT
- JMP start
-
-TEXT ·SyscallLoop(SB),NOSPLIT,$0
-start:
- SYSCALL
- JMP start
-
-TEXT ·SpinLoop(SB),NOSPLIT,$0
-start:
- JMP start
-
-TEXT ·FloatingPointWorks(SB),NOSPLIT,$0-8
- NO_LOCAL_POINTERS
- MOVQ $1, AX
- MOVQ AX, X0
- MOVQ $39, AX // getpid
- SYSCALL
- MOVQ X0, AX
- CMPQ AX, $1
- SETEQ ret+0(FP)
- RET
-
-#define TWIDDLE_REGS() \
- NOTQ R15; \
- NOTQ R14; \
- NOTQ R13; \
- NOTQ R12; \
- NOTQ BP; \
- NOTQ BX; \
- NOTQ R11; \
- NOTQ R10; \
- NOTQ R9; \
- NOTQ R8; \
- NOTQ AX; \
- NOTQ CX; \
- NOTQ DX; \
- NOTQ SI; \
- NOTQ DI; \
- NOTQ SP;
-
-TEXT ·TwiddleRegsSyscall(SB),NOSPLIT,$0
- TWIDDLE_REGS()
- SYSCALL
- RET // never reached
-
-TEXT ·TwiddleRegsFault(SB),NOSPLIT,$0
- TWIDDLE_REGS()
- JMP AX // must fault
- RET // never reached
-
-#define READ_FS() BYTE $0x64; BYTE $0x48; BYTE $0x8b; BYTE $0x00;
-#define READ_GS() BYTE $0x65; BYTE $0x48; BYTE $0x8b; BYTE $0x00;
-
-TEXT ·TwiddleSegments(SB),NOSPLIT,$0
- MOVQ $0x0, AX
- READ_GS()
- MOVQ AX, BX
- MOVQ $0x0, AX
- READ_FS()
- SYSCALL
- RET // never reached
diff --git a/pkg/sentry/platform/kvm/testutil/testutil_arm64.go b/pkg/sentry/platform/kvm/testutil/testutil_arm64.go
deleted file mode 100644
index c5235ca9d..000000000
--- a/pkg/sentry/platform/kvm/testutil/testutil_arm64.go
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2019 The gVisor Authors.
-//
-// 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 arm64
-
-package testutil
-
-import (
- "fmt"
- "reflect"
-
- "gvisor.dev/gvisor/pkg/sentry/arch"
-)
-
-// TLSWorks is a tls test.
-//
-// It returns true or false.
-func TLSWorks() bool
-
-// SetTestTarget sets the rip appropriately.
-func SetTestTarget(regs *arch.Registers, fn func()) {
- regs.Pc = uint64(reflect.ValueOf(fn).Pointer())
-}
-
-// SetTouchTarget sets rax appropriately.
-func SetTouchTarget(regs *arch.Registers, target *uintptr) {
- if target != nil {
- regs.Regs[8] = uint64(reflect.ValueOf(target).Pointer())
- } else {
- regs.Regs[8] = 0
- }
-}
-
-// RewindSyscall rewinds a syscall RIP.
-func RewindSyscall(regs *arch.Registers) {
- regs.Pc -= 4
-}
-
-// SetTestRegs initializes registers to known values.
-func SetTestRegs(regs *arch.Registers) {
- for i := 0; i <= 30; i++ {
- regs.Regs[i] = uint64(i) + 1
- }
-}
-
-// CheckTestRegs checks that registers were twiddled per TwiddleRegs.
-func CheckTestRegs(regs *arch.Registers, full bool) (err error) {
- for i := 0; i <= 30; i++ {
- if need := ^uint64(i + 1); regs.Regs[i] != need {
- err = addRegisterMismatch(err, fmt.Sprintf("R%d", i), regs.Regs[i], need)
- }
- }
- // Check tls.
- if need := ^uint64(11); regs.TPIDR_EL0 != need {
- err = addRegisterMismatch(err, "tpdir_el0", regs.TPIDR_EL0, need)
- }
- return
-}
diff --git a/pkg/sentry/platform/kvm/testutil/testutil_arm64.s b/pkg/sentry/platform/kvm/testutil/testutil_arm64.s
deleted file mode 100644
index 7348c29a5..000000000
--- a/pkg/sentry/platform/kvm/testutil/testutil_arm64.s
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright 2019 The gVisor Authors.
-//
-// 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 arm64
-
-// test_util_arm64.s provides ARM64 test functions.
-
-#include "funcdata.h"
-#include "textflag.h"
-
-#define SYS_GETPID 172
-
-// This function simulates the getpid syscall.
-TEXT ·Getpid(SB),NOSPLIT,$0
- NO_LOCAL_POINTERS
- MOVD $SYS_GETPID, R8
- SVC
- RET
-
-TEXT ·Touch(SB),NOSPLIT,$0
-start:
- MOVD 0(R8), R1
- MOVD $SYS_GETPID, R8 // getpid
- SVC
- B start
-
-TEXT ·HaltLoop(SB),NOSPLIT,$0
-start:
- HLT
- B start
-
-// This function simulates a loop of syscall.
-TEXT ·SyscallLoop(SB),NOSPLIT,$0
-start:
- SVC
- B start
-
-TEXT ·SpinLoop(SB),NOSPLIT,$0
-start:
- B start
-
-TEXT ·TLSWorks(SB),NOSPLIT,$0-8
- NO_LOCAL_POINTERS
- MOVD $0x6789, R5
- MSR R5, TPIDR_EL0
- MOVD $SYS_GETPID, R8 // getpid
- SVC
- MRS TPIDR_EL0, R6
- CMP R5, R6
- BNE isNaN
- MOVD $1, R0
- MOVD R0, ret+0(FP)
- RET
-isNaN:
- MOVD $0, ret+0(FP)
- RET
-
-TEXT ·FloatingPointWorks(SB),NOSPLIT,$0-8
- NO_LOCAL_POINTERS
- // gc will touch fpsimd, so we should test it.
- // such as in <runtime.deductSweepCredit>.
- FMOVD $(9.9), F0
- MOVD $SYS_GETPID, R8 // getpid
- SVC
- FMOVD $(9.9), F1
- FCMPD F0, F1
- BNE isNaN
- MOVD $1, R0
- MOVD R0, ret+0(FP)
- RET
-isNaN:
- MOVD $0, ret+0(FP)
- RET
-
-// MVN: bitwise logical NOT
-// This case simulates an application that modified R0-R30.
-#define TWIDDLE_REGS() \
- MVN R0, R0; \
- MVN R1, R1; \
- MVN R2, R2; \
- MVN R3, R3; \
- MVN R4, R4; \
- MVN R5, R5; \
- MVN R6, R6; \
- MVN R7, R7; \
- MVN R8, R8; \
- MVN R9, R9; \
- MVN R10, R10; \
- MVN R11, R11; \
- MVN R12, R12; \
- MVN R13, R13; \
- MVN R14, R14; \
- MVN R15, R15; \
- MVN R16, R16; \
- MVN R17, R17; \
- MVN R18_PLATFORM, R18_PLATFORM; \
- MVN R19, R19; \
- MVN R20, R20; \
- MVN R21, R21; \
- MVN R22, R22; \
- MVN R23, R23; \
- MVN R24, R24; \
- MVN R25, R25; \
- MVN R26, R26; \
- MVN R27, R27; \
- MVN g, g; \
- MVN R29, R29; \
- MVN R30, R30;
-
-TEXT ·TwiddleRegsSyscall(SB),NOSPLIT,$0
- TWIDDLE_REGS()
- MSR R10, TPIDR_EL0
- // Trapped in el0_svc.
- SVC
- RET // never reached
-
-TEXT ·TwiddleRegsFault(SB),NOSPLIT,$0
- TWIDDLE_REGS()
- MSR R10, TPIDR_EL0
- // Trapped in el0_ia.
- // Branch to Register branches unconditionally to an address in <Rn>.
- JMP (R6) // <=> br x6, must fault
- RET // never reached
diff --git a/pkg/sentry/platform/kvm/virtual_map_test.go b/pkg/sentry/platform/kvm/virtual_map_test.go
deleted file mode 100644
index 9b4545fdd..000000000
--- a/pkg/sentry/platform/kvm/virtual_map_test.go
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright 2018 The gVisor Authors.
-//
-// 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.
-
-package kvm
-
-import (
- "testing"
-
- "golang.org/x/sys/unix"
- "gvisor.dev/gvisor/pkg/usermem"
-)
-
-type checker struct {
- ok bool
- accessType usermem.AccessType
-}
-
-func (c *checker) Containing(addr uintptr) func(virtualRegion) {
- c.ok = false // Reset for below calls.
- return func(vr virtualRegion) {
- if vr.virtual <= addr && addr < vr.virtual+vr.length {
- c.ok = true
- c.accessType = vr.accessType
- }
- }
-}
-
-func TestParseMaps(t *testing.T) {
- c := new(checker)
-
- // Simple test.
- if err := applyVirtualRegions(c.Containing(0)); err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
-
- // MMap a new page.
- addr, _, errno := unix.RawSyscall6(
- unix.SYS_MMAP, 0, usermem.PageSize,
- unix.PROT_READ|unix.PROT_WRITE,
- unix.MAP_ANONYMOUS|unix.MAP_PRIVATE, 0, 0)
- if errno != 0 {
- t.Fatalf("unexpected map error: %v", errno)
- }
-
- // Re-parse maps.
- if err := applyVirtualRegions(c.Containing(addr)); err != nil {
- unix.RawSyscall(unix.SYS_MUNMAP, addr, usermem.PageSize, 0)
- t.Fatalf("unexpected error: %v", err)
- }
-
- // Assert that it now does contain the region.
- if !c.ok {
- unix.RawSyscall(unix.SYS_MUNMAP, addr, usermem.PageSize, 0)
- t.Fatalf("updated map does not contain 0x%08x, expected true", addr)
- }
-
- // Map the region as PROT_NONE.
- newAddr, _, errno := unix.RawSyscall6(
- unix.SYS_MMAP, addr, usermem.PageSize,
- unix.PROT_NONE,
- unix.MAP_ANONYMOUS|unix.MAP_FIXED|unix.MAP_PRIVATE, 0, 0)
- if errno != 0 {
- t.Fatalf("unexpected map error: %v", errno)
- }
- if newAddr != addr {
- t.Fatalf("unable to remap address: got 0x%08x, wanted 0x%08x", newAddr, addr)
- }
-
- // Re-parse maps.
- if err := applyVirtualRegions(c.Containing(addr)); err != nil {
- t.Fatalf("unexpected error: %v", err)
- }
- if !c.ok {
- t.Fatalf("final map does not contain 0x%08x, expected true", addr)
- }
- if c.accessType.Read || c.accessType.Write || c.accessType.Execute {
- t.Fatalf("final map has incorrect permissions for 0x%08x", addr)
- }
-
- // Unmap the region.
- unix.RawSyscall(unix.SYS_MUNMAP, addr, usermem.PageSize, 0)
-}
diff --git a/pkg/sentry/platform/platform_state_autogen.go b/pkg/sentry/platform/platform_state_autogen.go
new file mode 100644
index 000000000..7a4d04589
--- /dev/null
+++ b/pkg/sentry/platform/platform_state_autogen.go
@@ -0,0 +1,3 @@
+// automatically generated by stateify.
+
+package platform
diff --git a/pkg/sentry/platform/ptrace/BUILD b/pkg/sentry/platform/ptrace/BUILD
deleted file mode 100644
index fc43cc3c0..000000000
--- a/pkg/sentry/platform/ptrace/BUILD
+++ /dev/null
@@ -1,40 +0,0 @@
-load("//tools:defs.bzl", "go_library")
-
-package(licenses = ["notice"])
-
-go_library(
- name = "ptrace",
- srcs = [
- "filters.go",
- "ptrace.go",
- "ptrace_amd64.go",
- "ptrace_arm64.go",
- "ptrace_arm64_unsafe.go",
- "ptrace_unsafe.go",
- "stub_amd64.s",
- "stub_arm64.s",
- "stub_unsafe.go",
- "subprocess.go",
- "subprocess_amd64.go",
- "subprocess_arm64.go",
- "subprocess_linux.go",
- "subprocess_linux_unsafe.go",
- "subprocess_unsafe.go",
- ],
- visibility = ["//:sandbox"],
- deps = [
- "//pkg/abi/linux",
- "//pkg/context",
- "//pkg/log",
- "//pkg/procid",
- "//pkg/safecopy",
- "//pkg/seccomp",
- "//pkg/sentry/arch",
- "//pkg/sentry/memmap",
- "//pkg/sentry/platform",
- "//pkg/sentry/platform/interrupt",
- "//pkg/sync",
- "//pkg/usermem",
- "@org_golang_x_sys//unix:go_default_library",
- ],
-)
diff --git a/pkg/sentry/platform/ptrace/ptrace_amd64_state_autogen.go b/pkg/sentry/platform/ptrace/ptrace_amd64_state_autogen.go
new file mode 100644
index 000000000..f730ab393
--- /dev/null
+++ b/pkg/sentry/platform/ptrace/ptrace_amd64_state_autogen.go
@@ -0,0 +1,5 @@
+// automatically generated by stateify.
+
+// +build amd64
+
+package ptrace
diff --git a/pkg/sentry/platform/ptrace/ptrace_arm64_state_autogen.go b/pkg/sentry/platform/ptrace/ptrace_arm64_state_autogen.go
new file mode 100644
index 000000000..6239d1305
--- /dev/null
+++ b/pkg/sentry/platform/ptrace/ptrace_arm64_state_autogen.go
@@ -0,0 +1,5 @@
+// automatically generated by stateify.
+
+// +build arm64
+
+package ptrace
diff --git a/pkg/sentry/platform/ptrace/ptrace_arm64_unsafe_state_autogen.go b/pkg/sentry/platform/ptrace/ptrace_arm64_unsafe_state_autogen.go
new file mode 100644
index 000000000..6239d1305
--- /dev/null
+++ b/pkg/sentry/platform/ptrace/ptrace_arm64_unsafe_state_autogen.go
@@ -0,0 +1,5 @@
+// automatically generated by stateify.
+
+// +build arm64
+
+package ptrace
diff --git a/pkg/sentry/platform/ptrace/ptrace_linux_state_autogen.go b/pkg/sentry/platform/ptrace/ptrace_linux_state_autogen.go
new file mode 100644
index 000000000..9f90aef93
--- /dev/null
+++ b/pkg/sentry/platform/ptrace/ptrace_linux_state_autogen.go
@@ -0,0 +1,5 @@
+// automatically generated by stateify.
+
+// +build linux
+
+package ptrace
diff --git a/pkg/sentry/platform/ptrace/ptrace_linux_unsafe_state_autogen.go b/pkg/sentry/platform/ptrace/ptrace_linux_unsafe_state_autogen.go
new file mode 100644
index 000000000..45d94c547
--- /dev/null
+++ b/pkg/sentry/platform/ptrace/ptrace_linux_unsafe_state_autogen.go
@@ -0,0 +1,6 @@
+// automatically generated by stateify.
+
+// +build linux
+// +build amd64 arm64
+
+package ptrace
diff --git a/pkg/sentry/platform/ptrace/ptrace_state_autogen.go b/pkg/sentry/platform/ptrace/ptrace_state_autogen.go
new file mode 100644
index 000000000..1bf0526f9
--- /dev/null
+++ b/pkg/sentry/platform/ptrace/ptrace_state_autogen.go
@@ -0,0 +1,3 @@
+// automatically generated by stateify.
+
+package ptrace
diff --git a/pkg/sentry/platform/ptrace/ptrace_unsafe_state_autogen.go b/pkg/sentry/platform/ptrace/ptrace_unsafe_state_autogen.go
new file mode 100644
index 000000000..0a0989650
--- /dev/null
+++ b/pkg/sentry/platform/ptrace/ptrace_unsafe_state_autogen.go
@@ -0,0 +1,6 @@
+// automatically generated by stateify.
+
+// +build go1.12
+// +build !go1.18
+
+package ptrace