All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH]Fix the bug of guest os installation failure and win2k boot failure
@ 2008-03-17  8:08 Xu, Dongxiao
  2008-03-17  8:32 ` Keir Fraser
  0 siblings, 1 reply; 13+ messages in thread
From: Xu, Dongxiao @ 2008-03-17  8:08 UTC (permalink / raw)
  To: Keir Fraser, xen-devel

[-- Attachment #1: Type: text/plain, Size: 2760 bytes --]

Hi, Keir,

      This patch is to fix the problem of Linux guest installation failure and Windows 2000 boot failure.

      In the early code, we use vmx_vmexit_handler() -> vmx_io_instruction() function to emulate I/O instructions. But now, we use vmx_vmexit_handler() -> handle_mmio -> hvm_emulate_one() -> x86_emulate() to emulate I/O instructions. Also nowadays, the realmode emulation code walks through the path: vmx_realmode() -> realmode_emulate_one() -> hvm_emulate_one() -> x86_emulate().

      The I/O handle code in x86_emulate() checks the cpl and iopl value, and if cpl > iopl, it will generate a GP fault. This causes Linux guest installation failure and Windows 2000 boot failure. I think this check code may be not reasonable for two aspects: 

      1. If x86_emulate() is called from vmexit or from realmode emulation, I think this line of code is not needed, because:

            a). In I/O emulation, the cpu has already checked the cpl, iopl, and also the I/O bitmap before vmx_vmexit_handler() is called,
            b). For realmode, we shouldn't check the cpl and iopl, because any I/O operation is permitted in realmode.

      2. If x86_emulate() is called from multi.c, which emulates up to four instructions when dealing with PAE guest page tables. In this condition, the check is needed, but it is not correct, it should follow the code as follows, which is stated in the Intel SDM:

 If (cpl <= iopl)
     Do I/O operation;
 Else {
     If (I/O permission bit for the port == 0)
         Do I/O operation;
     Else 
         Generate GP fault;
 } 

      Now this patch remove the cpl and iopl check in I/O handler code in x86_emulate() function. And it checks the four instructions which would be emulated by multi.c, if any of them is IN/INS/OUT/OUTS, or REP IN/INS/OUT/OUTS, we will break that four-instruction emulation, and let the I/O instruction walk through the path of vmx_vmexit_handler() -> handle_mmio -> hvm_emulate_one() -> x86_emulate().

      Another way to solve this issue could be that, we put the entire io permission check in x86_emulate(), and use a flag to indicate whether we should do the check. If x86_emulate() is called by vmexit or realmode emulation, we skip this check; if it is called by multi.c, then we do the io permission check. But it may be a bit complex for hypervisor to read guest process’s TSS and find and check its io bitmap. 

BTW: Why the existence code doesn't check the LOCK prefix (which should cause #UD injected to guest)
      
      Welcome for your comment, thanks! 

Signed-off-by: Xu Dongxiao <dongxiao.xu@intel.com>

Best Regards,
--Dongxiao


[-- Attachment #2: io_check.patch --]
[-- Type: application/octet-stream, Size: 2618 bytes --]

Signed-off-by: Xu Dongxiao <dongxiao.xu@intel.com>

diff -r 59b8768d0d0d xen/arch/x86/mm/shadow/multi.c
--- a/xen/arch/x86/mm/shadow/multi.c	Wed Mar 05 11:18:25 2008 +0000
+++ b/xen/arch/x86/mm/shadow/multi.c	Mon Mar 17 14:59:03 2008 +0800
@@ -3165,8 +3165,40 @@ static int sh_page_fault(struct vcpu *v,
          * the "second half" of a 64-bit pagetable write. */
         for ( i = 0 ; i < 4 ; i++ )
         {
+            unsigned long ins, rc;
+            uint8_t b;
             shadow_continue_emulation(&emul_ctxt, regs);
             v->arch.paging.last_write_was_pt = 0;
+
+            rc = emul_ops->insn_fetch(x86_seg_cs, 
+                regs->eip + sizeof(uint8_t), 
+                &ins, sizeof(uint8_t), &emul_ctxt.ctxt);
+            if ( rc )
+                break;
+
+            b = (uint8_t)ins;
+
+            /* If the instruction is IN/INS/OUT/OUTS */
+            if ((b >= 0xe4 && b <= 0xe7) || (b >= 0xec && b <= 0xef) 
+                || (b >= 0x6c && b <= 0x6f))
+                break;
+            /* If the instruction is a REP prefix */
+            else if (b == 0xf3)
+            {
+                rc = emul_ops->insn_fetch(x86_seg_cs, 
+                    regs->eip + 2*sizeof(uint8_t), 
+                    &ins, sizeof(uint8_t), &emul_ctxt.ctxt);
+                if ( rc )
+                    break;
+
+                b = (uint8_t)ins;
+
+                /* If the instruction after the REP prefix is IN/INS/OUT/OUTS */
+                if ((b >= 0xe4 && b <= 0xe7) || (b >= 0xec && b <= 0xef) 
+                    || (b >= 0x6c && b <= 0x6f)) 
+                    break;
+            } 
+
             r = x86_emulate(&emul_ctxt.ctxt, emul_ops);
             if ( r == X86EMUL_OKAY )
             {
diff -r 59b8768d0d0d xen/arch/x86/x86_emulate.c
--- a/xen/arch/x86/x86_emulate.c	Wed Mar 05 11:18:25 2008 +0000
+++ b/xen/arch/x86/x86_emulate.c	Mon Mar 17 14:59:03 2008 +0800
@@ -2255,7 +2255,6 @@ x86_emulate(
 
     case 0x6c ... 0x6d: /* ins %dx,%es:%edi */ {
         unsigned long nr_reps = get_rep_prefix();
-        generate_exception_if(!mode_iopl(), EXC_GP, 0);
         dst.bytes = !(b & 1) ? 1 : (op_bytes == 8) ? 4 : op_bytes;
         dst.mem.seg = x86_seg_es;
         dst.mem.off = truncate_ea(_regs.edi);
@@ -2818,7 +2817,6 @@ x86_emulate(
         unsigned int port = ((b < 0xe8)
                              ? insn_fetch_type(uint8_t)
                              : (uint16_t)_regs.edx);
-        generate_exception_if(!mode_iopl(), EXC_GP, 0);
         op_bytes = !(b & 1) ? 1 : (op_bytes == 8) ? 4 : op_bytes;
         if ( b & 2 )
         {

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2008-03-18 16:32 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-03-17  8:08 [PATCH]Fix the bug of guest os installation failure and win2k boot failure Xu, Dongxiao
2008-03-17  8:32 ` Keir Fraser
2008-03-17 10:06   ` Xu, Dongxiao
2008-03-17 10:32     ` Keir Fraser
2008-03-17 11:16       ` [PATCH]Fix the bug of guest os installationfailure " Cui, Dexuan
2008-03-17 11:20         ` Keir Fraser
2008-03-18  1:49           ` Xu, Dongxiao
2008-03-18  8:46             ` Keir Fraser
2008-03-18  9:35               ` Xu, Dongxiao
2008-03-18 10:02                 ` Keir Fraser
2008-03-18 10:31                   ` Xu, Dongxiao
2008-03-18 10:47                     ` Keir Fraser
2008-03-18 16:32                   ` Keir Fraser

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.