Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* soc: imx: gpcv2: removing and probing fails
From: Stefan Agner @ 2018-01-08 21:12 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CAHQ1cqEutLV7wRWq3FdU1CyercLiiDgNL0trSuV5p-x7eGYFVg@mail.gmail.com>

On 2018-01-08 07:24, Andrey Smirnov wrote:
> On Sun, Jan 7, 2018 at 4:22 PM, Andrey Smirnov <andrew.smirnov@gmail.com> wrote:
>> On Sun, Jan 7, 2018 at 2:48 AM, Stefan Agner <stefan@agner.ch> wrote:
>>> Hi Andrew,
>>>
>>> I noticed that the driver fails when removing and probing again. As far
>>> as I can see due to duplicate add of the platform devices.
>>>
>>> As far as I can tell the driver should register the remove callback and
>>> do a platform_device_unregister on the newly created platform devices.
>>> However, as far as I can tell we don't hold on to a reference to them...
>>> I guess we could keep references in imx_gpcv2_probe, but maybe there is
>>> an easier way?
>>
>> Stefan:
>>
>> Good catch and sorry for the inconvenience. I just spent a little bit
>> of time repro-ing this and it looks like there are two separate bugs,
>> actually. First one, as you correctly pointed out, is due to
>> re-registration of pm-domain platform drivers. That, however, should
>> only result in a WARNING and a failed driver probing, not in a killed
>> init due to BUG. So the second one, that BUG message in the stack
>> trace, is due to the fact that I incorrectly provide statically
>> allocated data via dev.platform_data and it ends up being kfree'd in
>> platform_device_release().
>>
>> IMHO, this driver isn't really meant to be removed, so the simplest
>> solution to the first problem would be to specify
>> "imx_gpc_driver.driver.suppress_bind_attrs = true" and remove any
>> option to remove the driver, but I don't know if that's acceptable or
>> not.
>>
>> Shawn, would the above be acceptable upstream?
>>
>> Solution for bug #2 is trivial and I'll send patches for both once we
>> agree how to fix #1.
>>
>> Thanks,
>> Andrey Smirnov
>>
>> P.S: Also, since I based my code on gpc.c, I suspect that driver will
>> have exactly the same problem (I'll do some experiments to confirm)
> 
> Done with experiments. Same problem happens with gpc.c as well.

Yeah gpc.c also has another problem:
https://patchwork.kernel.org/patch/10148315/

But, yeah, you are right, even with that patch applied and when using
CONFIG_DEBUG_TEST_DRIVER_REMOVE=y it seems to show the problem as well.

I like the config symbol to test my own drivers, its just unfortunate
when mainline blows by default... But then, maybe it is the reason why
that config symbol got a UNSTABLE flag.

The full splash:
[    0.697548] ------------[ cut here ]------------
[    0.702212] WARNING: CPU: 0 PID: 1 at fs/sysfs/dir.c:31
sysfs_warn_dup+0x64/0x74
[    0.709695] sysfs: cannot create duplicate filename
'/devices/soc0/soc/2000000.aips-bus/20dc000.gpc/imx-pgc-power-domain.0'
[    0.720887] Modules linked in:
[    0.723965] CPU: 0 PID: 1 Comm: swapper/0 Not tainted
4.15.0-rc3-00061-g38f99f72e8f3-dirty #246
[    0.732694] Hardware name: Freescale i.MX6 Quad/DualLite (Device
Tree)
[    0.739263] [<8010f61c>] (unwind_backtrace) from [<8010b984>]
(show_stack+0x10/0x14)
[    0.747045] [<8010b984>] (show_stack) from [<80832024>]
(dump_stack+0x88/0x9c)
[    0.754308] [<80832024>] (dump_stack) from [<8011e7ac>]
(__warn+0xdc/0xf4)
[    0.761214] [<8011e7ac>] (__warn) from [<8011e7fc>]
(warn_slowpath_fmt+0x38/0x48)
[    0.768732] [<8011e7fc>] (warn_slowpath_fmt) from [<802768b0>]
(sysfs_warn_dup+0x64/0x74)
[    0.776950] [<802768b0>] (sysfs_warn_dup) from [<80276988>]
(sysfs_create_dir_ns+0x84/0x90)
[    0.785339] [<80276988>] (sysfs_create_dir_ns) from [<80836560>]
(kobject_add_internal+0xb4/0x30c)
[    0.794337] [<80836560>] (kobject_add_internal) from [<80836804>]
(kobject_add+0x4c/0x9c)
[    0.802554] [<80836804>] (kobject_add) from [<8050c030>]
(device_add+0xe0/0x594)
[    0.809991] [<8050c030>] (device_add) from [<805103d8>]
(platform_device_add+0x110/0x224)
[    0.818208] [<805103d8>] (platform_device_add) from [<8049bb94>]
(imx_gpc_probe+0x184/0x380)
[    0.826685] [<8049bb94>] (imx_gpc_probe) from [<805105c4>]
(platform_drv_probe+0x50/0xac)
[    0.834901] [<805105c4>] (platform_drv_probe) from [<8050ec0c>]
(driver_probe_device+0x1b4/0x3c8)
[    0.843810] [<8050ec0c>] (driver_probe_device) from [<8050eec4>]
(__driver_attach+0xa4/0xa8)
[    0.852284] [<8050eec4>] (__driver_attach) from [<8050cfe8>]
(bus_for_each_dev+0x4c/0x9c)
[    0.860495] [<8050cfe8>] (bus_for_each_dev) from [<8050e1a0>]
(bus_add_driver+0x188/0x20c)
[    0.868795] [<8050e1a0>] (bus_add_driver) from [<8050f7b4>]
(driver_register+0x78/0xf4)
[    0.876835] [<8050f7b4>] (driver_register) from [<80101b00>]
(do_one_initcall+0x44/0x168)
[    0.885049] [<80101b00>] (do_one_initcall) from [<80c00db8>]
(kernel_init_freeable+0x14c/0x1d8)
[    0.893789] [<80c00db8>] (kernel_init_freeable) from [<80844538>]
(kernel_init+0x8/0x10c)
[    0.902006] [<80844538>] (kernel_init) from [<80107a28>]
(ret_from_fork+0x14/0x2c)
[    0.909639] ---[ end trace ade27083f156a989 ]---
[    0.914277] ------------[ cut here ]------------
[    0.918934] WARNING: CPU: 0 PID: 1 at lib/kobject.c:240
kobject_add_internal+0x278/0x30c
[    0.927073] kobject_add_internal failed for imx-pgc-power-domain.0
with -EEXIST, don't try to register things with the same name in the
same directory.
[    0.940690] Modules linked in:
[    0.943763] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       
4.15.0-rc3-00061-g38f99f72e8f3-dirty #246
[    0.953796] Hardware name: Freescale i.MX6 Quad/DualLite (Device
Tree)
[    0.960357] [<8010f61c>] (unwind_backtrace) from [<8010b984>]
(show_stack+0x10/0x14)
[    0.968136] [<8010b984>] (show_stack) from [<80832024>]
(dump_stack+0x88/0x9c)
[    0.975394] [<80832024>] (dump_stack) from [<8011e7ac>]
(__warn+0xdc/0xf4)
[    0.982298] [<8011e7ac>] (__warn) from [<8011e7fc>]
(warn_slowpath_fmt+0x38/0x48)
[    0.989815] [<8011e7fc>] (warn_slowpath_fmt) from [<80836724>]
(kobject_add_internal+0x278/0x30c)
[    0.998725] [<80836724>] (kobject_add_internal) from [<80836804>]
(kobject_add+0x4c/0x9c)
[    1.006938] [<80836804>] (kobject_add) from [<8050c030>]
(device_add+0xe0/0x594)
[    1.014370] [<8050c030>] (device_add) from [<805103d8>]
(platform_device_add+0x110/0x224)
[    1.022583] [<805103d8>] (platform_device_add) from [<8049bb94>]
(imx_gpc_probe+0x184/0x380)
[    1.031057] [<8049bb94>] (imx_gpc_probe) from [<805105c4>]
(platform_drv_probe+0x50/0xac)
[    1.039269] [<805105c4>] (platform_drv_probe) from [<8050ec0c>]
(driver_probe_device+0x1b4/0x3c8)
[    1.048176] [<8050ec0c>] (driver_probe_device) from [<8050eec4>]
(__driver_attach+0xa4/0xa8)
[    1.056647] [<8050eec4>] (__driver_attach) from [<8050cfe8>]
(bus_for_each_dev+0x4c/0x9c)
[    1.064857] [<8050cfe8>] (bus_for_each_dev) from [<8050e1a0>]
(bus_add_driver+0x188/0x20c)
[    1.073153] [<8050e1a0>] (bus_add_driver) from [<8050f7b4>]
(driver_register+0x78/0xf4)
[    1.081191] [<8050f7b4>] (driver_register) from [<80101b00>]
(do_one_initcall+0x44/0x168)
[    1.089404] [<80101b00>] (do_one_initcall) from [<80c00db8>]
(kernel_init_freeable+0x14c/0x1d8)
[    1.098141] [<80c00db8>] (kernel_init_freeable) from [<80844538>]
(kernel_init+0x8/0x10c)
[    1.106355] [<80844538>] (kernel_init) from [<80107a28>]
(ret_from_fork+0x14/0x2c)
[    1.113979] ---[ end trace ade27083f156a98a ]---
[    1.118637] ------------[ cut here ]------------
[    1.123275] Kernel BUG at c46b9f56 [verbose debug info unavailable]
[    1.129564] Internal error: Oops - BUG: 0 [#1] SMP ARM
[    1.134719] Modules linked in:
[    1.137791] CPU: 0 PID: 1 Comm: swapper/0 Tainted: G        W       
4.15.0-rc3-00061-g38f99f72e8f3-dirty #246
[    1.147823] Hardware name: Freescale i.MX6 Quad/DualLite (Device
Tree)
[    1.154375] PC is at kfree+0xfc/0x140
[    1.158054] LR is at platform_device_release+0x10/0x34
[    1.163209] pc : [<801fd744>]    lr : [<805101b0>]    psr: 40000053
[    1.169495] sp : 84057de8  ip : 00000000  fp : 842e9e00
[    1.174736] r10: 842e9800  r9 : 80d23968  r8 : 80aa8a40
[    1.179980] r7 : 80952bac  r6 : 00000000  r5 : 842e9810  r4 :
842e9810
[    1.186529] r3 : 87dd2474  r2 : 87dd2460  r1 : a0000053  r0 :
80d23a20
[    1.193080] Flags: nZcv  IRQs on  FIQs off  Mode SVC_32  ISA ARM 
Segment none
[    1.200328] Control: 10c5387d  Table: 10004059  DAC: 00000051
[    1.206093] Process swapper/0 (pid: 1, stack limit = 0x86b82e40)
[    1.212122] Stack: (0x84057de8 to 0x84058000)
[    1.216499] 7de0:                   842e9810 842e9818 842e9810
842e9810 842e9810 00000000
[    1.224710] 7e00: 80952bac 805101b0 842e9818 80509eac 842e9818
80d2a784 84251480 80835f38
[    1.232919] 7e20: 87da98f4 80952bac 87da9810 ffffffef 87da98f4
8049bd2c 00000000 00000000
[    1.241128] 7e40: 84155a10 00000042 842500c0 00000000 80b410d8
84155a10 fffffffe 80d239d8
[    1.249337] 7e60: fffffdfb 80d239d8 80daefe8 00000000 00000000
805105c4 84155a10 00000000
[    1.257548] 7e80: 80daefe4 00000000 80d239d8 8050ec0c 87da95f0
00000000 000000d7 84155a10
[    1.265756] 7ea0: 80d239d8 84155a44 00000000 000000d7 80c5b83c
80c6c57c 00000000 8050eec4
[    1.273965] 7ec0: 00000000 80d239d8 8050ee20 8050cfe8 84050358
8414f6b4 80d239d8 842b4f00
[    1.282174] 7ee0: 80d2ab60 8050e1a0 80afef10 80c35700 80d239d8
80d239d8 00000000 80c35ecc
[    1.290384] 7f00: 80d58680 8050f7b4 ffffe000 00000000 80c35ecc
80101b00 80b94c44 000000d7
[    1.298595] 7f20: 00000000 8013a458 00000000 80b1dd5c 00000006
00000006 80aadf4c 00000000
[    1.306803] 7f40: 80ab7130 80aadfc0 87fffaee 87fffaf4 00000000
00000007 80d58680 80c5b830
[    1.315012] 7f60: 00000007 80d58680 80c5b834 80d58680 000000d7
80c00db8 00000006 00000006
[    1.323221] 7f80: 00000000 80c005b0 00000000 80844530 00000000
00000000 00000000 00000000
[    1.331430] 7fa0: 00000000 80844538 00000000 80107a28 00000000
00000000 00000000 00000000
[    1.339639] 7fc0: 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000
[    1.347848] 7fe0: 00000000 00000000 00000000 00000000 00000013
00000000 3fbfd7ff fed779df
[    1.356064] [<801fd744>] (kfree) from [<805101b0>]
(platform_device_release+0x10/0x34)
[    1.364019] [<805101b0>] (platform_device_release) from [<80509eac>]
(device_release+0x2c/0x90)
[    1.372759] [<80509eac>] (device_release) from [<80835f38>]
(kobject_put+0x94/0xe4)
[    1.380447] [<80835f38>] (kobject_put) from [<8049bd2c>]
(imx_gpc_probe+0x31c/0x380)
[    1.388224] [<8049bd2c>] (imx_gpc_probe) from [<805105c4>]
(platform_drv_probe+0x50/0xac)
[    1.396435] [<805105c4>] (platform_drv_probe) from [<8050ec0c>]
(driver_probe_device+0x1b4/0x3c8)
[    1.405345] [<8050ec0c>] (driver_probe_device) from [<8050eec4>]
(__driver_attach+0xa4/0xa8)
[    1.413815] [<8050eec4>] (__driver_attach) from [<8050cfe8>]
(bus_for_each_dev+0x4c/0x9c)
[    1.422024] [<8050cfe8>] (bus_for_each_dev) from [<8050e1a0>]
(bus_add_driver+0x188/0x20c)
[    1.430320] [<8050e1a0>] (bus_add_driver) from [<8050f7b4>]
(driver_register+0x78/0xf4)
[    1.438357] [<8050f7b4>] (driver_register) from [<80101b00>]
(do_one_initcall+0x44/0x168)
[    1.446568] [<80101b00>] (do_one_initcall) from [<80c00db8>]
(kernel_init_freeable+0x14c/0x1d8)
[    1.455305] [<80c00db8>] (kernel_init_freeable) from [<80844538>]
(kernel_init+0x8/0x10c)
[    1.463518] [<80844538>] (kernel_init) from [<80107a28>]
(ret_from_fork+0x14/0x2c)
[    1.471118] Code: 1a000003 e5923014 e3130001 1a000000 (e7f001f2)
[    1.477236] ---[ end trace ade27083f156a98b ]---
[    1.482097] Kernel panic - not syncing: Attempted to kill init!
exitcode=0x0000000b
[    1.482097]
[    1.491281] ---[ end Kernel panic - not syncing: Attempted to kill
init! exitcode=0x0000000b
[    1.491281]

--
Stefan

^ permalink raw reply

* [PATCH v2 1/5] pinctrl: imx: use struct imx_pinctrl_soc_info as a const
From: Stefan Agner @ 2018-01-08 20:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180108164855.GA6504@t450s.lan>

On 2018-01-08 17:48, Gary Bisson wrote:
> Hi Stefan,
> 
> On Sat, Jan 06, 2018 at 03:25:49PM +0100, Stefan Agner wrote:
>> For some SoCs the struct imx_pinctrl_soc_info is passed through
>> of_device_id.data which is const. Most variables are already const
>> or otherwise not written. However, some fields are modified at
>> runtime. Move those fields to the dynamically allocated struct
>> imx_pinctrl.
>>
>> Fixes: b3060044e495 ("pinctrl: freescale: imx7d: make of_device_ids const")
>> Cc: Shawn Guo <shawnguo@kernel.org>
>> Cc: Arvind Yadav <arvind.yadav.cs@gmail.com>
>> Cc: Dong Aisheng <aisheng.dong@nxp.com>
>> Cc: Gary Bisson <gary.bisson@boundarydevices.com>
>> Signed-off-by: Stefan Agner <stefan@agner.ch>
> 
> This is actually more or less a revert of a previous commit:
> b28742be4709 pinctrl: imx: remove const qualifier of imx_pinctrl_soc_info

Hm, I see. However, back then imx_pinctrl_probe still consumed a
non-const struct imx_pinctrl_soc_info pointer. So this constifies all
the way through. 

> 
> Note that the idea for this commit was to get dt-overlays working and
> able to do pinctrl changes using configfs interface to load an overlay
> (using Pantelis patch). Not sure where we stand on loading such overlay
> from user-space, is it still something that will happen?

I am all for dt-overlays and actually also hope that it will make it
completely into mainline. So whatever prevents using device tree
overlays should be addressed.

It seems that ngroups is now part of struct pinctrl_dev (num_groups),
which is still writable. So we should be fine?

As far as I can tell all remaining properties come from the drivers
directly and should not be influenced by anything in the device tree....

--
Stefan

^ permalink raw reply

* arm64 crashkernel fails to boot on acpi-only machines due to ACPI regions being no longer mapped as NOMAP
From: Bhupesh Sharma @ 2018-01-08 20:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <CACi5LpNRtXh-j9Y9HwRatDZwRMr++-ZeaSnk62vD3btpxsVv7w@mail.gmail.com>

Hello Akashi,

On Tue, Dec 26, 2017 at 8:26 AM, Bhupesh Sharma <bhsharma@redhat.com> wrote:
> On Tue, Dec 26, 2017 at 7:58 AM, AKASHI Takahiro
> <takahiro.akashi@linaro.org> wrote:
>> On Tue, Dec 26, 2017 at 09:35:17AM +0800, Dave Young wrote:
>>> [snip]
>>> > > > Well, we may be able to change pr_warn() to pr_warn_once() here, but
>>> > > > I hope that adding "numa=off" to kernel command line should also work.
>>> > >
>>> > > Hmm, adding "numa=off" to crashkernel bootargs works, and TBH it was
>>> > > my initial thought process as well, but I am not sure if this will
>>> > > cause any regressions on aarch64 systems which use crashdump feature.
>>> >
>>> > It should be fine since we use numa=off by default for all other arches
>>> > ie. x86, ppc64 and s390. Actually disabling numa in kdump kernel can save
>>> > mm component memory usage.
>>> >
>>>
>>> Forgot to say I means in RHEL and Fedora we use numa=off for kdump..
>>
>> Thank you for the clarification.
>> (It might be better to make numa off automatically if maxcpus == 0 (and 1?).)
>>
>
> Not sure if we can leave this to the distribution-specific kdump
> scripts (as the crashkernel boot can be held up for sufficient time
> and may appear stuck). The distribution scripts may be different (for
> e.g. ubuntu and RHEL/fedora) across distributions and may have
> different bootarg options.
>
> So how about considering a kernel fix only which doesn't require
> relying on changing the distribution-specific kdump scripts, as we
> should avoid introducing a regression while trying to fix a regression
> :)
>
> Just my 2 cents.
>

Sorry for the delay but I was on holidays in the last week.

Are you planning to send a patch to fix this issue or do you want me
to send a RFC version instead?

i think this is a blocking issue for aarch64 kdump support on newer
kernels (v4.14) and we are already hearing about this issue from other
users as well, so it would be great to get this fixed now that we have
root-caused the issue and found a possible way around.

Regards,
Bhupesh

^ permalink raw reply

* [PATCH v6 3/9] drm: Add Content Protection property
From: Sean Paul @ 2018-01-08 19:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180108195545.218615-1-seanpaul@chromium.org>

This patch adds a new optional connector property to allow userspace to enable
protection over the content it is displaying. This will typically be implemented
by the driver using HDCP.

The property is a tri-state with the following values:
- OFF: Self explanatory, no content protection
- DESIRED: Userspace requests that the driver enable protection
- ENABLED: Once the driver has authenticated the link, it sets this value

The driver is responsible for downgrading ENABLED to DESIRED if the link becomes
unprotected. The driver should also maintain the desiredness of protection
across hotplug/dpms/suspend.

If this looks familiar, I posted [1] this 3 years ago. We have been using this
in ChromeOS across exynos, mediatek, and rockchip over that time.

Changes in v2:
 - Pimp kerneldoc for content_protection_property (Daniel)
 - Drop sysfs attribute
Changes in v3:
 - None
Changes in v4:
- Changed kerneldoc to recommend userspace polling (Daniel)
- Changed kerneldoc to briefly describe how to attach the property (Daniel)
Changes in v5:
- checkpatch whitespace noise
- Change DRM_MODE_CONTENT_PROTECTION_OFF to DRM_MODE_CONTENT_PROTECTION_UNDESIRED
Changes in v6:
- None

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Sean Paul <seanpaul@chromium.org>

[1] https://lists.freedesktop.org/archives/dri-devel/2014-December/073336.html
---
 drivers/gpu/drm/drm_atomic.c    |  8 +++++
 drivers/gpu/drm/drm_connector.c | 78 +++++++++++++++++++++++++++++++++++++++++
 include/drm/drm_connector.h     | 16 +++++++++
 include/uapi/drm/drm_mode.h     |  4 +++
 4 files changed, 106 insertions(+)

diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c
index b76d49218cf1..69ff763a834e 100644
--- a/drivers/gpu/drm/drm_atomic.c
+++ b/drivers/gpu/drm/drm_atomic.c
@@ -1224,6 +1224,12 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector,
 		state->picture_aspect_ratio = val;
 	} else if (property == connector->scaling_mode_property) {
 		state->scaling_mode = val;
+	} else if (property == connector->content_protection_property) {
+		if (val == DRM_MODE_CONTENT_PROTECTION_ENABLED) {
+			DRM_DEBUG_KMS("only drivers can set CP Enabled\n");
+			return -EINVAL;
+		}
+		state->content_protection = val;
 	} else if (connector->funcs->atomic_set_property) {
 		return connector->funcs->atomic_set_property(connector,
 				state, property, val);
@@ -1303,6 +1309,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector,
 		*val = state->picture_aspect_ratio;
 	} else if (property == connector->scaling_mode_property) {
 		*val = state->scaling_mode;
+	} else if (property == connector->content_protection_property) {
+		*val = state->content_protection;
 	} else if (connector->funcs->atomic_get_property) {
 		return connector->funcs->atomic_get_property(connector,
 				state, property, val);
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index 2559c615d984..b85a7749709d 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -756,6 +756,13 @@ static const struct drm_prop_enum_list drm_tv_subconnector_enum_list[] = {
 DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name,
 		 drm_tv_subconnector_enum_list)
 
+static struct drm_prop_enum_list drm_cp_enum_list[] = {
+	{ DRM_MODE_CONTENT_PROTECTION_UNDESIRED, "Undesired" },
+	{ DRM_MODE_CONTENT_PROTECTION_DESIRED, "Desired" },
+	{ DRM_MODE_CONTENT_PROTECTION_ENABLED, "Enabled" },
+};
+DRM_ENUM_NAME_FN(drm_get_content_protection_name, drm_cp_enum_list)
+
 /**
  * DOC: standard connector properties
  *
@@ -826,6 +833,41 @@ DRM_ENUM_NAME_FN(drm_get_tv_subconnector_name,
  * 	Indicates the output should be ignored for purposes of displaying a
  * 	standard desktop environment or console. This is most likely because
  * 	the output device is not rectilinear.
+ * Content Protection:
+ *	This property is used by userspace to request the kernel protect future
+ *	content communicated over the link. When requested, kernel will apply
+ *	the appropriate means of protection (most often HDCP), and use the
+ *	property to tell userspace the protection is active.
+ *
+ *	Drivers can set this up by calling
+ *	drm_connector_attach_content_protection_property() on initialization.
+ *
+ *	The value of this property can be one of the following:
+ *
+ *	- DRM_MODE_CONTENT_PROTECTION_UNDESIRED = 0
+ *		The link is not protected, content is transmitted in the clear.
+ *	- DRM_MODE_CONTENT_PROTECTION_DESIRED = 1
+ *		Userspace has requested content protection, but the link is not
+ *		currently protected. When in this state, kernel should enable
+ *		Content Protection as soon as possible.
+ *	- DRM_MODE_CONTENT_PROTECTION_ENABLED = 2
+ *		Userspace has requested content protection, and the link is
+ *		protected. Only the driver can set the property to this value.
+ *		If userspace attempts to set to ENABLED, kernel will return
+ *		-EINVAL.
+ *
+ *	A few guidelines:
+ *
+ *	- DESIRED state should be preserved until userspace de-asserts it by
+ *	  setting the property to UNDESIRED. This means ENABLED should only
+ *	  transition to UNDESIRED when the user explicitly requests it.
+ *	- If the state is DESIRED, kernel should attempt to re-authenticate the
+ *	  link whenever possible. This includes across disable/enable, dpms,
+ *	  hotplug, downstream device changes, link status failures, etc..
+ *	- Userspace is responsible for polling the property to determine when
+ *	  the value transitions from ENABLED to DESIRED. This signifies the link
+ *	  is no longer protected and userspace should take appropriate action
+ *	  (whatever that might be).
  *
  * Connectors also have one standardized atomic property:
  *
@@ -1126,6 +1168,42 @@ int drm_connector_attach_scaling_mode_property(struct drm_connector *connector,
 }
 EXPORT_SYMBOL(drm_connector_attach_scaling_mode_property);
 
+/**
+ * drm_connector_attach_content_protection_property - attach content protection
+ * property
+ *
+ * @connector: connector to attach CP property on.
+ *
+ * This is used to add support for content protection on select connectors.
+ * Content Protection is intentionally vague to allow for different underlying
+ * technologies, however it is most implemented by HDCP.
+ *
+ * The content protection will be set to &drm_connector_state.content_protection
+ *
+ * Returns:
+ * Zero on success, negative errno on failure.
+ */
+int drm_connector_attach_content_protection_property(
+		struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct drm_property *prop;
+
+	prop = drm_property_create_enum(dev, 0, "Content Protection",
+					drm_cp_enum_list,
+					ARRAY_SIZE(drm_cp_enum_list));
+	if (!prop)
+		return -ENOMEM;
+
+	drm_object_attach_property(&connector->base, prop,
+				   DRM_MODE_CONTENT_PROTECTION_UNDESIRED);
+
+	connector->content_protection_property = prop;
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_connector_attach_content_protection_property);
+
 /**
  * drm_mode_create_aspect_ratio_property - create aspect ratio property
  * @dev: DRM device
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h
index ed38df4ac204..758a176e7b57 100644
--- a/include/drm/drm_connector.h
+++ b/include/drm/drm_connector.h
@@ -419,6 +419,12 @@ struct drm_connector_state {
 	 * upscaling, mostly used for built-in panels.
 	 */
 	unsigned int scaling_mode;
+
+	/**
+	 * @content_protection: Connector property to request content
+	 * protection. This is most commonly used for HDCP.
+	 */
+	unsigned int content_protection;
 };
 
 /**
@@ -766,6 +772,7 @@ struct drm_cmdline_mode {
  * @tile_h_size: horizontal size of this tile.
  * @tile_v_size: vertical size of this tile.
  * @scaling_mode_property:  Optional atomic property to control the upscaling.
+ * @content_protection_property: Optional property to control content protection
  *
  * Each connector may be connected to one or more CRTCs, or may be clonable by
  * another connector if they can share a CRTC.  Each connector also has a specific
@@ -856,6 +863,12 @@ struct drm_connector {
 
 	struct drm_property *scaling_mode_property;
 
+	/**
+	 * @content_protection_property: DRM ENUM property for content
+	 * protection
+	 */
+	struct drm_property *content_protection_property;
+
 	/**
 	 * @path_blob_ptr:
 	 *
@@ -1065,6 +1078,7 @@ const char *drm_get_dvi_i_subconnector_name(int val);
 const char *drm_get_dvi_i_select_name(int val);
 const char *drm_get_tv_subconnector_name(int val);
 const char *drm_get_tv_select_name(int val);
+const char *drm_get_content_protection_name(int val);
 
 int drm_mode_create_dvi_i_properties(struct drm_device *dev);
 int drm_mode_create_tv_properties(struct drm_device *dev,
@@ -1073,6 +1087,8 @@ int drm_mode_create_tv_properties(struct drm_device *dev,
 int drm_mode_create_scaling_mode_property(struct drm_device *dev);
 int drm_connector_attach_scaling_mode_property(struct drm_connector *connector,
 					       u32 scaling_mode_mask);
+int drm_connector_attach_content_protection_property(
+		struct drm_connector *connector);
 int drm_mode_create_aspect_ratio_property(struct drm_device *dev);
 int drm_mode_create_suggested_offset_properties(struct drm_device *dev);
 
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index 5597a87154e5..d1a69ff24fe8 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -173,6 +173,10 @@ extern "C" {
 		DRM_MODE_REFLECT_X | \
 		DRM_MODE_REFLECT_Y)
 
+/* Content Protection Flags */
+#define DRM_MODE_CONTENT_PROTECTION_UNDESIRED	0
+#define DRM_MODE_CONTENT_PROTECTION_DESIRED     1
+#define DRM_MODE_CONTENT_PROTECTION_ENABLED     2
 
 struct drm_mode_modeinfo {
 	__u32 clock;
-- 
2.16.0.rc0.223.g4a4ac83678-goog

^ permalink raw reply related

* [PATCH] mdio-sun4i: Fix a memory leak
From: David Miller @ 2018-01-08 19:30 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180106080009.5325-1-christophe.jaillet@wanadoo.fr>

From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
Date: Sat,  6 Jan 2018 09:00:09 +0100

> If the probing of the regulator is deferred, the memory allocated by
> 'mdiobus_alloc_size()' will be leaking.
> It should be freed before the next call to 'sun4i_mdio_probe()' which will
> reallocate it.
> 
> Fixes: 4bdcb1dd9feb ("net: Add MDIO bus driver for the Allwinner EMAC")
> Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>

Applied, thank you.

^ permalink raw reply

* [PATCH] iommu/exynos: Don't unconditionally steal bus ops
From: Robin Murphy @ 2018-01-08 19:27 UTC (permalink / raw)
  To: linux-arm-kernel

Removing the early device registration hook overlooked the fact that
it only ran conditionally on a compatible device being present in the
DT. With exynos_iommu_init() now running as an unconditional initcall,
problems arise on non-Exynos systems when other IOMMU drivers find
themselves unable to install their ops on the platform bus, or at worst
the Exynos ops get called with someone else's domain and all hell breaks
loose.

Fix this by delaying the setting of bus ops until an Exynos IOMMU is
actually found, to replicate the previous order of events.

Fixes: 928055a01b3f ("iommu/exynos: Remove custom platform device registration code")
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
 drivers/iommu/exynos-iommu.c | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 6a96a4c42153..e9e756156429 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -574,6 +574,12 @@ static int __init exynos_sysmmu_probe(struct platform_device *pdev)
 	struct sysmmu_drvdata *data;
 	struct resource *res;
 
+	if (platform_bus_type->iommu_ops != &exynos_iommu_ops) {
+		ret = bus_set_iommu(&platform_bus_type, &exynos_iommu_ops);
+		if (ret)
+			return ret;
+	}
+
 	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
@@ -1367,16 +1373,8 @@ static int __init exynos_iommu_init(void)
 		goto err_zero_lv2;
 	}
 
-	ret = bus_set_iommu(&platform_bus_type, &exynos_iommu_ops);
-	if (ret) {
-		pr_err("%s: Failed to register exynos-iommu driver.\n",
-								__func__);
-		goto err_set_iommu;
-	}
-
 	return 0;
-err_set_iommu:
-	kmem_cache_free(lv2table_kmem_cache, zero_lv2_table);
+
 err_zero_lv2:
 	platform_driver_unregister(&exynos_sysmmu_driver);
 err_reg_driver:
-- 
2.13.4.dirty

^ permalink raw reply related

* [PATCH] arm64: Implement branch predictor hardening for Falkor
From: Shanker Donthineni @ 2018-01-08 19:10 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180108184446.GC13175@arm.com>

Hi Will,

On 01/08/2018 12:44 PM, Will Deacon wrote:
> On Mon, Jan 08, 2018 at 05:09:33PM +0000, Will Deacon wrote:
>> On Fri, Jan 05, 2018 at 02:28:59PM -0600, Shanker Donthineni wrote:
>>> Falkor is susceptible to branch predictor aliasing and can
>>> theoretically be attacked by malicious code. This patch
>>> implements a mitigation for these attacks, preventing any
>>> malicious entries from affecting other victim contexts.
>>
>> Thanks, Shanker. I'll pick this up (fixing the typo pointed out by Drew).
> 
> Note that MIDR_FALKOR doesn't exist in mainline, so I had to drop those
> changes too. See the kpti branch for details.
> 

The FALKOR MIDR patch is already available in the upstream kernel v4.15-rc7
    https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/arch/arm64?h=v4.15-rc7&id=c622cc013cece073722592cff1ac6643a33b1622

If you want I can resend the above patch in v2 series including typo fix.

> If you'd like anything else done here, please send additional patches to me
> and Catalin that we can apply on top of what we currently have. Note that
> I'm in the air tomorrow, so won't be picking up email.
> 
> Cheers,
> 
> Will
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel at lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 

-- 
Shanker Donthineni
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.

^ permalink raw reply

* [PATCH v2 6/6] arm: KVM: Invalidate icache on guest exit for Cortex-A15
From: Marc Zyngier @ 2018-01-08 18:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180108185533.9698-1-marc.zyngier@arm.com>

In order to avoid aliasing attacks against the branch predictor
on Cortex-A15, let's invalidate the BTB on guest exit, which can
only be done by invalidating the icache (with ACTLR[0] being set).

We use the same hack as for A12/A17 to perform the vector decoding.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/include/asm/kvm_mmu.h |  4 ++++
 arch/arm/kvm/hyp/hyp-entry.S   | 27 ++++++++++++++++++++++++++-
 2 files changed, 30 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index b47db5b9e407..72ffb4d27fde 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -226,12 +226,16 @@ static inline void *kvm_get_hyp_vector(void)
 {
 	extern char __kvm_hyp_vector[];
 	extern char __kvm_hyp_vector_bp_inv[];
+	extern char __kvm_hyp_vector_ic_inv[];
 
 	switch(read_cpuid_part()) {
 	case ARM_CPU_PART_CORTEX_A12:
 	case ARM_CPU_PART_CORTEX_A17:
 		return kvm_ksym_ref(__kvm_hyp_vector_bp_inv);
 
+	case ARM_CPU_PART_CORTEX_A15:
+		return kvm_ksym_ref(__kvm_hyp_vector_ic_inv);
+
 	default:
 		return kvm_ksym_ref(__kvm_hyp_vector);
 	}
diff --git a/arch/arm/kvm/hyp/hyp-entry.S b/arch/arm/kvm/hyp/hyp-entry.S
index 2e8d2179eb70..7c0059927e2e 100644
--- a/arch/arm/kvm/hyp/hyp-entry.S
+++ b/arch/arm/kvm/hyp/hyp-entry.S
@@ -70,7 +70,31 @@ __kvm_hyp_vector:
 	W(b)	hyp_hvc
 	W(b)	hyp_irq
 	W(b)	hyp_fiq
-	
+
+	.align 5
+__kvm_hyp_vector_ic_inv:
+	.global __kvm_hyp_vector_ic_inv
+
+	/*
+	 * We encode the exception entry in the bottom 3 bits of
+	 * SP, and we have to guarantee to be 8 bytes aligned.
+	 */
+	W(add)	sp, sp, #1	/* Reset 	  7 */
+	W(add)	sp, sp, #1	/* Undef	  6 */
+	W(add)	sp, sp, #1	/* Syscall	  5 */
+	W(add)	sp, sp, #1	/* Prefetch abort 4 */
+	W(add)	sp, sp, #1	/* Data abort	  3 */
+	W(add)	sp, sp, #1	/* HVC		  2 */
+	W(add)	sp, sp, #1	/* IRQ		  1 */
+	W(add)	sp, sp, #1	/* FIQ		  0 */
+
+	sub	sp, sp, #1
+
+	mcr	p15, 0, r0, c7, c5, 0	/* ICIALLU */
+	isb
+
+	b	decode_vectors
+
 	.align 5
 __kvm_hyp_vector_bp_inv:
 	.global __kvm_hyp_vector_bp_inv
@@ -93,6 +117,7 @@ __kvm_hyp_vector_bp_inv:
 	mcr	p15, 0, r0, c7, c5, 6	/* BPIALL */
 	isb
 
+decode_vectors:
 	/*
 	 * Yet another silly hack: Use VPIDR as a temp register.
 	 * Thumb2 is really a pain, as SP cannot be used with most
-- 
2.14.2

^ permalink raw reply related

* [PATCH v2 5/6] arm: Invalidate icache on prefetch abort outside of user mapping on Cortex-A15
From: Marc Zyngier @ 2018-01-08 18:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180108185533.9698-1-marc.zyngier@arm.com>

In order to prevent aliasing attacks on the branch predictor,
invalidate the icache on Cortex-A15, which has the side effect
of invalidating the BTB. This requires ACTLR[0] to be set to 1
(secure operation).

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/include/asm/cp15.h | 1 +
 arch/arm/mm/fault.c         | 4 ++++
 2 files changed, 5 insertions(+)

diff --git a/arch/arm/include/asm/cp15.h b/arch/arm/include/asm/cp15.h
index 9e900ae855aa..07e27f212dc7 100644
--- a/arch/arm/include/asm/cp15.h
+++ b/arch/arm/include/asm/cp15.h
@@ -66,6 +66,7 @@
 #define write_sysreg(v, ...)		__write_sysreg(v, __VA_ARGS__)
 
 #define BPIALL				__ACCESS_CP15(c7, 0, c5, 6)
+#define ICIALLU				__ACCESS_CP15(c7, 0, c5, 0)
 
 extern unsigned long cr_alignment;	/* defined in entry-armv.S */
 
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index ff272ffcf741..bda37ce63fc7 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -417,6 +417,10 @@ do_pabt_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 		case ARM_CPU_PART_CORTEX_A17:
 			write_sysreg(0, BPIALL);
 			break;
+
+		case ARM_CPU_PART_CORTEX_A15:
+			write_sysreg(0, ICIALLU);
+			break;
 		}
 	}
 
