All of lore.kernel.org
 help / color / mirror / Atom feed
* [request for review] cmpxchg8b asm stuff
@ 2005-04-19 13:50 Gerd Knorr
  2005-04-19 15:46 ` Hollis Blanchard
  2005-04-21 10:54 ` Keir Fraser
  0 siblings, 2 replies; 4+ messages in thread
From: Gerd Knorr @ 2005-04-19 13:50 UTC (permalink / raw)
  To: xen-devel

  Hi,

Below is my very first attempt to write inline assembler, for atomic
updates of PAE pagetable entries using cmpxchg8b.  It builds, but is
completely untested otherwise as I don't have a PAE-enabled guest kernel
yet ...

Can someone with more experience than me please have a look at it?

Thanks,

  Gerd

--- xen.orig/arch/x86/mm.c	2005-04-19 11:56:20.000000000 +0200
+++ xen/arch/x86/mm.c	2005-04-19 15:29:01.000000000 +0200
@@ -834,12 +846,55 @@ static void free_l4_table(struct pfn_inf
 
 #endif /* __x86_64__ */
 
+static inline int cmpxchg8b_user(u64 *ptr, u64 oval, u64 nval)
+{
+    u32 o_hi = oval >> 32;
+    u32 o_lo = oval & 0xffffffff;
+    u32 n_hi = nval >> 32;
+    u32 n_lo = nval & 0xffffffff;
+    u32 rc = 0;
+
+    __asm__ __volatile__ (
+        "1: " LOCK_PREFIX "cmpxchg8b %[ptr]\n"
+        "2:\n"
+        ".section .fixup,\"ax\"\n"
+        "3:     movl $1, %[rc]\n"
+        "       jmp 2b\n"
+        ".previous\n"
+        ".section __ex_table,\"a\"\n"
+        "       .align 4\n"
+        "       .long 1b,3b\n"
+        ".previous"
+        : "=d" (o_hi), "=a" (o_lo), "=c" (n_hi), "=b" (n_lo),
+          [rc] "=r" (rc), [ptr] "m" (*__xg((volatile void *)ptr))
+        : "0" (o_hi), "1" (o_lo)
+        : "memory");
+    if ((o_hi != (oval >> 32)) ||
+        (o_lo != (oval & 0xffffffff)))
+        rc = 1;
+    return rc;
+}
 
 static inline int update_l1e(l1_pgentry_t *pl1e, 
                              l1_pgentry_t  ol1e, 
                              l1_pgentry_t  nl1e)
 {
-    /* FIXME: breaks with PAE */
+#if defined(__i386__) && defined(CONFIG_X86_PAE)
+
+    int rc;
+
+    rc = cmpxchg8b_user(pl1e, l1e_get_value(ol1e),
+                        l1e_get_value(nl1e));
+    if (unlikely(rc))
+    {
+        MEM_LOG("Failed to update %llx -> %llx [pae]\n",
+                l1e_get_value(ol1e), l1e_get_value(nl1e));
+        return 0;
+    }
+    return 1;
+
+#else
+
     unsigned long o = l1e_get_value(ol1e);
     unsigned long n = l1e_get_value(nl1e);
 
@@ -850,8 +905,9 @@ static inline int update_l1e(l1_pgentry_
                 l1e_get_value(ol1e), l1e_get_value(nl1e), o);
         return 0;
     }
-
     return 1;
+
+#endif
 }

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [request for review] cmpxchg8b asm stuff
  2005-04-19 13:50 [request for review] cmpxchg8b asm stuff Gerd Knorr
@ 2005-04-19 15:46 ` Hollis Blanchard
  2005-04-19 19:39   ` Gerd Knorr
  2005-04-21 10:54 ` Keir Fraser
  1 sibling, 1 reply; 4+ messages in thread
From: Hollis Blanchard @ 2005-04-19 15:46 UTC (permalink / raw)
  To: Gerd Knorr; +Cc: xen-devel

On Tue, 2005-04-19 at 15:50 +0200, Gerd Knorr wrote:

> Below is my very first attempt to write inline assembler, for atomic
> updates of PAE pagetable entries using cmpxchg8b.  It builds, but is
> completely untested otherwise as I don't have a PAE-enabled guest kernel
> yet ...
> 
> Can someone with more experience than me please have a look at it?
> 
> Thanks,
> 
>   Gerd
> 
> --- xen.orig/arch/x86/mm.c	2005-04-19 11:56:20.000000000 +0200
> +++ xen/arch/x86/mm.c	2005-04-19 15:29:01.000000000 +0200
> @@ -834,12 +846,55 @@ static void free_l4_table(struct pfn_inf
>  
>  #endif /* __x86_64__ */
>  
> +static inline int cmpxchg8b_user(u64 *ptr, u64 oval, u64 nval)
> +{
...
> +}

Shouldn't this go into include/asm-x86/system.h? You can add another
case to the __i386__ cmpxchg_user switch.

-- 
Hollis Blanchard
IBM Linux Technology Center

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [request for review] cmpxchg8b asm stuff
  2005-04-19 15:46 ` Hollis Blanchard
