From: root <root(a)localhost.localdomain>
---
 arch/arm64/include/asm/cputype.h           |  3 +++
 arch/arm64/include/asm/machine_types.h     | 39 ++++++++++++++++++++++++++++++
 arch/arm64/kernel/smp.c                    | 30 +++++++++++++++++++++++
 drivers/irqchip/irq-gic-phytium-2500-its.c | 37 ++++++++++++++++++++++++++++
 drivers/irqchip/irq-gic-phytium-2500.c     | 21 ++++++++++++++++
 5 files changed, 130 insertions(+)
 create mode 100644 arch/arm64/include/asm/machine_types.h
diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
index ef5b040..b5d815d 100644
--- a/arch/arm64/include/asm/cputype.h
+++ b/arch/arm64/include/asm/cputype.h
@@ -133,6 +133,9 @@
 #define MIDR_FUJITSU_ERRATUM_010001_MASK	(~MIDR_CPU_VAR_REV(1, 0))
 #define TCR_CLEAR_FUJITSU_ERRATUM_010001	(TCR_NFD1 | TCR_NFD0)
 
+#define PHYTIUM_CPU_PART_2500           0X663
+#define MIDR_FT_2500     MIDR_CPU_MODEL(ARM_CPU_IMP_PHYTIUM, PHYTIUM_CPU_PART_2500)
+
 #ifndef __ASSEMBLY__
 
 #include <asm/sysreg.h>
diff --git a/arch/arm64/include/asm/machine_types.h
b/arch/arm64/include/asm/machine_types.h
new file mode 100644
index 0000000..b1d2db5
--- /dev/null
+++ b/arch/arm64/include/asm/machine_types.h
@@ -0,0 +1,39 @@
+/*
+ *  Authors: Wang Yinfeng <wangyinfenng(a)phytium.com.cn>
+ *
+ *  Copyright (C) 2021, PHYTIUM Information Technology Co., Ltd.
+ *
+ *  This library is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public
+ *  License as published by the Free Software Foundation; either
+ *  version 2 of the License, or (at your option) any later version.
+ *
+ *  This library is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this library; if not, write to the
+ *  Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ *  Boston, MA 02110-1301, USA.
+ */
+
+#ifndef _MACHINE_TYPE_H_
+#define _MACHINE_TYPE_H_
+
+#include <asm/cputype.h>
+#include <linux/types.h>
+
+static inline bool phytium_part(u32 cpuid)
+{
+	return ((read_cpuid_id() & MIDR_CPU_MODEL_MASK) == cpuid);
+}
+
+#define typeof_ft1500a()	phytium_part(MIDR_FT_1500A)
+#define typeof_ft2000ahk()	phytium_part(MIDR_FT_2000AHK)
+#define typeof_ft2000plus()	phytium_part(MIDR_FT_2000PLUS)
+#define typeof_ft2004()	    phytium_part(MIDR_FT_2004)
+#define typeof_s2500()		phytium_part(MIDR_FT_2500)
+
+#endif
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 18e9727..c6d59bc 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -33,6 +33,8 @@
 #include <linux/kernel_stat.h>
 #include <linux/kexec.h>
 #include <linux/kvm_host.h>
+#include <linux/perf/arm_pmu.h>
+#include <linux/crash_dump.h>
 
 #include <asm/alternative.h>
 #include <asm/atomic.h>
@@ -530,6 +532,29 @@ static int __init smp_cpu_setup(int cpu)
 static bool bootcpu_valid __initdata;
 static unsigned int cpu_count = 1;
 
+#ifdef CONFIG_ARCH_PHYTIUM
+/*
+ * On phytium S2500 multi-socket server, for example 2-socket(2P), there are
+ * socekt0 and socket1 on the server:
+ * If storage device(like SAS controller and disks to save vmcore into) is
+ * installed on socket1 and second kernel brings up 2 CPUs both on socket0 with
+ * nr_cpus=2, then vmcore will fail to be saved into the disk.
+ * To avoid this issue, Bypass other non-cpu0 to ensure that each cpu0 on each
+ * socket can bootup and handle interrupt when booting the second kernel.
+ */
+static bool __init is_phytium_kdump_cpu_need_bypass(u64 hwid)
+{
+	if ((read_cpuid_id() & MIDR_CPU_MODEL_MASK) != MIDR_FT_2500)
+		return false;
+	/*Bypass other non-cpu0 to ensure second kernel can bring up each cpu0
+	 * on each socket*/
+	if (is_kdump_kernel() && (hwid & 0xffff) != (cpu_logical_map(0) &
0xffff))
+		return true;
+	return false;
+}
+#endif
+
+
 #ifdef CONFIG_ACPI
 static struct acpi_madt_generic_interrupt cpu_madt_gicc[NR_CPUS];
 
@@ -579,6 +604,11 @@ struct acpi_madt_generic_interrupt *acpi_cpu_get_madt_gicc(int cpu)
 	if (cpu_count >= NR_CPUS)
 		return;
 
+#ifdef CONFIG_ARCH_PHYTIUM
+	if (is_phytium_kdump_cpu_need_bypass(hwid))
+		return;
+#endif
+
 	/* map the logical cpu id to cpu MPIDR */
 	set_cpu_logical_map(cpu_count, hwid);
 
diff --git a/drivers/irqchip/irq-gic-phytium-2500-its.c
b/drivers/irqchip/irq-gic-phytium-2500-its.c
index 26b2349..3fbaafe 100644
--- a/drivers/irqchip/irq-gic-phytium-2500-its.c
+++ b/drivers/irqchip/irq-gic-phytium-2500-its.c
@@ -1677,6 +1677,23 @@ static int its_cpumask_select(struct its_device *its_dev,
     cpu = cpumask_any_and(mask_val, cpu_mask);
     cpus = cpus + cpu % skt_cpu_cnt[skt_id];
 
+    if (is_kdump_kernel()){
+	    skt = (cpu_logical_map(cpu) >> 16) & 0xff;
+	    if(skt_id == skt){
+		    return cpu;
+	    }
+	    for (i = 0; i < nr_cpu_ids; i++) {
+		    skt = (cpu_logical_map(i) >> 16) & 0xff;
+		    if ((skt >= 0) && (skt < MAX_MARS3_SKT_COUNT)) {
+			    if(skt_id == skt){
+				    return i;
+			    }
+		    } else if (0xff != skt ) {
+			    pr_err("socket address: %d is out of range.", skt);
+		    }
+	    }
+    }
+
         return cpus;
 }
 
@@ -3010,6 +3027,9 @@ static bool enabled_lpis_allowed(void)
 	phys_addr_t addr;
 	u64 val;
 
+	if (is_kdump_kernel())
+		return true;
+
 	/* Check whether the property table is in a reserved region */
 	val = gicr_read_propbaser(gic_data_rdist_rd_base() + GICR_PROPBASER);
 	addr = val & GENMASK_ULL(51, 12);
@@ -3653,6 +3673,23 @@ static int its_cpumask_first(struct its_device *its_dev,
         cpus = cpu;
     }
 
+    if (is_kdump_kernel()){
+	    skt = (cpu_logical_map(cpu) >> 16) & 0xff;
+	    if(skt_id == skt){
+		    return cpu;
+	    }
+	    for (i = 0; i < nr_cpu_ids; i++) {
+		    skt = (cpu_logical_map(i) >> 16) & 0xff;
+		    if ((skt >= 0) && (skt < MAX_MARS3_SKT_COUNT)) {
+			    if(skt_id == skt){
+				    return i;
+			    }
+		    } else if (0xff != skt ) {
+			    pr_err("socket address: %d is out of range.", skt);
+		    }
+	    }
+    }
+
     return cpus;
 }
 
diff --git a/drivers/irqchip/irq-gic-phytium-2500.c
b/drivers/irqchip/irq-gic-phytium-2500.c
index d6e198b..f08a9fa 100644
--- a/drivers/irqchip/irq-gic-phytium-2500.c
+++ b/drivers/irqchip/irq-gic-phytium-2500.c
@@ -22,6 +22,7 @@
 #include <linux/acpi.h>
 #include <linux/cpu.h>
 #include <linux/cpu_pm.h>
+#include <linux/crash_dump.h>
 #include <linux/delay.h>
 #include <linux/interrupt.h>
 #include <linux/irqdomain.h>
@@ -1347,6 +1348,23 @@ static int gic_cpumask_select(struct irq_data *d, const struct
cpumask *mask_val
     cpu = cpumask_any_and(mask_val, cpu_online_mask);
     cpus = cpus + cpu % skt_cpu_cnt[irq_skt];
 
+    if (is_kdump_kernel()){
+	    skt = (cpu_logical_map(cpu) >> 16) & 0xff;
+	    if(irq_skt == skt){
+		    return cpu;
+	    }
+	    for (i = 0; i < nr_cpu_ids; i++) {
+		    skt = (cpu_logical_map(i) >> 16) & 0xff;
+		    if ((skt >= 0) && (skt < MAX_MARS3_SOC_COUNT)) {
+			    if(irq_skt == skt){
+				    return i;
+			    }
+		    } else if (0xff != skt ) {
+			    pr_err("socket address: %d is out of range.", skt);
+		    }
+	    }
+    }
+
     return cpus;
 }
 
@@ -2439,6 +2457,9 @@ static void __init gic_acpi_setup_kvm_info(void)
 
 #ifdef CONFIG_ACPI
     mars3_sockets_bitmap = gic_mars3_sockets_bitmap();
+    if (is_kdump_kernel()){
+	    mars3_sockets_bitmap = 0x3;
+    }
     if (mars3_sockets_bitmap == 0){
         mars3_sockets_bitmap = 0x1;
         pr_err("No socket, please check cpus MPIDR_AFFINITY_LEVEL!!!");
-- 
1.8.3.1