[XTENSA] Clean up elf-gregset.
Remove additional registers from the ELF gregset structure that are only used by the kernel or are not required or invalid in user-space. The ar registers are always aligned to a windowbase value of 0, and the WB register is always assumed to be 0. Increase the size of the structure to 128 entries. This will provide enough space in future. Signed-off-by: Chris Zankel <chris@zankel.net>
This commit is contained in:
parent
0b2c3afdaa
commit
8d7e8240e6
|
@ -194,51 +194,18 @@ unsigned long get_wchan(struct task_struct *p)
|
||||||
void do_copy_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs,
|
void do_copy_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs,
|
||||||
struct task_struct *tsk)
|
struct task_struct *tsk)
|
||||||
{
|
{
|
||||||
int i, n, wb_offset;
|
|
||||||
|
|
||||||
elfregs->xchal_config_id0 = XCHAL_HW_CONFIGID0;
|
|
||||||
elfregs->xchal_config_id1 = XCHAL_HW_CONFIGID1;
|
|
||||||
|
|
||||||
__asm__ __volatile__ ("rsr %0, 176\n" : "=a" (i));
|
|
||||||
elfregs->cpux = i;
|
|
||||||
__asm__ __volatile__ ("rsr %0, 208\n" : "=a" (i));
|
|
||||||
elfregs->cpuy = i;
|
|
||||||
|
|
||||||
/* Note: PS.EXCM is not set while user task is running; its
|
/* Note: PS.EXCM is not set while user task is running; its
|
||||||
* being set in regs->ps is for exception handling convenience.
|
* being set in regs->ps is for exception handling convenience.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
elfregs->pc = regs->pc;
|
elfregs->pc = regs->pc;
|
||||||
elfregs->ps = (regs->ps & ~(1 << PS_EXCM_BIT));
|
elfregs->ps = (regs->ps & ~(1 << PS_EXCM_BIT));
|
||||||
elfregs->exccause = regs->exccause;
|
|
||||||
elfregs->excvaddr = regs->excvaddr;
|
|
||||||
elfregs->windowbase = regs->windowbase;
|
|
||||||
elfregs->windowstart = regs->windowstart;
|
|
||||||
elfregs->lbeg = regs->lbeg;
|
elfregs->lbeg = regs->lbeg;
|
||||||
elfregs->lend = regs->lend;
|
elfregs->lend = regs->lend;
|
||||||
elfregs->lcount = regs->lcount;
|
elfregs->lcount = regs->lcount;
|
||||||
elfregs->sar = regs->sar;
|
elfregs->sar = regs->sar;
|
||||||
elfregs->syscall = regs->syscall;
|
|
||||||
|
|
||||||
/* Copy register file.
|
memcpy (elfregs->a, regs->areg, sizeof(elfregs->a));
|
||||||
* The layout looks like this:
|
|
||||||
*
|
|
||||||
* | a0 ... a15 | Z ... Z | arX ... arY |
|
|
||||||
* current window unused saved frames
|
|
||||||
*/
|
|
||||||
|
|
||||||
memset (elfregs->ar, 0, sizeof(elfregs->ar));
|
|
||||||
|
|
||||||
wb_offset = regs->windowbase * 4;
|
|
||||||
n = (regs->wmask&1)? 4 : (regs->wmask&2)? 8 : (regs->wmask&4)? 12 : 16;
|
|
||||||
|
|
||||||
for (i = 0; i < n; i++)
|
|
||||||
elfregs->ar[(wb_offset + i) % XCHAL_NUM_AREGS] = regs->areg[i];
|
|
||||||
|
|
||||||
n = (regs->wmask >> 4) * 4;
|
|
||||||
|
|
||||||
for (i = XCHAL_NUM_AREGS - n; n > 0; i++, n--)
|
|
||||||
elfregs->ar[(wb_offset + i) % XCHAL_NUM_AREGS] = regs->areg[i];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void xtensa_elf_core_copy_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs)
|
void 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)
|
||||||
void do_restore_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs,
|
void do_restore_regs (xtensa_gregset_t *elfregs, struct pt_regs *regs,
|
||||||
struct task_struct *tsk)
|
struct task_struct *tsk)
|
||||||
{
|
{
|
||||||
int i, n, wb_offset;
|
const unsigned long ps_mask = PS_CALLINC_MASK | PS_OWB_MASK;
|
||||||
|
unsigned long ps;
|
||||||
|
|
||||||
/* Note: PS.EXCM is not set while user task is running; it
|
/* Note: PS.EXCM is not set while user task is running; it
|
||||||
* needs to be set in regs->ps is for exception handling convenience.
|
* needs to be set in regs->ps is for exception handling convenience.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
ps = (regs->ps & ~ps_mask) | (elfregs->ps & ps_mask) | (1<<PS_EXCM_BIT);
|
||||||
|
regs->ps = ps;
|
||||||
regs->pc = elfregs->pc;
|
regs->pc = elfregs->pc;
|
||||||
regs->ps = (elfregs->ps | (1 << PS_EXCM_BIT));
|
|
||||||
regs->exccause = elfregs->exccause;
|
|
||||||
regs->excvaddr = elfregs->excvaddr;
|
|
||||||
regs->windowbase = elfregs->windowbase;
|
|
||||||
regs->windowstart = elfregs->windowstart;
|
|
||||||
regs->lbeg = elfregs->lbeg;
|
regs->lbeg = elfregs->lbeg;
|
||||||
regs->lend = elfregs->lend;
|
regs->lend = elfregs->lend;
|
||||||
regs->lcount = elfregs->lcount;
|
regs->lcount = elfregs->lcount;
|
||||||
regs->sar = elfregs->sar;
|
regs->sar = elfregs->sar;
|
||||||
regs->syscall = elfregs->syscall;
|
|
||||||
|
|
||||||
/* Clear everything. */
|
memcpy (regs->areg, elfregs->a, sizeof(regs->areg));
|
||||||
|
|
||||||
memset (regs->areg, 0, sizeof(regs->areg));
|
|
||||||
|
|
||||||
/* Copy regs from live window frame. */
|
|
||||||
|
|
||||||
wb_offset = regs->windowbase * 4;
|
|
||||||
n = (regs->wmask&1)? 4 : (regs->wmask&2)? 8 : (regs->wmask&4)? 12 : 16;
|
|
||||||
|
|
||||||
for (i = 0; i < n; i++)
|
|
||||||
regs->areg[(wb_offset+i) % XCHAL_NUM_AREGS] = elfregs->ar[i];
|
|
||||||
|
|
||||||
n = (regs->wmask >> 4) * 4;
|
|
||||||
|
|
||||||
for (i = XCHAL_NUM_AREGS - n; n > 0; i++, n--)
|
|
||||||
regs->areg[(wb_offset+i) % XCHAL_NUM_AREGS] = elfregs->ar[i];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -349,9 +349,7 @@ void show_regs(struct pt_regs * regs)
|
||||||
|
|
||||||
wmask = regs->wmask & ~1;
|
wmask = regs->wmask & ~1;
|
||||||
|
|
||||||
for (i = 0; i < 32; i++) {
|
for (i = 0; i < 16; i++) {
|
||||||
if (wmask & (1 << (i / 4)))
|
|
||||||
break;
|
|
||||||
if ((i % 8) == 0)
|
if ((i % 8) == 0)
|
||||||
printk ("\n" KERN_INFO "a%02d: ", i);
|
printk ("\n" KERN_INFO "a%02d: ", i);
|
||||||
printk("%08lx ", regs->areg[i]);
|
printk("%08lx ", regs->areg[i]);
|
||||||
|
|
|
@ -72,109 +72,25 @@
|
||||||
|
|
||||||
/* ELF register definitions. This is needed for core dump support. */
|
/* ELF register definitions. This is needed for core dump support. */
|
||||||
|
|
||||||
/*
|
|
||||||
* elf_gregset_t contains the application-level state in the following order:
|
|
||||||
* Processor info: config_version, cpuxy
|
|
||||||
* Processor state: pc, ps, exccause, excvaddr, wb, ws,
|
|
||||||
* lbeg, lend, lcount, sar
|
|
||||||
* GP regs: ar0 - arXX
|
|
||||||
*/
|
|
||||||
|
|
||||||
typedef unsigned long elf_greg_t;
|
typedef unsigned long elf_greg_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
elf_greg_t xchal_config_id0;
|
|
||||||
elf_greg_t xchal_config_id1;
|
|
||||||
elf_greg_t cpux;
|
|
||||||
elf_greg_t cpuy;
|
|
||||||
elf_greg_t pc;
|
elf_greg_t pc;
|
||||||
elf_greg_t ps;
|
elf_greg_t ps;
|
||||||
elf_greg_t exccause;
|
|
||||||
elf_greg_t excvaddr;
|
|
||||||
elf_greg_t windowbase;
|
|
||||||
elf_greg_t windowstart;
|
|
||||||
elf_greg_t lbeg;
|
elf_greg_t lbeg;
|
||||||
elf_greg_t lend;
|
elf_greg_t lend;
|
||||||
elf_greg_t lcount;
|
elf_greg_t lcount;
|
||||||
elf_greg_t sar;
|
elf_greg_t sar;
|
||||||
elf_greg_t syscall;
|
elf_greg_t windowstart;
|
||||||
elf_greg_t ar[64];
|
elf_greg_t reserved[9+48];
|
||||||
|
elf_greg_t a[64];
|
||||||
} xtensa_gregset_t;
|
} xtensa_gregset_t;
|
||||||
|
|
||||||
#define ELF_NGREG (sizeof(xtensa_gregset_t) / sizeof(elf_greg_t))
|
#define ELF_NGREG (sizeof(xtensa_gregset_t) / sizeof(elf_greg_t))
|
||||||
|
|
||||||
typedef elf_greg_t elf_gregset_t[ELF_NGREG];
|
typedef elf_greg_t elf_gregset_t[ELF_NGREG];
|
||||||
|
|
||||||
/*
|
#define ELF_NFPREG 18
|
||||||
* Compute the size of the coprocessor and extra state layout (register info)
|
|
||||||
* table (in bytes).
|
|
||||||
* This is actually the maximum size of the table, as opposed to the size,
|
|
||||||
* which is available from the _xtensa_reginfo_table_size global variable.
|
|
||||||
*
|
|
||||||
* (See also arch/xtensa/kernel/coprocessor.S)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef XCHAL_EXTRA_SA_CONTENTS_LIBDB_NUM
|
|
||||||
# define XTENSA_CPE_LTABLE_SIZE 0
|
|
||||||
#else
|
|
||||||
# define XTENSA_CPE_SEGMENT(num) (num ? (1+num) : 0)
|
|
||||||
# define XTENSA_CPE_LTABLE_ENTRIES \
|
|
||||||
( XTENSA_CPE_SEGMENT(XCHAL_EXTRA_SA_CONTENTS_LIBDB_NUM) \
|
|
||||||
+ XTENSA_CPE_SEGMENT(XCHAL_CP0_SA_CONTENTS_LIBDB_NUM) \
|
|
||||||
+ XTENSA_CPE_SEGMENT(XCHAL_CP1_SA_CONTENTS_LIBDB_NUM) \
|
|
||||||
+ XTENSA_CPE_SEGMENT(XCHAL_CP2_SA_CONTENTS_LIBDB_NUM) \
|
|
||||||
+ XTENSA_CPE_SEGMENT(XCHAL_CP3_SA_CONTENTS_LIBDB_NUM) \
|
|
||||||
+ XTENSA_CPE_SEGMENT(XCHAL_CP4_SA_CONTENTS_LIBDB_NUM) \
|
|
||||||
+ XTENSA_CPE_SEGMENT(XCHAL_CP5_SA_CONTENTS_LIBDB_NUM) \
|
|
||||||
+ XTENSA_CPE_SEGMENT(XCHAL_CP6_SA_CONTENTS_LIBDB_NUM) \
|
|
||||||
+ XTENSA_CPE_SEGMENT(XCHAL_CP7_SA_CONTENTS_LIBDB_NUM) \
|
|
||||||
+ 1 /* final entry */ \
|
|
||||||
)
|
|
||||||
# define XTENSA_CPE_LTABLE_SIZE (XTENSA_CPE_LTABLE_ENTRIES * 8)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Instantiations of the elf_fpregset_t type contain, in most
|
|
||||||
* architectures, the floating point (FPU) register set.
|
|
||||||
* For Xtensa, this type is extended to contain all custom state,
|
|
||||||
* ie. coprocessor and "extra" (non-coprocessor) state (including,
|
|
||||||
* for example, TIE-defined states and register files; as well
|
|
||||||
* as other optional processor state).
|
|
||||||
* This includes FPU state if a floating-point coprocessor happens
|
|
||||||
* to have been configured within the Xtensa processor.
|
|
||||||
*
|
|
||||||
* TOTAL_FPREGS_SIZE is the required size (without rounding)
|
|
||||||
* of elf_fpregset_t. It provides space for the following:
|
|
||||||
*
|
|
||||||
* a) 32-bit mask of active coprocessors for this task (similar
|
|
||||||
* to CPENABLE in single-threaded Xtensa processor systems)
|
|
||||||
*
|
|
||||||
* b) table describing the layout of custom states (ie. of
|
|
||||||
* individual registers, etc) within the save areas
|
|
||||||
*
|
|
||||||
* c) save areas for each coprocessor and for non-coprocessor
|
|
||||||
* ("extra") state
|
|
||||||
*
|
|
||||||
* Note that save areas may require up to 16-byte alignment when
|
|
||||||
* accessed by save/restore sequences. We do not need to ensure
|
|
||||||
* such alignment in an elf_fpregset_t structure because custom
|
|
||||||
* state is not directly loaded/stored into it; rather, save area
|
|
||||||
* contents are copied to elf_fpregset_t from the active save areas
|
|
||||||
* (see 'struct task_struct' definition in processor.h for that)
|
|
||||||
* using memcpy(). But we do allow space for such alignment,
|
|
||||||
* to allow optimizations of layout and copying.
|
|
||||||
*/
|
|
||||||
#if 0
|
|
||||||
#define TOTAL_FPREGS_SIZE \
|
|
||||||
(4 + XTENSA_CPE_LTABLE_SIZE + XTENSA_CP_EXTRA_SIZE)
|
|
||||||
#define ELF_NFPREG \
|
|
||||||
((TOTAL_FPREGS_SIZE + sizeof(elf_fpreg_t) - 1) / sizeof(elf_fpreg_t))
|
|
||||||
#else
|
|
||||||
#define TOTAL_FPREGS_SIZE 0
|
|
||||||
#define ELF_NFPREG 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef unsigned int elf_fpreg_t;
|
typedef unsigned int elf_fpreg_t;
|
||||||
typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
|
typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
|
||||||
|
|
Loading…
Reference in New Issue