Merge branch 'f22' of ssh://pkgs.fedoraproject.org/kernel into f22-pf - 4.1.6-201
This commit is contained in:
commit
17824a13af
|
@ -0,0 +1,103 @@
|
|||
From 98f07385212073536f303c07ece455acdd4d267f Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?=D0=9D=D0=B8=D0=BA=D0=BE=D0=BB=D0=B0=D0=B9=20=D0=9A=D1=83?=
|
||||
=?UTF-8?q?=D0=B4=D1=80=D1=8F=D0=B2=D1=86=D0=B5=D0=B2?=
|
||||
<nkudriavtsev@gmail.com>
|
||||
Date: Tue, 21 Jul 2015 13:31:52 +0300
|
||||
Subject: [PATCH] HID: chicony: Add support for Acer Aspire Switch 12
|
||||
|
||||
Acer Aspire Switch 12 keyboard Chicony's controller reports too big usage
|
||||
index on the 1st interface. The patch fixes the report. The work based on
|
||||
solution from drivers/hid/hid-holtek-mouse.c
|
||||
|
||||
Bug report: https://bugzilla.kernel.org/show_bug.cgi?id=101721
|
||||
|
||||
Signed-off-by: Nicholas Kudriavtsev <nkudriavtsev@gmail.com>
|
||||
Signed-off-by: Jiri Kosina <jkosina@suse.com>
|
||||
---
|
||||
drivers/hid/hid-chicony.c | 26 ++++++++++++++++++++++++++
|
||||
drivers/hid/hid-core.c | 1 +
|
||||
drivers/hid/hid-ids.h | 1 +
|
||||
3 files changed, 28 insertions(+)
|
||||
|
||||
diff --git a/drivers/hid/hid-chicony.c b/drivers/hid/hid-chicony.c
|
||||
index b613d5a79684..bc3cec199fee 100644
|
||||
--- a/drivers/hid/hid-chicony.c
|
||||
+++ b/drivers/hid/hid-chicony.c
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <linux/input.h>
|
||||
#include <linux/hid.h>
|
||||
#include <linux/module.h>
|
||||
+#include <linux/usb.h>
|
||||
|
||||
#include "hid-ids.h"
|
||||
|
||||
@@ -57,10 +58,34 @@ static int ch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
||||
return 1;
|
||||
}
|
||||
|
||||
+static __u8 *ch_switch12_report_fixup(struct hid_device *hdev, __u8 *rdesc,
|
||||
+ unsigned int *rsize)
|
||||
+{
|
||||
+ struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
|
||||
+
|
||||
+ if (intf->cur_altsetting->desc.bInterfaceNumber == 1) {
|
||||
+ /* Change usage maximum and logical maximum from 0x7fff to
|
||||
+ * 0x2fff, so they don't exceed HID_MAX_USAGES */
|
||||
+ switch (hdev->product) {
|
||||
+ case USB_DEVICE_ID_CHICONY_ACER_SWITCH12:
|
||||
+ if (*rsize >= 128 && rdesc[64] == 0xff && rdesc[65] == 0x7f
|
||||
+ && rdesc[69] == 0xff && rdesc[70] == 0x7f) {
|
||||
+ hid_info(hdev, "Fixing up report descriptor\n");
|
||||
+ rdesc[65] = rdesc[70] = 0x2f;
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ }
|
||||
+ return rdesc;
|
||||
+}
|
||||
+
|
||||
+
|
||||
static const struct hid_device_id ch_devices[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_AK1D) },
|
||||
+ { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_ACER_SWITCH12) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(hid, ch_devices);
|
||||
@@ -68,6 +93,7 @@ MODULE_DEVICE_TABLE(hid, ch_devices);
|
||||
static struct hid_driver ch_driver = {
|
||||
.name = "chicony",
|
||||
.id_table = ch_devices,
|
||||
+ .report_fixup = ch_switch12_report_fixup,
|
||||
.input_mapping = ch_input_mapping,
|
||||
};
|
||||
module_hid_driver(ch_driver);
|
||||
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
|
||||
index e6fce23b121a..f90ca6574221 100644
|
||||
--- a/drivers/hid/hid-core.c
|
||||
+++ b/drivers/hid/hid-core.c
|
||||
@@ -1807,6 +1807,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS2) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_AK1D) },
|
||||
+ { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_ACER_SWITCH12) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CYGNAL, USB_DEVICE_ID_CYGNAL_CP2112) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) },
|
||||
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
|
||||
index b3b225b75d0a..79210ca8eff1 100644
|
||||
--- a/drivers/hid/hid-ids.h
|
||||
+++ b/drivers/hid/hid-ids.h
|
||||
@@ -233,6 +233,7 @@
|
||||
#define USB_DEVICE_ID_CHICONY_PIXART_USB_OPTICAL_MOUSE 0x1053
|
||||
#define USB_DEVICE_ID_CHICONY_WIRELESS2 0x1123
|
||||
#define USB_DEVICE_ID_CHICONY_AK1D 0x1125
|
||||
+#define USB_DEVICE_ID_CHICONY_ACER_SWITCH12 0x1421
|
||||
|
||||
#define USB_VENDOR_ID_CHUNGHWAT 0x2247
|
||||
#define USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH 0x0001
|
||||
--
|
||||
2.4.3
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
From 0621809e37936e7c2b3eac9165cf2aad7f9189eb Mon Sep 17 00:00:00 2001
|
||||
From: Krzysztof Kozlowski <k.kozlowski@samsung.com>
|
||||
Date: Mon, 3 Aug 2015 14:57:30 +0900
|
||||
Subject: [PATCH] HID: hid-input: Fix accessing freed memory during device
|
||||
disconnect
|
||||
|
||||
During unbinding the driver was dereferencing a pointer to memory
|
||||
already freed by power_supply_unregister().
|
||||
|
||||
Driver was freeing its internal description of battery through pointers
|
||||
stored in power_supply structure. However, because the core owns the
|
||||
power supply instance, after calling power_supply_unregister() this
|
||||
memory is freed and the driver cannot access these members.
|
||||
|
||||
Fix this by storing the pointer to internal description of battery in a
|
||||
local variable before calling power_supply_unregister(), so the pointer
|
||||
remains valid.
|
||||
|
||||
Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
|
||||
Reported-by: H.J. Lu <hjl.tools@gmail.com>
|
||||
Fixes: 297d716f6260 ("power_supply: Change ownership from driver to core")
|
||||
Cc: <stable@vger.kernel.org>
|
||||
Reviewed-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
|
||||
Signed-off-by: Jiri Kosina <jkosina@suse.com>
|
||||
---
|
||||
drivers/hid/hid-input.c | 7 +++++--
|
||||
1 file changed, 5 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
|
||||
index 3511bbab..e3c6364 100644
|
||||
--- a/drivers/hid/hid-input.c
|
||||
+++ b/drivers/hid/hid-input.c
|
||||
@@ -462,12 +462,15 @@ out:
|
||||
|
||||
static void hidinput_cleanup_battery(struct hid_device *dev)
|
||||
{
|
||||
+ const struct power_supply_desc *psy_desc;
|
||||
+
|
||||
if (!dev->battery)
|
||||
return;
|
||||
|
||||
+ psy_desc = dev->battery->desc;
|
||||
power_supply_unregister(dev->battery);
|
||||
- kfree(dev->battery->desc->name);
|
||||
- kfree(dev->battery->desc);
|
||||
+ kfree(psy_desc->name);
|
||||
+ kfree(psy_desc);
|
||||
dev->battery = NULL;
|
||||
}
|
||||
#else /* !CONFIG_HID_BATTERY_STRENGTH */
|
||||
--
|
||||
2.4.3
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
From 3881b164810a564714dfdc16520b0fe538ae4bf7 Mon Sep 17 00:00:00 2001
|
||||
From: David Howells <dhowells@redhat.com>
|
||||
Date: Mon, 27 Jul 2015 15:23:43 +0100
|
||||
Subject: [PATCH] KEYS: ensure we free the assoc array edit if edit is valid
|
||||
|
||||
__key_link_end is not freeing the associated array edit structure
|
||||
and this leads to a 512 byte memory leak each time an identical
|
||||
existing key is added with add_key().
|
||||
|
||||
The reason the add_key() system call returns okay is that
|
||||
key_create_or_update() calls __key_link_begin() before checking to see
|
||||
whether it can update a key directly rather than adding/replacing - which
|
||||
it turns out it can. Thus __key_link() is not called through
|
||||
__key_instantiate_and_link() and __key_link_end() must cancel the edit.
|
||||
|
||||
CVE-2015-1333
|
||||
|
||||
Signed-off-by: Colin Ian King <colin.king@canonical.com>
|
||||
Signed-off-by: David Howells <dhowells@redhat.com>
|
||||
---
|
||||
security/keys/keyring.c | 8 +++++---
|
||||
1 file changed, 5 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
|
||||
index e72548b5897e..d33437007ad2 100644
|
||||
--- a/security/keys/keyring.c
|
||||
+++ b/security/keys/keyring.c
|
||||
@@ -1181,9 +1181,11 @@ void __key_link_end(struct key *keyring,
|
||||
if (index_key->type == &key_type_keyring)
|
||||
up_write(&keyring_serialise_link_sem);
|
||||
|
||||
- if (edit && !edit->dead_leaf) {
|
||||
- key_payload_reserve(keyring,
|
||||
- keyring->datalen - KEYQUOTA_LINK_BYTES);
|
||||
+ if (edit) {
|
||||
+ if (!edit->dead_leaf) {
|
||||
+ key_payload_reserve(keyring,
|
||||
+ keyring->datalen - KEYQUOTA_LINK_BYTES);
|
||||
+ }
|
||||
assoc_array_cancel_edit(edit);
|
||||
}
|
||||
up_write(&keyring->sem);
|
||||
--
|
||||
2.4.3
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
From 512255a2ad2c832ca7d4de9f31245f73781922d0 Mon Sep 17 00:00:00 2001
|
||||
From: Andy Lutomirski <luto@kernel.org>
|
||||
Date: Mon, 17 Aug 2015 12:22:50 -0700
|
||||
Subject: [PATCH] Revert "sched/x86_64: Don't save flags on context switch"
|
||||
|
||||
This reverts commit:
|
||||
|
||||
2c7577a75837 ("sched/x86_64: Don't save flags on context switch")
|
||||
|
||||
It was a nice speedup. It's also not quite correct: SYSENTER
|
||||
enables interrupts too early.
|
||||
|
||||
We can re-add this optimization once the SYSENTER code is beaten
|
||||
into shape, which should happen in 4.3 or 4.4.
|
||||
|
||||
Signed-off-by: Andy Lutomirski <luto@kernel.org>
|
||||
Cc: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
Cc: Peter Zijlstra <peterz@infradead.org>
|
||||
Cc: Thomas Gleixner <tglx@linutronix.de>
|
||||
Cc: stable@vger.kernel.org # v3.19
|
||||
Link: http://lkml.kernel.org/r/85f56651f59f76624e80785a8fd3bdfdd089a818.1439838962.git.luto@kernel.org
|
||||
Signed-off-by: Ingo Molnar <mingo@kernel.org>
|
||||
---
|
||||
arch/x86/include/asm/switch_to.h | 12 ++++--------
|
||||
1 file changed, 4 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/arch/x86/include/asm/switch_to.h b/arch/x86/include/asm/switch_to.h
|
||||
index 751bf4b7bf11..d7f3b3b78ac3 100644
|
||||
--- a/arch/x86/include/asm/switch_to.h
|
||||
+++ b/arch/x86/include/asm/switch_to.h
|
||||
@@ -79,12 +79,12 @@ do { \
|
||||
#else /* CONFIG_X86_32 */
|
||||
|
||||
/* frame pointer must be last for get_wchan */
|
||||
-#define SAVE_CONTEXT "pushq %%rbp ; movq %%rsi,%%rbp\n\t"
|
||||
-#define RESTORE_CONTEXT "movq %%rbp,%%rsi ; popq %%rbp\t"
|
||||
+#define SAVE_CONTEXT "pushf ; pushq %%rbp ; movq %%rsi,%%rbp\n\t"
|
||||
+#define RESTORE_CONTEXT "movq %%rbp,%%rsi ; popq %%rbp ; popf\t"
|
||||
|
||||
#define __EXTRA_CLOBBER \
|
||||
, "rcx", "rbx", "rdx", "r8", "r9", "r10", "r11", \
|
||||
- "r12", "r13", "r14", "r15", "flags"
|
||||
+ "r12", "r13", "r14", "r15"
|
||||
|
||||
#ifdef CONFIG_CC_STACKPROTECTOR
|
||||
#define __switch_canary \
|
||||
@@ -100,11 +100,7 @@ do { \
|
||||
#define __switch_canary_iparam
|
||||
#endif /* CC_STACKPROTECTOR */
|
||||
|
||||
-/*
|
||||
- * There is no need to save or restore flags, because flags are always
|
||||
- * clean in kernel mode, with the possible exception of IOPL. Kernel IOPL
|
||||
- * has no effect.
|
||||
- */
|
||||
+/* Save restore flags to clear handle leaking NT */
|
||||
#define switch_to(prev, next, last) \
|
||||
asm volatile(SAVE_CONTEXT \
|
||||
"movq %%rsp,%P[threadrsp](%[prev])\n\t" /* save RSP */ \
|
||||
--
|
||||
2.4.3
|
||||
|
|
@ -1,13 +1,11 @@
|
|||
From b634bc924371a7df6459af04f37c91f65ac59df2 Mon Sep 17 00:00:00 2001
|
||||
From: Tom Lendacky <thomas.lendacky@amd.com>
|
||||
Date: Thu, 28 May 2015 16:38:57 -0400
|
||||
Subject: [PATCH 1/2] amd-xgbe-a0: Add support for XGBE on A0
|
||||
Date: Sat, 21 Feb 2015 12:25:12 -0500
|
||||
Subject: [PATCH] amd-xgbe-a0: Add support for XGBE on A0
|
||||
|
||||
Add XGBE driver support for A0 hardware.
|
||||
|
||||
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
|
||||
[fixup timespec -> timespec64]
|
||||
[use device_dma_is_coherent]
|
||||
Signed-off-by: Mark Salter <msalter@redhat.com>
|
||||
---
|
||||
drivers/net/ethernet/amd/Makefile | 1 +
|
||||
|
@ -19,11 +17,11 @@ Signed-off-by: Mark Salter <msalter@redhat.com>
|
|||
drivers/net/ethernet/amd/xgbe-a0/xgbe-dev.c | 2930 +++++++++++++++++++++++
|
||||
drivers/net/ethernet/amd/xgbe-a0/xgbe-drv.c | 2218 +++++++++++++++++
|
||||
drivers/net/ethernet/amd/xgbe-a0/xgbe-ethtool.c | 616 +++++
|
||||
drivers/net/ethernet/amd/xgbe-a0/xgbe-main.c | 618 +++++
|
||||
drivers/net/ethernet/amd/xgbe-a0/xgbe-main.c | 643 +++++
|
||||
drivers/net/ethernet/amd/xgbe-a0/xgbe-mdio.c | 312 +++
|
||||
drivers/net/ethernet/amd/xgbe-a0/xgbe-ptp.c | 278 +++
|
||||
drivers/net/ethernet/amd/xgbe-a0/xgbe.h | 868 +++++++
|
||||
13 files changed, 10269 insertions(+)
|
||||
13 files changed, 10294 insertions(+)
|
||||
create mode 100644 drivers/net/ethernet/amd/xgbe-a0/Makefile
|
||||
create mode 100644 drivers/net/ethernet/amd/xgbe-a0/xgbe-common.h
|
||||
create mode 100644 drivers/net/ethernet/amd/xgbe-a0/xgbe-dcb.c
|
||||
|
@ -38,7 +36,7 @@ Signed-off-by: Mark Salter <msalter@redhat.com>
|
|||
create mode 100644 drivers/net/ethernet/amd/xgbe-a0/xgbe.h
|
||||
|
||||
diff --git a/drivers/net/ethernet/amd/Makefile b/drivers/net/ethernet/amd/Makefile
|
||||
index a38a2dc..bf0cf2f 100644
|
||||
index a38a2dce3eb3..bf0cf2f8d2db 100644
|
||||
--- a/drivers/net/ethernet/amd/Makefile
|
||||
+++ b/drivers/net/ethernet/amd/Makefile
|
||||
@@ -18,3 +18,4 @@ obj-$(CONFIG_PCNET32) += pcnet32.o
|
||||
|
@ -48,7 +46,7 @@ index a38a2dc..bf0cf2f 100644
|
|||
+obj-$(CONFIG_AMD_XGBE) += xgbe-a0/
|
||||
diff --git a/drivers/net/ethernet/amd/xgbe-a0/Makefile b/drivers/net/ethernet/amd/xgbe-a0/Makefile
|
||||
new file mode 100644
|
||||
index 0000000..561116f
|
||||
index 000000000000..561116faadae
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/ethernet/amd/xgbe-a0/Makefile
|
||||
@@ -0,0 +1,8 @@
|
||||
|
@ -62,7 +60,7 @@ index 0000000..561116f
|
|||
+amd-xgbe-a0-$(CONFIG_DEBUG_FS) += xgbe-debugfs.o
|
||||
diff --git a/drivers/net/ethernet/amd/xgbe-a0/xgbe-common.h b/drivers/net/ethernet/amd/xgbe-a0/xgbe-common.h
|
||||
new file mode 100644
|
||||
index 0000000..75b08c6
|
||||
index 000000000000..75b08c63d39f
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/ethernet/amd/xgbe-a0/xgbe-common.h
|
||||
@@ -0,0 +1,1142 @@
|
||||
|
@ -1210,7 +1208,7 @@ index 0000000..75b08c6
|
|||
+#endif
|
||||
diff --git a/drivers/net/ethernet/amd/xgbe-a0/xgbe-dcb.c b/drivers/net/ethernet/amd/xgbe-a0/xgbe-dcb.c
|
||||
new file mode 100644
|
||||
index 0000000..343301c
|
||||
index 000000000000..343301cbf7b4
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/ethernet/amd/xgbe-a0/xgbe-dcb.c
|
||||
@@ -0,0 +1,269 @@
|
||||
|
@ -1485,7 +1483,7 @@ index 0000000..343301c
|
|||
+}
|
||||
diff --git a/drivers/net/ethernet/amd/xgbe-a0/xgbe-debugfs.c b/drivers/net/ethernet/amd/xgbe-a0/xgbe-debugfs.c
|
||||
new file mode 100644
|
||||
index 0000000..ecfa6f9
|
||||
index 000000000000..ecfa6f91da22
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/ethernet/amd/xgbe-a0/xgbe-debugfs.c
|
||||
@@ -0,0 +1,373 @@
|
||||
|
@ -1864,7 +1862,7 @@ index 0000000..ecfa6f9
|
|||
+}
|
||||
diff --git a/drivers/net/ethernet/amd/xgbe-a0/xgbe-desc.c b/drivers/net/ethernet/amd/xgbe-a0/xgbe-desc.c
|
||||
new file mode 100644
|
||||
index 0000000..5dd5777
|
||||
index 000000000000..5dd57779c82c
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/ethernet/amd/xgbe-a0/xgbe-desc.c
|
||||
@@ -0,0 +1,636 @@
|
||||
|
@ -2506,7 +2504,7 @@ index 0000000..5dd5777
|
|||
+}
|
||||
diff --git a/drivers/net/ethernet/amd/xgbe-a0/xgbe-dev.c b/drivers/net/ethernet/amd/xgbe-a0/xgbe-dev.c
|
||||
new file mode 100644
|
||||
index 0000000..2d88739
|
||||
index 000000000000..2d88739de41c
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/ethernet/amd/xgbe-a0/xgbe-dev.c
|
||||
@@ -0,0 +1,2930 @@
|
||||
|
@ -5442,7 +5440,7 @@ index 0000000..2d88739
|
|||
+}
|
||||
diff --git a/drivers/net/ethernet/amd/xgbe-a0/xgbe-drv.c b/drivers/net/ethernet/amd/xgbe-a0/xgbe-drv.c
|
||||
new file mode 100644
|
||||
index 0000000..ca4af9e
|
||||
index 000000000000..ca4af9e508b8
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/ethernet/amd/xgbe-a0/xgbe-drv.c
|
||||
@@ -0,0 +1,2218 @@
|
||||
|
@ -7666,7 +7664,7 @@ index 0000000..ca4af9e
|
|||
+}
|
||||
diff --git a/drivers/net/ethernet/amd/xgbe-a0/xgbe-ethtool.c b/drivers/net/ethernet/amd/xgbe-a0/xgbe-ethtool.c
|
||||
new file mode 100644
|
||||
index 0000000..165ff1c
|
||||
index 000000000000..165ff1ceedcc
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/ethernet/amd/xgbe-a0/xgbe-ethtool.c
|
||||
@@ -0,0 +1,616 @@
|
||||
|
@ -8288,10 +8286,10 @@ index 0000000..165ff1c
|
|||
+}
|
||||
diff --git a/drivers/net/ethernet/amd/xgbe-a0/xgbe-main.c b/drivers/net/ethernet/amd/xgbe-a0/xgbe-main.c
|
||||
new file mode 100644
|
||||
index 0000000..deb8551
|
||||
index 000000000000..a85fb4965835
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/ethernet/amd/xgbe-a0/xgbe-main.c
|
||||
@@ -0,0 +1,618 @@
|
||||
@@ -0,0 +1,643 @@
|
||||
+/*
|
||||
+ * AMD 10Gb Ethernet driver
|
||||
+ *
|
||||
|
@ -8478,8 +8476,13 @@ index 0000000..deb8551
|
|||
+#ifdef CONFIG_ACPI
|
||||
+static int xgbe_acpi_support(struct xgbe_prv_data *pdata)
|
||||
+{
|
||||
+ struct acpi_device *adev = pdata->adev;
|
||||
+ struct device *dev = pdata->dev;
|
||||
+ u32 property;
|
||||
+ acpi_handle handle;
|
||||
+ acpi_status status;
|
||||
+ unsigned long long data;
|
||||
+ int cca;
|
||||
+ int ret;
|
||||
+
|
||||
+ /* Obtain the system clock setting */
|
||||
|
@ -8500,6 +8503,24 @@ index 0000000..deb8551
|
|||
+ }
|
||||
+ pdata->ptpclk_rate = property;
|
||||
+
|
||||
+ /* Retrieve the device cache coherency value */
|
||||
+ handle = adev->handle;
|
||||
+ do {
|
||||
+ status = acpi_evaluate_integer(handle, "_CCA", NULL, &data);
|
||||
+ if (!ACPI_FAILURE(status)) {
|
||||
+ cca = data;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ status = acpi_get_parent(handle, &handle);
|
||||
+ } while (!ACPI_FAILURE(status));
|
||||
+
|
||||
+ if (ACPI_FAILURE(status)) {
|
||||
+ dev_err(dev, "error obtaining acpi coherency value\n");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ pdata->coherent = !!cca;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+#else /* CONFIG_ACPI */
|
||||
|
@ -8530,6 +8551,9 @@ index 0000000..deb8551
|
|||
+ }
|
||||
+ pdata->ptpclk_rate = clk_get_rate(pdata->ptpclk);
|
||||
+
|
||||
+ /* Retrieve the device cache coherency value */
|
||||
+ pdata->coherent = of_dma_is_coherent(dev->of_node);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+#else /* CONFIG_OF */
|
||||
|
@ -8648,7 +8672,6 @@ index 0000000..deb8551
|
|||
+ goto err_io;
|
||||
+
|
||||
+ /* Set the DMA coherency values */
|
||||
+ pdata->coherent = device_dma_is_coherent(pdata->dev);
|
||||
+ if (pdata->coherent) {
|
||||
+ pdata->axdomain = XGBE_DMA_OS_AXDOMAIN;
|
||||
+ pdata->arcache = XGBE_DMA_OS_ARCACHE;
|
||||
|
@ -8912,7 +8935,7 @@ index 0000000..deb8551
|
|||
+module_platform_driver(xgbe_a0_driver);
|
||||
diff --git a/drivers/net/ethernet/amd/xgbe-a0/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe-a0/xgbe-mdio.c
|
||||
new file mode 100644
|
||||
index 0000000..b84d048
|
||||
index 000000000000..b84d0481bed8
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/ethernet/amd/xgbe-a0/xgbe-mdio.c
|
||||
@@ -0,0 +1,312 @@
|
||||
|
@ -9230,7 +9253,7 @@ index 0000000..b84d048
|
|||
+}
|
||||
diff --git a/drivers/net/ethernet/amd/xgbe-a0/xgbe-ptp.c b/drivers/net/ethernet/amd/xgbe-a0/xgbe-ptp.c
|
||||
new file mode 100644
|
||||
index 0000000..1016aeb
|
||||
index 000000000000..1016aeb96162
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/ethernet/amd/xgbe-a0/xgbe-ptp.c
|
||||
@@ -0,0 +1,278 @@
|
||||
|
@ -9514,7 +9537,7 @@ index 0000000..1016aeb
|
|||
+}
|
||||
diff --git a/drivers/net/ethernet/amd/xgbe-a0/xgbe.h b/drivers/net/ethernet/amd/xgbe-a0/xgbe.h
|
||||
new file mode 100644
|
||||
index 0000000..04c00d2
|
||||
index 000000000000..04c00d236c49
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/ethernet/amd/xgbe-a0/xgbe.h
|
||||
@@ -0,0 +1,868 @@
|
||||
|
@ -10386,6 +10409,3 @@ index 0000000..04c00d2
|
|||
+#endif
|
||||
+
|
||||
+#endif
|
||||
--
|
||||
2.4.5
|
||||
|
||||
|
|
|
@ -1,104 +0,0 @@
|
|||
If there are too many pending per work I/O, too many
|
||||
high priority work thread can be generated so that
|
||||
system performance can be effected.
|
||||
|
||||
This patch limits the max pending per work I/O as 16,
|
||||
and will fackback to single queue mode when the max
|
||||
number is reached.
|
||||
|
||||
This patch fixes Fedora 22 live booting performance
|
||||
regression when it is booted from squashfs over dm
|
||||
based on loop, and looks the following reasons are
|
||||
related with the problem:
|
||||
|
||||
- not like other filesyststems(such as ext4), squashfs
|
||||
is a bit special, and I observed that increasing I/O jobs
|
||||
to access file in squashfs only improve I/O performance a
|
||||
little, but it can make big difference for ext4
|
||||
|
||||
- nested loop: both squashfs.img and ext3fs.img are mounted
|
||||
as loop block, and ext3fs.img is inside the squashfs
|
||||
|
||||
- during booting, lots of tasks may run concurrently
|
||||
|
||||
Fixes: b5dd2f6047ca108001328aac0e8588edd15f1778
|
||||
Cc: stable@vger.kernel.org (v4.0)
|
||||
Reported-by: Justin M. Forbes <jforbes@fedoraproject.org>
|
||||
Tested-by: Justin M. Forbes <jforbes@fedoraproject.org>
|
||||
Signed-off-by: Ming Lei <ming.lei@canonical.com>
|
||||
---
|
||||
drivers/block/loop.c | 19 +++++++++++++++++--
|
||||
drivers/block/loop.h | 2 ++
|
||||
2 files changed, 19 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
|
||||
index ae3fcb4..5a728c6 100644
|
||||
--- a/drivers/block/loop.c
|
||||
+++ b/drivers/block/loop.c
|
||||
@@ -1425,13 +1425,24 @@ static int loop_queue_rq(struct blk_mq_hw_ctx *hctx,
|
||||
const struct blk_mq_queue_data *bd)
|
||||
{
|
||||
struct loop_cmd *cmd = blk_mq_rq_to_pdu(bd->rq);
|
||||
+ struct loop_device *lo = cmd->rq->q->queuedata;
|
||||
+ bool single_queue = !!(cmd->rq->cmd_flags & REQ_WRITE);
|
||||
+
|
||||
+ /*
|
||||
+ * Fallback to single queue mode if the pending per work
|
||||
+ * I/O number reaches 16, otherwise too many high priority
|
||||
+ * worker thread may effect system performance as reported
|
||||
+ * in fedora live booting from squashfs over loop.
|
||||
+ */
|
||||
+ if (atomic_read(&lo->pending_per_work_io) >= 16)
|
||||
+ single_queue = true;
|
||||
|
||||
blk_mq_start_request(bd->rq);
|
||||
|
||||
- if (cmd->rq->cmd_flags & REQ_WRITE) {
|
||||
- struct loop_device *lo = cmd->rq->q->queuedata;
|
||||
+ if (single_queue) {
|
||||
bool need_sched = true;
|
||||
|
||||
+ cmd->per_work_io = false;
|
||||
spin_lock_irq(&lo->lo_lock);
|
||||
if (lo->write_started)
|
||||
need_sched = false;
|
||||
@@ -1443,6 +1454,8 @@ static int loop_queue_rq(struct blk_mq_hw_ctx *hctx,
|
||||
if (need_sched)
|
||||
queue_work(loop_wq, &lo->write_work);
|
||||
} else {
|
||||
+ atomic_inc(&lo->pending_per_work_io);
|
||||
+ cmd->per_work_io = true;
|
||||
queue_work(loop_wq, &cmd->read_work);
|
||||
}
|
||||
|
||||
@@ -1467,6 +1480,8 @@ static void loop_handle_cmd(struct loop_cmd *cmd)
|
||||
if (ret)
|
||||
cmd->rq->errors = -EIO;
|
||||
blk_mq_complete_request(cmd->rq);
|
||||
+ if (cmd->per_work_io)
|
||||
+ atomic_dec(&lo->pending_per_work_io);
|
||||
}
|
||||
|
||||
static void loop_queue_write_work(struct work_struct *work)
|
||||
diff --git a/drivers/block/loop.h b/drivers/block/loop.h
|
||||
index 301c27f..eb855f5 100644
|
||||
--- a/drivers/block/loop.h
|
||||
+++ b/drivers/block/loop.h
|
||||
@@ -57,6 +57,7 @@ struct loop_device {
|
||||
struct list_head write_cmd_head;
|
||||
struct work_struct write_work;
|
||||
bool write_started;
|
||||
+ atomic_t pending_per_work_io;
|
||||
int lo_state;
|
||||
struct mutex lo_ctl_mutex;
|
||||
|
||||
@@ -68,6 +69,7 @@ struct loop_device {
|
||||
struct loop_cmd {
|
||||
struct work_struct read_work;
|
||||
struct request *rq;
|
||||
+ bool per_work_io;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
--
|
||||
1.9.1
|
|
@ -136,11 +136,11 @@ CONFIG_LSM_MMAP_MIN_ADDR=32768
|
|||
|
||||
CONFIG_XZ_DEC_ARM=y
|
||||
|
||||
CONFIG_UACCESS_WITH_MEMCPY=y
|
||||
|
||||
CONFIG_PCI_HOST_GENERIC=y
|
||||
# CONFIG_PCI_LAYERSCAPE is not set
|
||||
# CONFIG_PCIE_IPROC is not set
|
||||
# Do NOT enable this, it breaks stuff and makes things go slow
|
||||
# CONFIG_UACCESS_WITH_MEMCPY is not set
|
||||
|
||||
CONFIG_LBDAF=y
|
||||
|
||||
|
|
|
@ -172,7 +172,7 @@ CONFIG_CRYPTO_842=m
|
|||
CONFIG_CRYPTO_DEV_NX_ENCRYPT=m
|
||||
CONFIG_CRYPTO_DEV_NX_COMPRESS=m
|
||||
CONFIG_CRYPTO_DEV_VMX=y
|
||||
CONFIG_CRYPTO_DEV_VMX_ENCRYPT=y
|
||||
# CONFIG_CRYPTO_DEV_VMX_ENCRYPT is not set
|
||||
|
||||
CONFIG_CXL=m
|
||||
|
||||
|
|
|
@ -162,7 +162,7 @@ CONFIG_CRYPTO_842=m
|
|||
CONFIG_CRYPTO_DEV_NX_ENCRYPT=m
|
||||
CONFIG_CRYPTO_DEV_NX_COMPRESS=m
|
||||
CONFIG_CRYPTO_DEV_VMX=y
|
||||
CONFIG_CRYPTO_DEV_VMX_ENCRYPT=y
|
||||
# CONFIG_CRYPTO_DEV_VMX_ENCRYPT is not set
|
||||
|
||||
CONFIG_CXL=m
|
||||
|
||||
|
|
|
@ -40,10 +40,10 @@ CONFIG_X86_PM_TIMER=y
|
|||
|
||||
CONFIG_EFI=y
|
||||
CONFIG_EFI_STUB=y
|
||||
CONFIG_EFI_VARS=y
|
||||
# CONFIG_EFI_VARS is not set
|
||||
CONFIG_EFIVAR_FS=y
|
||||
CONFIG_EFI_VARS_PSTORE=y
|
||||
CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE=y
|
||||
# CONFIG_EFI_VARS_PSTORE is not set
|
||||
# CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE is not set
|
||||
CONFIG_EFI_PCDP=y
|
||||
CONFIG_FB_EFI=y
|
||||
CONFIG_EARLY_PRINTK_EFI=y
|
||||
|
|
|
@ -0,0 +1,148 @@
|
|||
From 9851cf5d02703ab60b58a2335481cc195c72ff9c Mon Sep 17 00:00:00 2001
|
||||
From: Jonathon Jongsma <jjongsma@redhat.com>
|
||||
Date: Thu, 20 Aug 2015 12:04:32 -0700
|
||||
Subject: [PATCH] drm/qxl: validate monitors config modes
|
||||
|
||||
Due to some recent changes in
|
||||
drm_helper_probe_single_connector_modes_merge_bits(), old custom modes
|
||||
were not being pruned properly. In current kernels,
|
||||
drm_mode_validate_basic() is called to sanity-check each mode in the
|
||||
list. If the sanity-check passes, the mode's status gets set to to
|
||||
MODE_OK. In older kernels this check was not done, so old custom modes
|
||||
would still have a status of MODE_UNVERIFIED at this point, and would
|
||||
therefore be pruned later in the function.
|
||||
|
||||
As a result of this new behavior, the list of modes for a device always
|
||||
includes every custom mode ever configured for the device, with the
|
||||
largest one listed first. Since desktop environments usually choose the
|
||||
first preferred mode when a hotplug event is emitted, this had the
|
||||
result of making it very difficult for the user to reduce the size of
|
||||
the display.
|
||||
|
||||
The qxl driver did implement the mode_valid connector function, but it
|
||||
was empty. In order to restore the old behavior where old custom modes
|
||||
are pruned, we implement a proper mode_valid function for the qxl
|
||||
driver. This function now checks each mode against the last configured
|
||||
custom mode and the list of standard modes. If the mode doesn't match
|
||||
any of these, its status is set to MODE_BAD so that it will be pruned as
|
||||
expected.
|
||||
|
||||
Signed-off-by: Jonathon Jongsma <jjongsma at redhat.com>
|
||||
Cc: stable at vger.kernel.org
|
||||
---
|
||||
drivers/gpu/drm/qxl/qxl_display.c | 66 ++++++++++++++++++++++++---------------
|
||||
drivers/gpu/drm/qxl/qxl_drv.h | 2 ++
|
||||
2 files changed, 42 insertions(+), 26 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c
|
||||
index a8dbb3ef4e3c..7c6225c84ba6 100644
|
||||
--- a/drivers/gpu/drm/qxl/qxl_display.c
|
||||
+++ b/drivers/gpu/drm/qxl/qxl_display.c
|
||||
@@ -160,9 +160,35 @@ static int qxl_add_monitors_config_modes(struct drm_connector *connector,
|
||||
*pwidth = head->width;
|
||||
*pheight = head->height;
|
||||
drm_mode_probed_add(connector, mode);
|
||||
+ /* remember the last custom size for mode validation */
|
||||
+ qdev->monitors_config_width = mode->hdisplay;
|
||||
+ qdev->monitors_config_height = mode->vdisplay;
|
||||
return 1;
|
||||
}
|
||||
|
||||
+static struct mode_size {
|
||||
+ int w;
|
||||
+ int h;
|
||||
+} common_modes[] = {
|
||||
+ { 640, 480},
|
||||
+ { 720, 480},
|
||||
+ { 800, 600},
|
||||
+ { 848, 480},
|
||||
+ {1024, 768},
|
||||
+ {1152, 768},
|
||||
+ {1280, 720},
|
||||
+ {1280, 800},
|
||||
+ {1280, 854},
|
||||
+ {1280, 960},
|
||||
+ {1280, 1024},
|
||||
+ {1440, 900},
|
||||
+ {1400, 1050},
|
||||
+ {1680, 1050},
|
||||
+ {1600, 1200},
|
||||
+ {1920, 1080},
|
||||
+ {1920, 1200}
|
||||
+};
|
||||
+
|
||||
static int qxl_add_common_modes(struct drm_connector *connector,
|
||||
unsigned pwidth,
|
||||
unsigned pheight)
|
||||
@@ -170,29 +196,6 @@ static int qxl_add_common_modes(struct drm_connector *connector,
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct drm_display_mode *mode = NULL;
|
||||
int i;
|
||||
- struct mode_size {
|
||||
- int w;
|
||||
- int h;
|
||||
- } common_modes[] = {
|
||||
- { 640, 480},
|
||||
- { 720, 480},
|
||||
- { 800, 600},
|
||||
- { 848, 480},
|
||||
- {1024, 768},
|
||||
- {1152, 768},
|
||||
- {1280, 720},
|
||||
- {1280, 800},
|
||||
- {1280, 854},
|
||||
- {1280, 960},
|
||||
- {1280, 1024},
|
||||
- {1440, 900},
|
||||
- {1400, 1050},
|
||||
- {1680, 1050},
|
||||
- {1600, 1200},
|
||||
- {1920, 1080},
|
||||
- {1920, 1200}
|
||||
- };
|
||||
-
|
||||
for (i = 0; i < ARRAY_SIZE(common_modes); i++) {
|
||||
mode = drm_cvt_mode(dev, common_modes[i].w, common_modes[i].h,
|
||||
60, false, false, false);
|
||||
@@ -823,11 +826,22 @@ static int qxl_conn_get_modes(struct drm_connector *connector)
|
||||
static int qxl_conn_mode_valid(struct drm_connector *connector,
|
||||
struct drm_display_mode *mode)
|
||||
{
|
||||
+ struct drm_device *ddev = connector->dev;
|
||||
+ struct qxl_device *qdev = ddev->dev_private;
|
||||
+ int i;
|
||||
+
|
||||
/* TODO: is this called for user defined modes? (xrandr --add-mode)
|
||||
* TODO: check that the mode fits in the framebuffer */
|
||||
- DRM_DEBUG("%s: %dx%d status=%d\n", mode->name, mode->hdisplay,
|
||||
- mode->vdisplay, mode->status);
|
||||
- return MODE_OK;
|
||||
+
|
||||
+ if(qdev->monitors_config_width == mode->hdisplay &&
|
||||
+ qdev->monitors_config_height == mode->vdisplay)
|
||||
+ return MODE_OK;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(common_modes); i++) {
|
||||
+ if (common_modes[i].w == mode->hdisplay && common_modes[i].h == mode->vdisplay)
|
||||
+ return MODE_OK;
|
||||
+ }
|
||||
+ return MODE_BAD;
|
||||
}
|
||||
|
||||
static struct drm_encoder *qxl_best_encoder(struct drm_connector *connector)
|
||||
diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h
|
||||
index d8549690801d..01a86948eb8c 100644
|
||||
--- a/drivers/gpu/drm/qxl/qxl_drv.h
|
||||
+++ b/drivers/gpu/drm/qxl/qxl_drv.h
|
||||
@@ -325,6 +325,8 @@ struct qxl_device {
|
||||
struct work_struct fb_work;
|
||||
|
||||
struct drm_property *hotplug_mode_update_property;
|
||||
+ int monitors_config_width;
|
||||
+ int monitors_config_height;
|
||||
};
|
||||
|
||||
/* forward declaration for QXL_INFO_IO */
|
||||
--
|
||||
2.4.3
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
From a19afebb883f2a02ecf4b8d5a114ce6957a59238 Mon Sep 17 00:00:00 2001
|
||||
From: Thomas Hellstrom <thellstrom@vmware.com>
|
||||
Date: Wed, 26 Aug 2015 05:49:21 -0700
|
||||
Subject: [PATCH 2/2] drm/vmwgfx: Allow dropped masters render-node like access
|
||||
on legacy nodes v2
|
||||
|
||||
Applications like gnome-shell may try to render after dropping master
|
||||
privileges. Since the driver should now be safe against this scenario,
|
||||
allow those applications to use their legacy node like a render node.
|
||||
|
||||
v2: Add missing return statement.
|
||||
|
||||
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
|
||||
Reviewed-by: Sinclair Yeh <syeh@vmware.com>
|
||||
---
|
||||
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 7 ++++++-
|
||||
drivers/gpu/drm/vmwgfx/vmwgfx_surface.c | 6 ++++++
|
||||
2 files changed, 12 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
|
||||
index a4766acd0ea2..d022b509f1ac 100644
|
||||
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
|
||||
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
|
||||
@@ -993,10 +993,15 @@ static struct vmw_master *vmw_master_check(struct drm_device *dev,
|
||||
}
|
||||
|
||||
/*
|
||||
- * Check if we were previously master, but now dropped.
|
||||
+ * Check if we were previously master, but now dropped. In that
|
||||
+ * case, allow at least render node functionality.
|
||||
*/
|
||||
if (vmw_fp->locked_master) {
|
||||
mutex_unlock(&dev->master_mutex);
|
||||
+
|
||||
+ if (flags & DRM_RENDER_ALLOW)
|
||||
+ return NULL;
|
||||
+
|
||||
DRM_ERROR("Dropped master trying to access ioctl that "
|
||||
"requires authentication.\n");
|
||||
return ERR_PTR(-EACCES);
|
||||
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
|
||||
index 4d0c98edeb6a..7fc3e8abd0c4 100644
|
||||
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
|
||||
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
|
||||
@@ -906,6 +906,12 @@ vmw_surface_handle_reference(struct vmw_private *dev_priv,
|
||||
"surface reference.\n");
|
||||
return -EACCES;
|
||||
}
|
||||
+ if (ACCESS_ONCE(vmw_fpriv(file_priv)->locked_master)) {
|
||||
+ DRM_ERROR("Locked master refused legacy "
|
||||
+ "surface reference.\n");
|
||||
+ return -EACCES;
|
||||
+ }
|
||||
+
|
||||
handle = u_handle;
|
||||
}
|
||||
|
||||
--
|
||||
2.4.3
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
From: Eric Sandeen <sandeen@xxxxxxxxxx>
|
||||
Date: Wed, 05 Aug 2015 15:13:58 -0700
|
||||
Subject: [PATCH] ext4: don't manipulate recovery flag when freezing no-journal fs
|
||||
|
||||
At some point along this sequence of changes:
|
||||
|
||||
f6e63f9 ext4: fold ext4_nojournal_sops into ext4_sops
|
||||
bb04457 ext4: support freezing ext2 (nojournal) file systems
|
||||
9ca9238 ext4: Use separate super_operations structure for no_journal filesystems
|
||||
|
||||
ext4 started setting needs_recovery on filesystems without journals
|
||||
when they are unfrozen. This makes no sense, and in fact confuses
|
||||
blkid to the point where it doesn't recognize the filesystem at all.
|
||||
|
||||
(freeze ext2; unfreeze ext2; run blkid; see no output; run dumpe2fs,
|
||||
see needs_recovery set on fs w/ no journal).
|
||||
|
||||
To fix this, don't manipulate the INCOMPAT_RECOVER feature on
|
||||
filesystems without journals.
|
||||
|
||||
Reported-by: Stu Mark <smark@xxxxxxxxx>
|
||||
Signed-off-by: Eric Sandeen <sandeen@xxxxxxxxxx>
|
||||
---
|
||||
|
||||
Note, is there a reason that in ext4_freeze, if journal_flush
|
||||
fails, we skip the ext4_commit_super call? I didn't change that
|
||||
here, but it seems odd.
|
||||
|
||||
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
|
||||
index 58987b5..e7b345d 100644
|
||||
--- a/fs/ext4/super.c
|
||||
+++ b/fs/ext4/super.c
|
||||
@@ -4833,10 +4833,11 @@ static int ext4_freeze(struct super_block *sb)
|
||||
error = jbd2_journal_flush(journal);
|
||||
if (error < 0)
|
||||
goto out;
|
||||
+
|
||||
+ /* Journal blocked and flushed, clear needs_recovery flag. */
|
||||
+ EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
|
||||
}
|
||||
|
||||
- /* Journal blocked and flushed, clear needs_recovery flag. */
|
||||
- EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
|
||||
error = ext4_commit_super(sb, 1);
|
||||
out:
|
||||
if (journal)
|
||||
@@ -4854,8 +4855,11 @@ static int ext4_unfreeze(struct super_block *sb)
|
||||
if (sb->s_flags & MS_RDONLY)
|
||||
return 0;
|
||||
|
||||
- /* Reset the needs_recovery flag before the fs is unlocked. */
|
||||
- EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
|
||||
+ if (EXT4_SB(sb)->s_journal) {
|
||||
+ /* Reset the needs_recovery flag before the fs is unlocked. */
|
||||
+ EXT4_SET_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER);
|
||||
+ }
|
||||
+
|
||||
ext4_commit_super(sb, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
--
|
||||
To unsubscribe from this list: send the line "unsubscribe linux-ext4" in
|
||||
the body of a message to majordomo@xxxxxxxxxxxxxxx
|
||||
More majordomo info at http://vger.kernel.org/majordomo-info.html
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
From 9c8108a4d3a837c51a29f28229a06d97654eaeb6 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Leech <cleech@redhat.com>
|
||||
Date: Tue, 16 Jun 2015 16:07:13 -0700
|
||||
Subject: iSCSI: let session recovery_tmo sysfs writes persist across recovery
|
||||
|
||||
The iSCSI session recovery_tmo setting is writeable in sysfs, but it's
|
||||
also set every time a connection is established when parameters are set
|
||||
from iscsid over netlink. That results in the timeout being reset to
|
||||
the default value after every recovery.
|
||||
|
||||
The DM multipath tools want to use the sysfs interface to lower the
|
||||
default timeout when there are multiple paths to fail over. It has
|
||||
caused confusion that we have a writeable sysfs value that seem to keep
|
||||
resetting itself.
|
||||
|
||||
This patch adds an in-kernel flag that gets set once a sysfs write
|
||||
occurs, and then ignores netlink parameter setting once it's been
|
||||
modified via the sysfs interface. My thinking here is that the sysfs
|
||||
interface is much simpler for external tools to influence the session
|
||||
timeout, but if we're going to allow it to be modified directly we
|
||||
should ensure that setting is maintained.
|
||||
|
||||
Signed-off-by: Chris Leech <cleech@redhat.com>
|
||||
Reviewed-by: Mike Christie <michaelc@cs.wisc.edu>
|
||||
Signed-off-by: James Bottomley <JBottomley@Odin.com>
|
||||
|
||||
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
|
||||
index 55647aa..4c25539 100644
|
||||
--- a/drivers/scsi/scsi_transport_iscsi.c
|
||||
+++ b/drivers/scsi/scsi_transport_iscsi.c
|
||||
@@ -2042,6 +2042,7 @@ iscsi_alloc_session(struct Scsi_Host *shost, struct iscsi_transport *transport,
|
||||
session->transport = transport;
|
||||
session->creator = -1;
|
||||
session->recovery_tmo = 120;
|
||||
+ session->recovery_tmo_sysfs_override = false;
|
||||
session->state = ISCSI_SESSION_FREE;
|
||||
INIT_DELAYED_WORK(&session->recovery_work, session_recovery_timedout);
|
||||
INIT_LIST_HEAD(&session->sess_list);
|
||||
@@ -2786,7 +2787,8 @@ iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev)
|
||||
switch (ev->u.set_param.param) {
|
||||
case ISCSI_PARAM_SESS_RECOVERY_TMO:
|
||||
sscanf(data, "%d", &value);
|
||||
- session->recovery_tmo = value;
|
||||
+ if (!session->recovery_tmo_sysfs_override)
|
||||
+ session->recovery_tmo = value;
|
||||
break;
|
||||
default:
|
||||
err = transport->set_param(conn, ev->u.set_param.param,
|
||||
@@ -4049,13 +4051,15 @@ store_priv_session_##field(struct device *dev, \
|
||||
if ((session->state == ISCSI_SESSION_FREE) || \
|
||||
(session->state == ISCSI_SESSION_FAILED)) \
|
||||
return -EBUSY; \
|
||||
- if (strncmp(buf, "off", 3) == 0) \
|
||||
+ if (strncmp(buf, "off", 3) == 0) { \
|
||||
session->field = -1; \
|
||||
- else { \
|
||||
+ session->field##_sysfs_override = true; \
|
||||
+ } else { \
|
||||
val = simple_strtoul(buf, &cp, 0); \
|
||||
if (*cp != '\0' && *cp != '\n') \
|
||||
return -EINVAL; \
|
||||
session->field = val; \
|
||||
+ session->field##_sysfs_override = true; \
|
||||
} \
|
||||
return count; \
|
||||
}
|
||||
@@ -4066,6 +4070,7 @@ store_priv_session_##field(struct device *dev, \
|
||||
static ISCSI_CLASS_ATTR(priv_sess, field, S_IRUGO | S_IWUSR, \
|
||||
show_priv_session_##field, \
|
||||
store_priv_session_##field)
|
||||
+
|
||||
iscsi_priv_session_rw_attr(recovery_tmo, "%d");
|
||||
|
||||
static struct attribute *iscsi_session_attrs[] = {
|
||||
diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h
|
||||
index 2555ee5..6183d20 100644
|
||||
--- a/include/scsi/scsi_transport_iscsi.h
|
||||
+++ b/include/scsi/scsi_transport_iscsi.h
|
||||
@@ -241,6 +241,7 @@ struct iscsi_cls_session {
|
||||
|
||||
/* recovery fields */
|
||||
int recovery_tmo;
|
||||
+ bool recovery_tmo_sysfs_override;
|
||||
struct delayed_work recovery_work;
|
||||
|
||||
unsigned int target_id;
|
||||
--
|
||||
cgit v0.10.2
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
From 72695420d48c264b3ca0dacccda1a4789a52c2f6 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Fri, 24 Jul 2015 11:45:28 +0200
|
||||
Subject: [PATCH] ideapad-laptop: Add Lenovo Yoga 3 14 to no_hw_rfkill dmi list
|
||||
|
||||
Like some of the other Yoga models the Lenovo Yoga 3 14 does not have a
|
||||
hw rfkill switch, and trying to read the hw rfkill switch through the
|
||||
ideapad module causes it to always reported blocking breaking wifi.
|
||||
|
||||
This commit adds the Lenovo Yoga 3 14 to the no_hw_rfkill dmi list, fixing
|
||||
the wifi breakage.
|
||||
|
||||
BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=1239050
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
---
|
||||
drivers/platform/x86/ideapad-laptop.c | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
|
||||
index 76b57388d01b..81c3e582309a 100644
|
||||
--- a/drivers/platform/x86/ideapad-laptop.c
|
||||
+++ b/drivers/platform/x86/ideapad-laptop.c
|
||||
@@ -853,6 +853,13 @@ static const struct dmi_system_id no_hw_rfkill_list[] = {
|
||||
},
|
||||
},
|
||||
{
|
||||
+ .ident = "Lenovo Yoga 3 14",
|
||||
+ .matches = {
|
||||
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
+ DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Yoga 3 14"),
|
||||
+ },
|
||||
+ },
|
||||
+ {
|
||||
.ident = "Lenovo Yoga 3 Pro 1370",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
|
||||
--
|
||||
2.4.3
|
||||
|
197
kernel.spec
197
kernel.spec
|
@ -52,8 +52,8 @@ Summary: The Linux kernel
|
|||
%if 0%{?released_kernel}
|
||||
|
||||
# Do we have a -stable update to apply?
|
||||
#+Hu Pf against 4.1.2 v4.1-pf1: https://pf.natalenko.name/forum/index.php?topic=332.0
|
||||
%define stable_update 2
|
||||
#+Hu Pf against 4.1.6 v4.1-pf4: https://pf.natalenko.name/forum/index.php?topic=345.0 (https://pf.natalenko.name/forum/index.php?topic=344.0)
|
||||
%define stable_update 6
|
||||
# Set rpm version accordingly
|
||||
%if 0%{?stable_update}
|
||||
%define stablerev %{stable_update}
|
||||
|
@ -628,12 +628,6 @@ Patch26175: xen-pciback-Don-t-disable-PCI_COMMAND-on-PCI-device-.patch
|
|||
#rhbz 1212230
|
||||
Patch26176: Input-synaptics-pin-3-touches-when-the-firmware-repo.patch
|
||||
|
||||
#rhbz 1210857
|
||||
Patch26192: blk-loop-avoid-too-many-pending-per-work-IO.patch
|
||||
|
||||
#rhbz 1220118
|
||||
Patch26202: media-Fix-regression-in-some-more-dib0700-based-devi.patch
|
||||
|
||||
Patch26203: v4l-uvcvideo-Fix-incorrect-bandwidth-with-Chicony-de.patch
|
||||
|
||||
#rhbz 1217249
|
||||
|
@ -648,9 +642,6 @@ Patch26219: firmware-Drop-WARN-from-usermodehelper_read_trylock-.patch
|
|||
#rhbz 1226743
|
||||
Patch26221: drm-i915-turn-off-wc-mmaps.patch
|
||||
|
||||
# CVE-2015-XXXX rhbz 1230770 1230774
|
||||
Patch26231: kvm-x86-fix-kvm_apic_has_events-to-check-for-NULL-po.patch
|
||||
|
||||
# rhbz 1227891
|
||||
Patch26250: HID-rmi-Disable-populating-F30-when-the-touchpad-has.patch
|
||||
|
||||
|
@ -660,19 +651,40 @@ Patch26251: ideapad_laptop-Lenovo-G50-30-fix-rfkill-reports-wire.patch
|
|||
# rhbz 1180920 1206724
|
||||
Patch26252: pcmcia-fix-a-boot-time-warning-in-pcmcia-cs-code.patch
|
||||
|
||||
#CVE-2015-1333 rhbz 1244171
|
||||
Patch26253: KEYS-ensure-we-free-the-assoc-array-edit-if-edit-is-.patch
|
||||
#rhbz 1244511
|
||||
Patch507: HID-chicony-Add-support-for-Acer-Aspire-Switch-12.patch
|
||||
|
||||
# CVE-2015-3290 CVE-2015-3291 rhbz 1243465 1245927
|
||||
Patch26254: x86-asm-entry-64-Remove-pointless-jump-to-irq_return.patch
|
||||
Patch26255: x86-entry-Stop-using-PER_CPU_VAR-kernel_stack.patch
|
||||
Patch26256: x86-entry-Define-cpu_current_top_of_stack-for-64-bit.patch
|
||||
Patch26257: x86-nmi-Enable-nested-do_nmi-handling-for-64-bit-ker.patch
|
||||
Patch26258: x86-nmi-64-Remove-asm-code-that-saves-cr2.patch
|
||||
Patch26259: x86-nmi-64-Switch-stacks-on-userspace-NMI-entry.patch
|
||||
Patch26260: x86-nmi-64-Improve-nested-NMI-comments.patch
|
||||
Patch26261: x86-nmi-64-Reorder-nested-NMI-checks.patch
|
||||
Patch26262: x86-nmi-64-Use-DF-to-avoid-userspace-RSP-confusing-n.patch
|
||||
#rhbz 1251877 1251880 1250279 1248741
|
||||
# and probably more since ugh use after free bugs
|
||||
Patch26264: HID-hid-input-Fix-accessing-freed-memory-during-devi.patch
|
||||
|
||||
#rhbz 1239050
|
||||
Patch509: ideapad-laptop-Add-Lenovo-Yoga-3-14-to-no_hw_rfkill-.patch
|
||||
|
||||
#rhbz 1253789
|
||||
Patch511: iSCSI-let-session-recovery_tmo-sysfs-writes-persist.patch
|
||||
|
||||
#rhbz 1250717
|
||||
Patch512: ext4-dont-manipulate-recovery-flag-when-freezing.patch
|
||||
|
||||
#CVE-2015-6666 rhbz 1256746 1256753
|
||||
Patch513: Revert-sched-x86_64-Don-t-save-flags-on-context-swit.patch
|
||||
|
||||
#rhbz 1256281
|
||||
Patch26265: mmc-sdhci-fix-dma-memory-leak-in-sdhci_pre_req.patch
|
||||
|
||||
#rhbz 1224764
|
||||
Patch26266: x86-apic-Fix-fallout-from-x2apic-cleanup.patch
|
||||
|
||||
#rhbz 1257534
|
||||
Patch515: nv46-Change-mc-subdev-oclass-from-nv44-to-nv4c.patch
|
||||
|
||||
#rhbz 1212201
|
||||
Patch514: drm-qxl-validate-monitors-config-modes.patch
|
||||
|
||||
#rhbz 1257500
|
||||
Patch517: vmwgfx-Rework-device-initialization.patch
|
||||
Patch518: drm-vmwgfx-Allow-dropped-masters-render-node-like-ac.patch
|
||||
|
||||
# END OF PATCH DEFINITIONS
|
||||
|
||||
|
@ -1397,12 +1409,6 @@ ApplyPatch xen-pciback-Don-t-disable-PCI_COMMAND-on-PCI-device-.patch
|
|||
#rhbz 1212230
|
||||
ApplyPatch Input-synaptics-pin-3-touches-when-the-firmware-repo.patch
|
||||
|
||||
#rhbz 1210857
|
||||
ApplyPatch blk-loop-avoid-too-many-pending-per-work-IO.patch
|
||||
|
||||
#rhbz 1220118
|
||||
ApplyPatch media-Fix-regression-in-some-more-dib0700-based-devi.patch
|
||||
|
||||
ApplyPatch v4l-uvcvideo-Fix-incorrect-bandwidth-with-Chicony-de.patch
|
||||
|
||||
#rhbz 1217249
|
||||
|
@ -1422,9 +1428,6 @@ ApplyPatch drm-i915-turn-off-wc-mmaps.patch
|
|||
# pplyPatch Input-synaptics-allocate-3-slots-to-keep-stability-i.patch
|
||||
# pplyPatch Input-synaptics-pin-3-touches-when-the-firmware-repo.patch
|
||||
|
||||
# CVE-2015-XXXX rhbz 1230770 1230774
|
||||
ApplyPatch kvm-x86-fix-kvm_apic_has_events-to-check-for-NULL-po.patch
|
||||
|
||||
#rhbz 1227891
|
||||
ApplyPatch HID-rmi-Disable-populating-F30-when-the-touchpad-has.patch
|
||||
|
||||
|
@ -1434,19 +1437,39 @@ ApplyPatch ideapad_laptop-Lenovo-G50-30-fix-rfkill-reports-wire.patch
|
|||
# rhbz 1180920 1206724
|
||||
ApplyPatch pcmcia-fix-a-boot-time-warning-in-pcmcia-cs-code.patch
|
||||
|
||||
#CVE-2015-1333 rhbz 1244171
|
||||
ApplyPatch KEYS-ensure-we-free-the-assoc-array-edit-if-edit-is-.patch
|
||||
#rhbz 1244511
|
||||
ApplyPatch HID-chicony-Add-support-for-Acer-Aspire-Switch-12.patch
|
||||
|
||||
# CVE-2015-3290 CVE-2015-3291 rhbz 1243465 1245927
|
||||
ApplyPatch x86-asm-entry-64-Remove-pointless-jump-to-irq_return.patch
|
||||
ApplyPatch x86-entry-Stop-using-PER_CPU_VAR-kernel_stack.patch
|
||||
ApplyPatch x86-entry-Define-cpu_current_top_of_stack-for-64-bit.patch
|
||||
ApplyPatch x86-nmi-Enable-nested-do_nmi-handling-for-64-bit-ker.patch
|
||||
ApplyPatch x86-nmi-64-Remove-asm-code-that-saves-cr2.patch
|
||||
ApplyPatch x86-nmi-64-Switch-stacks-on-userspace-NMI-entry.patch
|
||||
ApplyPatch x86-nmi-64-Improve-nested-NMI-comments.patch
|
||||
ApplyPatch x86-nmi-64-Reorder-nested-NMI-checks.patch
|
||||
ApplyPatch x86-nmi-64-Use-DF-to-avoid-userspace-RSP-confusing-n.patch
|
||||
#rhbz 1251877 1251880 1250279 1248741
|
||||
ApplyPatch HID-hid-input-Fix-accessing-freed-memory-during-devi.patch
|
||||
|
||||
#rhbz 1239050
|
||||
ApplyPatch ideapad-laptop-Add-Lenovo-Yoga-3-14-to-no_hw_rfkill-.patch
|
||||
|
||||
#rhbz 1253789
|
||||
ApplyPatch iSCSI-let-session-recovery_tmo-sysfs-writes-persist.patch
|
||||
|
||||
#rhbz 1250717
|
||||
ApplyPatch ext4-dont-manipulate-recovery-flag-when-freezing.patch
|
||||
|
||||
#CVE-2015-6666 rhbz 1256746 1256753
|
||||
ApplyPatch Revert-sched-x86_64-Don-t-save-flags-on-context-swit.patch
|
||||
|
||||
#rhbz 1256281
|
||||
ApplyPatch mmc-sdhci-fix-dma-memory-leak-in-sdhci_pre_req.patch
|
||||
|
||||
#rhbz 1224764
|
||||
ApplyPatch x86-apic-Fix-fallout-from-x2apic-cleanup.patch
|
||||
|
||||
#rhbz 1257534
|
||||
ApplyPatch nv46-Change-mc-subdev-oclass-from-nv44-to-nv4c.patch
|
||||
|
||||
#rhbz 1212201
|
||||
ApplyPatch drm-qxl-validate-monitors-config-modes.patch
|
||||
|
||||
#rhbz 1257500
|
||||
ApplyPatch vmwgfx-Rework-device-initialization.patch
|
||||
ApplyPatch drm-vmwgfx-Allow-dropped-masters-render-node-like-ac.patch
|
||||
|
||||
# END OF PATCH APPLICATIONS
|
||||
|
||||
|
@ -2297,26 +2320,84 @@ fi
|
|||
# and build.
|
||||
#
|
||||
%changelog
|
||||
* Sat Aug 01 2015 Pavel Alexeev <Pahan@Hubbitus.info> - 4.1.2-200.hu.2.pf1
|
||||
- Merge Fedora changes, but stay at 4.1.2 as PF patch is.
|
||||
* Fri Sep 04 2015 Laura Abbott <labbott@redhat.com> - 4.1.6-201
|
||||
- Tag and build
|
||||
|
||||
#* Wed Jul 29 2015 Laura Abbott <labbott@redhat.com> - 4.1.3-201
|
||||
#- tag and build for CVE fixes
|
||||
* Thu Aug 27 2015 Josh Boyer <jwboyer@fedoraproject.org>
|
||||
- Fix vmware driver issues from Thomas Hellström (rhbz 1227193)
|
||||
- Add patch from Hans de Goede to fix nv46 based cards (rhbz 1257534)
|
||||
- Add patch from Jonathon Jongsma to fix modes in qxl (rhbz 1212201)
|
||||
|
||||
#* Mon Jul 27 2015 Laura Abbott <labbott@fedoraproject.org>
|
||||
#- CVE-2015-3290 CVE-2015-3291 NMI issues (rhbz 1243465 1245927)
|
||||
* Wed Aug 26 2015 Peter Robinson <pbrobinson@fedoraproject.org>
|
||||
- Disable CRYPTO_DEV_VMX_ENCRYPT on PPC for now to fix Power 8 boot (rhbz 1237089)
|
||||
|
||||
#* Mon Jul 27 2015 Josh Boyer <jwboyer@fedoraproject.org>
|
||||
#- CVE-2015-1333 add_key memory leak (rhbz 1244171)
|
||||
* Tue Aug 25 2015 Laura Abbott <labbott@fedoraproject.org>
|
||||
- Fix x2apic refactoring breakage (rhbz 1224764)
|
||||
|
||||
#* Thu Jul 23 2015 Laura Abbott <labbott@fedoraproject.org>
|
||||
#- Fix warning from pcmcia (rhbz 1180920 1206724)
|
||||
* Tue Aug 25 2015 Laura Abbott <labbott@fedoraproject.org>
|
||||
- Correct the sdhci DMA leak patch to actually compile (oops)
|
||||
|
||||
#* Wed Jul 22 2015 Laura Abbott <labbott@fedoraproject.org> - 4.1.3-200
|
||||
#- Add patches for Ideapad RF switches (rhbz 1192270)
|
||||
* Tue Aug 25 2015 Laura Abbott <labbott@fedoraproject.org>
|
||||
- Fix DMA leak from sdhci (rhbz 1256281)
|
||||
|
||||
#* Wed Jul 22 2015 Laura Abbott <labbott@fedoraproject.org>
|
||||
#- Linux v4.1.3
|
||||
* Tue Aug 25 2015 Josh Boyer <jwboyer@fedoraproject.org>
|
||||
- CVE-2015-6666 x86_64 NT flag handling DoS (rhbz 1256746 1256753)
|
||||
|
||||
* Fri Aug 21 2015 Josh Boyer <jwboyer@fedoraproject.org>
|
||||
- Disable EFI_VARS (rhbz 1252137)
|
||||
|
||||
* Thu Aug 20 2015 Josh Boyer <jwboyer@fedoraproject.org>
|
||||
- Fix incorrect ext4 freezing behavior on non-journaled fs (rhbz 1250717)
|
||||
|
||||
* Mon Aug 17 2015 Laura Abbott <labbott@fedoraproject.org> - 4.1.6-200
|
||||
- Linux v4.1.6
|
||||
- Actually apply the fix for rhbz 1253789
|
||||
|
||||
* Mon Aug 17 2015 Josh Boyer <jwboyer@fedoraproject.org>
|
||||
- Fix iscsi issue (rhbz 1253789)
|
||||
|
||||
* Sat Aug 15 2015 Josh Boyer <jwboyer@fedoraproject.org>
|
||||
- Patch from Hans de Goede to add yoga 3 rfkill quirk (rhbz 1239050)
|
||||
|
||||
* Tue Aug 11 2015 Peter Robinson <pbrobinson@fedoraproject.org>
|
||||
- Drop UACCESS_WITH_MEMCPY on ARMv7 as it's broken (rhbz 1250613)
|
||||
|
||||
* Mon Aug 10 2015 Laura Abbott <labbott@fedoraproject.org> - 4.1.5-200
|
||||
- Linux v4.1.5
|
||||
|
||||
* Mon Aug 10 2015 Laura Abbott <labbott@fedoraproject.org>
|
||||
- Fix use after free in HID input (rhbz 1251877 1251880 1250279 1248741)
|
||||
|
||||
* Tue Aug 04 2015 Josh Boyer <jwboyer@fedoraproject.org>
|
||||
- Patch from Nicholas Kudriavtsev for Acer Switch 12 Fn keys (rhbz 1244511)
|
||||
|
||||
* Tue Aug 4 2015 Peter Robinson <pbrobinson@fedoraproject.org>
|
||||
- Back port AMD Seattle a0 4.1 NIC driver update
|
||||
|
||||
* Mon Aug 03 2015 Josh Boyer <jwboyer@fedoraproject.org> - 4.1.4-200
|
||||
- Linux v4.1.4
|
||||
- CVE-2015-5697 info leak in md driver (rhbz 1249011 1249013)
|
||||
|
||||
#* Sat Aug 01 2015 Pavel Alexeev <Pahan@Hubbitus.info> - 4.1.2-200.hu.2.pf1
|
||||
#- Merge Fedora changes, but stay at 4.1.2 as PF patch is.
|
||||
|
||||
* Wed Jul 29 2015 Laura Abbott <labbott@redhat.com> - 4.1.3-201
|
||||
- tag and build for CVE fixes
|
||||
|
||||
* Mon Jul 27 2015 Laura Abbott <labbott@fedoraproject.org>
|
||||
- CVE-2015-3290 CVE-2015-3291 NMI issues (rhbz 1243465 1245927)
|
||||
|
||||
* Mon Jul 27 2015 Josh Boyer <jwboyer@fedoraproject.org>
|
||||
- CVE-2015-1333 add_key memory leak (rhbz 1244171)
|
||||
|
||||
* Thu Jul 23 2015 Laura Abbott <labbott@fedoraproject.org>
|
||||
- Fix warning from pcmcia (rhbz 1180920 1206724)
|
||||
|
||||
* Wed Jul 22 2015 Laura Abbott <labbott@fedoraproject.org> - 4.1.3-200
|
||||
- Add patches for Ideapad RF switches (rhbz 1192270)
|
||||
|
||||
* Wed Jul 22 2015 Laura Abbott <labbott@fedoraproject.org>
|
||||
- Linux v4.1.3
|
||||
|
||||
* Sat Jul 18 2015 Pavel Alexeev <Pahan@Hubbitus.info> - 4.1.2-200.hu.1.pf1
|
||||
- Linux 4.1.2
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
From: Paolo Bonzini <pbonzini@redhat.com>
|
||||
Date: Thu, 4 Jun 2015 10:18:22 +0200
|
||||
Subject: [PATCH] kvm: x86: fix kvm_apic_has_events to check for NULL pointer
|
||||
|
||||
Malicious (or egregiously buggy) userspace can trigger it, but it
|
||||
should never happen in normal operation.
|
||||
|
||||
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||||
---
|
||||
arch/x86/kvm/lapic.h | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
|
||||
index 0bc6c656625b..ca4f92d56e16 100644
|
||||
--- a/arch/x86/kvm/lapic.h
|
||||
+++ b/arch/x86/kvm/lapic.h
|
||||
@@ -165,7 +165,7 @@ static inline u16 apic_logical_id(struct kvm_apic_map *map, u32 ldr)
|
||||
|
||||
static inline bool kvm_apic_has_events(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
- return vcpu->arch.apic->pending_events;
|
||||
+ return kvm_vcpu_has_lapic(vcpu) && vcpu->arch.apic->pending_events;
|
||||
}
|
||||
|
||||
bool kvm_apic_pending_eoi(struct kvm_vcpu *vcpu, int vector);
|
|
@ -1,53 +0,0 @@
|
|||
From: Thomas Reitmayr <treitmayr@devbase.at>
|
||||
Date: Fri, 1 May 2015 20:18:04 -0300
|
||||
Subject: [PATCH] media: Fix regression in some more dib0700 based devices
|
||||
|
||||
Fix an oops during device initialization by correctly setting size_of_priv
|
||||
instead of leaving it 0.
|
||||
The regression was introduced by 8abe4a0a3f6d4217b16a ("[media] dib7000:
|
||||
export just one symbol") and only fixed for one type of dib0700 based
|
||||
devices in 9e334c75642b6e5bfb95 ("[media] Fix regression in some dib0700
|
||||
based devices").
|
||||
|
||||
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=92301
|
||||
|
||||
Fixes: 8abe4a0a3f6d4217b16a ("[media] dib7000: export just one symbol")
|
||||
|
||||
Cc: stable@vger.kernel.org # for version 3.17+
|
||||
Signed-off-by: Thomas Reitmayr <treitmayr@devbase.at>
|
||||
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
|
||||
---
|
||||
drivers/media/usb/dvb-usb/dib0700_devices.c | 6 ++++++
|
||||
1 file changed, 6 insertions(+)
|
||||
|
||||
diff --git a/drivers/media/usb/dvb-usb/dib0700_devices.c b/drivers/media/usb/dvb-usb/dib0700_devices.c
|
||||
index e1757b8f5f5d..6aa4e9f4e441 100644
|
||||
--- a/drivers/media/usb/dvb-usb/dib0700_devices.c
|
||||
+++ b/drivers/media/usb/dvb-usb/dib0700_devices.c
|
||||
@@ -3947,6 +3947,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
||||
|
||||
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
|
||||
}},
|
||||
+ .size_of_priv = sizeof(struct
|
||||
+ dib0700_adapter_state),
|
||||
}, {
|
||||
.num_frontends = 1,
|
||||
.fe = {{
|
||||
@@ -3959,6 +3961,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
||||
|
||||
DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
|
||||
}},
|
||||
+ .size_of_priv = sizeof(struct
|
||||
+ dib0700_adapter_state),
|
||||
}
|
||||
},
|
||||
|
||||
@@ -4012,6 +4016,8 @@ struct dvb_usb_device_properties dib0700_devices[] = {
|
||||
|
||||
DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
|
||||
}},
|
||||
+ .size_of_priv = sizeof(struct
|
||||
+ dib0700_adapter_state),
|
||||
},
|
||||
},
|
||||
|
|
@ -0,0 +1,223 @@
|
|||
From 5b942146e110c49f52bbaa034273b3affd787dfb Mon Sep 17 00:00:00 2001
|
||||
From: Haibo Chen <haibo.chen@freescale.com>
|
||||
Date: Tue, 25 Aug 2015 10:02:11 +0800
|
||||
Subject: [PATCH] mmc: sdhci: fix dma memory leak in sdhci_pre_req()
|
||||
|
||||
Currently one mrq->data maybe execute dma_map_sg() twice
|
||||
when mmc subsystem prepare over one new request, and the
|
||||
following log show up:
|
||||
sdhci[sdhci_pre_dma_transfer] invalid cookie: 24, next-cookie 25
|
||||
|
||||
In this condition, mrq->date map a dma-memory(1) in sdhci_pre_req
|
||||
for the first time, and map another dma-memory(2) in sdhci_prepare_data
|
||||
for the second time. But driver only unmap the dma-memory(2), and
|
||||
dma-memory(1) never unmapped, which cause the dma memory leak issue.
|
||||
|
||||
This patch use another method to map the dma memory for the mrq->data
|
||||
which can fix this dma memory leak issue.
|
||||
|
||||
Fixes: commit 348487cb28e66b0 ("mmc: sdhci: use pipeline mmc requests to improve performance")
|
||||
Cc: stable@vger.kernel.org # 4.0+
|
||||
Reported-and-tested-by: Jiri Slaby <jslaby@suse.cz>
|
||||
Signed-off-by: Haibo Chen <haibo.chen@freescale.com>
|
||||
[labbott@redhat.com: Add extra mmc field for compilation]
|
||||
Signed-off-by: Laura Abbott <labbott@redhat.com>
|
||||
|
||||
---
|
||||
drivers/mmc/host/sdhci.c | 67 ++++++++++++++++++------------------------------
|
||||
drivers/mmc/host/sdhci.h | 8 +++---
|
||||
include/linux/mmc/core.h | 1 +
|
||||
3 files changed, 30 insertions(+), 46 deletions(-)
|
||||
|
||||
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
|
||||
index bec8a30..ef5b604 100644
|
||||
--- a/drivers/mmc/host/sdhci.c
|
||||
+++ b/drivers/mmc/host/sdhci.c
|
||||
@@ -55,8 +55,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode);
|
||||
static void sdhci_tuning_timer(unsigned long data);
|
||||
static void sdhci_enable_preset_value(struct sdhci_host *host, bool enable);
|
||||
static int sdhci_pre_dma_transfer(struct sdhci_host *host,
|
||||
- struct mmc_data *data,
|
||||
- struct sdhci_host_next *next);
|
||||
+ struct mmc_data *data);
|
||||
static int sdhci_do_get_cd(struct sdhci_host *host);
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
@@ -510,7 +509,7 @@ static int sdhci_adma_table_pre(struct sdhci_host *host,
|
||||
goto fail;
|
||||
BUG_ON(host->align_addr & host->align_mask);
|
||||
|
||||
- host->sg_count = sdhci_pre_dma_transfer(host, data, NULL);
|
||||
+ host->sg_count = sdhci_pre_dma_transfer(host, data);
|
||||
if (host->sg_count < 0)
|
||||
goto unmap_align;
|
||||
|
||||
@@ -649,9 +648,11 @@ static void sdhci_adma_table_post(struct sdhci_host *host,
|
||||
}
|
||||
}
|
||||
|
||||
- if (!data->host_cookie)
|
||||
+ if (data->host_cookie == COOKIE_MAPPED) {
|
||||
dma_unmap_sg(mmc_dev(host->mmc), data->sg,
|
||||
data->sg_len, direction);
|
||||
+ data->host_cookie = COOKIE_UNMAPPED;
|
||||
+ }
|
||||
}
|
||||
|
||||
static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_command *cmd)
|
||||
@@ -847,7 +848,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_command *cmd)
|
||||
} else {
|
||||
int sg_cnt;
|
||||
|
||||
- sg_cnt = sdhci_pre_dma_transfer(host, data, NULL);
|
||||
+ sg_cnt = sdhci_pre_dma_transfer(host, data);
|
||||
if (sg_cnt <= 0) {
|
||||
/*
|
||||
* This only happens when someone fed
|
||||
@@ -963,11 +964,13 @@ static void sdhci_finish_data(struct sdhci_host *host)
|
||||
if (host->flags & SDHCI_USE_ADMA)
|
||||
sdhci_adma_table_post(host, data);
|
||||
else {
|
||||
- if (!data->host_cookie)
|
||||
+ if (data->host_cookie == COOKIE_MAPPED) {
|
||||
dma_unmap_sg(mmc_dev(host->mmc),
|
||||
data->sg, data->sg_len,
|
||||
(data->flags & MMC_DATA_READ) ?
|
||||
DMA_FROM_DEVICE : DMA_TO_DEVICE);
|
||||
+ data->host_cookie = COOKIE_UNMAPPED;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2129,49 +2132,36 @@ static void sdhci_post_req(struct mmc_host *mmc, struct mmc_request *mrq,
|
||||
struct mmc_data *data = mrq->data;
|
||||
|
||||
if (host->flags & SDHCI_REQ_USE_DMA) {
|
||||
- if (data->host_cookie)
|
||||
+ if (data->host_cookie == COOKIE_GIVEN ||
|
||||
+ data->host_cookie == COOKIE_MAPPED)
|
||||
dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
|
||||
data->flags & MMC_DATA_WRITE ?
|
||||
DMA_TO_DEVICE : DMA_FROM_DEVICE);
|
||||
- mrq->data->host_cookie = 0;
|
||||
+ data->host_cookie = COOKIE_UNMAPPED;
|
||||
}
|
||||
}
|
||||
|
||||
static int sdhci_pre_dma_transfer(struct sdhci_host *host,
|
||||
- struct mmc_data *data,
|
||||
- struct sdhci_host_next *next)
|
||||
+ struct mmc_data *data)
|
||||
{
|
||||
int sg_count;
|
||||
|
||||
- if (!next && data->host_cookie &&
|
||||
- data->host_cookie != host->next_data.cookie) {
|
||||
- pr_debug(DRIVER_NAME "[%s] invalid cookie: %d, next-cookie %d\n",
|
||||
- __func__, data->host_cookie, host->next_data.cookie);
|
||||
- data->host_cookie = 0;
|
||||
+ if (data->host_cookie == COOKIE_MAPPED) {
|
||||
+ data->host_cookie = COOKIE_GIVEN;
|
||||
+ return data->sg_count;
|
||||
}
|
||||
|
||||
- /* Check if next job is already prepared */
|
||||
- if (next ||
|
||||
- (!next && data->host_cookie != host->next_data.cookie)) {
|
||||
- sg_count = dma_map_sg(mmc_dev(host->mmc), data->sg,
|
||||
- data->sg_len,
|
||||
- data->flags & MMC_DATA_WRITE ?
|
||||
- DMA_TO_DEVICE : DMA_FROM_DEVICE);
|
||||
-
|
||||
- } else {
|
||||
- sg_count = host->next_data.sg_count;
|
||||
- host->next_data.sg_count = 0;
|
||||
- }
|
||||
+ WARN_ON(data->host_cookie == COOKIE_GIVEN);
|
||||
|
||||
+ sg_count = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len,
|
||||
+ data->flags & MMC_DATA_WRITE ?
|
||||
+ DMA_TO_DEVICE : DMA_FROM_DEVICE);
|
||||
|
||||
if (sg_count == 0)
|
||||
- return -EINVAL;
|
||||
+ return -ENOSPC;
|
||||
|
||||
- if (next) {
|
||||
- next->sg_count = sg_count;
|
||||
- data->host_cookie = ++next->cookie < 0 ? 1 : next->cookie;
|
||||
- } else
|
||||
- host->sg_count = sg_count;
|
||||
+ data->sg_count = sg_count;
|
||||
+ data->host_cookie = COOKIE_MAPPED;
|
||||
|
||||
return sg_count;
|
||||
}
|
||||
@@ -2181,16 +2171,10 @@ static void sdhci_pre_req(struct mmc_host *mmc, struct mmc_request *mrq,
|
||||
{
|
||||
struct sdhci_host *host = mmc_priv(mmc);
|
||||
|
||||
- if (mrq->data->host_cookie) {
|
||||
- mrq->data->host_cookie = 0;
|
||||
- return;
|
||||
- }
|
||||
+ mrq->data->host_cookie = COOKIE_UNMAPPED;
|
||||
|
||||
if (host->flags & SDHCI_REQ_USE_DMA)
|
||||
- if (sdhci_pre_dma_transfer(host,
|
||||
- mrq->data,
|
||||
- &host->next_data) < 0)
|
||||
- mrq->data->host_cookie = 0;
|
||||
+ sdhci_pre_dma_transfer(host, mrq->data);
|
||||
}
|
||||
|
||||
static void sdhci_card_event(struct mmc_host *mmc)
|
||||
@@ -3088,7 +3072,6 @@ int sdhci_add_host(struct sdhci_host *host)
|
||||
host->max_clk = host->ops->get_max_clock(host);
|
||||
}
|
||||
|
||||
- host->next_data.cookie = 1;
|
||||
/*
|
||||
* In case of Host Controller v3.00, find out whether clock
|
||||
* multiplier is supported.
|
||||
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h
|
||||
index e639b7f..eea23f6 100644
|
||||
--- a/drivers/mmc/host/sdhci.h
|
||||
+++ b/drivers/mmc/host/sdhci.h
|
||||
@@ -309,9 +309,10 @@ struct sdhci_adma2_64_desc {
|
||||
*/
|
||||
#define SDHCI_MAX_SEGS 128
|
||||
|
||||
-struct sdhci_host_next {
|
||||
- unsigned int sg_count;
|
||||
- s32 cookie;
|
||||
+enum sdhci_cookie {
|
||||
+ COOKIE_UNMAPPED,
|
||||
+ COOKIE_MAPPED,
|
||||
+ COOKIE_GIVEN,
|
||||
};
|
||||
|
||||
struct sdhci_host {
|
||||
@@ -506,7 +507,6 @@ struct sdhci_host {
|
||||
#define SDHCI_TUNING_MODE_1 0
|
||||
struct timer_list tuning_timer; /* Timer for tuning */
|
||||
|
||||
- struct sdhci_host_next next_data;
|
||||
unsigned long private[0] ____cacheline_aligned;
|
||||
};
|
||||
|
||||
diff --git a/include/linux/mmc/core.h b/include/linux/mmc/core.h
|
||||
index de722d4e..258daf9 100644
|
||||
--- a/include/linux/mmc/core.h
|
||||
+++ b/include/linux/mmc/core.h
|
||||
@@ -121,6 +121,7 @@ struct mmc_data {
|
||||
struct mmc_request *mrq; /* associated request */
|
||||
|
||||
unsigned int sg_len; /* size of scatter list */
|
||||
+ int sg_count; /* mapped sg entries */
|
||||
struct scatterlist *sg; /* I/O scatter list */
|
||||
s32 host_cookie; /* host private data */
|
||||
};
|
||||
--
|
||||
2.4.3
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
From 16f4f5f0dc33698b841bce71cbc0dd991935b7e1 Mon Sep 17 00:00:00 2001
|
||||
From: Hans de Goede <hdegoede@redhat.com>
|
||||
Date: Thu, 23 Jul 2015 17:20:12 +0200
|
||||
Subject: [PATCH] nv46: Change mc subdev oclass from nv44 to nv4c
|
||||
|
||||
MSI interrupts appear to not work for nv46 based cards. Change the mc
|
||||
subdev oclass for these cards from nv44 to nv4c, the nv4c mc code is
|
||||
identical to the nv44 mc code except that it does not use msi
|
||||
(it does not define a msi_rearm callback).
|
||||
|
||||
BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=90435
|
||||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||||
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
|
||||
---
|
||||
drivers/gpu/drm/nouveau/nvkm/engine/device/nv40.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/nv40.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/nv40.c
|
||||
index c6301361d14f..b4ad791b4851 100644
|
||||
--- a/drivers/gpu/drm/nouveau/nvkm/engine/device/nv40.c
|
||||
+++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/nv40.c
|
||||
@@ -265,7 +265,7 @@ nv40_identify(struct nvkm_device *device)
|
||||
device->oclass[NVDEV_SUBDEV_CLK ] = &nv40_clk_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_THERM ] = &nv40_therm_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_DEVINIT] = nv1a_devinit_oclass;
|
||||
- device->oclass[NVDEV_SUBDEV_MC ] = nv44_mc_oclass;
|
||||
+ device->oclass[NVDEV_SUBDEV_MC ] = nv4c_mc_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_BUS ] = nv31_bus_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_TIMER ] = &nv04_timer_oclass;
|
||||
device->oclass[NVDEV_SUBDEV_FB ] = nv46_fb_oclass;
|
||||
--
|
||||
2.4.3
|
||||
|
2
sources
2
sources
|
@ -1,3 +1,3 @@
|
|||
fe9dc0f6729f36400ea81aa41d614c37 linux-4.1.tar.xz
|
||||
5b4d0e18c713a479a7b4c1aa53a7432b perf-man-4.1.tar.gz
|
||||
6a388f552b05243ae4165735da839e24 patch-4.1.3.xz
|
||||
7dea69f02c906206f88df48085069eb6 patch-4.1.6.xz
|
||||
|
|
|
@ -0,0 +1,890 @@
|
|||
From c1d9b32d8ee2e97e2867fa759eb84d436cca0311 Mon Sep 17 00:00:00 2001
|
||||
From: Thomas Hellstrom <thellstrom@vmware.com>
|
||||
Date: Thu, 25 Jun 2015 10:47:43 -0700
|
||||
Subject: [PATCH 1/2] vmwgfx: Rework device initialization
|
||||
|
||||
This commit reworks device initialization so that we always enable the
|
||||
FIFO at driver load, deferring SVGA enable until either first modeset
|
||||
or fbdev enable.
|
||||
This should always leave the fifo properly enabled for render- and
|
||||
control nodes.
|
||||
In addition,
|
||||
*) We disable the use of VRAM when SVGA is not enabled.
|
||||
*) We simplify PM support so that we only throw out resources on hibernate,
|
||||
not on suspend, since the device keeps its state on suspend.
|
||||
|
||||
Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
|
||||
Reviewed-by: Sinclair Yeh <syeh@vmware.com>
|
||||
---
|
||||
drivers/gpu/drm/vmwgfx/vmwgfx_context.c | 8 +-
|
||||
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 337 ++++++++++++++++++--------------
|
||||
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 19 +-
|
||||
drivers/gpu/drm/vmwgfx/vmwgfx_fb.c | 4 +
|
||||
drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c | 12 +-
|
||||
drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 1 +
|
||||
drivers/gpu/drm/vmwgfx/vmwgfx_mob.c | 6 +-
|
||||
drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 1 +
|
||||
drivers/gpu/drm/vmwgfx/vmwgfx_shader.c | 4 +-
|
||||
drivers/gpu/drm/vmwgfx/vmwgfx_surface.c | 12 +-
|
||||
10 files changed, 230 insertions(+), 174 deletions(-)
|
||||
|
||||
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_context.c b/drivers/gpu/drm/vmwgfx/vmwgfx_context.c
|
||||
index 5ac92874404d..a8e370a55e90 100644
|
||||
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_context.c
|
||||
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_context.c
|
||||
@@ -140,7 +140,7 @@ static void vmw_hw_context_destroy(struct vmw_resource *res)
|
||||
cmd->body.cid = cpu_to_le32(res->id);
|
||||
|
||||
vmw_fifo_commit(dev_priv, sizeof(*cmd));
|
||||
- vmw_3d_resource_dec(dev_priv, false);
|
||||
+ vmw_fifo_resource_dec(dev_priv);
|
||||
}
|
||||
|
||||
static int vmw_gb_context_init(struct vmw_private *dev_priv,
|
||||
@@ -220,7 +220,7 @@ static int vmw_context_init(struct vmw_private *dev_priv,
|
||||
cmd->body.cid = cpu_to_le32(res->id);
|
||||
|
||||
vmw_fifo_commit(dev_priv, sizeof(*cmd));
|
||||
- (void) vmw_3d_resource_inc(dev_priv, false);
|
||||
+ vmw_fifo_resource_inc(dev_priv);
|
||||
vmw_resource_activate(res, vmw_hw_context_destroy);
|
||||
return 0;
|
||||
|
||||
@@ -281,7 +281,7 @@ static int vmw_gb_context_create(struct vmw_resource *res)
|
||||
cmd->header.size = sizeof(cmd->body);
|
||||
cmd->body.cid = res->id;
|
||||
vmw_fifo_commit(dev_priv, sizeof(*cmd));
|
||||
- (void) vmw_3d_resource_inc(dev_priv, false);
|
||||
+ vmw_fifo_resource_inc(dev_priv);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -414,7 +414,7 @@ static int vmw_gb_context_destroy(struct vmw_resource *res)
|
||||
if (dev_priv->query_cid == res->id)
|
||||
dev_priv->query_cid_valid = false;
|
||||
vmw_resource_release_id(res);
|
||||
- vmw_3d_resource_dec(dev_priv, false);
|
||||
+ vmw_fifo_resource_dec(dev_priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
|
||||
index 620bb5cf617c..a4766acd0ea2 100644
|
||||
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
|
||||
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
|
||||
@@ -339,24 +339,47 @@ static int vmw_dummy_query_bo_create(struct vmw_private *dev_priv)
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static int vmw_request_device(struct vmw_private *dev_priv)
|
||||
+/**
|
||||
+ * vmw_request_device_late - Perform late device setup
|
||||
+ *
|
||||
+ * @dev_priv: Pointer to device private.
|
||||
+ *
|
||||
+ * This function performs setup of otables and enables large command
|
||||
+ * buffer submission. These tasks are split out to a separate function
|
||||
+ * because it reverts vmw_release_device_early and is intended to be used
|
||||
+ * by an error path in the hibernation code.
|
||||
+ */
|
||||
+static int vmw_request_device_late(struct vmw_private *dev_priv)
|
||||
{
|
||||
int ret;
|
||||
|
||||
- ret = vmw_fifo_init(dev_priv, &dev_priv->fifo);
|
||||
- if (unlikely(ret != 0)) {
|
||||
- DRM_ERROR("Unable to initialize FIFO.\n");
|
||||
- return ret;
|
||||
- }
|
||||
- vmw_fence_fifo_up(dev_priv->fman);
|
||||
if (dev_priv->has_mob) {
|
||||
ret = vmw_otables_setup(dev_priv);
|
||||
if (unlikely(ret != 0)) {
|
||||
DRM_ERROR("Unable to initialize "
|
||||
"guest Memory OBjects.\n");
|
||||
- goto out_no_mob;
|
||||
+ return ret;
|
||||
}
|
||||
}
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int vmw_request_device(struct vmw_private *dev_priv)
|
||||
+{
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = vmw_fifo_init(dev_priv, &dev_priv->fifo);
|
||||
+ if (unlikely(ret != 0)) {
|
||||
+ DRM_ERROR("Unable to initialize FIFO.\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+ vmw_fence_fifo_up(dev_priv->fman);
|
||||
+
|
||||
+ ret = vmw_request_device_late(dev_priv);
|
||||
+ if (ret)
|
||||
+ goto out_no_mob;
|
||||
+
|
||||
ret = vmw_dummy_query_bo_create(dev_priv);
|
||||
if (unlikely(ret != 0))
|
||||
goto out_no_query_bo;
|
||||
@@ -364,15 +387,25 @@ static int vmw_request_device(struct vmw_private *dev_priv)
|
||||
return 0;
|
||||
|
||||
out_no_query_bo:
|
||||
- if (dev_priv->has_mob)
|
||||
+ if (dev_priv->has_mob) {
|
||||
+ (void) ttm_bo_evict_mm(&dev_priv->bdev, VMW_PL_MOB);
|
||||
vmw_otables_takedown(dev_priv);
|
||||
+ }
|
||||
out_no_mob:
|
||||
vmw_fence_fifo_down(dev_priv->fman);
|
||||
vmw_fifo_release(dev_priv, &dev_priv->fifo);
|
||||
return ret;
|
||||
}
|
||||
|
||||
-static void vmw_release_device(struct vmw_private *dev_priv)
|
||||
+/**
|
||||
+ * vmw_release_device_early - Early part of fifo takedown.
|
||||
+ *
|
||||
+ * @dev_priv: Pointer to device private struct.
|
||||
+ *
|
||||
+ * This is the first part of command submission takedown, to be called before
|
||||
+ * buffer management is taken down.
|
||||
+ */
|
||||
+static void vmw_release_device_early(struct vmw_private *dev_priv)
|
||||
{
|
||||
/*
|
||||
* Previous destructions should've released
|
||||
@@ -382,64 +415,24 @@ static void vmw_release_device(struct vmw_private *dev_priv)
|
||||
BUG_ON(dev_priv->pinned_bo != NULL);
|
||||
|
||||
ttm_bo_unref(&dev_priv->dummy_query_bo);
|
||||
- if (dev_priv->has_mob)
|
||||
+ if (dev_priv->has_mob) {
|
||||
+ ttm_bo_evict_mm(&dev_priv->bdev, VMW_PL_MOB);
|
||||
vmw_otables_takedown(dev_priv);
|
||||
- vmw_fence_fifo_down(dev_priv->fman);
|
||||
- vmw_fifo_release(dev_priv, &dev_priv->fifo);
|
||||
-}
|
||||
-
|
||||
-
|
||||
-/**
|
||||
- * Increase the 3d resource refcount.
|
||||
- * If the count was prevously zero, initialize the fifo, switching to svga
|
||||
- * mode. Note that the master holds a ref as well, and may request an
|
||||
- * explicit switch to svga mode if fb is not running, using @unhide_svga.
|
||||
- */
|
||||
-int vmw_3d_resource_inc(struct vmw_private *dev_priv,
|
||||
- bool unhide_svga)
|
||||
-{
|
||||
- int ret = 0;
|
||||
-
|
||||
- mutex_lock(&dev_priv->release_mutex);
|
||||
- if (unlikely(dev_priv->num_3d_resources++ == 0)) {
|
||||
- ret = vmw_request_device(dev_priv);
|
||||
- if (unlikely(ret != 0))
|
||||
- --dev_priv->num_3d_resources;
|
||||
- } else if (unhide_svga) {
|
||||
- vmw_write(dev_priv, SVGA_REG_ENABLE,
|
||||
- vmw_read(dev_priv, SVGA_REG_ENABLE) &
|
||||
- ~SVGA_REG_ENABLE_HIDE);
|
||||
}
|
||||
-
|
||||
- mutex_unlock(&dev_priv->release_mutex);
|
||||
- return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
- * Decrease the 3d resource refcount.
|
||||
- * If the count reaches zero, disable the fifo, switching to vga mode.
|
||||
- * Note that the master holds a refcount as well, and may request an
|
||||
- * explicit switch to vga mode when it releases its refcount to account
|
||||
- * for the situation of an X server vt switch to VGA with 3d resources
|
||||
- * active.
|
||||
+ * vmw_release_device_late - Late part of fifo takedown.
|
||||
+ *
|
||||
+ * @dev_priv: Pointer to device private struct.
|
||||
+ *
|
||||
+ * This is the last part of the command submission takedown, to be called when
|
||||
+ * command submission is no longer needed. It may wait on pending fences.
|
||||
*/
|
||||
-void vmw_3d_resource_dec(struct vmw_private *dev_priv,
|
||||
- bool hide_svga)
|
||||
+static void vmw_release_device_late(struct vmw_private *dev_priv)
|
||||
{
|
||||
- int32_t n3d;
|
||||
-
|
||||
- mutex_lock(&dev_priv->release_mutex);
|
||||
- if (unlikely(--dev_priv->num_3d_resources == 0))
|
||||
- vmw_release_device(dev_priv);
|
||||
- else if (hide_svga)
|
||||
- vmw_write(dev_priv, SVGA_REG_ENABLE,
|
||||
- vmw_read(dev_priv, SVGA_REG_ENABLE) |
|
||||
- SVGA_REG_ENABLE_HIDE);
|
||||
-
|
||||
- n3d = (int32_t) dev_priv->num_3d_resources;
|
||||
- mutex_unlock(&dev_priv->release_mutex);
|
||||
-
|
||||
- BUG_ON(n3d < 0);
|
||||
+ vmw_fence_fifo_down(dev_priv->fman);
|
||||
+ vmw_fifo_release(dev_priv, &dev_priv->fifo);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -603,6 +596,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
|
||||
spin_lock_init(&dev_priv->hw_lock);
|
||||
spin_lock_init(&dev_priv->waiter_lock);
|
||||
spin_lock_init(&dev_priv->cap_lock);
|
||||
+ spin_lock_init(&dev_priv->svga_lock);
|
||||
|
||||
for (i = vmw_res_context; i < vmw_res_max; ++i) {
|
||||
idr_init(&dev_priv->res_idr[i]);
|
||||
@@ -714,17 +708,6 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
|
||||
dev_priv->active_master = &dev_priv->fbdev_master;
|
||||
|
||||
|
||||
- ret = ttm_bo_device_init(&dev_priv->bdev,
|
||||
- dev_priv->bo_global_ref.ref.object,
|
||||
- &vmw_bo_driver,
|
||||
- dev->anon_inode->i_mapping,
|
||||
- VMWGFX_FILE_PAGE_OFFSET,
|
||||
- false);
|
||||
- if (unlikely(ret != 0)) {
|
||||
- DRM_ERROR("Failed initializing TTM buffer object driver.\n");
|
||||
- goto out_err1;
|
||||
- }
|
||||
-
|
||||
dev_priv->mmio_mtrr = arch_phys_wc_add(dev_priv->mmio_start,
|
||||
dev_priv->mmio_size);
|
||||
|
||||
@@ -787,13 +770,28 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
|
||||
goto out_no_fman;
|
||||
}
|
||||
|
||||
+ ret = ttm_bo_device_init(&dev_priv->bdev,
|
||||
+ dev_priv->bo_global_ref.ref.object,
|
||||
+ &vmw_bo_driver,
|
||||
+ dev->anon_inode->i_mapping,
|
||||
+ VMWGFX_FILE_PAGE_OFFSET,
|
||||
+ false);
|
||||
+ if (unlikely(ret != 0)) {
|
||||
+ DRM_ERROR("Failed initializing TTM buffer object driver.\n");
|
||||
+ goto out_no_bdev;
|
||||
+ }
|
||||
|
||||
+ /*
|
||||
+ * Enable VRAM, but initially don't use it until SVGA is enabled and
|
||||
+ * unhidden.
|
||||
+ */
|
||||
ret = ttm_bo_init_mm(&dev_priv->bdev, TTM_PL_VRAM,
|
||||
(dev_priv->vram_size >> PAGE_SHIFT));
|
||||
if (unlikely(ret != 0)) {
|
||||
DRM_ERROR("Failed initializing memory manager for VRAM.\n");
|
||||
goto out_no_vram;
|
||||
}
|
||||
+ dev_priv->bdev.man[TTM_PL_VRAM].use_type = false;
|
||||
|
||||
dev_priv->has_gmr = true;
|
||||
if (((dev_priv->capabilities & (SVGA_CAP_GMR | SVGA_CAP_GMR2)) == 0) ||
|
||||
@@ -814,18 +812,18 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
|
||||
}
|
||||
}
|
||||
|
||||
- vmw_kms_save_vga(dev_priv);
|
||||
-
|
||||
- /* Start kms and overlay systems, needs fifo. */
|
||||
ret = vmw_kms_init(dev_priv);
|
||||
if (unlikely(ret != 0))
|
||||
goto out_no_kms;
|
||||
vmw_overlay_init(dev_priv);
|
||||
|
||||
+ ret = vmw_request_device(dev_priv);
|
||||
+ if (ret)
|
||||
+ goto out_no_fifo;
|
||||
+
|
||||
if (dev_priv->enable_fb) {
|
||||
- ret = vmw_3d_resource_inc(dev_priv, true);
|
||||
- if (unlikely(ret != 0))
|
||||
- goto out_no_fifo;
|
||||
+ vmw_fifo_resource_inc(dev_priv);
|
||||
+ vmw_svga_enable(dev_priv);
|
||||
vmw_fb_init(dev_priv);
|
||||
}
|
||||
|
||||
@@ -838,13 +836,14 @@ out_no_fifo:
|
||||
vmw_overlay_close(dev_priv);
|
||||
vmw_kms_close(dev_priv);
|
||||
out_no_kms:
|
||||
- vmw_kms_restore_vga(dev_priv);
|
||||
if (dev_priv->has_mob)
|
||||
(void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_MOB);
|
||||
if (dev_priv->has_gmr)
|
||||
(void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_GMR);
|
||||
(void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM);
|
||||
out_no_vram:
|
||||
+ (void)ttm_bo_device_release(&dev_priv->bdev);
|
||||
+out_no_bdev:
|
||||
vmw_fence_manager_takedown(dev_priv->fman);
|
||||
out_no_fman:
|
||||
if (dev_priv->capabilities & SVGA_CAP_IRQMASK)
|
||||
@@ -860,8 +859,6 @@ out_err4:
|
||||
iounmap(dev_priv->mmio_virt);
|
||||
out_err3:
|
||||
arch_phys_wc_del(dev_priv->mmio_mtrr);
|
||||
- (void)ttm_bo_device_release(&dev_priv->bdev);
|
||||
-out_err1:
|
||||
vmw_ttm_global_release(dev_priv);
|
||||
out_err0:
|
||||
for (i = vmw_res_context; i < vmw_res_max; ++i)
|
||||
@@ -883,18 +880,22 @@ static int vmw_driver_unload(struct drm_device *dev)
|
||||
vfree(dev_priv->ctx.cmd_bounce);
|
||||
if (dev_priv->enable_fb) {
|
||||
vmw_fb_close(dev_priv);
|
||||
- vmw_kms_restore_vga(dev_priv);
|
||||
- vmw_3d_resource_dec(dev_priv, false);
|
||||
+ vmw_fifo_resource_dec(dev_priv);
|
||||
+ vmw_svga_disable(dev_priv);
|
||||
}
|
||||
+
|
||||
vmw_kms_close(dev_priv);
|
||||
vmw_overlay_close(dev_priv);
|
||||
|
||||
- if (dev_priv->has_mob)
|
||||
- (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_MOB);
|
||||
if (dev_priv->has_gmr)
|
||||
(void)ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_GMR);
|
||||
(void)ttm_bo_clean_mm(&dev_priv->bdev, TTM_PL_VRAM);
|
||||
|
||||
+ vmw_release_device_early(dev_priv);
|
||||
+ if (dev_priv->has_mob)
|
||||
+ (void) ttm_bo_clean_mm(&dev_priv->bdev, VMW_PL_MOB);
|
||||
+ (void) ttm_bo_device_release(&dev_priv->bdev);
|
||||
+ vmw_release_device_late(dev_priv);
|
||||
vmw_fence_manager_takedown(dev_priv->fman);
|
||||
if (dev_priv->capabilities & SVGA_CAP_IRQMASK)
|
||||
drm_irq_uninstall(dev_priv->dev);
|
||||
@@ -1148,27 +1149,13 @@ static int vmw_master_set(struct drm_device *dev,
|
||||
struct vmw_master *vmaster = vmw_master(file_priv->master);
|
||||
int ret = 0;
|
||||
|
||||
- if (!dev_priv->enable_fb) {
|
||||
- ret = vmw_3d_resource_inc(dev_priv, true);
|
||||
- if (unlikely(ret != 0))
|
||||
- return ret;
|
||||
- vmw_kms_save_vga(dev_priv);
|
||||
- vmw_write(dev_priv, SVGA_REG_TRACES, 0);
|
||||
- }
|
||||
-
|
||||
if (active) {
|
||||
BUG_ON(active != &dev_priv->fbdev_master);
|
||||
ret = ttm_vt_lock(&active->lock, false, vmw_fp->tfile);
|
||||
if (unlikely(ret != 0))
|
||||
- goto out_no_active_lock;
|
||||
+ return ret;
|
||||
|
||||
ttm_lock_set_kill(&active->lock, true, SIGTERM);
|
||||
- ret = ttm_bo_evict_mm(&dev_priv->bdev, TTM_PL_VRAM);
|
||||
- if (unlikely(ret != 0)) {
|
||||
- DRM_ERROR("Unable to clean VRAM on "
|
||||
- "master drop.\n");
|
||||
- }
|
||||
-
|
||||
dev_priv->active_master = NULL;
|
||||
}
|
||||
|
||||
@@ -1182,14 +1169,6 @@ static int vmw_master_set(struct drm_device *dev,
|
||||
dev_priv->active_master = vmaster;
|
||||
|
||||
return 0;
|
||||
-
|
||||
-out_no_active_lock:
|
||||
- if (!dev_priv->enable_fb) {
|
||||
- vmw_kms_restore_vga(dev_priv);
|
||||
- vmw_3d_resource_dec(dev_priv, true);
|
||||
- vmw_write(dev_priv, SVGA_REG_TRACES, 1);
|
||||
- }
|
||||
- return ret;
|
||||
}
|
||||
|
||||
static void vmw_master_drop(struct drm_device *dev,
|
||||
@@ -1214,16 +1193,9 @@ static void vmw_master_drop(struct drm_device *dev,
|
||||
}
|
||||
|
||||
ttm_lock_set_kill(&vmaster->lock, false, SIGTERM);
|
||||
- vmw_execbuf_release_pinned_bo(dev_priv);
|
||||
|
||||
- if (!dev_priv->enable_fb) {
|
||||
- ret = ttm_bo_evict_mm(&dev_priv->bdev, TTM_PL_VRAM);
|
||||
- if (unlikely(ret != 0))
|
||||
- DRM_ERROR("Unable to clean VRAM on master drop.\n");
|
||||
- vmw_kms_restore_vga(dev_priv);
|
||||
- vmw_3d_resource_dec(dev_priv, true);
|
||||
- vmw_write(dev_priv, SVGA_REG_TRACES, 1);
|
||||
- }
|
||||
+ if (!dev_priv->enable_fb)
|
||||
+ vmw_svga_disable(dev_priv);
|
||||
|
||||
dev_priv->active_master = &dev_priv->fbdev_master;
|
||||
ttm_lock_set_kill(&dev_priv->fbdev_master.lock, false, SIGTERM);
|
||||
@@ -1233,6 +1205,74 @@ static void vmw_master_drop(struct drm_device *dev,
|
||||
vmw_fb_on(dev_priv);
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * __vmw_svga_enable - Enable SVGA mode, FIFO and use of VRAM.
|
||||
+ *
|
||||
+ * @dev_priv: Pointer to device private struct.
|
||||
+ * Needs the reservation sem to be held in non-exclusive mode.
|
||||
+ */
|
||||
+void __vmw_svga_enable(struct vmw_private *dev_priv)
|
||||
+{
|
||||
+ spin_lock(&dev_priv->svga_lock);
|
||||
+ if (!dev_priv->bdev.man[TTM_PL_VRAM].use_type) {
|
||||
+ vmw_write(dev_priv, SVGA_REG_ENABLE, SVGA_REG_ENABLE);
|
||||
+ dev_priv->bdev.man[TTM_PL_VRAM].use_type = true;
|
||||
+ }
|
||||
+ spin_unlock(&dev_priv->svga_lock);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * vmw_svga_enable - Enable SVGA mode, FIFO and use of VRAM.
|
||||
+ *
|
||||
+ * @dev_priv: Pointer to device private struct.
|
||||
+ */
|
||||
+void vmw_svga_enable(struct vmw_private *dev_priv)
|
||||
+{
|
||||
+ ttm_read_lock(&dev_priv->reservation_sem, false);
|
||||
+ __vmw_svga_enable(dev_priv);
|
||||
+ ttm_read_unlock(&dev_priv->reservation_sem);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * __vmw_svga_disable - Disable SVGA mode and use of VRAM.
|
||||
+ *
|
||||
+ * @dev_priv: Pointer to device private struct.
|
||||
+ * Needs the reservation sem to be held in exclusive mode.
|
||||
+ * Will not empty VRAM. VRAM must be emptied by caller.
|
||||
+ */
|
||||
+void __vmw_svga_disable(struct vmw_private *dev_priv)
|
||||
+{
|
||||
+ spin_lock(&dev_priv->svga_lock);
|
||||
+ if (dev_priv->bdev.man[TTM_PL_VRAM].use_type) {
|
||||
+ dev_priv->bdev.man[TTM_PL_VRAM].use_type = false;
|
||||
+ vmw_write(dev_priv, SVGA_REG_ENABLE,
|
||||
+ SVGA_REG_ENABLE_ENABLE_HIDE);
|
||||
+ }
|
||||
+ spin_unlock(&dev_priv->svga_lock);
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * vmw_svga_disable - Disable SVGA_MODE, and use of VRAM. Keep the fifo
|
||||
+ * running.
|
||||
+ *
|
||||
+ * @dev_priv: Pointer to device private struct.
|
||||
+ * Will empty VRAM.
|
||||
+ */
|
||||
+void vmw_svga_disable(struct vmw_private *dev_priv)
|
||||
+{
|
||||
+ ttm_write_lock(&dev_priv->reservation_sem, false);
|
||||
+ spin_lock(&dev_priv->svga_lock);
|
||||
+ if (dev_priv->bdev.man[TTM_PL_VRAM].use_type) {
|
||||
+ dev_priv->bdev.man[TTM_PL_VRAM].use_type = false;
|
||||
+ vmw_write(dev_priv, SVGA_REG_ENABLE,
|
||||
+ SVGA_REG_ENABLE_ENABLE_HIDE);
|
||||
+ spin_unlock(&dev_priv->svga_lock);
|
||||
+ if (ttm_bo_evict_mm(&dev_priv->bdev, TTM_PL_VRAM))
|
||||
+ DRM_ERROR("Failed evicting VRAM buffers.\n");
|
||||
+ } else
|
||||
+ spin_unlock(&dev_priv->svga_lock);
|
||||
+ ttm_write_unlock(&dev_priv->reservation_sem);
|
||||
+}
|
||||
|
||||
static void vmw_remove(struct pci_dev *pdev)
|
||||
{
|
||||
@@ -1250,21 +1290,21 @@ static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
|
||||
|
||||
switch (val) {
|
||||
case PM_HIBERNATION_PREPARE:
|
||||
- case PM_SUSPEND_PREPARE:
|
||||
ttm_suspend_lock(&dev_priv->reservation_sem);
|
||||
|
||||
- /**
|
||||
+ /*
|
||||
* This empties VRAM and unbinds all GMR bindings.
|
||||
* Buffer contents is moved to swappable memory.
|
||||
*/
|
||||
vmw_execbuf_release_pinned_bo(dev_priv);
|
||||
vmw_resource_evict_all(dev_priv);
|
||||
+ vmw_release_device_early(dev_priv);
|
||||
ttm_bo_swapout_all(&dev_priv->bdev);
|
||||
-
|
||||
+ vmw_fence_fifo_down(dev_priv->fman);
|
||||
break;
|
||||
case PM_POST_HIBERNATION:
|
||||
- case PM_POST_SUSPEND:
|
||||
case PM_POST_RESTORE:
|
||||
+ vmw_fence_fifo_up(dev_priv->fman);
|
||||
ttm_suspend_unlock(&dev_priv->reservation_sem);
|
||||
|
||||
break;
|
||||
@@ -1276,20 +1316,13 @@ static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val,
|
||||
return 0;
|
||||
}
|
||||
|
||||
-/**
|
||||
- * These might not be needed with the virtual SVGA device.
|
||||
- */
|
||||
-
|
||||
static int vmw_pci_suspend(struct pci_dev *pdev, pm_message_t state)
|
||||
{
|
||||
struct drm_device *dev = pci_get_drvdata(pdev);
|
||||
struct vmw_private *dev_priv = vmw_priv(dev);
|
||||
|
||||
- if (dev_priv->num_3d_resources != 0) {
|
||||
- DRM_INFO("Can't suspend or hibernate "
|
||||
- "while 3D resources are active.\n");
|
||||
+ if (dev_priv->refuse_hibernation)
|
||||
return -EBUSY;
|
||||
- }
|
||||
|
||||
pci_save_state(pdev);
|
||||
pci_disable_device(pdev);
|
||||
@@ -1321,56 +1354,62 @@ static int vmw_pm_resume(struct device *kdev)
|
||||
return vmw_pci_resume(pdev);
|
||||
}
|
||||
|
||||
-static int vmw_pm_prepare(struct device *kdev)
|
||||
+static int vmw_pm_freeze(struct device *kdev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(kdev);
|
||||
struct drm_device *dev = pci_get_drvdata(pdev);
|
||||
struct vmw_private *dev_priv = vmw_priv(dev);
|
||||
|
||||
- /**
|
||||
- * Release 3d reference held by fbdev and potentially
|
||||
- * stop fifo.
|
||||
- */
|
||||
dev_priv->suspended = true;
|
||||
if (dev_priv->enable_fb)
|
||||
- vmw_3d_resource_dec(dev_priv, true);
|
||||
-
|
||||
- if (dev_priv->num_3d_resources != 0) {
|
||||
-
|
||||
- DRM_INFO("Can't suspend or hibernate "
|
||||
- "while 3D resources are active.\n");
|
||||
+ vmw_fifo_resource_dec(dev_priv);
|
||||
|
||||
+ if (atomic_read(&dev_priv->num_fifo_resources) != 0) {
|
||||
+ DRM_ERROR("Can't hibernate while 3D resources are active.\n");
|
||||
if (dev_priv->enable_fb)
|
||||
- vmw_3d_resource_inc(dev_priv, true);
|
||||
+ vmw_fifo_resource_inc(dev_priv);
|
||||
+ WARN_ON(vmw_request_device_late(dev_priv));
|
||||
dev_priv->suspended = false;
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
+ if (dev_priv->enable_fb)
|
||||
+ __vmw_svga_disable(dev_priv);
|
||||
+
|
||||
+ vmw_release_device_late(dev_priv);
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static void vmw_pm_complete(struct device *kdev)
|
||||
+static int vmw_pm_restore(struct device *kdev)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(kdev);
|
||||
struct drm_device *dev = pci_get_drvdata(pdev);
|
||||
struct vmw_private *dev_priv = vmw_priv(dev);
|
||||
+ int ret;
|
||||
|
||||
vmw_write(dev_priv, SVGA_REG_ID, SVGA_ID_2);
|
||||
(void) vmw_read(dev_priv, SVGA_REG_ID);
|
||||
|
||||
- /**
|
||||
- * Reclaim 3d reference held by fbdev and potentially
|
||||
- * start fifo.
|
||||
- */
|
||||
if (dev_priv->enable_fb)
|
||||
- vmw_3d_resource_inc(dev_priv, false);
|
||||
+ vmw_fifo_resource_inc(dev_priv);
|
||||
+
|
||||
+ ret = vmw_request_device(dev_priv);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ if (dev_priv->enable_fb)
|
||||
+ __vmw_svga_enable(dev_priv);
|
||||
|
||||
dev_priv->suspended = false;
|
||||
+
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops vmw_pm_ops = {
|
||||
- .prepare = vmw_pm_prepare,
|
||||
- .complete = vmw_pm_complete,
|
||||
+ .freeze = vmw_pm_freeze,
|
||||
+ .thaw = vmw_pm_restore,
|
||||
+ .restore = vmw_pm_restore,
|
||||
.suspend = vmw_pm_suspend,
|
||||
.resume = vmw_pm_resume,
|
||||
};
|
||||
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
|
||||
index d26a6daa9719..a5f221eaf076 100644
|
||||
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
|
||||
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
|
||||
@@ -484,6 +484,7 @@ struct vmw_private {
|
||||
|
||||
bool stealth;
|
||||
bool enable_fb;
|
||||
+ spinlock_t svga_lock;
|
||||
|
||||
/**
|
||||
* Master management.
|
||||
@@ -493,9 +494,10 @@ struct vmw_private {
|
||||
struct vmw_master fbdev_master;
|
||||
struct notifier_block pm_nb;
|
||||
bool suspended;
|
||||
+ bool refuse_hibernation;
|
||||
|
||||
struct mutex release_mutex;
|
||||
- uint32_t num_3d_resources;
|
||||
+ atomic_t num_fifo_resources;
|
||||
|
||||
/*
|
||||
* Replace this with an rwsem as soon as we have down_xx_interruptible()
|
||||
@@ -587,8 +589,9 @@ static inline uint32_t vmw_read(struct vmw_private *dev_priv,
|
||||
return val;
|
||||
}
|
||||
|
||||
-int vmw_3d_resource_inc(struct vmw_private *dev_priv, bool unhide_svga);
|
||||
-void vmw_3d_resource_dec(struct vmw_private *dev_priv, bool hide_svga);
|
||||
+extern void vmw_svga_enable(struct vmw_private *dev_priv);
|
||||
+extern void vmw_svga_disable(struct vmw_private *dev_priv);
|
||||
+
|
||||
|
||||
/**
|
||||
* GMR utilities - vmwgfx_gmr.c
|
||||
@@ -1116,4 +1119,14 @@ static inline struct ttm_mem_global *vmw_mem_glob(struct vmw_private *dev_priv)
|
||||
{
|
||||
return (struct ttm_mem_global *) dev_priv->mem_global_ref.object;
|
||||
}
|
||||
+
|
||||
+static inline void vmw_fifo_resource_inc(struct vmw_private *dev_priv)
|
||||
+{
|
||||
+ atomic_inc(&dev_priv->num_fifo_resources);
|
||||
+}
|
||||
+
|
||||
+static inline void vmw_fifo_resource_dec(struct vmw_private *dev_priv)
|
||||
+{
|
||||
+ atomic_dec(&dev_priv->num_fifo_resources);
|
||||
+}
|
||||
#endif
|
||||
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
|
||||
index 0a474f391fad..0e062613a7db 100644
|
||||
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
|
||||
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c
|
||||
@@ -596,7 +596,10 @@ int vmw_fb_off(struct vmw_private *vmw_priv)
|
||||
|
||||
info = vmw_priv->fb_info;
|
||||
par = info->par;
|
||||
+ if (!par->bo_ptr)
|
||||
+ return 0;
|
||||
|
||||
+ vmw_kms_save_vga(vmw_priv);
|
||||
spin_lock_irqsave(&par->dirty.lock, flags);
|
||||
par->dirty.active = false;
|
||||
spin_unlock_irqrestore(&par->dirty.lock, flags);
|
||||
@@ -648,6 +651,7 @@ int vmw_fb_on(struct vmw_private *vmw_priv)
|
||||
spin_lock_irqsave(&par->dirty.lock, flags);
|
||||
par->dirty.active = true;
|
||||
spin_unlock_irqrestore(&par->dirty.lock, flags);
|
||||
+ vmw_kms_restore_vga(vmw_priv);
|
||||
|
||||
err_no_buffer:
|
||||
vmw_fb_set_par(info);
|
||||
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
|
||||
index 39f2b03888e7..cd5d9f3fe0e0 100644
|
||||
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
|
||||
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c
|
||||
@@ -98,7 +98,6 @@ int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
|
||||
__le32 __iomem *fifo_mem = dev_priv->mmio_virt;
|
||||
uint32_t max;
|
||||
uint32_t min;
|
||||
- uint32_t dummy;
|
||||
|
||||
fifo->static_buffer_size = VMWGFX_FIFO_STATIC_SIZE;
|
||||
fifo->static_buffer = vmalloc(fifo->static_buffer_size);
|
||||
@@ -112,10 +111,6 @@ int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
|
||||
mutex_init(&fifo->fifo_mutex);
|
||||
init_rwsem(&fifo->rwsem);
|
||||
|
||||
- /*
|
||||
- * Allow mapping the first page read-only to user-space.
|
||||
- */
|
||||
-
|
||||
DRM_INFO("width %d\n", vmw_read(dev_priv, SVGA_REG_WIDTH));
|
||||
DRM_INFO("height %d\n", vmw_read(dev_priv, SVGA_REG_HEIGHT));
|
||||
DRM_INFO("bpp %d\n", vmw_read(dev_priv, SVGA_REG_BITS_PER_PIXEL));
|
||||
@@ -123,7 +118,9 @@ int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
|
||||
dev_priv->enable_state = vmw_read(dev_priv, SVGA_REG_ENABLE);
|
||||
dev_priv->config_done_state = vmw_read(dev_priv, SVGA_REG_CONFIG_DONE);
|
||||
dev_priv->traces_state = vmw_read(dev_priv, SVGA_REG_TRACES);
|
||||
- vmw_write(dev_priv, SVGA_REG_ENABLE, 1);
|
||||
+
|
||||
+ vmw_write(dev_priv, SVGA_REG_ENABLE, SVGA_REG_ENABLE_ENABLE_HIDE);
|
||||
+ vmw_write(dev_priv, SVGA_REG_TRACES, 0);
|
||||
|
||||
min = 4;
|
||||
if (dev_priv->capabilities & SVGA_CAP_EXTENDED_FIFO)
|
||||
@@ -155,7 +152,8 @@ int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo)
|
||||
atomic_set(&dev_priv->marker_seq, dev_priv->last_read_seqno);
|
||||
iowrite32(dev_priv->last_read_seqno, fifo_mem + SVGA_FIFO_FENCE);
|
||||
vmw_marker_queue_init(&fifo->marker_queue);
|
||||
- return vmw_fifo_send_fence(dev_priv, &dummy);
|
||||
+
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
void vmw_fifo_ping_host(struct vmw_private *dev_priv, uint32_t reason)
|
||||
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
|
||||
index 5c289f748ab4..53579f278b63 100644
|
||||
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
|
||||
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
|
||||
@@ -280,6 +280,7 @@ static int vmw_ldu_crtc_set_config(struct drm_mode_set *set)
|
||||
}
|
||||
|
||||
vmw_fb_off(dev_priv);
|
||||
+ vmw_svga_enable(dev_priv);
|
||||
|
||||
crtc->primary->fb = fb;
|
||||
encoder->crtc = crtc;
|
||||
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c b/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c
|
||||
index 04a64b8cd3cd..f06d60f41fa7 100644
|
||||
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c
|
||||
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c
|
||||
@@ -574,7 +574,7 @@ void vmw_mob_unbind(struct vmw_private *dev_priv,
|
||||
vmw_fence_single_bo(bo, NULL);
|
||||
ttm_bo_unreserve(bo);
|
||||
}
|
||||
- vmw_3d_resource_dec(dev_priv, false);
|
||||
+ vmw_fifo_resource_dec(dev_priv);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -627,7 +627,7 @@ int vmw_mob_bind(struct vmw_private *dev_priv,
|
||||
mob->pt_level += VMW_MOBFMT_PTDEPTH_1 - SVGA3D_MOBFMT_PTDEPTH_1;
|
||||
}
|
||||
|
||||
- (void) vmw_3d_resource_inc(dev_priv, false);
|
||||
+ vmw_fifo_resource_inc(dev_priv);
|
||||
|
||||
cmd = vmw_fifo_reserve(dev_priv, sizeof(*cmd));
|
||||
if (unlikely(cmd == NULL)) {
|
||||
@@ -648,7 +648,7 @@ int vmw_mob_bind(struct vmw_private *dev_priv,
|
||||
return 0;
|
||||
|
||||
out_no_cmd_space:
|
||||
- vmw_3d_resource_dec(dev_priv, false);
|
||||
+ vmw_fifo_resource_dec(dev_priv);
|
||||
if (pt_set_up)
|
||||
ttm_bo_unref(&mob->pt_bo);
|
||||
|
||||
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
|
||||
index 7dc591d04d9a..9e8eb364a6ac 100644
|
||||
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
|
||||
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c
|
||||
@@ -332,6 +332,7 @@ static int vmw_sou_crtc_set_config(struct drm_mode_set *set)
|
||||
}
|
||||
|
||||
vmw_fb_off(dev_priv);
|
||||
+ vmw_svga_enable(dev_priv);
|
||||
|
||||
if (mode->hdisplay != crtc->mode.hdisplay ||
|
||||
mode->vdisplay != crtc->mode.vdisplay) {
|
||||
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
|
||||
index 6a4584a43aa6..6110a433ebfe 100644
|
||||
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
|
||||
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
|
||||
@@ -165,7 +165,7 @@ static int vmw_gb_shader_create(struct vmw_resource *res)
|
||||
cmd->body.type = shader->type;
|
||||
cmd->body.sizeInBytes = shader->size;
|
||||
vmw_fifo_commit(dev_priv, sizeof(*cmd));
|
||||
- (void) vmw_3d_resource_inc(dev_priv, false);
|
||||
+ vmw_fifo_resource_inc(dev_priv);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -275,7 +275,7 @@ static int vmw_gb_shader_destroy(struct vmw_resource *res)
|
||||
vmw_fifo_commit(dev_priv, sizeof(*cmd));
|
||||
mutex_unlock(&dev_priv->binding_mutex);
|
||||
vmw_resource_release_id(res);
|
||||
- vmw_3d_resource_dec(dev_priv, false);
|
||||
+ vmw_fifo_resource_dec(dev_priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
|
||||
index 4ecdbf3e59da..4d0c98edeb6a 100644
|
||||
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
|
||||
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
|
||||
@@ -340,7 +340,7 @@ static void vmw_hw_surface_destroy(struct vmw_resource *res)
|
||||
dev_priv->used_memory_size -= res->backup_size;
|
||||
mutex_unlock(&dev_priv->cmdbuf_mutex);
|
||||
}
|
||||
- vmw_3d_resource_dec(dev_priv, false);
|
||||
+ vmw_fifo_resource_dec(dev_priv);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -576,14 +576,14 @@ static int vmw_surface_init(struct vmw_private *dev_priv,
|
||||
|
||||
BUG_ON(res_free == NULL);
|
||||
if (!dev_priv->has_mob)
|
||||
- (void) vmw_3d_resource_inc(dev_priv, false);
|
||||
+ vmw_fifo_resource_inc(dev_priv);
|
||||
ret = vmw_resource_init(dev_priv, res, true, res_free,
|
||||
(dev_priv->has_mob) ? &vmw_gb_surface_func :
|
||||
&vmw_legacy_surface_func);
|
||||
|
||||
if (unlikely(ret != 0)) {
|
||||
if (!dev_priv->has_mob)
|
||||
- vmw_3d_resource_dec(dev_priv, false);
|
||||
+ vmw_fifo_resource_dec(dev_priv);
|
||||
res_free(res);
|
||||
return ret;
|
||||
}
|
||||
@@ -1028,7 +1028,7 @@ static int vmw_gb_surface_create(struct vmw_resource *res)
|
||||
if (likely(res->id != -1))
|
||||
return 0;
|
||||
|
||||
- (void) vmw_3d_resource_inc(dev_priv, false);
|
||||
+ vmw_fifo_resource_inc(dev_priv);
|
||||
ret = vmw_resource_alloc_id(res);
|
||||
if (unlikely(ret != 0)) {
|
||||
DRM_ERROR("Failed to allocate a surface id.\n");
|
||||
@@ -1068,7 +1068,7 @@ static int vmw_gb_surface_create(struct vmw_resource *res)
|
||||
out_no_fifo:
|
||||
vmw_resource_release_id(res);
|
||||
out_no_id:
|
||||
- vmw_3d_resource_dec(dev_priv, false);
|
||||
+ vmw_fifo_resource_dec(dev_priv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1213,7 +1213,7 @@ static int vmw_gb_surface_destroy(struct vmw_resource *res)
|
||||
vmw_fifo_commit(dev_priv, sizeof(*cmd));
|
||||
mutex_unlock(&dev_priv->binding_mutex);
|
||||
vmw_resource_release_id(res);
|
||||
- vmw_3d_resource_dec(dev_priv, false);
|
||||
+ vmw_fifo_resource_dec(dev_priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
--
|
||||
2.4.3
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
From a57e456a7b28431b55e407e5ab78ebd5b378d19e Mon Sep 17 00:00:00 2001
|
||||
From: Thomas Gleixner <tglx@linutronix.de>
|
||||
Date: Sat, 22 Aug 2015 16:41:17 +0200
|
||||
Subject: [PATCH] x86/apic: Fix fallout from x2apic cleanup
|
||||
|
||||
In the recent x2apic cleanup I got two things really wrong:
|
||||
1) The safety check in __disable_x2apic which allows the function to
|
||||
be called unconditionally is backwards. The check is there to
|
||||
prevent access to the apic MSR in case that the machine has no
|
||||
apic. Though right now it returns if the machine has an apic and
|
||||
therefor the disabling of x2apic is never invoked.
|
||||
|
||||
2) x2apic_disable() sets x2apic_mode to 0 after registering the local
|
||||
apic. That's wrong, because register_lapic_address() checks x2apic
|
||||
mode and therefor takes the wrong code path.
|
||||
|
||||
This results in boot failures on machines with x2apic preenabled by
|
||||
BIOS and can also lead to an fatal MSR access on machines without
|
||||
apic.
|
||||
|
||||
The solutions are simple:
|
||||
1) Correct the sanity check for apic availability
|
||||
2) Clear x2apic_mode _before_ calling register_lapic_address()
|
||||
|
||||
Fixes: 659006bf3ae3 'x86/x2apic: Split enable and setup function'
|
||||
Reported-and-tested-by: Javier Monteagudo <javiermon@gmail.com>
|
||||
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
|
||||
Link: https://bugzilla.redhat.com/show_bug.cgi?id=1224764
|
||||
Cc: stable@vger.kernel.org # 4.0+
|
||||
Cc: Laura Abbott <labbott@redhat.com>
|
||||
Cc: Jiang Liu <jiang.liu@linux.intel.com>
|
||||
Cc: Joerg Roedel <joro@8bytes.org>
|
||||
Cc: Tony Luck <tony.luck@intel.com>
|
||||
Cc: Borislav Petkov <bp@alien8.de>
|
||||
---
|
||||
arch/x86/kernel/apic/apic.c | 14 +++++++-------
|
||||
1 file changed, 7 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
|
||||
index dcb5285..cde732c 100644
|
||||
--- a/arch/x86/kernel/apic/apic.c
|
||||
+++ b/arch/x86/kernel/apic/apic.c
|
||||
@@ -1424,7 +1424,7 @@ static inline void __x2apic_disable(void)
|
||||
{
|
||||
u64 msr;
|
||||
|
||||
- if (cpu_has_apic)
|
||||
+ if (!cpu_has_apic)
|
||||
return;
|
||||
|
||||
rdmsrl(MSR_IA32_APICBASE, msr);
|
||||
@@ -1483,10 +1483,13 @@ void x2apic_setup(void)
|
||||
|
||||
static __init void x2apic_disable(void)
|
||||
{
|
||||
- u32 x2apic_id;
|
||||
+ u32 x2apic_id, state = x2apic_state;
|
||||
|
||||
- if (x2apic_state != X2APIC_ON)
|
||||
- goto out;
|
||||
+ x2apic_mode = 0;
|
||||
+ x2apic_state = X2APIC_DISABLED;
|
||||
+
|
||||
+ if (state != X2APIC_ON)
|
||||
+ return;
|
||||
|
||||
x2apic_id = read_apic_id();
|
||||
if (x2apic_id >= 255)
|
||||
@@ -1494,9 +1497,6 @@ static __init void x2apic_disable(void)
|
||||
|
||||
__x2apic_disable();
|
||||
register_lapic_address(mp_lapic_addr);
|
||||
-out:
|
||||
- x2apic_state = X2APIC_DISABLED;
|
||||
- x2apic_mode = 0;
|
||||
}
|
||||
|
||||
static __init void x2apic_enable(void)
|
||||
--
|
||||
2.4.3
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
From 480ea71e661b2a48a8d28ea4327cafa666c267ff Mon Sep 17 00:00:00 2001
|
||||
From: Andy Lutomirski <luto@kernel.org>
|
||||
Date: Thu, 4 Jun 2015 13:24:29 -0700
|
||||
Subject: [PATCH 1/7] x86/asm/entry/64: Remove pointless jump to irq_return
|
||||
|
||||
INTERRUPT_RETURN turns into a jmp instruction. There's no need
|
||||
for extra indirection.
|
||||
|
||||
Signed-off-by: Andy Lutomirski <luto@kernel.org>
|
||||
Cc: <linux-kernel@vger.kernel.org>
|
||||
Cc: Andrew Morton <akpm@linux-foundation.org>
|
||||
Cc: Andy Lutomirski <luto@amacapital.net>
|
||||
Cc: Borislav Petkov <bp@alien8.de>
|
||||
Cc: Brian Gerst <brgerst@gmail.com>
|
||||
Cc: Denys Vlasenko <dvlasenk@redhat.com>
|
||||
Cc: H. Peter Anvin <hpa@zytor.com>
|
||||
Cc: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
Cc: Peter Zijlstra <peterz@infradead.org>
|
||||
Cc: Thomas Gleixner <tglx@linutronix.de>
|
||||
Link: http://lkml.kernel.org/r/2f2318653dbad284a59311f13f08cea71298fd7c.1433449436.git.luto@kernel.org
|
||||
Signed-off-by: Ingo Molnar <mingo@kernel.org>
|
||||
---
|
||||
arch/x86/kernel/entry_64.S | 4 +---
|
||||
1 file changed, 1 insertion(+), 3 deletions(-)
|
||||
|
||||
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
|
||||
index 02c2eff..b32f346 100644
|
||||
--- a/arch/x86/kernel/entry_64.S
|
||||
+++ b/arch/x86/kernel/entry_64.S
|
||||
@@ -793,8 +793,6 @@ retint_kernel:
|
||||
restore_c_regs_and_iret:
|
||||
RESTORE_C_REGS
|
||||
REMOVE_PT_GPREGS_FROM_STACK 8
|
||||
-
|
||||
-irq_return:
|
||||
INTERRUPT_RETURN
|
||||
|
||||
ENTRY(native_iret)
|
||||
@@ -1640,7 +1638,7 @@ nmi_restore:
|
||||
|
||||
/* Clear the NMI executing stack variable */
|
||||
movq $0, 5*8(%rsp)
|
||||
- jmp irq_return
|
||||
+ INTERRUPT_RETURN
|
||||
CFI_ENDPROC
|
||||
END(nmi)
|
||||
|
||||
--
|
||||
2.4.3
|
||||
|
|
@ -1,129 +0,0 @@
|
|||
From e154db431700ef8e9a29c0e88fa8a11b8dc8fc1e Mon Sep 17 00:00:00 2001
|
||||
From: Denys Vlasenko <dvlasenk@redhat.com>
|
||||
Date: Fri, 24 Apr 2015 17:31:35 +0200
|
||||
Subject: [PATCH 3/9] x86/entry: Define 'cpu_current_top_of_stack' for 64-bit
|
||||
code
|
||||
|
||||
32-bit code has PER_CPU_VAR(cpu_current_top_of_stack).
|
||||
64-bit code uses somewhat more obscure: PER_CPU_VAR(cpu_tss + TSS_sp0).
|
||||
|
||||
Define the 'cpu_current_top_of_stack' macro on CONFIG_X86_64
|
||||
as well so that the PER_CPU_VAR(cpu_current_top_of_stack)
|
||||
expression can be used in both 32-bit and 64-bit code.
|
||||
|
||||
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
|
||||
Cc: Alexei Starovoitov <ast@plumgrid.com>
|
||||
Cc: Andrew Morton <akpm@linux-foundation.org>
|
||||
Cc: Andy Lutomirski <luto@amacapital.net>
|
||||
Cc: Borislav Petkov <bp@alien8.de>
|
||||
Cc: Frederic Weisbecker <fweisbec@gmail.com>
|
||||
Cc: H. Peter Anvin <hpa@zytor.com>
|
||||
Cc: Kees Cook <keescook@chromium.org>
|
||||
Cc: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
Cc: Oleg Nesterov <oleg@redhat.com>
|
||||
Cc: Peter Zijlstra <peterz@infradead.org>
|
||||
Cc: Steven Rostedt <rostedt@goodmis.org>
|
||||
Cc: Thomas Gleixner <tglx@linutronix.de>
|
||||
Cc: Will Drewry <wad@chromium.org>
|
||||
Link: http://lkml.kernel.org/r/1429889495-27850-3-git-send-email-dvlasenk@redhat.com
|
||||
Signed-off-by: Ingo Molnar <mingo@kernel.org>
|
||||
---
|
||||
arch/x86/ia32/ia32entry.S | 4 ++--
|
||||
arch/x86/include/asm/thread_info.h | 10 ++++------
|
||||
arch/x86/kernel/entry_64.S | 2 +-
|
||||
arch/x86/xen/xen-asm_64.S | 5 +++--
|
||||
4 files changed, 10 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
|
||||
index e3c0f06..1c30fa9 100644
|
||||
--- a/arch/x86/ia32/ia32entry.S
|
||||
+++ b/arch/x86/ia32/ia32entry.S
|
||||
@@ -119,7 +119,7 @@ ENTRY(ia32_sysenter_target)
|
||||
* it is too small to ever cause noticeable irq latency.
|
||||
*/
|
||||
SWAPGS_UNSAFE_STACK
|
||||
- movq PER_CPU_VAR(cpu_tss + TSS_sp0), %rsp
|
||||
+ movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
|
||||
ENABLE_INTERRUPTS(CLBR_NONE)
|
||||
|
||||
/* Zero-extending 32-bit regs, do not remove */
|
||||
@@ -356,7 +356,7 @@ ENTRY(ia32_cstar_target)
|
||||
SWAPGS_UNSAFE_STACK
|
||||
movl %esp,%r8d
|
||||
CFI_REGISTER rsp,r8
|
||||
- movq PER_CPU_VAR(cpu_tss + TSS_sp0),%rsp
|
||||
+ movq PER_CPU_VAR(cpu_current_top_of_stack),%rsp
|
||||
ENABLE_INTERRUPTS(CLBR_NONE)
|
||||
|
||||
/* Zero-extending 32-bit regs, do not remove */
|
||||
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
|
||||
index d656a36..9ececd0 100644
|
||||
--- a/arch/x86/include/asm/thread_info.h
|
||||
+++ b/arch/x86/include/asm/thread_info.h
|
||||
@@ -197,16 +197,14 @@ static inline unsigned long current_stack_pointer(void)
|
||||
|
||||
#else /* !__ASSEMBLY__ */
|
||||
|
||||
+#ifdef CONFIG_X86_64
|
||||
+# define cpu_current_top_of_stack (cpu_tss + TSS_sp0)
|
||||
+#endif
|
||||
+
|
||||
/* Load thread_info address into "reg" */
|
||||
-#ifdef CONFIG_X86_32
|
||||
#define GET_THREAD_INFO(reg) \
|
||||
_ASM_MOV PER_CPU_VAR(cpu_current_top_of_stack),reg ; \
|
||||
_ASM_SUB $(THREAD_SIZE),reg ;
|
||||
-#else
|
||||
-#define GET_THREAD_INFO(reg) \
|
||||
- _ASM_MOV PER_CPU_VAR(cpu_tss + TSS_sp0),reg ; \
|
||||
- _ASM_SUB $(THREAD_SIZE),reg ;
|
||||
-#endif
|
||||
|
||||
/*
|
||||
* ASM operand which evaluates to a 'thread_info' address of
|
||||
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
|
||||
index 00cde3c..61e0f27 100644
|
||||
--- a/arch/x86/kernel/entry_64.S
|
||||
+++ b/arch/x86/kernel/entry_64.S
|
||||
@@ -216,7 +216,7 @@ ENTRY(system_call)
|
||||
GLOBAL(system_call_after_swapgs)
|
||||
|
||||
movq %rsp,PER_CPU_VAR(rsp_scratch)
|
||||
- movq PER_CPU_VAR(cpu_tss + TSS_sp0),%rsp
|
||||
+ movq PER_CPU_VAR(cpu_current_top_of_stack),%rsp
|
||||
|
||||
/* Construct struct pt_regs on stack */
|
||||
pushq_cfi $__USER_DS /* pt_regs->ss */
|
||||
diff --git a/arch/x86/xen/xen-asm_64.S b/arch/x86/xen/xen-asm_64.S
|
||||
index acc49e0..5e15e92 100644
|
||||
--- a/arch/x86/xen/xen-asm_64.S
|
||||
+++ b/arch/x86/xen/xen-asm_64.S
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <asm/processor-flags.h>
|
||||
#include <asm/segment.h>
|
||||
#include <asm/asm-offsets.h>
|
||||
+#include <asm/thread_info.h>
|
||||
|
||||
#include <xen/interface/xen.h>
|
||||
|
||||
@@ -70,7 +71,7 @@ ENTRY(xen_sysret64)
|
||||
* still with the kernel gs, so we can easily switch back
|
||||
*/
|
||||
movq %rsp, PER_CPU_VAR(rsp_scratch)
|
||||
- movq PER_CPU_VAR(cpu_tss + TSS_sp0), %rsp
|
||||
+ movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
|
||||
|
||||
pushq $__USER_DS
|
||||
pushq PER_CPU_VAR(rsp_scratch)
|
||||
@@ -89,7 +90,7 @@ ENTRY(xen_sysret32)
|
||||
* still with the kernel gs, so we can easily switch back
|
||||
*/
|
||||
movq %rsp, PER_CPU_VAR(rsp_scratch)
|
||||
- movq PER_CPU_VAR(cpu_tss + TSS_sp0), %rsp
|
||||
+ movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
|
||||
|
||||
pushq $__USER32_DS
|
||||
pushq PER_CPU_VAR(rsp_scratch)
|
||||
--
|
||||
2.4.3
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
From 252c6cff2b83c4cc969b64306956a5c8c130a50d Mon Sep 17 00:00:00 2001
|
||||
From: Denys Vlasenko <dvlasenk@redhat.com>
|
||||
Date: Fri, 24 Apr 2015 17:31:33 +0200
|
||||
Subject: [PATCH 2/9] x86/entry: Stop using PER_CPU_VAR(kernel_stack)
|
||||
|
||||
PER_CPU_VAR(kernel_stack) is redundant:
|
||||
|
||||
- On the 64-bit build, we can use PER_CPU_VAR(cpu_tss + TSS_sp0).
|
||||
- On the 32-bit build, we can use PER_CPU_VAR(cpu_current_top_of_stack).
|
||||
|
||||
PER_CPU_VAR(kernel_stack) will be deleted by a separate change.
|
||||
|
||||
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
|
||||
Cc: Alexei Starovoitov <ast@plumgrid.com>
|
||||
Cc: Andrew Morton <akpm@linux-foundation.org>
|
||||
Cc: Andy Lutomirski <luto@amacapital.net>
|
||||
Cc: Borislav Petkov <bp@alien8.de>
|
||||
Cc: Frederic Weisbecker <fweisbec@gmail.com>
|
||||
Cc: H. Peter Anvin <hpa@zytor.com>
|
||||
Cc: Kees Cook <keescook@chromium.org>
|
||||
Cc: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
Cc: Oleg Nesterov <oleg@redhat.com>
|
||||
Cc: Peter Zijlstra <peterz@infradead.org>
|
||||
Cc: Steven Rostedt <rostedt@goodmis.org>
|
||||
Cc: Thomas Gleixner <tglx@linutronix.de>
|
||||
Cc: Will Drewry <wad@chromium.org>
|
||||
Link: http://lkml.kernel.org/r/1429889495-27850-1-git-send-email-dvlasenk@redhat.com
|
||||
Signed-off-by: Ingo Molnar <mingo@kernel.org>
|
||||
---
|
||||
arch/x86/ia32/ia32entry.S | 2 +-
|
||||
arch/x86/include/asm/thread_info.h | 8 +++++++-
|
||||
arch/x86/kernel/entry_64.S | 2 +-
|
||||
arch/x86/xen/xen-asm_64.S | 5 +++--
|
||||
4 files changed, 12 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
|
||||
index 72bf268..e3c0f06 100644
|
||||
--- a/arch/x86/ia32/ia32entry.S
|
||||
+++ b/arch/x86/ia32/ia32entry.S
|
||||
@@ -356,7 +356,7 @@ ENTRY(ia32_cstar_target)
|
||||
SWAPGS_UNSAFE_STACK
|
||||
movl %esp,%r8d
|
||||
CFI_REGISTER rsp,r8
|
||||
- movq PER_CPU_VAR(kernel_stack),%rsp
|
||||
+ movq PER_CPU_VAR(cpu_tss + TSS_sp0),%rsp
|
||||
ENABLE_INTERRUPTS(CLBR_NONE)
|
||||
|
||||
/* Zero-extending 32-bit regs, do not remove */
|
||||
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
|
||||
index b4bdec3..d656a36 100644
|
||||
--- a/arch/x86/include/asm/thread_info.h
|
||||
+++ b/arch/x86/include/asm/thread_info.h
|
||||
@@ -198,9 +198,15 @@ static inline unsigned long current_stack_pointer(void)
|
||||
#else /* !__ASSEMBLY__ */
|
||||
|
||||
/* Load thread_info address into "reg" */
|
||||
+#ifdef CONFIG_X86_32
|
||||
#define GET_THREAD_INFO(reg) \
|
||||
- _ASM_MOV PER_CPU_VAR(kernel_stack),reg ; \
|
||||
+ _ASM_MOV PER_CPU_VAR(cpu_current_top_of_stack),reg ; \
|
||||
_ASM_SUB $(THREAD_SIZE),reg ;
|
||||
+#else
|
||||
+#define GET_THREAD_INFO(reg) \
|
||||
+ _ASM_MOV PER_CPU_VAR(cpu_tss + TSS_sp0),reg ; \
|
||||
+ _ASM_SUB $(THREAD_SIZE),reg ;
|
||||
+#endif
|
||||
|
||||
/*
|
||||
* ASM operand which evaluates to a 'thread_info' address of
|
||||
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
|
||||
index b32f346..00cde3c 100644
|
||||
--- a/arch/x86/kernel/entry_64.S
|
||||
+++ b/arch/x86/kernel/entry_64.S
|
||||
@@ -216,7 +216,7 @@ ENTRY(system_call)
|
||||
GLOBAL(system_call_after_swapgs)
|
||||
|
||||
movq %rsp,PER_CPU_VAR(rsp_scratch)
|
||||
- movq PER_CPU_VAR(kernel_stack),%rsp
|
||||
+ movq PER_CPU_VAR(cpu_tss + TSS_sp0),%rsp
|
||||
|
||||
/* Construct struct pt_regs on stack */
|
||||
pushq_cfi $__USER_DS /* pt_regs->ss */
|
||||
diff --git a/arch/x86/xen/xen-asm_64.S b/arch/x86/xen/xen-asm_64.S
|
||||
index 985fc3e..acc49e0 100644
|
||||
--- a/arch/x86/xen/xen-asm_64.S
|
||||
+++ b/arch/x86/xen/xen-asm_64.S
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <asm/percpu.h>
|
||||
#include <asm/processor-flags.h>
|
||||
#include <asm/segment.h>
|
||||
+#include <asm/asm-offsets.h>
|
||||
|
||||
#include <xen/interface/xen.h>
|
||||
|
||||
@@ -69,7 +70,7 @@ ENTRY(xen_sysret64)
|
||||
* still with the kernel gs, so we can easily switch back
|
||||
*/
|
||||
movq %rsp, PER_CPU_VAR(rsp_scratch)
|
||||
- movq PER_CPU_VAR(kernel_stack), %rsp
|
||||
+ movq PER_CPU_VAR(cpu_tss + TSS_sp0), %rsp
|
||||
|
||||
pushq $__USER_DS
|
||||
pushq PER_CPU_VAR(rsp_scratch)
|
||||
@@ -88,7 +89,7 @@ ENTRY(xen_sysret32)
|
||||
* still with the kernel gs, so we can easily switch back
|
||||
*/
|
||||
movq %rsp, PER_CPU_VAR(rsp_scratch)
|
||||
- movq PER_CPU_VAR(kernel_stack), %rsp
|
||||
+ movq PER_CPU_VAR(cpu_tss + TSS_sp0), %rsp
|
||||
|
||||
pushq $__USER32_DS
|
||||
pushq PER_CPU_VAR(rsp_scratch)
|
||||
--
|
||||
2.4.3
|
||||
|
|
@ -1,290 +0,0 @@
|
|||
From 7f340812f17f9c24519254fdaa88dd7b54fc3b59 Mon Sep 17 00:00:00 2001
|
||||
From: Andy Lutomirski <luto@kernel.org>
|
||||
Date: Fri, 10 Jul 2015 17:13:26 -0700
|
||||
Subject: [PATCH 5/7] x86/nmi/64: Improve nested NMI comments
|
||||
|
||||
commit ed02eaa10579ffd480c3bda29701e658f17196e9 upstream.
|
||||
|
||||
I found the nested NMI documentation to be difficult to follow.
|
||||
Improve the comments.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Andy Lutomirski <luto@kernel.org>
|
||||
[bwh: Backported to 4.0: adjust filename, context]
|
||||
[labbott: Context fixup around nmi_restore]
|
||||
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
|
||||
---
|
||||
arch/x86/kernel/entry_64.S | 160 ++++++++++++++++++++++++++-------------------
|
||||
arch/x86/kernel/nmi.c | 4 +-
|
||||
2 files changed, 94 insertions(+), 70 deletions(-)
|
||||
|
||||
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
|
||||
index 4fabbaa..152790c 100644
|
||||
--- a/arch/x86/kernel/entry_64.S
|
||||
+++ b/arch/x86/kernel/entry_64.S
|
||||
@@ -1411,11 +1411,12 @@ ENTRY(nmi)
|
||||
* If the variable is not set and the stack is not the NMI
|
||||
* stack then:
|
||||
* o Set the special variable on the stack
|
||||
- * o Copy the interrupt frame into a "saved" location on the stack
|
||||
- * o Copy the interrupt frame into a "copy" location on the stack
|
||||
+ * o Copy the interrupt frame into an "outermost" location on the
|
||||
+ * stack
|
||||
+ * o Copy the interrupt frame into an "iret" location on the stack
|
||||
* o Continue processing the NMI
|
||||
* If the variable is set or the previous stack is the NMI stack:
|
||||
- * o Modify the "copy" location to jump to the repeate_nmi
|
||||
+ * o Modify the "iret" location to jump to the repeat_nmi
|
||||
* o return back to the first NMI
|
||||
*
|
||||
* Now on exit of the first NMI, we first clear the stack variable
|
||||
@@ -1509,18 +1510,60 @@ ENTRY(nmi)
|
||||
|
||||
.Lnmi_from_kernel:
|
||||
/*
|
||||
- * Check the special variable on the stack to see if NMIs are
|
||||
- * executing.
|
||||
+ * Here's what our stack frame will look like:
|
||||
+ * +---------------------------------------------------------+
|
||||
+ * | original SS |
|
||||
+ * | original Return RSP |
|
||||
+ * | original RFLAGS |
|
||||
+ * | original CS |
|
||||
+ * | original RIP |
|
||||
+ * +---------------------------------------------------------+
|
||||
+ * | temp storage for rdx |
|
||||
+ * +---------------------------------------------------------+
|
||||
+ * | "NMI executing" variable |
|
||||
+ * +---------------------------------------------------------+
|
||||
+ * | iret SS } Copied from "outermost" frame |
|
||||
+ * | iret Return RSP } on each loop iteration; overwritten |
|
||||
+ * | iret RFLAGS } by a nested NMI to force another |
|
||||
+ * | iret CS } iteration if needed. |
|
||||
+ * | iret RIP } |
|
||||
+ * +---------------------------------------------------------+
|
||||
+ * | outermost SS } initialized in first_nmi; |
|
||||
+ * | outermost Return RSP } will not be changed before |
|
||||
+ * | outermost RFLAGS } NMI processing is done. |
|
||||
+ * | outermost CS } Copied to "iret" frame on each |
|
||||
+ * | outermost RIP } iteration. |
|
||||
+ * +---------------------------------------------------------+
|
||||
+ * | pt_regs |
|
||||
+ * +---------------------------------------------------------+
|
||||
+ *
|
||||
+ * The "original" frame is used by hardware. Before re-enabling
|
||||
+ * NMIs, we need to be done with it, and we need to leave enough
|
||||
+ * space for the asm code here.
|
||||
+ *
|
||||
+ * We return by executing IRET while RSP points to the "iret" frame.
|
||||
+ * That will either return for real or it will loop back into NMI
|
||||
+ * processing.
|
||||
+ *
|
||||
+ * The "outermost" frame is copied to the "iret" frame on each
|
||||
+ * iteration of the loop, so each iteration starts with the "iret"
|
||||
+ * frame pointing to the final return target.
|
||||
+ */
|
||||
+
|
||||
+ /*
|
||||
+ * Determine whether we're a nested NMI.
|
||||
+ *
|
||||
+ * First check "NMI executing". If it's set, then we're nested.
|
||||
+ * This will not detect if we interrupted an outer NMI just
|
||||
+ * before IRET.
|
||||
*/
|
||||
cmpl $1, -8(%rsp)
|
||||
je nested_nmi
|
||||
|
||||
/*
|
||||
- * Now test if the previous stack was an NMI stack.
|
||||
- * We need the double check. We check the NMI stack to satisfy the
|
||||
- * race when the first NMI clears the variable before returning.
|
||||
- * We check the variable because the first NMI could be in a
|
||||
- * breakpoint routine using a breakpoint stack.
|
||||
+ * Now test if the previous stack was an NMI stack. This covers
|
||||
+ * the case where we interrupt an outer NMI after it clears
|
||||
+ * "NMI executing" but before IRET.
|
||||
*/
|
||||
lea 6*8(%rsp), %rdx
|
||||
/* Compare the NMI stack (rdx) with the stack we came from (4*8(%rsp)) */
|
||||
@@ -1537,9 +1580,11 @@ ENTRY(nmi)
|
||||
|
||||
nested_nmi:
|
||||
/*
|
||||
- * Do nothing if we interrupted the fixup in repeat_nmi.
|
||||
- * It's about to repeat the NMI handler, so we are fine
|
||||
- * with ignoring this one.
|
||||
+ * If we interrupted an NMI that is between repeat_nmi and
|
||||
+ * end_repeat_nmi, then we must not modify the "iret" frame
|
||||
+ * because it's being written by the outer NMI. That's okay:
|
||||
+ * the outer NMI handler is about to call do_nmi anyway,
|
||||
+ * so we can just resume the outer NMI.
|
||||
*/
|
||||
movq $repeat_nmi, %rdx
|
||||
cmpq 8(%rsp), %rdx
|
||||
@@ -1549,7 +1594,10 @@ nested_nmi:
|
||||
ja nested_nmi_out
|
||||
|
||||
1:
|
||||
- /* Set up the interrupted NMIs stack to jump to repeat_nmi */
|
||||
+ /*
|
||||
+ * Modify the "iret" frame to point to repeat_nmi, forcing another
|
||||
+ * iteration of NMI handling.
|
||||
+ */
|
||||
leaq -1*8(%rsp), %rdx
|
||||
movq %rdx, %rsp
|
||||
CFI_ADJUST_CFA_OFFSET 1*8
|
||||
@@ -1568,60 +1616,23 @@ nested_nmi_out:
|
||||
popq_cfi %rdx
|
||||
CFI_RESTORE rdx
|
||||
|
||||
- /* No need to check faults here */
|
||||
+ /* We are returning to kernel mode, so this cannot result in a fault. */
|
||||
INTERRUPT_RETURN
|
||||
|
||||
CFI_RESTORE_STATE
|
||||
first_nmi:
|
||||
- /*
|
||||
- * Because nested NMIs will use the pushed location that we
|
||||
- * stored in rdx, we must keep that space available.
|
||||
- * Here's what our stack frame will look like:
|
||||
- * +-------------------------+
|
||||
- * | original SS |
|
||||
- * | original Return RSP |
|
||||
- * | original RFLAGS |
|
||||
- * | original CS |
|
||||
- * | original RIP |
|
||||
- * +-------------------------+
|
||||
- * | temp storage for rdx |
|
||||
- * +-------------------------+
|
||||
- * | NMI executing variable |
|
||||
- * +-------------------------+
|
||||
- * | copied SS |
|
||||
- * | copied Return RSP |
|
||||
- * | copied RFLAGS |
|
||||
- * | copied CS |
|
||||
- * | copied RIP |
|
||||
- * +-------------------------+
|
||||
- * | Saved SS |
|
||||
- * | Saved Return RSP |
|
||||
- * | Saved RFLAGS |
|
||||
- * | Saved CS |
|
||||
- * | Saved RIP |
|
||||
- * +-------------------------+
|
||||
- * | pt_regs |
|
||||
- * +-------------------------+
|
||||
- *
|
||||
- * The saved stack frame is used to fix up the copied stack frame
|
||||
- * that a nested NMI may change to make the interrupted NMI iret jump
|
||||
- * to the repeat_nmi. The original stack frame and the temp storage
|
||||
- * is also used by nested NMIs and can not be trusted on exit.
|
||||
- */
|
||||
- /* Do not pop rdx, nested NMIs will corrupt that part of the stack */
|
||||
+ /* Restore rdx. */
|
||||
movq (%rsp), %rdx
|
||||
CFI_RESTORE rdx
|
||||
|
||||
- /* Set the NMI executing variable on the stack. */
|
||||
+ /* Set "NMI executing" on the stack. */
|
||||
pushq_cfi $1
|
||||
|
||||
- /*
|
||||
- * Leave room for the "copied" frame
|
||||
- */
|
||||
+ /* Leave room for the "iret" frame */
|
||||
subq $(5*8), %rsp
|
||||
CFI_ADJUST_CFA_OFFSET 5*8
|
||||
|
||||
- /* Copy the stack frame to the Saved frame */
|
||||
+ /* Copy the "original" frame to the "outermost" frame */
|
||||
.rept 5
|
||||
pushq_cfi 11*8(%rsp)
|
||||
.endr
|
||||
@@ -1629,6 +1640,7 @@ first_nmi:
|
||||
|
||||
/* Everything up to here is safe from nested NMIs */
|
||||
|
||||
+repeat_nmi:
|
||||
/*
|
||||
* If there was a nested NMI, the first NMI's iret will return
|
||||
* here. But NMIs are still enabled and we can take another
|
||||
@@ -1637,16 +1649,21 @@ first_nmi:
|
||||
* it will just return, as we are about to repeat an NMI anyway.
|
||||
* This makes it safe to copy to the stack frame that a nested
|
||||
* NMI will update.
|
||||
- */
|
||||
-repeat_nmi:
|
||||
- /*
|
||||
- * Update the stack variable to say we are still in NMI (the update
|
||||
- * is benign for the non-repeat case, where 1 was pushed just above
|
||||
- * to this very stack slot).
|
||||
+ *
|
||||
+ * RSP is pointing to "outermost RIP". gsbase is unknown, but, if
|
||||
+ * we're repeating an NMI, gsbase has the same value that it had on
|
||||
+ * the first iteration. paranoid_entry will load the kernel
|
||||
+ * gsbase if needed before we call do_nmi.
|
||||
+ *
|
||||
+ * Set "NMI executing" in case we came back here via IRET.
|
||||
*/
|
||||
movq $1, 10*8(%rsp)
|
||||
|
||||
- /* Make another copy, this one may be modified by nested NMIs */
|
||||
+ /*
|
||||
+ * Copy the "outermost" frame to the "iret" frame. NMIs that nest
|
||||
+ * here must not modify the "iret" frame while we're writing to
|
||||
+ * it or it will end up containing garbage.
|
||||
+ */
|
||||
addq $(10*8), %rsp
|
||||
CFI_ADJUST_CFA_OFFSET -10*8
|
||||
.rept 5
|
||||
@@ -1657,9 +1674,9 @@ repeat_nmi:
|
||||
end_repeat_nmi:
|
||||
|
||||
/*
|
||||
- * Everything below this point can be preempted by a nested
|
||||
- * NMI if the first NMI took an exception and reset our iret stack
|
||||
- * so that we repeat another NMI.
|
||||
+ * Everything below this point can be preempted by a nested NMI.
|
||||
+ * If this happens, then the inner NMI will change the "iret"
|
||||
+ * frame to point back to repeat_nmi.
|
||||
*/
|
||||
pushq_cfi $-1 /* ORIG_RAX: no syscall to restart */
|
||||
ALLOC_PT_GPREGS_ON_STACK
|
||||
@@ -1686,11 +1703,18 @@ nmi_swapgs:
|
||||
nmi_restore:
|
||||
RESTORE_EXTRA_REGS
|
||||
RESTORE_C_REGS
|
||||
- /* Pop the extra iret frame at once */
|
||||
+
|
||||
+ /* Point RSP at the "iret" frame. */
|
||||
REMOVE_PT_GPREGS_FROM_STACK 6*8
|
||||
|
||||
- /* Clear the NMI executing stack variable */
|
||||
+ /* Clear "NMI executing". */
|
||||
movq $0, 5*8(%rsp)
|
||||
+
|
||||
+ /*
|
||||
+ * INTERRUPT_RETURN reads the "iret" frame and exits the NMI
|
||||
+ * stack in a single instruction. We are returning to kernel
|
||||
+ * mode, so this cannot result in a fault.
|
||||
+ */
|
||||
INTERRUPT_RETURN
|
||||
CFI_ENDPROC
|
||||
END(nmi)
|
||||
diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c
|
||||
index d8766b1..d05bd2e 100644
|
||||
--- a/arch/x86/kernel/nmi.c
|
||||
+++ b/arch/x86/kernel/nmi.c
|
||||
@@ -408,8 +408,8 @@ static void default_do_nmi(struct pt_regs *regs)
|
||||
NOKPROBE_SYMBOL(default_do_nmi);
|
||||
|
||||
/*
|
||||
- * NMIs can hit breakpoints which will cause it to lose its NMI context
|
||||
- * with the CPU when the breakpoint or page fault does an IRET.
|
||||
+ * NMIs can page fault or hit breakpoints which will cause it to lose
|
||||
+ * its NMI context with the CPU when the breakpoint or page fault does an IRET.
|
||||
*
|
||||
* As a result, NMIs can nest if NMIs get unmasked due an IRET during
|
||||
* NMI processing. On x86_64, the asm glue protects us from nested NMIs
|
||||
--
|
||||
2.4.3
|
||||
|
|
@ -1,58 +0,0 @@
|
|||
From 827b728c1e4aec28a115b6be56a0ac2407e9dd05 Mon Sep 17 00:00:00 2001
|
||||
From: Andy Lutomirski <luto@kernel.org>
|
||||
Date: Fri, 10 Jul 2015 12:03:34 -0700
|
||||
Subject: [PATCH 3/7] x86/nmi/64: Remove asm code that saves cr2
|
||||
|
||||
commit e7c2c90651fd54c3ca499fbb065ea5cbac30047d upstream.
|
||||
|
||||
Now that do_nmi saves cr2, we don't need to save it in asm.
|
||||
|
||||
This is a prerequisity for the fix for CVE-2015-3290.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Reviewed-by: Steven Rostedt <rostedt@goodmis.org>
|
||||
Acked-by: Borislav Petkov <bp@suse.de>
|
||||
Signed-off-by: Andy Lutomirski <luto@kernel.org>
|
||||
[bwh: Backported to 4.0: adjust filename, context]
|
||||
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
|
||||
---
|
||||
arch/x86/kernel/entry_64.S | 18 ------------------
|
||||
1 file changed, 18 deletions(-)
|
||||
|
||||
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
|
||||
index b32f346..34f07d7 100644
|
||||
--- a/arch/x86/kernel/entry_64.S
|
||||
+++ b/arch/x86/kernel/entry_64.S
|
||||
@@ -1603,29 +1603,11 @@ end_repeat_nmi:
|
||||
call paranoid_entry
|
||||
DEFAULT_FRAME 0
|
||||
|
||||
- /*
|
||||
- * Save off the CR2 register. If we take a page fault in the NMI then
|
||||
- * it could corrupt the CR2 value. If the NMI preempts a page fault
|
||||
- * handler before it was able to read the CR2 register, and then the
|
||||
- * NMI itself takes a page fault, the page fault that was preempted
|
||||
- * will read the information from the NMI page fault and not the
|
||||
- * origin fault. Save it off and restore it if it changes.
|
||||
- * Use the r12 callee-saved register.
|
||||
- */
|
||||
- movq %cr2, %r12
|
||||
-
|
||||
/* paranoidentry do_nmi, 0; without TRACE_IRQS_OFF */
|
||||
movq %rsp,%rdi
|
||||
movq $-1,%rsi
|
||||
call do_nmi
|
||||
|
||||
- /* Did the NMI take a page fault? Restore cr2 if it did */
|
||||
- movq %cr2, %rcx
|
||||
- cmpq %rcx, %r12
|
||||
- je 1f
|
||||
- movq %r12, %cr2
|
||||
-1:
|
||||
-
|
||||
testl %ebx,%ebx /* swapgs needed? */
|
||||
jnz nmi_restore
|
||||
nmi_swapgs:
|
||||
--
|
||||
2.4.3
|
||||
|
|
@ -1,90 +0,0 @@
|
|||
From dc46e3fb4b597196182d4b1f5d97d0dcca5018b6 Mon Sep 17 00:00:00 2001
|
||||
From: Andy Lutomirski <luto@kernel.org>
|
||||
Date: Sun, 12 Jul 2015 20:59:57 -0700
|
||||
Subject: [PATCH 6/7] x86/nmi/64: Reorder nested NMI checks
|
||||
|
||||
commit b7dcb27674b28ca49b710e95da74c44d32154bed upstream.
|
||||
|
||||
Check the repeat_nmi .. end_repeat_nmi special case first. The next
|
||||
patch will rework the RSP check and, as a side effect, the RSP check
|
||||
will no longer detect repeat_nmi .. end_repeat_nmi, so we'll need
|
||||
this ordering of the checks.
|
||||
|
||||
Note: this is more subtle than it appears. The check for repeat_nmi
|
||||
.. end_repeat_nmi jumps straight out of the NMI code instead of
|
||||
adjusting the "iret" frame to force a repeat. This is necessary,
|
||||
because the code between repeat_nmi and end_repeat_nmi sets "NMI
|
||||
executing" and then writes to the "iret" frame itself. If a nested
|
||||
NMI comes in and modifies the "iret" frame while repeat_nmi is also
|
||||
modifying it, we'll end up with garbage. The old code got this
|
||||
right, as does the new code, but the new code is a bit more
|
||||
explicit.
|
||||
|
||||
If we were to move the check right after the "NMI executing" check,
|
||||
then we'd get it wrong and have random crashes.
|
||||
|
||||
This is a prerequisite for the fix for CVE-2015-3291.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Andy Lutomirski <luto@kernel.org>
|
||||
[bwh: Backported to 4.0: adjust filename, spacing]
|
||||
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
|
||||
---
|
||||
arch/x86/kernel/entry_64.S | 34 ++++++++++++++++++----------------
|
||||
1 file changed, 18 insertions(+), 16 deletions(-)
|
||||
|
||||
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
|
||||
index 152790c..be2c4ba 100644
|
||||
--- a/arch/x86/kernel/entry_64.S
|
||||
+++ b/arch/x86/kernel/entry_64.S
|
||||
@@ -1553,7 +1553,24 @@ ENTRY(nmi)
|
||||
/*
|
||||
* Determine whether we're a nested NMI.
|
||||
*
|
||||
- * First check "NMI executing". If it's set, then we're nested.
|
||||
+ * If we interrupted kernel code between repeat_nmi and
|
||||
+ * end_repeat_nmi, then we are a nested NMI. We must not
|
||||
+ * modify the "iret" frame because it's being written by
|
||||
+ * the outer NMI. That's okay: the outer NMI handler is
|
||||
+ * about to about to call do_nmi anyway, so we can just
|
||||
+ * resume the outer NMI.
|
||||
+ */
|
||||
+
|
||||
+ movq $repeat_nmi, %rdx
|
||||
+ cmpq 8(%rsp), %rdx
|
||||
+ ja 1f
|
||||
+ movq $end_repeat_nmi, %rdx
|
||||
+ cmpq 8(%rsp), %rdx
|
||||
+ ja nested_nmi_out
|
||||
+1:
|
||||
+
|
||||
+ /*
|
||||
+ * Now check "NMI executing". If it's set, then we're nested.
|
||||
* This will not detect if we interrupted an outer NMI just
|
||||
* before IRET.
|
||||
*/
|
||||
@@ -1580,21 +1597,6 @@ ENTRY(nmi)
|
||||
|
||||
nested_nmi:
|
||||
/*
|
||||
- * If we interrupted an NMI that is between repeat_nmi and
|
||||
- * end_repeat_nmi, then we must not modify the "iret" frame
|
||||
- * because it's being written by the outer NMI. That's okay:
|
||||
- * the outer NMI handler is about to call do_nmi anyway,
|
||||
- * so we can just resume the outer NMI.
|
||||
- */
|
||||
- movq $repeat_nmi, %rdx
|
||||
- cmpq 8(%rsp), %rdx
|
||||
- ja 1f
|
||||
- movq $end_repeat_nmi, %rdx
|
||||
- cmpq 8(%rsp), %rdx
|
||||
- ja nested_nmi_out
|
||||
-
|
||||
-1:
|
||||
- /*
|
||||
* Modify the "iret" frame to point to repeat_nmi, forcing another
|
||||
* iteration of NMI handling.
|
||||
*/
|
||||
--
|
||||
2.4.3
|
||||
|
|
@ -1,140 +0,0 @@
|
|||
From f1a66b1c4d231e2e9d3a1f7affecb35df3ce0464 Mon Sep 17 00:00:00 2001
|
||||
From: Andy Lutomirski <luto@kernel.org>
|
||||
Date: Fri, 10 Jul 2015 11:35:31 -0700
|
||||
Subject: [PATCH 6/9] x86/nmi/64: Switch stacks on userspace NMI entry
|
||||
|
||||
commit 4fb2a8d9cb0efcd7405f1ad105d7f3c764afe02f upstream.
|
||||
|
||||
Returning to userspace is tricky: IRET can fail, and ESPFIX can
|
||||
rearrange the stack prior to IRET.
|
||||
|
||||
The NMI nesting fixup relies on a precise stack layout and atomic
|
||||
IRET. Rather than trying to teach the NMI nesting fixup to handle
|
||||
ESPFIX and failed IRET, punt: run NMIs that came from user mode on
|
||||
the normal kernel stack.
|
||||
|
||||
This will make some nested NMIs visible to C code, but the C code is
|
||||
okay with that.
|
||||
|
||||
As a side effect, this should speed up perf: it eliminates an RDMSR
|
||||
when NMIs come from user mode.
|
||||
|
||||
Fixes CVE-2015-3290.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Reviewed-by: Steven Rostedt <rostedt@goodmis.org>
|
||||
Reviewed-by: Borislav Petkov <bp@suse.de>
|
||||
Signed-off-by: Andy Lutomirski <luto@kernel.org>
|
||||
[bwh: Backported to 4.0:
|
||||
- Adjust filename, context
|
||||
- s/restore_c_regs_and_iret/restore_args/
|
||||
- Use kernel_stack + KERNEL_STACK_OFFSET instead of cpu_current_top_of_stack]
|
||||
[luto: Open-coded return path to avoid dependency on partial pt_regs details]
|
||||
[labbott: just use cpu_current_top_of_stack instead]
|
||||
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
|
||||
Signed-off-by: Andy Lutomirski <luto@kernel.org>
|
||||
---
|
||||
arch/x86/kernel/entry_64.S | 78 +++++++++++++++++++++++++++++++++++++++++++---
|
||||
1 file changed, 74 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
|
||||
index 6916856..75988f4 100644
|
||||
--- a/arch/x86/kernel/entry_64.S
|
||||
+++ b/arch/x86/kernel/entry_64.S
|
||||
@@ -1424,19 +1424,89 @@ ENTRY(nmi)
|
||||
* a nested NMI that updated the copy interrupt stack frame, a
|
||||
* jump will be made to the repeat_nmi code that will handle the second
|
||||
* NMI.
|
||||
+ *
|
||||
+ * However, espfix prevents us from directly returning to userspace
|
||||
+ * with a single IRET instruction. Similarly, IRET to user mode
|
||||
+ * can fault. We therefore handle NMIs from user space like
|
||||
+ * other IST entries.
|
||||
*/
|
||||
|
||||
/* Use %rdx as our temp variable throughout */
|
||||
pushq_cfi %rdx
|
||||
CFI_REL_OFFSET rdx, 0
|
||||
|
||||
+ testb $3, CS-RIP+8(%rsp)
|
||||
+ jz .Lnmi_from_kernel
|
||||
+
|
||||
/*
|
||||
- * If %cs was not the kernel segment, then the NMI triggered in user
|
||||
- * space, which means it is definitely not nested.
|
||||
+ * NMI from user mode. We need to run on the thread stack, but we
|
||||
+ * can't go through the normal entry paths: NMIs are masked, and
|
||||
+ * we don't want to enable interrupts, because then we'll end
|
||||
+ * up in an awkward situation in which IRQs are on but NMIs
|
||||
+ * are off.
|
||||
*/
|
||||
- cmpl $__KERNEL_CS, 16(%rsp)
|
||||
- jne first_nmi
|
||||
|
||||
+ SWAPGS
|
||||
+ cld
|
||||
+ movq %rsp, %rdx
|
||||
+ movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
|
||||
+ pushq 5*8(%rdx) /* pt_regs->ss */
|
||||
+ pushq 4*8(%rdx) /* pt_regs->rsp */
|
||||
+ pushq 3*8(%rdx) /* pt_regs->flags */
|
||||
+ pushq 2*8(%rdx) /* pt_regs->cs */
|
||||
+ pushq 1*8(%rdx) /* pt_regs->rip */
|
||||
+ pushq $-1 /* pt_regs->orig_ax */
|
||||
+ pushq %rdi /* pt_regs->di */
|
||||
+ pushq %rsi /* pt_regs->si */
|
||||
+ pushq (%rdx) /* pt_regs->dx */
|
||||
+ pushq %rcx /* pt_regs->cx */
|
||||
+ pushq %rax /* pt_regs->ax */
|
||||
+ pushq %r8 /* pt_regs->r8 */
|
||||
+ pushq %r9 /* pt_regs->r9 */
|
||||
+ pushq %r10 /* pt_regs->r10 */
|
||||
+ pushq %r11 /* pt_regs->r11 */
|
||||
+ pushq %rbx /* pt_regs->rbx */
|
||||
+ pushq %rbp /* pt_regs->rbp */
|
||||
+ pushq %r12 /* pt_regs->r12 */
|
||||
+ pushq %r13 /* pt_regs->r13 */
|
||||
+ pushq %r14 /* pt_regs->r14 */
|
||||
+ pushq %r15 /* pt_regs->r15 */
|
||||
+
|
||||
+ /*
|
||||
+ * At this point we no longer need to worry about stack damage
|
||||
+ * due to nesting -- we're on the normal thread stack and we're
|
||||
+ * done with the NMI stack.
|
||||
+ */
|
||||
+
|
||||
+ movq %rsp, %rdi
|
||||
+ movq $-1, %rsi
|
||||
+ call do_nmi
|
||||
+
|
||||
+ /*
|
||||
+ * Return back to user mode. We must *not* do the normal exit
|
||||
+ * work, because we don't want to enable interrupts. Fortunately,
|
||||
+ * do_nmi doesn't modify pt_regs.
|
||||
+ */
|
||||
+ SWAPGS
|
||||
+
|
||||
+ /*
|
||||
+ * Open-code the entire return process for compatibility with varying
|
||||
+ * register layouts across different kernel versions.
|
||||
+ */
|
||||
+ addq $6*8, %rsp /* skip bx, bp, and r12-r15 */
|
||||
+ popq %r11 /* pt_regs->r11 */
|
||||
+ popq %r10 /* pt_regs->r10 */
|
||||
+ popq %r9 /* pt_regs->r9 */
|
||||
+ popq %r8 /* pt_regs->r8 */
|
||||
+ popq %rax /* pt_regs->ax */
|
||||
+ popq %rcx /* pt_regs->cx */
|
||||
+ popq %rdx /* pt_regs->dx */
|
||||
+ popq %rsi /* pt_regs->si */
|
||||
+ popq %rdi /* pt_regs->di */
|
||||
+ addq $8, %rsp /* skip orig_ax */
|
||||
+ INTERRUPT_RETURN
|
||||
+
|
||||
+.Lnmi_from_kernel:
|
||||
/*
|
||||
* Check the special variable on the stack to see if NMIs are
|
||||
* executing.
|
||||
--
|
||||
2.4.3
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
From 8f3e2dab9567ee8c4e104f484941a858f353ea02 Mon Sep 17 00:00:00 2001
|
||||
From: Andy Lutomirski <luto@kernel.org>
|
||||
Date: Fri, 10 Jul 2015 17:25:53 -0700
|
||||
Subject: [PATCH 7/7] x86/nmi/64: Use DF to avoid userspace RSP confusing
|
||||
nested NMI detection
|
||||
|
||||
commit dc68c0f2ec634b2cfecf879235564da58d422cee upstream.
|
||||
|
||||
We have a tricky bug in the nested NMI code: if we see RSP pointing
|
||||
to the NMI stack on NMI entry from kernel mode, we assume that we
|
||||
are executing a nested NMI.
|
||||
|
||||
This isn't quite true. A malicious userspace program can point RSP
|
||||
at the NMI stack, issue SYSCALL, and arrange for an NMI to happen
|
||||
while RSP is still pointing at the NMI stack.
|
||||
|
||||
Fix it with a sneaky trick. Set DF in the region of code that the RSP
|
||||
check is intended to detect. IRET will clear DF atomically.
|
||||
|
||||
(Note: other than paravirt, there's little need for all this complexity.
|
||||
We could check RIP instead of RSP.)
|
||||
|
||||
Fixes CVE-2015-3291.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Reviewed-by: Steven Rostedt <rostedt@goodmis.org>
|
||||
Signed-off-by: Andy Lutomirski <luto@kernel.org>
|
||||
[bwh: Backported to 4.0: adjust filename, context]
|
||||
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
|
||||
---
|
||||
arch/x86/kernel/entry_64.S | 29 +++++++++++++++++++++++++----
|
||||
1 file changed, 25 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
|
||||
index be2c4ba..ce4431c 100644
|
||||
--- a/arch/x86/kernel/entry_64.S
|
||||
+++ b/arch/x86/kernel/entry_64.S
|
||||
@@ -1580,7 +1580,14 @@ ENTRY(nmi)
|
||||
/*
|
||||
* Now test if the previous stack was an NMI stack. This covers
|
||||
* the case where we interrupt an outer NMI after it clears
|
||||
- * "NMI executing" but before IRET.
|
||||
+ * "NMI executing" but before IRET. We need to be careful, though:
|
||||
+ * there is one case in which RSP could point to the NMI stack
|
||||
+ * despite there being no NMI active: naughty userspace controls
|
||||
+ * RSP at the very beginning of the SYSCALL targets. We can
|
||||
+ * pull a fast one on naughty userspace, though: we program
|
||||
+ * SYSCALL to mask DF, so userspace cannot cause DF to be set
|
||||
+ * if it controls the kernel's RSP. We set DF before we clear
|
||||
+ * "NMI executing".
|
||||
*/
|
||||
lea 6*8(%rsp), %rdx
|
||||
/* Compare the NMI stack (rdx) with the stack we came from (4*8(%rsp)) */
|
||||
@@ -1591,10 +1598,16 @@ ENTRY(nmi)
|
||||
cmpq %rdx, 4*8(%rsp)
|
||||
/* If it is below the NMI stack, it is a normal NMI */
|
||||
jb first_nmi
|
||||
- /* Ah, it is within the NMI stack, treat it as nested */
|
||||
+
|
||||
+ /* Ah, it is within the NMI stack. */
|
||||
+
|
||||
+ testb $(X86_EFLAGS_DF >> 8), (3*8 + 1)(%rsp)
|
||||
+ jz first_nmi /* RSP was user controlled. */
|
||||
|
||||
CFI_REMEMBER_STATE
|
||||
|
||||
+ /* This is a nested NMI. */
|
||||
+
|
||||
nested_nmi:
|
||||
/*
|
||||
* Modify the "iret" frame to point to repeat_nmi, forcing another
|
||||
@@ -1709,8 +1722,16 @@ nmi_restore:
|
||||
/* Point RSP at the "iret" frame. */
|
||||
REMOVE_PT_GPREGS_FROM_STACK 6*8
|
||||
|
||||
- /* Clear "NMI executing". */
|
||||
- movq $0, 5*8(%rsp)
|
||||
+ /*
|
||||
+ * Clear "NMI executing". Set DF first so that we can easily
|
||||
+ * distinguish the remaining code between here and IRET from
|
||||
+ * the SYSCALL entry and exit paths. On a native kernel, we
|
||||
+ * could just inspect RIP, but, on paravirt kernels,
|
||||
+ * INTERRUPT_RETURN can translate into a jump into a
|
||||
+ * hypercall page.
|
||||
+ */
|
||||
+ std
|
||||
+ movq $0, 5*8(%rsp) /* clear "NMI executing" */
|
||||
|
||||
/*
|
||||
* INTERRUPT_RETURN reads the "iret" frame and exits the NMI
|
||||
--
|
||||
2.4.3
|
||||
|
|
@ -1,196 +0,0 @@
|
|||
From 44c76628aaf7408eb93f2020d4aee0894f1d408e Mon Sep 17 00:00:00 2001
|
||||
From: Andy Lutomirski <luto@kernel.org>
|
||||
Date: Wed, 15 Jul 2015 10:29:33 -0700
|
||||
Subject: [PATCH 2/7] x86/nmi: Enable nested do_nmi() handling for 64-bit
|
||||
kernels
|
||||
|
||||
32-bit kernels handle nested NMIs in C. Enable the exact same
|
||||
handling on 64-bit kernels as well. This isn't currently
|
||||
necessary, but it will become necessary once the asm code starts
|
||||
allowing limited nesting.
|
||||
|
||||
Signed-off-by: Andy Lutomirski <luto@kernel.org>
|
||||
Reviewed-by: Steven Rostedt <rostedt@goodmis.org>
|
||||
Cc: Borislav Petkov <bp@suse.de>
|
||||
Cc: Linus Torvalds <torvalds@linux-foundation.org>
|
||||
Cc: Peter Zijlstra <peterz@infradead.org>
|
||||
Cc: Thomas Gleixner <tglx@linutronix.de>
|
||||
Cc: stable@vger.kernel.org
|
||||
Signed-off-by: Ingo Molnar <mingo@kernel.org>
|
||||
---
|
||||
arch/x86/kernel/nmi.c | 123 +++++++++++++++++++++-----------------------------
|
||||
1 file changed, 52 insertions(+), 71 deletions(-)
|
||||
|
||||
diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c
|
||||
index c3e985d..d8766b1 100644
|
||||
--- a/arch/x86/kernel/nmi.c
|
||||
+++ b/arch/x86/kernel/nmi.c
|
||||
@@ -408,15 +408,15 @@ static void default_do_nmi(struct pt_regs *regs)
|
||||
NOKPROBE_SYMBOL(default_do_nmi);
|
||||
|
||||
/*
|
||||
- * NMIs can hit breakpoints which will cause it to lose its
|
||||
- * NMI context with the CPU when the breakpoint does an iret.
|
||||
- */
|
||||
-#ifdef CONFIG_X86_32
|
||||
-/*
|
||||
- * For i386, NMIs use the same stack as the kernel, and we can
|
||||
- * add a workaround to the iret problem in C (preventing nested
|
||||
- * NMIs if an NMI takes a trap). Simply have 3 states the NMI
|
||||
- * can be in:
|
||||
+ * NMIs can hit breakpoints which will cause it to lose its NMI context
|
||||
+ * with the CPU when the breakpoint or page fault does an IRET.
|
||||
+ *
|
||||
+ * As a result, NMIs can nest if NMIs get unmasked due an IRET during
|
||||
+ * NMI processing. On x86_64, the asm glue protects us from nested NMIs
|
||||
+ * if the outer NMI came from kernel mode, but we can still nest if the
|
||||
+ * outer NMI came from user mode.
|
||||
+ *
|
||||
+ * To handle these nested NMIs, we have three states:
|
||||
*
|
||||
* 1) not running
|
||||
* 2) executing
|
||||
@@ -430,15 +430,14 @@ NOKPROBE_SYMBOL(default_do_nmi);
|
||||
* (Note, the latch is binary, thus multiple NMIs triggering,
|
||||
* when one is running, are ignored. Only one NMI is restarted.)
|
||||
*
|
||||
- * If an NMI hits a breakpoint that executes an iret, another
|
||||
- * NMI can preempt it. We do not want to allow this new NMI
|
||||
- * to run, but we want to execute it when the first one finishes.
|
||||
- * We set the state to "latched", and the exit of the first NMI will
|
||||
- * perform a dec_return, if the result is zero (NOT_RUNNING), then
|
||||
- * it will simply exit the NMI handler. If not, the dec_return
|
||||
- * would have set the state to NMI_EXECUTING (what we want it to
|
||||
- * be when we are running). In this case, we simply jump back
|
||||
- * to rerun the NMI handler again, and restart the 'latched' NMI.
|
||||
+ * If an NMI executes an iret, another NMI can preempt it. We do not
|
||||
+ * want to allow this new NMI to run, but we want to execute it when the
|
||||
+ * first one finishes. We set the state to "latched", and the exit of
|
||||
+ * the first NMI will perform a dec_return, if the result is zero
|
||||
+ * (NOT_RUNNING), then it will simply exit the NMI handler. If not, the
|
||||
+ * dec_return would have set the state to NMI_EXECUTING (what we want it
|
||||
+ * to be when we are running). In this case, we simply jump back to
|
||||
+ * rerun the NMI handler again, and restart the 'latched' NMI.
|
||||
*
|
||||
* No trap (breakpoint or page fault) should be hit before nmi_restart,
|
||||
* thus there is no race between the first check of state for NOT_RUNNING
|
||||
@@ -461,49 +460,36 @@ enum nmi_states {
|
||||
static DEFINE_PER_CPU(enum nmi_states, nmi_state);
|
||||
static DEFINE_PER_CPU(unsigned long, nmi_cr2);
|
||||
|
||||
-#define nmi_nesting_preprocess(regs) \
|
||||
- do { \
|
||||
- if (this_cpu_read(nmi_state) != NMI_NOT_RUNNING) { \
|
||||
- this_cpu_write(nmi_state, NMI_LATCHED); \
|
||||
- return; \
|
||||
- } \
|
||||
- this_cpu_write(nmi_state, NMI_EXECUTING); \
|
||||
- this_cpu_write(nmi_cr2, read_cr2()); \
|
||||
- } while (0); \
|
||||
- nmi_restart:
|
||||
-
|
||||
-#define nmi_nesting_postprocess() \
|
||||
- do { \
|
||||
- if (unlikely(this_cpu_read(nmi_cr2) != read_cr2())) \
|
||||
- write_cr2(this_cpu_read(nmi_cr2)); \
|
||||
- if (this_cpu_dec_return(nmi_state)) \
|
||||
- goto nmi_restart; \
|
||||
- } while (0)
|
||||
-#else /* x86_64 */
|
||||
+#ifdef CONFIG_X86_64
|
||||
/*
|
||||
- * In x86_64 things are a bit more difficult. This has the same problem
|
||||
- * where an NMI hitting a breakpoint that calls iret will remove the
|
||||
- * NMI context, allowing a nested NMI to enter. What makes this more
|
||||
- * difficult is that both NMIs and breakpoints have their own stack.
|
||||
- * When a new NMI or breakpoint is executed, the stack is set to a fixed
|
||||
- * point. If an NMI is nested, it will have its stack set at that same
|
||||
- * fixed address that the first NMI had, and will start corrupting the
|
||||
- * stack. This is handled in entry_64.S, but the same problem exists with
|
||||
- * the breakpoint stack.
|
||||
+ * In x86_64, we need to handle breakpoint -> NMI -> breakpoint. Without
|
||||
+ * some care, the inner breakpoint will clobber the outer breakpoint's
|
||||
+ * stack.
|
||||
*
|
||||
- * If a breakpoint is being processed, and the debug stack is being used,
|
||||
- * if an NMI comes in and also hits a breakpoint, the stack pointer
|
||||
- * will be set to the same fixed address as the breakpoint that was
|
||||
- * interrupted, causing that stack to be corrupted. To handle this case,
|
||||
- * check if the stack that was interrupted is the debug stack, and if
|
||||
- * so, change the IDT so that new breakpoints will use the current stack
|
||||
- * and not switch to the fixed address. On return of the NMI, switch back
|
||||
- * to the original IDT.
|
||||
+ * If a breakpoint is being processed, and the debug stack is being
|
||||
+ * used, if an NMI comes in and also hits a breakpoint, the stack
|
||||
+ * pointer will be set to the same fixed address as the breakpoint that
|
||||
+ * was interrupted, causing that stack to be corrupted. To handle this
|
||||
+ * case, check if the stack that was interrupted is the debug stack, and
|
||||
+ * if so, change the IDT so that new breakpoints will use the current
|
||||
+ * stack and not switch to the fixed address. On return of the NMI,
|
||||
+ * switch back to the original IDT.
|
||||
*/
|
||||
static DEFINE_PER_CPU(int, update_debug_stack);
|
||||
+#endif
|
||||
|
||||
-static inline void nmi_nesting_preprocess(struct pt_regs *regs)
|
||||
+dotraplinkage notrace void
|
||||
+do_nmi(struct pt_regs *regs, long error_code)
|
||||
{
|
||||
+ if (this_cpu_read(nmi_state) != NMI_NOT_RUNNING) {
|
||||
+ this_cpu_write(nmi_state, NMI_LATCHED);
|
||||
+ return;
|
||||
+ }
|
||||
+ this_cpu_write(nmi_state, NMI_EXECUTING);
|
||||
+ this_cpu_write(nmi_cr2, read_cr2());
|
||||
+nmi_restart:
|
||||
+
|
||||
+#ifdef CONFIG_X86_64
|
||||
/*
|
||||
* If we interrupted a breakpoint, it is possible that
|
||||
* the nmi handler will have breakpoints too. We need to
|
||||
@@ -514,22 +500,8 @@ static inline void nmi_nesting_preprocess(struct pt_regs *regs)
|
||||
debug_stack_set_zero();
|
||||
this_cpu_write(update_debug_stack, 1);
|
||||
}
|
||||
-}
|
||||
-
|
||||
-static inline void nmi_nesting_postprocess(void)
|
||||
-{
|
||||
- if (unlikely(this_cpu_read(update_debug_stack))) {
|
||||
- debug_stack_reset();
|
||||
- this_cpu_write(update_debug_stack, 0);
|
||||
- }
|
||||
-}
|
||||
#endif
|
||||
|
||||
-dotraplinkage notrace void
|
||||
-do_nmi(struct pt_regs *regs, long error_code)
|
||||
-{
|
||||
- nmi_nesting_preprocess(regs);
|
||||
-
|
||||
nmi_enter();
|
||||
|
||||
inc_irq_stat(__nmi_count);
|
||||
@@ -539,8 +511,17 @@ do_nmi(struct pt_regs *regs, long error_code)
|
||||
|
||||
nmi_exit();
|
||||
|
||||
- /* On i386, may loop back to preprocess */
|
||||
- nmi_nesting_postprocess();
|
||||
+#ifdef CONFIG_X86_64
|
||||
+ if (unlikely(this_cpu_read(update_debug_stack))) {
|
||||
+ debug_stack_reset();
|
||||
+ this_cpu_write(update_debug_stack, 0);
|
||||
+ }
|
||||
+#endif
|
||||
+
|
||||
+ if (unlikely(this_cpu_read(nmi_cr2) != read_cr2()))
|
||||
+ write_cr2(this_cpu_read(nmi_cr2));
|
||||
+ if (this_cpu_dec_return(nmi_state))
|
||||
+ goto nmi_restart;
|
||||
}
|
||||
NOKPROBE_SYMBOL(do_nmi);
|
||||
|
||||
--
|
||||
2.4.3
|
||||
|
Loading…
Reference in New Issue