Last active
March 18, 2021 11:05
-
-
Save pratiksampat/65ae79de1dfdfe0bbb591de957296252 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 4249d4f851105d611f03f4cebd3fe3813f2fe82b Mon Sep 17 00:00:00 2001 | |
From: Pratik Rajesh Sampat <psampat@linux.ibm.com> | |
Date: Thu, 18 Feb 2021 12:16:30 +0530 | |
Subject: [PATCH] SPR analysis framework | |
Track the SPR values before sleep and after wakeup and verify their | |
correctness by adding into the following buckets: | |
1. match | |
2. no match | |
3. increasing | |
4. invalid | |
If more SPRs need to be added, they need go into the "spr_list[]" in | |
spr_analysis.h. These SPRs also need to be added to | |
(saved/restored)_sprs() too in the format | |
local_paca->saved_spr_val[SPRN_X] = mfspr(SPRN_X); | |
This is needed because mfpsr is a compile time macro and cannot be | |
iterated over in runtime. | |
Signed-off-by: Pratik Rajesh Sampat <psampat@linux.ibm.com> | |
--- | |
arch/powerpc/include/asm/paca.h | 12 +++ | |
arch/powerpc/platforms/powernv/Makefile | 2 +- | |
arch/powerpc/platforms/powernv/idle.c | 7 ++ | |
arch/powerpc/platforms/powernv/spr_analysis.c | 82 +++++++++++++++++++ | |
arch/powerpc/platforms/powernv/spr_analysis.h | 10 +++ | |
5 files changed, 112 insertions(+), 1 deletion(-) | |
create mode 100644 arch/powerpc/platforms/powernv/spr_analysis.c | |
create mode 100644 arch/powerpc/platforms/powernv/spr_analysis.h | |
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h | |
index ec18ac818e3a..1004c82ed4f9 100644 | |
--- a/arch/powerpc/include/asm/paca.h | |
+++ b/arch/powerpc/include/asm/paca.h | |
@@ -55,6 +55,13 @@ extern unsigned int debug_smp_processor_id(void); /* from linux/smp.h */ | |
struct task_struct; | |
struct rtas_args; | |
+typedef enum { | |
+ mtch, | |
+ no_match, | |
+ increasing, | |
+ invalid | |
+} compare_t; | |
+ | |
/* | |
* Defines the layout of the paca. | |
* | |
@@ -204,6 +211,11 @@ struct paca_struct { | |
#endif | |
}; | |
}; | |
+ struct { | |
+ u64 saved_spr_val[1024]; | |
+ u64 restored_spr_val[1024]; | |
+ compare_t bucket[1024]; | |
+ }; | |
#endif | |
#ifdef CONFIG_PPC_BOOK3S_64 | |
diff --git a/arch/powerpc/platforms/powernv/Makefile b/arch/powerpc/platforms/powernv/Makefile | |
index 2eb6ae150d1f..2d6b29d048cc 100644 | |
--- a/arch/powerpc/platforms/powernv/Makefile | |
+++ b/arch/powerpc/platforms/powernv/Makefile | |
@@ -4,7 +4,7 @@ obj-y += idle.o opal-rtc.o opal-nvram.o opal-lpc.o opal-flash.o | |
obj-y += rng.o opal-elog.o opal-dump.o opal-sysparam.o opal-sensor.o | |
obj-y += opal-msglog.o opal-hmi.o opal-power.o opal-irqchip.o | |
obj-y += opal-kmsg.o opal-powercap.o opal-psr.o opal-sensor-groups.o | |
-obj-y += ultravisor.o | |
+obj-y += ultravisor.o spr_analysis.o | |
obj-$(CONFIG_SMP) += smp.o subcore.o subcore-asm.o | |
obj-$(CONFIG_FA_DUMP) += opal-fadump.o | |
diff --git a/arch/powerpc/platforms/powernv/idle.c b/arch/powerpc/platforms/powernv/idle.c | |
index 999997d9e9a9..cfeb59b8084b 100644 | |
--- a/arch/powerpc/platforms/powernv/idle.c | |
+++ b/arch/powerpc/platforms/powernv/idle.c | |
@@ -26,6 +26,7 @@ | |
#include "powernv.h" | |
#include "subcore.h" | |
+#include "spr_analysis.h" | |
/* Power ISA 3.0 allows for stop states 0x0 - 0xF */ | |
#define MAX_STOP_STATE 0xF | |
@@ -693,8 +694,13 @@ static unsigned long power9_idle_stop(unsigned long psscr, bool mmu_on) | |
sprs.amor = mfspr(SPRN_AMOR); | |
sprs.uamor = mfspr(SPRN_UAMOR); | |
+ saved_sprs(); | |
+ | |
srr1 = isa300_idle_stop_mayloss(psscr); /* go idle */ | |
+ restored_sprs(); | |
+ verify_sprs(); | |
+ trace_printk_spr_results(cpu); | |
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE | |
local_paca->requested_psscr = 0; | |
#endif | |
@@ -1533,6 +1539,7 @@ static int __init pnv_init_idle_states(void) | |
pnv_disable_deep_states(); | |
} | |
+ init_spr_list(); | |
out: | |
return 0; | |
} | |
diff --git a/arch/powerpc/platforms/powernv/spr_analysis.c b/arch/powerpc/platforms/powernv/spr_analysis.c | |
new file mode 100644 | |
index 000000000000..986ab8f72bae | |
--- /dev/null | |
+++ b/arch/powerpc/platforms/powernv/spr_analysis.c | |
@@ -0,0 +1,82 @@ | |
+#include <asm/smp.h> | |
+#include <linux/of.h> | |
+ | |
+#include "spr_analysis.h" | |
+ | |
+u64 spr_list[] = { | |
+ SPRN_LPCR, | |
+ SPRN_PTCR, | |
+ SPRN_PSSCR | |
+}; | |
+ | |
+/* | |
+ * To be refactored to allow iteration on mfspr() | |
+ */ | |
+void saved_sprs(void) { | |
+ local_paca->saved_spr_val[SPRN_LPCR] = mfspr(SPRN_LPCR); | |
+ local_paca->saved_spr_val[SPRN_PTCR] = mfspr(SPRN_PTCR); | |
+ local_paca->saved_spr_val[SPRN_PSSCR] = mfspr(SPRN_PSSCR); | |
+} | |
+ | |
+void restored_sprs(void) { | |
+ local_paca->restored_spr_val[SPRN_LPCR] = mfspr(SPRN_LPCR); | |
+ local_paca->restored_spr_val[SPRN_PTCR] = mfspr(SPRN_PTCR); | |
+ local_paca->restored_spr_val[SPRN_PSSCR] = mfspr(SPRN_PSSCR); | |
+} | |
+ | |
+void verify_sprs(void) { | |
+ int i; | |
+ for (i = 0; i < ARRAY_SIZE(spr_list); i++) { | |
+ if (local_paca->saved_spr_val[spr_list[i]] == | |
+ local_paca->restored_spr_val[spr_list[i]]) | |
+ local_paca->bucket[spr_list[i]] = mtch; | |
+ else if (local_paca->saved_spr_val[spr_list[i]] <= | |
+ local_paca->restored_spr_val[spr_list[i]]) | |
+ local_paca->bucket[spr_list[i]] = increasing; | |
+ else | |
+ local_paca->bucket[spr_list[i]] = no_match; | |
+ | |
+ } | |
+} | |
+ | |
+void trace_printk_spr_results(int cpu) { | |
+ int i; | |
+ for (i = 0; i < ARRAY_SIZE(spr_list); i++) { | |
+ switch(local_paca->bucket[spr_list[i]]){ | |
+ case mtch: | |
+ trace_printk("cpu=%d SPR=0x%llx status=OK::saved=0x%llx restored=0x%llx\n", | |
+ cpu, spr_list[i], | |
+ local_paca->saved_spr_val[spr_list[i]], | |
+ local_paca->restored_spr_val[spr_list[i]]); | |
+ break; | |
+ case increasing: | |
+ trace_printk("cpu=%d SPR=0x%llx status=Increasing::saved=0x%llx restored=0x%llx\n", | |
+ cpu, spr_list[i], | |
+ local_paca->saved_spr_val[spr_list[i]], | |
+ local_paca->restored_spr_val[spr_list[i]]); | |
+ break; | |
+ case no_match: | |
+ trace_printk("cpu=%d SPR=0x%llx status=No match::saved=0x%llx restored=0x%llx\n", | |
+ cpu, spr_list[i], | |
+ local_paca->saved_spr_val[spr_list[i]], | |
+ local_paca->restored_spr_val[spr_list[i]]); | |
+ break; | |
+ case invalid: | |
+ default: | |
+ trace_printk("cpu=%d SPR=0x%llx status=Invalid::saved=0x%llx restored=0x%llx\n", | |
+ cpu, spr_list[i], | |
+ local_paca->saved_spr_val[spr_list[i]], | |
+ local_paca->restored_spr_val[spr_list[i]]); | |
+ } | |
+ } | |
+} | |
+ | |
+void init_spr_list(void) { | |
+ int i; | |
+ | |
+ for (i = 0; i < ARRAY_SIZE(spr_list); i++) { | |
+ local_paca->saved_spr_val[spr_list[i]] = 0; | |
+ local_paca->restored_spr_val[spr_list[i]] = 0; | |
+ local_paca->bucket[spr_list[i]] = invalid; | |
+ } | |
+} | |
diff --git a/arch/powerpc/platforms/powernv/spr_analysis.h b/arch/powerpc/platforms/powernv/spr_analysis.h | |
new file mode 100644 | |
index 000000000000..f7e1873a0736 | |
--- /dev/null | |
+++ b/arch/powerpc/platforms/powernv/spr_analysis.h | |
@@ -0,0 +1,10 @@ | |
+#ifndef SPR_ANALYSIS_H | |
+#define SPR_ANALYSIS_H | |
+ | |
+extern void saved_sprs(void); | |
+extern void restored_sprs(void); | |
+extern void verify_sprs(void); | |
+extern void init_spr_list(void); | |
+extern void trace_printk_spr_results(int); | |
+ | |
+#endif | |
\ No newline at end of file | |
-- | |
2.17.1 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment