From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756831AbcKCOv5 (ORCPT ); Thu, 3 Nov 2016 10:51:57 -0400 Received: from Galois.linutronix.de ([146.0.238.70]:35476 "EHLO Galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932502AbcKCOvI (ORCPT ); Thu, 3 Nov 2016 10:51:08 -0400 From: Sebastian Andrzej Siewior To: linux-kernel@vger.kernel.org Cc: rt@linutronix.de, Sebastian Andrzej Siewior , Tony Luck , Borislav Petkov , linux-edac@vger.kernel.org, x86@kernel.org, Thomas Gleixner Subject: [PATCH 22/25] x86/mcheck: Do the init in one place Date: Thu, 3 Nov 2016 15:50:18 +0100 Message-Id: <20161103145021.28528-23-bigeasy@linutronix.de> X-Mailer: git-send-email 2.10.2 In-Reply-To: <20161103145021.28528-1-bigeasy@linutronix.de> References: <20161103145021.28528-1-bigeasy@linutronix.de> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Part of the init (memory allocation and so on) is done in mcheck_cpu_init(). While moving the the allocation to mcheck_init_device() (where the hotplug calls are initialized) it becomes necessary to move the callback (mcheck_cpu_init()), too. The callback is now removed from identify_cpu() and registered as a hotplug event which is invoked as the very first one which is shortly after the original point of invocation (look at smp_store_cpu_info() and notify_cpu_starting() in smp_callin()). One "visible" difference is that MCE for the boot CPU is not enabled at identify_boot_cpu() time but at device_initcall_sync() time. Either way, both times we had no userland around. Cc: Tony Luck Cc: Borislav Petkov Cc: linux-edac@vger.kernel.org Cc: x86@kernel.org Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Thomas Gleixner --- arch/x86/include/asm/mce.h | 2 -- arch/x86/kernel/cpu/common.c | 4 --- arch/x86/kernel/cpu/mcheck/mce.c | 77 ++++++++++++++++++++++++------------= ---- include/linux/cpuhotplug.h | 1 + 4 files changed, 48 insertions(+), 36 deletions(-) diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h index 978be74a12c1..ba8108166aec 100644 --- a/arch/x86/include/asm/mce.h +++ b/arch/x86/include/asm/mce.h @@ -203,12 +203,10 @@ extern int mce_p5_enabled; =20 #ifdef CONFIG_X86_MCE int mcheck_init(void); -void mcheck_cpu_init(struct cpuinfo_x86 *c); void mcheck_cpu_clear(struct cpuinfo_x86 *c); void mcheck_vendor_init_severity(void); #else static inline int mcheck_init(void) { return 0; } -static inline void mcheck_cpu_init(struct cpuinfo_x86 *c) {} static inline void mcheck_cpu_clear(struct cpuinfo_x86 *c) {} static inline void mcheck_vendor_init_severity(void) {} #endif diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index 9bd910a7dd0a..283b1fa64e69 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include @@ -1095,9 +1094,6 @@ static void identify_cpu(struct cpuinfo_x86 *c) c->x86_capability[i] |=3D boot_cpu_data.x86_capability[i]; } =20 - /* Init Machine Check Exception if available. */ - mcheck_cpu_init(c); - select_idle_routine(c); =20 #ifdef CONFIG_NUMA diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/= mce.c index 79b5ad9570ca..72af9db8526d 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -1436,11 +1436,24 @@ EXPORT_SYMBOL_GPL(mce_notify_irq); static int __mcheck_cpu_mce_banks_init(void) { int i; - u8 num_banks =3D mca_cfg.banks; + u64 cap; + unsigned int num_banks; + + rdmsrl(MSR_IA32_MCG_CAP, cap); + + num_banks =3D cap & MCG_BANKCNT_MASK; + pr_info("CPU supports %d MCE banks\n", num_banks); + + if (num_banks > MAX_NR_BANKS) { + pr_warn("Using only %u machine check banks out of %u\n", + MAX_NR_BANKS, num_banks); + num_banks =3D MAX_NR_BANKS; + } =20 mce_banks =3D kzalloc(num_banks * sizeof(struct mce_bank), GFP_KERNEL); if (!mce_banks) return -ENOMEM; + mca_cfg.banks =3D num_banks; =20 for (i =3D 0; i < num_banks; i++) { struct mce_bank *b =3D &mce_banks[i]; @@ -1462,25 +1475,11 @@ static int __mcheck_cpu_cap_init(void) rdmsrl(MSR_IA32_MCG_CAP, cap); =20 b =3D cap & MCG_BANKCNT_MASK; - if (!mca_cfg.banks) - pr_info("CPU supports %d MCE banks\n", b); - - if (b > MAX_NR_BANKS) { - pr_warn("Using only %u machine check banks out of %u\n", - MAX_NR_BANKS, b); + if (b > MAX_NR_BANKS) b =3D MAX_NR_BANKS; - } =20 /* Don't support asymmetric configurations today */ - WARN_ON(mca_cfg.banks !=3D 0 && b !=3D mca_cfg.banks); - mca_cfg.banks =3D b; - - if (!mce_banks) { - int err =3D __mcheck_cpu_mce_banks_init(); - - if (err) - return err; - } + WARN_ON(b !=3D mca_cfg.banks); =20 /* Use accurate RIP reporting if available. */ if ((cap & MCG_EXT_P) && MCG_EXT_CNT(cap) >=3D 9) @@ -1769,26 +1768,22 @@ void (*machine_check_vector)(struct pt_regs *, long= error_code) =3D * Called for each booted CPU to set up machine checks. * Must be called with preempt off: */ -void mcheck_cpu_init(struct cpuinfo_x86 *c) +static int mcheck_cpu_starting(unsigned int cpu) { + struct cpuinfo_x86 *c =3D &cpu_data(cpu); + if (mca_cfg.disabled) - return; + return 0; =20 if (__mcheck_cpu_ancient_init(c)) - return; + return 0; =20 if (!mce_available(c)) - return; + return 0; =20 if (__mcheck_cpu_cap_init() < 0 || __mcheck_cpu_apply_quirks(c) < 0) { mca_cfg.disabled =3D true; - return; - } - - if (mce_gen_pool_init()) { - mca_cfg.disabled =3D true; - pr_emerg("Couldn't allocate MCE records pool!\n"); - return; + return 0; } =20 machine_check_vector =3D do_machine_check; @@ -1797,6 +1792,7 @@ void mcheck_cpu_init(struct cpuinfo_x86 *c) __mcheck_cpu_init_vendor(c); __mcheck_cpu_init_clear_banks(); __mcheck_cpu_init_timer(); + return 0; } =20 /* @@ -2584,11 +2580,26 @@ static __init int mcheck_init_device(void) goto err_out; } =20 + err =3D __mcheck_cpu_mce_banks_init(); + if (err) + goto err_out_mem; + mce_init_banks(); =20 + err =3D mce_gen_pool_init(); + if (err) { + pr_emerg("Couldn't allocate MCE records pool!\n"); + goto err_init_pool; + } + err =3D subsys_system_register(&mce_subsys, NULL); if (err) - goto err_out_mem; + goto err_init_pool; + + err =3D cpuhp_setup_state(CPUHP_AP_X86_MCE_STARTING, "x86/mce:starting", + mcheck_cpu_starting, NULL); + if (err) + goto err_init_pool; =20 cpu_notifier_register_begin(); for_each_online_cpu(i) { @@ -2630,12 +2641,18 @@ static __init int mcheck_init_device(void) for_each_possible_cpu(i) mce_device_remove(i); =20 + cpuhp_remove_state(CPUHP_AP_X86_MCE_STARTING); + +err_init_pool: + mca_cfg.banks =3D 0; + kfree(mce_banks); + mce_banks =3D NULL; + err_out_mem: free_cpumask_var(mce_device_initialized); =20 err_out: pr_err("Unable to init device /dev/mcelog (rc: %d)\n", err); - return err; } device_initcall_sync(mcheck_init_device); diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h index 3410d83cc2e2..4fe2ba418471 100644 --- a/include/linux/cpuhotplug.h +++ b/include/linux/cpuhotplug.h @@ -64,6 +64,7 @@ enum cpuhp_state { CPUHP_BRINGUP_CPU, CPUHP_AP_IDLE_DEAD, CPUHP_AP_OFFLINE, + CPUHP_AP_X86_MCE_STARTING, CPUHP_AP_SCHED_STARTING, CPUHP_AP_RCUTREE_DYING, CPUHP_AP_IRQ_GIC_STARTING, --=20 2.10.2