x86/svm: Write the correct %eip into the outgoing task
authorAndrew Cooper <andrew.cooper3@citrix.com>
Wed, 11 Dec 2019 14:29:37 +0000 (15:29 +0100)
committerJan Beulich <jbeulich@suse.com>
Wed, 11 Dec 2019 14:29:37 +0000 (15:29 +0100)
commit81bd09fc7ca35ecba467ac3fa73b22ec82bcf158
tree6d3a8c9771d9ef85de3702f586b49b7511071609
parentb9527ec8f393166ee6cfee95fbe0390b166fe304
x86/svm: Write the correct %eip into the outgoing task

The TASK_SWITCH vmexit has fault semantics, and doesn't provide any NRIPs
assistance with instruction length.  As a result, any instruction-induced task
switch has the outgoing task's %eip pointing at the instruction switch caused
the switch, rather than after it.

This causes callers of task gates to livelock (repeatedly execute the call/jmp
to enter the task), and any restartable task to become a nop after its first
use (the (re)entry state points at the iret used to exit the task).

32bit Windows in particular is known to use task gates for NMI handling, and
to use NMI IPIs.

In the task switch handler, distinguish instruction-induced from
interrupt/exception-induced task switches, and decode the instruction under
%rip to calculate its length.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
master commit: 1d758bc6d1a8c0f658a874470c349ee4e27aee46
master date: 2019-11-28 17:14:38 +0000
xen/arch/x86/hvm/svm/emulate.c
xen/arch/x86/hvm/svm/svm.c
xen/include/asm-x86/hvm/svm/emulate.h