diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2011-01-24 02:42:41 -0500 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2011-04-19 21:03:24 -0400 |
commit | 948cf67c4726cca2fc57533dccadfb54d890689d (patch) | |
tree | e763f1b49f66cf2c73b5a902063e2cb828e5d06c /arch/powerpc/kernel | |
parent | 9d07bc841c9779b4d7902e417f4e509996ce805d (diff) |
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 <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r-- | arch/powerpc/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/powerpc/kernel/exceptions-64s.S | 30 | ||||
-rw-r--r-- | arch/powerpc/kernel/idle_power7.S | 97 |
3 files changed, 127 insertions, 1 deletions
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 7c6eb4974f25..0fd6273bb8a9 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
@@ -44,6 +44,7 @@ obj-$(CONFIG_PPC_BOOK3E_64) += exceptions-64e.o idle_book3e.o | |||
44 | obj-$(CONFIG_PPC64) += vdso64/ | 44 | obj-$(CONFIG_PPC64) += vdso64/ |
45 | obj-$(CONFIG_ALTIVEC) += vecemu.o | 45 | obj-$(CONFIG_ALTIVEC) += vecemu.o |
46 | obj-$(CONFIG_PPC_970_NAP) += idle_power4.o | 46 | obj-$(CONFIG_PPC_970_NAP) += idle_power4.o |
47 | obj-$(CONFIG_PPC_P7_NAP) += idle_power7.o | ||
47 | obj-$(CONFIG_PPC_OF) += of_platform.o prom_parse.o | 48 | obj-$(CONFIG_PPC_OF) += of_platform.o prom_parse.o |
48 | obj-$(CONFIG_PPC_CLOCK) += clock.o | 49 | obj-$(CONFIG_PPC_CLOCK) += clock.o |
49 | procfs-y := proc_powerpc.o | 50 | procfs-y := proc_powerpc.o |
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index e513c1d35b2a..ad06333631ac 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S | |||
@@ -37,7 +37,35 @@ | |||
37 | .globl __start_interrupts | 37 | .globl __start_interrupts |
38 | __start_interrupts: | 38 | __start_interrupts: |
39 | 39 | ||
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) | ||
41 | 69 | ||
42 | . = 0x200 | 70 | . = 0x200 |
43 | _machine_check_pSeries: | 71 | _machine_check_pSeries: |
diff --git a/arch/powerpc/kernel/idle_power7.S b/arch/powerpc/kernel/idle_power7.S new file mode 100644 index 000000000000..f8f0bc7f1d4f --- /dev/null +++ b/arch/powerpc/kernel/idle_power7.S | |||
@@ -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 | ||