x86/smp: Split sending INIT IPI out into a helper function

Putting CPUs into INIT is a safer place during kexec() to park CPUs.

Split the INIT assert/deassert sequence out so it can be reused.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Ashok Raj <ashok.raj@intel.com>
Link: https://lore.kernel.org/r/20230615193330.551157083@linutronix.de

+20 -29
+20 -29
arch/x86/kernel/smpboot.c
··· 853 853 return (send_status | accept_status); 854 854 } 855 855 856 - static int 857 - wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip) 856 + static void send_init_sequence(int phys_apicid) 858 857 { 859 - unsigned long send_status = 0, accept_status = 0; 860 - int maxlvt, num_starts, j; 858 + int maxlvt = lapic_get_maxlvt(); 861 859 862 - maxlvt = lapic_get_maxlvt(); 863 - 864 - /* 865 - * Be paranoid about clearing APIC errors. 866 - */ 860 + /* Be paranoid about clearing APIC errors. */ 867 861 if (APIC_INTEGRATED(boot_cpu_apic_version)) { 868 - if (maxlvt > 3) /* Due to the Pentium erratum 3AP. */ 862 + /* Due to the Pentium erratum 3AP. */ 863 + if (maxlvt > 3) 869 864 apic_write(APIC_ESR, 0); 870 865 apic_read(APIC_ESR); 871 866 } 872 867 873 - pr_debug("Asserting INIT\n"); 874 - 875 - /* 876 - * Turn INIT on target chip 877 - */ 878 - /* 879 - * Send IPI 880 - */ 881 - apic_icr_write(APIC_INT_LEVELTRIG | APIC_INT_ASSERT | APIC_DM_INIT, 882 - phys_apicid); 883 - 884 - pr_debug("Waiting for send to finish...\n"); 885 - send_status = safe_apic_wait_icr_idle(); 868 + /* Assert INIT on the target CPU */ 869 + apic_icr_write(APIC_INT_LEVELTRIG | APIC_INT_ASSERT | APIC_DM_INIT, phys_apicid); 870 + safe_apic_wait_icr_idle(); 886 871 887 872 udelay(init_udelay); 888 873 889 - pr_debug("Deasserting INIT\n"); 890 - 891 - /* Target chip */ 892 - /* Send IPI */ 874 + /* Deassert INIT on the target CPU */ 893 875 apic_icr_write(APIC_INT_LEVELTRIG | APIC_DM_INIT, phys_apicid); 876 + safe_apic_wait_icr_idle(); 877 + } 894 878 895 - pr_debug("Waiting for send to finish...\n"); 896 - send_status = safe_apic_wait_icr_idle(); 879 + /* 880 + * Wake up AP by INIT, INIT, STARTUP sequence. 881 + */ 882 + static int wakeup_secondary_cpu_via_init(int phys_apicid, unsigned long start_eip) 883 + { 884 + unsigned long send_status = 0, accept_status = 0; 885 + int num_starts, j, maxlvt = lapic_get_maxlvt(); 886 + 887 + send_init_sequence(phys_apicid); 897 888 898 889 mb(); 899 890