From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752194AbdIMI7P (ORCPT ); Wed, 13 Sep 2017 04:59:15 -0400 Received: from terminus.zytor.com ([65.50.211.136]:59575 "EHLO terminus.zytor.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751539AbdIMI7H (ORCPT ); Wed, 13 Sep 2017 04:59:07 -0400 Date: Wed, 13 Sep 2017 01:55:34 -0700 From: tip-bot for Andy Lutomirski Message-ID: Cc: tglx@linutronix.de, torvalds@linux-foundation.org, luto@kernel.org, jikos@kernel.org, hpa@zytor.com, bpetkov@suse.de, linux-kernel@vger.kernel.org, jkosina@suse.cz, mingo@kernel.org, peterz@infradead.org Reply-To: mingo@kernel.org, peterz@infradead.org, torvalds@linux-foundation.org, luto@kernel.org, jikos@kernel.org, tglx@linutronix.de, jkosina@suse.cz, hpa@zytor.com, bpetkov@suse.de, linux-kernel@vger.kernel.org In-Reply-To: <18ca57090651a6341e97083883f9e814c4f14684.1504847163.git.luto@kernel.org> References: <18ca57090651a6341e97083883f9e814c4f14684.1504847163.git.luto@kernel.org> To: linux-tip-commits@vger.kernel.org Subject: [tip:x86/urgent] x86/hibernate/64: Mask off CR3's PCID bits in the saved CR3 Git-Commit-ID: f34902c5c6c08024371202a680ce69f2d488776d X-Mailer: tip-git-log-daemon Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=UTF-8 Content-Disposition: inline Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Commit-ID: f34902c5c6c08024371202a680ce69f2d488776d Gitweb: http://git.kernel.org/tip/f34902c5c6c08024371202a680ce69f2d488776d Author: Andy Lutomirski AuthorDate: Thu, 7 Sep 2017 22:06:58 -0700 Committer: Ingo Molnar CommitDate: Wed, 13 Sep 2017 09:52:37 +0200 x86/hibernate/64: Mask off CR3's PCID bits in the saved CR3 Jiri reported a resume-from-hibernation failure triggered by PCID. The root cause appears to be rather odd. The hibernation asm restores a CR3 value that comes from the image header. If the image kernel has PCID on, it's entirely reasonable for this CR3 value to have one of the low 12 bits set. The restore code restores it with CR4.PCIDE=0, which means that those low 12 bits are accepted by the CPU but are either ignored or interpreted as a caching mode. This is odd, but still works. We blow up later when the image kernel restores CR4, though, since changing CR4.PCIDE with CR3[11:0] != 0 is illegal. Boom! FWIW, it's entirely unclear to me what's supposed to happen if a PAE kernel restores a non-PAE image or vice versa. Ditto for LA57. Reported-by: Jiri Kosina Tested-by: Jiri Kosina Signed-off-by: Andy Lutomirski Cc: Borislav Petkov Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Fixes: 660da7c9228f ("x86/mm: Enable CR4.PCIDE on supported systems") Link: http://lkml.kernel.org/r/18ca57090651a6341e97083883f9e814c4f14684.1504847163.git.luto@kernel.org Signed-off-by: Ingo Molnar --- arch/x86/power/hibernate_64.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/arch/x86/power/hibernate_64.c b/arch/x86/power/hibernate_64.c index f2598d8..f910c51 100644 --- a/arch/x86/power/hibernate_64.c +++ b/arch/x86/power/hibernate_64.c @@ -295,7 +295,26 @@ int arch_hibernation_header_save(void *addr, unsigned int max_size) return -EOVERFLOW; rdr->jump_address = (unsigned long)restore_registers; rdr->jump_address_phys = __pa_symbol(restore_registers); - rdr->cr3 = restore_cr3; + + /* + * The restore code fixes up CR3 and CR4 in the following sequence: + * + * [in hibernation asm] + * 1. CR3 <= temporary page tables + * 2. CR4 <= mmu_cr4_features (from the kernel that restores us) + * 3. CR3 <= rdr->cr3 + * 4. CR4 <= mmu_cr4_features (from us, i.e. the image kernel) + * [in restore_processor_state()] + * 5. CR4 <= saved CR4 + * 6. CR3 <= saved CR3 + * + * Our mmu_cr4_features has CR4.PCIDE=0, and toggling + * CR4.PCIDE while CR3's PCID bits are nonzero is illegal, so + * rdr->cr3 needs to point to valid page tables but must not + * have any of the PCID bits set. + */ + rdr->cr3 = restore_cr3 & ~CR3_PCID_MASK; + rdr->magic = RESTORE_MAGIC; hibernation_e820_save(rdr->e820_digest);