Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* iommu/arm-smmu: Regression (sleeping function called from invalid context)
From: Will Deacon @ 2014-02-03 16:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140131095809.GO13543@alberich>

Hi Andreas,

On Fri, Jan 31, 2014 at 09:58:09AM +0000, Andreas Herrmann wrote:
> On Fri, Jan 31, 2014 at 09:46:23AM +0100, Andreas Herrmann wrote:
> > On Fri, Jan 31, 2014 at 12:55:52AM +0100, Andreas Herrmann wrote:
> > > Hi Will,
> > > 
> > > Seems that commit a44a9791e778d9ccda50d5534028ed4057a9a45b
> > > (iommu/arm-smmu: use mutex instead of spinlock for locking page tables)
> > > introduced a regression.
> > > 
> > > At least I've hit
> > > 
> > >   BUG: scheduling while atomic: ksoftirqd/0/3/0x00000100
> > >...
> > 
> > >   BUG: sleeping function called from invalid context at mm/page_alloc.c:2679
> > >   in_atomic(): 1, irqs_disabled(): 128, pid: 0, name: swapper/0
> > >   CPU: 0 PID: 0 Comm: swapper/0 Not tainted 3.13.0-00016-g6e90346 #413
> > >   [<c0014740>] (unwind_backtrace+0x0/0xf8) from [<c00115b0>] (show_stack+0x10/0x14)
> > >   [<c00115b0>] (show_stack+0x10/0x14) from [<c057ea24>] (dump_stack+0x74/0xa8)
> > >   [<c057ea24>] (dump_stack+0x74/0xa8) from [<c00acc1c>] (__alloc_pages_nodemask+0x174/0x930)
> > >   [<c00acc1c>] (__alloc_pages_nodemask+0x174/0x930) from [<c042a250>] (arm_smmu_handle_mapping+0x470/0x66c)
> > >   [<c042a250>] (arm_smmu_handle_mapping+0x470/0x66c) from [<c0428e74>] (iommu_map+0xf0/0x148)
> > >   [<c0428e74>] (iommu_map+0xf0/0x148) from [<c001935c>] (__map_sg_chunk+0x198/0x2d4)
> > >...
> > 
> > > Maybe that was the reason why the offending commit was introduced(?).

Right, there are two issues here:

  (1) If we use a spinlock to protect our page tables, we can perform a
      blocking allocation whilst holding the lock (during a ->map()
      callback)

  (2) Fixing this to use a mutex means that we can't ->map() in atomic
      context. I hadn't thought that was something we would be doing...

> > > I think with the current code "atomic allocations" should be used when
> > > IO page tables are created. With below patch I've not triggered above
> > > errors.
> > 
> > I think allocating memory with GFP_KERNEL in this dma-mapping path
> > doesn't seem to be a good idea. What if the DMA operation for which we
> > modify IO page tables was triggered to free pages (page cache, swap)?
> 
> I mean in case we run out of memory wouldn't we worsen the situation
> by triggering additional IO (and thus DMA)? Whereas when we let the
> mapping fail, the OS "just might have to wait a little bit" until
> other DMA activities are completed, pages unmapped and iova freed. The
> freed resources instantly can be used for further DMA activities.
> 
> Hmm, but maybe I need to rethink this (and look more closely into
> page_alloc.c).

The problem I see is that we don't want to use atomic allocations for
potentially large allocations, especially where there are cases where we're
not called in atomic context.

How do other IOMMU drivers deal with this? amd_iommu.c uses GFP_KERNEL for
its pte allocation in iommu_ops, but GFP_ATOMIC for its dma_ops.

Will

^ permalink raw reply

* [PATCH RFC v4 00/10] ahci: library-ise ahci_platform, add sunxi driver and cleanup imx driver
From: Rob Herring @ 2014-02-03 16:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390236303-22538-1-git-send-email-hdegoede@redhat.com>

On Mon, Jan 20, 2014 at 10:44 AM, Hans de Goede <hdegoede@redhat.com> wrote:
> Hi All,
>
> Here is v4 of my patchset for adding ahci-sunxi support. It has grown quite
> a bit since I've been going for a more generic approach this time and I've
> also cleaned up the ahci-imx driver to use the same generic approach.

I don't know if you missed it or just don't intend to refactor all
AHCI drivers, but the highbank driver could benefit from this as well.

Rob

>
> History:
>
> v1, by Olliver Schinagl:
> This was using the approach of having a platform device which probe method
> creates a new child platform device which gets driven by ahci_platform.c,
> as done by ahci_imx.c .
>
> v2, by Hans de Goede:
> Stand-alone platform driver based on Olliver's work
>
> v3, by Hans de Goede:
> patch-series, with 4 different parts
> a) Make ahci_platform.c more generic, handle more then 1 clk, target pwr
>    regulator
> b) New ahci-sunxi code only populating ahci_platform_data, passed to
>    ahci_platform.c to of_device_id matching.
> c) Refactor ahci-imx code to work the same as the new ahci-sunxi code, this
>    is the reason why v3 is an RFC, I'm waiting for the wandboard I ordered to
>    arrive so that I can actually test this.
> d) dts bindings for the sunxi ahci parts
>
> v4, by Hans de Goede:
> patch-series, with 5 different parts:
> a) Make ahci_platform.c more generic, handle more then 1 clk, target pwr
>    regulator
> b) Turn parts of ahci_platform.c into a library for use by other drivers
> c) New ahci-sunxi driver using the ahci_platform.c library functionality
> d) Refactor ahci-imx code to work the same as the new ahci-sunxi code
> e) dts bindings for the sunxi ahci parts
>
> Parts a-d are intended for merging through the ata tree, the dts bindings
> will be merged to Maxime Ripard's sunxi-dts tree.
>
> Regards,
>
> Hans
>
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* [PATCH 1/2] clocksource: sunxi: Add new compatibles
From: Daniel Lezcano @ 2014-02-03 16:36 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391348280-9484-1-git-send-email-maxime.ripard@free-electrons.com>

On 02/02/2014 02:37 PM, Maxime Ripard wrote:
> The Allwinner A10 compatibles were following a slightly different compatible
> patterns than the rest of the SoCs for historical reasons. Add compatibles
> matching the other pattern to the timer driver for consistency, and keep the
> older one for backward compatibility.

Hi Maxime,

is it really needed to keep the old pattern ?



> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>   Documentation/devicetree/bindings/timer/allwinner,sun4i-timer.txt | 5 +++--
>   drivers/clocksource/sun4i_timer.c                                 | 4 ++++
>   2 files changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/timer/allwinner,sun4i-timer.txt b/Documentation/devicetree/bindings/timer/allwinner,sun4i-timer.txt
> index 48aeb78..d9e35ae 100644
> --- a/Documentation/devicetree/bindings/timer/allwinner,sun4i-timer.txt
> +++ b/Documentation/devicetree/bindings/timer/allwinner,sun4i-timer.txt
> @@ -2,7 +2,8 @@ Allwinner A1X SoCs Timer Controller
>
>   Required properties:
>
> -- compatible : should be "allwinner,sun4i-timer"
> +- compatible : should be "allwinner,sun4i-a10-timer"
> +               (Deprecated "allwinner,sun4i-timer")
>   - reg : Specifies base physical address and size of the registers.
>   - interrupts : The interrupt of the first timer
>   - clocks: phandle to the source clock (usually a 24 MHz fixed clock)
> @@ -10,7 +11,7 @@ Required properties:
>   Example:
>
>   timer {
> -	compatible = "allwinner,sun4i-timer";
> +	compatible = "allwinner,sun4i-a10-timer";
>   	reg = <0x01c20c00 0x400>;
>   	interrupts = <22>;
>   	clocks = <&osc>;
> diff --git a/drivers/clocksource/sun4i_timer.c b/drivers/clocksource/sun4i_timer.c
> index bf497af..de03895 100644
> --- a/drivers/clocksource/sun4i_timer.c
> +++ b/drivers/clocksource/sun4i_timer.c
> @@ -196,5 +196,9 @@ static void __init sun4i_timer_init(struct device_node *node)
>   	clockevents_config_and_register(&sun4i_clockevent, rate,
>   					TIMER_SYNC_TICKS, 0xffffffff);
>   }
> +CLOCKSOURCE_OF_DECLARE(sun4i, "allwinner,sun4i-a10-timer",
> +		       sun4i_timer_init);
> +
> +/* Deprecated */
>   CLOCKSOURCE_OF_DECLARE(sun4i, "allwinner,sun4i-timer",
>   		       sun4i_timer_init);
>


-- 
  <http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog

^ permalink raw reply

* [PATCH v5 15/16] ARM: add uprobes support
From: Jon Medhurst (Tixy) @ 2014-02-03 16:36 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390507559-4697-16-git-send-email-dave.long@linaro.org>

On Thu, 2014-01-23 at 15:05 -0500, David Long wrote:
> From: "David A. Long" <dave.long@linaro.org>
> 
> Using Rabin Vincent's ARM uprobes patches as a base, enable uprobes
> support on ARM.
> 
> Caveats:
> 
>  - Thumb is not supported
> 
> Signed-off-by: David A. Long <dave.long@linaro.org>

As this is based on Rabin's work, and the new files have his Copyright,
then this patch also needs his 'Signed-off-by'. Rabin, I assume that you
agree?

I have no more comments about this patch, however I have included the
rest of the patch below so Rabin can see it's contents (in case he
doesn't still have the original)...


