On 9/22/2013 6:23 PM, Linus Torvalds wrote:
> Alternatively, make %r13 point to the percpu side, but make sure that
> you always use an asm accessor to fetch the value. In particular, I
> think you need to make __my_cpu_offset be an inline asm that fetches
> %r13 into some other register. Otherwise you can never get it right.

We just came up against this on tilegx with a customer bug report in a
PREEMPT environment.  On tile, %tp is a GPR that points to the percpu area.
The following seems to be the right abstraction -- though I'd also argue
that letting barrier() clobber not just memory, but %tp, might be a better
solution, but it's not clear what the best way is to do per-architecture
overrides of per-compiler definitions like barrier().  See also the ARM v7
code, which has to do something similar, though their percpu pointer is
not a GPR, which changes the tradeoffs somewhat.

register unsigned long my_cpu_offset_reg asm("tp");

#ifdef CONFIG_PREEMPT
/*
 * For full preemption, we can't just use the register variable
 * directly, since we need barrier() to hazard against it, causing the
 * compiler to reload anything computed from a previous "tp" value.
 * But we also don't want to use volatile asm, since we'd like the
 * compiler to be able to cache the value across multiple percpu reads.
 * So we use a fake stack read as a hazard against barrier().
 */
static inline unsigned long __my_cpu_offset(void)
{
        unsigned long tp;
        register unsigned long *sp asm("sp");
        asm("move %0, tp" : "=r" (tp) : "m" (*sp));
        return tp;
}
#define __my_cpu_offset __my_cpu_offset()
#else
/*
 * We don't need to hazard against barrier() since "tp" doesn't ever
 * change with PREEMPT_NONE, and with PREEMPT_VOLUNTARY it only
 * changes at function call points, at which we are already re-reading
 * the value of "tp" due to "my_cpu_offset_reg" being a global variable.
 */
#define __my_cpu_offset my_cpu_offset_reg
#endif

#define set_my_cpu_offset(tp) (my_cpu_offset_reg = (tp))

-- 
Chris Metcalf, Tilera Corp.
http://www.tilera.com
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
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