processor.h 9.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
/*
 * Copyright 2010 Tilera Corporation. All Rights Reserved.
 *
 *   This program is free software; you can redistribute it and/or
 *   modify it under the terms of the GNU General Public License
 *   as published by the Free Software Foundation, version 2.
 *
 *   This program is distributed in the hope that it will be useful, but
 *   WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
 *   NON INFRINGEMENT.  See the GNU General Public License for
 *   more details.
 */

#ifndef _ASM_TILE_PROCESSOR_H
#define _ASM_TILE_PROCESSOR_H

#ifndef __ASSEMBLY__

/*
 * NOTE: we don't include <linux/ptrace.h> or <linux/percpu.h> as one
 * normally would, due to #include dependencies.
 */
24
#include <linux/types.h>
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76
#include <asm/ptrace.h>
#include <asm/percpu.h>

#include <arch/chip.h>
#include <arch/spr_def.h>

struct task_struct;
struct thread_struct;

typedef struct {
	unsigned long seg;
} mm_segment_t;

/*
 * Default implementation of macro that returns current
 * instruction pointer ("program counter").
 */
void *current_text_addr(void);

#if CHIP_HAS_TILE_DMA()
/* Capture the state of a suspended DMA. */
struct tile_dma_state {
	int enabled;
	unsigned long src;
	unsigned long dest;
	unsigned long strides;
	unsigned long chunk_size;
	unsigned long src_chunk;
	unsigned long dest_chunk;
	unsigned long byte;
	unsigned long status;
};

/*
 * A mask of the DMA status register for selecting only the 'running'
 * and 'done' bits.
 */
#define DMA_STATUS_MASK \
  (SPR_DMA_STATUS__RUNNING_MASK | SPR_DMA_STATUS__DONE_MASK)
#endif

/*
 * Track asynchronous TLB events (faults and access violations)
 * that occur while we are in kernel mode from DMA or the SN processor.
 */
struct async_tlb {
	short fault_num;         /* original fault number; 0 if none */
	char is_fault;           /* was it a fault (vs an access violation) */
	char is_write;           /* for fault: was it caused by a write? */
	unsigned long address;   /* what address faulted? */
};

77 78 79
#ifdef CONFIG_HARDWALL
struct hardwall_info;
#endif
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105

struct thread_struct {
	/* kernel stack pointer */
	unsigned long  ksp;
	/* kernel PC */
	unsigned long  pc;
	/* starting user stack pointer (for page migration) */
	unsigned long  usp0;
	/* pid of process that created this one */
	pid_t creator_pid;
#if CHIP_HAS_TILE_DMA()
	/* DMA info for suspended threads (byte == 0 means no DMA state) */
	struct tile_dma_state tile_dma_state;
#endif
	/* User EX_CONTEXT registers */
	unsigned long ex_context[2];
	/* User SYSTEM_SAVE registers */
	unsigned long system_save[4];
	/* User interrupt mask */
	unsigned long long interrupt_mask;
	/* User interrupt-control 0 state */
	unsigned long intctrl_0;
#if CHIP_HAS_PROC_STATUS_SPR()
	/* Any other miscellaneous processor state bits */
	unsigned long proc_status;
#endif
106 107 108 109 110 111 112 113 114 115 116 117
#if !CHIP_HAS_FIXED_INTVEC_BASE()
	/* Interrupt base for PL0 interrupts */
	unsigned long interrupt_vector_base;
#endif
#if CHIP_HAS_TILE_RTF_HWM()
	/* Tile cache retry fifo high-water mark */
	unsigned long tile_rtf_hwm;
#endif
#if CHIP_HAS_DSTREAM_PF()
	/* Data stream prefetch control */
	unsigned long dstream_pf;
#endif
118 119 120 121 122 123
#ifdef CONFIG_HARDWALL
	/* Is this task tied to an activated hardwall? */
	struct hardwall_info *hardwall;
	/* Chains this task into the list at hardwall->list. */
	struct list_head hardwall_list;
#endif
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
#if CHIP_HAS_TILE_DMA()
	/* Async DMA TLB fault information */
	struct async_tlb dma_async_tlb;
#endif
#if CHIP_HAS_SN_PROC()
	/* Was static network processor when we were switched out? */
	int sn_proc_running;
	/* Async SNI TLB fault information */
	struct async_tlb sn_async_tlb;
#endif
};

