WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] hvm vmx: Clean up vmx_io_instruction().

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] hvm vmx: Clean up vmx_io_instruction().
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Mon, 11 Jun 2007 02:22:17 -0700
Delivery-date: Tue, 12 Jun 2007 05:08:37 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1181034489 -3600
# Node ID 4f05a587cb6b146e1a24a5a672566ac35de40b71
# Parent  91301122db5128d8d94e90638c5a272479621f68
hvm vmx: Clean up vmx_io_instruction().

vmx_io_instruction() is too long, so it's hard to understand or change
something. The attached patch splits it into several readable functions,
making it easer to understand and extend.

Signed-off-by: Weidong Han <weidong.han@xxxxxxxxx>
Signed-off-by: Dexuan Cui <dexuan.cui@xxxxxxxxx>
---
 xen/arch/x86/hvm/vmx/vmx.c        |  595 +++++++++++++++++++++-----------------
 xen/include/asm-x86/hvm/vmx/vmx.h |   13 
 2 files changed, 347 insertions(+), 261 deletions(-)

diff -r 91301122db51 -r 4f05a587cb6b xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Tue Jun 05 10:00:15 2007 +0100
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Tue Jun 05 10:08:09 2007 +0100
@@ -929,7 +929,8 @@ static unsigned long vmx_get_segment_bas
     ASSERT(v == current);
 
 #ifdef __x86_64__
-    if ( vmx_long_mode_enabled(v) && (__vmread(GUEST_CS_AR_BYTES) & (1u<<13)) )
+    if ( vmx_long_mode_enabled(v) &&
+         (__vmread(GUEST_CS_AR_BYTES) & X86_SEG_AR_CS_LM_ACTIVE) )
         long_mode = 1;
 #endif
 
@@ -1097,9 +1098,10 @@ static int vmx_guest_x86_mode(struct vcp
     if ( unlikely(__vmread(GUEST_RFLAGS) & X86_EFLAGS_VM) )
         return 1;
     cs_ar_bytes = __vmread(GUEST_CS_AR_BYTES);
-    if ( vmx_long_mode_enabled(v) && likely(cs_ar_bytes & (1u<<13)) )
+    if ( vmx_long_mode_enabled(v) && likely(cs_ar_bytes &
+                                            X86_SEG_AR_CS_LM_ACTIVE) )
         return 8;
-    return (likely(cs_ar_bytes & (1u<<14)) ? 4 : 2);
+    return (likely(cs_ar_bytes & X86_SEG_AR_DEF_OP_SIZE) ? 4 : 2);
 }
 
 static int vmx_pae_enabled(struct vcpu *v)
@@ -1452,65 +1454,73 @@ static void vmx_do_invlpg(unsigned long 
     paging_invlpg(v, va);
 }
 
