linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] ARM: add support for context tracking subsystem
@ 2013-03-21  0:01 Kevin Hilman
  2013-03-21  0:01 ` [PATCH 1/4] ARM: context tracking: add exception support Kevin Hilman
                   ` (3 more replies)
  0 siblings, 4 replies; 8+ messages in thread
From: Kevin Hilman @ 2013-03-21  0:01 UTC (permalink / raw)
  To: linux-arm-kernel

commit 91d1aa43 (context_tracking: New context tracking susbsystem)
generalized parts of the RCU userspace extended quiescent state into
the context tracking subsystem.  Context tracking is then used 
to implement adaptive tickless (a.k.a full nohz)

Mainline currently only includes x86 support for the context tracking
susbsystem and the goal of this series is to add ARM support, in order
to make adaptive tickless functional on ARM.

Depends on the prerequistes series: 
  [PATCH 0/3] ARM: context tracking support prerequisites
  http://marc.info/?l=linux-kernel&m=136382248131438&w=2

Both of which are combined on top of Frederic's 3.9-rc1-nohz1 branch
and available here:
git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux.git arm-nohz-v2/context-tracking

Using this, I tested adaptive tickless on a 2 CPU ARM SoC (OMAP4
Panda.)

Kevin Hilman (4):
  ARM: context tracking: add exception support
  ARM: context tracking: instrument system calls
  ARM: context tracking: handle post exception/syscall/IRQ work
  ARM: Kconfig: allow context tracking

 arch/arm/Kconfig                   |  1 +
 arch/arm/include/asm/thread_info.h |  4 +++-
 arch/arm/kernel/ptrace.c           | 11 +++++++++++
 arch/arm/kernel/signal.c           | 12 +++++++++---
 arch/arm/kernel/traps.c            | 18 +++++++++++++++++-
 arch/arm/mm/fault.c                | 32 +++++++++++++++++++++++++++-----
 6 files changed, 68 insertions(+), 10 deletions(-)

-- 
1.8.2

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/4] ARM: context tracking: add exception support
  2013-03-21  0:01 [PATCH 0/4] ARM: add support for context tracking subsystem Kevin Hilman
