powerpc/powernv/idle: Restore AMR/UAMOR/AMOR/IAMR after idle

This is an implementation of commits 53a712bae5
("powerpc/powernv/idle: Restore AMR/UAMOR/AMOR after idle") and
a3f3072db6 ("powerpc/powernv/idle: Restore IAMR after idle") using
the new C-based idle code.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
[mpe: Extract from Nick's patch]
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
This commit is contained in:
Michael Ellerman 2019-04-30 14:28:17 +10:00
parent 10d91611f4
commit e9cef0189c
1 changed files with 46 additions and 6 deletions

View File

@ -296,7 +296,6 @@ struct p7_sprs {
/* per subcore */
u64 sdr1;
u64 rpr;
u64 amor;
/* per thread */
u64 lpcr;
@ -306,6 +305,12 @@ struct p7_sprs {
u64 spurr;
u64 dscr;
u64 wort;
/* per thread SPRs that get lost in shallow states */
u64 amr;
u64 iamr;
u64 amor;
u64 uamor;
};
static unsigned long power7_idle_insn(unsigned long type)
@ -342,7 +347,6 @@ static unsigned long power7_idle_insn(unsigned long type)
sprs.sdr1 = mfspr(SPRN_SDR1);
sprs.rpr = mfspr(SPRN_RPR);
sprs.amor = mfspr(SPRN_AMOR);
sprs.lpcr = mfspr(SPRN_LPCR);
if (cpu_has_feature(CPU_FTR_ARCH_207S)) {
@ -374,6 +378,13 @@ static unsigned long power7_idle_insn(unsigned long type)
atomic_unlock_thread_idle();
}
if (cpu_has_feature(CPU_FTR_ARCH_207S)) {
sprs.amr = mfspr(SPRN_AMR);
sprs.iamr = mfspr(SPRN_IAMR);
sprs.amor = mfspr(SPRN_AMOR);
sprs.uamor = mfspr(SPRN_UAMOR);
}
local_paca->thread_idle_state = type;
srr1 = isa206_idle_insn_mayloss(type); /* go idle */
local_paca->thread_idle_state = PNV_THREAD_RUNNING;
@ -381,6 +392,19 @@ static unsigned long power7_idle_insn(unsigned long type)
WARN_ON_ONCE(!srr1);
WARN_ON_ONCE(mfmsr() & (MSR_IR|MSR_DR));
if (cpu_has_feature(CPU_FTR_ARCH_207S)) {
if ((srr1 & SRR1_WAKESTATE) != SRR1_WS_NOLOSS) {
/*
* We don't need an isync after the mtsprs here because
* the upcoming mtmsrd is execution synchronizing.
*/
mtspr(SPRN_AMR, sprs.amr);
mtspr(SPRN_IAMR, sprs.iamr);
mtspr(SPRN_AMOR, sprs.amor);
mtspr(SPRN_UAMOR, sprs.uamor);
}
}
if (unlikely((srr1 & SRR1_WAKEMASK_P8) == SRR1_WAKEHMI))
hmi_exception_realmode(NULL);
@ -444,7 +468,6 @@ core_woken:
/* Per-subcore SPRs */
mtspr(SPRN_SDR1, sprs.sdr1);
mtspr(SPRN_RPR, sprs.rpr);
mtspr(SPRN_AMOR, sprs.amor);
subcore_woken:
/*
@ -560,7 +583,6 @@ struct p9_sprs {
u64 rpr;
u64 tscr;
u64 ldbar;
u64 amor;
/* per thread */
u64 lpcr;
@ -576,6 +598,12 @@ struct p9_sprs {
u32 mmcr0;
u32 mmcr1;
u64 mmcr2;
/* per thread SPRs that get lost in shallow states */
u64 amr;
u64 iamr;
u64 amor;
u64 uamor;
};
static unsigned long power9_idle_stop(unsigned long psscr, bool mmu_on)
@ -652,13 +680,17 @@ static unsigned long power9_idle_stop(unsigned long psscr, bool mmu_on)
sprs.rpr = mfspr(SPRN_RPR);
sprs.tscr = mfspr(SPRN_TSCR);
sprs.ldbar = mfspr(SPRN_LDBAR);
sprs.amor = mfspr(SPRN_AMOR);
sprs_saved = true;
atomic_start_thread_idle();
}
sprs.amr = mfspr(SPRN_AMR);
sprs.iamr = mfspr(SPRN_IAMR);
sprs.amor = mfspr(SPRN_AMOR);
sprs.uamor = mfspr(SPRN_UAMOR);
srr1 = isa300_idle_stop_mayloss(psscr); /* go idle */
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
@ -673,6 +705,15 @@ static unsigned long power9_idle_stop(unsigned long psscr, bool mmu_on)
if ((srr1 & SRR1_WAKESTATE) != SRR1_WS_NOLOSS) {
unsigned long mmcra;
/*
* We don't need an isync after the mtsprs here because the
* upcoming mtmsrd is execution synchronizing.
*/
mtspr(SPRN_AMR, sprs.amr);
mtspr(SPRN_IAMR, sprs.iamr);
mtspr(SPRN_AMOR, sprs.amor);
mtspr(SPRN_UAMOR, sprs.uamor);
/*
* Workaround for POWER9 DD2.0, if we lost resources, the ERAT
* might have been corrupted and needs flushing. We also need
@ -722,7 +763,6 @@ static unsigned long power9_idle_stop(unsigned long psscr, bool mmu_on)
mtspr(SPRN_RPR, sprs.rpr);
mtspr(SPRN_TSCR, sprs.tscr);
mtspr(SPRN_LDBAR, sprs.ldbar);
mtspr(SPRN_AMOR, sprs.amor);
if (pls >= pnv_first_tb_loss_level) {
/* TB loss */