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-3.1-testing] hvm: Improve in-Xen PIO emulation to b

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-3.1-testing] hvm: Improve in-Xen PIO emulation to better handle string PIO
From: "Xen patchbot-3.1-testing" <patchbot-3.1-testing@xxxxxxxxxxxxxxxxxxx>
Date: Mon, 14 Jan 2008 09:20:39 -0800
Delivery-date: Mon, 14 Jan 2008 09:27:05 -0800
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 Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1200137207 0
# Node ID d381e9278086085586b7afe20ecabe384be35876
# Parent  927fb0b1201ca9cb5436404abdd85bd215bc7ca5
hvm: Improve in-Xen PIO emulation to better handle string PIO
instructions.
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
xen-unstable changeset:   16709:9862217f3c34
xen-unstable date:        Sat Jan 12 11:13:57 2008 +0000
---
 xen/arch/x86/hvm/i8254.c     |   51 ++++++++++++-------------
 xen/arch/x86/hvm/intercept.c |   70 ++++++++++++++++++++++++++++++-----
 xen/arch/x86/hvm/pmtimer.c   |   29 +++++++-------
 xen/arch/x86/hvm/rtc.c       |   13 +++---
 xen/arch/x86/hvm/vpic.c      |   85 ++++++++++++++++---------------------------
 xen/include/asm-x86/hvm/io.h |   15 ++++---
 6 files changed, 149 insertions(+), 114 deletions(-)

diff -r 927fb0b1201c -r d381e9278086 xen/arch/x86/hvm/i8254.c
--- a/xen/arch/x86/hvm/i8254.c  Sat Jan 12 09:38:25 2008 +0000
+++ b/xen/arch/x86/hvm/i8254.c  Sat Jan 12 11:26:47 2008 +0000
@@ -48,8 +48,10 @@
 #define RW_STATE_WORD0 3
 #define RW_STATE_WORD1 4
 
-static int handle_pit_io(ioreq_t *p);
-static int handle_speaker_io(ioreq_t *p);
+static int handle_pit_io(
+    int dir, uint32_t port, uint32_t bytes, uint32_t *val);
+static int handle_speaker_io(
+    int dir, uint32_t port, uint32_t bytes, uint32_t *val);
 
 /* Compute with 96 bit intermediate result: (a*b)/c */
 static uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
@@ -530,24 +532,25 @@ void pit_deinit(struct domain *d)
 }
 
 /* the intercept action for PIT DM retval:0--not handled; 1--handled */  
