Subject: Re: FW: Single Stepping on TX3912
To: , <port-mips@netbsd.org>
From: Chris Bacon <ChrisB@transpond.co.uk>
List: port-hpcmips
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--