If a JTAG probe is connected to a MIPS cluster, then the CPC detects it
and latches the CPC.STAT_CONF.EJTAG_PROBE bit to 1. While set,
attempting to send a power-down command to a core will be blocked, and
the CPC will instead send the core to clock-off state. This can
interfere with systems fully entering a low power state where all
cores, CM, GIC, etc are powered down.
Detect that a JTAG probe is / has been connected to the cluster and
block the suspend attempt.
Attempting to suspend the system while a JTAG probe is connected now
yields:
# echo mem > /sys/power/state
[ 11.654000] PM: Syncing filesystems ... done.
[ 11.658000] JTAG probe is connected - abort suspend
-sh: echo: write error: Operation not permitted
#
To restore suspend, the JTAG probe should be disconnected or put into
quiescent state. Platform code can then clear the
CPC.STAT_CONF.EJTAG_PROBE bit.
Signed-off-by: Matt Redfearn <[email protected]>
---
arch/mips/kernel/pm-cps.c | 33 +++++++++++++++++++++++++++++++++
1 file changed, 33 insertions(+)
diff --git a/arch/mips/kernel/pm-cps.c b/arch/mips/kernel/pm-cps.c
index 421e06dfee72..2e0f4bad72b9 100644
--- a/arch/mips/kernel/pm-cps.c
+++ b/arch/mips/kernel/pm-cps.c
@@ -12,6 +12,7 @@
#include <linux/init.h>
#include <linux/percpu.h>
#include <linux/slab.h>
+#include <linux/suspend.h>
#include <asm/asm-offsets.h>
#include <asm/cacheflush.h>
@@ -670,6 +671,36 @@ static int cps_pm_online_cpu(unsigned int cpu)
return 0;
}
+#if defined(CONFIG_PM_SLEEP)
+static int cps_pm_power_notifier(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ unsigned int stat;
+
+ switch (event) {
+ case PM_SUSPEND_PREPARE:
+ stat = read_cpc_cl_stat_conf();
+ /*
+ * If we're attempting to suspend the system and power down all
+ * of the cores, the JTAG detect bit indicates that the CPC will
+ * instead put the cores into clock-off state. In this state
+ * a connected debugger can cause the CPU to attempt
+ * interactions with the powered down system. At best this will
+ * fail. At worst, it can hang the NoC, requiring a hard reset.
+ * To avoid this, just block system suspend if a JTAG probe
+ * is detected.
+ */
+ if (stat & CPC_Cx_STAT_CONF_EJTAG_PROBE_MSK) {
+ pr_warn("JTAG probe is connected - abort suspend\n");
+ return NOTIFY_BAD;
+ }
+ return NOTIFY_DONE;
+ default:
+ return NOTIFY_DONE;
+ }
+}
+#endif /* CONFIG_PM_SLEEP */
+
static int __init cps_pm_init(void)
{
/* A CM is required for all non-coherent states */
@@ -705,6 +736,8 @@ static int __init cps_pm_init(void)
pr_warn("pm-cps: no CPC, clock & power gating unavailable\n");
}
+ pm_notifier(cps_pm_power_notifier, 0);
+
return cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "mips/cps_pm:online",
cps_pm_online_cpu, NULL);
}
--
2.7.4
Hi Matt,
Thank you for the patch! Yet something to improve:
[auto build test ERROR on linus/master]
[also build test ERROR on v4.16-rc1 next-20180216]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
url: https://github.com/0day-ci/linux/commits/Matt-Redfearn/MIPS-pm-cps-Block-system-suspend-when-a-JTAG-probe-is-present/20180218-082248
config: mips-64r6el_defconfig (attached as .config)
compiler: mips64el-linux-gnuabi64-gcc (Debian 7.2.0-11) 7.2.0
reproduce:
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# save the attached .config to linux build tree
make.cross ARCH=mips
All errors (new ones prefixed by >>):
arch/mips//kernel/pm-cps.c: In function 'cps_pm_power_notifier':
>> arch/mips//kernel/pm-cps.c:693:14: error: 'CPC_Cx_STAT_CONF_EJTAG_PROBE_MSK' undeclared (first use in this function); did you mean 'CPC_Cx_STAT_CONF_EJTAG_PROBE'?
if (stat & CPC_Cx_STAT_CONF_EJTAG_PROBE_MSK) {
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CPC_Cx_STAT_CONF_EJTAG_PROBE
arch/mips//kernel/pm-cps.c:693:14: note: each undeclared identifier is reported only once for each function it appears in
vim +693 arch/mips//kernel/pm-cps.c
673
674 #if defined(CONFIG_PM_SLEEP)
675 static int cps_pm_power_notifier(struct notifier_block *this,
676 unsigned long event, void *ptr)
677 {
678 unsigned int stat;
679
680 switch (event) {
681 case PM_SUSPEND_PREPARE:
682 stat = read_cpc_cl_stat_conf();
683 /*
684 * If we're attempting to suspend the system and power down all
685 * of the cores, the JTAG detect bit indicates that the CPC will
686 * instead put the cores into clock-off state. In this state
687 * a connected debugger can cause the CPU to attempt
688 * interactions with the powered down system. At best this will
689 * fail. At worst, it can hang the NoC, requiring a hard reset.
690 * To avoid this, just block system suspend if a JTAG probe
691 * is detected.
692 */
> 693 if (stat & CPC_Cx_STAT_CONF_EJTAG_PROBE_MSK) {
694 pr_warn("JTAG probe is connected - abort suspend\n");
695 return NOTIFY_BAD;
696 }
697 return NOTIFY_DONE;
698 default:
699 return NOTIFY_DONE;
700 }
701 }
702 #endif /* CONFIG_PM_SLEEP */
703
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
If a JTAG probe is connected to a MIPS cluster, then the CPC detects it
and latches the CPC.STAT_CONF.EJTAG_PROBE bit to 1. While set,
attempting to send a power-down command to a core will be blocked, and
the CPC will instead send the core to clock-off state. This can
interfere with systems fully entering a low power state where all
cores, CM, GIC, etc are powered down.
Detect that a JTAG probe is / has been connected to the cluster and
block the suspend attempt.
Attempting to suspend the system while a JTAG probe is connected now
yields:
# echo mem > /sys/power/state
[ 11.654000] PM: Syncing filesystems ... done.
[ 11.658000] JTAG probe is connected - abort suspend
-sh: echo: write error: Operation not permitted
#
To restore suspend, the JTAG probe should be disconnected or put into
quiescent state. Platform code can then clear the
CPC.STAT_CONF.EJTAG_PROBE bit.
Signed-off-by: Matt Redfearn <[email protected]>
---
Changes in v2:
Fixed CPC_Cx_STAT_CONF_EJTAG_PROBE_MSK -> CPC_Cx_STAT_CONF_EJTAG_PROBE -
thanks kbuild test robot!
arch/mips/kernel/pm-cps.c | 33 +++++++++++++++++++++++++++++++++
1 file changed, 33 insertions(+)
diff --git a/arch/mips/kernel/pm-cps.c b/arch/mips/kernel/pm-cps.c
index 421e06dfee72..a17d85d51576 100644
--- a/arch/mips/kernel/pm-cps.c
+++ b/arch/mips/kernel/pm-cps.c
@@ -12,6 +12,7 @@
#include <linux/init.h>
#include <linux/percpu.h>
#include <linux/slab.h>
+#include <linux/suspend.h>
#include <asm/asm-offsets.h>
#include <asm/cacheflush.h>
@@ -670,6 +671,36 @@ static int cps_pm_online_cpu(unsigned int cpu)
return 0;
}
+#if defined(CONFIG_PM_SLEEP)
+static int cps_pm_power_notifier(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ unsigned int stat;
+
+ switch (event) {
+ case PM_SUSPEND_PREPARE:
+ stat = read_cpc_cl_stat_conf();
+ /*
+ * If we're attempting to suspend the system and power down all
+ * of the cores, the JTAG detect bit indicates that the CPC will
+ * instead put the cores into clock-off state. In this state
+ * a connected debugger can cause the CPU to attempt
+ * interactions with the powered down system. At best this will
+ * fail. At worst, it can hang the NoC, requiring a hard reset.
+ * To avoid this, just block system suspend if a JTAG probe
+ * is detected.
+ */
+ if (stat & CPC_Cx_STAT_CONF_EJTAG_PROBE) {
+ pr_warn("JTAG probe is connected - abort suspend\n");
+ return NOTIFY_BAD;
+ }
+ return NOTIFY_DONE;
+ default:
+ return NOTIFY_DONE;
+ }
+}
+#endif /* CONFIG_PM_SLEEP */
+
static int __init cps_pm_init(void)
{
/* A CM is required for all non-coherent states */
@@ -705,6 +736,8 @@ static int __init cps_pm_init(void)
pr_warn("pm-cps: no CPC, clock & power gating unavailable\n");
}
+ pm_notifier(cps_pm_power_notifier, 0);
+
return cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "mips/cps_pm:online",
cps_pm_online_cpu, NULL);
}
--
2.7.4