> ---
>  arch/arm/Kconfig                   |   4 +
>  arch/arm/include/asm/ptrace.h      |   6 +
>  arch/arm/include/asm/thread_info.h |   5 +-
>  arch/arm/include/asm/uprobes.h     |  45 ++++++++
>  arch/arm/kernel/Makefile           |   1 +
>  arch/arm/kernel/signal.c           |   4 +
>  arch/arm/kernel/uprobes-arm.c      | 231 +++++++++++++++++++++++++++++++++++++
>  arch/arm/kernel/uprobes.c          | 208 +++++++++++++++++++++++++++++++++
>  arch/arm/kernel/uprobes.h          |  35 ++++++
>  9 files changed, 538 insertions(+), 1 deletion(-)
>  create mode 100644 arch/arm/include/asm/uprobes.h
>  create mode 100644 arch/arm/kernel/uprobes-arm.c
>  create mode 100644 arch/arm/kernel/uprobes.c
>  create mode 100644 arch/arm/kernel/uprobes.h
> 
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index c1f1a7e..fec5a6b 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -203,6 +203,10 @@ config ZONE_DMA
>  config NEED_DMA_MAP_STATE
>         def_bool y
>  
> +config ARCH_SUPPORTS_UPROBES
> +	depends on KPROBES
> +	def_bool y
> +
>  config ARCH_HAS_DMA_SET_COHERENT_MASK
>  	bool
>  
> diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h
> index 04c99f3..ee688b0a 100644
> --- a/arch/arm/include/asm/ptrace.h
> +++ b/arch/arm/include/asm/ptrace.h
> @@ -80,6 +80,12 @@ static inline long regs_return_value(struct pt_regs *regs)
>  
>  #define instruction_pointer(regs)	(regs)->ARM_pc
>  
> +static inline void instruction_pointer_set(struct pt_regs *regs,
> +					   unsigned long val)
> +{
> +	instruction_pointer(regs) = val;
> +}
> +
>  #ifdef CONFIG_SMP
>  extern unsigned long profile_pc(struct pt_regs *regs);
>  #else
> diff --git a/arch/arm/include/asm/thread_info.h b/arch/arm/include/asm/thread_info.h
> index 71a06b2..f989d7c 100644
> --- a/arch/arm/include/asm/thread_info.h
> +++ b/arch/arm/include/asm/thread_info.h
> @@ -153,6 +153,7 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
>  #define TIF_SIGPENDING		0
>  #define TIF_NEED_RESCHED	1
>  #define TIF_NOTIFY_RESUME	2	/* callback before returning to user */
> +#define TIF_UPROBE		7
>  #define TIF_SYSCALL_TRACE	8
>  #define TIF_SYSCALL_AUDIT	9
>  #define TIF_SYSCALL_TRACEPOINT	10
> @@ -165,6 +166,7 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
>  #define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
>  #define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
>  #define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
> +#define _TIF_UPROBE		(1 << TIF_UPROBE)
>  #define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
>  #define _TIF_SYSCALL_AUDIT	(1 << TIF_SYSCALL_AUDIT)
>  #define _TIF_SYSCALL_TRACEPOINT	(1 << TIF_SYSCALL_TRACEPOINT)
> @@ -178,7 +180,8 @@ extern int vfp_restore_user_hwstate(struct user_vfp __user *,
>  /*
>   * Change these and you break ASM code in entry-common.S
>   */
> -#define _TIF_WORK_MASK		(_TIF_NEED_RESCHED | _TIF_SIGPENDING | _TIF_NOTIFY_RESUME)
> +#define _TIF_WORK_MASK		(_TIF_NEED_RESCHED | _TIF_SIGPENDING | \
> +				 _TIF_NOTIFY_RESUME | _TIF_UPROBE)
>  
>  #endif /* __KERNEL__ */
>  #endif /* __ASM_ARM_THREAD_INFO_H */
> diff --git a/arch/arm/include/asm/uprobes.h b/arch/arm/include/asm/uprobes.h
> new file mode 100644
> index 0000000..9472c20
> --- /dev/null
> +++ b/arch/arm/include/asm/uprobes.h
> @@ -0,0 +1,45 @@
> +/*
> + * Copyright (C) 2012 Rabin Vincent <rabin@rab.in>
> + *
> + * 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_UPROBES_H
> +#define _ASM_UPROBES_H
> +
> +#include <asm/probes.h>
> +#include <asm/opcodes.h>
> +
> +typedef u32 uprobe_opcode_t;
> +
> +#define MAX_UINSN_BYTES		4
> +#define UPROBE_XOL_SLOT_BYTES	64
> +
> +#define UPROBE_SWBP_ARM_INSN	0xe7f001f9
> +#define UPROBE_SS_ARM_INSN	0xe7f001fa
> +#define UPROBE_SWBP_INSN	__opcode_to_mem_arm(UPROBE_SWBP_ARM_INSN)
> +#define UPROBE_SWBP_INSN_SIZE	4
> +
> +struct arch_uprobe_task {
> +	u32 backup;
> +	unsigned long	saved_trap_no;
> +};
> +
> +struct arch_uprobe {
> +	u8 insn[MAX_UINSN_BYTES];
> +	unsigned long ixol[2];
> +	uprobe_opcode_t bpinsn;
> +	bool simulate;
> +	u32 pcreg;
> +	void (*prehandler)(struct arch_uprobe *auprobe,
> +			   struct arch_uprobe_task *autask,
> +			   struct pt_regs *regs);
> +	void (*posthandler)(struct arch_uprobe *auprobe,
> +			    struct arch_uprobe_task *autask,
> +			    struct pt_regs *regs);
> +	struct arch_probes_insn asi;
> +};
> +
> +#endif
> diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
> index bb739f2..a766bcb 100644
> --- a/arch/arm/kernel/Makefile
> +++ b/arch/arm/kernel/Makefile
> @@ -50,6 +50,7 @@ obj-$(CONFIG_DYNAMIC_FTRACE)	+= ftrace.o insn.o
>  obj-$(CONFIG_FUNCTION_GRAPH_TRACER)	+= ftrace.o insn.o
>  obj-$(CONFIG_JUMP_LABEL)	+= jump_label.o insn.o patch.o
>  obj-$(CONFIG_KEXEC)		+= machine_kexec.o relocate_kernel.o
> +obj-$(CONFIG_UPROBES)		+= probes.o probes-arm.o uprobes.o uprobes-arm.o
>  obj-$(CONFIG_KPROBES)		+= probes.o kprobes.o kprobes-common.o patch.o
>  ifdef CONFIG_THUMB2_KERNEL
>  obj-$(CONFIG_KPROBES)		+= kprobes-thumb.o probes-thumb.o
> diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
> index 04d6388..bd19834 100644
> --- a/arch/arm/kernel/signal.c
> +++ b/arch/arm/kernel/signal.c
> @@ -13,6 +13,7 @@
>  #include <linux/personality.h>
>  #include <linux/uaccess.h>
>  #include <linux/tracehook.h>
> +#include <linux/uprobes.h>
>  
>  #include <asm/elf.h>
>  #include <asm/cacheflush.h>
> @@ -590,6 +591,9 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall)
>  					return restart;
>  				}
>  				syscall = 0;
> +			} else if (thread_flags & _TIF_UPROBE) {
> +				clear_thread_flag(TIF_UPROBE);
> +				uprobe_notify_resume(regs);
>  			} else {
>  				clear_thread_flag(TIF_NOTIFY_RESUME);
>  				tracehook_notify_resume(regs);
> diff --git a/arch/arm/kernel/uprobes-arm.c b/arch/arm/kernel/uprobes-arm.c
> new file mode 100644
> index 0000000..d5feb50
> --- /dev/null
> +++ b/arch/arm/kernel/uprobes-arm.c
> @@ -0,0 +1,231 @@
> +/*
> + * Copyright (C) 2012 Rabin Vincent <rabin@rab.in>
> + *
> + * 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.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/wait.h>
> +#include <linux/uprobes.h>
> +#include <linux/module.h>
> +
> +#include "probes.h"
> +#include "probes-arm.h"
> +#include "uprobes.h"
> +
> +static int uprobes_substitute_pc(unsigned long *pinsn, u32 oregs)
> +{
> +	probes_opcode_t insn = __mem_to_opcode_arm(*pinsn);
> +	probes_opcode_t temp;
> +	probes_opcode_t mask;
> +	int freereg;
> +	u32 free = 0xffff;
> +	u32 regs;
> +
> +	for (regs = oregs; regs; regs >>= 4, insn >>= 4) {
> +		if ((regs & 0xf) == REG_TYPE_NONE)
> +			continue;
> +
> +		free &= ~(1 << (insn & 0xf));
> +	}
> +
> +	/* No PC, no problem */
> +	if (free & (1 << 15))
> +		return 15;
> +
> +	if (!free)
> +		return -1;
> +
> +	/*
> +	 * fls instead of ffs ensures that for "ldrd r0, r1, [pc]" we would
> +	 * pick LR instead of R1.
> +	 */
> +	freereg = free = fls(free) - 1;
> +
> +	temp = __mem_to_opcode_arm(*pinsn);
> +	insn = temp;
> +	regs = oregs;
> +	mask = 0xf;
> +
> +	for (; regs; regs >>= 4, mask <<= 4, free <<= 4, temp >>= 4) {
> +		if ((regs & 0xf) == REG_TYPE_NONE)
> +			continue;
> +
> +		if ((temp & 0xf) != 15)
> +			continue;
> +
> +		insn &= ~mask;
> +		insn |= free & mask;
> +	}
> +
> +	*pinsn = __opcode_to_mem_arm(insn);
> +	return freereg;
> +}
> +
> +static void uprobe_set_pc(struct arch_uprobe *auprobe,
> +			  struct arch_uprobe_task *autask,
> +			  struct pt_regs *regs)
> +{
> +	u32 pcreg = auprobe->pcreg;
> +
> +	autask->backup = regs->uregs[pcreg];
> +	regs->uregs[pcreg] = regs->ARM_pc + 8;
> +}
> +
> +static void uprobe_unset_pc(struct arch_uprobe *auprobe,
> +			    struct arch_uprobe_task *autask,
> +			    struct pt_regs *regs)
> +{
> +	/* PC will be taken care of by common code */
> +	regs->uregs[auprobe->pcreg] = autask->backup;
> +}
> +
> +static void uprobe_aluwrite_pc(struct arch_uprobe *auprobe,
> +			       struct arch_uprobe_task *autask,
> +			       struct pt_regs *regs)
> +{
> +	u32 pcreg = auprobe->pcreg;
> +
> +	alu_write_pc(regs->uregs[pcreg], regs);
> +	regs->uregs[pcreg] = autask->backup;
> +}
> +
> +static void uprobe_write_pc(struct arch_uprobe *auprobe,
> +			    struct arch_uprobe_task *autask,
> +			    struct pt_regs *regs)
> +{
> +	u32 pcreg = auprobe->pcreg;
> +
> +	load_write_pc(regs->uregs[pcreg], regs);
> +	regs->uregs[pcreg] = autask->backup;
> +}
> +
> +enum probes_insn
> +decode_pc_ro(probes_opcode_t insn, struct arch_probes_insn *asi,
> +	     struct decode_header *d)
> +{
> +	struct arch_uprobe *auprobe = container_of(asi, struct arch_uprobe,
> +						   asi);
> +	struct decode_emulate *decode = (struct decode_emulate *) d;
> +	u32 regs = decode->header.type_regs.bits >> DECODE_TYPE_BITS;
> +	int reg;
> +
> +	reg = uprobes_substitute_pc(&auprobe->ixol[0], regs);
> +	if (reg == 15)
> +		return INSN_GOOD;
> +
> +	if (reg == -1)
> +		return INSN_REJECTED;
> +
> +	auprobe->pcreg = reg;
> +	auprobe->prehandler = uprobe_set_pc;
> +	auprobe->posthandler = uprobe_unset_pc;
> +
> +	return INSN_GOOD;
> +}
> +
> +enum probes_insn
> +decode_wb_pc(probes_opcode_t insn, struct arch_probes_insn *asi,
> +	     struct decode_header *d, bool alu)
> +{
> +	struct arch_uprobe *auprobe = container_of(asi, struct arch_uprobe,
> +						   asi);
> +	enum probes_insn ret = decode_pc_ro(insn, asi, d);
> +
> +	if (((insn >> 12) & 0xf) == 15)
> +		auprobe->posthandler = alu ? uprobe_aluwrite_pc
> +					   : uprobe_write_pc;
> +
> +	return ret;
> +}
> +
> +enum probes_insn
> +decode_rd12rn16rm0rs8_rwflags(probes_opcode_t insn,
> +			      struct arch_probes_insn *asi,
> +			      struct decode_header *d)
> +{
> +	return decode_wb_pc(insn, asi, d, true);
> +}
> +
> +enum probes_insn
> +decode_ldr(probes_opcode_t insn, struct arch_probes_insn *asi,
> +	   struct decode_header *d)
> +{
> +	return decode_wb_pc(insn, asi, d, false);
> +}
> +
> +enum probes_insn
> +uprobe_decode_ldmstm(probes_opcode_t insn,
> +		     struct arch_probes_insn *asi, struct decode_header *d)
> +{
> +	struct arch_uprobe *auprobe = container_of(asi, struct arch_uprobe,
> +						   asi);
> +	unsigned reglist = insn & 0xffff;
> +	int rn = (insn >> 16) & 0xf;
> +	int lbit = insn & (1 << 20);
> +	unsigned used = reglist | (1 << rn);
> +
> +	if (rn == 15)
> +		return INSN_REJECTED;
> +
> +	if (!(used & (1 << 15)))
> +		return INSN_GOOD;
> +
> +	if (used & (1 << 14))
> +		return INSN_REJECTED;
> +
> +	/* Use LR instead of PC */
> +	insn ^= 0xc000;
> +
> +	auprobe->pcreg = 14;
> +	auprobe->ixol[0] = __opcode_to_mem_arm(insn);
> +
> +	auprobe->prehandler = uprobe_set_pc;
> +	if (lbit)
> +		auprobe->posthandler = uprobe_write_pc;
> +	else
> +		auprobe->posthandler = uprobe_unset_pc;
> +
> +	return INSN_GOOD;
> +}
> +
> +const union decode_action uprobes_probes_actions[] = {
> +	[PROBES_EMULATE_NONE] = {.handler = probes_simulate_nop},
> +	[PROBES_SIMULATE_NOP] = {.handler = probes_simulate_nop},
> +	[PROBES_PRELOAD_IMM] = {.handler = probes_simulate_nop},
> +	[PROBES_PRELOAD_REG] = {.handler = probes_simulate_nop},
> +	[PROBES_BRANCH_IMM] = {.handler = simulate_blx1},
> +	[PROBES_MRS] = {.handler = simulate_mrs},
> +	[PROBES_BRANCH_REG] = {.handler = simulate_blx2bx},
> +	[PROBES_CLZ] = {.handler = probes_simulate_nop},
> +	[PROBES_SATURATING_ARITHMETIC] = {.handler = probes_simulate_nop},
> +	[PROBES_MUL1] = {.handler = probes_simulate_nop},
> +	[PROBES_MUL2] = {.handler = probes_simulate_nop},
> +	[PROBES_SWP] = {.handler = probes_simulate_nop},
> +	[PROBES_LDRSTRD] = {.decoder = decode_pc_ro},
> +	[PROBES_LOAD_EXTRA] = {.decoder = decode_pc_ro},
> +	[PROBES_LOAD] = {.decoder = decode_ldr},
> +	[PROBES_STORE_EXTRA] = {.decoder = decode_pc_ro},
> +	[PROBES_STORE] = {.decoder = decode_pc_ro},
> +	[PROBES_MOV_IP_SP] = {.handler = simulate_mov_ipsp},
> +	[PROBES_DATA_PROCESSING_REG] = {
> +		.decoder = decode_rd12rn16rm0rs8_rwflags},
> +	[PROBES_DATA_PROCESSING_IMM] = {
> +		.decoder = decode_rd12rn16rm0rs8_rwflags},
> +	[PROBES_MOV_HALFWORD] = {.handler = probes_simulate_nop},
> +	[PROBES_SEV] = {.handler = probes_simulate_nop},
> +	[PROBES_WFE] = {.handler = probes_simulate_nop},
> +	[PROBES_SATURATE] = {.handler = probes_simulate_nop},
> +	[PROBES_REV] = {.handler = probes_simulate_nop},
> +	[PROBES_MMI] = {.handler = probes_simulate_nop},
> +	[PROBES_PACK] = {.handler = probes_simulate_nop},
> +	[PROBES_EXTEND] = {.handler = probes_simulate_nop},
> +	[PROBES_EXTEND_ADD] = {.handler = probes_simulate_nop},
> +	[PROBES_MUL_ADD_LONG] = {.handler = probes_simulate_nop},
> +	[PROBES_MUL_ADD] = {.handler = probes_simulate_nop},
> +	[PROBES_BITFIELD] = {.handler = probes_simulate_nop},
> +	[PROBES_BRANCH] = {.handler = simulate_bbl},
> +	[PROBES_LDMSTM] = {.decoder = uprobe_decode_ldmstm}
> +};
> diff --git a/arch/arm/kernel/uprobes.c b/arch/arm/kernel/uprobes.c
> new file mode 100644
> index 0000000..bfe08ba2
> --- /dev/null
> +++ b/arch/arm/kernel/uprobes.c
> @@ -0,0 +1,208 @@
> +/*
> + * Copyright (C) 2012 Rabin Vincent <rabin@rab.in>
> + *
> + * 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.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/highmem.h>
> +#include <linux/sched.h>
> +#include <linux/uprobes.h>
> +#include <linux/notifier.h>
> +
> +#include <asm/opcodes.h>
> +#include <asm/traps.h>
> +
> +#include "probes.h"
> +#include "probes-arm.h"
> +#include "uprobes.h"
> +
> +#define UPROBE_TRAP_NR	UINT_MAX
> +
> +bool is_swbp_insn(uprobe_opcode_t *insn)
> +{
> +	return (__mem_to_opcode_arm(*insn) & 0x0fffffff) ==
> +		(UPROBE_SWBP_ARM_INSN & 0x0fffffff);
> +}
> +
> +int set_swbp(struct arch_uprobe *auprobe, struct mm_struct *mm,
> +	     unsigned long vaddr)
> +{
> +	return uprobe_write_opcode(mm, vaddr,
> +		   __opcode_to_mem_arm(auprobe->bpinsn));
> +}
> +
> +bool arch_uprobe_ignore(struct arch_uprobe *auprobe, struct pt_regs *regs)
> +{
> +	if (!auprobe->asi.insn_check_cc(regs->ARM_cpsr)) {
> +		regs->ARM_pc += 4;
> +		return true;
> +	}
> +
> +	return false;
> +}
> +
> +bool arch_uprobe_skip_sstep(struct arch_uprobe *auprobe, struct pt_regs *regs)
> +{
> +	probes_opcode_t opcode;
> +
> +	if (!auprobe->simulate)
> +		return false;
> +
> +	opcode = __mem_to_opcode_arm(*(unsigned int *) auprobe->insn);
> +
> +	auprobe->asi.insn_singlestep(opcode, &auprobe->asi, regs);
> +
> +	return true;
> +}
> +
> +unsigned long
> +arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr,
> +				  struct pt_regs *regs)
> +{
> +	unsigned long orig_ret_vaddr;
> +
> +	orig_ret_vaddr = regs->ARM_lr;
> +	/* Replace the return addr with trampoline addr */
> +	regs->ARM_lr = trampoline_vaddr;
> +	return orig_ret_vaddr;
> +}
> +
> +int arch_uprobe_analyze_insn(struct arch_uprobe *auprobe, struct mm_struct *mm,
> +			     unsigned long addr)
> +{
> +	unsigned int insn;
> +	unsigned int bpinsn;
> +	enum probes_insn ret;
> +
> +	/* Thumb not yet support */
> +	if (addr & 0x3)
> +		return -EINVAL;
> +
> +	insn = __mem_to_opcode_arm(*(unsigned int *)auprobe->insn);
> +	auprobe->ixol[0] = __opcode_to_mem_arm(insn);
> +	auprobe->ixol[1] = __opcode_to_mem_arm(UPROBE_SS_ARM_INSN);
> +
> +	ret = arm_probes_decode_insn(insn, &auprobe->asi, false,
> +				     uprobes_probes_actions);
> +	switch (ret) {
> +	case INSN_REJECTED:
> +		return -EINVAL;
> +
> +	case INSN_GOOD_NO_SLOT:
> +		auprobe->simulate = true;
> +		break;
> +
> +	case INSN_GOOD:
> +	default:
> +		break;
> +	}
> +
> +	bpinsn = UPROBE_SWBP_ARM_INSN & 0x0fffffff;
> +	if (insn >= 0xe0000000)
> +		bpinsn |= 0xe0000000;  /* Unconditional instruction */
> +	else
> +		bpinsn |= insn & 0xf0000000;  /* Copy condition from insn */
> +
> +	auprobe->bpinsn = bpinsn;
> +
> +	return 0;
> +}
> +
> +int arch_uprobe_pre_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
> +{
> +	struct uprobe_task *utask = current->utask;
> +
> +	if (auprobe->prehandler)
> +		auprobe->prehandler(auprobe, &utask->autask, regs);
> +
> +	utask->autask.saved_trap_no = current->thread.trap_no;
> +	current->thread.trap_no = UPROBE_TRAP_NR;
> +	regs->ARM_pc = utask->xol_vaddr;
> +
> +	return 0;
> +}
> +
> +int arch_uprobe_post_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
> +{
> +	struct uprobe_task *utask = current->utask;
> +
> +	WARN_ON_ONCE(current->thread.trap_no != UPROBE_TRAP_NR);
> +
> +	current->thread.trap_no = utask->autask.saved_trap_no;
> +	regs->ARM_pc = utask->vaddr + 4;
> +
> +	if (auprobe->posthandler)
> +		auprobe->posthandler(auprobe, &utask->autask, regs);
> +
> +	return 0;
> +}
> +
> +bool arch_uprobe_xol_was_trapped(struct task_struct *t)
> +{
> +	if (t->thread.trap_no != UPROBE_TRAP_NR)
> +		return true;
> +
> +	return false;
> +}
> +
> +void arch_uprobe_abort_xol(struct arch_uprobe *auprobe, struct pt_regs *regs)
> +{
> +	struct uprobe_task *utask = current->utask;
> +
> +	current->thread.trap_no = utask->autask.saved_trap_no;
> +	instruction_pointer_set(regs, utask->vaddr);
> +}
> +
> +int arch_uprobe_exception_notify(struct notifier_block *self,
> +				 unsigned long val, void *data)
> +{
> +	return NOTIFY_DONE;
> +}
> +
> +static int uprobe_trap_handler(struct pt_regs *regs, unsigned int instr)
> +{
> +	unsigned long flags;
> +
> +	local_irq_save(flags);
> +	instr &= 0x0fffffff;
> +	if (instr == (UPROBE_SWBP_ARM_INSN & 0x0fffffff))
> +		uprobe_pre_sstep_notifier(regs);
> +	else if (instr == (UPROBE_SS_ARM_INSN & 0x0fffffff))
> +		uprobe_post_sstep_notifier(regs);
> +	local_irq_restore(flags);
> +
> +	return 0;
> +}
> +
> +unsigned long uprobe_get_swbp_addr(struct pt_regs *regs)
> +{
> +	return instruction_pointer(regs);
> +}
> +
> +static struct undef_hook uprobes_arm_break_hook = {
> +	.instr_mask	= 0x0fffffff,
> +	.instr_val	= (UPROBE_SWBP_ARM_INSN & 0x0fffffff),
> +	.cpsr_mask	= MODE_MASK,
> +	.cpsr_val	= USR_MODE,
> +	.fn		= uprobe_trap_handler,
> +};
> +
> +static struct undef_hook uprobes_arm_ss_hook = {
> +	.instr_mask	= 0x0fffffff,
> +	.instr_val	= (UPROBE_SS_ARM_INSN & 0x0fffffff),
> +	.cpsr_mask	= MODE_MASK,
> +	.cpsr_val	= USR_MODE,
> +	.fn		= uprobe_trap_handler,
> +};
> +
> +static int arch_uprobes_init(void)
> +{
> +	register_undef_hook(&uprobes_arm_break_hook);
> +	register_undef_hook(&uprobes_arm_ss_hook);
> +
> +	return 0;
> +}
> +device_initcall(arch_uprobes_init);
> diff --git a/arch/arm/kernel/uprobes.h b/arch/arm/kernel/uprobes.h
> new file mode 100644
> index 0000000..a6581f5
> --- /dev/null
> +++ b/arch/arm/kernel/uprobes.h
> @@ -0,0 +1,35 @@
> +/*
> + * Copyright (C) 2012 Rabin Vincent <rabin@rab.in>
> + *
> + * 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 __ARM_KERNEL_UPROBES_H
> +#define __ARM_KERNEL_UPROBES_H
> +
> +enum probes_insn uprobe_decode_ldmstm(probes_opcode_t insn,
> +				      struct arch_probes_insn *asi,
> +				      struct decode_header *d);
> +
> +enum probes_insn decode_ldr(probes_opcode_t insn,
> +			    struct arch_probes_insn *asi,
> +			    struct decode_header *d);
> +
> +enum probes_insn
> +decode_rd12rn16rm0rs8_rwflags(probes_opcode_t insn,
> +			      struct arch_probes_insn *asi,
> +			      struct decode_header *d);
> +
> +enum probes_insn
> +decode_wb_pc(probes_opcode_t insn, struct arch_probes_insn *asi,
> +	     struct decode_header *d, bool alu);
> +
> +enum probes_insn
> +decode_pc_ro(probes_opcode_t insn, struct arch_probes_insn *asi,
> +	     struct decode_header *d);
> +
> +extern const union decode_action uprobes_probes_actions[];
> +
> +#endif

^ permalink raw reply

* [PATCH resend 1/2] arm64: defer reloading a task's FPSIMD state to userland resume
From: Will Deacon @ 2014-02-03 16:36 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391163196-27619-1-git-send-email-ard.biesheuvel@linaro.org>

Hi Ard,

On Fri, Jan 31, 2014 at 10:13:15AM +0000, Ard Biesheuvel wrote:
> If a task gets scheduled out and back in again and nothing has touched
> its FPSIMD state in the mean time, there is really no reason to reload
> it from memory. Similarly, repeated calls to kernel_neon_begin() and
> kernel_neon_end() will preserve and restore the FPSIMD state every time.
> 
> This patch defers the FPSIMD state restore to the last possible moment,
> i.e., right before the task re-enters userland. If a task does not enter
> userland at all (for any reason), the existing FPSIMD state is preserved
> and may be reused by the owning task if it gets scheduled in again on the
> same CPU.

The one situation I'm unsure of here is how you deal with the saved fpsimd
state potentially being updated by a signal handler or a debugger. In this
case, we probably need to set _TIF_FOREIGN_FPSTATE to force a reload, or are
you handling this some other way?

Will

^ permalink raw reply

* [PATCH] clk: Fix notifier documentation
From: Sören Brinkmann @ 2014-02-03 16:36 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAPtuhTj7QmB-xFU40x_MCvbvo07M2_2sDfiOQNkf4oEGFPKiOg@mail.gmail.com>

On Fri, Jan 31, 2014 at 10:01:27PM -0800, Mike Turquette wrote:
> On Fri, Jan 31, 2014 at 5:49 PM, S?ren Brinkmann
> <soren.brinkmann@xilinx.com> wrote:
> > ping?
> 
> Hi Soren,
> 
> I'm a bit slow to review patches during the merge window. Thanks for
> the doc update. I'll take it in after -rc1 drops.

Sorry for my impatience. Thank you!

	S?ren

^ permalink raw reply

* [PATCH 0/3] ARM: v7m: updates for 3.15
From: Uwe Kleine-König @ 2014-02-03 16:37 UTC (permalink / raw)
  To: linux-arm-kernel

Hello Russell,

I'd like these three patches to go in during the 3.15 merge window. The
first two were already send earlier on this list (Message-Id:
20131210212550.GF18888 at pengutronix.de), I only squashed in a fix for a format
warning and an unused variable warning into the 2nd. The third is a trivial
patch to allow power management on v7-M.

The series is available in my repository in the v7m branch:

	git://git.pengutronix.de/git/ukl/linux.git v7m

If you are ok with the changes, tell how you want them to pick up:
signed tag to pull, patch system, pull as is, ...

Also I wonder if you still have 7889/1 on your radar, I expected it to
go in for 3.14-rc1. Is it just -ENOTIME on your side, or do you have any
concerns?

Best regards
Uwe

Uwe Kleine-K?nig (3):
  ARM: make isa_mode macro more robust and fix for v7-M
  ARM: show_regs: on v7-M there are no FIQs, different processor modes,
    ...
  ARM: v7m: add trivial suspend support

 arch/arm/Kconfig              | 2 +-
 arch/arm/include/asm/ptrace.h | 8 ++++++--
 arch/arm/kernel/process.c     | 5 +++++
 3 files changed, 12 insertions(+), 3 deletions(-)

-- 
1.8.5.3

^ permalink raw reply

* [PATCH 1/3] ARM: make isa_mode macro more robust and fix for v7-M
From: Uwe Kleine-König @ 2014-02-03 16:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391445443-28971-1-git-send-email-u.kleine-koenig@pengutronix.de>

The definition of isa_mode hardcodes the values to shift PSR_J_BIT and
PSR_T_BIT to move them to bits 1 and 0 respectively. Instead use __ffs to
calculate the shift from the #define already used for masking.

This is relevant on v7-M as there PSR_T_BIT is 0x01000000 instead of
0x00000020 for V7-[AR] and earlier. Because of that isa_mode produced
values >= 0x80000 which are unsuitable to index into isa_modes[4] there
and so made __show_regs read from undefined memory which resulted in
hangs and crashes.

Moreover isa_mode is wrong for v7-M even after this robustness fix as
there is no J-bit in the PSR register. So hardcode isa_mode to "Thumb"
for v7-M.

Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
---
 arch/arm/include/asm/ptrace.h | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h
index 04c99f36ff7f..627a03ebb987 100644
--- a/arch/arm/include/asm/ptrace.h
+++ b/arch/arm/include/asm/ptrace.h
@@ -27,9 +27,13 @@ struct pt_regs {
 #define thumb_mode(regs) (0)
 #endif
 
+#ifndef CONFIG_CPU_V7M
 #define isa_mode(regs) \
-	((((regs)->ARM_cpsr & PSR_J_BIT) >> 23) | \
-	 (((regs)->ARM_cpsr & PSR_T_BIT) >> 5))
+	((((regs)->ARM_cpsr & PSR_J_BIT) >> (__ffs(PSR_J_BIT) - 1)) | \
+	 (((regs)->ARM_cpsr & PSR_T_BIT) >> (__ffs(PSR_T_BIT))))
+#else
+#define isa_mode(regs) 1 /* Thumb */
+#endif
 
 #define processor_mode(regs) \
 	((regs)->ARM_cpsr & MODE_MASK)
