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