Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCHv3 16/19] arm64: use {COMPAT, }SYSCALL_DEFINE0 for sigreturn
From: Catalin Marinas @ 2018-06-19 15:48 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180618120310.39527-17-mark.rutland@arm.com>

On Mon, Jun 18, 2018 at 01:03:07PM +0100, Mark Rutland wrote:
> We don't currently annotate our various sigreturn functions as syscalls,
> as we need to do to use pt_regs syscall wrappers.
> 
> Let's mark them as real syscalls.
> 
> For compat_sys_sigreturn and compat_sys_rt_sigreturn, this changes the
> return type from int to long, matching the prototypes in sys32.c.
> 
> Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> Reviewed-by: Dominik Brodowski <linux@dominikbrodowski.net>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>

Acked-by: Catalin Marinas <catalin.marinas@arm.com>

^ permalink raw reply

* [PATCH 1/3] ARM: dts: imx53: Add 'ARM platform' node
From: Sebastian Reichel @ 2018-06-19 15:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1529329939-14117-1-git-send-email-festevam@gmail.com>

Hi,

On Mon, Jun 18, 2018 at 10:52:17AM -0300, Fabio Estevam wrote:
> From: Fabio Estevam <fabio.estevam@nxp.com>
> 
> As per the i.MX53 Reference Manual add an entry for the
> 'ARM platform' region in the device tree.
> 
> This is needed for accessing the ARM_GPC register to set the
> DBGEN bit, so that the debug clocks can be turned on.
> 
> Signed-off-by: Fabio Estevam <fabio.estevam@nxp.com>

Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
Tested-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>

-- Sebastian