-static int handle_pit_io(ioreq_t *p)
+static int handle_pit_io(
+    int dir, uint32_t port, uint32_t bytes, uint32_t *val)
 {
     struct PITState *vpit = vcpu_vpit(current);
 
-    if ( (p->size != 1) || p->data_is_ptr || (p->type != IOREQ_TYPE_PIO) )
+    if ( bytes != 1 )
     {
         gdprintk(XENLOG_WARNING, "PIT bad access\n");
         return 1;
     }
 
-    if ( p->dir == IOREQ_WRITE )
-    {
-        pit_ioport_write(vpit, p->addr, p->data);
+    if ( dir == IOREQ_WRITE )
+    {
+        pit_ioport_write(vpit, port, *val);
     }
     else
     {
-        if ( (p->addr & 3) != 3 )
-            p->data = pit_ioport_read(vpit, p->addr);
+        if ( (port & 3) != 3 )
+            *val = pit_ioport_read(vpit, port);
         else
             gdprintk(XENLOG_WARNING, "PIT: read A1:A0=3!\n");
     }
@@ -571,11 +574,12 @@ static uint32_t speaker_ioport_read(
             (pit_get_out(pit, 2) << 5) | (refresh_clock << 4));
 }
 
-static int handle_speaker_io(ioreq_t *p)
+static int handle_speaker_io(
+    int dir, uint32_t port, uint32_t bytes, uint32_t *val)
 {
     struct PITState *vpit = vcpu_vpit(current);
 
-    if ( (p->size != 1) || p->data_is_ptr || (p->type != IOREQ_TYPE_PIO) )
+    if ( bytes != 1 )
     {
         gdprintk(XENLOG_WARNING, "PIT_SPEAKER bad access\n");
         return 1;
@@ -583,10 +587,10 @@ static int handle_speaker_io(ioreq_t *p)
 
     spin_lock(&vpit->lock);
 
-    if ( p->dir == IOREQ_WRITE )
-        speaker_ioport_write(vpit, p->addr, p->data);
+    if ( dir == IOREQ_WRITE )
+        speaker_ioport_write(vpit, port, *val);
     else
-        p->data = speaker_ioport_read(vpit, p->addr);
+        *val = speaker_ioport_read(vpit, port);
 
     spin_unlock(&vpit->lock);
 
@@ -595,18 +599,13 @@ static int handle_speaker_io(ioreq_t *p)
 
 int pv_pit_handler(int port, int data, int write)
 {
-    ioreq_t ioreq = {
-        .size = 1,
-        .type = IOREQ_TYPE_PIO,
-        .addr = port,
-        .dir  = write ? 0 : 1,
-        .data = write ? data : 0,
-    };
+    int dir = write ? IOREQ_WRITE : IOREQ_READ;
+    uint32_t val = data;
 
     if ( port == 0x61 )
-        handle_speaker_io(&ioreq);
+        handle_speaker_io(dir, port, 1, &val);
     else
-        handle_pit_io(&ioreq);
-
-    return !write ? ioreq.data : 0;
-}
+        handle_pit_io(dir, port, 1, &val);
+
+    return !write ? val : 0;
+}
diff -r 927fb0b1201c -r d381e9278086 xen/arch/x86/hvm/intercept.c
--- a/xen/arch/x86/hvm/intercept.c      Sat Jan 12 09:38:25 2008 +0000
+++ b/xen/arch/x86/hvm/intercept.c      Sat Jan 12 11:26:47 2008 +0000
@@ -231,6 +231,50 @@ int hvm_mmio_intercept(ioreq_t *p)
     return 0;
 }
 
+static int process_portio_intercept(portio_action_t action, ioreq_t *p)
+{
+    int rc = 1, i, sign = p->df ? -1 : 1;
+    uint32_t data;
+
+    if ( p->dir == IOREQ_READ )
+    {
+        if ( !p->data_is_ptr )
+        {
+            rc = action(IOREQ_READ, p->addr, p->size, &data);
+            p->data = data;
+        }
+        else
+        {
+            for ( i = 0; i < p->count; i++ )
+            {
+                rc = action(IOREQ_READ, p->addr, p->size, &data);
+                (void)hvm_copy_to_guest_phys(p->data + sign*i*p->size,
+                                             &data, p->size);
+            }
+        }
+    }
+    else /* p->dir == IOREQ_WRITE */
+    {
+        if ( !p->data_is_ptr )
+        {
+            data = p->data;
+            rc = action(IOREQ_WRITE, p->addr, p->size, &data);
+        }
+        else
+        {
+            for ( i = 0; i < p->count; i++ )
+            {
+                data = 0;
+                (void)hvm_copy_from_guest_phys(&data, p->data + sign*i*p->size,
+                                               p->size);
+                rc = action(IOREQ_WRITE, p->addr, p->size, &data);
+            }
+        }
+    }
+
+    return rc;
+}
+
 /*
  * Check if the request is handled inside xen
  * return value: 0 --not handled; 1 --handled
@@ -239,25 +283,31 @@ int hvm_io_intercept(ioreq_t *p, int typ
 {
     struct vcpu *v = current;
     struct hvm_io_handler *handler =
-                           &(v->domain->arch.hvm_domain.io_handler);
+        &v->domain->arch.hvm_domain.io_handler;
     int i;
     unsigned long addr, size;
 
-    for (i = 0; i < handler->num_slot; i++) {
-        if( type != handler->hdl_list[i].type)
+    for ( i = 0; i < handler->num_slot; i++ )
+    {
+        if ( type != handler->hdl_list[i].type )
             continue;
         addr = handler->hdl_list[i].addr;
         size = handler->hdl_list[i].size;
-        if (p->addr >= addr &&
-            p->addr <  addr + size)
-            return handler->hdl_list[i].action(p);
+        if ( (p->addr >= addr) &&
+             ((p->addr + p->size) < (addr + size)) )
+        {
+            if ( type == HVM_PORTIO )
+                return process_portio_intercept(
+                    handler->hdl_list[i].action.portio, p);
+            return handler->hdl_list[i].action.mmio(p);
+        }
     }
     return 0;
 }
 
 int register_io_handler(
     struct domain *d, unsigned long addr, unsigned long size,
-    intercept_action_t action, int type)
+    void *action, int type)
 {
     struct hvm_io_handler *handler = &d->arch.hvm_domain.io_handler;
     int num = handler->num_slot;
@@ -266,8 +316,10 @@ int register_io_handler(
 
     handler->hdl_list[num].addr = addr;
     handler->hdl_list[num].size = size;
-    handler->hdl_list[num].action = action;
-    handler->hdl_list[num].type = type;
+    if ( (handler->hdl_list[num].type = type) == HVM_PORTIO )
+        handler->hdl_list[num].action.portio = action;
+    else
+        handler->hdl_list[num].action.mmio = action;
     handler->num_slot++;
 
     return 1;
diff -r 927fb0b1201c -r d381e9278086 xen/arch/x86/hvm/pmtimer.c
--- a/xen/arch/x86/hvm/pmtimer.c        Sat Jan 12 09:38:25 2008 +0000
+++ b/xen/arch/x86/hvm/pmtimer.c        Sat Jan 12 11:26:47 2008 +0000
@@ -114,7 +114,8 @@ static void pmt_timer_callback(void *opa
 }
 
 /* Handle port I/O to the PM1a_STS and PM1a_EN registers */
-static int handle_evt_io(ioreq_t *p)
+static int handle_evt_io(
+    int dir, uint32_t port, uint32_t bytes, uint32_t *val)
 {
     struct vcpu *v = current;
     PMTState *s = &v->domain->arch.hvm_domain.pl_time.vpmt;
@@ -123,10 +124,10 @@ static int handle_evt_io(ioreq_t *p)
 
     spin_lock(&s->lock);
 
-    if ( p->dir == IOREQ_WRITE )
+    if ( dir == IOREQ_WRITE )
     {
         /* Handle this I/O one byte at a time */
-        for ( i = p->size, addr = p->addr, data = p->data;
+        for ( i = bytes, addr = port, data = *val;
               i > 0;
               i--, addr++, data >>= 8 )
         {
@@ -150,9 +151,8 @@ static int handle_evt_io(ioreq_t *p)
                 
             default:
                 gdprintk(XENLOG_WARNING, 
-                         "Bad ACPI PM register write: %"PRIu64
-                         " bytes (%#"PRIx64") at %"PRIx64"\n", 
-                         p->size, p->data, p->addr);
+                         "Bad ACPI PM register write: %x bytes (%x) at %x\n", 
+                         bytes, *val, port);
             }
         }
         /* Fix up the SCI state to match the new register state */
@@ -161,10 +161,10 @@ static int handle_evt_io(ioreq_t *p)
     else /* p->dir == IOREQ_READ */
     {
         data = s->pm.pm1a_sts | (((uint32_t) s->pm.pm1a_en) << 16);
-        data >>= 8 * (p->addr - PM1a_STS_ADDR);
-        if ( p->size == 1 ) data &= 0xff;
-        else if ( p->size == 2 ) data &= 0xffff;
-        p->data = data;
+        data >>= 8 * (port - PM1a_STS_ADDR);
+        if ( bytes == 1 ) data &= 0xff;
+        else if ( bytes == 2 ) data &= 0xffff;
+        *val = data;
     }
 
     spin_unlock(&s->lock);
@@ -174,22 +174,23 @@ static int handle_evt_io(ioreq_t *p)
 
 
 /* Handle port I/O to the TMR_VAL register */
-static int handle_pmt_io(ioreq_t *p)
+static int handle_pmt_io(
+    int dir, uint32_t port, uint32_t bytes, uint32_t *val)
 {
     struct vcpu *v = current;
     PMTState *s = &v->domain->arch.hvm_domain.pl_time.vpmt;
 
-    if ( (p->size != 4) || p->data_is_ptr || (p->type != IOREQ_TYPE_PIO) )
+    if ( bytes != 4 )
     {
         gdprintk(XENLOG_WARNING, "HVM_PMT bad access\n");
         return 1;
     }
     
-    if ( p->dir == IOREQ_READ )
+    if ( dir == IOREQ_READ )
     {
         spin_lock(&s->lock);
         pmt_update_time(s);
-        p->data = s->pm.tmr_val;
+        *val = s->pm.tmr_val;
         spin_unlock(&s->lock);
         return 1;
     }
diff -r 927fb0b1201c -r d381e9278086 xen/arch/x86/hvm/rtc.c
--- a/xen/arch/x86/hvm/rtc.c    Sat Jan 12 09:38:25 2008 +0000
+++ b/xen/arch/x86/hvm/rtc.c    Sat Jan 12 11:26:47 2008 +0000
@@ -395,24 +395,25 @@ static uint32_t rtc_ioport_read(RTCState
     return ret;
 }
 
-static int handle_rtc_io(ioreq_t *p)
+static int handle_rtc_io(
+    int dir, uint32_t port, uint32_t bytes, uint32_t *val)
 {
     struct RTCState *vrtc = vcpu_vrtc(current);
 
-    if ( (p->size != 1) || p->data_is_ptr || (p->type != IOREQ_TYPE_PIO) )
+    if ( bytes != 1 )
     {
         gdprintk(XENLOG_WARNING, "HVM_RTC bas access\n");
         return 1;
     }
     
-    if ( p->dir == IOREQ_WRITE )
-    {
-        if ( rtc_ioport_write(vrtc, p->addr, p->data & 0xFF) )
+    if ( dir == IOREQ_WRITE )
+    {
+        if ( rtc_ioport_write(vrtc, port, (uint8_t)*val) )
             return 1;
     }
     else if ( vrtc->hw.cmos_index < RTC_CMOS_SIZE )
     {
-        p->data = rtc_ioport_read(vrtc, p->addr);
+        *val = rtc_ioport_read(vrtc, port);
         return 1;
     }
 
diff -r 927fb0b1201c -r d381e9278086 xen/arch/x86/hvm/vpic.c
--- a/xen/arch/x86/hvm/vpic.c   Sat Jan 12 09:38:25 2008 +0000
+++ b/xen/arch/x86/hvm/vpic.c   Sat Jan 12 11:26:47 2008 +0000
@@ -311,61 +311,45 @@ static uint32_t vpic_ioport_read(struct 
     return vpic->imr;
 }
 
-static int vpic_intercept_pic_io(ioreq_t *p)
+static int vpic_intercept_pic_io(
+    int dir, uint32_t port, uint32_t bytes, uint32_t *val)
+{
+    struct hvm_hw_vpic *vpic;
+
+    if ( bytes != 1 )
+    {
+        gdprintk(XENLOG_WARNING, "PIC_IO bad access size %d\n", bytes);
+        return 1;
+    }
+
+    vpic = &current->domain->arch.hvm_domain.vpic[port >> 7];
+
+    if ( dir == IOREQ_WRITE )
+        vpic_ioport_write(vpic, port, (uint8_t)*val);
+    else
+        *val = (uint8_t)vpic_ioport_read(vpic, port);
+
+    return 1;
+}
+
+static int vpic_intercept_elcr_io(
+    int dir, uint32_t port, uint32_t bytes, uint32_t *val)
 {
     struct hvm_hw_vpic *vpic;
     uint32_t data;
 
-    if ( (p->size != 1) || (p->count != 1) )
-    {
-        gdprintk(XENLOG_WARNING, "PIC_IO bad access size %d\n", (int)p->size);
+    if ( bytes != 1 )
+    {
+        gdprintk(XENLOG_WARNING, "PIC_IO bad access size %d\n", bytes);
         return 1;
     }
 
-    vpic = &current->domain->arch.hvm_domain.vpic[p->addr >> 7];
-
-    if ( p->dir == IOREQ_WRITE )
-    {
-        if ( p->data_is_ptr )
-            (void)hvm_copy_from_guest_phys(&data, p->data, p->size);
-        else
-            data = p->data;
-        vpic_ioport_write(vpic, (uint32_t)p->addr, (uint8_t)data);
-    }
-    else
-    {
-        data = vpic_ioport_read(vpic, (uint32_t)p->addr);
-        if ( p->data_is_ptr )
-            (void)hvm_copy_to_guest_phys(p->data, &data, p->size);
-        else
-            p->data = (u64)data;
-    }
-
-    return 1;
-}
-
-static int vpic_intercept_elcr_io(ioreq_t *p)
-{
-    struct hvm_hw_vpic *vpic;
-    uint32_t data;
-
-    if ( (p->size != 1) || (p->count != 1) )
-    {
-        gdprintk(XENLOG_WARNING, "PIC_IO bad access size %d\n", (int)p->size);
-        return 1;
-    }
-
-    vpic = &current->domain->arch.hvm_domain.vpic[p->addr & 1];
-
-    if ( p->dir == IOREQ_WRITE )
-    {
-        if ( p->data_is_ptr )
-            (void)hvm_copy_from_guest_phys(&data, p->data, p->size);
-        else
-            data = p->data;
-
+    vpic = &current->domain->arch.hvm_domain.vpic[port & 1];
+
+    if ( dir == IOREQ_WRITE )
+    {
         /* Some IRs are always edge trig. Slave IR is always level trig. */
-        data &= vpic_elcr_mask(vpic);
+        data = *val & vpic_elcr_mask(vpic);
         if ( vpic->is_master )
             data |= 1 << 2;
         vpic->elcr = data;
@@ -373,12 +357,7 @@ static int vpic_intercept_elcr_io(ioreq_
     else
     {
         /* Reader should not see hardcoded level-triggered slave IR. */
-        data = vpic->elcr & vpic_elcr_mask(vpic);
-
-        if ( p->data_is_ptr )
-            (void)hvm_copy_to_guest_phys(p->data, &data, p->size);
-        else
-            p->data = data;
+        *val = vpic->elcr & vpic_elcr_mask(vpic);
     }
 
     return 1;
diff -r 927fb0b1201c -r d381e9278086 xen/include/asm-x86/hvm/io.h
--- a/xen/include/asm-x86/hvm/io.h      Sat Jan 12 09:38:25 2008 +0000
+++ b/xen/include/asm-x86/hvm/io.h      Sat Jan 12 11:26:47 2008 +0000
@@ -85,23 +85,26 @@ struct hvm_io_op {
 #define HVM_PORTIO                  0
 #define HVM_MMIO                    1
 
-typedef int (*intercept_action_t)(ioreq_t *);
 typedef unsigned long (*hvm_mmio_read_t)(struct vcpu *v,
                                          unsigned long addr,
                                          unsigned long length);
-
 typedef void (*hvm_mmio_write_t)(struct vcpu *v,
                                unsigned long addr,
                                unsigned long length,
                                unsigned long val);
-
 typedef int (*hvm_mmio_check_t)(struct vcpu *v, unsigned long addr);
 
+typedef int (*portio_action_t)(
+    int dir, uint32_t port, uint32_t bytes, uint32_t *val);
+typedef int (*mmio_action_t)(ioreq_t *);
 struct io_handler {
     int                 type;
     unsigned long       addr;
     unsigned long       size;
-    intercept_action_t  action;
+    union {
+        portio_action_t portio;
+        mmio_action_t   mmio;
+    } action;
 };
 
 struct hvm_io_handler {
@@ -119,7 +122,7 @@ extern int hvm_io_intercept(ioreq_t *p, 
 extern int hvm_io_intercept(ioreq_t *p, int type);
 extern int register_io_handler(
     struct domain *d, unsigned long addr, unsigned long size,
-    intercept_action_t action, int type);
+    void *action, int type);
 
 static inline int hvm_portio_intercept(ioreq_t *p)
 {
@@ -132,7 +135,7 @@ extern int hvm_buffered_io_intercept(ior
 
 static inline int register_portio_handler(
     struct domain *d, unsigned long addr,
-    unsigned long size, intercept_action_t action)
+    unsigned long size, portio_action_t action)
 {
     return register_io_handler(d, addr, size, action, HVM_PORTIO);
 }

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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-3.1-testing] hvm: Improve in-Xen PIO emulation to better handle string PIO, Xen patchbot-3.1-testing <=