@ 2013-03-21  0:01 ` Kevin Hilman
  2013-03-21 21:49   ` Russell King - ARM Linux
  2013-03-21  0:01 ` [PATCH 2/4] ARM: context tracking: instrument system calls Kevin Hilman
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 8+ messages in thread
From: Kevin Hilman @ 2013-03-21  0:01 UTC (permalink / raw)
  To: linux-arm-kernel

Add ARM support for the context tracking subsystem by instrumenting
exception entry/exit points.

Special thanks to Mats Liljegren for testing, collaboration and adding
support for exceptions/faults that were missing in early test versions.

Cc: Mats Liljegren <mats.liljegren@enea.com>
Signed-off-by: Kevin Hilman <khilman@linaro.org>
---
 arch/arm/kernel/traps.c | 18 +++++++++++++++++-
 arch/arm/mm/fault.c     | 32 +++++++++++++++++++++++++++-----
 2 files changed, 44 insertions(+), 6 deletions(-)

diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 1c08911..0e5f9fa 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -25,6 +25,7 @@
 #include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/sched.h>
+#include <linux/context_tracking.h>
 
 #include <linux/atomic.h>
 #include <asm/cacheflush.h>
@@ -405,7 +406,9 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
 	unsigned int instr;
 	siginfo_t info;
 	void __user *pc;
+	enum ctx_state prev_state;
 
+	prev_state = exception_enter();
 	pc = (void __user *)instruction_pointer(regs);
 
 	if (processor_mode(regs) == SVC_MODE) {
@@ -433,8 +436,10 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
 		goto die_sig;
 	}
 
-	if (call_undef_hook(regs, instr) == 0)
+	if (call_undef_hook(regs, instr) == 0) {
+		exception_exit(prev_state);
 		return;
+	}
 
 die_sig:
 #ifdef CONFIG_DEBUG_USER
@@ -451,12 +456,17 @@ die_sig:
 	info.si_addr  = pc;
 
 	arm_notify_die("Oops - undefined instruction", regs, &info, 0, 6);
+	exception_exit(prev_state);
 }
 
 asmlinkage void do_unexp_fiq (struct pt_regs *regs)
 {
+	enum ctx_state prev_state;
+
+	prev_state = exception_enter();
 	printk("Hmm.  Unexpected FIQ received, but trying to continue\n");
 	printk("You may have a hardware problem...\n");
+	exception_exit(prev_state);
 }
 
 /*
@@ -467,6 +477,9 @@ asmlinkage void do_unexp_fiq (struct pt_regs *regs)
  */
 asmlinkage void bad_mode(struct pt_regs *regs, int reason)
 {
+	enum ctx_state prev_state;
+
+	prev_state = exception_enter();
 	console_verbose();
 
 	printk(KERN_CRIT "Bad mode in %s handler detected\n", handler[reason]);
@@ -746,7 +759,9 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs)
 {
 	unsigned long addr = instruction_pointer(regs);
 	siginfo_t info;
+	enum ctx_state prev_state;
 
+	prev_state = exception_enter();
 #ifdef CONFIG_DEBUG_USER
 	if (user_debug & UDBG_BADABORT) {
 		printk(KERN_ERR "[%d] %s: bad data abort: code %d instr 0x%08lx\n",
@@ -762,6 +777,7 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs)
 	info.si_addr  = (void __user *)addr;
 
 	arm_notify_die("unknown data abort code", regs, &info, instr, 0);
+	exception_exit(prev_state);
 }
 
 void __readwrite_bug(const char *fn)
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index 5dbf13f..759b70d 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -19,6 +19,7 @@
 #include <linux/sched.h>
 #include <linux/highmem.h>
 #include <linux/perf_event.h>
+#include <linux/context_tracking.h>
 
 #include <asm/exception.h>
 #include <asm/pgtable.h>
@@ -424,9 +425,15 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
 	pgd_t *pgd, *pgd_k;
 	pud_t *pud, *pud_k;
 	pmd_t *pmd, *pmd_k;
-
-	if (addr < TASK_SIZE)
-		return do_page_fault(addr, fsr, regs);
+	enum ctx_state prev_state;
+
+	prev_state = exception_enter();
+	if (addr < TASK_SIZE) {
+		int ret;
+		ret = do_page_fault(addr, fsr, regs);
+		exception_exit(prev_state);
+		return ret;
+	}
 
 	if (user_mode(regs))
 		goto bad_area;
@@ -472,10 +479,12 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
 		goto bad_area;
 
 	copy_pmd(pmd, pmd_k);
+	exception_exit(prev_state);
 	return 0;
 
 bad_area:
 	do_bad_area(addr, fsr, regs);
+	exception_exit(prev_state);
 	return 0;
 }
 #else					/* CONFIG_MMU */
@@ -494,7 +503,12 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
 static int
 do_sect_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 {
+	enum ctx_state prev_state;
+
+	prev_state = exception_enter();
 	do_bad_area(addr, fsr, regs);
+	exception_exit(prev_state);
+
 	return 0;
 }
 
@@ -542,9 +556,11 @@ do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 {
 	const struct fsr_info *inf = fsr_info + fsr_fs(fsr);
 	struct siginfo info;
+	enum ctx_state prev_state;
 
+	prev_state = exception_enter();
 	if (!inf->fn(addr, fsr & ~FSR_LNX_PF, regs))
-		return;
+		goto out;
 
 	printk(KERN_ALERT "Unhandled fault: %s (0x%03x) at 0x%08lx\n",
 		inf->name, fsr, addr);
@@ -554,6 +570,8 @@ do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 	info.si_code  = inf->code;
 	info.si_addr  = (void __user *)addr;
 	arm_notify_die("", regs, &info, fsr, 0);
+out:
+	exception_exit(prev_state);
 }
 
 void __init
@@ -574,9 +592,11 @@ do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs)
 {
 	const struct fsr_info *inf = ifsr_info + fsr_fs(ifsr);
 	struct siginfo info;
+	enum ctx_state prev_state;
 
+	prev_state = exception_enter();
 	if (!inf->fn(addr, ifsr | FSR_LNX_PF, regs))
-		return;
+		goto out;
 
 	printk(KERN_ALERT "Unhandled prefetch abort: %s (0x%03x) at 0x%08lx\n",
 		inf->name, ifsr, addr);
@@ -586,6 +606,8 @@ do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs)
 	info.si_code  = inf->code;
 	info.si_addr  = (void __user *)addr;
 	arm_notify_die("", regs, &info, ifsr, 0);
+out:
+	exception_exit(prev_state);
 }
 
 #ifndef CONFIG_ARM_LPAE
-- 
1.8.2

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/4] ARM: context tracking: instrument system calls
  2013-03-21  0:01 [PATCH 0/4] ARM: add support for context tracking subsystem Kevin Hilman
  2013-03-21  0:01 ` [PATCH 1/4] ARM: context tracking: add exception support Kevin Hilman
