Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e50e2f25 authored by Mike Frysinger's avatar Mike Frysinger
Browse files

Blackfin: initial regset support



We don't support core dumps (yet?), but this should make things easier.

Signed-off-by: default avatarMike Frysinger <vapier@gentoo.org>
parent f2ce4802
Loading
Loading
Loading
Loading
+7 −1
Original line number Original line Diff line number Diff line
@@ -22,12 +22,15 @@
#define EF_BFIN_CODE_IN_L2	0x00000040	/* --code-in-l2 */
#define EF_BFIN_CODE_IN_L2	0x00000040	/* --code-in-l2 */
#define EF_BFIN_DATA_IN_L2	0x00000080	/* --data-in-l2 */
#define EF_BFIN_DATA_IN_L2	0x00000080	/* --data-in-l2 */


#if 1	/* core dumps not supported, but linux/elfcore.h needs these */
typedef unsigned long elf_greg_t;
typedef unsigned long elf_greg_t;


#define ELF_NGREG 40 /* (sizeof(struct user_regs_struct) / sizeof(elf_greg_t)) */
#define ELF_NGREG (sizeof(struct pt_regs) / sizeof(elf_greg_t))
typedef elf_greg_t elf_gregset_t[ELF_NGREG];
typedef elf_greg_t elf_gregset_t[ELF_NGREG];


typedef struct { } elf_fpregset_t;
typedef struct { } elf_fpregset_t;
#endif

/*
/*
 * This is used to ensure we don't load something for the wrong architecture.
 * This is used to ensure we don't load something for the wrong architecture.
 */
 */
@@ -55,6 +58,9 @@ do { \
	_regs->p2	= _dynamic_addr;				\
	_regs->p2	= _dynamic_addr;				\
} while(0)
} while(0)


#if 0
#define CORE_DUMP_USE_REGSET
#endif
#define ELF_FDPIC_CORE_EFLAGS	EF_BFIN_FDPIC
#define ELF_FDPIC_CORE_EFLAGS	EF_BFIN_FDPIC
#define ELF_EXEC_PAGESIZE	4096
#define ELF_EXEC_PAGESIZE	4096


+0 −7
Original line number Original line Diff line number Diff line
@@ -98,13 +98,6 @@ void cpu_idle(void)
	}
	}
}
}


/* Fill in the fpu structure for a core dump.  */

int dump_fpu(struct pt_regs *regs, elf_fpregset_t * fpregs)
{
	return 1;
}

/*
/*
 * This gets run with P1 containing the
 * This gets run with P1 containing the
 * function to call, and R1 containing
 * function to call, and R1 containing
+90 −23
Original line number Original line Diff line number Diff line
@@ -9,9 +9,11 @@
#include <linux/sched.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/mm.h>
#include <linux/smp.h>
#include <linux/smp.h>
#include <linux/elf.h>
#include <linux/errno.h>
#include <linux/errno.h>
#include <linux/ptrace.h>
#include <linux/ptrace.h>
#include <linux/user.h>
#include <linux/user.h>
#include <linux/regset.h>
#include <linux/signal.h>
#include <linux/signal.h>
#include <linux/uaccess.h>
#include <linux/uaccess.h>


@@ -49,22 +51,6 @@ static inline struct pt_regs *task_pt_regs(struct task_struct *task)
	     (THREAD_SIZE - sizeof(struct pt_regs)));
	     (THREAD_SIZE - sizeof(struct pt_regs)));
}
}


/*
 * Get all user integer registers.
 */
static inline int ptrace_getregs(struct task_struct *tsk, void __user *uregs)
{
	struct pt_regs regs;
	memcpy(&regs, task_pt_regs(tsk), sizeof(regs));
	regs.usp = tsk->thread.usp;
	return copy_to_user(uregs, &regs, sizeof(struct pt_regs)) ? -EFAULT : 0;
}

/* 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).
 */

/*
/*
 * Get contents of register REGNO in task TASK.
 * Get contents of register REGNO in task TASK.
 */
 */
@@ -170,6 +156,84 @@ static inline int is_user_addr_valid(struct task_struct *child,
	return -EIO;
	return -EIO;
}
}


/*
 * retrieve the contents of Blackfin userspace general registers
 */
static int genregs_get(struct task_struct *target,
		       const struct user_regset *regset,
		       unsigned int pos, unsigned int count,
		       void *kbuf, void __user *ubuf)
{
	struct pt_regs *regs = task_pt_regs(target);
	int ret;

	/* This sucks ... */
	regs->usp = target->thread.usp;

	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
				  regs, 0, sizeof(*regs));
	if (ret < 0)
		return ret;

	return user_regset_copyout_zero(&pos, &count, &kbuf, &ubuf,
					sizeof(*regs), -1);
}

/*
 * update the contents of the Blackfin userspace general registers
 */
static int genregs_set(struct task_struct *target,
		       const struct user_regset *regset,
		       unsigned int pos, unsigned int count,
		       const void *kbuf, const void __user *ubuf)
{
	struct pt_regs *regs = task_pt_regs(target);
	int ret;

	/* Don't let people set SYSCFG (it's at the end of pt_regs) */
	ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf,
				 regs, 0, PT_SYSCFG);
	if (ret < 0)
		return ret;

	/* This sucks ... */
	target->thread.usp = regs->usp;
	/* regs->retx = regs->pc; */

	return user_regset_copyin_ignore(&pos, &count, &kbuf, &ubuf,
					PT_SYSCFG, -1);
}

/*
 * Define the register sets available on the Blackfin under Linux
 */
enum bfin_regset {
	REGSET_GENERAL,
};

static const struct user_regset bfin_regsets[] = {
	[REGSET_GENERAL] = {
		.core_note_type = NT_PRSTATUS,
		.n              = sizeof(struct pt_regs) / sizeof(long),
		.size           = sizeof(long),
		.align          = sizeof(long),
		.get            = genregs_get,
		.set            = genregs_set,
	},
};

static const struct user_regset_view user_bfin_native_view = {
	.name      = "Blackfin",
	.e_machine = EM_BLACKFIN,
	.regsets   = bfin_regsets,
	.n         = ARRAY_SIZE(bfin_regsets),
};

const struct user_regset_view *task_user_regset_view(struct task_struct *task)
{
	return &user_bfin_native_view;
}

void ptrace_enable(struct task_struct *child)
void ptrace_enable(struct task_struct *child)
{
{
	struct pt_regs *regs = task_pt_regs(child);
	struct pt_regs *regs = task_pt_regs(child);
@@ -327,15 +391,18 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
		break;
		break;


	case PTRACE_GETREGS:
	case PTRACE_GETREGS:
		/* Get all gp regs from the child. */
		pr_debug("ptrace: PTRACE_GETREGS\n");
		ret = ptrace_getregs(child, datap);
		return copy_regset_to_user(child, &user_bfin_native_view,
		break;
					   REGSET_GENERAL,
					   0, sizeof(struct pt_regs),
					   (void __user *)data);


	case PTRACE_SETREGS:
	case PTRACE_SETREGS:
		printk(KERN_WARNING "ptrace: SETREGS: **** NOT IMPLEMENTED ***\n");
		pr_debug("ptrace: PTRACE_SETREGS\n");
		/* Set all gp regs in the child. */
		return copy_regset_from_user(child, &user_bfin_native_view,
		ret = 0;
					     REGSET_GENERAL,
		break;
					     0, sizeof(struct pt_regs),
					     (const void __user *)data);


	default:
	default:
		ret = ptrace_request(child, request, addr, data);
		ret = ptrace_request(child, request, addr, data);