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

Re: [Xen-devel] [request for review] cmpxchg8b asm stuff



>   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@xxxxxxxxxxxxxxxxxxx
> http://lists.xensource.com/xen-devel
> 


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


 


Rackspace

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