, <port-mips@netbsd.org>
From: Chris Bacon <ChrisB@transpond.co.uk>
List: port-mips
Date: 11/27/2001 11:04:30
This is a multi-part message in MIME format.
------=_NextPart_000_070C_01C17733.49D88A90
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: 8bit
Sorry about the delay (a mere 5 months!), but here
are the diffs required to solve this problem.
This has only been tested on a TX3912
If there is any problem with how I've sent this fix
please let me know.
The two attached diffs are for:
sys\arch\mips\mips\trap.c
sys\arch\mips\include\ptrace.h
Chris
----- Original Message -----
From: "Jaromír Dolecek" <jdolecek@netbsd.org>
To: <roberts@transpond.co.uk>
Cc: <port-hpcmips@netbsd.org>; <port-mips@netbsd.org>; "'Chris Bacon'"
<chrisb@transpond.co.uk>
Sent: Thursday, June 28, 2001 6:52 PM
Subject: Re: FW: Single Stepping on TX3912
> Robert Smith wrote:
> > I have now solved this problem. It seems that there were some
> > bugs in /src/sys/arch/mips/mips/trap.c which led to incorrect
> > memory accesses when attempting to read/decode instructions
> > for the purpose of single stepping.
> >
> > If anyone is interested I can send them the fix. Alternatively, if
> > someone can give me some guidance, I will submit the fix into
> > the maintained code.
>
> Excellent work! You can either post it here, or send-pr the diff.
> The latter is probably better, so that committer won't need
> to dig archives to get the patch.
>
> Jaromir
> --
> Jaromir Dolecek <jdolecek@NetBSD.org>
http://www.ics.muni.cz/~dolecek/
> NetBSD - just plain best OS! -=*=- Got spare MCA cards or docs? Hand me
them!
>
>
------=_NextPart_000_070C_01C17733.49D88A90
Content-Type: application/octet-stream;
name="trap.c.diff"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="trap.c.diff"
--- trap.c Fri Jun 9 06:51:46 2000=0A=
+++ trap.c Mon Oct 15 15:31:34 2001=0A=
@@ -181,10 +181,15 @@=0A=
void syscall __P((unsigned, unsigned, unsigned));=0A=
void ast __P((unsigned));=0A=
=0A=
-vaddr_t MachEmulateBranch __P((struct frame *, vaddr_t, unsigned, int));=0A=
+static vaddr_t MachEmulateBranch0 __P((struct frame *, vaddr_t, =
unsigned, unsigned, int,int));=0A=
+static vaddr_t MachEmulateBranchProc __P((struct frame *, vaddr_t, =
struct proc*, unsigned, int));=0A=
+=0A=
+vaddr_t MachEmulateBranch __P((struct frame *, vaddr_t, unsigned, =
int));=0A=
+=0A=
extern void MachEmulateFP __P((unsigned));=0A=
extern void MachFPInterrupt __P((unsigned, unsigned, unsigned, struct =
frame *));=0A=
=0A=
+=0A=
void=0A=
userret(p, pc, sticks)=0A=
struct proc *p;=0A=
@@ -625,7 +630,7 @@=0A=
/* read break instruction */=0A=
instr =3D fuiword((void *)va);=0A=
#ifdef DEBUG=0A=
-/*XXX*/ printf("break insn 0x%x\n", instr);=0A=
+/*XXX*/ /*printf("break insn 0x%x @ 0x%x\n", instr,va);*/=0A=
#endif=0A=
=0A=
if (p->p_md.md_ss_addr !=3D va || instr !=3D MIPS_BREAK_SSTEP) {=0A=
@@ -636,17 +641,24 @@=0A=
* Restore original instruction and clear BP=0A=
*/=0A=
rv =3D suiword((void *)va, p->p_md.md_ss_instr);=0A=
- if (rv < 0) {=0A=
+ if (rv < 0) =0A=
+ {=0A=
vaddr_t sa, ea;=0A=
sa =3D trunc_page(va);=0A=
ea =3D round_page(va + sizeof(int) - 1);=0A=
- rv =3D uvm_map_protect(&p->p_vmspace->vm_map,=0A=
- sa, ea, VM_PROT_DEFAULT, FALSE);=0A=
- if (rv =3D=3D KERN_SUCCESS) {=0A=
- rv =3D suiword((void *)va, MIPS_BREAK_SSTEP);=0A=
+ rv =3D uvm_map_protect(&p->p_vmspace->vm_map,sa, ea, =
VM_PROT_DEFAULT, FALSE);=0A=
+ if (rv =3D=3D KERN_SUCCESS) =0A=
+ {=0A=
+ rv =3D suiword((void *)va, p->p_md.md_ss_instr);=0A=
(void)uvm_map_protect(&p->p_vmspace->vm_map,=0A=
sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, FALSE);=0A=
}=0A=
+ else=0A=
+ {=0A=
+ printf("Warning: can't restore instruction at 0x%x: 0x%x due to =
failure of uvm_map_protect() with %d \n",=0A=
+ p->p_md.md_ss_addr, p->p_md.md_ss_instr,rv);=0A=
+ =0A=
+ }=0A=
}=0A=
MachFlushCache();=0A=
=0A=
@@ -746,26 +758,93 @@=0A=
userret(p, pc, p->p_sticks);=0A=
}=0A=
=0A=
+=0A=
+/* =0A=
+ * Instruction write routine used by mips_singlestep(...).=0A=
+ */=0A=
+static int InsnWrite(struct proc *p, int va, int insn)=0A=
+{=0A=
+ struct uio uio;=0A=
+ struct iovec iov;=0A=
+ int rv;=0A=
+=0A=
+ iov.iov_base =3D (caddr_t)&insn;=0A=
+ iov.iov_len =3D sizeof(int);=0A=
+ uio.uio_iov =3D &iov;=0A=
+ uio.uio_iovcnt =3D 1;=0A=
+=0A=
+ uio.uio_offset =3D (off_t)va;=0A=
+ uio.uio_resid =3D sizeof(int);=0A=
+ uio.uio_segflg =3D UIO_SYSSPACE;=0A=
+ uio.uio_rw =3D UIO_WRITE;=0A=
+ uio.uio_procp =3D p;=0A=
+=0A=
+ rv =3D uvm_io(&p->p_vmspace->vm_map, &uio);=0A=
+ if (rv !=3D KERN_SUCCESS) =0A=
+ {=0A=
+ printf("SS %s (%d): Error - uvm_io(UIO_WRITE,0x%x,0x%x) returned =
%d\n",p->p_comm, p->p_pid,rv,va,insn);=0A=
+ }=0A=
+ return rv;=0A=
+}=0A=
+=0A=
+/* =0A=
+ * Instruction read routine used by mips_singlestep(...).=0A=
+ */=0A=
+static int InsnRead(struct proc *p, int va)=0A=
+{=0A=
+ struct uio uio;=0A=
+ struct iovec iov;=0A=
+ int rv;=0A=
+ int insn;=0A=
+=0A=
+ iov.iov_base =3D (caddr_t)&insn;=0A=
+ iov.iov_len =3D sizeof(int);=0A=
+ uio.uio_iov =3D &iov;=0A=
+ uio.uio_iovcnt =3D 1;=0A=
+=0A=
+ uio.uio_offset =3D (off_t)va;=0A=
+ uio.uio_resid =3D sizeof(int);=0A=
+ uio.uio_segflg =3D UIO_SYSSPACE;=0A=
+ uio.uio_rw =3D UIO_READ;=0A=
+ uio.uio_procp =3D p;=0A=
+=0A=
+ rv =3D uvm_io(&p->p_vmspace->vm_map, &uio);=0A=
+ if (rv !=3D KERN_SUCCESS) =0A=
+ {=0A=
+ printf("SS %s (%d): Error - uvm_io(UIO_READ,0x%x) returned =
%d\n",p->p_comm, p->p_pid,rv,va);=0A=
+ return -1;=0A=
+ }=0A=
+ return insn;=0A=
+}=0A=
+=0A=
+=0A=
/*=0A=
* Analyse 'next' PC address taking account of branch/jump instructions=0A=
*/=0A=
-vaddr_t=0A=
-MachEmulateBranch(f, instpc, fpuCSR, allowNonBranch)=0A=
- struct frame *f;=0A=
- vaddr_t instpc;=0A=
- unsigned fpuCSR;=0A=
- int allowNonBranch;=0A=
+static vaddr_t=0A=
+MachEmulateBranch0(f, instpc, insn, fpuCSR, allowNonBranch, verbose)=0A=
+ struct frame* f;=0A=
+ vaddr_t instpc;=0A=
+ unsigned insn;=0A=
+ unsigned fpuCSR;=0A=
+ int allowNonBranch;=0A=
+ int verbose;=0A=
{=0A=
-#define BRANCHTARGET(p) (4 + (p) + ((short)((InstFmt *)(p))->IType.imm =
<< 2))=0A=
+#define BRANCHTARGET(pc,inst) (4 + (pc) + (short) (inst.IType.imm << 2))=0A=
InstFmt inst;=0A=
vaddr_t nextpc;=0A=
=0A=
- if (instpc < MIPS_KSEG0_START)=0A=
- inst.word =3D fuiword((void *)instpc);=0A=
- else=0A=
- inst.word =3D *(unsigned *)instpc;=0A=
+ inst.word =3D insn;=0A=
+=0A=
+ if (verbose)=0A=
+ {=0A=
+ printf("MachEmulateBranch0(0x%x:0x%x) - JType.op =3D 0x%x, BT =3D =
0x%lx\n",=0A=
+ (unsigned) instpc,insn,(unsigned)inst.JType.op,=0A=
+ BRANCHTARGET(instpc,inst));=0A=
+ }=0A=
=0A=
- switch ((int)inst.JType.op) {=0A=
+ switch ((int)inst.JType.op) =0A=
+ {=0A=
case OP_SPECIAL:=0A=
if (inst.RType.func =3D=3D OP_JR || inst.RType.func =3D=3D OP_JALR)=0A=
nextpc =3D f->f_regs[inst.RType.rs];=0A=
@@ -782,7 +861,7 @@=0A=
case OP_BLTZL: /* squashed */=0A=
case OP_BLTZALL: /* squashed */=0A=
if ((int)(f->f_regs[inst.RType.rs]) < 0)=0A=
- nextpc =3D BRANCHTARGET(instpc);=0A=
+ nextpc =3D BRANCHTARGET(instpc,inst);=0A=
else=0A=
nextpc =3D instpc + 8;=0A=
break;=0A=
@@ -792,7 +871,7 @@=0A=
case OP_BGEZL: /* squashed */=0A=
case OP_BGEZALL: /* squashed */=0A=
if ((int)(f->f_regs[inst.RType.rs]) >=3D 0)=0A=
- nextpc =3D BRANCHTARGET(instpc);=0A=
+ nextpc =3D BRANCHTARGET(instpc,inst);=0A=
else=0A=
nextpc =3D instpc + 8;=0A=
break;=0A=
@@ -811,7 +890,7 @@=0A=
case OP_BEQ:=0A=
case OP_BEQL: /* squashed */=0A=
if (f->f_regs[inst.RType.rs] =3D=3D f->f_regs[inst.RType.rt])=0A=
- nextpc =3D BRANCHTARGET(instpc);=0A=
+ nextpc =3D BRANCHTARGET(instpc,inst);=0A=
else=0A=
nextpc =3D instpc + 8;=0A=
break;=0A=
@@ -819,7 +898,7 @@=0A=
case OP_BNE:=0A=
case OP_BNEL: /* squashed */=0A=
if (f->f_regs[inst.RType.rs] !=3D f->f_regs[inst.RType.rt])=0A=
- nextpc =3D BRANCHTARGET(instpc);=0A=
+ nextpc =3D BRANCHTARGET(instpc,inst);=0A=
else=0A=
nextpc =3D instpc + 8;=0A=
break;=0A=
@@ -827,7 +906,7 @@=0A=
case OP_BLEZ:=0A=
case OP_BLEZL: /* squashed */=0A=
if ((int)(f->f_regs[inst.RType.rs]) <=3D 0)=0A=
- nextpc =3D BRANCHTARGET(instpc);=0A=
+ nextpc =3D BRANCHTARGET(instpc,inst);=0A=
else=0A=
nextpc =3D instpc + 8;=0A=
break;=0A=
@@ -835,7 +914,7 @@=0A=
case OP_BGTZ:=0A=
case OP_BGTZL: /* squashed */=0A=
if ((int)(f->f_regs[inst.RType.rs]) > 0)=0A=
- nextpc =3D BRANCHTARGET(instpc);=0A=
+ nextpc =3D BRANCHTARGET(instpc,inst);=0A=
else=0A=
nextpc =3D instpc + 8;=0A=
break;=0A=
@@ -846,7 +925,7 @@=0A=
if ((inst.RType.rt & COPz_BC_TF_MASK) !=3D COPz_BC_TRUE)=0A=
condition =3D !condition;=0A=
if (condition)=0A=
- nextpc =3D BRANCHTARGET(instpc);=0A=
+ nextpc =3D BRANCHTARGET(instpc,inst);=0A=
else=0A=
nextpc =3D instpc + 8;=0A=
}=0A=
@@ -861,55 +940,132 @@=0A=
panic("MachEmulateBranch: Non-branch instruction");=0A=
nextpc =3D instpc + 4;=0A=
}=0A=
+=0A=
+ if (verbose)=0A=
+ {=0A=
+ printf("MachEmulateBranch0(0x%x:0x%x) - returning 0x%x\n",=0A=
+ (unsigned) instpc,insn,(unsigned)nextpc);=0A=
+ }=0A=
return nextpc;=0A=
#undef BRANCHTARGET=0A=
}=0A=
=0A=
+=0A=
+/*=0A=
+ * MachEmulateBranch(...);=0A=
+ */=0A=
+vaddr_t=0A=
+MachEmulateBranch(f, instpc, fpuCSR, allowNonBranch)=0A=
+ struct frame* f;=0A=
+ vaddr_t instpc;=0A=
+ unsigned fpuCSR;=0A=
+ int allowNonBranch;=0A=
+{=0A=
+ unsigned insn;=0A=
+ =0A=
+ if (instpc < MIPS_KSEG0_START)=0A=
+ insn =3D fuiword((void *)instpc);=0A=
+ else=0A=
+ insn =3D *(unsigned *)instpc;=0A=
+=0A=
+ return MachEmulateBranch0(f, instpc, insn, fpuCSR, =
allowNonBranch, 0);=0A=
+}=0A=
+=0A=
+=0A=
+/*=0A=
+ * MachEmulateBranchProc(...);=0A=
+ */=0A=
+static vaddr_t=0A=
+MachEmulateBranchProc(f, instpc, p, fpuCSR, allowNonBranch)=0A=
+ struct frame* f;=0A=
+ vaddr_t instpc;=0A=
+ struct proc* p;=0A=
+ unsigned fpuCSR;=0A=
+ int allowNonBranch;=0A=
+{=0A=
+ unsigned insn;=0A=
+=0A=
+ insn =3D InsnRead(p, (int)instpc);=0A=
+=0A=
+ return MachEmulateBranch0(f, instpc, insn, fpuCSR, =
allowNonBranch,0);=0A=
+}=0A=
+=0A=
/* XXX need to rewrite acient comment XXX=0A=
* This routine is called by procxmt() to single step one instruction.=0A=
* We do this by storing a break instruction after the current =
instruction,=0A=
* resuming execution, and then restoring the old instruction.=0A=
*/=0A=
-int=0A=
-mips_singlestep(p)=0A=
- struct proc *p;=0A=
+int mips_singlestep(struct proc *p)=0A=
{=0A=
- struct frame *f =3D (struct frame *)p->p_md.md_regs;=0A=
- vaddr_t pc, va;=0A=
- int rv;=0A=
+ struct frame* f =3D (struct frame *)p->p_md.md_regs;=0A=
+ vaddr_t pc, va, sa, ea;=0A=
+ int rv;=0A=
=0A=
- if (p->p_md.md_ss_addr) {=0A=
+ /*=0A=
+ * Confirm that a breakpoint has not already been set.=0A=
+ */=0A=
+ if (p->p_md.md_ss_addr) =0A=
+ {=0A=
printf("SS %s (%d): breakpoint already set at %x\n",=0A=
p->p_comm, p->p_pid, p->p_md.md_ss_addr);=0A=
return EFAULT;=0A=
}=0A=
+=0A=
+ /*=0A=
+ * Get the current program counter and determine the virtual=0A=
+ * address of the next instruction to be executed.=0A=
+ */=0A=
pc =3D (vaddr_t)f->f_regs[PC];=0A=
- if (fuiword((void *)pc) !=3D 0) /* not a NOP instruction */=0A=
- va =3D MachEmulateBranch(f, pc,=0A=
- p->p_addr->u_pcb.pcb_fpregs.r_regs[32], 1);=0A=
+ if (InsnRead(p, pc) !=3D 0) /* not a NOP instruction */=0A=
+ {=0A=
+ va =3D MachEmulateBranchProc(f, pc, p, =
p->p_addr->u_pcb.pcb_fpregs.r_regs[32], 1);=0A=
+ }=0A=
else=0A=
+ {=0A=
va =3D pc + sizeof(int);=0A=
+ }=0A=
+=0A=
+ /*=0A=
+ * Store the instruction and address of the next =0A=
+ * instruction to be executed (the break-point).=0A=
+ */=0A=
p->p_md.md_ss_addr =3D va;=0A=
- p->p_md.md_ss_instr =3D fuiword((void *)va);=0A=
- rv =3D suiword((void *)va, MIPS_BREAK_SSTEP);=0A=
- if (rv < 0) {=0A=
- vaddr_t sa, ea;=0A=
+ p->p_md.md_ss_instr =3D InsnRead(p, va);=0A=
+=0A=
+ /*=0A=
+ * Write the single-step break instruction to the=0A=
+ * next instruction's location.=0A=
+ */=0A=
+ rv =3D InsnWrite(p, va, MIPS_BREAK_SSTEP);=0A=
+ if (rv !=3D KERN_SUCCESS) =0A=
+ {=0A=
sa =3D trunc_page(va);=0A=
ea =3D round_page(va + sizeof(int) - 1);=0A=
- rv =3D uvm_map_protect(&p->p_vmspace->vm_map,=0A=
- sa, ea, VM_PROT_DEFAULT, FALSE);=0A=
- if (rv =3D=3D KERN_SUCCESS) {=0A=
- rv =3D suiword((void *)va, MIPS_BREAK_SSTEP);=0A=
- (void)uvm_map_protect(&p->p_vmspace->vm_map,=0A=
- sa, ea, VM_PROT_READ|VM_PROT_EXECUTE, FALSE);=0A=
- }=0A=
+ rv =3D uvm_map_protect(&p->p_vmspace->vm_map,sa, ea, VM_PROT_DEFAULT, =
FALSE);=0A=
+ if (rv =3D=3D KERN_SUCCESS) =0A=
+ {=0A=
+ rv =3D InsnWrite(p, va, MIPS_BREAK_SSTEP);=0A=
+ if (rv !=3D KERN_SUCCESS) =0A=
+ {=0A=
+ printf("SS %s (%d): Error - InsnWrite(...) returned =
%d\n",p->p_comm, p->p_pid,rv);=0A=
+ }=0A=
+ (void)uvm_map_protect(&p->p_vmspace->vm_map,sa, ea, =
VM_PROT_READ|VM_PROT_EXECUTE, FALSE);=0A=
+ }=0A=
+ else=0A=
+ {=0A=
+ printf("SS %s (%d): Error - uvm_map_protect(...) returned =
%d\n",p->p_comm, p->p_pid,rv);=0A=
+ }=0A=
+ }=0A=
+=0A=
+#if defined(DEBUG) && defined(VERBOSE)=0A=
+ if (rv =3D=3D KERN_SUCCESS) =0A=
+ {=0A=
+ printf("SS %s (%d): breakpoint (%x) set at %x: %x (pc %x) br %x\n",=0A=
+ p->p_comm, p->p_pid, MIPS_BREAK_SSTEP,p->p_md.md_ss_addr,=0A=
+ p->p_md.md_ss_instr, (unsigned int)pc, InsnRead(p, va)); /* XXX */=0A=
}=0A=
-#if 0=0A=
- printf("SS %s (%d): breakpoint set at %x: %x (pc %x) br %x\n",=0A=
- p->p_comm, p->p_pid, p->p_md.md_ss_addr,=0A=
- p->p_md.md_ss_instr, pc, fuword((void *)va)); /* XXX */=0A=
-#endif=0A=
- return 0;=0A=
+#endif /* DEBUG & VERBOSE */=0A=
+ return 0;=0A=
}=0A=
=0A=
=0A=
------=_NextPart_000_070C_01C17733.49D88A90
Content-Type: application/octet-stream;
name="ptrace.h.diff"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
filename="ptrace.h.diff"
--- ptrace.h Mon Oct 20 08:29:22 1997=0A=
+++ ptrace.h Mon Jun 11 18:26:08 2001=0A=
@@ -43,7 +43,7 @@=0A=
#ifndef _MIPS_PTRACE_H_=0A=
#define _MIPS_PTRACE_H_=0A=
=0A=
-/*#define PT_STEP (PT_FIRSTMACH + 0)*/=0A=
+#define PT_STEP (PT_FIRSTMACH + 0)=0A=
#define PT_GETREGS (PT_FIRSTMACH + 1)=0A=
#define PT_SETREGS (PT_FIRSTMACH + 2)=0A=
=0A=
------=_NextPart_000_070C_01C17733.49D88A90--