aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/xtensa/kernel/process.c63
-rw-r--r--arch/xtensa/kernel/traps.c4
-rw-r--r--include/asm-xtensa/elf.h92
3 files changed, 11 insertions, 148 deletions
diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c
index f53d7bd9dfb2..026138d641a4 100644
--- a/arch/xtensa/kernel/process.c
+++ b/arch/xtensa/kernel/process.c
@@ -194,51 +194,18 @@ unsigned long get_wchan(struct task_struct *p)
194void do_copy_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs, 194void do_copy_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs,
195 struct task_struct *tsk) 195 struct task_struct *tsk)
196{ 196{
197 int i, n, wb_offset;
198
199 elfregs->xchal_config_id0 = XCHAL_HW_CONFIGID0;
200 elfregs->xchal_config_id1 = XCHAL_HW_CONFIGID1;
201
202 __asm__ __volatile__ ("rsr %0, 176\n" : "=a" (i));
203 elfregs->cpux = i;
204 __asm__ __volatile__ ("rsr %0, 208\n" : "=a" (i));
205 elfregs->cpuy = i;
206
207 /* Note: PS.EXCM is not set while user task is running; its 197 /* Note: PS.EXCM is not set while user task is running; its
208 * being set in regs->ps is for exception handling convenience. 198 * being set in regs->ps is for exception handling convenience.
209 */ 199 */
210 200
211 elfregs->pc = regs->pc; 201 elfregs->pc = regs->pc;
212 elfregs->ps = (regs->ps & ~(1 << PS_EXCM_BIT)); 202 elfregs->ps = (regs->ps & ~(1 << PS_EXCM_BIT));
213 elfregs->exccause = regs->exccause;
214 elfregs->excvaddr = regs->excvaddr;
215 elfregs->windowbase = regs->windowbase;
216 elfregs->windowstart = regs->windowstart;
217 elfregs->lbeg = regs->lbeg; 203 elfregs->lbeg = regs->lbeg;
218 elfregs->lend = regs->lend; 204 elfregs->lend = regs->lend;
219 elfregs->lcount = regs->lcount; 205 elfregs->lcount = regs->lcount;
220 elfregs->sar = regs->sar; 206 elfregs->sar = regs->sar;
221 elfregs->syscall = regs->syscall;
222
223 /* Copy register file.
224 * The layout looks like this:
225 *
226 * | a0 ... a15 | Z ... Z | arX ... arY |
227 * current window unused saved frames
228 */
229
230 memset (elfregs->ar, 0, sizeof(elfregs->ar));
231
232 wb_offset = regs->windowbase * 4;
233 n = (regs->wmask&1)? 4 : (regs->wmask&2)? 8 : (regs->wmask&4)? 12 : 16;
234
235 for (i = 0; i < n; i++)
236 elfregs->ar[(wb_offset + i) % XCHAL_NUM_AREGS] = regs->areg[i];
237 207
238 n = (regs->wmask >> 4) * 4; 208 memcpy (elfregs->a, regs->areg, sizeof(elfregs->a));
239
240 for (i = XCHAL_NUM_AREGS - n; n > 0; i++, n--)
241 elfregs->ar[(wb_offset + i) % XCHAL_NUM_AREGS] = regs->areg[i];
242} 209}
243 210
244void xtensa_elf_core_copy_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs) 211void xtensa_elf_core_copy_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs)
@@ -252,40 +219,22 @@ void xtensa_elf_core_copy_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs)
252void do_restore_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs, 219void do_restore_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs,
253 struct task_struct *tsk) 220 struct task_struct *tsk)
254{ 221{
255 int i, n, wb_offset; 222 const unsigned long ps_mask = PS_CALLINC_MASK | PS_OWB_MASK;
223 unsigned long ps;
256 224
257 /* Note: PS.EXCM is not set while user task is running; it 225 /* Note: PS.EXCM is not set while user task is running; it
258 * needs to be set in regs->ps is for exception handling convenience. 226 * needs to be set in regs->ps is for exception handling convenience.
259 */ 227 */
260 228
229 ps = (regs->ps & ~ps_mask) | (elfregs->ps & ps_mask) | (1<<PS_EXCM_BIT);
230 regs->ps = ps;
261 regs->pc = elfregs->pc; 231 regs->pc = elfregs->pc;
262 regs->ps = (elfregs->ps | (1 << PS_EXCM_BIT));
263 regs->exccause = elfregs->exccause;
264 regs->excvaddr = elfregs->excvaddr;
265 regs->windowbase = elfregs->windowbase;
266 regs->windowstart = elfregs->windowstart;
267 regs->lbeg = elfregs->lbeg; 232 regs->lbeg = elfregs->lbeg;
268 regs->lend = elfregs->lend; 233 regs->lend = elfregs->lend;
269 regs->lcount = elfregs->lcount; 234 regs->lcount = elfregs->lcount;
270 regs->sar = elfregs->sar; 235 regs->sar = elfregs->sar;
271 regs->syscall = elfregs->syscall;
272
273 /* Clear everything. */
274
275 memset (regs->areg, 0, sizeof(regs->areg));
276
277 /* Copy regs from live window frame. */
278
279 wb_offset = regs->windowbase * 4;
280 n = (regs->wmask&1)? 4 : (regs->wmask&2)? 8 : (regs->wmask&4)? 12 : 16;
281
282 for (i = 0; i < n; i++)
283 regs->areg[(wb_offset+i) % XCHAL_NUM_AREGS] = elfregs->ar[i];
284
285 n = (regs->wmask >> 4) * 4;
286 236
287 for (i = XCHAL_NUM_AREGS - n; n > 0; i++, n--) 237 memcpy (regs->areg, elfregs->a, sizeof(regs->areg));
288 regs->areg[(wb_offset+i) % XCHAL_NUM_AREGS] = elfregs->ar[i];
289} 238}
290 239
291/* 240/*
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c
index 397bcd6ad08d..6f722f91ba92 100644
--- a/arch/xtensa/kernel/traps.c
+++ b/arch/xtensa/kernel/traps.c
@@ -349,9 +349,7 @@ void show_regs(struct pt_regs * regs)
349 349
350 wmask = regs->wmask & ~1; 350 wmask = regs->wmask & ~1;
351 351
352 for (i = 0; i < 32; i++) { 352 for (i = 0; i < 16; i++) {
353 if (wmask & (1 << (i / 4)))
354 break;
355 if ((i % 8) == 0) 353 if ((i % 8) == 0)
356 printk ("\n" KERN_INFO "a%02d: ", i); 354 printk ("\n" KERN_INFO "a%02d: ", i);
357 printk("%08lx ", regs->areg[i]); 355 printk("%08lx ", regs->areg[i]);
diff --git a/include/asm-xtensa/elf.h b/include/asm-xtensa/elf.h
index 467384542502..0444507b438d 100644
--- a/include/asm-xtensa/elf.h
+++ b/include/asm-xtensa/elf.h
@@ -72,109 +72,25 @@
72 72
73/* ELF register definitions. This is needed for core dump support. */ 73/* ELF register definitions. This is needed for core dump support. */
74 74
75/*
76 * elf_gregset_t contains the application-level state in the following order:
77 * Processor info: config_version, cpuxy
78 * Processor state: pc, ps, exccause, excvaddr, wb, ws,
79 * lbeg, lend, lcount, sar
80 * GP regs: ar0 - arXX
81 */
82
83typedef unsigned long elf_greg_t; 75typedef unsigned long elf_greg_t;
84 76
85typedef struct { 77typedef struct {
86 elf_greg_t xchal_config_id0;
87 elf_greg_t xchal_config_id1;
88 elf_greg_t cpux;
89 elf_greg_t cpuy;
90 elf_greg_t pc; 78 elf_greg_t pc;
91 elf_greg_t ps; 79 elf_greg_t ps;
92 elf_greg_t exccause;
93 elf_greg_t excvaddr;
94 elf_greg_t windowbase;
95 elf_greg_t windowstart;
96 elf_greg_t lbeg; 80 elf_greg_t lbeg;
97 elf_greg_t lend; 81 elf_greg_t lend;
98 elf_greg_t lcount; 82 elf_greg_t lcount;
99 elf_greg_t sar; 83 elf_greg_t sar;
100 elf_greg_t syscall; 84 elf_greg_t windowstart;
101 elf_greg_t ar[64]; 85 elf_greg_t reserved[9+48];
86 elf_greg_t a[64];
102} xtensa_gregset_t; 87} xtensa_gregset_t;
103 88
104#define ELF_NGREG (sizeof(xtensa_gregset_t) / sizeof(elf_greg_t)) 89#define ELF_NGREG (sizeof(xtensa_gregset_t) / sizeof(elf_greg_t))
105 90
106typedef elf_greg_t elf_gregset_t[ELF_NGREG]; 91typedef elf_greg_t elf_gregset_t[ELF_NGREG];
107 92
108/* 93#define ELF_NFPREG 18
109 * Compute the size of the coprocessor and extra state layout (register info)
110 * table (in bytes).
111 * This is actually the maximum size of the table, as opposed to the size,
112 * which is available from the _xtensa_reginfo_table_size global variable.
113 *
114 * (See also arch/xtensa/kernel/coprocessor.S)
115 *
116 */
117
118#ifndef XCHAL_EXTRA_SA_CONTENTS_LIBDB_NUM
119# define XTENSA_CPE_LTABLE_SIZE 0
120#else
121# define XTENSA_CPE_SEGMENT(num) (num ? (1+num) : 0)
122# define XTENSA_CPE_LTABLE_ENTRIES \
123 ( XTENSA_CPE_SEGMENT(XCHAL_EXTRA_SA_CONTENTS_LIBDB_NUM) \
124 + XTENSA_CPE_SEGMENT(XCHAL_CP0_SA_CONTENTS_LIBDB_NUM) \
125 + XTENSA_CPE_SEGMENT(XCHAL_CP1_SA_CONTENTS_LIBDB_NUM) \
126 + XTENSA_CPE_SEGMENT(XCHAL_CP2_SA_CONTENTS_LIBDB_NUM) \
127 + XTENSA_CPE_SEGMENT(XCHAL_CP3_SA_CONTENTS_LIBDB_NUM) \
128 + XTENSA_CPE_SEGMENT(XCHAL_CP4_SA_CONTENTS_LIBDB_NUM) \
129 + XTENSA_CPE_SEGMENT(XCHAL_CP5_SA_CONTENTS_LIBDB_NUM) \
130 + XTENSA_CPE_SEGMENT(XCHAL_CP6_SA_CONTENTS_LIBDB_NUM) \
131 + XTENSA_CPE_SEGMENT(XCHAL_CP7_SA_CONTENTS_LIBDB_NUM) \
132 + 1 /* final entry */ \
133 )
134# define XTENSA_CPE_LTABLE_SIZE (XTENSA_CPE_LTABLE_ENTRIES * 8)
135#endif
136
137
138/*
139 * Instantiations of the elf_fpregset_t type contain, in most
140 * architectures, the floating point (FPU) register set.
141 * For Xtensa, this type is extended to contain all custom state,
142 * ie. coprocessor and "extra" (non-coprocessor) state (including,
143 * for example, TIE-defined states and register files; as well
144 * as other optional processor state).
145 * This includes FPU state if a floating-point coprocessor happens
146 * to have been configured within the Xtensa processor.
147 *
148 * TOTAL_FPREGS_SIZE is the required size (without rounding)
149 * of elf_fpregset_t. It provides space for the following:
150 *
151 * a) 32-bit mask of active coprocessors for this task (similar
152 * to CPENABLE in single-threaded Xtensa processor systems)
153 *
154 * b) table describing the layout of custom states (ie. of
155 * individual registers, etc) within the save areas
156 *
157 * c) save areas for each coprocessor and for non-coprocessor
158 * ("extra") state
159 *
160 * Note that save areas may require up to 16-byte alignment when
161 * accessed by save/restore sequences. We do not need to ensure
162 * such alignment in an elf_fpregset_t structure because custom
163 * state is not directly loaded/stored into it; rather, save area
164 * contents are copied to elf_fpregset_t from the active save areas
165 * (see 'struct task_struct' definition in processor.h for that)
166 * using memcpy(). But we do allow space for such alignment,
167 * to allow optimizations of layout and copying.
168 */
169#if 0
170#define TOTAL_FPREGS_SIZE \
171 (4 + XTENSA_CPE_LTABLE_SIZE + XTENSA_CP_EXTRA_SIZE)
172#define ELF_NFPREG \
173 ((TOTAL_FPREGS_SIZE + sizeof(elf_fpreg_t) - 1) / sizeof(elf_fpreg_t))
174#else
175#define TOTAL_FPREGS_SIZE 0
176#define ELF_NFPREG 0
177#endif
178 94
179typedef unsigned int elf_fpreg_t; 95typedef unsigned int elf_fpreg_t;
180typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; 96typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];