arm64 kvm: add to ext_dabt injection support

If no vild syndrome(data abort outside memslots) was reported by kvm, let userspace to do the
ext_dabt injection to bail out this issue.

Signed-off-by: Robin Luk <lubin.lu@antgroup.com>
This commit is contained in:
Robin Luk 2020-11-21 14:13:06 +08:00
parent 60ae6c4d83
commit 6a85d13ccf
6 changed files with 69 additions and 7 deletions

View File

@ -91,6 +91,13 @@ func bluepillSigBus(c *vCPU) {
}
}
// bluepillHandleEnosys is reponsible for handling enosys error.
//
//go:nosplit
func bluepillHandleEnosys(c *vCPU) {
throw("run failed: ENOSYS")
}
// bluepillReadyStopGuest checks whether the current vCPU is ready for interrupt injection.
//
//go:nosplit
@ -126,3 +133,10 @@ func bluepillReadyStopGuest(c *vCPU) bool {
}
return true
}
// bluepillArchHandleExit checks architecture specific exitcode.
//
//go:nosplit
func bluepillArchHandleExit(c *vCPU, context unsafe.Pointer) {
c.die(bluepillArchContext(context), "unknown")
}

View File

@ -42,6 +42,13 @@ var (
sErrEsr: _ESR_ELx_SERR_NMI,
},
}
// vcpuExtDabt is the event of ext_dabt.
vcpuExtDabt = kvmVcpuEvents{
exception: exception{
extDabtPending: 1,
},
}
)
// getTLS returns the value of TPIDR_EL0 register.

View File

@ -85,7 +85,7 @@ func bluepillStopGuest(c *vCPU) {
uintptr(c.fd),
_KVM_SET_VCPU_EVENTS,
uintptr(unsafe.Pointer(&vcpuSErrBounce))); errno != 0 {
throw("sErr injection failed")
throw("bounce sErr injection failed")
}
}
@ -93,18 +93,54 @@ func bluepillStopGuest(c *vCPU) {
//
//go:nosplit
func bluepillSigBus(c *vCPU) {
// Host must support ARM64_HAS_RAS_EXTN.
if _, _, errno := syscall.RawSyscall( // escapes: no.
syscall.SYS_IOCTL,
uintptr(c.fd),
_KVM_SET_VCPU_EVENTS,
uintptr(unsafe.Pointer(&vcpuSErrNMI))); errno != 0 {
throw("sErr injection failed")
if errno == syscall.EINVAL {
throw("No ARM64_HAS_RAS_EXTN feature in host.")
}
throw("nmi sErr injection failed")
}
}
// bluepillExtDabt is reponsible for injecting external data abort.
//
//go:nosplit
func bluepillExtDabt(c *vCPU) {
if _, _, errno := syscall.RawSyscall( // escapes: no.
syscall.SYS_IOCTL,
uintptr(c.fd),
_KVM_SET_VCPU_EVENTS,
uintptr(unsafe.Pointer(&vcpuExtDabt))); errno != 0 {
throw("ext_dabt injection failed")
}
}
// bluepillHandleEnosys is reponsible for handling enosys error.
//
//go:nosplit
func bluepillHandleEnosys(c *vCPU) {
bluepillExtDabt(c)
}
// bluepillReadyStopGuest checks whether the current vCPU is ready for sError injection.
//
//go:nosplit
func bluepillReadyStopGuest(c *vCPU) bool {
return true
}
// bluepillArchHandleExit checks architecture specific exitcode.
//
//go:nosplit
func bluepillArchHandleExit(c *vCPU, context unsafe.Pointer) {
switch c.runData.exitReason {
case _KVM_EXIT_ARM_NISV:
bluepillExtDabt(c)
default:
c.die(bluepillArchContext(context), "unknown")
}
}

View File

@ -148,6 +148,9 @@ func bluepillHandler(context unsafe.Pointer) {
// mode and have interrupts disabled.
bluepillSigBus(c)
continue // Rerun vCPU.
case syscall.ENOSYS:
bluepillHandleEnosys(c)
continue
default:
throw("run failed")
}
@ -220,7 +223,7 @@ func bluepillHandler(context unsafe.Pointer) {
c.die(bluepillArchContext(context), "entry failed")
return
default:
c.die(bluepillArchContext(context), "unknown")
bluepillArchHandleExit(c, context)
return
}
}

View File

@ -47,10 +47,11 @@ type userRegs struct {
}
type exception struct {
sErrPending uint8
sErrHasEsr uint8
pad [6]uint8
sErrEsr uint64
sErrPending uint8
sErrHasEsr uint8
extDabtPending uint8
pad [5]uint8
sErrEsr uint64
}
type kvmVcpuEvents struct {

View File

@ -56,6 +56,7 @@ const (
_KVM_EXIT_FAIL_ENTRY = 0x9
_KVM_EXIT_INTERNAL_ERROR = 0x11
_KVM_EXIT_SYSTEM_EVENT = 0x18
_KVM_EXIT_ARM_NISV = 0x1c
)
// KVM capability options.