-- 
2.14.2

^ permalink raw reply related

* [PATCH v2 4/6] arm: Add icache invalidation on switch_mm for Cortex-A15
From: Marc Zyngier @ 2018-01-08 18:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180108185533.9698-1-marc.zyngier@arm.com>

In order to avoid aliasing attacks against the branch predictor,
Cortex-A15 require to invalidate the BTB when switching
from one user context to another. The only way to do so on this
CPU is to perform an ICIALLU, having set ACTLR[0] to 1 from secure
mode.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/mm/proc-v7-2level.S | 10 ++++++++++
 arch/arm/mm/proc-v7-3level.S | 16 ++++++++++++++++
 arch/arm/mm/proc-v7.S        | 18 +++++++++++++++++-
 3 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/arch/arm/mm/proc-v7-2level.S b/arch/arm/mm/proc-v7-2level.S
index 0422e58b74e8..7dc9e1c69039 100644
--- a/arch/arm/mm/proc-v7-2level.S
+++ b/arch/arm/mm/proc-v7-2level.S
@@ -40,7 +40,17 @@
  *	Note that we always need to flush BTAC/BTB if IBE is set
  *	even on Cortex-A8 revisions not affected by 430973.
  *	If IBE is not set, the flush BTAC/BTB won't do anything.