> ---
>  arch/arm/boot/dts/imx53.dtsi | 5 +++++
>  1 file changed, 5 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/imx53.dtsi b/arch/arm/boot/dts/imx53.dtsi
> index 1a7a7bb..a70fbf4 100644
> --- a/arch/arm/boot/dts/imx53.dtsi
> +++ b/arch/arm/boot/dts/imx53.dtsi
> @@ -672,6 +672,11 @@
>  				status = "disabled";
>  			};
>  
> +			arm_platform: arm-platform at 63fa0000 {
> +				compatible = "fsl,imx53-arm-plat", "fsl,imx51-arm-plat";
> +				reg = <0x63fa0000 0x28>;
> +			};
> +
>  			owire: owire at 63fa4000 {
>  				compatible = "fsl,imx53-owire", "fsl,imx21-owire";
>  				reg = <0x63fa4000 0x4000>;
> -- 
> 2.7.4
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180619/35578c63/attachment.sig>

^ permalink raw reply

* [PATCH 2/3] ARM: dts: imx53: Add a label for the PMU node
From: Sebastian Reichel @ 2018-06-19 15:49 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1529329939-14117-2-git-send-email-festevam@gmail.com>

Hi,

On Mon, Jun 18, 2018 at 10:52:18AM -0300, Fabio Estevam wrote:
> From: Fabio Estevam <fabio.estevam@nxp.com>
> 
> Add a label for the PMU node so that the board dts may be able to
> pass the 'secure-reg-access' property like this:
> 
> &pmu {
> 	secure-reg-access;
> };
> 
> This also makes it consistent with the PMU node in imx6qdl.dtsi
> 
> Signed-off-by: Fabio Estevam <fabio.estevam@nxp.com>
> ---

Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
Tested-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>

-- Sebastian

>  arch/arm/boot/dts/imx53.dtsi | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/arm/boot/dts/imx53.dtsi b/arch/arm/boot/dts/imx53.dtsi
> index a70fbf4..263bd39f 100644
> --- a/arch/arm/boot/dts/imx53.dtsi
> +++ b/arch/arm/boot/dts/imx53.dtsi
> @@ -113,7 +113,7 @@
>  		};
>  	};
>  
> -	pmu {
> +	pmu: pmu {
>  		compatible = "arm,cortex-a8-pmu";
>  		interrupt-parent = <&tzic>;
>  		interrupts = <77>;
> -- 
> 2.7.4
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180619/46dda09f/attachment.sig>

^ permalink raw reply

* [PATCH] arm64: mm: mark tramp_pg_dir read-only
From: Will Deacon @ 2018-06-19 15:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAKv+Gu-x-e+M7_28m=zMeZ2=1p6DXWvu2L4K988jpfYjK+=JaA@mail.gmail.com>

On Tue, Jun 19, 2018 at 05:40:26PM +0200, Ard Biesheuvel wrote:
> On 19 June 2018 at 17:37, Will Deacon <will.deacon@arm.com> wrote:
> > On Tue, Jun 19, 2018 at 05:29:03PM +0200, Ard Biesheuvel wrote:
> >> On 19 June 2018 at 17:28, Will Deacon <will.deacon@arm.com> wrote:
> >> > On Tue, Jun 19, 2018 at 05:23:41PM +0200, Ard Biesheuvel wrote:
> >> >> On 19 June 2018 at 17:20, Will Deacon <will.deacon@arm.com> wrote:
> >> >> > Hi Ard,
> >> >> >
> >> >> > Sorry, I forgot to reply to this.
> >> >> >
> >> >> > On Wed, May 30, 2018 at 11:53:20AM +0200, Ard Biesheuvel wrote:
> >> >> >> On 30 May 2018 at 11:14, Will Deacon <will.deacon@arm.com> wrote:
> >> >> >> > On Wed, May 30, 2018 at 12:48:06PM +0800, YaoJun wrote:
> >> >> >> >> To protect against KSMA(Kernel Space Mirroring Attack), make
> >> >> >> >> tramp_pg_dir read-only. The principle of KSMA is to insert a
> >> >> >> >> carefully constructed PGD entry into the translation table.
> >> >> >> >> The type of this entry is block, which maps the kernel text
> >> >> >> >> and its access permissions bits are 01. The user process can
> >> >> >> >> then modify kernel text directly through this mapping. In this
> >> >> >> >> way, an arbitrary write can be converted to multiple arbitrary
> >> >> >> >> writes.
> >> >> >> >>
> >> >> >> >> Signed-off-by: YaoJun <yaojun8558363@gmail.com>
> >> >> >> >> ---
> >> >> >> >>  arch/arm64/mm/mmu.c | 4 ++++
> >> >> >> >>  1 file changed, 4 insertions(+)
> >> >> >> >>
> >> >> >> >> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> >> >> >> >> index 2dbb2c9f1ec1..ac4b22c7e435 100644
> >> >> >> >> --- a/arch/arm64/mm/mmu.c
> >> >> >> >> +++ b/arch/arm64/mm/mmu.c
> >> >> >> >> @@ -551,6 +551,10 @@ static int __init map_entry_trampoline(void)
> >> >> >> >>       __create_pgd_mapping(tramp_pg_dir, pa_start, TRAMP_VALIAS, PAGE_SIZE,
> >> >> >> >>                            prot, pgd_pgtable_alloc, 0);
> >> >> >> >>
> >> >> >> >> +     update_mapping_prot(__pa_symbol(tramp_pg_dir),
> >> >> >> >> +                             (unsigned long)tramp_pg_dir,
> >> >> >> >> +                             PGD_SIZE, PAGE_KERNEL_RO);
> >> >> >> >
> >> >> >> > Hmm, I like the idea but is there a risk that the page table has been mapped
> >> >> >> > as part of a block entry, which we can't safely split at this point (i.e.
> >> >> >> > we'll run into one of the BUG_ONs in the mapping code)?
> >> >> >> >
> >> >> >>
> >> >> >> We'd need to create a separate segment for it initially so the mapping
> >> >> >> is already at the right granularity.
> >> >> >
> >> >> > Why do you think that's the case? I can't see anything that guarantees this
> >> >> > for the page table itself.
> >> >> >
> >> >>
> >> >> We'd need to pass NO_BLOCK_MAPPINGS to map_kernel_segment(),
> >> >> obviously, but that shouldn't hurt since that segment is relatively
> >> >> tiny anyway.
> >> >
> >> > Ah right, with NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS, I agree that we're good.
> >> > Ideally, we'd move {idmap,swapper,tramp}_pg_dir into .rodata...
> >> >
> >>
> >> idmap and tramp yes, but swapper needs to be modifiable at runtime, no?
> >
> > Right, but couldn't we swizzle the permissions in e.g. set_pmd? We could
> > even predicate that on a sanity check of the prot.
> >
> 
> Swizzle the permissions of the entire .rodata segment? That sounds
> doable, but there is a whole class of data that belongs in this
> category, and I think PaX/grsecurity had an API for that (but I don't
> think anyone is upstreaming that yet). So let's not reinvent that
> wheel for swapper_pg_dir only.

I wasn't thinking of the whole .rodata segment -- just the page containing
the entry being modified, but ok. I was hoping to avoid getting involved
with the PaX/grsec stuff as it seems rather toxic from what I've seen.

Will

^ permalink raw reply

* [PATCHv3 17/19] arm64: use SYSCALL_DEFINE6() for mmap
From: Catalin Marinas @ 2018-06-19 15:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180618120310.39527-18-mark.rutland@arm.com>

On Mon, Jun 18, 2018 at 01:03:08PM +0100, Mark Rutland wrote:
> We don't currently annotate our mmap implementation as a syscall, as we
> need to do to use pt_regs syscall wrappers.
> 
> Let's mark it as a real syscall.
> 
> There should be no functional change as a result of this patch.
> 
> Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> Reviewed-by: Dominik Brodowski <linux@dominikbrodowski.net>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>

Acked-by: Catalin Marinas <catalin.marinas@arm.com>

^ permalink raw reply

* [PATCH 3/3] ARM: mx5: Set the DBGEN bit in ARM_GPC register
From: Sebastian Reichel @ 2018-06-19 15:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1529329939-14117-3-git-send-email-festevam@gmail.com>

Hi,

On Mon, Jun 18, 2018 at 10:52:19AM -0300, Fabio Estevam wrote:
> From: Fabio Estevam <fabio.estevam@nxp.com>
> 
> On i.MX51/i.MX53 it is necessery to set the DBGEN bit in 
> ARM_GPC register in order to turn on the debug clocks.
> 
> The DBGEN bit of ARM_GPC register has the following description
> in the i.MX53 Reference Manual:
> 
> "This allows the user to manually activate clocks within the debug
> system. This register bit directly controls the platform's dbgen_out
> output signal which connects to the DAP_SYS to enable all debug clocks.
> Once enabled, the clocks cannot be disabled except by asserting the
> disable_trace input of the DAP_SYS."
> 
> Based on a previous patch from Sebastian Reichel.
> 
> Signed-off-by: Fabio Estevam <fabio.estevam@nxp.com>
> ---

Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
Tested-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>

-- Sebastian

>  arch/arm/mach-imx/common.h     |  1 +
>  arch/arm/mach-imx/cpu-imx5.c   | 38 ++++++++++++++++++++++++++++++++++++++
>  arch/arm/mach-imx/mach-imx53.c |  2 ++
>  3 files changed, 41 insertions(+)
> 
> diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
> index c8d68e9..db78329 100644
> --- a/arch/arm/mach-imx/common.h
> +++ b/arch/arm/mach-imx/common.h
> @@ -62,6 +62,7 @@ void imx_gpc_set_arm_power_up_timing(u32 sw2iso, u32 sw);
>  void imx_gpc_set_arm_power_down_timing(u32 sw2iso, u32 sw);
>  void imx25_pm_init(void);
>  void imx27_pm_init(void);
> +void imx5_pmu_init(void);
>  
>  enum mxc_cpu_pwr_mode {
>  	WAIT_CLOCKED,		/* wfi only */
> diff --git a/arch/arm/mach-imx/cpu-imx5.c b/arch/arm/mach-imx/cpu-imx5.c
> index 4f2d1c7..6c5a055 100644
> --- a/arch/arm/mach-imx/cpu-imx5.c
> +++ b/arch/arm/mach-imx/cpu-imx5.c
> @@ -117,3 +117,41 @@ int mx53_revision(void)
>  	return mx5_cpu_rev;
>  }
>  EXPORT_SYMBOL(mx53_revision);
> +
> +#define ARM_GPC		0x4
> +#define DBGEN		BIT(16)
> +
> +/*
> + * This enables the DBGEN bit in ARM_GPC register, which is
> + * required for accessing some performance counter features.
> + * Technically it is only required while perf is used, but to
> + * keep the source code simple we just enable it all the time
> + * when the kernel configuration allows using the feature.
> + */
> +void imx5_pmu_init(void)
> +{
> +	void __iomem *arm_plat_base;
> +	struct device_node *np;
> +	u32 gpc;
> +
> +	if (!IS_ENABLED(CONFIG_ARM_PMU))
> +		return;
> +
> +	np = of_find_compatible_node(NULL, NULL, "arm,cortex-a8-pmu");
> +	if (!np)
> +		return;
> +
> +	np = of_find_compatible_node(NULL, NULL, "fsl,imx51-arm-plat");
> +	if (!np)
> +		return;
> +
> +	arm_plat_base = of_iomap(np, 0);
> +	if (!arm_plat_base) {
> +		pr_warn("Unable to map ARM platform registers\n");
> +		return;
> +	}
> +
> +	gpc = readl_relaxed(arm_plat_base + ARM_GPC);
> +	gpc |= DBGEN;
> +	writel_relaxed(gpc, arm_plat_base + ARM_GPC);
> +}
> diff --git a/arch/arm/mach-imx/mach-imx53.c b/arch/arm/mach-imx/mach-imx53.c
> index 07c2e8d..15fba89 100644
> --- a/arch/arm/mach-imx/mach-imx53.c
> +++ b/arch/arm/mach-imx/mach-imx53.c
> @@ -32,6 +32,8 @@ static void __init imx53_dt_init(void)
>  {
>  	imx_src_init();
>  
> +	imx5_pmu_init();
> +
>  	imx_aips_allow_unprivileged_access("fsl,imx53-aipstz");
>  }
>  
> -- 
> 2.7.4
> 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180619/956e0d5d/attachment-0001.sig>

^ permalink raw reply

* [PATCHv3 18/19] arm64: convert compat wrappers to C
From: Catalin Marinas @ 2018-06-19 15:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180618120310.39527-19-mark.rutland@arm.com>

On Mon, Jun 18, 2018 at 01:03:09PM +0100, Mark Rutland wrote:
> In preparation for converting to pt_regs syscall wrappers, convert our
> existing compat wrappers to C. This will allow the pt_regs wrappers to
> be automatically generated, and will allow for the compat register
> manipulation to be folded in with the pt_regs accesses.
> 
> To avoid confusion with the upcoming pt_regs wrappers and existing
> compat wrappers provided by core code, the C wrappers are renamed to
> compat_sys_aarch32_<syscall>.
> 
> With the assembly wrappers gone, we can get rid of entry32.S and the
> associated boilerplate.
> 
> Note that these must call the ksys_* syscall entry points, as the usual
> sys_* entry points will be modified to take a single pt_regs pointer
> argument.
> 
> Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>

Acked-by: Catalin Marinas <catalin.marinas@arm.com>

^ permalink raw reply

* [PATCH] arm64: mm: mark tramp_pg_dir read-only
From: Ard Biesheuvel @ 2018-06-19 15:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180619155001.GP13984@arm.com>

On 19 June 2018 at 17:50, Will Deacon <will.deacon@arm.com> wrote:
> On Tue, Jun 19, 2018 at 05:40:26PM +0200, Ard Biesheuvel wrote:
>> On 19 June 2018 at 17:37, Will Deacon <will.deacon@arm.com> wrote:
>> > On Tue, Jun 19, 2018 at 05:29:03PM +0200, Ard Biesheuvel wrote:
>> >> On 19 June 2018 at 17:28, Will Deacon <will.deacon@arm.com> wrote:
>> >> > On Tue, Jun 19, 2018 at 05:23:41PM +0200, Ard Biesheuvel wrote:
>> >> >> On 19 June 2018 at 17:20, Will Deacon <will.deacon@arm.com> wrote:
>> >> >> > Hi Ard,
>> >> >> >
>> >> >> > Sorry, I forgot to reply to this.
>> >> >> >
>> >> >> > On Wed, May 30, 2018 at 11:53:20AM +0200, Ard Biesheuvel wrote:
>> >> >> >> On 30 May 2018 at 11:14, Will Deacon <will.deacon@arm.com> wrote:
>> >> >> >> > On Wed, May 30, 2018 at 12:48:06PM +0800, YaoJun wrote:
>> >> >> >> >> To protect against KSMA(Kernel Space Mirroring Attack), make
>> >> >> >> >> tramp_pg_dir read-only. The principle of KSMA is to insert a
>> >> >> >> >> carefully constructed PGD entry into the translation table.
>> >> >> >> >> The type of this entry is block, which maps the kernel text
>> >> >> >> >> and its access permissions bits are 01. The user process can
>> >> >> >> >> then modify kernel text directly through this mapping. In this
>> >> >> >> >> way, an arbitrary write can be converted to multiple arbitrary
>> >> >> >> >> writes.
>> >> >> >> >>
>> >> >> >> >> Signed-off-by: YaoJun <yaojun8558363@gmail.com>
>> >> >> >> >> ---
>> >> >> >> >>  arch/arm64/mm/mmu.c | 4 ++++
>> >> >> >> >>  1 file changed, 4 insertions(+)
>> >> >> >> >>
>> >> >> >> >> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
>> >> >> >> >> index 2dbb2c9f1ec1..ac4b22c7e435 100644
>> >> >> >> >> --- a/arch/arm64/mm/mmu.c
>> >> >> >> >> +++ b/arch/arm64/mm/mmu.c
>> >> >> >> >> @@ -551,6 +551,10 @@ static int __init map_entry_trampoline(void)
>> >> >> >> >>       __create_pgd_mapping(tramp_pg_dir, pa_start, TRAMP_VALIAS, PAGE_SIZE,
>> >> >> >> >>                            prot, pgd_pgtable_alloc, 0);
>> >> >> >> >>
>> >> >> >> >> +     update_mapping_prot(__pa_symbol(tramp_pg_dir),
>> >> >> >> >> +                             (unsigned long)tramp_pg_dir,
>> >> >> >> >> +                             PGD_SIZE, PAGE_KERNEL_RO);
>> >> >> >> >
>> >> >> >> > Hmm, I like the idea but is there a risk that the page table has been mapped
>> >> >> >> > as part of a block entry, which we can't safely split at this point (i.e.
>> >> >> >> > we'll run into one of the BUG_ONs in the mapping code)?
>> >> >> >> >
>> >> >> >>
>> >> >> >> We'd need to create a separate segment for it initially so the mapping
>> >> >> >> is already at the right granularity.
>> >> >> >
>> >> >> > Why do you think that's the case? I can't see anything that guarantees this
>> >> >> > for the page table itself.
>> >> >> >
>> >> >>
>> >> >> We'd need to pass NO_BLOCK_MAPPINGS to map_kernel_segment(),
>> >> >> obviously, but that shouldn't hurt since that segment is relatively
>> >> >> tiny anyway.
>> >> >
>> >> > Ah right, with NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS, I agree that we're good.
>> >> > Ideally, we'd move {idmap,swapper,tramp}_pg_dir into .rodata...
>> >> >
>> >>
>> >> idmap and tramp yes, but swapper needs to be modifiable at runtime, no?
>> >
>> > Right, but couldn't we swizzle the permissions in e.g. set_pmd? We could
>> > even predicate that on a sanity check of the prot.
>> >
>>
>> Swizzle the permissions of the entire .rodata segment? That sounds
>> doable, but there is a whole class of data that belongs in this
>> category, and I think PaX/grsecurity had an API for that (but I don't
>> think anyone is upstreaming that yet). So let's not reinvent that
>> wheel for swapper_pg_dir only.
>
> I wasn't thinking of the whole .rodata segment -- just the page containing
> the entry being modified, but ok.

That means we will need to map .rodata down to pages as well, or at
least avoid contiguous mappings.

> I was hoping to avoid getting involved
> with the PaX/grsec stuff as it seems rather toxic from what I've seen.
>

Indeed.

^ permalink raw reply

* [PATCH 0/5] RFC: Mezzanine handling for 96boards
From: Rob Herring @ 2018-06-19 15:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180618074556.6944-1-linus.walleij@linaro.org>

On Mon, Jun 18, 2018 at 1:45 AM, Linus Walleij <linus.walleij@linaro.org> wrote:
> This is a proposal for how to handle the non-discoverable
> 96boards plug-in expansion boards called "mezzanines" in the
> Linux kernel. It is a working RFC series meant for discussion
> at the moment.
>
> The RFC was done on the brand new Ultra96 board from Xilinx
> with a Secure96 mezzanine expansion board. The main part
> is in patch 4, the rest is enabling and examples.
>
> The code can be obtained from here:
> https://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-integrator.git/log/?h=ultra96
>
> You can for example probably augment the DTS file for any
> upstream-supported 96board and get the Secure96 going with
> it with minor efforts.
>
> TODO:
>
> - Proper device tree bindings for the connector, for now
>   look at the example.
>
> - Discuss whether to actually do this or just take it all and
>   flush it down the drain because the community doesn't like
>   it. I'm not one of those especially infatuated with my own code,
>   I always stay by the old programming project management mantra
>   to calculate to make one version and throw it away as stepping
>   stone to a good final design.
>
> - Placement: putting this in drivers/bus is just an example.
>   drivers/platform/96boards-mezzanines is fine too, maybe better?
>
> - I am especially curious about input from Andy and Mika from
>   the Intel/ACPI camp on what they have seen for non-discoverable
>   plug-in boards. Does this problem even exist in the Intel
>   world, or not...
>
> Background:
>
> - These boards connect on a custom connector on this family
>   of boards. The relationship is many-to-many with the connector
>   as nexus. The electronic standard for the connector is specified:
>   https://github.com/96boards/documentation/blob/master/Specifications/96Boards-CE-Specification.pdf
>   Example mezzanines:
>   https://www.96boards.org/documentation/mezzanine/
>
> - These boards have siblings on other platforms, the problem
>   scope is similar with BeagleBone "capes":
>   https://beagleboard.org/capes
>   Raspberry Pi expansion boards:
>   https://www.abelectronics.co.uk/products/18/raspberry-pi-expansion-boards
>   Intel Edison, Galileo, Joule also have expansion boards.
>
> Idea: add a driver for the connector itself and tie it in to
> the device tree with a compatible string. Since the boards
> are non-discoverable two mechanisms are provided to discover
> them:
>
> - Add a very simple device tree node with just a compatible
>   string for the board in the node. This will be simple to
>   add from e.g. a boot loader or as an overlay from userspace.
>
>   board {
>         compatible = "96boards,secure96";
>   };
>
>
> - Echo 1 > boardname into a sysfs file to populate the
>   board and echo 0 > boardname to depopulate it. This
>   makes it easy to even switch out expansion boards at
>   runtime, if allowed by the electronics.
>
>   > cd /sys/devices/platform/connector
>   > echo 1 > secure96
>   lscon connector: called mezzanine_store on secure96
>   lscon connector: populate secure96
>   at24 1-0050: 2048 byte 24c128 EEPROM, writable, 128 bytes/write
>   atmel-ecc 1-0060: configuration zone is unlocked
>   tpm_tis_spi spi0.0: 2.0 TPM (device-id 0x1B, rev-id 16)
>   (...)
>
> What this patch set does not do:
>
> - It does not use device tree or ACPI DSDT or any other
>   hardware decription language to model the contents of the
>   board per se. Instead the boards buses are populated
>   directly with platform devices.
>
> Predictable complaints about this design:
>
> Q: This is not device tree overlays. Why is it not device
>    tree overlays?
>
> A1: Right tool for the job, overlays are complex and the
>     plan to get it in place seems to be spanning years, this
>     is a few devices on simple busses and it works today.
>     Using this approach I can already work on shaping up
>     drivers for the mezzanine board devices as proved by:
>     https://marc.info/?l=linux-crypto-vger&m=152820660120590&w=2
>     https://marc.info/?l=linux-crypto-vger&m=152820662820595&w=2
>     (...)
>
>     I can work on drivers for the chips on the
>     Secure96 mezzanine board. It's just an example of
>     what the mezzanine community can do.
>     Now they are hacking around in userspace instead of
>     doing/reusing kernel drivers for their stuff:
>     https://github.com/jbech-linaro/secure96
>
>     This way we can bring developers for these components
>     into the kernel community instead of telling them to
>     wait for some big infrastructure that comes later
>     before they can contribute their stuff.
>
> A2: Overlays does not solve the problem if the system runs
>     ACPI, and what about if the same connector[s] appear
>     on a server board, servers use ACPI. Also notice
>     that Intel have development boards with non-discoverable
>     expansion boards as well. They just will not use
>     device tree.
>
> A3: Overlays is Big Upfront Design.
>     https://en.wikipedia.org/wiki/Big_Design_Up_Front
>     This way of designing things is associated with the
>     (pejorative term) "waterfall model" which is out of
>     fashion as a way of doing development. I think I am not
>     the only one slightly annoyed by the fact that device
>     tree overlays is now starting to look like a very
>     big very upfront design. It's just not possible to get
>     something up and running in small iterative steps with
>     device tree overlays. Instead huge efforts are
>     required and it involves major possible showstoppers
>     and uncertain outcome as indicated by Frank's TODO:
>     https://elinux.org/Frank's_Evolving_Overlay_Thoughts

I don't agree. This can be broken down into various smaller mostly
independent problems. Overlay handling is mostly an orthogonal
problem. The exception is that we need to ensure bindings allow a
decoupling of upstream of the connector and downstream of the
connector so the downstream part can be a reusable overlay. Defining
anything while ignoring this known criteria would be a mistake.

The list is roughly like this:

- Connector node binding and probing infrastructure
- GPIO (already done w/ gpio-map binding)
- I2C
- SPI
- Pinmux
- clocks
- OF graph (displays, cameras, etc.)
- USB (re-use the USB connector binding for non-standard connectors)
- Userspace interface

We don't have to support every interface from the start. The bindings
and corresponding kernel support can be designed 1-by-1 for the most
part. Start with something simple like a GPIO LED on a mezzanine. Once
the base is functionality is there, the other parts can be worked on
incrementally. We can punt any overlay handling to the bootloader
initially. That punts all the issues around overlays like designing a
userspace interface, where overlays are located (filesystem, passed
from bootloader, built into the kernel), when they are loaded, and how
to specify which overlays to load. Most of Frank's list is related to
these issues.

Rob

^ permalink raw reply

* [PATCHv3 13/19] kernel: add ksys_personality()
From: Mark Rutland @ 2018-06-19 15:53 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180619154541.7uugqiquxzkcpfwj@armageddon.cambridge.arm.com>

On Tue, Jun 19, 2018 at 04:45:41PM +0100, Catalin Marinas wrote:
> On Mon, Jun 18, 2018 at 01:03:04PM +0100, Mark Rutland wrote:
> > diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
> > index 73810808cdf2..14312d334345 100644
> > --- a/include/linux/syscalls.h
> > +++ b/include/linux/syscalls.h
> > @@ -80,6 +80,7 @@ union bpf_attr;
> >  #include <linux/unistd.h>
> >  #include <linux/quota.h>
> >  #include <linux/key.h>
> > +#include <linux/personality.h>
> >  #include <trace/syscall.h>
> >  
> >  #ifdef CONFIG_ARCH_HAS_SYSCALL_WRAPPER
> > @@ -1277,4 +1278,14 @@ static inline long ksys_truncate(const char __user *pathname, loff_t length)
> >  	return do_sys_truncate(pathname, length);
> >  }
> >  
> > +static inline unsigned int ksys_personality(unsigned int personality)
> > +{
> > +	unsigned int old = current->personality;
> > +
> > +	if (personality != 0xffffffff)
> > +		set_personality(personality);
> > +
> > +	return old;
> > +}
> > +
> >  #endif
> 
> It looks like this is identical to sys_personality() in
> kernel/exec_domain.c. Should you call ksys_personality() from there
> directly (a few lines saved)?

I had originally done so [1], but Christophe preferred that I open-code
the logic [2].

Thanks,
Mark.

[1] https://lkml.kernel.org/r/20180514094640.27569-13-mark.rutland at arm.com
[2] https://lkml.kernel.org/r/20180514120756.GA11638 at infradead.org

^ permalink raw reply

* [PATCH] arm64: mm: mark tramp_pg_dir read-only
From: Will Deacon @ 2018-06-19 15:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAKv+Gu-fA61TbOWOfMbwffyJEzMDKrOSOOw0nbNbeO-xm8YbaA@mail.gmail.com>

On Tue, Jun 19, 2018 at 05:51:46PM +0200, Ard Biesheuvel wrote:
> On 19 June 2018 at 17:50, Will Deacon <will.deacon@arm.com> wrote:
> > On Tue, Jun 19, 2018 at 05:40:26PM +0200, Ard Biesheuvel wrote:
> >> On 19 June 2018 at 17:37, Will Deacon <will.deacon@arm.com> wrote:
> >> > On Tue, Jun 19, 2018 at 05:29:03PM +0200, Ard Biesheuvel wrote:
> >> >> On 19 June 2018 at 17:28, Will Deacon <will.deacon@arm.com> wrote:
> >> >> > On Tue, Jun 19, 2018 at 05:23:41PM +0200, Ard Biesheuvel wrote:
> >> >> >> On 19 June 2018 at 17:20, Will Deacon <will.deacon@arm.com> wrote:
> >> >> >> > On Wed, May 30, 2018 at 11:53:20AM +0200, Ard Biesheuvel wrote:
> >> >> >> >> On 30 May 2018 at 11:14, Will Deacon <will.deacon@arm.com> wrote:
> >> >> >> >> > On Wed, May 30, 2018 at 12:48:06PM +0800, YaoJun wrote:
> >> >> >> >> >> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
> >> >> >> >> >> index 2dbb2c9f1ec1..ac4b22c7e435 100644
> >> >> >> >> >> --- a/arch/arm64/mm/mmu.c
> >> >> >> >> >> +++ b/arch/arm64/mm/mmu.c
> >> >> >> >> >> @@ -551,6 +551,10 @@ static int __init map_entry_trampoline(void)
> >> >> >> >> >>       __create_pgd_mapping(tramp_pg_dir, pa_start, TRAMP_VALIAS, PAGE_SIZE,
> >> >> >> >> >>                            prot, pgd_pgtable_alloc, 0);
> >> >> >> >> >>
> >> >> >> >> >> +     update_mapping_prot(__pa_symbol(tramp_pg_dir),
> >> >> >> >> >> +                             (unsigned long)tramp_pg_dir,
> >> >> >> >> >> +                             PGD_SIZE, PAGE_KERNEL_RO);
> >> >> >> >> >
> >> >> >> >> > Hmm, I like the idea but is there a risk that the page table has been mapped
> >> >> >> >> > as part of a block entry, which we can't safely split at this point (i.e.
> >> >> >> >> > we'll run into one of the BUG_ONs in the mapping code)?
> >> >> >> >> >
> >> >> >> >>
> >> >> >> >> We'd need to create a separate segment for it initially so the mapping
> >> >> >> >> is already at the right granularity.
> >> >> >> >
> >> >> >> > Why do you think that's the case? I can't see anything that guarantees this
> >> >> >> > for the page table itself.
> >> >> >> >
> >> >> >>
> >> >> >> We'd need to pass NO_BLOCK_MAPPINGS to map_kernel_segment(),
> >> >> >> obviously, but that shouldn't hurt since that segment is relatively
> >> >> >> tiny anyway.
> >> >> >
> >> >> > Ah right, with NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS, I agree that we're good.
> >> >> > Ideally, we'd move {idmap,swapper,tramp}_pg_dir into .rodata...
> >> >> >
> >> >>
> >> >> idmap and tramp yes, but swapper needs to be modifiable at runtime, no?
> >> >
> >> > Right, but couldn't we swizzle the permissions in e.g. set_pmd? We could
> >> > even predicate that on a sanity check of the prot.
> >> >
> >>
> >> Swizzle the permissions of the entire .rodata segment? That sounds
> >> doable, but there is a whole class of data that belongs in this
> >> category, and I think PaX/grsecurity had an API for that (but I don't
> >> think anyone is upstreaming that yet). So let's not reinvent that
> >> wheel for swapper_pg_dir only.
> >
> > I wasn't thinking of the whole .rodata segment -- just the page containing
> > the entry being modified, but ok.
> 
> That means we will need to map .rodata down to pages as well, or at
> least avoid contiguous mappings.

Doesn't it already avoid those?

Will

^ permalink raw reply

* [PATCH] arm64: mm: mark tramp_pg_dir read-only
From: Ard Biesheuvel @ 2018-06-19 16:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180619155512.GQ13984@arm.com>

On 19 June 2018 at 17:55, Will Deacon <will.deacon@arm.com> wrote:
> On Tue, Jun 19, 2018 at 05:51:46PM +0200, Ard Biesheuvel wrote:
>> On 19 June 2018 at 17:50, Will Deacon <will.deacon@arm.com> wrote:
>> > On Tue, Jun 19, 2018 at 05:40:26PM +0200, Ard Biesheuvel wrote:
>> >> On 19 June 2018 at 17:37, Will Deacon <will.deacon@arm.com> wrote:
>> >> > On Tue, Jun 19, 2018 at 05:29:03PM +0200, Ard Biesheuvel wrote:
>> >> >> On 19 June 2018 at 17:28, Will Deacon <will.deacon@arm.com> wrote:
>> >> >> > On Tue, Jun 19, 2018 at 05:23:41PM +0200, Ard Biesheuvel wrote:
>> >> >> >> On 19 June 2018 at 17:20, Will Deacon <will.deacon@arm.com> wrote:
>> >> >> >> > On Wed, May 30, 2018 at 11:53:20AM +0200, Ard Biesheuvel wrote:
>> >> >> >> >> On 30 May 2018 at 11:14, Will Deacon <will.deacon@arm.com> wrote:
>> >> >> >> >> > On Wed, May 30, 2018 at 12:48:06PM +0800, YaoJun wrote:
>> >> >> >> >> >> diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
>> >> >> >> >> >> index 2dbb2c9f1ec1..ac4b22c7e435 100644
>> >> >> >> >> >> --- a/arch/arm64/mm/mmu.c
>> >> >> >> >> >> +++ b/arch/arm64/mm/mmu.c
>> >> >> >> >> >> @@ -551,6 +551,10 @@ static int __init map_entry_trampoline(void)
>> >> >> >> >> >>       __create_pgd_mapping(tramp_pg_dir, pa_start, TRAMP_VALIAS, PAGE_SIZE,
>> >> >> >> >> >>                            prot, pgd_pgtable_alloc, 0);
>> >> >> >> >> >>
>> >> >> >> >> >> +     update_mapping_prot(__pa_symbol(tramp_pg_dir),
>> >> >> >> >> >> +                             (unsigned long)tramp_pg_dir,
>> >> >> >> >> >> +                             PGD_SIZE, PAGE_KERNEL_RO);
>> >> >> >> >> >
>> >> >> >> >> > Hmm, I like the idea but is there a risk that the page table has been mapped
>> >> >> >> >> > as part of a block entry, which we can't safely split at this point (i.e.
>> >> >> >> >> > we'll run into one of the BUG_ONs in the mapping code)?
>> >> >> >> >> >
>> >> >> >> >>
>> >> >> >> >> We'd need to create a separate segment for it initially so the mapping
>> >> >> >> >> is already at the right granularity.
>> >> >> >> >
>> >> >> >> > Why do you think that's the case? I can't see anything that guarantees this
>> >> >> >> > for the page table itself.
>> >> >> >> >
>> >> >> >>
>> >> >> >> We'd need to pass NO_BLOCK_MAPPINGS to map_kernel_segment(),
>> >> >> >> obviously, but that shouldn't hurt since that segment is relatively
>> >> >> >> tiny anyway.
>> >> >> >
>> >> >> > Ah right, with NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS, I agree that we're good.
>> >> >> > Ideally, we'd move {idmap,swapper,tramp}_pg_dir into .rodata...
>> >> >> >
>> >> >>
>> >> >> idmap and tramp yes, but swapper needs to be modifiable at runtime, no?
>> >> >
>> >> > Right, but couldn't we swizzle the permissions in e.g. set_pmd? We could
>> >> > even predicate that on a sanity check of the prot.
>> >> >
>> >>
>> >> Swizzle the permissions of the entire .rodata segment? That sounds
>> >> doable, but there is a whole class of data that belongs in this
>> >> category, and I think PaX/grsecurity had an API for that (but I don't
>> >> think anyone is upstreaming that yet). So let's not reinvent that
>> >> wheel for swapper_pg_dir only.
>> >
>> > I wasn't thinking of the whole .rodata segment -- just the page containing
>> > the entry being modified, but ok.
>>
>> That means we will need to map .rodata down to pages as well, or at
>> least avoid contiguous mappings.
>
> Doesn't it already avoid those?
>

You are right, it does.

^ permalink raw reply

* [PATCH -tip v6 05/27] ARM: kprobes: Remove jprobe arm implementation
From: Masami Hiramatsu @ 2018-06-19 16:06 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <152942424698.15209.15245996287444292393.stgit@devbox>

Remove arch dependent setjump/longjump functions
and unused fields in kprobe_ctlblk for jprobes
from arch/arm.

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Russell King <linux@armlinux.org.uk>
Cc: linux-arm-kernel at lists.infradead.org
---
 arch/arm/include/asm/kprobes.h |    2 -
 arch/arm/include/asm/probes.h  |    1 
 arch/arm/probes/kprobes/core.c |  114 ----------------------------------------
 3 files changed, 117 deletions(-)

diff --git a/arch/arm/include/asm/kprobes.h b/arch/arm/include/asm/kprobes.h
index 59655459da59..82290f212d8e 100644
--- a/arch/arm/include/asm/kprobes.h
+++ b/arch/arm/include/asm/kprobes.h
@@ -44,8 +44,6 @@ struct prev_kprobe {
 struct kprobe_ctlblk {
 	unsigned int kprobe_status;
 	struct prev_kprobe prev_kprobe;
-	struct pt_regs jprobe_saved_regs;
-	char jprobes_stack[MAX_STACK_SIZE];
 };
 
 void arch_remove_kprobe(struct kprobe *);
diff --git a/arch/arm/include/asm/probes.h b/arch/arm/include/asm/probes.h
index 1e5b9bb92270..991c9127c650 100644
--- a/arch/arm/include/asm/probes.h
+++ b/arch/arm/include/asm/probes.h
@@ -51,7 +51,6 @@ struct arch_probes_insn {
  * We assume one instruction can consume at most 64 bytes stack, which is
  * 'push {r0-r15}'. Instructions consume more or unknown stack space like
  * 'str r0, [sp, #-80]' and 'str r0, [sp, r1]' should be prohibit to probe.
- * Both kprobe and jprobe use this macro.
  */
 #define MAX_STACK_SIZE			64
 
diff --git a/arch/arm/probes/kprobes/core.c b/arch/arm/probes/kprobes/core.c
index e90cc8a08186..23562111c511 100644
--- a/arch/arm/probes/kprobes/core.c
+++ b/arch/arm/probes/kprobes/core.c
@@ -47,9 +47,6 @@
 			   (unsigned long)(addr) +	\
 			   (size))
 
-/* Used as a marker in ARM_pc to note when we're in a jprobe. */
-#define JPROBE_MAGIC_ADDR		0xffffffff
-
 DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL;
 DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk);
 
@@ -521,117 +518,6 @@ void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
 	regs->ARM_lr = (unsigned long)&kretprobe_trampoline;
 }
 