@ 2013-03-21  0:01 ` Kevin Hilman
  2013-03-21  0:02 ` [PATCH 3/4] ARM: context tracking: handle post exception/syscall/IRQ work Kevin Hilman
  2013-03-21  0:02 ` [PATCH 4/4] ARM: Kconfig: allow context tracking Kevin Hilman
  3 siblings, 0 replies; 8+ messages in thread
From: Kevin Hilman @ 2013-03-21  0:01 UTC (permalink / raw)
  To: linux-arm-kernel

When context tracking (TIF_NOHZ), force the syscall slow path by
adding _TIF_NOHZ to _TIF_SYSCALL_WORK.  Use the syscall trace
enter/exit paths to do the context tracking.  This corresponds to
commit bf5a3c13 (x86: Syscall hooks for userspace RCU extended QS.)

Also cover the special case in syscall_trace_exit() based on commit
2c5594df (rcu: Fix unrecovered RCU user mode in syscall_trace_leave())
for x86.

Special thanks to Mats Liljegren for collaboration and additional
testing.

Cc: Mats Liljegren <mats.liljegren@enea.com>
Signed-off-by: Kevin Hilman <khilman@linaro.org>
---
 arch/arm/include/asm/thread_info.h |  4 +++-
 arch/arm/kernel/ptrace.c           | 11 +++++++++++
 2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
index cddda1f..e4c7e21 100644
--- a/arch/arm/include/asm/thread_info.h
+++ b/arch/arm/include/asm/thread_info.h
@@ -152,6 +152,7 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
 #define TIF_SYSCALL_AUDIT	9
 #define TIF_SYSCALL_TRACEPOINT	10
 #define TIF_SECCOMP		11	/* seccomp syscall filtering active */
+#define TIF_NOHZ		12	/* in adaptive nohz mode */
 #define TIF_USING_IWMMXT	17
 #define TIF_MEMDIE		18	/* is terminating due to OOM killer */
 #define TIF_RESTORE_SIGMASK	20
@@ -165,10 +166,11 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
 #define _TIF_SYSCALL_TRACEPOINT	(1 << TIF_SYSCALL_TRACEPOINT)
 #define _TIF_SECCOMP		(1 << TIF_SECCOMP)
 #define _TIF_USING_IWMMXT	(1 << TIF_USING_IWMMXT)
+#define _TIF_NOHZ		(1 << TIF_NOHZ)
 
 /* Checks for any syscall work in entry-common.S */
 #define _TIF_SYSCALL_WORK (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \
-			   _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP)
+			   _TIF_SYSCALL_TRACEPOINT | _TIF_SECCOMP | _TIF_NOHZ)
 
 /*
  * Change these and you break ASM code in entry-common.S
diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c
index 03deeff..3ab329a 100644
--- a/arch/arm/kernel/ptrace.c
+++ b/arch/arm/kernel/ptrace.c
@@ -26,6 +26,7 @@
 #include <linux/audit.h>
 #include <linux/tracehook.h>
 #include <linux/unistd.h>
+#include <linux/context_tracking.h>
 
 #include <asm/pgtable.h>
 #include <asm/traps.h>
@@ -941,6 +942,8 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs, int scno)
 {
 	current_thread_info()->syscall = scno;
 
+	user_exit();
+
 	/* Do the secure computing check first; failures should be fast. */
 	if (secure_computing(scno) == -1)
 		return -1;
@@ -960,6 +963,12 @@ asmlinkage int syscall_trace_enter(struct pt_regs *regs, int scno)
 asmlinkage void syscall_trace_exit(struct pt_regs *regs)
 {
 	/*
+	 * We may come here right after calling do_work_pending() in
+	 * which case we can be in context_tracking user mode.
+	 */
+	user_exit();
+
+	/*
 	 * Audit the syscall before anything else, as a debugger may
 	 * come in and change the current registers.
 	 */
@@ -976,4 +985,6 @@ asmlinkage void syscall_trace_exit(struct pt_regs *regs)
 
 	if (test_thread_flag(TIF_SYSCALL_TRACE))
 		tracehook_report_syscall(regs, PTRACE_SYSCALL_EXIT);
+
+	user_enter();
 }
-- 
1.8.2

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 3/4] ARM: context tracking: handle post exception/syscall/IRQ work
  2013-03-21  0:01 [PATCH 0/4] ARM: add support for context tracking subsystem Kevin Hilman
  2013-03-21  0:01 ` [PATCH 1/4] ARM: context tracking: add exception support Kevin Hilman
  2013-03-21  0:01 ` [PATCH 2/4] ARM: context tracking: instrument system calls Kevin Hilman
@ 2013-03-21  0:02 ` Kevin Hilman
  2013-03-21  0:02 ` [PATCH 4/4] ARM: Kconfig: allow context tracking Kevin Hilman
  3 siblings, 0 replies; 8+ messages in thread
From: Kevin Hilman @ 2013-03-21  0:02 UTC (permalink / raw)
  To: linux-arm-kernel

do_work_pending() may be called on IRQ, exception or syscall exit (for
reschedule, signal handling, etc.) , but user_enter() may have already
been called (e.g. by syscall return path.)

Since do_work_pending() is still in kernel mode, keep context_tracker
up to date by using user_exit/user_enter.

Based on commit edf55fda35c7dc7f2d9241c3abaddaf759b457c6 (x86: Exit
RCU extended QS on notify resume)

Signed-off-by: Kevin Hilman <khilman@linaro.org>
---
 arch/arm/kernel/signal.c | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 296786b..42514fd 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -12,6 +12,7 @@
 #include <linux/personality.h>
 #include <linux/uaccess.h>
 #include <linux/tracehook.h>
+#include <linux/context_tracking.h>
 
 #include <asm/elf.h>
 #include <asm/cacheflush.h>
@@ -575,12 +576,15 @@ static int do_signal(struct pt_regs *regs, int syscall)
 asmlinkage int
 do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall)
 {
+	int retval = 0;
+
+	user_exit();
 	do {
 		if (likely(thread_flags & _TIF_NEED_RESCHED)) {
 			schedule();
 		} else {
 			if (unlikely(!user_mode(regs)))
-				return 0;
+				break;
 			local_irq_enable();
 			if (thread_flags & _TIF_SIGPENDING) {
 				int restart = do_signal(regs, syscall);
@@ -590,7 +594,8 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall)
 					 * Deal with it without leaving
 					 * the kernel space.
 					 */
-					return restart;
+					retval = restart;
+					break;
 				}
 				syscall = 0;
 			} else {
@@ -601,5 +606,6 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall)
 		local_irq_disable();
 		thread_flags = current_thread_info()->flags;
 	} while (thread_flags & _TIF_WORK_MASK);
-	return 0;
+	user_enter();
+	return retval;
 }
-- 
1.8.2

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 4/4] ARM: Kconfig: allow context tracking
  2013-03-21  0:01 [PATCH 0/4] ARM: add support for context tracking subsystem Kevin Hilman
                   ` (2 preceding siblings ...)
  2013-03-21  0:02 ` [PATCH 3/4] ARM: context tracking: handle post exception/syscall/IRQ work Kevin Hilman
@ 2013-03-21  0:02 ` Kevin Hilman
  3 siblings, 0 replies; 8+ messages in thread