+ *
+ *	Cortex-A15 requires ACTLR[0] to be set from secure in order
+ *	for the icache invalidation to also invalidate the BTB.
  */
+ENTRY(cpu_ca15_switch_mm)
+#ifdef CONFIG_MMU
+	mcr	p15, 0, r0, c7, c5, 0			@ ICIALLU
+	isb
+	b	cpu_v7_switch_mm
+#endif
+ENDPROC(cpu_ca15_switch_mm)
 ENTRY(cpu_v7_btbinv_switch_mm)
 #ifdef CONFIG_MMU
 	mov	r2, #0
diff --git a/arch/arm/mm/proc-v7-3level.S b/arch/arm/mm/proc-v7-3level.S
index f6adfe88ead2..0a2245b309e5 100644
--- a/arch/arm/mm/proc-v7-3level.S
+++ b/arch/arm/mm/proc-v7-3level.S
@@ -71,6 +71,22 @@ ENTRY(cpu_v7_switch_mm)
 ENDPROC(cpu_v7_switch_mm)
 ENDPROC(cpu_v7_btbinv_switch_mm)
 
+/*
+ *	Cortex-A15 requires ACTLR[0] to be set from secure in order
+ *	for the icache invalidation to also invalidate the BTB.
+ */
+ENTRY(cpu_ca15_switch_mm)
+#ifdef CONFIG_MMU
+	mcr	p15, 0, r0, c7, c5, 0			@ ICIALLU
+	mmid	r2, r2
+	asid	r2, r2
+	orr	rpgdh, rpgdh, r2, lsl #(48 - 32)	@ upper 32-bits of pgd
+	mcrr	p15, 0, rpgdl, rpgdh, c2		@ set TTB 0
+	isb
+#endif
+	ret	lr
+ENDPROC(cpu_ca15_switch_mm)
+
 #ifdef __ARMEB__
 #define rl r3
 #define rh r2
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 0a14967fd400..9310fd9aa1cf 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -173,6 +173,21 @@ ENDPROC(cpu_v7_do_resume)
 	globl_equ	cpu_v7_btbinv_do_resume,	cpu_v7_do_resume
 #endif
 
+/*
+ * Cortex-A15 that require an icache invalidation on switch_mm
+ */
+	globl_equ	cpu_ca15_proc_init,		cpu_v7_proc_init
+	globl_equ	cpu_ca15_proc_fin,		cpu_v7_proc_fin
+	globl_equ	cpu_ca15_reset,			cpu_v7_reset
+	globl_equ	cpu_ca15_do_idle,		cpu_v7_do_idle
+	globl_equ	cpu_ca15_dcache_clean_area, 	cpu_v7_dcache_clean_area
+	globl_equ	cpu_ca15_set_pte_ext,		cpu_v7_set_pte_ext
+	globl_equ	cpu_ca15_suspend_size,		cpu_v7_suspend_size
+#ifdef CONFIG_ARM_CPU_SUSPEND
+	globl_equ	cpu_ca15_do_suspend,		cpu_v7_do_suspend
+	globl_equ	cpu_ca15_do_resume,		cpu_v7_do_resume
+#endif
+
 /*
  * Cortex-A9 processor functions
  */
@@ -549,6 +564,7 @@ __v7_setup_stack:
 	@ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
 	define_processor_functions v7, dabort=v7_early_abort, pabort=v7_pabort, suspend=1
 	define_processor_functions v7_btbinv, dabort=v7_early_abort, pabort=v7_pabort, suspend=1
+	define_processor_functions ca15, dabort=v7_early_abort, pabort=v7_pabort, suspend=1
 #ifndef CONFIG_ARM_LPAE
 	define_processor_functions ca9mp, dabort=v7_early_abort, pabort=v7_pabort, suspend=1
 #endif
@@ -668,7 +684,7 @@ __v7_ca12mp_proc_info:
 __v7_ca15mp_proc_info:
 	.long	0x410fc0f0
 	.long	0xff0ffff0
-	__v7_proc __v7_ca15mp_proc_info, __v7_ca15mp_setup
+	__v7_proc __v7_ca15mp_proc_info, __v7_ca15mp_setup, proc_fns = ca15_processor_functions
 	.size	__v7_ca15mp_proc_info, . - __v7_ca15mp_proc_info
 
 	/*
-- 
2.14.2

^ permalink raw reply related

* [PATCH v2 3/6] arm: KVM: Invalidate BTB on guest exit
From: Marc Zyngier @ 2018-01-08 18:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180108185533.9698-1-marc.zyngier@arm.com>

In order to avoid aliasing attacks against the branch predictor,
let's invalidate the BTB on guest exit. This is made complicated
by the fact that we cannot take a branch before invalidating the
BTB.

Another thing is that we perform the invalidation on all
implementations, no matter if they are affected or not.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/include/asm/kvm_asm.h |  2 --
 arch/arm/include/asm/kvm_mmu.h | 13 ++++++++-
 arch/arm/kvm/hyp/hyp-entry.S   | 64 ++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 74 insertions(+), 5 deletions(-)

diff --git a/arch/arm/include/asm/kvm_asm.h b/arch/arm/include/asm/kvm_asm.h
index 36dd2962a42d..df24ed48977d 100644
--- a/arch/arm/include/asm/kvm_asm.h
+++ b/arch/arm/include/asm/kvm_asm.h
@@ -61,8 +61,6 @@ struct kvm_vcpu;
 extern char __kvm_hyp_init[];
 extern char __kvm_hyp_init_end[];
 
-extern char __kvm_hyp_vector[];
-
 extern void __kvm_flush_vm_context(void);
 extern void __kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa);
 extern void __kvm_tlb_flush_vmid(struct kvm *kvm);
diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index eb46fc81a440..b47db5b9e407 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -37,6 +37,7 @@
 
 #include <linux/highmem.h>
 #include <asm/cacheflush.h>
+#include <asm/cputype.h>
 #include <asm/pgalloc.h>
 #include <asm/stage2_pgtable.h>
 
@@ -223,7 +224,17 @@ static inline unsigned int kvm_get_vmid_bits(void)
 
 static inline void *kvm_get_hyp_vector(void)
 {
-	return kvm_ksym_ref(__kvm_hyp_vector);
+	extern char __kvm_hyp_vector[];
+	extern char __kvm_hyp_vector_bp_inv[];
+
+	switch(read_cpuid_part()) {
+	case ARM_CPU_PART_CORTEX_A12:
+	case ARM_CPU_PART_CORTEX_A17:
+		return kvm_ksym_ref(__kvm_hyp_vector_bp_inv);
+
+	default:
+		return kvm_ksym_ref(__kvm_hyp_vector);
+	}
 }
 
 static inline int kvm_map_vectors(void)
diff --git a/arch/arm/kvm/hyp/hyp-entry.S b/arch/arm/kvm/hyp/hyp-entry.S
index 95a2faefc070..2e8d2179eb70 100644
--- a/arch/arm/kvm/hyp/hyp-entry.S
+++ b/arch/arm/kvm/hyp/hyp-entry.S
@@ -70,6 +70,59 @@ __kvm_hyp_vector:
 	W(b)	hyp_hvc
 	W(b)	hyp_irq
 	W(b)	hyp_fiq
+	
+	.align 5
+__kvm_hyp_vector_bp_inv:
+	.global __kvm_hyp_vector_bp_inv
+
+	/*
+	 * We encode the exception entry in the bottom 3 bits of
+	 * SP, and we have to guarantee to be 8 bytes aligned.
+	 */
+	W(add)	sp, sp, #1	/* Reset 	  7 */
+	W(add)	sp, sp, #1	/* Undef	  6 */
+	W(add)	sp, sp, #1	/* Syscall	  5 */
+	W(add)	sp, sp, #1	/* Prefetch abort 4 */
+	W(add)	sp, sp, #1	/* Data abort	  3 */
+	W(add)	sp, sp, #1	/* HVC		  2 */
+	W(add)	sp, sp, #1	/* IRQ		  1 */
+	W(add)	sp, sp, #1	/* FIQ		  0 */
+
+	sub	sp, sp, #1
+
+	mcr	p15, 0, r0, c7, c5, 6	/* BPIALL */
+	isb
+
+	/*
+	 * Yet another silly hack: Use VPIDR as a temp register.
+	 * Thumb2 is really a pain, as SP cannot be used with most
+	 * of the bitwise instructions. The vect_br macro ensures
+	 * things gets cleaned-up.
+	 */
+	mcr	p15, 4, r0, c0, c0, 0	/* VPIDR */
+	mov	r0, sp
+	and	r0, r0, #7
+	sub	sp, sp, r0
+	push	{r1, r2}
+	mov	r1, r0
+	mrc	p15, 4, r0, c0, c0, 0	/* VPIDR */
+	mrc	p15, 0, r2, c0, c0, 0	/* MIDR  */
+	mcr	p15, 4, r2, c0, c0, 0	/* VPIDR */
+
+.macro vect_br val, targ
+	cmp	r1, #\val
+	popeq	{r1, r2}
+	beq	\targ
+.endm
+
+	vect_br	0, hyp_fiq
+	vect_br	1, hyp_irq
+	vect_br	2, hyp_hvc
+	vect_br	3, hyp_dabt
+	vect_br	4, hyp_pabt
+	vect_br	5, hyp_svc
+	vect_br	6, hyp_undef
+	vect_br	7, hyp_reset
 
 .macro invalid_vector label, cause
 	.align
@@ -149,7 +202,14 @@ hyp_hvc:
 	bx	ip
 
 1:
-	push	{lr}
+	/*
+	 * Pushing r2 here is just a way of keeping the stack aligned to
+	 * 8 bytes on any path that can trigger a HYP exception. Here,
+	 * we may well be about to jump into the guest, and the guest
+	 * exit would otherwise be badly decoded by our fancy
+	 * "decode-exception-without-a-branch" code...
+	 */
+	push	{r2, lr}
 
 	mov	lr, r0
 	mov	r0, r1
@@ -159,7 +219,7 @@ hyp_hvc:
 THUMB(	orr	lr, #1)
 	blx	lr			@ Call the HYP function
 
-	pop	{lr}
+	pop	{r2, lr}
 	eret
 
 guest_trap:
-- 
2.14.2

^ permalink raw reply related

* [PATCH v2 2/6] arm: Invalidate BTB on prefetch abort outside of user mapping on Cortex A8, A9, A12 and A17
From: Marc Zyngier @ 2018-01-08 18:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180108185533.9698-1-marc.zyngier@arm.com>

In order to prevent aliasing attacks on the branch predictor,
invalidate the BTB on CPUs that are known to be affected when taking
a prefetch abort on a address that is outside of a user task limit.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/include/asm/cp15.h |  2 ++
 arch/arm/mm/fault.c         | 19 +++++++++++++
 arch/arm/mm/fsr-2level.c    |  4 +--
 arch/arm/mm/fsr-3level.c    | 67 ++++++++++++++++++++++++++++++++++++++++++++-
 4 files changed, 89 insertions(+), 3 deletions(-)

diff --git a/arch/arm/include/asm/cp15.h b/arch/arm/include/asm/cp15.h
index 4c9fa72b59f5..9e900ae855aa 100644
--- a/arch/arm/include/asm/cp15.h
+++ b/arch/arm/include/asm/cp15.h
@@ -65,6 +65,8 @@
 #define __write_sysreg(v, r, w, c, t)	asm volatile(w " " c : : "r" ((t)(v)))
 #define write_sysreg(v, ...)		__write_sysreg(v, __VA_ARGS__)
 
+#define BPIALL				__ACCESS_CP15(c7, 0, c5, 6)
+
 extern unsigned long cr_alignment;	/* defined in entry-armv.S */
 
 static inline unsigned long get_cr(void)
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c
index 42f585379e19..ff272ffcf741 100644
--- a/arch/arm/mm/fault.c
+++ b/arch/arm/mm/fault.c
@@ -21,6 +21,7 @@
 #include <linux/highmem.h>
 #include <linux/perf_event.h>
 
+#include <asm/cp15.h>
 #include <asm/exception.h>
 #include <asm/pgtable.h>
 #include <asm/system_misc.h>
@@ -181,6 +182,7 @@ __do_user_fault(struct task_struct *tsk, unsigned long addr,
 	si.si_errno = 0;
 	si.si_code = code;
 	si.si_addr = (void __user *)addr;
+
 	force_sig_info(sig, &si, tsk);
 }
 
@@ -404,6 +406,23 @@ do_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
 }
 #endif					/* CONFIG_MMU */
 