-int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
-{
-	struct jprobe *jp = container_of(p, struct jprobe, kp);
-	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
-	long sp_addr = regs->ARM_sp;
-	long cpsr;
-
-	kcb->jprobe_saved_regs = *regs;
-	memcpy(kcb->jprobes_stack, (void *)sp_addr, MIN_STACK_SIZE(sp_addr));
-	regs->ARM_pc = (long)jp->entry;
-
-	cpsr = regs->ARM_cpsr | PSR_I_BIT;
-#ifdef CONFIG_THUMB2_KERNEL
-	/* Set correct Thumb state in cpsr */
-	if (regs->ARM_pc & 1)
-		cpsr |= PSR_T_BIT;
-	else
-		cpsr &= ~PSR_T_BIT;
-#endif
-	regs->ARM_cpsr = cpsr;
-
-	preempt_disable();
-	return 1;
-}
-
-void __kprobes jprobe_return(void)
-{
-	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
-
-	__asm__ __volatile__ (
-		/*
-		 * Setup an empty pt_regs. Fill SP and PC fields as
-		 * they're needed by longjmp_break_handler.
-		 *
-		 * We allocate some slack between the original SP and start of
-		 * our fabricated regs. To be precise we want to have worst case
-		 * covered which is STMFD with all 16 regs so we allocate 2 *
-		 * sizeof(struct_pt_regs)).
-		 *
-		 * This is to prevent any simulated instruction from writing
-		 * over the regs when they are accessing the stack.
-		 */
-#ifdef CONFIG_THUMB2_KERNEL
-		"sub    r0, %0, %1		\n\t"
-		"mov    sp, r0			\n\t"
-#else
-		"sub    sp, %0, %1		\n\t"
-#endif
-		"ldr    r0, ="__stringify(JPROBE_MAGIC_ADDR)"\n\t"
-		"str    %0, [sp, %2]		\n\t"
-		"str    r0, [sp, %3]		\n\t"
-		"mov    r0, sp			\n\t"
-		"bl     kprobe_handler		\n\t"
-
-		/*
-		 * Return to the context saved by setjmp_pre_handler
-		 * and restored by longjmp_break_handler.
-		 */
-#ifdef CONFIG_THUMB2_KERNEL
-		"ldr	lr, [sp, %2]		\n\t" /* lr = saved sp */
-		"ldrd	r0, r1, [sp, %5]	\n\t" /* r0,r1 = saved lr,pc */
-		"ldr	r2, [sp, %4]		\n\t" /* r2 = saved psr */
-		"stmdb	lr!, {r0, r1, r2}	\n\t" /* push saved lr and */
-						      /* rfe context */
-		"ldmia	sp, {r0 - r12}		\n\t"
-		"mov	sp, lr			\n\t"
-		"ldr	lr, [sp], #4		\n\t"
-		"rfeia	sp!			\n\t"
-#else
-		"ldr	r0, [sp, %4]		\n\t"
-		"msr	cpsr_cxsf, r0		\n\t"
-		"ldmia	sp, {r0 - pc}		\n\t"
-#endif
-		:
-		: "r" (kcb->jprobe_saved_regs.ARM_sp),
-		  "I" (sizeof(struct pt_regs) * 2),
-		  "J" (offsetof(struct pt_regs, ARM_sp)),
-		  "J" (offsetof(struct pt_regs, ARM_pc)),
-		  "J" (offsetof(struct pt_regs, ARM_cpsr)),
-		  "J" (offsetof(struct pt_regs, ARM_lr))
-		: "memory", "cc");
-}
-
-int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
-{
-	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
-	long stack_addr = kcb->jprobe_saved_regs.ARM_sp;
-	long orig_sp = regs->ARM_sp;
-	struct jprobe *jp = container_of(p, struct jprobe, kp);
-
-	if (regs->ARM_pc == JPROBE_MAGIC_ADDR) {
-		if (orig_sp != stack_addr) {
-			struct pt_regs *saved_regs =
-				(struct pt_regs *)kcb->jprobe_saved_regs.ARM_sp;
-			printk("current sp %lx does not match saved sp %lx\n",
-			       orig_sp, stack_addr);
-			printk("Saved registers for jprobe %p\n", jp);
-			show_regs(saved_regs);
-			printk("Current registers\n");
-			show_regs(regs);
-			BUG();
-		}
-		*regs = kcb->jprobe_saved_regs;
-		memcpy((void *)stack_addr, kcb->jprobes_stack,
-		       MIN_STACK_SIZE(stack_addr));
-		preempt_enable_no_resched();
-		return 1;
-	}
-	return 0;
-}
-
 int __kprobes arch_trampoline_kprobe(struct kprobe *p)
 {
 	return 0;

^ permalink raw reply related

* [PATCH -tip v6 06/27] arm64: kprobes: Remove jprobe implementation
From: Masami Hiramatsu @ 2018-06-19 16:07 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <152942424698.15209.15245996287444292393.stgit@devbox>

Remove arch dependent setjump/longjump functions
and unused fields in kprobe_ctlblk for jprobes
from arch/arm64.

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Acked-by: Will Deacon <will.deacon@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: linux-arm-kernel at lists.infradead.org
---
 arch/arm64/include/asm/kprobes.h   |    1 -
 arch/arm64/kernel/probes/kprobes.c |   68 ------------------------------------
 2 files changed, 69 deletions(-)

diff --git a/arch/arm64/include/asm/kprobes.h b/arch/arm64/include/asm/kprobes.h
index 6deb8d726041..d5a44cf859e9 100644
--- a/arch/arm64/include/asm/kprobes.h
+++ b/arch/arm64/include/asm/kprobes.h
@@ -48,7 +48,6 @@ struct kprobe_ctlblk {
 	unsigned long saved_irqflag;
 	struct prev_kprobe prev_kprobe;
 	struct kprobe_step_ctx ss_ctx;
-	struct pt_regs jprobe_saved_regs;
 };
 
 void arch_remove_kprobe(struct kprobe *);
diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
index d849d9804011..3ca2351109a6 100644
--- a/arch/arm64/kernel/probes/kprobes.c
+++ b/arch/arm64/kernel/probes/kprobes.c
@@ -465,74 +465,6 @@ kprobe_breakpoint_handler(struct pt_regs *regs, unsigned int esr)
 	return DBG_HOOK_HANDLED;
 }
 
