GNU Linux-libre 4.14.290-gnu1
[releases.git] / arch / metag / include / asm / processor.h
1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * Copyright (C) 2005,2006,2007,2008 Imagination Technologies
4  */
5
6 #ifndef __ASM_METAG_PROCESSOR_H
7 #define __ASM_METAG_PROCESSOR_H
8
9 #include <linux/atomic.h>
10
11 #include <asm/page.h>
12 #include <asm/ptrace.h>
13 #include <asm/metag_regs.h>
14
15 /*
16  * Default implementation of macro that returns current
17  * instruction pointer ("program counter").
18  */
19 #define current_text_addr() ({ __label__ _l; _l: &&_l; })
20
21 /* The task stops where the kernel starts */
22 #define TASK_SIZE       PAGE_OFFSET
23 /* Add an extra page of padding at the top of the stack for the guard page. */
24 #define STACK_TOP       (TASK_SIZE - PAGE_SIZE)
25 #define STACK_TOP_MAX   STACK_TOP
26 /* Maximum virtual space for stack */
27 #define STACK_SIZE_MAX  (CONFIG_MAX_STACK_SIZE_MB*1024*1024)
28
29 /* This decides where the kernel will search for a free chunk of vm
30  * space during mmap's.
31  */
32 #define TASK_UNMAPPED_BASE      META_MEMORY_BASE
33
34 typedef struct {
35         unsigned long seg;
36 } mm_segment_t;
37
38 #ifdef CONFIG_METAG_FPU
39 struct meta_fpu_context {
40         TBICTXEXTFPU fpstate;
41         union {
42                 struct {
43                         TBICTXEXTBB4 fx8_15;
44                         TBICTXEXTFPACC fpacc;
45                 } fx8_15;
46                 struct {
47                         TBICTXEXTFPACC fpacc;
48                         TBICTXEXTBB4 unused;
49                 } nofx8_15;
50         } extfpstate;
51         bool needs_restore;
52 };
53 #else
54 struct meta_fpu_context {};
55 #endif
56
57 #ifdef CONFIG_METAG_DSP
58 struct meta_ext_context {
59         struct {
60                 TBIEXTCTX ctx;
61                 TBICTXEXTBB8 bb8;
62                 TBIDUAL ax[TBICTXEXTAXX_BYTES / sizeof(TBIDUAL)];
63                 TBICTXEXTHL2 hl2;
64                 TBICTXEXTTDPR ext;
65                 TBICTXEXTRP6 rp;
66         } regs;
67
68         /* DSPRAM A and B save areas. */
69         void *ram[2];
70
71         /* ECH encoded size of DSPRAM save areas. */
72         unsigned int ram_sz[2];
73 };
74 #else
75 struct meta_ext_context {};
76 #endif
77
78 struct thread_struct {
79         PTBICTX kernel_context;
80         /* A copy of the user process Sig.SaveMask. */
81         unsigned int user_flags;
82         struct meta_fpu_context *fpu_context;
83         void __user *tls_ptr;
84         unsigned short int_depth;
85         unsigned short txdefr_failure;
86         struct meta_ext_context *dsp_context;
87 };
88
89 #define INIT_THREAD  { \
90         NULL,                   /* kernel_context */    \
91         0,                      /* user_flags */        \
92         NULL,                   /* fpu_context */       \
93         NULL,                   /* tls_ptr */           \
94         1,                      /* int_depth - we start in kernel */    \
95         0,                      /* txdefr_failure */    \
96         NULL,                   /* dsp_context */       \
97 }
98
99 /* Needed to make #define as we are referencing 'current', that is not visible
100  * yet.
101  *
102  * Stack layout is as below.
103
104       argc            argument counter (integer)
105       argv[0]         program name (pointer)
106       argv[1...N]     program args (pointers)
107       argv[argc-1]    end of args (integer)
108       NULL
109       env[0...N]      environment variables (pointers)
110       NULL
111
112  */
113 #define start_thread(regs, pc, usp) do {                                   \
114         unsigned int *argc = (unsigned int *) bprm->exec;                  \
115         current->thread.int_depth = 1;                                     \
116         /* Force this process down to user land */                         \
117         regs->ctx.SaveMask = TBICTX_PRIV_BIT;                              \
118         regs->ctx.CurrPC = pc;                                             \
119         regs->ctx.AX[0].U0 = usp;                                          \
120         regs->ctx.DX[3].U1 = *((int *)argc);                    /* argc */ \
121         regs->ctx.DX[3].U0 = (int)((int *)argc + 1);            /* argv */ \
122         regs->ctx.DX[2].U1 = (int)((int *)argc +                           \
123                                    regs->ctx.DX[3].U1 + 2);     /* envp */ \
124         regs->ctx.DX[2].U0 = 0;                            /* rtld_fini */ \
125 } while (0)
126
127 /* Forward declaration, a strange C thing */
128 struct task_struct;
129
130 /* Free all resources held by a thread. */
131 static inline void release_thread(struct task_struct *dead_task)
132 {
133 }
134
135 /*
136  * Return saved PC of a blocked thread.
137  */
138 #define thread_saved_pc(tsk)    \
139         ((unsigned long)(tsk)->thread.kernel_context->CurrPC)
140 #define thread_saved_sp(tsk)    \
141         ((unsigned long)(tsk)->thread.kernel_context->AX[0].U0)
142 #define thread_saved_fp(tsk)    \
143         ((unsigned long)(tsk)->thread.kernel_context->AX[1].U0)
144
145 unsigned long get_wchan(struct task_struct *p);
146
147 #define KSTK_EIP(tsk)   (task_pt_regs(tsk)->ctx.CurrPC)
148 #define KSTK_ESP(tsk)   (task_pt_regs(tsk)->ctx.AX[0].U0)
149
150 #define user_stack_pointer(regs)        ((regs)->ctx.AX[0].U0)
151
152 #define cpu_relax()     barrier()
153
154 extern void setup_priv(void);
155
156 static inline unsigned int hard_processor_id(void)
157 {
158         unsigned int id;
159
160         asm volatile ("MOV      %0, TXENABLE\n"
161                       "AND      %0, %0, %1\n"
162                       "LSR      %0, %0, %2\n"
163                       : "=&d" (id)
164                       : "I" (TXENABLE_THREAD_BITS),
165                         "K" (TXENABLE_THREAD_S)
166                       );
167
168         return id;
169 }
170
171 #define OP3_EXIT        0
172
173 #define HALT_OK         0
174 #define HALT_PANIC      -1
175
176 /*
177  * Halt (stop) the hardware thread. This instruction sequence is the
178  * standard way to cause a Meta hardware thread to exit. The exit code
179  * is pushed onto the stack which is interpreted by the debug adapter.
180  */
181 static inline void hard_processor_halt(int exit_code)
182 {
183         asm volatile ("MOV      D1Ar1, %0\n"
184                       "MOV      D0Ar6, %1\n"
185                       "MSETL    [A0StP],D0Ar6,D0Ar4,D0Ar2\n"
186                       "1:\n"
187                       "SWITCH   #0xC30006\n"
188                       "B                1b\n"
189                       : : "r" (exit_code), "K" (OP3_EXIT));
190 }
191
192 /* Set these hooks to call SoC specific code to restart/halt/power off. */
193 extern void (*soc_restart)(char *cmd);
194 extern void (*soc_halt)(void);
195
196 extern void show_trace(struct task_struct *tsk, unsigned long *sp,
197                        struct pt_regs *regs);
198
199 extern const struct seq_operations cpuinfo_op;
200
201 #endif