Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934402AbcCKDxY (ORCPT ); Thu, 10 Mar 2016 22:53:24 -0500 Received: from g4t3426.houston.hp.com ([15.201.208.54]:20805 "EHLO g4t3426.houston.hp.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S934232AbcCKDxV (ORCPT ); Thu, 10 Mar 2016 22:53:21 -0500 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, x86@kernel.org, linux-kernel@vger.kernel.org, Toshi Kani Subject: [PATCH 2/2] x86/mtrr: Refactor PAT initialization code Date: Thu, 10 Mar 2016 21:45:46 -0700 Message-Id: <1457671546-13486-3-git-send-email-toshi.kani@hpe.com> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1457671546-13486-1-git-send-email-toshi.kani@hpe.com> References: <1457671546-13486-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: 5463 Lines: 174 MTRR manages PAT initialization as it implements a rendezvous handler that initializes PAT as part of MTRR initialization. When CPU does not support MTRR, ex. qemu32 virtual CPU, MTRR simply skips PAT init, which causes PAT left enabled without initialization. Also, get_mtrr_state() calls pat_init() on BSP even if MTRR is disabled by its MSR. This causes pat_init() be called on BSP only. The following changes are made to address these issues: - Move BSP's PAT init code to mtrr_bp_pat_init(), and change mtrr_bp_init() to call it if MTRR is enabled. This keeps the init condition consistent with mtrr_ap_init() and mtrr_aps_init() for APs. - Change mtrr_bp_init() to call pat_disable() when MTRR is disabled. - Change mtrr_bp_init() stub function to call pat_disable() when CONFIG_MTRR is unset. The table below discribes how PAT is initialized in all possible cases. Legend ---------------------------- E Enabled in CPU feature and MSR D Disabled in CPU feature or MSR nopat "nopat" boot option specified !PAT CONFIG_X86_PAT unset !MTRR CONFIG_MTRR unset MTRR PAT ACTION ==================================================================== E E MTRR calls pat_init() -> PAT enabled E D MTRR calls pat_init() -> PAT disabled per cpu_has_pat D E MTRR calls pat_disable() -> PAT disabled (*) D D MTRR calls pat_disable() -> PAT disabled E nopat nopat() calls pat_disable() -> PAT disabled D nopat nopat() calls pat_disable() -> PAT disabled E !PAT MTRR calls pat_init() -> PAT disabled per __pat_enabled D !PAT MTRR calls pat_disable() -> PAT disabled !MTRR !PAT mtrr_bp_init() stub calls pat_disable() -> PAT disabled (*) Further enhancement may enable PAT if needed 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/generic.c | 24 ++++++++++++++---------- arch/x86/kernel/cpu/mtrr/main.c | 13 ++++++++++++- arch/x86/kernel/cpu/mtrr/mtrr.h | 1 + 4 files changed, 32 insertions(+), 12 deletions(-) diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h index b94f6f6..a965e74 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("PAT disabled by MTRR"); +} #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/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c index c870af1..136ae86 100644 --- a/arch/x86/kernel/cpu/mtrr/generic.c +++ b/arch/x86/kernel/cpu/mtrr/generic.c @@ -444,11 +444,24 @@ static void __init print_mtrr_state(void) pr_debug("TOM2: %016llx aka %lldM\n", mtrr_tom2, mtrr_tom2>>20); } +/* PAT setup for BP. We need to go through sync steps here */ +void __init mtrr_bp_pat_init(void) +{ + unsigned long flags; + + local_irq_save(flags); + prepare_set(); + + pat_init(); + + post_set(); + local_irq_restore(flags); +} + /* Grab all of the MTRR state for this CPU into *state */ bool __init get_mtrr_state(void) { struct mtrr_var_range *vrs; - unsigned long flags; unsigned lo, dummy; unsigned int i; @@ -481,15 +494,6 @@ bool __init get_mtrr_state(void) mtrr_state_set = 1; - /* PAT setup for BP. We need to go through sync steps here */ - local_irq_save(flags); - prepare_set(); - - pat_init(); - - post_set(); - local_irq_restore(flags); - return !!(mtrr_state.enabled & MTRR_STATE_MTRR_ENABLED); } diff --git a/arch/x86/kernel/cpu/mtrr/main.c b/arch/x86/kernel/cpu/mtrr/main.c index 5c3d149..d9e91f1 100644 --- a/arch/x86/kernel/cpu/mtrr/main.c +++ b/arch/x86/kernel/cpu/mtrr/main.c @@ -752,6 +752,9 @@ void __init mtrr_bp_init(void) /* BIOS may override */ __mtrr_enabled = get_mtrr_state(); + if (mtrr_enabled()) + mtrr_bp_pat_init(); + if (mtrr_cleanup(phys_addr)) { changed_by_mtrr_cleanup = 1; mtrr_if->set_all(); @@ -759,8 +762,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. + * Disable PAT until the handler can initialize both features + * independently. + */ + pat_disable("PAT disabled by MTRR"); + } } void mtrr_ap_init(void) diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.h b/arch/x86/kernel/cpu/mtrr/mtrr.h index 951884d..6c7ced0 100644 --- a/arch/x86/kernel/cpu/mtrr/mtrr.h +++ b/arch/x86/kernel/cpu/mtrr/mtrr.h @@ -52,6 +52,7 @@ void set_mtrr_prepare_save(struct set_mtrr_context *ctxt); void fill_mtrr_var_range(unsigned int index, u32 base_lo, u32 base_hi, u32 mask_lo, u32 mask_hi); bool get_mtrr_state(void); +void mtrr_bp_pat_init(void); extern void set_mtrr_ops(const struct mtrr_ops *ops);