-int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
-{
-	struct jprobe *jp = container_of(p, struct jprobe, kp);
-	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
-
-	kcb->jprobe_saved_regs = *regs;
-	/*
-	 * Since we can't be sure where in the stack frame "stacked"
-	 * pass-by-value arguments are stored we just don't try to
-	 * duplicate any of the stack. Do not use jprobes on functions that
-	 * use more than 64 bytes (after padding each to an 8 byte boundary)
-	 * of arguments, or pass individual arguments larger than 16 bytes.
-	 */
-
-	instruction_pointer_set(regs, (unsigned long) jp->entry);
-	preempt_disable();
-	pause_graph_tracing();
-	return 1;
-}
-
-void __kprobes jprobe_return(void)
-{
-	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
-
-	/*
-	 * Jprobe handler return by entering break exception,
-	 * encoded same as kprobe, but with following conditions
-	 * -a special PC to identify it from the other kprobes.
-	 * -restore stack addr to original saved pt_regs
-	 */
-	asm volatile("				mov sp, %0	\n"
-		     "jprobe_return_break:	brk %1		\n"
-		     :
-		     : "r" (kcb->jprobe_saved_regs.sp),
-		       "I" (BRK64_ESR_KPROBES)
-		     : "memory");
-
-	unreachable();
-}
-
-int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
-{
-	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
-	long stack_addr = kcb->jprobe_saved_regs.sp;
-	long orig_sp = kernel_stack_pointer(regs);
-	struct jprobe *jp = container_of(p, struct jprobe, kp);
-	extern const char jprobe_return_break[];
-
-	if (instruction_pointer(regs) != (u64) jprobe_return_break)
-		return 0;
-
-	if (orig_sp != stack_addr) {
-		struct pt_regs *saved_regs =
-		    (struct pt_regs *)kcb->jprobe_saved_regs.sp;
-		pr_err("current sp %lx does not match saved sp %lx\n",
-		       orig_sp, stack_addr);
-		pr_err("Saved registers for jprobe %p\n", jp);
-		__show_regs(saved_regs);
-		pr_err("Current registers\n");
-		__show_regs(regs);
-		BUG();
-	}
-	unpause_graph_tracing();
-	*regs = kcb->jprobe_saved_regs;
-	preempt_enable_no_resched();
-	return 1;
-}
-
 bool arch_within_kprobe_blacklist(unsigned long addr)
 {
 	if ((addr >= (unsigned long)__kprobes_text_start &&

^ permalink raw reply related

* [PATCH -tip v6 16/27] ARM: kprobes: Don't call the ->break_handler() in arm kprobes code
From: Masami Hiramatsu @ 2018-06-19 16:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <152942424698.15209.15245996287444292393.stgit@devbox>

Don't call the ->break_handler() from the arm kprobes code,
because it was only used by jprobes which got removed.

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Russell King <linux@armlinux.org.uk>
Cc: linux-arm-kernel at lists.infradead.org
---
 arch/arm/probes/kprobes/core.c |   11 -----------
 1 file changed, 11 deletions(-)

diff --git a/arch/arm/probes/kprobes/core.c b/arch/arm/probes/kprobes/core.c
index 23562111c511..3192350f389d 100644
--- a/arch/arm/probes/kprobes/core.c
+++ b/arch/arm/probes/kprobes/core.c
@@ -315,17 +315,6 @@ void __kprobes kprobe_handler(struct pt_regs *regs)
 				reset_current_kprobe();
 			}
 		}
-	} else if (cur) {
-		/* We probably hit a jprobe.  Call its break handler. */
-		if (cur->break_handler && cur->break_handler(cur, regs)) {
-			kcb->kprobe_status = KPROBE_HIT_SS;
-			singlestep(cur, regs, kcb);
-			if (cur->post_handler) {
-				kcb->kprobe_status = KPROBE_HIT_SSDONE;
-				cur->post_handler(cur, regs, 0);
-			}
-		}
-		reset_current_kprobe();
 	} else {
 		/*
 		 * The probe was removed and a race is in progress.

^ permalink raw reply related

* [PATCH -tip v6 17/27] arm64: kprobes: Don't call the ->break_handler() in arm64 kprobes code
From: Masami Hiramatsu @ 2018-06-19 16:12 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <152942424698.15209.15245996287444292393.stgit@devbox>

Don't call the ->break_handler() from the arm64 kprobes code,
because it was only used by jprobes which got removed.

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Acked-by: Will Deacon <will.deacon@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: linux-arm-kernel at lists.infradead.org
---
 arch/arm64/kernel/probes/kprobes.c |    8 --------
 1 file changed, 8 deletions(-)

diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
index 3ca2351109a6..076c3c0775a6 100644
--- a/arch/arm64/kernel/probes/kprobes.c
+++ b/arch/arm64/kernel/probes/kprobes.c
@@ -408,14 +408,6 @@ static void __kprobes kprobe_handler(struct pt_regs *regs)
 				return;
 			}
 		}
-	} else if ((le32_to_cpu(*(kprobe_opcode_t *) addr) ==
-	    BRK64_OPCODE_KPROBES) && cur_kprobe) {
-		/* We probably hit a jprobe.  Call its break handler. */
-		if (cur_kprobe->break_handler  &&
-		     cur_kprobe->break_handler(cur_kprobe, regs)) {
-			setup_singlestep(cur_kprobe, regs, kcb, 0);
-			return;
-		}
 	}
 	/*
 	 * The breakpoint instruction was removed right

^ permalink raw reply related

* [PATCHv3 19/19] arm64: implement syscall wrappers
From: Catalin Marinas @ 2018-06-19 16:13 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180618120310.39527-20-mark.rutland@arm.com>

On Mon, Jun 18, 2018 at 01:03:10PM +0100, Mark Rutland wrote:
> To minimize the risk of userspace-controlled values being used under
> speculation, this patch adds pt_regs based syscall wrappers for arm64,
> which pass the minimum set of required userspace values to syscall
> implementations. For each syscall, a wrapper which takes a pt_regs
> argument is automatically generated, and this extracts the arguments
> before calling the "real" syscall implementation.
> 
> Each syscall has three functions generated:
> 
> * __do_<compat_>sys_<name> is the "real" syscall implementation, with
>   the expected prototype.
> 
> * __se_<compat_>sys_<name> is the sign-extension/narrowing wrapper,
>   inherited from common code. This takes a series of long parameters,
>   casting each to the requisite types required by the "real" syscall
>   implementation in __do_<compat_>sys_<name>.
> 
>   This wrapper *may* not be necessary on arm64 given the AAPCS rules on
>   unused register bits, but it seemed safer to keep the wrapper for now.
> 
> * __arm64_<compat_>_sys_<name> takes a struct pt_regs pointer, and
>   extracts *only* the relevant register values, passing these on to the
>   __se_<compat_>sys_<name> wrapper.
> 
> The syscall invocation code is updated to handle the calling convention
> required by __arm64_<compat_>_sys_<name>, and passes a single struct
> pt_regs pointer.
> 
> The compiler can fold the syscall implementation and its wrappers, such
> that the overhead of this approach is minimized.
> 
> Note that we play games with sys_ni_syscall(). It can't be defined with
> SYSCALL_DEFINE0() because we must avoid the possibility of error
> injection. Additionally, there are a couple of locations where we need
> to call it from C code, and we don't (currently) have a
> ksys_ni_syscall().  While it has no wrapper, passing in a redundant
> pt_regs pointer is benign per the AAPCS.
> 
> When ARCH_HAS_SYSCALL_WRAPPER is selected, no prototype is defines for
> sys_ni_syscall(). Since we need to treat it differently for in-kernel
> calls and the syscall tables, the prototype is defined as-required.
> 
> The wrappers are largely the same as their x86 counterparts, but
> simplified as we don't have a variety of compat calling conventions that
> require separate stubs. Unlike x86, we have some zero-argument compat
> syscalls, and must define COMPAT_SYSCALL_DEFINE0() to ensure that these
> are also given an __arm64_compat_sys_ prefix.
> 
> Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> Reviewed-by: Dominik Brodowski <linux@dominikbrodowski.net>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>

Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>

^ permalink raw reply

* [PATCHv3 00/19] arm64: invoke syscalls with pt_regs
From: Catalin Marinas @ 2018-06-19 16:14 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180619153810.mm4yt3pqjagvjo7p@lakrids.cambridge.arm.com>

On Tue, Jun 19, 2018 at 04:38:10PM +0100, Mark Rutland wrote:
> From b47791fe74fce8bb48696ab0cdda48a9bae0e397 Mon Sep 17 00:00:00 2001
> From: Mark Rutland <mark.rutland@arm.com>
> Date: Tue, 19 Jun 2018 12:49:54 +0100
> Subject: [PATCH] arm64: don't restore GPRs when context tracking
> 
> Now that syscalls are invoked with pt_regs, we no longer need to ensure
> that the argument regsiters are live in the entry assembly, and it's
> fine to not restore them after context_tracking_user_exit() has
> corrupted them.
> 
> Signed-off-by: Mark Rutland <mark.rutland@arm.com>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Will Deacon <will.deacon@arm.com>

Acked-by: Catalin Marinas <catalin.marinas@arm.com>

^ permalink raw reply

* [PATCH -tip v6 24/27] bpf: error-inject: kprobes: Clear current_kprobe and enable preempt in kprobe
From: Masami Hiramatsu @ 2018-06-19 16:15 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <152942424698.15209.15245996287444292393.stgit@devbox>

Clear current_kprobe and enable preemption in kprobe
even if pre_handler returns !0.

This simplifies function override using kprobes.

Jprobe used to require to keep the preemption disabled and
keep current_kprobe until it returned to original function
entry. For this reason kprobe_int3_handler() and similar
arch dependent kprobe handers checks pre_handler result
and exit without enabling preemption if the result is !0.

After removing the jprobe, Kprobes does not need to
keep preempt disabled even if user handler returns !0
anymore.

But since the function override handler in error-inject
and bpf is also returns !0 if it overrides a function,
to balancing the preempt count, it enables preemption
and reset current kprobe by itself.

That is a bad design that is very buggy. This fixes
such unbalanced preempt-count and current_kprobes setting
in kprobes, bpf and error-inject.

Note: for powerpc and x86, this removes all preempt_disable
from kprobe_ftrace_handler because ftrace callbacks are
called under preempt disabled.

Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Acked-by: "Naveen N. Rao" <naveen.n.rao@linux.vnet.ibm.com>
Cc: Vineet Gupta <vgupta@synopsys.com>
Cc: Russell King <linux@armlinux.org.uk>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Cc: Ralf Baechle <ralf@linux-mips.org>
Cc: James Hogan <jhogan@kernel.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Cc: Yoshinori Sato <ysato@users.sourceforge.jp>
Cc: Rich Felker <dalias@libc.org>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Josef Bacik <jbacik@fb.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: x86 at kernel.org
Cc: linux-snps-arc at lists.infradead.org
Cc: linux-kernel at vger.kernel.org
Cc: linux-arm-kernel at lists.infradead.org
Cc: linux-ia64 at vger.kernel.org
Cc: linux-mips at linux-mips.org
Cc: linuxppc-dev at lists.ozlabs.org
Cc: linux-s390 at vger.kernel.org
Cc: linux-sh at vger.kernel.org
Cc: sparclinux at vger.kernel.org
---
 Changes in v6:
  - Simplify kprobe_ftrace_handler change on x86 and powerpc code.
 Changes in v5:
  - Fix kprobe_ftrace_handler in arch/powerpc too.
---
 arch/arc/kernel/kprobes.c            |    5 +++--
 arch/arm/probes/kprobes/core.c       |   10 +++++-----
 arch/arm64/kernel/probes/kprobes.c   |   10 +++++-----
 arch/ia64/kernel/kprobes.c           |   13 ++++---------
 arch/mips/kernel/kprobes.c           |    4 ++--
 arch/powerpc/kernel/kprobes-ftrace.c |   19 ++++++-------------
 arch/powerpc/kernel/kprobes.c        |    7 +++++--
 arch/s390/kernel/kprobes.c           |    7 ++++---
 arch/sh/kernel/kprobes.c             |    7 ++++---
 arch/sparc/kernel/kprobes.c          |    7 ++++---
 arch/x86/kernel/kprobes/core.c       |    4 ++++
 arch/x86/kernel/kprobes/ftrace.c     |    9 +++------
 kernel/fail_function.c               |    3 ---
 kernel/trace/trace_kprobe.c          |   11 +++--------
 14 files changed, 52 insertions(+), 64 deletions(-)

diff --git a/arch/arc/kernel/kprobes.c b/arch/arc/kernel/kprobes.c
index 465365696c91..df35d4c0b0b8 100644
--- a/arch/arc/kernel/kprobes.c
+++ b/arch/arc/kernel/kprobes.c
@@ -231,6 +231,9 @@ int __kprobes arc_kprobe_handler(unsigned long addr, struct pt_regs *regs)
 		if (!p->pre_handler || !p->pre_handler(p, regs)) {
 			setup_singlestep(p, regs);
 			kcb->kprobe_status = KPROBE_HIT_SS;
+		} else {
+			reset_current_kprobe();
+			preempt_enable_no_resched();
 		}
 
 		return 1;
@@ -442,9 +445,7 @@ static int __kprobes trampoline_probe_handler(struct kprobe *p,
 	kretprobe_assert(ri, orig_ret_address, trampoline_address);
 	regs->ret = orig_ret_address;
 
-	reset_current_kprobe();
 	kretprobe_hash_unlock(current, &flags);
-	preempt_enable_no_resched();
 
 	hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) {
 		hlist_del(&ri->hlist);
diff --git a/arch/arm/probes/kprobes/core.c b/arch/arm/probes/kprobes/core.c
index 3192350f389d..8d37601fdb20 100644
--- a/arch/arm/probes/kprobes/core.c
+++ b/arch/arm/probes/kprobes/core.c
@@ -300,10 +300,10 @@ void __kprobes kprobe_handler(struct pt_regs *regs)
 
 			/*
 			 * If we have no pre-handler or it returned 0, we
-			 * continue with normal processing.  If we have a
-			 * pre-handler and it returned non-zero, it prepped
-			 * for calling the break_handler below on re-entry,
-			 * so get out doing nothing more here.
+			 * continue with normal processing. If we have a
+			 * pre-handler and it returned non-zero, it will
+			 * modify the execution path and no need to single
+			 * stepping. Let's just reset current kprobe and exit.
 			 */
 			if (!p->pre_handler || !p->pre_handler(p, regs)) {
 				kcb->kprobe_status = KPROBE_HIT_SS;
@@ -312,8 +312,8 @@ void __kprobes kprobe_handler(struct pt_regs *regs)
 					kcb->kprobe_status = KPROBE_HIT_SSDONE;
 					p->post_handler(p, regs, 0);
 				}
