mirror of
				https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/linux-loongson
				synced 2025-10-31 12:09:34 +00:00 
			
		
		
		
	 857fb252a1
			
		
	
	
		857fb252a1
		
	
	
	
	
		
			
			Use the generic ptrace_resume code for PTRACE_SYSCALL, PTRACE_CONT, PTRACE_KILL and PTRACE_SINGLESTEP. This implies defining arch_has_single_step in <asm/ptrace.h> and implementing the user_enable_single_step and user_disable_single_step functions, which also causes the breakpoint information to be cleared on fork, which could be considered a bug fix. Also the TIF_SYSCALL_TRACE thread flag is now cleared on PTRACE_KILL which it previously wasn't which is consistent with all architectures using the modern ptrace code. Signed-off-by: Christoph Hellwig <hch@lst.de> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Roland McGrath <roland@redhat.com> Cc: Yoshinori Sato <ysato@users.sourceforge.jp> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
		
			
				
	
	
		
			85 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			85 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  *  linux/arch/h8300/platform/h8s/ptrace_h8s.c
 | |
|  *    ptrace cpu depend helper functions
 | |
|  *
 | |
|  *  Yoshinori Sato <ysato@users.sourceforge.jp>
 | |
|  *
 | |
|  * This file is subject to the terms and conditions of the GNU General
 | |
|  * Public License.  See the file COPYING in the main directory of
 | |
|  * this archive for more details.
 | |
|  */
 | |
| 
 | |
| #include <linux/linkage.h>
 | |
| #include <linux/sched.h>
 | |
| #include <linux/errno.h>
 | |
| #include <asm/ptrace.h>
 | |
| 
 | |
| #define CCR_MASK  0x6f
 | |
| #define EXR_TRACE 0x80
 | |
| 
 | |
| /* Mapping from PT_xxx to the stack offset at which the register is
 | |
|    saved.  Notice that usp has no stack-slot and needs to be treated
 | |
|    specially (see get_reg/put_reg below). */
 | |
| static const int h8300_register_offset[] = {
 | |
| 	PT_REG(er1), PT_REG(er2), PT_REG(er3), PT_REG(er4),
 | |
| 	PT_REG(er5), PT_REG(er6), PT_REG(er0), PT_REG(orig_er0),
 | |
| 	PT_REG(ccr), PT_REG(pc),  0,           PT_REG(exr)
 | |
| };
 | |
| 
 | |
| /* read register */
 | |
| long h8300_get_reg(struct task_struct *task, int regno)
 | |
| {
 | |
| 	switch (regno) {
 | |
| 	case PT_USP:
 | |
| 		return task->thread.usp + sizeof(long)*2 + 2;
 | |
| 	case PT_CCR:
 | |
| 	case PT_EXR:
 | |
| 	    return *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]);
 | |
| 	default:
 | |
| 	    return *(unsigned long *)(task->thread.esp0 + h8300_register_offset[regno]);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| /* write register */
 | |
| int h8300_put_reg(struct task_struct *task, int regno, unsigned long data)
 | |
| {
 | |
| 	unsigned short oldccr;
 | |
| 	switch (regno) {
 | |
| 	case PT_USP:
 | |
| 		task->thread.usp = data - sizeof(long)*2 - 2;
 | |
| 	case PT_CCR:
 | |
| 		oldccr = *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]);
 | |
| 		oldccr &= ~CCR_MASK;
 | |
| 		data &= CCR_MASK;
 | |
| 		data |= oldccr;
 | |
| 		*(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]) = data;
 | |
| 		break;
 | |
| 	case PT_EXR:
 | |
| 		/* exr modify not support */
 | |
| 		return -EIO;
 | |
| 	default:
 | |
| 		*(unsigned long *)(task->thread.esp0 + h8300_register_offset[regno]) = data;
 | |
| 		break;
 | |
| 	}
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /* disable singlestep */
 | |
| void user_disable_single_step(struct task_struct *child)
 | |
| {
 | |
| 	*(unsigned short *)(child->thread.esp0 + h8300_register_offset[PT_EXR]) &= ~EXR_TRACE;
 | |
| }
 | |
| 
 | |
| /* enable singlestep */
 | |
| void user_enable_single_step(struct task_struct *child)
 | |
| {
 | |
| 	*(unsigned short *)(child->thread.esp0 + h8300_register_offset[PT_EXR]) |= EXR_TRACE;
 | |
| }
 | |
| 
 | |
| asmlinkage void trace_trap(unsigned long bp)
 | |
| {
 | |
| 	(void)bp;
 | |
| 	force_sig(SIGTRAP,current);
 | |
| }
 | |
| 
 |