Hi Andre,

On Tue, May 07, 2013 at 09:51:00PM +0100, André Hentschel wrote:
> From: =?UTF-8?q?Andr=C3=A9=20Hentschel?= <[email protected]>

Might just be my mailer, but you should check that your name is intact here
otherwise the git log will be mangled.

> Since commit 6a1c53124aa1 the user writeable TLS register was zeroed to
> prevent it from being used as a covert channel between two tasks.
> 
> There are more and more applications coming to WinRT, Wine could support them,
> but mostly they expect to have the thread environment block (TEB) in TPIDRURW.
> 
> This patch preserves that register per thread instead of clearing it.
> Unlike the TPIDRURO, which is already switched, the TPIDRURW
> can be updated from userspace so needs careful treatment in the case that we
> modify TPIDRURW and call fork(). To avoid this we must always read
> TPIDRURW in copy_thread.
> 
> Signed-off-by: André Hentschel <[email protected]>
> Signed-off-by: Will Deacon <[email protected]>
> Signed-off-by: Jonathan Austin <[email protected]> 

[...]

> diff --git a/arch/arm/include/asm/tls.h b/arch/arm/include/asm/tls.h
> index 73409e6..22756ab 100644
> --- a/arch/arm/include/asm/tls.h
> +++ b/arch/arm/include/asm/tls.h
> @@ -2,27 +2,30 @@
>  #define __ASMARM_TLS_H
>  
>  #ifdef __ASSEMBLY__
> -     .macro set_tls_none, tp, tmp1, tmp2
> +#include <asm/asm-offsets.h>
> +     .macro switch_tls_none, base, tp, tpuser, tmp1, tmp2
>       .endm
>  
> -     .macro set_tls_v6k, tp, tmp1, tmp2
> +     .macro switch_tls_v6k, base, tp, tpuser, tmp1, tmp2
> +     mrc     p15, 0, \tmp2, c13, c0, 2       @ get the user r/w register
>       mcr     p15, 0, \tp, c13, c0, 3         @ set TLS register
> -     mov     \tmp1, #0
> -     mcr     p15, 0, \tmp1, c13, c0, 2       @ clear user r/w TLS register
> +     mcr     p15, 0, \tpuser, c13, c0, 2     @ and the user r/w register
> +     strne   \tmp2, [\base, #TI_TP_VALUE + 4] @ save it

Why is this conditional?

>       .endm
>  
> -     .macro set_tls_v6, tp, tmp1, tmp2
> +     .macro switch_tls_v6, base, tp, tpuser, tmp1, tmp2
>       ldr     \tmp1, =elf_hwcap
>       ldr     \tmp1, [\tmp1, #0]
>       mov     \tmp2, #0xffff0fff
>       tst     \tmp1, #HWCAP_TLS               @ hardware TLS available?
> -     mcrne   p15, 0, \tp, c13, c0, 3         @ yes, set TLS register
> -     movne   \tmp1, #0
> -     mcrne   p15, 0, \tmp1, c13, c0, 2       @ clear user r/w TLS register
>       streq   \tp, [\tmp2, #-15]              @ set TLS value at 0xffff0ff0
> +     mrcne   p15, 0, \tmp2, c13, c0, 2       @ get the user r/w register
> +     mcrne   p15, 0, \tp, c13, c0, 3         @ yes, set TLS register
> +     mcrne   p15, 0, \tpuser, c13, c0, 2     @ set user r/w register
> +     strne   \tmp2, [\base, #TI_TP_VALUE + 4] @ save it
>       .endm
>  
> -     .macro set_tls_software, tp, tmp1, tmp2
> +     .macro switch_tls_software, base, tp, tpuser, tmp1, tmp2
>       mov     \tmp1, #0xffff0fff
>       str     \tp, [\tmp1, #-15]              @ set TLS value at 0xffff0ff0
>       .endm
> @@ -31,19 +34,31 @@
>  #ifdef CONFIG_TLS_REG_EMUL
>  #define tls_emu              1
>  #define has_tls_reg          1
> -#define set_tls              set_tls_none
> +#define switch_tls   switch_tls_none
>  #elif defined(CONFIG_CPU_V6)
>  #define tls_emu              0
>  #define has_tls_reg          (elf_hwcap & HWCAP_TLS)
> -#define set_tls              set_tls_v6
> +#define switch_tls   switch_tls_v6
>  #elif defined(CONFIG_CPU_32v6K)
>  #define tls_emu              0
>  #define has_tls_reg          1
> -#define set_tls              set_tls_v6k
> +#define switch_tls   switch_tls_v6k
>  #else
>  #define tls_emu              0
>  #define has_tls_reg          0
> -#define set_tls              set_tls_software
> +#define switch_tls   switch_tls_software
>  #endif
>  
> +#ifndef __ASSEMBLY__
> +static inline unsigned long get_tlsuser(void)
> +{
> +     if (has_tls_reg && !tls_emu)
> +     {
> +             unsigned long t;
> +             __asm__("mrc p15, 0, %0, c13, c0, 2" : "=r" (t));
> +             return t;
> +     }
> +     return 0;

This isn't standard kernel coding style. Please do something like:

        static inline unsigned long get_tlsuser(void)
        {
                unsigned long reg = 0;

                if (has_tls_reg && !tls_emu)
                        asm("mrc p15, 0, %0, c13, c0, 2" : "=r" (reg));

                return reg;
        }

Will
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to