-				reset_current_kprobe();
 			}
+			reset_current_kprobe();
 		}
 	} else {
 		/*
diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c
index 076c3c0775a6..5daf3d721cb7 100644
--- a/arch/arm64/kernel/probes/kprobes.c
+++ b/arch/arm64/kernel/probes/kprobes.c
@@ -395,9 +395,9 @@ static void __kprobes kprobe_handler(struct pt_regs *regs)
 			/*
 			 * If we have no pre-handler or it returned 0, we
 			 * continue with normal processing.  If we have a
-			 * pre-handler and it returned non-zero, it prepped
-			 * for calling the break_handler below on re-entry,
-			 * so get out doing nothing more here.
+			 * pre-handler and it returned non-zero, it will
+			 * modify the execution path and no need to single
+			 * stepping. Let's just reset current kprobe and exit.
 			 *
 			 * pre_handler can hit a breakpoint and can step thru
 			 * before return, keep PSTATE D-flag enabled until
@@ -405,8 +405,8 @@ static void __kprobes kprobe_handler(struct pt_regs *regs)
 			 */
 			if (!p->pre_handler || !p->pre_handler(p, regs)) {
 				setup_singlestep(p, regs, kcb, 0);
-				return;
-			}
+			} else
+				reset_current_kprobe();
 		}
 	}
 	/*
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c
index 74c8524e6309..aa41bd5cf9b7 100644
--- a/arch/ia64/kernel/kprobes.c
+++ b/arch/ia64/kernel/kprobes.c
@@ -478,12 +478,9 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
 			 */
 			break;
 	}
-
 	kretprobe_assert(ri, orig_ret_address, trampoline_address);
 
-	reset_current_kprobe();
 	kretprobe_hash_unlock(current, &flags);