+static int
+do_pabt_page_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
+{
+	if (addr > TASK_SIZE) {
+		switch(read_cpuid_part()) {
+		case ARM_CPU_PART_CORTEX_A8:
+		case ARM_CPU_PART_CORTEX_A9:
+		case ARM_CPU_PART_CORTEX_A12:
+		case ARM_CPU_PART_CORTEX_A17:
+			write_sysreg(0, BPIALL);
+			break;
+		}
+	}
+
+	return do_page_fault(addr, fsr, regs);
+}
+
 /*
  * First Level Translation Fault Handler
  *
diff --git a/arch/arm/mm/fsr-2level.c b/arch/arm/mm/fsr-2level.c
index f2be95197265..ca07f72d8624 100644
--- a/arch/arm/mm/fsr-2level.c
+++ b/arch/arm/mm/fsr-2level.c
@@ -51,7 +51,7 @@ static struct fsr_info ifsr_info[] = {
 	{ do_bad,		SIGBUS,  0,		"unknown 4"			   },
 	{ do_translation_fault,	SIGSEGV, SEGV_MAPERR,	"section translation fault"	   },
 	{ do_bad,		SIGSEGV, SEGV_ACCERR,	"page access flag fault"	   },
-	{ do_page_fault,	SIGSEGV, SEGV_MAPERR,	"page translation fault"	   },
+	{ do_pabt_page_fault,	SIGSEGV, SEGV_MAPERR,	"page translation fault"	   },
 	{ do_bad,		SIGBUS,	 0,		"external abort on non-linefetch"  },
 	{ do_bad,		SIGSEGV, SEGV_ACCERR,	"section domain fault"		   },
 	{ do_bad,		SIGBUS,  0,		"unknown 10"			   },
@@ -59,7 +59,7 @@ static struct fsr_info ifsr_info[] = {
 	{ do_bad,		SIGBUS,	 0,		"external abort on translation"	   },
 	{ do_sect_fault,	SIGSEGV, SEGV_ACCERR,	"section permission fault"	   },
 	{ do_bad,		SIGBUS,	 0,		"external abort on translation"	   },
-	{ do_page_fault,	SIGSEGV, SEGV_ACCERR,	"page permission fault"		   },
+	{ do_pabt_page_fault,	SIGSEGV, SEGV_ACCERR,	"page permission fault"		   },
 	{ do_bad,		SIGBUS,  0,		"unknown 16"			   },
 	{ do_bad,		SIGBUS,  0,		"unknown 17"			   },
 	{ do_bad,		SIGBUS,  0,		"unknown 18"			   },
diff --git a/arch/arm/mm/fsr-3level.c b/arch/arm/mm/fsr-3level.c
index d0ae2963656a..88cfc7d06a30 100644
--- a/arch/arm/mm/fsr-3level.c
+++ b/arch/arm/mm/fsr-3level.c
@@ -66,4 +66,69 @@ static struct fsr_info fsr_info[] = {
 	{ do_bad,		SIGBUS,  0,		"unknown 63"			},
 };
 
-#define ifsr_info	fsr_info
+static struct fsr_info ifsr_info[] = {
+	{ do_bad,		SIGBUS,  0,		"unknown 0"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 1"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 2"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 3"			},
+	{ do_bad,		SIGBUS,  0,		"reserved translation fault"	},
+	{ do_translation_fault,	SIGSEGV, SEGV_MAPERR,	"level 1 translation fault"	},
+	{ do_translation_fault,	SIGSEGV, SEGV_MAPERR,	"level 2 translation fault"	},
+	{ do_pabt_page_fault,	SIGSEGV, SEGV_MAPERR,	"level 3 translation fault"	},
+	{ do_bad,		SIGBUS,  0,		"reserved access flag fault"	},
+	{ do_bad,		SIGSEGV, SEGV_ACCERR,	"level 1 access flag fault"	},
+	{ do_pabt_page_fault,	SIGSEGV, SEGV_ACCERR,	"level 2 access flag fault"	},
+	{ do_pabt_page_fault,	SIGSEGV, SEGV_ACCERR,	"level 3 access flag fault"	},
+	{ do_bad,		SIGBUS,  0,		"reserved permission fault"	},
+	{ do_bad,		SIGSEGV, SEGV_ACCERR,	"level 1 permission fault"	},
+	{ do_pabt_page_fault,	SIGSEGV, SEGV_ACCERR,	"level 2 permission fault"	},
+	{ do_pabt_page_fault,	SIGSEGV, SEGV_ACCERR,	"level 3 permission fault"	},
+	{ do_bad,		SIGBUS,  0,		"synchronous external abort"	},
+	{ do_bad,		SIGBUS,  0,		"asynchronous external abort"	},
+	{ do_bad,		SIGBUS,  0,		"unknown 18"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 19"			},
+	{ do_bad,		SIGBUS,  0,		"synchronous abort (translation table walk)" },
+	{ do_bad,		SIGBUS,  0,		"synchronous abort (translation table walk)" },
+	{ do_bad,		SIGBUS,  0,		"synchronous abort (translation table walk)" },
+	{ do_bad,		SIGBUS,  0,		"synchronous abort (translation table walk)" },
+	{ do_bad,		SIGBUS,  0,		"synchronous parity error"	},
+	{ do_bad,		SIGBUS,  0,		"asynchronous parity error"	},
+	{ do_bad,		SIGBUS,  0,		"unknown 26"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 27"			},
+	{ do_bad,		SIGBUS,  0,		"synchronous parity error (translation table walk" },
+	{ do_bad,		SIGBUS,  0,		"synchronous parity error (translation table walk" },
+	{ do_bad,		SIGBUS,  0,		"synchronous parity error (translation table walk" },
+	{ do_bad,		SIGBUS,  0,		"synchronous parity error (translation table walk" },
+	{ do_bad,		SIGBUS,  0,		"unknown 32"			},
+	{ do_bad,		SIGBUS,  BUS_ADRALN,	"alignment fault"		},
+	{ do_bad,		SIGBUS,  0,		"debug event"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 35"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 36"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 37"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 38"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 39"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 40"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 41"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 42"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 43"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 44"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 45"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 46"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 47"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 48"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 49"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 50"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 51"			},
+	{ do_bad,		SIGBUS,  0,		"implementation fault (lockdown abort)" },
+	{ do_bad,		SIGBUS,  0,		"unknown 53"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 54"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 55"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 56"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 57"			},
+	{ do_bad,		SIGBUS,  0,		"implementation fault (coprocessor abort)" },
+	{ do_bad,		SIGBUS,  0,		"unknown 59"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 60"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 61"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 62"			},
+	{ do_bad,		SIGBUS,  0,		"unknown 63"			},
+};
-- 
2.14.2

^ permalink raw reply related

* [PATCH v2 1/6] arm: Add BTB invalidation on switch_mm for Cortex-A9, A12 and A17
From: Marc Zyngier @ 2018-01-08 18:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180108185533.9698-1-marc.zyngier@arm.com>

In order to avoid aliasing attacks against the branch predictor,
some implementations require to invalidate the BTB when switching
from one user context to another.

For this, we reuse the existing implementation for Cortex-A8, and
apply it to A9, A12 and A17.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/mm/proc-v7-2level.S |  4 ++--
 arch/arm/mm/proc-v7-3level.S |  6 ++++++
 arch/arm/mm/proc-v7.S        | 30 +++++++++++++++---------------
 3 files changed, 23 insertions(+), 17 deletions(-)

diff --git a/arch/arm/mm/proc-v7-2level.S b/arch/arm/mm/proc-v7-2level.S
index c6141a5435c3..0422e58b74e8 100644
--- a/arch/arm/mm/proc-v7-2level.S
+++ b/arch/arm/mm/proc-v7-2level.S
@@ -41,7 +41,7 @@
  *	even on Cortex-A8 revisions not affected by 430973.
  *	If IBE is not set, the flush BTAC/BTB won't do anything.
  */
-ENTRY(cpu_ca8_switch_mm)
+ENTRY(cpu_v7_btbinv_switch_mm)
 #ifdef CONFIG_MMU
 	mov	r2, #0
 	mcr	p15, 0, r2, c7, c5, 6		@ flush BTAC/BTB
@@ -66,7 +66,7 @@ ENTRY(cpu_v7_switch_mm)
 #endif
 	bx	lr
 ENDPROC(cpu_v7_switch_mm)
-ENDPROC(cpu_ca8_switch_mm)
+ENDPROC(cpu_v7_btbinv_switch_mm)
 
 /*
  *	cpu_v7_set_pte_ext(ptep, pte)
diff --git a/arch/arm/mm/proc-v7-3level.S b/arch/arm/mm/proc-v7-3level.S
index 7d16bbc4102b..f6adfe88ead2 100644
--- a/arch/arm/mm/proc-v7-3level.S
+++ b/arch/arm/mm/proc-v7-3level.S
@@ -54,6 +54,11 @@
  * Set the translation table base pointer to be pgd_phys (physical address of
  * the new TTB).
  */
+ENTRY(cpu_v7_btbinv_switch_mm)
+#ifdef CONFIG_MMU
+	mov	r3, #0
+	mcr	p15, 0, r2, c7, c5, 6			@ flush BTAC/BTB
+#endif
 ENTRY(cpu_v7_switch_mm)
 #ifdef CONFIG_MMU
 	mmid	r2, r2
@@ -64,6 +69,7 @@ ENTRY(cpu_v7_switch_mm)
 #endif
 	ret	lr
 ENDPROC(cpu_v7_switch_mm)
+ENDPROC(cpu_v7_btbinv_switch_mm)
 
 #ifdef __ARMEB__
 #define rl r3
diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S
index 01d64c0b2563..0a14967fd400 100644
--- a/arch/arm/mm/proc-v7.S
+++ b/arch/arm/mm/proc-v7.S
@@ -159,18 +159,18 @@ ENDPROC(cpu_v7_do_resume)
 #endif
 
 /*
- * Cortex-A8
+ * Cortex-A8/A12/A17 that require a BTB invalidation on switch_mm
  */
-	globl_equ	cpu_ca8_proc_init,	cpu_v7_proc_init
-	globl_equ	cpu_ca8_proc_fin,	cpu_v7_proc_fin
-	globl_equ	cpu_ca8_reset,		cpu_v7_reset
-	globl_equ	cpu_ca8_do_idle,	cpu_v7_do_idle
-	globl_equ	cpu_ca8_dcache_clean_area, cpu_v7_dcache_clean_area
-	globl_equ	cpu_ca8_set_pte_ext,	cpu_v7_set_pte_ext
-	globl_equ	cpu_ca8_suspend_size,	cpu_v7_suspend_size
+	globl_equ	cpu_v7_btbinv_proc_init,	cpu_v7_proc_init
+	globl_equ	cpu_v7_btbinv_proc_fin,		cpu_v7_proc_fin
+	globl_equ	cpu_v7_btbinv_reset,		cpu_v7_reset
+	globl_equ	cpu_v7_btbinv_do_idle,		cpu_v7_do_idle
+	globl_equ	cpu_v7_btbinv_dcache_clean_area, cpu_v7_dcache_clean_area
+	globl_equ	cpu_v7_btbinv_set_pte_ext,	cpu_v7_set_pte_ext
+	globl_equ	cpu_v7_btbinv_suspend_size,	cpu_v7_suspend_size
 #ifdef CONFIG_ARM_CPU_SUSPEND
-	globl_equ	cpu_ca8_do_suspend,	cpu_v7_do_suspend
-	globl_equ	cpu_ca8_do_resume,	cpu_v7_do_resume
+	globl_equ	cpu_v7_btbinv_do_suspend,	cpu_v7_do_suspend
+	globl_equ	cpu_v7_btbinv_do_resume,	cpu_v7_do_resume
 #endif
 
 /*
@@ -181,7 +181,7 @@ ENDPROC(cpu_v7_do_resume)
 	globl_equ	cpu_ca9mp_reset,	cpu_v7_reset
 	globl_equ	cpu_ca9mp_do_idle,	cpu_v7_do_idle
 	globl_equ	cpu_ca9mp_dcache_clean_area, cpu_v7_dcache_clean_area
-	globl_equ	cpu_ca9mp_switch_mm,	cpu_v7_switch_mm
+	globl_equ	cpu_ca9mp_switch_mm,	cpu_v7_btbinv_switch_mm
 	globl_equ	cpu_ca9mp_set_pte_ext,	cpu_v7_set_pte_ext
 .globl	cpu_ca9mp_suspend_size
 .equ	cpu_ca9mp_suspend_size, cpu_v7_suspend_size + 4 * 2
@@ -548,8 +548,8 @@ __v7_setup_stack:
 
 	@ define struct processor (see <asm/proc-fns.h> and proc-macros.S)
 	define_processor_functions v7, dabort=v7_early_abort, pabort=v7_pabort, suspend=1
+	define_processor_functions v7_btbinv, dabort=v7_early_abort, pabort=v7_pabort, suspend=1
 #ifndef CONFIG_ARM_LPAE
-	define_processor_functions ca8, dabort=v7_early_abort, pabort=v7_pabort, suspend=1
 	define_processor_functions ca9mp, dabort=v7_early_abort, pabort=v7_pabort, suspend=1
 #endif
 #ifdef CONFIG_CPU_PJ4B
@@ -614,7 +614,7 @@ __v7_ca9mp_proc_info:
 __v7_ca8_proc_info:
 	.long	0x410fc080
 	.long	0xff0ffff0
-	__v7_proc __v7_ca8_proc_info, __v7_setup, proc_fns = ca8_processor_functions
+	__v7_proc __v7_ca8_proc_info, __v7_setup, proc_fns = v7_btbinv_processor_functions
 	.size	__v7_ca8_proc_info, . - __v7_ca8_proc_info
 
 #endif	/* CONFIG_ARM_LPAE */
