Skip to content

Commit

Permalink
FRV: Fix the new-style kernel_thread() stuff
Browse files Browse the repository at this point in the history
The kernel_thread() changes for FRV don't work, and FRV fails to boot,
starting with:

	commit 02ce496
	Author: Al Viro <viro@zeniv.linux.org.uk>
	Date:   Tue Sep 18 22:18:51 2012 -0400
	Subject: frv: split ret_from_fork, simplify kernel_thread() a lot

The problem is that the userspace registers are completely cleared when a
kernel thread is created and all subsequent user threads are then copied from
that.  Unfortunately, however, the TBR and PSR registers are restored from the
pt_regs and the values they should be set to are clobbered by the memset.

Instead, copy across the old user registers as normal, and then merely alter
GR8 and GR9 in it if we're going to execute a kernel thread.

Signed-off-by: David Howells <dhowells@redhat.com>
  • Loading branch information
David Howells committed Nov 2, 2012
1 parent 1ee6f56 commit e7aa51b
Showing 1 changed file with 3 additions and 2 deletions.
5 changes: 3 additions & 2 deletions arch/frv/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,9 @@ int copy_thread(unsigned long clone_flags,
childregs = (struct pt_regs *)
(task_stack_page(p) + THREAD_SIZE - FRV_FRAME0_SIZE);

/* set up the userspace frame (the only place that the USP is stored) */
*childregs = *__kernel_frame0_ptr;

p->set_child_tid = p->clear_child_tid = NULL;

p->thread.frame = childregs;
Expand All @@ -191,10 +194,8 @@ int copy_thread(unsigned long clone_flags,
p->thread.frame0 = childregs;

if (unlikely(!regs)) {
memset(childregs, 0, sizeof(struct pt_regs));
childregs->gr9 = usp; /* function */
childregs->gr8 = arg;
childregs->psr = PSR_S;
p->thread.pc = (unsigned long) ret_from_kernel_thread;
save_user_regs(p->thread.user);
return 0;
Expand Down

0 comments on commit e7aa51b

Please sign in to comment.