Skip to content

Commit 948cf67

Browse files
committed
powerpc: Add NAP mode support on Power7 in HV mode
Wakeup comes from the system reset handler with a potential loss of the non-hypervisor CPU state. We save the non-volatile state on the stack and a pointer to it in the PACA, which the system reset handler uses to restore things Signed-off-by: Benjamin Herrenschmidt <[email protected]>
1 parent 9d07bc8 commit 948cf67

File tree

7 files changed

+139
-2
lines changed

7 files changed

+139
-2
lines changed

arch/powerpc/include/asm/machdep.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ struct machdep_calls {
267267

268268
extern void e500_idle(void);
269269
extern void power4_idle(void);
270+
extern void power7_idle(void);
270271
extern void ppc6xx_idle(void);
271272
extern void book3e_idle(void);
272273

arch/powerpc/include/asm/paca.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ struct paca_struct {
125125
struct task_struct *__current; /* Pointer to current */
126126
u64 kstack; /* Saved Kernel stack addr */
127127
u64 stab_rr; /* stab/slb round-robin counter */
128-
u64 saved_r1; /* r1 save for RTAS calls */
128+
u64 saved_r1; /* r1 save for RTAS calls or PM */
129129
u64 saved_msr; /* MSR saved here by enter_rtas */
130130
u16 trap_save; /* Used when bad stack is encountered */
131131
u8 soft_enabled; /* irq soft-enable flag */

arch/powerpc/include/asm/ppc-opcode.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@
5656
#define PPC_INST_TLBSRX_DOT 0x7c0006a5
5757
#define PPC_INST_XXLOR 0xf0000510
5858

59+
#define PPC_INST_NAP 0x4c000364
60+
#define PPC_INST_SLEEP 0x4c0003a4
61+
5962
/* macros to insert fields into opcodes */
6063
#define __PPC_RA(a) (((a) & 0x1f) << 16)
6164
#define __PPC_RB(b) (((b) & 0x1f) << 11)
@@ -126,4 +129,7 @@
126129
#define XXLOR(t, a, b) stringify_in_c(.long PPC_INST_XXLOR | \
127130
VSX_XX3((t), (a), (b)))
128131

132+
#define PPC_NAP stringify_in_c(.long PPC_INST_NAP)
133+
#define PPC_SLEEP stringify_in_c(.long PPC_INST_SLEEP)
134+
129135
#endif /* _ASM_POWERPC_PPC_OPCODE_H */

arch/powerpc/kernel/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ obj-$(CONFIG_PPC_BOOK3E_64) += exceptions-64e.o idle_book3e.o
4444
obj-$(CONFIG_PPC64) += vdso64/
4545
obj-$(CONFIG_ALTIVEC) += vecemu.o
4646
obj-$(CONFIG_PPC_970_NAP) += idle_power4.o
47+
obj-$(CONFIG_PPC_P7_NAP) += idle_power7.o
4748
obj-$(CONFIG_PPC_OF) += of_platform.o prom_parse.o
4849
obj-$(CONFIG_PPC_CLOCK) += clock.o
4950
procfs-y := proc_powerpc.o

arch/powerpc/kernel/exceptions-64s.S

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,35 @@
3737
.globl __start_interrupts
3838
__start_interrupts:
3939

40-
STD_EXCEPTION_PSERIES(0x100, 0x100, system_reset)
40+
.globl system_reset_pSeries;
41+
system_reset_pSeries:
42+
HMT_MEDIUM;
43+
DO_KVM 0x100;
44+
SET_SCRATCH0(r13)
45+
#ifdef CONFIG_PPC_P7_NAP
46+
BEGIN_FTR_SECTION
47+
/* Running native on arch 2.06 or later, check if we are
48+
* waking up from nap. We only handle no state loss and
49+
* supervisor state loss. We do -not- handle hypervisor
50+
* state loss at this time.
51+
*/
52+
mfspr r13,SPRN_SRR1
53+
rlwinm r13,r13,47-31,30,31
54+
cmpwi cr0,r13,1
55+
bne 1f
56+
b .power7_wakeup_noloss
57+
1: cmpwi cr0,r13,2
58+
bne 1f
59+
b .power7_wakeup_loss
60+
/* Total loss of HV state is fatal, we could try to use the
61+
* PIR to locate a PACA, then use an emergency stack etc...
62+
* but for now, let's just stay stuck here
63+
*/
64+
1: cmpwi cr0,r13,3
65+
beq .
66+
END_FTR_SECTION_IFSET(CPU_FTR_HVMODE_206)
67+
#endif /* CONFIG_PPC_P7_NAP */
68+
EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common, EXC_STD)
4169

