From: Quanyang Wang <[email protected]>
When kernel booting, it will create a cpuid map between the logical cpus
and physical cpus. In a normal boot, the cpuid map is as below:
Physical Logical
0 ==> 0
1 ==> 1
But in kdump, there is a condition that the crash happens at the
physical cpu1, and the crash kernel will run at the physical cpu1 too,
so the cpuid map in crash kernel is as below:
Physical Logical
1 ==> 0
0 ==> 1
The functions zynq_slcr_cpu_stop/start is to stop/start the physical
cpus, the parameter cpu should be the physical cpuid. So use
cpu_logical_map to translate the logical cpuid to physical cpuid.
Or else the logical cpu0(physical cpu1) will stop itself and
the processor will hang.
Signed-off-by: Quanyang Wang <[email protected]>
Signed-off-by: Michal Simek <[email protected]>
---
arch/arm/mach-zynq/platsmp.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-zynq/platsmp.c b/arch/arm/mach-zynq/platsmp.c
index a10085be9073..68ec303fa278 100644
--- a/arch/arm/mach-zynq/platsmp.c
+++ b/arch/arm/mach-zynq/platsmp.c
@@ -15,6 +15,7 @@
#include <linux/init.h>
#include <linux/io.h>
#include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
#include <asm/smp_scu.h>
#include <linux/irqchip/arm-gic.h>
#include "common.h"
@@ -30,6 +31,7 @@ int zynq_cpun_start(u32 address, int cpu)
{
u32 trampoline_code_size = &zynq_secondary_trampoline_end -
&zynq_secondary_trampoline;
+ u32 phy_cpuid = cpu_logical_map(cpu);
/* MS: Expectation that SLCR are directly map and accessible */
/* Not possible to jump to non aligned address */
@@ -39,7 +41,7 @@ int zynq_cpun_start(u32 address, int cpu)
u32 trampoline_size = &zynq_secondary_trampoline_jump -
&zynq_secondary_trampoline;
- zynq_slcr_cpu_stop(cpu);
+ zynq_slcr_cpu_stop(phy_cpuid);
if (address) {
if (__pa(PAGE_OFFSET)) {
zero = ioremap(0, trampoline_code_size);
@@ -68,7 +70,7 @@ int zynq_cpun_start(u32 address, int cpu)
if (__pa(PAGE_OFFSET))
iounmap(zero);
}
- zynq_slcr_cpu_start(cpu);
+ zynq_slcr_cpu_start(phy_cpuid);
return 0;
}
--
2.17.1
st 23. 10. 2019 v 12:57 odesÃlatel Michal Simek
<[email protected]> napsal:
>
> From: Quanyang Wang <[email protected]>
>
> When kernel booting, it will create a cpuid map between the logical cpus
> and physical cpus. In a normal boot, the cpuid map is as below:
>
> Physical Logical
> 0 ==> 0
> 1 ==> 1
>
> But in kdump, there is a condition that the crash happens at the
> physical cpu1, and the crash kernel will run at the physical cpu1 too,
> so the cpuid map in crash kernel is as below:
>
> Physical Logical
> 1 ==> 0
> 0 ==> 1
>
> The functions zynq_slcr_cpu_stop/start is to stop/start the physical
> cpus, the parameter cpu should be the physical cpuid. So use
> cpu_logical_map to translate the logical cpuid to physical cpuid.
> Or else the logical cpu0(physical cpu1) will stop itself and
> the processor will hang.
>
> Signed-off-by: Quanyang Wang <[email protected]>
> Signed-off-by: Michal Simek <[email protected]>
> ---
>
> arch/arm/mach-zynq/platsmp.c | 6 ++++--
> 1 file changed, 4 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm/mach-zynq/platsmp.c b/arch/arm/mach-zynq/platsmp.c
> index a10085be9073..68ec303fa278 100644
> --- a/arch/arm/mach-zynq/platsmp.c
> +++ b/arch/arm/mach-zynq/platsmp.c
> @@ -15,6 +15,7 @@
> #include <linux/init.h>
> #include <linux/io.h>
> #include <asm/cacheflush.h>
> +#include <asm/smp_plat.h>
> #include <asm/smp_scu.h>
> #include <linux/irqchip/arm-gic.h>
> #include "common.h"
> @@ -30,6 +31,7 @@ int zynq_cpun_start(u32 address, int cpu)
> {
> u32 trampoline_code_size = &zynq_secondary_trampoline_end -
> &zynq_secondary_trampoline;
> + u32 phy_cpuid = cpu_logical_map(cpu);
>
> /* MS: Expectation that SLCR are directly map and accessible */
> /* Not possible to jump to non aligned address */
> @@ -39,7 +41,7 @@ int zynq_cpun_start(u32 address, int cpu)
> u32 trampoline_size = &zynq_secondary_trampoline_jump -
> &zynq_secondary_trampoline;
>
> - zynq_slcr_cpu_stop(cpu);
> + zynq_slcr_cpu_stop(phy_cpuid);
> if (address) {
> if (__pa(PAGE_OFFSET)) {
> zero = ioremap(0, trampoline_code_size);
> @@ -68,7 +70,7 @@ int zynq_cpun_start(u32 address, int cpu)
> if (__pa(PAGE_OFFSET))
> iounmap(zero);
> }
> - zynq_slcr_cpu_start(cpu);
> + zynq_slcr_cpu_start(phy_cpuid);
>
> return 0;
> }
> --
> 2.17.1
>
Tested-by: Michal Simek <[email protected]>
Applied,
Michal
--
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: http://www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Xilinx Microblaze
Maintainer of Linux kernel - Xilinx Zynq ARM and ZynqMP ARM64 SoCs
U-Boot custodian - Xilinx Microblaze/Zynq/ZynqMP/Versal SoCs