Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756020AbcCPXyr (ORCPT ); Wed, 16 Mar 2016 19:54:47 -0400 Received: from g4t3427.houston.hp.com ([15.201.208.55]:48007 "EHLO g4t3427.houston.hp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S935373AbcCPXyq (ORCPT ); Wed, 16 Mar 2016 19:54:46 -0400 From: Toshi Kani To: mingo@kernel.org, bp@suse.de, hpa@zytor.com, tglx@linutronix.de Cc: mcgrof@suse.com, jgross@suse.com, paul.gortmaker@windriver.com, konrad.wilk@oracle.com, elliott@hpe.com, x86@kernel.org, xen-devel@lists.xenproject.org, linux-kernel@vger.kernel.org, Toshi Kani Subject: [PATCH v2 3/6] x86/mtrr: Fix Xorg crashes in Qemu sessions Date: Wed, 16 Mar 2016 18:46:56 -0600 Message-Id: <1458175619-32206-2-git-send-email-toshi.kani@hpe.com> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1458175619-32206-1-git-send-email-toshi.kani@hpe.com> References: <1458175619-32206-1-git-send-email-toshi.kani@hpe.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 4906 Lines: 136 A Xorg failure on qemu32 was reported as a regression caused by 'commit 9cd25aac1f44 ("x86/mm/pat: Emulate PAT when it is disabled")'. [1] This patch fixes the regression. Negative effects of this regression were two failures in Xorg on qemu32 env, which were triggered by the fact that its virtual CPU does not support MTRR. [2] #1. copy_process() failed in the check in reserve_pfn_range() copy_process copy_mm dup_mm dup_mmap copy_page_range track_pfn_copy reserve_pfn_range #2. error path in copy_process() then hit WARN_ON_ONCE in untrack_pfn(). x86/PAT: Xorg:509 map pfn expected mapping type uncached- minus for [mem 0xfd000000-0xfdffffff], got write-combining Call Trace: dump_stack+0x58/0x79 warn_slowpath_common+0x8b/0xc0 ? untrack_pfn+0x9f/0xb0 ? untrack_pfn+0x9f/0xb0 warn_slowpath_null+0x22/0x30 untrack_pfn+0x9f/0xb0 ? __kunmap_atomic+0x54/0x110 unmap_single_vma+0x56f/0x580 ? pagevec_move_tail_fn+0xa0/0xa0 unmap_vmas+0x43/0x60 exit_mmap+0x5f/0xf0 mmput+0x2d/0xa0 copy_process.part.47+0x1229/0x1430 _do_fork+0xb4/0x3b0 SyS_clone+0x2c/0x30 do_syscall_32_irqs_on+0x54/0xb0 entry_INT80_32+0x2a/0x2a These negative effects are caused by two separate bugs, but they can be dealt in lower priority. Fixing the pat_init() issue below avoids Xorg to hit these cases. When the CPU does not support MTRR, MTRR does not call pat_init(), which leaves PAT enabled without initializing PAT. This pat_init() issue is a long-standing issue, but manifested as issue #1 (and then hit issue #2) with the commit because the memtype now tracks cache attribute with 'page_cache_mode'. A WC map request is tracked as WC in memtype, but sets a PTE as UC (pgprot) per __cachemode2pte_tbl[]. This caused the error in reserve_pfn_range() when it was called from track_pfn_copy(), which obtained pgprot from a PTE. It converts pgprot to page_cache_mode, which does not necessarily result in the original page_cache_mode since __cachemode2pte_tbl[] redirects multiple types to UC. This is a separate issue in reserve_pfn_range(). This pat_init() issue existed before the commit, but we used pgprot in memtype. Hence, we did not have issue #1 before. But WC request resulted in WT in effect because WC pgrot is actually WT when PAT is not initialized. This is not how it was designed to work. When PAT is set to disable properly, WC is converted to UC. The use of WT can result in a system crash if the target range does not support WT. Fortunately, nobody ran into such issue before. To fix this pat_init() issue, PAT code has been enhanced to provide pat_disable() interface, which disables the OS to initialize PAT MSR, and sets PAT table to the BIOS handoff state. This patch changes MTRR code to call pat_disable() when MTRR is disabled as PAT cannot be initialized in this case. This sets PAT to disable properly, and makes PAT code to bypass the memtype check. This avoids issue #1 (which can be dealt in lower priority). [1]: https://lkml.org/lkml/2016/3/3/828 [2]: https://lkml.org/lkml/2016/3/4/775 Signed-off-by: Toshi Kani Cc: Borislav Petkov Cc: Luis R. Rodriguez Cc: Juergen Gross Cc: Ingo Molnar Cc: H. Peter Anvin Cc: Thomas Gleixner --- arch/x86/include/asm/mtrr.h | 6 +++++- arch/x86/kernel/cpu/mtrr/main.c | 10 +++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h index b94f6f6..634c593 100644 --- a/arch/x86/include/asm/mtrr.h +++ b/arch/x86/include/asm/mtrr.h @@ -24,6 +24,7 @@ #define _ASM_X86_MTRR_H #include +#include /* @@ -83,9 +84,12 @@ static inline int mtrr_trim_uncached_memory(unsigned long end_pfn) static inline void mtrr_centaur_report_mcr(int mcr, u32 lo, u32 hi) { } +static inline void mtrr_bp_init(void) +{ + pat_disable("Skip PAT initialization"); +} #define mtrr_ap_init() do {} while (0) -#define mtrr_bp_init() do {} while (0) #define set_mtrr_aps_delayed_init() do {} while (0) #define mtrr_aps_init() do {} while (0) #define mtrr_bp_restore() do {} while (0) diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index 10f8d47..2d7d8d7 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -759,8 +759,16 @@ void __init mtrr_bp_init(void) } } - if (!mtrr_enabled()) + if (!mtrr_enabled()) { pr_info("MTRR: Disabled\n"); + + /* + * PAT initialization relies on MTRR's rendezvous handler. + * Skip PAT init until the handler can initialize both + * features independently. + */ + pat_disable("Skip PAT initialization"); + } } void mtrr_ap_init(void)