-
-static int vmx_check_descriptor(int long_mode, unsigned long eip, int inst_len,
-                                enum x86_segment seg, unsigned long *base,
-                                u32 *limit, u32 *ar_bytes)
+/*
+ * get segment for string pio according to guest instruction
+ */
+static void vmx_str_pio_get_segment(int long_mode, unsigned long eip,
+                                   int inst_len, enum x86_segment *seg)
+{
+    unsigned char inst[MAX_INST_LEN];
+    int i;
+    extern int inst_copy_from_guest(unsigned char *, unsigned long, int);
+
+    if ( !long_mode )
+        eip += __vmread(GUEST_CS_BASE);
+
+    memset(inst, 0, MAX_INST_LEN);
+    if ( inst_copy_from_guest(inst, eip, inst_len) != inst_len )
+    {
+        gdprintk(XENLOG_ERR, "Get guest instruction failed\n");
+        domain_crash(current->domain);
+        return;
+    }
+
+    for ( i = 0; i < inst_len; i++ )
+    {
+        switch ( inst[i] )
+        {
+        case 0xf3: /* REPZ */
+        case 0xf2: /* REPNZ */
+        case 0xf0: /* LOCK */
+        case 0x66: /* data32 */
+        case 0x67: /* addr32 */
+#ifdef __x86_64__
+        case 0x40 ... 0x4f: /* REX */
+#endif
+            continue;
+        case 0x2e: /* CS */
+            *seg = x86_seg_cs;
+            continue;
+        case 0x36: /* SS */
+            *seg = x86_seg_ss;
+            continue;
+        case 0x26: /* ES */
+            *seg = x86_seg_es;
+            continue;
+        case 0x64: /* FS */
+            *seg = x86_seg_fs;
+            continue;
+        case 0x65: /* GS */
+            *seg = x86_seg_gs;
+            continue;
+        case 0x3e: /* DS */
+            *seg = x86_seg_ds;
+            continue;
+        }
+    }
+}
+
+static int vmx_str_pio_check_descriptor(int long_mode, unsigned long eip,
+                                        int inst_len, enum x86_segment seg,
+                                        unsigned long *base, u32 *limit,
+                                        u32 *ar_bytes)
 {
     enum vmcs_field ar_field, base_field, limit_field;
 
     *base = 0;
     *limit = 0;
     if ( seg != x86_seg_es )
-    {
-        unsigned char inst[MAX_INST_LEN];
-        int i;
-        extern int inst_copy_from_guest(unsigned char *, unsigned long, int);
-
-        if ( !long_mode )
-            eip += __vmread(GUEST_CS_BASE);
-        memset(inst, 0, MAX_INST_LEN);
-        if ( inst_copy_from_guest(inst, eip, inst_len) != inst_len )
-        {
-            gdprintk(XENLOG_ERR, "Get guest instruction failed\n");
-            domain_crash(current->domain);
-            return 0;
-        }
-
-        for ( i = 0; i < inst_len; i++ )
-        {
-            switch ( inst[i] )
-            {
-            case 0xf3: /* REPZ */
-            case 0xf2: /* REPNZ */
-            case 0xf0: /* LOCK */
-            case 0x66: /* data32 */
-            case 0x67: /* addr32 */
-#ifdef __x86_64__
-            case 0x40 ... 0x4f: /* REX */
-#endif
-                continue;
-            case 0x2e: /* CS */
-                seg = x86_seg_cs;
-                continue;
-            case 0x36: /* SS */
-                seg = x86_seg_ss;
-                continue;
-            case 0x26: /* ES */
-                seg = x86_seg_es;
-                continue;
-            case 0x64: /* FS */
-                seg = x86_seg_fs;
-                continue;
-            case 0x65: /* GS */
-                seg = x86_seg_gs;
-                continue;
-            case 0x3e: /* DS */
-                seg = x86_seg_ds;
-                continue;
-            }
-        }
-    }
+        vmx_str_pio_get_segment(long_mode, eip, inst_len, &seg);
 
     switch ( seg )
     {
@@ -1559,30 +1569,172 @@ static int vmx_check_descriptor(int long
     return !(*ar_bytes & 0x10000);
 }
 
-static void vmx_io_instruction(unsigned long exit_qualification,
-                               unsigned long inst_len)
-{
-    struct cpu_user_regs *regs;
-    struct hvm_io_op *pio_opp;
+
+static inline void vmx_str_pio_check_limit(u32 limit, unsigned int size,
+                                           u32 ar_bytes, unsigned long addr,
+                                           unsigned long base, int df,
+                                           unsigned long *count)
+{
+    unsigned long ea = addr - base;
+
+    /* Offset must be within limits. */
+    ASSERT(ea == (u32)ea);
+    if ( (u32)(ea + size - 1) < (u32)ea ||
+         (ar_bytes & 0xc) != 0x4 ? ea + size - 1 > limit
+                                 : ea <= limit )
+    {
+        vmx_inject_hw_exception(current, TRAP_gp_fault, 0);
+        return;
+    }
+
+    /* Check the limit for repeated instructions, as above we checked
+       only the first instance. Truncate the count if a limit violation
+       would occur. Note that the checking is not necessary for page
+       granular segments as transfers crossing page boundaries will be
+       broken up anyway. */
+    if ( !(ar_bytes & X86_SEG_AR_GRANULARITY) && *count > 1 )
+    {
+        if ( (ar_bytes & 0xc) != 0x4 )
+        {
+            /* expand-up */
+            if ( !df )
+            {
+                if ( ea + *count * size - 1 < ea ||
+                     ea + *count * size - 1 > limit )
+                    *count = (limit + 1UL - ea) / size;
+            }
+            else
+            {
+                if ( *count - 1 > ea / size )
+                    *count = ea / size + 1;
+            }
+        }
+        else
+        {
+            /* expand-down */
+            if ( !df )
+            {
+                if ( *count - 1 > -(s32)ea / size )
+                    *count = -(s32)ea / size + 1UL;
+            }
+            else
+            {
+                if ( ea < (*count - 1) * size ||
+                     ea - (*count - 1) * size <= limit )
+                    *count = (ea - limit - 1) / size + 1;
+            }
+        }
+        ASSERT(*count);
+    }
+}
+
+#ifdef __x86_64__
+static inline void vmx_str_pio_lm_check_limit(struct cpu_user_regs *regs,
+                                              unsigned int size,
+                                              unsigned long addr,
+                                              unsigned long *count)
+{
+    if ( !is_canonical_address(addr) ||
+         !is_canonical_address(addr + size - 1) )
+    {
+        vmx_inject_hw_exception(current, TRAP_gp_fault, 0);
+        return;
+    }
+    if ( *count > (1UL << 48) / size )
+        *count = (1UL << 48) / size;
+    if ( !(regs->eflags & EF_DF) )
+    {
+        if ( addr + *count * size - 1 < addr ||
+             !is_canonical_address(addr + *count * size - 1) )
+            *count = (addr & ~((1UL << 48) - 1)) / size;
+    }
+    else
+    {
+        if ( (*count - 1) * size > addr ||
+             !is_canonical_address(addr + (*count - 1) * size) )
+            *count = (addr & ~((1UL << 48) - 1)) / size + 1;
+    }
+    ASSERT(*count);
+}
+#endif
+
+static inline void vmx_send_str_pio(struct cpu_user_regs *regs,
+                                    struct hvm_io_op *pio_opp,
+                                    unsigned long inst_len, unsigned int port,
+                                    int sign, unsigned int size, int dir,
+                                    int df, unsigned long addr,
+                                    unsigned long paddr, unsigned long count)
+{
+    /*
+     * Handle string pio instructions that cross pages or that
+     * are unaligned. See the comments in hvm_domain.c/handle_mmio()
+     */
+    if ( (addr & PAGE_MASK) != ((addr + size - 1) & PAGE_MASK) ) {
+        unsigned long value = 0;
+
+        pio_opp->flags |= OVERLAP;
+
+        if ( dir == IOREQ_WRITE )   /* OUTS */
+        {
+            if ( hvm_paging_enabled(current) )
+            {
+                int rv = hvm_copy_from_guest_virt(&value, addr, size);
+                if ( rv != 0 )
+                {
+                    /* Failed on the page-spanning copy.  Inject PF into
+                     * the guest for the address where we failed. */
+                    addr += size - rv;
+                    gdprintk(XENLOG_DEBUG, "Pagefault reading non-io side "
+                             "of a page-spanning PIO: va=%#lx\n", addr);
+                    vmx_inject_exception(TRAP_page_fault, 0, addr);
+                    return;
+                }
+            }
+            else
+                (void) hvm_copy_from_guest_phys(&value, addr, size);
+        } else /* dir != IOREQ_WRITE */
+            /* Remember where to write the result, as a *VA*.
+             * Must be a VA so we can handle the page overlap
+             * correctly in hvm_pio_assist() */
+            pio_opp->addr = addr;
+
+        if ( count == 1 )
+            regs->eip += inst_len;
+
+        send_pio_req(port, 1, size, value, dir, df, 0);
+    } else {
+        unsigned long last_addr = sign > 0 ? addr + count * size - 1
+                                           : addr - (count - 1) * size;
+
+        if ( (addr & PAGE_MASK) != (last_addr & PAGE_MASK) )
+        {
+            if ( sign > 0 )
+                count = (PAGE_SIZE - (addr & ~PAGE_MASK)) / size;
+            else
+                count = (addr & ~PAGE_MASK) / size + 1;
+        } else
+            regs->eip += inst_len;
+
+        send_pio_req(port, count, size, paddr, dir, df, 1);
+    }
+}
+
+static void vmx_str_pio_handler(unsigned long exit_qualification,
+                                unsigned long inst_len,
+                                struct cpu_user_regs *regs,
+                                struct hvm_io_op *pio_opp)
+{
     unsigned int port, size;
     int dir, df, vm86;
-
-    pio_opp = &current->arch.hvm_vcpu.io_op;
-    pio_opp->instr = INSTR_PIO;
-    pio_opp->flags = 0;
-
-    regs = &pio_opp->io_context;
-
-    /* Copy current guest state into io instruction state structure. */
-    memcpy(regs, guest_cpu_user_regs(), HVM_CONTEXT_STACK_BYTES);
-    hvm_store_cpu_guest_regs(current, regs, NULL);
+    unsigned long addr, count = 1, base;
+    paddr_t paddr;
+    unsigned long gfn;
+    u32 ar_bytes, limit;
+    int sign;
+    int long_mode = 0;
 
     vm86 = regs->eflags & X86_EFLAGS_VM ? 1 : 0;
     df = regs->eflags & X86_EFLAGS_DF ? 1 : 0;
-
-    HVM_DBG_LOG(DBG_LEVEL_IO, "vm86 %d, eip=%x:%lx, "
-                "exit_qualification = %lx",
-                vm86, regs->cs, (unsigned long)regs->eip, exit_qualification);
 
     if ( test_bit(6, &exit_qualification) )
         port = (exit_qualification >> 16) & 0xFFFF;
@@ -1592,201 +1744,122 @@ static void vmx_io_instruction(unsigned 
     size = (exit_qualification & 7) + 1;
     dir = test_bit(3, &exit_qualification); /* direction */
 
-    if (dir==IOREQ_READ)
+    if ( dir == IOREQ_READ )
         HVMTRACE_2D(IO_READ,  current, port, size);
     else
         HVMTRACE_2D(IO_WRITE, current, port, size);
 
-    if ( test_bit(4, &exit_qualification) ) { /* string instruction */
-        unsigned long addr, count = 1, base;
-        paddr_t paddr;
-        unsigned long gfn;
-        u32 ar_bytes, limit;
-        int sign = regs->eflags & X86_EFLAGS_DF ? -1 : 1;
-        int long_mode = 0;
-
-        ar_bytes = __vmread(GUEST_CS_AR_BYTES);
+    sign = regs->eflags & X86_EFLAGS_DF ? -1 : 1;
+    ar_bytes = __vmread(GUEST_CS_AR_BYTES);
 #ifdef __x86_64__
-        if ( vmx_long_mode_enabled(current) && (ar_bytes & (1u<<13)) )
-            long_mode = 1;
+    if ( vmx_long_mode_enabled(current) &&
+         (ar_bytes & X86_SEG_AR_CS_LM_ACTIVE) )
+        long_mode = 1;
 #endif
-        addr = __vmread(GUEST_LINEAR_ADDRESS);
-
-        if ( test_bit(5, &exit_qualification) ) { /* "rep" prefix */
-            pio_opp->flags |= REPZ;
-            count = regs->ecx;
-            if ( !long_mode && (vm86 || !(ar_bytes & (1u<<14))) )
-                count &= 0xFFFF;
-        }
-
-        /*
-         * In protected mode, guest linear address is invalid if the
-         * selector is null.
-         */
-        if ( !vmx_check_descriptor(long_mode, regs->eip, inst_len,
-                                   dir==IOREQ_WRITE ? x86_seg_ds : x86_seg_es,
-                                   &base, &limit, &ar_bytes) ) {
-            if ( !long_mode ) {
-                vmx_inject_hw_exception(current, TRAP_gp_fault, 0);
-                return;
-            }
-            addr = dir == IOREQ_WRITE ? base + regs->esi : regs->edi;
-        }
-
+    addr = __vmread(GUEST_LINEAR_ADDRESS);
+
+    if ( test_bit(5, &exit_qualification) ) { /* "rep" prefix */
+        pio_opp->flags |= REPZ;
+        count = regs->ecx;
+        if ( !long_mode &&
+            (vm86 || !(ar_bytes & X86_SEG_AR_DEF_OP_SIZE)) )
+            count &= 0xFFFF;
+    }
+
+    /*
+     * In protected mode, guest linear address is invalid if the
+     * selector is null.
+     */
+    if ( !vmx_str_pio_check_descriptor(long_mode, regs->eip, inst_len,
+                                       dir==IOREQ_WRITE ? x86_seg_ds :
+                                       x86_seg_es, &base, &limit,
+                                       &ar_bytes) ) {
         if ( !long_mode ) {
-            unsigned long ea = addr - base;
-
-            /* Segment must be readable for outs and writeable for ins. */
-            if ( dir == IOREQ_WRITE ? (ar_bytes & 0xa) == 0x8
-                                    : (ar_bytes & 0xa) != 0x2 ) {
-                vmx_inject_hw_exception(current, TRAP_gp_fault, 0);
-                return;
-            }
-
-            /* Offset must be within limits. */
-            ASSERT(ea == (u32)ea);
-            if ( (u32)(ea + size - 1) < (u32)ea ||
-                 (ar_bytes & 0xc) != 0x4 ? ea + size - 1 > limit
-                                         : ea <= limit )
-            {
-                vmx_inject_hw_exception(current, TRAP_gp_fault, 0);
-                return;
-            }
-
-            /* Check the limit for repeated instructions, as above we checked
-               only the first instance. Truncate the count if a limit violation
-               would occur. Note that the checking is not necessary for page
-               granular segments as transfers crossing page boundaries will be
-               broken up anyway. */
-            if ( !(ar_bytes & (1u<<15)) && count > 1 )
-            {
-                if ( (ar_bytes & 0xc) != 0x4 )
-                {
-                    /* expand-up */
-                    if ( !df )
-                    {
-                        if ( ea + count * size - 1 < ea ||
-                             ea + count * size - 1 > limit )
-                            count = (limit + 1UL - ea) / size;
-                    }
-                    else
-                    {
-                        if ( count - 1 > ea / size )
-                            count = ea / size + 1;
-                    }
-                }
-                else
-                {
-                    /* expand-down */
-                    if ( !df )
-                    {
-                        if ( count - 1 > -(s32)ea / size )
-                            count = -(s32)ea / size + 1UL;
-                    }
-                    else
-                    {
-                        if ( ea < (count - 1) * size ||
-                             ea - (count - 1) * size <= limit )
-                            count = (ea - limit - 1) / size + 1;
-                    }
-                }
-                ASSERT(count);
-            }
-        }
+            vmx_inject_hw_exception(current, TRAP_gp_fault, 0);
+            return;
+        }
+        addr = dir == IOREQ_WRITE ? base + regs->esi : regs->edi;
+    }
+
+    if ( !long_mode )
+    {
+        /* Segment must be readable for outs and writeable for ins. */
+        if ( dir == IOREQ_WRITE ? (ar_bytes & 0xa) == 0x8
+                                : (ar_bytes & 0xa) != 0x2 ) {
+            vmx_inject_hw_exception(current, TRAP_gp_fault, 0);
+            return;
+        }
+
+        vmx_str_pio_check_limit(limit, size, ar_bytes, addr, base, df, &count);
+    }
 #ifdef __x86_64__
+    else
+    {
+        vmx_str_pio_lm_check_limit(regs, size, addr, &count);
+    }
+#endif
+
+    /* Translate the address to a physical address */
+    gfn = paging_gva_to_gfn(current, addr);
+    if ( gfn == INVALID_GFN )
+    {
+        /* The guest does not have the RAM address mapped.
+         * Need to send in a page fault */
+        int errcode = 0;
+        /* IO read --> memory write */
+        if ( dir == IOREQ_READ ) errcode |= PFEC_write_access;
+        vmx_inject_exception(TRAP_page_fault, errcode, addr);
+        return;
+    }
+    paddr = (paddr_t)gfn << PAGE_SHIFT | (addr & ~PAGE_MASK);
+
+    vmx_send_str_pio(regs, pio_opp, inst_len, port, sign,
+                     size, dir, df, addr, paddr, count);
+}
+
+static void vmx_io_instruction(unsigned long exit_qualification,
+                               unsigned long inst_len)
+{
+    struct cpu_user_regs *regs;
+    struct hvm_io_op *pio_opp;
+
+    pio_opp = &current->arch.hvm_vcpu.io_op;
+    pio_opp->instr = INSTR_PIO;
+    pio_opp->flags = 0;
+
+    regs = &pio_opp->io_context;
+
+    /* Copy current guest state into io instruction state structure. */
+    memcpy(regs, guest_cpu_user_regs(), HVM_CONTEXT_STACK_BYTES);
+    hvm_store_cpu_guest_regs(current, regs, NULL);
+
+    HVM_DBG_LOG(DBG_LEVEL_IO, "vm86 %d, eip=%x:%lx, "
+                "exit_qualification = %lx",
+                regs->eflags & X86_EFLAGS_VM ? 1 : 0,
+                regs->cs, (unsigned long)regs->eip, exit_qualification);
+
+    if ( test_bit(4, &exit_qualification) ) /* string instrucation */
+        vmx_str_pio_handler(exit_qualification, inst_len, regs, pio_opp);
+    else
+    {
+        unsigned int port, size;
+        int dir, df;
+
+        df = regs->eflags & X86_EFLAGS_DF ? 1 : 0;
+
+        if ( test_bit(6, &exit_qualification) )
+            port = (exit_qualification >> 16) & 0xFFFF;
         else
-        {
-            if ( !is_canonical_address(addr) ||
-                 !is_canonical_address(addr + size - 1) )
-            {
-                vmx_inject_hw_exception(current, TRAP_gp_fault, 0);
-                return;
-            }
-            if ( count > (1UL << 48) / size )
-                count = (1UL << 48) / size;
-            if ( !(regs->eflags & EF_DF) )
-            {
-                if ( addr + count * size - 1 < addr ||
-                     !is_canonical_address(addr + count * size - 1) )
-                    count = (addr & ~((1UL << 48) - 1)) / size;
-            }
-            else
-            {
-                if ( (count - 1) * size > addr ||
-                     !is_canonical_address(addr + (count - 1) * size) )
-                    count = (addr & ~((1UL << 48) - 1)) / size + 1;
-            }
-            ASSERT(count);
-        }
-#endif
-
-        /* Translate the address to a physical address */
-        gfn = paging_gva_to_gfn(current, addr);
-        if ( gfn == INVALID_GFN ) 
-        {
-            /* The guest does not have the RAM address mapped. 
-             * Need to send in a page fault */
-            int errcode = 0;
-            /* IO read --> memory write */
-            if ( dir == IOREQ_READ ) errcode |= PFEC_write_access;
-            vmx_inject_exception(TRAP_page_fault, errcode, addr);
-            return;
-        }
-        paddr = (paddr_t)gfn << PAGE_SHIFT | (addr & ~PAGE_MASK);
-
-        /*
-         * Handle string pio instructions that cross pages or that
-         * are unaligned. See the comments in hvm_domain.c/handle_mmio()
-         */
-        if ( (addr & PAGE_MASK) != ((addr + size - 1) & PAGE_MASK) ) {
-            unsigned long value = 0;
-
-            pio_opp->flags |= OVERLAP;
-
-            if ( dir == IOREQ_WRITE )   /* OUTS */
-            {
-                if ( hvm_paging_enabled(current) )
-                {
-                    int rv = hvm_copy_from_guest_virt(&value, addr, size);
-                    if ( rv != 0 ) 
-                    {
-                        /* Failed on the page-spanning copy.  Inject PF into
-                         * the guest for the address where we failed. */ 
-                        addr += size - rv;
-                        gdprintk(XENLOG_DEBUG, "Pagefault reading non-io side "
-                                 "of a page-spanning PIO: va=%#lx\n", addr);
-                        vmx_inject_exception(TRAP_page_fault, 0, addr);
-                        return;
-                    }
-                }
-                else
-                    (void) hvm_copy_from_guest_phys(&value, addr, size);
-            } else /* dir != IOREQ_WRITE */
-                /* Remember where to write the result, as a *VA*.
-                 * Must be a VA so we can handle the page overlap 
-                 * correctly in hvm_pio_assist() */
-                pio_opp->addr = addr;
-
-            if ( count == 1 )
-                regs->eip += inst_len;
-
-            send_pio_req(port, 1, size, value, dir, df, 0);
-        } else {
-            unsigned long last_addr = sign > 0 ? addr + count * size - 1
-                                               : addr - (count - 1) * size;
-
-            if ( (addr & PAGE_MASK) != (last_addr & PAGE_MASK) )
-            {
-                if ( sign > 0 )
-                    count = (PAGE_SIZE - (addr & ~PAGE_MASK)) / size;
-                else
-                    count = (addr & ~PAGE_MASK) / size + 1;
-            } else
-                regs->eip += inst_len;
-
-            send_pio_req(port, count, size, paddr, dir, df, 1);
-        }
-    } else {
+            port = regs->edx & 0xffff;
+
+        size = (exit_qualification & 7) + 1;
+        dir = test_bit(3, &exit_qualification); /* direction */
+
+        if ( dir == IOREQ_READ )
+            HVMTRACE_2D(IO_READ,  current, port, size);
+        else
+            HVMTRACE_2D(IO_WRITE, current, port, size);
+
         if ( port == 0xe9 && dir == IOREQ_WRITE && size == 1 )
             hvm_print_line(current, regs->eax); /* guest debug output */
 
diff -r 91301122db51 -r 4f05a587cb6b xen/include/asm-x86/hvm/vmx/vmx.h
--- a/xen/include/asm-x86/hvm/vmx/vmx.h Tue Jun 05 10:00:15 2007 +0100
+++ b/xen/include/asm-x86/hvm/vmx/vmx.h Tue Jun 05 10:08:09 2007 +0100
@@ -130,6 +130,19 @@ void vmx_vlapic_msr_changed(struct vcpu 
 #define TYPE_MOV_FROM_DR                (1 << 4)
 #define DEBUG_REG_ACCESS_REG            0xf00   /* 11:8, general purpose 
register */
 
+/*
+ * Access Rights
+ */
+#define X86_SEG_AR_SEG_TYPE     0xf        /* 3:0, segment type */
+#define X86_SEG_AR_DESC_TYPE    (1u << 4)  /* 4, descriptor type */
+#define X86_SEG_AR_DPL          0x60       /* 6:5, descriptor privilege level 
*/
+#define X86_SEG_AR_SEG_PRESENT  (1u << 7)  /* 7, segment present */
+#define X86_SEG_AR_AVL          (1u << 12) /* 12, available for system 
software */
+#define X86_SEG_AR_CS_LM_ACTIVE (1u << 13) /* 13, long mode active (CS only) */
+#define X86_SEG_AR_DEF_OP_SIZE  (1u << 14) /* 14, default operation size */
+#define X86_SEG_AR_GRANULARITY  (1u << 15) /* 15, granularity */
+#define X86_SEG_AR_SEG_UNUSABLE (1u << 16) /* 16, segment unusable */
+
 /* These bits in the CR4 are owned by the host */
 #if CONFIG_PAGING_LEVELS >= 3
 #define VMX_CR4_HOST_MASK (X86_CR4_VMXE | X86_CR4_PAE)

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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] hvm vmx: Clean up vmx_io_instruction()., Xen patchbot-unstable <=