mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
kvm: avoid siginfo allocations.
PiperOrigin-RevId: 219492587 Change-Id: I47f6fc0b74a4907ab0aff03d5f26453bdb983bb5
This commit is contained in:
@@ -29,6 +29,9 @@ type context struct {
|
||||
// machine is the parent machine, and is immutable.
|
||||
machine *machine
|
||||
|
||||
// info is the arch.SignalInfo cached for this context.
|
||||
info arch.SignalInfo
|
||||
|
||||
// interrupt is the interrupt context.
|
||||
interrupt interrupt.Forwarder
|
||||
}
|
||||
@@ -65,7 +68,7 @@ func (c *context) Switch(as platform.AddressSpace, ac arch.Context, _ int32) (*a
|
||||
}
|
||||
|
||||
// Take the blue pill.
|
||||
si, at, err := cpu.SwitchToUser(switchOpts)
|
||||
at, err := cpu.SwitchToUser(switchOpts, &c.info)
|
||||
|
||||
// Clear the address space.
|
||||
cpu.active.set(nil)
|
||||
@@ -75,7 +78,7 @@ func (c *context) Switch(as platform.AddressSpace, ac arch.Context, _ int32) (*a
|
||||
|
||||
// All done.
|
||||
c.interrupt.Disable()
|
||||
return si, at, err
|
||||
return &c.info, at, err
|
||||
}
|
||||
|
||||
// Interrupt interrupts the running context.
|
||||
|
||||
@@ -156,12 +156,13 @@ func applicationTest(t testHarness, useHostMappings bool, target func(), fn func
|
||||
|
||||
func TestApplicationSyscall(t *testing.T) {
|
||||
applicationTest(t, true, testutil.SyscallLoop, func(c *vCPU, regs *syscall.PtraceRegs, pt *pagetables.PageTables) bool {
|
||||
if _, _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
var si arch.SignalInfo
|
||||
if _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
Registers: regs,
|
||||
FloatingPointState: dummyFPState,
|
||||
PageTables: pt,
|
||||
FullRestore: true,
|
||||
}); err == platform.ErrContextInterrupt {
|
||||
}, &si); err == platform.ErrContextInterrupt {
|
||||
return true // Retry.
|
||||
} else if err != nil {
|
||||
t.Errorf("application syscall with full restore failed: %v", err)
|
||||
@@ -169,11 +170,12 @@ func TestApplicationSyscall(t *testing.T) {
|
||||
return false
|
||||
})
|
||||
applicationTest(t, true, testutil.SyscallLoop, func(c *vCPU, regs *syscall.PtraceRegs, pt *pagetables.PageTables) bool {
|
||||
if _, _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
var si arch.SignalInfo
|
||||
if _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
Registers: regs,
|
||||
FloatingPointState: dummyFPState,
|
||||
PageTables: pt,
|
||||
}); err == platform.ErrContextInterrupt {
|
||||
}, &si); err == platform.ErrContextInterrupt {
|
||||
return true // Retry.
|
||||
} else if err != nil {
|
||||
t.Errorf("application syscall with partial restore failed: %v", err)
|
||||
@@ -185,27 +187,29 @@ func TestApplicationSyscall(t *testing.T) {
|
||||
func TestApplicationFault(t *testing.T) {
|
||||
applicationTest(t, true, testutil.Touch, func(c *vCPU, regs *syscall.PtraceRegs, pt *pagetables.PageTables) bool {
|
||||
testutil.SetTouchTarget(regs, nil) // Cause fault.
|
||||
if si, _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
var si arch.SignalInfo
|
||||
if _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
Registers: regs,
|
||||
FloatingPointState: dummyFPState,
|
||||
PageTables: pt,
|
||||
FullRestore: true,
|
||||
}); err == platform.ErrContextInterrupt {
|
||||
}, &si); err == platform.ErrContextInterrupt {
|
||||
return true // Retry.
|
||||
} else if err != platform.ErrContextSignal || (si != nil && si.Signo != int32(syscall.SIGSEGV)) {
|
||||
} else if err != platform.ErrContextSignal || si.Signo != int32(syscall.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 *syscall.PtraceRegs, pt *pagetables.PageTables) bool {
|
||||
testutil.SetTouchTarget(regs, nil) // Cause fault.
|
||||
if si, _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
var si arch.SignalInfo
|
||||
if _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
Registers: regs,
|
||||
FloatingPointState: dummyFPState,
|
||||
PageTables: pt,
|
||||
}); err == platform.ErrContextInterrupt {
|
||||
}, &si); err == platform.ErrContextInterrupt {
|
||||
return true // Retry.
|
||||
} else if err != platform.ErrContextSignal || (si != nil && si.Signo != int32(syscall.SIGSEGV)) {
|
||||
} else if err != platform.ErrContextSignal || si.Signo != int32(syscall.SIGSEGV) {
|
||||
t.Errorf("application fault with partial restore got (%v, %v), expected (%v, SIGSEGV)", err, si, platform.ErrContextSignal)
|
||||
}
|
||||
return false
|
||||
@@ -216,11 +220,12 @@ 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.
|
||||
for {
|
||||
if _, _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
var si arch.SignalInfo
|
||||
if _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
Registers: regs,
|
||||
FloatingPointState: dummyFPState,
|
||||
PageTables: pt,
|
||||
}); err == platform.ErrContextInterrupt {
|
||||
}, &si); err == platform.ErrContextInterrupt {
|
||||
continue // Retry.
|
||||
} else if err != nil {
|
||||
t.Errorf("application register check with partial restore got unexpected error: %v", err)
|
||||
@@ -238,12 +243,13 @@ 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.
|
||||
for {
|
||||
if si, _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
var si arch.SignalInfo
|
||||
if _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
Registers: regs,
|
||||
FloatingPointState: dummyFPState,
|
||||
PageTables: pt,
|
||||
FullRestore: true,
|
||||
}); err == platform.ErrContextInterrupt {
|
||||
}, &si); 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)
|
||||
@@ -261,12 +267,13 @@ func TestSegments(t *testing.T) {
|
||||
applicationTest(t, true, testutil.TwiddleSegments, func(c *vCPU, regs *syscall.PtraceRegs, pt *pagetables.PageTables) bool {
|
||||
testutil.SetTestSegments(regs)
|
||||
for {
|
||||
if _, _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
var si arch.SignalInfo
|
||||
if _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
Registers: regs,
|
||||
FloatingPointState: dummyFPState,
|
||||
PageTables: pt,
|
||||
FullRestore: true,
|
||||
}); err == platform.ErrContextInterrupt {
|
||||
}, &si); err == platform.ErrContextInterrupt {
|
||||
continue // Retry.
|
||||
} else if err != nil {
|
||||
t.Errorf("application segment check with full restore got unexpected error: %v", err)
|
||||
@@ -286,11 +293,12 @@ func TestBounce(t *testing.T) {
|
||||
time.Sleep(time.Millisecond)
|
||||
c.BounceToKernel()
|
||||
}()
|
||||
if _, _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
var si arch.SignalInfo
|
||||
if _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
Registers: regs,
|
||||
FloatingPointState: dummyFPState,
|
||||
PageTables: pt,
|
||||
}); err != platform.ErrContextInterrupt {
|
||||
}, &si); err != platform.ErrContextInterrupt {
|
||||
t.Errorf("application partial restore: got %v, wanted %v", err, platform.ErrContextInterrupt)
|
||||
}
|
||||
return false
|
||||
@@ -300,12 +308,13 @@ func TestBounce(t *testing.T) {
|
||||
time.Sleep(time.Millisecond)
|
||||
c.BounceToKernel()
|
||||
}()
|
||||
if _, _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
var si arch.SignalInfo
|
||||
if _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
Registers: regs,
|
||||
FloatingPointState: dummyFPState,
|
||||
PageTables: pt,
|
||||
FullRestore: true,
|
||||
}); err != platform.ErrContextInterrupt {
|
||||
}, &si); err != platform.ErrContextInterrupt {
|
||||
t.Errorf("application full restore: got %v, wanted %v", err, platform.ErrContextInterrupt)
|
||||
}
|
||||
return false
|
||||
@@ -331,11 +340,12 @@ func TestBounceStress(t *testing.T) {
|
||||
c.BounceToKernel()
|
||||
}()
|
||||
randomSleep()
|
||||
if _, _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
var si arch.SignalInfo
|
||||
if _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
Registers: regs,
|
||||
FloatingPointState: dummyFPState,
|
||||
PageTables: pt,
|
||||
}); err != platform.ErrContextInterrupt {
|
||||
}, &si); err != platform.ErrContextInterrupt {
|
||||
t.Errorf("application partial restore: got %v, wanted %v", err, platform.ErrContextInterrupt)
|
||||
}
|
||||
c.unlock()
|
||||
@@ -351,11 +361,12 @@ func TestInvalidate(t *testing.T) {
|
||||
applicationTest(t, true, testutil.Touch, func(c *vCPU, regs *syscall.PtraceRegs, pt *pagetables.PageTables) bool {
|
||||
testutil.SetTouchTarget(regs, &data) // Read legitimate value.
|
||||
for {
|
||||
if _, _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
var si arch.SignalInfo
|
||||
if _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
Registers: regs,
|
||||
FloatingPointState: dummyFPState,
|
||||
PageTables: pt,
|
||||
}); err == platform.ErrContextInterrupt {
|
||||
}, &si); err == platform.ErrContextInterrupt {
|
||||
continue // Retry.
|
||||
} else if err != nil {
|
||||
t.Errorf("application partial restore: got %v, wanted nil", err)
|
||||
@@ -365,12 +376,13 @@ func TestInvalidate(t *testing.T) {
|
||||
// Unmap the page containing data & invalidate.
|
||||
pt.Unmap(usermem.Addr(reflect.ValueOf(&data).Pointer() & ^uintptr(usermem.PageSize-1)), usermem.PageSize)
|
||||
for {
|
||||
if _, _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
var si arch.SignalInfo
|
||||
if _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
Registers: regs,
|
||||
FloatingPointState: dummyFPState,
|
||||
PageTables: pt,
|
||||
Flush: true,
|
||||
}); err == platform.ErrContextInterrupt {
|
||||
}, &si); err == platform.ErrContextInterrupt {
|
||||
continue // Retry.
|
||||
} else if err != platform.ErrContextSignal {
|
||||
t.Errorf("application partial restore: got %v, wanted %v", err, platform.ErrContextSignal)
|
||||
@@ -388,27 +400,29 @@ func IsFault(err error, si *arch.SignalInfo) bool {
|
||||
|
||||
func TestEmptyAddressSpace(t *testing.T) {
|
||||
applicationTest(t, false, testutil.SyscallLoop, func(c *vCPU, regs *syscall.PtraceRegs, pt *pagetables.PageTables) bool {
|
||||
if si, _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
var si arch.SignalInfo
|
||||
if _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
Registers: regs,
|
||||
FloatingPointState: dummyFPState,
|
||||
PageTables: pt,
|
||||
}); err == platform.ErrContextInterrupt {
|
||||
}, &si); err == platform.ErrContextInterrupt {
|
||||
return true // Retry.
|
||||
} else if !IsFault(err, si) {
|
||||
} else if !IsFault(err, &si) {
|
||||
t.Errorf("first fault with partial restore failed got %v", err)
|
||||
t.Logf("registers: %#v", ®s)
|
||||
}
|
||||
return false
|
||||
})
|
||||
applicationTest(t, false, testutil.SyscallLoop, func(c *vCPU, regs *syscall.PtraceRegs, pt *pagetables.PageTables) bool {
|
||||
if si, _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
var si arch.SignalInfo
|
||||
if _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
Registers: regs,
|
||||
FloatingPointState: dummyFPState,
|
||||
PageTables: pt,
|
||||
FullRestore: true,
|
||||
}); err == platform.ErrContextInterrupt {
|
||||
}, &si); err == platform.ErrContextInterrupt {
|
||||
return true // Retry.
|
||||
} else if !IsFault(err, si) {
|
||||
} else if !IsFault(err, &si) {
|
||||
t.Errorf("first fault with full restore failed got %v", err)
|
||||
t.Logf("registers: %#v", ®s)
|
||||
}
|
||||
@@ -459,11 +473,12 @@ func BenchmarkApplicationSyscall(b *testing.B) {
|
||||
a int // Count for ErrContextInterrupt.
|
||||
)
|
||||
applicationTest(b, true, testutil.SyscallLoop, func(c *vCPU, regs *syscall.PtraceRegs, pt *pagetables.PageTables) bool {
|
||||
if _, _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
var si arch.SignalInfo
|
||||
if _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
Registers: regs,
|
||||
FloatingPointState: dummyFPState,
|
||||
PageTables: pt,
|
||||
}); err == platform.ErrContextInterrupt {
|
||||
}, &si); err == platform.ErrContextInterrupt {
|
||||
a++
|
||||
return true // Ignore.
|
||||
} else if err != nil {
|
||||
@@ -495,11 +510,12 @@ func BenchmarkWorldSwitchToUserRoundtrip(b *testing.B) {
|
||||
a int
|
||||
)
|
||||
applicationTest(b, true, testutil.SyscallLoop, func(c *vCPU, regs *syscall.PtraceRegs, pt *pagetables.PageTables) bool {
|
||||
if _, _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
var si arch.SignalInfo
|
||||
if _, err := c.SwitchToUser(ring0.SwitchOpts{
|
||||
Registers: regs,
|
||||
FloatingPointState: dummyFPState,
|
||||
PageTables: pt,
|
||||
}); err == platform.ErrContextInterrupt {
|
||||
}, &si); err == platform.ErrContextInterrupt {
|
||||
a++
|
||||
return true // Ignore.
|
||||
} else if err != nil {
|
||||
|
||||
@@ -156,19 +156,19 @@ func (c *vCPU) initArchState() error {
|
||||
// nonCanonical generates a canonical address return.
|
||||
//
|
||||
//go:nosplit
|
||||
func nonCanonical(addr uint64, signal int32) (*arch.SignalInfo, usermem.AccessType, error) {
|
||||
info := &arch.SignalInfo{
|
||||
func nonCanonical(addr uint64, signal int32, info *arch.SignalInfo) (usermem.AccessType, error) {
|
||||
*info = arch.SignalInfo{
|
||||
Signo: signal,
|
||||
Code: arch.SignalInfoKernel,
|
||||
}
|
||||
info.SetAddr(addr) // Include address.
|
||||
return info, usermem.NoAccess, platform.ErrContextSignal
|
||||
return usermem.NoAccess, platform.ErrContextSignal
|
||||
}
|
||||
|
||||
// fault generates an appropriate fault return.
|
||||
//
|
||||
//go:nosplit
|
||||
func (c *vCPU) fault(signal int32) (*arch.SignalInfo, usermem.AccessType, error) {
|
||||
func (c *vCPU) fault(signal int32, info *arch.SignalInfo) (usermem.AccessType, error) {
|
||||
bluepill(c) // Probably no-op, but may not be.
|
||||
faultAddr := ring0.ReadCR2()
|
||||
code, user := c.ErrorCode()
|
||||
@@ -176,11 +176,10 @@ func (c *vCPU) fault(signal int32) (*arch.SignalInfo, usermem.AccessType, error)
|
||||
// The last fault serviced by this CPU was not a user
|
||||
// fault, so we can't reliably trust the faultAddr or
|
||||
// the code provided here. We need to re-execute.
|
||||
return nil, usermem.NoAccess, platform.ErrContextInterrupt
|
||||
}
|
||||
info := &arch.SignalInfo{
|
||||
Signo: signal,
|
||||
return usermem.NoAccess, platform.ErrContextInterrupt
|
||||
}
|
||||
// Reset the pointed SignalInfo.
|
||||
*info = arch.SignalInfo{Signo: signal}
|
||||
info.SetAddr(uint64(faultAddr))
|
||||
accessType := usermem.AccessType{
|
||||
Read: code&(1<<1) == 0,
|
||||
@@ -192,20 +191,20 @@ func (c *vCPU) fault(signal int32) (*arch.SignalInfo, usermem.AccessType, error)
|
||||
} else {
|
||||
info.Code = 2 // SEGV_ACCERR.
|
||||
}
|
||||
return info, accessType, platform.ErrContextSignal
|
||||
return accessType, platform.ErrContextSignal
|
||||
}
|
||||
|
||||
// SwitchToUser unpacks architectural-details.
|
||||
func (c *vCPU) SwitchToUser(switchOpts ring0.SwitchOpts) (*arch.SignalInfo, usermem.AccessType, error) {
|
||||
func (c *vCPU) SwitchToUser(switchOpts ring0.SwitchOpts, info *arch.SignalInfo) (usermem.AccessType, error) {
|
||||
// Check for canonical addresses.
|
||||
if regs := switchOpts.Registers; !ring0.IsCanonical(regs.Rip) {
|
||||
return nonCanonical(regs.Rip, int32(syscall.SIGSEGV))
|
||||
return nonCanonical(regs.Rip, int32(syscall.SIGSEGV), info)
|
||||
} else if !ring0.IsCanonical(regs.Rsp) {
|
||||
return nonCanonical(regs.Rsp, int32(syscall.SIGBUS))
|
||||
return nonCanonical(regs.Rsp, int32(syscall.SIGBUS), info)
|
||||
} else if !ring0.IsCanonical(regs.Fs_base) {
|
||||
return nonCanonical(regs.Fs_base, int32(syscall.SIGBUS))
|
||||
return nonCanonical(regs.Fs_base, int32(syscall.SIGBUS), info)
|
||||
} else if !ring0.IsCanonical(regs.Gs_base) {
|
||||
return nonCanonical(regs.Gs_base, int32(syscall.SIGBUS))
|
||||
return nonCanonical(regs.Gs_base, int32(syscall.SIGBUS), info)
|
||||
}
|
||||
|
||||
// Assign PCIDs.
|
||||
@@ -231,25 +230,25 @@ func (c *vCPU) SwitchToUser(switchOpts ring0.SwitchOpts) (*arch.SignalInfo, user
|
||||
switch vector {
|
||||
case ring0.Syscall, ring0.SyscallInt80:
|
||||
// Fast path: system call executed.
|
||||
return nil, usermem.NoAccess, nil
|
||||
return usermem.NoAccess, nil
|
||||
|
||||
case ring0.PageFault:
|
||||
return c.fault(int32(syscall.SIGSEGV))
|
||||
return c.fault(int32(syscall.SIGSEGV), info)
|
||||
|
||||
case ring0.Debug, ring0.Breakpoint:
|
||||
info := &arch.SignalInfo{
|
||||
*info = arch.SignalInfo{
|
||||
Signo: int32(syscall.SIGTRAP),
|
||||
Code: 1, // TRAP_BRKPT (breakpoint).
|
||||
}
|
||||
info.SetAddr(switchOpts.Registers.Rip) // Include address.
|
||||
return info, usermem.AccessType{}, platform.ErrContextSignal
|
||||
return usermem.AccessType{}, platform.ErrContextSignal
|
||||
|
||||
case ring0.GeneralProtectionFault,
|
||||
ring0.SegmentNotPresent,
|
||||
ring0.BoundRangeExceeded,
|
||||
ring0.InvalidTSS,
|
||||
ring0.StackSegmentFault:
|
||||
info := &arch.SignalInfo{
|
||||
*info = arch.SignalInfo{
|
||||
Signo: int32(syscall.SIGSEGV),
|
||||
Code: arch.SignalInfoKernel,
|
||||
}
|
||||
@@ -258,52 +257,52 @@ func (c *vCPU) SwitchToUser(switchOpts ring0.SwitchOpts) (*arch.SignalInfo, user
|
||||
// When CPUID faulting is enabled, we will generate a #GP(0) when
|
||||
// userspace executes a CPUID instruction. This is handled above,
|
||||
// because we need to be able to map and read user memory.
|
||||
return info, usermem.AccessType{}, platform.ErrContextSignalCPUID
|
||||
return usermem.AccessType{}, platform.ErrContextSignalCPUID
|
||||
}
|
||||
return info, usermem.AccessType{}, platform.ErrContextSignal
|
||||
return usermem.AccessType{}, platform.ErrContextSignal
|
||||
|
||||
case ring0.InvalidOpcode:
|
||||
info := &arch.SignalInfo{
|
||||
*info = arch.SignalInfo{
|
||||
Signo: int32(syscall.SIGILL),
|
||||
Code: 1, // ILL_ILLOPC (illegal opcode).
|
||||
}
|
||||
info.SetAddr(switchOpts.Registers.Rip) // Include address.
|
||||
return info, usermem.AccessType{}, platform.ErrContextSignal
|
||||
return usermem.AccessType{}, platform.ErrContextSignal
|
||||
|
||||
case ring0.DivideByZero:
|
||||
info := &arch.SignalInfo{
|
||||
*info = arch.SignalInfo{
|
||||
Signo: int32(syscall.SIGFPE),
|
||||
Code: 1, // FPE_INTDIV (divide by zero).
|
||||
}
|
||||
info.SetAddr(switchOpts.Registers.Rip) // Include address.
|
||||
return info, usermem.AccessType{}, platform.ErrContextSignal
|
||||
return usermem.AccessType{}, platform.ErrContextSignal
|
||||
|
||||
case ring0.Overflow:
|
||||
info := &arch.SignalInfo{
|
||||
*info = arch.SignalInfo{
|
||||
Signo: int32(syscall.SIGFPE),
|
||||
Code: 1, // FPE_INTOVF (integer overflow).
|
||||
}
|
||||
info.SetAddr(switchOpts.Registers.Rip) // Include address.
|
||||
return info, usermem.AccessType{}, platform.ErrContextSignal
|
||||
return usermem.AccessType{}, platform.ErrContextSignal
|
||||
|
||||
case ring0.X87FloatingPointException,
|
||||
ring0.SIMDFloatingPointException:
|
||||
info := &arch.SignalInfo{
|
||||
*info = arch.SignalInfo{
|
||||
Signo: int32(syscall.SIGFPE),
|
||||
Code: 7, // FPE_FLTINV (invalid operation).
|
||||
}
|
||||
info.SetAddr(switchOpts.Registers.Rip) // Include address.
|
||||
return info, usermem.AccessType{}, platform.ErrContextSignal
|
||||
return usermem.AccessType{}, platform.ErrContextSignal
|
||||
|
||||
case ring0.Vector(bounce): // ring0.VirtualizationException
|
||||
return nil, usermem.NoAccess, platform.ErrContextInterrupt
|
||||
return usermem.NoAccess, platform.ErrContextInterrupt
|
||||
|
||||
case ring0.AlignmentCheck:
|
||||
info := &arch.SignalInfo{
|
||||
*info = arch.SignalInfo{
|
||||
Signo: int32(syscall.SIGBUS),
|
||||
Code: 2, // BUS_ADRERR (physical address does not exist).
|
||||
}
|
||||
return info, usermem.NoAccess, platform.ErrContextSignal
|
||||
return usermem.NoAccess, platform.ErrContextSignal
|
||||
|
||||
case ring0.NMI:
|
||||
// An NMI is generated only when a fault is not servicable by
|
||||
@@ -311,7 +310,7 @@ func (c *vCPU) SwitchToUser(switchOpts ring0.SwitchOpts) (*arch.SignalInfo, user
|
||||
// really not. This could happen, e.g. if some file is
|
||||
// truncated (and would generate a SIGBUS) and we map it
|
||||
// directly into the instance.
|
||||
return c.fault(int32(syscall.SIGBUS))
|
||||
return c.fault(int32(syscall.SIGBUS), info)
|
||||
|
||||
case ring0.DeviceNotAvailable,
|
||||
ring0.DoubleFault,
|
||||
|
||||
Reference in New Issue
Block a user