From: Kevin Hilman @ 2013-03-21  0:02 UTC (permalink / raw)
  To: linux-arm-kernel

Signed-off-by: Kevin Hilman <khilman@linaro.org>
---
 arch/arm/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 9473d55..4028fb2 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -60,6 +60,7 @@ config ARM
 	select OLD_SIGSUSPEND3
 	select OLD_SIGACTION
 	select HAVE_VIRT_CPU_ACCOUNTING
+	select HAVE_CONTEXT_TRACKING
 	help
 	  The ARM series is a line of low-power-consumption RISC chip designs
 	  licensed by ARM Ltd and targeted at embedded applications and
-- 
1.8.2

^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 1/4] ARM: context tracking: add exception support
  2013-03-21  0:01 ` [PATCH 1/4] ARM: context tracking: add exception support Kevin Hilman
@ 2013-03-21 21:49   ` Russell King - ARM Linux
  2013-03-22  0:33     ` Kevin Hilman
  2013-03-26  0:28     ` Kevin Hilman
  0 siblings, 2 replies; 8+ messages in thread
From: Russell King - ARM Linux @ 2013-03-21 21:49 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Mar 20, 2013 at 05:01:58PM -0700, Kevin Hilman wrote:
> Add ARM support for the context tracking subsystem by instrumenting
> exception entry/exit points.
> 
> Special thanks to Mats Liljegren for testing, collaboration and adding
> support for exceptions/faults that were missing in early test versions.

Not sure all of these are a good idea or are correct...

> @@ -405,7 +406,9 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
>  	unsigned int instr;
>  	siginfo_t info;
>  	void __user *pc;
> +	enum ctx_state prev_state;
>  
> +	prev_state = exception_enter();
>  	pc = (void __user *)instruction_pointer(regs);
>  
>  	if (processor_mode(regs) == SVC_MODE) {
> @@ -433,8 +436,10 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
>  		goto die_sig;
>  	}
>  
> -	if (call_undef_hook(regs, instr) == 0)
> +	if (call_undef_hook(regs, instr) == 0) {
> +		exception_exit(prev_state);
>  		return;
> +	}
>  
>  die_sig:
>  #ifdef CONFIG_DEBUG_USER
> @@ -451,12 +456,17 @@ die_sig:
>  	info.si_addr  = pc;
>  
>  	arm_notify_die("Oops - undefined instruction", regs, &info, 0, 6);
> +	exception_exit(prev_state);

