|
@@ -85,7 +85,61 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_ARCH_300)
|
|
|
std r3,_WORT(r1)
|
|
|
mfspr r3,SPRN_WORC
|
|
|
std r3,_WORC(r1)
|
|
|
+/*
|
|
|
+ * On POWER9, there are idle states such as stop4, invoked via cpuidle,
|
|
|
+ * that lose hypervisor resources. In such cases, we need to save
|
|
|
+ * additional SPRs before entering those idle states so that they can
|
|
|
+ * be restored to their older values on wakeup from the idle state.
|
|
|
+ *
|
|
|
+ * On POWER8, the only such deep idle state is winkle which is used
|
|
|
+ * only in the context of CPU-Hotplug, where these additional SPRs are
|
|
|
+ * reinitiazed to a sane value. Hence there is no need to save/restore
|
|
|
+ * these SPRs.
|
|
|
+ */
|
|
|
+BEGIN_FTR_SECTION
|
|
|
+ blr
|
|
|
+END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300)
|
|
|
+
|
|
|
+power9_save_additional_sprs:
|
|
|
+ mfspr r3, SPRN_PID
|
|
|
+ mfspr r4, SPRN_LDBAR
|
|
|
+ std r3, STOP_PID(r13)
|
|
|
+ std r4, STOP_LDBAR(r13)
|
|
|
|
|
|
+ mfspr r3, SPRN_FSCR
|
|
|
+ mfspr r4, SPRN_HFSCR
|
|
|
+ std r3, STOP_FSCR(r13)
|
|
|
+ std r4, STOP_HFSCR(r13)
|
|
|
+
|
|
|
+ mfspr r3, SPRN_MMCRA
|
|
|
+ mfspr r4, SPRN_MMCR1
|
|
|
+ std r3, STOP_MMCRA(r13)
|
|
|
+ std r4, STOP_MMCR1(r13)
|
|
|
+
|
|
|
+ mfspr r3, SPRN_MMCR2
|
|
|
+ std r3, STOP_MMCR2(r13)
|
|
|
+ blr
|
|
|
+
|
|
|
+power9_restore_additional_sprs:
|
|
|
+ ld r3,_LPCR(r1)
|
|
|
+ ld r4, STOP_PID(r13)
|
|
|
+ mtspr SPRN_LPCR,r3
|
|
|
+ mtspr SPRN_PID, r4
|
|
|
+
|
|
|
+ ld r3, STOP_LDBAR(r13)
|
|
|
+ ld r4, STOP_FSCR(r13)
|
|
|
+ mtspr SPRN_LDBAR, r3
|
|
|
+ mtspr SPRN_FSCR, r4
|
|
|
+
|
|
|
+ ld r3, STOP_HFSCR(r13)
|
|
|
+ ld r4, STOP_MMCRA(r13)
|
|
|
+ mtspr SPRN_HFSCR, r3
|
|
|
+ mtspr SPRN_MMCRA, r4
|
|
|
+ /* We have already restored PACA_MMCR0 */
|
|
|
+ ld r3, STOP_MMCR1(r13)
|
|
|
+ ld r4, STOP_MMCR2(r13)
|
|
|
+ mtspr SPRN_MMCR1, r3
|
|
|
+ mtspr SPRN_MMCR2, r4
|
|
|
blr
|
|
|
|
|
|
/*
|
|
@@ -803,9 +857,16 @@ no_segments:
|
|
|
mtctr r12
|
|
|
bctrl
|
|
|
|
|
|
+/*
|
|
|
+ * On POWER9, we can come here on wakeup from a cpuidle stop state.
|
|
|
+ * Hence restore the additional SPRs to the saved value.
|
|
|
+ *
|
|
|
+ * On POWER8, we come here only on winkle. Since winkle is used
|
|
|
+ * only in the case of CPU-Hotplug, we don't need to restore
|
|
|
+ * the additional SPRs.
|
|
|
+ */
|
|
|
BEGIN_FTR_SECTION
|
|
|
- ld r4,_LPCR(r1)
|
|
|
- mtspr SPRN_LPCR,r4
|
|
|
+ bl power9_restore_additional_sprs
|
|
|
END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
|
|
|
hypervisor_state_restored:
|
|
|
|