#endif /* !__ASSEMBLY__ */

/*
 * Start with "sp" this many bytes below the top of the kernel stack.
 * This preserves the invariant that a called function may write to *sp.
 */
#define STACK_TOP_DELTA 8

/*
 * When entering the kernel via a fault, start with the top of the
 * pt_regs structure this many bytes below the top of the page.
 * This aligns the pt_regs structure optimally for cache-line access.
 */
#ifdef __tilegx__
#define KSTK_PTREGS_GAP  48
#else
#define KSTK_PTREGS_GAP  56
#endif

#ifndef __ASSEMBLY__

#ifdef __tilegx__
#define TASK_SIZE_MAX		(MEM_LOW_END + 1)
#else
#define TASK_SIZE_MAX		PAGE_OFFSET
#endif

/* TASK_SIZE and related variables are always checked in "current" context. */
#ifdef CONFIG_COMPAT
#define COMPAT_TASK_SIZE	(1UL << 31)
#define TASK_SIZE		((current_thread_info()->status & TS_COMPAT) ?\
				 COMPAT_TASK_SIZE : TASK_SIZE_MAX)
#else
#define TASK_SIZE		TASK_SIZE_MAX
#endif

/* We provide a minimal "vdso" a la x86; just the sigreturn code for now. */
#define VDSO_BASE		(TASK_SIZE - PAGE_SIZE)

#define STACK_TOP		VDSO_BASE

/* STACK_TOP_MAX is used temporarily in execve and should not check COMPAT. */
#define STACK_TOP_MAX		TASK_SIZE_MAX

/*
 * This decides where the kernel will search for a free chunk of vm
 * space during mmap's, if it is using bottom-up mapping.
 */
#define TASK_UNMAPPED_BASE	(PAGE_ALIGN(TASK_SIZE / 3))

#define HAVE_ARCH_PICK_MMAP_LAYOUT

#define INIT_THREAD {                                                   \
	.ksp = (unsigned long)init_stack + THREAD_SIZE - STACK_TOP_DELTA, \
	.interrupt_mask = -1ULL                                         \
}

/* Kernel stack top for the task that first boots on this cpu. */
DECLARE_PER_CPU(unsigned long, boot_sp);

/* PC to boot from on this cpu. */
DECLARE_PER_CPU(unsigned long, boot_pc);

/* Do necessary setup to start up a newly executed thread. */
static inline void start_thread(struct pt_regs *regs,
				unsigned long pc, unsigned long usp)
{
	regs->pc = pc;
	regs->sp = usp;
}

/* Free all resources held by a thread. */
static inline void release_thread(struct task_struct *dead_task)
{
	/* Nothing for now */
}

/* Prepare to copy thread state - unlazy all lazy status. */
#define prepare_to_copy(tsk)	do { } while (0)

extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);


/*
 * Return saved (kernel) PC of a blocked thread.
 * Only used in a printk() in kernel/sched.c, so don't work too hard.
 */
#define thread_saved_pc(t)   ((t)->thread.pc)

unsigned long get_wchan(struct task_struct *p);

/* Return initial ksp value for given task. */
#define task_ksp0(task) ((unsigned long)(task)->stack + THREAD_SIZE)

/* Return some info about the user process TASK. */
#define KSTK_TOP(task)	(task_ksp0(task) - STACK_TOP_DELTA)
#define task_pt_regs(task) \
  ((struct pt_regs *)(task_ksp0(task) - KSTK_PTREGS_GAP) - 1)
#define task_sp(task)	(task_pt_regs(task)->sp)
#define task_pc(task)	(task_pt_regs(task)->pc)
/* Aliases for pc and sp (used in fs/proc/array.c) */
#define KSTK_EIP(task)	task_pc(task)
#define KSTK_ESP(task)	task_sp(task)

/* Standard format for printing registers and other word-size data. */
#ifdef __tilegx__
# define REGFMT "0x%016lx"
#else
# define REGFMT "0x%08lx"
#endif

/*
 * Do some slow action (e.g. read a slow SPR).
 * Note that this must also have compiler-barrier semantics since
 * it may be used in a busy loop reading memory.
 */
static inline void cpu_relax(void)
{
	__insn_mfspr(SPR_PASS);
	barrier();
}

