aboutsummaryrefslogtreecommitdiffstats
path: root/arch/tile/include/asm/processor.h
diff options
context:
space:
mode:
authorChris Metcalf <cmetcalf@tilera.com>2013-08-10 12:35:02 -0400
committerChris Metcalf <cmetcalf@tilera.com>2013-08-30 11:56:58 -0400
commit35f059761c5ac313d13372fe3cdaa41bce3d0dbf (patch)
tree1a8f7e0eba01afac74c081348530fccd63dc48e4 /arch/tile/include/asm/processor.h
parent4036c7d3542ce82ea343bf95dd05ca46aefba9aa (diff)
tilegx: change how we find the kernel stack
Previously, we used a special-purpose register (SPR_SYSTEM_SAVE_K_0) to hold the CPU number and the top of the current kernel stack by using the low bits to hold the CPU number, and using the high bits to hold the address of the page just above where we'd want the kernel stack to be. That way we could initialize a new SP when first entering the kernel by just masking the SPR value and subtracting a couple of words. However, it's actually more useful to be able to place an arbitrary kernel-top value in the SPR. This allows us to create a new stack context (e.g. for virtualization) with an arbitrary top-of-stack VA. To make this work, we now store the CPU number in the high bits, above the highest legal VA bit (42 bits in the current tilegx microarchitecture). The full 42 bits are thus available to store the top of stack value. Getting the current cpu (a relatively common operation) is still fast; it's now a shift rather than a mask. We make this change only for tilegx, since tilepro has too few SPR bits to do this, and we don't need this support on tilepro anyway. Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
Diffstat (limited to 'arch/tile/include/asm/processor.h')
-rw-r--r--arch/tile/include/asm/processor.h47
1 files changed, 33 insertions, 14 deletions
diff --git a/arch/tile/include/asm/processor.h b/arch/tile/include/asm/processor.h
index 461322b473b5..230b830e94d4 100644
--- a/arch/tile/include/asm/processor.h
+++ b/arch/tile/include/asm/processor.h
@@ -148,9 +148,10 @@ struct thread_struct {
148 148
149/* 149/*
150 * Start with "sp" this many bytes below the top of the kernel stack. 150 * Start with "sp" this many bytes below the top of the kernel stack.
151 * This preserves the invariant that a called function may write to *sp. 151 * This allows us to be cache-aware when handling the initial save
152 * of the pt_regs value to the stack.
152 */ 153 */
153#define STACK_TOP_DELTA 8 154#define STACK_TOP_DELTA 64
154 155
155/* 156/*
156 * When entering the kernel via a fault, start with the top of the 157 * When entering the kernel via a fault, start with the top of the
@@ -234,15 +235,15 @@ extern int do_work_pending(struct pt_regs *regs, u32 flags);
234unsigned long get_wchan(struct task_struct *p); 235unsigned long get_wchan(struct task_struct *p);
235 236
236/* Return initial ksp value for given task. */ 237/* Return initial ksp value for given task. */
237#define task_ksp0(task) ((unsigned long)(task)->stack + THREAD_SIZE) 238#define task_ksp0(task) \
239 ((unsigned long)(task)->stack + THREAD_SIZE - STACK_TOP_DELTA)
238 240
239/* Return some info about the user process TASK. */ 241/* Return some info about the user process TASK. */
240#define KSTK_TOP(task) (task_ksp0(task) - STACK_TOP_DELTA)
241#define task_pt_regs(task) \ 242#define task_pt_regs(task) \
242 ((struct pt_regs *)(task_ksp0(task) - KSTK_PTREGS_GAP) - 1) 243 ((struct pt_regs *)(task_ksp0(task) - KSTK_PTREGS_GAP) - 1)
243#define current_pt_regs() \ 244#define current_pt_regs() \
244 ((struct pt_regs *)((stack_pointer | (THREAD_SIZE - 1)) - \ 245 ((struct pt_regs *)((stack_pointer | (THREAD_SIZE - 1)) - \
245 (KSTK_PTREGS_GAP - 1)) - 1) 246 STACK_TOP_DELTA - (KSTK_PTREGS_GAP - 1)) - 1)
246#define task_sp(task) (task_pt_regs(task)->sp) 247#define task_sp(task) (task_pt_regs(task)->sp)
247#define task_pc(task) (task_pt_regs(task)->pc) 248#define task_pc(task) (task_pt_regs(task)->pc)
248/* Aliases for pc and sp (used in fs/proc/array.c) */ 249/* Aliases for pc and sp (used in fs/proc/array.c) */
@@ -355,20 +356,38 @@ extern int kdata_huge;
355#define KERNEL_PL CONFIG_KERNEL_PL 356#define KERNEL_PL CONFIG_KERNEL_PL
356 357
357/* SYSTEM_SAVE_K_0 holds the current cpu number ORed with ksp0. */ 358/* SYSTEM_SAVE_K_0 holds the current cpu number ORed with ksp0. */
358#define CPU_LOG_MASK_VALUE 12 359#ifdef __tilegx__
359#define CPU_MASK_VALUE ((1 << CPU_LOG_MASK_VALUE) - 1) 360#define CPU_SHIFT 48
360#if CONFIG_NR_CPUS > CPU_MASK_VALUE 361#if CHIP_VA_WIDTH() > CPU_SHIFT
361# error Too many cpus! 362# error Too many VA bits!
362#endif 363#endif
364#define MAX_CPU_ID ((1 << (64 - CPU_SHIFT)) - 1)
363#define raw_smp_processor_id() \ 365#define raw_smp_processor_id() \
364 ((int)__insn_mfspr(SPR_SYSTEM_SAVE_K_0) & CPU_MASK_VALUE) 366 ((int)(__insn_mfspr(SPR_SYSTEM_SAVE_K_0) >> CPU_SHIFT))
365#define get_current_ksp0() \ 367#define get_current_ksp0() \
366 (__insn_mfspr(SPR_SYSTEM_SAVE_K_0) & ~CPU_MASK_VALUE) 368 ((unsigned long)(((long)__insn_mfspr(SPR_SYSTEM_SAVE_K_0) << \
369 (64 - CPU_SHIFT)) >> (64 - CPU_SHIFT)))
370#define next_current_ksp0(task) ({ \
371 unsigned long __ksp0 = task_ksp0(task) & ((1UL << CPU_SHIFT) - 1); \
372 unsigned long __cpu = (long)raw_smp_processor_id() << CPU_SHIFT; \
373 __ksp0 | __cpu; \
374})
375#else
376#define LOG2_NR_CPU_IDS 6
377#define MAX_CPU_ID ((1 << LOG2_NR_CPU_IDS) - 1)
378#define raw_smp_processor_id() \
379 ((int)__insn_mfspr(SPR_SYSTEM_SAVE_K_0) & MAX_CPU_ID)
380#define get_current_ksp0() \
381 (__insn_mfspr(SPR_SYSTEM_SAVE_K_0) & ~MAX_CPU_ID)
367#define next_current_ksp0(task) ({ \ 382#define next_current_ksp0(task) ({ \
368 unsigned long __ksp0 = task_ksp0(task); \ 383 unsigned long __ksp0 = task_ksp0(task); \
369 int __cpu = raw_smp_processor_id(); \ 384 int __cpu = raw_smp_processor_id(); \
370 BUG_ON(__ksp0 & CPU_MASK_VALUE); \ 385 BUG_ON(__ksp0 & MAX_CPU_ID); \
371 __ksp0 | __cpu; \ 386 __ksp0 | __cpu; \
372}) 387})
388#endif
389#if CONFIG_NR_CPUS > (MAX_CPU_ID + 1)
390# error Too many cpus!
391#endif
373 392
374#endif /* _ASM_TILE_PROCESSOR_H */ 393#endif /* _ASM_TILE_PROCESSOR_H */