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

Commit f2cb4777 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull ARC fixes from Vineet Gupta:
 - Fix for /proc/<pid>/maps "stack" vma annotation
 - sched stats not printing correct sleeping task PC
 - perf not reporting page faults

* tag 'arc-4.0-fixes-1' of git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc:
  ARC: Fix thread_saved_pc()
  ARC: Fix KSTK_ESP()
  ARC: perf: Enable generic software events
  ARC: Make arc_unwind_core accessible externally
parents 97754e3c 3240dd57
Loading
Loading
Loading
Loading
+7 −7
Original line number Diff line number Diff line
@@ -47,9 +47,6 @@ struct thread_struct {
/* Forward declaration, a strange C thing */
struct task_struct;

/* Return saved PC of a blocked thread  */
unsigned long thread_saved_pc(struct task_struct *t);

#define task_pt_regs(p) \
	((struct pt_regs *)(THREAD_SIZE + (void *)task_stack_page(p)) - 1)

@@ -72,18 +69,21 @@ unsigned long thread_saved_pc(struct task_struct *t);
#define release_segments(mm)        do { } while (0)

#define KSTK_EIP(tsk)   (task_pt_regs(tsk)->ret)
#define KSTK_ESP(tsk)   (task_pt_regs(tsk)->sp)

/*
 * Where abouts of Task's sp, fp, blink when it was last seen in kernel mode.
 * Look in process.c for details of kernel stack layout
 */
#define KSTK_ESP(tsk)   (tsk->thread.ksp)
#define TSK_K_ESP(tsk)		(tsk->thread.ksp)

#define KSTK_REG(tsk, off)	(*((unsigned int *)(KSTK_ESP(tsk) + \
#define TSK_K_REG(tsk, off)	(*((unsigned int *)(TSK_K_ESP(tsk) + \
					sizeof(struct callee_regs) + off)))

#define KSTK_BLINK(tsk) KSTK_REG(tsk, 4)
#define KSTK_FP(tsk)    KSTK_REG(tsk, 0)
#define TSK_K_BLINK(tsk)	TSK_K_REG(tsk, 4)
#define TSK_K_FP(tsk)		TSK_K_REG(tsk, 0)

#define thread_saved_pc(tsk)	TSK_K_BLINK(tsk)

extern void start_thread(struct pt_regs * regs, unsigned long pc,
			 unsigned long usp);
+37 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014-15 Synopsys, Inc. (www.synopsys.com)
 * Copyright (C) 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#ifndef __ASM_STACKTRACE_H
#define __ASM_STACKTRACE_H

#include <linux/sched.h>

/**
 * arc_unwind_core - Unwind the kernel mode stack for an execution context
 * @tsk:		NULL for current task, specific task otherwise
 * @regs:		pt_regs used to seed the unwinder {SP, FP, BLINK, PC}
 * 			If NULL, use pt_regs of @tsk (if !NULL) otherwise
 * 			use the current values of {SP, FP, BLINK, PC}
 * @consumer_fn:	Callback invoked for each frame unwound
 * 			Returns 0 to continue unwinding, -1 to stop
 * @arg:		Arg to callback
 *
 * Returns the address of first function in stack
 *
 * Semantics:
 *  - synchronous unwinding (e.g. dump_stack): @tsk  NULL, @regs  NULL
 *  - Asynchronous unwinding of sleeping task: @tsk !NULL, @regs  NULL
 *  - Asynchronous unwinding of intr/excp etc: @tsk !NULL, @regs !NULL
 */
notrace noinline unsigned int arc_unwind_core(
	struct task_struct *tsk, struct pt_regs *regs,
	int (*consumer_fn) (unsigned int, void *),
	void *arg);

#endif /* __ASM_STACKTRACE_H */
+0 −23
Original line number Diff line number Diff line
@@ -192,29 +192,6 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu)
	return 0;
}

/*
 * API: expected by schedular Code: If thread is sleeping where is that.
 * What is this good for? it will be always the scheduler or ret_from_fork.
 * So we hard code that anyways.
 */
unsigned long thread_saved_pc(struct task_struct *t)
{
	struct pt_regs *regs = task_pt_regs(t);
	unsigned long blink = 0;

	/*
	 * If the thread being queried for in not itself calling this, then it
	 * implies it is not executing, which in turn implies it is sleeping,
	 * which in turn implies it got switched OUT by the schedular.
	 * In that case, it's kernel mode blink can reliably retrieved as per
	 * the picture above (right above pt_regs).
	 */
	if (t != current && t->state != TASK_RUNNING)
		blink = *((unsigned int *)regs - 1);

	return blink;
}

int elf_check_arch(const struct elf32_hdr *x)
{
	unsigned int eflags;
+17 −4
Original line number Diff line number Diff line
@@ -43,6 +43,10 @@ static void seed_unwind_frame_info(struct task_struct *tsk,
				   struct pt_regs *regs,
				   struct unwind_frame_info *frame_info)
{
	/*
	 * synchronous unwinding (e.g. dump_stack)
	 *  - uses current values of SP and friends
	 */
	if (tsk == NULL && regs == NULL) {
		unsigned long fp, sp, blink, ret;
		frame_info->task = current;
@@ -61,12 +65,17 @@ static void seed_unwind_frame_info(struct task_struct *tsk,
		frame_info->regs.r63 = ret;
		frame_info->call_frame = 0;
	} else if (regs == NULL) {
		/*
		 * Asynchronous unwinding of sleeping task
		 *  - Gets SP etc from task's pt_regs (saved bottom of kernel
		 *    mode stack of task)
		 */

		frame_info->task = tsk;

		frame_info->regs.r27 = KSTK_FP(tsk);
		frame_info->regs.r28 = KSTK_ESP(tsk);
		frame_info->regs.r31 = KSTK_BLINK(tsk);
		frame_info->regs.r27 = TSK_K_FP(tsk);
		frame_info->regs.r28 = TSK_K_ESP(tsk);
		frame_info->regs.r31 = TSK_K_BLINK(tsk);
		frame_info->regs.r63 = (unsigned int)__switch_to;

		/* In the prologue of __switch_to, first FP is saved on stack
@@ -83,6 +92,10 @@ static void seed_unwind_frame_info(struct task_struct *tsk,
		frame_info->call_frame = 0;

	} else {
		/*
		 * Asynchronous unwinding of intr/exception
		 *  - Just uses the pt_regs passed
		 */
		frame_info->task = tsk;

		frame_info->regs.r27 = regs->fp;
@@ -95,7 +108,7 @@ static void seed_unwind_frame_info(struct task_struct *tsk,

#endif

static noinline unsigned int
notrace noinline unsigned int
arc_unwind_core(struct task_struct *tsk, struct pt_regs *regs,
		int (*consumer_fn) (unsigned int, void *), void *arg)
{
+2 −0
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@
 */

#include <linux/types.h>
#include <linux/perf_event.h>
#include <linux/ptrace.h>
#include <linux/uaccess.h>
#include <asm/disasm.h>
@@ -253,6 +254,7 @@ int misaligned_fixup(unsigned long address, struct pt_regs *regs,
		}
	}

	perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, address);
	return 0;

fault:
Loading