mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Deflake kvm_test.
PiperOrigin-RevId: 200439846 Change-Id: I9970fe0716cb02f0f41b754891d55db7e0729f56
This commit is contained in:
@@ -71,7 +71,6 @@ go_library(
|
||||
|
||||
go_test(
|
||||
name = "kvm_test",
|
||||
size = "small",
|
||||
srcs = [
|
||||
"kvm_test.go",
|
||||
"virtual_map_test.go",
|
||||
|
||||
@@ -157,7 +157,9 @@ func TestApplicationSyscall(t *testing.T) {
|
||||
FloatingPointState: dummyFPState,
|
||||
PageTables: pt,
|
||||
FullRestore: true,
|
||||
}); err != nil {
|
||||
}); err == platform.ErrContextInterrupt {
|
||||
return true // Retry.
|
||||
} else if err != nil {
|
||||
t.Errorf("application syscall with full restore failed: %v", err)
|
||||
}
|
||||
return false
|
||||
@@ -167,7 +169,9 @@ func TestApplicationSyscall(t *testing.T) {
|
||||
Registers: regs,
|
||||
FloatingPointState: dummyFPState,
|
||||
PageTables: pt,
|
||||
}); err != nil {
|
||||
}); err == platform.ErrContextInterrupt {
|
||||
return true // Retry.
|
||||
} else if err != nil {
|
||||
t.Errorf("application syscall with partial restore failed: %v", err)
|
||||
}
|
||||
return false
|
||||
@@ -182,7 +186,9 @@ func TestApplicationFault(t *testing.T) {
|
||||
FloatingPointState: dummyFPState,
|
||||
PageTables: pt,
|
||||
FullRestore: true,
|
||||
}); err != platform.ErrContextSignal || (si != nil && si.Signo != int32(syscall.SIGSEGV)) {
|
||||
}); err == platform.ErrContextInterrupt {
|
||||
return true // Retry.
|
||||
} else if err != platform.ErrContextSignal || (si != nil && si.Signo != int32(syscall.SIGSEGV)) {
|
||||
t.Errorf("application fault with full restore got (%v, %v), expected (%v, SIGSEGV)", err, si, platform.ErrContextSignal)
|
||||
}
|
||||
return false
|
||||
@@ -193,7 +199,9 @@ func TestApplicationFault(t *testing.T) {
|
||||
Registers: regs,
|
||||
FloatingPointState: dummyFPState,
|
||||
PageTables: pt,
|
||||
}); err != platform.ErrContextSignal || (si != nil && si.Signo != int32(syscall.SIGSEGV)) {
|
||||
}); err == platform.ErrContextInterrupt {
|
||||
return true // Retry.
|
||||
} else if err != platform.ErrContextSignal || (si != nil && si.Signo != int32(syscall.SIGSEGV)) {
|
||||
t.Errorf("application fault with partial restore got (%v, %v), expected (%v, SIGSEGV)", err, si, platform.ErrContextSignal)
|
||||
}
|
||||
return false
|
||||
@@ -203,15 +211,20 @@ func TestApplicationFault(t *testing.T) {
|
||||
func TestRegistersSyscall(t *testing.T) {
|
||||
applicationTest(t, true, testutil.TwiddleRegsSyscall, func(c *vCPU, regs *syscall.PtraceRegs, pt *pagetables.PageTables) bool {
|
||||
testutil.SetTestRegs(regs) // Fill values for all registers.
|
||||
if _, _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
Registers: regs,
|
||||
FloatingPointState: dummyFPState,
|
||||
PageTables: pt,
|
||||
}); 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)
|
||||
for {
|
||||
if _, _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
Registers: regs,
|
||||
FloatingPointState: dummyFPState,
|
||||
PageTables: pt,
|
||||
}); 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
|
||||
})
|
||||
@@ -220,16 +233,21 @@ func TestRegistersSyscall(t *testing.T) {
|
||||
func TestRegistersFault(t *testing.T) {
|
||||
applicationTest(t, true, testutil.TwiddleRegsFault, func(c *vCPU, regs *syscall.PtraceRegs, pt *pagetables.PageTables) bool {
|
||||
testutil.SetTestRegs(regs) // Fill values for all registers.
|
||||
if si, _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
Registers: regs,
|
||||
FloatingPointState: dummyFPState,
|
||||
PageTables: pt,
|
||||
FullRestore: true,
|
||||
}); err != platform.ErrContextSignal || si.Signo != int32(syscall.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)
|
||||
for {
|
||||
if si, _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
Registers: regs,
|
||||
FloatingPointState: dummyFPState,
|
||||
PageTables: pt,
|
||||
FullRestore: true,
|
||||
}); err == platform.ErrContextInterrupt {
|
||||
continue // Retry.
|
||||
} else if err != platform.ErrContextSignal || si.Signo != int32(syscall.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
|
||||
})
|
||||
@@ -238,16 +256,21 @@ func TestRegistersFault(t *testing.T) {
|
||||
func TestSegments(t *testing.T) {
|
||||
applicationTest(t, true, testutil.TwiddleSegments, func(c *vCPU, regs *syscall.PtraceRegs, pt *pagetables.PageTables) bool {
|
||||
testutil.SetTestSegments(regs)
|
||||
if _, _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
Registers: regs,
|
||||
FloatingPointState: dummyFPState,
|
||||
PageTables: pt,
|
||||
FullRestore: true,
|
||||
}); 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)
|
||||
for {
|
||||
if _, _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
Registers: regs,
|
||||
FloatingPointState: dummyFPState,
|
||||
PageTables: pt,
|
||||
FullRestore: true,
|
||||
}); 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
|
||||
})
|
||||
@@ -323,22 +346,32 @@ func TestInvalidate(t *testing.T) {
|
||||
var data uintptr // Used below.
|
||||
applicationTest(t, true, testutil.Touch, func(c *vCPU, regs *syscall.PtraceRegs, pt *pagetables.PageTables) bool {
|
||||
testutil.SetTouchTarget(regs, &data) // Read legitimate value.
|
||||
if _, _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
Registers: regs,
|
||||
FloatingPointState: dummyFPState,
|
||||
PageTables: pt,
|
||||
}); err != nil {
|
||||
t.Errorf("application partial restore: got %v, wanted nil", err)
|
||||
for {
|
||||
if _, _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
Registers: regs,
|
||||
FloatingPointState: dummyFPState,
|
||||
PageTables: pt,
|
||||
}); 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)
|
||||
if _, _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
Registers: regs,
|
||||
FloatingPointState: dummyFPState,
|
||||
PageTables: pt,
|
||||
Flush: true,
|
||||
}); err != platform.ErrContextSignal {
|
||||
t.Errorf("application partial restore: got %v, wanted %v", err, platform.ErrContextSignal)
|
||||
for {
|
||||
if _, _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
Registers: regs,
|
||||
FloatingPointState: dummyFPState,
|
||||
PageTables: pt,
|
||||
Flush: true,
|
||||
}); 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
|
||||
})
|
||||
@@ -355,7 +388,9 @@ func TestEmptyAddressSpace(t *testing.T) {
|
||||
Registers: regs,
|
||||
FloatingPointState: dummyFPState,
|
||||
PageTables: pt,
|
||||
}); !IsFault(err, 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", ®s)
|
||||
}
|
||||
@@ -367,7 +402,9 @@ func TestEmptyAddressSpace(t *testing.T) {
|
||||
FloatingPointState: dummyFPState,
|
||||
PageTables: pt,
|
||||
FullRestore: true,
|
||||
}); !IsFault(err, 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", ®s)
|
||||
}
|
||||
@@ -422,11 +459,10 @@ func BenchmarkApplicationSyscall(b *testing.B) {
|
||||
Registers: regs,
|
||||
FloatingPointState: dummyFPState,
|
||||
PageTables: pt,
|
||||
}); err != nil {
|
||||
if err == platform.ErrContextInterrupt {
|
||||
a++
|
||||
return true // Ignore.
|
||||
}
|
||||
}); err == platform.ErrContextInterrupt {
|
||||
a++
|
||||
return true // Ignore.
|
||||
} else if err != nil {
|
||||
b.Fatalf("benchmark failed: %v", err)
|
||||
}
|
||||
i++
|
||||
@@ -459,11 +495,10 @@ func BenchmarkWorldSwitchToUserRoundtrip(b *testing.B) {
|
||||
Registers: regs,
|
||||
FloatingPointState: dummyFPState,
|
||||
PageTables: pt,
|
||||
}); err != nil {
|
||||
if err == platform.ErrContextInterrupt {
|
||||
a++
|
||||
return true // Ignore.
|
||||
}
|
||||
}); 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
|
||||
@@ -474,6 +509,6 @@ func BenchmarkWorldSwitchToUserRoundtrip(b *testing.B) {
|
||||
return i < b.N
|
||||
})
|
||||
if a != 0 {
|
||||
b.Logf("EAGAIN occurred %d times (in %d iterations).", a, a+i)
|
||||
b.Logf("ErrContextInterrupt occurred %d times (in %d iterations).", a, a+i)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,14 +22,16 @@ import (
|
||||
)
|
||||
|
||||
type checker struct {
|
||||
ok bool
|
||||
ok bool
|
||||
accessType usermem.AccessType
|
||||
}
|
||||
|
||||
func (c *checker) Contains(addr uintptr) func(virtualRegion) {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,7 +40,7 @@ func TestParseMaps(t *testing.T) {
|
||||
c := new(checker)
|
||||
|
||||
// Simple test.
|
||||
if err := applyVirtualRegions(c.Contains(0)); err != nil {
|
||||
if err := applyVirtualRegions(c.Containing(0)); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
@@ -52,7 +54,7 @@ func TestParseMaps(t *testing.T) {
|
||||
}
|
||||
|
||||
// Re-parse maps.
|
||||
if err := applyVirtualRegions(c.Contains(addr)); err != nil {
|
||||
if err := applyVirtualRegions(c.Containing(addr)); err != nil {
|
||||
syscall.RawSyscall(syscall.SYS_MUNMAP, addr, usermem.PageSize, 0)
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
@@ -63,16 +65,29 @@ func TestParseMaps(t *testing.T) {
|
||||
t.Fatalf("updated map does not contain 0x%08x, expected true", addr)
|
||||
}
|
||||
|
||||
// Unmap the region.
|
||||
syscall.RawSyscall(syscall.SYS_MUNMAP, addr, usermem.PageSize, 0)
|
||||
// Map the region as PROT_NONE.
|
||||
newAddr, _, errno := syscall.RawSyscall6(
|
||||
syscall.SYS_MMAP, addr, usermem.PageSize,
|
||||
syscall.PROT_NONE,
|
||||
syscall.MAP_ANONYMOUS|syscall.MAP_FIXED|syscall.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.Contains(addr)); err != nil {
|
||||
if err := applyVirtualRegions(c.Containing(addr)); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
// Assert that it once again does _not_ contain the region.
|
||||
if c.ok {
|
||||
t.Fatalf("final map does contain 0x%08x, expected false", addr)
|
||||
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.
|
||||
syscall.RawSyscall(syscall.SYS_MUNMAP, addr, usermem.PageSize, 0)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user