Merge pull request #2272 from lubinszARM:pr_serr_injection

PiperOrigin-RevId: 317933650
This commit is contained in:
gVisor bot
2020-06-23 13:53:56 -07:00
7 changed files with 82 additions and 19 deletions
@@ -17,6 +17,7 @@
package kvm
import (
"syscall"
"unsafe"
"gvisor.dev/gvisor/pkg/sentry/arch"
@@ -60,3 +61,27 @@ func dieArchSetup(c *vCPU, context *arch.SignalContext64, guestRegs *userRegs) {
func getHypercallID(addr uintptr) int {
return _KVM_HYPERCALL_MAX
}
// bluepillStopGuest is reponsible for injecting interrupt.
//
//go:nosplit
func bluepillStopGuest(c *vCPU) {
// Interrupt: we must have requested an interrupt
// window; set the interrupt line.
if _, _, errno := syscall.RawSyscall(
syscall.SYS_IOCTL,
uintptr(c.fd),
_KVM_INTERRUPT,
uintptr(unsafe.Pointer(&bounce))); errno != 0 {
throw("interrupt injection failed")
}
// Clear previous injection request.
c.runData.requestInterruptWindow = 0
}
// bluepillReadyStopGuest checks whether the current vCPU is ready for interrupt injection.
//
//go:nosplit
func bluepillReadyStopGuest(c *vCPU) bool {
return c.runData.readyForInterruptInjection != 0
}
+11
View File
@@ -26,6 +26,17 @@ import (
var (
// The action for bluepillSignal is changed by sigaction().
bluepillSignal = syscall.SIGILL
// vcpuSErr is the event of system error.
vcpuSErr = kvmVcpuEvents{
exception: exception{
sErrPending: 1,
sErrHasEsr: 0,
pad: [6]uint8{0, 0, 0, 0, 0, 0},
sErrEsr: 1,
},
rsvd: [12]uint32{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
}
)
// bluepillArchEnter is called during bluepillEnter.
@@ -17,6 +17,7 @@
package kvm
import (
"syscall"
"unsafe"
"gvisor.dev/gvisor/pkg/sentry/arch"
@@ -74,3 +75,23 @@ func getHypercallID(addr uintptr) int {
return int(((addr) - arm64HypercallMMIOBase) >> 3)
}
}
// bluepillStopGuest is reponsible for injecting sError.
//
//go:nosplit
func bluepillStopGuest(c *vCPU) {
if _, _, errno := syscall.RawSyscall(
syscall.SYS_IOCTL,
uintptr(c.fd),
_KVM_SET_VCPU_EVENTS,
uintptr(unsafe.Pointer(&vcpuSErr))); errno != 0 {
throw("sErr injection failed")
}
}
// bluepillReadyStopGuest checks whether the current vCPU is ready for sError injection.
//
//go:nosplit
func bluepillReadyStopGuest(c *vCPU) bool {
return true
}
+5 -15
View File
@@ -133,12 +133,12 @@ func bluepillHandler(context unsafe.Pointer) {
// PIC, we can't inject an interrupt while they are
// masked. We need to request a window if it's not
// ready.
if c.runData.readyForInterruptInjection == 0 {
c.runData.requestInterruptWindow = 1
continue // Rerun vCPU.
} else {
if bluepillReadyStopGuest(c) {
// Force injection below; the vCPU is ready.
c.runData.exitReason = _KVM_EXIT_IRQ_WINDOW_OPEN
} else {
c.runData.requestInterruptWindow = 1
continue // Rerun vCPU.
}
case syscall.EFAULT:
// If a fault is not serviceable due to the host
@@ -217,17 +217,7 @@ func bluepillHandler(context unsafe.Pointer) {
}
}
case _KVM_EXIT_IRQ_WINDOW_OPEN:
// Interrupt: we must have requested an interrupt
// window; set the interrupt line.
if _, _, errno := syscall.RawSyscall(
syscall.SYS_IOCTL,
uintptr(c.fd),
_KVM_INTERRUPT,
uintptr(unsafe.Pointer(&bounce))); errno != 0 {
throw("interrupt injection failed")
}
// Clear previous injection request.
c.runData.requestInterruptWindow = 0
bluepillStopGuest(c)
case _KVM_EXIT_SHUTDOWN:
c.die(bluepillArchContext(context), "shutdown")
return
+12
View File
@@ -46,6 +46,18 @@ type userRegs struct {
fpRegs userFpsimdState
}
type exception struct {
sErrPending uint8
sErrHasEsr uint8
pad [6]uint8
sErrEsr uint64
}
type kvmVcpuEvents struct {
exception
rsvd [12]uint32
}
// updateGlobalOnce does global initialization. It has to be called only once.
func updateGlobalOnce(fd int) error {
physicalInit()
+6 -2
View File
@@ -35,6 +35,8 @@ const (
_KVM_GET_SUPPORTED_CPUID = 0xc008ae05
_KVM_SET_CPUID2 = 0x4008ae90
_KVM_SET_SIGNAL_MASK = 0x4004ae8b
_KVM_GET_VCPU_EVENTS = 0x8040ae9f
_KVM_SET_VCPU_EVENTS = 0x4040aea0
)
// KVM exit reasons.
@@ -54,8 +56,10 @@ const (
// KVM capability options.
const (
_KVM_CAP_MAX_VCPUS = 0x42
_KVM_CAP_ARM_VM_IPA_SIZE = 0xa5
_KVM_CAP_MAX_VCPUS = 0x42
_KVM_CAP_ARM_VM_IPA_SIZE = 0xa5
_KVM_CAP_VCPU_EVENTS = 0x29
_KVM_CAP_ARM_INJECT_SERROR_ESR = 0x9e
)
// KVM limits.
@@ -273,8 +273,8 @@ func (c *vCPU) SwitchToUser(switchOpts ring0.SwitchOpts, info *arch.SignalInfo)
case ring0.PageFault:
return c.fault(int32(syscall.SIGSEGV), info)
case 0xaa:
return usermem.NoAccess, nil
case ring0.Vector(bounce): // ring0.VirtualizationException
return usermem.NoAccess, platform.ErrContextInterrupt
default:
return usermem.NoAccess, platform.ErrContextSignal
}