x86/hvm: implement hvmemul_write() using real mappings
authorAndrew Cooper <andrew.cooper3@citrix.com>
Wed, 11 Oct 2017 12:48:50 +0000 (14:48 +0200)
committerJan Beulich <jbeulich@suse.com>
Wed, 11 Oct 2017 12:48:50 +0000 (14:48 +0200)
commit8cbd4fb0b7eab0a5bbe09058a75a8fd288032547
treec73a22a775a906abdc9df3c528ea52cc2244659c
parentcf8e5f25a940928550e69b543ed67df1d73f7b09
x86/hvm: implement hvmemul_write() using real mappings

An access which crosses a page boundary is performed atomically by x86
hardware, albeit with a severe performance penalty.  An important corner case
is when a straddled access hits two pages which differ in whether a
translation exists, or in net access rights.

The use of hvm_copy*() in hvmemul_write() is problematic, because it performs
a translation then completes the partial write, before moving onto the next
translation.

If an individual emulated write straddles two pages, the first of which is
writable, and the second of which is not, the first half of the write will
complete before #PF is raised from the second half.

This results in guest state corruption as a side effect of emulation, which
has been observed to cause windows to crash while under introspection.

Introduce the hvmemul_{,un}map_linear_addr() helpers, which translate an
entire contents of a linear access, and vmap() the underlying frames to
provide a contiguous virtual mapping for the emulator to use.  This is the
same mechanism as used by the shadow emulation code.

This will catch any translation issues and abort the emulation before any
modifications occur.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Signed-off-by: Alexandru Isaila <aisaila@bitdefender.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Paul Durrant <paul.durrant@citrix.com>
xen/arch/x86/hvm/emulate.c
xen/include/asm-x86/hvm/emulate.h