[xtensa-cvscommit] linux/arch/xtensa/kernel process.c,1.3,1.4 ptrace.c,1.4,1.5
Brought to you by:
zankel
|
From: <joe...@us...> - 2003-01-25 03:12:48
|
Update of /cvsroot/xtensa/linux/arch/xtensa/kernel
In directory sc8-pr-cvs1:/tmp/cvs-serv9373/arch/xtensa/kernel
Modified Files:
process.c ptrace.c
Log Message:
Kernel changes to support core dumps and a more efficient ptrace interface. TIE information is still missing.
Index: process.c
===================================================================
RCS file: /cvsroot/xtensa/linux/arch/xtensa/kernel/process.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -C2 -d -r1.3 -r1.4
*** process.c 18 Oct 2002 21:57:26 -0000 1.3
--- process.c 25 Jan 2003 03:12:45 -0000 1.4
***************
*** 326,327 ****
--- 326,431 ----
return regs->aregs[0];
}
+
+
+ /* do_copy_regs() gathers information from 'struct pt_regs' and
+ * 'current->thread.aregs[]' to fill in the elf_gregset_t structure.
+ *
+ * elf_gregset_t and 'struct pt_regs' are vastly different formats of
+ * processor registers. Besides different ordering, elf_gregset_t
+ * contains non-live register information that 'struct pt_regs' does
+ * not. Exception handling (primarily) uses 'struct pt_regs'. Core
+ * files and ptrace use elf_gregset_t. */
+
+ void do_copy_regs (elf_gregset_t *elfregs, struct pt_regs *regs, struct task_struct *tsk)
+ {
+ int i, wb_offset; /* wb_offset must be signed */
+
+ 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;
+
+ elfregs->pc = regs->pc;
+ elfregs->ps = regs->ps;
+ elfregs->exccause = regs->exccause;
+ elfregs->excvaddr = regs->excvaddr;
+ elfregs->wb = regs->wb;
+ elfregs->ws = regs->ws;
+ elfregs->lbeg = regs->lbeg;
+ elfregs->lend = regs->lend;
+ elfregs->lcount = regs->lcount;
+ elfregs->sar = regs->sar;
+
+ /* Clear everything. We don't have values for all of them, so
+ some remain zero. */
+ memset (elfregs->ar, 0, sizeof(elfregs->ar));
+
+ /* Copy regs from live window frame. */
+ wb_offset = regs->wb * 4;
+ for (i = 0; i < 16; i++)
+ /* using wb_offset as register number */
+ elfregs->ar[(wb_offset + i) % XCHAL_NUM_AREGS] = regs->aregs[i];
+
+ /* Copy regs from non-live registers.
+ regs->wmask indicates the number of window panes saved. */
+ wb_offset = regs->wb;
+ for (i = 0; i < regs->wmask; i++) {
+ /* using wb_offset as window-pane number */
+ if (--wb_offset < 0)
+ wb_offset = XCHAL_NUM_AREGS / 4;
+ elfregs->ar[wb_offset*4 + 0] = tsk->thread.regfile[i + 0];
+ elfregs->ar[wb_offset*4 + 1] = tsk->thread.regfile[i + 1];
+ elfregs->ar[wb_offset*4 + 2] = tsk->thread.regfile[i + 2];
+ elfregs->ar[wb_offset*4 + 3] = tsk->thread.regfile[i + 3];
+ }
+ }
+
+ void xtensa_elf_core_copy_regs (elf_gregset_t *elfregs, struct pt_regs *regs)
+ {
+ do_copy_regs (elfregs, regs, current);
+ }
+
+
+ /* The inverse of do_copy_regs(). No error or sanity checking. */
+
+ void do_restore_regs (elf_gregset_t *elfregs, struct pt_regs *regs, struct task_struct *tsk)
+ {
+ int i, wb_offset; /* wb_offset must be signed */
+
+ regs->pc = elfregs->pc;
+ regs->ps = elfregs->ps;
+ regs->exccause = elfregs->exccause;
+ regs->excvaddr = elfregs->excvaddr;
+ regs->wb = elfregs->wb;
+ regs->ws = elfregs->ws;
+ regs->lbeg = elfregs->lbeg;
+ regs->lend = elfregs->lend;
+ regs->lcount = elfregs->lcount;
+ regs->sar = elfregs->sar;
+
+ /* Clear everything. We don't have values for all of them, so
+ some remain zero. */
+ memset (tsk->thread.regfile, 0, sizeof(tsk->thread.regfile));
+
+ /* Copy regs from live window frame. */
+ wb_offset = elfregs->wb * 4;
+ for (i = 0; i < 16; i++)
+ /* using wb_offset as register number */
+ regs->aregs[i] = elfregs->ar[(wb_offset + i) % XCHAL_NUM_AREGS];
+
+ /* Copy regs from non-live registers.
+ regs->wmask indicates the number of window panes saved. */
+ wb_offset = elfregs->wb;
+ for (i = 0; i < regs->wmask; i++) {
+ /* using wb_offset as window-pane number */
+ if (--wb_offset < 0)
+ wb_offset = XCHAL_NUM_AREGS / 4;
+ tsk->thread.regfile[i + 0] = elfregs->ar[wb_offset*4 + 0];
+ tsk->thread.regfile[i + 1] = elfregs->ar[wb_offset*4 + 1];
+ tsk->thread.regfile[i + 2] = elfregs->ar[wb_offset*4 + 2];
+ tsk->thread.regfile[i + 3] = elfregs->ar[wb_offset*4 + 3];
+ }
+ }
Index: ptrace.c
===================================================================
RCS file: /cvsroot/xtensa/linux/arch/xtensa/kernel/ptrace.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -C2 -d -r1.4 -r1.5
*** ptrace.c 4 Oct 2002 06:30:55 -0000 1.4
--- ptrace.c 25 Jan 2003 03:12:45 -0000 1.5
***************
*** 10,14 ****
* Kevin D. Kissell, ke...@mi... and Carsten Langgaard, car...@mi...
* Copyright (C) 1999 MIPS Technologies, Inc.
! * Scott Foehner, sfo...@te...
* Copyright (C) 2002 Tensilica, Inc.
*/
--- 10,14 ----
* Kevin D. Kissell, ke...@mi... and Carsten Langgaard, car...@mi...
* Copyright (C) 1999 MIPS Technologies, Inc.
! * Scott Foehner, sfo...@te... and Joe Taylor, jo...@te...
* Copyright (C) 2002 Tensilica, Inc.
*/
***************
*** 27,33 ****
--- 27,43 ----
#include <asm/system.h>
#include <asm/uaccess.h>
+ #include <asm/elf.h>
#define PT_SINGLESTEP 0x10000
+ extern void do_copy_regs (elf_gregset_t *, struct pt_regs *, struct task_struct *);
+ extern void do_restore_regs (elf_gregset_t *, struct pt_regs *, struct task_struct *);
+
+
+ #if 0
+
+ /* XTFIXME: Removed in favor of the PTRACE_GETUSER interface. Delete
+ * after some time. [JET, 24 Jan 2003] */
+
/* Given a valid wb and ws, find the first valid "pane" */
/* Pane is given as the distance from pane 0, which is wb */
***************
*** 48,52 ****
return count+1;
}
!
/*
--- 58,63 ----
return count+1;
}
!
! #endif /* if 0 */
/*
***************
*** 63,67 ****
{
struct task_struct *child;
! int res, ar_reg, a_reg, first_pane;
extern void save_fp(struct task_struct *);
--- 74,78 ----
{
struct task_struct *child;
! int res;
extern void save_fp(struct task_struct *);
***************
*** 123,126 ****
--- 134,143 ----
goto out;
}
+
+ #if 0
+
+ /* XTFIXME: Removed in favor of the PTRACE_GETUSER interface. Delete
+ * after some time. [JET, 24 Jan 2003] */
+
/* Read the word at location addr in the USER area. */
case PTRACE_PEEKUSR: {
***************
*** 128,133 ****
unsigned long tmp;
! regs = (struct pt_regs *)
! (((unsigned long) child) + __KSTK_TOS_OFFSET);
tmp = 0; /* Default return value. */
--- 145,149 ----
unsigned long tmp;
! regs = __KSTK_TOS(child);
tmp = 0; /* Default return value. */
***************
*** 214,217 ****
--- 230,236 ----
goto out;
}
+
+ #endif /* if 0 */
+
case PTRACE_POKETEXT: /* write the word at location addr. */
case PTRACE_POKEDATA:
***************
*** 222,231 ****
res = -EIO;
goto out;
case PTRACE_POKEUSR: {
struct pt_regs *regs;
unsigned long tmp;
res = 0;
! regs = (struct pt_regs *)
! (((unsigned long) child) + __KSTK_TOS_OFFSET);
switch (addr) {
--- 241,257 ----
res = -EIO;
goto out;
+
+
+
+ #if 0
+
+ /* XTFIXME: Removed in favor of the PTRACE_GETUSER interface. Delete
+ * after some time. [JET, 24 Jan 2003] */
+
case PTRACE_POKEUSR: {
struct pt_regs *regs;
unsigned long tmp;
res = 0;
! regs = __KSTK_TOS(child);
switch (addr) {
***************
*** 274,287 ****
}
! case PTRACE_SINGLESTEP:
! res = -EIO;
! if ((unsigned long) data > _NSIG)
! break;
! child->ptrace &= ~PT_TRACESYS;
! child->ptrace |= PT_SINGLESTEP;
! child->exit_code = data;
! wake_up_process(child);
! res = 0;
! break;
case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
--- 300,304 ----
}
! #endif /* if 0 */
case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */
***************
*** 314,329 ****
break;
! case PTRACE_DETACH: /* detach a process that was attached. */
! res = ptrace_detach(child, data);
break;
! #if 0
! case PTRACE_SETOPTIONS:
! if (data & PTRACE_O_TRACESYSGOOD)
! child->ptrace |= PT_TRACESYSGOOD;
! else
! child->ptrace &= ~PT_TRACESYSGOOD;
res = 0;
break;
! #endif
default:
res = -EIO;
--- 331,397 ----
break;
! case PTRACE_SINGLESTEP:
! res = -EIO;
! if ((unsigned long) data > _NSIG)
! break;
! child->ptrace &= ~PT_TRACESYS;
! child->ptrace |= PT_SINGLESTEP;
! child->exit_code = data;
! wake_up_process(child);
! res = 0;
break;
!
! case PTRACE_GETREGS:
! {
! /* 'data' points to user memory in which to write.
! * Mainly due to the non-live register values, we
! * reformat the register values into something more
! * standard. For convenience, we use the handy
! * elf_gregset_t format. */
!
! elf_gregset_t format;
! struct pt_regs *regs = __KSTK_TOS(child);
!
! do_copy_regs (&format, regs, child);
!
! /* Now, copy to user space nice and easy... */
res = 0;
+ if (copy_to_user((void *)data, &format, sizeof(elf_gregset_t)))
+ res = -EFAULT;
break;
! }
!
! case PTRACE_SETREGS:
! {
! /* 'data' points to user memory that contains the new
! * values in the elf_gregset_t format. */
!
! elf_gregset_t format;
! struct pt_regs *regs = __KSTK_TOS(child);
!
! if (copy_from_user(&format, (void *)data, sizeof(elf_gregset_t))) {
! res = -EFAULT;
! break;
! }
!
! /* XTFIXME: Perhaps we want some sanity checks on
! * these user-space values? See ARM version. Are
! * debuggers a security concern? */
!
! do_restore_regs (&format, regs, child);
!
! break;
! }
!
! case PTRACE_GETFPREGS:
! break;
!
! case PTRACE_SETFPREGS:
! break;
!
! case PTRACE_DETACH: /* detach a process that was attached. */
! res = ptrace_detach(child, data);
! break;
!
default:
res = -EIO;
|