So, FP emulation and VFP support happens via a separate path.  Does this
also need to be instrumented?

>  }
>  
>  asmlinkage void do_unexp_fiq (struct pt_regs *regs)
>  {
> +	enum ctx_state prev_state;
> +
> +	prev_state = exception_enter();
>  	printk("Hmm.  Unexpected FIQ received, but trying to continue\n");
>  	printk("You may have a hardware problem...\n");
> +	exception_exit(prev_state);

Not a good idea.  If we get here chances are things are really broken.

>  }
>  
>  /*
> @@ -467,6 +477,9 @@ asmlinkage void do_unexp_fiq (struct pt_regs *regs)
>   */
>  asmlinkage void bad_mode(struct pt_regs *regs, int reason)
>  {
> +	enum ctx_state prev_state;
> +
> +	prev_state = exception_enter();
>  	console_verbose();
>  
>  	printk(KERN_CRIT "Bad mode in %s handler detected\n", handler[reason]);

Same here.  If we get here, we're probably about to die a horrid death.

> @@ -746,7 +759,9 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs)
>  {
>  	unsigned long addr = instruction_pointer(regs);
>  	siginfo_t info;
> +	enum ctx_state prev_state;
>  
> +	prev_state = exception_enter();
>  #ifdef CONFIG_DEBUG_USER
>  	if (user_debug & UDBG_BADABORT) {
>  		printk(KERN_ERR "[%d] %s: bad data abort: code %d instr 0x%08lx\n",
> @@ -762,6 +777,7 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs)
>  	info.si_addr  = (void __user *)addr;
>  
>  	arm_notify_die("unknown data abort code", regs, &info, instr, 0);
> +	exception_exit(prev_state);
>  }
>  
>  void __readwrite_bug(const char *fn)
> diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
> index 5dbf13f..759b70d 100644
> --- a/arch/arm/mm/fault.c
> +++ b/arch/arm/mm/fault.c
> @@ -19,6 +19,7 @@
>  #include <linux/sched.h>
>  #include <linux/highmem.h>
>  #include <linux/perf_event.h>
> +#include <linux/context_tracking.h>
>  
>  #include <asm/exception.h>
>  #include <asm/pgtable.h>
> @@ -424,9 +425,15 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
>  	pgd_t *pgd, *pgd_k;
>  	pud_t *pud, *pud_k;
>  	pmd_t *pmd, *pmd_k;
> -
> -	if (addr < TASK_SIZE)
> -		return do_page_fault(addr, fsr, regs);
> +	enum ctx_state prev_state;
> +
> +	prev_state = exception_enter();
> +	if (addr < TASK_SIZE) {
> +		int ret;
> +		ret = do_page_fault(addr, fsr, regs);
> +		exception_exit(prev_state);
> +		return ret;
> +	}
>  
>  	if (user_mode(regs))
>  		goto bad_area;
> @@ -472,10 +479,12 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
>  		goto bad_area;
>  
>  	copy_pmd(pmd, pmd_k);
> +	exception_exit(prev_state);
>  	return 0;
>  
>  bad_area:
>  	do_bad_area(addr, fsr, regs);
> +	exception_exit(prev_state);
>  	return 0;
>  }
>  #else					/* CONFIG_MMU */
> @@ -494,7 +503,12 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
>  static int
>  do_sect_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
>  {
> +	enum ctx_state prev_state;
> +
> +	prev_state = exception_enter();
>  	do_bad_area(addr, fsr, regs);
> +	exception_exit(prev_state);
> +
>  	return 0;
>  }
>  
> @@ -542,9 +556,11 @@ do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
>  {
>  	const struct fsr_info *inf = fsr_info + fsr_fs(fsr);
>  	struct siginfo info;
> +	enum ctx_state prev_state;
>  
> +	prev_state = exception_enter();
>  	if (!inf->fn(addr, fsr & ~FSR_LNX_PF, regs))
> -		return;
> +		goto out;
>  
>  	printk(KERN_ALERT "Unhandled fault: %s (0x%03x) at 0x%08lx\n",
>  		inf->name, fsr, addr);
> @@ -554,6 +570,8 @@ do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
>  	info.si_code  = inf->code;
>  	info.si_addr  = (void __user *)addr;
>  	arm_notify_die("", regs, &info, fsr, 0);
> +out:
> +	exception_exit(prev_state);
>  }
>  
>  void __init
> @@ -574,9 +592,11 @@ do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs)
>  {
>  	const struct fsr_info *inf = ifsr_info + fsr_fs(ifsr);
>  	struct siginfo info;
> +	enum ctx_state prev_state;
>  
> +	prev_state = exception_enter();
>  	if (!inf->fn(addr, ifsr | FSR_LNX_PF, regs))
> -		return;
> +		goto out;
>  
>  	printk(KERN_ALERT "Unhandled prefetch abort: %s (0x%03x) at 0x%08lx\n",
>  		inf->name, ifsr, addr);
> @@ -586,6 +606,8 @@ do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs)
>  	info.si_code  = inf->code;
>  	info.si_addr  = (void __user *)addr;
>  	arm_notify_die("", regs, &info, ifsr, 0);
> +out:
> +	exception_exit(prev_state);
>  }
>  
>  #ifndef CONFIG_ARM_LPAE