-	preempt_enable_no_resched();
 
 	hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) {
 		hlist_del(&ri->hlist);
@@ -851,13 +848,11 @@ static int __kprobes pre_kprobes_handler(struct die_args *args)
 	set_current_kprobe(p, kcb);
 	kcb->kprobe_status = KPROBE_HIT_ACTIVE;
 
-	if (p->pre_handler && p->pre_handler(p, regs))
-		/*
-		 * Our pre-handler is specifically requesting that we just
-		 * do a return.  This is used for both the jprobe pre-handler
-		 * and the kretprobe trampoline
-		 */
+	if (p->pre_handler && p->pre_handler(p, regs)) {
+		reset_current_kprobe();
+		preempt_enable_no_resched();
 		return 1;
+	}
 
 #if !defined(CONFIG_PREEMPT)
 	if (p->ainsn.inst_flag == INST_FLAG_BOOSTABLE && !p->post_handler) {
diff --git a/arch/mips/kernel/kprobes.c b/arch/mips/kernel/kprobes.c
index 7fd277bc59b9..54cd675c5d1d 100644
--- a/arch/mips/kernel/kprobes.c
+++ b/arch/mips/kernel/kprobes.c
@@ -358,6 +358,8 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
 
 	if (p->pre_handler && p->pre_handler(p, regs)) {
 		/* handler has already set things up, so skip ss setup */
+		reset_current_kprobe();
+		preempt_enable_no_resched();
 		return 1;
 	}
 
@@ -543,9 +545,7 @@ static int __kprobes trampoline_probe_handler(struct kprobe *p,
 	kretprobe_assert(ri, orig_ret_address, trampoline_address);
 	instruction_pointer(regs) = orig_ret_address;
 
-	reset_current_kprobe();
 	kretprobe_hash_unlock(current, &flags);
-	preempt_enable_no_resched();
 
 	hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) {
 		hlist_del(&ri->hlist);
diff --git a/arch/powerpc/kernel/kprobes-ftrace.c b/arch/powerpc/kernel/kprobes-ftrace.c
index 070d1d862444..e4a49c051325 100644
--- a/arch/powerpc/kernel/kprobes-ftrace.c
+++ b/arch/powerpc/kernel/kprobes-ftrace.c
@@ -32,11 +32,9 @@ void kprobe_ftrace_handler(unsigned long nip, unsigned long parent_nip,
 	struct kprobe *p;
 	struct kprobe_ctlblk *kcb;
 
-	preempt_disable();
-
 	p = get_kprobe((kprobe_opcode_t *)nip);
 	if (unlikely(!p) || kprobe_disabled(p))
-		goto end;
+		return;
 
 	kcb = get_kprobe_ctlblk();
 	if (kprobe_running()) {
@@ -60,18 +58,13 @@ void kprobe_ftrace_handler(unsigned long nip, unsigned long parent_nip,
 				kcb->kprobe_status = KPROBE_HIT_SSDONE;
 				p->post_handler(p, regs, 0);
 			}
-			__this_cpu_write(current_kprobe, NULL);
-		} else {
-			/*
-			 * If pre_handler returns !0, it sets regs->nip and
-			 * resets current kprobe. In this case, we should not
-			 * re-enable preemption.
-			 */
-			return;
 		}
+		/*
+		 * If pre_handler returns !0, it changes regs->nip. We have to
+		 * skip emulating post_handler.
+		 */
+		__this_cpu_write(current_kprobe, NULL);
 	}
-end:
-	preempt_enable_no_resched();
 }
 NOKPROBE_SYMBOL(kprobe_ftrace_handler);
 
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c
index f06747e2e70d..5c60bb0f927f 100644
--- a/arch/powerpc/kernel/kprobes.c
+++ b/arch/powerpc/kernel/kprobes.c
@@ -358,9 +358,12 @@ int kprobe_handler(struct pt_regs *regs)
 
 	kcb->kprobe_status = KPROBE_HIT_ACTIVE;
 	set_current_kprobe(p, regs, kcb);
-	if (p->pre_handler && p->pre_handler(p, regs))
-		/* handler has already set things up, so skip ss setup */
+	if (p->pre_handler && p->pre_handler(p, regs)) {
+		/* handler changed execution path, so skip ss setup */
+		reset_current_kprobe();
+		preempt_enable_no_resched();
 		return 1;
+	}
 
 	if (p->ainsn.boostable >= 0) {
 		ret = try_to_emulate(p, regs);
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index 3e34018960b5..7c0a095e9c5f 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -326,8 +326,11 @@ static int kprobe_handler(struct pt_regs *regs)
 			 */
 			push_kprobe(kcb, p);
 			kcb->kprobe_status = KPROBE_HIT_ACTIVE;
-			if (p->pre_handler && p->pre_handler(p, regs))
+			if (p->pre_handler && p->pre_handler(p, regs)) {
+				pop_kprobe(kcb);
+				preempt_enable_no_resched();
 				return 1;
+			}
 			kcb->kprobe_status = KPROBE_HIT_SS;
 		}
 		enable_singlestep(kcb, regs, (unsigned long) p->ainsn.insn);
@@ -431,9 +434,7 @@ static int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
 
 	regs->psw.addr = orig_ret_address;
 
-	pop_kprobe(get_kprobe_ctlblk());
 	kretprobe_hash_unlock(current, &flags);
-	preempt_enable_no_resched();
 
 	hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) {
 		hlist_del(&ri->hlist);
diff --git a/arch/sh/kernel/kprobes.c b/arch/sh/kernel/kprobes.c
index 4fafe0cd12c6..241e903dd3ee 100644
--- a/arch/sh/kernel/kprobes.c
+++ b/arch/sh/kernel/kprobes.c
@@ -272,9 +272,12 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
 	set_current_kprobe(p, regs, kcb);
 	kcb->kprobe_status = KPROBE_HIT_ACTIVE;
 
-	if (p->pre_handler && p->pre_handler(p, regs))
+	if (p->pre_handler && p->pre_handler(p, regs)) {
 		/* handler has already set things up, so skip ss setup */
+		reset_current_kprobe();
+		preempt_enable_no_resched();
 		return 1;
+	}
 
 	prepare_singlestep(p, regs);
 	kcb->kprobe_status = KPROBE_HIT_SS;
@@ -352,8 +355,6 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
 	regs->pc = orig_ret_address;
 	kretprobe_hash_unlock(current, &flags);
 
-	preempt_enable_no_resched();
-
 	hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) {
 		hlist_del(&ri->hlist);
 		kfree(ri);
diff --git a/arch/sparc/kernel/kprobes.c b/arch/sparc/kernel/kprobes.c
index c684c96ef2e9..dfbca2470536 100644
--- a/arch/sparc/kernel/kprobes.c
+++ b/arch/sparc/kernel/kprobes.c
@@ -175,8 +175,11 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
 
 	set_current_kprobe(p, regs, kcb);
 	kcb->kprobe_status = KPROBE_HIT_ACTIVE;
-	if (p->pre_handler && p->pre_handler(p, regs))
+	if (p->pre_handler && p->pre_handler(p, regs)) {
+		reset_current_kprobe();
+		preempt_enable_no_resched();
 		return 1;
+	}
 
 	prepare_singlestep(p, regs, kcb);
 	kcb->kprobe_status = KPROBE_HIT_SS;
@@ -508,9 +511,7 @@ static int __kprobes trampoline_probe_handler(struct kprobe *p,
 	regs->tpc = orig_ret_address;
 	regs->tnpc = orig_ret_address + 4;
 
-	reset_current_kprobe();
 	kretprobe_hash_unlock(current, &flags);
-	preempt_enable_no_resched();
 
 	hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) {
 		hlist_del(&ri->hlist);
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
index 0ac16a0d93e5..814e26b7c8a2 100644
--- a/arch/x86/kernel/kprobes/core.c
+++ b/arch/x86/kernel/kprobes/core.c
@@ -694,6 +694,10 @@ int kprobe_int3_handler(struct pt_regs *regs)
 			 */
 			if (!p->pre_handler || !p->pre_handler(p, regs))
 				setup_singlestep(p, regs, kcb, 0);
+			else {
+				reset_current_kprobe();
+				preempt_enable_no_resched();
+			}
 			return 1;
 		}
 	} else if (*addr != BREAKPOINT_INSTRUCTION) {
diff --git a/arch/x86/kernel/kprobes/ftrace.c b/arch/x86/kernel/kprobes/ftrace.c
index 02a6dd1b6bd0..ef819e19650b 100644
--- a/arch/x86/kernel/kprobes/ftrace.c
+++ b/arch/x86/kernel/kprobes/ftrace.c
@@ -45,8 +45,6 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
 		/* Kprobe handler expects regs->ip = ip + 1 as breakpoint hit */
 		regs->ip = ip + sizeof(kprobe_opcode_t);
 
-		/* To emulate trap based kprobes, preempt_disable here */
-		preempt_disable();
 		__this_cpu_write(current_kprobe, p);
 		kcb->kprobe_status = KPROBE_HIT_ACTIVE;
 		if (!p->pre_handler || !p->pre_handler(p, regs)) {
@@ -60,13 +58,12 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
 				p->post_handler(p, regs, 0);
 			}
 			regs->ip = orig_ip;
-			__this_cpu_write(current_kprobe, NULL);
-			preempt_enable_no_resched();
 		}
 		/*
-		 * If pre_handler returns !0, it sets regs->ip and
-		 * resets current kprobe, and keep preempt count +1.
+		 * If pre_handler returns !0, it changes regs->ip. We have to
+		 * skip emulating post_handler.
 		 */
+		__this_cpu_write(current_kprobe, NULL);
 	}
 }
 NOKPROBE_SYMBOL(kprobe_ftrace_handler);
diff --git a/kernel/fail_function.c b/kernel/fail_function.c
index 1d5632d8bbcc..b090688df94f 100644
--- a/kernel/fail_function.c
+++ b/kernel/fail_function.c
@@ -184,9 +184,6 @@ static int fei_kprobe_handler(struct kprobe *kp, struct pt_regs *regs)
 	if (should_fail(&fei_fault_attr, 1)) {
 		regs_set_return_value(regs, attr->retval);
 		override_function_with_return(regs);
-		/* Kprobe specific fixup */
-		reset_current_kprobe();
-		preempt_enable_no_resched();
 		return 1;
 	}
 
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index daa81571b22a..7e3b944b6ac1 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -1217,16 +1217,11 @@ kprobe_perf_func(struct trace_kprobe *tk, struct pt_regs *regs)
 
 		/*
 		 * We need to check and see if we modified the pc of the
-		 * pt_regs, and if so clear the kprobe and return 1 so that we
-		 * don't do the single stepping.
-		 * The ftrace kprobe handler leaves it up to us to re-enable
-		 * preemption here before returning if we've modified the ip.
+		 * pt_regs, and if so return 1 so that we don't do the
+		 * single stepping.
 		 */
-		if (orig_ip != instruction_pointer(regs)) {
-			reset_current_kprobe();
-			preempt_enable_no_resched();
+		if (orig_ip != instruction_pointer(regs))
 			return 1;
-		}
 		if (!ret)
 			return 0;
 	}

^ permalink raw reply related

* [PATCH] ARM: proc-v7: fix Thumb annotation of cpu_v7_hvc_switch_mm
From: Ard Biesheuvel @ 2018-06-19 16:29 UTC (permalink / raw)
  To: linux-arm-kernel

Due to what appears to be a copy/paste error, the opening ENTRY()
of cpu_v7_hvc_switch_mm() lacks a matching ENDPROC(), and instead,
the one for cpu_v7_smc_switch_mm() is duplicated.