@@ -658,7 +658,7 @@ __v7_ca7mp_proc_info:
 __v7_ca12mp_proc_info:
 	.long	0x410fc0d0
 	.long	0xff0ffff0
-	__v7_proc __v7_ca12mp_proc_info, __v7_ca12mp_setup
+	__v7_proc __v7_ca12mp_proc_info, __v7_ca12mp_setup, proc_fns = v7_btbinv_processor_functions
 	.size	__v7_ca12mp_proc_info, . - __v7_ca12mp_proc_info
 
 	/*
@@ -688,7 +688,7 @@ __v7_b15mp_proc_info:
 __v7_ca17mp_proc_info:
 	.long	0x410fc0e0
 	.long	0xff0ffff0
-	__v7_proc __v7_ca17mp_proc_info, __v7_ca17mp_setup
+	__v7_proc __v7_ca17mp_proc_info, __v7_ca17mp_setup, proc_fns = v7_btbinv_processor_functions
 	.size	__v7_ca17mp_proc_info, . - __v7_ca17mp_proc_info
 
 	/*
-- 
2.14.2

^ permalink raw reply related

* [PATCH v2 0/6] ARM branch predictor hardening
From: Marc Zyngier @ 2018-01-08 18:55 UTC (permalink / raw)
  To: linux-arm-kernel

This small series implements some basic BP hardening by invalidating
the BTB on CPUs that are known to be susceptible to aliasing attacks.

These patches are closely modelled against what we do on arm64,
although simpler as we can rely on an architected instruction to
perform the invalidation. The notable exception is Cortex-A15, where
BTB invalidation behaves like a NOP, and the only way to shoot the
predictor down is to invalidate the icache *and* to have ACTLR[0] set
to 1 (which is a secure-only operation).

The first patch reuses the Cortex-A8 BTB invalidation in switch_mm and
generalises it to be used on all affected CPUs. The second perform the
same invalidation on prefetch abort outside of the userspace
range. The third one nukes it on guest exit, and results in some major
surgery as we cannot take a branch from the vectors (that, and Thumb2
being a massive pain).

Patches 4 to 6 are doing a similar thing for Cortex-A15, which the
aforementioned ICIALLU.

Note 1: Contrary to the initial version, this new series relies on
the arm64/kpti branch (I reuse the per-CPU vector hook for KVM).

Note 2: M-class CPUs are not affected and for R-class cores, the
mitigation doesn't make much sense since we do not enforce user/kernel
isolation.

* From v1:
  - Fixed broken hyp_fiq vector (noticed by Ard)
  - Fixed broken BTB invalidation in LPAE switch_mm (reported by Andre)
  - Revamped invalidation on PABT (noticed by James on arm64,
    suggested by Will)
  - Rewrote the whole HYP sequence, as Thumb2 was pretty unhappy about
    arithmetic with the stack pointer

Marc Zyngier (6):
  arm: Add BTB invalidation on switch_mm for Cortex-A9, A12 and A17
  arm: Invalidate BTB on prefetch abort outside of user mapping on
    Cortex A8, A9, A12 and A17
  arm: KVM: Invalidate BTB on guest exit
  arm: Add icache invalidation on switch_mm for Cortex-A15
  arm: Invalidate icache on prefetch abort outside of user mapping on
    Cortex-A15
  arm: KVM: Invalidate icache on guest exit for Cortex-A15

 arch/arm/include/asm/cp15.h    |  3 ++
 arch/arm/include/asm/kvm_asm.h |  2 -
 arch/arm/include/asm/kvm_mmu.h | 17 +++++++-
 arch/arm/kvm/hyp/hyp-entry.S   | 89 +++++++++++++++++++++++++++++++++++++++++-
 arch/arm/mm/fault.c            | 23 +++++++++++
 arch/arm/mm/fsr-2level.c       |  4 +-
 arch/arm/mm/fsr-3level.c       | 67 ++++++++++++++++++++++++++++++-
 arch/arm/mm/proc-v7-2level.S   | 14 ++++++-
 arch/arm/mm/proc-v7-3level.S   | 22 +++++++++++
 arch/arm/mm/proc-v7.S          | 48 +++++++++++++++--------
 10 files changed, 263 insertions(+), 26 deletions(-)

-- 
2.14.2

^ permalink raw reply

* [PATCH v3 00/13] arm64 kpti hardening and variant 2 workarounds
From: Catalin Marinas @ 2018-01-08 18:53 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1515432758-26440-1-git-send-email-will.deacon@arm.com>

On Mon, Jan 08, 2018 at 05:32:25PM +0000, Will Deacon wrote:
> Jayachandran C (1):
>   arm64: cputype: Add MIDR values for Cavium ThunderX2 CPUs
> 
> Marc Zyngier (3):
>   arm64: Move post_ttbr_update_workaround to C code
>   arm64: KVM: Use per-CPU vector when BP hardening is enabled
>   arm64: KVM: Make PSCI_VERSION a fast path
> 
> Shanker Donthineni (1):
>   arm64: Implement branch predictor hardening for Falkor
> 
> Will Deacon (8):
>   arm64: use RET instruction for exiting the trampoline
>   arm64: Kconfig: Reword UNMAP_KERNEL_AT_EL0 kconfig entry
>   arm64: Take into account ID_AA64PFR0_EL1.CSV3
>   arm64: cpufeature: Pass capability structure to ->enable callback
>   drivers/firmware: Expose psci_get_version through psci_ops structure
>   arm64: Add skeleton to harden the branch predictor against aliasing
>     attacks
>   arm64: cputype: Add missing MIDR values for Cortex-A72 and Cortex-A75
>   arm64: Implement branch predictor hardening for affected Cortex-A CPUs

I'm queuing these into the arm64 for-next/core (after some overnight
testing). Any additional fixes should be done on top.

Thanks.

-- 
Catalin

^ permalink raw reply

* [PATCH] arm64: Implement branch predictor hardening for Falkor
From: Will Deacon @ 2018-01-08 18:44 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180108170933.GU25869@arm.com>

On Mon, Jan 08, 2018 at 05:09:33PM +0000, Will Deacon wrote:
> On Fri, Jan 05, 2018 at 02:28:59PM -0600, Shanker Donthineni wrote:
> > Falkor is susceptible to branch predictor aliasing and can
> > theoretically be attacked by malicious code. This patch
> > implements a mitigation for these attacks, preventing any
> > malicious entries from affecting other victim contexts.
> 
> Thanks, Shanker. I'll pick this up (fixing the typo pointed out by Drew).

Note that MIDR_FALKOR doesn't exist in mainline, so I had to drop those
changes too. See the kpti branch for details.

If you'd like anything else done here, please send additional patches to me
and Catalin that we can apply on top of what we currently have. Note that
I'm in the air tomorrow, so won't be picking up email.

Cheers,

Will

^ permalink raw reply

* [PATCH 2/2] iommu: Clean up of_iommu_init_fn
From: Robin Murphy @ 2018-01-08 18:42 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <f1a506337bf602c54f4d6d417c14ca556a5f3674.1515436860.git.robin.murphy@arm.com>

Now that no more drivers rely on arbitrary early initialisation via an
of_iommu_init_fn hook, let's clean up the redundant remnants. The
IOMMU_OF_DECLARE() macro needs to remain for now, as the probe-deferral
mechanism has no other nice way to detect built-in drivers before they
have registered themselves, such that it can make the right decision.

Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
 drivers/iommu/arm-smmu-v3.c  |  2 +-
 drivers/iommu/arm-smmu.c     | 12 ++++++------
 drivers/iommu/exynos-iommu.c |  2 +-
 drivers/iommu/msm_iommu.c    |  2 +-
 drivers/iommu/of_iommu.c     | 16 ----------------
 drivers/iommu/qcom_iommu.c   |  2 +-
 include/linux/of_iommu.h     |  5 +----
 7 files changed, 11 insertions(+), 30 deletions(-)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 57c92aa3122e..1abbf42a8bd5 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -3009,7 +3009,7 @@ static struct platform_driver arm_smmu_driver = {
 };
 module_platform_driver(arm_smmu_driver);
 
-IOMMU_OF_DECLARE(arm_smmuv3, "arm,smmu-v3", NULL);
+IOMMU_OF_DECLARE(arm_smmuv3, "arm,smmu-v3");
 
 MODULE_DESCRIPTION("IOMMU API for ARM architected SMMUv3 implementations");
 MODULE_AUTHOR("Will Deacon <will.deacon@arm.com>");
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 3bdb799d3b4b..56147a2be3d0 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -2208,12 +2208,12 @@ static struct platform_driver arm_smmu_driver = {
 };
 module_platform_driver(arm_smmu_driver);
 
-IOMMU_OF_DECLARE(arm_smmuv1, "arm,smmu-v1", NULL);
-IOMMU_OF_DECLARE(arm_smmuv2, "arm,smmu-v2", NULL);
-IOMMU_OF_DECLARE(arm_mmu400, "arm,mmu-400", NULL);
-IOMMU_OF_DECLARE(arm_mmu401, "arm,mmu-401", NULL);
-IOMMU_OF_DECLARE(arm_mmu500, "arm,mmu-500", NULL);
-IOMMU_OF_DECLARE(cavium_smmuv2, "cavium,smmu-v2", NULL);
+IOMMU_OF_DECLARE(arm_smmuv1, "arm,smmu-v1");
+IOMMU_OF_DECLARE(arm_smmuv2, "arm,smmu-v2");
+IOMMU_OF_DECLARE(arm_mmu400, "arm,mmu-400");
+IOMMU_OF_DECLARE(arm_mmu401, "arm,mmu-401");
+IOMMU_OF_DECLARE(arm_mmu500, "arm,mmu-500");
+IOMMU_OF_DECLARE(cavium_smmuv2, "cavium,smmu-v2");
 
 MODULE_DESCRIPTION("IOMMU API for ARM architected SMMU implementations");
 MODULE_AUTHOR("Will Deacon <will.deacon@arm.com>");
diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index f596fcc32898..6a96a4c42153 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -1385,4 +1385,4 @@ static int __init exynos_iommu_init(void)
 }
 core_initcall(exynos_iommu_init);
 
-IOMMU_OF_DECLARE(exynos_iommu_of, "samsung,exynos-sysmmu", NULL);
+IOMMU_OF_DECLARE(exynos_iommu_of, "samsung,exynos-sysmmu");
diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index dda1ce87a070..0d3350463a3f 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -877,7 +877,7 @@ static void __exit msm_iommu_driver_exit(void)
 subsys_initcall(msm_iommu_driver_init);
 module_exit(msm_iommu_driver_exit);
 
-IOMMU_OF_DECLARE(msm_iommu_of, "qcom,apq8064-iommu", NULL);
+IOMMU_OF_DECLARE(msm_iommu_of, "qcom,apq8064-iommu");
 
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>");
diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index 50947ebb6d17..5c36a8b7656a 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -231,19 +231,3 @@ const struct iommu_ops *of_iommu_configure(struct device *dev,
 
 	return ops;
 }
-
-static int __init of_iommu_init(void)
-{
-	struct device_node *np;
-	const struct of_device_id *match, *matches = &__iommu_of_table;
-
-	for_each_matching_node_and_match(np, matches, &match) {
-		const of_iommu_init_fn init_fn = match->data;
-
-		if (init_fn && init_fn(np))
-			pr_err("Failed to initialise IOMMU %pOF\n", np);
-	}
-
-	return 0;
-}
-postcore_initcall_sync(of_iommu_init);
diff --git a/drivers/iommu/qcom_iommu.c b/drivers/iommu/qcom_iommu.c
index c8a587d034b0..37ecc49deab8 100644
--- a/drivers/iommu/qcom_iommu.c
+++ b/drivers/iommu/qcom_iommu.c
@@ -924,7 +924,7 @@ static void __exit qcom_iommu_exit(void)
 module_init(qcom_iommu_init);
 module_exit(qcom_iommu_exit);
 
-IOMMU_OF_DECLARE(qcom_iommu_dev, "qcom,msm-iommu-v1", NULL);
+IOMMU_OF_DECLARE(qcom_iommu_dev, "qcom,msm-iommu-v1");
 
 MODULE_DESCRIPTION("IOMMU API for QCOM IOMMU v1 implementations");
 MODULE_LICENSE("GPL v2");
diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h
index 13394ac83c66..0cac59db95bc 100644
--- a/include/linux/of_iommu.h
+++ b/include/linux/of_iommu.h
@@ -33,9 +33,6 @@ static inline const struct iommu_ops *of_iommu_configure(struct device *dev,
 
 extern struct of_device_id __iommu_of_table;
 
-typedef int (*of_iommu_init_fn)(struct device_node *);
-
-#define IOMMU_OF_DECLARE(name, compat, fn) \
-	_OF_DECLARE(iommu, name, compat, fn, of_iommu_init_fn)
+#define IOMMU_OF_DECLARE(name, compat)	OF_DECLARE_1(iommu, name, compat, NULL)
 
 #endif /* __OF_IOMMU_H */
