diff options
Diffstat (limited to 'kernel/arch/metag/include/asm/processor.h')
-rw-r--r-- | kernel/arch/metag/include/asm/processor.h | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/kernel/arch/metag/include/asm/processor.h b/kernel/arch/metag/include/asm/processor.h new file mode 100644 index 000000000..0838ca699 --- /dev/null +++ b/kernel/arch/metag/include/asm/processor.h @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2005,2006,2007,2008 Imagination Technologies + */ + +#ifndef __ASM_METAG_PROCESSOR_H +#define __ASM_METAG_PROCESSOR_H + +#include <linux/atomic.h> + +#include <asm/page.h> +#include <asm/ptrace.h> +#include <asm/metag_regs.h> + +/* + * Default implementation of macro that returns current + * instruction pointer ("program counter"). + */ +#define current_text_addr() ({ __label__ _l; _l: &&_l; }) + +/* The task stops where the kernel starts */ +#define TASK_SIZE PAGE_OFFSET +/* Add an extra page of padding at the top of the stack for the guard page. */ +#define STACK_TOP (TASK_SIZE - PAGE_SIZE) +#define STACK_TOP_MAX STACK_TOP +/* Maximum virtual space for stack */ +#define STACK_SIZE_MAX (CONFIG_MAX_STACK_SIZE_MB*1024*1024) + +/* This decides where the kernel will search for a free chunk of vm + * space during mmap's. + */ +#define TASK_UNMAPPED_BASE META_MEMORY_BASE + +typedef struct { + unsigned long seg; +} mm_segment_t; + +#ifdef CONFIG_METAG_FPU +struct meta_fpu_context { + TBICTXEXTFPU fpstate; + union { + struct { + TBICTXEXTBB4 fx8_15; + TBICTXEXTFPACC fpacc; + } fx8_15; + struct { + TBICTXEXTFPACC fpacc; + TBICTXEXTBB4 unused; + } nofx8_15; + } extfpstate; + bool needs_restore; +}; +#else +struct meta_fpu_context {}; +#endif + +#ifdef CONFIG_METAG_DSP +struct meta_ext_context { + struct { + TBIEXTCTX ctx; + TBICTXEXTBB8 bb8; + TBIDUAL ax[TBICTXEXTAXX_BYTES / sizeof(TBIDUAL)]; + TBICTXEXTHL2 hl2; + TBICTXEXTTDPR ext; + TBICTXEXTRP6 rp; + } regs; + + /* DSPRAM A and B save areas. */ + void *ram[2]; + + /* ECH encoded size of DSPRAM save areas. */ + unsigned int ram_sz[2]; +}; +#else +struct meta_ext_context {}; +#endif + +struct thread_struct { + PTBICTX kernel_context; + /* A copy of the user process Sig.SaveMask. */ + unsigned int user_flags; + struct meta_fpu_context *fpu_context; + void __user *tls_ptr; + unsigned short int_depth; + unsigned short txdefr_failure; + struct meta_ext_context *dsp_context; +}; + +#define INIT_THREAD { \ + NULL, /* kernel_context */ \ + 0, /* user_flags */ \ + NULL, /* fpu_context */ \ + NULL, /* tls_ptr */ \ + 1, /* int_depth - we start in kernel */ \ + 0, /* txdefr_failure */ \ + NULL, /* dsp_context */ \ +} + +/* Needed to make #define as we are referencing 'current', that is not visible + * yet. + * + * Stack layout is as below. + + argc argument counter (integer) + argv[0] program name (pointer) + argv[1...N] program args (pointers) + argv[argc-1] end of args (integer) + NULL + env[0...N] environment variables (pointers) + NULL + + */ +#define start_thread(regs, pc, usp) do { \ + unsigned int *argc = (unsigned int *) bprm->exec; \ + current->thread.int_depth = 1; \ + /* Force this process down to user land */ \ + regs->ctx.SaveMask = TBICTX_PRIV_BIT; \ + regs->ctx.CurrPC = pc; \ + regs->ctx.AX[0].U0 = usp; \ + regs->ctx.DX[3].U1 = *((int *)argc); /* argc */ \ + regs->ctx.DX[3].U0 = (int)((int *)argc + 1); /* argv */ \ + regs->ctx.DX[2].U1 = (int)((int *)argc + \ + regs->ctx.DX[3].U1 + 2); /* envp */ \ + regs->ctx.DX[2].U0 = 0; /* rtld_fini */ \ +} while (0) + +/* Forward declaration, a strange C thing */ +struct task_struct; + +/* Free all resources held by a thread. */ +static inline void release_thread(struct task_struct *dead_task) +{ +} + +#define copy_segments(tsk, mm) do { } while (0) +#define release_segments(mm) do { } while (0) + +extern void exit_thread(void); + +/* + * Return saved PC of a blocked thread. + */ +#define thread_saved_pc(tsk) \ + ((unsigned long)(tsk)->thread.kernel_context->CurrPC) +#define thread_saved_sp(tsk) \ + ((unsigned long)(tsk)->thread.kernel_context->AX[0].U0) +#define thread_saved_fp(tsk) \ + ((unsigned long)(tsk)->thread.kernel_context->AX[1].U0) + +unsigned long get_wchan(struct task_struct *p); + +#define KSTK_EIP(tsk) (task_pt_regs(tsk)->ctx.CurrPC) +#define KSTK_ESP(tsk) (task_pt_regs(tsk)->ctx.AX[0].U0) + +#define user_stack_pointer(regs) ((regs)->ctx.AX[0].U0) + +#define cpu_relax() barrier() +#define cpu_relax_lowlatency() cpu_relax() + +extern void setup_priv(void); + +static inline unsigned int hard_processor_id(void) +{ + unsigned int id; + + asm volatile ("MOV %0, TXENABLE\n" + "AND %0, %0, %1\n" + "LSR %0, %0, %2\n" + : "=&d" (id) + : "I" (TXENABLE_THREAD_BITS), + "K" (TXENABLE_THREAD_S) + ); + + return id; +} + +#define OP3_EXIT 0 + +#define HALT_OK 0 +#define HALT_PANIC -1 + +/* + * Halt (stop) the hardware thread. This instruction sequence is the + * standard way to cause a Meta hardware thread to exit. The exit code + * is pushed onto the stack which is interpreted by the debug adapter. + */ +static inline void hard_processor_halt(int exit_code) +{ + asm volatile ("MOV D1Ar1, %0\n" + "MOV D0Ar6, %1\n" + "MSETL [A0StP],D0Ar6,D0Ar4,D0Ar2\n" + "1:\n" + "SWITCH #0xC30006\n" + "B 1b\n" + : : "r" (exit_code), "K" (OP3_EXIT)); +} + +/* Set these hooks to call SoC specific code to restart/halt/power off. */ +extern void (*soc_restart)(char *cmd); +extern void (*soc_halt)(void); + +extern void show_trace(struct task_struct *tsk, unsigned long *sp, + struct pt_regs *regs); + +extern const struct seq_operations cpuinfo_op; + +#endif |