4270
. = 0x200
4371
_machine_check_pSeries:

arch/powerpc/kernel/idle_power7.S

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/*
2+
* This file contains the power_save function for 970-family CPUs.
3+
*
4+
* This program is free software; you can redistribute it and/or
5+
* modify it under the terms of the GNU General Public License
6+
* as published by the Free Software Foundation; either version
7+
* 2 of the License, or (at your option) any later version.
8+
*/
9+
10+
#include <linux/threads.h>
11+
#include <asm/processor.h>
12+
#include <asm/page.h>
13+
#include <asm/cputable.h>
14+
#include <asm/thread_info.h>
15+
#include <asm/ppc_asm.h>
16+
#include <asm/asm-offsets.h>
17+
#include <asm/ppc-opcode.h>
18+
19+
#undef DEBUG
20+
21+
.text
22+
23+
_GLOBAL(power7_idle)
24+
/* Now check if user or arch enabled NAP mode */
25+
LOAD_REG_ADDRBASE(r3,powersave_nap)
26+
lwz r4,ADDROFF(powersave_nap)(r3)
27+
cmpwi 0,r4,0
28+
beqlr
29+
30+
/* NAP is a state loss, we create a regs frame on the
31+
* stack, fill it up with the state we care about and
32+
* stick a pointer to it in PACAR1. We really only
33+
* need to save PC, some CR bits and the NV GPRs,
34+
* but for now an interrupt frame will do.
35+
*/
36+
mflr r0
37+
std r0,16(r1)
38+
stdu r1,-INT_FRAME_SIZE(r1)
39+
std r0,_LINK(r1)
40+
std r0,_NIP(r1)
41+
42+
#ifndef CONFIG_SMP
43+
/* Make sure FPU, VSX etc... are flushed as we may lose
44+
* state when going to nap mode
45+
*/
46+
bl .discard_lazy_cpu_state
47+
#endif /* CONFIG_SMP */
48+
49+
/* Hard disable interrupts */
50+
mfmsr r9
51+
rldicl r9,r9,48,1
52+
rotldi r9,r9,16
53+
mtmsrd r9,1 /* hard-disable interrupts */
54+
li r0,0
55+
stb r0,PACASOFTIRQEN(r13) /* we'll hard-enable shortly */
56+
stb r0,PACAHARDIRQEN(r13)
57+
58+
/* Continue saving state */
59+
SAVE_GPR(2, r1)
60+
SAVE_NVGPRS(r1)
61+
mfcr r3
62+
std r3,_CCR(r1)
63+
std r9,_MSR(r1)
64+
std r1,PACAR1(r13)
65+
66+
/* Magic NAP mode enter sequence */
67+
std r0,0(r1)
68+
ptesync
69+
ld r0,0(r1)
70+
1: cmp cr0,r0,r0
71+
bne 1b
72+
PPC_NAP
73+
b .
74+
75+
_GLOBAL(power7_wakeup_loss)
76+
GET_PACA(r13)
77+
ld r1,PACAR1(r13)
78+
REST_NVGPRS(r1)
79+
REST_GPR(2, r1)
80+
ld r3,_CCR(r1)
81+
ld r4,_MSR(r1)
82+
ld r5,_NIP(r1)
83+
addi r1,r1,INT_FRAME_SIZE
84+
mtcr r3
85+
mtspr SPRN_SRR1,r4
86+
mtspr SPRN_SRR0,r5
87+
rfid
88+
89+
_GLOBAL(power7_wakeup_noloss)
90+
GET_PACA(r13)
91+
ld r1,PACAR1(r13)
92+
ld r4,_MSR(r1)
93+
ld r5,_NIP(r1)
94+
addi r1,r1,INT_FRAME_SIZE
95+
mtspr SPRN_SRR1,r4
96+
mtspr SPRN_SRR0,r5
97+
rfid

arch/powerpc/platforms/Kconfig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,10 @@ config PPC_970_NAP
147147
bool
148148
default n
149149

150+
config PPC_P7_NAP
151+
bool
152+
default n
153+
150154
config PPC_INDIRECT_IO
151155
bool
152156
select GENERIC_IOMAP

0 commit comments

Comments
 (0)