-- 
2.13.4.dirty

^ permalink raw reply related

* [PATCH 1/2] iommu/msm: Claim bus ops on probe
From: Robin Murphy @ 2018-01-08 18:42 UTC (permalink / raw)
  To: linux-arm-kernel

Since the MSM IOMMU driver now probes via DT exclusively rather than
platform data, dependent masters should be deferred until the IOMMU
itself is ready. Thus we can do away with the early initialisation
hook to unconditionally claim the bus ops, and instead do that only
once an IOMMU is actually probed. Furthermore, this should also make
the driver safe for multiplatform kernels on non-MSM SoCs.

Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
 drivers/iommu/msm_iommu.c | 16 +++-------------
 1 file changed, 3 insertions(+), 13 deletions(-)

diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index 04f4d51ffacb..dda1ce87a070 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -823,6 +823,8 @@ static int msm_iommu_probe(struct platform_device *pdev)
 		goto fail;
 	}
 
+	bus_set_iommu(&platform_bus_type, &msm_iommu_ops);
+
 	pr_info("device mapped at %p, irq %d with %d ctx banks\n",
 		iommu->base, iommu->irq, iommu->ncb);
 
@@ -875,19 +877,7 @@ static void __exit msm_iommu_driver_exit(void)
 subsys_initcall(msm_iommu_driver_init);
 module_exit(msm_iommu_driver_exit);
 
-static int __init msm_iommu_init(void)
-{
-	bus_set_iommu(&platform_bus_type, &msm_iommu_ops);
-	return 0;
-}
-
-static int __init msm_iommu_of_setup(struct device_node *np)
-{
-	msm_iommu_init();
-	return 0;
-}
-
-IOMMU_OF_DECLARE(msm_iommu_of, "qcom,apq8064-iommu", msm_iommu_of_setup);
+IOMMU_OF_DECLARE(msm_iommu_of, "qcom,apq8064-iommu", NULL);
 
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>");
-- 
2.13.4.dirty

^ permalink raw reply related

* [PATCH] phy: work around 'phys' references to usb-phy devices
From: Kishon Vijay Abraham I @ 2018-01-08 18:32 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180108130116.80148-1-arnd@arndb.de>

Hi Arnd,

On Monday 08 January 2018 06:31 PM, Arnd Bergmann wrote:
> Stefan Wahren reports a problem with a warning fix that was merged
> for v4.15: we had lots of device nodes with a 'phys' property pointing
> to a device node that is not compliant with the binding documented in
> Documentation/devicetree/bindings/phy/phy-bindings.txt
> 
> This generally works because USB HCD drivers that support both the generic
> phy subsystem and the older usb-phy subsystem ignore most errors from
> phy_get() and related calls and then use the usb-phy driver instead.
> 
> However, usb_add_hcd() (along with the respective functions in dwc2 and
> dwc3) propagate the EPROBE_DEFER return code so we can try again whenever
> the driver gets loaded. In case the driver is written for the usb-phy
> subsystem (like usb-generic-phy aka usb-nop-xceiv), we will never load
> a generic-phy driver for it, and keep failing here.
> 
> There is only a small number of remaining usb-phy drivers that support
> device tree, so this adds a workaround by providing a full list of the
> potentially affected drivers, and always failing the probe with -ENODEV
> here, which is the same behavior that we used to get with incorrect
> device tree files. Since we generally want older kernels to also want
> to work with the fixed devicetree files, it would be good to backport
> the patch into stable kernels as well (3.13+ are possibly affected).
> Reverting back to the DTS sources that work would in theory fix USB
> support for now, but in the long run we'd run into the same problem
> again when the drivers get ported from usb-phy to generic-phy.
> 
> Fixes: 014d6da6cb25 ("ARM: dts: bcm283x: Fix DTC warnings about missing phy-cells")
> Link: https://marc.info/?l=linux-usb&m=151518314314753&w=2
> Cc: stable at vger.kernel.org
> Cc: Stefan Wahren <stefan.wahren@i2se.com>
> Cc: Felipe Balbi <balbi@kernel.org>
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
> This obviously needs to be tested, I wrote this up as a reply to
> Stefan's bug report. I'm fairly sure that I covered all usb-phy
> driver strings here. My goal is to have a fix merged into 4.15
> rather than reverting all the DT fixes.

Shouldn't the fix be in phy consumer drivers to not return error if it's able
to find the phy either using usb-phy or generic phy?
> ---
>  drivers/phy/phy-core.c | 27 +++++++++++++++++++++++++++
>  1 file changed, 27 insertions(+)
> 
> diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
> index b4964b067aec..bb4dd2a2de2d 100644
> --- a/drivers/phy/phy-core.c
> +++ b/drivers/phy/phy-core.c
> @@ -387,6 +387,24 @@ int phy_calibrate(struct phy *phy)
>  }
>  EXPORT_SYMBOL_GPL(phy_calibrate);
>  
> +static struct of_device_id __maybe_unused legacy_usbphy[] = {
> +	{ .compatible = "fsl,imx23-usbphy" },
> +	{ .compatible = "fsl,imx6q-usbphy" },
> +	{ .compatible = "fsl,imx6sl-usbphy" },
> +	{ .compatible = "fsl,imx6sx-usbphy" },
> +	{ .compatible = "fsl,imx6ul-usbphy" },
> +	{ .compatible = "fsl,vf610-usbphy" },
> +	{ .compatible = "nvidia,tegra20-usb-phy" },
> +	{ .compatible = "nvidia,tegra30-usb-phy" },
> +	{ .compatible = "nxp,isp1301" },
> +	{ .compatible = "ti,am335x-usb-ctrl-module" },
> +	{ .compatible = "ti,am335x-usb-phy" },
> +	{ .compatible = "ti,keystone-usbphy" },
> +	{ .compatible = "ti,twl6030-usb" },
> +	{ .compatible = "usb-nop-xceiv" },
> +	{},

"ti,am335x-usb-ctrl-module" and "ti,twl6030-usb" are not phys.

Thanks
Kishon

^ permalink raw reply

* [v2,03/11] arm64: Take into account ID_AA64PFR0_EL1.CSV3
From: Alan Cox @ 2018-01-08 18:22 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180108175100.GW25869@arm.com>

> > On systems that are not vulnerable to variant 3, this is an unnecessary
> > overhead.  
> 
> KASLR can be bypassed on CPUs that are not vulnerable to variant 3 simply
> by timing how long accesses to kernel addresses from EL0 take -- please read
> the original KAISER paper for details about that attack on x86. kpti
> mitigates that. If you don't care about KASLR, don't enable it (arguably
> it's useless without kpti).

KASLR is primarily of value for remote protection.

Alan

^ permalink raw reply

* [PATCH v6 14/16] firmware: arm_sdei: Discover SDEI support via ACPI
From: Lorenzo Pieralisi @ 2018-01-08 17:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180108153818.22743-15-james.morse@arm.com>

On Mon, Jan 08, 2018 at 03:38:16PM +0000, James Morse wrote:
> SDEI defines a new ACPI table to indicate the presence of the interface.
> The conduit is discovered in the same way as PSCI.
> 
> For ACPI we need to create the platform device ourselves as SDEI doesn't
> have an entry in the DSDT.
> 
> The SDEI platform device should be created after ACPI has been initialised
> so that we can parse the table, but before GHES devices are created, which
> may register SDE events if they use SDEI as their notification type.
> 
> Signed-off-by: James Morse <james.morse@arm.com>
> Acked-by: Catalin Marinas <catalin.marinas@arm.com>
> ---
>  drivers/firmware/arm_sdei.c | 41 ++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 40 insertions(+), 1 deletion(-)

Reviewed-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>

> diff --git a/drivers/firmware/arm_sdei.c b/drivers/firmware/arm_sdei.c
> index 10a8bfa7339a..fb7caa3628b9 100644
> --- a/drivers/firmware/arm_sdei.c
> +++ b/drivers/firmware/arm_sdei.c
> @@ -907,6 +907,14 @@ static int sdei_get_conduit(struct platform_device *pdev)
>  		}
>  
>  		pr_warn("invalid \"method\" property: %s\n", method);
> +	} else if (IS_ENABLED(CONFIG_ACPI) && !acpi_disabled) {
> +		if (acpi_psci_use_hvc()) {
> +			sdei_firmware_call = &sdei_smccc_hvc;
> +			return CONDUIT_HVC;
> +		} else {
> +			sdei_firmware_call = &sdei_smccc_smc;
> +			return CONDUIT_SMC;
> +		}
>  	}
>  
>  	return CONDUIT_INVALID;
> @@ -1020,14 +1028,45 @@ static bool __init sdei_present_dt(void)
>  	return true;
>  }
>  
> +static bool __init sdei_present_acpi(void)
> +{
> +	acpi_status status;
> +	struct platform_device *pdev;
> +	struct acpi_table_header *sdei_table_header;
> +
> +	if (acpi_disabled)
> +		return false;
> +
> +	status = acpi_get_table(ACPI_SIG_SDEI, 0, &sdei_table_header);
> +	if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
> +		const char *msg = acpi_format_exception(status);
> +
> +		pr_info("Failed to get ACPI:SDEI table, %s\n", msg);
> +	}
> +	if (ACPI_FAILURE(status))
> +		return false;
> +
> +	pdev = platform_device_register_simple(sdei_driver.driver.name, 0, NULL,
> +					       0);
> +	if (IS_ERR(pdev))
> +		return false;
> +
> +	return true;
> +}
> +
>  static int __init sdei_init(void)
>  {
> -	if (sdei_present_dt())
> +	if (sdei_present_dt() || sdei_present_acpi())
>  		platform_driver_register(&sdei_driver);
>  
>  	return 0;
>  }
>  
> +/*
> + * On an ACPI system SDEI needs to be ready before HEST:GHES tries to register
> + * its events. ACPI is initialised from a subsys_initcall(), GHES is initialised
> + * by device_initcall(). We want to be called in the middle.
> + */
>  subsys_initcall_sync(sdei_init);
>  
>  int sdei_event_handler(struct pt_regs *regs,
> -- 
> 2.15.0
> 

^ permalink raw reply

* [v2,03/11] arm64: Take into account ID_AA64PFR0_EL1.CSV3
From: Marc Zyngier @ 2018-01-08 17:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180108174016.GB180149@jc-sabre>

On 08/01/18 17:40, Jayachandran C wrote:
> On Mon, Jan 08, 2018 at 09:20:09AM +0000, Marc Zyngier wrote:
>> On 08/01/18 07:24, Jayachandran C wrote:
>>> On Fri, Jan 05, 2018 at 01:12:33PM +0000, Will Deacon wrote:
>>>> For non-KASLR kernels where the KPTI behaviour has not been overridden
>>>> on the command line we can use ID_AA64PFR0_EL1.CSV3 to determine whether
>>>> or not we should unmap the kernel whilst running at EL0.
>>>>
>>>> Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
>>>> Signed-off-by: Will Deacon <will.deacon@arm.com>
>>>> ---
>>>>  arch/arm64/include/asm/sysreg.h | 1 +
>>>>  arch/arm64/kernel/cpufeature.c  | 8 +++++++-
>>>>  2 files changed, 8 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
>>>> index 08cc88574659..ae519bbd3f9e 100644
>>>> --- a/arch/arm64/include/asm/sysreg.h
>>>> +++ b/arch/arm64/include/asm/sysreg.h
>>>> @@ -437,6 +437,7 @@
>>>>  #define ID_AA64ISAR1_DPB_SHIFT		0
>>>>  
>>>>  /* id_aa64pfr0 */
>>>> +#define ID_AA64PFR0_CSV3_SHIFT		60
>>>>  #define ID_AA64PFR0_SVE_SHIFT		32
>>>>  #define ID_AA64PFR0_GIC_SHIFT		24
>>>>  #define ID_AA64PFR0_ASIMD_SHIFT		20
>>>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>>>> index 9f0545dfe497..d723fc071f39 100644
>>>> --- a/arch/arm64/kernel/cpufeature.c
>>>> +++ b/arch/arm64/kernel/cpufeature.c
>>>> @@ -145,6 +145,7 @@ static const struct arm64_ftr_bits ftr_id_aa64isar1[] = {
>>>>  };
>>>>  
>>>>  static const struct arm64_ftr_bits ftr_id_aa64pfr0[] = {
>>>> +	ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_CSV3_SHIFT, 4, 0),
>>>>  	ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_SVE_SHIFT, 4, 0),
>>>>  	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_GIC_SHIFT, 4, 0),
>>>>  	S_ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_ASIMD_SHIFT, 4, ID_AA64PFR0_ASIMD_NI),
>>>> @@ -851,6 +852,8 @@ static int __kpti_forced; /* 0: not forced, >0: forced on, <0: forced off */
>>>>  static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
>>>>  				int __unused)
>>>>  {
>>>> +	u64 pfr0 = read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1);
>>>> +
>>>>  	/* Forced on command line? */
>>>>  	if (__kpti_forced) {
>>>>  		pr_info_once("kernel page table isolation forced %s by command line option\n",
>>>> @@ -862,7 +865,9 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
>>>>  	if (IS_ENABLED(CONFIG_RANDOMIZE_BASE))
>>>>  		return true;
>>>>  
>>>> -	return false;
>>>> +	/* Defer to CPU feature registers */
>>>> +	return !cpuid_feature_extract_unsigned_field(pfr0,
>>>> +						     ID_AA64PFR0_CSV3_SHIFT);
>>>
>>> If I read this correctly, this enables KPTI on all processors without the CSV3
>>> set (which seems to be a future capability).
>>>
>>> Turning on KPTI has a small but significant overhead, so I think we should turn
>>> it off on processors that are not vulnerable to CVE-2017-5754. Can we add something
>>> like  this:
>>>
>>> --->8
>>> diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
>>> index 19ed09b..202b037 100644
>>> --- a/arch/arm64/kernel/cpufeature.c
>>> +++ b/arch/arm64/kernel/cpufeature.c
>>> @@ -862,6 +862,13 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
>>>                 return __kpti_forced > 0;
>>>         }
>>>  
>>> +       /* Don't force KPTI for CPUs that are not vulnerable */
>>> +       switch (read_cpuid_id() & MIDR_CPU_MODEL_MASK) {
>>> +               case MIDR_CAVIUM_THUNDERX2:
>>> +               case MIDR_BRCM_VULCAN:
>>> +                       return false;
>>> +       }
>>> +
>>>         /* Useful for KASLR robustness */
>>>         if (IS_ENABLED(CONFIG_RANDOMIZE_BASE))
>>>                 return true;
>>>
>>
>> KPTI is also an improvement for KASLR. Why would you deprive a user of
>> the choice to further secure their system?
> 
> The user has a choice with kpti= at the kernel command line, so we are
> not depriving the user of a choice. KASLR is expected to be enabled by
> distributions, and KPTI will be enabled by default as well.
> 
> On systems that are not vulnerable to variant 3, this is an unnecessary
> overhead.

KASLR can be defeated if you don't have KPTI enabled. The original
KAISER paper is quite clear about that.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny...

^ permalink raw reply

* [v2,03/11] arm64: Take into account ID_AA64PFR0_EL1.CSV3
From: Will Deacon @ 2018-01-08 17:51 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180108174016.GB180149@jc-sabre>

On Mon, Jan 08, 2018 at 09:40:17AM -0800, Jayachandran C wrote:
> On Mon, Jan 08, 2018 at 09:20:09AM +0000, Marc Zyngier wrote:
> > On 08/01/18 07:24, Jayachandran C wrote:
> > > diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> > > index 19ed09b..202b037 100644
> > > --- a/arch/arm64/kernel/cpufeature.c
> > > +++ b/arch/arm64/kernel/cpufeature.c
> > > @@ -862,6 +862,13 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
> > >                 return __kpti_forced > 0;
> > >         }
> > >  
> > > +       /* Don't force KPTI for CPUs that are not vulnerable */
> > > +       switch (read_cpuid_id() & MIDR_CPU_MODEL_MASK) {
> > > +               case MIDR_CAVIUM_THUNDERX2:
> > > +               case MIDR_BRCM_VULCAN:
> > > +                       return false;
> > > +       }
> > > +
> > >         /* Useful for KASLR robustness */
> > >         if (IS_ENABLED(CONFIG_RANDOMIZE_BASE))
> > >                 return true;
> > > 
> > 
> > KPTI is also an improvement for KASLR. Why would you deprive a user of
> > the choice to further secure their system?
> 
> The user has a choice with kpti= at the kernel command line, so we are
> not depriving the user of a choice. KASLR is expected to be enabled by
> distributions, and KPTI will be enabled by default as well.
> 
> On systems that are not vulnerable to variant 3, this is an unnecessary
> overhead.