-- 
1.8.5.3

^ permalink raw reply related

* [PATCH 2/3] ARM: show_regs: on v7-M there are no FIQs, different processor modes, ...
From: Uwe Kleine-König @ 2014-02-03 16:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391445443-28971-1-git-send-email-u.kleine-koenig@pengutronix.de>

no indication about irqs in PSR and only a single ISA. So skip the whole
decoding and just print the xPSR on v7-M.

Also mark two static variables as __maybe_unused to prevent the compiler
from emitting:

	arch/arm/kernel/process.c:51:20: warning: 'processor_modes' defined but not used [-Wunused-variable]
	arch/arm/kernel/process.c:58:20: warning: 'isa_modes' defined but not used [-Wunused-variable]

Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
---
 arch/arm/kernel/process.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 92f7b15dd221..204f7d273319 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -48,14 +48,14 @@ unsigned long __stack_chk_guard __read_mostly;
 EXPORT_SYMBOL(__stack_chk_guard);
 #endif
 
-static const char *processor_modes[] = {
+static const char *processor_modes[] __maybe_unused = {
   "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" ,
   "UK8_26" , "UK9_26" , "UK10_26", "UK11_26", "UK12_26", "UK13_26", "UK14_26", "UK15_26",
   "USER_32", "FIQ_32" , "IRQ_32" , "SVC_32" , "UK4_32" , "UK5_32" , "UK6_32" , "ABT_32" ,
   "UK8_32" , "UK9_32" , "UK10_32", "UND_32" , "UK12_32", "UK13_32", "UK14_32", "SYS_32"
 };
 
-static const char *isa_modes[] = {
+static const char *isa_modes[] __maybe_unused = {
   "ARM" , "Thumb" , "Jazelle", "ThumbEE"
 };
 
@@ -276,12 +276,17 @@ void __show_regs(struct pt_regs *regs)
 	buf[3] = flags & PSR_V_BIT ? 'V' : 'v';
 	buf[4] = '\0';
 
+#ifndef CONFIG_CPU_V7M
 	printk("Flags: %s  IRQs o%s  FIQs o%s  Mode %s  ISA %s  Segment %s\n",
 		buf, interrupts_enabled(regs) ? "n" : "ff",
 		fast_interrupts_enabled(regs) ? "n" : "ff",
 		processor_modes[processor_mode(regs)],
 		isa_modes[isa_mode(regs)],
 		get_fs() == get_ds() ? "kernel" : "user");
+#else
+	printk("xPSR: %08lx\n", regs->ARM_cpsr);
+#endif
+
 #ifdef CONFIG_CPU_CP15
 	{
 		unsigned int ctrl;
-- 
1.8.5.3

^ permalink raw reply related

* [PATCH 3/3] ARM: v7m: add trivial suspend support
From: Uwe Kleine-König @ 2014-02-03 16:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391445443-28971-1-git-send-email-u.kleine-koenig@pengutronix.de>

Signed-off-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
---
 arch/arm/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index e25419817791..41266af5dfc8 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -2270,7 +2270,7 @@ source "kernel/power/Kconfig"
 config ARCH_SUSPEND_POSSIBLE
 	depends on !ARCH_S5PC100
 	depends on CPU_ARM920T || CPU_ARM926T || CPU_FEROCEON || CPU_SA1100 || \
-		CPU_V6 || CPU_V6K || CPU_V7 || CPU_XSC3 || CPU_XSCALE || CPU_MOHAWK
+		CPU_V6 || CPU_V6K || CPU_V7 || CPU_V7M || CPU_XSC3 || CPU_XSCALE || CPU_MOHAWK
 	def_bool y
 
 config ARM_CPU_SUSPEND
-- 
1.8.5.3

^ permalink raw reply related

* Why are imprecise external aborts masked on recent kernel while booting ?
From: Fabrice Gasnier @ 2014-02-03 16:43 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <52EF5D8E.4050600@st.com>

Hi,

I had no success with msr instruction to set CPSR.A bit.

I re-checked on a 3.4 kernel, msr instruction present in former 
"kernel_thread_helper()" routine was not responsible for clearing CPSR.A 
bit.
'A' bit was cleared because SPSR was altered before executing following 
instruction in arch/arm/kernel/entry-header.S :
movs    pc, lr                @ return & move spsr_svc into cpsr

Sorry for the confusion in my first email: that movs instruction was 
responsible for clearing 'A' bit on 3.4 kernel. But on recent kernel, 
"restore_user_regs" macro seems no longer called for a kernel thread.

So, I tried the 'cps'instruction that does it! I re-worked slightly your 
previous patch.
I also noticed that secondary needs to be set separately.

Please, could you comment on the following patch ? (I can resend 
correctly formated patch if you wish) :

diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index dc894ab..e22b109 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -378,6 +378,9 @@ asmlinkage void secondary_start_kernel(void)
         local_irq_enable();
         local_fiq_enable();

+       /* Enable imprecise aborts */
+       asm volatile("cpsie     a");
+
         /*
          * OK, it's off to the idle thread for us
          */
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 4636d56..a9567bb 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -900,6 +900,10 @@ void __init early_trap_init(void *vectors_base)

         flush_icache_range(vectors, vectors + PAGE_SIZE * 2);
         modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
+
+       /* Enable imprecise aborts */
+       asm volatile("cpsie     a");
+
  #else /* ifndef CONFIG_CPU_V7M */
         /*
          * on V7-M there is no need to copy the vector table to a dedicated

Thanks,
BR,
Fabrice

On 02/03/2014 10:12 AM, Fabrice Gasnier wrote:
> Hi Russell,
>
> Thank you for your help.
> I just tried following patch on both 3.10 and above vanilla 3.13.1.
> Unfortunately, these instructions have no effect on the arm cpsr.
> I dumped regs right after msr instruction have been executed. It 
> remains untouched :
>
> Here is assembly from gdb:
>
>    0xc064a400 <+128>:    mov    r3, #256    ; 0x100
>    0xc064a404 <+132>:    mrs    r2, CPSR
>    0xc064a408 <+136>:    bic    r2, r2, r3
>    0xc064a40c <+140>:    msr    CPSR_c, r2
>
> CPSR.A bit is still set after these instructions : 0x600001d3
> Although, I see it has been cleared in r2: 0x600000d3
>
> Please advise.
> Thanks,
> BR,
> Fabrice
> On 01/31/2014 06:08 PM, Russell King - ARM Linux wrote:
>>> Is it possible to unmask imprecise data aborts earlier in the boot
>>> >process (e.g. before PCIe bus enumeration, when drivers are being 
>>> probed)
>>> >?
>> How about this patch?
>>
>> diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
>> index 172ee18ff124..b0ff06f49cd0 100644
>> --- a/arch/arm/kernel/traps.c
>> +++ b/arch/arm/kernel/traps.c
>> @@ -900,6 +900,15 @@ void __init early_trap_init(void *vectors_base)
>>         flush_icache_range(vectors, vectors + PAGE_SIZE * 2);
>>       modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
>> +
>> +    /* Enable imprecise aborts */
>> +    asm volatile(
>> +        "mrs    %0, cpsr\n"
>> +    "    bic    %0, %0, %1\n"
>> +    "    msr    cpsr_c, %0"
>> +        : "=&r" (i)
>> +        : "r" (PSR_A_BIT));
>> +
>>   #else /* ifndef CONFIG_CPU_V7M */
>>       /*
>>        * on V7-M there is no need to copy the vector table to a 
>> dedicated
>

^ permalink raw reply related

* [PATCH v5 00/16] uprobes: Add uprobes support for ARM
From: Jon Medhurst (Tixy) @ 2014-02-03 16:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1390507559-4697-1-git-send-email-dave.long@linaro.org>

On Thu, 2014-01-23 at 15:05 -0500, David Long wrote:
> From: "David A. Long" <dave.long@linaro.org>
> 
> This patch series adds basic uprobes support to ARM. It is based on patches
> developed earlier by Rabin Vincent. That approach of adding hooks into
> the kprobes instruction parsing code was not well received. This approach
> separates the ARM instruction parsing code in kprobes out into a separate set
> of functions which can be used by both kprobes and uprobes. Both kprobes and
> uprobes then provide their own semantic action tables to process the results of
> the parsing.

Assuming my comment about 'const' use in patch 5 is addressed, then for
patches 2 to 14 you can add:

Acked-by: Jon Medhurst <tixy@linaro.org>

Thanks Dave for persevering.

-- 
Tixy

^ permalink raw reply

* [PATCH v2 08/11] of: Increase MAX_PHANDLE_ARGS
From: Will Deacon @ 2014-02-03 16:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAL_Jsq+=dm4kPk=e0h_up9=wvED4fd3MBtSNFxm2NEz_yag-uA@mail.gmail.com>

On Fri, Jan 31, 2014 at 04:24:09PM +0000, Rob Herring wrote:
> On Thu, Jan 30, 2014 at 11:45 AM, Andreas Herrmann
> <andreas.herrmann@calxeda.com> wrote:
> > Do you agree on increasing MAX_PHANDLE_ARGS to 32?
> 
> Yes, but more than that will require a closer look. Please get this
> into next early in the cycle.

If you want to get this patch in early, I suggest taking it via a tree other
than mine. I don't put my iommu queue into -next, since it goes to Joerg
around -rc4, who then sticks it in after that.

Will

^ permalink raw reply

* [PATCH] at91: pmc: Fixed irq's name allocation for programmable clocks
From: Jean-Jacques Hiblot @ 2014-02-03 16:46 UTC (permalink / raw)
  To: linux-arm-kernel

The name provided to request_irq() must be valid until the irq is
released.
This patch allocates and formats the string with kasprintf().

Signed-off-by: Jean-Jacques Hiblot <jjhiblot@traphandler.com>
---
 drivers/clk/at91/clk-programmable.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/at91/clk-programmable.c b/drivers/clk/at91/clk-programmable.c
index 8e242c7..0f8bf0f 100644
--- a/drivers/clk/at91/clk-programmable.c
+++ b/drivers/clk/at91/clk-programmable.c
@@ -19,6 +19,7 @@
 #include <linux/sched.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/string.h>
 
 #include "pmc.h"
 
@@ -247,7 +248,7 @@ at91_clk_register_programmable(struct at91_pmc *pmc, unsigned int irq,
 	struct clk_programmable *prog;
 	struct clk *clk = NULL;
 	struct clk_init_data init;
-	char irq_name[11];
+	char *irq_name;
 
 	if (id > PROG_ID_MAX)
 		return ERR_PTR(-EINVAL);
@@ -269,7 +270,7 @@ at91_clk_register_programmable(struct at91_pmc *pmc, unsigned int irq,
 	prog->irq = irq;
 	init_waitqueue_head(&prog->wait);
 	irq_set_status_flags(prog->irq, IRQ_NOAUTOEN);
-	snprintf(irq_name, sizeof(irq_name), "clk-prog%d", id);
+	irq_name = kasprintf(GFP_KERNEL, "clk-prog%d", id);
 	ret = request_irq(prog->irq, clk_programmable_irq_handler,
 			  IRQF_TRIGGER_HIGH, irq_name, prog);
 	if (ret)
-- 
1.8.5.2

^ permalink raw reply related

* [PATCH v4 2/5] arm: add new asm macro update_sctlr
From: Leif Lindholm @ 2014-02-03 16:46 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140203160051.GG14112@mudshark.cambridge.arm.com>

On Mon, Feb 03, 2014 at 04:00:51PM +0000, Will Deacon wrote:
> > > > With the two call sites in uefi_phys.S as:
> > > > 
> > > > 	ldr	r5, =(CR_M)
> > > > 	update_sctlr	r12, , r5
> > > > and
> > > > 	ldr	r4, =(CR_I | CR_C | CR_M)
> > > > 	update_sctlr	r12, r4
> > > 
> > > These ldr= could be movs, right?
> > 
> > The first one could.
> > The second one could be movw on armv7+.
> > 
> > > If so, I definitely prefer this to putting an ldr = into the macro itself
> > > (option 2).
> > 
> > And your preference between 1) and 2) is?
> 
> (1), using bic and mov[tw] where possible.

(1): ok, thanks.

bic: sure, that was an oversight.

mov[tw]: why?
Then we end up battling different available immediate fields in A32/T32
instruction sets and v5/v6/v7 architecture versions.

/
    Leif

^ permalink raw reply

* a LLC sched domain bug for panda board?
From: Alex Shi @ 2014-02-03 16:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAKfTPtDJ267W9UMRj-pgyha0yf1L-VWBMKgi+QdVEA4zFJYXLw@mail.gmail.com>

On 02/04/2014 12:28 AM, Vincent Guittot wrote:
> On 3 February 2014 17:27, Vincent Guittot <vincent.guittot@linaro.org> wrote:
>> Have you checked that CONFIG_SCHED_LC is set ?
> 
> sorry it's CONFIG_SCHED_MC

Thanks for reminder! no it wasn't set. Does it means
arch/arm/configs/omap2plus_defconfig need add this config?

> 
>>
>>
>> On 3 February 2014 17:17, Alex Shi <alex.shi@linaro.org> wrote:
>>> I just run the 3.14-rc1 kernel on panda board. The only domain for it is
>>> 'CPU' domain, but this domain has no SD_SHARE_PKG_RESOURCES setting, it
>>> has no sd_llc.
>>>
>>> Guess the right domain for this board should be MC. So is it a bug?
>>>
>>> ..
>>> /proc/sys/kernel/sched_domain/cpu0/domain0/name:CPU
>>> ..
>>> /proc/sys/kernel/sched_domain/cpu1/domain0/name:CPU
>>>
>>> --
>>> Thanks
>>>     Alex
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
>>> the body of a message to majordomo at vger.kernel.org
>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>> Please read the FAQ at  http://www.tux.org/lkml/


-- 
Thanks
    Alex

^ permalink raw reply

* [PATCH v4 2/5] arm: add new asm macro update_sctlr
From: Will Deacon @ 2014-02-03 16:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140203164636.GJ11329@bivouac.eciton.net>

On Mon, Feb 03, 2014 at 04:46:36PM +0000, Leif Lindholm wrote:
> On Mon, Feb 03, 2014 at 04:00:51PM +0000, Will Deacon wrote:
> > > > > With the two call sites in uefi_phys.S as:
> > > > > 
> > > > > 	ldr	r5, =(CR_M)
> > > > > 	update_sctlr	r12, , r5
> > > > > and
> > > > > 	ldr	r4, =(CR_I | CR_C | CR_M)
> > > > > 	update_sctlr	r12, r4
> > > > 
> > > > These ldr= could be movs, right?
> > > 
> > > The first one could.
> > > The second one could be movw on armv7+.
> > > 
> > > > If so, I definitely prefer this to putting an ldr = into the macro itself
> > > > (option 2).
> > > 
> > > And your preference between 1) and 2) is?
> > 
> > (1), using bic and mov[tw] where possible.
> 
> (1): ok, thanks.
> 
> bic: sure, that was an oversight.
> 
> mov[tw]: why?
> Then we end up battling different available immediate fields in A32/T32
> instruction sets and v5/v6/v7 architecture versions.

I was making the assumption that UEFI was going to be v7 only... is this not
true?

Will

^ permalink raw reply

* [PATCH] at91: pmc: Fixed irq's name allocation for programmable clocks
From: boris brezillon @ 2014-02-03 17:13 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391445961-20755-1-git-send-email-jjhiblot@traphandler.com>

Hello JJ,

On 03/02/2014 17:46, Jean-Jacques Hiblot wrote:
> The name provided to request_irq() must be valid until the irq is
> released.
> This patch allocates and formats the string with kasprintf().

Thanks for reporting this bug.

>
> Signed-off-by: Jean-Jacques Hiblot <jjhiblot@traphandler.com>
> ---
>   drivers/clk/at91/clk-programmable.c | 5 +++--
>   1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/clk/at91/clk-programmable.c b/drivers/clk/at91/clk-programmable.c
> index 8e242c7..0f8bf0f 100644
> --- a/drivers/clk/at91/clk-programmable.c
> +++ b/drivers/clk/at91/clk-programmable.c
> @@ -19,6 +19,7 @@
>   #include <linux/sched.h>
>   #include <linux/interrupt.h>
>   #include <linux/irq.h>
> +#include <linux/string.h>
>   
>   #include "pmc.h"
>   
> @@ -247,7 +248,7 @@ at91_clk_register_programmable(struct at91_pmc *pmc, unsigned int irq,
>   	struct clk_programmable *prog;
>   	struct clk *clk = NULL;
>   	struct clk_init_data init;
> -	char irq_name[11];
> +	char *irq_name;
>   
>   	if (id > PROG_ID_MAX)
>   		return ERR_PTR(-EINVAL);
> @@ -269,7 +270,7 @@ at91_clk_register_programmable(struct at91_pmc *pmc, unsigned int irq,
>   	prog->irq = irq;
>   	init_waitqueue_head(&prog->wait);
>   	irq_set_status_flags(prog->irq, IRQ_NOAUTOEN);
> -	snprintf(irq_name, sizeof(irq_name), "clk-prog%d", id);
> +	irq_name = kasprintf(GFP_KERNEL, "clk-prog%d", id);

Could you either use a static table with the prog clk names or store the 
name in
the clk_programmable struct ?
This way we could avoid the additional dynamic allocation.

static prog_clk_names = {
   "clk-prog0",
[...]
   "clk-prog7",
};

[...]
     ret = request_irq(prog->irq, clk_programmable_irq_handler, 
IRQF_TRIGGER_HIGH, prog_clk_names[id], prog);


or

struct clk_programmable {
[...]
     char irq_name[11];
[...]
};

[...]

snprintf(prog->irq_name, sizeof(prog->irq_name), "clk-prog%d", id);
ret = request_irq(prog->irq, clk_programmable_irq_handler, 
IRQF_TRIGGER_HIGH, prog->irq_name, prog);

Best Regards,

Boris
>   	ret = request_irq(prog->irq, clk_programmable_irq_handler,
>   			  IRQF_TRIGGER_HIGH, irq_name, prog);
>   	if (ret)

^ permalink raw reply

* [PATCH 2/5] cpu: add generic support for CPU feature based module autoloading
From: Ard Biesheuvel @ 2014-02-03 17:13 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391014246-9715-3-git-send-email-ard.biesheuvel@linaro.org>

Hello Greg,

Would you care to comment on this patch?

It adds some Kconfig clutter, but this is removed again in the next patch
(http://marc.info/?l=linux-arm-kernel&m=139101443708663&w=2),
which has already been acked by hpa here:
http://marc.info/?l=linux-arm-kernel&m=139101589509168&w=2

Example enabling it for arm64:
http://marc.info/?l=linux-arm-kernel&m=139101486308822&w=2

Example using it (optional AES instructions on arm64):
http://marc.info/?l=linux-arm-kernel&m=139101446008665&w=2

Best regards,
Ard.



On 29 January 2014 17:50, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> This patch adds support for advertising optional CPU features over udev using
> the modalias, and for declaring compatibility with/dependency upon such a
> feature in a module.
>
> This feature can be enabled by setting CONFIG_GENERIC_CPU_AUTOPROBE for the
> architecture, and supplying a file <asm/cpufeature.h> which defines how the
> numbers used in the modalias string map to actual CPU features.
>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
>  drivers/base/Kconfig              |  8 ++++++
>  drivers/base/cpu.c                | 39 +++++++++++++++++++++----
>  include/linux/cpufeature.h        | 60 +++++++++++++++++++++++++++++++++++++++
>  include/linux/mod_devicetable.h   |  9 ++++++
>  scripts/mod/devicetable-offsets.c |  3 ++
>  scripts/mod/file2alias.c          | 10 +++++++
>  6 files changed, 123 insertions(+), 6 deletions(-)
>  create mode 100644 include/linux/cpufeature.h
>
> diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
> index ec36e7772e57..3f0d3732df7f 100644
> --- a/drivers/base/Kconfig
> +++ b/drivers/base/Kconfig
> @@ -185,6 +185,14 @@ config GENERIC_CPU_DEVICES
>         bool
>         default n
>
> +config HAVE_CPU_AUTOPROBE
> +       def_bool ARCH_HAS_CPU_AUTOPROBE
> +
> +config GENERIC_CPU_AUTOPROBE
> +       bool
> +       depends on !ARCH_HAS_CPU_AUTOPROBE
> +       select HAVE_CPU_AUTOPROBE
> +
>  config SOC_BUS
>         bool
>
> diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
> index 270649012e64..8a38bf8c792f 100644
> --- a/drivers/base/cpu.c
> +++ b/drivers/base/cpu.c
> @@ -15,6 +15,7 @@
>  #include <linux/percpu.h>
>  #include <linux/acpi.h>
>  #include <linux/of.h>
> +#include <linux/cpufeature.h>
>
>  #include "base.h"
>
> @@ -286,12 +287,38 @@ static void cpu_device_release(struct device *dev)
>          */
>  }
>
> -#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
> +#ifdef CONFIG_HAVE_CPU_AUTOPROBE
> +#ifdef CONFIG_GENERIC_CPU_AUTOPROBE
> +static ssize_t print_cpu_modalias(struct device *dev,
> +                                 struct device_attribute *attr,
> +                                 char *buf)
> +{
> +       ssize_t n;
> +       u32 i;
> +
> +       n = sprintf(buf, "cpu:type:" CPU_FEATURE_TYPEFMT ":feature:",
> +                   CPU_FEATURE_TYPEVAL);
> +
> +       for (i = 0; i < MAX_CPU_FEATURES; i++)
> +               if (cpu_have_feature(i)) {
> +                       if (PAGE_SIZE < n + sizeof(",XXXX\n")) {
> +                               WARN(1, "CPU features overflow page\n");
> +                               break;
> +                       }
> +                       n += sprintf(&buf[n], ",%04X", i);
> +               }
> +       buf[n++] = '\n';
> +       return n;
> +}
> +#else
> +#define print_cpu_modalias     arch_print_cpu_modalias
> +#endif
> +
>  static int cpu_uevent(struct device *dev, struct kobj_uevent_env *env)
>  {
>         char *buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
>         if (buf) {
> -               arch_print_cpu_modalias(NULL, NULL, buf);
> +               print_cpu_modalias(NULL, NULL, buf);
>                 add_uevent_var(env, "MODALIAS=%s", buf);
>                 kfree(buf);
>         }
> @@ -319,7 +346,7 @@ int register_cpu(struct cpu *cpu, int num)
>         cpu->dev.offline_disabled = !cpu->hotpluggable;
>         cpu->dev.offline = !cpu_online(num);
>         cpu->dev.of_node = of_get_cpu_node(num, NULL);
> -#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
> +#ifdef CONFIG_HAVE_CPU_AUTOPROBE
>         cpu->dev.bus->uevent = cpu_uevent;
>  #endif
>         cpu->dev.groups = common_cpu_attr_groups;
> @@ -343,8 +370,8 @@ struct device *get_cpu_device(unsigned cpu)
>  }
>  EXPORT_SYMBOL_GPL(get_cpu_device);
>
> -#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
> -static DEVICE_ATTR(modalias, 0444, arch_print_cpu_modalias, NULL);
> +#ifdef CONFIG_HAVE_CPU_AUTOPROBE
> +static DEVICE_ATTR(modalias, 0444, print_cpu_modalias, NULL);
>  #endif
>
>  static struct attribute *cpu_root_attrs[] = {
> @@ -357,7 +384,7 @@ static struct attribute *cpu_root_attrs[] = {
>         &cpu_attrs[2].attr.attr,
>         &dev_attr_kernel_max.attr,
>         &dev_attr_offline.attr,
> -#ifdef CONFIG_ARCH_HAS_CPU_AUTOPROBE
> +#ifdef CONFIG_HAVE_CPU_AUTOPROBE
>         &dev_attr_modalias.attr,
>  #endif
>         NULL
> diff --git a/include/linux/cpufeature.h b/include/linux/cpufeature.h
> new file mode 100644
> index 000000000000..c4d4eb8ac9fe
> --- /dev/null
> +++ b/include/linux/cpufeature.h
> @@ -0,0 +1,60 @@
> +/*
> + * Copyright (C) 2014 Linaro Ltd. <ard.biesheuvel@linaro.org>
> + *
> + * 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 __LINUX_CPUFEATURE_H
> +#define __LINUX_CPUFEATURE_H
> +
> +#ifdef CONFIG_GENERIC_CPU_AUTOPROBE
> +
> +#include <linux/mod_devicetable.h>
> +#include <asm/cpufeature.h>
> +
> +/*
> + * Macros imported from <asm/cpufeature.h>:
> + * - cpu_feature(x)            ordinal value of feature called 'x'
> + * - cpu_have_feature(u32 n)   whether feature #n is available
> + * - MAX_CPU_FEATURES          upper bound for feature ordinal values
> + * Optional:
> + * - CPU_FEATURE_TYPEFMT       format string fragment for printing the cpu type
> + * - CPU_FEATURE_TYPEVAL       set of values matching the format string above
> + */
> +
> +#ifndef CPU_FEATURE_TYPEFMT
> +#define CPU_FEATURE_TYPEFMT    "%s"
> +#endif
> +
> +#ifndef CPU_FEATURE_TYPEVAL
> +#define CPU_FEATURE_TYPEVAL    ELF_PLATFORM
> +#endif
> +
> +/*
> + * Use module_cpu_feature_match(feature, module_init_function) to
> + * declare that
> + * a) the module shall be probed upon discovery of CPU feature 'feature'
> + *    (typically at boot time using udev)
> + * b) the module must not be loaded if CPU feature 'feature' is not present
> + *    (not even by manual insmod).
> + *
> + * For a list of legal values for 'feature', please consult the file
> + * 'asm/cpufeature.h' of your favorite architecture.
> + */
> +#define module_cpu_feature_match(x, __init)                    \
> +static struct cpu_feature const cpu_feature_match_ ## x[] =    \
> +       { { .feature = cpu_feature(x) }, { } };                 \
> +MODULE_DEVICE_TABLE(cpu, cpu_feature_match_ ## x);             \
> +                                                               \
> +static int cpu_feature_match_ ## x ## _init(void)              \
> +{                                                              \
> +       if (!cpu_have_feature(cpu_feature(x)))                  \
> +               return -ENODEV;                                 \
> +       return __init();                                        \
> +}                                                              \
> +module_init(cpu_feature_match_ ## x ## _init)
> +
> +#endif
> +#endif
> diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
> index 45e921401b06..f2ac87c613a5 100644
> --- a/include/linux/mod_devicetable.h
> +++ b/include/linux/mod_devicetable.h
> @@ -564,6 +564,15 @@ struct x86_cpu_id {
>  #define X86_MODEL_ANY  0
>  #define X86_FEATURE_ANY 0      /* Same as FPU, you can't test for that */
>
> +/*
> + * Generic table type for matching CPU features.
> + * @feature:   the bit number of the feature (0 - 65535)
> + */
> +
> +struct cpu_feature {
> +       __u16   feature;
> +};
> +
>  #define IPACK_ANY_FORMAT 0xff
>  #define IPACK_ANY_ID (~0)
>  struct ipack_device_id {
> diff --git a/scripts/mod/devicetable-offsets.c b/scripts/mod/devicetable-offsets.c
> index bb5d115ca671..f282516acc7b 100644
> --- a/scripts/mod/devicetable-offsets.c
> +++ b/scripts/mod/devicetable-offsets.c
> @@ -174,6 +174,9 @@ int main(void)
>         DEVID_FIELD(x86_cpu_id, model);
>         DEVID_FIELD(x86_cpu_id, vendor);
>
> +       DEVID(cpu_feature);
> +       DEVID_FIELD(cpu_feature, feature);
> +
>         DEVID(mei_cl_device_id);
>         DEVID_FIELD(mei_cl_device_id, name);
>
> diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
> index 23708636b05c..8a69005228d8 100644
> --- a/scripts/mod/file2alias.c
> +++ b/scripts/mod/file2alias.c
> @@ -1135,6 +1135,16 @@ static int do_x86cpu_entry(const char *filename, void *symval,
>  }
>  ADD_TO_DEVTABLE("x86cpu", x86_cpu_id, do_x86cpu_entry);
>
> +/* LOOKS like cpu:type:*:feature:*FEAT* */
> +static int do_cpu_entry(const char *filename, void *symval, char *alias)
> +{
> +       DEF_FIELD(symval, cpu_feature, feature);
> +
> +       sprintf(alias, "cpu:type:*:feature:*%04X*", feature);
> +       return 1;
> +}
> +ADD_TO_DEVTABLE("cpu", cpu_feature, do_cpu_entry);
> +
>  /* Looks like: mei:S */
>  static int do_mei_entry(const char *filename, void *symval,
>                         char *alias)
> --
> 1.8.3.2
>

^ permalink raw reply

* [PATCH v2 3/5] spi: sunxi: Add Allwinner A31 SPI controller driver
From: Kevin Hilman @ 2014-02-03 17:39 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140131081147.GC2950@lukather>

Maxime Ripard <maxime.ripard@free-electrons.com> writes:

> Hi Kevin,
>
> On Thu, Jan 30, 2014 at 03:52:16PM -0800, Kevin Hilman wrote:
>> On Wed, Jan 29, 2014 at 5:32 AM, Maxime Ripard
>> <maxime.ripard@free-electrons.com> wrote:
>> > On Wed, Jan 29, 2014 at 12:25:20PM +0000, Mark Brown wrote:
>> >> On Wed, Jan 29, 2014 at 12:10:48PM +0100, Maxime Ripard wrote:
>> >>
>> >> > +config SPI_SUN6I
>> >> > +   tristate "Allwinner A31 SPI controller"
>> >> > +   depends on ARCH_SUNXI || COMPILE_TEST
>> >> > +   select PM_RUNTIME
>> >> > +   help
>> >> > +     This enables using the SPI controller on the Allwinner A31 SoCs.
>> >> > +
>> >>
>> >> A select of PM_RUNTIME is both surprising and odd - why is that there?
>> >> The usual idiom is that the device starts out powered up (flagged using
>> >> pm_runtime_set_active()) and then runtime PM then suspends it when it's
>> >> compiled in.  That way if for some reason people want to avoid runtime
>> >> PM they can still use the device.
>> >
>> > Since pm_runtime_set_active and all the pm_runtime* callbacks in
>> > general are defined to pretty much empty functions, how the
>> > suspend/resume callbacks are called then? Obviously, we need them to
>> > be run, hence why I added the select here, but now I'm seeing a
>> > construct like what's following acceptable then?
>> 
>> Even with your 'select', The runtime PM callbacks will never be called
>> in the current driver.  pm_runtime_enable() doesn't do any runtime PM
>> transitions.  It just allows transitions to happen when they're
>> triggered by _get()/_put()/etc.
>
> Actually, pm_runtime_get_sync is called by the SPI framework whenever
> the device needs to be used. And pm_runtime_put whenever it's not used
> anymore, so the callbacks are actually called.

Ah, right.  I forgot that the SPI framework is using runtime PM now.

>> 
>> > pm_runtime_enable(&pdev->dev);
>> > if (!pm_runtime_enabled(&pdev->dev))
>> >    sun6i_spi_runtime_resume(&pdev->dev);
>> 
>> Similarily here, it's not the pm_runtime_enable that will fail when
>> runtime PM is disabled (or not built-in), it's a pm_runtime_get_sync()
>> that will fail.
>
> In the case where pm_runtime is disabled, pm_runtime_enabled will only
> return false, and hence the resume callback will be called. get_sync
> will fail too when the framework will call it, but since the device is
> already initialized, it's fine I guess.
>
>> What you want is something like this in ->probe()
>> 
>>    sun6i_spi_runtime_resume();
>>    /* now, device is always activated whether or not runtime PM is enabled */
>>    pm_runtime_enable();
>>    pm_runtime_set_active();  /* tells runtime PM core device is
>> already active */
>>    pm_runtime_get_sync();
>> 
>> This 'get' will increase the usecount, but not actually call the
>> callbacks because we told the RPM core that the device was already
>> activated with _set_active().
>> 
>> And then, in ->remove(), you'll want
>> 
>>    pm_runtime_put();
>>    pm_runtime_disable();
>> 
>> And if runtime PM is not enabled in the kernel, then the device will
>> be left on (which is kinda what you want if you didn't build runtime
>> PM into the kernel.)
>
> Yes, but that also mean that the device is actually on after the
> probe, even if it's never going to be used. From what I got reading
> the pm_runtime code, the suspend callback is called only whenever you
> call _put, so the device will be suspended only after it's been used
> the first time, right?
>
> Wouldn't it be better if it was suspended by default, and just waken
> up whenever the framework needs it?

Yes, but that's the job of runtime PM.  Without runtime PM, you have to
live with leaving the device powered up all the time.

Kevin

^ permalink raw reply

* [PATCH] arm: document "mach-virt" platform.
From: Christoffer Dall @ 2014-02-03 17:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <52EF9D9F.5020600@codeaurora.org>

On Mon, Feb 03, 2014 at 08:46:07AM -0500, Christopher Covington wrote:
> Hi Christoffer,
> 
> On 02/02/2014 11:56 PM, Christoffer Dall wrote:
> > On Thu, Jan 30, 2014 at 11:54:46AM -0500, Christopher Covington wrote:
> >> I think it would be informative to provide pointers here to commonly used
> >> paravirtualized devices, especially VirtIO PCI/MMIO.
> > 
> > I disagree: that would only encourage limited testing or assumptions
> > about these specific devices when really this platform is just a
> > bare-bones platform driven by device tree which should make no
> > preference, whatsoever, about which devices are used with the platform.
> 
> I'd be all for clearly stating that no assumptions can be made. Perhaps you
> can explain though how providing less documentation will result in more
> testing? The assertion does not currently make sense to me.
> 
If the documentation states that this is commonly used with virtio/xen
pv drivers, then I'm afraid people will just assume that's the only
devices the platform is used with.

Any mention of specific devices or features steers the attention away
from the essential point of this documentation.

I don't see how adding this text helps.  Such documentation should go
elsewhere, in QEMU, or a Xen/KVM web page or something like that.

Anyway, I'm not religious about this point.

-Christoffer

^ permalink raw reply

* [PATCH v4 2/5] arm: add new asm macro update_sctlr
From: Leif Lindholm @ 2014-02-03 18:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20140203165718.GO14112@mudshark.cambridge.arm.com>

On Mon, Feb 03, 2014 at 04:57:18PM +0000, Will Deacon wrote:
> > mov[tw]: why?
> > Then we end up battling different available immediate fields in A32/T32
> > instruction sets and v5/v6/v7 architecture versions.
> 
> I was making the assumption that UEFI was going to be v7 only... is this not
> true?

There is no such requirement in the specification.
It even mentions requirements for ARMv4 in one place :)

But I also don't understand why ldr= should be avoided.
This is not performance sensitive (called once on system boot), and
it's already executing with the caches off, so even if it ends up
being a literal load it does not pollute.

/
    Leif

^ permalink raw reply

* [PATCH] perf: ARM64: wire up perf_regs and unwind support
From: Jean Pihet @ 2014-02-03 18:17 UTC (permalink / raw)
  To: linux-arm-kernel

This patch hooks in the perf_regs and libunwind code for ARM64.
The tools/perf/arch/arm64 is created; it contains the arch specific
code for DWARF unwinding.

Signed-off-by: Jean Pihet <jean.pihet@linaro.org>
Acked-by: Will Deacon <will.deacon@arm.com>
---
 tools/perf/arch/arm64/Makefile            |  7 +++
 tools/perf/arch/arm64/include/perf_regs.h | 88 +++++++++++++++++++++++++++++++
 tools/perf/arch/arm64/util/dwarf-regs.c   | 80 ++++++++++++++++++++++++++++
 tools/perf/arch/arm64/util/unwind.c       | 82 ++++++++++++++++++++++++++++
 tools/perf/config/Makefile                |  8 ++-
 5 files changed, 264 insertions(+), 1 deletion(-)
 create mode 100644 tools/perf/arch/arm64/Makefile
 create mode 100644 tools/perf/arch/arm64/include/perf_regs.h
 create mode 100644 tools/perf/arch/arm64/util/dwarf-regs.c
 create mode 100644 tools/perf/arch/arm64/util/unwind.c

diff --git a/tools/perf/arch/arm64/Makefile b/tools/perf/arch/arm64/Makefile
new file mode 100644
index 0000000..fe9b61e
--- /dev/null
+++ b/tools/perf/arch/arm64/Makefile
@@ -0,0 +1,7 @@
+ifndef NO_DWARF
+PERF_HAVE_DWARF_REGS := 1
+LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/dwarf-regs.o
+endif
+ifndef NO_LIBUNWIND
+LIB_OBJS += $(OUTPUT)arch/$(ARCH)/util/unwind.o
+endif
diff --git a/tools/perf/arch/arm64/include/perf_regs.h b/tools/perf/arch/arm64/include/perf_regs.h
new file mode 100644
index 0000000..2359546
--- /dev/null
+++ b/tools/perf/arch/arm64/include/perf_regs.h
@@ -0,0 +1,88 @@
+#ifndef ARCH_PERF_REGS_H
+#define ARCH_PERF_REGS_H
+
+#include <stdlib.h>
+#include "../../util/types.h"
+#include <asm/perf_regs.h>
+
+#define PERF_REGS_MASK	((1ULL << PERF_REG_ARM64_MAX) - 1)
+#define PERF_REG_IP	PERF_REG_ARM64_PC
+#define PERF_REG_SP	PERF_REG_ARM64_SP
+
+static inline const char *perf_reg_name(int id)
+{
+	switch (id) {
+	case PERF_REG_ARM64_X0:
+		return "x0";
+	case PERF_REG_ARM64_X1:
+		return "x1";
+	case PERF_REG_ARM64_X2:
+		return "x2";
+	case PERF_REG_ARM64_X3:
+		return "x3";
+	case PERF_REG_ARM64_X4:
+		return "x4";
+	case PERF_REG_ARM64_X5:
+		return "x5";
+	case PERF_REG_ARM64_X6:
+		return "x6";
+	case PERF_REG_ARM64_X7:
+		return "x7";
+	case PERF_REG_ARM64_X8:
+		return "x8";
+	case PERF_REG_ARM64_X9:
+		return "x9";
+	case PERF_REG_ARM64_X10:
+		return "x10";
+	case PERF_REG_ARM64_X11:
+		return "x11";
+	case PERF_REG_ARM64_X12:
+		return "x12";
+	case PERF_REG_ARM64_X13:
+		return "x13";
+	case PERF_REG_ARM64_X14:
+		return "x14";
+	case PERF_REG_ARM64_X15:
+		return "x15";
+	case PERF_REG_ARM64_X16:
+		return "x16";
+	case PERF_REG_ARM64_X17:
+		return "x17";
+	case PERF_REG_ARM64_X18:
+		return "x18";
+	case PERF_REG_ARM64_X19:
+		return "x19";
+	case PERF_REG_ARM64_X20:
+		return "x20";
+	case PERF_REG_ARM64_X21:
+		return "x21";
+	case PERF_REG_ARM64_X22:
+		return "x22";
+	case PERF_REG_ARM64_X23:
+		return "x23";
+	case PERF_REG_ARM64_X24:
+		return "x24";
+	case PERF_REG_ARM64_X25:
+		return "x25";
+	case PERF_REG_ARM64_X26:
+		return "x26";
+	case PERF_REG_ARM64_X27:
+		return "x27";
+	case PERF_REG_ARM64_X28:
+		return "x28";
+	case PERF_REG_ARM64_X29:
+		return "x29";
+	case PERF_REG_ARM64_SP:
+		return "sp";
+	case PERF_REG_ARM64_LR:
+		return "lr";
+	case PERF_REG_ARM64_PC:
+		return "pc";
+	default:
+		return NULL;
+	}
+
+	return NULL;
+}
+
+#endif /* ARCH_PERF_REGS_H */
diff --git a/tools/perf/arch/arm64/util/dwarf-regs.c b/tools/perf/arch/arm64/util/dwarf-regs.c
new file mode 100644
index 0000000..d49efeb
--- /dev/null
+++ b/tools/perf/arch/arm64/util/dwarf-regs.c
@@ -0,0 +1,80 @@
+/*
+ * Mapping of DWARF debug register numbers into register names.
+ *
+ * Copyright (C) 2010 Will Deacon, ARM Ltd.
+ *
+ * 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.
+ */
+
+#include <stddef.h>
+#include <dwarf-regs.h>
+
+struct pt_regs_dwarfnum {
+	const char *name;
+	unsigned int dwarfnum;
+};
+
+#define STR(s) #s
+#define REG_DWARFNUM_NAME(r, num) {.name = r, .dwarfnum = num}
+#define GPR_DWARFNUM_NAME(num) \
+	{.name = STR(%x##num), .dwarfnum = num}
+#define REG_DWARFNUM_END {.name = NULL, .dwarfnum = 0}
+
+/*
+ * Reference:
+ * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0057b/IHI0057B_aadwarf64.pdf
+ */
+static const struct pt_regs_dwarfnum regdwarfnum_table[] = {
+	GPR_DWARFNUM_NAME(0),
+	GPR_DWARFNUM_NAME(1),
+	GPR_DWARFNUM_NAME(2),
+	GPR_DWARFNUM_NAME(3),
+	GPR_DWARFNUM_NAME(4),
+	GPR_DWARFNUM_NAME(5),
+	GPR_DWARFNUM_NAME(6),
+	GPR_DWARFNUM_NAME(7),
+	GPR_DWARFNUM_NAME(8),
+	GPR_DWARFNUM_NAME(9),
+	GPR_DWARFNUM_NAME(10),
+	GPR_DWARFNUM_NAME(11),
+	GPR_DWARFNUM_NAME(12),
+	GPR_DWARFNUM_NAME(13),
+	GPR_DWARFNUM_NAME(14),
+	GPR_DWARFNUM_NAME(15),
+	GPR_DWARFNUM_NAME(16),
+	GPR_DWARFNUM_NAME(17),
+	GPR_DWARFNUM_NAME(18),
+	GPR_DWARFNUM_NAME(19),
+	GPR_DWARFNUM_NAME(20),
+	GPR_DWARFNUM_NAME(21),
+	GPR_DWARFNUM_NAME(22),
+	GPR_DWARFNUM_NAME(23),
+	GPR_DWARFNUM_NAME(24),
+	GPR_DWARFNUM_NAME(25),
+	GPR_DWARFNUM_NAME(26),
+	GPR_DWARFNUM_NAME(27),
+	GPR_DWARFNUM_NAME(28),
+	GPR_DWARFNUM_NAME(29),
+	REG_DWARFNUM_NAME("%lr", 30),
+	REG_DWARFNUM_NAME("%sp", 31),
+	REG_DWARFNUM_END,
+};
+
+/**
+ * get_arch_regstr() - lookup register name from it's DWARF register number
+ * @n:	the DWARF register number
+ *
+ * get_arch_regstr() returns the name of the register in struct
+ * regdwarfnum_table from it's DWARF register number. If the register is not
+ * found in the table, this returns NULL;
+ */
+const char *get_arch_regstr(unsigned int n)
+{
+	const struct pt_regs_dwarfnum *roff;
+	for (roff = regdwarfnum_table; roff->name != NULL; roff++)
+		if (roff->dwarfnum == n)
+			return roff->name;
+	return NULL;
+}
diff --git a/tools/perf/arch/arm64/util/unwind.c b/tools/perf/arch/arm64/util/unwind.c
new file mode 100644
index 0000000..8d37a4c
--- /dev/null
+++ b/tools/perf/arch/arm64/util/unwind.c
@@ -0,0 +1,82 @@
+
+#include <errno.h>
+#include <libunwind.h>
+#include "perf_regs.h"
+#include "../../util/unwind.h"
+
+int unwind__arch_reg_id(int regnum)
+{
+	switch (regnum) {
+	case UNW_AARCH64_X0:
+		return PERF_REG_ARM64_X0;
+	case UNW_AARCH64_X1:
+		return PERF_REG_ARM64_X1;
+	case UNW_AARCH64_X2:
+		return PERF_REG_ARM64_X2;
+	case UNW_AARCH64_X3:
+		return PERF_REG_ARM64_X3;
+	case UNW_AARCH64_X4:
+		return PERF_REG_ARM64_X4;
+	case UNW_AARCH64_X5:
+		return PERF_REG_ARM64_X5;
+	case UNW_AARCH64_X6:
+		return PERF_REG_ARM64_X6;
+	case UNW_AARCH64_X7:
+		return PERF_REG_ARM64_X7;
+	case UNW_AARCH64_X8:
+		return PERF_REG_ARM64_X8;
+	case UNW_AARCH64_X9:
+		return PERF_REG_ARM64_X9;
+	case UNW_AARCH64_X10:
+		return PERF_REG_ARM64_X10;
+	case UNW_AARCH64_X11:
+		return PERF_REG_ARM64_X11;
+	case UNW_AARCH64_X12:
+		return PERF_REG_ARM64_X12;
+	case UNW_AARCH64_X13:
+		return PERF_REG_ARM64_X13;
+	case UNW_AARCH64_X14:
+		return PERF_REG_ARM64_X14;
+	case UNW_AARCH64_X15:
+		return PERF_REG_ARM64_X15;
+	case UNW_AARCH64_X16:
+		return PERF_REG_ARM64_X16;
+	case UNW_AARCH64_X17:
+		return PERF_REG_ARM64_X17;
+	case UNW_AARCH64_X18:
+		return PERF_REG_ARM64_X18;
+	case UNW_AARCH64_X19:
+		return PERF_REG_ARM64_X19;
+	case UNW_AARCH64_X20:
+		return PERF_REG_ARM64_X20;
+	case UNW_AARCH64_X21:
+		return PERF_REG_ARM64_X21;
+	case UNW_AARCH64_X22:
+		return PERF_REG_ARM64_X22;
+	case UNW_AARCH64_X23:
+		return PERF_REG_ARM64_X23;
+	case UNW_AARCH64_X24:
+		return PERF_REG_ARM64_X24;
+	case UNW_AARCH64_X25:
+		return PERF_REG_ARM64_X25;
+	case UNW_AARCH64_X26:
+		return PERF_REG_ARM64_X26;
+	case UNW_AARCH64_X27:
+		return PERF_REG_ARM64_X27;
+	case UNW_AARCH64_X28:
+		return PERF_REG_ARM64_X28;
+	case UNW_AARCH64_X29:
+		return PERF_REG_ARM64_X29;
+	case UNW_AARCH64_X30:
+		return PERF_REG_ARM64_LR;
+	case UNW_AARCH64_SP:
+		return PERF_REG_ARM64_SP;
+	case UNW_AARCH64_PC:
+		return PERF_REG_ARM64_PC;
+	default:
+		pr_err("unwind: invalid reg id %d\n", regnum);
+		return -EINVAL;
+	}
+
+	return -EINVAL;
+}
diff --git a/tools/perf/config/Makefile b/tools/perf/config/Makefile
index c48d449..5c0a6ed 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/config/Makefile
@@ -29,11 +29,17 @@ ifeq ($(ARCH),x86)
   endif
   NO_PERF_REGS := 0
 endif
+
 ifeq ($(ARCH),arm)
   NO_PERF_REGS := 0
   LIBUNWIND_LIBS = -lunwind -lunwind-arm
 endif
 
+ifeq ($(ARCH),arm64)
+  NO_PERF_REGS := 0
+  LIBUNWIND_LIBS = -lunwind -lunwind-aarch64
+endif
+
 ifeq ($(LIBUNWIND_LIBS),)
   NO_LIBUNWIND := 1
 else
@@ -327,7 +333,7 @@ ifndef NO_LIBUNWIND
     msg := $(warning No libunwind found, disabling post unwind support. Please install libunwind-dev[el] >= 1.1);
     NO_LIBUNWIND := 1
   else
-    ifeq ($(ARCH),arm)
+    ifeq ($(ARCH),$(filter $(ARCH),arm arm64))
       $(call feature_check,libunwind-debug-frame)
       ifneq ($(feature-libunwind-debug-frame), 1)
         msg := $(warning No debug_frame support found in libunwind);
-- 
1.7.11.7

^ permalink raw reply related

* [PATCH v6 0/3] perf: AARCH64 arch support
From: Jean Pihet @ 2014-02-03 18:18 UTC (permalink / raw)
  To: linux-arm-kernel

Add AARCH64 specific support. This includes the following:
- AARCH64 perf registers definition and hooks,
- compat mode registers use, i.e. profiling a 32-bit binary on
   a 64-bit system,
- unwinding using the dwarf information from the .debug_frame
   section of the ELF binary,
- unwinding using the frame pointer information; in 64-bit and
   compat modes.

Notes:
- the tools/perf change is submitted separately on LKML,
- support for unwinding using the dwarf information in compat
mode requires some changes to the libunwind code. Those changes
have been submitted on the libunwind ML and are in discussion.

Tested on ARMv7, ARMv8 and x86_64 platforms. The compat mode has been
tested on ARMv8 using statically built 32-bit binaries.


Jean Pihet (3):
  ARM64: perf: add support for perf registers API
  ARM64: perf: add support for frame pointer unwinding in compat mode
  ARM64: perf: support dwarf unwinding in compat mode

 arch/arm64/Kconfig                      |  2 +
 arch/arm64/include/asm/compat.h         |  2 +-
 arch/arm64/include/asm/ptrace.h         |  3 +-
 arch/arm64/include/uapi/asm/Kbuild      |  1 +
 arch/arm64/include/uapi/asm/perf_regs.h | 40 ++++++++++++++++++
 arch/arm64/kernel/Makefile              |  1 +
 arch/arm64/kernel/perf_event.c          | 75 +++++++++++++++++++++++++++++----
 arch/arm64/kernel/perf_regs.c           | 44 +++++++++++++++++++
 8 files changed, 158 insertions(+), 10 deletions(-)
 create mode 100644 arch/arm64/include/uapi/asm/perf_regs.h
 create mode 100644 arch/arm64/kernel/perf_regs.c

-- 
1.7.11.7

^ permalink raw reply

* [PATCH 1/3] ARM64: perf: add support for perf registers API
From: Jean Pihet @ 2014-02-03 18:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1391451509-31265-1-git-send-email-jean.pihet@linaro.org>

This patch implements the functions required for the perf registers API,
allowing the perf tool to interface kernel register dumps with libunwind
in order to provide userspace backtracing.
Compat mode is also supported.

Only the general purpose user space registers are exported, i.e.:
 PERF_REG_ARM_X0,
 ...
 PERF_REG_ARM_X28,
 PERF_REG_ARM_FP,
 PERF_REG_ARM_LR,
 PERF_REG_ARM_SP,
 PERF_REG_ARM_PC
and not the PERF_REG_ARM_V* registers.

Signed-off-by: Jean Pihet <jean.pihet@linaro.org>
Acked-by: Will Deacon <will.deacon@arm.com>
---
 arch/arm64/Kconfig                      |  2 ++
 arch/arm64/include/asm/ptrace.h         |  1 +
 arch/arm64/include/uapi/asm/Kbuild      |  1 +
 arch/arm64/include/uapi/asm/perf_regs.h | 40 ++++++++++++++++++++++++++++++
 arch/arm64/kernel/Makefile              |  1 +
 arch/arm64/kernel/perf_regs.c           | 44 +++++++++++++++++++++++++++++++++
 6 files changed, 89 insertions(+)
 create mode 100644 arch/arm64/include/uapi/asm/perf_regs.h
 create mode 100644 arch/arm64/kernel/perf_regs.c

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index dd4327f..e9899bb 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -37,6 +37,8 @@ config ARM64
 	select HAVE_HW_BREAKPOINT if PERF_EVENTS
 	select HAVE_MEMBLOCK
 	select HAVE_PERF_EVENTS
+	select HAVE_PERF_REGS
+	select HAVE_PERF_USER_STACK_DUMP
 	select IRQ_DOMAIN
 	select MODULES_USE_ELF_RELA
 	select NO_BOOTMEM
diff --git a/arch/arm64/include/asm/ptrace.h b/arch/arm64/include/asm/ptrace.h
index 0e7fa49..fbb0020 100644
--- a/arch/arm64/include/asm/ptrace.h
+++ b/arch/arm64/include/asm/ptrace.h
@@ -68,6 +68,7 @@
 
 /* Architecturally defined mapping between AArch32 and AArch64 registers */
 #define compat_usr(x)	regs[(x)]
+#define compat_fp	regs[11]
 #define compat_sp	regs[13]
 #define compat_lr	regs[14]
 #define compat_sp_hyp	regs[15]
diff --git a/arch/arm64/include/uapi/asm/Kbuild b/arch/arm64/include/uapi/asm/Kbuild
index e4b78bd..942376d 100644
--- a/arch/arm64/include/uapi/asm/Kbuild
+++ b/arch/arm64/include/uapi/asm/Kbuild
@@ -9,6 +9,7 @@ header-y += byteorder.h
 header-y += fcntl.h
 header-y += hwcap.h
 header-y += kvm_para.h
+header-y += perf_regs.h
 header-y += param.h
 header-y += ptrace.h
 header-y += setup.h
diff --git a/arch/arm64/include/uapi/asm/perf_regs.h b/arch/arm64/include/uapi/asm/perf_regs.h
new file mode 100644
index 0000000..172b831
--- /dev/null
+++ b/arch/arm64/include/uapi/asm/perf_regs.h
@@ -0,0 +1,40 @@
+#ifndef _ASM_ARM64_PERF_REGS_H
+#define _ASM_ARM64_PERF_REGS_H
+
+enum perf_event_arm_regs {
+	PERF_REG_ARM64_X0,
+	PERF_REG_ARM64_X1,
+	PERF_REG_ARM64_X2,
+	PERF_REG_ARM64_X3,
+	PERF_REG_ARM64_X4,
+	PERF_REG_ARM64_X5,
+	PERF_REG_ARM64_X6,
+	PERF_REG_ARM64_X7,
+	PERF_REG_ARM64_X8,
+	PERF_REG_ARM64_X9,
+	PERF_REG_ARM64_X10,
+	PERF_REG_ARM64_X11,
+	PERF_REG_ARM64_X12,
+	PERF_REG_ARM64_X13,
+	PERF_REG_ARM64_X14,
+	PERF_REG_ARM64_X15,
+	PERF_REG_ARM64_X16,
+	PERF_REG_ARM64_X17,
+	PERF_REG_ARM64_X18,
+	PERF_REG_ARM64_X19,
+	PERF_REG_ARM64_X20,
+	PERF_REG_ARM64_X21,
+	PERF_REG_ARM64_X22,
+	PERF_REG_ARM64_X23,
+	PERF_REG_ARM64_X24,
+	PERF_REG_ARM64_X25,
+	PERF_REG_ARM64_X26,
+	PERF_REG_ARM64_X27,
+	PERF_REG_ARM64_X28,
+	PERF_REG_ARM64_X29,
+	PERF_REG_ARM64_LR,
+	PERF_REG_ARM64_SP,
+	PERF_REG_ARM64_PC,
+	PERF_REG_ARM64_MAX,
+};
+#endif /* _ASM_ARM64_PERF_REGS_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 2d4554b..9a5d592 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -15,6 +15,7 @@ arm64-obj-$(CONFIG_COMPAT)		+= sys32.o kuser32.o signal32.o 	\
 					   sys_compat.o
 arm64-obj-$(CONFIG_MODULES)		+= arm64ksyms.o module.o
 arm64-obj-$(CONFIG_SMP)			+= smp.o smp_spin_table.o
+arm64-obj-$(CONFIG_PERF_EVENTS)		+= perf_regs.o
 arm64-obj-$(CONFIG_HW_PERF_EVENTS)	+= perf_event.o
 arm64-obj-$(CONFIG_HAVE_HW_BREAKPOINT)+= hw_breakpoint.o
 arm64-obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
diff --git a/arch/arm64/kernel/perf_regs.c b/arch/arm64/kernel/perf_regs.c
new file mode 100644
index 0000000..f2d6f0a
--- /dev/null
+++ b/arch/arm64/kernel/perf_regs.c
@@ -0,0 +1,44 @@
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/perf_event.h>
+#include <linux/bug.h>
+#include <asm/perf_regs.h>
+#include <asm/ptrace.h>
+
+u64 perf_reg_value(struct pt_regs *regs, int idx)
+{
+	if (WARN_ON_ONCE((u32)idx >= PERF_REG_ARM64_MAX))
+		return 0;
+
+	/*
+	 * Compat (i.e. 32 bit) mode:
+	 * - PC has been set in the pt_regs struct in kernel_entry,
+	 * - Handle SP and LR here.
+	 */
+	if (compat_user_mode(regs)) {
+		if ((u32)idx == PERF_REG_ARM64_SP)
+			return regs->compat_sp;
+		if ((u32)idx == PERF_REG_ARM64_LR)
+			return regs->compat_lr;
+	}
+
+	return regs->regs[idx];
+}
+
+#define REG_RESERVED (~((1ULL << PERF_REG_ARM64_MAX) - 1))
+
+int perf_reg_validate(u64 mask)
+{
+	if (!mask || mask & REG_RESERVED)
+		return -EINVAL;
+
+	return 0;
+}
+
+u64 perf_reg_abi(struct task_struct *task)
+{
+	if (is_compat_thread(task_thread_info(task)))
+		return PERF_SAMPLE_REGS_ABI_32;
+	else
+		return PERF_SAMPLE_REGS_ABI_64;
+}
-- 
1.7.11.7

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox