x86, hvm: Fix stdvga and buffered-io code.
authorKeir Fraser <keir@xensource.com>
Thu, 1 Nov 2007 09:48:14 +0000 (09:48 +0000)
committerKeir Fraser <keir@xensource.com>
Thu, 1 Nov 2007 09:48:14 +0000 (09:48 +0000)
Corrected a bug in the stdvga code where it did not properly handle 32
bit operations. The buf_ioreq_t can now store 32 bits of data.

Signed-off-by: Robert Phillips <rphillips@virtualiron.com>
Signed-off-by: Ben Guthro <bguthro@virtualiron.com>
xen/arch/x86/hvm/intercept.c
xen/arch/x86/hvm/stdvga.c
xen/include/public/hvm/ioreq.h

index 20eeed5849f15e92a6139195bcd92388b851d483..8ffb26460a41c934cf41d96f99e6334f9d93f876 100644 (file)
@@ -157,19 +157,26 @@ int hvm_buffered_io_send(ioreq_t *p)
     struct hvm_ioreq_page *iorp = &v->domain->arch.hvm_domain.buf_ioreq;
     buffered_iopage_t *pg = iorp->va;
     buf_ioreq_t bp;
-    /* Timeoffset sends 64b data, but no address.  Use two consecutive slots. */
+    /* Timeoffset sends 64b data, but no address. Use two consecutive slots. */
     int qw = 0;
 
     /* Ensure buffered_iopage fits in a page */
     BUILD_BUG_ON(sizeof(buffered_iopage_t) > PAGE_SIZE);
 
     /* Return 0 for the cases we can't deal with. */
-    if (p->addr > 0xffffful || p->data_is_ptr || p->df || p->count != 1)
+    if ( (p->addr > 0xffffful) || p->data_is_ptr || p->df || (p->count != 1) )
+    {
+        gdprintk(XENLOG_DEBUG, "slow ioreq.  type:%d size:%ld addr:0x%08lx "
+                 "dir:%d ptr:%d df:%d count:%ld\n",
+                 p->type, p->size, p->addr, !!p->dir,
+                 !!p->data_is_ptr, !!p->df, p->count);
         return 0;
+    }
 
     bp.type = p->type;
     bp.dir  = p->dir;
-    switch (p->size) {
+    switch ( p->size )
+    {
     case 1:
         bp.size = 0;
         break;
@@ -182,8 +189,6 @@ int hvm_buffered_io_send(ioreq_t *p)
     case 8:
         bp.size = 3;
         qw = 1;
-        gdprintk(XENLOG_INFO, "quadword ioreq type:%d data:%"PRIx64"\n",
-                 p->type, p->data);
         break;
     default:
         gdprintk(XENLOG_WARNING, "unexpected ioreq size:%"PRId64"\n", p->size);
@@ -191,11 +196,12 @@ int hvm_buffered_io_send(ioreq_t *p)
     }
     
     bp.data = p->data;
-    bp.addr = qw ? ((p->data >> 16) & 0xfffful) : (p->addr & 0xffffful);
+    bp.addr = p->addr;
     
     spin_lock(&iorp->lock);
 
-    if ( (pg->write_pointer - pg->read_pointer) >= IOREQ_BUFFER_SLOT_NUM - (qw ? 1 : 0))
+    if ( (pg->write_pointer - pg->read_pointer) >=
+         (IOREQ_BUFFER_SLOT_NUM - qw) )
     {
         /* The queue is full: send the iopacket through the normal path. */
         spin_unlock(&iorp->lock);
@@ -205,9 +211,9 @@ int hvm_buffered_io_send(ioreq_t *p)
     memcpy(&pg->buf_ioreq[pg->write_pointer % IOREQ_BUFFER_SLOT_NUM],
            &bp, sizeof(bp));
     
-    if (qw) {
+    if ( qw )
+    {
         bp.data = p->data >> 32;
-        bp.addr = (p->data >> 48) & 0xfffful;
         memcpy(&pg->buf_ioreq[(pg->write_pointer+1) % IOREQ_BUFFER_SLOT_NUM],
                &bp, sizeof(bp));
     }
@@ -215,7 +221,7 @@ int hvm_buffered_io_send(ioreq_t *p)
     /* Make the ioreq_t visible /before/ write_pointer. */
     wmb();
     pg->write_pointer += qw ? 2 : 1;
-    
+
     spin_unlock(&iorp->lock);
     
     return 1;
index 79bcc5b07408a9911fe514236ccb039b31a535a7..7d2599ca692f8e539ac299cf9b265498c7d92cfb 100644 (file)
@@ -296,6 +296,8 @@ int stdvga_intercept_pio(ioreq_t *p)
     {
         if ( p->size != 1 )
             gdprintk(XENLOG_WARNING, "unexpected io size:%d\n", (int)p->size);
+        if ( p->data_is_ptr )
+            gdprintk(XENLOG_WARNING, "unexpected data_is_ptr\n");
         if ( !((p->addr == 0x3c5) && (s->sr_index >= sizeof(sr_mask))) &&
              !((p->addr == 0x3cf) && (s->gr_index >= sizeof(gr_mask))) )
         {
@@ -643,6 +645,10 @@ int stdvga_intercept_mmio(ioreq_t *p)
             s->cache = 0;
         }
     }
+    else
+    {
+        buf = (p->dir == IOREQ_WRITE);
+    }
 
     rc = (buf && hvm_buffered_io_send(p));
 
index bb11ce35476905784ad90d39a2ef57b2065ee82b..18922c44401ebf4af436dea496472b535c274de2 100644 (file)
@@ -80,9 +80,9 @@ typedef struct shared_iopage shared_iopage_t;
 struct buf_ioreq {
     uint8_t  type;   /*  I/O type                    */
     uint8_t  dir:1;  /*  1=read, 0=write             */
-    uint8_t  size:2; /*  0=>1, 1=>2, 3=>8. If 8 then use two contig buf_ioreqs */
-    uint16_t data;   /*  (low order) data            */
-    uint32_t addr;   /*  physical address or high-order data */
+    uint8_t  size:2; /*  0=>1, 1=>2, 2=>4, 3=>8. If 8, use two buf_ioreqs */
+    uint32_t addr:20;/*  physical address            */
+    uint32_t data;   /*  data                        */
 };
 typedef struct buf_ioreq buf_ioreq_t;