KASLR can be bypassed on CPUs that are not vulnerable to variant 3 simply
by timing how long accesses to kernel addresses from EL0 take -- please read
the original KAISER paper for details about that attack on x86. kpti
mitigates that. If you don't care about KASLR, don't enable it (arguably
it's useless without kpti).

Will

^ permalink raw reply

* [v2,03/11] arm64: Take into account ID_AA64PFR0_EL1.CSV3
From: Jayachandran C @ 2018-01-08 17:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20180108170624.GT25869@arm.com>

On Mon, Jan 08, 2018 at 05:06:24PM +0000, Will Deacon wrote:
> On Sun, Jan 07, 2018 at 11:24:02PM -0800, Jayachandran C wrote:
> > On Fri, Jan 05, 2018 at 01:12:33PM +0000, Will Deacon wrote:
> > > For non-KASLR kernels where the KPTI behaviour has not been overridden
> > > on the command line we can use ID_AA64PFR0_EL1.CSV3 to determine whether
> > > or not we should unmap the kernel whilst running at EL0.
> > > 
> > > Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> > > Signed-off-by: Will Deacon <will.deacon@arm.com>
> > > ---
> > >  arch/arm64/include/asm/sysreg.h | 1 +
> > >  arch/arm64/kernel/cpufeature.c  | 8 +++++++-
> > >  2 files changed, 8 insertions(+), 1 deletion(-)
> > > 
> > > diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
> > > index 08cc88574659..ae519bbd3f9e 100644
> > > --- a/arch/arm64/include/asm/sysreg.h
> > > +++ b/arch/arm64/include/asm/sysreg.h
> > > @@ -437,6 +437,7 @@
> > >  #define ID_AA64ISAR1_DPB_SHIFT		0
> > >  
> > >  /* id_aa64pfr0 */
> > > +#define ID_AA64PFR0_CSV3_SHIFT		60
> > >  #define ID_AA64PFR0_SVE_SHIFT		32
> > >  #define ID_AA64PFR0_GIC_SHIFT		24
> > >  #define ID_AA64PFR0_ASIMD_SHIFT		20
> > > diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> > > index 9f0545dfe497..d723fc071f39 100644
> > > --- a/arch/arm64/kernel/cpufeature.c
> > > +++ b/arch/arm64/kernel/cpufeature.c
> > > @@ -145,6 +145,7 @@ static const struct arm64_ftr_bits ftr_id_aa64isar1[] = {
> > >  };
> > >  
> > >  static const struct arm64_ftr_bits ftr_id_aa64pfr0[] = {
> > > +	ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_LOWER_SAFE, ID_AA64PFR0_CSV3_SHIFT, 4, 0),
> > >  	ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_SVE_SHIFT, 4, 0),
> > >  	ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_GIC_SHIFT, 4, 0),
> > >  	S_ARM64_FTR_BITS(FTR_VISIBLE, FTR_STRICT, FTR_LOWER_SAFE, ID_AA64PFR0_ASIMD_SHIFT, 4, ID_AA64PFR0_ASIMD_NI),
> > > @@ -851,6 +852,8 @@ static int __kpti_forced; /* 0: not forced, >0: forced on, <0: forced off */
> > >  static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
> > >  				int __unused)
> > >  {
> > > +	u64 pfr0 = read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1);
> > > +
> > >  	/* Forced on command line? */
> > >  	if (__kpti_forced) {
> > >  		pr_info_once("kernel page table isolation forced %s by command line option\n",
> > > @@ -862,7 +865,9 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
> > >  	if (IS_ENABLED(CONFIG_RANDOMIZE_BASE))
> > >  		return true;
> > >  
> > > -	return false;
> > > +	/* Defer to CPU feature registers */
> > > +	return !cpuid_feature_extract_unsigned_field(pfr0,
> > > +						     ID_AA64PFR0_CSV3_SHIFT);
> > 
> > If I read this correctly, this enables KPTI on all processors without the CSV3
> > set (which seems to be a future capability).
> > 
> > Turning on KPTI has a small but significant overhead, so I think we should turn
> > it off on processors that are not vulnerable to CVE-2017-5754. Can we add something
> > like  this:
> > 
> > --->8
> > diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c
> > index 19ed09b..202b037 100644
> > --- a/arch/arm64/kernel/cpufeature.c
> > +++ b/arch/arm64/kernel/cpufeature.c
> > @@ -862,6 +862,13 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
> >                 return __kpti_forced > 0;
> >         }
> >  
> > +       /* Don't force KPTI for CPUs that are not vulnerable */
> > +       switch (read_cpuid_id() & MIDR_CPU_MODEL_MASK) {
> > +               case MIDR_CAVIUM_THUNDERX2:
> > +               case MIDR_BRCM_VULCAN:
> > +                       return false;
> > +       }
> > +
> 
> KASLR aside (I agree with Marc on that), I did consider an MIDR whitelist,
> but it gets nasty for big.LITTLE systems if maxcpus= is used and we see a
> non-whitelisted CPU after we've booted. At this point, we can't actually
> bring the thing online.
> 
> You could make the argument that if you're passing maxcpus= then you can just
> easily pass kpti= as well, but I wasn't sure.

The code above should be a reasonable addition for getting the default right.
If by any chance these CPUs are shown to be vulnerable to timing attacks that
can bypass KASLR, we will need to move the change below the line:

  	if (IS_ENABLED(CONFIG_RANDOMIZE_BASE))
  		return true;

The current code, which is purely based on future capability does not handle
CPUs without the vulnerablility properly. Can we fix this?

Thanks,
JC

^ permalink raw reply

* [PATCH 1/3] arm: Add BTB invalidation on switch_mm for Cortex-A9, A12, A15 and A17
From: Robin Murphy @ 2018-01-08 17:50 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <f48d11af-32b7-1c20-abaa-1efdf24616d0@arm.com>

Hi Marc,

On 08/01/18 14:46, Marc Zyngier wrote:
> On 08/01/18 14:29, Andre Przywara wrote:
>> Hi,
>>
>> On 06/01/18 12:09, Marc Zyngier wrote:
>>> In order to avoid aliasing attacks against the branch predictor,
>>> some implementations require to invalidate the BTB when switching
>>> from one user context to another.
>>>
>>> For this, we reuse the existing implementation for Cortex-A8, and
>>> apply it to A9, A12, A15, and A17.
>>>
>>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>>> ---
>>>   arch/arm/mm/proc-v7-2level.S |  4 ++--
>>>   arch/arm/mm/proc-v7-3level.S |  6 ++++++
>>>   arch/arm/mm/proc-v7.S        | 32 ++++++++++++++++----------------
>>>   3 files changed, 24 insertions(+), 18 deletions(-)
>>>
>>> diff --git a/arch/arm/mm/proc-v7-2level.S b/arch/arm/mm/proc-v7-2level.S
>>> index c6141a5435c3..0422e58b74e8 100644
>>> --- a/arch/arm/mm/proc-v7-2level.S
>>> +++ b/arch/arm/mm/proc-v7-2level.S
>>> @@ -41,7 +41,7 @@
>>>    *	even on Cortex-A8 revisions not affected by 430973.
>>>    *	If IBE is not set, the flush BTAC/BTB won't do anything.
>>>    */
>>> -ENTRY(cpu_ca8_switch_mm)
>>> +ENTRY(cpu_v7_btbinv_switch_mm)
>>>   #ifdef CONFIG_MMU
>>>   	mov	r2, #0
>>>   	mcr	p15, 0, r2, c7, c5, 6		@ flush BTAC/BTB
>>> @@ -66,7 +66,7 @@ ENTRY(cpu_v7_switch_mm)
>>>   #endif
>>>   	bx	lr
>>>   ENDPROC(cpu_v7_switch_mm)
>>> -ENDPROC(cpu_ca8_switch_mm)
>>> +ENDPROC(cpu_v7_btbinv_switch_mm)
>>>   
>>>   /*
>>>    *	cpu_v7_set_pte_ext(ptep, pte)
>>> diff --git a/arch/arm/mm/proc-v7-3level.S b/arch/arm/mm/proc-v7-3level.S
>>> index 7d16bbc4102b..934272e1fa08 100644
>>> --- a/arch/arm/mm/proc-v7-3level.S
>>> +++ b/arch/arm/mm/proc-v7-3level.S
>>> @@ -54,6 +54,11 @@
>>>    * Set the translation table base pointer to be pgd_phys (physical address of
>>>    * the new TTB).
>>>    */
>>> +ENTRY(cpu_v7_btbinv_switch_mm)
>>> +#ifdef CONFIG_MMU
>>> +	mov	r2, #0
>>> +	mcr	p15, 0, r2, c7, c5, 6			@ flush BTAC/BTB
>>
>> r2 is already used below: this is the second argument to the function.
>> The first argument is a phys_addr_t, so it takes both r0 and r1 already.
>> That's why we need to use r3 above.
>> This fixes a crash on the Midway for me.
> 
> I suppose you have DRAM above 4GB. Lucky you! I'll fix that in v2.

Why even zero a register at all? Since BPIALL ignores the value of Rt 
(DDI0406C.c, p1744) it shouldn't matter which register you use nor what 
it contains.

Robin.

^ permalink raw reply


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