Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751731AbeAEEin (ORCPT + 1 other); Thu, 4 Jan 2018 23:38:43 -0500 Received: from mx1.redhat.com ([209.132.183.28]:37018 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751640AbeAEEim (ORCPT ); Thu, 4 Jan 2018 23:38:42 -0500 Date: Fri, 5 Jan 2018 12:38:38 +0800 From: Baoquan He To: linux-kernel@vger.kernel.org Cc: mingo@redhat.com, tglx@linutronix.de, hpa@zytor.com, x86@kernel.org, douly.fnst@cn.fujitsu.com, rostedt@goodmis.org, jgross@suse.com, peterz@infradead.org, uobergfe@redhat.com, joro@8bytes.org Subject: [RESEND PATCH 2/3] x86/apic/kexec: Enable legacy irq mode before jump to kexec/kdump kernel Message-ID: <20180105043838.GK7235@x1> References: <1515123732-28908-1-git-send-email-bhe@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <1515123732-28908-1-git-send-email-bhe@redhat.com> User-Agent: Mutt/1.7.0 (2016-08-17) X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Fri, 05 Jan 2018 04:38:42 +0000 (UTC) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Return-Path: In commit commit 522e66464467 ("x86/apic: Disable I/O APIC before shutdown of the local APIC"). lapic_shutdown() invocation is moved after disable_IO_APIC(). In fact in disable_IO_APIC(), it not only calls clear_IO_APIC() to disable IO-APIC, also sets sets LAPIC and IO-APIC to make system be PIC or Virtual wire mode. While the above commit putting disable_IO_APIC earlier causes local APIC is completely disabled. So the legacy irq mode is disabled too before jump to kexec/kdump kernel. In normal kernel it defaults to be PIC mode or Virtual Wire mode during system initialization before APIC mode is enabled and this is done by BIOS initialization. But kexec/kdump kernel won't go through BIOS, so we should set system as PIC or Virtual Wire mode before jump to kdump kernel code directly. So let's take clear_IO_APIC out from disable_IO_APIC and rename disable_IO_APIC as switch_to_legacy_irq_mode. Then only call clear_IO_APIC when IO-APIC need be disabled. And call switch_to_legacy_irq_mode before kexec/kdump jumping. Signed-off-by: Baoquan He --- arch/x86/include/asm/io_apic.h | 3 ++- arch/x86/kernel/apic/io_apic.c | 12 ++++-------- arch/x86/kernel/crash.c | 2 +- arch/x86/kernel/machine_kexec_32.c | 15 +++++---------- arch/x86/kernel/machine_kexec_64.c | 15 +++++---------- arch/x86/kernel/reboot.c | 2 +- 6 files changed, 18 insertions(+), 31 deletions(-) diff --git a/arch/x86/include/asm/io_apic.h b/arch/x86/include/asm/io_apic.h index a8834dd546cd..e38ad3863a2c 100644 --- a/arch/x86/include/asm/io_apic.h +++ b/arch/x86/include/asm/io_apic.h @@ -192,7 +192,8 @@ static inline unsigned int io_apic_read(unsigned int apic, unsigned int reg) extern void setup_IO_APIC(void); extern void enable_IO_APIC(void); -extern void disable_IO_APIC(void); +extern void clear_IO_APIC (void); +extern void switch_to_legacy_irq_mode(void); extern int IO_APIC_get_PCI_irq_vector(int bus, int devfn, int pin); extern void print_IO_APICs(void); #else /* !CONFIG_X86_IO_APIC */ diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 8a7963421460..a47aa915d18c 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c @@ -587,7 +587,7 @@ static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin) mpc_ioapic_id(apic), pin); } -static void clear_IO_APIC (void) +void clear_IO_APIC (void) { int apic, pin; @@ -1439,15 +1439,11 @@ void native_disable_io_apic(void) } /* - * Not an __init, needed by the reboot code + * Not an __init, needed by kexec/kdump code. + * For safety IO-APIC and Local APIC need be cleared before this. */ -void disable_IO_APIC(void) +void switch_to_legacy_irq_mode(void) { - /* - * Clear the IO-APIC before rebooting: - */ - clear_IO_APIC(); - if (!nr_legacy_irqs()) return; diff --git a/arch/x86/kernel/crash.c b/arch/x86/kernel/crash.c index 10e74d4778a1..318ffeaaf55a 100644 --- a/arch/x86/kernel/crash.c +++ b/arch/x86/kernel/crash.c @@ -199,7 +199,7 @@ void native_machine_crash_shutdown(struct pt_regs *regs) #ifdef CONFIG_X86_IO_APIC /* Prevent crash_kexec() from deadlocking on ioapic_lock. */ ioapic_zap_locks(); - disable_IO_APIC(); + clear_IO_APIC(); #endif lapic_shutdown(); #ifdef CONFIG_HPET_TIMER diff --git a/arch/x86/kernel/machine_kexec_32.c b/arch/x86/kernel/machine_kexec_32.c index edfede768688..7ab10d930cc6 100644 --- a/arch/x86/kernel/machine_kexec_32.c +++ b/arch/x86/kernel/machine_kexec_32.c @@ -190,18 +190,13 @@ void machine_kexec(struct kimage *image) local_irq_disable(); hw_breakpoint_disable(); - if (image->preserve_context) { #ifdef CONFIG_X86_IO_APIC - /* - * We need to put APICs in legacy mode so that we can - * get timer interrupts in second kernel. kexec/kdump - * paths already have calls to disable_IO_APIC() in - * one form or other. kexec jump path also need - * one. - */ - disable_IO_APIC(); + /* + * We need to put APICs in legacy mode so that we can + * get timer interrupts in second kernel. + */ + switch_to_legacy_irq_mode(); #endif - } control_page = page_address(image->control_code_page); memcpy(control_page, relocate_kernel, KEXEC_CONTROL_CODE_MAX_SIZE); diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c index 1f790cf9d38f..b5c0cbed6791 100644 --- a/arch/x86/kernel/machine_kexec_64.c +++ b/arch/x86/kernel/machine_kexec_64.c @@ -288,18 +288,13 @@ void machine_kexec(struct kimage *image) local_irq_disable(); hw_breakpoint_disable(); - if (image->preserve_context) { #ifdef CONFIG_X86_IO_APIC - /* - * We need to put APICs in legacy mode so that we can - * get timer interrupts in second kernel. kexec/kdump - * paths already have calls to disable_IO_APIC() in - * one form or other. kexec jump path also need - * one. - */ - disable_IO_APIC(); + /* + * We need to put APICs in legacy mode so that we can + * get timer interrupts in second kernel. + */ + switch_to_legacy_irq_mode(); #endif - } control_page = page_address(image->control_code_page) + PAGE_SIZE; memcpy(control_page, relocate_kernel, KEXEC_CONTROL_CODE_MAX_SIZE); diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 2126b9d27c34..b70cc0f38a29 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -666,7 +666,7 @@ void native_machine_shutdown(void) * Even without the erratum, it still makes sense to quiet IO APIC * before disabling Local APIC. */ - disable_IO_APIC(); + clear_IO_APIC(); #endif #ifdef CONFIG_SMP -- 2.5.5