diff options
author | gVisor bot <gvisor-bot@google.com> | 2021-03-23 22:50:14 -0700 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2021-03-23 22:50:14 -0700 |
commit | 8ee4a3f6d0e75e51e088a431376d2976b0dac866 (patch) | |
tree | fe85fee268fd2f7c4012d566a048dac107f742a1 /pkg | |
parent | 56a9a13976ad800a8a34b194d35f0169d0a0bb23 (diff) | |
parent | 2f3dac78ca9aa1abb9d27570bc9ece0f486ddb60 (diff) |
Merge pull request #5677 from avagin:kvm-mmio
PiperOrigin-RevId: 364728696
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/sentry/platform/kvm/machine_amd64.go | 23 |
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() |