mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
x86/svm: Apply the virtual-8086 IOPL check to INT n only
In virtual-8086 mode with IOPL < 3, INT n raises #GP(0). INT1, INT3
and INTO are not affected. They are delivered normally.
svm_emul_swint_injection() applies the check to all of them, so an ICEBP
raises #GP instead of #DB. It also reports the IDT entry in the #GP
error code instead of 0.
Move the check earier prior to setting up ec, and limit it to INT n only.
Fixes: 897d59a426 ("x86/svm: Introduce svm_emul_swint_injection()")
Signed-off-by: Stefano Stabellini <stefano.stabellini@amd.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
This commit is contained in:
1 parent
69633efbca
commit
bd7e286e87
1 file changed
+11
-10
+11
-10
@@ -1139,6 +1139,17 @@ static void svm_emul_swint_injection(struct x86_event *event)
|
||||
if ( !(vmcb_get_cr0(vmcb) & X86_CR0_PE) )
|
||||
goto raise_exception; /* TODO: support real-mode injection? */
|
||||
|
||||
/*
|
||||
* In vm86 mode, INT $N is subject to IOPL.
|
||||
*
|
||||
* TODO: It is also subject to CR4.VME=1, which would require reading the
|
||||
* TSS Software Interrupt Redirection bitmap.
|
||||
*/
|
||||
if ( type == X86_ET_SW_INT &&
|
||||
regs->eflags & X86_EFLAGS_VM &&
|
||||
MASK_EXTR(regs->eflags, X86_EFLAGS_IOPL) != 3 )
|
||||
goto raise_exception;
|
||||
|
||||
idte_size = lm ? 16 : 8;
|
||||
idte_offset = trap * idte_size;
|
||||
|
||||
@@ -1146,16 +1157,6 @@ static void svm_emul_swint_injection(struct x86_event *event)
|
||||
ec = (trap << 3) | X86_XEC_IDT |
|
||||
(type == X86_ET_PRIV_SW_EXC ? X86_XEC_EXT : 0);
|
||||
|
||||
/*
|
||||
* TODO: This does not cover the v8086 mode with CR4.VME case
|
||||
* correctly, but falls on the safe side from the point of view of a
|
||||
* 32bit OS. Someone with many TUITs can see about reading the TSS
|
||||
* Software Interrupt Redirection bitmap.
|
||||
*/
|
||||
if ( (regs->eflags & X86_EFLAGS_VM) &&
|
||||
MASK_EXTR(regs->eflags, X86_EFLAGS_IOPL) != 3 )
|
||||
goto raise_exception;
|
||||
|
||||
/*
|
||||
* Read all 8/16 bytes so the idtr limit check is applied properly to
|
||||
* this entry, even though we don't look at all the words read.
|
||||
|
||||