Given that it is ENDPROC() that emits the Thumb annotation, the
cpu_v7_hvc_switch_mm() routine will be called in ARM mode on a
Thumb2 kernel, resulting in the following splat:

  Internal error: Oops - undefined instruction: 0 [#1] SMP THUMB2
  Modules linked in:
  CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.18.0-rc1-00030-g4d28ad89189d-dirty #488
  Hardware name: QEMU KVM Virtual Machine, BIOS 0.0.0 02/06/2015
  PC is at cpu_v7_hvc_switch_mm+0x12/0x18
  LR is at flush_old_exec+0x31b/0x570
  pc : [<c0316efe>]    lr : [<c04117c7>]    psr: 00000013
  sp : ee899e50  ip : 00000000  fp : 00000001
  r10: eda28f34  r9 : eda31800  r8 : c12470e0
  r7 : eda1fc00  r6 : eda53000  r5 : 00000000  r4 : ee88c000
  r3 : c0316eec  r2 : 00000001  r1 : eda53000  r0 : 6da6c000
  Flags: nzcv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none

Note the 'ISA ARM' in the last line.

Fix this by using the correct name in ENDPROC().

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 arch/arm/mm/proc-v7.S | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 6fe52819e014..339eb17c9808 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -112,7 +112,7 @@ ENTRY(cpu_v7_hvc_switch_mm)
 	hvc	#0
 	ldmfd	sp!, {r0 - r3}
 	b	cpu_v7_switch_mm
-ENDPROC(cpu_v7_smc_switch_mm)
+ENDPROC(cpu_v7_hvc_switch_mm)
 #endif
 ENTRY(cpu_v7_iciallu_switch_mm)
 	mov	r3, #0
-- 
2.17.1

^ permalink raw reply related

* [PATCH 1/2] arm64: avoid alloc memory on offline node
From: Lorenzo Pieralisi @ 2018-06-19 16:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <87r2l23i2b.fsf@e105922-lin.cambridge.arm.com>

On Tue, Jun 19, 2018 at 04:35:40PM +0100, Punit Agrawal wrote:
> Michal Hocko <mhocko@kernel.org> writes:
> 
> > On Tue 19-06-18 15:54:26, Punit Agrawal wrote:
> > [...]
> >> In terms of $SUBJECT, I wonder if it's worth taking the original patch
> >> as a temporary fix (it'll also be easier to backport) while we work on
> >> fixing these other issues and enabling memoryless nodes.
> >
> > Well, x86 already does that but copying this antipatern is not really
> > nice. So it is good as a quick fix but it would be definitely much
> > better to have a robust fix. Who knows how many other places might hit
> > this. You certainly do not want to add a hack like this all over...
> 
> Completely agree! I was only suggesting it as a temporary measure,
> especially as it looked like a proper fix might be invasive.
> 
> Another fix might be to change the node specific allocation to node
> agnostic allocations. It isn't clear why the allocation is being
> requested from a specific node. I think Lorenzo suggested this in one of
> the threads.

I think that code was just copypasted but it is better to fix the
underlying issue.

> I've started putting together a set fixing the issues identified in this
> thread. It should give a better idea on the best course of action.

On ACPI ARM64, this diff should do if I read the code correctly, it
should be (famous last words) just a matter of mapping PXMs to nodes for
every SRAT GICC entry, feel free to pick it up if it works.

Yes, we can take the original patch just because it is safer for an -rc
cycle even though if the patch below would do delaying the fix for a
couple of -rc (to get it tested across ACPI ARM64 NUMA platforms) is
not a disaster.

Lorenzo

-- >8 --
diff --git a/arch/arm64/kernel/acpi_numa.c b/arch/arm64/kernel/acpi_numa.c
index d190a7b231bf..877b268ef9fa 100644
--- a/arch/arm64/kernel/acpi_numa.c
+++ b/arch/arm64/kernel/acpi_numa.c
@@ -70,12 +70,6 @@ void __init acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa)
 	if (!(pa->flags & ACPI_SRAT_GICC_ENABLED))
 		return;
 
-	if (cpus_in_srat >= NR_CPUS) {
-		pr_warn_once("SRAT: cpu_to_node_map[%d] is too small, may not be able to use all cpus\n",
-			     NR_CPUS);
-		return;
-	}
-
 	pxm = pa->proximity_domain;
 	node = acpi_map_pxm_to_node(pxm);
 
@@ -85,6 +79,14 @@ void __init acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa)
 		return;
 	}
 
+	node_set(node, numa_nodes_parsed);
+
+	if (cpus_in_srat >= NR_CPUS) {
+		pr_warn_once("SRAT: cpu_to_node_map[%d] is too small, may not be able to use all cpus\n",
+			     NR_CPUS);
+		return;
+	}
+
 	mpidr = acpi_map_madt_entry(pa->acpi_processor_uid);
 	if (mpidr == PHYS_CPUID_INVALID) {
 		pr_err("SRAT: PXM %d with ACPI ID %d has no valid MPIDR in MADT\n",
@@ -95,7 +97,6 @@ void __init acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa)
 
 	early_node_cpu_hwid[cpus_in_srat].node_id = node;
 	early_node_cpu_hwid[cpus_in_srat].cpu_hwid =  mpidr;
-	node_set(node, numa_nodes_parsed);
 	cpus_in_srat++;
 	pr_info("SRAT: PXM %d -> MPIDR 0x%Lx -> Node %d\n",
 		pxm, mpidr, node);

^ permalink raw reply related

* [PATCH 3/3] arm64: IPI each CPU after invalidating the I-cache for kernel mappings
From: Will Deacon @ 2018-06-19 16:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180619135528.4rxgluvroybxgxem@lakrids.cambridge.arm.com>

On Tue, Jun 19, 2018 at 02:55:28PM +0100, Mark Rutland wrote:
> On Tue, Jun 19, 2018 at 01:48:15PM +0100, Will Deacon wrote:
> > diff --git a/arch/arm64/kernel/insn.c b/arch/arm64/kernel/insn.c
> > index 816d03c4c913..4cc41864f277 100644
> > --- a/arch/arm64/kernel/insn.c
> > +++ b/arch/arm64/kernel/insn.c
> > @@ -249,7 +249,6 @@ static int __kprobes aarch64_insn_patch_text_cb(void *arg)
> >  	} else {
> >  		while (atomic_read(&pp->cpu_count) <= num_online_cpus())
> >  			cpu_relax();
> > -		isb();
> >  	}
> 
> Something seems amiss here. 
> 
> We call __apply_alternatives_multi_stop() via stop_machine(), and I
> thought that ensured that all CPUs had IRQs masked.
> 
> If so, the IPI from flush_icache_range() will deadlock.
> 
> If not, we can take IRQs, and execute potentially patched code.

Yes, I think you're right, and I think this only applies to kprobes (since
it patches arbitrary instructions and requires the stop_machine()). However,
I think that highlights another issue, which is that the "nosync" patching
cases as used by things like jump_labels are still going to want this IPI,
so actually the fastpath stuff can all be ripped out. ftrace can probably
be left as-is, since I doubt it's critical that new CPUs immediately see
dynamic tracepoints.

I'll cook a patch sorting this out and include it in v2.

> I think there's also an existing problem here. Even if with have IRQs
> masked, we could take SDEI events (or GICv3 psudeo-NMIs, once we have
> those). I don't know how we can manage those.

I guess there are just some places where we can't deal with an SDEI event.
That said, it's fine as long as the SDEI path is careful about what it runs
(and SDEI is masked until the worst of the patching is over during boot).

James?

Will

^ permalink raw reply

* [PATCH v5 0/7] add virt-dma support for imx-sdma
From: Robin Gong @ 2018-06-19 16:56 UTC (permalink / raw)
  To: linux-arm-kernel

The legacy sdma driver has below limitations or drawbacks:
  1. Hardcode the max BDs number as "PAGE_SIZE / sizeof(*)", and alloc
     one page size for one channel regardless of only few BDs needed
     most time. But in few cases, the max PAGE_SIZE maybe not enough.
  2. One SDMA channel can't stop immediatley once channel disabled which
     means SDMA interrupt may come in after this channel terminated.There
     are some patches for this corner case such as commit "2746e2c389f9",
     but not cover non-cyclic.

The common virt-dma overcomes the above limitations. It can alloc bd
dynamically and free bd once this tx transfer done. No memory wasted or
maximum limititation here, only depends on how many memory can be requested
from kernel. For No.2, such issue can be workaround by checking if there
is available descript("sdmac->desc") now once the unwanted interrupt
coming. At last the common virt-dma is easier for sdma driver maintain.

Change from v4:
  1. identify lockdep issue which caused by allocate memory with
     'GFP_KERNEL', change to 'GFP_NOWAIT' instead so that lockdep
     ignore check. That also make sense since Audio/uart driver may
     call dma function after spin_lock_irqsave()...
  2. use dma pool instead for bd description allocated,since audio
     driver may call dma_terminate_all in irq. Please refer to 7/7.
  3. remove 7/7 serial patch in v4, since lockdep issued fixed by No.1 

Change from v3:
  1. add two uart patches which impacted by this patchset.
  2. unlock 'vc.lock' before cyclic dma callback and lock again after
     it because some driver such as uart will call dmaengine_tx_status
     which will acquire 'vc.lock' again and dead lock comes out.
  3. remove 'Revert commit' stuff since that patch is not wrong and
     combine two patch into one patch as Sascha's comment.

Change from v2:
  1. include Sascha's patch to make the main patch easier to review.
     Thanks Sacha.
  2. remove useless 'desc'/'chan' in struct sdma_channe.

Change from v1:
  1. split v1 patch into 5 patches.
  2. remove some unnecessary condition check.
  3. remove unnecessary 'pending' list.

Robin Gong (6):
  tty: serial: imx: correct dma cookie status
  dmaengine: imx-sdma: add virt-dma support
  dmaengine: imx-sdma: remove useless 'lock' and 'enabled' in 'struct
    sdma_channel'
  dmaengine: imx-sdma: remove the maximum limitation for bd numbers
  dmaengine: imx-sdma: add sdma_transfer_init to decrease code overlap
  dmaengine: imx-sdma: alloclate bd memory from dma pool

Sascha Hauer (1):
  dmaengine: imx-sdma: factor out a struct sdma_desc from struct
    sdma_channel

 drivers/dma/Kconfig      |   1 +
 drivers/dma/imx-sdma.c   | 400 +++++++++++++++++++++++++++--------------------
 drivers/tty/serial/imx.c |   2 +-
 3 files changed, 235 insertions(+), 168 deletions(-)

-- 
2.7.4

^ permalink raw reply

* [PATCH v5 1/7] tty: serial: imx: correct dma cookie status
From: Robin Gong @ 2018-06-19 16:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1529427424-12321-1-git-send-email-yibin.gong@nxp.com>

Correct to check the right rx dma cookie status in spit of it
works because only one cookie is running in the current sdma.
But it will not once sdma driver support multi cookies
running based on virt-dma.

Signed-off-by: Robin Gong <yibin.gong@nxp.com>
---
 drivers/tty/serial/imx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 4e85357..2879407 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -1051,7 +1051,7 @@ static void imx_uart_dma_rx_callback(void *data)
 	unsigned int r_bytes;
 	unsigned int bd_size;
 