What is the reason for putting all this in the individual functions
and not in the prefetch/data abort handlers -
do_PrefetchAbort()/do_DataAbort()?

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/4] ARM: context tracking: add exception support
  2013-03-21 21:49   ` Russell King - ARM Linux
@ 2013-03-22  0:33     ` Kevin Hilman
  2013-03-26  0:28     ` Kevin Hilman
  1 sibling, 0 replies; 8+ messages in thread
From: Kevin Hilman @ 2013-03-22  0:33 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Russell,

Russell King - ARM Linux <linux@arm.linux.org.uk> writes:

> On Wed, Mar 20, 2013 at 05:01:58PM -0700, Kevin Hilman wrote:
>> Add ARM support for the context tracking subsystem by instrumenting
>> exception entry/exit points.
>> 
>> Special thanks to Mats Liljegren for testing, collaboration and adding
>> support for exceptions/faults that were missing in early test versions.
>
> Not sure all of these are a good idea or are correct...

Thanks for the review.

>> @@ -405,7 +406,9 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
>>  	unsigned int instr;
>>  	siginfo_t info;
>>  	void __user *pc;
>> +	enum ctx_state prev_state;
>>  
>> +	prev_state = exception_enter();
>>  	pc = (void __user *)instruction_pointer(regs);
>>  
>>  	if (processor_mode(regs) == SVC_MODE) {
>> @@ -433,8 +436,10 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
>>  		goto die_sig;
>>  	}
>>  
>> -	if (call_undef_hook(regs, instr) == 0)
>> +	if (call_undef_hook(regs, instr) == 0) {
>> +		exception_exit(prev_state);
>>  		return;
>> +	}
>>  
>>  die_sig:
>>  #ifdef CONFIG_DEBUG_USER
>> @@ -451,12 +456,17 @@ die_sig:
>>  	info.si_addr  = pc;
>>  
>>  	arm_notify_die("Oops - undefined instruction", regs, &info, 0, 6);
>> +	exception_exit(prev_state);
>
> So, FP emulation and VFP support happens via a separate path.  Does this
> also need to be instrumented?

Yes, those will need to be instrumented too. I haven't looked at the
floating point stuff (and am obviously not testing any FP userspace
currently.)  Thanks for the reminder, I'll look at that next (feel free
to point me in the right direction if you have suggestions about where
to best instrument those.  I've not yet looked closely at how either are
handled.)

>>  }
>>  
>>  asmlinkage void do_unexp_fiq (struct pt_regs *regs)
>>  {
>> +	enum ctx_state prev_state;
>> +
>> +	prev_state = exception_enter();
>>  	printk("Hmm.  Unexpected FIQ received, but trying to continue\n");
>>  	printk("You may have a hardware problem...\n");
>> +	exception_exit(prev_state);
>
> Not a good idea.  If we get here chances are things are really broken.
>
>>  }
>>  
>>  /*
>> @@ -467,6 +477,9 @@ asmlinkage void do_unexp_fiq (struct pt_regs *regs)
>>   */
>>  asmlinkage void bad_mode(struct pt_regs *regs, int reason)
>>  {
>> +	enum ctx_state prev_state;
>> +
>> +	prev_state = exception_enter();
>>  	console_verbose();
>>  
>>  	printk(KERN_CRIT "Bad mode in %s handler detected\n", handler[reason]);
>
> Same here.  If we get here, we're probably about to die a horrid death.

Yeah, I was wondering if I should bother with these "about to die"
scenarios.  I'll drop them since they may cause more problems than
they're worth.

>> @@ -746,7 +759,9 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs)
>>  {
>>  	unsigned long addr = instruction_pointer(regs);
>>  	siginfo_t info;
>> +	enum ctx_state prev_state;
>>  
>> +	prev_state = exception_enter();
>>  #ifdef CONFIG_DEBUG_USER
>>  	if (user_debug & UDBG_BADABORT) {
>>  		printk(KERN_ERR "[%d] %s: bad data abort: code %d instr 0x%08lx\n",
>> @@ -762,6 +777,7 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs)
>>  	info.si_addr  = (void __user *)addr;
>>  
>>  	arm_notify_die("unknown data abort code", regs, &info, instr, 0);
>> +	exception_exit(prev_state);
>>  }
>>  
>>  void __readwrite_bug(const char *fn)
>> diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
>> index 5dbf13f..759b70d 100644
>> --- a/arch/arm/mm/fault.c
>> +++ b/arch/arm/mm/fault.c
>> @@ -19,6 +19,7 @@
>>  #include <linux/sched.h>
>>  #include <linux/highmem.h>
>>  #include <linux/perf_event.h>
>> +#include <linux/context_tracking.h>
>>  
>>  #include <asm/exception.h>
>>  #include <asm/pgtable.h>
>> @@ -424,9 +425,15 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
>>  	pgd_t *pgd, *pgd_k;
>>  	pud_t *pud, *pud_k;
>>  	pmd_t *pmd, *pmd_k;
>> -
>> -	if (addr < TASK_SIZE)
>> -		return do_page_fault(addr, fsr, regs);
>> +	enum ctx_state prev_state;
>> +
>> +	prev_state = exception_enter();
>> +	if (addr < TASK_SIZE) {
>> +		int ret;
>> +		ret = do_page_fault(addr, fsr, regs);
>> +		exception_exit(prev_state);
>> +		return ret;
>> +	}
>>  
>>  	if (user_mode(regs))
>>  		goto bad_area;
>> @@ -472,10 +479,12 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
>>  		goto bad_area;
>>  
>>  	copy_pmd(pmd, pmd_k);
>> +	exception_exit(prev_state);
>>  	return 0;
>>  
>>  bad_area:
>>  	do_bad_area(addr, fsr, regs);
>> +	exception_exit(prev_state);
>>  	return 0;
>>  }
>>  #else					/* CONFIG_MMU */
>> @@ -494,7 +503,12 @@ do_translation_fault(unsigned long addr, unsigned int fsr,
>>  static int
>>  do_sect_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
>>  {
>> +	enum ctx_state prev_state;
>> +
>> +	prev_state = exception_enter();
>>  	do_bad_area(addr, fsr, regs);
>> +	exception_exit(prev_state);
>> +
>>  	return 0;
>>  }
>>  
>> @@ -542,9 +556,11 @@ do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
>>  {
>>  	const struct fsr_info *inf = fsr_info + fsr_fs(fsr);
>>  	struct siginfo info;
>> +	enum ctx_state prev_state;
>>  
>> +	prev_state = exception_enter();
>>  	if (!inf->fn(addr, fsr & ~FSR_LNX_PF, regs))
>> -		return;
>> +		goto out;
>>  
>>  	printk(KERN_ALERT "Unhandled fault: %s (0x%03x) at 0x%08lx\n",
>>  		inf->name, fsr, addr);
>> @@ -554,6 +570,8 @@ do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
>>  	info.si_code  = inf->code;
>>  	info.si_addr  = (void __user *)addr;
>>  	arm_notify_die("", regs, &info, fsr, 0);
>> +out:
>> +	exception_exit(prev_state);
>>  }
>>  
>>  void __init
>> @@ -574,9 +592,11 @@ do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs)
>>  {
>>  	const struct fsr_info *inf = ifsr_info + fsr_fs(ifsr);
>>  	struct siginfo info;
>> +	enum ctx_state prev_state;
>>  
>> +	prev_state = exception_enter();
>>  	if (!inf->fn(addr, ifsr | FSR_LNX_PF, regs))
>> -		return;
>> +		goto out;
>>  
>>  	printk(KERN_ALERT "Unhandled prefetch abort: %s (0x%03x) at 0x%08lx\n",
>>  		inf->name, ifsr, addr);
>> @@ -586,6 +606,8 @@ do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs)
>>  	info.si_code  = inf->code;
>>  	info.si_addr  = (void __user *)addr;
>>  	arm_notify_die("", regs, &info, ifsr, 0);
>> +out:
>> +	exception_exit(prev_state);
>>  }
>>  
>>  #ifndef CONFIG_ARM_LPAE
>
> What is the reason for putting all this in the individual functions
> and not in the prefetch/data abort handlers -
> do_PrefetchAbort()/do_DataAbort()?

Ugh, I instrumented the main prefetch/data abort handlers but then added
in some of the individual functions.  I'll drop all the individual ones
that go through the fsr table anyways.  Thanks for catching that.

Kevin

^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/4] ARM: context tracking: add exception support
  2013-03-21 21:49   ` Russell King - ARM Linux
  2013-03-22  0:33     ` Kevin Hilman
@ 2013-03-26  0:28     ` Kevin Hilman
  1 sibling, 0 replies; 8+ messages in thread
