Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 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 77 78 79 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 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 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 | /*
* 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)
/*
* 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
|