[HVM] Use correct types for guest physical addresses
authorTim Deegan <Tim.Deegan@xensource.com>
Tue, 31 Oct 2006 16:42:46 +0000 (16:42 +0000)
committerTim Deegan <Tim.Deegan@xensource.com>
Tue, 31 Oct 2006 16:42:46 +0000 (16:42 +0000)
Guest physical addresses are not guaranteed to fit in either a pointer
or an unsigned long int; use paddr_t for them.
Signed-off-by: Tim Deegan <Tim.Deegan@xensource.com>
18 files changed:
tools/ioemu/target-i386-dm/helper2.c
tools/libxc/xc_hvm_build.c
xen/arch/ia64/vmx/mmio.c
xen/arch/x86/hvm/hvm.c
xen/arch/x86/hvm/i8254.c
xen/arch/x86/hvm/i8259.c
xen/arch/x86/hvm/intercept.c
xen/arch/x86/hvm/io.c
xen/arch/x86/hvm/platform.c
xen/arch/x86/hvm/pmtimer.c
xen/arch/x86/hvm/rtc.c
xen/arch/x86/hvm/svm/svm.c
xen/arch/x86/mm/shadow/multi.c
xen/arch/x86/mm/shadow/types.h
xen/include/asm-x86/hvm/io.h
xen/include/asm-x86/hvm/support.h
xen/include/asm-x86/shadow.h
xen/include/public/hvm/ioreq.h

index 22ea8b56e3f67303eb2ed9f350711fb13591299f..1948e01cdd338606a6671d57a38f14abb7f201c0 100644 (file)
@@ -193,10 +193,10 @@ void sp_info()
     for (i = 0; i < vcpus; i++) {
         req = &(shared_page->vcpu_iodata[i].vp_ioreq);
         term_printf("vcpu %d: event port %d\n", i, ioreq_local_port[i]);
-        term_printf("  req state: %x, pvalid: %x, addr: %"PRIx64", "
+        term_printf("  req state: %x, ptr: %x, addr: %"PRIx64", "
                     "data: %"PRIx64", count: %"PRIx64", size: %"PRIx64"\n",
-                    req->state, req->pdata_valid, req->addr,
-                    req->u.data, req->count, req->size);
+                    req->state, req->data_is_ptr, req->addr,
+                    req->data, req->count, req->size);
         term_printf("  IO totally occurred on this vcpu: %"PRIx64"\n",
                     req->io_count);
     }
@@ -216,10 +216,10 @@ static ioreq_t *__cpu_get_ioreq(int vcpu)
     }
 
     fprintf(logfile, "False I/O request ... in-service already: "
-            "%x, pvalid: %x, port: %"PRIx64", "
+            "%x, ptr: %x, port: %"PRIx64", "
             "data: %"PRIx64", count: %"PRIx64", size: %"PRIx64"\n",
-            req->state, req->pdata_valid, req->addr,
-            req->u.data, req->count, req->size);
+            req->state, req->data_is_ptr, req->addr,
+            req->data, req->count, req->size);
     return NULL;
 }
 