@ 2005-04-19 19:39   ` Gerd Knorr
  0 siblings, 0 replies; 4+ messages in thread
From: Gerd Knorr @ 2005-04-19 19:39 UTC (permalink / raw)
  To: Hollis Blanchard; +Cc: xen-devel

> > +++ xen/arch/x86/mm.c	2005-04-19 15:29:01.000000000 +0200
> >  
> > +static inline int cmpxchg8b_user(u64 *ptr, u64 oval, u64 nval)

> Shouldn't this go into include/asm-x86/system.h?

Well, maybe later.  I want to have it working correctly first, then
optimize and then check how to integrate that nicely.

> You can add another case to the __i386__ cmpxchg_user switch.

That would be the most obvious place, yes.  Not fully sure yet that this
is really a good idea though as it is sort-of special case for 64bit
data on a 32bit machine, you have to split the 64bit values into two
32bit regs and so on (unlike the 64bit version on x86_64 which simply
uses the 64bit registers).  Maybe it's better to keep that separate as
it might be easier to optimize it then, not evaluated yet.

  Gerd

-- 
#define printk(args...) fprintf(stderr, ## args)

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [request for review] cmpxchg8b asm stuff
  2005-04-19 13:50 [request for review] cmpxchg8b asm stuff Gerd Knorr
  2005-04-19 15:46 ` Hollis Blanchard
@ 2005-04-21 10:54 ` Keir Fraser
  1 sibling, 0 replies; 4+ messages in thread
From: Keir Fraser @ 2005-04-21 10:54 UTC (permalink / raw)
  To: Gerd Knorr; +Cc: xen-devel

>   Hi,
> 
> Below is my very first attempt to write inline assembler, for atomic
> updates of PAE pagetable entries using cmpxchg8b.  It builds, but is
> completely untested otherwise as I don't have a PAE-enabled guest kernel
> yet ...
> 
> Can someone with more experience than me please have a look at it?

Thanks - I've checked in an 8-byte extension to cmpxchg_user() for
32-bit builds. Differences from yours include:

 1. The "A" register specifier is used to match a 64-bit C variable
    with EDX:EAX. This is neater than manually splitting into "a"
    and "d" constraints, then manually recombining at the end.
    Unfortunately there is no such shortcut for ECX:EBX.

 2. n_hi, n_lo and ptr are not output constraints, so they belong in
    the second constraint list, with no "=" in the specifier string.

 3. I don't like the non-positional argument specifiers (e.g., [rc],
    [ptr]) very much. Maybe worthwhile for longer code fragments but
    for very short ones I'd rather have less clutter in the constraint
    lists. 

 4. No need to return non-zero if the cmpxchg fails. The return code
    indicates only whether the cmpxchg access faulted or not: it is up
    to the caller to compare the value seen with what they expected.
    This gets rid of a few lines in your cmpxchg8b_user.

I think that covers it. :-)

 -- Keir

> 
> Thanks,
> 
>   Gerd
> 
> --- xen.orig/arch/x86/mm.c	2005-04-19 11:56:20.000000000 +0200
> +++ xen/arch/x86/mm.c	2005-04-19 15:29:01.000000000 +0200
> @@ -834,12 +846,55 @@ static void free_l4_table(struct pfn_inf
>  
>  #endif /* __x86_64__ */
>  
> +static inline int cmpxchg8b_user(u64 *ptr, u64 oval, u64 nval)
> +{
> +    u32 o_hi = oval >> 32;
> +    u32 o_lo = oval & 0xffffffff;
> +    u32 n_hi = nval >> 32;
> +    u32 n_lo = nval & 0xffffffff;
> +    u32 rc = 0;
> +
> +    __asm__ __volatile__ (
> +        "1: " LOCK_PREFIX "cmpxchg8b %[ptr]\n"
> +        "2:\n"
> +        ".section .fixup,\"ax\"\n"
> +        "3:     movl $1, %[rc]\n"
> +        "       jmp 2b\n"
> +        ".previous\n"
> +        ".section __ex_table,\"a\"\n"
> +        "       .align 4\n"
> +        "       .long 1b,3b\n"
> +        ".previous"
> +        : "=d" (o_hi), "=a" (o_lo), "=c" (n_hi), "=b" (n_lo),
> +          [rc] "=r" (rc), [ptr] "m" (*__xg((volatile void *)ptr))
> +        : "0" (o_hi), "1" (o_lo)
> +        : "memory");
> +    if ((o_hi != (oval >> 32)) ||
> +        (o_lo != (oval & 0xffffffff)))
> +        rc = 1;
> +    return rc;
> +}
>  
>  static inline int update_l1e(l1_pgentry_t *pl1e, 
>                               l1_pgentry_t  ol1e, 
>                               l1_pgentry_t  nl1e)
>  {
> -    /* FIXME: breaks with PAE */
> +#if defined(__i386__) && defined(CONFIG_X86_PAE)
> +
> +    int rc;
> +
> +    rc = cmpxchg8b_user(pl1e, l1e_get_value(ol1e),
> +                        l1e_get_value(nl1e));
> +    if (unlikely(rc))
> +    {
> +        MEM_LOG("Failed to update %llx -> %llx [pae]\n",
> +                l1e_get_value(ol1e), l1e_get_value(nl1e));
> +        return 0;
> +    }
> +    return 1;
> +
> +#else
> +
>      unsigned long o = l1e_get_value(ol1e);
>      unsigned long n = l1e_get_value(nl1e);
>  
> @@ -850,8 +905,9 @@ static inline int update_l1e(l1_pgentry_
>                  l1e_get_value(ol1e), l1e_get_value(nl1e), o);
>          return 0;
>      }
> -
>      return 1;
> +
> +#endif
>  }
>  
>  
> 
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xensource.com
> http://lists.xensource.com/xen-devel
> 

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2005-04-21 10:54 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-04-19 13:50 [request for review] cmpxchg8b asm stuff Gerd Knorr
2005-04-19 15:46 ` Hollis Blanchard
2005-04-19 19:39   ` Gerd Knorr
2005-04-21 10:54 ` Keir Fraser

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.