-	status = dmaengine_tx_status(chan, (dma_cookie_t)0, &state);
+	status = dmaengine_tx_status(chan, sport->rx_cookie, &state);
 
 	if (status == DMA_ERROR) {
 		imx_uart_clear_rx_errors(sport);
-- 
2.7.4

^ permalink raw reply related

* [PATCH v5 2/7] dmaengine: imx-sdma: factor out a struct sdma_desc from struct sdma_channel
From: Robin Gong @ 2018-06-19 16:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1529427424-12321-1-git-send-email-yibin.gong@nxp.com>

From: Sascha Hauer <s.hauer@pengutronix.de>

This is a preparation step to make the adding of virt-dma easier.
We create a struct sdma_desc, move some fields from struct sdma_channel
there and add a pointer from the former to the latter. For now we
allocate the data statically in struct sdma_channel, but with
virt-dma support it will be dynamically allocated.

Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Signed-off-by: Robin Gong <yibin.gong@nxp.com>
---
 drivers/dma/imx-sdma.c | 137 ++++++++++++++++++++++++++++++-------------------
 1 file changed, 83 insertions(+), 54 deletions(-)

diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index f0779926..19c351f 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -289,6 +289,30 @@ struct sdma_context_data {
 struct sdma_engine;
 
 /**
+ * struct sdma_desc - descriptor structor for one transfer
+ * @vd			descriptor for virt dma
+ * @num_bd		max NUM_BD. number of descriptors currently handling
+ * @buf_tail		ID of the buffer that was processed
+ * @buf_ptail		ID of the previous buffer that was processed
+ * @period_len		period length, used in cyclic.
+ * @chn_real_count	the real count updated from bd->mode.count
+ * @chn_count		the transfer count setuped
+ * @sdmac		sdma_channel pointer
+ * @bd			pointer of alloced bd
+ */
+struct sdma_desc {
+	unsigned int		num_bd;
+	dma_addr_t		bd_phys;
+	unsigned int		buf_tail;
+	unsigned int		buf_ptail;
+	unsigned int		period_len;
+	unsigned int		chn_real_count;
+	unsigned int		chn_count;
+	struct sdma_channel	*sdmac;
+	struct sdma_buffer_descriptor *bd;
+};
+
+/**
  * struct sdma_channel - housekeeping for a SDMA channel
  *
  * @sdma		pointer to the SDMA engine for this channel
@@ -298,11 +322,10 @@ struct sdma_engine;
  * @event_id0		aka dma request line
  * @event_id1		for channels that use 2 events
  * @word_size		peripheral access size
- * @buf_tail		ID of the buffer that was processed
- * @buf_ptail		ID of the previous buffer that was processed
- * @num_bd		max NUM_BD. number of descriptors currently handling
  */
 struct sdma_channel {
+	struct sdma_desc		*desc;
+	struct sdma_desc		_desc;
 	struct sdma_engine		*sdma;
 	unsigned int			channel;
 	enum dma_transfer_direction		direction;
@@ -310,12 +333,6 @@ struct sdma_channel {
 	unsigned int			event_id0;
 	unsigned int			event_id1;
 	enum dma_slave_buswidth		word_size;
-	unsigned int			buf_tail;
-	unsigned int			buf_ptail;
-	unsigned int			num_bd;
-	unsigned int			period_len;
-	struct sdma_buffer_descriptor	*bd;
-	dma_addr_t			bd_phys;
 	unsigned int			pc_from_device, pc_to_device;
 	unsigned int			device_to_device;
 	unsigned long			flags;
@@ -325,10 +342,8 @@ struct sdma_channel {
 	u32				shp_addr, per_addr;
 	struct dma_chan			chan;
 	spinlock_t			lock;
-	struct dma_async_tx_descriptor	desc;
+	struct dma_async_tx_descriptor	txdesc;
 	enum dma_status			status;
-	unsigned int			chn_count;
-	unsigned int			chn_real_count;
 	struct tasklet_struct		tasklet;
 	struct imx_dma_data		data;
 	bool				enabled;
@@ -391,6 +406,8 @@ struct sdma_engine {
 	u32				spba_start_addr;
 	u32				spba_end_addr;
 	unsigned int			irq;
+	dma_addr_t			bd0_phys;
+	struct sdma_buffer_descriptor	*bd0;
 };
 
 static struct sdma_driver_data sdma_imx31 = {
@@ -625,7 +642,7 @@ static int sdma_run_channel0(struct sdma_engine *sdma)
 static int sdma_load_script(struct sdma_engine *sdma, void *buf, int size,
 		u32 address)
 {
-	struct sdma_buffer_descriptor *bd0 = sdma->channel[0].bd;
+	struct sdma_buffer_descriptor *bd0 = sdma->bd0;
 	void *buf_virt;
 	dma_addr_t buf_phys;
 	int ret;
@@ -700,7 +717,9 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
 	 * call callback function.
 	 */
 	while (1) {
-		bd = &sdmac->bd[sdmac->buf_tail];
+		struct sdma_desc *desc = sdmac->desc;
+
+		bd = &desc->bd[desc->buf_tail];
 
 		if (bd->mode.status & BD_DONE)
 			break;
@@ -716,11 +735,11 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
 		* the number of bytes present in the current buffer descriptor.
 		*/
 
-		sdmac->chn_real_count = bd->mode.count;
+		desc->chn_real_count = bd->mode.count;
 		bd->mode.status |= BD_DONE;
-		bd->mode.count = sdmac->period_len;
-		sdmac->buf_ptail = sdmac->buf_tail;
-		sdmac->buf_tail = (sdmac->buf_tail + 1) % sdmac->num_bd;
+		bd->mode.count = desc->period_len;
+		desc->buf_ptail = desc->buf_tail;
+		desc->buf_tail = (desc->buf_tail + 1) % desc->num_bd;
 
 		/*
 		 * The callback is called from the interrupt context in order
@@ -729,7 +748,7 @@ static void sdma_update_channel_loop(struct sdma_channel *sdmac)
 		 * executed.
 		 */
 
-		dmaengine_desc_get_callback_invoke(&sdmac->desc, NULL);
+		dmaengine_desc_get_callback_invoke(&sdmac->txdesc, NULL);
 
 		if (error)
 			sdmac->status = old_status;
@@ -742,17 +761,17 @@ static void mxc_sdma_handle_channel_normal(unsigned long data)
 	struct sdma_buffer_descriptor *bd;
 	int i, error = 0;
 
-	sdmac->chn_real_count = 0;
+	sdmac->desc->chn_real_count = 0;
 	/*
 	 * non loop mode. Iterate over all descriptors, collect
 	 * errors and call callback function
 	 */
-	for (i = 0; i < sdmac->num_bd; i++) {
-		bd = &sdmac->bd[i];
+	for (i = 0; i < sdmac->desc->num_bd; i++) {
+		bd = &sdmac->desc->bd[i];
 
 		 if (bd->mode.status & (BD_DONE | BD_RROR))
 			error = -EIO;
-		 sdmac->chn_real_count += bd->mode.count;
+		 sdmac->desc->chn_real_count += bd->mode.count;
 	}
 
 	if (error)
@@ -760,9 +779,9 @@ static void mxc_sdma_handle_channel_normal(unsigned long data)
 	else
 		sdmac->status = DMA_COMPLETE;
 
-	dma_cookie_complete(&sdmac->desc);
+	dma_cookie_complete(&sdmac->txdesc);
 
-	dmaengine_desc_get_callback_invoke(&sdmac->desc, NULL);
+	dmaengine_desc_get_callback_invoke(&sdmac->txdesc, NULL);
 }
 
 static irqreturn_t sdma_int_handler(int irq, void *dev_id)
@@ -890,7 +909,7 @@ static int sdma_load_context(struct sdma_channel *sdmac)
 	int channel = sdmac->channel;
 	int load_address;
 	struct sdma_context_data *context = sdma->context;
-	struct sdma_buffer_descriptor *bd0 = sdma->channel[0].bd;
+	struct sdma_buffer_descriptor *bd0 = sdma->bd0;
 	int ret;
 	unsigned long flags;
 
@@ -1093,18 +1112,22 @@ static int sdma_set_channel_priority(struct sdma_channel *sdmac,
 static int sdma_request_channel(struct sdma_channel *sdmac)
 {
 	struct sdma_engine *sdma = sdmac->sdma;
+	struct sdma_desc *desc;
 	int channel = sdmac->channel;
 	int ret = -EBUSY;
 
-	sdmac->bd = dma_zalloc_coherent(NULL, PAGE_SIZE, &sdmac->bd_phys,
+	sdmac->desc = &sdmac->_desc;
+	desc = sdmac->desc;
+
+	desc->bd = dma_zalloc_coherent(NULL, PAGE_SIZE, &desc->bd_phys,
 					GFP_KERNEL);
-	if (!sdmac->bd) {
+	if (!desc->bd) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
-	sdma->channel_control[channel].base_bd_ptr = sdmac->bd_phys;
-	sdma->channel_control[channel].current_bd_ptr = sdmac->bd_phys;
+	sdma->channel_control[channel].base_bd_ptr = desc->bd_phys;
+	sdma->channel_control[channel].current_bd_ptr = desc->bd_phys;
 
 	sdma_set_channel_priority(sdmac, MXC_SDMA_DEFAULT_PRIORITY);
 	return 0;
@@ -1169,10 +1192,10 @@ static int sdma_alloc_chan_resources(struct dma_chan *chan)
 	if (ret)
 		goto disable_clk_ahb;
 
-	dma_async_tx_descriptor_init(&sdmac->desc, chan);
-	sdmac->desc.tx_submit = sdma_tx_submit;
+	dma_async_tx_descriptor_init(&sdmac->txdesc, chan);
+	sdmac->txdesc.tx_submit = sdma_tx_submit;
 	/* txd.flags will be overwritten in prep funcs */
-	sdmac->desc.flags = DMA_CTRL_ACK;
+	sdmac->txdesc.flags = DMA_CTRL_ACK;
 
 	return 0;
 
@@ -1187,6 +1210,7 @@ static void sdma_free_chan_resources(struct dma_chan *chan)
 {
 	struct sdma_channel *sdmac = to_sdma_chan(chan);
 	struct sdma_engine *sdma = sdmac->sdma;
+	struct sdma_desc *desc = sdmac->desc;
 
 	sdma_disable_channel(chan);
 
@@ -1200,7 +1224,7 @@ static void sdma_free_chan_resources(struct dma_chan *chan)
 
 	sdma_set_channel_priority(sdmac, 0);
 
-	dma_free_coherent(NULL, PAGE_SIZE, sdmac->bd, sdmac->bd_phys);
+	dma_free_coherent(NULL, PAGE_SIZE, desc->bd, desc->bd_phys);
 
 	clk_disable(sdma->clk_ipg);
 	clk_disable(sdma->clk_ahb);
@@ -1216,6 +1240,7 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
 	int ret, i, count;
 	int channel = sdmac->channel;
 	struct scatterlist *sg;
+	struct sdma_desc *desc = sdmac->desc;
 
 	if (sdmac->status == DMA_IN_PROGRESS)
 		return NULL;
@@ -1223,9 +1248,9 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
 
 	sdmac->flags = 0;
 
-	sdmac->buf_tail = 0;
-	sdmac->buf_ptail = 0;
-	sdmac->chn_real_count = 0;
+	desc->buf_tail = 0;
+	desc->buf_ptail = 0;
+	desc->chn_real_count = 0;
 
 	dev_dbg(sdma->dev, "setting up %d entries for channel %d.\n",
 			sg_len, channel);
@@ -1242,9 +1267,9 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
 		goto err_out;
 	}
 
-	sdmac->chn_count = 0;
+	desc->chn_count = 0;
 	for_each_sg(sgl, sg, sg_len, i) {
-		struct sdma_buffer_descriptor *bd = &sdmac->bd[i];
+		struct sdma_buffer_descriptor *bd = &desc->bd[i];
 		int param;
 
 		bd->buffer_addr = sg->dma_address;
@@ -1259,7 +1284,7 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
 		}
 
 		bd->mode.count = count;
-		sdmac->chn_count += count;
+		desc->chn_count += count;
 
 		if (sdmac->word_size > DMA_SLAVE_BUSWIDTH_4_BYTES) {
 			ret =  -EINVAL;
@@ -1300,10 +1325,10 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
 		bd->mode.status = param;
 	}
 
-	sdmac->num_bd = sg_len;
-	sdma->channel_control[channel].current_bd_ptr = sdmac->bd_phys;
+	desc->num_bd = sg_len;
+	sdma->channel_control[channel].current_bd_ptr = desc->bd_phys;
 
-	return &sdmac->desc;
+	return &sdmac->txdesc;
 err_out:
 	sdmac->status = DMA_ERROR;
 	return NULL;
@@ -1319,6 +1344,7 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
 	int num_periods = buf_len / period_len;
 	int channel = sdmac->channel;
 	int ret, i = 0, buf = 0;
+	struct sdma_desc *desc = sdmac->desc;
 
 	dev_dbg(sdma->dev, "%s channel: %d\n", __func__, channel);
 
@@ -1327,10 +1353,10 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
 
 	sdmac->status = DMA_IN_PROGRESS;
 
-	sdmac->buf_tail = 0;
-	sdmac->buf_ptail = 0;
-	sdmac->chn_real_count = 0;
-	sdmac->period_len = period_len;
+	desc->buf_tail = 0;
+	desc->buf_ptail = 0;
+	desc->chn_real_count = 0;
+	desc->period_len = period_len;
 
 	sdmac->flags |= IMX_DMA_SG_LOOP;
 	sdmac->direction = direction;
@@ -1351,7 +1377,7 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
 	}
 
 	while (buf < buf_len) {
-		struct sdma_buffer_descriptor *bd = &sdmac->bd[i];
+		struct sdma_buffer_descriptor *bd = &desc->bd[i];
 		int param;
 
 		bd->buffer_addr = dma_addr;
@@ -1382,10 +1408,10 @@ static struct dma_async_tx_descriptor *sdma_prep_dma_cyclic(
 		i++;
 	}
 
-	sdmac->num_bd = num_periods;
-	sdma->channel_control[channel].current_bd_ptr = sdmac->bd_phys;
+	desc->num_bd = num_periods;
+	sdma->channel_control[channel].current_bd_ptr = desc->bd_phys;
 
-	return &sdmac->desc;
+	return &sdmac->txdesc;
 err_out:
 	sdmac->status = DMA_ERROR;
 	return NULL;
@@ -1424,13 +1450,14 @@ static enum dma_status sdma_tx_status(struct dma_chan *chan,
 				      struct dma_tx_state *txstate)
 {
 	struct sdma_channel *sdmac = to_sdma_chan(chan);
+	struct sdma_desc *desc = sdmac->desc;
 	u32 residue;
 
 	if (sdmac->flags & IMX_DMA_SG_LOOP)
-		residue = (sdmac->num_bd - sdmac->buf_ptail) *
-			   sdmac->period_len - sdmac->chn_real_count;
+		residue = (desc->num_bd - desc->buf_ptail) *
+			   desc->period_len - desc->chn_real_count;
 	else
-		residue = sdmac->chn_count - sdmac->chn_real_count;
+		residue = desc->chn_count - desc->chn_real_count;
 
 	dma_set_tx_state(txstate, chan->completed_cookie, chan->cookie,
 			 residue);
@@ -1654,6 +1681,8 @@ static int sdma_init(struct sdma_engine *sdma)
 	if (ret)
 		goto err_dma_alloc;
 
+	sdma->bd0 = sdma->channel[0].desc->bd;
+
 	sdma_config_ownership(&sdma->channel[0], false, true, false);
 
 	/* Set Command Channel (Channel Zero) */
-- 
2.7.4

^ 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