struct siginfo;
extern void arch_coredump_signal(struct siginfo *, struct pt_regs *);
#define arch_coredump_signal arch_coredump_signal

262 263 264 265
/* Info on this processor (see fs/proc/cpuinfo.c) */
struct seq_operations;
extern const struct seq_operations cpuinfo_op;

266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
/* Provide information about the chip model. */
extern char chip_model[64];

/* Data on which physical memory controller corresponds to which NUMA node. */
extern int node_controller[];


/* Do we dump information to the console when a user application crashes? */
extern int show_crashinfo;

#if CHIP_HAS_CBOX_HOME_MAP()
/* Does the heap allocator return hash-for-home pages by default? */
extern int hash_default;

/* Should kernel stack pages be hash-for-home? */
extern int kstack_hash;
282 283 284 285

/* Does MAP_ANONYMOUS return hash-for-home pages by default? */
#define uheap_hash hash_default

286 287 288
#else
#define hash_default 0
#define kstack_hash 0
289
#define uheap_hash 0
290 291 292 293 294
#endif

/* Are we using huge pages in the TLB for kernel data? */
extern int kdata_huge;

295
#define PREFETCH_STRIDE CHIP_L2_LINE_SIZE()
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350

#else /* __ASSEMBLY__ */

/* Do some slow action (e.g. read a slow SPR). */
#define CPU_RELAX       mfspr zero, SPR_PASS

#endif /* !__ASSEMBLY__ */

/* Assembly code assumes that the PL is in the low bits. */
#if SPR_EX_CONTEXT_1_1__PL_SHIFT != 0
# error Fix assembly assumptions about PL
#endif

/* We sometimes use these macros for EX_CONTEXT_0_1 as well. */
#if SPR_EX_CONTEXT_1_1__PL_SHIFT != SPR_EX_CONTEXT_0_1__PL_SHIFT || \
    SPR_EX_CONTEXT_1_1__PL_RMASK != SPR_EX_CONTEXT_0_1__PL_RMASK || \
    SPR_EX_CONTEXT_1_1__ICS_SHIFT != SPR_EX_CONTEXT_0_1__ICS_SHIFT || \
    SPR_EX_CONTEXT_1_1__ICS_RMASK != SPR_EX_CONTEXT_0_1__ICS_RMASK
# error Fix assumptions that EX1 macros work for both PL0 and PL1
#endif

/* Allow pulling apart and recombining the PL and ICS bits in EX_CONTEXT. */
#define EX1_PL(ex1) \
  (((ex1) >> SPR_EX_CONTEXT_1_1__PL_SHIFT) & SPR_EX_CONTEXT_1_1__PL_RMASK)
#define EX1_ICS(ex1) \
  (((ex1) >> SPR_EX_CONTEXT_1_1__ICS_SHIFT) & SPR_EX_CONTEXT_1_1__ICS_RMASK)
#define PL_ICS_EX1(pl, ics) \
  (((pl) << SPR_EX_CONTEXT_1_1__PL_SHIFT) | \
   ((ics) << SPR_EX_CONTEXT_1_1__ICS_SHIFT))

/*
 * Provide symbolic constants for PLs.
 * Note that assembly code assumes that USER_PL is zero.
 */
#define USER_PL 0
#define KERNEL_PL 1

/* SYSTEM_SAVE_1_0 holds the current cpu number ORed with ksp0. */
#define CPU_LOG_MASK_VALUE 12
#define CPU_MASK_VALUE ((1 << CPU_LOG_MASK_VALUE) - 1)
#if CONFIG_NR_CPUS > CPU_MASK_VALUE
# error Too many cpus!
#endif
#define raw_smp_processor_id() \
	((int)__insn_mfspr(SPR_SYSTEM_SAVE_1_0) & CPU_MASK_VALUE)
#define get_current_ksp0() \
	(__insn_mfspr(SPR_SYSTEM_SAVE_1_0) & ~CPU_MASK_VALUE)
#define next_current_ksp0(task) ({ \
	unsigned long __ksp0 = task_ksp0(task); \
	int __cpu = raw_smp_processor_id(); \
	BUG_ON(__ksp0 & CPU_MASK_VALUE); \
	__ksp0 | __cpu; \
})

#endif /* _ASM_TILE_PROCESSOR_H */