From: Kevin Hilman @ 2013-03-26  0:28 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Russell,

Russell King - ARM Linux <linux@arm.linux.org.uk> writes:

> On Wed, Mar 20, 2013 at 05:01:58PM -0700, Kevin Hilman wrote:
>> Add ARM support for the context tracking subsystem by instrumenting
>> exception entry/exit points.
>> 
>> Special thanks to Mats Liljegren for testing, collaboration and adding
>> support for exceptions/faults that were missing in early test versions.

[...]

>> @@ -405,7 +406,9 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
>>  	unsigned int instr;
>>  	siginfo_t info;
>>  	void __user *pc;
>> +	enum ctx_state prev_state;
>>  
>> +	prev_state = exception_enter();
>>  	pc = (void __user *)instruction_pointer(regs);
>>  
>>  	if (processor_mode(regs) == SVC_MODE) {
>> @@ -433,8 +436,10 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
>>  		goto die_sig;
>>  	}
>>  
>> -	if (call_undef_hook(regs, instr) == 0)
>> +	if (call_undef_hook(regs, instr) == 0) {
>> +		exception_exit(prev_state);
>>  		return;
>> +	}
>>  
>>  die_sig:
>>  #ifdef CONFIG_DEBUG_USER
>> @@ -451,12 +456,17 @@ die_sig:
>>  	info.si_addr  = pc;
>>  
>>  	arm_notify_die("Oops - undefined instruction", regs, &info, 0, 6);
>> +	exception_exit(prev_state);
>
> So, FP emulation and VFP support happens via a separate path.  Does this
> also need to be instrumented?