@@ -305,26 +305,26 @@ void cpu_ioreq_pio(CPUState *env, ioreq_t *req)
     sign = req->df ? -1 : 1;
 
     if (req->dir == IOREQ_READ) {
-        if (!req->pdata_valid) {
-            req->u.data = do_inp(env, req->addr, req->size);
+        if (!req->data_is_ptr) {
+            req->data = do_inp(env, req->addr, req->size);
         } else {
             unsigned long tmp;
 
             for (i = 0; i < req->count; i++) {
                 tmp = do_inp(env, req->addr, req->size);
-                write_physical((target_phys_addr_t) req->u.pdata
+                write_physical((target_phys_addr_t) req->data
                   + (sign * i * req->size),
                   req->size, &tmp);
             }
         }
     } else if (req->dir == IOREQ_WRITE) {
-        if (!req->pdata_valid) {
-            do_outp(env, req->addr, req->size, req->u.data);
+        if (!req->data_is_ptr) {
+            do_outp(env, req->addr, req->size, req->data);
         } else {
             for (i = 0; i < req->count; i++) {
                 unsigned long tmp;
 
-                read_physical((target_phys_addr_t) req->u.pdata
+                read_physical((target_phys_addr_t) req->data
                   + (sign * i * req->size),
                   req->size, &tmp);
                 do_outp(env, req->addr, req->size, tmp);
@@ -339,18 +339,18 @@ void cpu_ioreq_move(CPUState *env, ioreq_t *req)
 
     sign = req->df ? -1 : 1;
 
-    if (!req->pdata_valid) {
+    if (!req->data_is_ptr) {
         if (req->dir == IOREQ_READ) {
             for (i = 0; i < req->count; i++) {
                 read_physical(req->addr
                   + (sign * i * req->size),
-                  req->size, &req->u.data);
+                  req->size, &req->data);
             }
         } else if (req->dir == IOREQ_WRITE) {
             for (i = 0; i < req->count; i++) {
                 write_physical(req->addr
                   + (sign * i * req->size),
-                  req->size, &req->u.data);
+                  req->size, &req->data);
             }
         }
     } else {
@@ -361,13 +361,13 @@ void cpu_ioreq_move(CPUState *env, ioreq_t *req)
                 read_physical(req->addr
                   + (sign * i * req->size),
                   req->size, &tmp);
-                write_physical((target_phys_addr_t )req->u.pdata
+                write_physical((target_phys_addr_t )req->data
                   + (sign * i * req->size),
                   req->size, &tmp);
             }
         } else if (req->dir == IOREQ_WRITE) {
             for (i = 0; i < req->count; i++) {
-                read_physical((target_phys_addr_t) req->u.pdata
+                read_physical((target_phys_addr_t) req->data
                   + (sign * i * req->size),
                   req->size, &tmp);
                 write_physical(req->addr
@@ -382,66 +382,66 @@ void cpu_ioreq_and(CPUState *env, ioreq_t *req)
 {
     unsigned long tmp1, tmp2;
 
-    if (req->pdata_valid != 0)
+    if (req->data_is_ptr != 0)
         hw_error("expected scalar value");
 
     read_physical(req->addr, req->size, &tmp1);
     if (req->dir == IOREQ_WRITE) {
-        tmp2 = tmp1 & (unsigned long) req->u.data;
+        tmp2 = tmp1 & (unsigned long) req->data;
         write_physical(req->addr, req->size, &tmp2);
     }
-    req->u.data = tmp1;
+    req->data = tmp1;
 }
 
 void cpu_ioreq_add(CPUState *env, ioreq_t *req)
 {
     unsigned long tmp1, tmp2;
 
-    if (req->pdata_valid != 0)
+    if (req->data_is_ptr != 0)
         hw_error("expected scalar value");
 
     read_physical(req->addr, req->size, &tmp1);
     if (req->dir == IOREQ_WRITE) {
-        tmp2 = tmp1 + (unsigned long) req->u.data;
+        tmp2 = tmp1 + (unsigned long) req->data;
         write_physical(req->addr, req->size, &tmp2);
     }
-    req->u.data = tmp1;
+    req->data = tmp1;
 }
 
 void cpu_ioreq_or(CPUState *env, ioreq_t *req)
 {
     unsigned long tmp1, tmp2;
 
-    if (req->pdata_valid != 0)
+    if (req->data_is_ptr != 0)
         hw_error("expected scalar value");
 
     read_physical(req->addr, req->size, &tmp1);
     if (req->dir == IOREQ_WRITE) {
-        tmp2 = tmp1 | (unsigned long) req->u.data;
+        tmp2 = tmp1 | (unsigned long) req->data;
         write_physical(req->addr, req->size, &tmp2);
     }
-    req->u.data = tmp1;
+    req->data = tmp1;
 }
 
 void cpu_ioreq_xor(CPUState *env, ioreq_t *req)
 {
     unsigned long tmp1, tmp2;
 
-    if (req->pdata_valid != 0)
+    if (req->data_is_ptr != 0)
         hw_error("expected scalar value");
 
     read_physical(req->addr, req->size, &tmp1);
     if (req->dir == IOREQ_WRITE) {
-        tmp2 = tmp1 ^ (unsigned long) req->u.data;
+        tmp2 = tmp1 ^ (unsigned long) req->data;
         write_physical(req->addr, req->size, &tmp2);
     }
-    req->u.data = tmp1;
+    req->data = tmp1;
 }
 
 void __handle_ioreq(CPUState *env, ioreq_t *req)
 {
-    if (!req->pdata_valid && req->dir == IOREQ_WRITE && req->size != 4)
-       req->u.data &= (1UL << (8 * req->size)) - 1;
+    if (!req->data_is_ptr && req->dir == IOREQ_WRITE && req->size != 4)
+       req->data &= (1UL << (8 * req->size)) - 1;
 
     switch (req->type) {
     case IOREQ_TYPE_PIO:
index 5d81491bc5725d3a03007f25ce3be20bc6924124..09f3d99a86181b46cecba9d0c8bbd42f057c244a 100644 (file)
@@ -12,7 +12,6 @@
 #include <unistd.h>
 #include <zlib.h>
 #include <xen/hvm/hvm_info_table.h>
-#include <xen/hvm/ioreq.h>
 #include <xen/hvm/params.h>
 #include <xen/hvm/e820.h>
 
index d605e828f00babd3ead2dd91f44a0fb3faa7273b..04d1c68d74127324737fbf95e0133fdd649d6615 100644 (file)
@@ -214,8 +214,8 @@ static void low_mmio_access(VCPU *vcpu, u64 pa, u64 *val, size_t s, int dir)
     p->count = 1;
     p->dir = dir;
     if(dir==IOREQ_WRITE)     //write;
-        p->u.data = *val;
-    p->pdata_valid = 0;
+        p->data = *val;
+    p->data_is_ptr = 0;
     p->type = 1;
     p->df = 0;
 
@@ -227,7 +227,7 @@ static void low_mmio_access(VCPU *vcpu, u64 pa, u64 *val, size_t s, int dir)
     }else 
     vmx_send_assist_req(v);
     if(dir==IOREQ_READ){ //read
-        *val=p->u.data;
+        *val=p->data;
     }
     return;
 }
@@ -249,8 +249,8 @@ static void legacy_io_access(VCPU *vcpu, u64 pa, u64 *val, size_t s, int dir)
     p->count = 1;
     p->dir = dir;
     if(dir==IOREQ_WRITE)     //write;
-        p->u.data = *val;
-    p->pdata_valid = 0;
+        p->data = *val;
+    p->data_is_ptr = 0;
     p->type = 0;
     p->df = 0;
 
@@ -258,15 +258,15 @@ static void legacy_io_access(VCPU *vcpu, u64 pa, u64 *val, size_t s, int dir)
 
     vmx_send_assist_req(v);
     if(dir==IOREQ_READ){ //read
-        *val=p->u.data;
+        *val=p->data;
     }
 #ifdef DEBUG_PCI
     if(dir==IOREQ_WRITE)
         if(p->addr == 0xcf8UL)
-            printk("Write 0xcf8, with val [0x%lx]\n", p->u.data);
+            printk("Write 0xcf8, with val [0x%lx]\n", p->data);
     else
         if(p->addr == 0xcfcUL)
-            printk("Read 0xcfc, with val [0x%lx]\n", p->u.data);
+            printk("Read 0xcfc, with val [0x%lx]\n", p->data);
 #endif //DEBUG_PCI
     return;
 }
index 0c6a7b6e645a63b9142b22e42d391b6e7edefc2d..dc82e253e8c10be87ad960082e3130fc0aef6a64 100644 (file)
@@ -406,16 +406,13 @@ void hvm_hlt(unsigned long rflags)
 /*
  * __hvm_copy():
  *  @buf  = hypervisor buffer
- *  @addr = guest virtual or physical address to copy to/from
+ *  @addr = guest physical address to copy to/from
  *  @size = number of bytes to copy
  *  @dir  = copy *to* guest (TRUE) or *from* guest (FALSE)?
- *  @phy  = interpret addr as physical (TRUE) or virtual (FALSE) address?
  * Returns number of bytes failed to copy (0 == complete success).
  */
-static int __hvm_copy(
-    void *buf, unsigned long addr, int size, int dir, int phy)
+static int __hvm_copy(void *buf, paddr_t addr, int size, int dir)
 {
-    struct vcpu *v = current;
     unsigned long mfn;
     char *p;
     int count, todo;
@@ -425,9 +422,7 @@ static int __hvm_copy(
     {
         count = min_t(int, PAGE_SIZE - (addr & ~PAGE_MASK), todo);
 
-        mfn = phy ? 
-            get_mfn_from_gpfn(addr >> PAGE_SHIFT) :
-            mfn_x(sh_vcpu_gfn_to_mfn(v, shadow_gva_to_gfn(v, addr)));
+        mfn = get_mfn_from_gpfn(addr >> PAGE_SHIFT);
         if ( mfn == INVALID_MFN )
             return todo;
 
@@ -448,24 +443,24 @@ static int __hvm_copy(
     return 0;
 }
 
-int hvm_copy_to_guest_phys(unsigned long paddr, void *buf, int size)
+int hvm_copy_to_guest_phys(paddr_t paddr, void *buf, int size)
 {
-    return __hvm_copy(buf, paddr, size, 1, 1);
+    return __hvm_copy(buf, paddr, size, 1);
 }
 
-int hvm_copy_from_guest_phys(void *buf, unsigned long paddr, int size)
+int hvm_copy_from_guest_phys(void *buf, paddr_t paddr, int size)
 {
-    return __hvm_copy(buf, paddr, size, 0, 1);
+    return __hvm_copy(buf, paddr, size, 0);
 }
 
 int hvm_copy_to_guest_virt(unsigned long vaddr, void *buf, int size)
 {
-    return __hvm_copy(buf, vaddr, size, 1, 0);
+    return __hvm_copy(buf, shadow_gva_to_gpa(current, vaddr), size, 1);
 }
 
 int hvm_copy_from_guest_virt(void *buf, unsigned long vaddr, int size)
 {
-    return __hvm_copy(buf, vaddr, size, 0, 0);
+    return __hvm_copy(buf, shadow_gva_to_gpa(current, vaddr), size, 0);
 }
 
 /*
index 464ddee8f9615881d0d9b81f3e4b2a5180ca0ead..96a80cf67033013cda6622befc9517335c7d048b 100644 (file)
@@ -392,17 +392,17 @@ static int handle_pit_io(ioreq_t *p)
     struct PITState *vpit = &(v->domain->arch.hvm_domain.pl_time.vpit);
 
     if (p->size != 1 ||
-        p->pdata_valid ||
+        p->data_is_ptr ||
         p->type != IOREQ_TYPE_PIO){
         printk("HVM_PIT:wrong PIT IO!\n");
         return 1;
     }
     
     if (p->dir == 0) {/* write */
-        pit_ioport_write(vpit, p->addr, p->u.data);
+        pit_ioport_write(vpit, p->addr, p->data);
     } else if (p->dir == 1) { /* read */
         if ( (p->addr & 3) != 3 ) {
-            p->u.data = pit_ioport_read(vpit, p->addr);
+            p->data = pit_ioport_read(vpit, p->addr);
         } else {
             printk("HVM_PIT: read A1:A0=3!\n");
         }
@@ -434,16 +434,16 @@ static int handle_speaker_io(ioreq_t *p)
     struct PITState *vpit = &(v->domain->arch.hvm_domain.pl_time.vpit);
 
     if (p->size != 1 ||
-        p->pdata_valid ||
+        p->data_is_ptr ||
         p->type != IOREQ_TYPE_PIO){
         printk("HVM_SPEAKER:wrong SPEAKER IO!\n");
         return 1;
     }
     
     if (p->dir == 0) {/* write */
-        speaker_ioport_write(vpit, p->addr, p->u.data);
+        speaker_ioport_write(vpit, p->addr, p->data);
     } else if (p->dir == 1) {/* read */
-        p->u.data = speaker_ioport_read(vpit, p->addr);
+        p->data = speaker_ioport_read(vpit, p->addr);
     }
 
     return 1;
index 470b9e70c1eae711d1976c6589f411f21cc46793..5da40cf7f926a3f4575169e64d9622c6f9a81dcb 100644 (file)
@@ -491,11 +491,10 @@ static int intercept_pic_io(ioreq_t *p)
 
     pic = &current->domain->arch.hvm_domain.vpic;
     if ( p->dir == IOREQ_WRITE ) {
-        if ( p->pdata_valid )
-            (void)hvm_copy_from_guest_phys(
-                &data, (unsigned long)p->u.pdata, p->size);
+        if ( p->data_is_ptr )
+            (void)hvm_copy_from_guest_phys(&data, p->data, p->size);
         else
-            data = p->u.data;
+            data = p->data;
         spin_lock_irqsave(&pic->lock, flags);
         pic_ioport_write((void*)&pic->pics[p->addr>>7],
                 (uint32_t) p->addr, (uint32_t) (data & 0xff));
@@ -506,11 +505,10 @@ static int intercept_pic_io(ioreq_t *p)
         data = pic_ioport_read(
             (void*)&pic->pics[p->addr>>7], (uint32_t) p->addr);
         spin_unlock_irqrestore(&pic->lock, flags);
-        if ( p->pdata_valid )
-            (void)hvm_copy_to_guest_phys(
-                (unsigned long)p->u.pdata, &data, p->size);
+        if ( p->data_is_ptr )
+            (void)hvm_copy_to_guest_phys(p->data, &data, p->size);
         else
-            p->u.data = (u64)data;
+            p->data = (u64)data;
     }
     return 1;
 }
@@ -528,11 +526,10 @@ static int intercept_elcr_io(ioreq_t *p)
 
     s = &current->domain->arch.hvm_domain.vpic;
     if ( p->dir == IOREQ_WRITE ) {
-        if ( p->pdata_valid )
-            (void)hvm_copy_from_guest_phys(
-                &data, (unsigned long)p->u.pdata, p->size);
+        if ( p->data_is_ptr )
+            (void)hvm_copy_from_guest_phys(&data, p->data, p->size);
         else
-            data = p->u.data;
+            data = p->data;
         spin_lock_irqsave(&s->lock, flags);
         elcr_ioport_write((void*)&s->pics[p->addr&1],
                 (uint32_t) p->addr, (uint32_t)( data & 0xff));
@@ -543,11 +540,10 @@ static int intercept_elcr_io(ioreq_t *p)
     else {
         data = (u64) elcr_ioport_read(
                 (void*)&s->pics[p->addr&1], (uint32_t) p->addr);
-        if ( p->pdata_valid )
-            (void)hvm_copy_to_guest_phys(
-                (unsigned long)p->u.pdata, &data, p->size);
+        if ( p->data_is_ptr )
+            (void)hvm_copy_to_guest_phys(p->data, &data, p->size);
         else
-            p->u.data = (u64)data;
+            p->data = (u64)data;
     }
     return 1;
 }
index 8c20d9f23c70c006e229ec37c5d80da870605fe2..8a6dc963dfdd57f02ea3a9c6f367426d8724dce2 100644 (file)
@@ -67,12 +67,12 @@ static inline void hvm_mmio_access(struct vcpu *v,
     switch ( p->type ) {
     case IOREQ_TYPE_COPY:
     {
-        if ( !p->pdata_valid ) {
+        if ( !p->data_is_ptr ) {
             if ( p->dir == IOREQ_READ )
-                p->u.data = read_handler(v, p->addr, p->size);
+                p->data = read_handler(v, p->addr, p->size);
             else    /* p->dir == IOREQ_WRITE */
-                write_handler(v, p->addr, p->size, p->u.data);
-        } else {    /* !p->pdata_valid */
+                write_handler(v, p->addr, p->size, p->data);
+        } else {    /* p->data_is_ptr */
             int i, sign = (p->df) ? -1 : 1;
 
             if ( p->dir == IOREQ_READ ) {
@@ -81,7 +81,7 @@ static inline void hvm_mmio_access(struct vcpu *v,
                         p->addr + (sign * i * p->size),
                         p->size);
                     (void)hvm_copy_to_guest_phys(
-                        (unsigned long)p->u.pdata + (sign * i * p->size),
+                        p->data + (sign * i * p->size),
                         &data,
                         p->size);
                 }
@@ -89,7 +89,7 @@ static inline void hvm_mmio_access(struct vcpu *v,
                 for ( i = 0; i < p->count; i++ ) {
                     (void)hvm_copy_from_guest_phys(
                         &data,
-                        (unsigned long)p->u.pdata + (sign * i * p->size),
+                        p->data + (sign * i * p->size),
                         p->size);
                     write_handler(v,
                         p->addr + (sign * i * p->size),
@@ -103,37 +103,37 @@ static inline void hvm_mmio_access(struct vcpu *v,
     case IOREQ_TYPE_AND:
         tmp1 = read_handler(v, p->addr, p->size);
         if ( p->dir == IOREQ_WRITE ) {
-            tmp2 = tmp1 & (unsigned long) p->u.data;
+            tmp2 = tmp1 & (unsigned long) p->data;
             write_handler(v, p->addr, p->size, tmp2);
         }
-        p->u.data = tmp1;
+        p->data = tmp1;
         break;
 
     case IOREQ_TYPE_ADD:
         tmp1 = read_handler(v, p->addr, p->size);
         if (p->dir == IOREQ_WRITE) {
-            tmp2 = tmp1 + (unsigned long) p->u.data;
+            tmp2 = tmp1 + (unsigned long) p->data;
             write_handler(v, p->addr, p->size, tmp2);
         }
-        p->u.data = tmp1;
+        p->data = tmp1;
         break;
 
     case IOREQ_TYPE_OR:
         tmp1 = read_handler(v, p->addr, p->size);
         if ( p->dir == IOREQ_WRITE ) {
-            tmp2 = tmp1 | (unsigned long) p->u.data;
+            tmp2 = tmp1 | (unsigned long) p->data;
             write_handler(v, p->addr, p->size, tmp2);
         }
-        p->u.data = tmp1;
+        p->data = tmp1;
         break;
 
     case IOREQ_TYPE_XOR:
         tmp1 = read_handler(v, p->addr, p->size);
         if ( p->dir == IOREQ_WRITE ) {
-            tmp2 = tmp1 ^ (unsigned long) p->u.data;
+            tmp2 = tmp1 ^ (unsigned long) p->data;
             write_handler(v, p->addr, p->size, tmp2);
         }
-        p->u.data = tmp1;
+        p->data = tmp1;
         break;
 
     case IOREQ_TYPE_XCHG:
@@ -142,8 +142,8 @@ static inline void hvm_mmio_access(struct vcpu *v,
          * its own local APIC.
          */
         tmp1 = read_handler(v, p->addr, p->size);
-        write_handler(v, p->addr, p->size, (unsigned long) p->u.data);
-        p->u.data = tmp1;
+        write_handler(v, p->addr, p->size, (unsigned long) p->data);
+        p->data = tmp1;
         break;
 
     default:
index 8bf9afc470f0ce595e4d6592c2bfb620da1c0b67..f5c13d131bc28eea2faa9cc636e971a7c39f4003 100644 (file)
@@ -365,7 +365,7 @@ static void hvm_pio_assist(struct cpu_user_regs *regs, ioreq_t *p,
     unsigned long old_eax;
     int sign = p->df ? -1 : 1;
 
-    if ( p->pdata_valid || (pio_opp->flags & OVERLAP) )
+    if ( p->data_is_ptr || (pio_opp->flags & OVERLAP) )
     {
         if ( pio_opp->flags & REPZ )
             regs->ecx -= p->count;
@@ -376,9 +376,9 @@ static void hvm_pio_assist(struct cpu_user_regs *regs, ioreq_t *p,
             {
                 unsigned long addr = pio_opp->addr;
                 if ( hvm_paging_enabled(current) )
-                    (void)hvm_copy_to_guest_virt(addr, &p->u.data, p->size);
+                    (void)hvm_copy_to_guest_virt(addr, &p->data, p->size);
                 else
-                    (void)hvm_copy_to_guest_phys(addr, &p->u.data, p->size);
+                    (void)hvm_copy_to_guest_phys(addr, &p->data, p->size);
             }
             regs->edi += sign * p->count * p->size;
         }
@@ -394,13 +394,13 @@ static void hvm_pio_assist(struct cpu_user_regs *regs, ioreq_t *p,
         switch ( p->size )
         {
         case 1:
-            regs->eax = (old_eax & 0xffffff00) | (p->u.data & 0xff);
+            regs->eax = (old_eax & 0xffffff00) | (p->data & 0xff);
             break;
         case 2:
-            regs->eax = (old_eax & 0xffff0000) | (p->u.data & 0xffff);
+            regs->eax = (old_eax & 0xffff0000) | (p->data & 0xffff);
             break;
         case 4:
-            regs->eax = (p->u.data & 0xffffffff);
+            regs->eax = (p->data & 0xffffffff);
             break;
         default:
             printk("Error: %s unknown port size\n", __FUNCTION__);
@@ -425,7 +425,7 @@ static void hvm_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p,
     case INSTR_MOV:
         if (dst & REGISTER) {
             index = operand_index(dst);
-            set_reg_value(size, index, 0, regs, p->u.data);
+            set_reg_value(size, index, 0, regs, p->data);
         }
         break;
 
@@ -433,15 +433,15 @@ static void hvm_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p,
         if (dst & REGISTER) {
             switch (size) {
             case BYTE:
-                p->u.data &= 0xFFULL;
+                p->data &= 0xFFULL;
                 break;
 
             case WORD:
-                p->u.data &= 0xFFFFULL;
+                p->data &= 0xFFFFULL;
                 break;
 
             case LONG:
-                p->u.data &= 0xFFFFFFFFULL;
+                p->data &= 0xFFFFFFFFULL;
                 break;
 
             default:
@@ -449,7 +449,7 @@ static void hvm_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p,
                 domain_crash_synchronous();
             }
             index = operand_index(dst);
-            set_reg_value(operand_size(dst), index, 0, regs, p->u.data);
+            set_reg_value(operand_size(dst), index, 0, regs, p->data);
         }
         break;
 
@@ -457,21 +457,21 @@ static void hvm_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p,
         if (dst & REGISTER) {
             switch (size) {
             case BYTE:
-                p->u.data &= 0xFFULL;
-                if ( p->u.data & 0x80ULL )
-                    p->u.data |= 0xFFFFFFFFFFFFFF00ULL;
+                p->data &= 0xFFULL;
+                if ( p->data & 0x80ULL )
+                    p->data |= 0xFFFFFFFFFFFFFF00ULL;
                 break;
 
             case WORD:
-                p->u.data &= 0xFFFFULL;
-                if ( p->u.data & 0x8000ULL )
-                    p->u.data |= 0xFFFFFFFFFFFF0000ULL;
+                p->data &= 0xFFFFULL;
+                if ( p->data & 0x8000ULL )
+                    p->data |= 0xFFFFFFFFFFFF0000ULL;
                 break;
 
             case LONG:
-                p->u.data &= 0xFFFFFFFFULL;
-                if ( p->u.data & 0x80000000ULL )
-                    p->u.data |= 0xFFFFFFFF00000000ULL;
+                p->data &= 0xFFFFFFFFULL;
+                if ( p->data & 0x80000000ULL )
+                    p->data |= 0xFFFFFFFF00000000ULL;
                 break;
 
             default:
@@ -479,7 +479,7 @@ static void hvm_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p,
                 domain_crash_synchronous();
             }
             index = operand_index(dst);
-            set_reg_value(operand_size(dst), index, 0, regs, p->u.data);
+            set_reg_value(operand_size(dst), index, 0, regs, p->data);
         }
         break;
 
@@ -493,9 +493,9 @@ static void hvm_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p,
             unsigned long addr = mmio_opp->addr;
 
             if (hvm_paging_enabled(current))
-                (void)hvm_copy_to_guest_virt(addr, &p->u.data, p->size);
+                (void)hvm_copy_to_guest_virt(addr, &p->data, p->size);
             else
-                (void)hvm_copy_to_guest_phys(addr, &p->u.data, p->size);
+                (void)hvm_copy_to_guest_phys(addr, &p->data, p->size);
         }
 
         regs->esi += sign * p->count * p->size;
@@ -521,14 +521,14 @@ static void hvm_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p,
         if (src & REGISTER) {
             index = operand_index(src);
             value = get_reg_value(size, index, 0, regs);
-            diff = (unsigned long) p->u.data & value;
+            diff = (unsigned long) p->data & value;
         } else if (src & IMMEDIATE) {
             value = mmio_opp->immediate;
-            diff = (unsigned long) p->u.data & value;
+            diff = (unsigned long) p->data & value;
         } else if (src & MEMORY) {
             index = operand_index(dst);
             value = get_reg_value(size, index, 0, regs);
-            diff = (unsigned long) p->u.data & value;
+            diff = (unsigned long) p->data & value;
             set_reg_value(size, index, 0, regs, diff);
         }
 
@@ -536,14 +536,14 @@ static void hvm_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p,
         if (src & REGISTER) {
             index = operand_index(src);
             value = get_reg_value(size, index, 0, regs);
-            diff = (unsigned long) p->u.data + value;
+            diff = (unsigned long) p->data + value;
         } else if (src & IMMEDIATE) {
             value = mmio_opp->immediate;
-            diff = (unsigned long) p->u.data + value;
+            diff = (unsigned long) p->data + value;
         } else if (src & MEMORY) {
             index = operand_index(dst);
             value = get_reg_value(size, index, 0, regs);
-            diff = (unsigned long) p->u.data + value;
+            diff = (unsigned long) p->data + value;
             set_reg_value(size, index, 0, regs, diff);
         }
 
@@ -563,14 +563,14 @@ static void hvm_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p,
         if (src & REGISTER) {
             index = operand_index(src);
             value = get_reg_value(size, index, 0, regs);
-            diff = (unsigned long) p->u.data | value;
+            diff = (unsigned long) p->data | value;
         } else if (src & IMMEDIATE) {
             value = mmio_opp->immediate;
-            diff = (unsigned long) p->u.data | value;
+            diff = (unsigned long) p->data | value;
         } else if (src & MEMORY) {
             index = operand_index(dst);
             value = get_reg_value(size, index, 0, regs);
-            diff = (unsigned long) p->u.data | value;
+            diff = (unsigned long) p->data | value;
             set_reg_value(size, index, 0, regs, diff);
         }
 
@@ -590,14 +590,14 @@ static void hvm_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p,
         if (src & REGISTER) {
             index = operand_index(src);
             value = get_reg_value(size, index, 0, regs);
-            diff = (unsigned long) p->u.data ^ value;
+            diff = (unsigned long) p->data ^ value;
         } else if (src & IMMEDIATE) {
             value = mmio_opp->immediate;
-            diff = (unsigned long) p->u.data ^ value;
+            diff = (unsigned long) p->data ^ value;
         } else if (src & MEMORY) {
             index = operand_index(dst);
             value = get_reg_value(size, index, 0, regs);
-            diff = (unsigned long) p->u.data ^ value;
+            diff = (unsigned long) p->data ^ value;
             set_reg_value(size, index, 0, regs, diff);
         }
 
@@ -618,14 +618,14 @@ static void hvm_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p,
         if (src & REGISTER) {
             index = operand_index(src);
             value = get_reg_value(size, index, 0, regs);
-            diff = (unsigned long) p->u.data - value;
+            diff = (unsigned long) p->data - value;
         } else if (src & IMMEDIATE) {
             value = mmio_opp->immediate;
-            diff = (unsigned long) p->u.data - value;
+            diff = (unsigned long) p->data - value;
         } else if (src & MEMORY) {
             index = operand_index(dst);
             value = get_reg_value(size, index, 0, regs);
-            diff = value - (unsigned long) p->u.data;
+            diff = value - (unsigned long) p->data;
             if ( mmio_opp->instr == INSTR_SUB )
                 set_reg_value(size, index, 0, regs, diff);
         }
@@ -636,9 +636,9 @@ static void hvm_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p,
          */
         regs->eflags &= ~(X86_EFLAGS_CF|X86_EFLAGS_PF|X86_EFLAGS_AF|
                           X86_EFLAGS_ZF|X86_EFLAGS_SF|X86_EFLAGS_OF);
-        set_eflags_CF(size, value, (unsigned long) p->u.data, regs);
-        set_eflags_OF(size, diff, value, (unsigned long) p->u.data, regs);
-        set_eflags_AF(size, diff, value, (unsigned long) p->u.data, regs);
+        set_eflags_CF(size, value, (unsigned long) p->data, regs);
+        set_eflags_OF(size, diff, value, (unsigned long) p->data, regs);
+        set_eflags_AF(size, diff, value, (unsigned long) p->data, regs);
         set_eflags_ZF(size, diff, regs);
         set_eflags_SF(size, diff, regs);
         set_eflags_PF(size, diff, regs);
@@ -654,7 +654,7 @@ static void hvm_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p,
             index = operand_index(dst);
             value = get_reg_value(size, index, 0, regs);
         }
-        diff = (unsigned long) p->u.data & value;
+        diff = (unsigned long) p->data & value;
 
         /*
          * Sets the SF, ZF, and PF status flags. CF and OF are set to 0
@@ -674,7 +674,7 @@ static void hvm_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p,
         }
         else if ( src & IMMEDIATE )
             value = mmio_opp->immediate;
-        if (p->u.data & (1 << (value & ((1 << 5) - 1))))
+        if (p->data & (1 << (value & ((1 << 5) - 1))))
             regs->eflags |= X86_EFLAGS_CF;
         else
             regs->eflags &= ~X86_EFLAGS_CF;
@@ -684,10 +684,10 @@ static void hvm_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p,
     case INSTR_XCHG:
         if (src & REGISTER) {
             index = operand_index(src);
-            set_reg_value(size, index, 0, regs, p->u.data);
+            set_reg_value(size, index, 0, regs, p->data);
         } else {
             index = operand_index(dst);
-            set_reg_value(size, index, 0, regs, p->u.data);
+            set_reg_value(size, index, 0, regs, p->data);
         }
         break;
     }
index e26b3e96d091a66b95fd74df2c12a14e7a78e230..2fd21991b3d908bc9bbbe2e8943d64df1560a061 100644 (file)
@@ -741,7 +741,7 @@ static void hvm_send_assist_req(struct vcpu *v)
 }
 
 void send_pio_req(unsigned long port, unsigned long count, int size,
-                  long value, int dir, int df, int pvalid)
+                  long value, int dir, int df, int value_is_ptr)
 {
     struct vcpu *v = current;
     vcpu_iodata_t *vio;
@@ -749,8 +749,8 @@ void send_pio_req(unsigned long port, unsigned long count, int size,
 
     if ( size == 0 || count == 0 ) {
         printk("null pio request? port %lx, count %lx, "
-               "size %d, value %lx, dir %d, pvalid %d.\n",
-               port, count, size, value, dir, pvalid);
+               "size %d, value %lx, dir %d, value_is_ptr %d.\n",
+               port, count, size, value, dir, value_is_ptr);
     }
 
     vio = get_vio(v->domain, v->vcpu_id);
@@ -765,7 +765,7 @@ void send_pio_req(unsigned long port, unsigned long count, int size,
                p->state);
 
     p->dir = dir;
-    p->pdata_valid = pvalid;
+    p->data_is_ptr = value_is_ptr;
 
     p->type = IOREQ_TYPE_PIO;
     p->size = size;
@@ -775,14 +775,14 @@ void send_pio_req(unsigned long port, unsigned long count, int size,
 
     p->io_count++;
 
-    if ( pvalid )   /* get physical address of data */
+    if ( value_is_ptr )   /* get physical address of data */
     {
         if ( hvm_paging_enabled(current) )
-            p->u.pdata = (void *)shadow_gva_to_gpa(current, value);
+            p->data = shadow_gva_to_gpa(current, value);
         else
-            p->u.pdata = (void *)value; /* guest VA == guest PA */
+            p->data = value; /* guest VA == guest PA */
     } else if ( dir == IOREQ_WRITE )
-        p->u.data = value;
+        p->data = value;
 
     if ( hvm_portio_intercept(p) ) {
         p->state = STATE_IORESP_READY;
@@ -795,7 +795,7 @@ void send_pio_req(unsigned long port, unsigned long count, int size,
 
 static void send_mmio_req(unsigned char type, unsigned long gpa,
                           unsigned long count, int size, long value,
-                          int dir, int df, int pvalid)
+                          int dir, int df, int value_is_ptr)
 {
     struct vcpu *v = current;
     vcpu_iodata_t *vio;
@@ -803,8 +803,8 @@ static void send_mmio_req(unsigned char type, unsigned long gpa,
 
     if ( size == 0 || count == 0 ) {
         printk("null mmio request? type %d, gpa %lx, "
-               "count %lx, size %d, value %lx, dir %d, pvalid %d.\n",
-               type, gpa, count, size, value, dir, pvalid);
+               "count %lx, size %d, value %lx, dir %d, value_is_ptr %d.\n",
+               type, gpa, count, size, value, dir, value_is_ptr);
     }
 
     vio = get_vio(v->domain, v->vcpu_id);
@@ -819,7 +819,7 @@ static void send_mmio_req(unsigned char type, unsigned long gpa,
         printk("WARNING: send mmio with something already pending (%d)?\n",
                p->state);
     p->dir = dir;
-    p->pdata_valid = pvalid;
+    p->data_is_ptr = value_is_ptr;
 
     p->type = type;
     p->size = size;
@@ -829,13 +829,13 @@ static void send_mmio_req(unsigned char type, unsigned long gpa,
 
     p->io_count++;
 
-    if (pvalid) {
+    if (value_is_ptr) {
         if (hvm_paging_enabled(v))
-            p->u.data = shadow_gva_to_gpa(v, value);
+            p->data = shadow_gva_to_gpa(v, value);
         else
-            p->u.pdata = (void *) value; /* guest VA == guest PA */
+            p->data = value; /* guest VA == guest PA */
     } else
-        p->u.data = value;
+        p->data = value;
 
     if ( hvm_mmio_intercept(p) || hvm_buffered_io_intercept(p) ) {
         p->state = STATE_IORESP_READY;
index e0c93536ea614c2cd25e8269eb72c904e2f71e31..f857de8f872f1888fd3b36a010d01c9fa14d4d4a 100644 (file)
@@ -20,7 +20,7 @@ static int handle_pmt_io(ioreq_t *p)
     uint64_t curr_gtime;
 
     if (p->size != 4 ||
-        p->pdata_valid ||
+        p->data_is_ptr ||
         p->type != IOREQ_TYPE_PIO){
         printk("HVM_PMT: wrong PM timer IO\n");
         return 1;
@@ -32,7 +32,7 @@ static int handle_pmt_io(ioreq_t *p)
     } else if (p->dir == 1) { /* read */
         curr_gtime = hvm_get_guest_time(s->vcpu);
         s->pm1_timer += ((curr_gtime - s->last_gtime) * s->scale) >> 32;
-        p->u.data = s->pm1_timer;
+        p->data = s->pm1_timer;
         s->last_gtime = curr_gtime;
         return 1;
     }
index 0f5e11986e0b64becc40d9fbbead94ba8e1e66eb..5aff1b72d0607568ec0468265af6eef882ea4046 100644 (file)
@@ -345,17 +345,17 @@ static int handle_rtc_io(ioreq_t *p)
     struct RTCState *vrtc = &v->domain->arch.hvm_domain.pl_time.vrtc;
 
     if (p->size != 1 ||
-        p->pdata_valid ||
+        p->data_is_ptr ||
         p->type != IOREQ_TYPE_PIO){
         printk("HVM_RTC: wrong RTC IO!\n");
         return 1;
     }
     
     if (p->dir == 0) { /* write */
-        if (rtc_ioport_write(vrtc, p->addr, p->u.data & 0xFF))
+        if (rtc_ioport_write(vrtc, p->addr, p->data & 0xFF))
             return 1;
     } else if (p->dir == 1 && vrtc->cmos_index < RTC_SIZE) { /* read */
-        p->u.data = rtc_ioport_read(vrtc, p->addr);
+        p->data = rtc_ioport_read(vrtc, p->addr);
         return 1;
     }
     return 0;
index 2d6fb878a0ff7f68ad54ea65142493206753918c..634900f195b858b1fe76ab9c11ef5b7012e3a168 100644 (file)
@@ -2545,10 +2545,10 @@ void walk_shadow_and_guest_pt(unsigned long gva)
     l1_pgentry_t spte;
     struct vcpu        *v    = current;
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
-    unsigned long gpa;
+    paddr_t gpa;
 
     gpa = shadow_gva_to_gpa(current, gva);
-    printk( "gva = %lx, gpa=%lx, gCR3=%x\n", gva, gpa, (u32)vmcb->cr3 );
+    printk("gva = %lx, gpa=%"PRIpaddr", gCR3=%x\n", gva, gpa, (u32)vmcb->cr3);
     if( !svm_paging_enabled(v) || mmio_space(gpa) )
         return;
 
index b70c979fbd0d9f9eaaf4a6eb4b773b34d3bdaf42..c3b7f51c2185b111923de1a866981123818d25ea 100644 (file)
  *
  * THINGS TO DO LATER:
  * 
- * FIX GVA_TO_GPA
- * The current interface returns an unsigned long, which is not big enough
- * to hold a physical address in PAE.  Should return a gfn instead.
- * 
  * TEARDOWN HEURISTICS
  * Also: have a heuristic for when to destroy a previous paging-mode's 
  * shadows.  When a guest is done with its start-of-day 32-bit tables
@@ -2837,7 +2833,7 @@ static int sh_page_fault(struct vcpu *v,
     perfc_incrc(shadow_fault_mmio);
     sh_audit_gw(v, &gw);
     unmap_walk(v, &gw);
-    SHADOW_PRINTK("mmio\n");
+    SHADOW_PRINTK("mmio %#"PRIpaddr"\n", gpa);
     shadow_audit_tables(v);
     reset_early_unshadow(v);
     shadow_unlock(d);
@@ -2941,7 +2937,7 @@ sh_gva_to_gfn(struct vcpu *v, unsigned long va)
 }
 
 
-static unsigned long
+static paddr_t
 sh_gva_to_gpa(struct vcpu *v, unsigned long va)
 /* Called to translate a guest virtual address to what the *guest*
  * pagetables would map it to. */
@@ -2950,7 +2946,7 @@ sh_gva_to_gpa(struct vcpu *v, unsigned long va)
     if ( gfn == INVALID_GFN )
         return 0;
     else
-        return (gfn << PAGE_SHIFT) | (va & ~PAGE_MASK);
+        return (((paddr_t)gfn) << PAGE_SHIFT) + (va & ~PAGE_MASK);
 }
 
 
index 69d077f5619273839823b5803fb08e8af8766cda..058fc7e91da579c0a9f2dbc13869b9c2dab8cccc 100644 (file)
@@ -404,11 +404,22 @@ valid_gfn(gfn_t m)
 }
 
 /* Translation between mfns and gfns */
+
+// vcpu-specific version of gfn_to_mfn().  This is where we hide the dirty
+// little secret that, for hvm guests with paging disabled, nearly all of the
+// shadow code actually think that the guest is running on *untranslated* page
+// tables (which is actually domain->phys_table).
+//
+
 static inline mfn_t
 vcpu_gfn_to_mfn(struct vcpu *v, gfn_t gfn)
 {
-    return sh_vcpu_gfn_to_mfn(v, gfn_x(gfn));
-} 
+    if ( !shadow_vcpu_mode_translate(v) )
+        return _mfn(gfn_x(gfn));
+    if ( likely(current->domain == v->domain) )
+        return _mfn(get_mfn_from_gpfn(gfn_x(gfn)));
+    return sh_gfn_to_mfn_foreign(v->domain, gfn_x(gfn));
+}
 
 static inline gfn_t
 mfn_to_gfn(struct domain *d, mfn_t mfn)
index 98441ee260a1c9bed92e12997b0c1682476416e1..a49cf34ad3d62140229c3bdb5ec2ff7bdbcc1391 100644 (file)
@@ -142,7 +142,7 @@ static inline int irq_masked(unsigned long eflags)
 #endif
 
 extern void send_pio_req(unsigned long port, unsigned long count, int size,
-                         long value, int dir, int df, int pvalid);
+                         long value, int dir, int df, int value_is_ptr);
 extern void handle_mmio(unsigned long gpa);
 extern void hvm_interrupt_post(struct vcpu *v, int vector, int type);
 extern void hvm_io_assist(struct vcpu *v);
index 1c557c228f7d4308d0a04a2d945bc02d2c2539d2..c7149c1894f072a672e3ea4ba017142f61f70a81 100644 (file)
@@ -136,8 +136,8 @@ extern unsigned int opt_hvm_debug_level;
 
 extern int hvm_enabled;
 
-int hvm_copy_to_guest_phys(unsigned long paddr, void *buf, int size);
-int hvm_copy_from_guest_phys(void *buf, unsigned long paddr, int size);
+int hvm_copy_to_guest_phys(paddr_t paddr, void *buf, int size);
+int hvm_copy_from_guest_phys(void *buf, paddr_t paddr, int size);
 int hvm_copy_to_guest_virt(unsigned long vaddr, void *buf, int size);
 int hvm_copy_from_guest_virt(void *buf, unsigned long vaddr, int size);
 
index 27cf6843eb856faad6effc4ce691cb4e02ca971d..d020251379f18bb7d6d5781e4701d4fca562d65a 100644 (file)
@@ -259,7 +259,7 @@ struct shadow_paging_mode {
     int           (*page_fault            )(struct vcpu *v, unsigned long va,
                                             struct cpu_user_regs *regs);
     int           (*invlpg                )(struct vcpu *v, unsigned long va);
-    unsigned long (*gva_to_gpa            )(struct vcpu *v, unsigned long va);
+    paddr_t       (*gva_to_gpa            )(struct vcpu *v, unsigned long va);
     unsigned long (*gva_to_gfn            )(struct vcpu *v, unsigned long va);
     void          (*update_cr3            )(struct vcpu *v);
     int           (*map_and_validate_gl1e )(struct vcpu *v, mfn_t gmfn,
@@ -368,11 +368,13 @@ shadow_invlpg(struct vcpu *v, unsigned long va)
     return v->arch.shadow.mode->invlpg(v, va);
 }
 
-static inline unsigned long
+static inline paddr_t
 shadow_gva_to_gpa(struct vcpu *v, unsigned long va)
 /* Called to translate a guest virtual address to what the *guest*
  * pagetables would map it to. */
 {
+    if ( unlikely(!shadow_vcpu_mode_translate(v)) )
+        return (paddr_t) va;
     return v->arch.shadow.mode->gva_to_gpa(v, va);
 }
 
@@ -381,6 +383,8 @@ shadow_gva_to_gfn(struct vcpu *v, unsigned long va)
 /* Called to translate a guest virtual address to what the *guest*
  * pagetables would map it to. */
 {
+    if ( unlikely(!shadow_vcpu_mode_translate(v)) )
+        return va >> PAGE_SHIFT;
     return v->arch.shadow.mode->gva_to_gfn(v, va);
 }
 
@@ -673,21 +677,6 @@ sh_gfn_to_mfn(struct domain *d, unsigned long gfn)
         return sh_gfn_to_mfn_foreign(d, gfn);
 }
 
-// vcpu-specific version of gfn_to_mfn().  This is where we hide the dirty
-// little secret that, for hvm guests with paging disabled, nearly all of the
-// shadow code actually think that the guest is running on *untranslated* page
-// tables (which is actually domain->phys_table).
-//
-static inline mfn_t
-sh_vcpu_gfn_to_mfn(struct vcpu *v, unsigned long gfn)
-{ 
-    if ( !shadow_vcpu_mode_translate(v) )
-        return _mfn(gfn);
-    if ( likely(current->domain == v->domain) )
-        return _mfn(get_mfn_from_gpfn(gfn));
-    return sh_gfn_to_mfn_foreign(v->domain, gfn);
-}
-
 static inline unsigned long
 sh_mfn_to_gfn(struct domain *d, mfn_t mfn)
 {
index b7f68c1282f280256d36306a95c26af8c1a9bd06..47cf3688067a512131d94d3d3cf1cc2d52990223 100644 (file)
@@ -45,12 +45,10 @@ struct ioreq {
     uint64_t addr;          /*  physical address            */
     uint64_t size;          /*  size in bytes               */
     uint64_t count;         /*  for rep prefixes            */
-    union {
-        uint64_t data;      /*  data                        */
-        void    *pdata;     /*  pointer to data             */
-    } u;
+    uint64_t data;          /*  data (or paddr of data)     */
     uint8_t state:4;
-    uint8_t pdata_valid:1;  /* if 1, use pdata above        */
+    uint8_t data_is_ptr:1;  /*  if 1, data above is the guest paddr 
+                             *   of the real data to use.   */
     uint8_t dir:1;          /*  1=read, 0=write             */
     uint8_t df:1;
     uint8_t type;           /* I/O type                     */