summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorgVisor bot <gvisor-bot@google.com>2021-03-24 05:56:09 +0000
committergVisor bot <gvisor-bot@google.com>2021-03-24 05:56:09 +0000
commit15bcc00b79decbc781d2d1badd5c654ed2609ea8 (patch)
tree286f4740681344a2b406354cf14899b95595aa0d
parent6d6d1361a87d19477c9f035405065fc9b714ef73 (diff)
parent8ee4a3f6d0e75e51e088a431376d2976b0dac866 (diff)
Merge release-20210315.0-20-g8ee4a3f6d (automated)
-rw-r--r--pkg/sentry/platform/kvm/machine_amd64.go23
1 files changed, 23 insertions, 0 deletions
diff --git a/pkg/sentry/platform/kvm/machine_amd64.go b/pkg/sentry/platform/kvm/machine_amd64.go
index 8f2c82e73..3af96c7e5 100644
--- a/pkg/sentry/platform/kvm/machine_amd64.go
+++ b/pkg/sentry/platform/kvm/machine_amd64.go
@@ -294,6 +294,28 @@ func (c *vCPU) fault(signal int32, info *arch.SignalInfo) (usermem.AccessType, e
return accessType, platform.ErrContextSignal
}
+//go:nosplit
+//go:noinline
+func loadByte(ptr *byte) byte {
+ return *ptr
+}
+
+// prefaultFloatingPointState touches each page of the floating point state to
+// be sure that its physical pages are mapped.
+//
+// Otherwise the kernel can trigger KVM_EXIT_MMIO and an instruction that
+// triggered a fault will be emulated by the kvm kernel code, but it can't
+// emulate instructions like xsave and xrstor.
+//
+//go:nosplit
+func prefaultFloatingPointState(data *fpu.State) {
+ size := len(*data)
+ for i := 0; i < size; i += usermem.PageSize {
+ loadByte(&(*data)[i])
+ }
+ loadByte(&(*data)[size-1])
+}
+
// SwitchToUser unpacks architectural-details.
func (c *vCPU) SwitchToUser(switchOpts ring0.SwitchOpts, info *arch.SignalInfo) (usermem.AccessType, error) {
// Check for canonical addresses.
@@ -324,6 +346,7 @@ func (c *vCPU) SwitchToUser(switchOpts ring0.SwitchOpts, info *arch.SignalInfo)
// allocations occur.
entersyscall()
bluepill(c)
+ prefaultFloatingPointState(switchOpts.FloatingPointState)
vector = c.CPU.SwitchToUser(switchOpts)
exitsyscall()