Looking a little closer at how FP/VFP support are handled along with the
rest of the exceptions, I wondered if it might be simpler to do
something like the patch below.  It instruments the assembly directly
using the existing usr_entry macro, and the ret_to_user path.

Doing that would replace instrumenting the various handlers
(do_DataAbort/do_PrefetchAbort), and would handle the FP emulation VFP
support as well.

If this looks OK, I can probably rework the syscall support as well.
This approach covers the slow syscall return path already.  Instead of
forcing the slowpath on all syscalls, I would just need to instrument
the syscall entry and fast syscall return.

Kevin


diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 0f82098..050472c 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -396,6 +396,9 @@ ENDPROC(__pabt_svc)
 #ifdef CONFIG_IRQSOFF_TRACER
 	bl	trace_hardirqs_off
 #endif
+#ifdef CONFIG_CONTEXT_TRACKING
+	bl	user_exit
+#endif	
 	.endm
 
 	.macro	kuser_cmpxchg_check
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S
index 3248cde..3bef99b 100644
--- a/arch/arm/kernel/entry-common.S
+++ b/arch/arm/kernel/entry-common.S
@@ -74,6 +74,9 @@ no_work_pending:
 #if defined(CONFIG_IRQSOFF_TRACER)
 	asm_trace_hardirqs_on
 #endif
+#if defined(CONFIG_CONTEXT_TRACKING)
+	bl user_enter
+#endif	
 	/* perform architecture specific actions before user return */
 	arch_ret_to_user r1, lr

^ permalink raw reply related	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2013-03-26  0:28 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-03-21  0:01 [PATCH 0/4] ARM: add support for context tracking subsystem Kevin Hilman
2013-03-21  0:01 ` [PATCH 1/4] ARM: context tracking: add exception support Kevin Hilman
2013-03-21 21:49   ` Russell King - ARM Linux
2013-03-22  0:33     ` Kevin Hilman
2013-03-26  0:28     ` Kevin Hilman
2013-03-21  0:01 ` [PATCH 2/4] ARM: context tracking: instrument system calls Kevin Hilman
2013-03-21  0:02 ` [PATCH 3/4] ARM: context tracking: handle post exception/syscall/IRQ work Kevin Hilman
2013-03-21  0:02 ` [PATCH 4/4] ARM: Kconfig: allow context tracking Kevin Hilman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).