[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[XenPPC] [rfc] [patch] grant_entry.flags accessors



These patches are similar to changeset 10747 (which added
vcpu_mark_events_pending), in that they allow PPC to work around some
unusually-sized atomic operations, this time in the grant table driver.

Keir, do you think it's a good idea to make a wiki page to list where
the current ABI is causing problems? That way, when the ABI opens up
again (Xen 4?), we'll have a list of places to fix?

Anyways, I expect you'll have alternate name/interface suggestions in
the patches, so they're just RFC for now.

Signed-off-by: Hollis Blanchard <hollisb@xxxxxxxxxx>

diff -r b3dfb02fc2c2 xen/common/grant_table.c
--- a/xen/common/grant_table.c  Thu Jun 22 10:58:41 2006 -0500
+++ b/xen/common/grant_table.c  Fri Jun 23 16:13:48 2006 -0500
@@ -287,10 +287,10 @@ __gnttab_map_grant_ref(
 
     if ( !(op->flags & GNTMAP_readonly) &&
          !(act->pin & (GNTPIN_hstw_mask|GNTPIN_devw_mask)) )
-        clear_bit(_GTF_writing, &sha->flags);
+        clear_entry_flag(_GTF_writing, &sha->flags);
 
     if ( !act->pin )
-        clear_bit(_GTF_reading, &sha->flags);
+        clear_entry_flag(_GTF_reading, &sha->flags);
 
  unlock_out:
     spin_unlock(&rd->grant_table->lock);
@@ -425,10 +425,10 @@ __gnttab_unmap_grant_ref(
 
     if ( ((act->pin & (GNTPIN_devw_mask|GNTPIN_hstw_mask)) == 0) &&
          !(flags & GNTMAP_readonly) )
-        clear_bit(_GTF_writing, &sha->flags);
+        clear_entry_flag(_GTF_writing, &sha->flags);
 
     if ( act->pin == 0 )
-        clear_bit(_GTF_reading, &sha->flags);
+        clear_entry_flag(_GTF_reading, &sha->flags);
 
  unmap_out:
     op->status = rc;
@@ -889,11 +889,11 @@ gnttab_release_mappings(
             }
 
             if ( (act->pin & (GNTPIN_devw_mask|GNTPIN_hstw_mask)) == 0 )
-                clear_bit(_GTF_writing, &sha->flags);
+                clear_entry_flag(_GTF_writing, &sha->flags);
         }
 
         if ( act->pin == 0 )
-            clear_bit(_GTF_reading, &sha->flags);
+            clear_entry_flag(_GTF_reading, &sha->flags);
 
         spin_unlock(&rd->grant_table->lock);
 
diff -r b3dfb02fc2c2 xen/include/asm-ia64/grant_table.h
--- a/xen/include/asm-ia64/grant_table.h        Thu Jun 22 10:58:41 2006 -0500
+++ b/xen/include/asm-ia64/grant_table.h        Fri Jun 23 16:13:48 2006 -0500
@@ -55,4 +55,9 @@ void guest_physmap_add_page(struct domai
 
 #define gnttab_log_dirty(d, f) ((void)0)
 
+static inline void clear_entry_flag(unsigned long nr, uint16_t *addr)
+{
+       clear_bit(nr, addr);
+}
+
 #endif /* __ASM_GRANT_TABLE_H__ */
diff -r b3dfb02fc2c2 xen/include/asm-x86/grant_table.h
--- a/xen/include/asm-x86/grant_table.h Thu Jun 22 10:58:41 2006 -0500
+++ b/xen/include/asm-x86/grant_table.h Fri Jun 23 16:13:48 2006 -0500
@@ -33,4 +33,9 @@ int destroy_grant_host_mapping(
 
 #define gnttab_log_dirty(d, f) mark_dirty((d), (f))
 
+static inline void clear_entry_flag(unsigned long nr, uint16_t *addr)
+{
+       clear_bit(nr, addr);
+}
+
 #endif /* __ASM_GRANT_TABLE_H__ */

For reference, here's the Xen PPC hack:

diff -r b3dfb02fc2c2 xen/include/asm-ppc/grant_table.h
--- a/xen/include/asm-ppc/grant_table.h Thu Jun 22 10:58:41 2006 -0500
+++ b/xen/include/asm-ppc/grant_table.h Fri Jun 23 16:13:48 2006 -0500
@@ -26,4 +26,16 @@
 #define mark_dirty(d, f) ((void )0)
 #include "../asm-x86/grant_table.h"
 
+static inline void clear_entry_flag(unsigned long nr, uint16_t *addr)
+{
+       unsigned long *laddr;
+       unsigned long lnr;
+
+       BUG_ON((ulong)addr % sizeof(ulong));
+
+       lnr = (BITS_PER_LONG - (sizeof(*addr) * 8)) + nr;
+       laddr = (unsigned long *)addr;
+       clear_bit(lnr, laddr);
+}
+
 #endif  /* __ASM_PPC_GRANT_TABLE_H__ */

The Linux patch applies to the current sparse tree with slight offsets:

diff -r 6f3d44537b76 drivers/xen/core/gnttab.c
--- a/drivers/xen/core/gnttab.c Fri Jun 16 16:07:38 2006 -0500
+++ b/drivers/xen/core/gnttab.c Fri Jun 23 16:14:27 2006 -0500
@@ -201,7 +201,7 @@ gnttab_end_foreign_access_ref(grant_ref_
                        printk(KERN_ALERT "WARNING: g.e. still in use!\n");
                        return 0;
                }
-       } while ((nflags = synch_cmpxchg(&shared[ref].flags, flags, 0)) !=
+       } while ((nflags = gnttab_cmpxchg_flags(&shared[ref].flags, flags, 0)) 
!=
                 flags);
 
        return 1;
@@ -256,7 +256,7 @@ gnttab_end_foreign_transfer_ref(grant_re
          * reference and return failure (== 0).
          */
        while (!((flags = shared[ref].flags) & GTF_transfer_committed)) {
-               if (synch_cmpxchg(&shared[ref].flags, flags, 0) == flags)
+               if (gnttab_cmpxchg_flags(&shared[ref].flags, flags, 0) == flags)
                        return 0;
                cpu_relax();
        }
diff -r 6f3d44537b76 include/asm-i386/mach-xen/asm/synch_bitops.h
--- a/include/asm-i386/mach-xen/asm/synch_bitops.h      Fri Jun 16 16:07:38 
2006 -0500
+++ b/include/asm-i386/mach-xen/asm/synch_bitops.h      Fri Jun 23 16:14:27 
2006 -0500
@@ -138,4 +138,6 @@ static __inline__ int synch_var_test_bit
  synch_const_test_bit((nr),(addr)) : \
  synch_var_test_bit((nr),(addr)))
 
+#define gnttab_cmpxchg_flags synch_cmpxchg
+
 #endif /* __XEN_SYNCH_BITOPS_H__ */
diff -r 6f3d44537b76 include/asm-ia64/synch_bitops.h
--- a/include/asm-ia64/synch_bitops.h   Fri Jun 16 16:07:38 2006 -0500
+++ b/include/asm-ia64/synch_bitops.h   Fri Jun 23 16:14:27 2006 -0500
@@ -58,4 +58,6 @@ static __inline__ int synch_var_test_bit
  synch_const_test_bit((nr),(addr)) : \
  synch_var_test_bit((nr),(addr)))
 
+#define gnttab_cmpxchg_flags synch_cmpxchg
+
 #endif /* __XEN_SYNCH_BITOPS_H__ */

For reference, the Linux PPC hack:

diff -r 6f3d44537b76 include/asm-powerpc/xen/asm/synch_bitops.h
--- a/include/asm-powerpc/xen/asm/synch_bitops.h        Fri Jun 16 16:07:38 
2006 -0500
+++ b/include/asm-powerpc/xen/asm/synch_bitops.h        Fri Jun 23 16:14:27 
2006 -0500
@@ -21,4 +21,28 @@
 #error "this only works for CONFIG_SMP"
 #endif
 
+/* HACK: grant_entry.flags is two bytes, but our atomic instructions
+ * only store in 4/8 byte quantities. However, because it's part of the guest
+ * ABI, we can't change its size without breaking backwards compatibility. In
+ * this particular case, struct grant_entry is big enough that we can safely
+ * store 4 bytes into it. However, some munging is needed...
+ */
+static inline __u16 gnttab_cmpxchg_flags(__u16 *ptr, __u16 o, __u16 n)
+{
+       volatile __u32 *laddr;
+       unsigned long shift = (sizeof(*laddr) - sizeof(*ptr)) * 8;
+       __u32 orig;
+       __u32 old;
+       __u32 new;
+
+       BUG_ON((long)ptr % sizeof(*laddr));
+
+       laddr = (volatile __u32 *)ptr;
+       orig = *laddr;
+       old = ((unsigned long)o << shift) | (orig & ((1UL<<shift)-1));
+       new = ((unsigned long)n << shift) | (orig & ((1UL<<shift)-1));
+
+       return synch_cmpxchg(laddr, old, new);
+}
+
 #endif /* __SYNCH_BITOPS_H__ */


-- 
Hollis Blanchard
IBM Linux Technology Center


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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.