diff options
Diffstat (limited to 'arch/powerpc')
191 files changed, 6329 insertions, 1711 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 44df1bac9701..29158913a66b 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -138,6 +138,7 @@ config PPC | |||
138 | select HAVE_OPROFILE | 138 | select HAVE_OPROFILE |
139 | select HAVE_SYSCALL_WRAPPERS if PPC64 | 139 | select HAVE_SYSCALL_WRAPPERS if PPC64 |
140 | select GENERIC_ATOMIC64 if PPC32 | 140 | select GENERIC_ATOMIC64 if PPC32 |
141 | select HAVE_IRQ_WORK | ||
141 | select HAVE_PERF_EVENTS | 142 | select HAVE_PERF_EVENTS |
142 | select HAVE_REGS_AND_STACK_ACCESS_API | 143 | select HAVE_REGS_AND_STACK_ACCESS_API |
143 | select HAVE_HW_BREAKPOINT if PERF_EVENTS && PPC_BOOK3S_64 | 144 | select HAVE_HW_BREAKPOINT if PERF_EVENTS && PPC_BOOK3S_64 |
diff --git a/arch/powerpc/boot/addnote.c b/arch/powerpc/boot/addnote.c index b1e5611b2ab1..349b5530d2c4 100644 --- a/arch/powerpc/boot/addnote.c +++ b/arch/powerpc/boot/addnote.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #include <string.h> | 20 | #include <string.h> |
21 | 21 | ||
22 | /* CHRP note section */ | 22 | /* CHRP note section */ |
23 | char arch[] = "PowerPC"; | 23 | static const char arch[] = "PowerPC"; |
24 | 24 | ||
25 | #define N_DESCR 6 | 25 | #define N_DESCR 6 |
26 | unsigned int descr[N_DESCR] = { | 26 | unsigned int descr[N_DESCR] = { |
@@ -33,7 +33,7 @@ unsigned int descr[N_DESCR] = { | |||
33 | }; | 33 | }; |
34 | 34 | ||
35 | /* RPA note section */ | 35 | /* RPA note section */ |
36 | char rpaname[] = "IBM,RPA-Client-Config"; | 36 | static const char rpaname[] = "IBM,RPA-Client-Config"; |
37 | 37 | ||
38 | /* | 38 | /* |
39 | * Note: setting ignore_my_client_config *should* mean that OF ignores | 39 | * Note: setting ignore_my_client_config *should* mean that OF ignores |
diff --git a/arch/powerpc/boot/dts/bluestone.dts b/arch/powerpc/boot/dts/bluestone.dts new file mode 100644 index 000000000000..9bb3d72c0e5a --- /dev/null +++ b/arch/powerpc/boot/dts/bluestone.dts | |||
@@ -0,0 +1,254 @@ | |||
1 | /* | ||
2 | * Device Tree for Bluestone (APM821xx) board. | ||
3 | * | ||
4 | * Copyright (c) 2010, Applied Micro Circuits Corporation | ||
5 | * Author: Tirumala R Marri <tmarri@apm.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License as | ||
9 | * published by the Free Software Foundation; either version 2 of | ||
10 | * the License, or (at your option) any later version. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU General Public License | ||
18 | * along with this program; if not, write to the Free Software | ||
19 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | ||
20 | * MA 02111-1307 USA | ||
21 | * | ||
22 | */ | ||
23 | |||
24 | /dts-v1/; | ||
25 | |||
26 | / { | ||
27 | #address-cells = <2>; | ||
28 | #size-cells = <1>; | ||
29 | model = "apm,bluestone"; | ||
30 | compatible = "apm,bluestone"; | ||
31 | dcr-parent = <&{/cpus/cpu@0}>; | ||
32 | |||
33 | aliases { | ||
34 | ethernet0 = &EMAC0; | ||
35 | serial0 = &UART0; | ||
36 | serial1 = &UART1; | ||
37 | }; | ||
38 | |||
39 | cpus { | ||
40 | #address-cells = <1>; | ||
41 | #size-cells = <0>; | ||
42 | |||
43 | cpu@0 { | ||
44 | device_type = "cpu"; | ||
45 | model = "PowerPC,apm821xx"; | ||
46 | reg = <0x00000000>; | ||
47 | clock-frequency = <0>; /* Filled in by U-Boot */ | ||
48 | timebase-frequency = <0>; /* Filled in by U-Boot */ | ||
49 | i-cache-line-size = <32>; | ||
50 | d-cache-line-size = <32>; | ||
51 | i-cache-size = <32768>; | ||
52 | d-cache-size = <32768>; | ||
53 | dcr-controller; | ||
54 | dcr-access-method = "native"; | ||
55 | next-level-cache = <&L2C0>; | ||
56 | }; | ||
57 | }; | ||
58 | |||
59 | memory { | ||
60 | device_type = "memory"; | ||
61 | reg = <0x00000000 0x00000000 0x00000000>; /* Filled in by U-Boot */ | ||
62 | }; | ||
63 | |||
64 | UIC0: interrupt-controller0 { | ||
65 | compatible = "ibm,uic"; | ||
66 | interrupt-controller; | ||
67 | cell-index = <0>; | ||
68 | dcr-reg = <0x0c0 0x009>; | ||
69 | #address-cells = <0>; | ||
70 | #size-cells = <0>; | ||
71 | #interrupt-cells = <2>; | ||
72 | }; | ||
73 | |||
74 | UIC1: interrupt-controller1 { | ||
75 | compatible = "ibm,uic"; | ||
76 | interrupt-controller; | ||
77 | cell-index = <1>; | ||
78 | dcr-reg = <0x0d0 0x009>; | ||
79 | #address-cells = <0>; | ||
80 | #size-cells = <0>; | ||
81 | #interrupt-cells = <2>; | ||
82 | interrupts = <0x1e 0x4 0x1f 0x4>; /* cascade */ | ||
83 | interrupt-parent = <&UIC0>; | ||
84 | }; | ||
85 | |||
86 | UIC2: interrupt-controller2 { | ||
87 | compatible = "ibm,uic"; | ||
88 | interrupt-controller; | ||
89 | cell-index = <2>; | ||
90 | dcr-reg = <0x0e0 0x009>; | ||
91 | #address-cells = <0>; | ||
92 | #size-cells = <0>; | ||
93 | #interrupt-cells = <2>; | ||
94 | interrupts = <0xa 0x4 0xb 0x4>; /* cascade */ | ||
95 | interrupt-parent = <&UIC0>; | ||
96 | }; | ||
97 | |||
98 | UIC3: interrupt-controller3 { | ||
99 | compatible = "ibm,uic"; | ||
100 | interrupt-controller; | ||
101 | cell-index = <3>; | ||
102 | dcr-reg = <0x0f0 0x009>; | ||
103 | #address-cells = <0>; | ||
104 | #size-cells = <0>; | ||
105 | #interrupt-cells = <2>; | ||
106 | interrupts = <0x10 0x4 0x11 0x4>; /* cascade */ | ||
107 | interrupt-parent = <&UIC0>; | ||
108 | }; | ||
109 | |||
110 | SDR0: sdr { | ||
111 | compatible = "ibm,sdr-apm821xx"; | ||
112 | dcr-reg = <0x00e 0x002>; | ||
113 | }; | ||
114 | |||
115 | CPR0: cpr { | ||
116 | compatible = "ibm,cpr-apm821xx"; | ||
117 | dcr-reg = <0x00c 0x002>; | ||
118 | }; | ||
119 | |||
120 | plb { | ||
121 | compatible = "ibm,plb4"; | ||
122 | #address-cells = <2>; | ||
123 | #size-cells = <1>; | ||
124 | ranges; | ||
125 | clock-frequency = <0>; /* Filled in by U-Boot */ | ||
126 | |||
127 | SDRAM0: sdram { | ||
128 | compatible = "ibm,sdram-apm821xx"; | ||
129 | dcr-reg = <0x010 0x002>; | ||
130 | }; | ||
131 | |||
132 | MAL0: mcmal { | ||
133 | compatible = "ibm,mcmal2"; | ||
134 | descriptor-memory = "ocm"; | ||
135 | dcr-reg = <0x180 0x062>; | ||
136 | num-tx-chans = <1>; | ||
137 | num-rx-chans = <1>; | ||
138 | #address-cells = <0>; | ||
139 | #size-cells = <0>; | ||
140 | interrupt-parent = <&UIC2>; | ||
141 | interrupts = < /*TXEOB*/ 0x6 0x4 | ||
142 | /*RXEOB*/ 0x7 0x4 | ||
143 | /*SERR*/ 0x3 0x4 | ||
144 | /*TXDE*/ 0x4 0x4 | ||
145 | /*RXDE*/ 0x5 0x4 | ||
146 | }; | ||
147 | |||
148 | POB0: opb { | ||
149 | compatible = "ibm,opb"; | ||
150 | #address-cells = <1>; | ||
151 | #size-cells = <1>; | ||
152 | ranges = <0xb0000000 0x00000004 0xb0000000 0x50000000>; | ||
153 | clock-frequency = <0>; /* Filled in by U-Boot */ | ||
154 | |||
155 | EBC0: ebc { | ||
156 | compatible = "ibm,ebc"; | ||
157 | dcr-reg = <0x012 0x002>; | ||
158 | #address-cells = <2>; | ||
159 | #size-cells = <1>; | ||
160 | clock-frequency = <0>; /* Filled in by U-Boot */ | ||
161 | /* ranges property is supplied by U-Boot */ | ||
162 | ranges = < 0x00000003 0x00000000 0xe0000000 0x8000000>; | ||
163 | interrupts = <0x6 0x4>; | ||
164 | interrupt-parent = <&UIC1>; | ||
165 | |||
166 | nor_flash@0,0 { | ||
167 | compatible = "amd,s29gl512n", "cfi-flash"; | ||
168 | bank-width = <2>; | ||
169 | reg = <0x00000000 0x00000000 0x00400000>; | ||
170 | #address-cells = <1>; | ||
171 | #size-cells = <1>; | ||
172 | partition@0 { | ||
173 | label = "kernel"; | ||
174 | reg = <0x00000000 0x00180000>; | ||
175 | }; | ||
176 | partition@180000 { | ||
177 | label = "env"; | ||
178 | reg = <0x00180000 0x00020000>; | ||
179 | }; | ||
180 | partition@1a0000 { | ||
181 | label = "u-boot"; | ||
182 | reg = <0x001a0000 0x00060000>; | ||
183 | }; | ||
184 | }; | ||
185 | } | ||
186 | |||
187 | UART0: serial@ef600300 { | ||
188 | device_type = "serial"; | ||
189 | compatible = "ns16550"; | ||
190 | reg = <0xef600300 0x00000008>; | ||
191 | virtual-reg = <0xef600300>; | ||
192 | clock-frequency = <0>; /* Filled in by U-Boot */ | ||
193 | current-speed = <0>; /* Filled in by U-Boot */ | ||
194 | interrupt-parent = <&UIC1>; | ||
195 | interrupts = <0x1 0x4>; | ||
196 | }; | ||
197 | |||
198 | IIC0: i2c@ef600700 { | ||
199 | compatible = "ibm,iic"; | ||
200 | reg = <0xef600700 0x00000014>; | ||
201 | interrupt-parent = <&UIC0>; | ||
202 | interrupts = <0x2 0x4>; | ||
203 | }; | ||
204 | |||
205 | IIC1: i2c@ef600800 { | ||
206 | compatible = "ibm,iic"; | ||
207 | reg = <0xef600800 0x00000014>; | ||
208 | interrupt-parent = <&UIC0>; | ||
209 | interrupts = <0x3 0x4>; | ||
210 | }; | ||
211 | |||
212 | RGMII0: emac-rgmii@ef601500 { | ||
213 | compatible = "ibm,rgmii"; | ||
214 | reg = <0xef601500 0x00000008>; | ||
215 | has-mdio; | ||
216 | }; | ||
217 | |||
218 | TAH0: emac-tah@ef601350 { | ||
219 | compatible = "ibm,tah"; | ||
220 | reg = <0xef601350 0x00000030>; | ||
221 | }; | ||
222 | |||
223 | EMAC0: ethernet@ef600c00 { | ||
224 | device_type = "network"; | ||
225 | compatible = "ibm,emac4sync"; | ||
226 | interrupt-parent = <&EMAC0>; | ||
227 | interrupts = <0x0 0x1>; | ||
228 | #interrupt-cells = <1>; | ||
229 | #address-cells = <0>; | ||
230 | #size-cells = <0>; | ||
231 | interrupt-map = </*Status*/ 0x0 &UIC2 0x10 0x4 | ||
232 | /*Wake*/ 0x1 &UIC2 0x14 0x4>; | ||
233 | reg = <0xef600c00 0x000000c4>; | ||
234 | local-mac-address = [000000000000]; /* Filled in by U-Boot */ | ||
235 | mal-device = <&MAL0>; | ||
236 | mal-tx-channel = <0>; | ||
237 | mal-rx-channel = <0>; | ||
238 | cell-index = <0>; | ||
239 | max-frame-size = <9000>; | ||
240 | rx-fifo-size = <16384>; | ||
241 | tx-fifo-size = <2048>; | ||
242 | phy-mode = "rgmii"; | ||
243 | phy-map = <0x00000000>; | ||
244 | rgmii-device = <&RGMII0>; | ||
245 | rgmii-channel = <0>; | ||
246 | tah-device = <&TAH0>; | ||
247 | tah-channel = <0>; | ||
248 | has-inverted-stacr-oc; | ||
249 | has-new-stacr-staopc; | ||
250 | }; | ||
251 | }; | ||
252 | |||
253 | }; | ||
254 | }; | ||
diff --git a/arch/powerpc/boot/dts/mpc8308_p1m.dts b/arch/powerpc/boot/dts/mpc8308_p1m.dts new file mode 100644 index 000000000000..05a76ccfd499 --- /dev/null +++ b/arch/powerpc/boot/dts/mpc8308_p1m.dts | |||
@@ -0,0 +1,332 @@ | |||
1 | /* | ||
2 | * mpc8308_p1m Device Tree Source | ||
3 | * | ||
4 | * Copyright 2010 Ilya Yanok, Emcraft Systems, yanok@emcraft.com | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | |||
12 | /dts-v1/; | ||
13 | |||
14 | / { | ||
15 | compatible = "denx,mpc8308_p1m"; | ||
16 | #address-cells = <1>; | ||
17 | #size-cells = <1>; | ||
18 | |||
19 | aliases { | ||
20 | ethernet0 = &enet0; | ||
21 | ethernet1 = &enet1; | ||
22 | serial0 = &serial0; | ||
23 | serial1 = &serial1; | ||
24 | pci0 = &pci0; | ||
25 | }; | ||
26 | |||
27 | cpus { | ||
28 | #address-cells = <1>; | ||
29 | #size-cells = <0>; | ||
30 | |||
31 | PowerPC,8308@0 { | ||
32 | device_type = "cpu"; | ||
33 | reg = <0x0>; | ||
34 | d-cache-line-size = <32>; | ||
35 | i-cache-line-size = <32>; | ||
36 | d-cache-size = <16384>; | ||
37 | i-cache-size = <16384>; | ||
38 | timebase-frequency = <0>; // from bootloader | ||
39 | bus-frequency = <0>; // from bootloader | ||
40 | clock-frequency = <0>; // from bootloader | ||
41 | }; | ||
42 | }; | ||
43 | |||
44 | memory { | ||
45 | device_type = "memory"; | ||
46 | reg = <0x00000000 0x08000000>; // 128MB at 0 | ||
47 | }; | ||
48 | |||
49 | localbus@e0005000 { | ||
50 | #address-cells = <2>; | ||
51 | #size-cells = <1>; | ||
52 | compatible = "fsl,mpc8315-elbc", "fsl,elbc", "simple-bus"; | ||
53 | reg = <0xe0005000 0x1000>; | ||
54 | interrupts = <77 0x8>; | ||
55 | interrupt-parent = <&ipic>; | ||
56 | |||
57 | ranges = <0x0 0x0 0xfc000000 0x04000000 | ||
58 | 0x1 0x0 0xfbff0000 0x00008000 | ||
59 | 0x2 0x0 0xfbff8000 0x00008000>; | ||
60 | |||
61 | flash@0,0 { | ||
62 | #address-cells = <1>; | ||
63 | #size-cells = <1>; | ||
64 | compatible = "cfi-flash"; | ||
65 | reg = <0x0 0x0 0x4000000>; | ||
66 | bank-width = <2>; | ||
67 | device-width = <1>; | ||
68 | |||
69 | u-boot@0 { | ||
70 | reg = <0x0 0x60000>; | ||
71 | read-only; | ||
72 | }; | ||
73 | env@60000 { | ||
74 | reg = <0x60000 0x20000>; | ||
75 | }; | ||
76 | env1@80000 { | ||
77 | reg = <0x80000 0x20000>; | ||
78 | }; | ||
79 | kernel@a0000 { | ||
80 | reg = <0xa0000 0x200000>; | ||
81 | }; | ||
82 | dtb@2a0000 { | ||
83 | reg = <0x2a0000 0x20000>; | ||
84 | }; | ||
85 | ramdisk@2c0000 { | ||
86 | reg = <0x2c0000 0x640000>; | ||
87 | }; | ||
88 | user@700000 { | ||
89 | reg = <0x700000 0x3900000>; | ||
90 | }; | ||
91 | }; | ||
92 | |||
93 | can@1,0 { | ||
94 | compatible = "nxp,sja1000"; | ||
95 | reg = <0x1 0x0 0x80>; | ||
96 | interrupts = <18 0x8>; | ||
97 | interrups-parent = <&ipic>; | ||
98 | }; | ||
99 | |||
100 | cpld@2,0 { | ||
101 | compatible = "denx,mpc8308_p1m-cpld"; | ||
102 | reg = <0x2 0x0 0x8>; | ||
103 | interrupts = <48 0x8>; | ||
104 | interrups-parent = <&ipic>; | ||
105 | }; | ||
106 | }; | ||
107 | |||
108 | immr@e0000000 { | ||
109 | #address-cells = <1>; | ||
110 | #size-cells = <1>; | ||
111 | device_type = "soc"; | ||
112 | compatible = "fsl,mpc8308-immr", "simple-bus"; | ||
113 | ranges = <0 0xe0000000 0x00100000>; | ||
114 | reg = <0xe0000000 0x00000200>; | ||
115 | bus-frequency = <0>; | ||
116 | |||
117 | i2c@3000 { | ||
118 | #address-cells = <1>; | ||
119 | #size-cells = <0>; | ||
120 | compatible = "fsl-i2c"; | ||
121 | reg = <0x3000 0x100>; | ||
122 | interrupts = <14 0x8>; | ||
123 | interrupt-parent = <&ipic>; | ||
124 | dfsrr; | ||
125 | fram@50 { | ||
126 | compatible = "ramtron,24c64"; | ||
127 | reg = <0x50>; | ||
128 | }; | ||
129 | }; | ||
130 | |||
131 | i2c@3100 { | ||
132 | #address-cells = <1>; | ||
133 | #size-cells = <0>; | ||
134 | compatible = "fsl-i2c"; | ||
135 | reg = <0x3100 0x100>; | ||
136 | interrupts = <15 0x8>; | ||
137 | interrupt-parent = <&ipic>; | ||
138 | dfsrr; | ||
139 | pwm@28 { | ||
140 | compatible = "maxim,ds1050"; | ||
141 | reg = <0x28>; | ||
142 | }; | ||
143 | sensor@48 { | ||
144 | compatible = "maxim,max6625"; | ||
145 | reg = <0x48>; | ||
146 | }; | ||
147 | sensor@49 { | ||
148 | compatible = "maxim,max6625"; | ||
149 | reg = <0x49>; | ||
150 | }; | ||
151 | sensor@4b { | ||
152 | compatible = "maxim,max6625"; | ||
153 | reg = <0x4b>; | ||
154 | }; | ||
155 | }; | ||
156 | |||
157 | usb@23000 { | ||
158 | compatible = "fsl-usb2-dr"; | ||
159 | reg = <0x23000 0x1000>; | ||
160 | #address-cells = <1>; | ||
161 | #size-cells = <0>; | ||
162 | interrupt-parent = <&ipic>; | ||
163 | interrupts = <38 0x8>; | ||
164 | dr_mode = "peripheral"; | ||
165 | phy_type = "ulpi"; | ||
166 | }; | ||
167 | |||
168 | enet0: ethernet@24000 { | ||
169 | #address-cells = <1>; | ||
170 | #size-cells = <1>; | ||
171 | ranges = <0x0 0x24000 0x1000>; | ||
172 | |||
173 | cell-index = <0>; | ||
174 | device_type = "network"; | ||
175 | model = "eTSEC"; | ||
176 | compatible = "gianfar"; | ||
177 | reg = <0x24000 0x1000>; | ||
178 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
179 | interrupts = <32 0x8 33 0x8 34 0x8>; | ||
180 | interrupt-parent = <&ipic>; | ||
181 | phy-handle = < &phy1 >; | ||
182 | |||
183 | mdio@520 { | ||
184 | #address-cells = <1>; | ||
185 | #size-cells = <0>; | ||
186 | compatible = "fsl,gianfar-mdio"; | ||
187 | reg = <0x520 0x20>; | ||
188 | phy1: ethernet-phy@1 { | ||
189 | interrupt-parent = <&ipic>; | ||
190 | interrupts = <17 0x8>; | ||
191 | reg = <0x1>; | ||
192 | device_type = "ethernet-phy"; | ||
193 | }; | ||
194 | phy2: ethernet-phy@2 { | ||
195 | interrupt-parent = <&ipic>; | ||
196 | interrupts = <19 0x8>; | ||
197 | reg = <0x2>; | ||
198 | device_type = "ethernet-phy"; | ||
199 | }; | ||
200 | tbi0: tbi-phy@11 { | ||
201 | reg = <0x11>; | ||
202 | device_type = "tbi-phy"; | ||
203 | }; | ||
204 | }; | ||
205 | }; | ||
206 | |||
207 | enet1: ethernet@25000 { | ||
208 | #address-cells = <1>; | ||
209 | #size-cells = <1>; | ||
210 | cell-index = <1>; | ||
211 | device_type = "network"; | ||
212 | model = "eTSEC"; | ||
213 | compatible = "gianfar"; | ||
214 | reg = <0x25000 0x1000>; | ||
215 | ranges = <0x0 0x25000 0x1000>; | ||
216 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
217 | interrupts = <35 0x8 36 0x8 37 0x8>; | ||
218 | interrupt-parent = <&ipic>; | ||
219 | phy-handle = < &phy2 >; | ||
220 | |||
221 | mdio@520 { | ||
222 | #address-cells = <1>; | ||
223 | #size-cells = <0>; | ||
224 | compatible = "fsl,gianfar-tbi"; | ||
225 | reg = <0x520 0x20>; | ||
226 | tbi1: tbi-phy@11 { | ||
227 | reg = <0x11>; | ||
228 | device_type = "tbi-phy"; | ||
229 | }; | ||
230 | }; | ||
231 | }; | ||
232 | |||
233 | serial0: serial@4500 { | ||
234 | cell-index = <0>; | ||
235 | device_type = "serial"; | ||
236 | compatible = "ns16550"; | ||
237 | reg = <0x4500 0x100>; | ||
238 | clock-frequency = <133333333>; | ||
239 | interrupts = <9 0x8>; | ||
240 | interrupt-parent = <&ipic>; | ||
241 | }; | ||
242 | |||
243 | serial1: serial@4600 { | ||
244 | cell-index = <1>; | ||
245 | device_type = "serial"; | ||
246 | compatible = "ns16550"; | ||
247 | reg = <0x4600 0x100>; | ||
248 | clock-frequency = <133333333>; | ||
249 | interrupts = <10 0x8>; | ||
250 | interrupt-parent = <&ipic>; | ||
251 | }; | ||
252 | |||
253 | gpio@c00 { | ||
254 | #gpio-cells = <2>; | ||
255 | compatible = "fsl,mpc8308-gpio", "fsl,mpc8349-gpio"; | ||
256 | reg = <0xc00 0x18>; | ||
257 | interrupts = <74 0x8>; | ||
258 | interrupt-parent = <&ipic>; | ||
259 | gpio-controller; | ||
260 | }; | ||
261 | |||
262 | timer@500 { | ||
263 | compatible = "fsl,mpc8308-gtm", "fsl,gtm"; | ||
264 | reg = <0x500 0x100>; | ||
265 | interrupts = <90 8 78 8 84 8 72 8>; | ||
266 | interrupt-parent = <&ipic>; | ||
267 | clock-frequency = <133333333>; | ||
268 | }; | ||
269 | |||
270 | /* IPIC | ||
271 | * interrupts cell = <intr #, sense> | ||
272 | * sense values match linux IORESOURCE_IRQ_* defines: | ||
273 | * sense == 8: Level, low assertion | ||
274 | * sense == 2: Edge, high-to-low change | ||
275 | */ | ||
276 | ipic: interrupt-controller@700 { | ||
277 | compatible = "fsl,ipic"; | ||
278 | interrupt-controller; | ||
279 | #address-cells = <0>; | ||
280 | #interrupt-cells = <2>; | ||
281 | reg = <0x700 0x100>; | ||
282 | device_type = "ipic"; | ||
283 | }; | ||
284 | |||
285 | ipic-msi@7c0 { | ||
286 | compatible = "fsl,ipic-msi"; | ||
287 | reg = <0x7c0 0x40>; | ||
288 | msi-available-ranges = <0x0 0x100>; | ||
289 | interrupts = < 0x43 0x8 | ||
290 | 0x4 0x8 | ||
291 | 0x51 0x8 | ||
292 | 0x52 0x8 | ||
293 | 0x56 0x8 | ||
294 | 0x57 0x8 | ||
295 | 0x58 0x8 | ||
296 | 0x59 0x8 >; | ||
297 | interrupt-parent = < &ipic >; | ||
298 | }; | ||
299 | |||
300 | }; | ||
301 | |||
302 | pci0: pcie@e0009000 { | ||
303 | #address-cells = <3>; | ||
304 | #size-cells = <2>; | ||
305 | #interrupt-cells = <1>; | ||
306 | device_type = "pci"; | ||
307 | compatible = "fsl,mpc8308-pcie", "fsl,mpc8314-pcie"; | ||
308 | reg = <0xe0009000 0x00001000 | ||
309 | 0xb0000000 0x01000000>; | ||
310 | ranges = <0x02000000 0 0xa0000000 0xa0000000 0 0x10000000 | ||
311 | 0x01000000 0 0x00000000 0xb1000000 0 0x00800000>; | ||
312 | bus-range = <0 0>; | ||
313 | interrupt-map-mask = <0 0 0 0>; | ||
314 | interrupt-map = <0 0 0 0 &ipic 1 8>; | ||
315 | interrupts = <0x1 0x8>; | ||
316 | interrupt-parent = <&ipic>; | ||
317 | clock-frequency = <0>; | ||
318 | |||
319 | pcie@0 { | ||
320 | #address-cells = <3>; | ||
321 | #size-cells = <2>; | ||
322 | device_type = "pci"; | ||
323 | reg = <0 0 0 0 0>; | ||
324 | ranges = <0x02000000 0 0xa0000000 | ||
325 | 0x02000000 0 0xa0000000 | ||
326 | 0 0x10000000 | ||
327 | 0x01000000 0 0x00000000 | ||
328 | 0x01000000 0 0x00000000 | ||
329 | 0 0x00800000>; | ||
330 | }; | ||
331 | }; | ||
332 | }; | ||
diff --git a/arch/powerpc/boot/dts/mpc8536ds.dts b/arch/powerpc/boot/dts/mpc8536ds.dts index 815cebb2e3e5..a75c10eed269 100644 --- a/arch/powerpc/boot/dts/mpc8536ds.dts +++ b/arch/powerpc/boot/dts/mpc8536ds.dts | |||
@@ -108,6 +108,58 @@ | |||
108 | }; | 108 | }; |
109 | }; | 109 | }; |
110 | 110 | ||
111 | spi@7000 { | ||
112 | #address-cells = <1>; | ||
113 | #size-cells = <0>; | ||
114 | compatible = "fsl,mpc8536-espi"; | ||
115 | reg = <0x7000 0x1000>; | ||
116 | interrupts = <59 0x2>; | ||
117 | interrupt-parent = <&mpic>; | ||
118 | fsl,espi-num-chipselects = <4>; | ||
119 | |||
120 | flash@0 { | ||
121 | #address-cells = <1>; | ||
122 | #size-cells = <1>; | ||
123 | compatible = "spansion,s25sl12801"; | ||
124 | reg = <0>; | ||
125 | spi-max-frequency = <40000000>; | ||
126 | partition@u-boot { | ||
127 | label = "u-boot"; | ||
128 | reg = <0x00000000 0x00100000>; | ||
129 | read-only; | ||
130 | }; | ||
131 | partition@kernel { | ||
132 | label = "kernel"; | ||
133 | reg = <0x00100000 0x00500000>; | ||
134 | read-only; | ||
135 | }; | ||
136 | partition@dtb { | ||
137 | label = "dtb"; | ||
138 | reg = <0x00600000 0x00100000>; | ||
139 | read-only; | ||
140 | }; | ||
141 | partition@fs { | ||
142 | label = "file system"; | ||
143 | reg = <0x00700000 0x00900000>; | ||
144 | }; | ||
145 | }; | ||
146 | flash@1 { | ||
147 | compatible = "spansion,s25sl12801"; | ||
148 | reg = <1>; | ||
149 | spi-max-frequency = <40000000>; | ||
150 | }; | ||
151 | flash@2 { | ||
152 | compatible = "spansion,s25sl12801"; | ||
153 | reg = <2>; | ||
154 | spi-max-frequency = <40000000>; | ||
155 | }; | ||
156 | flash@3 { | ||
157 | compatible = "spansion,s25sl12801"; | ||
158 | reg = <3>; | ||
159 | spi-max-frequency = <40000000>; | ||
160 | }; | ||
161 | }; | ||
162 | |||
111 | dma@21300 { | 163 | dma@21300 { |
112 | #address-cells = <1>; | 164 | #address-cells = <1>; |
113 | #size-cells = <1>; | 165 | #size-cells = <1>; |
diff --git a/arch/powerpc/boot/dts/p1022ds.dts b/arch/powerpc/boot/dts/p1022ds.dts index 8bcb10b92677..2bbecbb4cbf9 100644 --- a/arch/powerpc/boot/dts/p1022ds.dts +++ b/arch/powerpc/boot/dts/p1022ds.dts | |||
@@ -148,6 +148,17 @@ | |||
148 | label = "reserved-nand"; | 148 | label = "reserved-nand"; |
149 | }; | 149 | }; |
150 | }; | 150 | }; |
151 | |||
152 | board-control@3,0 { | ||
153 | compatible = "fsl,p1022ds-pixis"; | ||
154 | reg = <3 0 0x30>; | ||
155 | interrupt-parent = <&mpic>; | ||
156 | /* | ||
157 | * IRQ8 is generated if the "EVENT" switch is pressed | ||
158 | * and PX_CTL[EVESEL] is set to 00. | ||
159 | */ | ||
160 | interrupts = <8 8>; | ||
161 | }; | ||
151 | }; | 162 | }; |
152 | 163 | ||
153 | soc@fffe00000 { | 164 | soc@fffe00000 { |
diff --git a/arch/powerpc/boot/dts/p4080ds.dts b/arch/powerpc/boot/dts/p4080ds.dts index 2f0de24e3822..5b7fc29dd6cf 100644 --- a/arch/powerpc/boot/dts/p4080ds.dts +++ b/arch/powerpc/boot/dts/p4080ds.dts | |||
@@ -236,22 +236,19 @@ | |||
236 | }; | 236 | }; |
237 | 237 | ||
238 | spi@110000 { | 238 | spi@110000 { |
239 | cell-index = <0>; | ||
240 | #address-cells = <1>; | 239 | #address-cells = <1>; |
241 | #size-cells = <0>; | 240 | #size-cells = <0>; |
242 | compatible = "fsl,espi"; | 241 | compatible = "fsl,p4080-espi", "fsl,mpc8536-espi"; |
243 | reg = <0x110000 0x1000>; | 242 | reg = <0x110000 0x1000>; |
244 | interrupts = <53 0x2>; | 243 | interrupts = <53 0x2>; |
245 | interrupt-parent = <&mpic>; | 244 | interrupt-parent = <&mpic>; |
246 | espi,num-ss-bits = <4>; | 245 | fsl,espi-num-chipselects = <4>; |
247 | mode = "cpu"; | ||
248 | 246 | ||
249 | fsl_m25p80@0 { | 247 | flash@0 { |
250 | #address-cells = <1>; | 248 | #address-cells = <1>; |
251 | #size-cells = <1>; | 249 | #size-cells = <1>; |
252 | compatible = "fsl,espi-flash"; | 250 | compatible = "spansion,s25sl12801"; |
253 | reg = <0>; | 251 | reg = <0>; |
254 | linux,modalias = "fsl_m25p80"; | ||
255 | spi-max-frequency = <40000000>; /* input clock */ | 252 | spi-max-frequency = <40000000>; /* input clock */ |
256 | partition@u-boot { | 253 | partition@u-boot { |
257 | label = "u-boot"; | 254 | label = "u-boot"; |
diff --git a/arch/powerpc/configs/44x/bluestone_defconfig b/arch/powerpc/configs/44x/bluestone_defconfig new file mode 100644 index 000000000000..ac65b48b8ccd --- /dev/null +++ b/arch/powerpc/configs/44x/bluestone_defconfig | |||
@@ -0,0 +1,68 @@ | |||
1 | CONFIG_44x=y | ||
2 | CONFIG_EXPERIMENTAL=y | ||
3 | CONFIG_SYSVIPC=y | ||
4 | CONFIG_POSIX_MQUEUE=y | ||
5 | CONFIG_LOG_BUF_SHIFT=14 | ||
6 | CONFIG_BLK_DEV_INITRD=y | ||
7 | CONFIG_EMBEDDED=y | ||
8 | # CONFIG_VM_EVENT_COUNTERS is not set | ||
9 | # CONFIG_PCI_QUIRKS is not set | ||
10 | # CONFIG_COMPAT_BRK is not set | ||
11 | CONFIG_BLUESTONE=y | ||
12 | # CONFIG_EBONY is not set | ||
13 | # CONFIG_KVM_GUEST is not set | ||
14 | CONFIG_NO_HZ=y | ||
15 | CONFIG_HIGH_RES_TIMERS=y | ||
16 | CONFIG_SPARSE_IRQ=y | ||
17 | CONFIG_CMDLINE_BOOL=y | ||
18 | CONFIG_CMDLINE="" | ||
19 | CONFIG_NET=y | ||
20 | CONFIG_PACKET=y | ||
21 | CONFIG_UNIX=y | ||
22 | CONFIG_INET=y | ||
23 | CONFIG_IP_PNP=y | ||
24 | CONFIG_IP_PNP_DHCP=y | ||
25 | CONFIG_IP_PNP_BOOTP=y | ||
26 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | ||
27 | CONFIG_CONNECTOR=y | ||
28 | CONFIG_MTD=y | ||
29 | CONFIG_MTD_PARTITIONS=y | ||
30 | CONFIG_MTD_CMDLINE_PARTS=y | ||
31 | CONFIG_MTD_OF_PARTS=y | ||
32 | CONFIG_MTD_CHAR=y | ||
33 | CONFIG_MTD_BLOCK=y | ||
34 | CONFIG_MTD_CFI=y | ||
35 | CONFIG_MTD_CFI_AMDSTD=y | ||
36 | CONFIG_MTD_PHYSMAP_OF=y | ||
37 | CONFIG_PROC_DEVICETREE=y | ||
38 | CONFIG_BLK_DEV_RAM=y | ||
39 | CONFIG_BLK_DEV_RAM_SIZE=35000 | ||
40 | CONFIG_NETDEVICES=y | ||
41 | CONFIG_NET_ETHERNET=y | ||
42 | CONFIG_IBM_NEW_EMAC=y | ||
43 | CONFIG_IBM_NEW_EMAC_RXB=256 | ||
44 | CONFIG_IBM_NEW_EMAC_TXB=256 | ||
45 | CONFIG_SERIAL_8250=y | ||
46 | CONFIG_SERIAL_8250_CONSOLE=y | ||
47 | CONFIG_SERIAL_8250_NR_UARTS=2 | ||
48 | CONFIG_SERIAL_8250_RUNTIME_UARTS=2 | ||
49 | CONFIG_SERIAL_8250_EXTENDED=y | ||
50 | CONFIG_SERIAL_8250_SHARE_IRQ=y | ||
51 | CONFIG_SERIAL_OF_PLATFORM=y | ||
52 | CONFIG_I2C=y | ||
53 | CONFIG_I2C_CHARDEV=y | ||
54 | CONFIG_I2C_IBM_IIC=y | ||
55 | CONFIG_SENSORS_AD7414=y | ||
56 | # CONFIG_HID_SUPPORT is not set | ||
57 | # CONFIG_USB_SUPPORT is not set | ||
58 | CONFIG_RTC_CLASS=y | ||
59 | CONFIG_RTC_DRV_M41T80=y | ||
60 | CONFIG_EXT2_FS=y | ||
61 | CONFIG_EXT3_FS=y | ||
62 | CONFIG_PROC_KCORE=y | ||
63 | CONFIG_TMPFS=y | ||
64 | CONFIG_CRAMFS=y | ||
65 | CONFIG_NFS_FS=y | ||
66 | CONFIG_NFS_V3=y | ||
67 | CONFIG_ROOT_NFS=y | ||
68 | CONFIG_NLS=y | ||
diff --git a/arch/powerpc/configs/e55xx_smp_defconfig b/arch/powerpc/configs/e55xx_smp_defconfig new file mode 100644 index 000000000000..94d120ef99cf --- /dev/null +++ b/arch/powerpc/configs/e55xx_smp_defconfig | |||
@@ -0,0 +1,84 @@ | |||
1 | CONFIG_PPC64=y | ||
2 | CONFIG_PPC_BOOK3E_64=y | ||
3 | # CONFIG_VIRT_CPU_ACCOUNTING is not set | ||
4 | CONFIG_SMP=y | ||
5 | CONFIG_NR_CPUS=2 | ||
6 | CONFIG_EXPERIMENTAL=y | ||
7 | CONFIG_SYSVIPC=y | ||
8 | CONFIG_BSD_PROCESS_ACCT=y | ||
9 | CONFIG_IKCONFIG=y | ||
10 | CONFIG_IKCONFIG_PROC=y | ||
11 | CONFIG_LOG_BUF_SHIFT=14 | ||
12 | CONFIG_SYSFS_DEPRECATED_V2=y | ||
13 | CONFIG_BLK_DEV_INITRD=y | ||
14 | # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set | ||
15 | CONFIG_EMBEDDED=y | ||
16 | CONFIG_KALLSYMS_ALL=y | ||
17 | CONFIG_KALLSYMS_EXTRA_PASS=y | ||
18 | CONFIG_MODULES=y | ||
19 | CONFIG_MODULE_UNLOAD=y | ||
20 | CONFIG_MODULE_FORCE_UNLOAD=y | ||
21 | CONFIG_MODVERSIONS=y | ||
22 | # CONFIG_BLK_DEV_BSG is not set | ||
23 | CONFIG_P5020_DS=y | ||
24 | # CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set | ||
25 | CONFIG_NO_HZ=y | ||
26 | CONFIG_HIGH_RES_TIMERS=y | ||
27 | CONFIG_BINFMT_MISC=m | ||
28 | CONFIG_SPARSE_IRQ=y | ||
29 | # CONFIG_PCI is not set | ||
30 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | ||
31 | CONFIG_PROC_DEVICETREE=y | ||
32 | CONFIG_BLK_DEV_LOOP=y | ||
33 | CONFIG_BLK_DEV_RAM=y | ||
34 | CONFIG_BLK_DEV_RAM_SIZE=131072 | ||
35 | CONFIG_EEPROM_LEGACY=y | ||
36 | CONFIG_INPUT_FF_MEMLESS=m | ||
37 | # CONFIG_INPUT_MOUSEDEV is not set | ||
38 | # CONFIG_INPUT_KEYBOARD is not set | ||
39 | # CONFIG_INPUT_MOUSE is not set | ||
40 | CONFIG_SERIO_LIBPS2=y | ||
41 | CONFIG_SERIAL_8250=y | ||
42 | CONFIG_SERIAL_8250_CONSOLE=y | ||
43 | CONFIG_SERIAL_8250_EXTENDED=y | ||
44 | CONFIG_SERIAL_8250_MANY_PORTS=y | ||
45 | CONFIG_SERIAL_8250_DETECT_IRQ=y | ||
46 | CONFIG_SERIAL_8250_RSA=y | ||
47 | CONFIG_I2C=y | ||
48 | # CONFIG_HWMON is not set | ||
49 | CONFIG_VIDEO_OUTPUT_CONTROL=y | ||
50 | # CONFIG_HID_SUPPORT is not set | ||
51 | # CONFIG_USB_SUPPORT is not set | ||
52 | CONFIG_DMADEVICES=y | ||
53 | CONFIG_FSL_DMA=y | ||
54 | CONFIG_EXT2_FS=y | ||
55 | CONFIG_EXT3_FS=y | ||
56 | # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set | ||
57 | CONFIG_PROC_KCORE=y | ||
58 | CONFIG_TMPFS=y | ||
59 | # CONFIG_MISC_FILESYSTEMS is not set | ||
60 | CONFIG_PARTITION_ADVANCED=y | ||
61 | CONFIG_MAC_PARTITION=y | ||
62 | CONFIG_NLS=y | ||
63 | CONFIG_NLS_UTF8=m | ||
64 | CONFIG_CRC_T10DIF=y | ||
65 | CONFIG_CRC_ITU_T=m | ||
66 | CONFIG_LIBCRC32C=m | ||
67 | CONFIG_FRAME_WARN=1024 | ||
68 | CONFIG_DEBUG_FS=y | ||
69 | CONFIG_DEBUG_KERNEL=y | ||
70 | CONFIG_DETECT_HUNG_TASK=y | ||
71 | # CONFIG_DEBUG_BUGVERBOSE is not set | ||
72 | CONFIG_DEBUG_INFO=y | ||
73 | # CONFIG_RCU_CPU_STALL_DETECTOR is not set | ||
74 | CONFIG_SYSCTL_SYSCALL_CHECK=y | ||
75 | CONFIG_VIRQ_DEBUG=y | ||
76 | CONFIG_CRYPTO=y | ||
77 | CONFIG_CRYPTO_CBC=y | ||
78 | CONFIG_CRYPTO_PCBC=m | ||
79 | CONFIG_CRYPTO_HMAC=y | ||
80 | CONFIG_CRYPTO_MD5=y | ||
81 | CONFIG_CRYPTO_SHA1=m | ||
82 | CONFIG_CRYPTO_DES=y | ||
83 | # CONFIG_CRYPTO_ANSI_CPRNG is not set | ||
84 | CONFIG_CRYPTO_DEV_TALITOS=y | ||
diff --git a/arch/powerpc/configs/ppc44x_defconfig b/arch/powerpc/configs/ppc44x_defconfig index cd446fba3fae..2fa05f7be4cb 100644 --- a/arch/powerpc/configs/ppc44x_defconfig +++ b/arch/powerpc/configs/ppc44x_defconfig | |||
@@ -12,6 +12,7 @@ CONFIG_MODULES=y | |||
12 | CONFIG_MODULE_UNLOAD=y | 12 | CONFIG_MODULE_UNLOAD=y |
13 | # CONFIG_BLK_DEV_BSG is not set | 13 | # CONFIG_BLK_DEV_BSG is not set |
14 | CONFIG_BAMBOO=y | 14 | CONFIG_BAMBOO=y |
15 | CONFIG_BLUESTONE=y | ||
15 | CONFIG_SAM440EP=y | 16 | CONFIG_SAM440EP=y |
16 | CONFIG_SEQUOIA=y | 17 | CONFIG_SEQUOIA=y |
17 | CONFIG_TAISHAN=y | 18 | CONFIG_TAISHAN=y |
@@ -97,14 +98,17 @@ CONFIG_USB_STORAGE=m | |||
97 | CONFIG_EXT2_FS=y | 98 | CONFIG_EXT2_FS=y |
98 | CONFIG_EXT3_FS=m | 99 | CONFIG_EXT3_FS=m |
99 | # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set | 100 | # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set |
100 | CONFIG_INOTIFY=y | ||
101 | CONFIG_VFAT_FS=m | 101 | CONFIG_VFAT_FS=m |
102 | CONFIG_PROC_KCORE=y | 102 | CONFIG_PROC_KCORE=y |
103 | CONFIG_TMPFS=y | 103 | CONFIG_TMPFS=y |
104 | CONFIG_JFFS2_FS=y | 104 | CONFIG_JFFS2_FS=y |
105 | CONFIG_UBIFS_FS=m | 105 | CONFIG_UBIFS_FS=m |
106 | CONFIG_UBIFS_FS_XATTR=y | 106 | CONFIG_UBIFS_FS_XATTR=y |
107 | CONFIG_LOGFS=m | ||
107 | CONFIG_CRAMFS=y | 108 | CONFIG_CRAMFS=y |
109 | CONFIG_SQUASHFS=m | ||
110 | CONFIG_SQUASHFS_XATTR=y | ||
111 | CONFIG_SQUASHFS_LZO=y | ||
108 | CONFIG_NFS_FS=y | 112 | CONFIG_NFS_FS=y |
109 | CONFIG_NFS_V3=y | 113 | CONFIG_NFS_V3=y |
110 | CONFIG_ROOT_NFS=y | 114 | CONFIG_ROOT_NFS=y |
@@ -116,11 +120,8 @@ CONFIG_DEBUG_KERNEL=y | |||
116 | CONFIG_DETECT_HUNG_TASK=y | 120 | CONFIG_DETECT_HUNG_TASK=y |
117 | # CONFIG_RCU_CPU_STALL_DETECTOR is not set | 121 | # CONFIG_RCU_CPU_STALL_DETECTOR is not set |
118 | CONFIG_SYSCTL_SYSCALL_CHECK=y | 122 | CONFIG_SYSCTL_SYSCALL_CHECK=y |
119 | CONFIG_CRYPTO_CBC=y | ||
120 | CONFIG_CRYPTO_ECB=y | 123 | CONFIG_CRYPTO_ECB=y |
121 | CONFIG_CRYPTO_PCBC=y | 124 | CONFIG_CRYPTO_PCBC=y |
122 | CONFIG_CRYPTO_MD5=y | ||
123 | CONFIG_CRYPTO_DES=y | ||
124 | # CONFIG_CRYPTO_ANSI_CPRNG is not set | 125 | # CONFIG_CRYPTO_ANSI_CPRNG is not set |
125 | # CONFIG_CRYPTO_HW is not set | 126 | # CONFIG_CRYPTO_HW is not set |
126 | CONFIG_VIRTUALIZATION=y | 127 | CONFIG_VIRTUALIZATION=y |
diff --git a/arch/powerpc/configs/ppc64e_defconfig b/arch/powerpc/configs/ppc64e_defconfig index 04ae0740b6d0..7bd1763877ba 100644 --- a/arch/powerpc/configs/ppc64e_defconfig +++ b/arch/powerpc/configs/ppc64e_defconfig | |||
@@ -18,6 +18,7 @@ CONFIG_MODULES=y | |||
18 | CONFIG_MODULE_UNLOAD=y | 18 | CONFIG_MODULE_UNLOAD=y |
19 | CONFIG_MODVERSIONS=y | 19 | CONFIG_MODVERSIONS=y |
20 | CONFIG_MODULE_SRCVERSION_ALL=y | 20 | CONFIG_MODULE_SRCVERSION_ALL=y |
21 | CONFIG_P5020_DS=y | ||
21 | CONFIG_CPU_FREQ=y | 22 | CONFIG_CPU_FREQ=y |
22 | CONFIG_CPU_FREQ_GOV_POWERSAVE=y | 23 | CONFIG_CPU_FREQ_GOV_POWERSAVE=y |
23 | CONFIG_CPU_FREQ_GOV_USERSPACE=y | 24 | CONFIG_CPU_FREQ_GOV_USERSPACE=y |
@@ -256,7 +257,6 @@ CONFIG_HID_ZEROPLUS=y | |||
256 | CONFIG_USB=y | 257 | CONFIG_USB=y |
257 | CONFIG_USB_DEVICEFS=y | 258 | CONFIG_USB_DEVICEFS=y |
258 | CONFIG_USB_EHCI_HCD=y | 259 | CONFIG_USB_EHCI_HCD=y |
259 | CONFIG_USB_EHCI_TT_NEWSCHED=y | ||
260 | # CONFIG_USB_EHCI_HCD_PPC_OF is not set | 260 | # CONFIG_USB_EHCI_HCD_PPC_OF is not set |
261 | CONFIG_USB_OHCI_HCD=y | 261 | CONFIG_USB_OHCI_HCD=y |
262 | CONFIG_USB_STORAGE=m | 262 | CONFIG_USB_STORAGE=m |
@@ -290,7 +290,6 @@ CONFIG_JFS_POSIX_ACL=y | |||
290 | CONFIG_JFS_SECURITY=y | 290 | CONFIG_JFS_SECURITY=y |
291 | CONFIG_XFS_FS=m | 291 | CONFIG_XFS_FS=m |
292 | CONFIG_XFS_POSIX_ACL=y | 292 | CONFIG_XFS_POSIX_ACL=y |
293 | CONFIG_INOTIFY=y | ||
294 | CONFIG_AUTOFS4_FS=m | 293 | CONFIG_AUTOFS4_FS=m |
295 | CONFIG_ISO9660_FS=y | 294 | CONFIG_ISO9660_FS=y |
296 | CONFIG_UDF_FS=m | 295 | CONFIG_UDF_FS=m |
@@ -384,7 +383,6 @@ CONFIG_CRYPTO_TGR192=m | |||
384 | CONFIG_CRYPTO_WP512=m | 383 | CONFIG_CRYPTO_WP512=m |
385 | CONFIG_CRYPTO_AES=m | 384 | CONFIG_CRYPTO_AES=m |
386 | CONFIG_CRYPTO_ANUBIS=m | 385 | CONFIG_CRYPTO_ANUBIS=m |
387 | CONFIG_CRYPTO_ARC4=m | ||
388 | CONFIG_CRYPTO_BLOWFISH=m | 386 | CONFIG_CRYPTO_BLOWFISH=m |
389 | CONFIG_CRYPTO_CAST6=m | 387 | CONFIG_CRYPTO_CAST6=m |
390 | CONFIG_CRYPTO_KHAZAD=m | 388 | CONFIG_CRYPTO_KHAZAD=m |
diff --git a/arch/powerpc/include/asm/checksum.h b/arch/powerpc/include/asm/checksum.h index 7cdf358337cf..ce0c28495f9a 100644 --- a/arch/powerpc/include/asm/checksum.h +++ b/arch/powerpc/include/asm/checksum.h | |||
@@ -52,12 +52,22 @@ extern __wsum csum_partial(const void *buff, int len, __wsum sum); | |||
52 | extern __wsum csum_partial_copy_generic(const void *src, void *dst, | 52 | extern __wsum csum_partial_copy_generic(const void *src, void *dst, |
53 | int len, __wsum sum, | 53 | int len, __wsum sum, |
54 | int *src_err, int *dst_err); | 54 | int *src_err, int *dst_err); |
55 | |||
56 | #ifdef __powerpc64__ | ||
57 | #define _HAVE_ARCH_COPY_AND_CSUM_FROM_USER | ||
58 | extern __wsum csum_and_copy_from_user(const void __user *src, void *dst, | ||
59 | int len, __wsum sum, int *err_ptr); | ||
60 | #define HAVE_CSUM_COPY_USER | ||
61 | extern __wsum csum_and_copy_to_user(const void *src, void __user *dst, | ||
62 | int len, __wsum sum, int *err_ptr); | ||
63 | #else | ||
55 | /* | 64 | /* |
56 | * the same as csum_partial, but copies from src to dst while it | 65 | * the same as csum_partial, but copies from src to dst while it |
57 | * checksums. | 66 | * checksums. |
58 | */ | 67 | */ |
59 | #define csum_partial_copy_from_user(src, dst, len, sum, errp) \ | 68 | #define csum_partial_copy_from_user(src, dst, len, sum, errp) \ |
60 | csum_partial_copy_generic((__force const void *)(src), (dst), (len), (sum), (errp), NULL) | 69 | csum_partial_copy_generic((__force const void *)(src), (dst), (len), (sum), (errp), NULL) |
70 | #endif | ||
61 | 71 | ||
62 | #define csum_partial_copy_nocheck(src, dst, len, sum) \ | 72 | #define csum_partial_copy_nocheck(src, dst, len, sum) \ |
63 | csum_partial_copy_generic((src), (dst), (len), (sum), NULL, NULL) | 73 | csum_partial_copy_generic((src), (dst), (len), (sum), NULL, NULL) |
diff --git a/arch/powerpc/include/asm/compat.h b/arch/powerpc/include/asm/compat.h index a11d4eac4f97..2296112e247b 100644 --- a/arch/powerpc/include/asm/compat.h +++ b/arch/powerpc/include/asm/compat.h | |||
@@ -143,7 +143,7 @@ static inline void __user *arch_compat_alloc_user_space(long len) | |||
143 | * We cant access below the stack pointer in the 32bit ABI and | 143 | * We cant access below the stack pointer in the 32bit ABI and |
144 | * can access 288 bytes in the 64bit ABI | 144 | * can access 288 bytes in the 64bit ABI |
145 | */ | 145 | */ |
146 | if (!(test_thread_flag(TIF_32BIT))) | 146 | if (!is_32bit_task()) |
147 | usp -= 288; | 147 | usp -= 288; |
148 | 148 | ||
149 | return (void __user *) (usp - len); | 149 | return (void __user *) (usp - len); |
@@ -213,7 +213,7 @@ struct compat_shmid64_ds { | |||
213 | 213 | ||
214 | static inline int is_compat_task(void) | 214 | static inline int is_compat_task(void) |
215 | { | 215 | { |
216 | return test_thread_flag(TIF_32BIT); | 216 | return is_32bit_task(); |
217 | } | 217 | } |
218 | 218 | ||
219 | #endif /* __KERNEL__ */ | 219 | #endif /* __KERNEL__ */ |
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h index 3a40a992e594..f3a1fdd9cf08 100644 --- a/arch/powerpc/include/asm/cputable.h +++ b/arch/powerpc/include/asm/cputable.h | |||
@@ -198,6 +198,7 @@ extern const char *powerpc_base_platform; | |||
198 | #define CPU_FTR_CP_USE_DCBTZ LONG_ASM_CONST(0x0040000000000000) | 198 | #define CPU_FTR_CP_USE_DCBTZ LONG_ASM_CONST(0x0040000000000000) |
199 | #define CPU_FTR_UNALIGNED_LD_STD LONG_ASM_CONST(0x0080000000000000) | 199 | #define CPU_FTR_UNALIGNED_LD_STD LONG_ASM_CONST(0x0080000000000000) |
200 | #define CPU_FTR_ASYM_SMT LONG_ASM_CONST(0x0100000000000000) | 200 | #define CPU_FTR_ASYM_SMT LONG_ASM_CONST(0x0100000000000000) |
201 | #define CPU_FTR_STCX_CHECKS_ADDRESS LONG_ASM_CONST(0x0200000000000000) | ||
201 | 202 | ||
202 | #ifndef __ASSEMBLY__ | 203 | #ifndef __ASSEMBLY__ |
203 | 204 | ||
@@ -392,28 +393,31 @@ extern const char *powerpc_base_platform; | |||
392 | CPU_FTR_MMCRA | CPU_FTR_CTRL) | 393 | CPU_FTR_MMCRA | CPU_FTR_CTRL) |
393 | #define CPU_FTRS_POWER4 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \ | 394 | #define CPU_FTRS_POWER4 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \ |
394 | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ | 395 | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ |
395 | CPU_FTR_MMCRA | CPU_FTR_CP_USE_DCBTZ) | 396 | CPU_FTR_MMCRA | CPU_FTR_CP_USE_DCBTZ | \ |
397 | CPU_FTR_STCX_CHECKS_ADDRESS) | ||
396 | #define CPU_FTRS_PPC970 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \ | 398 | #define CPU_FTRS_PPC970 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \ |
397 | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ | 399 | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ |
398 | CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP | CPU_FTR_MMCRA | \ | 400 | CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP | CPU_FTR_MMCRA | \ |
399 | CPU_FTR_CP_USE_DCBTZ) | 401 | CPU_FTR_CP_USE_DCBTZ | CPU_FTR_STCX_CHECKS_ADDRESS) |
400 | #define CPU_FTRS_POWER5 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \ | 402 | #define CPU_FTRS_POWER5 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \ |
401 | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ | 403 | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ |
402 | CPU_FTR_MMCRA | CPU_FTR_SMT | \ | 404 | CPU_FTR_MMCRA | CPU_FTR_SMT | \ |
403 | CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \ | 405 | CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \ |
404 | CPU_FTR_PURR) | 406 | CPU_FTR_PURR | CPU_FTR_STCX_CHECKS_ADDRESS) |
405 | #define CPU_FTRS_POWER6 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \ | 407 | #define CPU_FTRS_POWER6 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \ |
406 | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ | 408 | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ |
407 | CPU_FTR_MMCRA | CPU_FTR_SMT | \ | 409 | CPU_FTR_MMCRA | CPU_FTR_SMT | \ |
408 | CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \ | 410 | CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \ |
409 | CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \ | 411 | CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \ |
410 | CPU_FTR_DSCR | CPU_FTR_UNALIGNED_LD_STD) | 412 | CPU_FTR_DSCR | CPU_FTR_UNALIGNED_LD_STD | \ |
413 | CPU_FTR_STCX_CHECKS_ADDRESS) | ||
411 | #define CPU_FTRS_POWER7 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \ | 414 | #define CPU_FTRS_POWER7 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \ |
412 | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ | 415 | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ |
413 | CPU_FTR_MMCRA | CPU_FTR_SMT | \ | 416 | CPU_FTR_MMCRA | CPU_FTR_SMT | \ |
414 | CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \ | 417 | CPU_FTR_COHERENT_ICACHE | CPU_FTR_LOCKLESS_TLBIE | \ |
415 | CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \ | 418 | CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \ |
416 | CPU_FTR_DSCR | CPU_FTR_SAO | CPU_FTR_ASYM_SMT) | 419 | CPU_FTR_DSCR | CPU_FTR_SAO | CPU_FTR_ASYM_SMT | \ |
420 | CPU_FTR_STCX_CHECKS_ADDRESS) | ||
417 | #define CPU_FTRS_CELL (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \ | 421 | #define CPU_FTRS_CELL (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \ |
418 | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ | 422 | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ |
419 | CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \ | 423 | CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \ |
diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h index 8c9c6ad2004e..6d2416a85709 100644 --- a/arch/powerpc/include/asm/dma-mapping.h +++ b/arch/powerpc/include/asm/dma-mapping.h | |||
@@ -127,19 +127,7 @@ static inline int dma_supported(struct device *dev, u64 mask) | |||
127 | return dma_ops->dma_supported(dev, mask); | 127 | return dma_ops->dma_supported(dev, mask); |
128 | } | 128 | } |
129 | 129 | ||
130 | static inline int dma_set_mask(struct device *dev, u64 dma_mask) | 130 | extern int dma_set_mask(struct device *dev, u64 dma_mask); |
131 | { | ||
132 | struct dma_map_ops *dma_ops = get_dma_ops(dev); | ||
133 | |||
134 | if (unlikely(dma_ops == NULL)) | ||
135 | return -EIO; | ||
136 | if (dma_ops->set_dma_mask != NULL) | ||
137 | return dma_ops->set_dma_mask(dev, dma_mask); | ||
138 | if (!dev->dma_mask || !dma_supported(dev, dma_mask)) | ||
139 | return -EIO; | ||
140 | *dev->dma_mask = dma_mask; | ||
141 | return 0; | ||
142 | } | ||
143 | 131 | ||
144 | static inline void *dma_alloc_coherent(struct device *dev, size_t size, | 132 | static inline void *dma_alloc_coherent(struct device *dev, size_t size, |
145 | dma_addr_t *dma_handle, gfp_t flag) | 133 | dma_addr_t *dma_handle, gfp_t flag) |
diff --git a/arch/powerpc/include/asm/elf.h b/arch/powerpc/include/asm/elf.h index c376eda15313..2b917c69ed15 100644 --- a/arch/powerpc/include/asm/elf.h +++ b/arch/powerpc/include/asm/elf.h | |||
@@ -250,7 +250,7 @@ do { \ | |||
250 | * the 64bit ABI has never had these issues dont enable the workaround | 250 | * the 64bit ABI has never had these issues dont enable the workaround |
251 | * even if we have an executable stack. | 251 | * even if we have an executable stack. |
252 | */ | 252 | */ |
253 | # define elf_read_implies_exec(ex, exec_stk) (test_thread_flag(TIF_32BIT) ? \ | 253 | # define elf_read_implies_exec(ex, exec_stk) (is_32bit_task() ? \ |
254 | (exec_stk == EXSTACK_DEFAULT) : 0) | 254 | (exec_stk == EXSTACK_DEFAULT) : 0) |
255 | #else | 255 | #else |
256 | # define SET_PERSONALITY(ex) \ | 256 | # define SET_PERSONALITY(ex) \ |
diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h index 57c400071995..7778d6f0c878 100644 --- a/arch/powerpc/include/asm/exception-64s.h +++ b/arch/powerpc/include/asm/exception-64s.h | |||
@@ -137,7 +137,8 @@ | |||
137 | li r10,0; \ | 137 | li r10,0; \ |
138 | ld r11,exception_marker@toc(r2); \ | 138 | ld r11,exception_marker@toc(r2); \ |
139 | std r10,RESULT(r1); /* clear regs->result */ \ | 139 | std r10,RESULT(r1); /* clear regs->result */ \ |
140 | std r11,STACK_FRAME_OVERHEAD-16(r1); /* mark the frame */ | 140 | std r11,STACK_FRAME_OVERHEAD-16(r1); /* mark the frame */ \ |
141 | ACCOUNT_STOLEN_TIME | ||
141 | 142 | ||
142 | /* | 143 | /* |
143 | * Exception vectors. | 144 | * Exception vectors. |
diff --git a/arch/powerpc/include/asm/fsl_85xx_cache_sram.h b/arch/powerpc/include/asm/fsl_85xx_cache_sram.h new file mode 100644 index 000000000000..2af2bdc37b2e --- /dev/null +++ b/arch/powerpc/include/asm/fsl_85xx_cache_sram.h | |||
@@ -0,0 +1,48 @@ | |||
1 | /* | ||
2 | * Copyright 2009 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * Cache SRAM handling for QorIQ platform | ||
5 | * | ||
6 | * Author: Vivek Mahajan <vivek.mahajan@freescale.com> | ||
7 | |||
8 | * This file is derived from the original work done | ||
9 | * by Sylvain Munaut for the Bestcomm SRAM allocator. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the | ||
13 | * Free Software Foundation; either version 2 of the License, or (at your | ||
14 | * option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | */ | ||
25 | |||
26 | #ifndef __ASM_POWERPC_FSL_85XX_CACHE_SRAM_H__ | ||
27 | #define __ASM_POWERPC_FSL_85XX_CACHE_SRAM_H__ | ||
28 | |||
29 | #include <asm/rheap.h> | ||
30 | #include <linux/spinlock.h> | ||
31 | |||
32 | /* | ||
33 | * Cache-SRAM | ||
34 | */ | ||
35 | |||
36 | struct mpc85xx_cache_sram { | ||
37 | phys_addr_t base_phys; | ||
38 | void *base_virt; | ||
39 | unsigned int size; | ||
40 | rh_info_t *rh; | ||
41 | spinlock_t lock; | ||
42 | }; | ||
43 | |||
44 | extern void mpc85xx_cache_sram_free(void *ptr); | ||
45 | extern void *mpc85xx_cache_sram_alloc(unsigned int size, | ||
46 | phys_addr_t *phys, unsigned int align); | ||
47 | |||
48 | #endif /* __AMS_POWERPC_FSL_85XX_CACHE_SRAM_H__ */ | ||
diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h index bd100fcf40d0..ff08b70b36d4 100644 --- a/arch/powerpc/include/asm/hw_irq.h +++ b/arch/powerpc/include/asm/hw_irq.h | |||
@@ -16,42 +16,57 @@ extern void timer_interrupt(struct pt_regs *); | |||
16 | #ifdef CONFIG_PPC64 | 16 | #ifdef CONFIG_PPC64 |
17 | #include <asm/paca.h> | 17 | #include <asm/paca.h> |
18 | 18 | ||
19 | static inline unsigned long local_get_flags(void) | 19 | static inline unsigned long arch_local_save_flags(void) |
20 | { | 20 | { |
21 | unsigned long flags; | 21 | unsigned long flags; |
22 | 22 | ||
23 | __asm__ __volatile__("lbz %0,%1(13)" | 23 | asm volatile( |
24 | : "=r" (flags) | 24 | "lbz %0,%1(13)" |
25 | : "i" (offsetof(struct paca_struct, soft_enabled))); | 25 | : "=r" (flags) |
26 | : "i" (offsetof(struct paca_struct, soft_enabled))); | ||
26 | 27 | ||
27 | return flags; | 28 | return flags; |
28 | } | 29 | } |
29 | 30 | ||
30 | static inline unsigned long raw_local_irq_disable(void) | 31 | static inline unsigned long arch_local_irq_disable(void) |
31 | { | 32 | { |
32 | unsigned long flags, zero; | 33 | unsigned long flags, zero; |
33 | 34 | ||
34 | __asm__ __volatile__("li %1,0; lbz %0,%2(13); stb %1,%2(13)" | 35 | asm volatile( |
35 | : "=r" (flags), "=&r" (zero) | 36 | "li %1,0; lbz %0,%2(13); stb %1,%2(13)" |
36 | : "i" (offsetof(struct paca_struct, soft_enabled)) | 37 | : "=r" (flags), "=&r" (zero) |
37 | : "memory"); | 38 | : "i" (offsetof(struct paca_struct, soft_enabled)) |
39 | : "memory"); | ||
38 | 40 | ||
39 | return flags; | 41 | return flags; |
40 | } | 42 | } |
41 | 43 | ||
42 | extern void raw_local_irq_restore(unsigned long); | 44 | extern void arch_local_irq_restore(unsigned long); |
43 | extern void iseries_handle_interrupts(void); | 45 | extern void iseries_handle_interrupts(void); |
44 | 46 | ||
45 | #define raw_local_irq_enable() raw_local_irq_restore(1) | 47 | static inline void arch_local_irq_enable(void) |
46 | #define raw_local_save_flags(flags) ((flags) = local_get_flags()) | 48 | { |
47 | #define raw_local_irq_save(flags) ((flags) = raw_local_irq_disable()) | 49 | arch_local_irq_restore(1); |
50 | } | ||
51 | |||
52 | static inline unsigned long arch_local_irq_save(void) | ||
53 | { | ||
54 | return arch_local_irq_disable(); | ||
55 | } | ||
56 | |||
57 | static inline bool arch_irqs_disabled_flags(unsigned long flags) | ||
58 | { | ||
59 | return flags == 0; | ||
60 | } | ||
48 | 61 | ||
49 | #define raw_irqs_disabled() (local_get_flags() == 0) | 62 | static inline bool arch_irqs_disabled(void) |
50 | #define raw_irqs_disabled_flags(flags) ((flags) == 0) | 63 | { |
64 | return arch_irqs_disabled_flags(arch_local_save_flags()); | ||
65 | } | ||
51 | 66 | ||
52 | #ifdef CONFIG_PPC_BOOK3E | 67 | #ifdef CONFIG_PPC_BOOK3E |
53 | #define __hard_irq_enable() __asm__ __volatile__("wrteei 1": : :"memory"); | 68 | #define __hard_irq_enable() asm volatile("wrteei 1" : : : "memory"); |
54 | #define __hard_irq_disable() __asm__ __volatile__("wrteei 0": : :"memory"); | 69 | #define __hard_irq_disable() asm volatile("wrteei 0" : : : "memory"); |
55 | #else | 70 | #else |
56 | #define __hard_irq_enable() __mtmsrd(mfmsr() | MSR_EE, 1) | 71 | #define __hard_irq_enable() __mtmsrd(mfmsr() | MSR_EE, 1) |
57 | #define __hard_irq_disable() __mtmsrd(mfmsr() & ~MSR_EE, 1) | 72 | #define __hard_irq_disable() __mtmsrd(mfmsr() & ~MSR_EE, 1) |
@@ -64,64 +79,66 @@ extern void iseries_handle_interrupts(void); | |||
64 | get_paca()->hard_enabled = 0; \ | 79 | get_paca()->hard_enabled = 0; \ |
65 | } while(0) | 80 | } while(0) |
66 | 81 | ||
67 | #else | 82 | #else /* CONFIG_PPC64 */ |
68 | 83 | ||
69 | #if defined(CONFIG_BOOKE) | ||
70 | #define SET_MSR_EE(x) mtmsr(x) | 84 | #define SET_MSR_EE(x) mtmsr(x) |
71 | #define raw_local_irq_restore(flags) __asm__ __volatile__("wrtee %0" : : "r" (flags) : "memory") | 85 | |
86 | static inline unsigned long arch_local_save_flags(void) | ||
87 | { | ||
88 | return mfmsr(); | ||
89 | } | ||
90 | |||
91 | static inline void arch_local_irq_restore(unsigned long flags) | ||
92 | { | ||
93 | #if defined(CONFIG_BOOKE) | ||
94 | asm volatile("wrtee %0" : : "r" (flags) : "memory"); | ||
72 | #else | 95 | #else |
73 | #define SET_MSR_EE(x) mtmsr(x) | 96 | mtmsr(flags); |
74 | #define raw_local_irq_restore(flags) mtmsr(flags) | ||
75 | #endif | 97 | #endif |
98 | } | ||
76 | 99 | ||
77 | static inline void raw_local_irq_disable(void) | 100 | static inline unsigned long arch_local_irq_save(void) |
78 | { | 101 | { |
102 | unsigned long flags = arch_local_save_flags(); | ||
79 | #ifdef CONFIG_BOOKE | 103 | #ifdef CONFIG_BOOKE |
80 | __asm__ __volatile__("wrteei 0": : :"memory"); | 104 | asm volatile("wrteei 0" : : : "memory"); |
81 | #else | 105 | #else |
82 | unsigned long msr; | 106 | SET_MSR_EE(flags & ~MSR_EE); |
83 | |||
84 | msr = mfmsr(); | ||
85 | SET_MSR_EE(msr & ~MSR_EE); | ||
86 | #endif | 107 | #endif |
108 | return flags; | ||
87 | } | 109 | } |
88 | 110 | ||
89 | static inline void raw_local_irq_enable(void) | 111 | static inline void arch_local_irq_disable(void) |
90 | { | 112 | { |
91 | #ifdef CONFIG_BOOKE | 113 | #ifdef CONFIG_BOOKE |
92 | __asm__ __volatile__("wrteei 1": : :"memory"); | 114 | asm volatile("wrteei 0" : : : "memory"); |
93 | #else | 115 | #else |
94 | unsigned long msr; | 116 | arch_local_irq_save(); |
95 | |||
96 | msr = mfmsr(); | ||
97 | SET_MSR_EE(msr | MSR_EE); | ||
98 | #endif | 117 | #endif |
99 | } | 118 | } |
100 | 119 | ||
101 | static inline void raw_local_irq_save_ptr(unsigned long *flags) | 120 | static inline void arch_local_irq_enable(void) |
102 | { | 121 | { |
103 | unsigned long msr; | ||
104 | msr = mfmsr(); | ||
105 | *flags = msr; | ||
106 | #ifdef CONFIG_BOOKE | 122 | #ifdef CONFIG_BOOKE |
107 | __asm__ __volatile__("wrteei 0": : :"memory"); | 123 | asm volatile("wrteei 1" : : : "memory"); |
108 | #else | 124 | #else |
109 | SET_MSR_EE(msr & ~MSR_EE); | 125 | unsigned long msr = mfmsr(); |
126 | SET_MSR_EE(msr | MSR_EE); | ||
110 | #endif | 127 | #endif |
111 | } | 128 | } |
112 | 129 | ||
113 | #define raw_local_save_flags(flags) ((flags) = mfmsr()) | 130 | static inline bool arch_irqs_disabled_flags(unsigned long flags) |
114 | #define raw_local_irq_save(flags) raw_local_irq_save_ptr(&flags) | ||
115 | #define raw_irqs_disabled() ((mfmsr() & MSR_EE) == 0) | ||
116 | #define raw_irqs_disabled_flags(flags) (((flags) & MSR_EE) == 0) | ||
117 | |||
118 | #define hard_irq_disable() raw_local_irq_disable() | ||
119 | |||
120 | static inline int irqs_disabled_flags(unsigned long flags) | ||
121 | { | 131 | { |
122 | return (flags & MSR_EE) == 0; | 132 | return (flags & MSR_EE) == 0; |
123 | } | 133 | } |
124 | 134 | ||
135 | static inline bool arch_irqs_disabled(void) | ||
136 | { | ||
137 | return arch_irqs_disabled_flags(arch_local_save_flags()); | ||
138 | } | ||
139 | |||
140 | #define hard_irq_disable() arch_local_irq_disable() | ||
141 | |||
125 | #endif /* CONFIG_PPC64 */ | 142 | #endif /* CONFIG_PPC64 */ |
126 | 143 | ||
127 | /* | 144 | /* |
diff --git a/arch/powerpc/include/asm/hydra.h b/arch/powerpc/include/asm/hydra.h index 1ad4eed07fbe..5b0c98bd46ab 100644 --- a/arch/powerpc/include/asm/hydra.h +++ b/arch/powerpc/include/asm/hydra.h | |||
@@ -10,7 +10,7 @@ | |||
10 | * | 10 | * |
11 | * © Copyright 1995 Apple Computer, Inc. All rights reserved. | 11 | * © Copyright 1995 Apple Computer, Inc. All rights reserved. |
12 | * | 12 | * |
13 | * It's available online from http://chrp.apple.com/MacTech.pdf. | 13 | * It's available online from http://www.cpu.lu/~mlan/ftp/MacTech.pdf |
14 | * You can obtain paper copies of this book from computer bookstores or by | 14 | * You can obtain paper copies of this book from computer bookstores or by |
15 | * writing Morgan Kaufmann Publishers, Inc., 340 Pine Street, Sixth Floor, San | 15 | * writing Morgan Kaufmann Publishers, Inc., 340 Pine Street, Sixth Floor, San |
16 | * Francisco, CA 94104. Reference ISBN 1-55860-393-X. | 16 | * Francisco, CA 94104. Reference ISBN 1-55860-393-X. |
diff --git a/arch/powerpc/include/asm/irqflags.h b/arch/powerpc/include/asm/irqflags.h index 5f68ecfdf516..b85d8ddbb666 100644 --- a/arch/powerpc/include/asm/irqflags.h +++ b/arch/powerpc/include/asm/irqflags.h | |||
@@ -6,7 +6,7 @@ | |||
6 | 6 | ||
7 | #ifndef __ASSEMBLY__ | 7 | #ifndef __ASSEMBLY__ |
8 | /* | 8 | /* |
9 | * Get definitions for raw_local_save_flags(x), etc. | 9 | * Get definitions for arch_local_save_flags(x), etc. |
10 | */ | 10 | */ |
11 | #include <asm/hw_irq.h> | 11 | #include <asm/hw_irq.h> |
12 | 12 | ||
diff --git a/arch/powerpc/include/asm/kexec.h b/arch/powerpc/include/asm/kexec.h index 076327f2eff7..f54408d995b5 100644 --- a/arch/powerpc/include/asm/kexec.h +++ b/arch/powerpc/include/asm/kexec.h | |||
@@ -91,6 +91,7 @@ extern void machine_kexec_simple(struct kimage *image); | |||
91 | extern void crash_kexec_secondary(struct pt_regs *regs); | 91 | extern void crash_kexec_secondary(struct pt_regs *regs); |
92 | extern int overlaps_crashkernel(unsigned long start, unsigned long size); | 92 | extern int overlaps_crashkernel(unsigned long start, unsigned long size); |
93 | extern void reserve_crashkernel(void); | 93 | extern void reserve_crashkernel(void); |
94 | extern void machine_kexec_mask_interrupts(void); | ||
94 | 95 | ||
95 | #else /* !CONFIG_KEXEC */ | 96 | #else /* !CONFIG_KEXEC */ |
96 | static inline int kexec_sr_activated(int cpu) { return 0; } | 97 | static inline int kexec_sr_activated(int cpu) { return 0; } |
diff --git a/arch/powerpc/include/asm/kvm.h b/arch/powerpc/include/asm/kvm.h index 6c5547d82bbe..18ea6963ad77 100644 --- a/arch/powerpc/include/asm/kvm.h +++ b/arch/powerpc/include/asm/kvm.h | |||
@@ -86,5 +86,6 @@ struct kvm_guest_debug_arch { | |||
86 | 86 | ||
87 | #define KVM_INTERRUPT_SET -1U | 87 | #define KVM_INTERRUPT_SET -1U |
88 | #define KVM_INTERRUPT_UNSET -2U | 88 | #define KVM_INTERRUPT_UNSET -2U |
89 | #define KVM_INTERRUPT_SET_LEVEL -3U | ||
89 | 90 | ||
90 | #endif /* __LINUX_KVM_POWERPC_H */ | 91 | #endif /* __LINUX_KVM_POWERPC_H */ |
diff --git a/arch/powerpc/include/asm/kvm_asm.h b/arch/powerpc/include/asm/kvm_asm.h index c5ea4cda34b3..5b7504674397 100644 --- a/arch/powerpc/include/asm/kvm_asm.h +++ b/arch/powerpc/include/asm/kvm_asm.h | |||
@@ -58,6 +58,7 @@ | |||
58 | #define BOOK3S_INTERRUPT_INST_STORAGE 0x400 | 58 | #define BOOK3S_INTERRUPT_INST_STORAGE 0x400 |
59 | #define BOOK3S_INTERRUPT_INST_SEGMENT 0x480 | 59 | #define BOOK3S_INTERRUPT_INST_SEGMENT 0x480 |
60 | #define BOOK3S_INTERRUPT_EXTERNAL 0x500 | 60 | #define BOOK3S_INTERRUPT_EXTERNAL 0x500 |
61 | #define BOOK3S_INTERRUPT_EXTERNAL_LEVEL 0x501 | ||
61 | #define BOOK3S_INTERRUPT_ALIGNMENT 0x600 | 62 | #define BOOK3S_INTERRUPT_ALIGNMENT 0x600 |
62 | #define BOOK3S_INTERRUPT_PROGRAM 0x700 | 63 | #define BOOK3S_INTERRUPT_PROGRAM 0x700 |
63 | #define BOOK3S_INTERRUPT_FP_UNAVAIL 0x800 | 64 | #define BOOK3S_INTERRUPT_FP_UNAVAIL 0x800 |
@@ -84,7 +85,8 @@ | |||
84 | #define BOOK3S_IRQPRIO_EXTERNAL 13 | 85 | #define BOOK3S_IRQPRIO_EXTERNAL 13 |
85 | #define BOOK3S_IRQPRIO_DECREMENTER 14 | 86 | #define BOOK3S_IRQPRIO_DECREMENTER 14 |
86 | #define BOOK3S_IRQPRIO_PERFORMANCE_MONITOR 15 | 87 | #define BOOK3S_IRQPRIO_PERFORMANCE_MONITOR 15 |
87 | #define BOOK3S_IRQPRIO_MAX 16 | 88 | #define BOOK3S_IRQPRIO_EXTERNAL_LEVEL 16 |
89 | #define BOOK3S_IRQPRIO_MAX 17 | ||
88 | 90 | ||
89 | #define BOOK3S_HFLAG_DCBZ32 0x1 | 91 | #define BOOK3S_HFLAG_DCBZ32 0x1 |
90 | #define BOOK3S_HFLAG_SLB 0x2 | 92 | #define BOOK3S_HFLAG_SLB 0x2 |
diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h index 8274a2d43925..d62e703f1214 100644 --- a/arch/powerpc/include/asm/kvm_book3s.h +++ b/arch/powerpc/include/asm/kvm_book3s.h | |||
@@ -38,15 +38,6 @@ struct kvmppc_slb { | |||
38 | bool class : 1; | 38 | bool class : 1; |
39 | }; | 39 | }; |
40 | 40 | ||
41 | struct kvmppc_sr { | ||
42 | u32 raw; | ||
43 | u32 vsid; | ||
44 | bool Ks : 1; | ||
45 | bool Kp : 1; | ||
46 | bool nx : 1; | ||
47 | bool valid : 1; | ||
48 | }; | ||
49 | |||
50 | struct kvmppc_bat { | 41 | struct kvmppc_bat { |
51 | u64 raw; | 42 | u64 raw; |
52 | u32 bepi; | 43 | u32 bepi; |
@@ -69,6 +60,13 @@ struct kvmppc_sid_map { | |||
69 | #define SID_MAP_NUM (1 << SID_MAP_BITS) | 60 | #define SID_MAP_NUM (1 << SID_MAP_BITS) |
70 | #define SID_MAP_MASK (SID_MAP_NUM - 1) | 61 | #define SID_MAP_MASK (SID_MAP_NUM - 1) |
71 | 62 | ||
63 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
64 | #define SID_CONTEXTS 1 | ||
65 | #else | ||
66 | #define SID_CONTEXTS 128 | ||
67 | #define VSID_POOL_SIZE (SID_CONTEXTS * 16) | ||
68 | #endif | ||
69 | |||
72 | struct kvmppc_vcpu_book3s { | 70 | struct kvmppc_vcpu_book3s { |
73 | struct kvm_vcpu vcpu; | 71 | struct kvm_vcpu vcpu; |
74 | struct kvmppc_book3s_shadow_vcpu *shadow_vcpu; | 72 | struct kvmppc_book3s_shadow_vcpu *shadow_vcpu; |
@@ -79,20 +77,22 @@ struct kvmppc_vcpu_book3s { | |||
79 | u64 vsid; | 77 | u64 vsid; |
80 | } slb_shadow[64]; | 78 | } slb_shadow[64]; |
81 | u8 slb_shadow_max; | 79 | u8 slb_shadow_max; |
82 | struct kvmppc_sr sr[16]; | ||
83 | struct kvmppc_bat ibat[8]; | 80 | struct kvmppc_bat ibat[8]; |
84 | struct kvmppc_bat dbat[8]; | 81 | struct kvmppc_bat dbat[8]; |
85 | u64 hid[6]; | 82 | u64 hid[6]; |
86 | u64 gqr[8]; | 83 | u64 gqr[8]; |
87 | int slb_nr; | 84 | int slb_nr; |
88 | u32 dsisr; | ||
89 | u64 sdr1; | 85 | u64 sdr1; |
90 | u64 hior; | 86 | u64 hior; |
91 | u64 msr_mask; | 87 | u64 msr_mask; |
92 | u64 vsid_first; | ||
93 | u64 vsid_next; | 88 | u64 vsid_next; |
89 | #ifdef CONFIG_PPC_BOOK3S_32 | ||
90 | u32 vsid_pool[VSID_POOL_SIZE]; | ||
91 | #else | ||
92 | u64 vsid_first; | ||
94 | u64 vsid_max; | 93 | u64 vsid_max; |
95 | int context_id; | 94 | #endif |
95 | int context_id[SID_CONTEXTS]; | ||
96 | ulong prog_flags; /* flags to inject when giving a 700 trap */ | 96 | ulong prog_flags; /* flags to inject when giving a 700 trap */ |
97 | }; | 97 | }; |
98 | 98 | ||
@@ -131,9 +131,10 @@ extern void kvmppc_set_bat(struct kvm_vcpu *vcpu, struct kvmppc_bat *bat, | |||
131 | bool upper, u32 val); | 131 | bool upper, u32 val); |
132 | extern void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr); | 132 | extern void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr); |
133 | extern int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu); | 133 | extern int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu); |
134 | extern pfn_t kvmppc_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn); | ||
134 | 135 | ||
135 | extern u32 kvmppc_trampoline_lowmem; | 136 | extern ulong kvmppc_trampoline_lowmem; |
136 | extern u32 kvmppc_trampoline_enter; | 137 | extern ulong kvmppc_trampoline_enter; |
137 | extern void kvmppc_rmcall(ulong srr0, ulong srr1); | 138 | extern void kvmppc_rmcall(ulong srr0, ulong srr1); |
138 | extern void kvmppc_load_up_fpu(void); | 139 | extern void kvmppc_load_up_fpu(void); |
139 | extern void kvmppc_load_up_altivec(void); | 140 | extern void kvmppc_load_up_altivec(void); |
diff --git a/arch/powerpc/include/asm/kvm_fpu.h b/arch/powerpc/include/asm/kvm_fpu.h index c3d4f0518a67..92daae132492 100644 --- a/arch/powerpc/include/asm/kvm_fpu.h +++ b/arch/powerpc/include/asm/kvm_fpu.h | |||
@@ -82,7 +82,7 @@ FPD_THREE_IN(fmadd) | |||
82 | FPD_THREE_IN(fnmsub) | 82 | FPD_THREE_IN(fnmsub) |
83 | FPD_THREE_IN(fnmadd) | 83 | FPD_THREE_IN(fnmadd) |
84 | 84 | ||
85 | extern void kvm_cvt_fd(u32 *from, u64 *to, u64 *fpscr); | 85 | extern void kvm_cvt_fd(u32 *from, u64 *to); |
86 | extern void kvm_cvt_df(u64 *from, u32 *to, u64 *fpscr); | 86 | extern void kvm_cvt_df(u64 *from, u32 *to); |
87 | 87 | ||
88 | #endif | 88 | #endif |
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index b0b23c007d6e..bba3b9b72a39 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
26 | #include <linux/types.h> | 26 | #include <linux/types.h> |
27 | #include <linux/kvm_types.h> | 27 | #include <linux/kvm_types.h> |
28 | #include <linux/kvm_para.h> | ||
28 | #include <asm/kvm_asm.h> | 29 | #include <asm/kvm_asm.h> |
29 | 30 | ||
30 | #define KVM_MAX_VCPUS 1 | 31 | #define KVM_MAX_VCPUS 1 |
@@ -41,12 +42,17 @@ | |||
41 | 42 | ||
42 | #define HPTEG_CACHE_NUM (1 << 15) | 43 | #define HPTEG_CACHE_NUM (1 << 15) |
43 | #define HPTEG_HASH_BITS_PTE 13 | 44 | #define HPTEG_HASH_BITS_PTE 13 |
45 | #define HPTEG_HASH_BITS_PTE_LONG 12 | ||
44 | #define HPTEG_HASH_BITS_VPTE 13 | 46 | #define HPTEG_HASH_BITS_VPTE 13 |
45 | #define HPTEG_HASH_BITS_VPTE_LONG 5 | 47 | #define HPTEG_HASH_BITS_VPTE_LONG 5 |
46 | #define HPTEG_HASH_NUM_PTE (1 << HPTEG_HASH_BITS_PTE) | 48 | #define HPTEG_HASH_NUM_PTE (1 << HPTEG_HASH_BITS_PTE) |
49 | #define HPTEG_HASH_NUM_PTE_LONG (1 << HPTEG_HASH_BITS_PTE_LONG) | ||
47 | #define HPTEG_HASH_NUM_VPTE (1 << HPTEG_HASH_BITS_VPTE) | 50 | #define HPTEG_HASH_NUM_VPTE (1 << HPTEG_HASH_BITS_VPTE) |
48 | #define HPTEG_HASH_NUM_VPTE_LONG (1 << HPTEG_HASH_BITS_VPTE_LONG) | 51 | #define HPTEG_HASH_NUM_VPTE_LONG (1 << HPTEG_HASH_BITS_VPTE_LONG) |
49 | 52 | ||
53 | /* Physical Address Mask - allowed range of real mode RAM access */ | ||
54 | #define KVM_PAM 0x0fffffffffffffffULL | ||
55 | |||
50 | struct kvm; | 56 | struct kvm; |
51 | struct kvm_run; | 57 | struct kvm_run; |
52 | struct kvm_vcpu; | 58 | struct kvm_vcpu; |
@@ -159,8 +165,10 @@ struct kvmppc_mmu { | |||
159 | 165 | ||
160 | struct hpte_cache { | 166 | struct hpte_cache { |
161 | struct hlist_node list_pte; | 167 | struct hlist_node list_pte; |
168 | struct hlist_node list_pte_long; | ||
162 | struct hlist_node list_vpte; | 169 | struct hlist_node list_vpte; |
163 | struct hlist_node list_vpte_long; | 170 | struct hlist_node list_vpte_long; |
171 | struct rcu_head rcu_head; | ||
164 | u64 host_va; | 172 | u64 host_va; |
165 | u64 pfn; | 173 | u64 pfn; |
166 | ulong slot; | 174 | ulong slot; |
@@ -210,28 +218,20 @@ struct kvm_vcpu_arch { | |||
210 | u32 cr; | 218 | u32 cr; |
211 | #endif | 219 | #endif |
212 | 220 | ||
213 | ulong msr; | ||
214 | #ifdef CONFIG_PPC_BOOK3S | 221 | #ifdef CONFIG_PPC_BOOK3S |
215 | ulong shadow_msr; | 222 | ulong shadow_msr; |
216 | ulong hflags; | 223 | ulong hflags; |
217 | ulong guest_owned_ext; | 224 | ulong guest_owned_ext; |
218 | #endif | 225 | #endif |
219 | u32 mmucr; | 226 | u32 mmucr; |
220 | ulong sprg0; | ||
221 | ulong sprg1; | ||
222 | ulong sprg2; | ||
223 | ulong sprg3; | ||
224 | ulong sprg4; | 227 | ulong sprg4; |
225 | ulong sprg5; | 228 | ulong sprg5; |
226 | ulong sprg6; | 229 | ulong sprg6; |
227 | ulong sprg7; | 230 | ulong sprg7; |
228 | ulong srr0; | ||
229 | ulong srr1; | ||
230 | ulong csrr0; | 231 | ulong csrr0; |
231 | ulong csrr1; | 232 | ulong csrr1; |
232 | ulong dsrr0; | 233 | ulong dsrr0; |
233 | ulong dsrr1; | 234 | ulong dsrr1; |
234 | ulong dear; | ||
235 | ulong esr; | 235 | ulong esr; |
236 | u32 dec; | 236 | u32 dec; |
237 | u32 decar; | 237 | u32 decar; |
@@ -290,12 +290,17 @@ struct kvm_vcpu_arch { | |||
290 | struct tasklet_struct tasklet; | 290 | struct tasklet_struct tasklet; |
291 | u64 dec_jiffies; | 291 | u64 dec_jiffies; |
292 | unsigned long pending_exceptions; | 292 | unsigned long pending_exceptions; |
293 | struct kvm_vcpu_arch_shared *shared; | ||
294 | unsigned long magic_page_pa; /* phys addr to map the magic page to */ | ||
295 | unsigned long magic_page_ea; /* effect. addr to map the magic page to */ | ||
293 | 296 | ||
294 | #ifdef CONFIG_PPC_BOOK3S | 297 | #ifdef CONFIG_PPC_BOOK3S |
295 | struct hlist_head hpte_hash_pte[HPTEG_HASH_NUM_PTE]; | 298 | struct hlist_head hpte_hash_pte[HPTEG_HASH_NUM_PTE]; |
299 | struct hlist_head hpte_hash_pte_long[HPTEG_HASH_NUM_PTE_LONG]; | ||
296 | struct hlist_head hpte_hash_vpte[HPTEG_HASH_NUM_VPTE]; | 300 | struct hlist_head hpte_hash_vpte[HPTEG_HASH_NUM_VPTE]; |
297 | struct hlist_head hpte_hash_vpte_long[HPTEG_HASH_NUM_VPTE_LONG]; | 301 | struct hlist_head hpte_hash_vpte_long[HPTEG_HASH_NUM_VPTE_LONG]; |
298 | int hpte_cache_count; | 302 | int hpte_cache_count; |
303 | spinlock_t mmu_lock; | ||
299 | #endif | 304 | #endif |
300 | }; | 305 | }; |
301 | 306 | ||
diff --git a/arch/powerpc/include/asm/kvm_para.h b/arch/powerpc/include/asm/kvm_para.h index 2d48f6a63d0b..50533f9adf40 100644 --- a/arch/powerpc/include/asm/kvm_para.h +++ b/arch/powerpc/include/asm/kvm_para.h | |||
@@ -20,16 +20,153 @@ | |||
20 | #ifndef __POWERPC_KVM_PARA_H__ | 20 | #ifndef __POWERPC_KVM_PARA_H__ |
21 | #define __POWERPC_KVM_PARA_H__ | 21 | #define __POWERPC_KVM_PARA_H__ |
22 | 22 | ||
23 | #include <linux/types.h> | ||
24 | |||
25 | struct kvm_vcpu_arch_shared { | ||
26 | __u64 scratch1; | ||
27 | __u64 scratch2; | ||
28 | __u64 scratch3; | ||
29 | __u64 critical; /* Guest may not get interrupts if == r1 */ | ||
30 | __u64 sprg0; | ||
31 | __u64 sprg1; | ||
32 | __u64 sprg2; | ||
33 | __u64 sprg3; | ||
34 | __u64 srr0; | ||
35 | __u64 srr1; | ||
36 | __u64 dar; | ||
37 | __u64 msr; | ||
38 | __u32 dsisr; | ||
39 | __u32 int_pending; /* Tells the guest if we have an interrupt */ | ||
40 | __u32 sr[16]; | ||
41 | }; | ||
42 | |||
43 | #define KVM_SC_MAGIC_R0 0x4b564d21 /* "KVM!" */ | ||
44 | #define HC_VENDOR_KVM (42 << 16) | ||
45 | #define HC_EV_SUCCESS 0 | ||
46 | #define HC_EV_UNIMPLEMENTED 12 | ||
47 | |||
48 | #define KVM_FEATURE_MAGIC_PAGE 1 | ||
49 | |||
50 | #define KVM_MAGIC_FEAT_SR (1 << 0) | ||
51 | |||
23 | #ifdef __KERNEL__ | 52 | #ifdef __KERNEL__ |
24 | 53 | ||
54 | #ifdef CONFIG_KVM_GUEST | ||
55 | |||
56 | #include <linux/of.h> | ||
57 | |||
58 | static inline int kvm_para_available(void) | ||
59 | { | ||
60 | struct device_node *hyper_node; | ||
61 | |||
62 | hyper_node = of_find_node_by_path("/hypervisor"); | ||
63 | if (!hyper_node) | ||
64 | return 0; | ||
65 | |||
66 | if (!of_device_is_compatible(hyper_node, "linux,kvm")) | ||
67 | return 0; | ||
68 | |||
69 | return 1; | ||
70 | } | ||
71 | |||
72 | extern unsigned long kvm_hypercall(unsigned long *in, | ||
73 | unsigned long *out, | ||
74 | unsigned long nr); | ||
75 | |||
76 | #else | ||
77 | |||
25 | static inline int kvm_para_available(void) | 78 | static inline int kvm_para_available(void) |
26 | { | 79 | { |
27 | return 0; | 80 | return 0; |
28 | } | 81 | } |
29 | 82 | ||
83 | static unsigned long kvm_hypercall(unsigned long *in, | ||
84 | unsigned long *out, | ||
85 | unsigned long nr) | ||
86 | { | ||
87 | return HC_EV_UNIMPLEMENTED; | ||
88 | } | ||
89 | |||
90 | #endif | ||
91 | |||
92 | static inline long kvm_hypercall0_1(unsigned int nr, unsigned long *r2) | ||
93 | { | ||
94 | unsigned long in[8]; | ||
95 | unsigned long out[8]; | ||
96 | unsigned long r; | ||
97 | |||
98 | r = kvm_hypercall(in, out, nr | HC_VENDOR_KVM); | ||
99 | *r2 = out[0]; | ||
100 | |||
101 | return r; | ||
102 | } | ||
103 | |||
104 | static inline long kvm_hypercall0(unsigned int nr) | ||
105 | { | ||
106 | unsigned long in[8]; | ||
107 | unsigned long out[8]; | ||
108 | |||
109 | return kvm_hypercall(in, out, nr | HC_VENDOR_KVM); | ||
110 | } | ||
111 | |||
112 | static inline long kvm_hypercall1(unsigned int nr, unsigned long p1) | ||
113 | { | ||
114 | unsigned long in[8]; | ||
115 | unsigned long out[8]; | ||
116 | |||
117 | in[0] = p1; | ||
118 | return kvm_hypercall(in, out, nr | HC_VENDOR_KVM); | ||
119 | } | ||
120 | |||
121 | static inline long kvm_hypercall2(unsigned int nr, unsigned long p1, | ||
122 | unsigned long p2) | ||
123 | { | ||
124 | unsigned long in[8]; | ||
125 | unsigned long out[8]; | ||
126 | |||
127 | in[0] = p1; | ||
128 | in[1] = p2; | ||
129 | return kvm_hypercall(in, out, nr | HC_VENDOR_KVM); | ||
130 | } | ||
131 | |||
132 | static inline long kvm_hypercall3(unsigned int nr, unsigned long p1, | ||
133 | unsigned long p2, unsigned long p3) | ||
134 | { | ||
135 | unsigned long in[8]; | ||
136 | unsigned long out[8]; | ||
137 | |||
138 | in[0] = p1; | ||
139 | in[1] = p2; | ||
140 | in[2] = p3; | ||
141 | return kvm_hypercall(in, out, nr | HC_VENDOR_KVM); | ||
142 | } | ||
143 | |||
144 | static inline long kvm_hypercall4(unsigned int nr, unsigned long p1, | ||
145 | unsigned long p2, unsigned long p3, | ||
146 | unsigned long p4) | ||
147 | { | ||
148 | unsigned long in[8]; | ||
149 | unsigned long out[8]; | ||
150 | |||
151 | in[0] = p1; | ||
152 | in[1] = p2; | ||
153 | in[2] = p3; | ||
154 | in[3] = p4; | ||
155 | return kvm_hypercall(in, out, nr | HC_VENDOR_KVM); | ||
156 | } | ||
157 | |||
158 | |||
30 | static inline unsigned int kvm_arch_para_features(void) | 159 | static inline unsigned int kvm_arch_para_features(void) |
31 | { | 160 | { |
32 | return 0; | 161 | unsigned long r; |
162 | |||
163 | if (!kvm_para_available()) | ||
164 | return 0; | ||
165 | |||
166 | if(kvm_hypercall0_1(KVM_HC_FEATURES, &r)) | ||
167 | return 0; | ||
168 | |||
169 | return r; | ||
33 | } | 170 | } |
34 | 171 | ||
35 | #endif /* __KERNEL__ */ | 172 | #endif /* __KERNEL__ */ |
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h index 18d139ec2d22..ecb3bc74c344 100644 --- a/arch/powerpc/include/asm/kvm_ppc.h +++ b/arch/powerpc/include/asm/kvm_ppc.h | |||
@@ -107,6 +107,7 @@ extern int kvmppc_booke_init(void); | |||
107 | extern void kvmppc_booke_exit(void); | 107 | extern void kvmppc_booke_exit(void); |
108 | 108 | ||
109 | extern void kvmppc_core_destroy_mmu(struct kvm_vcpu *vcpu); | 109 | extern void kvmppc_core_destroy_mmu(struct kvm_vcpu *vcpu); |
110 | extern int kvmppc_kvm_pv(struct kvm_vcpu *vcpu); | ||
110 | 111 | ||
111 | /* | 112 | /* |
112 | * Cuts out inst bits with ordering according to spec. | 113 | * Cuts out inst bits with ordering according to spec. |
diff --git a/arch/powerpc/include/asm/lppaca.h b/arch/powerpc/include/asm/lppaca.h index 14b592dfb4e8..7f5e0fefebb0 100644 --- a/arch/powerpc/include/asm/lppaca.h +++ b/arch/powerpc/include/asm/lppaca.h | |||
@@ -153,6 +153,8 @@ struct lppaca { | |||
153 | 153 | ||
154 | extern struct lppaca lppaca[]; | 154 | extern struct lppaca lppaca[]; |
155 | 155 | ||
156 | #define lppaca_of(cpu) (*paca[cpu].lppaca_ptr) | ||
157 | |||
156 | /* | 158 | /* |
157 | * SLB shadow buffer structure as defined in the PAPR. The save_area | 159 | * SLB shadow buffer structure as defined in the PAPR. The save_area |
158 | * contains adjacent ESID and VSID pairs for each shadowed SLB. The | 160 | * contains adjacent ESID and VSID pairs for each shadowed SLB. The |
@@ -170,6 +172,33 @@ struct slb_shadow { | |||
170 | 172 | ||
171 | extern struct slb_shadow slb_shadow[]; | 173 | extern struct slb_shadow slb_shadow[]; |
172 | 174 | ||
175 | /* | ||
176 | * Layout of entries in the hypervisor's dispatch trace log buffer. | ||
177 | */ | ||
178 | struct dtl_entry { | ||
179 | u8 dispatch_reason; | ||
180 | u8 preempt_reason; | ||
181 | u16 processor_id; | ||
182 | u32 enqueue_to_dispatch_time; | ||
183 | u32 ready_to_enqueue_time; | ||
184 | u32 waiting_to_ready_time; | ||
185 | u64 timebase; | ||
186 | u64 fault_addr; | ||
187 | u64 srr0; | ||
188 | u64 srr1; | ||
189 | }; | ||
190 | |||
191 | #define DISPATCH_LOG_BYTES 4096 /* bytes per cpu */ | ||
192 | #define N_DISPATCH_LOG (DISPATCH_LOG_BYTES / sizeof(struct dtl_entry)) | ||
193 | |||
194 | /* | ||
195 | * When CONFIG_VIRT_CPU_ACCOUNTING = y, the cpu accounting code controls | ||
196 | * reading from the dispatch trace log. If other code wants to consume | ||
197 | * DTL entries, it can set this pointer to a function that will get | ||
198 | * called once for each DTL entry that gets processed. | ||
199 | */ | ||
200 | extern void (*dtl_consumer)(struct dtl_entry *entry, u64 index); | ||
201 | |||
173 | #endif /* CONFIG_PPC_BOOK3S */ | 202 | #endif /* CONFIG_PPC_BOOK3S */ |
174 | #endif /* __KERNEL__ */ | 203 | #endif /* __KERNEL__ */ |
175 | #endif /* _ASM_POWERPC_LPPACA_H */ | 204 | #endif /* _ASM_POWERPC_LPPACA_H */ |
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h index adc8e6cdf339..d045b0145537 100644 --- a/arch/powerpc/include/asm/machdep.h +++ b/arch/powerpc/include/asm/machdep.h | |||
@@ -102,6 +102,9 @@ struct machdep_calls { | |||
102 | void (*pci_dma_dev_setup)(struct pci_dev *dev); | 102 | void (*pci_dma_dev_setup)(struct pci_dev *dev); |
103 | void (*pci_dma_bus_setup)(struct pci_bus *bus); | 103 | void (*pci_dma_bus_setup)(struct pci_bus *bus); |
104 | 104 | ||
105 | /* Platform set_dma_mask override */ | ||
106 | int (*dma_set_mask)(struct device *dev, u64 dma_mask); | ||
107 | |||
105 | int (*probe)(void); | 108 | int (*probe)(void); |
106 | void (*setup_arch)(void); /* Optional, may be NULL */ | 109 | void (*setup_arch)(void); /* Optional, may be NULL */ |
107 | void (*init_early)(void); | 110 | void (*init_early)(void); |
diff --git a/arch/powerpc/include/asm/memblock.h b/arch/powerpc/include/asm/memblock.h index 3c29728b56b1..43efc345065e 100644 --- a/arch/powerpc/include/asm/memblock.h +++ b/arch/powerpc/include/asm/memblock.h | |||
@@ -5,11 +5,4 @@ | |||
5 | 5 | ||
6 | #define MEMBLOCK_DBG(fmt...) udbg_printf(fmt) | 6 | #define MEMBLOCK_DBG(fmt...) udbg_printf(fmt) |
7 | 7 | ||
8 | #ifdef CONFIG_PPC32 | ||
9 | extern phys_addr_t lowmem_end_addr; | ||
10 | #define MEMBLOCK_REAL_LIMIT lowmem_end_addr | ||
11 | #else | ||
12 | #define MEMBLOCK_REAL_LIMIT 0 | ||
13 | #endif | ||
14 | |||
15 | #endif /* _ASM_POWERPC_MEMBLOCK_H */ | 8 | #endif /* _ASM_POWERPC_MEMBLOCK_H */ |
diff --git a/arch/powerpc/include/asm/mmu-book3e.h b/arch/powerpc/include/asm/mmu-book3e.h index 87a1d787c5b6..8eaed81ea642 100644 --- a/arch/powerpc/include/asm/mmu-book3e.h +++ b/arch/powerpc/include/asm/mmu-book3e.h | |||
@@ -114,6 +114,17 @@ | |||
114 | 114 | ||
115 | #define MAS7_RPN 0xFFFFFFFF | 115 | #define MAS7_RPN 0xFFFFFFFF |
116 | 116 | ||
117 | /* Bit definitions for MMUCFG */ | ||
118 | #define MMUCFG_MAVN 0x00000003 /* MMU Architecture Version Number */ | ||
119 | #define MMUCFG_MAVN_V1 0x00000000 /* v1.0 */ | ||
120 | #define MMUCFG_MAVN_V2 0x00000001 /* v2.0 */ | ||
121 | #define MMUCFG_NTLBS 0x0000000c /* Number of TLBs */ | ||
122 | #define MMUCFG_PIDSIZE 0x000007c0 /* PID Reg Size */ | ||
123 | #define MMUCFG_TWC 0x00008000 /* TLB Write Conditional (v2.0) */ | ||
124 | #define MMUCFG_LRAT 0x00010000 /* LRAT Supported (v2.0) */ | ||
125 | #define MMUCFG_RASIZE 0x00fe0000 /* Real Addr Size */ | ||
126 | #define MMUCFG_LPIDSIZE 0x0f000000 /* LPID Reg Size */ | ||
127 | |||
117 | /* Bit definitions for MMUCSR0 */ | 128 | /* Bit definitions for MMUCSR0 */ |
118 | #define MMUCSR0_TLB1FI 0x00000002 /* TLB1 Flash invalidate */ | 129 | #define MMUCSR0_TLB1FI 0x00000002 /* TLB1 Flash invalidate */ |
119 | #define MMUCSR0_TLB0FI 0x00000004 /* TLB0 Flash invalidate */ | 130 | #define MMUCSR0_TLB0FI 0x00000004 /* TLB0 Flash invalidate */ |
@@ -133,6 +144,10 @@ | |||
133 | #define TLBnCFG_GTWE 0x00010000 /* Guest can write */ | 144 | #define TLBnCFG_GTWE 0x00010000 /* Guest can write */ |
134 | #define TLBnCFG_IND 0x00020000 /* IND entries supported */ | 145 | #define TLBnCFG_IND 0x00020000 /* IND entries supported */ |
135 | #define TLBnCFG_PT 0x00040000 /* Can load from page table */ | 146 | #define TLBnCFG_PT 0x00040000 /* Can load from page table */ |
147 | #define TLBnCFG_MINSIZE 0x00f00000 /* Minimum Page Size (v1.0) */ | ||
148 | #define TLBnCFG_MINSIZE_SHIFT 20 | ||
149 | #define TLBnCFG_MAXSIZE 0x000f0000 /* Maximum Page Size (v1.0) */ | ||
150 | #define TLBnCFG_MAXSIZE_SHIFT 16 | ||
136 | #define TLBnCFG_ASSOC 0xff000000 /* Associativity */ | 151 | #define TLBnCFG_ASSOC 0xff000000 /* Associativity */ |
137 | 152 | ||
138 | /* TLBnPS encoding */ | 153 | /* TLBnPS encoding */ |
diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h index 7ebf42ed84a2..bb40a06d3b77 100644 --- a/arch/powerpc/include/asm/mmu.h +++ b/arch/powerpc/include/asm/mmu.h | |||
@@ -2,6 +2,8 @@ | |||
2 | #define _ASM_POWERPC_MMU_H_ | 2 | #define _ASM_POWERPC_MMU_H_ |
3 | #ifdef __KERNEL__ | 3 | #ifdef __KERNEL__ |
4 | 4 | ||
5 | #include <linux/types.h> | ||
6 | |||
5 | #include <asm/asm-compat.h> | 7 | #include <asm/asm-compat.h> |
6 | #include <asm/feature-fixups.h> | 8 | #include <asm/feature-fixups.h> |
7 | 9 | ||
@@ -82,6 +84,16 @@ extern unsigned int __start___mmu_ftr_fixup, __stop___mmu_ftr_fixup; | |||
82 | extern void early_init_mmu(void); | 84 | extern void early_init_mmu(void); |
83 | extern void early_init_mmu_secondary(void); | 85 | extern void early_init_mmu_secondary(void); |
84 | 86 | ||
87 | extern void setup_initial_memory_limit(phys_addr_t first_memblock_base, | ||
88 | phys_addr_t first_memblock_size); | ||
89 | |||
90 | #ifdef CONFIG_PPC64 | ||
91 | /* This is our real memory area size on ppc64 server, on embedded, we | ||
92 | * make it match the size our of bolted TLB area | ||
93 | */ | ||
94 | extern u64 ppc64_rma_size; | ||
95 | #endif /* CONFIG_PPC64 */ | ||
96 | |||
85 | #endif /* !__ASSEMBLY__ */ | 97 | #endif /* !__ASSEMBLY__ */ |
86 | 98 | ||
87 | /* The kernel use the constants below to index in the page sizes array. | 99 | /* The kernel use the constants below to index in the page sizes array. |
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h index 1ff6662f7faf..ec57540cd7af 100644 --- a/arch/powerpc/include/asm/paca.h +++ b/arch/powerpc/include/asm/paca.h | |||
@@ -85,6 +85,8 @@ struct paca_struct { | |||
85 | u8 kexec_state; /* set when kexec down has irqs off */ | 85 | u8 kexec_state; /* set when kexec down has irqs off */ |
86 | #ifdef CONFIG_PPC_STD_MMU_64 | 86 | #ifdef CONFIG_PPC_STD_MMU_64 |
87 | struct slb_shadow *slb_shadow_ptr; | 87 | struct slb_shadow *slb_shadow_ptr; |
88 | struct dtl_entry *dispatch_log; | ||
89 | struct dtl_entry *dispatch_log_end; | ||
88 | 90 | ||
89 | /* | 91 | /* |
90 | * Now, starting in cacheline 2, the exception save areas | 92 | * Now, starting in cacheline 2, the exception save areas |
@@ -129,13 +131,19 @@ struct paca_struct { | |||
129 | u8 soft_enabled; /* irq soft-enable flag */ | 131 | u8 soft_enabled; /* irq soft-enable flag */ |
130 | u8 hard_enabled; /* set if irqs are enabled in MSR */ | 132 | u8 hard_enabled; /* set if irqs are enabled in MSR */ |
131 | u8 io_sync; /* writel() needs spin_unlock sync */ | 133 | u8 io_sync; /* writel() needs spin_unlock sync */ |
132 | u8 perf_event_pending; /* PM interrupt while soft-disabled */ | 134 | u8 irq_work_pending; /* IRQ_WORK interrupt while soft-disable */ |
133 | 135 | ||
134 | /* Stuff for accurate time accounting */ | 136 | /* Stuff for accurate time accounting */ |
135 | u64 user_time; /* accumulated usermode TB ticks */ | 137 | u64 user_time; /* accumulated usermode TB ticks */ |
136 | u64 system_time; /* accumulated system TB ticks */ | 138 | u64 system_time; /* accumulated system TB ticks */ |
137 | u64 startpurr; /* PURR/TB value snapshot */ | 139 | u64 user_time_scaled; /* accumulated usermode SPURR ticks */ |
140 | u64 starttime; /* TB value snapshot */ | ||
141 | u64 starttime_user; /* TB value on exit to usermode */ | ||
138 | u64 startspurr; /* SPURR value snapshot */ | 142 | u64 startspurr; /* SPURR value snapshot */ |
143 | u64 utime_sspurr; /* ->user_time when ->startspurr set */ | ||
144 | u64 stolen_time; /* TB ticks taken by hypervisor */ | ||
145 | u64 dtl_ridx; /* read index in dispatch log */ | ||
146 | struct dtl_entry *dtl_curr; /* pointer corresponding to dtl_ridx */ | ||
139 | 147 | ||
140 | #ifdef CONFIG_KVM_BOOK3S_HANDLER | 148 | #ifdef CONFIG_KVM_BOOK3S_HANDLER |
141 | /* We use this to store guest state in */ | 149 | /* We use this to store guest state in */ |
diff --git a/arch/powerpc/include/asm/page_64.h b/arch/powerpc/include/asm/page_64.h index 358ff14ea25e..932f88dcf6fa 100644 --- a/arch/powerpc/include/asm/page_64.h +++ b/arch/powerpc/include/asm/page_64.h | |||
@@ -163,7 +163,7 @@ do { \ | |||
163 | #endif /* !CONFIG_HUGETLB_PAGE */ | 163 | #endif /* !CONFIG_HUGETLB_PAGE */ |
164 | 164 | ||
165 | #define VM_DATA_DEFAULT_FLAGS \ | 165 | #define VM_DATA_DEFAULT_FLAGS \ |
166 | (test_thread_flag(TIF_32BIT) ? \ | 166 | (is_32bit_task() ? \ |
167 | VM_DATA_DEFAULT_FLAGS32 : VM_DATA_DEFAULT_FLAGS64) | 167 | VM_DATA_DEFAULT_FLAGS32 : VM_DATA_DEFAULT_FLAGS64) |
168 | 168 | ||
169 | /* | 169 | /* |
@@ -179,7 +179,7 @@ do { \ | |||
179 | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) | 179 | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) |
180 | 180 | ||
181 | #define VM_STACK_DEFAULT_FLAGS \ | 181 | #define VM_STACK_DEFAULT_FLAGS \ |
182 | (test_thread_flag(TIF_32BIT) ? \ | 182 | (is_32bit_task() ? \ |
183 | VM_STACK_DEFAULT_FLAGS32 : VM_STACK_DEFAULT_FLAGS64) | 183 | VM_STACK_DEFAULT_FLAGS32 : VM_STACK_DEFAULT_FLAGS64) |
184 | 184 | ||
185 | #include <asm-generic/getorder.h> | 185 | #include <asm-generic/getorder.h> |
diff --git a/arch/powerpc/include/asm/ppc-pci.h b/arch/powerpc/include/asm/ppc-pci.h index 42fdff0e4b32..43268f15004e 100644 --- a/arch/powerpc/include/asm/ppc-pci.h +++ b/arch/powerpc/include/asm/ppc-pci.h | |||
@@ -28,8 +28,8 @@ extern void find_and_init_phbs(void); | |||
28 | extern struct pci_dev *isa_bridge_pcidev; /* may be NULL if no ISA bus */ | 28 | extern struct pci_dev *isa_bridge_pcidev; /* may be NULL if no ISA bus */ |
29 | 29 | ||
30 | /** Bus Unit ID macros; get low and hi 32-bits of the 64-bit BUID */ | 30 | /** Bus Unit ID macros; get low and hi 32-bits of the 64-bit BUID */ |
31 | #define BUID_HI(buid) ((buid) >> 32) | 31 | #define BUID_HI(buid) upper_32_bits(buid) |
32 | #define BUID_LO(buid) ((buid) & 0xffffffff) | 32 | #define BUID_LO(buid) lower_32_bits(buid) |
33 | 33 | ||
34 | /* PCI device_node operations */ | 34 | /* PCI device_node operations */ |
35 | struct device_node; | 35 | struct device_node; |
diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h index 498fe09263d3..98210067c1cc 100644 --- a/arch/powerpc/include/asm/ppc_asm.h +++ b/arch/powerpc/include/asm/ppc_asm.h | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <asm/asm-compat.h> | 9 | #include <asm/asm-compat.h> |
10 | #include <asm/processor.h> | 10 | #include <asm/processor.h> |
11 | #include <asm/ppc-opcode.h> | 11 | #include <asm/ppc-opcode.h> |
12 | #include <asm/firmware.h> | ||
12 | 13 | ||
13 | #ifndef __ASSEMBLY__ | 14 | #ifndef __ASSEMBLY__ |
14 | #error __FILE__ should only be used in assembler files | 15 | #error __FILE__ should only be used in assembler files |
@@ -26,17 +27,13 @@ | |||
26 | #ifndef CONFIG_VIRT_CPU_ACCOUNTING | 27 | #ifndef CONFIG_VIRT_CPU_ACCOUNTING |
27 | #define ACCOUNT_CPU_USER_ENTRY(ra, rb) | 28 | #define ACCOUNT_CPU_USER_ENTRY(ra, rb) |
28 | #define ACCOUNT_CPU_USER_EXIT(ra, rb) | 29 | #define ACCOUNT_CPU_USER_EXIT(ra, rb) |
30 | #define ACCOUNT_STOLEN_TIME | ||
29 | #else | 31 | #else |
30 | #define ACCOUNT_CPU_USER_ENTRY(ra, rb) \ | 32 | #define ACCOUNT_CPU_USER_ENTRY(ra, rb) \ |
31 | beq 2f; /* if from kernel mode */ \ | 33 | beq 2f; /* if from kernel mode */ \ |
32 | BEGIN_FTR_SECTION; \ | 34 | MFTB(ra); /* get timebase */ \ |
33 | mfspr ra,SPRN_PURR; /* get processor util. reg */ \ | 35 | ld rb,PACA_STARTTIME_USER(r13); \ |
34 | END_FTR_SECTION_IFSET(CPU_FTR_PURR); \ | 36 | std ra,PACA_STARTTIME(r13); \ |
35 | BEGIN_FTR_SECTION; \ | ||
36 | MFTB(ra); /* or get TB if no PURR */ \ | ||
37 | END_FTR_SECTION_IFCLR(CPU_FTR_PURR); \ | ||
38 | ld rb,PACA_STARTPURR(r13); \ | ||
39 | std ra,PACA_STARTPURR(r13); \ | ||
40 | subf rb,rb,ra; /* subtract start value */ \ | 37 | subf rb,rb,ra; /* subtract start value */ \ |
41 | ld ra,PACA_USER_TIME(r13); \ | 38 | ld ra,PACA_USER_TIME(r13); \ |
42 | add ra,ra,rb; /* add on to user time */ \ | 39 | add ra,ra,rb; /* add on to user time */ \ |
@@ -44,19 +41,34 @@ END_FTR_SECTION_IFCLR(CPU_FTR_PURR); \ | |||
44 | 2: | 41 | 2: |
45 | 42 | ||
46 | #define ACCOUNT_CPU_USER_EXIT(ra, rb) \ | 43 | #define ACCOUNT_CPU_USER_EXIT(ra, rb) \ |
47 | BEGIN_FTR_SECTION; \ | 44 | MFTB(ra); /* get timebase */ \ |
48 | mfspr ra,SPRN_PURR; /* get processor util. reg */ \ | 45 | ld rb,PACA_STARTTIME(r13); \ |
49 | END_FTR_SECTION_IFSET(CPU_FTR_PURR); \ | 46 | std ra,PACA_STARTTIME_USER(r13); \ |
50 | BEGIN_FTR_SECTION; \ | ||
51 | MFTB(ra); /* or get TB if no PURR */ \ | ||
52 | END_FTR_SECTION_IFCLR(CPU_FTR_PURR); \ | ||
53 | ld rb,PACA_STARTPURR(r13); \ | ||
54 | std ra,PACA_STARTPURR(r13); \ | ||
55 | subf rb,rb,ra; /* subtract start value */ \ | 47 | subf rb,rb,ra; /* subtract start value */ \ |
56 | ld ra,PACA_SYSTEM_TIME(r13); \ | 48 | ld ra,PACA_SYSTEM_TIME(r13); \ |
57 | add ra,ra,rb; /* add on to user time */ \ | 49 | add ra,ra,rb; /* add on to system time */ \ |
58 | std ra,PACA_SYSTEM_TIME(r13); | 50 | std ra,PACA_SYSTEM_TIME(r13) |
59 | #endif | 51 | |
52 | #ifdef CONFIG_PPC_SPLPAR | ||
53 | #define ACCOUNT_STOLEN_TIME \ | ||
54 | BEGIN_FW_FTR_SECTION; \ | ||
55 | beq 33f; \ | ||
56 | /* from user - see if there are any DTL entries to process */ \ | ||
57 | ld r10,PACALPPACAPTR(r13); /* get ptr to VPA */ \ | ||
58 | ld r11,PACA_DTL_RIDX(r13); /* get log read index */ \ | ||
59 | ld r10,LPPACA_DTLIDX(r10); /* get log write index */ \ | ||
60 | cmpd cr1,r11,r10; \ | ||
61 | beq+ cr1,33f; \ | ||
62 | bl .accumulate_stolen_time; \ | ||
63 | 33: \ | ||
64 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR) | ||
65 | |||
66 | #else /* CONFIG_PPC_SPLPAR */ | ||
67 | #define ACCOUNT_STOLEN_TIME | ||
68 | |||
69 | #endif /* CONFIG_PPC_SPLPAR */ | ||
70 | |||
71 | #endif /* CONFIG_VIRT_CPU_ACCOUNTING */ | ||
60 | 72 | ||
61 | /* | 73 | /* |
62 | * Macros for storing registers into and loading registers from | 74 | * Macros for storing registers into and loading registers from |
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h index 19c05b0f74be..4c14187ba02d 100644 --- a/arch/powerpc/include/asm/processor.h +++ b/arch/powerpc/include/asm/processor.h | |||
@@ -118,7 +118,7 @@ extern struct task_struct *last_task_used_spe; | |||
118 | #define TASK_UNMAPPED_BASE_USER32 (PAGE_ALIGN(TASK_SIZE_USER32 / 4)) | 118 | #define TASK_UNMAPPED_BASE_USER32 (PAGE_ALIGN(TASK_SIZE_USER32 / 4)) |
119 | #define TASK_UNMAPPED_BASE_USER64 (PAGE_ALIGN(TASK_SIZE_USER64 / 4)) | 119 | #define TASK_UNMAPPED_BASE_USER64 (PAGE_ALIGN(TASK_SIZE_USER64 / 4)) |
120 | 120 | ||
121 | #define TASK_UNMAPPED_BASE ((test_thread_flag(TIF_32BIT)) ? \ | 121 | #define TASK_UNMAPPED_BASE ((is_32bit_task()) ? \ |
122 | TASK_UNMAPPED_BASE_USER32 : TASK_UNMAPPED_BASE_USER64 ) | 122 | TASK_UNMAPPED_BASE_USER32 : TASK_UNMAPPED_BASE_USER64 ) |
123 | #endif | 123 | #endif |
124 | 124 | ||
@@ -128,7 +128,7 @@ extern struct task_struct *last_task_used_spe; | |||
128 | #define STACK_TOP_USER64 TASK_SIZE_USER64 | 128 | #define STACK_TOP_USER64 TASK_SIZE_USER64 |
129 | #define STACK_TOP_USER32 TASK_SIZE_USER32 | 129 | #define STACK_TOP_USER32 TASK_SIZE_USER32 |
130 | 130 | ||
131 | #define STACK_TOP (test_thread_flag(TIF_32BIT) ? \ | 131 | #define STACK_TOP (is_32bit_task() ? \ |
132 | STACK_TOP_USER32 : STACK_TOP_USER64) | 132 | STACK_TOP_USER32 : STACK_TOP_USER64) |
133 | 133 | ||
134 | #define STACK_TOP_MAX STACK_TOP_USER64 | 134 | #define STACK_TOP_MAX STACK_TOP_USER64 |
diff --git a/arch/powerpc/include/asm/pte-common.h b/arch/powerpc/include/asm/pte-common.h index f2b370180a09..76bb195e4f24 100644 --- a/arch/powerpc/include/asm/pte-common.h +++ b/arch/powerpc/include/asm/pte-common.h | |||
@@ -171,6 +171,13 @@ extern unsigned long bad_call_to_PMD_PAGE_SIZE(void); | |||
171 | /* Make modules code happy. We don't set RO yet */ | 171 | /* Make modules code happy. We don't set RO yet */ |
172 | #define PAGE_KERNEL_EXEC PAGE_KERNEL_X | 172 | #define PAGE_KERNEL_EXEC PAGE_KERNEL_X |
173 | 173 | ||
174 | /* | ||
175 | * Don't just check for any non zero bits in __PAGE_USER, since for book3e | ||
176 | * and PTE_64BIT, PAGE_KERNEL_X contains _PAGE_BAP_SR which is also in | ||
177 | * _PAGE_USER. Need to explictly match _PAGE_BAP_UR bit in that case too. | ||
178 | */ | ||
179 | #define pte_user(val) ((val & _PAGE_USER) == _PAGE_USER) | ||
180 | |||
174 | /* Advertise special mapping type for AGP */ | 181 | /* Advertise special mapping type for AGP */ |
175 | #define PAGE_AGP (PAGE_KERNEL_NC) | 182 | #define PAGE_AGP (PAGE_KERNEL_NC) |
176 | #define HAVE_PAGE_AGP | 183 | #define HAVE_PAGE_AGP |
diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h index 3d35f8ae377e..9a1193e30f26 100644 --- a/arch/powerpc/include/asm/rtas.h +++ b/arch/powerpc/include/asm/rtas.h | |||
@@ -187,6 +187,7 @@ extern void rtas_progress(char *s, unsigned short hex); | |||
187 | extern void rtas_initialize(void); | 187 | extern void rtas_initialize(void); |
188 | extern int rtas_suspend_cpu(struct rtas_suspend_me_data *data); | 188 | extern int rtas_suspend_cpu(struct rtas_suspend_me_data *data); |
189 | extern int rtas_suspend_last_cpu(struct rtas_suspend_me_data *data); | 189 | extern int rtas_suspend_last_cpu(struct rtas_suspend_me_data *data); |
190 | extern int rtas_ibm_suspend_me(struct rtas_args *); | ||
190 | 191 | ||
191 | struct rtc_time; | 192 | struct rtc_time; |
192 | extern unsigned long rtas_get_boot_time(void); | 193 | extern unsigned long rtas_get_boot_time(void); |
diff --git a/arch/powerpc/include/asm/systbl.h b/arch/powerpc/include/asm/systbl.h index 3d212669a130..aa0f1ebb4aaf 100644 --- a/arch/powerpc/include/asm/systbl.h +++ b/arch/powerpc/include/asm/systbl.h | |||
@@ -329,3 +329,22 @@ COMPAT_SYS(rt_tgsigqueueinfo) | |||
329 | SYSCALL(fanotify_init) | 329 | SYSCALL(fanotify_init) |
330 | COMPAT_SYS(fanotify_mark) | 330 | COMPAT_SYS(fanotify_mark) |
331 | SYSCALL_SPU(prlimit64) | 331 | SYSCALL_SPU(prlimit64) |
332 | SYSCALL_SPU(socket) | ||
333 | SYSCALL_SPU(bind) | ||
334 | SYSCALL_SPU(connect) | ||
335 | SYSCALL_SPU(listen) | ||
336 | SYSCALL_SPU(accept) | ||
337 | SYSCALL_SPU(getsockname) | ||
338 | SYSCALL_SPU(getpeername) | ||
339 | SYSCALL_SPU(socketpair) | ||
340 | SYSCALL_SPU(send) | ||
341 | SYSCALL_SPU(sendto) | ||
342 | COMPAT_SYS_SPU(recv) | ||
343 | COMPAT_SYS_SPU(recvfrom) | ||
344 | SYSCALL_SPU(shutdown) | ||
345 | COMPAT_SYS_SPU(setsockopt) | ||
346 | COMPAT_SYS_SPU(getsockopt) | ||
347 | COMPAT_SYS_SPU(sendmsg) | ||
348 | COMPAT_SYS_SPU(recvmsg) | ||
349 | COMPAT_SYS_SPU(recvmmsg) | ||
350 | SYSCALL_SPU(accept4) | ||
diff --git a/arch/powerpc/include/asm/system.h b/arch/powerpc/include/asm/system.h index 6c294acac848..5e474ddd2273 100644 --- a/arch/powerpc/include/asm/system.h +++ b/arch/powerpc/include/asm/system.h | |||
@@ -154,8 +154,8 @@ extern void enable_kernel_spe(void); | |||
154 | extern void giveup_spe(struct task_struct *); | 154 | extern void giveup_spe(struct task_struct *); |
155 | extern void load_up_spe(struct task_struct *); | 155 | extern void load_up_spe(struct task_struct *); |
156 | extern int fix_alignment(struct pt_regs *); | 156 | extern int fix_alignment(struct pt_regs *); |
157 | extern void cvt_fd(float *from, double *to, struct thread_struct *thread); | 157 | extern void cvt_fd(float *from, double *to); |
158 | extern void cvt_df(double *from, float *to, struct thread_struct *thread); | 158 | extern void cvt_df(double *from, float *to); |
159 | 159 | ||
160 | #ifndef CONFIG_SMP | 160 | #ifndef CONFIG_SMP |
161 | extern void discard_lazy_cpu_state(void); | 161 | extern void discard_lazy_cpu_state(void); |
@@ -542,10 +542,6 @@ extern void reloc_got2(unsigned long); | |||
542 | 542 | ||
543 | #define PTRRELOC(x) ((typeof(x)) add_reloc_offset((unsigned long)(x))) | 543 | #define PTRRELOC(x) ((typeof(x)) add_reloc_offset((unsigned long)(x))) |
544 | 544 | ||
545 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
546 | extern void account_system_vtime(struct task_struct *); | ||
547 | #endif | ||
548 | |||
549 | extern struct dentry *powerpc_debugfs_root; | 545 | extern struct dentry *powerpc_debugfs_root; |
550 | 546 | ||
551 | #endif /* __KERNEL__ */ | 547 | #endif /* __KERNEL__ */ |
diff --git a/arch/powerpc/include/asm/time.h b/arch/powerpc/include/asm/time.h index dc779dfcf258..fe6f7c2c9c68 100644 --- a/arch/powerpc/include/asm/time.h +++ b/arch/powerpc/include/asm/time.h | |||
@@ -34,7 +34,6 @@ extern void to_tm(int tim, struct rtc_time * tm); | |||
34 | extern void GregorianDay(struct rtc_time *tm); | 34 | extern void GregorianDay(struct rtc_time *tm); |
35 | 35 | ||
36 | extern void generic_calibrate_decr(void); | 36 | extern void generic_calibrate_decr(void); |
37 | extern void snapshot_timebase(void); | ||
38 | 37 | ||
39 | extern void set_dec_cpu6(unsigned int val); | 38 | extern void set_dec_cpu6(unsigned int val); |
40 | 39 | ||
@@ -212,12 +211,8 @@ struct cpu_usage { | |||
212 | DECLARE_PER_CPU(struct cpu_usage, cpu_usage_array); | 211 | DECLARE_PER_CPU(struct cpu_usage, cpu_usage_array); |
213 | 212 | ||
214 | #if defined(CONFIG_VIRT_CPU_ACCOUNTING) | 213 | #if defined(CONFIG_VIRT_CPU_ACCOUNTING) |
215 | extern void calculate_steal_time(void); | ||
216 | extern void snapshot_timebases(void); | ||
217 | #define account_process_vtime(tsk) account_process_tick(tsk, 0) | 214 | #define account_process_vtime(tsk) account_process_tick(tsk, 0) |
218 | #else | 215 | #else |
219 | #define calculate_steal_time() do { } while (0) | ||
220 | #define snapshot_timebases() do { } while (0) | ||
221 | #define account_process_vtime(tsk) do { } while (0) | 216 | #define account_process_vtime(tsk) do { } while (0) |
222 | #endif | 217 | #endif |
223 | 218 | ||
diff --git a/arch/powerpc/include/asm/unistd.h b/arch/powerpc/include/asm/unistd.h index 597e6f9d094a..6151937657f6 100644 --- a/arch/powerpc/include/asm/unistd.h +++ b/arch/powerpc/include/asm/unistd.h | |||
@@ -348,10 +348,29 @@ | |||
348 | #define __NR_fanotify_init 323 | 348 | #define __NR_fanotify_init 323 |
349 | #define __NR_fanotify_mark 324 | 349 | #define __NR_fanotify_mark 324 |
350 | #define __NR_prlimit64 325 | 350 | #define __NR_prlimit64 325 |
351 | #define __NR_socket 326 | ||
352 | #define __NR_bind 327 | ||
353 | #define __NR_connect 328 | ||
354 | #define __NR_listen 329 | ||
355 | #define __NR_accept 330 | ||
356 | #define __NR_getsockname 331 | ||
357 | #define __NR_getpeername 332 | ||
358 | #define __NR_socketpair 333 | ||
359 | #define __NR_send 334 | ||
360 | #define __NR_sendto 335 | ||
361 | #define __NR_recv 336 | ||
362 | #define __NR_recvfrom 337 | ||
363 | #define __NR_shutdown 338 | ||
364 | #define __NR_setsockopt 339 | ||
365 | #define __NR_getsockopt 340 | ||
366 | #define __NR_sendmsg 341 | ||
367 | #define __NR_recvmsg 342 | ||
368 | #define __NR_recvmmsg 343 | ||
369 | #define __NR_accept4 344 | ||
351 | 370 | ||
352 | #ifdef __KERNEL__ | 371 | #ifdef __KERNEL__ |
353 | 372 | ||
354 | #define __NR_syscalls 326 | 373 | #define __NR_syscalls 345 |
355 | 374 | ||
356 | #define __NR__exit __NR_exit | 375 | #define __NR__exit __NR_exit |
357 | #define NR_syscalls __NR_syscalls | 376 | #define NR_syscalls __NR_syscalls |
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 1dda70129141..36c30f31ec93 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
@@ -55,7 +55,9 @@ obj-$(CONFIG_IBMVIO) += vio.o | |||
55 | obj-$(CONFIG_IBMEBUS) += ibmebus.o | 55 | obj-$(CONFIG_IBMEBUS) += ibmebus.o |
56 | obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o | 56 | obj-$(CONFIG_GENERIC_TBSYNC) += smp-tbsync.o |
57 | obj-$(CONFIG_CRASH_DUMP) += crash_dump.o | 57 | obj-$(CONFIG_CRASH_DUMP) += crash_dump.o |
58 | ifeq ($(CONFIG_PPC32),y) | ||
58 | obj-$(CONFIG_E500) += idle_e500.o | 59 | obj-$(CONFIG_E500) += idle_e500.o |
60 | endif | ||
59 | obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o | 61 | obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o |
60 | obj-$(CONFIG_TAU) += tau_6xx.o | 62 | obj-$(CONFIG_TAU) += tau_6xx.o |
61 | obj-$(CONFIG_HIBERNATION) += swsusp.o suspend.o | 63 | obj-$(CONFIG_HIBERNATION) += swsusp.o suspend.o |
@@ -67,7 +69,7 @@ endif | |||
67 | obj64-$(CONFIG_HIBERNATION) += swsusp_asm64.o | 69 | obj64-$(CONFIG_HIBERNATION) += swsusp_asm64.o |
68 | obj-$(CONFIG_MODULES) += module.o module_$(CONFIG_WORD_SIZE).o | 70 | obj-$(CONFIG_MODULES) += module.o module_$(CONFIG_WORD_SIZE).o |
69 | obj-$(CONFIG_44x) += cpu_setup_44x.o | 71 | obj-$(CONFIG_44x) += cpu_setup_44x.o |
70 | obj-$(CONFIG_FSL_BOOKE) += cpu_setup_fsl_booke.o dbell.o | 72 | obj-$(CONFIG_PPC_FSL_BOOK3E) += cpu_setup_fsl_booke.o dbell.o |
71 | obj-$(CONFIG_PPC_BOOK3E_64) += dbell.o | 73 | obj-$(CONFIG_PPC_BOOK3E_64) += dbell.o |
72 | 74 | ||
73 | extra-y := head_$(CONFIG_WORD_SIZE).o | 75 | extra-y := head_$(CONFIG_WORD_SIZE).o |
@@ -127,6 +129,8 @@ ifneq ($(CONFIG_XMON)$(CONFIG_KEXEC),) | |||
127 | obj-y += ppc_save_regs.o | 129 | obj-y += ppc_save_regs.o |
128 | endif | 130 | endif |
129 | 131 | ||
132 | obj-$(CONFIG_KVM_GUEST) += kvm.o kvm_emul.o | ||
133 | |||
130 | # Disable GCOV in odd or sensitive code | 134 | # Disable GCOV in odd or sensitive code |
131 | GCOV_PROFILE_prom_init.o := n | 135 | GCOV_PROFILE_prom_init.o := n |
132 | GCOV_PROFILE_ftrace.o := n | 136 | GCOV_PROFILE_ftrace.o := n |
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c index b876e989220b..8184ee97e484 100644 --- a/arch/powerpc/kernel/align.c +++ b/arch/powerpc/kernel/align.c | |||
@@ -889,7 +889,7 @@ int fix_alignment(struct pt_regs *regs) | |||
889 | #ifdef CONFIG_PPC_FPU | 889 | #ifdef CONFIG_PPC_FPU |
890 | preempt_disable(); | 890 | preempt_disable(); |
891 | enable_kernel_fp(); | 891 | enable_kernel_fp(); |
892 | cvt_df(&data.dd, (float *)&data.v[4], ¤t->thread); | 892 | cvt_df(&data.dd, (float *)&data.v[4]); |
893 | preempt_enable(); | 893 | preempt_enable(); |
894 | #else | 894 | #else |
895 | return 0; | 895 | return 0; |
@@ -933,7 +933,7 @@ int fix_alignment(struct pt_regs *regs) | |||
933 | #ifdef CONFIG_PPC_FPU | 933 | #ifdef CONFIG_PPC_FPU |
934 | preempt_disable(); | 934 | preempt_disable(); |
935 | enable_kernel_fp(); | 935 | enable_kernel_fp(); |
936 | cvt_fd((float *)&data.v[4], &data.dd, ¤t->thread); | 936 | cvt_fd((float *)&data.v[4], &data.dd); |
937 | preempt_enable(); | 937 | preempt_enable(); |
938 | #else | 938 | #else |
939 | return 0; | 939 | return 0; |
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 1c0607ddccc0..bd0df2e6aa8f 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
@@ -48,11 +48,11 @@ | |||
48 | #ifdef CONFIG_PPC_ISERIES | 48 | #ifdef CONFIG_PPC_ISERIES |
49 | #include <asm/iseries/alpaca.h> | 49 | #include <asm/iseries/alpaca.h> |
50 | #endif | 50 | #endif |
51 | #ifdef CONFIG_KVM | 51 | #if defined(CONFIG_KVM) || defined(CONFIG_KVM_GUEST) |
52 | #include <linux/kvm_host.h> | 52 | #include <linux/kvm_host.h> |
53 | #ifndef CONFIG_BOOKE | ||
54 | #include <asm/kvm_book3s.h> | ||
55 | #endif | 53 | #endif |
54 | #if defined(CONFIG_KVM) && defined(CONFIG_PPC_BOOK3S) | ||
55 | #include <asm/kvm_book3s.h> | ||
56 | #endif | 56 | #endif |
57 | 57 | ||
58 | #ifdef CONFIG_PPC32 | 58 | #ifdef CONFIG_PPC32 |
@@ -61,7 +61,7 @@ | |||
61 | #endif | 61 | #endif |
62 | #endif | 62 | #endif |
63 | 63 | ||
64 | #if defined(CONFIG_FSL_BOOKE) | 64 | #if defined(CONFIG_PPC_FSL_BOOK3E) |
65 | #include "../mm/mmu_decl.h" | 65 | #include "../mm/mmu_decl.h" |
66 | #endif | 66 | #endif |
67 | 67 | ||
@@ -181,17 +181,19 @@ int main(void) | |||
181 | offsetof(struct slb_shadow, save_area[SLB_NUM_BOLTED - 1].vsid)); | 181 | offsetof(struct slb_shadow, save_area[SLB_NUM_BOLTED - 1].vsid)); |
182 | DEFINE(SLBSHADOW_STACKESID, | 182 | DEFINE(SLBSHADOW_STACKESID, |
183 | offsetof(struct slb_shadow, save_area[SLB_NUM_BOLTED - 1].esid)); | 183 | offsetof(struct slb_shadow, save_area[SLB_NUM_BOLTED - 1].esid)); |
184 | DEFINE(SLBSHADOW_SAVEAREA, offsetof(struct slb_shadow, save_area)); | ||
184 | DEFINE(LPPACASRR0, offsetof(struct lppaca, saved_srr0)); | 185 | DEFINE(LPPACASRR0, offsetof(struct lppaca, saved_srr0)); |
185 | DEFINE(LPPACASRR1, offsetof(struct lppaca, saved_srr1)); | 186 | DEFINE(LPPACASRR1, offsetof(struct lppaca, saved_srr1)); |
186 | DEFINE(LPPACAANYINT, offsetof(struct lppaca, int_dword.any_int)); | 187 | DEFINE(LPPACAANYINT, offsetof(struct lppaca, int_dword.any_int)); |
187 | DEFINE(LPPACADECRINT, offsetof(struct lppaca, int_dword.fields.decr_int)); | 188 | DEFINE(LPPACADECRINT, offsetof(struct lppaca, int_dword.fields.decr_int)); |
188 | DEFINE(SLBSHADOW_SAVEAREA, offsetof(struct slb_shadow, save_area)); | 189 | DEFINE(LPPACA_DTLIDX, offsetof(struct lppaca, dtl_idx)); |
190 | DEFINE(PACA_DTL_RIDX, offsetof(struct paca_struct, dtl_ridx)); | ||
189 | #endif /* CONFIG_PPC_STD_MMU_64 */ | 191 | #endif /* CONFIG_PPC_STD_MMU_64 */ |
190 | DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp)); | 192 | DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp)); |
191 | DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id)); | 193 | DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id)); |
192 | DEFINE(PACAKEXECSTATE, offsetof(struct paca_struct, kexec_state)); | 194 | DEFINE(PACAKEXECSTATE, offsetof(struct paca_struct, kexec_state)); |
193 | DEFINE(PACA_STARTPURR, offsetof(struct paca_struct, startpurr)); | 195 | DEFINE(PACA_STARTTIME, offsetof(struct paca_struct, starttime)); |
194 | DEFINE(PACA_STARTSPURR, offsetof(struct paca_struct, startspurr)); | 196 | DEFINE(PACA_STARTTIME_USER, offsetof(struct paca_struct, starttime_user)); |
195 | DEFINE(PACA_USER_TIME, offsetof(struct paca_struct, user_time)); | 197 | DEFINE(PACA_USER_TIME, offsetof(struct paca_struct, user_time)); |
196 | DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time)); | 198 | DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time)); |
197 | DEFINE(PACA_TRAP_SAVE, offsetof(struct paca_struct, trap_save)); | 199 | DEFINE(PACA_TRAP_SAVE, offsetof(struct paca_struct, trap_save)); |
@@ -394,12 +396,13 @@ int main(void) | |||
394 | DEFINE(VCPU_HOST_STACK, offsetof(struct kvm_vcpu, arch.host_stack)); | 396 | DEFINE(VCPU_HOST_STACK, offsetof(struct kvm_vcpu, arch.host_stack)); |
395 | DEFINE(VCPU_HOST_PID, offsetof(struct kvm_vcpu, arch.host_pid)); | 397 | DEFINE(VCPU_HOST_PID, offsetof(struct kvm_vcpu, arch.host_pid)); |
396 | DEFINE(VCPU_GPRS, offsetof(struct kvm_vcpu, arch.gpr)); | 398 | DEFINE(VCPU_GPRS, offsetof(struct kvm_vcpu, arch.gpr)); |
397 | DEFINE(VCPU_MSR, offsetof(struct kvm_vcpu, arch.msr)); | ||
398 | DEFINE(VCPU_SPRG4, offsetof(struct kvm_vcpu, arch.sprg4)); | 399 | DEFINE(VCPU_SPRG4, offsetof(struct kvm_vcpu, arch.sprg4)); |
399 | DEFINE(VCPU_SPRG5, offsetof(struct kvm_vcpu, arch.sprg5)); | 400 | DEFINE(VCPU_SPRG5, offsetof(struct kvm_vcpu, arch.sprg5)); |
400 | DEFINE(VCPU_SPRG6, offsetof(struct kvm_vcpu, arch.sprg6)); | 401 | DEFINE(VCPU_SPRG6, offsetof(struct kvm_vcpu, arch.sprg6)); |
401 | DEFINE(VCPU_SPRG7, offsetof(struct kvm_vcpu, arch.sprg7)); | 402 | DEFINE(VCPU_SPRG7, offsetof(struct kvm_vcpu, arch.sprg7)); |
402 | DEFINE(VCPU_SHADOW_PID, offsetof(struct kvm_vcpu, arch.shadow_pid)); | 403 | DEFINE(VCPU_SHADOW_PID, offsetof(struct kvm_vcpu, arch.shadow_pid)); |
404 | DEFINE(VCPU_SHARED, offsetof(struct kvm_vcpu, arch.shared)); | ||
405 | DEFINE(VCPU_SHARED_MSR, offsetof(struct kvm_vcpu_arch_shared, msr)); | ||
403 | 406 | ||
404 | /* book3s */ | 407 | /* book3s */ |
405 | #ifdef CONFIG_PPC_BOOK3S | 408 | #ifdef CONFIG_PPC_BOOK3S |
@@ -464,11 +467,27 @@ int main(void) | |||
464 | DEFINE(VCPU_FAULT_ESR, offsetof(struct kvm_vcpu, arch.fault_esr)); | 467 | DEFINE(VCPU_FAULT_ESR, offsetof(struct kvm_vcpu, arch.fault_esr)); |
465 | #endif /* CONFIG_PPC_BOOK3S */ | 468 | #endif /* CONFIG_PPC_BOOK3S */ |
466 | #endif | 469 | #endif |
470 | |||
471 | #ifdef CONFIG_KVM_GUEST | ||
472 | DEFINE(KVM_MAGIC_SCRATCH1, offsetof(struct kvm_vcpu_arch_shared, | ||
473 | scratch1)); | ||
474 | DEFINE(KVM_MAGIC_SCRATCH2, offsetof(struct kvm_vcpu_arch_shared, | ||
475 | scratch2)); | ||
476 | DEFINE(KVM_MAGIC_SCRATCH3, offsetof(struct kvm_vcpu_arch_shared, | ||
477 | scratch3)); | ||
478 | DEFINE(KVM_MAGIC_INT, offsetof(struct kvm_vcpu_arch_shared, | ||
479 | int_pending)); | ||
480 | DEFINE(KVM_MAGIC_MSR, offsetof(struct kvm_vcpu_arch_shared, msr)); | ||
481 | DEFINE(KVM_MAGIC_CRITICAL, offsetof(struct kvm_vcpu_arch_shared, | ||
482 | critical)); | ||
483 | DEFINE(KVM_MAGIC_SR, offsetof(struct kvm_vcpu_arch_shared, sr)); | ||
484 | #endif | ||
485 | |||
467 | #ifdef CONFIG_44x | 486 | #ifdef CONFIG_44x |
468 | DEFINE(PGD_T_LOG2, PGD_T_LOG2); | 487 | DEFINE(PGD_T_LOG2, PGD_T_LOG2); |
469 | DEFINE(PTE_T_LOG2, PTE_T_LOG2); | 488 | DEFINE(PTE_T_LOG2, PTE_T_LOG2); |
470 | #endif | 489 | #endif |
471 | #ifdef CONFIG_FSL_BOOKE | 490 | #ifdef CONFIG_PPC_FSL_BOOK3E |
472 | DEFINE(TLBCAM_SIZE, sizeof(struct tlbcam)); | 491 | DEFINE(TLBCAM_SIZE, sizeof(struct tlbcam)); |
473 | DEFINE(TLBCAM_MAS0, offsetof(struct tlbcam, MAS0)); | 492 | DEFINE(TLBCAM_MAS0, offsetof(struct tlbcam, MAS0)); |
474 | DEFINE(TLBCAM_MAS1, offsetof(struct tlbcam, MAS1)); | 493 | DEFINE(TLBCAM_MAS1, offsetof(struct tlbcam, MAS1)); |
diff --git a/arch/powerpc/kernel/cpu_setup_44x.S b/arch/powerpc/kernel/cpu_setup_44x.S index 7d606f89a839..e32b4a9a2c22 100644 --- a/arch/powerpc/kernel/cpu_setup_44x.S +++ b/arch/powerpc/kernel/cpu_setup_44x.S | |||
@@ -35,6 +35,7 @@ _GLOBAL(__setup_cpu_440grx) | |||
35 | _GLOBAL(__setup_cpu_460ex) | 35 | _GLOBAL(__setup_cpu_460ex) |
36 | _GLOBAL(__setup_cpu_460gt) | 36 | _GLOBAL(__setup_cpu_460gt) |
37 | _GLOBAL(__setup_cpu_460sx) | 37 | _GLOBAL(__setup_cpu_460sx) |
38 | _GLOBAL(__setup_cpu_apm821xx) | ||
38 | mflr r4 | 39 | mflr r4 |
39 | bl __init_fpu_44x | 40 | bl __init_fpu_44x |
40 | bl __fixup_440A_mcheck | 41 | bl __fixup_440A_mcheck |
diff --git a/arch/powerpc/kernel/cpu_setup_fsl_booke.S b/arch/powerpc/kernel/cpu_setup_fsl_booke.S index 0adb50ad8031..894e64fa481e 100644 --- a/arch/powerpc/kernel/cpu_setup_fsl_booke.S +++ b/arch/powerpc/kernel/cpu_setup_fsl_booke.S | |||
@@ -51,6 +51,7 @@ _GLOBAL(__e500_dcache_setup) | |||
51 | isync | 51 | isync |
52 | blr | 52 | blr |
53 | 53 | ||
54 | #ifdef CONFIG_PPC32 | ||
54 | _GLOBAL(__setup_cpu_e200) | 55 | _GLOBAL(__setup_cpu_e200) |
55 | /* enable dedicated debug exception handling resources (Debug APU) */ | 56 | /* enable dedicated debug exception handling resources (Debug APU) */ |
56 | mfspr r3,SPRN_HID0 | 57 | mfspr r3,SPRN_HID0 |
@@ -72,3 +73,17 @@ _GLOBAL(__setup_cpu_e500mc) | |||
72 | bl __setup_e500mc_ivors | 73 | bl __setup_e500mc_ivors |
73 | mtlr r4 | 74 | mtlr r4 |
74 | blr | 75 | blr |
76 | #endif | ||
77 | /* Right now, restore and setup are the same thing */ | ||
78 | _GLOBAL(__restore_cpu_e5500) | ||
79 | _GLOBAL(__setup_cpu_e5500) | ||
80 | mflr r4 | ||
81 | bl __e500_icache_setup | ||
82 | bl __e500_dcache_setup | ||
83 | #ifdef CONFIG_PPC_BOOK3E_64 | ||
84 | bl .__setup_base_ivors | ||
85 | #else | ||
86 | bl __setup_e500mc_ivors | ||
87 | #endif | ||
88 | mtlr r4 | ||
89 | blr | ||
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 1f9123f412ec..96a908f1cd87 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c | |||
@@ -48,6 +48,7 @@ extern void __setup_cpu_440x5(unsigned long offset, struct cpu_spec* spec); | |||
48 | extern void __setup_cpu_460ex(unsigned long offset, struct cpu_spec* spec); | 48 | extern void __setup_cpu_460ex(unsigned long offset, struct cpu_spec* spec); |
49 | extern void __setup_cpu_460gt(unsigned long offset, struct cpu_spec* spec); | 49 | extern void __setup_cpu_460gt(unsigned long offset, struct cpu_spec* spec); |
50 | extern void __setup_cpu_460sx(unsigned long offset, struct cpu_spec *spec); | 50 | extern void __setup_cpu_460sx(unsigned long offset, struct cpu_spec *spec); |
51 | extern void __setup_cpu_apm821xx(unsigned long offset, struct cpu_spec *spec); | ||
51 | extern void __setup_cpu_603(unsigned long offset, struct cpu_spec* spec); | 52 | extern void __setup_cpu_603(unsigned long offset, struct cpu_spec* spec); |
52 | extern void __setup_cpu_604(unsigned long offset, struct cpu_spec* spec); | 53 | extern void __setup_cpu_604(unsigned long offset, struct cpu_spec* spec); |
53 | extern void __setup_cpu_750(unsigned long offset, struct cpu_spec* spec); | 54 | extern void __setup_cpu_750(unsigned long offset, struct cpu_spec* spec); |
@@ -66,6 +67,10 @@ extern void __restore_cpu_ppc970(void); | |||
66 | extern void __setup_cpu_power7(unsigned long offset, struct cpu_spec* spec); | 67 | extern void __setup_cpu_power7(unsigned long offset, struct cpu_spec* spec); |
67 | extern void __restore_cpu_power7(void); | 68 | extern void __restore_cpu_power7(void); |
68 | #endif /* CONFIG_PPC64 */ | 69 | #endif /* CONFIG_PPC64 */ |
70 | #if defined(CONFIG_E500) | ||
71 | extern void __setup_cpu_e5500(unsigned long offset, struct cpu_spec* spec); | ||
72 | extern void __restore_cpu_e5500(void); | ||
73 | #endif /* CONFIG_E500 */ | ||
69 | 74 | ||
70 | /* This table only contains "desktop" CPUs, it need to be filled with embedded | 75 | /* This table only contains "desktop" CPUs, it need to be filled with embedded |
71 | * ones as well... | 76 | * ones as well... |
@@ -1805,6 +1810,20 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
1805 | .machine_check = machine_check_440A, | 1810 | .machine_check = machine_check_440A, |
1806 | .platform = "ppc440", | 1811 | .platform = "ppc440", |
1807 | }, | 1812 | }, |
1813 | { /* 464 in APM821xx */ | ||
1814 | .pvr_mask = 0xffffff00, | ||
1815 | .pvr_value = 0x12C41C80, | ||
1816 | .cpu_name = "APM821XX", | ||
1817 | .cpu_features = CPU_FTRS_44X, | ||
1818 | .cpu_user_features = COMMON_USER_BOOKE | | ||
1819 | PPC_FEATURE_HAS_FPU, | ||
1820 | .mmu_features = MMU_FTR_TYPE_44x, | ||
1821 | .icache_bsize = 32, | ||
1822 | .dcache_bsize = 32, | ||
1823 | .cpu_setup = __setup_cpu_apm821xx, | ||
1824 | .machine_check = machine_check_440A, | ||
1825 | .platform = "ppc440", | ||
1826 | }, | ||
1808 | { /* 476 core */ | 1827 | { /* 476 core */ |
1809 | .pvr_mask = 0xffff0000, | 1828 | .pvr_mask = 0xffff0000, |
1810 | .pvr_value = 0x11a50000, | 1829 | .pvr_value = 0x11a50000, |
@@ -1891,7 +1910,9 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
1891 | .platform = "ppc5554", | 1910 | .platform = "ppc5554", |
1892 | } | 1911 | } |
1893 | #endif /* CONFIG_E200 */ | 1912 | #endif /* CONFIG_E200 */ |
1913 | #endif /* CONFIG_PPC32 */ | ||
1894 | #ifdef CONFIG_E500 | 1914 | #ifdef CONFIG_E500 |
1915 | #ifdef CONFIG_PPC32 | ||
1895 | { /* e500 */ | 1916 | { /* e500 */ |
1896 | .pvr_mask = 0xffff0000, | 1917 | .pvr_mask = 0xffff0000, |
1897 | .pvr_value = 0x80200000, | 1918 | .pvr_value = 0x80200000, |
@@ -1946,6 +1967,26 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
1946 | .machine_check = machine_check_e500mc, | 1967 | .machine_check = machine_check_e500mc, |
1947 | .platform = "ppce500mc", | 1968 | .platform = "ppce500mc", |
1948 | }, | 1969 | }, |
1970 | #endif /* CONFIG_PPC32 */ | ||
1971 | { /* e5500 */ | ||
1972 | .pvr_mask = 0xffff0000, | ||
1973 | .pvr_value = 0x80240000, | ||
1974 | .cpu_name = "e5500", | ||
1975 | .cpu_features = CPU_FTRS_E500MC, | ||
1976 | .cpu_user_features = COMMON_USER_BOOKE, | ||
1977 | .mmu_features = MMU_FTR_TYPE_FSL_E | MMU_FTR_BIG_PHYS | | ||
1978 | MMU_FTR_USE_TLBILX, | ||
1979 | .icache_bsize = 64, | ||
1980 | .dcache_bsize = 64, | ||
1981 | .num_pmcs = 4, | ||
1982 | .oprofile_cpu_type = "ppc/e500mc", | ||
1983 | .oprofile_type = PPC_OPROFILE_FSL_EMB, | ||
1984 | .cpu_setup = __setup_cpu_e5500, | ||
1985 | .cpu_restore = __restore_cpu_e5500, | ||
1986 | .machine_check = machine_check_e500mc, | ||
1987 | .platform = "ppce5500", | ||
1988 | }, | ||
1989 | #ifdef CONFIG_PPC32 | ||
1949 | { /* default match */ | 1990 | { /* default match */ |
1950 | .pvr_mask = 0x00000000, | 1991 | .pvr_mask = 0x00000000, |
1951 | .pvr_value = 0x00000000, | 1992 | .pvr_value = 0x00000000, |
@@ -1960,8 +2001,8 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
1960 | .machine_check = machine_check_e500, | 2001 | .machine_check = machine_check_e500, |
1961 | .platform = "powerpc", | 2002 | .platform = "powerpc", |
1962 | } | 2003 | } |
1963 | #endif /* CONFIG_E500 */ | ||
1964 | #endif /* CONFIG_PPC32 */ | 2004 | #endif /* CONFIG_PPC32 */ |
2005 | #endif /* CONFIG_E500 */ | ||
1965 | 2006 | ||
1966 | #ifdef CONFIG_PPC_BOOK3E_64 | 2007 | #ifdef CONFIG_PPC_BOOK3E_64 |
1967 | { /* This is a default entry to get going, to be replaced by | 2008 | { /* This is a default entry to get going, to be replaced by |
diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c index 4457382f8667..832c8c4db254 100644 --- a/arch/powerpc/kernel/crash.c +++ b/arch/powerpc/kernel/crash.c | |||
@@ -414,18 +414,7 @@ void default_machine_crash_shutdown(struct pt_regs *regs) | |||
414 | crash_kexec_wait_realmode(crashing_cpu); | 414 | crash_kexec_wait_realmode(crashing_cpu); |
415 | #endif | 415 | #endif |
416 | 416 | ||
417 | for_each_irq(i) { | 417 | machine_kexec_mask_interrupts(); |
418 | struct irq_desc *desc = irq_to_desc(i); | ||
419 | |||
420 | if (!desc || !desc->chip || !desc->chip->eoi) | ||
421 | continue; | ||
422 | |||
423 | if (desc->status & IRQ_INPROGRESS) | ||
424 | desc->chip->eoi(i); | ||
425 | |||
426 | if (!(desc->status & IRQ_DISABLED)) | ||
427 | desc->chip->shutdown(i); | ||
428 | } | ||
429 | 418 | ||
430 | /* | 419 | /* |
431 | * Call registered shutdown routines savely. Swap out | 420 | * Call registered shutdown routines savely. Swap out |
diff --git a/arch/powerpc/kernel/dma-iommu.c b/arch/powerpc/kernel/dma-iommu.c index 37771a518119..6e54a0fd31aa 100644 --- a/arch/powerpc/kernel/dma-iommu.c +++ b/arch/powerpc/kernel/dma-iommu.c | |||
@@ -74,16 +74,17 @@ static int dma_iommu_dma_supported(struct device *dev, u64 mask) | |||
74 | { | 74 | { |
75 | struct iommu_table *tbl = get_iommu_table_base(dev); | 75 | struct iommu_table *tbl = get_iommu_table_base(dev); |
76 | 76 | ||
77 | if (!tbl || tbl->it_offset > mask) { | 77 | if (!tbl) { |
78 | printk(KERN_INFO | 78 | dev_info(dev, "Warning: IOMMU dma not supported: mask 0x%08llx" |
79 | "Warning: IOMMU offset too big for device mask\n"); | 79 | ", table unavailable\n", mask); |
80 | if (tbl) | 80 | return 0; |
81 | printk(KERN_INFO | 81 | } |
82 | "mask: 0x%08llx, table offset: 0x%08lx\n", | 82 | |
83 | mask, tbl->it_offset); | 83 | if ((tbl->it_offset + tbl->it_size) > (mask >> IOMMU_PAGE_SHIFT)) { |
84 | else | 84 | dev_info(dev, "Warning: IOMMU window too big for device mask\n"); |
85 | printk(KERN_INFO "mask: 0x%08llx, table unavailable\n", | 85 | dev_info(dev, "mask: 0x%08llx, table end: 0x%08lx\n", |
86 | mask); | 86 | mask, (tbl->it_offset + tbl->it_size) << |
87 | IOMMU_PAGE_SHIFT); | ||
87 | return 0; | 88 | return 0; |
88 | } else | 89 | } else |
89 | return 1; | 90 | return 1; |
diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma.c index 84d6367ec003..cf02cad62d9a 100644 --- a/arch/powerpc/kernel/dma.c +++ b/arch/powerpc/kernel/dma.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/memblock.h> | 12 | #include <linux/memblock.h> |
13 | #include <asm/bug.h> | 13 | #include <asm/bug.h> |
14 | #include <asm/abs_addr.h> | 14 | #include <asm/abs_addr.h> |
15 | #include <asm/machdep.h> | ||
15 | 16 | ||
16 | /* | 17 | /* |
17 | * Generic direct DMA implementation | 18 | * Generic direct DMA implementation |
@@ -89,7 +90,7 @@ static int dma_direct_dma_supported(struct device *dev, u64 mask) | |||
89 | /* Could be improved so platforms can set the limit in case | 90 | /* Could be improved so platforms can set the limit in case |
90 | * they have limited DMA windows | 91 | * they have limited DMA windows |
91 | */ | 92 | */ |
92 | return mask >= (memblock_end_of_DRAM() - 1); | 93 | return mask >= get_dma_offset(dev) + (memblock_end_of_DRAM() - 1); |
93 | #else | 94 | #else |
94 | return 1; | 95 | return 1; |
95 | #endif | 96 | #endif |
@@ -154,6 +155,23 @@ EXPORT_SYMBOL(dma_direct_ops); | |||
154 | 155 | ||
155 | #define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16) | 156 | #define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16) |
156 | 157 | ||
158 | int dma_set_mask(struct device *dev, u64 dma_mask) | ||
159 | { | ||
160 | struct dma_map_ops *dma_ops = get_dma_ops(dev); | ||
161 | |||
162 | if (ppc_md.dma_set_mask) | ||
163 | return ppc_md.dma_set_mask(dev, dma_mask); | ||
164 | if (unlikely(dma_ops == NULL)) | ||
165 | return -EIO; | ||
166 | if (dma_ops->set_dma_mask != NULL) | ||
167 | return dma_ops->set_dma_mask(dev, dma_mask); | ||
168 | if (!dev->dma_mask || !dma_supported(dev, dma_mask)) | ||
169 | return -EIO; | ||
170 | *dev->dma_mask = dma_mask; | ||
171 | return 0; | ||
172 | } | ||
173 | EXPORT_SYMBOL(dma_set_mask); | ||
174 | |||
157 | static int __init dma_init(void) | 175 | static int __init dma_init(void) |
158 | { | 176 | { |
159 | dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); | 177 | dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); |
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 42e9d908914a..d82878c4daa6 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S | |||
@@ -97,6 +97,24 @@ system_call_common: | |||
97 | addi r9,r1,STACK_FRAME_OVERHEAD | 97 | addi r9,r1,STACK_FRAME_OVERHEAD |
98 | ld r11,exception_marker@toc(r2) | 98 | ld r11,exception_marker@toc(r2) |
99 | std r11,-16(r9) /* "regshere" marker */ | 99 | std r11,-16(r9) /* "regshere" marker */ |
100 | #if defined(CONFIG_VIRT_CPU_ACCOUNTING) && defined(CONFIG_PPC_SPLPAR) | ||
101 | BEGIN_FW_FTR_SECTION | ||
102 | beq 33f | ||
103 | /* if from user, see if there are any DTL entries to process */ | ||
104 | ld r10,PACALPPACAPTR(r13) /* get ptr to VPA */ | ||
105 | ld r11,PACA_DTL_RIDX(r13) /* get log read index */ | ||
106 | ld r10,LPPACA_DTLIDX(r10) /* get log write index */ | ||
107 | cmpd cr1,r11,r10 | ||
108 | beq+ cr1,33f | ||
109 | bl .accumulate_stolen_time | ||
110 | REST_GPR(0,r1) | ||
111 | REST_4GPRS(3,r1) | ||
112 | REST_2GPRS(7,r1) | ||
113 | addi r9,r1,STACK_FRAME_OVERHEAD | ||
114 | 33: | ||
115 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR) | ||
116 | #endif /* CONFIG_VIRT_CPU_ACCOUNTING && CONFIG_PPC_SPLPAR */ | ||
117 | |||
100 | #ifdef CONFIG_TRACE_IRQFLAGS | 118 | #ifdef CONFIG_TRACE_IRQFLAGS |
101 | bl .trace_hardirqs_on | 119 | bl .trace_hardirqs_on |
102 | REST_GPR(0,r1) | 120 | REST_GPR(0,r1) |
@@ -202,7 +220,9 @@ syscall_exit: | |||
202 | bge- syscall_error | 220 | bge- syscall_error |
203 | syscall_error_cont: | 221 | syscall_error_cont: |
204 | ld r7,_NIP(r1) | 222 | ld r7,_NIP(r1) |
223 | BEGIN_FTR_SECTION | ||
205 | stdcx. r0,0,r1 /* to clear the reservation */ | 224 | stdcx. r0,0,r1 /* to clear the reservation */ |
225 | END_FTR_SECTION_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS) | ||
206 | andi. r6,r8,MSR_PR | 226 | andi. r6,r8,MSR_PR |
207 | ld r4,_LINK(r1) | 227 | ld r4,_LINK(r1) |
208 | /* | 228 | /* |
@@ -419,6 +439,17 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | |||
419 | sync | 439 | sync |
420 | #endif /* CONFIG_SMP */ | 440 | #endif /* CONFIG_SMP */ |
421 | 441 | ||
442 | /* | ||
443 | * If we optimise away the clear of the reservation in system | ||
444 | * calls because we know the CPU tracks the address of the | ||
445 | * reservation, then we need to clear it here to cover the | ||
446 | * case that the kernel context switch path has no larx | ||
447 | * instructions. | ||
448 | */ | ||
449 | BEGIN_FTR_SECTION | ||
450 | ldarx r6,0,r1 | ||
451 | END_FTR_SECTION_IFSET(CPU_FTR_STCX_CHECKS_ADDRESS) | ||
452 | |||
422 | addi r6,r4,-THREAD /* Convert THREAD to 'current' */ | 453 | addi r6,r4,-THREAD /* Convert THREAD to 'current' */ |
423 | std r6,PACACURRENT(r13) /* Set new 'current' */ | 454 | std r6,PACACURRENT(r13) /* Set new 'current' */ |
424 | 455 | ||
@@ -576,7 +607,16 @@ ALT_FW_FTR_SECTION_END_IFCLR(FW_FEATURE_ISERIES) | |||
576 | andi. r0,r3,MSR_RI | 607 | andi. r0,r3,MSR_RI |
577 | beq- unrecov_restore | 608 | beq- unrecov_restore |
578 | 609 | ||
610 | /* | ||
611 | * Clear the reservation. If we know the CPU tracks the address of | ||
612 | * the reservation then we can potentially save some cycles and use | ||
613 | * a larx. On POWER6 and POWER7 this is significantly faster. | ||
614 | */ | ||
615 | BEGIN_FTR_SECTION | ||
579 | stdcx. r0,0,r1 /* to clear the reservation */ | 616 | stdcx. r0,0,r1 /* to clear the reservation */ |
617 | FTR_SECTION_ELSE | ||
618 | ldarx r4,0,r1 | ||
619 | ALT_FTR_SECTION_END_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS) | ||
580 | 620 | ||
581 | /* | 621 | /* |
582 | * Clear RI before restoring r13. If we are returning to | 622 | * Clear RI before restoring r13. If we are returning to |
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index f53029a01554..9f8b01d6466f 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S | |||
@@ -299,6 +299,12 @@ slb_miss_user_pseries: | |||
299 | b . /* prevent spec. execution */ | 299 | b . /* prevent spec. execution */ |
300 | #endif /* __DISABLED__ */ | 300 | #endif /* __DISABLED__ */ |
301 | 301 | ||
302 | /* KVM's trampoline code needs to be close to the interrupt handlers */ | ||
303 | |||
304 | #ifdef CONFIG_KVM_BOOK3S_64_HANDLER | ||
305 | #include "../kvm/book3s_rmhandlers.S" | ||
306 | #endif | ||
307 | |||
302 | .align 7 | 308 | .align 7 |
303 | .globl __end_interrupts | 309 | .globl __end_interrupts |
304 | __end_interrupts: | 310 | __end_interrupts: |
@@ -818,12 +824,12 @@ END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES) | |||
818 | 824 | ||
819 | /* | 825 | /* |
820 | * hash_page couldn't handle it, set soft interrupt enable back | 826 | * hash_page couldn't handle it, set soft interrupt enable back |
821 | * to what it was before the trap. Note that .raw_local_irq_restore | 827 | * to what it was before the trap. Note that .arch_local_irq_restore |
822 | * handles any interrupts pending at this point. | 828 | * handles any interrupts pending at this point. |
823 | */ | 829 | */ |
824 | ld r3,SOFTE(r1) | 830 | ld r3,SOFTE(r1) |
825 | TRACE_AND_RESTORE_IRQ_PARTIAL(r3, 11f) | 831 | TRACE_AND_RESTORE_IRQ_PARTIAL(r3, 11f) |
826 | bl .raw_local_irq_restore | 832 | bl .arch_local_irq_restore |
827 | b 11f | 833 | b 11f |
828 | 834 | ||
829 | /* We have a data breakpoint exception - handle it */ | 835 | /* We have a data breakpoint exception - handle it */ |
diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S index fc8f5b14019c..e86c040ae585 100644 --- a/arch/powerpc/kernel/fpu.S +++ b/arch/powerpc/kernel/fpu.S | |||
@@ -163,24 +163,14 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX) | |||
163 | /* | 163 | /* |
164 | * These are used in the alignment trap handler when emulating | 164 | * These are used in the alignment trap handler when emulating |
165 | * single-precision loads and stores. | 165 | * single-precision loads and stores. |
166 | * We restore and save the fpscr so the task gets the same result | ||
167 | * and exceptions as if the cpu had performed the load or store. | ||
168 | */ | 166 | */ |
169 | 167 | ||
170 | _GLOBAL(cvt_fd) | 168 | _GLOBAL(cvt_fd) |
171 | lfd 0,THREAD_FPSCR(r5) /* load up fpscr value */ | ||
172 | MTFSF_L(0) | ||
173 | lfs 0,0(r3) | 169 | lfs 0,0(r3) |
174 | stfd 0,0(r4) | 170 | stfd 0,0(r4) |
175 | mffs 0 | ||
176 | stfd 0,THREAD_FPSCR(r5) /* save new fpscr value */ | ||
177 | blr | 171 | blr |
178 | 172 | ||
179 | _GLOBAL(cvt_df) | 173 | _GLOBAL(cvt_df) |
180 | lfd 0,THREAD_FPSCR(r5) /* load up fpscr value */ | ||
181 | MTFSF_L(0) | ||
182 | lfd 0,0(r3) | 174 | lfd 0,0(r3) |
183 | stfs 0,0(r4) | 175 | stfs 0,0(r4) |
184 | mffs 0 | ||
185 | stfd 0,THREAD_FPSCR(r5) /* save new fpscr value */ | ||
186 | blr | 176 | blr |
diff --git a/arch/powerpc/kernel/head_40x.S b/arch/powerpc/kernel/head_40x.S index a90625f9b485..8278e8bad5a0 100644 --- a/arch/powerpc/kernel/head_40x.S +++ b/arch/powerpc/kernel/head_40x.S | |||
@@ -923,11 +923,7 @@ initial_mmu: | |||
923 | mtspr SPRN_PID,r0 | 923 | mtspr SPRN_PID,r0 |
924 | sync | 924 | sync |
925 | 925 | ||
926 | /* Configure and load two entries into TLB slots 62 and 63. | 926 | /* Configure and load one entry into TLB slots 63 */ |
927 | * In case we are pinning TLBs, these are reserved in by the | ||
928 | * other TLB functions. If not reserving, then it doesn't | ||
929 | * matter where they are loaded. | ||
930 | */ | ||
931 | clrrwi r4,r4,10 /* Mask off the real page number */ | 927 | clrrwi r4,r4,10 /* Mask off the real page number */ |
932 | ori r4,r4,(TLB_WR | TLB_EX) /* Set the write and execute bits */ | 928 | ori r4,r4,(TLB_WR | TLB_EX) /* Set the write and execute bits */ |
933 | 929 | ||
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index c571cd3c1453..f0dd577e4a5b 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S | |||
@@ -166,12 +166,6 @@ exception_marker: | |||
166 | #include "exceptions-64s.S" | 166 | #include "exceptions-64s.S" |
167 | #endif | 167 | #endif |
168 | 168 | ||
169 | /* KVM trampoline code needs to be close to the interrupt handlers */ | ||
170 | |||
171 | #ifdef CONFIG_KVM_BOOK3S_64_HANDLER | ||
172 | #include "../kvm/book3s_rmhandlers.S" | ||
173 | #endif | ||
174 | |||
175 | _GLOBAL(generic_secondary_thread_init) | 169 | _GLOBAL(generic_secondary_thread_init) |
176 | mr r24,r3 | 170 | mr r24,r3 |
177 | 171 | ||
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S index 4faeba247854..529b817f473b 100644 --- a/arch/powerpc/kernel/head_fsl_booke.S +++ b/arch/powerpc/kernel/head_fsl_booke.S | |||
@@ -152,8 +152,11 @@ _ENTRY(__early_start) | |||
152 | /* Check to see if we're the second processor, and jump | 152 | /* Check to see if we're the second processor, and jump |
153 | * to the secondary_start code if so | 153 | * to the secondary_start code if so |
154 | */ | 154 | */ |
155 | mfspr r24,SPRN_PIR | 155 | lis r24, boot_cpuid@h |
156 | cmpwi r24,0 | 156 | ori r24, r24, boot_cpuid@l |
157 | lwz r24, 0(r24) | ||
158 | cmpwi r24, -1 | ||
159 | mfspr r24,SPRN_PIR | ||
157 | bne __secondary_start | 160 | bne __secondary_start |
158 | #endif | 161 | #endif |
159 | 162 | ||
@@ -175,6 +178,9 @@ _ENTRY(__early_start) | |||
175 | li r0,0 | 178 | li r0,0 |
176 | stwu r0,THREAD_SIZE-STACK_FRAME_OVERHEAD(r1) | 179 | stwu r0,THREAD_SIZE-STACK_FRAME_OVERHEAD(r1) |
177 | 180 | ||
181 | rlwinm r22,r1,0,0,31-THREAD_SHIFT /* current thread_info */ | ||
182 | stw r24, TI_CPU(r22) | ||
183 | |||
178 | bl early_init | 184 | bl early_init |
179 | 185 | ||
180 | #ifdef CONFIG_RELOCATABLE | 186 | #ifdef CONFIG_RELOCATABLE |
diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c index 9b626cfffce1..f62efdfd1769 100644 --- a/arch/powerpc/kernel/ibmebus.c +++ b/arch/powerpc/kernel/ibmebus.c | |||
@@ -162,13 +162,10 @@ static int ibmebus_create_device(struct device_node *dn) | |||
162 | dev->dev.bus = &ibmebus_bus_type; | 162 | dev->dev.bus = &ibmebus_bus_type; |
163 | dev->dev.archdata.dma_ops = &ibmebus_dma_ops; | 163 | dev->dev.archdata.dma_ops = &ibmebus_dma_ops; |
164 | 164 | ||
165 | ret = of_device_register(dev); | 165 | ret = of_device_add(dev); |
166 | if (ret) { | 166 | if (ret) |
167 | of_device_free(dev); | 167 | platform_device_put(dev); |
168 | return ret; | 168 | return ret; |
169 | } | ||
170 | |||
171 | return 0; | ||
172 | } | 169 | } |
173 | 170 | ||
174 | static int ibmebus_create_devices(const struct of_device_id *matches) | 171 | static int ibmebus_create_devices(const struct of_device_id *matches) |
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 4a65386995d7..ce557f6f00fc 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c | |||
@@ -116,7 +116,7 @@ static inline notrace void set_soft_enabled(unsigned long enable) | |||
116 | : : "r" (enable), "i" (offsetof(struct paca_struct, soft_enabled))); | 116 | : : "r" (enable), "i" (offsetof(struct paca_struct, soft_enabled))); |
117 | } | 117 | } |
118 | 118 | ||
119 | notrace void raw_local_irq_restore(unsigned long en) | 119 | notrace void arch_local_irq_restore(unsigned long en) |
120 | { | 120 | { |
121 | /* | 121 | /* |
122 | * get_paca()->soft_enabled = en; | 122 | * get_paca()->soft_enabled = en; |
@@ -192,7 +192,7 @@ notrace void raw_local_irq_restore(unsigned long en) | |||
192 | 192 | ||
193 | __hard_irq_enable(); | 193 | __hard_irq_enable(); |
194 | } | 194 | } |
195 | EXPORT_SYMBOL(raw_local_irq_restore); | 195 | EXPORT_SYMBOL(arch_local_irq_restore); |
196 | #endif /* CONFIG_PPC64 */ | 196 | #endif /* CONFIG_PPC64 */ |
197 | 197 | ||
198 | static int show_other_interrupts(struct seq_file *p, int prec) | 198 | static int show_other_interrupts(struct seq_file *p, int prec) |
@@ -587,8 +587,10 @@ struct irq_host *irq_alloc_host(struct device_node *of_node, | |||
587 | * this will be fixed once slab is made available early | 587 | * this will be fixed once slab is made available early |
588 | * instead of the current cruft | 588 | * instead of the current cruft |
589 | */ | 589 | */ |
590 | if (mem_init_done) | 590 | if (mem_init_done) { |
591 | of_node_put(host->of_node); | ||
591 | kfree(host); | 592 | kfree(host); |
593 | } | ||
592 | return NULL; | 594 | return NULL; |
593 | } | 595 | } |
594 | irq_map[0].host = host; | 596 | irq_map[0].host = host; |
@@ -1143,7 +1145,7 @@ static int virq_debug_show(struct seq_file *m, void *private) | |||
1143 | unsigned long flags; | 1145 | unsigned long flags; |
1144 | struct irq_desc *desc; | 1146 | struct irq_desc *desc; |
1145 | const char *p; | 1147 | const char *p; |
1146 | char none[] = "none"; | 1148 | static const char none[] = "none"; |
1147 | int i; | 1149 | int i; |
1148 | 1150 | ||
1149 | seq_printf(m, "%-5s %-7s %-15s %s\n", "virq", "hwirq", | 1151 | seq_printf(m, "%-5s %-7s %-15s %s\n", "virq", "hwirq", |
diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c new file mode 100644 index 000000000000..428d0e538aec --- /dev/null +++ b/arch/powerpc/kernel/kvm.c | |||
@@ -0,0 +1,596 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2010 SUSE Linux Products GmbH. All rights reserved. | ||
3 | * | ||
4 | * Authors: | ||
5 | * Alexander Graf <agraf@suse.de> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License, version 2, as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/kvm_host.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/kvm_para.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/of.h> | ||
26 | |||
27 | #include <asm/reg.h> | ||
28 | #include <asm/sections.h> | ||
29 | #include <asm/cacheflush.h> | ||
30 | #include <asm/disassemble.h> | ||
31 | |||
32 | #define KVM_MAGIC_PAGE (-4096L) | ||
33 | #define magic_var(x) KVM_MAGIC_PAGE + offsetof(struct kvm_vcpu_arch_shared, x) | ||
34 | |||
35 | #define KVM_INST_LWZ 0x80000000 | ||
36 | #define KVM_INST_STW 0x90000000 | ||
37 | #define KVM_INST_LD 0xe8000000 | ||
38 | #define KVM_INST_STD 0xf8000000 | ||
39 | #define KVM_INST_NOP 0x60000000 | ||
40 | #define KVM_INST_B 0x48000000 | ||
41 | #define KVM_INST_B_MASK 0x03ffffff | ||
42 | #define KVM_INST_B_MAX 0x01ffffff | ||
43 | |||
44 | #define KVM_MASK_RT 0x03e00000 | ||
45 | #define KVM_RT_30 0x03c00000 | ||
46 | #define KVM_MASK_RB 0x0000f800 | ||
47 | #define KVM_INST_MFMSR 0x7c0000a6 | ||
48 | #define KVM_INST_MFSPR_SPRG0 0x7c1042a6 | ||
49 | #define KVM_INST_MFSPR_SPRG1 0x7c1142a6 | ||
50 | #define KVM_INST_MFSPR_SPRG2 0x7c1242a6 | ||
51 | #define KVM_INST_MFSPR_SPRG3 0x7c1342a6 | ||
52 | #define KVM_INST_MFSPR_SRR0 0x7c1a02a6 | ||
53 | #define KVM_INST_MFSPR_SRR1 0x7c1b02a6 | ||
54 | #define KVM_INST_MFSPR_DAR 0x7c1302a6 | ||
55 | #define KVM_INST_MFSPR_DSISR 0x7c1202a6 | ||
56 | |||
57 | #define KVM_INST_MTSPR_SPRG0 0x7c1043a6 | ||
58 | #define KVM_INST_MTSPR_SPRG1 0x7c1143a6 | ||
59 | #define KVM_INST_MTSPR_SPRG2 0x7c1243a6 | ||
60 | #define KVM_INST_MTSPR_SPRG3 0x7c1343a6 | ||
61 | #define KVM_INST_MTSPR_SRR0 0x7c1a03a6 | ||
62 | #define KVM_INST_MTSPR_SRR1 0x7c1b03a6 | ||
63 | #define KVM_INST_MTSPR_DAR 0x7c1303a6 | ||
64 | #define KVM_INST_MTSPR_DSISR 0x7c1203a6 | ||
65 | |||
66 | #define KVM_INST_TLBSYNC 0x7c00046c | ||
67 | #define KVM_INST_MTMSRD_L0 0x7c000164 | ||
68 | #define KVM_INST_MTMSRD_L1 0x7c010164 | ||
69 | #define KVM_INST_MTMSR 0x7c000124 | ||
70 | |||
71 | #define KVM_INST_WRTEEI_0 0x7c000146 | ||
72 | #define KVM_INST_WRTEEI_1 0x7c008146 | ||
73 | |||
74 | #define KVM_INST_MTSRIN 0x7c0001e4 | ||
75 | |||
76 | static bool kvm_patching_worked = true; | ||
77 | static char kvm_tmp[1024 * 1024]; | ||
78 | static int kvm_tmp_index; | ||
79 | |||
80 | static inline void kvm_patch_ins(u32 *inst, u32 new_inst) | ||
81 | { | ||
82 | *inst = new_inst; | ||
83 | flush_icache_range((ulong)inst, (ulong)inst + 4); | ||
84 | } | ||
85 | |||
86 | static void kvm_patch_ins_ll(u32 *inst, long addr, u32 rt) | ||
87 | { | ||
88 | #ifdef CONFIG_64BIT | ||
89 | kvm_patch_ins(inst, KVM_INST_LD | rt | (addr & 0x0000fffc)); | ||
90 | #else | ||
91 | kvm_patch_ins(inst, KVM_INST_LWZ | rt | (addr & 0x0000fffc)); | ||
92 | #endif | ||
93 | } | ||
94 | |||
95 | static void kvm_patch_ins_ld(u32 *inst, long addr, u32 rt) | ||
96 | { | ||
97 | #ifdef CONFIG_64BIT | ||
98 | kvm_patch_ins(inst, KVM_INST_LD | rt | (addr & 0x0000fffc)); | ||
99 | #else | ||
100 | kvm_patch_ins(inst, KVM_INST_LWZ | rt | ((addr + 4) & 0x0000fffc)); | ||
101 | #endif | ||
102 | } | ||
103 | |||
104 | static void kvm_patch_ins_lwz(u32 *inst, long addr, u32 rt) | ||
105 | { | ||
106 | kvm_patch_ins(inst, KVM_INST_LWZ | rt | (addr & 0x0000ffff)); | ||
107 | } | ||
108 | |||
109 | static void kvm_patch_ins_std(u32 *inst, long addr, u32 rt) | ||
110 | { | ||
111 | #ifdef CONFIG_64BIT | ||
112 | kvm_patch_ins(inst, KVM_INST_STD | rt | (addr & 0x0000fffc)); | ||
113 | #else | ||
114 | kvm_patch_ins(inst, KVM_INST_STW | rt | ((addr + 4) & 0x0000fffc)); | ||
115 | #endif | ||
116 | } | ||
117 | |||
118 | static void kvm_patch_ins_stw(u32 *inst, long addr, u32 rt) | ||
119 | { | ||
120 | kvm_patch_ins(inst, KVM_INST_STW | rt | (addr & 0x0000fffc)); | ||
121 | } | ||
122 | |||
123 | static void kvm_patch_ins_nop(u32 *inst) | ||
124 | { | ||
125 | kvm_patch_ins(inst, KVM_INST_NOP); | ||
126 | } | ||
127 | |||
128 | static void kvm_patch_ins_b(u32 *inst, int addr) | ||
129 | { | ||
130 | #ifdef CONFIG_RELOCATABLE | ||
131 | /* On relocatable kernels interrupts handlers and our code | ||
132 | can be in different regions, so we don't patch them */ | ||
133 | |||
134 | extern u32 __end_interrupts; | ||
135 | if ((ulong)inst < (ulong)&__end_interrupts) | ||
136 | return; | ||
137 | #endif | ||
138 | |||
139 | kvm_patch_ins(inst, KVM_INST_B | (addr & KVM_INST_B_MASK)); | ||
140 | } | ||
141 | |||
142 | static u32 *kvm_alloc(int len) | ||
143 | { | ||
144 | u32 *p; | ||
145 | |||
146 | if ((kvm_tmp_index + len) > ARRAY_SIZE(kvm_tmp)) { | ||
147 | printk(KERN_ERR "KVM: No more space (%d + %d)\n", | ||
148 | kvm_tmp_index, len); | ||
149 | kvm_patching_worked = false; | ||
150 | return NULL; | ||
151 | } | ||
152 | |||
153 | p = (void*)&kvm_tmp[kvm_tmp_index]; | ||
154 | kvm_tmp_index += len; | ||
155 | |||
156 | return p; | ||
157 | } | ||
158 | |||
159 | extern u32 kvm_emulate_mtmsrd_branch_offs; | ||
160 | extern u32 kvm_emulate_mtmsrd_reg_offs; | ||
161 | extern u32 kvm_emulate_mtmsrd_orig_ins_offs; | ||
162 | extern u32 kvm_emulate_mtmsrd_len; | ||
163 | extern u32 kvm_emulate_mtmsrd[]; | ||
164 | |||
165 | static void kvm_patch_ins_mtmsrd(u32 *inst, u32 rt) | ||
166 | { | ||
167 | u32 *p; | ||
168 | int distance_start; | ||
169 | int distance_end; | ||
170 | ulong next_inst; | ||
171 | |||
172 | p = kvm_alloc(kvm_emulate_mtmsrd_len * 4); | ||
173 | if (!p) | ||
174 | return; | ||
175 | |||
176 | /* Find out where we are and put everything there */ | ||
177 | distance_start = (ulong)p - (ulong)inst; | ||
178 | next_inst = ((ulong)inst + 4); | ||
179 | distance_end = next_inst - (ulong)&p[kvm_emulate_mtmsrd_branch_offs]; | ||
180 | |||
181 | /* Make sure we only write valid b instructions */ | ||
182 | if (distance_start > KVM_INST_B_MAX) { | ||
183 | kvm_patching_worked = false; | ||
184 | return; | ||
185 | } | ||
186 | |||
187 | /* Modify the chunk to fit the invocation */ | ||
188 | memcpy(p, kvm_emulate_mtmsrd, kvm_emulate_mtmsrd_len * 4); | ||
189 | p[kvm_emulate_mtmsrd_branch_offs] |= distance_end & KVM_INST_B_MASK; | ||
190 | switch (get_rt(rt)) { | ||
191 | case 30: | ||
192 | kvm_patch_ins_ll(&p[kvm_emulate_mtmsrd_reg_offs], | ||
193 | magic_var(scratch2), KVM_RT_30); | ||
194 | break; | ||
195 | case 31: | ||
196 | kvm_patch_ins_ll(&p[kvm_emulate_mtmsrd_reg_offs], | ||
197 | magic_var(scratch1), KVM_RT_30); | ||
198 | break; | ||
199 | default: | ||
200 | p[kvm_emulate_mtmsrd_reg_offs] |= rt; | ||
201 | break; | ||
202 | } | ||
203 | |||
204 | p[kvm_emulate_mtmsrd_orig_ins_offs] = *inst; | ||
205 | flush_icache_range((ulong)p, (ulong)p + kvm_emulate_mtmsrd_len * 4); | ||
206 | |||
207 | /* Patch the invocation */ | ||
208 | kvm_patch_ins_b(inst, distance_start); | ||
209 | } | ||
210 | |||
211 | extern u32 kvm_emulate_mtmsr_branch_offs; | ||
212 | extern u32 kvm_emulate_mtmsr_reg1_offs; | ||
213 | extern u32 kvm_emulate_mtmsr_reg2_offs; | ||
214 | extern u32 kvm_emulate_mtmsr_orig_ins_offs; | ||
215 | extern u32 kvm_emulate_mtmsr_len; | ||
216 | extern u32 kvm_emulate_mtmsr[]; | ||
217 | |||
218 | static void kvm_patch_ins_mtmsr(u32 *inst, u32 rt) | ||
219 | { | ||
220 | u32 *p; | ||
221 | int distance_start; | ||
222 | int distance_end; | ||
223 | ulong next_inst; | ||
224 | |||
225 | p = kvm_alloc(kvm_emulate_mtmsr_len * 4); | ||
226 | if (!p) | ||
227 | return; | ||
228 | |||
229 | /* Find out where we are and put everything there */ | ||
230 | distance_start = (ulong)p - (ulong)inst; | ||
231 | next_inst = ((ulong)inst + 4); | ||
232 | distance_end = next_inst - (ulong)&p[kvm_emulate_mtmsr_branch_offs]; | ||
233 | |||
234 | /* Make sure we only write valid b instructions */ | ||
235 | if (distance_start > KVM_INST_B_MAX) { | ||
236 | kvm_patching_worked = false; | ||
237 | return; | ||
238 | } | ||
239 | |||
240 | /* Modify the chunk to fit the invocation */ | ||
241 | memcpy(p, kvm_emulate_mtmsr, kvm_emulate_mtmsr_len * 4); | ||
242 | p[kvm_emulate_mtmsr_branch_offs] |= distance_end & KVM_INST_B_MASK; | ||
243 | |||
244 | /* Make clobbered registers work too */ | ||
245 | switch (get_rt(rt)) { | ||
246 | case 30: | ||
247 | kvm_patch_ins_ll(&p[kvm_emulate_mtmsr_reg1_offs], | ||
248 | magic_var(scratch2), KVM_RT_30); | ||
249 | kvm_patch_ins_ll(&p[kvm_emulate_mtmsr_reg2_offs], | ||
250 | magic_var(scratch2), KVM_RT_30); | ||
251 | break; | ||
252 | case 31: | ||
253 | kvm_patch_ins_ll(&p[kvm_emulate_mtmsr_reg1_offs], | ||
254 | magic_var(scratch1), KVM_RT_30); | ||
255 | kvm_patch_ins_ll(&p[kvm_emulate_mtmsr_reg2_offs], | ||
256 | magic_var(scratch1), KVM_RT_30); | ||
257 | break; | ||
258 | default: | ||
259 | p[kvm_emulate_mtmsr_reg1_offs] |= rt; | ||
260 | p[kvm_emulate_mtmsr_reg2_offs] |= rt; | ||
261 | break; | ||
262 | } | ||
263 | |||
264 | p[kvm_emulate_mtmsr_orig_ins_offs] = *inst; | ||
265 | flush_icache_range((ulong)p, (ulong)p + kvm_emulate_mtmsr_len * 4); | ||
266 | |||
267 | /* Patch the invocation */ | ||
268 | kvm_patch_ins_b(inst, distance_start); | ||
269 | } | ||
270 | |||
271 | #ifdef CONFIG_BOOKE | ||
272 | |||
273 | extern u32 kvm_emulate_wrteei_branch_offs; | ||
274 | extern u32 kvm_emulate_wrteei_ee_offs; | ||
275 | extern u32 kvm_emulate_wrteei_len; | ||
276 | extern u32 kvm_emulate_wrteei[]; | ||
277 | |||
278 | static void kvm_patch_ins_wrteei(u32 *inst) | ||
279 | { | ||
280 | u32 *p; | ||
281 | int distance_start; | ||
282 | int distance_end; | ||
283 | ulong next_inst; | ||
284 | |||
285 | p = kvm_alloc(kvm_emulate_wrteei_len * 4); | ||
286 | if (!p) | ||
287 | return; | ||
288 | |||
289 | /* Find out where we are and put everything there */ | ||
290 | distance_start = (ulong)p - (ulong)inst; | ||
291 | next_inst = ((ulong)inst + 4); | ||
292 | distance_end = next_inst - (ulong)&p[kvm_emulate_wrteei_branch_offs]; | ||
293 | |||
294 | /* Make sure we only write valid b instructions */ | ||
295 | if (distance_start > KVM_INST_B_MAX) { | ||
296 | kvm_patching_worked = false; | ||
297 | return; | ||
298 | } | ||
299 | |||
300 | /* Modify the chunk to fit the invocation */ | ||
301 | memcpy(p, kvm_emulate_wrteei, kvm_emulate_wrteei_len * 4); | ||
302 | p[kvm_emulate_wrteei_branch_offs] |= distance_end & KVM_INST_B_MASK; | ||
303 | p[kvm_emulate_wrteei_ee_offs] |= (*inst & MSR_EE); | ||
304 | flush_icache_range((ulong)p, (ulong)p + kvm_emulate_wrteei_len * 4); | ||
305 | |||
306 | /* Patch the invocation */ | ||
307 | kvm_patch_ins_b(inst, distance_start); | ||
308 | } | ||
309 | |||
310 | #endif | ||
311 | |||
312 | #ifdef CONFIG_PPC_BOOK3S_32 | ||
313 | |||
314 | extern u32 kvm_emulate_mtsrin_branch_offs; | ||
315 | extern u32 kvm_emulate_mtsrin_reg1_offs; | ||
316 | extern u32 kvm_emulate_mtsrin_reg2_offs; | ||
317 | extern u32 kvm_emulate_mtsrin_orig_ins_offs; | ||
318 | extern u32 kvm_emulate_mtsrin_len; | ||
319 | extern u32 kvm_emulate_mtsrin[]; | ||
320 | |||
321 | static void kvm_patch_ins_mtsrin(u32 *inst, u32 rt, u32 rb) | ||
322 | { | ||
323 | u32 *p; | ||
324 | int distance_start; | ||
325 | int distance_end; | ||
326 | ulong next_inst; | ||
327 | |||
328 | p = kvm_alloc(kvm_emulate_mtsrin_len * 4); | ||
329 | if (!p) | ||
330 | return; | ||
331 | |||
332 | /* Find out where we are and put everything there */ | ||
333 | distance_start = (ulong)p - (ulong)inst; | ||
334 | next_inst = ((ulong)inst + 4); | ||
335 | distance_end = next_inst - (ulong)&p[kvm_emulate_mtsrin_branch_offs]; | ||
336 | |||
337 | /* Make sure we only write valid b instructions */ | ||
338 | if (distance_start > KVM_INST_B_MAX) { | ||
339 | kvm_patching_worked = false; | ||
340 | return; | ||
341 | } | ||
342 | |||
343 | /* Modify the chunk to fit the invocation */ | ||
344 | memcpy(p, kvm_emulate_mtsrin, kvm_emulate_mtsrin_len * 4); | ||
345 | p[kvm_emulate_mtsrin_branch_offs] |= distance_end & KVM_INST_B_MASK; | ||
346 | p[kvm_emulate_mtsrin_reg1_offs] |= (rb << 10); | ||
347 | p[kvm_emulate_mtsrin_reg2_offs] |= rt; | ||
348 | p[kvm_emulate_mtsrin_orig_ins_offs] = *inst; | ||
349 | flush_icache_range((ulong)p, (ulong)p + kvm_emulate_mtsrin_len * 4); | ||
350 | |||
351 | /* Patch the invocation */ | ||
352 | kvm_patch_ins_b(inst, distance_start); | ||
353 | } | ||
354 | |||
355 | #endif | ||
356 | |||
357 | static void kvm_map_magic_page(void *data) | ||
358 | { | ||
359 | u32 *features = data; | ||
360 | |||
361 | ulong in[8]; | ||
362 | ulong out[8]; | ||
363 | |||
364 | in[0] = KVM_MAGIC_PAGE; | ||
365 | in[1] = KVM_MAGIC_PAGE; | ||
366 | |||
367 | kvm_hypercall(in, out, HC_VENDOR_KVM | KVM_HC_PPC_MAP_MAGIC_PAGE); | ||
368 | |||
369 | *features = out[0]; | ||
370 | } | ||
371 | |||
372 | static void kvm_check_ins(u32 *inst, u32 features) | ||
373 | { | ||
374 | u32 _inst = *inst; | ||
375 | u32 inst_no_rt = _inst & ~KVM_MASK_RT; | ||
376 | u32 inst_rt = _inst & KVM_MASK_RT; | ||
377 | |||
378 | switch (inst_no_rt) { | ||
379 | /* Loads */ | ||
380 | case KVM_INST_MFMSR: | ||
381 | kvm_patch_ins_ld(inst, magic_var(msr), inst_rt); | ||
382 | break; | ||
383 | case KVM_INST_MFSPR_SPRG0: | ||
384 | kvm_patch_ins_ld(inst, magic_var(sprg0), inst_rt); | ||
385 | break; | ||
386 | case KVM_INST_MFSPR_SPRG1: | ||
387 | kvm_patch_ins_ld(inst, magic_var(sprg1), inst_rt); | ||
388 | break; | ||
389 | case KVM_INST_MFSPR_SPRG2: | ||
390 | kvm_patch_ins_ld(inst, magic_var(sprg2), inst_rt); | ||
391 | break; | ||
392 | case KVM_INST_MFSPR_SPRG3: | ||
393 | kvm_patch_ins_ld(inst, magic_var(sprg3), inst_rt); | ||
394 | break; | ||
395 | case KVM_INST_MFSPR_SRR0: | ||
396 | kvm_patch_ins_ld(inst, magic_var(srr0), inst_rt); | ||
397 | break; | ||
398 | case KVM_INST_MFSPR_SRR1: | ||
399 | kvm_patch_ins_ld(inst, magic_var(srr1), inst_rt); | ||
400 | break; | ||
401 | case KVM_INST_MFSPR_DAR: | ||
402 | kvm_patch_ins_ld(inst, magic_var(dar), inst_rt); | ||
403 | break; | ||
404 | case KVM_INST_MFSPR_DSISR: | ||
405 | kvm_patch_ins_lwz(inst, magic_var(dsisr), inst_rt); | ||
406 | break; | ||
407 | |||
408 | /* Stores */ | ||
409 | case KVM_INST_MTSPR_SPRG0: | ||
410 | kvm_patch_ins_std(inst, magic_var(sprg0), inst_rt); | ||
411 | break; | ||
412 | case KVM_INST_MTSPR_SPRG1: | ||
413 | kvm_patch_ins_std(inst, magic_var(sprg1), inst_rt); | ||
414 | break; | ||
415 | case KVM_INST_MTSPR_SPRG2: | ||
416 | kvm_patch_ins_std(inst, magic_var(sprg2), inst_rt); | ||
417 | break; | ||
418 | case KVM_INST_MTSPR_SPRG3: | ||
419 | kvm_patch_ins_std(inst, magic_var(sprg3), inst_rt); | ||
420 | break; | ||
421 | case KVM_INST_MTSPR_SRR0: | ||
422 | kvm_patch_ins_std(inst, magic_var(srr0), inst_rt); | ||
423 | break; | ||
424 | case KVM_INST_MTSPR_SRR1: | ||
425 | kvm_patch_ins_std(inst, magic_var(srr1), inst_rt); | ||
426 | break; | ||
427 | case KVM_INST_MTSPR_DAR: | ||
428 | kvm_patch_ins_std(inst, magic_var(dar), inst_rt); | ||
429 | break; | ||
430 | case KVM_INST_MTSPR_DSISR: | ||
431 | kvm_patch_ins_stw(inst, magic_var(dsisr), inst_rt); | ||
432 | break; | ||
433 | |||
434 | /* Nops */ | ||
435 | case KVM_INST_TLBSYNC: | ||
436 | kvm_patch_ins_nop(inst); | ||
437 | break; | ||
438 | |||
439 | /* Rewrites */ | ||
440 | case KVM_INST_MTMSRD_L1: | ||
441 | kvm_patch_ins_mtmsrd(inst, inst_rt); | ||
442 | break; | ||
443 | case KVM_INST_MTMSR: | ||
444 | case KVM_INST_MTMSRD_L0: | ||
445 | kvm_patch_ins_mtmsr(inst, inst_rt); | ||
446 | break; | ||
447 | } | ||
448 | |||
449 | switch (inst_no_rt & ~KVM_MASK_RB) { | ||
450 | #ifdef CONFIG_PPC_BOOK3S_32 | ||
451 | case KVM_INST_MTSRIN: | ||
452 | if (features & KVM_MAGIC_FEAT_SR) { | ||
453 | u32 inst_rb = _inst & KVM_MASK_RB; | ||
454 | kvm_patch_ins_mtsrin(inst, inst_rt, inst_rb); | ||
455 | } | ||
456 | break; | ||
457 | break; | ||
458 | #endif | ||
459 | } | ||
460 | |||
461 | switch (_inst) { | ||
462 | #ifdef CONFIG_BOOKE | ||
463 | case KVM_INST_WRTEEI_0: | ||
464 | case KVM_INST_WRTEEI_1: | ||
465 | kvm_patch_ins_wrteei(inst); | ||
466 | break; | ||
467 | #endif | ||
468 | } | ||
469 | } | ||
470 | |||
471 | static void kvm_use_magic_page(void) | ||
472 | { | ||
473 | u32 *p; | ||
474 | u32 *start, *end; | ||
475 | u32 tmp; | ||
476 | u32 features; | ||
477 | |||
478 | /* Tell the host to map the magic page to -4096 on all CPUs */ | ||
479 | on_each_cpu(kvm_map_magic_page, &features, 1); | ||
480 | |||
481 | /* Quick self-test to see if the mapping works */ | ||
482 | if (__get_user(tmp, (u32*)KVM_MAGIC_PAGE)) { | ||
483 | kvm_patching_worked = false; | ||
484 | return; | ||
485 | } | ||
486 | |||
487 | /* Now loop through all code and find instructions */ | ||
488 | start = (void*)_stext; | ||
489 | end = (void*)_etext; | ||
490 | |||
491 | for (p = start; p < end; p++) | ||
492 | kvm_check_ins(p, features); | ||
493 | |||
494 | printk(KERN_INFO "KVM: Live patching for a fast VM %s\n", | ||
495 | kvm_patching_worked ? "worked" : "failed"); | ||
496 | } | ||
497 | |||
498 | unsigned long kvm_hypercall(unsigned long *in, | ||
499 | unsigned long *out, | ||
500 | unsigned long nr) | ||
501 | { | ||
502 | unsigned long register r0 asm("r0"); | ||
503 | unsigned long register r3 asm("r3") = in[0]; | ||
504 | unsigned long register r4 asm("r4") = in[1]; | ||
505 | unsigned long register r5 asm("r5") = in[2]; | ||
506 | unsigned long register r6 asm("r6") = in[3]; | ||
507 | unsigned long register r7 asm("r7") = in[4]; | ||
508 | unsigned long register r8 asm("r8") = in[5]; | ||
509 | unsigned long register r9 asm("r9") = in[6]; | ||
510 | unsigned long register r10 asm("r10") = in[7]; | ||
511 | unsigned long register r11 asm("r11") = nr; | ||
512 | unsigned long register r12 asm("r12"); | ||
513 | |||
514 | asm volatile("bl kvm_hypercall_start" | ||
515 | : "=r"(r0), "=r"(r3), "=r"(r4), "=r"(r5), "=r"(r6), | ||
516 | "=r"(r7), "=r"(r8), "=r"(r9), "=r"(r10), "=r"(r11), | ||
517 | "=r"(r12) | ||
518 | : "r"(r3), "r"(r4), "r"(r5), "r"(r6), "r"(r7), "r"(r8), | ||
519 | "r"(r9), "r"(r10), "r"(r11) | ||
520 | : "memory", "cc", "xer", "ctr", "lr"); | ||
521 | |||
522 | out[0] = r4; | ||
523 | out[1] = r5; | ||
524 | out[2] = r6; | ||
525 | out[3] = r7; | ||
526 | out[4] = r8; | ||
527 | out[5] = r9; | ||
528 | out[6] = r10; | ||
529 | out[7] = r11; | ||
530 | |||
531 | return r3; | ||
532 | } | ||
533 | EXPORT_SYMBOL_GPL(kvm_hypercall); | ||
534 | |||
535 | static int kvm_para_setup(void) | ||
536 | { | ||
537 | extern u32 kvm_hypercall_start; | ||
538 | struct device_node *hyper_node; | ||
539 | u32 *insts; | ||
540 | int len, i; | ||
541 | |||
542 | hyper_node = of_find_node_by_path("/hypervisor"); | ||
543 | if (!hyper_node) | ||
544 | return -1; | ||
545 | |||
546 | insts = (u32*)of_get_property(hyper_node, "hcall-instructions", &len); | ||
547 | if (len % 4) | ||
548 | return -1; | ||
549 | if (len > (4 * 4)) | ||
550 | return -1; | ||
551 | |||
552 | for (i = 0; i < (len / 4); i++) | ||
553 | kvm_patch_ins(&(&kvm_hypercall_start)[i], insts[i]); | ||
554 | |||
555 | return 0; | ||
556 | } | ||
557 | |||
558 | static __init void kvm_free_tmp(void) | ||
559 | { | ||
560 | unsigned long start, end; | ||
561 | |||
562 | start = (ulong)&kvm_tmp[kvm_tmp_index + (PAGE_SIZE - 1)] & PAGE_MASK; | ||
563 | end = (ulong)&kvm_tmp[ARRAY_SIZE(kvm_tmp)] & PAGE_MASK; | ||
564 | |||
565 | /* Free the tmp space we don't need */ | ||
566 | for (; start < end; start += PAGE_SIZE) { | ||
567 | ClearPageReserved(virt_to_page(start)); | ||
568 | init_page_count(virt_to_page(start)); | ||
569 | free_page(start); | ||
570 | totalram_pages++; | ||
571 | } | ||
572 | } | ||
573 | |||
574 | static int __init kvm_guest_init(void) | ||
575 | { | ||
576 | if (!kvm_para_available()) | ||
577 | goto free_tmp; | ||
578 | |||
579 | if (kvm_para_setup()) | ||
580 | goto free_tmp; | ||
581 | |||
582 | if (kvm_para_has_feature(KVM_FEATURE_MAGIC_PAGE)) | ||
583 | kvm_use_magic_page(); | ||
584 | |||
585 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
586 | /* Enable napping */ | ||
587 | powersave_nap = 1; | ||
588 | #endif | ||
589 | |||
590 | free_tmp: | ||
591 | kvm_free_tmp(); | ||
592 | |||
593 | return 0; | ||
594 | } | ||
595 | |||
596 | postcore_initcall(kvm_guest_init); | ||
diff --git a/arch/powerpc/kernel/kvm_emul.S b/arch/powerpc/kernel/kvm_emul.S new file mode 100644 index 000000000000..f2b1b2523e61 --- /dev/null +++ b/arch/powerpc/kernel/kvm_emul.S | |||
@@ -0,0 +1,302 @@ | |||
1 | /* | ||
2 | * This program is free software; you can redistribute it and/or modify | ||
3 | * it under the terms of the GNU General Public License, version 2, as | ||
4 | * published by the Free Software Foundation. | ||
5 | * | ||
6 | * This program is distributed in the hope that it will be useful, | ||
7 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
8 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
9 | * GNU General Public License for more details. | ||
10 | * | ||
11 | * You should have received a copy of the GNU General Public License | ||
12 | * along with this program; if not, write to the Free Software | ||
13 | * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
14 | * | ||
15 | * Copyright SUSE Linux Products GmbH 2010 | ||
16 | * | ||
17 | * Authors: Alexander Graf <agraf@suse.de> | ||
18 | */ | ||
19 | |||
20 | #include <asm/ppc_asm.h> | ||
21 | #include <asm/kvm_asm.h> | ||
22 | #include <asm/reg.h> | ||
23 | #include <asm/page.h> | ||
24 | #include <asm/asm-offsets.h> | ||
25 | |||
26 | /* Hypercall entry point. Will be patched with device tree instructions. */ | ||
27 | |||
28 | .global kvm_hypercall_start | ||
29 | kvm_hypercall_start: | ||
30 | li r3, -1 | ||
31 | nop | ||
32 | nop | ||
33 | nop | ||
34 | blr | ||
35 | |||
36 | #define KVM_MAGIC_PAGE (-4096) | ||
37 | |||
38 | #ifdef CONFIG_64BIT | ||
39 | #define LL64(reg, offs, reg2) ld reg, (offs)(reg2) | ||
40 | #define STL64(reg, offs, reg2) std reg, (offs)(reg2) | ||
41 | #else | ||
42 | #define LL64(reg, offs, reg2) lwz reg, (offs + 4)(reg2) | ||
43 | #define STL64(reg, offs, reg2) stw reg, (offs + 4)(reg2) | ||
44 | #endif | ||
45 | |||
46 | #define SCRATCH_SAVE \ | ||
47 | /* Enable critical section. We are critical if \ | ||
48 | shared->critical == r1 */ \ | ||
49 | STL64(r1, KVM_MAGIC_PAGE + KVM_MAGIC_CRITICAL, 0); \ | ||
50 | \ | ||
51 | /* Save state */ \ | ||
52 | PPC_STL r31, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH1)(0); \ | ||
53 | PPC_STL r30, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH2)(0); \ | ||
54 | mfcr r31; \ | ||
55 | stw r31, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH3)(0); | ||
56 | |||
57 | #define SCRATCH_RESTORE \ | ||
58 | /* Restore state */ \ | ||
59 | PPC_LL r31, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH1)(0); \ | ||
60 | lwz r30, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH3)(0); \ | ||
61 | mtcr r30; \ | ||
62 | PPC_LL r30, (KVM_MAGIC_PAGE + KVM_MAGIC_SCRATCH2)(0); \ | ||
63 | \ | ||
64 | /* Disable critical section. We are critical if \ | ||
65 | shared->critical == r1 and r2 is always != r1 */ \ | ||
66 | STL64(r2, KVM_MAGIC_PAGE + KVM_MAGIC_CRITICAL, 0); | ||
67 | |||
68 | .global kvm_emulate_mtmsrd | ||
69 | kvm_emulate_mtmsrd: | ||
70 | |||
71 | SCRATCH_SAVE | ||
72 | |||
73 | /* Put MSR & ~(MSR_EE|MSR_RI) in r31 */ | ||
74 | LL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0) | ||
75 | lis r30, (~(MSR_EE | MSR_RI))@h | ||
76 | ori r30, r30, (~(MSR_EE | MSR_RI))@l | ||
77 | and r31, r31, r30 | ||
78 | |||
79 | /* OR the register's (MSR_EE|MSR_RI) on MSR */ | ||
80 | kvm_emulate_mtmsrd_reg: | ||
81 | ori r30, r0, 0 | ||
82 | andi. r30, r30, (MSR_EE|MSR_RI) | ||
83 | or r31, r31, r30 | ||
84 | |||
85 | /* Put MSR back into magic page */ | ||
86 | STL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0) | ||
87 | |||
88 | /* Check if we have to fetch an interrupt */ | ||
89 | lwz r31, (KVM_MAGIC_PAGE + KVM_MAGIC_INT)(0) | ||
90 | cmpwi r31, 0 | ||
91 | beq+ no_check | ||
92 | |||
93 | /* Check if we may trigger an interrupt */ | ||
94 | andi. r30, r30, MSR_EE | ||
95 | beq no_check | ||
96 | |||
97 | SCRATCH_RESTORE | ||
98 | |||
99 | /* Nag hypervisor */ | ||
100 | kvm_emulate_mtmsrd_orig_ins: | ||
101 | tlbsync | ||
102 | |||
103 | b kvm_emulate_mtmsrd_branch | ||
104 | |||
105 | no_check: | ||
106 | |||
107 | SCRATCH_RESTORE | ||
108 | |||
109 | /* Go back to caller */ | ||
110 | kvm_emulate_mtmsrd_branch: | ||
111 | b . | ||
112 | kvm_emulate_mtmsrd_end: | ||
113 | |||
114 | .global kvm_emulate_mtmsrd_branch_offs | ||
115 | kvm_emulate_mtmsrd_branch_offs: | ||
116 | .long (kvm_emulate_mtmsrd_branch - kvm_emulate_mtmsrd) / 4 | ||
117 | |||
118 | .global kvm_emulate_mtmsrd_reg_offs | ||
119 | kvm_emulate_mtmsrd_reg_offs: | ||
120 | .long (kvm_emulate_mtmsrd_reg - kvm_emulate_mtmsrd) / 4 | ||
121 | |||
122 | .global kvm_emulate_mtmsrd_orig_ins_offs | ||
123 | kvm_emulate_mtmsrd_orig_ins_offs: | ||
124 | .long (kvm_emulate_mtmsrd_orig_ins - kvm_emulate_mtmsrd) / 4 | ||
125 | |||
126 | .global kvm_emulate_mtmsrd_len | ||
127 | kvm_emulate_mtmsrd_len: | ||
128 | .long (kvm_emulate_mtmsrd_end - kvm_emulate_mtmsrd) / 4 | ||
129 | |||
130 | |||
131 | #define MSR_SAFE_BITS (MSR_EE | MSR_CE | MSR_ME | MSR_RI) | ||
132 | #define MSR_CRITICAL_BITS ~MSR_SAFE_BITS | ||
133 | |||
134 | .global kvm_emulate_mtmsr | ||
135 | kvm_emulate_mtmsr: | ||
136 | |||
137 | SCRATCH_SAVE | ||
138 | |||
139 | /* Fetch old MSR in r31 */ | ||
140 | LL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0) | ||
141 | |||
142 | /* Find the changed bits between old and new MSR */ | ||
143 | kvm_emulate_mtmsr_reg1: | ||
144 | ori r30, r0, 0 | ||
145 | xor r31, r30, r31 | ||
146 | |||
147 | /* Check if we need to really do mtmsr */ | ||
148 | LOAD_REG_IMMEDIATE(r30, MSR_CRITICAL_BITS) | ||
149 | and. r31, r31, r30 | ||
150 | |||
151 | /* No critical bits changed? Maybe we can stay in the guest. */ | ||
152 | beq maybe_stay_in_guest | ||
153 | |||
154 | do_mtmsr: | ||
155 | |||
156 | SCRATCH_RESTORE | ||
157 | |||
158 | /* Just fire off the mtmsr if it's critical */ | ||
159 | kvm_emulate_mtmsr_orig_ins: | ||
160 | mtmsr r0 | ||
161 | |||
162 | b kvm_emulate_mtmsr_branch | ||
163 | |||
164 | maybe_stay_in_guest: | ||
165 | |||
166 | /* Get the target register in r30 */ | ||
167 | kvm_emulate_mtmsr_reg2: | ||
168 | ori r30, r0, 0 | ||
169 | |||
170 | /* Check if we have to fetch an interrupt */ | ||
171 | lwz r31, (KVM_MAGIC_PAGE + KVM_MAGIC_INT)(0) | ||
172 | cmpwi r31, 0 | ||
173 | beq+ no_mtmsr | ||
174 | |||
175 | /* Check if we may trigger an interrupt */ | ||
176 | andi. r31, r30, MSR_EE | ||
177 | beq no_mtmsr | ||
178 | |||
179 | b do_mtmsr | ||
180 | |||
181 | no_mtmsr: | ||
182 | |||
183 | /* Put MSR into magic page because we don't call mtmsr */ | ||
184 | STL64(r30, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0) | ||
185 | |||
186 | SCRATCH_RESTORE | ||
187 | |||
188 | /* Go back to caller */ | ||
189 | kvm_emulate_mtmsr_branch: | ||
190 | b . | ||
191 | kvm_emulate_mtmsr_end: | ||
192 | |||
193 | .global kvm_emulate_mtmsr_branch_offs | ||
194 | kvm_emulate_mtmsr_branch_offs: | ||
195 | .long (kvm_emulate_mtmsr_branch - kvm_emulate_mtmsr) / 4 | ||
196 | |||
197 | .global kvm_emulate_mtmsr_reg1_offs | ||
198 | kvm_emulate_mtmsr_reg1_offs: | ||
199 | .long (kvm_emulate_mtmsr_reg1 - kvm_emulate_mtmsr) / 4 | ||
200 | |||
201 | .global kvm_emulate_mtmsr_reg2_offs | ||
202 | kvm_emulate_mtmsr_reg2_offs: | ||
203 | .long (kvm_emulate_mtmsr_reg2 - kvm_emulate_mtmsr) / 4 | ||
204 | |||
205 | .global kvm_emulate_mtmsr_orig_ins_offs | ||
206 | kvm_emulate_mtmsr_orig_ins_offs: | ||
207 | .long (kvm_emulate_mtmsr_orig_ins - kvm_emulate_mtmsr) / 4 | ||
208 | |||
209 | .global kvm_emulate_mtmsr_len | ||
210 | kvm_emulate_mtmsr_len: | ||
211 | .long (kvm_emulate_mtmsr_end - kvm_emulate_mtmsr) / 4 | ||
212 | |||
213 | |||
214 | |||
215 | .global kvm_emulate_wrteei | ||
216 | kvm_emulate_wrteei: | ||
217 | |||
218 | SCRATCH_SAVE | ||
219 | |||
220 | /* Fetch old MSR in r31 */ | ||
221 | LL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0) | ||
222 | |||
223 | /* Remove MSR_EE from old MSR */ | ||
224 | li r30, 0 | ||
225 | ori r30, r30, MSR_EE | ||
226 | andc r31, r31, r30 | ||
227 | |||
228 | /* OR new MSR_EE onto the old MSR */ | ||
229 | kvm_emulate_wrteei_ee: | ||
230 | ori r31, r31, 0 | ||
231 | |||
232 | /* Write new MSR value back */ | ||
233 | STL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0) | ||
234 | |||
235 | SCRATCH_RESTORE | ||
236 | |||
237 | /* Go back to caller */ | ||
238 | kvm_emulate_wrteei_branch: | ||
239 | b . | ||
240 | kvm_emulate_wrteei_end: | ||
241 | |||
242 | .global kvm_emulate_wrteei_branch_offs | ||
243 | kvm_emulate_wrteei_branch_offs: | ||
244 | .long (kvm_emulate_wrteei_branch - kvm_emulate_wrteei) / 4 | ||
245 | |||
246 | .global kvm_emulate_wrteei_ee_offs | ||
247 | kvm_emulate_wrteei_ee_offs: | ||
248 | .long (kvm_emulate_wrteei_ee - kvm_emulate_wrteei) / 4 | ||
249 | |||
250 | .global kvm_emulate_wrteei_len | ||
251 | kvm_emulate_wrteei_len: | ||
252 | .long (kvm_emulate_wrteei_end - kvm_emulate_wrteei) / 4 | ||
253 | |||
254 | |||
255 | .global kvm_emulate_mtsrin | ||
256 | kvm_emulate_mtsrin: | ||
257 | |||
258 | SCRATCH_SAVE | ||
259 | |||
260 | LL64(r31, KVM_MAGIC_PAGE + KVM_MAGIC_MSR, 0) | ||
261 | andi. r31, r31, MSR_DR | MSR_IR | ||
262 | beq kvm_emulate_mtsrin_reg1 | ||
263 | |||
264 | SCRATCH_RESTORE | ||
265 | |||
266 | kvm_emulate_mtsrin_orig_ins: | ||
267 | nop | ||
268 | b kvm_emulate_mtsrin_branch | ||
269 | |||
270 | kvm_emulate_mtsrin_reg1: | ||
271 | /* rX >> 26 */ | ||
272 | rlwinm r30,r0,6,26,29 | ||
273 | |||
274 | kvm_emulate_mtsrin_reg2: | ||
275 | stw r0, (KVM_MAGIC_PAGE + KVM_MAGIC_SR)(r30) | ||
276 | |||
277 | SCRATCH_RESTORE | ||
278 | |||
279 | /* Go back to caller */ | ||
280 | kvm_emulate_mtsrin_branch: | ||
281 | b . | ||
282 | kvm_emulate_mtsrin_end: | ||
283 | |||
284 | .global kvm_emulate_mtsrin_branch_offs | ||
285 | kvm_emulate_mtsrin_branch_offs: | ||
286 | .long (kvm_emulate_mtsrin_branch - kvm_emulate_mtsrin) / 4 | ||
287 | |||
288 | .global kvm_emulate_mtsrin_reg1_offs | ||
289 | kvm_emulate_mtsrin_reg1_offs: | ||
290 | .long (kvm_emulate_mtsrin_reg1 - kvm_emulate_mtsrin) / 4 | ||
291 | |||
292 | .global kvm_emulate_mtsrin_reg2_offs | ||
293 | kvm_emulate_mtsrin_reg2_offs: | ||
294 | .long (kvm_emulate_mtsrin_reg2 - kvm_emulate_mtsrin) / 4 | ||
295 | |||
296 | .global kvm_emulate_mtsrin_orig_ins_offs | ||
297 | kvm_emulate_mtsrin_orig_ins_offs: | ||
298 | .long (kvm_emulate_mtsrin_orig_ins - kvm_emulate_mtsrin) / 4 | ||
299 | |||
300 | .global kvm_emulate_mtsrin_len | ||
301 | kvm_emulate_mtsrin_len: | ||
302 | .long (kvm_emulate_mtsrin_end - kvm_emulate_mtsrin) / 4 | ||
diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c index c1fd0f9658fd..c834757bebc0 100644 --- a/arch/powerpc/kernel/legacy_serial.c +++ b/arch/powerpc/kernel/legacy_serial.c | |||
@@ -52,14 +52,14 @@ static int __init add_legacy_port(struct device_node *np, int want_index, | |||
52 | phys_addr_t taddr, unsigned long irq, | 52 | phys_addr_t taddr, unsigned long irq, |
53 | upf_t flags, int irq_check_parent) | 53 | upf_t flags, int irq_check_parent) |
54 | { | 54 | { |
55 | const u32 *clk, *spd; | 55 | const __be32 *clk, *spd; |
56 | u32 clock = BASE_BAUD * 16; | 56 | u32 clock = BASE_BAUD * 16; |
57 | int index; | 57 | int index; |
58 | 58 | ||
59 | /* get clock freq. if present */ | 59 | /* get clock freq. if present */ |
60 | clk = of_get_property(np, "clock-frequency", NULL); | 60 | clk = of_get_property(np, "clock-frequency", NULL); |
61 | if (clk && *clk) | 61 | if (clk && *clk) |
62 | clock = *clk; | 62 | clock = be32_to_cpup(clk); |
63 | 63 | ||
64 | /* get default speed if present */ | 64 | /* get default speed if present */ |
65 | spd = of_get_property(np, "current-speed", NULL); | 65 | spd = of_get_property(np, "current-speed", NULL); |
@@ -109,7 +109,7 @@ static int __init add_legacy_port(struct device_node *np, int want_index, | |||
109 | legacy_serial_infos[index].taddr = taddr; | 109 | legacy_serial_infos[index].taddr = taddr; |
110 | legacy_serial_infos[index].np = of_node_get(np); | 110 | legacy_serial_infos[index].np = of_node_get(np); |
111 | legacy_serial_infos[index].clock = clock; | 111 | legacy_serial_infos[index].clock = clock; |
112 | legacy_serial_infos[index].speed = spd ? *spd : 0; | 112 | legacy_serial_infos[index].speed = spd ? be32_to_cpup(spd) : 0; |
113 | legacy_serial_infos[index].irq_check_parent = irq_check_parent; | 113 | legacy_serial_infos[index].irq_check_parent = irq_check_parent; |
114 | 114 | ||
115 | printk(KERN_DEBUG "Found legacy serial port %d for %s\n", | 115 | printk(KERN_DEBUG "Found legacy serial port %d for %s\n", |
@@ -168,7 +168,7 @@ static int __init add_legacy_soc_port(struct device_node *np, | |||
168 | static int __init add_legacy_isa_port(struct device_node *np, | 168 | static int __init add_legacy_isa_port(struct device_node *np, |
169 | struct device_node *isa_brg) | 169 | struct device_node *isa_brg) |
170 | { | 170 | { |
171 | const u32 *reg; | 171 | const __be32 *reg; |
172 | const char *typep; | 172 | const char *typep; |
173 | int index = -1; | 173 | int index = -1; |
174 | u64 taddr; | 174 | u64 taddr; |
@@ -181,7 +181,7 @@ static int __init add_legacy_isa_port(struct device_node *np, | |||
181 | return -1; | 181 | return -1; |
182 | 182 | ||
183 | /* Verify it's an IO port, we don't support anything else */ | 183 | /* Verify it's an IO port, we don't support anything else */ |
184 | if (!(reg[0] & 0x00000001)) | 184 | if (!(be32_to_cpu(reg[0]) & 0x00000001)) |
185 | return -1; | 185 | return -1; |
186 | 186 | ||
187 | /* Now look for an "ibm,aix-loc" property that gives us ordering | 187 | /* Now look for an "ibm,aix-loc" property that gives us ordering |
@@ -202,7 +202,7 @@ static int __init add_legacy_isa_port(struct device_node *np, | |||
202 | taddr = 0; | 202 | taddr = 0; |
203 | 203 | ||
204 | /* Add port, irq will be dealt with later */ | 204 | /* Add port, irq will be dealt with later */ |
205 | return add_legacy_port(np, index, UPIO_PORT, reg[1], taddr, | 205 | return add_legacy_port(np, index, UPIO_PORT, be32_to_cpu(reg[1]), taddr, |
206 | NO_IRQ, UPF_BOOT_AUTOCONF, 0); | 206 | NO_IRQ, UPF_BOOT_AUTOCONF, 0); |
207 | 207 | ||
208 | } | 208 | } |
@@ -251,9 +251,9 @@ static int __init add_legacy_pci_port(struct device_node *np, | |||
251 | * we get to their "reg" property | 251 | * we get to their "reg" property |
252 | */ | 252 | */ |
253 | if (np != pci_dev) { | 253 | if (np != pci_dev) { |
254 | const u32 *reg = of_get_property(np, "reg", NULL); | 254 | const __be32 *reg = of_get_property(np, "reg", NULL); |
255 | if (reg && (*reg < 4)) | 255 | if (reg && (be32_to_cpup(reg) < 4)) |
256 | index = lindex = *reg; | 256 | index = lindex = be32_to_cpup(reg); |
257 | } | 257 | } |
258 | 258 | ||
259 | /* Local index means it's the Nth port in the PCI chip. Unfortunately | 259 | /* Local index means it's the Nth port in the PCI chip. Unfortunately |
@@ -507,7 +507,7 @@ static int __init check_legacy_serial_console(void) | |||
507 | struct device_node *prom_stdout = NULL; | 507 | struct device_node *prom_stdout = NULL; |
508 | int i, speed = 0, offset = 0; | 508 | int i, speed = 0, offset = 0; |
509 | const char *name; | 509 | const char *name; |
510 | const u32 *spd; | 510 | const __be32 *spd; |
511 | 511 | ||
512 | DBG(" -> check_legacy_serial_console()\n"); | 512 | DBG(" -> check_legacy_serial_console()\n"); |
513 | 513 | ||
@@ -547,7 +547,7 @@ static int __init check_legacy_serial_console(void) | |||
547 | } | 547 | } |
548 | spd = of_get_property(prom_stdout, "current-speed", NULL); | 548 | spd = of_get_property(prom_stdout, "current-speed", NULL); |
549 | if (spd) | 549 | if (spd) |
550 | speed = *spd; | 550 | speed = be32_to_cpup(spd); |
551 | 551 | ||
552 | if (strcmp(name, "serial") != 0) | 552 | if (strcmp(name, "serial") != 0) |
553 | goto not_found; | 553 | goto not_found; |
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c index 50362b6ef6e9..16468362ad57 100644 --- a/arch/powerpc/kernel/lparcfg.c +++ b/arch/powerpc/kernel/lparcfg.c | |||
@@ -56,7 +56,7 @@ static unsigned long get_purr(void) | |||
56 | 56 | ||
57 | for_each_possible_cpu(cpu) { | 57 | for_each_possible_cpu(cpu) { |
58 | if (firmware_has_feature(FW_FEATURE_ISERIES)) | 58 | if (firmware_has_feature(FW_FEATURE_ISERIES)) |
59 | sum_purr += lppaca[cpu].emulated_time_base; | 59 | sum_purr += lppaca_of(cpu).emulated_time_base; |
60 | else { | 60 | else { |
61 | struct cpu_usage *cu; | 61 | struct cpu_usage *cu; |
62 | 62 | ||
@@ -263,7 +263,7 @@ static void parse_ppp_data(struct seq_file *m) | |||
263 | ppp_data.active_system_procs); | 263 | ppp_data.active_system_procs); |
264 | 264 | ||
265 | /* pool related entries are apropriate for shared configs */ | 265 | /* pool related entries are apropriate for shared configs */ |
266 | if (lppaca[0].shared_proc) { | 266 | if (lppaca_of(0).shared_proc) { |
267 | unsigned long pool_idle_time, pool_procs; | 267 | unsigned long pool_idle_time, pool_procs; |
268 | 268 | ||
269 | seq_printf(m, "pool=%d\n", ppp_data.pool_num); | 269 | seq_printf(m, "pool=%d\n", ppp_data.pool_num); |
@@ -460,8 +460,8 @@ static void pseries_cmo_data(struct seq_file *m) | |||
460 | return; | 460 | return; |
461 | 461 | ||
462 | for_each_possible_cpu(cpu) { | 462 | for_each_possible_cpu(cpu) { |
463 | cmo_faults += lppaca[cpu].cmo_faults; | 463 | cmo_faults += lppaca_of(cpu).cmo_faults; |
464 | cmo_fault_time += lppaca[cpu].cmo_fault_time; | 464 | cmo_fault_time += lppaca_of(cpu).cmo_fault_time; |
465 | } | 465 | } |
466 | 466 | ||
467 | seq_printf(m, "cmo_faults=%lu\n", cmo_faults); | 467 | seq_printf(m, "cmo_faults=%lu\n", cmo_faults); |
@@ -479,8 +479,8 @@ static void splpar_dispatch_data(struct seq_file *m) | |||
479 | unsigned long dispatch_dispersions = 0; | 479 | unsigned long dispatch_dispersions = 0; |
480 | 480 | ||
481 | for_each_possible_cpu(cpu) { | 481 | for_each_possible_cpu(cpu) { |
482 | dispatches += lppaca[cpu].yield_count; | 482 | dispatches += lppaca_of(cpu).yield_count; |
483 | dispatch_dispersions += lppaca[cpu].dispersion_count; | 483 | dispatch_dispersions += lppaca_of(cpu).dispersion_count; |
484 | } | 484 | } |
485 | 485 | ||
486 | seq_printf(m, "dispatches=%lu\n", dispatches); | 486 | seq_printf(m, "dispatches=%lu\n", dispatches); |
@@ -545,7 +545,7 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v) | |||
545 | seq_printf(m, "partition_potential_processors=%d\n", | 545 | seq_printf(m, "partition_potential_processors=%d\n", |
546 | partition_potential_processors); | 546 | partition_potential_processors); |
547 | 547 | ||
548 | seq_printf(m, "shared_processor_mode=%d\n", lppaca[0].shared_proc); | 548 | seq_printf(m, "shared_processor_mode=%d\n", lppaca_of(0).shared_proc); |
549 | 549 | ||
550 | seq_printf(m, "slb_size=%d\n", mmu_slb_size); | 550 | seq_printf(m, "slb_size=%d\n", mmu_slb_size); |
551 | 551 | ||
@@ -780,6 +780,7 @@ static const struct file_operations lparcfg_fops = { | |||
780 | .write = lparcfg_write, | 780 | .write = lparcfg_write, |
781 | .open = lparcfg_open, | 781 | .open = lparcfg_open, |
782 | .release = single_release, | 782 | .release = single_release, |
783 | .llseek = seq_lseek, | ||
783 | }; | 784 | }; |
784 | 785 | ||
785 | static int __init lparcfg_init(void) | 786 | static int __init lparcfg_init(void) |
diff --git a/arch/powerpc/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec.c index dd6c141f1662..df7e20c191cd 100644 --- a/arch/powerpc/kernel/machine_kexec.c +++ b/arch/powerpc/kernel/machine_kexec.c | |||
@@ -14,10 +14,34 @@ | |||
14 | #include <linux/threads.h> | 14 | #include <linux/threads.h> |
15 | #include <linux/memblock.h> | 15 | #include <linux/memblock.h> |
16 | #include <linux/of.h> | 16 | #include <linux/of.h> |
17 | #include <linux/irq.h> | ||
18 | |||
17 | #include <asm/machdep.h> | 19 | #include <asm/machdep.h> |
18 | #include <asm/prom.h> | 20 | #include <asm/prom.h> |
19 | #include <asm/sections.h> | 21 | #include <asm/sections.h> |
20 | 22 | ||
23 | void machine_kexec_mask_interrupts(void) { | ||
24 | unsigned int i; | ||
25 | |||
26 | for_each_irq(i) { | ||
27 | struct irq_desc *desc = irq_to_desc(i); | ||
28 | |||
29 | if (!desc || !desc->chip) | ||
30 | continue; | ||
31 | |||
32 | if (desc->chip->eoi && | ||
33 | desc->status & IRQ_INPROGRESS) | ||
34 | desc->chip->eoi(i); | ||
35 | |||
36 | if (desc->chip->mask) | ||
37 | desc->chip->mask(i); | ||
38 | |||
39 | if (desc->chip->disable && | ||
40 | !(desc->status & IRQ_DISABLED)) | ||
41 | desc->chip->disable(i); | ||
42 | } | ||
43 | } | ||
44 | |||
21 | void machine_crash_shutdown(struct pt_regs *regs) | 45 | void machine_crash_shutdown(struct pt_regs *regs) |
22 | { | 46 | { |
23 | if (ppc_md.machine_crash_shutdown) | 47 | if (ppc_md.machine_crash_shutdown) |
diff --git a/arch/powerpc/kernel/machine_kexec_32.c b/arch/powerpc/kernel/machine_kexec_32.c index ae63a964b858..e63f2e7d2efb 100644 --- a/arch/powerpc/kernel/machine_kexec_32.c +++ b/arch/powerpc/kernel/machine_kexec_32.c | |||
@@ -39,6 +39,10 @@ void default_machine_kexec(struct kimage *image) | |||
39 | /* Interrupts aren't acceptable while we reboot */ | 39 | /* Interrupts aren't acceptable while we reboot */ |
40 | local_irq_disable(); | 40 | local_irq_disable(); |
41 | 41 | ||
42 | /* mask each interrupt so we are in a more sane state for the | ||
43 | * kexec kernel */ | ||
44 | machine_kexec_mask_interrupts(); | ||
45 | |||
42 | page_list = image->head; | 46 | page_list = image->head; |
43 | 47 | ||
44 | /* we need both effective and real address here */ | 48 | /* we need both effective and real address here */ |
diff --git a/arch/powerpc/kernel/module.c b/arch/powerpc/kernel/module.c index 477c663e0140..49cee9df225b 100644 --- a/arch/powerpc/kernel/module.c +++ b/arch/powerpc/kernel/module.c | |||
@@ -63,11 +63,6 @@ int module_finalize(const Elf_Ehdr *hdr, | |||
63 | const Elf_Shdr *sechdrs, struct module *me) | 63 | const Elf_Shdr *sechdrs, struct module *me) |
64 | { | 64 | { |
65 | const Elf_Shdr *sect; | 65 | const Elf_Shdr *sect; |
66 | int err; | ||
67 | |||
68 | err = module_bug_finalize(hdr, sechdrs, me); | ||
69 | if (err) | ||
70 | return err; | ||
71 | 66 | ||
72 | /* Apply feature fixups */ | 67 | /* Apply feature fixups */ |
73 | sect = find_section(hdr, sechdrs, "__ftr_fixup"); | 68 | sect = find_section(hdr, sechdrs, "__ftr_fixup"); |
@@ -101,5 +96,4 @@ int module_finalize(const Elf_Ehdr *hdr, | |||
101 | 96 | ||
102 | void module_arch_cleanup(struct module *mod) | 97 | void module_arch_cleanup(struct module *mod) |
103 | { | 98 | { |
104 | module_bug_cleanup(mod); | ||
105 | } | 99 | } |
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c index d0a26f1770fe..ebf9846f3c3b 100644 --- a/arch/powerpc/kernel/paca.c +++ b/arch/powerpc/kernel/paca.c | |||
@@ -27,6 +27,20 @@ extern unsigned long __toc_start; | |||
27 | #ifdef CONFIG_PPC_BOOK3S | 27 | #ifdef CONFIG_PPC_BOOK3S |
28 | 28 | ||
29 | /* | 29 | /* |
30 | * We only have to have statically allocated lppaca structs on | ||
31 | * legacy iSeries, which supports at most 64 cpus. | ||
32 | */ | ||
33 | #ifdef CONFIG_PPC_ISERIES | ||
34 | #if NR_CPUS < 64 | ||
35 | #define NR_LPPACAS NR_CPUS | ||
36 | #else | ||
37 | #define NR_LPPACAS 64 | ||
38 | #endif | ||
39 | #else /* not iSeries */ | ||
40 | #define NR_LPPACAS 1 | ||
41 | #endif | ||
42 | |||
43 | /* | ||
30 | * The structure which the hypervisor knows about - this structure | 44 | * The structure which the hypervisor knows about - this structure |
31 | * should not cross a page boundary. The vpa_init/register_vpa call | 45 | * should not cross a page boundary. The vpa_init/register_vpa call |
32 | * is now known to fail if the lppaca structure crosses a page | 46 | * is now known to fail if the lppaca structure crosses a page |
@@ -36,7 +50,7 @@ extern unsigned long __toc_start; | |||
36 | * will suffice to ensure that it doesn't cross a page boundary. | 50 | * will suffice to ensure that it doesn't cross a page boundary. |
37 | */ | 51 | */ |
38 | struct lppaca lppaca[] = { | 52 | struct lppaca lppaca[] = { |
39 | [0 ... (NR_CPUS-1)] = { | 53 | [0 ... (NR_LPPACAS-1)] = { |
40 | .desc = 0xd397d781, /* "LpPa" */ | 54 | .desc = 0xd397d781, /* "LpPa" */ |
41 | .size = sizeof(struct lppaca), | 55 | .size = sizeof(struct lppaca), |
42 | .dyn_proc_status = 2, | 56 | .dyn_proc_status = 2, |
@@ -49,6 +63,54 @@ struct lppaca lppaca[] = { | |||
49 | }, | 63 | }, |
50 | }; | 64 | }; |
51 | 65 | ||
66 | static struct lppaca *extra_lppacas; | ||
67 | static long __initdata lppaca_size; | ||
68 | |||
69 | static void allocate_lppacas(int nr_cpus, unsigned long limit) | ||
70 | { | ||
71 | if (nr_cpus <= NR_LPPACAS) | ||
72 | return; | ||
73 | |||
74 | lppaca_size = PAGE_ALIGN(sizeof(struct lppaca) * | ||
75 | (nr_cpus - NR_LPPACAS)); | ||
76 | extra_lppacas = __va(memblock_alloc_base(lppaca_size, | ||
77 | PAGE_SIZE, limit)); | ||
78 | } | ||
79 | |||
80 | static struct lppaca *new_lppaca(int cpu) | ||
81 | { | ||
82 | struct lppaca *lp; | ||
83 | |||
84 | if (cpu < NR_LPPACAS) | ||
85 | return &lppaca[cpu]; | ||
86 | |||
87 | lp = extra_lppacas + (cpu - NR_LPPACAS); | ||
88 | *lp = lppaca[0]; | ||
89 | |||
90 | return lp; | ||
91 | } | ||
92 | |||
93 | static void free_lppacas(void) | ||
94 | { | ||
95 | long new_size = 0, nr; | ||
96 | |||
97 | if (!lppaca_size) | ||
98 | return; | ||
99 | nr = num_possible_cpus() - NR_LPPACAS; | ||
100 | if (nr > 0) | ||
101 | new_size = PAGE_ALIGN(nr * sizeof(struct lppaca)); | ||
102 | if (new_size >= lppaca_size) | ||
103 | return; | ||
104 | |||
105 | memblock_free(__pa(extra_lppacas) + new_size, lppaca_size - new_size); | ||
106 | lppaca_size = new_size; | ||
107 | } | ||
108 | |||
109 | #else | ||
110 | |||
111 | static inline void allocate_lppacas(int nr_cpus, unsigned long limit) { } | ||
112 | static inline void free_lppacas(void) { } | ||
113 | |||
52 | #endif /* CONFIG_PPC_BOOK3S */ | 114 | #endif /* CONFIG_PPC_BOOK3S */ |
53 | 115 | ||
54 | #ifdef CONFIG_PPC_STD_MMU_64 | 116 | #ifdef CONFIG_PPC_STD_MMU_64 |
@@ -88,7 +150,7 @@ void __init initialise_paca(struct paca_struct *new_paca, int cpu) | |||
88 | unsigned long kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL; | 150 | unsigned long kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL; |
89 | 151 | ||
90 | #ifdef CONFIG_PPC_BOOK3S | 152 | #ifdef CONFIG_PPC_BOOK3S |
91 | new_paca->lppaca_ptr = &lppaca[cpu]; | 153 | new_paca->lppaca_ptr = new_lppaca(cpu); |
92 | #else | 154 | #else |
93 | new_paca->kernel_pgd = swapper_pg_dir; | 155 | new_paca->kernel_pgd = swapper_pg_dir; |
94 | #endif | 156 | #endif |
@@ -127,7 +189,7 @@ void __init allocate_pacas(void) | |||
127 | * the first segment. On iSeries they must be within the area mapped | 189 | * the first segment. On iSeries they must be within the area mapped |
128 | * by the HV, which is HvPagesToMap * HVPAGESIZE bytes. | 190 | * by the HV, which is HvPagesToMap * HVPAGESIZE bytes. |
129 | */ | 191 | */ |
130 | limit = min(0x10000000ULL, memblock.rmo_size); | 192 | limit = min(0x10000000ULL, ppc64_rma_size); |
131 | if (firmware_has_feature(FW_FEATURE_ISERIES)) | 193 | if (firmware_has_feature(FW_FEATURE_ISERIES)) |
132 | limit = min(limit, HvPagesToMap * HVPAGESIZE); | 194 | limit = min(limit, HvPagesToMap * HVPAGESIZE); |
133 | 195 | ||
@@ -144,6 +206,8 @@ void __init allocate_pacas(void) | |||
144 | printk(KERN_DEBUG "Allocated %u bytes for %d pacas at %p\n", | 206 | printk(KERN_DEBUG "Allocated %u bytes for %d pacas at %p\n", |
145 | paca_size, nr_cpus, paca); | 207 | paca_size, nr_cpus, paca); |
146 | 208 | ||
209 | allocate_lppacas(nr_cpus, limit); | ||
210 | |||
147 | /* Can't use for_each_*_cpu, as they aren't functional yet */ | 211 | /* Can't use for_each_*_cpu, as they aren't functional yet */ |
148 | for (cpu = 0; cpu < nr_cpus; cpu++) | 212 | for (cpu = 0; cpu < nr_cpus; cpu++) |
149 | initialise_paca(&paca[cpu], cpu); | 213 | initialise_paca(&paca[cpu], cpu); |
@@ -164,4 +228,6 @@ void __init free_unused_pacas(void) | |||
164 | paca_size - new_size); | 228 | paca_size - new_size); |
165 | 229 | ||
166 | paca_size = new_size; | 230 | paca_size = new_size; |
231 | |||
232 | free_lppacas(); | ||
167 | } | 233 | } |
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 9021c4ad4bbd..10a44e68ef11 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c | |||
@@ -1090,8 +1090,6 @@ void __devinit pcibios_setup_bus_devices(struct pci_bus *bus) | |||
1090 | bus->number, bus->self ? pci_name(bus->self) : "PHB"); | 1090 | bus->number, bus->self ? pci_name(bus->self) : "PHB"); |
1091 | 1091 | ||
1092 | list_for_each_entry(dev, &bus->devices, bus_list) { | 1092 | list_for_each_entry(dev, &bus->devices, bus_list) { |
1093 | struct dev_archdata *sd = &dev->dev.archdata; | ||
1094 | |||
1095 | /* Cardbus can call us to add new devices to a bus, so ignore | 1093 | /* Cardbus can call us to add new devices to a bus, so ignore |
1096 | * those who are already fully discovered | 1094 | * those who are already fully discovered |
1097 | */ | 1095 | */ |
@@ -1107,7 +1105,7 @@ void __devinit pcibios_setup_bus_devices(struct pci_bus *bus) | |||
1107 | set_dev_node(&dev->dev, pcibus_to_node(dev->bus)); | 1105 | set_dev_node(&dev->dev, pcibus_to_node(dev->bus)); |
1108 | 1106 | ||
1109 | /* Hook up default DMA ops */ | 1107 | /* Hook up default DMA ops */ |
1110 | sd->dma_ops = pci_dma_ops; | 1108 | set_dma_ops(&dev->dev, pci_dma_ops); |
1111 | set_dma_offset(&dev->dev, PCI_DRAM_OFFSET); | 1109 | set_dma_offset(&dev->dev, PCI_DRAM_OFFSET); |
1112 | 1110 | ||
1113 | /* Additional platform DMA/iommu setup */ | 1111 | /* Additional platform DMA/iommu setup */ |
diff --git a/arch/powerpc/kernel/perf_callchain.c b/arch/powerpc/kernel/perf_callchain.c index 95ad9dad298e..d05ae4204bbf 100644 --- a/arch/powerpc/kernel/perf_callchain.c +++ b/arch/powerpc/kernel/perf_callchain.c | |||
@@ -23,18 +23,6 @@ | |||
23 | #include "ppc32.h" | 23 | #include "ppc32.h" |
24 | #endif | 24 | #endif |
25 | 25 | ||
26 | /* | ||
27 | * Store another value in a callchain_entry. | ||
28 | */ | ||
29 | static inline void callchain_store(struct perf_callchain_entry *entry, u64 ip) | ||
30 | { | ||
31 | unsigned int nr = entry->nr; | ||
32 | |||
33 | if (nr < PERF_MAX_STACK_DEPTH) { | ||
34 | entry->ip[nr] = ip; | ||
35 | entry->nr = nr + 1; | ||
36 | } | ||
37 | } | ||
38 | 26 | ||
39 | /* | 27 | /* |
40 | * Is sp valid as the address of the next kernel stack frame after prev_sp? | 28 | * Is sp valid as the address of the next kernel stack frame after prev_sp? |
@@ -58,8 +46,8 @@ static int valid_next_sp(unsigned long sp, unsigned long prev_sp) | |||
58 | return 0; | 46 | return 0; |
59 | } | 47 | } |
60 | 48 | ||
61 | static void perf_callchain_kernel(struct pt_regs *regs, | 49 | void |
62 | struct perf_callchain_entry *entry) | 50 | perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs) |
63 | { | 51 | { |
64 | unsigned long sp, next_sp; | 52 | unsigned long sp, next_sp; |
65 | unsigned long next_ip; | 53 | unsigned long next_ip; |
@@ -69,8 +57,7 @@ static void perf_callchain_kernel(struct pt_regs *regs, | |||
69 | 57 | ||
70 | lr = regs->link; | 58 | lr = regs->link; |
71 | sp = regs->gpr[1]; | 59 | sp = regs->gpr[1]; |
72 | callchain_store(entry, PERF_CONTEXT_KERNEL); | 60 | perf_callchain_store(entry, regs->nip); |
73 | callchain_store(entry, regs->nip); | ||
74 | 61 | ||
75 | if (!validate_sp(sp, current, STACK_FRAME_OVERHEAD)) | 62 | if (!validate_sp(sp, current, STACK_FRAME_OVERHEAD)) |
76 | return; | 63 | return; |
@@ -89,7 +76,7 @@ static void perf_callchain_kernel(struct pt_regs *regs, | |||
89 | next_ip = regs->nip; | 76 | next_ip = regs->nip; |
90 | lr = regs->link; | 77 | lr = regs->link; |
91 | level = 0; | 78 | level = 0; |
92 | callchain_store(entry, PERF_CONTEXT_KERNEL); | 79 | perf_callchain_store(entry, PERF_CONTEXT_KERNEL); |
93 | 80 | ||
94 | } else { | 81 | } else { |
95 | if (level == 0) | 82 | if (level == 0) |
@@ -111,7 +98,7 @@ static void perf_callchain_kernel(struct pt_regs *regs, | |||
111 | ++level; | 98 | ++level; |
112 | } | 99 | } |
113 | 100 | ||
114 | callchain_store(entry, next_ip); | 101 | perf_callchain_store(entry, next_ip); |
115 | if (!valid_next_sp(next_sp, sp)) | 102 | if (!valid_next_sp(next_sp, sp)) |
116 | return; | 103 | return; |
117 | sp = next_sp; | 104 | sp = next_sp; |
@@ -233,8 +220,8 @@ static int sane_signal_64_frame(unsigned long sp) | |||
233 | puc == (unsigned long) &sf->uc; | 220 | puc == (unsigned long) &sf->uc; |
234 | } | 221 | } |
235 | 222 | ||
236 | static void perf_callchain_user_64(struct pt_regs *regs, | 223 | static void perf_callchain_user_64(struct perf_callchain_entry *entry, |
237 | struct perf_callchain_entry *entry) | 224 | struct pt_regs *regs) |
238 | { | 225 | { |
239 | unsigned long sp, next_sp; | 226 | unsigned long sp, next_sp; |
240 | unsigned long next_ip; | 227 | unsigned long next_ip; |
@@ -246,8 +233,7 @@ static void perf_callchain_user_64(struct pt_regs *regs, | |||
246 | next_ip = regs->nip; | 233 | next_ip = regs->nip; |
247 | lr = regs->link; | 234 | lr = regs->link; |
248 | sp = regs->gpr[1]; | 235 | sp = regs->gpr[1]; |
249 | callchain_store(entry, PERF_CONTEXT_USER); | 236 | perf_callchain_store(entry, next_ip); |
250 | callchain_store(entry, next_ip); | ||
251 | 237 | ||
252 | for (;;) { | 238 | for (;;) { |
253 | fp = (unsigned long __user *) sp; | 239 | fp = (unsigned long __user *) sp; |
@@ -276,14 +262,14 @@ static void perf_callchain_user_64(struct pt_regs *regs, | |||
276 | read_user_stack_64(&uregs[PT_R1], &sp)) | 262 | read_user_stack_64(&uregs[PT_R1], &sp)) |
277 | return; | 263 | return; |
278 | level = 0; | 264 | level = 0; |
279 | callchain_store(entry, PERF_CONTEXT_USER); | 265 | perf_callchain_store(entry, PERF_CONTEXT_USER); |
280 | callchain_store(entry, next_ip); | 266 | perf_callchain_store(entry, next_ip); |
281 | continue; | 267 | continue; |
282 | } | 268 | } |
283 | 269 | ||
284 | if (level == 0) | 270 | if (level == 0) |
285 | next_ip = lr; | 271 | next_ip = lr; |
286 | callchain_store(entry, next_ip); | 272 | perf_callchain_store(entry, next_ip); |
287 | ++level; | 273 | ++level; |
288 | sp = next_sp; | 274 | sp = next_sp; |
289 | } | 275 | } |
@@ -315,8 +301,8 @@ static int read_user_stack_32(unsigned int __user *ptr, unsigned int *ret) | |||
315 | return __get_user_inatomic(*ret, ptr); | 301 | return __get_user_inatomic(*ret, ptr); |
316 | } | 302 | } |
317 | 303 | ||
318 | static inline void perf_callchain_user_64(struct pt_regs *regs, | 304 | static inline void perf_callchain_user_64(struct perf_callchain_entry *entry, |
319 | struct perf_callchain_entry *entry) | 305 | struct pt_regs *regs) |
320 | { | 306 | { |
321 | } | 307 | } |
322 | 308 | ||
@@ -435,8 +421,8 @@ static unsigned int __user *signal_frame_32_regs(unsigned int sp, | |||
435 | return mctx->mc_gregs; | 421 | return mctx->mc_gregs; |
436 | } | 422 | } |
437 | 423 | ||
438 | static void perf_callchain_user_32(struct pt_regs *regs, | 424 | static void perf_callchain_user_32(struct perf_callchain_entry *entry, |
439 | struct perf_callchain_entry *entry) | 425 | struct pt_regs *regs) |
440 | { | 426 | { |
441 | unsigned int sp, next_sp; | 427 | unsigned int sp, next_sp; |
442 | unsigned int next_ip; | 428 | unsigned int next_ip; |
@@ -447,8 +433,7 @@ static void perf_callchain_user_32(struct pt_regs *regs, | |||
447 | next_ip = regs->nip; | 433 | next_ip = regs->nip; |
448 | lr = regs->link; | 434 | lr = regs->link; |
449 | sp = regs->gpr[1]; | 435 | sp = regs->gpr[1]; |
450 | callchain_store(entry, PERF_CONTEXT_USER); | 436 | perf_callchain_store(entry, next_ip); |
451 | callchain_store(entry, next_ip); | ||
452 | 437 | ||
453 | while (entry->nr < PERF_MAX_STACK_DEPTH) { | 438 | while (entry->nr < PERF_MAX_STACK_DEPTH) { |
454 | fp = (unsigned int __user *) (unsigned long) sp; | 439 | fp = (unsigned int __user *) (unsigned long) sp; |
@@ -470,45 +455,24 @@ static void perf_callchain_user_32(struct pt_regs *regs, | |||
470 | read_user_stack_32(&uregs[PT_R1], &sp)) | 455 | read_user_stack_32(&uregs[PT_R1], &sp)) |
471 | return; | 456 | return; |
472 | level = 0; | 457 | level = 0; |
473 | callchain_store(entry, PERF_CONTEXT_USER); | 458 | perf_callchain_store(entry, PERF_CONTEXT_USER); |
474 | callchain_store(entry, next_ip); | 459 | perf_callchain_store(entry, next_ip); |
475 | continue; | 460 | continue; |
476 | } | 461 | } |
477 | 462 | ||
478 | if (level == 0) | 463 | if (level == 0) |
479 | next_ip = lr; | 464 | next_ip = lr; |
480 | callchain_store(entry, next_ip); | 465 | perf_callchain_store(entry, next_ip); |
481 | ++level; | 466 | ++level; |
482 | sp = next_sp; | 467 | sp = next_sp; |
483 | } | 468 | } |
484 | } | 469 | } |
485 | 470 | ||
486 | /* | 471 | void |
487 | * Since we can't get PMU interrupts inside a PMU interrupt handler, | 472 | perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) |
488 | * we don't need separate irq and nmi entries here. | ||
489 | */ | ||
490 | static DEFINE_PER_CPU(struct perf_callchain_entry, cpu_perf_callchain); | ||
491 | |||
492 | struct perf_callchain_entry *perf_callchain(struct pt_regs *regs) | ||
493 | { | 473 | { |
494 | struct perf_callchain_entry *entry = &__get_cpu_var(cpu_perf_callchain); | 474 | if (current_is_64bit()) |
495 | 475 | perf_callchain_user_64(entry, regs); | |
496 | entry->nr = 0; | 476 | else |
497 | 477 | perf_callchain_user_32(entry, regs); | |
498 | if (!user_mode(regs)) { | ||
499 | perf_callchain_kernel(regs, entry); | ||
500 | if (current->mm) | ||
501 | regs = task_pt_regs(current); | ||
502 | else | ||
503 | regs = NULL; | ||
504 | } | ||
505 | |||
506 | if (regs) { | ||
507 | if (current_is_64bit()) | ||
508 | perf_callchain_user_64(regs, entry); | ||
509 | else | ||
510 | perf_callchain_user_32(regs, entry); | ||
511 | } | ||
512 | |||
513 | return entry; | ||
514 | } | 478 | } |
diff --git a/arch/powerpc/kernel/perf_event.c b/arch/powerpc/kernel/perf_event.c index d301a30445e0..3129c855933c 100644 --- a/arch/powerpc/kernel/perf_event.c +++ b/arch/powerpc/kernel/perf_event.c | |||
@@ -402,6 +402,9 @@ static void power_pmu_read(struct perf_event *event) | |||
402 | { | 402 | { |
403 | s64 val, delta, prev; | 403 | s64 val, delta, prev; |
404 | 404 | ||
405 | if (event->hw.state & PERF_HES_STOPPED) | ||
406 | return; | ||
407 | |||
405 | if (!event->hw.idx) | 408 | if (!event->hw.idx) |
406 | return; | 409 | return; |
407 | /* | 410 | /* |
@@ -517,7 +520,7 @@ static void write_mmcr0(struct cpu_hw_events *cpuhw, unsigned long mmcr0) | |||
517 | * Disable all events to prevent PMU interrupts and to allow | 520 | * Disable all events to prevent PMU interrupts and to allow |
518 | * events to be added or removed. | 521 | * events to be added or removed. |
519 | */ | 522 | */ |
520 | void hw_perf_disable(void) | 523 | static void power_pmu_disable(struct pmu *pmu) |
521 | { | 524 | { |
522 | struct cpu_hw_events *cpuhw; | 525 | struct cpu_hw_events *cpuhw; |
523 | unsigned long flags; | 526 | unsigned long flags; |
@@ -565,7 +568,7 @@ void hw_perf_disable(void) | |||
565 | * If we were previously disabled and events were added, then | 568 | * If we were previously disabled and events were added, then |
566 | * put the new config on the PMU. | 569 | * put the new config on the PMU. |
567 | */ | 570 | */ |
568 | void hw_perf_enable(void) | 571 | static void power_pmu_enable(struct pmu *pmu) |
569 | { | 572 | { |
570 | struct perf_event *event; | 573 | struct perf_event *event; |
571 | struct cpu_hw_events *cpuhw; | 574 | struct cpu_hw_events *cpuhw; |
@@ -672,6 +675,8 @@ void hw_perf_enable(void) | |||
672 | } | 675 | } |
673 | local64_set(&event->hw.prev_count, val); | 676 | local64_set(&event->hw.prev_count, val); |
674 | event->hw.idx = idx; | 677 | event->hw.idx = idx; |
678 | if (event->hw.state & PERF_HES_STOPPED) | ||
679 | val = 0; | ||
675 | write_pmc(idx, val); | 680 | write_pmc(idx, val); |
676 | perf_event_update_userpage(event); | 681 | perf_event_update_userpage(event); |
677 | } | 682 | } |
@@ -727,7 +732,7 @@ static int collect_events(struct perf_event *group, int max_count, | |||
727 | * re-enable the PMU in order to get hw_perf_enable to do the | 732 | * re-enable the PMU in order to get hw_perf_enable to do the |
728 | * actual work of reconfiguring the PMU. | 733 | * actual work of reconfiguring the PMU. |
729 | */ | 734 | */ |
730 | static int power_pmu_enable(struct perf_event *event) | 735 | static int power_pmu_add(struct perf_event *event, int ef_flags) |
731 | { | 736 | { |
732 | struct cpu_hw_events *cpuhw; | 737 | struct cpu_hw_events *cpuhw; |
733 | unsigned long flags; | 738 | unsigned long flags; |
@@ -735,7 +740,7 @@ static int power_pmu_enable(struct perf_event *event) | |||
735 | int ret = -EAGAIN; | 740 | int ret = -EAGAIN; |
736 | 741 | ||
737 | local_irq_save(flags); | 742 | local_irq_save(flags); |
738 | perf_disable(); | 743 | perf_pmu_disable(event->pmu); |
739 | 744 | ||
740 | /* | 745 | /* |
741 | * Add the event to the list (if there is room) | 746 | * Add the event to the list (if there is room) |
@@ -749,6 +754,9 @@ static int power_pmu_enable(struct perf_event *event) | |||
749 | cpuhw->events[n0] = event->hw.config; | 754 | cpuhw->events[n0] = event->hw.config; |
750 | cpuhw->flags[n0] = event->hw.event_base; | 755 | cpuhw->flags[n0] = event->hw.event_base; |
751 | 756 | ||
757 | if (!(ef_flags & PERF_EF_START)) | ||
758 | event->hw.state = PERF_HES_STOPPED | PERF_HES_UPTODATE; | ||
759 | |||
752 | /* | 760 | /* |
753 | * If group events scheduling transaction was started, | 761 | * If group events scheduling transaction was started, |
754 | * skip the schedulability test here, it will be peformed | 762 | * skip the schedulability test here, it will be peformed |
@@ -769,7 +777,7 @@ nocheck: | |||
769 | 777 | ||
770 | ret = 0; | 778 | ret = 0; |
771 | out: | 779 | out: |
772 | perf_enable(); | 780 | perf_pmu_enable(event->pmu); |
773 | local_irq_restore(flags); | 781 | local_irq_restore(flags); |
774 | return ret; | 782 | return ret; |
775 | } | 783 | } |
@@ -777,14 +785,14 @@ nocheck: | |||
777 | /* | 785 | /* |
778 | * Remove a event from the PMU. | 786 | * Remove a event from the PMU. |
779 | */ | 787 | */ |
780 | static void power_pmu_disable(struct perf_event *event) | 788 | static void power_pmu_del(struct perf_event *event, int ef_flags) |
781 | { | 789 | { |
782 | struct cpu_hw_events *cpuhw; | 790 | struct cpu_hw_events *cpuhw; |
783 | long i; | 791 | long i; |
784 | unsigned long flags; | 792 | unsigned long flags; |
785 | 793 | ||
786 | local_irq_save(flags); | 794 | local_irq_save(flags); |
787 | perf_disable(); | 795 | perf_pmu_disable(event->pmu); |
788 | 796 | ||
789 | power_pmu_read(event); | 797 | power_pmu_read(event); |
790 | 798 | ||
@@ -821,34 +829,60 @@ static void power_pmu_disable(struct perf_event *event) | |||
821 | cpuhw->mmcr[0] &= ~(MMCR0_PMXE | MMCR0_FCECE); | 829 | cpuhw->mmcr[0] &= ~(MMCR0_PMXE | MMCR0_FCECE); |
822 | } | 830 | } |
823 | 831 | ||
824 | perf_enable(); | 832 | perf_pmu_enable(event->pmu); |
825 | local_irq_restore(flags); | 833 | local_irq_restore(flags); |
826 | } | 834 | } |
827 | 835 | ||
828 | /* | 836 | /* |
829 | * Re-enable interrupts on a event after they were throttled | 837 | * POWER-PMU does not support disabling individual counters, hence |
830 | * because they were coming too fast. | 838 | * program their cycle counter to their max value and ignore the interrupts. |
831 | */ | 839 | */ |
832 | static void power_pmu_unthrottle(struct perf_event *event) | 840 | |
841 | static void power_pmu_start(struct perf_event *event, int ef_flags) | ||
842 | { | ||
843 | unsigned long flags; | ||
844 | s64 left; | ||
845 | |||
846 | if (!event->hw.idx || !event->hw.sample_period) | ||
847 | return; | ||
848 | |||
849 | if (!(event->hw.state & PERF_HES_STOPPED)) | ||
850 | return; | ||
851 | |||
852 | if (ef_flags & PERF_EF_RELOAD) | ||
853 | WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE)); | ||
854 | |||
855 | local_irq_save(flags); | ||
856 | perf_pmu_disable(event->pmu); | ||
857 | |||
858 | event->hw.state = 0; | ||
859 | left = local64_read(&event->hw.period_left); | ||
860 | write_pmc(event->hw.idx, left); | ||
861 | |||
862 | perf_event_update_userpage(event); | ||
863 | perf_pmu_enable(event->pmu); | ||
864 | local_irq_restore(flags); | ||
865 | } | ||
866 | |||
867 | static void power_pmu_stop(struct perf_event *event, int ef_flags) | ||
833 | { | 868 | { |
834 | s64 val, left; | ||
835 | unsigned long flags; | 869 | unsigned long flags; |
836 | 870 | ||
837 | if (!event->hw.idx || !event->hw.sample_period) | 871 | if (!event->hw.idx || !event->hw.sample_period) |
838 | return; | 872 | return; |
873 | |||
874 | if (event->hw.state & PERF_HES_STOPPED) | ||
875 | return; | ||
876 | |||
839 | local_irq_save(flags); | 877 | local_irq_save(flags); |
840 | perf_disable(); | 878 | perf_pmu_disable(event->pmu); |
879 | |||
841 | power_pmu_read(event); | 880 | power_pmu_read(event); |
842 | left = event->hw.sample_period; | 881 | event->hw.state |= PERF_HES_STOPPED | PERF_HES_UPTODATE; |
843 | event->hw.last_period = left; | 882 | write_pmc(event->hw.idx, 0); |
844 | val = 0; | 883 | |
845 | if (left < 0x80000000L) | ||
846 | val = 0x80000000L - left; | ||
847 | write_pmc(event->hw.idx, val); | ||
848 | local64_set(&event->hw.prev_count, val); | ||
849 | local64_set(&event->hw.period_left, left); | ||
850 | perf_event_update_userpage(event); | 884 | perf_event_update_userpage(event); |
851 | perf_enable(); | 885 | perf_pmu_enable(event->pmu); |
852 | local_irq_restore(flags); | 886 | local_irq_restore(flags); |
853 | } | 887 | } |
854 | 888 | ||
@@ -857,10 +891,11 @@ static void power_pmu_unthrottle(struct perf_event *event) | |||
857 | * Set the flag to make pmu::enable() not perform the | 891 | * Set the flag to make pmu::enable() not perform the |
858 | * schedulability test, it will be performed at commit time | 892 | * schedulability test, it will be performed at commit time |
859 | */ | 893 | */ |
860 | void power_pmu_start_txn(const struct pmu *pmu) | 894 | void power_pmu_start_txn(struct pmu *pmu) |
861 | { | 895 | { |
862 | struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events); | 896 | struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events); |
863 | 897 | ||
898 | perf_pmu_disable(pmu); | ||
864 | cpuhw->group_flag |= PERF_EVENT_TXN; | 899 | cpuhw->group_flag |= PERF_EVENT_TXN; |
865 | cpuhw->n_txn_start = cpuhw->n_events; | 900 | cpuhw->n_txn_start = cpuhw->n_events; |
866 | } | 901 | } |
@@ -870,11 +905,12 @@ void power_pmu_start_txn(const struct pmu *pmu) | |||
870 | * Clear the flag and pmu::enable() will perform the | 905 | * Clear the flag and pmu::enable() will perform the |
871 | * schedulability test. | 906 | * schedulability test. |
872 | */ | 907 | */ |
873 | void power_pmu_cancel_txn(const struct pmu *pmu) | 908 | void power_pmu_cancel_txn(struct pmu *pmu) |
874 | { | 909 | { |
875 | struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events); | 910 | struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events); |
876 | 911 | ||
877 | cpuhw->group_flag &= ~PERF_EVENT_TXN; | 912 | cpuhw->group_flag &= ~PERF_EVENT_TXN; |
913 | perf_pmu_enable(pmu); | ||
878 | } | 914 | } |
879 | 915 | ||
880 | /* | 916 | /* |
@@ -882,7 +918,7 @@ void power_pmu_cancel_txn(const struct pmu *pmu) | |||
882 | * Perform the group schedulability test as a whole | 918 | * Perform the group schedulability test as a whole |
883 | * Return 0 if success | 919 | * Return 0 if success |
884 | */ | 920 | */ |
885 | int power_pmu_commit_txn(const struct pmu *pmu) | 921 | int power_pmu_commit_txn(struct pmu *pmu) |
886 | { | 922 | { |
887 | struct cpu_hw_events *cpuhw; | 923 | struct cpu_hw_events *cpuhw; |
888 | long i, n; | 924 | long i, n; |
@@ -901,19 +937,10 @@ int power_pmu_commit_txn(const struct pmu *pmu) | |||
901 | cpuhw->event[i]->hw.config = cpuhw->events[i]; | 937 | cpuhw->event[i]->hw.config = cpuhw->events[i]; |
902 | 938 | ||
903 | cpuhw->group_flag &= ~PERF_EVENT_TXN; | 939 | cpuhw->group_flag &= ~PERF_EVENT_TXN; |
940 | perf_pmu_enable(pmu); | ||
904 | return 0; | 941 | return 0; |
905 | } | 942 | } |
906 | 943 | ||
907 | struct pmu power_pmu = { | ||
908 | .enable = power_pmu_enable, | ||
909 | .disable = power_pmu_disable, | ||
910 | .read = power_pmu_read, | ||
911 | .unthrottle = power_pmu_unthrottle, | ||
912 | .start_txn = power_pmu_start_txn, | ||
913 | .cancel_txn = power_pmu_cancel_txn, | ||
914 | .commit_txn = power_pmu_commit_txn, | ||
915 | }; | ||
916 | |||
917 | /* | 944 | /* |
918 | * Return 1 if we might be able to put event on a limited PMC, | 945 | * Return 1 if we might be able to put event on a limited PMC, |
919 | * or 0 if not. | 946 | * or 0 if not. |
@@ -1014,7 +1041,7 @@ static int hw_perf_cache_event(u64 config, u64 *eventp) | |||
1014 | return 0; | 1041 | return 0; |
1015 | } | 1042 | } |
1016 | 1043 | ||
1017 | const struct pmu *hw_perf_event_init(struct perf_event *event) | 1044 | static int power_pmu_event_init(struct perf_event *event) |
1018 | { | 1045 | { |
1019 | u64 ev; | 1046 | u64 ev; |
1020 | unsigned long flags; | 1047 | unsigned long flags; |
@@ -1026,25 +1053,27 @@ const struct pmu *hw_perf_event_init(struct perf_event *event) | |||
1026 | struct cpu_hw_events *cpuhw; | 1053 | struct cpu_hw_events *cpuhw; |
1027 | 1054 | ||
1028 | if (!ppmu) | 1055 | if (!ppmu) |
1029 | return ERR_PTR(-ENXIO); | 1056 | return -ENOENT; |
1057 | |||
1030 | switch (event->attr.type) { | 1058 | switch (event->attr.type) { |
1031 | case PERF_TYPE_HARDWARE: | 1059 | case PERF_TYPE_HARDWARE: |
1032 | ev = event->attr.config; | 1060 | ev = event->attr.config; |
1033 | if (ev >= ppmu->n_generic || ppmu->generic_events[ev] == 0) | 1061 | if (ev >= ppmu->n_generic || ppmu->generic_events[ev] == 0) |
1034 | return ERR_PTR(-EOPNOTSUPP); | 1062 | return -EOPNOTSUPP; |
1035 | ev = ppmu->generic_events[ev]; | 1063 | ev = ppmu->generic_events[ev]; |
1036 | break; | 1064 | break; |
1037 | case PERF_TYPE_HW_CACHE: | 1065 | case PERF_TYPE_HW_CACHE: |
1038 | err = hw_perf_cache_event(event->attr.config, &ev); | 1066 | err = hw_perf_cache_event(event->attr.config, &ev); |
1039 | if (err) | 1067 | if (err) |
1040 | return ERR_PTR(err); | 1068 | return err; |
1041 | break; | 1069 | break; |
1042 | case PERF_TYPE_RAW: | 1070 | case PERF_TYPE_RAW: |
1043 | ev = event->attr.config; | 1071 | ev = event->attr.config; |
1044 | break; | 1072 | break; |
1045 | default: | 1073 | default: |
1046 | return ERR_PTR(-EINVAL); | 1074 | return -ENOENT; |
1047 | } | 1075 | } |
1076 | |||
1048 | event->hw.config_base = ev; | 1077 | event->hw.config_base = ev; |
1049 | event->hw.idx = 0; | 1078 | event->hw.idx = 0; |
1050 | 1079 | ||
@@ -1063,7 +1092,7 @@ const struct pmu *hw_perf_event_init(struct perf_event *event) | |||
1063 | * XXX we should check if the task is an idle task. | 1092 | * XXX we should check if the task is an idle task. |
1064 | */ | 1093 | */ |
1065 | flags = 0; | 1094 | flags = 0; |
1066 | if (event->ctx->task) | 1095 | if (event->attach_state & PERF_ATTACH_TASK) |
1067 | flags |= PPMU_ONLY_COUNT_RUN; | 1096 | flags |= PPMU_ONLY_COUNT_RUN; |
1068 | 1097 | ||
1069 | /* | 1098 | /* |
@@ -1081,7 +1110,7 @@ const struct pmu *hw_perf_event_init(struct perf_event *event) | |||
1081 | */ | 1110 | */ |
1082 | ev = normal_pmc_alternative(ev, flags); | 1111 | ev = normal_pmc_alternative(ev, flags); |
1083 | if (!ev) | 1112 | if (!ev) |
1084 | return ERR_PTR(-EINVAL); | 1113 | return -EINVAL; |
1085 | } | 1114 | } |
1086 | } | 1115 | } |
1087 | 1116 | ||
@@ -1095,19 +1124,19 @@ const struct pmu *hw_perf_event_init(struct perf_event *event) | |||
1095 | n = collect_events(event->group_leader, ppmu->n_counter - 1, | 1124 | n = collect_events(event->group_leader, ppmu->n_counter - 1, |
1096 | ctrs, events, cflags); | 1125 | ctrs, events, cflags); |
1097 | if (n < 0) | 1126 | if (n < 0) |
1098 | return ERR_PTR(-EINVAL); | 1127 | return -EINVAL; |
1099 | } | 1128 | } |
1100 | events[n] = ev; | 1129 | events[n] = ev; |
1101 | ctrs[n] = event; | 1130 | ctrs[n] = event; |
1102 | cflags[n] = flags; | 1131 | cflags[n] = flags; |
1103 | if (check_excludes(ctrs, cflags, n, 1)) | 1132 | if (check_excludes(ctrs, cflags, n, 1)) |
1104 | return ERR_PTR(-EINVAL); | 1133 | return -EINVAL; |
1105 | 1134 | ||
1106 | cpuhw = &get_cpu_var(cpu_hw_events); | 1135 | cpuhw = &get_cpu_var(cpu_hw_events); |
1107 | err = power_check_constraints(cpuhw, events, cflags, n + 1); | 1136 | err = power_check_constraints(cpuhw, events, cflags, n + 1); |
1108 | put_cpu_var(cpu_hw_events); | 1137 | put_cpu_var(cpu_hw_events); |
1109 | if (err) | 1138 | if (err) |
1110 | return ERR_PTR(-EINVAL); | 1139 | return -EINVAL; |
1111 | 1140 | ||
1112 | event->hw.config = events[n]; | 1141 | event->hw.config = events[n]; |
1113 | event->hw.event_base = cflags[n]; | 1142 | event->hw.event_base = cflags[n]; |
@@ -1132,11 +1161,23 @@ const struct pmu *hw_perf_event_init(struct perf_event *event) | |||
1132 | } | 1161 | } |
1133 | event->destroy = hw_perf_event_destroy; | 1162 | event->destroy = hw_perf_event_destroy; |
1134 | 1163 | ||
1135 | if (err) | 1164 | return err; |
1136 | return ERR_PTR(err); | ||
1137 | return &power_pmu; | ||
1138 | } | 1165 | } |
1139 | 1166 | ||
1167 | struct pmu power_pmu = { | ||
1168 | .pmu_enable = power_pmu_enable, | ||
1169 | .pmu_disable = power_pmu_disable, | ||
1170 | .event_init = power_pmu_event_init, | ||
1171 | .add = power_pmu_add, | ||
1172 | .del = power_pmu_del, | ||
1173 | .start = power_pmu_start, | ||
1174 | .stop = power_pmu_stop, | ||
1175 | .read = power_pmu_read, | ||
1176 | .start_txn = power_pmu_start_txn, | ||
1177 | .cancel_txn = power_pmu_cancel_txn, | ||
1178 | .commit_txn = power_pmu_commit_txn, | ||
1179 | }; | ||
1180 | |||
1140 | /* | 1181 | /* |
1141 | * A counter has overflowed; update its count and record | 1182 | * A counter has overflowed; update its count and record |
1142 | * things if requested. Note that interrupts are hard-disabled | 1183 | * things if requested. Note that interrupts are hard-disabled |
@@ -1149,6 +1190,11 @@ static void record_and_restart(struct perf_event *event, unsigned long val, | |||
1149 | s64 prev, delta, left; | 1190 | s64 prev, delta, left; |
1150 | int record = 0; | 1191 | int record = 0; |
1151 | 1192 | ||
1193 | if (event->hw.state & PERF_HES_STOPPED) { | ||
1194 | write_pmc(event->hw.idx, 0); | ||
1195 | return; | ||
1196 | } | ||
1197 | |||
1152 | /* we don't have to worry about interrupts here */ | 1198 | /* we don't have to worry about interrupts here */ |
1153 | prev = local64_read(&event->hw.prev_count); | 1199 | prev = local64_read(&event->hw.prev_count); |
1154 | delta = (val - prev) & 0xfffffffful; | 1200 | delta = (val - prev) & 0xfffffffful; |
@@ -1171,6 +1217,11 @@ static void record_and_restart(struct perf_event *event, unsigned long val, | |||
1171 | val = 0x80000000LL - left; | 1217 | val = 0x80000000LL - left; |
1172 | } | 1218 | } |
1173 | 1219 | ||
1220 | write_pmc(event->hw.idx, val); | ||
1221 | local64_set(&event->hw.prev_count, val); | ||
1222 | local64_set(&event->hw.period_left, left); | ||
1223 | perf_event_update_userpage(event); | ||
1224 | |||
1174 | /* | 1225 | /* |
1175 | * Finally record data if requested. | 1226 | * Finally record data if requested. |
1176 | */ | 1227 | */ |
@@ -1183,23 +1234,9 @@ static void record_and_restart(struct perf_event *event, unsigned long val, | |||
1183 | if (event->attr.sample_type & PERF_SAMPLE_ADDR) | 1234 | if (event->attr.sample_type & PERF_SAMPLE_ADDR) |
1184 | perf_get_data_addr(regs, &data.addr); | 1235 | perf_get_data_addr(regs, &data.addr); |
1185 | 1236 | ||
1186 | if (perf_event_overflow(event, nmi, &data, regs)) { | 1237 | if (perf_event_overflow(event, nmi, &data, regs)) |
1187 | /* | 1238 | power_pmu_stop(event, 0); |
1188 | * Interrupts are coming too fast - throttle them | ||
1189 | * by setting the event to 0, so it will be | ||
1190 | * at least 2^30 cycles until the next interrupt | ||
1191 | * (assuming each event counts at most 2 counts | ||
1192 | * per cycle). | ||
1193 | */ | ||
1194 | val = 0; | ||
1195 | left = ~0ULL >> 1; | ||
1196 | } | ||
1197 | } | 1239 | } |
1198 | |||
1199 | write_pmc(event->hw.idx, val); | ||
1200 | local64_set(&event->hw.prev_count, val); | ||
1201 | local64_set(&event->hw.period_left, left); | ||
1202 | perf_event_update_userpage(event); | ||
1203 | } | 1240 | } |
1204 | 1241 | ||
1205 | /* | 1242 | /* |
@@ -1342,6 +1379,7 @@ int register_power_pmu(struct power_pmu *pmu) | |||
1342 | freeze_events_kernel = MMCR0_FCHV; | 1379 | freeze_events_kernel = MMCR0_FCHV; |
1343 | #endif /* CONFIG_PPC64 */ | 1380 | #endif /* CONFIG_PPC64 */ |
1344 | 1381 | ||
1382 | perf_pmu_register(&power_pmu); | ||
1345 | perf_cpu_notifier(power_pmu_notifier); | 1383 | perf_cpu_notifier(power_pmu_notifier); |
1346 | 1384 | ||
1347 | return 0; | 1385 | return 0; |
diff --git a/arch/powerpc/kernel/perf_event_fsl_emb.c b/arch/powerpc/kernel/perf_event_fsl_emb.c index 1ba45471ae43..7ecca59ddf77 100644 --- a/arch/powerpc/kernel/perf_event_fsl_emb.c +++ b/arch/powerpc/kernel/perf_event_fsl_emb.c | |||
@@ -156,6 +156,9 @@ static void fsl_emb_pmu_read(struct perf_event *event) | |||
156 | { | 156 | { |
157 | s64 val, delta, prev; | 157 | s64 val, delta, prev; |
158 | 158 | ||
159 | if (event->hw.state & PERF_HES_STOPPED) | ||
160 | return; | ||
161 | |||
159 | /* | 162 | /* |
160 | * Performance monitor interrupts come even when interrupts | 163 | * Performance monitor interrupts come even when interrupts |
161 | * are soft-disabled, as long as interrupts are hard-enabled. | 164 | * are soft-disabled, as long as interrupts are hard-enabled. |
@@ -177,7 +180,7 @@ static void fsl_emb_pmu_read(struct perf_event *event) | |||
177 | * Disable all events to prevent PMU interrupts and to allow | 180 | * Disable all events to prevent PMU interrupts and to allow |
178 | * events to be added or removed. | 181 | * events to be added or removed. |
179 | */ | 182 | */ |
180 | void hw_perf_disable(void) | 183 | static void fsl_emb_pmu_disable(struct pmu *pmu) |
181 | { | 184 | { |
182 | struct cpu_hw_events *cpuhw; | 185 | struct cpu_hw_events *cpuhw; |
183 | unsigned long flags; | 186 | unsigned long flags; |
@@ -216,7 +219,7 @@ void hw_perf_disable(void) | |||
216 | * If we were previously disabled and events were added, then | 219 | * If we were previously disabled and events were added, then |
217 | * put the new config on the PMU. | 220 | * put the new config on the PMU. |
218 | */ | 221 | */ |
219 | void hw_perf_enable(void) | 222 | static void fsl_emb_pmu_enable(struct pmu *pmu) |
220 | { | 223 | { |
221 | struct cpu_hw_events *cpuhw; | 224 | struct cpu_hw_events *cpuhw; |
222 | unsigned long flags; | 225 | unsigned long flags; |
@@ -262,8 +265,8 @@ static int collect_events(struct perf_event *group, int max_count, | |||
262 | return n; | 265 | return n; |
263 | } | 266 | } |
264 | 267 | ||
265 | /* perf must be disabled, context locked on entry */ | 268 | /* context locked on entry */ |
266 | static int fsl_emb_pmu_enable(struct perf_event *event) | 269 | static int fsl_emb_pmu_add(struct perf_event *event, int flags) |
267 | { | 270 | { |
268 | struct cpu_hw_events *cpuhw; | 271 | struct cpu_hw_events *cpuhw; |
269 | int ret = -EAGAIN; | 272 | int ret = -EAGAIN; |
@@ -271,6 +274,7 @@ static int fsl_emb_pmu_enable(struct perf_event *event) | |||
271 | u64 val; | 274 | u64 val; |
272 | int i; | 275 | int i; |
273 | 276 | ||
277 | perf_pmu_disable(event->pmu); | ||
274 | cpuhw = &get_cpu_var(cpu_hw_events); | 278 | cpuhw = &get_cpu_var(cpu_hw_events); |
275 | 279 | ||
276 | if (event->hw.config & FSL_EMB_EVENT_RESTRICTED) | 280 | if (event->hw.config & FSL_EMB_EVENT_RESTRICTED) |
@@ -301,6 +305,12 @@ static int fsl_emb_pmu_enable(struct perf_event *event) | |||
301 | val = 0x80000000L - left; | 305 | val = 0x80000000L - left; |
302 | } | 306 | } |
303 | local64_set(&event->hw.prev_count, val); | 307 | local64_set(&event->hw.prev_count, val); |
308 | |||
309 | if (!(flags & PERF_EF_START)) { | ||
310 | event->hw.state = PERF_HES_STOPPED | PERF_HES_UPTODATE; | ||
311 | val = 0; | ||
312 | } | ||
313 | |||
304 | write_pmc(i, val); | 314 | write_pmc(i, val); |
305 | perf_event_update_userpage(event); | 315 | perf_event_update_userpage(event); |
306 | 316 | ||
@@ -310,15 +320,17 @@ static int fsl_emb_pmu_enable(struct perf_event *event) | |||
310 | ret = 0; | 320 | ret = 0; |
311 | out: | 321 | out: |
312 | put_cpu_var(cpu_hw_events); | 322 | put_cpu_var(cpu_hw_events); |
323 | perf_pmu_enable(event->pmu); | ||
313 | return ret; | 324 | return ret; |
314 | } | 325 | } |
315 | 326 | ||
316 | /* perf must be disabled, context locked on entry */ | 327 | /* context locked on entry */ |
317 | static void fsl_emb_pmu_disable(struct perf_event *event) | 328 | static void fsl_emb_pmu_del(struct perf_event *event, int flags) |
318 | { | 329 | { |
319 | struct cpu_hw_events *cpuhw; | 330 | struct cpu_hw_events *cpuhw; |
320 | int i = event->hw.idx; | 331 | int i = event->hw.idx; |
321 | 332 | ||
333 | perf_pmu_disable(event->pmu); | ||
322 | if (i < 0) | 334 | if (i < 0) |
323 | goto out; | 335 | goto out; |
324 | 336 | ||
@@ -346,44 +358,57 @@ static void fsl_emb_pmu_disable(struct perf_event *event) | |||
346 | cpuhw->n_events--; | 358 | cpuhw->n_events--; |
347 | 359 | ||
348 | out: | 360 | out: |
361 | perf_pmu_enable(event->pmu); | ||
349 | put_cpu_var(cpu_hw_events); | 362 | put_cpu_var(cpu_hw_events); |
350 | } | 363 | } |
351 | 364 | ||
352 | /* | 365 | static void fsl_emb_pmu_start(struct perf_event *event, int ef_flags) |
353 | * Re-enable interrupts on a event after they were throttled | ||
354 | * because they were coming too fast. | ||
355 | * | ||
356 | * Context is locked on entry, but perf is not disabled. | ||
357 | */ | ||
358 | static void fsl_emb_pmu_unthrottle(struct perf_event *event) | ||
359 | { | 366 | { |
360 | s64 val, left; | ||
361 | unsigned long flags; | 367 | unsigned long flags; |
368 | s64 left; | ||
362 | 369 | ||
363 | if (event->hw.idx < 0 || !event->hw.sample_period) | 370 | if (event->hw.idx < 0 || !event->hw.sample_period) |
364 | return; | 371 | return; |
372 | |||
373 | if (!(event->hw.state & PERF_HES_STOPPED)) | ||
374 | return; | ||
375 | |||
376 | if (ef_flags & PERF_EF_RELOAD) | ||
377 | WARN_ON_ONCE(!(event->hw.state & PERF_HES_UPTODATE)); | ||
378 | |||
365 | local_irq_save(flags); | 379 | local_irq_save(flags); |
366 | perf_disable(); | 380 | perf_pmu_disable(event->pmu); |
367 | fsl_emb_pmu_read(event); | 381 | |
368 | left = event->hw.sample_period; | 382 | event->hw.state = 0; |
369 | event->hw.last_period = left; | 383 | left = local64_read(&event->hw.period_left); |
370 | val = 0; | 384 | write_pmc(event->hw.idx, left); |
371 | if (left < 0x80000000L) | 385 | |
372 | val = 0x80000000L - left; | ||
373 | write_pmc(event->hw.idx, val); | ||
374 | local64_set(&event->hw.prev_count, val); | ||
375 | local64_set(&event->hw.period_left, left); | ||
376 | perf_event_update_userpage(event); | 386 | perf_event_update_userpage(event); |
377 | perf_enable(); | 387 | perf_pmu_enable(event->pmu); |
378 | local_irq_restore(flags); | 388 | local_irq_restore(flags); |
379 | } | 389 | } |
380 | 390 | ||
381 | static struct pmu fsl_emb_pmu = { | 391 | static void fsl_emb_pmu_stop(struct perf_event *event, int ef_flags) |
382 | .enable = fsl_emb_pmu_enable, | 392 | { |
383 | .disable = fsl_emb_pmu_disable, | 393 | unsigned long flags; |
384 | .read = fsl_emb_pmu_read, | 394 | |
385 | .unthrottle = fsl_emb_pmu_unthrottle, | 395 | if (event->hw.idx < 0 || !event->hw.sample_period) |
386 | }; | 396 | return; |
397 | |||
398 | if (event->hw.state & PERF_HES_STOPPED) | ||
399 | return; | ||
400 | |||
401 | local_irq_save(flags); | ||
402 | perf_pmu_disable(event->pmu); | ||
403 | |||
404 | fsl_emb_pmu_read(event); | ||
405 | event->hw.state |= PERF_HES_STOPPED | PERF_HES_UPTODATE; | ||
406 | write_pmc(event->hw.idx, 0); | ||
407 | |||
408 | perf_event_update_userpage(event); | ||
409 | perf_pmu_enable(event->pmu); | ||
410 | local_irq_restore(flags); | ||
411 | } | ||
387 | 412 | ||
388 | /* | 413 | /* |
389 | * Release the PMU if this is the last perf_event. | 414 | * Release the PMU if this is the last perf_event. |
@@ -428,7 +453,7 @@ static int hw_perf_cache_event(u64 config, u64 *eventp) | |||
428 | return 0; | 453 | return 0; |
429 | } | 454 | } |
430 | 455 | ||
431 | const struct pmu *hw_perf_event_init(struct perf_event *event) | 456 | static int fsl_emb_pmu_event_init(struct perf_event *event) |
432 | { | 457 | { |
433 | u64 ev; | 458 | u64 ev; |
434 | struct perf_event *events[MAX_HWEVENTS]; | 459 | struct perf_event *events[MAX_HWEVENTS]; |
@@ -441,14 +466,14 @@ const struct pmu *hw_perf_event_init(struct perf_event *event) | |||
441 | case PERF_TYPE_HARDWARE: | 466 | case PERF_TYPE_HARDWARE: |
442 | ev = event->attr.config; | 467 | ev = event->attr.config; |
443 | if (ev >= ppmu->n_generic || ppmu->generic_events[ev] == 0) | 468 | if (ev >= ppmu->n_generic || ppmu->generic_events[ev] == 0) |
444 | return ERR_PTR(-EOPNOTSUPP); | 469 | return -EOPNOTSUPP; |
445 | ev = ppmu->generic_events[ev]; | 470 | ev = ppmu->generic_events[ev]; |
446 | break; | 471 | break; |
447 | 472 | ||
448 | case PERF_TYPE_HW_CACHE: | 473 | case PERF_TYPE_HW_CACHE: |
449 | err = hw_perf_cache_event(event->attr.config, &ev); | 474 | err = hw_perf_cache_event(event->attr.config, &ev); |
450 | if (err) | 475 | if (err) |
451 | return ERR_PTR(err); | 476 | return err; |
452 | break; | 477 | break; |
453 | 478 | ||
454 | case PERF_TYPE_RAW: | 479 | case PERF_TYPE_RAW: |
@@ -456,12 +481,12 @@ const struct pmu *hw_perf_event_init(struct perf_event *event) | |||
456 | break; | 481 | break; |
457 | 482 | ||
458 | default: | 483 | default: |
459 | return ERR_PTR(-EINVAL); | 484 | return -ENOENT; |
460 | } | 485 | } |
461 | 486 | ||
462 | event->hw.config = ppmu->xlate_event(ev); | 487 | event->hw.config = ppmu->xlate_event(ev); |
463 | if (!(event->hw.config & FSL_EMB_EVENT_VALID)) | 488 | if (!(event->hw.config & FSL_EMB_EVENT_VALID)) |
464 | return ERR_PTR(-EINVAL); | 489 | return -EINVAL; |
465 | 490 | ||
466 | /* | 491 | /* |
467 | * If this is in a group, check if it can go on with all the | 492 | * If this is in a group, check if it can go on with all the |
@@ -473,7 +498,7 @@ const struct pmu *hw_perf_event_init(struct perf_event *event) | |||
473 | n = collect_events(event->group_leader, | 498 | n = collect_events(event->group_leader, |
474 | ppmu->n_counter - 1, events); | 499 | ppmu->n_counter - 1, events); |
475 | if (n < 0) | 500 | if (n < 0) |
476 | return ERR_PTR(-EINVAL); | 501 | return -EINVAL; |
477 | } | 502 | } |
478 | 503 | ||
479 | if (event->hw.config & FSL_EMB_EVENT_RESTRICTED) { | 504 | if (event->hw.config & FSL_EMB_EVENT_RESTRICTED) { |
@@ -484,7 +509,7 @@ const struct pmu *hw_perf_event_init(struct perf_event *event) | |||
484 | } | 509 | } |
485 | 510 | ||
486 | if (num_restricted >= ppmu->n_restricted) | 511 | if (num_restricted >= ppmu->n_restricted) |
487 | return ERR_PTR(-EINVAL); | 512 | return -EINVAL; |
488 | } | 513 | } |
489 | 514 | ||
490 | event->hw.idx = -1; | 515 | event->hw.idx = -1; |
@@ -497,7 +522,7 @@ const struct pmu *hw_perf_event_init(struct perf_event *event) | |||
497 | if (event->attr.exclude_kernel) | 522 | if (event->attr.exclude_kernel) |
498 | event->hw.config_base |= PMLCA_FCS; | 523 | event->hw.config_base |= PMLCA_FCS; |
499 | if (event->attr.exclude_idle) | 524 | if (event->attr.exclude_idle) |
500 | return ERR_PTR(-ENOTSUPP); | 525 | return -ENOTSUPP; |
501 | 526 | ||
502 | event->hw.last_period = event->hw.sample_period; | 527 | event->hw.last_period = event->hw.sample_period; |
503 | local64_set(&event->hw.period_left, event->hw.last_period); | 528 | local64_set(&event->hw.period_left, event->hw.last_period); |
@@ -523,11 +548,20 @@ const struct pmu *hw_perf_event_init(struct perf_event *event) | |||
523 | } | 548 | } |
524 | event->destroy = hw_perf_event_destroy; | 549 | event->destroy = hw_perf_event_destroy; |
525 | 550 | ||
526 | if (err) | 551 | return err; |
527 | return ERR_PTR(err); | ||
528 | return &fsl_emb_pmu; | ||
529 | } | 552 | } |
530 | 553 | ||
554 | static struct pmu fsl_emb_pmu = { | ||
555 | .pmu_enable = fsl_emb_pmu_enable, | ||
556 | .pmu_disable = fsl_emb_pmu_disable, | ||
557 | .event_init = fsl_emb_pmu_event_init, | ||
558 | .add = fsl_emb_pmu_add, | ||
559 | .del = fsl_emb_pmu_del, | ||
560 | .start = fsl_emb_pmu_start, | ||
561 | .stop = fsl_emb_pmu_stop, | ||
562 | .read = fsl_emb_pmu_read, | ||
563 | }; | ||
564 | |||
531 | /* | 565 | /* |
532 | * A counter has overflowed; update its count and record | 566 | * A counter has overflowed; update its count and record |
533 | * things if requested. Note that interrupts are hard-disabled | 567 | * things if requested. Note that interrupts are hard-disabled |
@@ -540,6 +574,11 @@ static void record_and_restart(struct perf_event *event, unsigned long val, | |||
540 | s64 prev, delta, left; | 574 | s64 prev, delta, left; |
541 | int record = 0; | 575 | int record = 0; |
542 | 576 | ||
577 | if (event->hw.state & PERF_HES_STOPPED) { | ||
578 | write_pmc(event->hw.idx, 0); | ||
579 | return; | ||
580 | } | ||
581 | |||
543 | /* we don't have to worry about interrupts here */ | 582 | /* we don't have to worry about interrupts here */ |
544 | prev = local64_read(&event->hw.prev_count); | 583 | prev = local64_read(&event->hw.prev_count); |
545 | delta = (val - prev) & 0xfffffffful; | 584 | delta = (val - prev) & 0xfffffffful; |
@@ -562,6 +601,11 @@ static void record_and_restart(struct perf_event *event, unsigned long val, | |||
562 | val = 0x80000000LL - left; | 601 | val = 0x80000000LL - left; |
563 | } | 602 | } |
564 | 603 | ||
604 | write_pmc(event->hw.idx, val); | ||
605 | local64_set(&event->hw.prev_count, val); | ||
606 | local64_set(&event->hw.period_left, left); | ||
607 | perf_event_update_userpage(event); | ||
608 | |||
565 | /* | 609 | /* |
566 | * Finally record data if requested. | 610 | * Finally record data if requested. |
567 | */ | 611 | */ |
@@ -571,23 +615,9 @@ static void record_and_restart(struct perf_event *event, unsigned long val, | |||
571 | perf_sample_data_init(&data, 0); | 615 | perf_sample_data_init(&data, 0); |
572 | data.period = event->hw.last_period; | 616 | data.period = event->hw.last_period; |
573 | 617 | ||
574 | if (perf_event_overflow(event, nmi, &data, regs)) { | 618 | if (perf_event_overflow(event, nmi, &data, regs)) |
575 | /* | 619 | fsl_emb_pmu_stop(event, 0); |
576 | * Interrupts are coming too fast - throttle them | ||
577 | * by setting the event to 0, so it will be | ||
578 | * at least 2^30 cycles until the next interrupt | ||
579 | * (assuming each event counts at most 2 counts | ||
580 | * per cycle). | ||
581 | */ | ||
582 | val = 0; | ||
583 | left = ~0ULL >> 1; | ||
584 | } | ||
585 | } | 620 | } |
586 | |||
587 | write_pmc(event->hw.idx, val); | ||
588 | local64_set(&event->hw.prev_count, val); | ||
589 | local64_set(&event->hw.period_left, left); | ||
590 | perf_event_update_userpage(event); | ||
591 | } | 621 | } |
592 | 622 | ||
593 | static void perf_event_interrupt(struct pt_regs *regs) | 623 | static void perf_event_interrupt(struct pt_regs *regs) |
@@ -651,5 +681,7 @@ int register_fsl_emb_pmu(struct fsl_emb_pmu *pmu) | |||
651 | pr_info("%s performance monitor hardware support registered\n", | 681 | pr_info("%s performance monitor hardware support registered\n", |
652 | pmu->name); | 682 | pmu->name); |
653 | 683 | ||
684 | perf_pmu_register(&fsl_emb_pmu); | ||
685 | |||
654 | return 0; | 686 | return 0; |
655 | } | 687 | } |
diff --git a/arch/powerpc/kernel/ppc970-pmu.c b/arch/powerpc/kernel/ppc970-pmu.c index 8eff48e20dba..3fee685de4df 100644 --- a/arch/powerpc/kernel/ppc970-pmu.c +++ b/arch/powerpc/kernel/ppc970-pmu.c | |||
@@ -169,9 +169,11 @@ static int p970_marked_instr_event(u64 event) | |||
169 | switch (unit) { | 169 | switch (unit) { |
170 | case PM_VPU: | 170 | case PM_VPU: |
171 | mask = 0x4c; /* byte 0 bits 2,3,6 */ | 171 | mask = 0x4c; /* byte 0 bits 2,3,6 */ |
172 | break; | ||
172 | case PM_LSU0: | 173 | case PM_LSU0: |
173 | /* byte 2 bits 0,2,3,4,6; all of byte 1 */ | 174 | /* byte 2 bits 0,2,3,4,6; all of byte 1 */ |
174 | mask = 0x085dff00; | 175 | mask = 0x085dff00; |
176 | break; | ||
175 | case PM_LSU1L: | 177 | case PM_LSU1L: |
176 | mask = 0x50 << 24; /* byte 3 bits 4,6 */ | 178 | mask = 0x50 << 24; /* byte 3 bits 4,6 */ |
177 | break; | 179 | break; |
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index b1c648a36b03..84906d3fc860 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
@@ -517,7 +517,6 @@ struct task_struct *__switch_to(struct task_struct *prev, | |||
517 | 517 | ||
518 | account_system_vtime(current); | 518 | account_system_vtime(current); |
519 | account_process_vtime(current); | 519 | account_process_vtime(current); |
520 | calculate_steal_time(); | ||
521 | 520 | ||
522 | /* | 521 | /* |
523 | * We can't take a PMU exception inside _switch() since there is a | 522 | * We can't take a PMU exception inside _switch() since there is a |
@@ -1298,14 +1297,3 @@ unsigned long randomize_et_dyn(unsigned long base) | |||
1298 | 1297 | ||
1299 | return ret; | 1298 | return ret; |
1300 | } | 1299 | } |
1301 | |||
1302 | #ifdef CONFIG_SMP | ||
1303 | int arch_sd_sibling_asym_packing(void) | ||
1304 | { | ||
1305 | if (cpu_has_feature(CPU_FTR_ASYM_SMT)) { | ||
1306 | printk_once(KERN_INFO "Enabling Asymmetric SMT scheduling\n"); | ||
1307 | return SD_ASYM_PACKING; | ||
1308 | } | ||
1309 | return 0; | ||
1310 | } | ||
1311 | #endif | ||
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index fed9bf6187d1..9e3132db718b 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
@@ -66,6 +66,7 @@ | |||
66 | int __initdata iommu_is_off; | 66 | int __initdata iommu_is_off; |
67 | int __initdata iommu_force_on; | 67 | int __initdata iommu_force_on; |
68 | unsigned long tce_alloc_start, tce_alloc_end; | 68 | unsigned long tce_alloc_start, tce_alloc_end; |
69 | u64 ppc64_rma_size; | ||
69 | #endif | 70 | #endif |
70 | 71 | ||
71 | static int __init early_parse_mem(char *p) | 72 | static int __init early_parse_mem(char *p) |
@@ -98,7 +99,7 @@ static void __init move_device_tree(void) | |||
98 | 99 | ||
99 | if ((memory_limit && (start + size) > memory_limit) || | 100 | if ((memory_limit && (start + size) > memory_limit) || |
100 | overlaps_crashkernel(start, size)) { | 101 | overlaps_crashkernel(start, size)) { |
101 | p = __va(memblock_alloc_base(size, PAGE_SIZE, memblock.rmo_size)); | 102 | p = __va(memblock_alloc(size, PAGE_SIZE)); |
102 | memcpy(p, initial_boot_params, size); | 103 | memcpy(p, initial_boot_params, size); |
103 | initial_boot_params = (struct boot_param_header *)p; | 104 | initial_boot_params = (struct boot_param_header *)p; |
104 | DBG("Moved device tree to 0x%p\n", p); | 105 | DBG("Moved device tree to 0x%p\n", p); |
@@ -363,10 +364,15 @@ static int __init early_init_dt_scan_cpus(unsigned long node, | |||
363 | return 0; | 364 | return 0; |
364 | } | 365 | } |
365 | 366 | ||
366 | void __init early_init_dt_scan_chosen_arch(unsigned long node) | 367 | int __init early_init_dt_scan_chosen_ppc(unsigned long node, const char *uname, |
368 | int depth, void *data) | ||
367 | { | 369 | { |
368 | unsigned long *lprop; | 370 | unsigned long *lprop; |
369 | 371 | ||
372 | /* Use common scan routine to determine if this is the chosen node */ | ||
373 | if (early_init_dt_scan_chosen(node, uname, depth, data) == 0) | ||
374 | return 0; | ||
375 | |||
370 | #ifdef CONFIG_PPC64 | 376 | #ifdef CONFIG_PPC64 |
371 | /* check if iommu is forced on or off */ | 377 | /* check if iommu is forced on or off */ |
372 | if (of_get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL) | 378 | if (of_get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL) |
@@ -398,6 +404,9 @@ void __init early_init_dt_scan_chosen_arch(unsigned long node) | |||
398 | if (lprop) | 404 | if (lprop) |
399 | crashk_res.end = crashk_res.start + *lprop - 1; | 405 | crashk_res.end = crashk_res.start + *lprop - 1; |
400 | #endif | 406 | #endif |
407 | |||
408 | /* break now */ | ||
409 | return 1; | ||
401 | } | 410 | } |
402 | 411 | ||
403 | #ifdef CONFIG_PPC_PSERIES | 412 | #ifdef CONFIG_PPC_PSERIES |
@@ -492,7 +501,7 @@ static int __init early_init_dt_scan_memory_ppc(unsigned long node, | |||
492 | 501 | ||
493 | void __init early_init_dt_add_memory_arch(u64 base, u64 size) | 502 | void __init early_init_dt_add_memory_arch(u64 base, u64 size) |
494 | { | 503 | { |
495 | #if defined(CONFIG_PPC64) | 504 | #ifdef CONFIG_PPC64 |
496 | if (iommu_is_off) { | 505 | if (iommu_is_off) { |
497 | if (base >= 0x80000000ul) | 506 | if (base >= 0x80000000ul) |
498 | return; | 507 | return; |
@@ -501,9 +510,13 @@ void __init early_init_dt_add_memory_arch(u64 base, u64 size) | |||
501 | } | 510 | } |
502 | #endif | 511 | #endif |
503 | 512 | ||
504 | memblock_add(base, size); | 513 | /* First MEMBLOCK added, do some special initializations */ |
505 | 514 | if (memstart_addr == ~(phys_addr_t)0) | |
515 | setup_initial_memory_limit(base, size); | ||
506 | memstart_addr = min((u64)memstart_addr, base); | 516 | memstart_addr = min((u64)memstart_addr, base); |
517 | |||
518 | /* Add the chunk to the MEMBLOCK list */ | ||
519 | memblock_add(base, size); | ||
507 | } | 520 | } |
508 | 521 | ||
509 | u64 __init early_init_dt_alloc_memory_arch(u64 size, u64 align) | 522 | u64 __init early_init_dt_alloc_memory_arch(u64 size, u64 align) |
@@ -655,7 +668,6 @@ static void __init phyp_dump_reserve_mem(void) | |||
655 | static inline void __init phyp_dump_reserve_mem(void) {} | 668 | static inline void __init phyp_dump_reserve_mem(void) {} |
656 | #endif /* CONFIG_PHYP_DUMP && CONFIG_PPC_RTAS */ | 669 | #endif /* CONFIG_PHYP_DUMP && CONFIG_PPC_RTAS */ |
657 | 670 | ||
658 | |||
659 | void __init early_init_devtree(void *params) | 671 | void __init early_init_devtree(void *params) |
660 | { | 672 | { |
661 | phys_addr_t limit; | 673 | phys_addr_t limit; |
@@ -679,10 +691,11 @@ void __init early_init_devtree(void *params) | |||
679 | * device-tree, including the platform type, initrd location and | 691 | * device-tree, including the platform type, initrd location and |
680 | * size, TCE reserve, and more ... | 692 | * size, TCE reserve, and more ... |
681 | */ | 693 | */ |
682 | of_scan_flat_dt(early_init_dt_scan_chosen, NULL); | 694 | of_scan_flat_dt(early_init_dt_scan_chosen_ppc, NULL); |
683 | 695 | ||
684 | /* Scan memory nodes and rebuild MEMBLOCKs */ | 696 | /* Scan memory nodes and rebuild MEMBLOCKs */ |
685 | memblock_init(); | 697 | memblock_init(); |
698 | |||
686 | of_scan_flat_dt(early_init_dt_scan_root, NULL); | 699 | of_scan_flat_dt(early_init_dt_scan_root, NULL); |
687 | of_scan_flat_dt(early_init_dt_scan_memory_ppc, NULL); | 700 | of_scan_flat_dt(early_init_dt_scan_memory_ppc, NULL); |
688 | 701 | ||
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 11f3cd9c832f..286d9783d93f 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c | |||
@@ -1681,7 +1681,7 @@ long do_syscall_trace_enter(struct pt_regs *regs) | |||
1681 | 1681 | ||
1682 | if (unlikely(current->audit_context)) { | 1682 | if (unlikely(current->audit_context)) { |
1683 | #ifdef CONFIG_PPC64 | 1683 | #ifdef CONFIG_PPC64 |
1684 | if (!test_thread_flag(TIF_32BIT)) | 1684 | if (!is_32bit_task()) |
1685 | audit_syscall_entry(AUDIT_ARCH_PPC64, | 1685 | audit_syscall_entry(AUDIT_ARCH_PPC64, |
1686 | regs->gpr[0], | 1686 | regs->gpr[0], |
1687 | regs->gpr[3], regs->gpr[4], | 1687 | regs->gpr[3], regs->gpr[4], |
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 41048de3c6c3..8fe8bc61c10a 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c | |||
@@ -805,7 +805,7 @@ static void rtas_percpu_suspend_me(void *info) | |||
805 | __rtas_suspend_cpu((struct rtas_suspend_me_data *)info, 1); | 805 | __rtas_suspend_cpu((struct rtas_suspend_me_data *)info, 1); |
806 | } | 806 | } |
807 | 807 | ||
808 | static int rtas_ibm_suspend_me(struct rtas_args *args) | 808 | int rtas_ibm_suspend_me(struct rtas_args *args) |
809 | { | 809 | { |
810 | long state; | 810 | long state; |
811 | long rc; | 811 | long rc; |
@@ -855,7 +855,7 @@ static int rtas_ibm_suspend_me(struct rtas_args *args) | |||
855 | return atomic_read(&data.error); | 855 | return atomic_read(&data.error); |
856 | } | 856 | } |
857 | #else /* CONFIG_PPC_PSERIES */ | 857 | #else /* CONFIG_PPC_PSERIES */ |
858 | static int rtas_ibm_suspend_me(struct rtas_args *args) | 858 | int rtas_ibm_suspend_me(struct rtas_args *args) |
859 | { | 859 | { |
860 | return -ENOSYS; | 860 | return -ENOSYS; |
861 | } | 861 | } |
@@ -969,7 +969,7 @@ void __init rtas_initialize(void) | |||
969 | */ | 969 | */ |
970 | #ifdef CONFIG_PPC64 | 970 | #ifdef CONFIG_PPC64 |
971 | if (machine_is(pseries) && firmware_has_feature(FW_FEATURE_LPAR)) { | 971 | if (machine_is(pseries) && firmware_has_feature(FW_FEATURE_LPAR)) { |
972 | rtas_region = min(memblock.rmo_size, RTAS_INSTANTIATE_MAX); | 972 | rtas_region = min(ppc64_rma_size, RTAS_INSTANTIATE_MAX); |
973 | ibm_suspend_me_token = rtas_token("ibm,suspend-me"); | 973 | ibm_suspend_me_token = rtas_token("ibm,suspend-me"); |
974 | } | 974 | } |
975 | #endif | 975 | #endif |
diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c index 67a84d8f118d..2b442e6c21e6 100644 --- a/arch/powerpc/kernel/rtas_flash.c +++ b/arch/powerpc/kernel/rtas_flash.c | |||
@@ -716,6 +716,7 @@ static const struct file_operations rtas_flash_operations = { | |||
716 | .write = rtas_flash_write, | 716 | .write = rtas_flash_write, |
717 | .open = rtas_excl_open, | 717 | .open = rtas_excl_open, |
718 | .release = rtas_flash_release, | 718 | .release = rtas_flash_release, |
719 | .llseek = default_llseek, | ||
719 | }; | 720 | }; |
720 | 721 | ||
721 | static const struct file_operations manage_flash_operations = { | 722 | static const struct file_operations manage_flash_operations = { |
@@ -724,6 +725,7 @@ static const struct file_operations manage_flash_operations = { | |||
724 | .write = manage_flash_write, | 725 | .write = manage_flash_write, |
725 | .open = rtas_excl_open, | 726 | .open = rtas_excl_open, |
726 | .release = rtas_excl_release, | 727 | .release = rtas_excl_release, |
728 | .llseek = default_llseek, | ||
727 | }; | 729 | }; |
728 | 730 | ||
729 | static const struct file_operations validate_flash_operations = { | 731 | static const struct file_operations validate_flash_operations = { |
@@ -732,6 +734,7 @@ static const struct file_operations validate_flash_operations = { | |||
732 | .write = validate_flash_write, | 734 | .write = validate_flash_write, |
733 | .open = rtas_excl_open, | 735 | .open = rtas_excl_open, |
734 | .release = validate_flash_release, | 736 | .release = validate_flash_release, |
737 | .llseek = default_llseek, | ||
735 | }; | 738 | }; |
736 | 739 | ||
737 | static int __init rtas_flash_init(void) | 740 | static int __init rtas_flash_init(void) |
diff --git a/arch/powerpc/kernel/rtasd.c b/arch/powerpc/kernel/rtasd.c index 638883e23e3a..0438f819fe6b 100644 --- a/arch/powerpc/kernel/rtasd.c +++ b/arch/powerpc/kernel/rtasd.c | |||
@@ -354,6 +354,7 @@ static const struct file_operations proc_rtas_log_operations = { | |||
354 | .poll = rtas_log_poll, | 354 | .poll = rtas_log_poll, |
355 | .open = rtas_log_open, | 355 | .open = rtas_log_open, |
356 | .release = rtas_log_release, | 356 | .release = rtas_log_release, |
357 | .llseek = noop_llseek, | ||
357 | }; | 358 | }; |
358 | 359 | ||
359 | static int enable_surveillance(int timeout) | 360 | static int enable_surveillance(int timeout) |
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 93666f9cabf1..1d2fbc905303 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c | |||
@@ -46,7 +46,7 @@ | |||
46 | 46 | ||
47 | extern void bootx_init(unsigned long r4, unsigned long phys); | 47 | extern void bootx_init(unsigned long r4, unsigned long phys); |
48 | 48 | ||
49 | int boot_cpuid; | 49 | int boot_cpuid = -1; |
50 | EXPORT_SYMBOL_GPL(boot_cpuid); | 50 | EXPORT_SYMBOL_GPL(boot_cpuid); |
51 | int boot_cpuid_phys; | 51 | int boot_cpuid_phys; |
52 | 52 | ||
@@ -246,7 +246,7 @@ static void __init irqstack_early_init(void) | |||
246 | unsigned int i; | 246 | unsigned int i; |
247 | 247 | ||
248 | /* interrupt stacks must be in lowmem, we get that for free on ppc32 | 248 | /* interrupt stacks must be in lowmem, we get that for free on ppc32 |
249 | * as the memblock is limited to lowmem by MEMBLOCK_REAL_LIMIT */ | 249 | * as the memblock is limited to lowmem by default */ |
250 | for_each_possible_cpu(i) { | 250 | for_each_possible_cpu(i) { |
251 | softirq_ctx[i] = (struct thread_info *) | 251 | softirq_ctx[i] = (struct thread_info *) |
252 | __va(memblock_alloc(THREAD_SIZE, THREAD_SIZE)); | 252 | __va(memblock_alloc(THREAD_SIZE, THREAD_SIZE)); |
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index e72690ec9b87..2a178b0ebcdf 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
@@ -486,7 +486,7 @@ static void __init emergency_stack_init(void) | |||
486 | * bringup, we need to get at them in real mode. This means they | 486 | * bringup, we need to get at them in real mode. This means they |
487 | * must also be within the RMO region. | 487 | * must also be within the RMO region. |
488 | */ | 488 | */ |
489 | limit = min(slb0_limit(), memblock.rmo_size); | 489 | limit = min(slb0_limit(), ppc64_rma_size); |
490 | 490 | ||
491 | for_each_possible_cpu(i) { | 491 | for_each_possible_cpu(i) { |
492 | unsigned long sp; | 492 | unsigned long sp; |
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 0008bc58e826..68034bbf2e4f 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c | |||
@@ -508,9 +508,6 @@ int __devinit start_secondary(void *unused) | |||
508 | if (smp_ops->take_timebase) | 508 | if (smp_ops->take_timebase) |
509 | smp_ops->take_timebase(); | 509 | smp_ops->take_timebase(); |
510 | 510 | ||
511 | if (system_state > SYSTEM_BOOTING) | ||
512 | snapshot_timebase(); | ||
513 | |||
514 | secondary_cpu_time_init(); | 511 | secondary_cpu_time_init(); |
515 | 512 | ||
516 | ipi_call_lock(); | 513 | ipi_call_lock(); |
@@ -575,11 +572,18 @@ void __init smp_cpus_done(unsigned int max_cpus) | |||
575 | 572 | ||
576 | free_cpumask_var(old_mask); | 573 | free_cpumask_var(old_mask); |
577 | 574 | ||
578 | snapshot_timebases(); | ||
579 | |||
580 | dump_numa_cpu_topology(); | 575 | dump_numa_cpu_topology(); |
581 | } | 576 | } |
582 | 577 | ||
578 | int arch_sd_sibling_asym_packing(void) | ||
579 | { | ||
580 | if (cpu_has_feature(CPU_FTR_ASYM_SMT)) { | ||
581 | printk_once(KERN_INFO "Enabling Asymmetric SMT scheduling\n"); | ||
582 | return SD_ASYM_PACKING; | ||
583 | } | ||
584 | return 0; | ||
585 | } | ||
586 | |||
583 | #ifdef CONFIG_HOTPLUG_CPU | 587 | #ifdef CONFIG_HOTPLUG_CPU |
584 | int __cpu_disable(void) | 588 | int __cpu_disable(void) |
585 | { | 589 | { |
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 8533b3b83f5d..010406958d97 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
@@ -53,7 +53,7 @@ | |||
53 | #include <linux/posix-timers.h> | 53 | #include <linux/posix-timers.h> |
54 | #include <linux/irq.h> | 54 | #include <linux/irq.h> |
55 | #include <linux/delay.h> | 55 | #include <linux/delay.h> |
56 | #include <linux/perf_event.h> | 56 | #include <linux/irq_work.h> |
57 | #include <asm/trace.h> | 57 | #include <asm/trace.h> |
58 | 58 | ||
59 | #include <asm/io.h> | 59 | #include <asm/io.h> |
@@ -161,10 +161,9 @@ extern struct timezone sys_tz; | |||
161 | static long timezone_offset; | 161 | static long timezone_offset; |
162 | 162 | ||
163 | unsigned long ppc_proc_freq; | 163 | unsigned long ppc_proc_freq; |
164 | EXPORT_SYMBOL(ppc_proc_freq); | 164 | EXPORT_SYMBOL_GPL(ppc_proc_freq); |
165 | unsigned long ppc_tb_freq; | 165 | unsigned long ppc_tb_freq; |
166 | 166 | EXPORT_SYMBOL_GPL(ppc_tb_freq); | |
167 | static DEFINE_PER_CPU(u64, last_jiffy); | ||
168 | 167 | ||
169 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 168 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
170 | /* | 169 | /* |
@@ -185,6 +184,8 @@ DEFINE_PER_CPU(unsigned long, cputime_scaled_last_delta); | |||
185 | 184 | ||
186 | cputime_t cputime_one_jiffy; | 185 | cputime_t cputime_one_jiffy; |
187 | 186 | ||
187 | void (*dtl_consumer)(struct dtl_entry *, u64); | ||
188 | |||
188 | static void calc_cputime_factors(void) | 189 | static void calc_cputime_factors(void) |
189 | { | 190 | { |
190 | struct div_result res; | 191 | struct div_result res; |
@@ -200,62 +201,153 @@ static void calc_cputime_factors(void) | |||
200 | } | 201 | } |
201 | 202 | ||
202 | /* | 203 | /* |
203 | * Read the PURR on systems that have it, otherwise the timebase. | 204 | * Read the SPURR on systems that have it, otherwise the PURR, |
205 | * or if that doesn't exist return the timebase value passed in. | ||
204 | */ | 206 | */ |
205 | static u64 read_purr(void) | 207 | static u64 read_spurr(u64 tb) |
206 | { | 208 | { |
209 | if (cpu_has_feature(CPU_FTR_SPURR)) | ||
210 | return mfspr(SPRN_SPURR); | ||
207 | if (cpu_has_feature(CPU_FTR_PURR)) | 211 | if (cpu_has_feature(CPU_FTR_PURR)) |
208 | return mfspr(SPRN_PURR); | 212 | return mfspr(SPRN_PURR); |
209 | return mftb(); | 213 | return tb; |
210 | } | 214 | } |
211 | 215 | ||
216 | #ifdef CONFIG_PPC_SPLPAR | ||
217 | |||
212 | /* | 218 | /* |
213 | * Read the SPURR on systems that have it, otherwise the purr | 219 | * Scan the dispatch trace log and count up the stolen time. |
220 | * Should be called with interrupts disabled. | ||
214 | */ | 221 | */ |
215 | static u64 read_spurr(u64 purr) | 222 | static u64 scan_dispatch_log(u64 stop_tb) |
216 | { | 223 | { |
217 | /* | 224 | u64 i = local_paca->dtl_ridx; |
218 | * cpus without PURR won't have a SPURR | 225 | struct dtl_entry *dtl = local_paca->dtl_curr; |
219 | * We already know the former when we use this, so tell gcc | 226 | struct dtl_entry *dtl_end = local_paca->dispatch_log_end; |
220 | */ | 227 | struct lppaca *vpa = local_paca->lppaca_ptr; |
221 | if (cpu_has_feature(CPU_FTR_PURR) && cpu_has_feature(CPU_FTR_SPURR)) | 228 | u64 tb_delta; |
222 | return mfspr(SPRN_SPURR); | 229 | u64 stolen = 0; |
223 | return purr; | 230 | u64 dtb; |
231 | |||
232 | if (i == vpa->dtl_idx) | ||
233 | return 0; | ||
234 | while (i < vpa->dtl_idx) { | ||
235 | if (dtl_consumer) | ||
236 | dtl_consumer(dtl, i); | ||
237 | dtb = dtl->timebase; | ||
238 | tb_delta = dtl->enqueue_to_dispatch_time + | ||
239 | dtl->ready_to_enqueue_time; | ||
240 | barrier(); | ||
241 | if (i + N_DISPATCH_LOG < vpa->dtl_idx) { | ||
242 | /* buffer has overflowed */ | ||
243 | i = vpa->dtl_idx - N_DISPATCH_LOG; | ||
244 | dtl = local_paca->dispatch_log + (i % N_DISPATCH_LOG); | ||
245 | continue; | ||
246 | } | ||
247 | if (dtb > stop_tb) | ||
248 | break; | ||
249 | stolen += tb_delta; | ||
250 | ++i; | ||
251 | ++dtl; | ||
252 | if (dtl == dtl_end) | ||
253 | dtl = local_paca->dispatch_log; | ||
254 | } | ||
255 | local_paca->dtl_ridx = i; | ||
256 | local_paca->dtl_curr = dtl; | ||
257 | return stolen; | ||
224 | } | 258 | } |
225 | 259 | ||
226 | /* | 260 | /* |
261 | * Accumulate stolen time by scanning the dispatch trace log. | ||
262 | * Called on entry from user mode. | ||
263 | */ | ||
264 | void accumulate_stolen_time(void) | ||
265 | { | ||
266 | u64 sst, ust; | ||
267 | |||
268 | sst = scan_dispatch_log(get_paca()->starttime_user); | ||
269 | ust = scan_dispatch_log(get_paca()->starttime); | ||
270 | get_paca()->system_time -= sst; | ||
271 | get_paca()->user_time -= ust; | ||
272 | get_paca()->stolen_time += ust + sst; | ||
273 | } | ||
274 | |||
275 | static inline u64 calculate_stolen_time(u64 stop_tb) | ||
276 | { | ||
277 | u64 stolen = 0; | ||
278 | |||
279 | if (get_paca()->dtl_ridx != get_paca()->lppaca_ptr->dtl_idx) { | ||
280 | stolen = scan_dispatch_log(stop_tb); | ||
281 | get_paca()->system_time -= stolen; | ||
282 | } | ||
283 | |||
284 | stolen += get_paca()->stolen_time; | ||
285 | get_paca()->stolen_time = 0; | ||
286 | return stolen; | ||
287 | } | ||
288 | |||
289 | #else /* CONFIG_PPC_SPLPAR */ | ||
290 | static inline u64 calculate_stolen_time(u64 stop_tb) | ||
291 | { | ||
292 | return 0; | ||
293 | } | ||
294 | |||
295 | #endif /* CONFIG_PPC_SPLPAR */ | ||
296 | |||
297 | /* | ||
227 | * Account time for a transition between system, hard irq | 298 | * Account time for a transition between system, hard irq |
228 | * or soft irq state. | 299 | * or soft irq state. |
229 | */ | 300 | */ |
230 | void account_system_vtime(struct task_struct *tsk) | 301 | void account_system_vtime(struct task_struct *tsk) |
231 | { | 302 | { |
232 | u64 now, nowscaled, delta, deltascaled, sys_time; | 303 | u64 now, nowscaled, delta, deltascaled; |
233 | unsigned long flags; | 304 | unsigned long flags; |
305 | u64 stolen, udelta, sys_scaled, user_scaled; | ||
234 | 306 | ||
235 | local_irq_save(flags); | 307 | local_irq_save(flags); |
236 | now = read_purr(); | 308 | now = mftb(); |
237 | nowscaled = read_spurr(now); | 309 | nowscaled = read_spurr(now); |
238 | delta = now - get_paca()->startpurr; | 310 | get_paca()->system_time += now - get_paca()->starttime; |
311 | get_paca()->starttime = now; | ||
239 | deltascaled = nowscaled - get_paca()->startspurr; | 312 | deltascaled = nowscaled - get_paca()->startspurr; |
240 | get_paca()->startpurr = now; | ||
241 | get_paca()->startspurr = nowscaled; | 313 | get_paca()->startspurr = nowscaled; |
242 | if (!in_interrupt()) { | 314 | |
243 | /* deltascaled includes both user and system time. | 315 | stolen = calculate_stolen_time(now); |
244 | * Hence scale it based on the purr ratio to estimate | 316 | |
245 | * the system time */ | 317 | delta = get_paca()->system_time; |
246 | sys_time = get_paca()->system_time; | 318 | get_paca()->system_time = 0; |
247 | if (get_paca()->user_time) | 319 | udelta = get_paca()->user_time - get_paca()->utime_sspurr; |
248 | deltascaled = deltascaled * sys_time / | 320 | get_paca()->utime_sspurr = get_paca()->user_time; |
249 | (sys_time + get_paca()->user_time); | 321 | |
250 | delta += sys_time; | 322 | /* |
251 | get_paca()->system_time = 0; | 323 | * Because we don't read the SPURR on every kernel entry/exit, |
324 | * deltascaled includes both user and system SPURR ticks. | ||
325 | * Apportion these ticks to system SPURR ticks and user | ||
326 | * SPURR ticks in the same ratio as the system time (delta) | ||
327 | * and user time (udelta) values obtained from the timebase | ||
328 | * over the same interval. The system ticks get accounted here; | ||
329 | * the user ticks get saved up in paca->user_time_scaled to be | ||
330 | * used by account_process_tick. | ||
331 | */ | ||
332 | sys_scaled = delta; | ||
333 | user_scaled = udelta; | ||
334 | if (deltascaled != delta + udelta) { | ||
335 | if (udelta) { | ||
336 | sys_scaled = deltascaled * delta / (delta + udelta); | ||
337 | user_scaled = deltascaled - sys_scaled; | ||
338 | } else { | ||
339 | sys_scaled = deltascaled; | ||
340 | } | ||
341 | } | ||
342 | get_paca()->user_time_scaled += user_scaled; | ||
343 | |||
344 | if (in_irq() || idle_task(smp_processor_id()) != tsk) { | ||
345 | account_system_time(tsk, 0, delta, sys_scaled); | ||
346 | if (stolen) | ||
347 | account_steal_time(stolen); | ||
348 | } else { | ||
349 | account_idle_time(delta + stolen); | ||
252 | } | 350 | } |
253 | if (in_irq() || idle_task(smp_processor_id()) != tsk) | ||
254 | account_system_time(tsk, 0, delta, deltascaled); | ||
255 | else | ||
256 | account_idle_time(delta); | ||
257 | __get_cpu_var(cputime_last_delta) = delta; | ||
258 | __get_cpu_var(cputime_scaled_last_delta) = deltascaled; | ||
259 | local_irq_restore(flags); | 351 | local_irq_restore(flags); |
260 | } | 352 | } |
261 | EXPORT_SYMBOL_GPL(account_system_vtime); | 353 | EXPORT_SYMBOL_GPL(account_system_vtime); |
@@ -265,125 +357,26 @@ EXPORT_SYMBOL_GPL(account_system_vtime); | |||
265 | * by the exception entry and exit code to the generic process | 357 | * by the exception entry and exit code to the generic process |
266 | * user and system time records. | 358 | * user and system time records. |
267 | * Must be called with interrupts disabled. | 359 | * Must be called with interrupts disabled. |
360 | * Assumes that account_system_vtime() has been called recently | ||
361 | * (i.e. since the last entry from usermode) so that | ||
362 | * get_paca()->user_time_scaled is up to date. | ||
268 | */ | 363 | */ |
269 | void account_process_tick(struct task_struct *tsk, int user_tick) | 364 | void account_process_tick(struct task_struct *tsk, int user_tick) |
270 | { | 365 | { |
271 | cputime_t utime, utimescaled; | 366 | cputime_t utime, utimescaled; |
272 | 367 | ||
273 | utime = get_paca()->user_time; | 368 | utime = get_paca()->user_time; |
369 | utimescaled = get_paca()->user_time_scaled; | ||
274 | get_paca()->user_time = 0; | 370 | get_paca()->user_time = 0; |
275 | utimescaled = cputime_to_scaled(utime); | 371 | get_paca()->user_time_scaled = 0; |
372 | get_paca()->utime_sspurr = 0; | ||
276 | account_user_time(tsk, utime, utimescaled); | 373 | account_user_time(tsk, utime, utimescaled); |
277 | } | 374 | } |
278 | 375 | ||
279 | /* | ||
280 | * Stuff for accounting stolen time. | ||
281 | */ | ||
282 | struct cpu_purr_data { | ||
283 | int initialized; /* thread is running */ | ||
284 | u64 tb; /* last TB value read */ | ||
285 | u64 purr; /* last PURR value read */ | ||
286 | u64 spurr; /* last SPURR value read */ | ||
287 | }; | ||
288 | |||
289 | /* | ||
290 | * Each entry in the cpu_purr_data array is manipulated only by its | ||
291 | * "owner" cpu -- usually in the timer interrupt but also occasionally | ||
292 | * in process context for cpu online. As long as cpus do not touch | ||
293 | * each others' cpu_purr_data, disabling local interrupts is | ||
294 | * sufficient to serialize accesses. | ||
295 | */ | ||
296 | static DEFINE_PER_CPU(struct cpu_purr_data, cpu_purr_data); | ||
297 | |||
298 | static void snapshot_tb_and_purr(void *data) | ||
299 | { | ||
300 | unsigned long flags; | ||
301 | struct cpu_purr_data *p = &__get_cpu_var(cpu_purr_data); | ||
302 | |||
303 | local_irq_save(flags); | ||
304 | p->tb = get_tb_or_rtc(); | ||
305 | p->purr = mfspr(SPRN_PURR); | ||
306 | wmb(); | ||
307 | p->initialized = 1; | ||
308 | local_irq_restore(flags); | ||
309 | } | ||
310 | |||
311 | /* | ||
312 | * Called during boot when all cpus have come up. | ||
313 | */ | ||
314 | void snapshot_timebases(void) | ||
315 | { | ||
316 | if (!cpu_has_feature(CPU_FTR_PURR)) | ||
317 | return; | ||
318 | on_each_cpu(snapshot_tb_and_purr, NULL, 1); | ||
319 | } | ||
320 | |||
321 | /* | ||
322 | * Must be called with interrupts disabled. | ||
323 | */ | ||
324 | void calculate_steal_time(void) | ||
325 | { | ||
326 | u64 tb, purr; | ||
327 | s64 stolen; | ||
328 | struct cpu_purr_data *pme; | ||
329 | |||
330 | pme = &__get_cpu_var(cpu_purr_data); | ||
331 | if (!pme->initialized) | ||
332 | return; /* !CPU_FTR_PURR or early in early boot */ | ||
333 | tb = mftb(); | ||
334 | purr = mfspr(SPRN_PURR); | ||
335 | stolen = (tb - pme->tb) - (purr - pme->purr); | ||
336 | if (stolen > 0) { | ||
337 | if (idle_task(smp_processor_id()) != current) | ||
338 | account_steal_time(stolen); | ||
339 | else | ||
340 | account_idle_time(stolen); | ||
341 | } | ||
342 | pme->tb = tb; | ||
343 | pme->purr = purr; | ||
344 | } | ||
345 | |||
346 | #ifdef CONFIG_PPC_SPLPAR | ||
347 | /* | ||
348 | * Must be called before the cpu is added to the online map when | ||
349 | * a cpu is being brought up at runtime. | ||
350 | */ | ||
351 | static void snapshot_purr(void) | ||
352 | { | ||
353 | struct cpu_purr_data *pme; | ||
354 | unsigned long flags; | ||
355 | |||
356 | if (!cpu_has_feature(CPU_FTR_PURR)) | ||
357 | return; | ||
358 | local_irq_save(flags); | ||
359 | pme = &__get_cpu_var(cpu_purr_data); | ||
360 | pme->tb = mftb(); | ||
361 | pme->purr = mfspr(SPRN_PURR); | ||
362 | pme->initialized = 1; | ||
363 | local_irq_restore(flags); | ||
364 | } | ||
365 | |||
366 | #endif /* CONFIG_PPC_SPLPAR */ | ||
367 | |||
368 | #else /* ! CONFIG_VIRT_CPU_ACCOUNTING */ | 376 | #else /* ! CONFIG_VIRT_CPU_ACCOUNTING */ |
369 | #define calc_cputime_factors() | 377 | #define calc_cputime_factors() |
370 | #define calculate_steal_time() do { } while (0) | ||
371 | #endif | 378 | #endif |
372 | 379 | ||
373 | #if !(defined(CONFIG_VIRT_CPU_ACCOUNTING) && defined(CONFIG_PPC_SPLPAR)) | ||
374 | #define snapshot_purr() do { } while (0) | ||
375 | #endif | ||
376 | |||
377 | /* | ||
378 | * Called when a cpu comes up after the system has finished booting, | ||
379 | * i.e. as a result of a hotplug cpu action. | ||
380 | */ | ||
381 | void snapshot_timebase(void) | ||
382 | { | ||
383 | __get_cpu_var(last_jiffy) = get_tb_or_rtc(); | ||
384 | snapshot_purr(); | ||
385 | } | ||
386 | |||
387 | void __delay(unsigned long loops) | 380 | void __delay(unsigned long loops) |
388 | { | 381 | { |
389 | unsigned long start; | 382 | unsigned long start; |
@@ -493,60 +486,60 @@ void __init iSeries_time_init_early(void) | |||
493 | } | 486 | } |
494 | #endif /* CONFIG_PPC_ISERIES */ | 487 | #endif /* CONFIG_PPC_ISERIES */ |
495 | 488 | ||
496 | #ifdef CONFIG_PERF_EVENTS | 489 | #ifdef CONFIG_IRQ_WORK |
497 | 490 | ||
498 | /* | 491 | /* |
499 | * 64-bit uses a byte in the PACA, 32-bit uses a per-cpu variable... | 492 | * 64-bit uses a byte in the PACA, 32-bit uses a per-cpu variable... |
500 | */ | 493 | */ |
501 | #ifdef CONFIG_PPC64 | 494 | #ifdef CONFIG_PPC64 |
502 | static inline unsigned long test_perf_event_pending(void) | 495 | static inline unsigned long test_irq_work_pending(void) |
503 | { | 496 | { |
504 | unsigned long x; | 497 | unsigned long x; |
505 | 498 | ||
506 | asm volatile("lbz %0,%1(13)" | 499 | asm volatile("lbz %0,%1(13)" |
507 | : "=r" (x) | 500 | : "=r" (x) |
508 | : "i" (offsetof(struct paca_struct, perf_event_pending))); | 501 | : "i" (offsetof(struct paca_struct, irq_work_pending))); |
509 | return x; | 502 | return x; |
510 | } | 503 | } |
511 | 504 | ||
512 | static inline void set_perf_event_pending_flag(void) | 505 | static inline void set_irq_work_pending_flag(void) |
513 | { | 506 | { |
514 | asm volatile("stb %0,%1(13)" : : | 507 | asm volatile("stb %0,%1(13)" : : |
515 | "r" (1), | 508 | "r" (1), |
516 | "i" (offsetof(struct paca_struct, perf_event_pending))); | 509 | "i" (offsetof(struct paca_struct, irq_work_pending))); |
517 | } | 510 | } |
518 | 511 | ||
519 | static inline void clear_perf_event_pending(void) | 512 | static inline void clear_irq_work_pending(void) |
520 | { | 513 | { |
521 | asm volatile("stb %0,%1(13)" : : | 514 | asm volatile("stb %0,%1(13)" : : |
522 | "r" (0), | 515 | "r" (0), |
523 | "i" (offsetof(struct paca_struct, perf_event_pending))); | 516 | "i" (offsetof(struct paca_struct, irq_work_pending))); |
524 | } | 517 | } |
525 | 518 | ||
526 | #else /* 32-bit */ | 519 | #else /* 32-bit */ |
527 | 520 | ||
528 | DEFINE_PER_CPU(u8, perf_event_pending); | 521 | DEFINE_PER_CPU(u8, irq_work_pending); |
529 | 522 | ||
530 | #define set_perf_event_pending_flag() __get_cpu_var(perf_event_pending) = 1 | 523 | #define set_irq_work_pending_flag() __get_cpu_var(irq_work_pending) = 1 |
531 | #define test_perf_event_pending() __get_cpu_var(perf_event_pending) | 524 | #define test_irq_work_pending() __get_cpu_var(irq_work_pending) |
532 | #define clear_perf_event_pending() __get_cpu_var(perf_event_pending) = 0 | 525 | #define clear_irq_work_pending() __get_cpu_var(irq_work_pending) = 0 |
533 | 526 | ||
534 | #endif /* 32 vs 64 bit */ | 527 | #endif /* 32 vs 64 bit */ |
535 | 528 | ||
536 | void set_perf_event_pending(void) | 529 | void set_irq_work_pending(void) |
537 | { | 530 | { |
538 | preempt_disable(); | 531 | preempt_disable(); |
539 | set_perf_event_pending_flag(); | 532 | set_irq_work_pending_flag(); |
540 | set_dec(1); | 533 | set_dec(1); |
541 | preempt_enable(); | 534 | preempt_enable(); |
542 | } | 535 | } |
543 | 536 | ||
544 | #else /* CONFIG_PERF_EVENTS */ | 537 | #else /* CONFIG_IRQ_WORK */ |
545 | 538 | ||
546 | #define test_perf_event_pending() 0 | 539 | #define test_irq_work_pending() 0 |
547 | #define clear_perf_event_pending() | 540 | #define clear_irq_work_pending() |
548 | 541 | ||
549 | #endif /* CONFIG_PERF_EVENTS */ | 542 | #endif /* CONFIG_IRQ_WORK */ |
550 | 543 | ||
551 | /* | 544 | /* |
552 | * For iSeries shared processors, we have to let the hypervisor | 545 | * For iSeries shared processors, we have to let the hypervisor |
@@ -585,11 +578,9 @@ void timer_interrupt(struct pt_regs * regs) | |||
585 | old_regs = set_irq_regs(regs); | 578 | old_regs = set_irq_regs(regs); |
586 | irq_enter(); | 579 | irq_enter(); |
587 | 580 | ||
588 | calculate_steal_time(); | 581 | if (test_irq_work_pending()) { |
589 | 582 | clear_irq_work_pending(); | |
590 | if (test_perf_event_pending()) { | 583 | irq_work_run(); |
591 | clear_perf_event_pending(); | ||
592 | perf_event_do_pending(); | ||
593 | } | 584 | } |
594 | 585 | ||
595 | #ifdef CONFIG_PPC_ISERIES | 586 | #ifdef CONFIG_PPC_ISERIES |
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index a45a63c3a0c7..1b2cdc8eec90 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
@@ -538,6 +538,11 @@ int machine_check_e500(struct pt_regs *regs) | |||
538 | 538 | ||
539 | return 0; | 539 | return 0; |
540 | } | 540 | } |
541 | |||
542 | int machine_check_generic(struct pt_regs *regs) | ||
543 | { | ||
544 | return 0; | ||
545 | } | ||
541 | #elif defined(CONFIG_E200) | 546 | #elif defined(CONFIG_E200) |
542 | int machine_check_e200(struct pt_regs *regs) | 547 | int machine_check_e200(struct pt_regs *regs) |
543 | { | 548 | { |
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index 13002fe206e7..fd8728729abc 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c | |||
@@ -159,7 +159,7 @@ static void dump_vdso_pages(struct vm_area_struct * vma) | |||
159 | { | 159 | { |
160 | int i; | 160 | int i; |
161 | 161 | ||
162 | if (!vma || test_thread_flag(TIF_32BIT)) { | 162 | if (!vma || is_32bit_task()) { |
163 | printk("vDSO32 @ %016lx:\n", (unsigned long)vdso32_kbase); | 163 | printk("vDSO32 @ %016lx:\n", (unsigned long)vdso32_kbase); |
164 | for (i=0; i<vdso32_pages; i++) { | 164 | for (i=0; i<vdso32_pages; i++) { |
165 | struct page *pg = virt_to_page(vdso32_kbase + | 165 | struct page *pg = virt_to_page(vdso32_kbase + |
@@ -170,7 +170,7 @@ static void dump_vdso_pages(struct vm_area_struct * vma) | |||
170 | dump_one_vdso_page(pg, upg); | 170 | dump_one_vdso_page(pg, upg); |
171 | } | 171 | } |
172 | } | 172 | } |
173 | if (!vma || !test_thread_flag(TIF_32BIT)) { | 173 | if (!vma || !is_32bit_task()) { |
174 | printk("vDSO64 @ %016lx:\n", (unsigned long)vdso64_kbase); | 174 | printk("vDSO64 @ %016lx:\n", (unsigned long)vdso64_kbase); |
175 | for (i=0; i<vdso64_pages; i++) { | 175 | for (i=0; i<vdso64_pages; i++) { |
176 | struct page *pg = virt_to_page(vdso64_kbase + | 176 | struct page *pg = virt_to_page(vdso64_kbase + |
@@ -200,7 +200,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) | |||
200 | return 0; | 200 | return 0; |
201 | 201 | ||
202 | #ifdef CONFIG_PPC64 | 202 | #ifdef CONFIG_PPC64 |
203 | if (test_thread_flag(TIF_32BIT)) { | 203 | if (is_32bit_task()) { |
204 | vdso_pagelist = vdso32_pagelist; | 204 | vdso_pagelist = vdso32_pagelist; |
205 | vdso_pages = vdso32_pages; | 205 | vdso_pages = vdso32_pages; |
206 | vdso_base = VDSO32_MBASE; | 206 | vdso_base = VDSO32_MBASE; |
diff --git a/arch/powerpc/kernel/vdso32/Makefile b/arch/powerpc/kernel/vdso32/Makefile index 51ead52141bd..9a7946c41738 100644 --- a/arch/powerpc/kernel/vdso32/Makefile +++ b/arch/powerpc/kernel/vdso32/Makefile | |||
@@ -14,10 +14,10 @@ obj-vdso32 := $(addprefix $(obj)/, $(obj-vdso32)) | |||
14 | 14 | ||
15 | GCOV_PROFILE := n | 15 | GCOV_PROFILE := n |
16 | 16 | ||
17 | EXTRA_CFLAGS := -shared -fno-common -fno-builtin | 17 | ccflags-y := -shared -fno-common -fno-builtin |
18 | EXTRA_CFLAGS += -nostdlib -Wl,-soname=linux-vdso32.so.1 \ | 18 | ccflags-y += -nostdlib -Wl,-soname=linux-vdso32.so.1 \ |
19 | $(call cc-ldoption, -Wl$(comma)--hash-style=sysv) | 19 | $(call cc-ldoption, -Wl$(comma)--hash-style=sysv) |
20 | EXTRA_AFLAGS := -D__VDSO32__ -s | 20 | asflags-y := -D__VDSO32__ -s |
21 | 21 | ||
22 | obj-y += vdso32_wrapper.o | 22 | obj-y += vdso32_wrapper.o |
23 | extra-y += vdso32.lds | 23 | extra-y += vdso32.lds |
diff --git a/arch/powerpc/kernel/vdso64/Makefile b/arch/powerpc/kernel/vdso64/Makefile index 79da65d44a2a..8c500d8622e4 100644 --- a/arch/powerpc/kernel/vdso64/Makefile +++ b/arch/powerpc/kernel/vdso64/Makefile | |||
@@ -9,10 +9,10 @@ obj-vdso64 := $(addprefix $(obj)/, $(obj-vdso64)) | |||
9 | 9 | ||
10 | GCOV_PROFILE := n | 10 | GCOV_PROFILE := n |
11 | 11 | ||
12 | EXTRA_CFLAGS := -shared -fno-common -fno-builtin | 12 | ccflags-y := -shared -fno-common -fno-builtin |
13 | EXTRA_CFLAGS += -nostdlib -Wl,-soname=linux-vdso64.so.1 \ | 13 | ccflags-y += -nostdlib -Wl,-soname=linux-vdso64.so.1 \ |
14 | $(call cc-ldoption, -Wl$(comma)--hash-style=sysv) | 14 | $(call cc-ldoption, -Wl$(comma)--hash-style=sysv) |
15 | EXTRA_AFLAGS := -D__VDSO64__ -s | 15 | asflags-y := -D__VDSO64__ -s |
16 | 16 | ||
17 | obj-y += vdso64_wrapper.o | 17 | obj-y += vdso64_wrapper.o |
18 | extra-y += vdso64.lds | 18 | extra-y += vdso64.lds |
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index fa3469ddaef8..d692989a4318 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c | |||
@@ -1184,7 +1184,12 @@ EXPORT_SYMBOL(vio_unregister_driver); | |||
1184 | /* vio_dev refcount hit 0 */ | 1184 | /* vio_dev refcount hit 0 */ |
1185 | static void __devinit vio_dev_release(struct device *dev) | 1185 | static void __devinit vio_dev_release(struct device *dev) |
1186 | { | 1186 | { |
1187 | /* XXX should free TCE table */ | 1187 | struct iommu_table *tbl = get_iommu_table_base(dev); |
1188 | |||
1189 | /* iSeries uses a common table for all vio devices */ | ||
1190 | if (!firmware_has_feature(FW_FEATURE_ISERIES) && tbl) | ||
1191 | iommu_free_table(tbl, dev->of_node ? | ||
1192 | dev->of_node->full_name : dev_name(dev)); | ||
1188 | of_node_put(dev->of_node); | 1193 | of_node_put(dev->of_node); |
1189 | kfree(to_vio_dev(dev)); | 1194 | kfree(to_vio_dev(dev)); |
1190 | } | 1195 | } |
@@ -1254,8 +1259,7 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node) | |||
1254 | if (device_register(&viodev->dev)) { | 1259 | if (device_register(&viodev->dev)) { |
1255 | printk(KERN_ERR "%s: failed to register device %s\n", | 1260 | printk(KERN_ERR "%s: failed to register device %s\n", |
1256 | __func__, dev_name(&viodev->dev)); | 1261 | __func__, dev_name(&viodev->dev)); |
1257 | /* XXX free TCE table */ | 1262 | put_device(&viodev->dev); |
1258 | kfree(viodev); | ||
1259 | return NULL; | 1263 | return NULL; |
1260 | } | 1264 | } |
1261 | 1265 | ||
diff --git a/arch/powerpc/kvm/44x.c b/arch/powerpc/kvm/44x.c index 73c0a3f64ed1..74d0e7421143 100644 --- a/arch/powerpc/kvm/44x.c +++ b/arch/powerpc/kvm/44x.c | |||
@@ -43,7 +43,7 @@ int kvmppc_core_check_processor_compat(void) | |||
43 | { | 43 | { |
44 | int r; | 44 | int r; |
45 | 45 | ||
46 | if (strcmp(cur_cpu_spec->platform, "ppc440") == 0) | 46 | if (strncmp(cur_cpu_spec->platform, "ppc440", 6) == 0) |
47 | r = 0; | 47 | r = 0; |
48 | else | 48 | else |
49 | r = -ENOTSUPP; | 49 | r = -ENOTSUPP; |
@@ -72,6 +72,7 @@ int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu) | |||
72 | /* Since the guest can directly access the timebase, it must know the | 72 | /* Since the guest can directly access the timebase, it must know the |
73 | * real timebase frequency. Accordingly, it must see the state of | 73 | * real timebase frequency. Accordingly, it must see the state of |
74 | * CCR1[TCS]. */ | 74 | * CCR1[TCS]. */ |
75 | /* XXX CCR1 doesn't exist on all 440 SoCs. */ | ||
75 | vcpu->arch.ccr1 = mfspr(SPRN_CCR1); | 76 | vcpu->arch.ccr1 = mfspr(SPRN_CCR1); |
76 | 77 | ||
77 | for (i = 0; i < ARRAY_SIZE(vcpu_44x->shadow_refs); i++) | 78 | for (i = 0; i < ARRAY_SIZE(vcpu_44x->shadow_refs); i++) |
@@ -123,8 +124,14 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id) | |||
123 | if (err) | 124 | if (err) |
124 | goto free_vcpu; | 125 | goto free_vcpu; |
125 | 126 | ||
127 | vcpu->arch.shared = (void*)__get_free_page(GFP_KERNEL|__GFP_ZERO); | ||
128 | if (!vcpu->arch.shared) | ||
129 | goto uninit_vcpu; | ||
130 | |||
126 | return vcpu; | 131 | return vcpu; |
127 | 132 | ||
133 | uninit_vcpu: | ||
134 | kvm_vcpu_uninit(vcpu); | ||
128 | free_vcpu: | 135 | free_vcpu: |
129 | kmem_cache_free(kvm_vcpu_cache, vcpu_44x); | 136 | kmem_cache_free(kvm_vcpu_cache, vcpu_44x); |
130 | out: | 137 | out: |
@@ -135,6 +142,7 @@ void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu) | |||
135 | { | 142 | { |
136 | struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); | 143 | struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); |
137 | 144 | ||
145 | free_page((unsigned long)vcpu->arch.shared); | ||
138 | kvm_vcpu_uninit(vcpu); | 146 | kvm_vcpu_uninit(vcpu); |
139 | kmem_cache_free(kvm_vcpu_cache, vcpu_44x); | 147 | kmem_cache_free(kvm_vcpu_cache, vcpu_44x); |
140 | } | 148 | } |
diff --git a/arch/powerpc/kvm/44x_tlb.c b/arch/powerpc/kvm/44x_tlb.c index 9b9b5cdea840..5f3cff83e089 100644 --- a/arch/powerpc/kvm/44x_tlb.c +++ b/arch/powerpc/kvm/44x_tlb.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #ifdef DEBUG | 47 | #ifdef DEBUG |
48 | void kvmppc_dump_tlbs(struct kvm_vcpu *vcpu) | 48 | void kvmppc_dump_tlbs(struct kvm_vcpu *vcpu) |
49 | { | 49 | { |
50 | struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); | ||
50 | struct kvmppc_44x_tlbe *tlbe; | 51 | struct kvmppc_44x_tlbe *tlbe; |
51 | int i; | 52 | int i; |
52 | 53 | ||
@@ -221,14 +222,14 @@ gpa_t kvmppc_mmu_xlate(struct kvm_vcpu *vcpu, unsigned int gtlb_index, | |||
221 | 222 | ||
222 | int kvmppc_mmu_itlb_index(struct kvm_vcpu *vcpu, gva_t eaddr) | 223 | int kvmppc_mmu_itlb_index(struct kvm_vcpu *vcpu, gva_t eaddr) |
223 | { | 224 | { |
224 | unsigned int as = !!(vcpu->arch.msr & MSR_IS); | 225 | unsigned int as = !!(vcpu->arch.shared->msr & MSR_IS); |
225 | 226 | ||
226 | return kvmppc_44x_tlb_index(vcpu, eaddr, vcpu->arch.pid, as); | 227 | return kvmppc_44x_tlb_index(vcpu, eaddr, vcpu->arch.pid, as); |
227 | } | 228 | } |
228 | 229 | ||
229 | int kvmppc_mmu_dtlb_index(struct kvm_vcpu *vcpu, gva_t eaddr) | 230 | int kvmppc_mmu_dtlb_index(struct kvm_vcpu *vcpu, gva_t eaddr) |
230 | { | 231 | { |
231 | unsigned int as = !!(vcpu->arch.msr & MSR_DS); | 232 | unsigned int as = !!(vcpu->arch.shared->msr & MSR_DS); |
232 | 233 | ||
233 | return kvmppc_44x_tlb_index(vcpu, eaddr, vcpu->arch.pid, as); | 234 | return kvmppc_44x_tlb_index(vcpu, eaddr, vcpu->arch.pid, as); |
234 | } | 235 | } |
@@ -354,7 +355,7 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gpa_t gpaddr, | |||
354 | 355 | ||
355 | stlbe.word1 = (hpaddr & 0xfffffc00) | ((hpaddr >> 32) & 0xf); | 356 | stlbe.word1 = (hpaddr & 0xfffffc00) | ((hpaddr >> 32) & 0xf); |
356 | stlbe.word2 = kvmppc_44x_tlb_shadow_attrib(flags, | 357 | stlbe.word2 = kvmppc_44x_tlb_shadow_attrib(flags, |
357 | vcpu->arch.msr & MSR_PR); | 358 | vcpu->arch.shared->msr & MSR_PR); |
358 | stlbe.tid = !(asid & 0xff); | 359 | stlbe.tid = !(asid & 0xff); |
359 | 360 | ||
360 | /* Keep track of the reference so we can properly release it later. */ | 361 | /* Keep track of the reference so we can properly release it later. */ |
@@ -423,7 +424,7 @@ static int tlbe_is_host_safe(const struct kvm_vcpu *vcpu, | |||
423 | 424 | ||
424 | /* Does it match current guest AS? */ | 425 | /* Does it match current guest AS? */ |
425 | /* XXX what about IS != DS? */ | 426 | /* XXX what about IS != DS? */ |
426 | if (get_tlb_ts(tlbe) != !!(vcpu->arch.msr & MSR_IS)) | 427 | if (get_tlb_ts(tlbe) != !!(vcpu->arch.shared->msr & MSR_IS)) |
427 | return 0; | 428 | return 0; |
428 | 429 | ||
429 | gpa = get_tlb_raddr(tlbe); | 430 | gpa = get_tlb_raddr(tlbe); |
diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile index d45c818a384c..4d6863823f69 100644 --- a/arch/powerpc/kvm/Makefile +++ b/arch/powerpc/kvm/Makefile | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror | 5 | subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror |
6 | 6 | ||
7 | EXTRA_CFLAGS += -Ivirt/kvm -Iarch/powerpc/kvm | 7 | ccflags-y := -Ivirt/kvm -Iarch/powerpc/kvm |
8 | 8 | ||
9 | common-objs-y = $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o) | 9 | common-objs-y = $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o) |
10 | 10 | ||
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c index a3cef30d1d42..e316847c08c0 100644 --- a/arch/powerpc/kvm/book3s.c +++ b/arch/powerpc/kvm/book3s.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/kvm_host.h> | 17 | #include <linux/kvm_host.h> |
18 | #include <linux/err.h> | 18 | #include <linux/err.h> |
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include "trace.h" | ||
20 | 21 | ||
21 | #include <asm/reg.h> | 22 | #include <asm/reg.h> |
22 | #include <asm/cputable.h> | 23 | #include <asm/cputable.h> |
@@ -35,7 +36,6 @@ | |||
35 | #define VCPU_STAT(x) offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU | 36 | #define VCPU_STAT(x) offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU |
36 | 37 | ||
37 | /* #define EXIT_DEBUG */ | 38 | /* #define EXIT_DEBUG */ |
38 | /* #define EXIT_DEBUG_SIMPLE */ | ||
39 | /* #define DEBUG_EXT */ | 39 | /* #define DEBUG_EXT */ |
40 | 40 | ||
41 | static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr, | 41 | static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr, |
@@ -105,65 +105,71 @@ void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu) | |||
105 | kvmppc_giveup_ext(vcpu, MSR_VSX); | 105 | kvmppc_giveup_ext(vcpu, MSR_VSX); |
106 | } | 106 | } |
107 | 107 | ||
108 | #if defined(EXIT_DEBUG) | ||
109 | static u32 kvmppc_get_dec(struct kvm_vcpu *vcpu) | ||
110 | { | ||
111 | u64 jd = mftb() - vcpu->arch.dec_jiffies; | ||
112 | return vcpu->arch.dec - jd; | ||
113 | } | ||
114 | #endif | ||
115 | |||
116 | static void kvmppc_recalc_shadow_msr(struct kvm_vcpu *vcpu) | 108 | static void kvmppc_recalc_shadow_msr(struct kvm_vcpu *vcpu) |
117 | { | 109 | { |
118 | vcpu->arch.shadow_msr = vcpu->arch.msr; | 110 | ulong smsr = vcpu->arch.shared->msr; |
111 | |||
119 | /* Guest MSR values */ | 112 | /* Guest MSR values */ |
120 | vcpu->arch.shadow_msr &= MSR_FE0 | MSR_FE1 | MSR_SF | MSR_SE | | 113 | smsr &= MSR_FE0 | MSR_FE1 | MSR_SF | MSR_SE | MSR_BE | MSR_DE; |
121 | MSR_BE | MSR_DE; | ||
122 | /* Process MSR values */ | 114 | /* Process MSR values */ |
123 | vcpu->arch.shadow_msr |= MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_PR | | 115 | smsr |= MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_PR | MSR_EE; |
124 | MSR_EE; | ||
125 | /* External providers the guest reserved */ | 116 | /* External providers the guest reserved */ |
126 | vcpu->arch.shadow_msr |= (vcpu->arch.msr & vcpu->arch.guest_owned_ext); | 117 | smsr |= (vcpu->arch.shared->msr & vcpu->arch.guest_owned_ext); |
127 | /* 64-bit Process MSR values */ | 118 | /* 64-bit Process MSR values */ |
128 | #ifdef CONFIG_PPC_BOOK3S_64 | 119 | #ifdef CONFIG_PPC_BOOK3S_64 |
129 | vcpu->arch.shadow_msr |= MSR_ISF | MSR_HV; | 120 | smsr |= MSR_ISF | MSR_HV; |
130 | #endif | 121 | #endif |
122 | vcpu->arch.shadow_msr = smsr; | ||
131 | } | 123 | } |
132 | 124 | ||
133 | void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 msr) | 125 | void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 msr) |
134 | { | 126 | { |
135 | ulong old_msr = vcpu->arch.msr; | 127 | ulong old_msr = vcpu->arch.shared->msr; |
136 | 128 | ||
137 | #ifdef EXIT_DEBUG | 129 | #ifdef EXIT_DEBUG |
138 | printk(KERN_INFO "KVM: Set MSR to 0x%llx\n", msr); | 130 | printk(KERN_INFO "KVM: Set MSR to 0x%llx\n", msr); |
139 | #endif | 131 | #endif |
140 | 132 | ||
141 | msr &= to_book3s(vcpu)->msr_mask; | 133 | msr &= to_book3s(vcpu)->msr_mask; |
142 | vcpu->arch.msr = msr; | 134 | vcpu->arch.shared->msr = msr; |
143 | kvmppc_recalc_shadow_msr(vcpu); | 135 | kvmppc_recalc_shadow_msr(vcpu); |
144 | 136 | ||
145 | if (msr & (MSR_WE|MSR_POW)) { | 137 | if (msr & MSR_POW) { |
146 | if (!vcpu->arch.pending_exceptions) { | 138 | if (!vcpu->arch.pending_exceptions) { |
147 | kvm_vcpu_block(vcpu); | 139 | kvm_vcpu_block(vcpu); |
148 | vcpu->stat.halt_wakeup++; | 140 | vcpu->stat.halt_wakeup++; |
141 | |||
142 | /* Unset POW bit after we woke up */ | ||
143 | msr &= ~MSR_POW; | ||
144 | vcpu->arch.shared->msr = msr; | ||
149 | } | 145 | } |
150 | } | 146 | } |
151 | 147 | ||
152 | if ((vcpu->arch.msr & (MSR_PR|MSR_IR|MSR_DR)) != | 148 | if ((vcpu->arch.shared->msr & (MSR_PR|MSR_IR|MSR_DR)) != |
153 | (old_msr & (MSR_PR|MSR_IR|MSR_DR))) { | 149 | (old_msr & (MSR_PR|MSR_IR|MSR_DR))) { |
154 | kvmppc_mmu_flush_segments(vcpu); | 150 | kvmppc_mmu_flush_segments(vcpu); |
155 | kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu)); | 151 | kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu)); |
152 | |||
153 | /* Preload magic page segment when in kernel mode */ | ||
154 | if (!(msr & MSR_PR) && vcpu->arch.magic_page_pa) { | ||
155 | struct kvm_vcpu_arch *a = &vcpu->arch; | ||
156 | |||
157 | if (msr & MSR_DR) | ||
158 | kvmppc_mmu_map_segment(vcpu, a->magic_page_ea); | ||
159 | else | ||
160 | kvmppc_mmu_map_segment(vcpu, a->magic_page_pa); | ||
161 | } | ||
156 | } | 162 | } |
157 | 163 | ||
158 | /* Preload FPU if it's enabled */ | 164 | /* Preload FPU if it's enabled */ |
159 | if (vcpu->arch.msr & MSR_FP) | 165 | if (vcpu->arch.shared->msr & MSR_FP) |
160 | kvmppc_handle_ext(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, MSR_FP); | 166 | kvmppc_handle_ext(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, MSR_FP); |
161 | } | 167 | } |
162 | 168 | ||
163 | void kvmppc_inject_interrupt(struct kvm_vcpu *vcpu, int vec, u64 flags) | 169 | void kvmppc_inject_interrupt(struct kvm_vcpu *vcpu, int vec, u64 flags) |
164 | { | 170 | { |
165 | vcpu->arch.srr0 = kvmppc_get_pc(vcpu); | 171 | vcpu->arch.shared->srr0 = kvmppc_get_pc(vcpu); |
166 | vcpu->arch.srr1 = vcpu->arch.msr | flags; | 172 | vcpu->arch.shared->srr1 = vcpu->arch.shared->msr | flags; |
167 | kvmppc_set_pc(vcpu, to_book3s(vcpu)->hior + vec); | 173 | kvmppc_set_pc(vcpu, to_book3s(vcpu)->hior + vec); |
168 | vcpu->arch.mmu.reset_msr(vcpu); | 174 | vcpu->arch.mmu.reset_msr(vcpu); |
169 | } | 175 | } |
@@ -180,6 +186,7 @@ static int kvmppc_book3s_vec2irqprio(unsigned int vec) | |||
180 | case 0x400: prio = BOOK3S_IRQPRIO_INST_STORAGE; break; | 186 | case 0x400: prio = BOOK3S_IRQPRIO_INST_STORAGE; break; |
181 | case 0x480: prio = BOOK3S_IRQPRIO_INST_SEGMENT; break; | 187 | case 0x480: prio = BOOK3S_IRQPRIO_INST_SEGMENT; break; |
182 | case 0x500: prio = BOOK3S_IRQPRIO_EXTERNAL; break; | 188 | case 0x500: prio = BOOK3S_IRQPRIO_EXTERNAL; break; |
189 | case 0x501: prio = BOOK3S_IRQPRIO_EXTERNAL_LEVEL; break; | ||
183 | case 0x600: prio = BOOK3S_IRQPRIO_ALIGNMENT; break; | 190 | case 0x600: prio = BOOK3S_IRQPRIO_ALIGNMENT; break; |
184 | case 0x700: prio = BOOK3S_IRQPRIO_PROGRAM; break; | 191 | case 0x700: prio = BOOK3S_IRQPRIO_PROGRAM; break; |
185 | case 0x800: prio = BOOK3S_IRQPRIO_FP_UNAVAIL; break; | 192 | case 0x800: prio = BOOK3S_IRQPRIO_FP_UNAVAIL; break; |
@@ -199,6 +206,9 @@ static void kvmppc_book3s_dequeue_irqprio(struct kvm_vcpu *vcpu, | |||
199 | { | 206 | { |
200 | clear_bit(kvmppc_book3s_vec2irqprio(vec), | 207 | clear_bit(kvmppc_book3s_vec2irqprio(vec), |
201 | &vcpu->arch.pending_exceptions); | 208 | &vcpu->arch.pending_exceptions); |
209 | |||
210 | if (!vcpu->arch.pending_exceptions) | ||
211 | vcpu->arch.shared->int_pending = 0; | ||
202 | } | 212 | } |
203 | 213 | ||
204 | void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec) | 214 | void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec) |
@@ -237,13 +247,19 @@ void kvmppc_core_dequeue_dec(struct kvm_vcpu *vcpu) | |||
237 | void kvmppc_core_queue_external(struct kvm_vcpu *vcpu, | 247 | void kvmppc_core_queue_external(struct kvm_vcpu *vcpu, |
238 | struct kvm_interrupt *irq) | 248 | struct kvm_interrupt *irq) |
239 | { | 249 | { |
240 | kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_EXTERNAL); | 250 | unsigned int vec = BOOK3S_INTERRUPT_EXTERNAL; |
251 | |||
252 | if (irq->irq == KVM_INTERRUPT_SET_LEVEL) | ||
253 | vec = BOOK3S_INTERRUPT_EXTERNAL_LEVEL; | ||
254 | |||
255 | kvmppc_book3s_queue_irqprio(vcpu, vec); | ||
241 | } | 256 | } |
242 | 257 | ||
243 | void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu, | 258 | void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu, |
244 | struct kvm_interrupt *irq) | 259 | struct kvm_interrupt *irq) |
245 | { | 260 | { |
246 | kvmppc_book3s_dequeue_irqprio(vcpu, BOOK3S_INTERRUPT_EXTERNAL); | 261 | kvmppc_book3s_dequeue_irqprio(vcpu, BOOK3S_INTERRUPT_EXTERNAL); |
262 | kvmppc_book3s_dequeue_irqprio(vcpu, BOOK3S_INTERRUPT_EXTERNAL_LEVEL); | ||
247 | } | 263 | } |
248 | 264 | ||
249 | int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority) | 265 | int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority) |
@@ -251,14 +267,29 @@ int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority) | |||
251 | int deliver = 1; | 267 | int deliver = 1; |
252 | int vec = 0; | 268 | int vec = 0; |
253 | ulong flags = 0ULL; | 269 | ulong flags = 0ULL; |
270 | ulong crit_raw = vcpu->arch.shared->critical; | ||
271 | ulong crit_r1 = kvmppc_get_gpr(vcpu, 1); | ||
272 | bool crit; | ||
273 | |||
274 | /* Truncate crit indicators in 32 bit mode */ | ||
275 | if (!(vcpu->arch.shared->msr & MSR_SF)) { | ||
276 | crit_raw &= 0xffffffff; | ||
277 | crit_r1 &= 0xffffffff; | ||
278 | } | ||
279 | |||
280 | /* Critical section when crit == r1 */ | ||
281 | crit = (crit_raw == crit_r1); | ||
282 | /* ... and we're in supervisor mode */ | ||
283 | crit = crit && !(vcpu->arch.shared->msr & MSR_PR); | ||
254 | 284 | ||
255 | switch (priority) { | 285 | switch (priority) { |
256 | case BOOK3S_IRQPRIO_DECREMENTER: | 286 | case BOOK3S_IRQPRIO_DECREMENTER: |
257 | deliver = vcpu->arch.msr & MSR_EE; | 287 | deliver = (vcpu->arch.shared->msr & MSR_EE) && !crit; |
258 | vec = BOOK3S_INTERRUPT_DECREMENTER; | 288 | vec = BOOK3S_INTERRUPT_DECREMENTER; |
259 | break; | 289 | break; |
260 | case BOOK3S_IRQPRIO_EXTERNAL: | 290 | case BOOK3S_IRQPRIO_EXTERNAL: |
261 | deliver = vcpu->arch.msr & MSR_EE; | 291 | case BOOK3S_IRQPRIO_EXTERNAL_LEVEL: |
292 | deliver = (vcpu->arch.shared->msr & MSR_EE) && !crit; | ||
262 | vec = BOOK3S_INTERRUPT_EXTERNAL; | 293 | vec = BOOK3S_INTERRUPT_EXTERNAL; |
263 | break; | 294 | break; |
264 | case BOOK3S_IRQPRIO_SYSTEM_RESET: | 295 | case BOOK3S_IRQPRIO_SYSTEM_RESET: |
@@ -320,9 +351,27 @@ int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority) | |||
320 | return deliver; | 351 | return deliver; |
321 | } | 352 | } |
322 | 353 | ||
354 | /* | ||
355 | * This function determines if an irqprio should be cleared once issued. | ||
356 | */ | ||
357 | static bool clear_irqprio(struct kvm_vcpu *vcpu, unsigned int priority) | ||
358 | { | ||
359 | switch (priority) { | ||
360 | case BOOK3S_IRQPRIO_DECREMENTER: | ||
361 | /* DEC interrupts get cleared by mtdec */ | ||
362 | return false; | ||
363 | case BOOK3S_IRQPRIO_EXTERNAL_LEVEL: | ||
364 | /* External interrupts get cleared by userspace */ | ||
365 | return false; | ||
366 | } | ||
367 | |||
368 | return true; | ||
369 | } | ||
370 | |||
323 | void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu) | 371 | void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu) |
324 | { | 372 | { |
325 | unsigned long *pending = &vcpu->arch.pending_exceptions; | 373 | unsigned long *pending = &vcpu->arch.pending_exceptions; |
374 | unsigned long old_pending = vcpu->arch.pending_exceptions; | ||
326 | unsigned int priority; | 375 | unsigned int priority; |
327 | 376 | ||
328 | #ifdef EXIT_DEBUG | 377 | #ifdef EXIT_DEBUG |
@@ -332,8 +381,7 @@ void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu) | |||
332 | priority = __ffs(*pending); | 381 | priority = __ffs(*pending); |
333 | while (priority < BOOK3S_IRQPRIO_MAX) { | 382 | while (priority < BOOK3S_IRQPRIO_MAX) { |
334 | if (kvmppc_book3s_irqprio_deliver(vcpu, priority) && | 383 | if (kvmppc_book3s_irqprio_deliver(vcpu, priority) && |
335 | (priority != BOOK3S_IRQPRIO_DECREMENTER)) { | 384 | clear_irqprio(vcpu, priority)) { |
336 | /* DEC interrupts get cleared by mtdec */ | ||
337 | clear_bit(priority, &vcpu->arch.pending_exceptions); | 385 | clear_bit(priority, &vcpu->arch.pending_exceptions); |
338 | break; | 386 | break; |
339 | } | 387 | } |
@@ -342,6 +390,12 @@ void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu) | |||
342 | BITS_PER_BYTE * sizeof(*pending), | 390 | BITS_PER_BYTE * sizeof(*pending), |
343 | priority + 1); | 391 | priority + 1); |
344 | } | 392 | } |
393 | |||
394 | /* Tell the guest about our interrupt status */ | ||
395 | if (*pending) | ||
396 | vcpu->arch.shared->int_pending = 1; | ||
397 | else if (old_pending) | ||
398 | vcpu->arch.shared->int_pending = 0; | ||
345 | } | 399 | } |
346 | 400 | ||
347 | void kvmppc_set_pvr(struct kvm_vcpu *vcpu, u32 pvr) | 401 | void kvmppc_set_pvr(struct kvm_vcpu *vcpu, u32 pvr) |
@@ -398,6 +452,25 @@ void kvmppc_set_pvr(struct kvm_vcpu *vcpu, u32 pvr) | |||
398 | } | 452 | } |
399 | } | 453 | } |
400 | 454 | ||
455 | pfn_t kvmppc_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn) | ||
456 | { | ||
457 | ulong mp_pa = vcpu->arch.magic_page_pa; | ||
458 | |||
459 | /* Magic page override */ | ||
460 | if (unlikely(mp_pa) && | ||
461 | unlikely(((gfn << PAGE_SHIFT) & KVM_PAM) == | ||
462 | ((mp_pa & PAGE_MASK) & KVM_PAM))) { | ||
463 | ulong shared_page = ((ulong)vcpu->arch.shared) & PAGE_MASK; | ||
464 | pfn_t pfn; | ||
465 | |||
466 | pfn = (pfn_t)virt_to_phys((void*)shared_page) >> PAGE_SHIFT; | ||
467 | get_page(pfn_to_page(pfn)); | ||
468 | return pfn; | ||
469 | } | ||
470 | |||
471 | return gfn_to_pfn(vcpu->kvm, gfn); | ||
472 | } | ||
473 | |||
401 | /* Book3s_32 CPUs always have 32 bytes cache line size, which Linux assumes. To | 474 | /* Book3s_32 CPUs always have 32 bytes cache line size, which Linux assumes. To |
402 | * make Book3s_32 Linux work on Book3s_64, we have to make sure we trap dcbz to | 475 | * make Book3s_32 Linux work on Book3s_64, we have to make sure we trap dcbz to |
403 | * emulate 32 bytes dcbz length. | 476 | * emulate 32 bytes dcbz length. |
@@ -415,8 +488,10 @@ static void kvmppc_patch_dcbz(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte) | |||
415 | int i; | 488 | int i; |
416 | 489 | ||
417 | hpage = gfn_to_page(vcpu->kvm, pte->raddr >> PAGE_SHIFT); | 490 | hpage = gfn_to_page(vcpu->kvm, pte->raddr >> PAGE_SHIFT); |
418 | if (is_error_page(hpage)) | 491 | if (is_error_page(hpage)) { |
492 | kvm_release_page_clean(hpage); | ||
419 | return; | 493 | return; |
494 | } | ||
420 | 495 | ||
421 | hpage_offset = pte->raddr & ~PAGE_MASK; | 496 | hpage_offset = pte->raddr & ~PAGE_MASK; |
422 | hpage_offset &= ~0xFFFULL; | 497 | hpage_offset &= ~0xFFFULL; |
@@ -437,14 +512,14 @@ static void kvmppc_patch_dcbz(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte) | |||
437 | static int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, bool data, | 512 | static int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, bool data, |
438 | struct kvmppc_pte *pte) | 513 | struct kvmppc_pte *pte) |
439 | { | 514 | { |
440 | int relocated = (vcpu->arch.msr & (data ? MSR_DR : MSR_IR)); | 515 | int relocated = (vcpu->arch.shared->msr & (data ? MSR_DR : MSR_IR)); |
441 | int r; | 516 | int r; |
442 | 517 | ||
443 | if (relocated) { | 518 | if (relocated) { |
444 | r = vcpu->arch.mmu.xlate(vcpu, eaddr, pte, data); | 519 | r = vcpu->arch.mmu.xlate(vcpu, eaddr, pte, data); |
445 | } else { | 520 | } else { |
446 | pte->eaddr = eaddr; | 521 | pte->eaddr = eaddr; |
447 | pte->raddr = eaddr & 0xffffffff; | 522 | pte->raddr = eaddr & KVM_PAM; |
448 | pte->vpage = VSID_REAL | eaddr >> 12; | 523 | pte->vpage = VSID_REAL | eaddr >> 12; |
449 | pte->may_read = true; | 524 | pte->may_read = true; |
450 | pte->may_write = true; | 525 | pte->may_write = true; |
@@ -533,6 +608,13 @@ mmio: | |||
533 | 608 | ||
534 | static int kvmppc_visible_gfn(struct kvm_vcpu *vcpu, gfn_t gfn) | 609 | static int kvmppc_visible_gfn(struct kvm_vcpu *vcpu, gfn_t gfn) |
535 | { | 610 | { |
611 | ulong mp_pa = vcpu->arch.magic_page_pa; | ||
612 | |||
613 | if (unlikely(mp_pa) && | ||
614 | unlikely((mp_pa & KVM_PAM) >> PAGE_SHIFT == gfn)) { | ||
615 | return 1; | ||
616 | } | ||
617 | |||
536 | return kvm_is_visible_gfn(vcpu->kvm, gfn); | 618 | return kvm_is_visible_gfn(vcpu->kvm, gfn); |
537 | } | 619 | } |
538 | 620 | ||
@@ -545,8 +627,8 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
545 | int page_found = 0; | 627 | int page_found = 0; |
546 | struct kvmppc_pte pte; | 628 | struct kvmppc_pte pte; |
547 | bool is_mmio = false; | 629 | bool is_mmio = false; |
548 | bool dr = (vcpu->arch.msr & MSR_DR) ? true : false; | 630 | bool dr = (vcpu->arch.shared->msr & MSR_DR) ? true : false; |
549 | bool ir = (vcpu->arch.msr & MSR_IR) ? true : false; | 631 | bool ir = (vcpu->arch.shared->msr & MSR_IR) ? true : false; |
550 | u64 vsid; | 632 | u64 vsid; |
551 | 633 | ||
552 | relocated = data ? dr : ir; | 634 | relocated = data ? dr : ir; |
@@ -558,12 +640,12 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
558 | pte.may_execute = true; | 640 | pte.may_execute = true; |
559 | pte.may_read = true; | 641 | pte.may_read = true; |
560 | pte.may_write = true; | 642 | pte.may_write = true; |
561 | pte.raddr = eaddr & 0xffffffff; | 643 | pte.raddr = eaddr & KVM_PAM; |
562 | pte.eaddr = eaddr; | 644 | pte.eaddr = eaddr; |
563 | pte.vpage = eaddr >> 12; | 645 | pte.vpage = eaddr >> 12; |
564 | } | 646 | } |
565 | 647 | ||
566 | switch (vcpu->arch.msr & (MSR_DR|MSR_IR)) { | 648 | switch (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) { |
567 | case 0: | 649 | case 0: |
568 | pte.vpage |= ((u64)VSID_REAL << (SID_SHIFT - 12)); | 650 | pte.vpage |= ((u64)VSID_REAL << (SID_SHIFT - 12)); |
569 | break; | 651 | break; |
@@ -571,7 +653,7 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
571 | case MSR_IR: | 653 | case MSR_IR: |
572 | vcpu->arch.mmu.esid_to_vsid(vcpu, eaddr >> SID_SHIFT, &vsid); | 654 | vcpu->arch.mmu.esid_to_vsid(vcpu, eaddr >> SID_SHIFT, &vsid); |
573 | 655 | ||
574 | if ((vcpu->arch.msr & (MSR_DR|MSR_IR)) == MSR_DR) | 656 | if ((vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) == MSR_DR) |
575 | pte.vpage |= ((u64)VSID_REAL_DR << (SID_SHIFT - 12)); | 657 | pte.vpage |= ((u64)VSID_REAL_DR << (SID_SHIFT - 12)); |
576 | else | 658 | else |
577 | pte.vpage |= ((u64)VSID_REAL_IR << (SID_SHIFT - 12)); | 659 | pte.vpage |= ((u64)VSID_REAL_IR << (SID_SHIFT - 12)); |
@@ -594,20 +676,23 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
594 | 676 | ||
595 | if (page_found == -ENOENT) { | 677 | if (page_found == -ENOENT) { |
596 | /* Page not found in guest PTE entries */ | 678 | /* Page not found in guest PTE entries */ |
597 | vcpu->arch.dear = kvmppc_get_fault_dar(vcpu); | 679 | vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu); |
598 | to_book3s(vcpu)->dsisr = to_svcpu(vcpu)->fault_dsisr; | 680 | vcpu->arch.shared->dsisr = to_svcpu(vcpu)->fault_dsisr; |
599 | vcpu->arch.msr |= (to_svcpu(vcpu)->shadow_srr1 & 0x00000000f8000000ULL); | 681 | vcpu->arch.shared->msr |= |
682 | (to_svcpu(vcpu)->shadow_srr1 & 0x00000000f8000000ULL); | ||
600 | kvmppc_book3s_queue_irqprio(vcpu, vec); | 683 | kvmppc_book3s_queue_irqprio(vcpu, vec); |
601 | } else if (page_found == -EPERM) { | 684 | } else if (page_found == -EPERM) { |
602 | /* Storage protection */ | 685 | /* Storage protection */ |
603 | vcpu->arch.dear = kvmppc_get_fault_dar(vcpu); | 686 | vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu); |
604 | to_book3s(vcpu)->dsisr = to_svcpu(vcpu)->fault_dsisr & ~DSISR_NOHPTE; | 687 | vcpu->arch.shared->dsisr = |
605 | to_book3s(vcpu)->dsisr |= DSISR_PROTFAULT; | 688 | to_svcpu(vcpu)->fault_dsisr & ~DSISR_NOHPTE; |
606 | vcpu->arch.msr |= (to_svcpu(vcpu)->shadow_srr1 & 0x00000000f8000000ULL); | 689 | vcpu->arch.shared->dsisr |= DSISR_PROTFAULT; |
690 | vcpu->arch.shared->msr |= | ||
691 | (to_svcpu(vcpu)->shadow_srr1 & 0x00000000f8000000ULL); | ||
607 | kvmppc_book3s_queue_irqprio(vcpu, vec); | 692 | kvmppc_book3s_queue_irqprio(vcpu, vec); |
608 | } else if (page_found == -EINVAL) { | 693 | } else if (page_found == -EINVAL) { |
609 | /* Page not found in guest SLB */ | 694 | /* Page not found in guest SLB */ |
610 | vcpu->arch.dear = kvmppc_get_fault_dar(vcpu); | 695 | vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu); |
611 | kvmppc_book3s_queue_irqprio(vcpu, vec + 0x80); | 696 | kvmppc_book3s_queue_irqprio(vcpu, vec + 0x80); |
612 | } else if (!is_mmio && | 697 | } else if (!is_mmio && |
613 | kvmppc_visible_gfn(vcpu, pte.raddr >> PAGE_SHIFT)) { | 698 | kvmppc_visible_gfn(vcpu, pte.raddr >> PAGE_SHIFT)) { |
@@ -695,9 +780,11 @@ static int kvmppc_read_inst(struct kvm_vcpu *vcpu) | |||
695 | 780 | ||
696 | ret = kvmppc_ld(vcpu, &srr0, sizeof(u32), &last_inst, false); | 781 | ret = kvmppc_ld(vcpu, &srr0, sizeof(u32), &last_inst, false); |
697 | if (ret == -ENOENT) { | 782 | if (ret == -ENOENT) { |
698 | vcpu->arch.msr = kvmppc_set_field(vcpu->arch.msr, 33, 33, 1); | 783 | ulong msr = vcpu->arch.shared->msr; |
699 | vcpu->arch.msr = kvmppc_set_field(vcpu->arch.msr, 34, 36, 0); | 784 | |
700 | vcpu->arch.msr = kvmppc_set_field(vcpu->arch.msr, 42, 47, 0); | 785 | msr = kvmppc_set_field(msr, 33, 33, 1); |
786 | msr = kvmppc_set_field(msr, 34, 36, 0); | ||
787 | vcpu->arch.shared->msr = kvmppc_set_field(msr, 42, 47, 0); | ||
701 | kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_INST_STORAGE); | 788 | kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_INST_STORAGE); |
702 | return EMULATE_AGAIN; | 789 | return EMULATE_AGAIN; |
703 | } | 790 | } |
@@ -736,7 +823,7 @@ static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr, | |||
736 | if (vcpu->arch.hflags & BOOK3S_HFLAG_PAIRED_SINGLE) | 823 | if (vcpu->arch.hflags & BOOK3S_HFLAG_PAIRED_SINGLE) |
737 | return RESUME_GUEST; | 824 | return RESUME_GUEST; |
738 | 825 | ||
739 | if (!(vcpu->arch.msr & msr)) { | 826 | if (!(vcpu->arch.shared->msr & msr)) { |
740 | kvmppc_book3s_queue_irqprio(vcpu, exit_nr); | 827 | kvmppc_book3s_queue_irqprio(vcpu, exit_nr); |
741 | return RESUME_GUEST; | 828 | return RESUME_GUEST; |
742 | } | 829 | } |
@@ -796,16 +883,8 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
796 | 883 | ||
797 | run->exit_reason = KVM_EXIT_UNKNOWN; | 884 | run->exit_reason = KVM_EXIT_UNKNOWN; |
798 | run->ready_for_interrupt_injection = 1; | 885 | run->ready_for_interrupt_injection = 1; |
799 | #ifdef EXIT_DEBUG | 886 | |
800 | printk(KERN_EMERG "exit_nr=0x%x | pc=0x%lx | dar=0x%lx | dec=0x%x | msr=0x%lx\n", | 887 | trace_kvm_book3s_exit(exit_nr, vcpu); |
801 | exit_nr, kvmppc_get_pc(vcpu), kvmppc_get_fault_dar(vcpu), | ||
802 | kvmppc_get_dec(vcpu), to_svcpu(vcpu)->shadow_srr1); | ||
803 | #elif defined (EXIT_DEBUG_SIMPLE) | ||
804 | if ((exit_nr != 0x900) && (exit_nr != 0x500)) | ||
805 | printk(KERN_EMERG "exit_nr=0x%x | pc=0x%lx | dar=0x%lx | msr=0x%lx\n", | ||
806 | exit_nr, kvmppc_get_pc(vcpu), kvmppc_get_fault_dar(vcpu), | ||
807 | vcpu->arch.msr); | ||
808 | #endif | ||
809 | kvm_resched(vcpu); | 888 | kvm_resched(vcpu); |
810 | switch (exit_nr) { | 889 | switch (exit_nr) { |
811 | case BOOK3S_INTERRUPT_INST_STORAGE: | 890 | case BOOK3S_INTERRUPT_INST_STORAGE: |
@@ -836,9 +915,9 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
836 | kvmppc_mmu_pte_flush(vcpu, kvmppc_get_pc(vcpu), ~0xFFFUL); | 915 | kvmppc_mmu_pte_flush(vcpu, kvmppc_get_pc(vcpu), ~0xFFFUL); |
837 | r = RESUME_GUEST; | 916 | r = RESUME_GUEST; |
838 | } else { | 917 | } else { |
839 | vcpu->arch.msr |= to_svcpu(vcpu)->shadow_srr1 & 0x58000000; | 918 | vcpu->arch.shared->msr |= |
919 | to_svcpu(vcpu)->shadow_srr1 & 0x58000000; | ||
840 | kvmppc_book3s_queue_irqprio(vcpu, exit_nr); | 920 | kvmppc_book3s_queue_irqprio(vcpu, exit_nr); |
841 | kvmppc_mmu_pte_flush(vcpu, kvmppc_get_pc(vcpu), ~0xFFFUL); | ||
842 | r = RESUME_GUEST; | 921 | r = RESUME_GUEST; |
843 | } | 922 | } |
844 | break; | 923 | break; |
@@ -861,17 +940,16 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
861 | if (to_svcpu(vcpu)->fault_dsisr & DSISR_NOHPTE) { | 940 | if (to_svcpu(vcpu)->fault_dsisr & DSISR_NOHPTE) { |
862 | r = kvmppc_handle_pagefault(run, vcpu, dar, exit_nr); | 941 | r = kvmppc_handle_pagefault(run, vcpu, dar, exit_nr); |
863 | } else { | 942 | } else { |
864 | vcpu->arch.dear = dar; | 943 | vcpu->arch.shared->dar = dar; |
865 | to_book3s(vcpu)->dsisr = to_svcpu(vcpu)->fault_dsisr; | 944 | vcpu->arch.shared->dsisr = to_svcpu(vcpu)->fault_dsisr; |
866 | kvmppc_book3s_queue_irqprio(vcpu, exit_nr); | 945 | kvmppc_book3s_queue_irqprio(vcpu, exit_nr); |
867 | kvmppc_mmu_pte_flush(vcpu, vcpu->arch.dear, ~0xFFFUL); | ||
868 | r = RESUME_GUEST; | 946 | r = RESUME_GUEST; |
869 | } | 947 | } |
870 | break; | 948 | break; |
871 | } | 949 | } |
872 | case BOOK3S_INTERRUPT_DATA_SEGMENT: | 950 | case BOOK3S_INTERRUPT_DATA_SEGMENT: |
873 | if (kvmppc_mmu_map_segment(vcpu, kvmppc_get_fault_dar(vcpu)) < 0) { | 951 | if (kvmppc_mmu_map_segment(vcpu, kvmppc_get_fault_dar(vcpu)) < 0) { |
874 | vcpu->arch.dear = kvmppc_get_fault_dar(vcpu); | 952 | vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu); |
875 | kvmppc_book3s_queue_irqprio(vcpu, | 953 | kvmppc_book3s_queue_irqprio(vcpu, |
876 | BOOK3S_INTERRUPT_DATA_SEGMENT); | 954 | BOOK3S_INTERRUPT_DATA_SEGMENT); |
877 | } | 955 | } |
@@ -904,7 +982,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
904 | program_interrupt: | 982 | program_interrupt: |
905 | flags = to_svcpu(vcpu)->shadow_srr1 & 0x1f0000ull; | 983 | flags = to_svcpu(vcpu)->shadow_srr1 & 0x1f0000ull; |
906 | 984 | ||
907 | if (vcpu->arch.msr & MSR_PR) { | 985 | if (vcpu->arch.shared->msr & MSR_PR) { |
908 | #ifdef EXIT_DEBUG | 986 | #ifdef EXIT_DEBUG |
909 | printk(KERN_INFO "Userspace triggered 0x700 exception at 0x%lx (0x%x)\n", kvmppc_get_pc(vcpu), kvmppc_get_last_inst(vcpu)); | 987 | printk(KERN_INFO "Userspace triggered 0x700 exception at 0x%lx (0x%x)\n", kvmppc_get_pc(vcpu), kvmppc_get_last_inst(vcpu)); |
910 | #endif | 988 | #endif |
@@ -941,10 +1019,10 @@ program_interrupt: | |||
941 | break; | 1019 | break; |
942 | } | 1020 | } |
943 | case BOOK3S_INTERRUPT_SYSCALL: | 1021 | case BOOK3S_INTERRUPT_SYSCALL: |
944 | // XXX make user settable | ||
945 | if (vcpu->arch.osi_enabled && | 1022 | if (vcpu->arch.osi_enabled && |
946 | (((u32)kvmppc_get_gpr(vcpu, 3)) == OSI_SC_MAGIC_R3) && | 1023 | (((u32)kvmppc_get_gpr(vcpu, 3)) == OSI_SC_MAGIC_R3) && |
947 | (((u32)kvmppc_get_gpr(vcpu, 4)) == OSI_SC_MAGIC_R4)) { | 1024 | (((u32)kvmppc_get_gpr(vcpu, 4)) == OSI_SC_MAGIC_R4)) { |
1025 | /* MOL hypercalls */ | ||
948 | u64 *gprs = run->osi.gprs; | 1026 | u64 *gprs = run->osi.gprs; |
949 | int i; | 1027 | int i; |
950 | 1028 | ||
@@ -953,8 +1031,13 @@ program_interrupt: | |||
953 | gprs[i] = kvmppc_get_gpr(vcpu, i); | 1031 | gprs[i] = kvmppc_get_gpr(vcpu, i); |
954 | vcpu->arch.osi_needed = 1; | 1032 | vcpu->arch.osi_needed = 1; |
955 | r = RESUME_HOST_NV; | 1033 | r = RESUME_HOST_NV; |
956 | 1034 | } else if (!(vcpu->arch.shared->msr & MSR_PR) && | |
1035 | (((u32)kvmppc_get_gpr(vcpu, 0)) == KVM_SC_MAGIC_R0)) { | ||
1036 | /* KVM PV hypercalls */ | ||
1037 | kvmppc_set_gpr(vcpu, 3, kvmppc_kvm_pv(vcpu)); | ||
1038 | r = RESUME_GUEST; | ||
957 | } else { | 1039 | } else { |
1040 | /* Guest syscalls */ | ||
958 | vcpu->stat.syscall_exits++; | 1041 | vcpu->stat.syscall_exits++; |
959 | kvmppc_book3s_queue_irqprio(vcpu, exit_nr); | 1042 | kvmppc_book3s_queue_irqprio(vcpu, exit_nr); |
960 | r = RESUME_GUEST; | 1043 | r = RESUME_GUEST; |
@@ -989,9 +1072,9 @@ program_interrupt: | |||
989 | } | 1072 | } |
990 | case BOOK3S_INTERRUPT_ALIGNMENT: | 1073 | case BOOK3S_INTERRUPT_ALIGNMENT: |
991 | if (kvmppc_read_inst(vcpu) == EMULATE_DONE) { | 1074 | if (kvmppc_read_inst(vcpu) == EMULATE_DONE) { |
992 | to_book3s(vcpu)->dsisr = kvmppc_alignment_dsisr(vcpu, | 1075 | vcpu->arch.shared->dsisr = kvmppc_alignment_dsisr(vcpu, |
993 | kvmppc_get_last_inst(vcpu)); | 1076 | kvmppc_get_last_inst(vcpu)); |
994 | vcpu->arch.dear = kvmppc_alignment_dar(vcpu, | 1077 | vcpu->arch.shared->dar = kvmppc_alignment_dar(vcpu, |
995 | kvmppc_get_last_inst(vcpu)); | 1078 | kvmppc_get_last_inst(vcpu)); |
996 | kvmppc_book3s_queue_irqprio(vcpu, exit_nr); | 1079 | kvmppc_book3s_queue_irqprio(vcpu, exit_nr); |
997 | } | 1080 | } |
@@ -1031,9 +1114,7 @@ program_interrupt: | |||
1031 | } | 1114 | } |
1032 | } | 1115 | } |
1033 | 1116 | ||
1034 | #ifdef EXIT_DEBUG | 1117 | trace_kvm_book3s_reenter(r, vcpu); |
1035 | printk(KERN_EMERG "KVM exit: vcpu=0x%p pc=0x%lx r=0x%x\n", vcpu, kvmppc_get_pc(vcpu), r); | ||
1036 | #endif | ||
1037 | 1118 | ||
1038 | return r; | 1119 | return r; |
1039 | } | 1120 | } |
@@ -1052,14 +1133,14 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) | |||
1052 | regs->ctr = kvmppc_get_ctr(vcpu); | 1133 | regs->ctr = kvmppc_get_ctr(vcpu); |
1053 | regs->lr = kvmppc_get_lr(vcpu); | 1134 | regs->lr = kvmppc_get_lr(vcpu); |
1054 | regs->xer = kvmppc_get_xer(vcpu); | 1135 | regs->xer = kvmppc_get_xer(vcpu); |
1055 | regs->msr = vcpu->arch.msr; | 1136 | regs->msr = vcpu->arch.shared->msr; |
1056 | regs->srr0 = vcpu->arch.srr0; | 1137 | regs->srr0 = vcpu->arch.shared->srr0; |
1057 | regs->srr1 = vcpu->arch.srr1; | 1138 | regs->srr1 = vcpu->arch.shared->srr1; |
1058 | regs->pid = vcpu->arch.pid; | 1139 | regs->pid = vcpu->arch.pid; |
1059 | regs->sprg0 = vcpu->arch.sprg0; | 1140 | regs->sprg0 = vcpu->arch.shared->sprg0; |
1060 | regs->sprg1 = vcpu->arch.sprg1; | 1141 | regs->sprg1 = vcpu->arch.shared->sprg1; |
1061 | regs->sprg2 = vcpu->arch.sprg2; | 1142 | regs->sprg2 = vcpu->arch.shared->sprg2; |
1062 | regs->sprg3 = vcpu->arch.sprg3; | 1143 | regs->sprg3 = vcpu->arch.shared->sprg3; |
1063 | regs->sprg5 = vcpu->arch.sprg4; | 1144 | regs->sprg5 = vcpu->arch.sprg4; |
1064 | regs->sprg6 = vcpu->arch.sprg5; | 1145 | regs->sprg6 = vcpu->arch.sprg5; |
1065 | regs->sprg7 = vcpu->arch.sprg6; | 1146 | regs->sprg7 = vcpu->arch.sprg6; |
@@ -1080,12 +1161,12 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) | |||
1080 | kvmppc_set_lr(vcpu, regs->lr); | 1161 | kvmppc_set_lr(vcpu, regs->lr); |
1081 | kvmppc_set_xer(vcpu, regs->xer); | 1162 | kvmppc_set_xer(vcpu, regs->xer); |
1082 | kvmppc_set_msr(vcpu, regs->msr); | 1163 | kvmppc_set_msr(vcpu, regs->msr); |
1083 | vcpu->arch.srr0 = regs->srr0; | 1164 | vcpu->arch.shared->srr0 = regs->srr0; |
1084 | vcpu->arch.srr1 = regs->srr1; | 1165 | vcpu->arch.shared->srr1 = regs->srr1; |
1085 | vcpu->arch.sprg0 = regs->sprg0; | 1166 | vcpu->arch.shared->sprg0 = regs->sprg0; |
1086 | vcpu->arch.sprg1 = regs->sprg1; | 1167 | vcpu->arch.shared->sprg1 = regs->sprg1; |
1087 | vcpu->arch.sprg2 = regs->sprg2; | 1168 | vcpu->arch.shared->sprg2 = regs->sprg2; |
1088 | vcpu->arch.sprg3 = regs->sprg3; | 1169 | vcpu->arch.shared->sprg3 = regs->sprg3; |
1089 | vcpu->arch.sprg5 = regs->sprg4; | 1170 | vcpu->arch.sprg5 = regs->sprg4; |
1090 | vcpu->arch.sprg6 = regs->sprg5; | 1171 | vcpu->arch.sprg6 = regs->sprg5; |
1091 | vcpu->arch.sprg7 = regs->sprg6; | 1172 | vcpu->arch.sprg7 = regs->sprg6; |
@@ -1111,10 +1192,9 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu, | |||
1111 | sregs->u.s.ppc64.slb[i].slbv = vcpu3s->slb[i].origv; | 1192 | sregs->u.s.ppc64.slb[i].slbv = vcpu3s->slb[i].origv; |
1112 | } | 1193 | } |
1113 | } else { | 1194 | } else { |
1114 | for (i = 0; i < 16; i++) { | 1195 | for (i = 0; i < 16; i++) |
1115 | sregs->u.s.ppc32.sr[i] = vcpu3s->sr[i].raw; | 1196 | sregs->u.s.ppc32.sr[i] = vcpu->arch.shared->sr[i]; |
1116 | sregs->u.s.ppc32.sr[i] = vcpu3s->sr[i].raw; | 1197 | |
1117 | } | ||
1118 | for (i = 0; i < 8; i++) { | 1198 | for (i = 0; i < 8; i++) { |
1119 | sregs->u.s.ppc32.ibat[i] = vcpu3s->ibat[i].raw; | 1199 | sregs->u.s.ppc32.ibat[i] = vcpu3s->ibat[i].raw; |
1120 | sregs->u.s.ppc32.dbat[i] = vcpu3s->dbat[i].raw; | 1200 | sregs->u.s.ppc32.dbat[i] = vcpu3s->dbat[i].raw; |
@@ -1225,6 +1305,7 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id) | |||
1225 | struct kvmppc_vcpu_book3s *vcpu_book3s; | 1305 | struct kvmppc_vcpu_book3s *vcpu_book3s; |
1226 | struct kvm_vcpu *vcpu; | 1306 | struct kvm_vcpu *vcpu; |
1227 | int err = -ENOMEM; | 1307 | int err = -ENOMEM; |
1308 | unsigned long p; | ||
1228 | 1309 | ||
1229 | vcpu_book3s = vmalloc(sizeof(struct kvmppc_vcpu_book3s)); | 1310 | vcpu_book3s = vmalloc(sizeof(struct kvmppc_vcpu_book3s)); |
1230 | if (!vcpu_book3s) | 1311 | if (!vcpu_book3s) |
@@ -1242,6 +1323,12 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id) | |||
1242 | if (err) | 1323 | if (err) |
1243 | goto free_shadow_vcpu; | 1324 | goto free_shadow_vcpu; |
1244 | 1325 | ||
1326 | p = __get_free_page(GFP_KERNEL|__GFP_ZERO); | ||
1327 | /* the real shared page fills the last 4k of our page */ | ||
1328 | vcpu->arch.shared = (void*)(p + PAGE_SIZE - 4096); | ||
1329 | if (!p) | ||
1330 | goto uninit_vcpu; | ||
1331 | |||
1245 | vcpu->arch.host_retip = kvm_return_point; | 1332 | vcpu->arch.host_retip = kvm_return_point; |
1246 | vcpu->arch.host_msr = mfmsr(); | 1333 | vcpu->arch.host_msr = mfmsr(); |
1247 | #ifdef CONFIG_PPC_BOOK3S_64 | 1334 | #ifdef CONFIG_PPC_BOOK3S_64 |
@@ -1268,10 +1355,12 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id) | |||
1268 | 1355 | ||
1269 | err = kvmppc_mmu_init(vcpu); | 1356 | err = kvmppc_mmu_init(vcpu); |
1270 | if (err < 0) | 1357 | if (err < 0) |
1271 | goto free_shadow_vcpu; | 1358 | goto uninit_vcpu; |
1272 | 1359 | ||
1273 | return vcpu; | 1360 | return vcpu; |
1274 | 1361 | ||
1362 | uninit_vcpu: | ||
1363 | kvm_vcpu_uninit(vcpu); | ||
1275 | free_shadow_vcpu: | 1364 | free_shadow_vcpu: |
1276 | kfree(vcpu_book3s->shadow_vcpu); | 1365 | kfree(vcpu_book3s->shadow_vcpu); |
1277 | free_vcpu: | 1366 | free_vcpu: |
@@ -1284,6 +1373,7 @@ void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu) | |||
1284 | { | 1373 | { |
1285 | struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); | 1374 | struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); |
1286 | 1375 | ||
1376 | free_page((unsigned long)vcpu->arch.shared & PAGE_MASK); | ||
1287 | kvm_vcpu_uninit(vcpu); | 1377 | kvm_vcpu_uninit(vcpu); |
1288 | kfree(vcpu_book3s->shadow_vcpu); | 1378 | kfree(vcpu_book3s->shadow_vcpu); |
1289 | vfree(vcpu_book3s); | 1379 | vfree(vcpu_book3s); |
@@ -1346,7 +1436,7 @@ int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) | |||
1346 | local_irq_enable(); | 1436 | local_irq_enable(); |
1347 | 1437 | ||
1348 | /* Preload FPU if it's enabled */ | 1438 | /* Preload FPU if it's enabled */ |
1349 | if (vcpu->arch.msr & MSR_FP) | 1439 | if (vcpu->arch.shared->msr & MSR_FP) |
1350 | kvmppc_handle_ext(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, MSR_FP); | 1440 | kvmppc_handle_ext(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, MSR_FP); |
1351 | 1441 | ||
1352 | ret = __kvmppc_vcpu_entry(kvm_run, vcpu); | 1442 | ret = __kvmppc_vcpu_entry(kvm_run, vcpu); |
diff --git a/arch/powerpc/kvm/book3s_32_mmu.c b/arch/powerpc/kvm/book3s_32_mmu.c index 3292d76101d2..c8cefdd15fd8 100644 --- a/arch/powerpc/kvm/book3s_32_mmu.c +++ b/arch/powerpc/kvm/book3s_32_mmu.c | |||
@@ -58,14 +58,39 @@ static inline bool check_debug_ip(struct kvm_vcpu *vcpu) | |||
58 | #endif | 58 | #endif |
59 | } | 59 | } |
60 | 60 | ||
61 | static inline u32 sr_vsid(u32 sr_raw) | ||
62 | { | ||
63 | return sr_raw & 0x0fffffff; | ||
64 | } | ||
65 | |||
66 | static inline bool sr_valid(u32 sr_raw) | ||
67 | { | ||
68 | return (sr_raw & 0x80000000) ? false : true; | ||
69 | } | ||
70 | |||
71 | static inline bool sr_ks(u32 sr_raw) | ||
72 | { | ||
73 | return (sr_raw & 0x40000000) ? true: false; | ||
74 | } | ||
75 | |||
76 | static inline bool sr_kp(u32 sr_raw) | ||
77 | { | ||
78 | return (sr_raw & 0x20000000) ? true: false; | ||
79 | } | ||
80 | |||
81 | static inline bool sr_nx(u32 sr_raw) | ||
82 | { | ||
83 | return (sr_raw & 0x10000000) ? true: false; | ||
84 | } | ||
85 | |||
61 | static int kvmppc_mmu_book3s_32_xlate_bat(struct kvm_vcpu *vcpu, gva_t eaddr, | 86 | static int kvmppc_mmu_book3s_32_xlate_bat(struct kvm_vcpu *vcpu, gva_t eaddr, |
62 | struct kvmppc_pte *pte, bool data); | 87 | struct kvmppc_pte *pte, bool data); |
63 | static int kvmppc_mmu_book3s_32_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid, | 88 | static int kvmppc_mmu_book3s_32_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid, |
64 | u64 *vsid); | 89 | u64 *vsid); |
65 | 90 | ||
66 | static struct kvmppc_sr *find_sr(struct kvmppc_vcpu_book3s *vcpu_book3s, gva_t eaddr) | 91 | static u32 find_sr(struct kvm_vcpu *vcpu, gva_t eaddr) |
67 | { | 92 | { |
68 | return &vcpu_book3s->sr[(eaddr >> 28) & 0xf]; | 93 | return vcpu->arch.shared->sr[(eaddr >> 28) & 0xf]; |
69 | } | 94 | } |
70 | 95 | ||
71 | static u64 kvmppc_mmu_book3s_32_ea_to_vp(struct kvm_vcpu *vcpu, gva_t eaddr, | 96 | static u64 kvmppc_mmu_book3s_32_ea_to_vp(struct kvm_vcpu *vcpu, gva_t eaddr, |
@@ -87,7 +112,7 @@ static void kvmppc_mmu_book3s_32_reset_msr(struct kvm_vcpu *vcpu) | |||
87 | } | 112 | } |
88 | 113 | ||
89 | static hva_t kvmppc_mmu_book3s_32_get_pteg(struct kvmppc_vcpu_book3s *vcpu_book3s, | 114 | static hva_t kvmppc_mmu_book3s_32_get_pteg(struct kvmppc_vcpu_book3s *vcpu_book3s, |
90 | struct kvmppc_sr *sre, gva_t eaddr, | 115 | u32 sre, gva_t eaddr, |
91 | bool primary) | 116 | bool primary) |
92 | { | 117 | { |
93 | u32 page, hash, pteg, htabmask; | 118 | u32 page, hash, pteg, htabmask; |
@@ -96,7 +121,7 @@ static hva_t kvmppc_mmu_book3s_32_get_pteg(struct kvmppc_vcpu_book3s *vcpu_book3 | |||
96 | page = (eaddr & 0x0FFFFFFF) >> 12; | 121 | page = (eaddr & 0x0FFFFFFF) >> 12; |
97 | htabmask = ((vcpu_book3s->sdr1 & 0x1FF) << 16) | 0xFFC0; | 122 | htabmask = ((vcpu_book3s->sdr1 & 0x1FF) << 16) | 0xFFC0; |
98 | 123 | ||
99 | hash = ((sre->vsid ^ page) << 6); | 124 | hash = ((sr_vsid(sre) ^ page) << 6); |
100 | if (!primary) | 125 | if (!primary) |
101 | hash = ~hash; | 126 | hash = ~hash; |
102 | hash &= htabmask; | 127 | hash &= htabmask; |
@@ -104,8 +129,8 @@ static hva_t kvmppc_mmu_book3s_32_get_pteg(struct kvmppc_vcpu_book3s *vcpu_book3 | |||
104 | pteg = (vcpu_book3s->sdr1 & 0xffff0000) | hash; | 129 | pteg = (vcpu_book3s->sdr1 & 0xffff0000) | hash; |
105 | 130 | ||
106 | dprintk("MMU: pc=0x%lx eaddr=0x%lx sdr1=0x%llx pteg=0x%x vsid=0x%x\n", | 131 | dprintk("MMU: pc=0x%lx eaddr=0x%lx sdr1=0x%llx pteg=0x%x vsid=0x%x\n", |
107 | vcpu_book3s->vcpu.arch.pc, eaddr, vcpu_book3s->sdr1, pteg, | 132 | kvmppc_get_pc(&vcpu_book3s->vcpu), eaddr, vcpu_book3s->sdr1, pteg, |
108 | sre->vsid); | 133 | sr_vsid(sre)); |
109 | 134 | ||
110 | r = gfn_to_hva(vcpu_book3s->vcpu.kvm, pteg >> PAGE_SHIFT); | 135 | r = gfn_to_hva(vcpu_book3s->vcpu.kvm, pteg >> PAGE_SHIFT); |
111 | if (kvm_is_error_hva(r)) | 136 | if (kvm_is_error_hva(r)) |
@@ -113,10 +138,9 @@ static hva_t kvmppc_mmu_book3s_32_get_pteg(struct kvmppc_vcpu_book3s *vcpu_book3 | |||
113 | return r | (pteg & ~PAGE_MASK); | 138 | return r | (pteg & ~PAGE_MASK); |
114 | } | 139 | } |
115 | 140 | ||
116 | static u32 kvmppc_mmu_book3s_32_get_ptem(struct kvmppc_sr *sre, gva_t eaddr, | 141 | static u32 kvmppc_mmu_book3s_32_get_ptem(u32 sre, gva_t eaddr, bool primary) |
117 | bool primary) | ||
118 | { | 142 | { |
119 | return ((eaddr & 0x0fffffff) >> 22) | (sre->vsid << 7) | | 143 | return ((eaddr & 0x0fffffff) >> 22) | (sr_vsid(sre) << 7) | |
120 | (primary ? 0 : 0x40) | 0x80000000; | 144 | (primary ? 0 : 0x40) | 0x80000000; |
121 | } | 145 | } |
122 | 146 | ||
@@ -133,7 +157,7 @@ static int kvmppc_mmu_book3s_32_xlate_bat(struct kvm_vcpu *vcpu, gva_t eaddr, | |||
133 | else | 157 | else |
134 | bat = &vcpu_book3s->ibat[i]; | 158 | bat = &vcpu_book3s->ibat[i]; |
135 | 159 | ||
136 | if (vcpu->arch.msr & MSR_PR) { | 160 | if (vcpu->arch.shared->msr & MSR_PR) { |
137 | if (!bat->vp) | 161 | if (!bat->vp) |
138 | continue; | 162 | continue; |
139 | } else { | 163 | } else { |
@@ -180,17 +204,17 @@ static int kvmppc_mmu_book3s_32_xlate_pte(struct kvm_vcpu *vcpu, gva_t eaddr, | |||
180 | bool primary) | 204 | bool primary) |
181 | { | 205 | { |
182 | struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); | 206 | struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); |
183 | struct kvmppc_sr *sre; | 207 | u32 sre; |
184 | hva_t ptegp; | 208 | hva_t ptegp; |
185 | u32 pteg[16]; | 209 | u32 pteg[16]; |
186 | u32 ptem = 0; | 210 | u32 ptem = 0; |
187 | int i; | 211 | int i; |
188 | int found = 0; | 212 | int found = 0; |
189 | 213 | ||
190 | sre = find_sr(vcpu_book3s, eaddr); | 214 | sre = find_sr(vcpu, eaddr); |
191 | 215 | ||
192 | dprintk_pte("SR 0x%lx: vsid=0x%x, raw=0x%x\n", eaddr >> 28, | 216 | dprintk_pte("SR 0x%lx: vsid=0x%x, raw=0x%x\n", eaddr >> 28, |
193 | sre->vsid, sre->raw); | 217 | sr_vsid(sre), sre); |
194 | 218 | ||
195 | pte->vpage = kvmppc_mmu_book3s_32_ea_to_vp(vcpu, eaddr, data); | 219 | pte->vpage = kvmppc_mmu_book3s_32_ea_to_vp(vcpu, eaddr, data); |
196 | 220 | ||
@@ -214,8 +238,8 @@ static int kvmppc_mmu_book3s_32_xlate_pte(struct kvm_vcpu *vcpu, gva_t eaddr, | |||
214 | pte->raddr = (pteg[i+1] & ~(0xFFFULL)) | (eaddr & 0xFFF); | 238 | pte->raddr = (pteg[i+1] & ~(0xFFFULL)) | (eaddr & 0xFFF); |
215 | pp = pteg[i+1] & 3; | 239 | pp = pteg[i+1] & 3; |
216 | 240 | ||
217 | if ((sre->Kp && (vcpu->arch.msr & MSR_PR)) || | 241 | if ((sr_kp(sre) && (vcpu->arch.shared->msr & MSR_PR)) || |
218 | (sre->Ks && !(vcpu->arch.msr & MSR_PR))) | 242 | (sr_ks(sre) && !(vcpu->arch.shared->msr & MSR_PR))) |
219 | pp |= 4; | 243 | pp |= 4; |
220 | 244 | ||
221 | pte->may_write = false; | 245 | pte->may_write = false; |
@@ -269,7 +293,7 @@ no_page_found: | |||
269 | dprintk_pte("KVM MMU: No PTE found (sdr1=0x%llx ptegp=0x%lx)\n", | 293 | dprintk_pte("KVM MMU: No PTE found (sdr1=0x%llx ptegp=0x%lx)\n", |
270 | to_book3s(vcpu)->sdr1, ptegp); | 294 | to_book3s(vcpu)->sdr1, ptegp); |
271 | for (i=0; i<16; i+=2) { | 295 | for (i=0; i<16; i+=2) { |
272 | dprintk_pte(" %02d: 0x%x - 0x%x (0x%llx)\n", | 296 | dprintk_pte(" %02d: 0x%x - 0x%x (0x%x)\n", |
273 | i, pteg[i], pteg[i+1], ptem); | 297 | i, pteg[i], pteg[i+1], ptem); |
274 | } | 298 | } |
275 | } | 299 | } |
@@ -281,8 +305,24 @@ static int kvmppc_mmu_book3s_32_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, | |||
281 | struct kvmppc_pte *pte, bool data) | 305 | struct kvmppc_pte *pte, bool data) |
282 | { | 306 | { |
283 | int r; | 307 | int r; |
308 | ulong mp_ea = vcpu->arch.magic_page_ea; | ||
284 | 309 | ||
285 | pte->eaddr = eaddr; | 310 | pte->eaddr = eaddr; |
311 | |||
312 | /* Magic page override */ | ||
313 | if (unlikely(mp_ea) && | ||
314 | unlikely((eaddr & ~0xfffULL) == (mp_ea & ~0xfffULL)) && | ||
315 | !(vcpu->arch.shared->msr & MSR_PR)) { | ||
316 | pte->vpage = kvmppc_mmu_book3s_32_ea_to_vp(vcpu, eaddr, data); | ||
317 | pte->raddr = vcpu->arch.magic_page_pa | (pte->raddr & 0xfff); | ||
318 | pte->raddr &= KVM_PAM; | ||
319 | pte->may_execute = true; | ||
320 | pte->may_read = true; | ||
321 | pte->may_write = true; | ||
322 | |||
323 | return 0; | ||
324 | } | ||
325 | |||
286 | r = kvmppc_mmu_book3s_32_xlate_bat(vcpu, eaddr, pte, data); | 326 | r = kvmppc_mmu_book3s_32_xlate_bat(vcpu, eaddr, pte, data); |
287 | if (r < 0) | 327 | if (r < 0) |
288 | r = kvmppc_mmu_book3s_32_xlate_pte(vcpu, eaddr, pte, data, true); | 328 | r = kvmppc_mmu_book3s_32_xlate_pte(vcpu, eaddr, pte, data, true); |
@@ -295,30 +335,13 @@ static int kvmppc_mmu_book3s_32_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, | |||
295 | 335 | ||
296 | static u32 kvmppc_mmu_book3s_32_mfsrin(struct kvm_vcpu *vcpu, u32 srnum) | 336 | static u32 kvmppc_mmu_book3s_32_mfsrin(struct kvm_vcpu *vcpu, u32 srnum) |
297 | { | 337 | { |
298 | return to_book3s(vcpu)->sr[srnum].raw; | 338 | return vcpu->arch.shared->sr[srnum]; |
299 | } | 339 | } |
300 | 340 | ||
301 | static void kvmppc_mmu_book3s_32_mtsrin(struct kvm_vcpu *vcpu, u32 srnum, | 341 | static void kvmppc_mmu_book3s_32_mtsrin(struct kvm_vcpu *vcpu, u32 srnum, |
302 | ulong value) | 342 | ulong value) |
303 | { | 343 | { |
304 | struct kvmppc_sr *sre; | 344 | vcpu->arch.shared->sr[srnum] = value; |
305 | |||
306 | sre = &to_book3s(vcpu)->sr[srnum]; | ||
307 | |||
308 | /* Flush any left-over shadows from the previous SR */ | ||
309 | |||
310 | /* XXX Not necessary? */ | ||
311 | /* kvmppc_mmu_pte_flush(vcpu, ((u64)sre->vsid) << 28, 0xf0000000ULL); */ | ||
312 | |||
313 | /* And then put in the new SR */ | ||
314 | sre->raw = value; | ||
315 | sre->vsid = (value & 0x0fffffff); | ||
316 | sre->valid = (value & 0x80000000) ? false : true; | ||
317 | sre->Ks = (value & 0x40000000) ? true : false; | ||
318 | sre->Kp = (value & 0x20000000) ? true : false; | ||
319 | sre->nx = (value & 0x10000000) ? true : false; | ||
320 | |||
321 | /* Map the new segment */ | ||
322 | kvmppc_mmu_map_segment(vcpu, srnum << SID_SHIFT); | 345 | kvmppc_mmu_map_segment(vcpu, srnum << SID_SHIFT); |
323 | } | 346 | } |
324 | 347 | ||
@@ -331,19 +354,19 @@ static int kvmppc_mmu_book3s_32_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid, | |||
331 | u64 *vsid) | 354 | u64 *vsid) |
332 | { | 355 | { |
333 | ulong ea = esid << SID_SHIFT; | 356 | ulong ea = esid << SID_SHIFT; |
334 | struct kvmppc_sr *sr; | 357 | u32 sr; |
335 | u64 gvsid = esid; | 358 | u64 gvsid = esid; |
336 | 359 | ||
337 | if (vcpu->arch.msr & (MSR_DR|MSR_IR)) { | 360 | if (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) { |
338 | sr = find_sr(to_book3s(vcpu), ea); | 361 | sr = find_sr(vcpu, ea); |
339 | if (sr->valid) | 362 | if (sr_valid(sr)) |
340 | gvsid = sr->vsid; | 363 | gvsid = sr_vsid(sr); |
341 | } | 364 | } |
342 | 365 | ||
343 | /* In case we only have one of MSR_IR or MSR_DR set, let's put | 366 | /* In case we only have one of MSR_IR or MSR_DR set, let's put |
344 | that in the real-mode context (and hope RM doesn't access | 367 | that in the real-mode context (and hope RM doesn't access |
345 | high memory) */ | 368 | high memory) */ |
346 | switch (vcpu->arch.msr & (MSR_DR|MSR_IR)) { | 369 | switch (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) { |
347 | case 0: | 370 | case 0: |
348 | *vsid = VSID_REAL | esid; | 371 | *vsid = VSID_REAL | esid; |
349 | break; | 372 | break; |
@@ -354,8 +377,8 @@ static int kvmppc_mmu_book3s_32_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid, | |||
354 | *vsid = VSID_REAL_DR | gvsid; | 377 | *vsid = VSID_REAL_DR | gvsid; |
355 | break; | 378 | break; |
356 | case MSR_DR|MSR_IR: | 379 | case MSR_DR|MSR_IR: |
357 | if (sr->valid) | 380 | if (sr_valid(sr)) |
358 | *vsid = sr->vsid; | 381 | *vsid = sr_vsid(sr); |
359 | else | 382 | else |
360 | *vsid = VSID_BAT | gvsid; | 383 | *vsid = VSID_BAT | gvsid; |
361 | break; | 384 | break; |
@@ -363,7 +386,7 @@ static int kvmppc_mmu_book3s_32_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid, | |||
363 | BUG(); | 386 | BUG(); |
364 | } | 387 | } |
365 | 388 | ||
366 | if (vcpu->arch.msr & MSR_PR) | 389 | if (vcpu->arch.shared->msr & MSR_PR) |
367 | *vsid |= VSID_PR; | 390 | *vsid |= VSID_PR; |
368 | 391 | ||
369 | return 0; | 392 | return 0; |
diff --git a/arch/powerpc/kvm/book3s_32_mmu_host.c b/arch/powerpc/kvm/book3s_32_mmu_host.c index 0b51ef872c1e..9fecbfbce773 100644 --- a/arch/powerpc/kvm/book3s_32_mmu_host.c +++ b/arch/powerpc/kvm/book3s_32_mmu_host.c | |||
@@ -19,7 +19,6 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | #include <linux/kvm_host.h> | 21 | #include <linux/kvm_host.h> |
22 | #include <linux/hash.h> | ||
23 | 22 | ||
24 | #include <asm/kvm_ppc.h> | 23 | #include <asm/kvm_ppc.h> |
25 | #include <asm/kvm_book3s.h> | 24 | #include <asm/kvm_book3s.h> |
@@ -77,7 +76,14 @@ void kvmppc_mmu_invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte) | |||
77 | * a hash, so we don't waste cycles on looping */ | 76 | * a hash, so we don't waste cycles on looping */ |
78 | static u16 kvmppc_sid_hash(struct kvm_vcpu *vcpu, u64 gvsid) | 77 | static u16 kvmppc_sid_hash(struct kvm_vcpu *vcpu, u64 gvsid) |
79 | { | 78 | { |
80 | return hash_64(gvsid, SID_MAP_BITS); | 79 | return (u16)(((gvsid >> (SID_MAP_BITS * 7)) & SID_MAP_MASK) ^ |
80 | ((gvsid >> (SID_MAP_BITS * 6)) & SID_MAP_MASK) ^ | ||
81 | ((gvsid >> (SID_MAP_BITS * 5)) & SID_MAP_MASK) ^ | ||
82 | ((gvsid >> (SID_MAP_BITS * 4)) & SID_MAP_MASK) ^ | ||
83 | ((gvsid >> (SID_MAP_BITS * 3)) & SID_MAP_MASK) ^ | ||
84 | ((gvsid >> (SID_MAP_BITS * 2)) & SID_MAP_MASK) ^ | ||
85 | ((gvsid >> (SID_MAP_BITS * 1)) & SID_MAP_MASK) ^ | ||
86 | ((gvsid >> (SID_MAP_BITS * 0)) & SID_MAP_MASK)); | ||
81 | } | 87 | } |
82 | 88 | ||
83 | 89 | ||
@@ -86,7 +92,7 @@ static struct kvmppc_sid_map *find_sid_vsid(struct kvm_vcpu *vcpu, u64 gvsid) | |||
86 | struct kvmppc_sid_map *map; | 92 | struct kvmppc_sid_map *map; |
87 | u16 sid_map_mask; | 93 | u16 sid_map_mask; |
88 | 94 | ||
89 | if (vcpu->arch.msr & MSR_PR) | 95 | if (vcpu->arch.shared->msr & MSR_PR) |
90 | gvsid |= VSID_PR; | 96 | gvsid |= VSID_PR; |
91 | 97 | ||
92 | sid_map_mask = kvmppc_sid_hash(vcpu, gvsid); | 98 | sid_map_mask = kvmppc_sid_hash(vcpu, gvsid); |
@@ -147,8 +153,8 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte) | |||
147 | struct hpte_cache *pte; | 153 | struct hpte_cache *pte; |
148 | 154 | ||
149 | /* Get host physical address for gpa */ | 155 | /* Get host physical address for gpa */ |
150 | hpaddr = gfn_to_pfn(vcpu->kvm, orig_pte->raddr >> PAGE_SHIFT); | 156 | hpaddr = kvmppc_gfn_to_pfn(vcpu, orig_pte->raddr >> PAGE_SHIFT); |
151 | if (kvm_is_error_hva(hpaddr)) { | 157 | if (is_error_pfn(hpaddr)) { |
152 | printk(KERN_INFO "Couldn't get guest page for gfn %lx!\n", | 158 | printk(KERN_INFO "Couldn't get guest page for gfn %lx!\n", |
153 | orig_pte->eaddr); | 159 | orig_pte->eaddr); |
154 | return -EINVAL; | 160 | return -EINVAL; |
@@ -253,7 +259,7 @@ static struct kvmppc_sid_map *create_sid_map(struct kvm_vcpu *vcpu, u64 gvsid) | |||
253 | u16 sid_map_mask; | 259 | u16 sid_map_mask; |
254 | static int backwards_map = 0; | 260 | static int backwards_map = 0; |
255 | 261 | ||
256 | if (vcpu->arch.msr & MSR_PR) | 262 | if (vcpu->arch.shared->msr & MSR_PR) |
257 | gvsid |= VSID_PR; | 263 | gvsid |= VSID_PR; |
258 | 264 | ||
259 | /* We might get collisions that trap in preceding order, so let's | 265 | /* We might get collisions that trap in preceding order, so let's |
@@ -269,18 +275,15 @@ static struct kvmppc_sid_map *create_sid_map(struct kvm_vcpu *vcpu, u64 gvsid) | |||
269 | backwards_map = !backwards_map; | 275 | backwards_map = !backwards_map; |
270 | 276 | ||
271 | /* Uh-oh ... out of mappings. Let's flush! */ | 277 | /* Uh-oh ... out of mappings. Let's flush! */ |
272 | if (vcpu_book3s->vsid_next >= vcpu_book3s->vsid_max) { | 278 | if (vcpu_book3s->vsid_next >= VSID_POOL_SIZE) { |
273 | vcpu_book3s->vsid_next = vcpu_book3s->vsid_first; | 279 | vcpu_book3s->vsid_next = 0; |
274 | memset(vcpu_book3s->sid_map, 0, | 280 | memset(vcpu_book3s->sid_map, 0, |
275 | sizeof(struct kvmppc_sid_map) * SID_MAP_NUM); | 281 | sizeof(struct kvmppc_sid_map) * SID_MAP_NUM); |
276 | kvmppc_mmu_pte_flush(vcpu, 0, 0); | 282 | kvmppc_mmu_pte_flush(vcpu, 0, 0); |
277 | kvmppc_mmu_flush_segments(vcpu); | 283 | kvmppc_mmu_flush_segments(vcpu); |
278 | } | 284 | } |
279 | map->host_vsid = vcpu_book3s->vsid_next; | 285 | map->host_vsid = vcpu_book3s->vsid_pool[vcpu_book3s->vsid_next]; |
280 | 286 | vcpu_book3s->vsid_next++; | |
281 | /* Would have to be 111 to be completely aligned with the rest of | ||
282 | Linux, but that is just way too little space! */ | ||
283 | vcpu_book3s->vsid_next+=1; | ||
284 | 287 | ||
285 | map->guest_vsid = gvsid; | 288 | map->guest_vsid = gvsid; |
286 | map->valid = true; | 289 | map->valid = true; |
@@ -327,40 +330,38 @@ void kvmppc_mmu_flush_segments(struct kvm_vcpu *vcpu) | |||
327 | 330 | ||
328 | void kvmppc_mmu_destroy(struct kvm_vcpu *vcpu) | 331 | void kvmppc_mmu_destroy(struct kvm_vcpu *vcpu) |
329 | { | 332 | { |
333 | int i; | ||
334 | |||
330 | kvmppc_mmu_hpte_destroy(vcpu); | 335 | kvmppc_mmu_hpte_destroy(vcpu); |
331 | preempt_disable(); | 336 | preempt_disable(); |
332 | __destroy_context(to_book3s(vcpu)->context_id); | 337 | for (i = 0; i < SID_CONTEXTS; i++) |
338 | __destroy_context(to_book3s(vcpu)->context_id[i]); | ||
333 | preempt_enable(); | 339 | preempt_enable(); |
334 | } | 340 | } |
335 | 341 | ||
336 | /* From mm/mmu_context_hash32.c */ | 342 | /* From mm/mmu_context_hash32.c */ |
337 | #define CTX_TO_VSID(ctx) (((ctx) * (897 * 16)) & 0xffffff) | 343 | #define CTX_TO_VSID(c, id) ((((c) * (897 * 16)) + (id * 0x111)) & 0xffffff) |
338 | 344 | ||
339 | int kvmppc_mmu_init(struct kvm_vcpu *vcpu) | 345 | int kvmppc_mmu_init(struct kvm_vcpu *vcpu) |
340 | { | 346 | { |
341 | struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu); | 347 | struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu); |
342 | int err; | 348 | int err; |
343 | ulong sdr1; | 349 | ulong sdr1; |
350 | int i; | ||
351 | int j; | ||
344 | 352 | ||
345 | err = __init_new_context(); | 353 | for (i = 0; i < SID_CONTEXTS; i++) { |
346 | if (err < 0) | 354 | err = __init_new_context(); |
347 | return -1; | 355 | if (err < 0) |
348 | vcpu3s->context_id = err; | 356 | goto init_fail; |
349 | 357 | vcpu3s->context_id[i] = err; | |
350 | vcpu3s->vsid_max = CTX_TO_VSID(vcpu3s->context_id + 1) - 1; | ||
351 | vcpu3s->vsid_first = CTX_TO_VSID(vcpu3s->context_id); | ||
352 | |||
353 | #if 0 /* XXX still doesn't guarantee uniqueness */ | ||
354 | /* We could collide with the Linux vsid space because the vsid | ||
355 | * wraps around at 24 bits. We're safe if we do our own space | ||
356 | * though, so let's always set the highest bit. */ | ||
357 | 358 | ||
358 | vcpu3s->vsid_max |= 0x00800000; | 359 | /* Remember context id for this combination */ |
359 | vcpu3s->vsid_first |= 0x00800000; | 360 | for (j = 0; j < 16; j++) |
360 | #endif | 361 | vcpu3s->vsid_pool[(i * 16) + j] = CTX_TO_VSID(err, j); |
361 | BUG_ON(vcpu3s->vsid_max < vcpu3s->vsid_first); | 362 | } |
362 | 363 | ||
363 | vcpu3s->vsid_next = vcpu3s->vsid_first; | 364 | vcpu3s->vsid_next = 0; |
364 | 365 | ||
365 | /* Remember where the HTAB is */ | 366 | /* Remember where the HTAB is */ |
366 | asm ( "mfsdr1 %0" : "=r"(sdr1) ); | 367 | asm ( "mfsdr1 %0" : "=r"(sdr1) ); |
@@ -370,4 +371,14 @@ int kvmppc_mmu_init(struct kvm_vcpu *vcpu) | |||
370 | kvmppc_mmu_hpte_init(vcpu); | 371 | kvmppc_mmu_hpte_init(vcpu); |
371 | 372 | ||
372 | return 0; | 373 | return 0; |
374 | |||
375 | init_fail: | ||
376 | for (j = 0; j < i; j++) { | ||
377 | if (!vcpu3s->context_id[j]) | ||
378 | continue; | ||
379 | |||
380 | __destroy_context(to_book3s(vcpu)->context_id[j]); | ||
381 | } | ||
382 | |||
383 | return -1; | ||
373 | } | 384 | } |
diff --git a/arch/powerpc/kvm/book3s_64_mmu.c b/arch/powerpc/kvm/book3s_64_mmu.c index 4025ea26b3c1..d7889ef3211e 100644 --- a/arch/powerpc/kvm/book3s_64_mmu.c +++ b/arch/powerpc/kvm/book3s_64_mmu.c | |||
@@ -163,6 +163,22 @@ static int kvmppc_mmu_book3s_64_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, | |||
163 | bool found = false; | 163 | bool found = false; |
164 | bool perm_err = false; | 164 | bool perm_err = false; |
165 | int second = 0; | 165 | int second = 0; |
166 | ulong mp_ea = vcpu->arch.magic_page_ea; | ||
167 | |||
168 | /* Magic page override */ | ||
169 | if (unlikely(mp_ea) && | ||
170 | unlikely((eaddr & ~0xfffULL) == (mp_ea & ~0xfffULL)) && | ||
171 | !(vcpu->arch.shared->msr & MSR_PR)) { | ||
172 | gpte->eaddr = eaddr; | ||
173 | gpte->vpage = kvmppc_mmu_book3s_64_ea_to_vp(vcpu, eaddr, data); | ||
174 | gpte->raddr = vcpu->arch.magic_page_pa | (gpte->raddr & 0xfff); | ||
175 | gpte->raddr &= KVM_PAM; | ||
176 | gpte->may_execute = true; | ||
177 | gpte->may_read = true; | ||
178 | gpte->may_write = true; | ||
179 | |||
180 | return 0; | ||
181 | } | ||
166 | 182 | ||
167 | slbe = kvmppc_mmu_book3s_64_find_slbe(vcpu_book3s, eaddr); | 183 | slbe = kvmppc_mmu_book3s_64_find_slbe(vcpu_book3s, eaddr); |
168 | if (!slbe) | 184 | if (!slbe) |
@@ -180,9 +196,9 @@ do_second: | |||
180 | goto no_page_found; | 196 | goto no_page_found; |
181 | } | 197 | } |
182 | 198 | ||
183 | if ((vcpu->arch.msr & MSR_PR) && slbe->Kp) | 199 | if ((vcpu->arch.shared->msr & MSR_PR) && slbe->Kp) |
184 | key = 4; | 200 | key = 4; |
185 | else if (!(vcpu->arch.msr & MSR_PR) && slbe->Ks) | 201 | else if (!(vcpu->arch.shared->msr & MSR_PR) && slbe->Ks) |
186 | key = 4; | 202 | key = 4; |
187 | 203 | ||
188 | for (i=0; i<16; i+=2) { | 204 | for (i=0; i<16; i+=2) { |
@@ -381,7 +397,7 @@ static void kvmppc_mmu_book3s_64_slbia(struct kvm_vcpu *vcpu) | |||
381 | for (i = 1; i < vcpu_book3s->slb_nr; i++) | 397 | for (i = 1; i < vcpu_book3s->slb_nr; i++) |
382 | vcpu_book3s->slb[i].valid = false; | 398 | vcpu_book3s->slb[i].valid = false; |
383 | 399 | ||
384 | if (vcpu->arch.msr & MSR_IR) { | 400 | if (vcpu->arch.shared->msr & MSR_IR) { |
385 | kvmppc_mmu_flush_segments(vcpu); | 401 | kvmppc_mmu_flush_segments(vcpu); |
386 | kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu)); | 402 | kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu)); |
387 | } | 403 | } |
@@ -445,14 +461,15 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid, | |||
445 | ulong ea = esid << SID_SHIFT; | 461 | ulong ea = esid << SID_SHIFT; |
446 | struct kvmppc_slb *slb; | 462 | struct kvmppc_slb *slb; |
447 | u64 gvsid = esid; | 463 | u64 gvsid = esid; |
464 | ulong mp_ea = vcpu->arch.magic_page_ea; | ||
448 | 465 | ||
449 | if (vcpu->arch.msr & (MSR_DR|MSR_IR)) { | 466 | if (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) { |
450 | slb = kvmppc_mmu_book3s_64_find_slbe(to_book3s(vcpu), ea); | 467 | slb = kvmppc_mmu_book3s_64_find_slbe(to_book3s(vcpu), ea); |
451 | if (slb) | 468 | if (slb) |
452 | gvsid = slb->vsid; | 469 | gvsid = slb->vsid; |
453 | } | 470 | } |
454 | 471 | ||
455 | switch (vcpu->arch.msr & (MSR_DR|MSR_IR)) { | 472 | switch (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) { |
456 | case 0: | 473 | case 0: |
457 | *vsid = VSID_REAL | esid; | 474 | *vsid = VSID_REAL | esid; |
458 | break; | 475 | break; |
@@ -464,7 +481,7 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid, | |||
464 | break; | 481 | break; |
465 | case MSR_DR|MSR_IR: | 482 | case MSR_DR|MSR_IR: |
466 | if (!slb) | 483 | if (!slb) |
467 | return -ENOENT; | 484 | goto no_slb; |
468 | 485 | ||
469 | *vsid = gvsid; | 486 | *vsid = gvsid; |
470 | break; | 487 | break; |
@@ -473,10 +490,21 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid, | |||
473 | break; | 490 | break; |
474 | } | 491 | } |
475 | 492 | ||
476 | if (vcpu->arch.msr & MSR_PR) | 493 | if (vcpu->arch.shared->msr & MSR_PR) |
477 | *vsid |= VSID_PR; | 494 | *vsid |= VSID_PR; |
478 | 495 | ||
479 | return 0; | 496 | return 0; |
497 | |||
498 | no_slb: | ||
499 | /* Catch magic page case */ | ||
500 | if (unlikely(mp_ea) && | ||
501 | unlikely(esid == (mp_ea >> SID_SHIFT)) && | ||
502 | !(vcpu->arch.shared->msr & MSR_PR)) { | ||
503 | *vsid = VSID_REAL | esid; | ||
504 | return 0; | ||
505 | } | ||
506 | |||
507 | return -EINVAL; | ||
480 | } | 508 | } |
481 | 509 | ||
482 | static bool kvmppc_mmu_book3s_64_is_dcbz32(struct kvm_vcpu *vcpu) | 510 | static bool kvmppc_mmu_book3s_64_is_dcbz32(struct kvm_vcpu *vcpu) |
diff --git a/arch/powerpc/kvm/book3s_64_mmu_host.c b/arch/powerpc/kvm/book3s_64_mmu_host.c index 384179a5002b..fa2f08434ba5 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_host.c +++ b/arch/powerpc/kvm/book3s_64_mmu_host.c | |||
@@ -20,7 +20,6 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <linux/kvm_host.h> | 22 | #include <linux/kvm_host.h> |
23 | #include <linux/hash.h> | ||
24 | 23 | ||
25 | #include <asm/kvm_ppc.h> | 24 | #include <asm/kvm_ppc.h> |
26 | #include <asm/kvm_book3s.h> | 25 | #include <asm/kvm_book3s.h> |
@@ -28,24 +27,9 @@ | |||
28 | #include <asm/machdep.h> | 27 | #include <asm/machdep.h> |
29 | #include <asm/mmu_context.h> | 28 | #include <asm/mmu_context.h> |
30 | #include <asm/hw_irq.h> | 29 | #include <asm/hw_irq.h> |
30 | #include "trace.h" | ||
31 | 31 | ||
32 | #define PTE_SIZE 12 | 32 | #define PTE_SIZE 12 |
33 | #define VSID_ALL 0 | ||
34 | |||
35 | /* #define DEBUG_MMU */ | ||
36 | /* #define DEBUG_SLB */ | ||
37 | |||
38 | #ifdef DEBUG_MMU | ||
39 | #define dprintk_mmu(a, ...) printk(KERN_INFO a, __VA_ARGS__) | ||
40 | #else | ||
41 | #define dprintk_mmu(a, ...) do { } while(0) | ||
42 | #endif | ||
43 | |||
44 | #ifdef DEBUG_SLB | ||
45 | #define dprintk_slb(a, ...) printk(KERN_INFO a, __VA_ARGS__) | ||
46 | #else | ||
47 | #define dprintk_slb(a, ...) do { } while(0) | ||
48 | #endif | ||
49 | 33 | ||
50 | void kvmppc_mmu_invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte) | 34 | void kvmppc_mmu_invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte) |
51 | { | 35 | { |
@@ -58,34 +42,39 @@ void kvmppc_mmu_invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte) | |||
58 | * a hash, so we don't waste cycles on looping */ | 42 | * a hash, so we don't waste cycles on looping */ |
59 | static u16 kvmppc_sid_hash(struct kvm_vcpu *vcpu, u64 gvsid) | 43 | static u16 kvmppc_sid_hash(struct kvm_vcpu *vcpu, u64 gvsid) |
60 | { | 44 | { |
61 | return hash_64(gvsid, SID_MAP_BITS); | 45 | return (u16)(((gvsid >> (SID_MAP_BITS * 7)) & SID_MAP_MASK) ^ |
46 | ((gvsid >> (SID_MAP_BITS * 6)) & SID_MAP_MASK) ^ | ||
47 | ((gvsid >> (SID_MAP_BITS * 5)) & SID_MAP_MASK) ^ | ||
48 | ((gvsid >> (SID_MAP_BITS * 4)) & SID_MAP_MASK) ^ | ||
49 | ((gvsid >> (SID_MAP_BITS * 3)) & SID_MAP_MASK) ^ | ||
50 | ((gvsid >> (SID_MAP_BITS * 2)) & SID_MAP_MASK) ^ | ||
51 | ((gvsid >> (SID_MAP_BITS * 1)) & SID_MAP_MASK) ^ | ||
52 | ((gvsid >> (SID_MAP_BITS * 0)) & SID_MAP_MASK)); | ||
62 | } | 53 | } |
63 | 54 | ||
55 | |||
64 | static struct kvmppc_sid_map *find_sid_vsid(struct kvm_vcpu *vcpu, u64 gvsid) | 56 | static struct kvmppc_sid_map *find_sid_vsid(struct kvm_vcpu *vcpu, u64 gvsid) |
65 | { | 57 | { |
66 | struct kvmppc_sid_map *map; | 58 | struct kvmppc_sid_map *map; |
67 | u16 sid_map_mask; | 59 | u16 sid_map_mask; |
68 | 60 | ||
69 | if (vcpu->arch.msr & MSR_PR) | 61 | if (vcpu->arch.shared->msr & MSR_PR) |
70 | gvsid |= VSID_PR; | 62 | gvsid |= VSID_PR; |
71 | 63 | ||
72 | sid_map_mask = kvmppc_sid_hash(vcpu, gvsid); | 64 | sid_map_mask = kvmppc_sid_hash(vcpu, gvsid); |
73 | map = &to_book3s(vcpu)->sid_map[sid_map_mask]; | 65 | map = &to_book3s(vcpu)->sid_map[sid_map_mask]; |
74 | if (map->guest_vsid == gvsid) { | 66 | if (map->valid && (map->guest_vsid == gvsid)) { |
75 | dprintk_slb("SLB: Searching: 0x%llx -> 0x%llx\n", | 67 | trace_kvm_book3s_slb_found(gvsid, map->host_vsid); |
76 | gvsid, map->host_vsid); | ||
77 | return map; | 68 | return map; |
78 | } | 69 | } |
79 | 70 | ||
80 | map = &to_book3s(vcpu)->sid_map[SID_MAP_MASK - sid_map_mask]; | 71 | map = &to_book3s(vcpu)->sid_map[SID_MAP_MASK - sid_map_mask]; |
81 | if (map->guest_vsid == gvsid) { | 72 | if (map->valid && (map->guest_vsid == gvsid)) { |
82 | dprintk_slb("SLB: Searching 0x%llx -> 0x%llx\n", | 73 | trace_kvm_book3s_slb_found(gvsid, map->host_vsid); |
83 | gvsid, map->host_vsid); | ||
84 | return map; | 74 | return map; |
85 | } | 75 | } |
86 | 76 | ||
87 | dprintk_slb("SLB: Searching %d/%d: 0x%llx -> not found\n", | 77 | trace_kvm_book3s_slb_fail(sid_map_mask, gvsid); |
88 | sid_map_mask, SID_MAP_MASK - sid_map_mask, gvsid); | ||
89 | return NULL; | 78 | return NULL; |
90 | } | 79 | } |
91 | 80 | ||
@@ -101,18 +90,13 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte) | |||
101 | struct kvmppc_sid_map *map; | 90 | struct kvmppc_sid_map *map; |
102 | 91 | ||
103 | /* Get host physical address for gpa */ | 92 | /* Get host physical address for gpa */ |
104 | hpaddr = gfn_to_pfn(vcpu->kvm, orig_pte->raddr >> PAGE_SHIFT); | 93 | hpaddr = kvmppc_gfn_to_pfn(vcpu, orig_pte->raddr >> PAGE_SHIFT); |
105 | if (kvm_is_error_hva(hpaddr)) { | 94 | if (is_error_pfn(hpaddr)) { |
106 | printk(KERN_INFO "Couldn't get guest page for gfn %lx!\n", orig_pte->eaddr); | 95 | printk(KERN_INFO "Couldn't get guest page for gfn %lx!\n", orig_pte->eaddr); |
107 | return -EINVAL; | 96 | return -EINVAL; |
108 | } | 97 | } |
109 | hpaddr <<= PAGE_SHIFT; | 98 | hpaddr <<= PAGE_SHIFT; |
110 | #if PAGE_SHIFT == 12 | 99 | hpaddr |= orig_pte->raddr & (~0xfffULL & ~PAGE_MASK); |
111 | #elif PAGE_SHIFT == 16 | ||
112 | hpaddr |= orig_pte->raddr & 0xf000; | ||
113 | #else | ||
114 | #error Unknown page size | ||
115 | #endif | ||
116 | 100 | ||
117 | /* and write the mapping ea -> hpa into the pt */ | 101 | /* and write the mapping ea -> hpa into the pt */ |
118 | vcpu->arch.mmu.esid_to_vsid(vcpu, orig_pte->eaddr >> SID_SHIFT, &vsid); | 102 | vcpu->arch.mmu.esid_to_vsid(vcpu, orig_pte->eaddr >> SID_SHIFT, &vsid); |
@@ -161,10 +145,7 @@ map_again: | |||
161 | } else { | 145 | } else { |
162 | struct hpte_cache *pte = kvmppc_mmu_hpte_cache_next(vcpu); | 146 | struct hpte_cache *pte = kvmppc_mmu_hpte_cache_next(vcpu); |
163 | 147 | ||
164 | dprintk_mmu("KVM: %c%c Map 0x%lx: [%lx] 0x%lx (0x%llx) -> %lx\n", | 148 | trace_kvm_book3s_64_mmu_map(rflags, hpteg, va, hpaddr, orig_pte); |
165 | ((rflags & HPTE_R_PP) == 3) ? '-' : 'w', | ||
166 | (rflags & HPTE_R_N) ? '-' : 'x', | ||
167 | orig_pte->eaddr, hpteg, va, orig_pte->vpage, hpaddr); | ||
168 | 149 | ||
169 | /* The ppc_md code may give us a secondary entry even though we | 150 | /* The ppc_md code may give us a secondary entry even though we |
170 | asked for a primary. Fix up. */ | 151 | asked for a primary. Fix up. */ |
@@ -191,7 +172,7 @@ static struct kvmppc_sid_map *create_sid_map(struct kvm_vcpu *vcpu, u64 gvsid) | |||
191 | u16 sid_map_mask; | 172 | u16 sid_map_mask; |
192 | static int backwards_map = 0; | 173 | static int backwards_map = 0; |
193 | 174 | ||
194 | if (vcpu->arch.msr & MSR_PR) | 175 | if (vcpu->arch.shared->msr & MSR_PR) |
195 | gvsid |= VSID_PR; | 176 | gvsid |= VSID_PR; |
196 | 177 | ||
197 | /* We might get collisions that trap in preceding order, so let's | 178 | /* We might get collisions that trap in preceding order, so let's |
@@ -219,8 +200,7 @@ static struct kvmppc_sid_map *create_sid_map(struct kvm_vcpu *vcpu, u64 gvsid) | |||
219 | map->guest_vsid = gvsid; | 200 | map->guest_vsid = gvsid; |
220 | map->valid = true; | 201 | map->valid = true; |
221 | 202 | ||
222 | dprintk_slb("SLB: New mapping at %d: 0x%llx -> 0x%llx\n", | 203 | trace_kvm_book3s_slb_map(sid_map_mask, gvsid, map->host_vsid); |
223 | sid_map_mask, gvsid, map->host_vsid); | ||
224 | 204 | ||
225 | return map; | 205 | return map; |
226 | } | 206 | } |
@@ -292,7 +272,7 @@ int kvmppc_mmu_map_segment(struct kvm_vcpu *vcpu, ulong eaddr) | |||
292 | to_svcpu(vcpu)->slb[slb_index].esid = slb_esid; | 272 | to_svcpu(vcpu)->slb[slb_index].esid = slb_esid; |
293 | to_svcpu(vcpu)->slb[slb_index].vsid = slb_vsid; | 273 | to_svcpu(vcpu)->slb[slb_index].vsid = slb_vsid; |
294 | 274 | ||
295 | dprintk_slb("slbmte %#llx, %#llx\n", slb_vsid, slb_esid); | 275 | trace_kvm_book3s_slbmte(slb_vsid, slb_esid); |
296 | 276 | ||
297 | return 0; | 277 | return 0; |
298 | } | 278 | } |
@@ -306,7 +286,7 @@ void kvmppc_mmu_flush_segments(struct kvm_vcpu *vcpu) | |||
306 | void kvmppc_mmu_destroy(struct kvm_vcpu *vcpu) | 286 | void kvmppc_mmu_destroy(struct kvm_vcpu *vcpu) |
307 | { | 287 | { |
308 | kvmppc_mmu_hpte_destroy(vcpu); | 288 | kvmppc_mmu_hpte_destroy(vcpu); |
309 | __destroy_context(to_book3s(vcpu)->context_id); | 289 | __destroy_context(to_book3s(vcpu)->context_id[0]); |
310 | } | 290 | } |
311 | 291 | ||
312 | int kvmppc_mmu_init(struct kvm_vcpu *vcpu) | 292 | int kvmppc_mmu_init(struct kvm_vcpu *vcpu) |
@@ -317,10 +297,10 @@ int kvmppc_mmu_init(struct kvm_vcpu *vcpu) | |||
317 | err = __init_new_context(); | 297 | err = __init_new_context(); |
318 | if (err < 0) | 298 | if (err < 0) |
319 | return -1; | 299 | return -1; |
320 | vcpu3s->context_id = err; | 300 | vcpu3s->context_id[0] = err; |
321 | 301 | ||
322 | vcpu3s->vsid_max = ((vcpu3s->context_id + 1) << USER_ESID_BITS) - 1; | 302 | vcpu3s->vsid_max = ((vcpu3s->context_id[0] + 1) << USER_ESID_BITS) - 1; |
323 | vcpu3s->vsid_first = vcpu3s->context_id << USER_ESID_BITS; | 303 | vcpu3s->vsid_first = vcpu3s->context_id[0] << USER_ESID_BITS; |
324 | vcpu3s->vsid_next = vcpu3s->vsid_first; | 304 | vcpu3s->vsid_next = vcpu3s->vsid_first; |
325 | 305 | ||
326 | kvmppc_mmu_hpte_init(vcpu); | 306 | kvmppc_mmu_hpte_init(vcpu); |
diff --git a/arch/powerpc/kvm/book3s_emulate.c b/arch/powerpc/kvm/book3s_emulate.c index c85f906038ce..466846557089 100644 --- a/arch/powerpc/kvm/book3s_emulate.c +++ b/arch/powerpc/kvm/book3s_emulate.c | |||
@@ -73,8 +73,8 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
73 | switch (get_xop(inst)) { | 73 | switch (get_xop(inst)) { |
74 | case OP_19_XOP_RFID: | 74 | case OP_19_XOP_RFID: |
75 | case OP_19_XOP_RFI: | 75 | case OP_19_XOP_RFI: |
76 | kvmppc_set_pc(vcpu, vcpu->arch.srr0); | 76 | kvmppc_set_pc(vcpu, vcpu->arch.shared->srr0); |
77 | kvmppc_set_msr(vcpu, vcpu->arch.srr1); | 77 | kvmppc_set_msr(vcpu, vcpu->arch.shared->srr1); |
78 | *advance = 0; | 78 | *advance = 0; |
79 | break; | 79 | break; |
80 | 80 | ||
@@ -86,14 +86,15 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
86 | case 31: | 86 | case 31: |
87 | switch (get_xop(inst)) { | 87 | switch (get_xop(inst)) { |
88 | case OP_31_XOP_MFMSR: | 88 | case OP_31_XOP_MFMSR: |
89 | kvmppc_set_gpr(vcpu, get_rt(inst), vcpu->arch.msr); | 89 | kvmppc_set_gpr(vcpu, get_rt(inst), |
90 | vcpu->arch.shared->msr); | ||
90 | break; | 91 | break; |
91 | case OP_31_XOP_MTMSRD: | 92 | case OP_31_XOP_MTMSRD: |
92 | { | 93 | { |
93 | ulong rs = kvmppc_get_gpr(vcpu, get_rs(inst)); | 94 | ulong rs = kvmppc_get_gpr(vcpu, get_rs(inst)); |
94 | if (inst & 0x10000) { | 95 | if (inst & 0x10000) { |
95 | vcpu->arch.msr &= ~(MSR_RI | MSR_EE); | 96 | vcpu->arch.shared->msr &= ~(MSR_RI | MSR_EE); |
96 | vcpu->arch.msr |= rs & (MSR_RI | MSR_EE); | 97 | vcpu->arch.shared->msr |= rs & (MSR_RI | MSR_EE); |
97 | } else | 98 | } else |
98 | kvmppc_set_msr(vcpu, rs); | 99 | kvmppc_set_msr(vcpu, rs); |
99 | break; | 100 | break; |
@@ -204,14 +205,14 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
204 | ra = kvmppc_get_gpr(vcpu, get_ra(inst)); | 205 | ra = kvmppc_get_gpr(vcpu, get_ra(inst)); |
205 | 206 | ||
206 | addr = (ra + rb) & ~31ULL; | 207 | addr = (ra + rb) & ~31ULL; |
207 | if (!(vcpu->arch.msr & MSR_SF)) | 208 | if (!(vcpu->arch.shared->msr & MSR_SF)) |
208 | addr &= 0xffffffff; | 209 | addr &= 0xffffffff; |
209 | vaddr = addr; | 210 | vaddr = addr; |
210 | 211 | ||
211 | r = kvmppc_st(vcpu, &addr, 32, zeros, true); | 212 | r = kvmppc_st(vcpu, &addr, 32, zeros, true); |
212 | if ((r == -ENOENT) || (r == -EPERM)) { | 213 | if ((r == -ENOENT) || (r == -EPERM)) { |
213 | *advance = 0; | 214 | *advance = 0; |
214 | vcpu->arch.dear = vaddr; | 215 | vcpu->arch.shared->dar = vaddr; |
215 | to_svcpu(vcpu)->fault_dar = vaddr; | 216 | to_svcpu(vcpu)->fault_dar = vaddr; |
216 | 217 | ||
217 | dsisr = DSISR_ISSTORE; | 218 | dsisr = DSISR_ISSTORE; |
@@ -220,7 +221,7 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
220 | else if (r == -EPERM) | 221 | else if (r == -EPERM) |
221 | dsisr |= DSISR_PROTFAULT; | 222 | dsisr |= DSISR_PROTFAULT; |
222 | 223 | ||
223 | to_book3s(vcpu)->dsisr = dsisr; | 224 | vcpu->arch.shared->dsisr = dsisr; |
224 | to_svcpu(vcpu)->fault_dsisr = dsisr; | 225 | to_svcpu(vcpu)->fault_dsisr = dsisr; |
225 | 226 | ||
226 | kvmppc_book3s_queue_irqprio(vcpu, | 227 | kvmppc_book3s_queue_irqprio(vcpu, |
@@ -263,7 +264,7 @@ void kvmppc_set_bat(struct kvm_vcpu *vcpu, struct kvmppc_bat *bat, bool upper, | |||
263 | } | 264 | } |
264 | } | 265 | } |
265 | 266 | ||
266 | static u32 kvmppc_read_bat(struct kvm_vcpu *vcpu, int sprn) | 267 | static struct kvmppc_bat *kvmppc_find_bat(struct kvm_vcpu *vcpu, int sprn) |
267 | { | 268 | { |
268 | struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); | 269 | struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); |
269 | struct kvmppc_bat *bat; | 270 | struct kvmppc_bat *bat; |
@@ -285,35 +286,7 @@ static u32 kvmppc_read_bat(struct kvm_vcpu *vcpu, int sprn) | |||
285 | BUG(); | 286 | BUG(); |
286 | } | 287 | } |
287 | 288 | ||
288 | if (sprn % 2) | 289 | return bat; |
289 | return bat->raw >> 32; | ||
290 | else | ||
291 | return bat->raw; | ||
292 | } | ||
293 | |||
294 | static void kvmppc_write_bat(struct kvm_vcpu *vcpu, int sprn, u32 val) | ||
295 | { | ||
296 | struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); | ||
297 | struct kvmppc_bat *bat; | ||
298 | |||
299 | switch (sprn) { | ||
300 | case SPRN_IBAT0U ... SPRN_IBAT3L: | ||
301 | bat = &vcpu_book3s->ibat[(sprn - SPRN_IBAT0U) / 2]; | ||
302 | break; | ||
303 | case SPRN_IBAT4U ... SPRN_IBAT7L: | ||
304 | bat = &vcpu_book3s->ibat[4 + ((sprn - SPRN_IBAT4U) / 2)]; | ||
305 | break; | ||
306 | case SPRN_DBAT0U ... SPRN_DBAT3L: | ||
307 | bat = &vcpu_book3s->dbat[(sprn - SPRN_DBAT0U) / 2]; | ||
308 | break; | ||
309 | case SPRN_DBAT4U ... SPRN_DBAT7L: | ||
310 | bat = &vcpu_book3s->dbat[4 + ((sprn - SPRN_DBAT4U) / 2)]; | ||
311 | break; | ||
312 | default: | ||
313 | BUG(); | ||
314 | } | ||
315 | |||
316 | kvmppc_set_bat(vcpu, bat, !(sprn % 2), val); | ||
317 | } | 290 | } |
318 | 291 | ||
319 | int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs) | 292 | int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs) |
@@ -326,10 +299,10 @@ int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs) | |||
326 | to_book3s(vcpu)->sdr1 = spr_val; | 299 | to_book3s(vcpu)->sdr1 = spr_val; |
327 | break; | 300 | break; |
328 | case SPRN_DSISR: | 301 | case SPRN_DSISR: |
329 | to_book3s(vcpu)->dsisr = spr_val; | 302 | vcpu->arch.shared->dsisr = spr_val; |
330 | break; | 303 | break; |
331 | case SPRN_DAR: | 304 | case SPRN_DAR: |
332 | vcpu->arch.dear = spr_val; | 305 | vcpu->arch.shared->dar = spr_val; |
333 | break; | 306 | break; |
334 | case SPRN_HIOR: | 307 | case SPRN_HIOR: |
335 | to_book3s(vcpu)->hior = spr_val; | 308 | to_book3s(vcpu)->hior = spr_val; |
@@ -338,12 +311,16 @@ int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs) | |||
338 | case SPRN_IBAT4U ... SPRN_IBAT7L: | 311 | case SPRN_IBAT4U ... SPRN_IBAT7L: |
339 | case SPRN_DBAT0U ... SPRN_DBAT3L: | 312 | case SPRN_DBAT0U ... SPRN_DBAT3L: |
340 | case SPRN_DBAT4U ... SPRN_DBAT7L: | 313 | case SPRN_DBAT4U ... SPRN_DBAT7L: |
341 | kvmppc_write_bat(vcpu, sprn, (u32)spr_val); | 314 | { |
315 | struct kvmppc_bat *bat = kvmppc_find_bat(vcpu, sprn); | ||
316 | |||
317 | kvmppc_set_bat(vcpu, bat, !(sprn % 2), (u32)spr_val); | ||
342 | /* BAT writes happen so rarely that we're ok to flush | 318 | /* BAT writes happen so rarely that we're ok to flush |
343 | * everything here */ | 319 | * everything here */ |
344 | kvmppc_mmu_pte_flush(vcpu, 0, 0); | 320 | kvmppc_mmu_pte_flush(vcpu, 0, 0); |
345 | kvmppc_mmu_flush_segments(vcpu); | 321 | kvmppc_mmu_flush_segments(vcpu); |
346 | break; | 322 | break; |
323 | } | ||
347 | case SPRN_HID0: | 324 | case SPRN_HID0: |
348 | to_book3s(vcpu)->hid[0] = spr_val; | 325 | to_book3s(vcpu)->hid[0] = spr_val; |
349 | break; | 326 | break; |
@@ -433,16 +410,24 @@ int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt) | |||
433 | case SPRN_IBAT4U ... SPRN_IBAT7L: | 410 | case SPRN_IBAT4U ... SPRN_IBAT7L: |
434 | case SPRN_DBAT0U ... SPRN_DBAT3L: | 411 | case SPRN_DBAT0U ... SPRN_DBAT3L: |
435 | case SPRN_DBAT4U ... SPRN_DBAT7L: | 412 | case SPRN_DBAT4U ... SPRN_DBAT7L: |
436 | kvmppc_set_gpr(vcpu, rt, kvmppc_read_bat(vcpu, sprn)); | 413 | { |
414 | struct kvmppc_bat *bat = kvmppc_find_bat(vcpu, sprn); | ||
415 | |||
416 | if (sprn % 2) | ||
417 | kvmppc_set_gpr(vcpu, rt, bat->raw >> 32); | ||
418 | else | ||
419 | kvmppc_set_gpr(vcpu, rt, bat->raw); | ||
420 | |||
437 | break; | 421 | break; |
422 | } | ||
438 | case SPRN_SDR1: | 423 | case SPRN_SDR1: |
439 | kvmppc_set_gpr(vcpu, rt, to_book3s(vcpu)->sdr1); | 424 | kvmppc_set_gpr(vcpu, rt, to_book3s(vcpu)->sdr1); |
440 | break; | 425 | break; |
441 | case SPRN_DSISR: | 426 | case SPRN_DSISR: |
442 | kvmppc_set_gpr(vcpu, rt, to_book3s(vcpu)->dsisr); | 427 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->dsisr); |
443 | break; | 428 | break; |
444 | case SPRN_DAR: | 429 | case SPRN_DAR: |
445 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.dear); | 430 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->dar); |
446 | break; | 431 | break; |
447 | case SPRN_HIOR: | 432 | case SPRN_HIOR: |
448 | kvmppc_set_gpr(vcpu, rt, to_book3s(vcpu)->hior); | 433 | kvmppc_set_gpr(vcpu, rt, to_book3s(vcpu)->hior); |
diff --git a/arch/powerpc/kvm/book3s_mmu_hpte.c b/arch/powerpc/kvm/book3s_mmu_hpte.c index 4868d4a7ebc5..79751d8dd131 100644 --- a/arch/powerpc/kvm/book3s_mmu_hpte.c +++ b/arch/powerpc/kvm/book3s_mmu_hpte.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/kvm_host.h> | 21 | #include <linux/kvm_host.h> |
22 | #include <linux/hash.h> | 22 | #include <linux/hash.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include "trace.h" | ||
24 | 25 | ||
25 | #include <asm/kvm_ppc.h> | 26 | #include <asm/kvm_ppc.h> |
26 | #include <asm/kvm_book3s.h> | 27 | #include <asm/kvm_book3s.h> |
@@ -30,14 +31,6 @@ | |||
30 | 31 | ||
31 | #define PTE_SIZE 12 | 32 | #define PTE_SIZE 12 |
32 | 33 | ||
33 | /* #define DEBUG_MMU */ | ||
34 | |||
35 | #ifdef DEBUG_MMU | ||
36 | #define dprintk_mmu(a, ...) printk(KERN_INFO a, __VA_ARGS__) | ||
37 | #else | ||
38 | #define dprintk_mmu(a, ...) do { } while(0) | ||
39 | #endif | ||
40 | |||
41 | static struct kmem_cache *hpte_cache; | 34 | static struct kmem_cache *hpte_cache; |
42 | 35 | ||
43 | static inline u64 kvmppc_mmu_hash_pte(u64 eaddr) | 36 | static inline u64 kvmppc_mmu_hash_pte(u64 eaddr) |
@@ -45,6 +38,12 @@ static inline u64 kvmppc_mmu_hash_pte(u64 eaddr) | |||
45 | return hash_64(eaddr >> PTE_SIZE, HPTEG_HASH_BITS_PTE); | 38 | return hash_64(eaddr >> PTE_SIZE, HPTEG_HASH_BITS_PTE); |
46 | } | 39 | } |
47 | 40 | ||
41 | static inline u64 kvmppc_mmu_hash_pte_long(u64 eaddr) | ||
42 | { | ||
43 | return hash_64((eaddr & 0x0ffff000) >> PTE_SIZE, | ||
44 | HPTEG_HASH_BITS_PTE_LONG); | ||
45 | } | ||
46 | |||
48 | static inline u64 kvmppc_mmu_hash_vpte(u64 vpage) | 47 | static inline u64 kvmppc_mmu_hash_vpte(u64 vpage) |
49 | { | 48 | { |
50 | return hash_64(vpage & 0xfffffffffULL, HPTEG_HASH_BITS_VPTE); | 49 | return hash_64(vpage & 0xfffffffffULL, HPTEG_HASH_BITS_VPTE); |
@@ -60,77 +59,128 @@ void kvmppc_mmu_hpte_cache_map(struct kvm_vcpu *vcpu, struct hpte_cache *pte) | |||
60 | { | 59 | { |
61 | u64 index; | 60 | u64 index; |
62 | 61 | ||
62 | trace_kvm_book3s_mmu_map(pte); | ||
63 | |||
64 | spin_lock(&vcpu->arch.mmu_lock); | ||
65 | |||
63 | /* Add to ePTE list */ | 66 | /* Add to ePTE list */ |
64 | index = kvmppc_mmu_hash_pte(pte->pte.eaddr); | 67 | index = kvmppc_mmu_hash_pte(pte->pte.eaddr); |
65 | hlist_add_head(&pte->list_pte, &vcpu->arch.hpte_hash_pte[index]); | 68 | hlist_add_head_rcu(&pte->list_pte, &vcpu->arch.hpte_hash_pte[index]); |
69 | |||
70 | /* Add to ePTE_long list */ | ||
71 | index = kvmppc_mmu_hash_pte_long(pte->pte.eaddr); | ||
72 | hlist_add_head_rcu(&pte->list_pte_long, | ||
73 | &vcpu->arch.hpte_hash_pte_long[index]); | ||
66 | 74 | ||
67 | /* Add to vPTE list */ | 75 | /* Add to vPTE list */ |
68 | index = kvmppc_mmu_hash_vpte(pte->pte.vpage); | 76 | index = kvmppc_mmu_hash_vpte(pte->pte.vpage); |
69 | hlist_add_head(&pte->list_vpte, &vcpu->arch.hpte_hash_vpte[index]); | 77 | hlist_add_head_rcu(&pte->list_vpte, &vcpu->arch.hpte_hash_vpte[index]); |
70 | 78 | ||
71 | /* Add to vPTE_long list */ | 79 | /* Add to vPTE_long list */ |
72 | index = kvmppc_mmu_hash_vpte_long(pte->pte.vpage); | 80 | index = kvmppc_mmu_hash_vpte_long(pte->pte.vpage); |
73 | hlist_add_head(&pte->list_vpte_long, | 81 | hlist_add_head_rcu(&pte->list_vpte_long, |
74 | &vcpu->arch.hpte_hash_vpte_long[index]); | 82 | &vcpu->arch.hpte_hash_vpte_long[index]); |
83 | |||
84 | spin_unlock(&vcpu->arch.mmu_lock); | ||
85 | } | ||
86 | |||
87 | static void free_pte_rcu(struct rcu_head *head) | ||
88 | { | ||
89 | struct hpte_cache *pte = container_of(head, struct hpte_cache, rcu_head); | ||
90 | kmem_cache_free(hpte_cache, pte); | ||
75 | } | 91 | } |
76 | 92 | ||
77 | static void invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte) | 93 | static void invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte) |
78 | { | 94 | { |
79 | dprintk_mmu("KVM: Flushing SPT: 0x%lx (0x%llx) -> 0x%llx\n", | 95 | trace_kvm_book3s_mmu_invalidate(pte); |
80 | pte->pte.eaddr, pte->pte.vpage, pte->host_va); | ||
81 | 96 | ||
82 | /* Different for 32 and 64 bit */ | 97 | /* Different for 32 and 64 bit */ |
83 | kvmppc_mmu_invalidate_pte(vcpu, pte); | 98 | kvmppc_mmu_invalidate_pte(vcpu, pte); |
84 | 99 | ||
100 | spin_lock(&vcpu->arch.mmu_lock); | ||
101 | |||
102 | /* pte already invalidated in between? */ | ||
103 | if (hlist_unhashed(&pte->list_pte)) { | ||
104 | spin_unlock(&vcpu->arch.mmu_lock); | ||
105 | return; | ||
106 | } | ||
107 | |||
108 | hlist_del_init_rcu(&pte->list_pte); | ||
109 | hlist_del_init_rcu(&pte->list_pte_long); | ||
110 | hlist_del_init_rcu(&pte->list_vpte); | ||
111 | hlist_del_init_rcu(&pte->list_vpte_long); | ||
112 | |||
85 | if (pte->pte.may_write) | 113 | if (pte->pte.may_write) |
86 | kvm_release_pfn_dirty(pte->pfn); | 114 | kvm_release_pfn_dirty(pte->pfn); |
87 | else | 115 | else |
88 | kvm_release_pfn_clean(pte->pfn); | 116 | kvm_release_pfn_clean(pte->pfn); |
89 | 117 | ||
90 | hlist_del(&pte->list_pte); | 118 | spin_unlock(&vcpu->arch.mmu_lock); |
91 | hlist_del(&pte->list_vpte); | ||
92 | hlist_del(&pte->list_vpte_long); | ||
93 | 119 | ||
94 | vcpu->arch.hpte_cache_count--; | 120 | vcpu->arch.hpte_cache_count--; |
95 | kmem_cache_free(hpte_cache, pte); | 121 | call_rcu(&pte->rcu_head, free_pte_rcu); |
96 | } | 122 | } |
97 | 123 | ||
98 | static void kvmppc_mmu_pte_flush_all(struct kvm_vcpu *vcpu) | 124 | static void kvmppc_mmu_pte_flush_all(struct kvm_vcpu *vcpu) |
99 | { | 125 | { |
100 | struct hpte_cache *pte; | 126 | struct hpte_cache *pte; |
101 | struct hlist_node *node, *tmp; | 127 | struct hlist_node *node; |
102 | int i; | 128 | int i; |
103 | 129 | ||
130 | rcu_read_lock(); | ||
131 | |||
104 | for (i = 0; i < HPTEG_HASH_NUM_VPTE_LONG; i++) { | 132 | for (i = 0; i < HPTEG_HASH_NUM_VPTE_LONG; i++) { |
105 | struct hlist_head *list = &vcpu->arch.hpte_hash_vpte_long[i]; | 133 | struct hlist_head *list = &vcpu->arch.hpte_hash_vpte_long[i]; |
106 | 134 | ||
107 | hlist_for_each_entry_safe(pte, node, tmp, list, list_vpte_long) | 135 | hlist_for_each_entry_rcu(pte, node, list, list_vpte_long) |
108 | invalidate_pte(vcpu, pte); | 136 | invalidate_pte(vcpu, pte); |
109 | } | 137 | } |
138 | |||
139 | rcu_read_unlock(); | ||
110 | } | 140 | } |
111 | 141 | ||
112 | static void kvmppc_mmu_pte_flush_page(struct kvm_vcpu *vcpu, ulong guest_ea) | 142 | static void kvmppc_mmu_pte_flush_page(struct kvm_vcpu *vcpu, ulong guest_ea) |
113 | { | 143 | { |
114 | struct hlist_head *list; | 144 | struct hlist_head *list; |
115 | struct hlist_node *node, *tmp; | 145 | struct hlist_node *node; |
116 | struct hpte_cache *pte; | 146 | struct hpte_cache *pte; |
117 | 147 | ||
118 | /* Find the list of entries in the map */ | 148 | /* Find the list of entries in the map */ |
119 | list = &vcpu->arch.hpte_hash_pte[kvmppc_mmu_hash_pte(guest_ea)]; | 149 | list = &vcpu->arch.hpte_hash_pte[kvmppc_mmu_hash_pte(guest_ea)]; |
120 | 150 | ||
151 | rcu_read_lock(); | ||
152 | |||
121 | /* Check the list for matching entries and invalidate */ | 153 | /* Check the list for matching entries and invalidate */ |
122 | hlist_for_each_entry_safe(pte, node, tmp, list, list_pte) | 154 | hlist_for_each_entry_rcu(pte, node, list, list_pte) |
123 | if ((pte->pte.eaddr & ~0xfffUL) == guest_ea) | 155 | if ((pte->pte.eaddr & ~0xfffUL) == guest_ea) |
124 | invalidate_pte(vcpu, pte); | 156 | invalidate_pte(vcpu, pte); |
157 | |||
158 | rcu_read_unlock(); | ||
125 | } | 159 | } |
126 | 160 | ||
127 | void kvmppc_mmu_pte_flush(struct kvm_vcpu *vcpu, ulong guest_ea, ulong ea_mask) | 161 | static void kvmppc_mmu_pte_flush_long(struct kvm_vcpu *vcpu, ulong guest_ea) |
128 | { | 162 | { |
129 | u64 i; | 163 | struct hlist_head *list; |
164 | struct hlist_node *node; | ||
165 | struct hpte_cache *pte; | ||
130 | 166 | ||
131 | dprintk_mmu("KVM: Flushing %d Shadow PTEs: 0x%lx & 0x%lx\n", | 167 | /* Find the list of entries in the map */ |
132 | vcpu->arch.hpte_cache_count, guest_ea, ea_mask); | 168 | list = &vcpu->arch.hpte_hash_pte_long[ |
169 | kvmppc_mmu_hash_pte_long(guest_ea)]; | ||
133 | 170 | ||
171 | rcu_read_lock(); | ||
172 | |||
173 | /* Check the list for matching entries and invalidate */ | ||
174 | hlist_for_each_entry_rcu(pte, node, list, list_pte_long) | ||
175 | if ((pte->pte.eaddr & 0x0ffff000UL) == guest_ea) | ||
176 | invalidate_pte(vcpu, pte); | ||
177 | |||
178 | rcu_read_unlock(); | ||
179 | } | ||
180 | |||
181 | void kvmppc_mmu_pte_flush(struct kvm_vcpu *vcpu, ulong guest_ea, ulong ea_mask) | ||
182 | { | ||
183 | trace_kvm_book3s_mmu_flush("", vcpu, guest_ea, ea_mask); | ||
134 | guest_ea &= ea_mask; | 184 | guest_ea &= ea_mask; |
135 | 185 | ||
136 | switch (ea_mask) { | 186 | switch (ea_mask) { |
@@ -138,9 +188,7 @@ void kvmppc_mmu_pte_flush(struct kvm_vcpu *vcpu, ulong guest_ea, ulong ea_mask) | |||
138 | kvmppc_mmu_pte_flush_page(vcpu, guest_ea); | 188 | kvmppc_mmu_pte_flush_page(vcpu, guest_ea); |
139 | break; | 189 | break; |
140 | case 0x0ffff000: | 190 | case 0x0ffff000: |
141 | /* 32-bit flush w/o segment, go through all possible segments */ | 191 | kvmppc_mmu_pte_flush_long(vcpu, guest_ea); |
142 | for (i = 0; i < 0x100000000ULL; i += 0x10000000ULL) | ||
143 | kvmppc_mmu_pte_flush(vcpu, guest_ea | i, ~0xfffUL); | ||
144 | break; | 192 | break; |
145 | case 0: | 193 | case 0: |
146 | /* Doing a complete flush -> start from scratch */ | 194 | /* Doing a complete flush -> start from scratch */ |
@@ -156,39 +204,46 @@ void kvmppc_mmu_pte_flush(struct kvm_vcpu *vcpu, ulong guest_ea, ulong ea_mask) | |||
156 | static void kvmppc_mmu_pte_vflush_short(struct kvm_vcpu *vcpu, u64 guest_vp) | 204 | static void kvmppc_mmu_pte_vflush_short(struct kvm_vcpu *vcpu, u64 guest_vp) |
157 | { | 205 | { |
158 | struct hlist_head *list; | 206 | struct hlist_head *list; |
159 | struct hlist_node *node, *tmp; | 207 | struct hlist_node *node; |
160 | struct hpte_cache *pte; | 208 | struct hpte_cache *pte; |
161 | u64 vp_mask = 0xfffffffffULL; | 209 | u64 vp_mask = 0xfffffffffULL; |
162 | 210 | ||
163 | list = &vcpu->arch.hpte_hash_vpte[kvmppc_mmu_hash_vpte(guest_vp)]; | 211 | list = &vcpu->arch.hpte_hash_vpte[kvmppc_mmu_hash_vpte(guest_vp)]; |
164 | 212 | ||
213 | rcu_read_lock(); | ||
214 | |||
165 | /* Check the list for matching entries and invalidate */ | 215 | /* Check the list for matching entries and invalidate */ |
166 | hlist_for_each_entry_safe(pte, node, tmp, list, list_vpte) | 216 | hlist_for_each_entry_rcu(pte, node, list, list_vpte) |
167 | if ((pte->pte.vpage & vp_mask) == guest_vp) | 217 | if ((pte->pte.vpage & vp_mask) == guest_vp) |
168 | invalidate_pte(vcpu, pte); | 218 | invalidate_pte(vcpu, pte); |
219 | |||
220 | rcu_read_unlock(); | ||
169 | } | 221 | } |
170 | 222 | ||
171 | /* Flush with mask 0xffffff000 */ | 223 | /* Flush with mask 0xffffff000 */ |
172 | static void kvmppc_mmu_pte_vflush_long(struct kvm_vcpu *vcpu, u64 guest_vp) | 224 | static void kvmppc_mmu_pte_vflush_long(struct kvm_vcpu *vcpu, u64 guest_vp) |
173 | { | 225 | { |
174 | struct hlist_head *list; | 226 | struct hlist_head *list; |
175 | struct hlist_node *node, *tmp; | 227 | struct hlist_node *node; |
176 | struct hpte_cache *pte; | 228 | struct hpte_cache *pte; |
177 | u64 vp_mask = 0xffffff000ULL; | 229 | u64 vp_mask = 0xffffff000ULL; |
178 | 230 | ||
179 | list = &vcpu->arch.hpte_hash_vpte_long[ | 231 | list = &vcpu->arch.hpte_hash_vpte_long[ |
180 | kvmppc_mmu_hash_vpte_long(guest_vp)]; | 232 | kvmppc_mmu_hash_vpte_long(guest_vp)]; |
181 | 233 | ||
234 | rcu_read_lock(); | ||
235 | |||
182 | /* Check the list for matching entries and invalidate */ | 236 | /* Check the list for matching entries and invalidate */ |
183 | hlist_for_each_entry_safe(pte, node, tmp, list, list_vpte_long) | 237 | hlist_for_each_entry_rcu(pte, node, list, list_vpte_long) |
184 | if ((pte->pte.vpage & vp_mask) == guest_vp) | 238 | if ((pte->pte.vpage & vp_mask) == guest_vp) |
185 | invalidate_pte(vcpu, pte); | 239 | invalidate_pte(vcpu, pte); |
240 | |||
241 | rcu_read_unlock(); | ||
186 | } | 242 | } |
187 | 243 | ||
188 | void kvmppc_mmu_pte_vflush(struct kvm_vcpu *vcpu, u64 guest_vp, u64 vp_mask) | 244 | void kvmppc_mmu_pte_vflush(struct kvm_vcpu *vcpu, u64 guest_vp, u64 vp_mask) |
189 | { | 245 | { |
190 | dprintk_mmu("KVM: Flushing %d Shadow vPTEs: 0x%llx & 0x%llx\n", | 246 | trace_kvm_book3s_mmu_flush("v", vcpu, guest_vp, vp_mask); |
191 | vcpu->arch.hpte_cache_count, guest_vp, vp_mask); | ||
192 | guest_vp &= vp_mask; | 247 | guest_vp &= vp_mask; |
193 | 248 | ||
194 | switch(vp_mask) { | 249 | switch(vp_mask) { |
@@ -206,21 +261,24 @@ void kvmppc_mmu_pte_vflush(struct kvm_vcpu *vcpu, u64 guest_vp, u64 vp_mask) | |||
206 | 261 | ||
207 | void kvmppc_mmu_pte_pflush(struct kvm_vcpu *vcpu, ulong pa_start, ulong pa_end) | 262 | void kvmppc_mmu_pte_pflush(struct kvm_vcpu *vcpu, ulong pa_start, ulong pa_end) |
208 | { | 263 | { |
209 | struct hlist_node *node, *tmp; | 264 | struct hlist_node *node; |
210 | struct hpte_cache *pte; | 265 | struct hpte_cache *pte; |
211 | int i; | 266 | int i; |
212 | 267 | ||
213 | dprintk_mmu("KVM: Flushing %d Shadow pPTEs: 0x%lx - 0x%lx\n", | 268 | trace_kvm_book3s_mmu_flush("p", vcpu, pa_start, pa_end); |
214 | vcpu->arch.hpte_cache_count, pa_start, pa_end); | 269 | |
270 | rcu_read_lock(); | ||
215 | 271 | ||
216 | for (i = 0; i < HPTEG_HASH_NUM_VPTE_LONG; i++) { | 272 | for (i = 0; i < HPTEG_HASH_NUM_VPTE_LONG; i++) { |
217 | struct hlist_head *list = &vcpu->arch.hpte_hash_vpte_long[i]; | 273 | struct hlist_head *list = &vcpu->arch.hpte_hash_vpte_long[i]; |
218 | 274 | ||
219 | hlist_for_each_entry_safe(pte, node, tmp, list, list_vpte_long) | 275 | hlist_for_each_entry_rcu(pte, node, list, list_vpte_long) |
220 | if ((pte->pte.raddr >= pa_start) && | 276 | if ((pte->pte.raddr >= pa_start) && |
221 | (pte->pte.raddr < pa_end)) | 277 | (pte->pte.raddr < pa_end)) |
222 | invalidate_pte(vcpu, pte); | 278 | invalidate_pte(vcpu, pte); |
223 | } | 279 | } |
280 | |||
281 | rcu_read_unlock(); | ||
224 | } | 282 | } |
225 | 283 | ||
226 | struct hpte_cache *kvmppc_mmu_hpte_cache_next(struct kvm_vcpu *vcpu) | 284 | struct hpte_cache *kvmppc_mmu_hpte_cache_next(struct kvm_vcpu *vcpu) |
@@ -254,11 +312,15 @@ int kvmppc_mmu_hpte_init(struct kvm_vcpu *vcpu) | |||
254 | /* init hpte lookup hashes */ | 312 | /* init hpte lookup hashes */ |
255 | kvmppc_mmu_hpte_init_hash(vcpu->arch.hpte_hash_pte, | 313 | kvmppc_mmu_hpte_init_hash(vcpu->arch.hpte_hash_pte, |
256 | ARRAY_SIZE(vcpu->arch.hpte_hash_pte)); | 314 | ARRAY_SIZE(vcpu->arch.hpte_hash_pte)); |
315 | kvmppc_mmu_hpte_init_hash(vcpu->arch.hpte_hash_pte_long, | ||
316 | ARRAY_SIZE(vcpu->arch.hpte_hash_pte_long)); | ||
257 | kvmppc_mmu_hpte_init_hash(vcpu->arch.hpte_hash_vpte, | 317 | kvmppc_mmu_hpte_init_hash(vcpu->arch.hpte_hash_vpte, |
258 | ARRAY_SIZE(vcpu->arch.hpte_hash_vpte)); | 318 | ARRAY_SIZE(vcpu->arch.hpte_hash_vpte)); |
259 | kvmppc_mmu_hpte_init_hash(vcpu->arch.hpte_hash_vpte_long, | 319 | kvmppc_mmu_hpte_init_hash(vcpu->arch.hpte_hash_vpte_long, |
260 | ARRAY_SIZE(vcpu->arch.hpte_hash_vpte_long)); | 320 | ARRAY_SIZE(vcpu->arch.hpte_hash_vpte_long)); |
261 | 321 | ||
322 | spin_lock_init(&vcpu->arch.mmu_lock); | ||
323 | |||
262 | return 0; | 324 | return 0; |
263 | } | 325 | } |
264 | 326 | ||
diff --git a/arch/powerpc/kvm/book3s_paired_singles.c b/arch/powerpc/kvm/book3s_paired_singles.c index 474f2e24050a..7b0ee96c1bed 100644 --- a/arch/powerpc/kvm/book3s_paired_singles.c +++ b/arch/powerpc/kvm/book3s_paired_singles.c | |||
@@ -159,20 +159,21 @@ | |||
159 | 159 | ||
160 | static inline void kvmppc_sync_qpr(struct kvm_vcpu *vcpu, int rt) | 160 | static inline void kvmppc_sync_qpr(struct kvm_vcpu *vcpu, int rt) |
161 | { | 161 | { |
162 | kvm_cvt_df(&vcpu->arch.fpr[rt], &vcpu->arch.qpr[rt], &vcpu->arch.fpscr); | 162 | kvm_cvt_df(&vcpu->arch.fpr[rt], &vcpu->arch.qpr[rt]); |
163 | } | 163 | } |
164 | 164 | ||
165 | static void kvmppc_inject_pf(struct kvm_vcpu *vcpu, ulong eaddr, bool is_store) | 165 | static void kvmppc_inject_pf(struct kvm_vcpu *vcpu, ulong eaddr, bool is_store) |
166 | { | 166 | { |
167 | u64 dsisr; | 167 | u64 dsisr; |
168 | struct kvm_vcpu_arch_shared *shared = vcpu->arch.shared; | ||
168 | 169 | ||
169 | vcpu->arch.msr = kvmppc_set_field(vcpu->arch.msr, 33, 36, 0); | 170 | shared->msr = kvmppc_set_field(shared->msr, 33, 36, 0); |
170 | vcpu->arch.msr = kvmppc_set_field(vcpu->arch.msr, 42, 47, 0); | 171 | shared->msr = kvmppc_set_field(shared->msr, 42, 47, 0); |
171 | vcpu->arch.dear = eaddr; | 172 | shared->dar = eaddr; |
172 | /* Page Fault */ | 173 | /* Page Fault */ |
173 | dsisr = kvmppc_set_field(0, 33, 33, 1); | 174 | dsisr = kvmppc_set_field(0, 33, 33, 1); |
174 | if (is_store) | 175 | if (is_store) |
175 | to_book3s(vcpu)->dsisr = kvmppc_set_field(dsisr, 38, 38, 1); | 176 | shared->dsisr = kvmppc_set_field(dsisr, 38, 38, 1); |
176 | kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_DATA_STORAGE); | 177 | kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_DATA_STORAGE); |
177 | } | 178 | } |
178 | 179 | ||
@@ -204,7 +205,7 @@ static int kvmppc_emulate_fpr_load(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
204 | /* put in registers */ | 205 | /* put in registers */ |
205 | switch (ls_type) { | 206 | switch (ls_type) { |
206 | case FPU_LS_SINGLE: | 207 | case FPU_LS_SINGLE: |
207 | kvm_cvt_fd((u32*)tmp, &vcpu->arch.fpr[rs], &vcpu->arch.fpscr); | 208 | kvm_cvt_fd((u32*)tmp, &vcpu->arch.fpr[rs]); |
208 | vcpu->arch.qpr[rs] = *((u32*)tmp); | 209 | vcpu->arch.qpr[rs] = *((u32*)tmp); |
209 | break; | 210 | break; |
210 | case FPU_LS_DOUBLE: | 211 | case FPU_LS_DOUBLE: |
@@ -230,7 +231,7 @@ static int kvmppc_emulate_fpr_store(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
230 | 231 | ||
231 | switch (ls_type) { | 232 | switch (ls_type) { |
232 | case FPU_LS_SINGLE: | 233 | case FPU_LS_SINGLE: |
233 | kvm_cvt_df(&vcpu->arch.fpr[rs], (u32*)tmp, &vcpu->arch.fpscr); | 234 | kvm_cvt_df(&vcpu->arch.fpr[rs], (u32*)tmp); |
234 | val = *((u32*)tmp); | 235 | val = *((u32*)tmp); |
235 | len = sizeof(u32); | 236 | len = sizeof(u32); |
236 | break; | 237 | break; |
@@ -296,7 +297,7 @@ static int kvmppc_emulate_psq_load(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
296 | emulated = EMULATE_DONE; | 297 | emulated = EMULATE_DONE; |
297 | 298 | ||
298 | /* put in registers */ | 299 | /* put in registers */ |
299 | kvm_cvt_fd(&tmp[0], &vcpu->arch.fpr[rs], &vcpu->arch.fpscr); | 300 | kvm_cvt_fd(&tmp[0], &vcpu->arch.fpr[rs]); |
300 | vcpu->arch.qpr[rs] = tmp[1]; | 301 | vcpu->arch.qpr[rs] = tmp[1]; |
301 | 302 | ||
302 | dprintk(KERN_INFO "KVM: PSQ_LD [0x%x, 0x%x] at 0x%lx (%d)\n", tmp[0], | 303 | dprintk(KERN_INFO "KVM: PSQ_LD [0x%x, 0x%x] at 0x%lx (%d)\n", tmp[0], |
@@ -314,7 +315,7 @@ static int kvmppc_emulate_psq_store(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
314 | u32 tmp[2]; | 315 | u32 tmp[2]; |
315 | int len = w ? sizeof(u32) : sizeof(u64); | 316 | int len = w ? sizeof(u32) : sizeof(u64); |
316 | 317 | ||
317 | kvm_cvt_df(&vcpu->arch.fpr[rs], &tmp[0], &vcpu->arch.fpscr); | 318 | kvm_cvt_df(&vcpu->arch.fpr[rs], &tmp[0]); |
318 | tmp[1] = vcpu->arch.qpr[rs]; | 319 | tmp[1] = vcpu->arch.qpr[rs]; |
319 | 320 | ||
320 | r = kvmppc_st(vcpu, &addr, len, tmp, true); | 321 | r = kvmppc_st(vcpu, &addr, len, tmp, true); |
@@ -516,9 +517,9 @@ static int kvmppc_ps_three_in(struct kvm_vcpu *vcpu, bool rc, | |||
516 | WARN_ON(rc); | 517 | WARN_ON(rc); |
517 | 518 | ||
518 | /* PS0 */ | 519 | /* PS0 */ |
519 | kvm_cvt_df(&fpr[reg_in1], &ps0_in1, &vcpu->arch.fpscr); | 520 | kvm_cvt_df(&fpr[reg_in1], &ps0_in1); |
520 | kvm_cvt_df(&fpr[reg_in2], &ps0_in2, &vcpu->arch.fpscr); | 521 | kvm_cvt_df(&fpr[reg_in2], &ps0_in2); |
521 | kvm_cvt_df(&fpr[reg_in3], &ps0_in3, &vcpu->arch.fpscr); | 522 | kvm_cvt_df(&fpr[reg_in3], &ps0_in3); |
522 | 523 | ||
523 | if (scalar & SCALAR_LOW) | 524 | if (scalar & SCALAR_LOW) |
524 | ps0_in2 = qpr[reg_in2]; | 525 | ps0_in2 = qpr[reg_in2]; |
@@ -529,7 +530,7 @@ static int kvmppc_ps_three_in(struct kvm_vcpu *vcpu, bool rc, | |||
529 | ps0_in1, ps0_in2, ps0_in3, ps0_out); | 530 | ps0_in1, ps0_in2, ps0_in3, ps0_out); |
530 | 531 | ||
531 | if (!(scalar & SCALAR_NO_PS0)) | 532 | if (!(scalar & SCALAR_NO_PS0)) |
532 | kvm_cvt_fd(&ps0_out, &fpr[reg_out], &vcpu->arch.fpscr); | 533 | kvm_cvt_fd(&ps0_out, &fpr[reg_out]); |
533 | 534 | ||
534 | /* PS1 */ | 535 | /* PS1 */ |
535 | ps1_in1 = qpr[reg_in1]; | 536 | ps1_in1 = qpr[reg_in1]; |
@@ -566,12 +567,12 @@ static int kvmppc_ps_two_in(struct kvm_vcpu *vcpu, bool rc, | |||
566 | WARN_ON(rc); | 567 | WARN_ON(rc); |
567 | 568 | ||
568 | /* PS0 */ | 569 | /* PS0 */ |
569 | kvm_cvt_df(&fpr[reg_in1], &ps0_in1, &vcpu->arch.fpscr); | 570 | kvm_cvt_df(&fpr[reg_in1], &ps0_in1); |
570 | 571 | ||
571 | if (scalar & SCALAR_LOW) | 572 | if (scalar & SCALAR_LOW) |
572 | ps0_in2 = qpr[reg_in2]; | 573 | ps0_in2 = qpr[reg_in2]; |
573 | else | 574 | else |
574 | kvm_cvt_df(&fpr[reg_in2], &ps0_in2, &vcpu->arch.fpscr); | 575 | kvm_cvt_df(&fpr[reg_in2], &ps0_in2); |
575 | 576 | ||
576 | func(&vcpu->arch.fpscr, &ps0_out, &ps0_in1, &ps0_in2); | 577 | func(&vcpu->arch.fpscr, &ps0_out, &ps0_in1, &ps0_in2); |
577 | 578 | ||
@@ -579,7 +580,7 @@ static int kvmppc_ps_two_in(struct kvm_vcpu *vcpu, bool rc, | |||
579 | dprintk(KERN_INFO "PS2 ps0 -> f(0x%x, 0x%x) = 0x%x\n", | 580 | dprintk(KERN_INFO "PS2 ps0 -> f(0x%x, 0x%x) = 0x%x\n", |
580 | ps0_in1, ps0_in2, ps0_out); | 581 | ps0_in1, ps0_in2, ps0_out); |
581 | 582 | ||
582 | kvm_cvt_fd(&ps0_out, &fpr[reg_out], &vcpu->arch.fpscr); | 583 | kvm_cvt_fd(&ps0_out, &fpr[reg_out]); |
583 | } | 584 | } |
584 | 585 | ||
585 | /* PS1 */ | 586 | /* PS1 */ |
@@ -615,13 +616,13 @@ static int kvmppc_ps_one_in(struct kvm_vcpu *vcpu, bool rc, | |||
615 | WARN_ON(rc); | 616 | WARN_ON(rc); |
616 | 617 | ||
617 | /* PS0 */ | 618 | /* PS0 */ |
618 | kvm_cvt_df(&fpr[reg_in], &ps0_in, &vcpu->arch.fpscr); | 619 | kvm_cvt_df(&fpr[reg_in], &ps0_in); |
619 | func(&vcpu->arch.fpscr, &ps0_out, &ps0_in); | 620 | func(&vcpu->arch.fpscr, &ps0_out, &ps0_in); |
620 | 621 | ||
621 | dprintk(KERN_INFO "PS1 ps0 -> f(0x%x) = 0x%x\n", | 622 | dprintk(KERN_INFO "PS1 ps0 -> f(0x%x) = 0x%x\n", |
622 | ps0_in, ps0_out); | 623 | ps0_in, ps0_out); |
623 | 624 | ||
624 | kvm_cvt_fd(&ps0_out, &fpr[reg_out], &vcpu->arch.fpscr); | 625 | kvm_cvt_fd(&ps0_out, &fpr[reg_out]); |
625 | 626 | ||
626 | /* PS1 */ | 627 | /* PS1 */ |
627 | ps1_in = qpr[reg_in]; | 628 | ps1_in = qpr[reg_in]; |
@@ -658,7 +659,7 @@ int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu) | |||
658 | if (!kvmppc_inst_is_paired_single(vcpu, inst)) | 659 | if (!kvmppc_inst_is_paired_single(vcpu, inst)) |
659 | return EMULATE_FAIL; | 660 | return EMULATE_FAIL; |
660 | 661 | ||
661 | if (!(vcpu->arch.msr & MSR_FP)) { | 662 | if (!(vcpu->arch.shared->msr & MSR_FP)) { |
662 | kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL); | 663 | kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL); |
663 | return EMULATE_AGAIN; | 664 | return EMULATE_AGAIN; |
664 | } | 665 | } |
@@ -671,7 +672,7 @@ int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu) | |||
671 | #ifdef DEBUG | 672 | #ifdef DEBUG |
672 | for (i = 0; i < ARRAY_SIZE(vcpu->arch.fpr); i++) { | 673 | for (i = 0; i < ARRAY_SIZE(vcpu->arch.fpr); i++) { |
673 | u32 f; | 674 | u32 f; |
674 | kvm_cvt_df(&vcpu->arch.fpr[i], &f, &vcpu->arch.fpscr); | 675 | kvm_cvt_df(&vcpu->arch.fpr[i], &f); |
675 | dprintk(KERN_INFO "FPR[%d] = 0x%x / 0x%llx QPR[%d] = 0x%x\n", | 676 | dprintk(KERN_INFO "FPR[%d] = 0x%x / 0x%llx QPR[%d] = 0x%x\n", |
676 | i, f, vcpu->arch.fpr[i], i, vcpu->arch.qpr[i]); | 677 | i, f, vcpu->arch.fpr[i], i, vcpu->arch.qpr[i]); |
677 | } | 678 | } |
@@ -796,8 +797,7 @@ int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu) | |||
796 | vcpu->arch.fpr[ax_rd] = vcpu->arch.fpr[ax_ra]; | 797 | vcpu->arch.fpr[ax_rd] = vcpu->arch.fpr[ax_ra]; |
797 | /* vcpu->arch.qpr[ax_rd] = vcpu->arch.fpr[ax_rb]; */ | 798 | /* vcpu->arch.qpr[ax_rd] = vcpu->arch.fpr[ax_rb]; */ |
798 | kvm_cvt_df(&vcpu->arch.fpr[ax_rb], | 799 | kvm_cvt_df(&vcpu->arch.fpr[ax_rb], |
799 | &vcpu->arch.qpr[ax_rd], | 800 | &vcpu->arch.qpr[ax_rd]); |
800 | &vcpu->arch.fpscr); | ||
801 | break; | 801 | break; |
802 | case OP_4X_PS_MERGE01: | 802 | case OP_4X_PS_MERGE01: |
803 | WARN_ON(rcomp); | 803 | WARN_ON(rcomp); |
@@ -808,19 +808,16 @@ int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu) | |||
808 | WARN_ON(rcomp); | 808 | WARN_ON(rcomp); |
809 | /* vcpu->arch.fpr[ax_rd] = vcpu->arch.qpr[ax_ra]; */ | 809 | /* vcpu->arch.fpr[ax_rd] = vcpu->arch.qpr[ax_ra]; */ |
810 | kvm_cvt_fd(&vcpu->arch.qpr[ax_ra], | 810 | kvm_cvt_fd(&vcpu->arch.qpr[ax_ra], |
811 | &vcpu->arch.fpr[ax_rd], | 811 | &vcpu->arch.fpr[ax_rd]); |
812 | &vcpu->arch.fpscr); | ||
813 | /* vcpu->arch.qpr[ax_rd] = vcpu->arch.fpr[ax_rb]; */ | 812 | /* vcpu->arch.qpr[ax_rd] = vcpu->arch.fpr[ax_rb]; */ |
814 | kvm_cvt_df(&vcpu->arch.fpr[ax_rb], | 813 | kvm_cvt_df(&vcpu->arch.fpr[ax_rb], |
815 | &vcpu->arch.qpr[ax_rd], | 814 | &vcpu->arch.qpr[ax_rd]); |
816 | &vcpu->arch.fpscr); | ||
817 | break; | 815 | break; |
818 | case OP_4X_PS_MERGE11: | 816 | case OP_4X_PS_MERGE11: |
819 | WARN_ON(rcomp); | 817 | WARN_ON(rcomp); |
820 | /* vcpu->arch.fpr[ax_rd] = vcpu->arch.qpr[ax_ra]; */ | 818 | /* vcpu->arch.fpr[ax_rd] = vcpu->arch.qpr[ax_ra]; */ |
821 | kvm_cvt_fd(&vcpu->arch.qpr[ax_ra], | 819 | kvm_cvt_fd(&vcpu->arch.qpr[ax_ra], |
822 | &vcpu->arch.fpr[ax_rd], | 820 | &vcpu->arch.fpr[ax_rd]); |
823 | &vcpu->arch.fpscr); | ||
824 | vcpu->arch.qpr[ax_rd] = vcpu->arch.qpr[ax_rb]; | 821 | vcpu->arch.qpr[ax_rd] = vcpu->arch.qpr[ax_rb]; |
825 | break; | 822 | break; |
826 | } | 823 | } |
@@ -1255,7 +1252,7 @@ int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu) | |||
1255 | #ifdef DEBUG | 1252 | #ifdef DEBUG |
1256 | for (i = 0; i < ARRAY_SIZE(vcpu->arch.fpr); i++) { | 1253 | for (i = 0; i < ARRAY_SIZE(vcpu->arch.fpr); i++) { |
1257 | u32 f; | 1254 | u32 f; |
1258 | kvm_cvt_df(&vcpu->arch.fpr[i], &f, &vcpu->arch.fpscr); | 1255 | kvm_cvt_df(&vcpu->arch.fpr[i], &f); |
1259 | dprintk(KERN_INFO "FPR[%d] = 0x%x\n", i, f); | 1256 | dprintk(KERN_INFO "FPR[%d] = 0x%x\n", i, f); |
1260 | } | 1257 | } |
1261 | #endif | 1258 | #endif |
diff --git a/arch/powerpc/kvm/book3s_rmhandlers.S b/arch/powerpc/kvm/book3s_rmhandlers.S index 506d5c316c96..2b9c9088d00e 100644 --- a/arch/powerpc/kvm/book3s_rmhandlers.S +++ b/arch/powerpc/kvm/book3s_rmhandlers.S | |||
@@ -202,8 +202,25 @@ _GLOBAL(kvmppc_rmcall) | |||
202 | 202 | ||
203 | #if defined(CONFIG_PPC_BOOK3S_32) | 203 | #if defined(CONFIG_PPC_BOOK3S_32) |
204 | #define STACK_LR INT_FRAME_SIZE+4 | 204 | #define STACK_LR INT_FRAME_SIZE+4 |
205 | |||
206 | /* load_up_xxx have to run with MSR_DR=0 on Book3S_32 */ | ||
207 | #define MSR_EXT_START \ | ||
208 | PPC_STL r20, _NIP(r1); \ | ||
209 | mfmsr r20; \ | ||
210 | LOAD_REG_IMMEDIATE(r3, MSR_DR|MSR_EE); \ | ||
211 | andc r3,r20,r3; /* Disable DR,EE */ \ | ||
212 | mtmsr r3; \ | ||
213 | sync | ||
214 | |||
215 | #define MSR_EXT_END \ | ||
216 | mtmsr r20; /* Enable DR,EE */ \ | ||
217 | sync; \ | ||
218 | PPC_LL r20, _NIP(r1) | ||
219 | |||
205 | #elif defined(CONFIG_PPC_BOOK3S_64) | 220 | #elif defined(CONFIG_PPC_BOOK3S_64) |
206 | #define STACK_LR _LINK | 221 | #define STACK_LR _LINK |
222 | #define MSR_EXT_START | ||
223 | #define MSR_EXT_END | ||
207 | #endif | 224 | #endif |
208 | 225 | ||
209 | /* | 226 | /* |
@@ -215,19 +232,12 @@ _GLOBAL(kvmppc_load_up_ ## what); \ | |||
215 | PPC_STLU r1, -INT_FRAME_SIZE(r1); \ | 232 | PPC_STLU r1, -INT_FRAME_SIZE(r1); \ |
216 | mflr r3; \ | 233 | mflr r3; \ |
217 | PPC_STL r3, STACK_LR(r1); \ | 234 | PPC_STL r3, STACK_LR(r1); \ |
218 | PPC_STL r20, _NIP(r1); \ | 235 | MSR_EXT_START; \ |
219 | mfmsr r20; \ | ||
220 | LOAD_REG_IMMEDIATE(r3, MSR_DR|MSR_EE); \ | ||
221 | andc r3,r20,r3; /* Disable DR,EE */ \ | ||
222 | mtmsr r3; \ | ||
223 | sync; \ | ||
224 | \ | 236 | \ |
225 | bl FUNC(load_up_ ## what); \ | 237 | bl FUNC(load_up_ ## what); \ |
226 | \ | 238 | \ |
227 | mtmsr r20; /* Enable DR,EE */ \ | 239 | MSR_EXT_END; \ |
228 | sync; \ | ||
229 | PPC_LL r3, STACK_LR(r1); \ | 240 | PPC_LL r3, STACK_LR(r1); \ |
230 | PPC_LL r20, _NIP(r1); \ | ||
231 | mtlr r3; \ | 241 | mtlr r3; \ |
232 | addi r1, r1, INT_FRAME_SIZE; \ | 242 | addi r1, r1, INT_FRAME_SIZE; \ |
233 | blr | 243 | blr |
@@ -242,10 +252,10 @@ define_load_up(vsx) | |||
242 | 252 | ||
243 | .global kvmppc_trampoline_lowmem | 253 | .global kvmppc_trampoline_lowmem |
244 | kvmppc_trampoline_lowmem: | 254 | kvmppc_trampoline_lowmem: |
245 | .long kvmppc_handler_lowmem_trampoline - CONFIG_KERNEL_START | 255 | PPC_LONG kvmppc_handler_lowmem_trampoline - CONFIG_KERNEL_START |
246 | 256 | ||
247 | .global kvmppc_trampoline_enter | 257 | .global kvmppc_trampoline_enter |
248 | kvmppc_trampoline_enter: | 258 | kvmppc_trampoline_enter: |
249 | .long kvmppc_handler_trampoline_enter - CONFIG_KERNEL_START | 259 | PPC_LONG kvmppc_handler_trampoline_enter - CONFIG_KERNEL_START |
250 | 260 | ||
251 | #include "book3s_segment.S" | 261 | #include "book3s_segment.S" |
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index 8d4e35f5372c..77575d08c818 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c | |||
@@ -62,9 +62,10 @@ void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu) | |||
62 | { | 62 | { |
63 | int i; | 63 | int i; |
64 | 64 | ||
65 | printk("pc: %08lx msr: %08lx\n", vcpu->arch.pc, vcpu->arch.msr); | 65 | printk("pc: %08lx msr: %08llx\n", vcpu->arch.pc, vcpu->arch.shared->msr); |
66 | printk("lr: %08lx ctr: %08lx\n", vcpu->arch.lr, vcpu->arch.ctr); | 66 | printk("lr: %08lx ctr: %08lx\n", vcpu->arch.lr, vcpu->arch.ctr); |
67 | printk("srr0: %08lx srr1: %08lx\n", vcpu->arch.srr0, vcpu->arch.srr1); | 67 | printk("srr0: %08llx srr1: %08llx\n", vcpu->arch.shared->srr0, |
68 | vcpu->arch.shared->srr1); | ||
68 | 69 | ||
69 | printk("exceptions: %08lx\n", vcpu->arch.pending_exceptions); | 70 | printk("exceptions: %08lx\n", vcpu->arch.pending_exceptions); |
70 | 71 | ||
@@ -130,13 +131,19 @@ void kvmppc_core_dequeue_dec(struct kvm_vcpu *vcpu) | |||
130 | void kvmppc_core_queue_external(struct kvm_vcpu *vcpu, | 131 | void kvmppc_core_queue_external(struct kvm_vcpu *vcpu, |
131 | struct kvm_interrupt *irq) | 132 | struct kvm_interrupt *irq) |
132 | { | 133 | { |
133 | kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_EXTERNAL); | 134 | unsigned int prio = BOOKE_IRQPRIO_EXTERNAL; |
135 | |||
136 | if (irq->irq == KVM_INTERRUPT_SET_LEVEL) | ||
137 | prio = BOOKE_IRQPRIO_EXTERNAL_LEVEL; | ||
138 | |||
139 | kvmppc_booke_queue_irqprio(vcpu, prio); | ||
134 | } | 140 | } |
135 | 141 | ||
136 | void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu, | 142 | void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu, |
137 | struct kvm_interrupt *irq) | 143 | struct kvm_interrupt *irq) |
138 | { | 144 | { |
139 | clear_bit(BOOKE_IRQPRIO_EXTERNAL, &vcpu->arch.pending_exceptions); | 145 | clear_bit(BOOKE_IRQPRIO_EXTERNAL, &vcpu->arch.pending_exceptions); |
146 | clear_bit(BOOKE_IRQPRIO_EXTERNAL_LEVEL, &vcpu->arch.pending_exceptions); | ||
140 | } | 147 | } |
141 | 148 | ||
142 | /* Deliver the interrupt of the corresponding priority, if possible. */ | 149 | /* Deliver the interrupt of the corresponding priority, if possible. */ |
@@ -146,6 +153,26 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu, | |||
146 | int allowed = 0; | 153 | int allowed = 0; |
147 | ulong uninitialized_var(msr_mask); | 154 | ulong uninitialized_var(msr_mask); |
148 | bool update_esr = false, update_dear = false; | 155 | bool update_esr = false, update_dear = false; |
156 | ulong crit_raw = vcpu->arch.shared->critical; | ||
157 | ulong crit_r1 = kvmppc_get_gpr(vcpu, 1); | ||
158 | bool crit; | ||
159 | bool keep_irq = false; | ||
160 | |||
161 | /* Truncate crit indicators in 32 bit mode */ | ||
162 | if (!(vcpu->arch.shared->msr & MSR_SF)) { | ||
163 | crit_raw &= 0xffffffff; | ||
164 | crit_r1 &= 0xffffffff; | ||
165 | } | ||
166 | |||
167 | /* Critical section when crit == r1 */ | ||
168 | crit = (crit_raw == crit_r1); | ||
169 | /* ... and we're in supervisor mode */ | ||
170 | crit = crit && !(vcpu->arch.shared->msr & MSR_PR); | ||
171 | |||
172 | if (priority == BOOKE_IRQPRIO_EXTERNAL_LEVEL) { | ||
173 | priority = BOOKE_IRQPRIO_EXTERNAL; | ||
174 | keep_irq = true; | ||
175 | } | ||
149 | 176 | ||
150 | switch (priority) { | 177 | switch (priority) { |
151 | case BOOKE_IRQPRIO_DTLB_MISS: | 178 | case BOOKE_IRQPRIO_DTLB_MISS: |
@@ -169,36 +196,38 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu, | |||
169 | break; | 196 | break; |
170 | case BOOKE_IRQPRIO_CRITICAL: | 197 | case BOOKE_IRQPRIO_CRITICAL: |
171 | case BOOKE_IRQPRIO_WATCHDOG: | 198 | case BOOKE_IRQPRIO_WATCHDOG: |
172 | allowed = vcpu->arch.msr & MSR_CE; | 199 | allowed = vcpu->arch.shared->msr & MSR_CE; |
173 | msr_mask = MSR_ME; | 200 | msr_mask = MSR_ME; |
174 | break; | 201 | break; |
175 | case BOOKE_IRQPRIO_MACHINE_CHECK: | 202 | case BOOKE_IRQPRIO_MACHINE_CHECK: |
176 | allowed = vcpu->arch.msr & MSR_ME; | 203 | allowed = vcpu->arch.shared->msr & MSR_ME; |
177 | msr_mask = 0; | 204 | msr_mask = 0; |
178 | break; | 205 | break; |
179 | case BOOKE_IRQPRIO_EXTERNAL: | 206 | case BOOKE_IRQPRIO_EXTERNAL: |
180 | case BOOKE_IRQPRIO_DECREMENTER: | 207 | case BOOKE_IRQPRIO_DECREMENTER: |
181 | case BOOKE_IRQPRIO_FIT: | 208 | case BOOKE_IRQPRIO_FIT: |
182 | allowed = vcpu->arch.msr & MSR_EE; | 209 | allowed = vcpu->arch.shared->msr & MSR_EE; |
210 | allowed = allowed && !crit; | ||
183 | msr_mask = MSR_CE|MSR_ME|MSR_DE; | 211 | msr_mask = MSR_CE|MSR_ME|MSR_DE; |
184 | break; | 212 | break; |
185 | case BOOKE_IRQPRIO_DEBUG: | 213 | case BOOKE_IRQPRIO_DEBUG: |
186 | allowed = vcpu->arch.msr & MSR_DE; | 214 | allowed = vcpu->arch.shared->msr & MSR_DE; |
187 | msr_mask = MSR_ME; | 215 | msr_mask = MSR_ME; |
188 | break; | 216 | break; |
189 | } | 217 | } |
190 | 218 | ||
191 | if (allowed) { | 219 | if (allowed) { |
192 | vcpu->arch.srr0 = vcpu->arch.pc; | 220 | vcpu->arch.shared->srr0 = vcpu->arch.pc; |
193 | vcpu->arch.srr1 = vcpu->arch.msr; | 221 | vcpu->arch.shared->srr1 = vcpu->arch.shared->msr; |
194 | vcpu->arch.pc = vcpu->arch.ivpr | vcpu->arch.ivor[priority]; | 222 | vcpu->arch.pc = vcpu->arch.ivpr | vcpu->arch.ivor[priority]; |
195 | if (update_esr == true) | 223 | if (update_esr == true) |
196 | vcpu->arch.esr = vcpu->arch.queued_esr; | 224 | vcpu->arch.esr = vcpu->arch.queued_esr; |
197 | if (update_dear == true) | 225 | if (update_dear == true) |
198 | vcpu->arch.dear = vcpu->arch.queued_dear; | 226 | vcpu->arch.shared->dar = vcpu->arch.queued_dear; |
199 | kvmppc_set_msr(vcpu, vcpu->arch.msr & msr_mask); | 227 | kvmppc_set_msr(vcpu, vcpu->arch.shared->msr & msr_mask); |
200 | 228 | ||
201 | clear_bit(priority, &vcpu->arch.pending_exceptions); | 229 | if (!keep_irq) |
230 | clear_bit(priority, &vcpu->arch.pending_exceptions); | ||
202 | } | 231 | } |
203 | 232 | ||
204 | return allowed; | 233 | return allowed; |
@@ -208,6 +237,7 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu, | |||
208 | void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu) | 237 | void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu) |
209 | { | 238 | { |
210 | unsigned long *pending = &vcpu->arch.pending_exceptions; | 239 | unsigned long *pending = &vcpu->arch.pending_exceptions; |
240 | unsigned long old_pending = vcpu->arch.pending_exceptions; | ||
211 | unsigned int priority; | 241 | unsigned int priority; |
212 | 242 | ||
213 | priority = __ffs(*pending); | 243 | priority = __ffs(*pending); |
@@ -219,6 +249,12 @@ void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu) | |||
219 | BITS_PER_BYTE * sizeof(*pending), | 249 | BITS_PER_BYTE * sizeof(*pending), |
220 | priority + 1); | 250 | priority + 1); |
221 | } | 251 | } |
252 | |||
253 | /* Tell the guest about our interrupt status */ | ||
254 | if (*pending) | ||
255 | vcpu->arch.shared->int_pending = 1; | ||
256 | else if (old_pending) | ||
257 | vcpu->arch.shared->int_pending = 0; | ||
222 | } | 258 | } |
223 | 259 | ||
224 | /** | 260 | /** |
@@ -265,7 +301,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
265 | break; | 301 | break; |
266 | 302 | ||
267 | case BOOKE_INTERRUPT_PROGRAM: | 303 | case BOOKE_INTERRUPT_PROGRAM: |
268 | if (vcpu->arch.msr & MSR_PR) { | 304 | if (vcpu->arch.shared->msr & MSR_PR) { |
269 | /* Program traps generated by user-level software must be handled | 305 | /* Program traps generated by user-level software must be handled |
270 | * by the guest kernel. */ | 306 | * by the guest kernel. */ |
271 | kvmppc_core_queue_program(vcpu, vcpu->arch.fault_esr); | 307 | kvmppc_core_queue_program(vcpu, vcpu->arch.fault_esr); |
@@ -337,7 +373,15 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
337 | break; | 373 | break; |
338 | 374 | ||
339 | case BOOKE_INTERRUPT_SYSCALL: | 375 | case BOOKE_INTERRUPT_SYSCALL: |
340 | kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_SYSCALL); | 376 | if (!(vcpu->arch.shared->msr & MSR_PR) && |
377 | (((u32)kvmppc_get_gpr(vcpu, 0)) == KVM_SC_MAGIC_R0)) { | ||
378 | /* KVM PV hypercalls */ | ||
379 | kvmppc_set_gpr(vcpu, 3, kvmppc_kvm_pv(vcpu)); | ||
380 | r = RESUME_GUEST; | ||
381 | } else { | ||
382 | /* Guest syscalls */ | ||
383 | kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_SYSCALL); | ||
384 | } | ||
341 | kvmppc_account_exit(vcpu, SYSCALL_EXITS); | 385 | kvmppc_account_exit(vcpu, SYSCALL_EXITS); |
342 | r = RESUME_GUEST; | 386 | r = RESUME_GUEST; |
343 | break; | 387 | break; |
@@ -466,15 +510,19 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
466 | /* Initial guest state: 16MB mapping 0 -> 0, PC = 0, MSR = 0, R1 = 16MB */ | 510 | /* Initial guest state: 16MB mapping 0 -> 0, PC = 0, MSR = 0, R1 = 16MB */ |
467 | int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) | 511 | int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) |
468 | { | 512 | { |
513 | int i; | ||
514 | |||
469 | vcpu->arch.pc = 0; | 515 | vcpu->arch.pc = 0; |
470 | vcpu->arch.msr = 0; | 516 | vcpu->arch.shared->msr = 0; |
471 | kvmppc_set_gpr(vcpu, 1, (16<<20) - 8); /* -8 for the callee-save LR slot */ | 517 | kvmppc_set_gpr(vcpu, 1, (16<<20) - 8); /* -8 for the callee-save LR slot */ |
472 | 518 | ||
473 | vcpu->arch.shadow_pid = 1; | 519 | vcpu->arch.shadow_pid = 1; |
474 | 520 | ||
475 | /* Eye-catching number so we know if the guest takes an interrupt | 521 | /* Eye-catching numbers so we know if the guest takes an interrupt |
476 | * before it's programmed its own IVPR. */ | 522 | * before it's programmed its own IVPR/IVORs. */ |
477 | vcpu->arch.ivpr = 0x55550000; | 523 | vcpu->arch.ivpr = 0x55550000; |
524 | for (i = 0; i < BOOKE_IRQPRIO_MAX; i++) | ||
525 | vcpu->arch.ivor[i] = 0x7700 | i * 4; | ||
478 | 526 | ||
479 | kvmppc_init_timing_stats(vcpu); | 527 | kvmppc_init_timing_stats(vcpu); |
480 | 528 | ||
@@ -490,14 +538,14 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) | |||
490 | regs->ctr = vcpu->arch.ctr; | 538 | regs->ctr = vcpu->arch.ctr; |
491 | regs->lr = vcpu->arch.lr; | 539 | regs->lr = vcpu->arch.lr; |
492 | regs->xer = kvmppc_get_xer(vcpu); | 540 | regs->xer = kvmppc_get_xer(vcpu); |
493 | regs->msr = vcpu->arch.msr; | 541 | regs->msr = vcpu->arch.shared->msr; |
494 | regs->srr0 = vcpu->arch.srr0; | 542 | regs->srr0 = vcpu->arch.shared->srr0; |
495 | regs->srr1 = vcpu->arch.srr1; | 543 | regs->srr1 = vcpu->arch.shared->srr1; |
496 | regs->pid = vcpu->arch.pid; | 544 | regs->pid = vcpu->arch.pid; |
497 | regs->sprg0 = vcpu->arch.sprg0; | 545 | regs->sprg0 = vcpu->arch.shared->sprg0; |
498 | regs->sprg1 = vcpu->arch.sprg1; | 546 | regs->sprg1 = vcpu->arch.shared->sprg1; |
499 | regs->sprg2 = vcpu->arch.sprg2; | 547 | regs->sprg2 = vcpu->arch.shared->sprg2; |
500 | regs->sprg3 = vcpu->arch.sprg3; | 548 | regs->sprg3 = vcpu->arch.shared->sprg3; |
501 | regs->sprg5 = vcpu->arch.sprg4; | 549 | regs->sprg5 = vcpu->arch.sprg4; |
502 | regs->sprg6 = vcpu->arch.sprg5; | 550 | regs->sprg6 = vcpu->arch.sprg5; |
503 | regs->sprg7 = vcpu->arch.sprg6; | 551 | regs->sprg7 = vcpu->arch.sprg6; |
@@ -518,12 +566,12 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) | |||
518 | vcpu->arch.lr = regs->lr; | 566 | vcpu->arch.lr = regs->lr; |
519 | kvmppc_set_xer(vcpu, regs->xer); | 567 | kvmppc_set_xer(vcpu, regs->xer); |
520 | kvmppc_set_msr(vcpu, regs->msr); | 568 | kvmppc_set_msr(vcpu, regs->msr); |
521 | vcpu->arch.srr0 = regs->srr0; | 569 | vcpu->arch.shared->srr0 = regs->srr0; |
522 | vcpu->arch.srr1 = regs->srr1; | 570 | vcpu->arch.shared->srr1 = regs->srr1; |
523 | vcpu->arch.sprg0 = regs->sprg0; | 571 | vcpu->arch.shared->sprg0 = regs->sprg0; |
524 | vcpu->arch.sprg1 = regs->sprg1; | 572 | vcpu->arch.shared->sprg1 = regs->sprg1; |
525 | vcpu->arch.sprg2 = regs->sprg2; | 573 | vcpu->arch.shared->sprg2 = regs->sprg2; |
526 | vcpu->arch.sprg3 = regs->sprg3; | 574 | vcpu->arch.shared->sprg3 = regs->sprg3; |
527 | vcpu->arch.sprg5 = regs->sprg4; | 575 | vcpu->arch.sprg5 = regs->sprg4; |
528 | vcpu->arch.sprg6 = regs->sprg5; | 576 | vcpu->arch.sprg6 = regs->sprg5; |
529 | vcpu->arch.sprg7 = regs->sprg6; | 577 | vcpu->arch.sprg7 = regs->sprg6; |
diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h index d59bcca1f9d8..492bb7030358 100644 --- a/arch/powerpc/kvm/booke.h +++ b/arch/powerpc/kvm/booke.h | |||
@@ -46,7 +46,9 @@ | |||
46 | #define BOOKE_IRQPRIO_FIT 17 | 46 | #define BOOKE_IRQPRIO_FIT 17 |
47 | #define BOOKE_IRQPRIO_DECREMENTER 18 | 47 | #define BOOKE_IRQPRIO_DECREMENTER 18 |
48 | #define BOOKE_IRQPRIO_PERFORMANCE_MONITOR 19 | 48 | #define BOOKE_IRQPRIO_PERFORMANCE_MONITOR 19 |
49 | #define BOOKE_IRQPRIO_MAX 19 | 49 | /* Internal pseudo-irqprio for level triggered externals */ |
50 | #define BOOKE_IRQPRIO_EXTERNAL_LEVEL 20 | ||
51 | #define BOOKE_IRQPRIO_MAX 20 | ||
50 | 52 | ||
51 | extern unsigned long kvmppc_booke_handlers; | 53 | extern unsigned long kvmppc_booke_handlers; |
52 | 54 | ||
@@ -54,12 +56,12 @@ extern unsigned long kvmppc_booke_handlers; | |||
54 | * changing. */ | 56 | * changing. */ |
55 | static inline void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr) | 57 | static inline void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr) |
56 | { | 58 | { |
57 | if ((new_msr & MSR_PR) != (vcpu->arch.msr & MSR_PR)) | 59 | if ((new_msr & MSR_PR) != (vcpu->arch.shared->msr & MSR_PR)) |
58 | kvmppc_mmu_priv_switch(vcpu, new_msr & MSR_PR); | 60 | kvmppc_mmu_priv_switch(vcpu, new_msr & MSR_PR); |
59 | 61 | ||
60 | vcpu->arch.msr = new_msr; | 62 | vcpu->arch.shared->msr = new_msr; |
61 | 63 | ||
62 | if (vcpu->arch.msr & MSR_WE) { | 64 | if (vcpu->arch.shared->msr & MSR_WE) { |
63 | kvm_vcpu_block(vcpu); | 65 | kvm_vcpu_block(vcpu); |
64 | kvmppc_set_exit_type(vcpu, EMULATED_MTMSRWE_EXITS); | 66 | kvmppc_set_exit_type(vcpu, EMULATED_MTMSRWE_EXITS); |
65 | }; | 67 | }; |
diff --git a/arch/powerpc/kvm/booke_emulate.c b/arch/powerpc/kvm/booke_emulate.c index cbc790ee1928..1260f5f24c0c 100644 --- a/arch/powerpc/kvm/booke_emulate.c +++ b/arch/powerpc/kvm/booke_emulate.c | |||
@@ -31,8 +31,8 @@ | |||
31 | 31 | ||
32 | static void kvmppc_emul_rfi(struct kvm_vcpu *vcpu) | 32 | static void kvmppc_emul_rfi(struct kvm_vcpu *vcpu) |
33 | { | 33 | { |
34 | vcpu->arch.pc = vcpu->arch.srr0; | 34 | vcpu->arch.pc = vcpu->arch.shared->srr0; |
35 | kvmppc_set_msr(vcpu, vcpu->arch.srr1); | 35 | kvmppc_set_msr(vcpu, vcpu->arch.shared->srr1); |
36 | } | 36 | } |
37 | 37 | ||
38 | int kvmppc_booke_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, | 38 | int kvmppc_booke_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, |
@@ -62,7 +62,7 @@ int kvmppc_booke_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
62 | 62 | ||
63 | case OP_31_XOP_MFMSR: | 63 | case OP_31_XOP_MFMSR: |
64 | rt = get_rt(inst); | 64 | rt = get_rt(inst); |
65 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.msr); | 65 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->msr); |
66 | kvmppc_set_exit_type(vcpu, EMULATED_MFMSR_EXITS); | 66 | kvmppc_set_exit_type(vcpu, EMULATED_MFMSR_EXITS); |
67 | break; | 67 | break; |
68 | 68 | ||
@@ -74,13 +74,13 @@ int kvmppc_booke_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
74 | 74 | ||
75 | case OP_31_XOP_WRTEE: | 75 | case OP_31_XOP_WRTEE: |
76 | rs = get_rs(inst); | 76 | rs = get_rs(inst); |
77 | vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE) | 77 | vcpu->arch.shared->msr = (vcpu->arch.shared->msr & ~MSR_EE) |
78 | | (kvmppc_get_gpr(vcpu, rs) & MSR_EE); | 78 | | (kvmppc_get_gpr(vcpu, rs) & MSR_EE); |
79 | kvmppc_set_exit_type(vcpu, EMULATED_WRTEE_EXITS); | 79 | kvmppc_set_exit_type(vcpu, EMULATED_WRTEE_EXITS); |
80 | break; | 80 | break; |
81 | 81 | ||
82 | case OP_31_XOP_WRTEEI: | 82 | case OP_31_XOP_WRTEEI: |
83 | vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE) | 83 | vcpu->arch.shared->msr = (vcpu->arch.shared->msr & ~MSR_EE) |
84 | | (inst & MSR_EE); | 84 | | (inst & MSR_EE); |
85 | kvmppc_set_exit_type(vcpu, EMULATED_WRTEE_EXITS); | 85 | kvmppc_set_exit_type(vcpu, EMULATED_WRTEE_EXITS); |
86 | break; | 86 | break; |
@@ -105,7 +105,7 @@ int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs) | |||
105 | 105 | ||
106 | switch (sprn) { | 106 | switch (sprn) { |
107 | case SPRN_DEAR: | 107 | case SPRN_DEAR: |
108 | vcpu->arch.dear = spr_val; break; | 108 | vcpu->arch.shared->dar = spr_val; break; |
109 | case SPRN_ESR: | 109 | case SPRN_ESR: |
110 | vcpu->arch.esr = spr_val; break; | 110 | vcpu->arch.esr = spr_val; break; |
111 | case SPRN_DBCR0: | 111 | case SPRN_DBCR0: |
@@ -200,7 +200,7 @@ int kvmppc_booke_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt) | |||
200 | case SPRN_IVPR: | 200 | case SPRN_IVPR: |
201 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivpr); break; | 201 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.ivpr); break; |
202 | case SPRN_DEAR: | 202 | case SPRN_DEAR: |
203 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.dear); break; | 203 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->dar); break; |
204 | case SPRN_ESR: | 204 | case SPRN_ESR: |
205 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.esr); break; | 205 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.esr); break; |
206 | case SPRN_DBCR0: | 206 | case SPRN_DBCR0: |
diff --git a/arch/powerpc/kvm/booke_interrupts.S b/arch/powerpc/kvm/booke_interrupts.S index 380a78cf484d..049846911ce4 100644 --- a/arch/powerpc/kvm/booke_interrupts.S +++ b/arch/powerpc/kvm/booke_interrupts.S | |||
@@ -415,7 +415,8 @@ lightweight_exit: | |||
415 | lwz r8, VCPU_GPR(r8)(r4) | 415 | lwz r8, VCPU_GPR(r8)(r4) |
416 | lwz r3, VCPU_PC(r4) | 416 | lwz r3, VCPU_PC(r4) |
417 | mtsrr0 r3 | 417 | mtsrr0 r3 |
418 | lwz r3, VCPU_MSR(r4) | 418 | lwz r3, VCPU_SHARED(r4) |
419 | lwz r3, VCPU_SHARED_MSR(r3) | ||
419 | oris r3, r3, KVMPPC_MSR_MASK@h | 420 | oris r3, r3, KVMPPC_MSR_MASK@h |
420 | ori r3, r3, KVMPPC_MSR_MASK@l | 421 | ori r3, r3, KVMPPC_MSR_MASK@l |
421 | mtsrr1 r3 | 422 | mtsrr1 r3 |
diff --git a/arch/powerpc/kvm/e500.c b/arch/powerpc/kvm/e500.c index e8a00b0c4449..71750f2dd5d3 100644 --- a/arch/powerpc/kvm/e500.c +++ b/arch/powerpc/kvm/e500.c | |||
@@ -117,8 +117,14 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id) | |||
117 | if (err) | 117 | if (err) |
118 | goto uninit_vcpu; | 118 | goto uninit_vcpu; |
119 | 119 | ||
120 | vcpu->arch.shared = (void*)__get_free_page(GFP_KERNEL|__GFP_ZERO); | ||
121 | if (!vcpu->arch.shared) | ||
122 | goto uninit_tlb; | ||
123 | |||
120 | return vcpu; | 124 | return vcpu; |
121 | 125 | ||
126 | uninit_tlb: | ||
127 | kvmppc_e500_tlb_uninit(vcpu_e500); | ||
122 | uninit_vcpu: | 128 | uninit_vcpu: |
123 | kvm_vcpu_uninit(vcpu); | 129 | kvm_vcpu_uninit(vcpu); |
124 | free_vcpu: | 130 | free_vcpu: |
@@ -131,6 +137,7 @@ void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu) | |||
131 | { | 137 | { |
132 | struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); | 138 | struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); |
133 | 139 | ||
140 | free_page((unsigned long)vcpu->arch.shared); | ||
134 | kvmppc_e500_tlb_uninit(vcpu_e500); | 141 | kvmppc_e500_tlb_uninit(vcpu_e500); |
135 | kvm_vcpu_uninit(vcpu); | 142 | kvm_vcpu_uninit(vcpu); |
136 | kmem_cache_free(kvm_vcpu_cache, vcpu_e500); | 143 | kmem_cache_free(kvm_vcpu_cache, vcpu_e500); |
diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c index 21011e12caeb..d6d6d47a75a9 100644 --- a/arch/powerpc/kvm/e500_tlb.c +++ b/arch/powerpc/kvm/e500_tlb.c | |||
@@ -226,8 +226,7 @@ static void kvmppc_e500_stlbe_invalidate(struct kvmppc_vcpu_e500 *vcpu_e500, | |||
226 | 226 | ||
227 | kvmppc_e500_shadow_release(vcpu_e500, tlbsel, esel); | 227 | kvmppc_e500_shadow_release(vcpu_e500, tlbsel, esel); |
228 | stlbe->mas1 = 0; | 228 | stlbe->mas1 = 0; |
229 | trace_kvm_stlb_inval(index_of(tlbsel, esel), stlbe->mas1, stlbe->mas2, | 229 | trace_kvm_stlb_inval(index_of(tlbsel, esel)); |
230 | stlbe->mas3, stlbe->mas7); | ||
231 | } | 230 | } |
232 | 231 | ||
233 | static void kvmppc_e500_tlb1_invalidate(struct kvmppc_vcpu_e500 *vcpu_e500, | 232 | static void kvmppc_e500_tlb1_invalidate(struct kvmppc_vcpu_e500 *vcpu_e500, |
@@ -298,7 +297,8 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, | |||
298 | /* Get reference to new page. */ | 297 | /* Get reference to new page. */ |
299 | new_page = gfn_to_page(vcpu_e500->vcpu.kvm, gfn); | 298 | new_page = gfn_to_page(vcpu_e500->vcpu.kvm, gfn); |
300 | if (is_error_page(new_page)) { | 299 | if (is_error_page(new_page)) { |
301 | printk(KERN_ERR "Couldn't get guest page for gfn %lx!\n", gfn); | 300 | printk(KERN_ERR "Couldn't get guest page for gfn %lx!\n", |
301 | (long)gfn); | ||
302 | kvm_release_page_clean(new_page); | 302 | kvm_release_page_clean(new_page); |
303 | return; | 303 | return; |
304 | } | 304 | } |
@@ -314,10 +314,10 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, | |||
314 | | MAS1_TID(get_tlb_tid(gtlbe)) | MAS1_TS | MAS1_VALID; | 314 | | MAS1_TID(get_tlb_tid(gtlbe)) | MAS1_TS | MAS1_VALID; |
315 | stlbe->mas2 = (gvaddr & MAS2_EPN) | 315 | stlbe->mas2 = (gvaddr & MAS2_EPN) |
316 | | e500_shadow_mas2_attrib(gtlbe->mas2, | 316 | | e500_shadow_mas2_attrib(gtlbe->mas2, |
317 | vcpu_e500->vcpu.arch.msr & MSR_PR); | 317 | vcpu_e500->vcpu.arch.shared->msr & MSR_PR); |
318 | stlbe->mas3 = (hpaddr & MAS3_RPN) | 318 | stlbe->mas3 = (hpaddr & MAS3_RPN) |
319 | | e500_shadow_mas3_attrib(gtlbe->mas3, | 319 | | e500_shadow_mas3_attrib(gtlbe->mas3, |
320 | vcpu_e500->vcpu.arch.msr & MSR_PR); | 320 | vcpu_e500->vcpu.arch.shared->msr & MSR_PR); |
321 | stlbe->mas7 = (hpaddr >> 32) & MAS7_RPN; | 321 | stlbe->mas7 = (hpaddr >> 32) & MAS7_RPN; |
322 | 322 | ||
323 | trace_kvm_stlb_write(index_of(tlbsel, esel), stlbe->mas1, stlbe->mas2, | 323 | trace_kvm_stlb_write(index_of(tlbsel, esel), stlbe->mas1, stlbe->mas2, |
@@ -576,28 +576,28 @@ int kvmppc_e500_emul_tlbwe(struct kvm_vcpu *vcpu) | |||
576 | 576 | ||
577 | int kvmppc_mmu_itlb_index(struct kvm_vcpu *vcpu, gva_t eaddr) | 577 | int kvmppc_mmu_itlb_index(struct kvm_vcpu *vcpu, gva_t eaddr) |
578 | { | 578 | { |
579 | unsigned int as = !!(vcpu->arch.msr & MSR_IS); | 579 | unsigned int as = !!(vcpu->arch.shared->msr & MSR_IS); |
580 | 580 | ||
581 | return kvmppc_e500_tlb_search(vcpu, eaddr, get_cur_pid(vcpu), as); | 581 | return kvmppc_e500_tlb_search(vcpu, eaddr, get_cur_pid(vcpu), as); |
582 | } | 582 | } |
583 | 583 | ||
584 | int kvmppc_mmu_dtlb_index(struct kvm_vcpu *vcpu, gva_t eaddr) | 584 | int kvmppc_mmu_dtlb_index(struct kvm_vcpu *vcpu, gva_t eaddr) |
585 | { | 585 | { |
586 | unsigned int as = !!(vcpu->arch.msr & MSR_DS); | 586 | unsigned int as = !!(vcpu->arch.shared->msr & MSR_DS); |
587 | 587 | ||
588 | return kvmppc_e500_tlb_search(vcpu, eaddr, get_cur_pid(vcpu), as); | 588 | return kvmppc_e500_tlb_search(vcpu, eaddr, get_cur_pid(vcpu), as); |
589 | } | 589 | } |
590 | 590 | ||
591 | void kvmppc_mmu_itlb_miss(struct kvm_vcpu *vcpu) | 591 | void kvmppc_mmu_itlb_miss(struct kvm_vcpu *vcpu) |
592 | { | 592 | { |
593 | unsigned int as = !!(vcpu->arch.msr & MSR_IS); | 593 | unsigned int as = !!(vcpu->arch.shared->msr & MSR_IS); |
594 | 594 | ||
595 | kvmppc_e500_deliver_tlb_miss(vcpu, vcpu->arch.pc, as); | 595 | kvmppc_e500_deliver_tlb_miss(vcpu, vcpu->arch.pc, as); |
596 | } | 596 | } |
597 | 597 | ||
598 | void kvmppc_mmu_dtlb_miss(struct kvm_vcpu *vcpu) | 598 | void kvmppc_mmu_dtlb_miss(struct kvm_vcpu *vcpu) |
599 | { | 599 | { |
600 | unsigned int as = !!(vcpu->arch.msr & MSR_DS); | 600 | unsigned int as = !!(vcpu->arch.shared->msr & MSR_DS); |
601 | 601 | ||
602 | kvmppc_e500_deliver_tlb_miss(vcpu, vcpu->arch.fault_dear, as); | 602 | kvmppc_e500_deliver_tlb_miss(vcpu, vcpu->arch.fault_dear, as); |
603 | } | 603 | } |
diff --git a/arch/powerpc/kvm/e500_tlb.h b/arch/powerpc/kvm/e500_tlb.h index d28e3010a5e2..458946b4775d 100644 --- a/arch/powerpc/kvm/e500_tlb.h +++ b/arch/powerpc/kvm/e500_tlb.h | |||
@@ -171,7 +171,7 @@ static inline int tlbe_is_host_safe(const struct kvm_vcpu *vcpu, | |||
171 | 171 | ||
172 | /* Does it match current guest AS? */ | 172 | /* Does it match current guest AS? */ |
173 | /* XXX what about IS != DS? */ | 173 | /* XXX what about IS != DS? */ |
174 | if (get_tlb_ts(tlbe) != !!(vcpu->arch.msr & MSR_IS)) | 174 | if (get_tlb_ts(tlbe) != !!(vcpu->arch.shared->msr & MSR_IS)) |
175 | return 0; | 175 | return 0; |
176 | 176 | ||
177 | gpa = get_tlb_raddr(tlbe); | 177 | gpa = get_tlb_raddr(tlbe); |
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c index 4568ec386c2a..c64fd2909bb2 100644 --- a/arch/powerpc/kvm/emulate.c +++ b/arch/powerpc/kvm/emulate.c | |||
@@ -145,7 +145,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) | |||
145 | /* this default type might be overwritten by subcategories */ | 145 | /* this default type might be overwritten by subcategories */ |
146 | kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS); | 146 | kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS); |
147 | 147 | ||
148 | pr_debug(KERN_INFO "Emulating opcode %d / %d\n", get_op(inst), get_xop(inst)); | 148 | pr_debug("Emulating opcode %d / %d\n", get_op(inst), get_xop(inst)); |
149 | 149 | ||
150 | switch (get_op(inst)) { | 150 | switch (get_op(inst)) { |
151 | case OP_TRAP: | 151 | case OP_TRAP: |
@@ -242,9 +242,11 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) | |||
242 | 242 | ||
243 | switch (sprn) { | 243 | switch (sprn) { |
244 | case SPRN_SRR0: | 244 | case SPRN_SRR0: |
245 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.srr0); break; | 245 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->srr0); |
246 | break; | ||
246 | case SPRN_SRR1: | 247 | case SPRN_SRR1: |
247 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.srr1); break; | 248 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->srr1); |
249 | break; | ||
248 | case SPRN_PVR: | 250 | case SPRN_PVR: |
249 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.pvr); break; | 251 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.pvr); break; |
250 | case SPRN_PIR: | 252 | case SPRN_PIR: |
@@ -261,13 +263,17 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) | |||
261 | kvmppc_set_gpr(vcpu, rt, get_tb()); break; | 263 | kvmppc_set_gpr(vcpu, rt, get_tb()); break; |
262 | 264 | ||
263 | case SPRN_SPRG0: | 265 | case SPRN_SPRG0: |
264 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.sprg0); break; | 266 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->sprg0); |
267 | break; | ||
265 | case SPRN_SPRG1: | 268 | case SPRN_SPRG1: |
266 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.sprg1); break; | 269 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->sprg1); |
270 | break; | ||
267 | case SPRN_SPRG2: | 271 | case SPRN_SPRG2: |
268 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.sprg2); break; | 272 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->sprg2); |
273 | break; | ||
269 | case SPRN_SPRG3: | 274 | case SPRN_SPRG3: |
270 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.sprg3); break; | 275 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.shared->sprg3); |
276 | break; | ||
271 | /* Note: SPRG4-7 are user-readable, so we don't get | 277 | /* Note: SPRG4-7 are user-readable, so we don't get |
272 | * a trap. */ | 278 | * a trap. */ |
273 | 279 | ||
@@ -275,7 +281,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) | |||
275 | { | 281 | { |
276 | u64 jd = get_tb() - vcpu->arch.dec_jiffies; | 282 | u64 jd = get_tb() - vcpu->arch.dec_jiffies; |
277 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.dec - jd); | 283 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.dec - jd); |
278 | pr_debug(KERN_INFO "mfDEC: %x - %llx = %lx\n", | 284 | pr_debug("mfDEC: %x - %llx = %lx\n", |
279 | vcpu->arch.dec, jd, | 285 | vcpu->arch.dec, jd, |
280 | kvmppc_get_gpr(vcpu, rt)); | 286 | kvmppc_get_gpr(vcpu, rt)); |
281 | break; | 287 | break; |
@@ -320,9 +326,11 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) | |||
320 | rs = get_rs(inst); | 326 | rs = get_rs(inst); |
321 | switch (sprn) { | 327 | switch (sprn) { |
322 | case SPRN_SRR0: | 328 | case SPRN_SRR0: |
323 | vcpu->arch.srr0 = kvmppc_get_gpr(vcpu, rs); break; | 329 | vcpu->arch.shared->srr0 = kvmppc_get_gpr(vcpu, rs); |
330 | break; | ||
324 | case SPRN_SRR1: | 331 | case SPRN_SRR1: |
325 | vcpu->arch.srr1 = kvmppc_get_gpr(vcpu, rs); break; | 332 | vcpu->arch.shared->srr1 = kvmppc_get_gpr(vcpu, rs); |
333 | break; | ||
326 | 334 | ||
327 | /* XXX We need to context-switch the timebase for | 335 | /* XXX We need to context-switch the timebase for |
328 | * watchdog and FIT. */ | 336 | * watchdog and FIT. */ |
@@ -337,13 +345,17 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) | |||
337 | break; | 345 | break; |
338 | 346 | ||
339 | case SPRN_SPRG0: | 347 | case SPRN_SPRG0: |
340 | vcpu->arch.sprg0 = kvmppc_get_gpr(vcpu, rs); break; | 348 | vcpu->arch.shared->sprg0 = kvmppc_get_gpr(vcpu, rs); |
349 | break; | ||
341 | case SPRN_SPRG1: | 350 | case SPRN_SPRG1: |
342 | vcpu->arch.sprg1 = kvmppc_get_gpr(vcpu, rs); break; | 351 | vcpu->arch.shared->sprg1 = kvmppc_get_gpr(vcpu, rs); |
352 | break; | ||
343 | case SPRN_SPRG2: | 353 | case SPRN_SPRG2: |
344 | vcpu->arch.sprg2 = kvmppc_get_gpr(vcpu, rs); break; | 354 | vcpu->arch.shared->sprg2 = kvmppc_get_gpr(vcpu, rs); |
355 | break; | ||
345 | case SPRN_SPRG3: | 356 | case SPRN_SPRG3: |
346 | vcpu->arch.sprg3 = kvmppc_get_gpr(vcpu, rs); break; | 357 | vcpu->arch.shared->sprg3 = kvmppc_get_gpr(vcpu, rs); |
358 | break; | ||
347 | 359 | ||
348 | default: | 360 | default: |
349 | emulated = kvmppc_core_emulate_mtspr(vcpu, sprn, rs); | 361 | emulated = kvmppc_core_emulate_mtspr(vcpu, sprn, rs); |
diff --git a/arch/powerpc/kvm/fpu.S b/arch/powerpc/kvm/fpu.S index cb34bbe16113..bf68d597549e 100644 --- a/arch/powerpc/kvm/fpu.S +++ b/arch/powerpc/kvm/fpu.S | |||
@@ -273,19 +273,11 @@ FPD_THREE_IN(fnmsub) | |||
273 | FPD_THREE_IN(fnmadd) | 273 | FPD_THREE_IN(fnmadd) |
274 | 274 | ||
275 | _GLOBAL(kvm_cvt_fd) | 275 | _GLOBAL(kvm_cvt_fd) |
276 | lfd 0,0(r5) /* load up fpscr value */ | ||
277 | MTFSF_L(0) | ||
278 | lfs 0,0(r3) | 276 | lfs 0,0(r3) |
279 | stfd 0,0(r4) | 277 | stfd 0,0(r4) |
280 | mffs 0 | ||
281 | stfd 0,0(r5) /* save new fpscr value */ | ||
282 | blr | 278 | blr |
283 | 279 | ||
284 | _GLOBAL(kvm_cvt_df) | 280 | _GLOBAL(kvm_cvt_df) |
285 | lfd 0,0(r5) /* load up fpscr value */ | ||
286 | MTFSF_L(0) | ||
287 | lfd 0,0(r3) | 281 | lfd 0,0(r3) |
288 | stfs 0,0(r4) | 282 | stfs 0,0(r4) |
289 | mffs 0 | ||
290 | stfd 0,0(r5) /* save new fpscr value */ | ||
291 | blr | 283 | blr |
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index 72a4ad86ee91..2f87a1627f6c 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c | |||
@@ -38,9 +38,56 @@ | |||
38 | 38 | ||
39 | int kvm_arch_vcpu_runnable(struct kvm_vcpu *v) | 39 | int kvm_arch_vcpu_runnable(struct kvm_vcpu *v) |
40 | { | 40 | { |
41 | return !(v->arch.msr & MSR_WE) || !!(v->arch.pending_exceptions); | 41 | return !(v->arch.shared->msr & MSR_WE) || |
42 | !!(v->arch.pending_exceptions); | ||
42 | } | 43 | } |
43 | 44 | ||
45 | int kvmppc_kvm_pv(struct kvm_vcpu *vcpu) | ||
46 | { | ||
47 | int nr = kvmppc_get_gpr(vcpu, 11); | ||
48 | int r; | ||
49 | unsigned long __maybe_unused param1 = kvmppc_get_gpr(vcpu, 3); | ||
50 | unsigned long __maybe_unused param2 = kvmppc_get_gpr(vcpu, 4); | ||
51 | unsigned long __maybe_unused param3 = kvmppc_get_gpr(vcpu, 5); | ||
52 | unsigned long __maybe_unused param4 = kvmppc_get_gpr(vcpu, 6); | ||
53 | unsigned long r2 = 0; | ||
54 | |||
55 | if (!(vcpu->arch.shared->msr & MSR_SF)) { | ||
56 | /* 32 bit mode */ | ||
57 | param1 &= 0xffffffff; | ||
58 | param2 &= 0xffffffff; | ||
59 | param3 &= 0xffffffff; | ||
60 | param4 &= 0xffffffff; | ||
61 | } | ||
62 | |||
63 | switch (nr) { | ||
64 | case HC_VENDOR_KVM | KVM_HC_PPC_MAP_MAGIC_PAGE: | ||
65 | { | ||
66 | vcpu->arch.magic_page_pa = param1; | ||
67 | vcpu->arch.magic_page_ea = param2; | ||
68 | |||
69 | r2 = KVM_MAGIC_FEAT_SR; | ||
70 | |||
71 | r = HC_EV_SUCCESS; | ||
72 | break; | ||
73 | } | ||
74 | case HC_VENDOR_KVM | KVM_HC_FEATURES: | ||
75 | r = HC_EV_SUCCESS; | ||
76 | #if defined(CONFIG_PPC_BOOK3S) /* XXX Missing magic page on BookE */ | ||
77 | r2 |= (1 << KVM_FEATURE_MAGIC_PAGE); | ||
78 | #endif | ||
79 | |||
80 | /* Second return value is in r4 */ | ||
81 | break; | ||
82 | default: | ||
83 | r = HC_EV_UNIMPLEMENTED; | ||
84 | break; | ||
85 | } | ||
86 | |||
87 | kvmppc_set_gpr(vcpu, 4, r2); | ||
88 | |||
89 | return r; | ||
90 | } | ||
44 | 91 | ||
45 | int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu) | 92 | int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu) |
46 | { | 93 | { |
@@ -145,8 +192,10 @@ int kvm_dev_ioctl_check_extension(long ext) | |||
145 | case KVM_CAP_PPC_SEGSTATE: | 192 | case KVM_CAP_PPC_SEGSTATE: |
146 | case KVM_CAP_PPC_PAIRED_SINGLES: | 193 | case KVM_CAP_PPC_PAIRED_SINGLES: |
147 | case KVM_CAP_PPC_UNSET_IRQ: | 194 | case KVM_CAP_PPC_UNSET_IRQ: |
195 | case KVM_CAP_PPC_IRQ_LEVEL: | ||
148 | case KVM_CAP_ENABLE_CAP: | 196 | case KVM_CAP_ENABLE_CAP: |
149 | case KVM_CAP_PPC_OSI: | 197 | case KVM_CAP_PPC_OSI: |
198 | case KVM_CAP_PPC_GET_PVINFO: | ||
150 | r = 1; | 199 | r = 1; |
151 | break; | 200 | break; |
152 | case KVM_CAP_COALESCED_MMIO: | 201 | case KVM_CAP_COALESCED_MMIO: |
@@ -534,16 +583,53 @@ out: | |||
534 | return r; | 583 | return r; |
535 | } | 584 | } |
536 | 585 | ||
586 | static int kvm_vm_ioctl_get_pvinfo(struct kvm_ppc_pvinfo *pvinfo) | ||
587 | { | ||
588 | u32 inst_lis = 0x3c000000; | ||
589 | u32 inst_ori = 0x60000000; | ||
590 | u32 inst_nop = 0x60000000; | ||
591 | u32 inst_sc = 0x44000002; | ||
592 | u32 inst_imm_mask = 0xffff; | ||
593 | |||
594 | /* | ||
595 | * The hypercall to get into KVM from within guest context is as | ||
596 | * follows: | ||
597 | * | ||
598 | * lis r0, r0, KVM_SC_MAGIC_R0@h | ||
599 | * ori r0, KVM_SC_MAGIC_R0@l | ||
600 | * sc | ||
601 | * nop | ||
602 | */ | ||
603 | pvinfo->hcall[0] = inst_lis | ((KVM_SC_MAGIC_R0 >> 16) & inst_imm_mask); | ||
604 | pvinfo->hcall[1] = inst_ori | (KVM_SC_MAGIC_R0 & inst_imm_mask); | ||
605 | pvinfo->hcall[2] = inst_sc; | ||
606 | pvinfo->hcall[3] = inst_nop; | ||
607 | |||
608 | return 0; | ||
609 | } | ||
610 | |||
537 | long kvm_arch_vm_ioctl(struct file *filp, | 611 | long kvm_arch_vm_ioctl(struct file *filp, |
538 | unsigned int ioctl, unsigned long arg) | 612 | unsigned int ioctl, unsigned long arg) |
539 | { | 613 | { |
614 | void __user *argp = (void __user *)arg; | ||
540 | long r; | 615 | long r; |
541 | 616 | ||
542 | switch (ioctl) { | 617 | switch (ioctl) { |
618 | case KVM_PPC_GET_PVINFO: { | ||
619 | struct kvm_ppc_pvinfo pvinfo; | ||
620 | r = kvm_vm_ioctl_get_pvinfo(&pvinfo); | ||
621 | if (copy_to_user(argp, &pvinfo, sizeof(pvinfo))) { | ||
622 | r = -EFAULT; | ||
623 | goto out; | ||
624 | } | ||
625 | |||
626 | break; | ||
627 | } | ||
543 | default: | 628 | default: |
544 | r = -ENOTTY; | 629 | r = -ENOTTY; |
545 | } | 630 | } |
546 | 631 | ||
632 | out: | ||
547 | return r; | 633 | return r; |
548 | } | 634 | } |
549 | 635 | ||
diff --git a/arch/powerpc/kvm/trace.h b/arch/powerpc/kvm/trace.h index a8e840018052..3aca1b042b8c 100644 --- a/arch/powerpc/kvm/trace.h +++ b/arch/powerpc/kvm/trace.h | |||
@@ -98,6 +98,245 @@ TRACE_EVENT(kvm_gtlb_write, | |||
98 | __entry->word1, __entry->word2) | 98 | __entry->word1, __entry->word2) |
99 | ); | 99 | ); |
100 | 100 | ||
101 | |||
102 | /************************************************************************* | ||
103 | * Book3S trace points * | ||
104 | *************************************************************************/ | ||
105 | |||
106 | #ifdef CONFIG_PPC_BOOK3S | ||
107 | |||
108 | TRACE_EVENT(kvm_book3s_exit, | ||
109 | TP_PROTO(unsigned int exit_nr, struct kvm_vcpu *vcpu), | ||
110 | TP_ARGS(exit_nr, vcpu), | ||
111 | |||
112 | TP_STRUCT__entry( | ||
113 | __field( unsigned int, exit_nr ) | ||
114 | __field( unsigned long, pc ) | ||
115 | __field( unsigned long, msr ) | ||
116 | __field( unsigned long, dar ) | ||
117 | __field( unsigned long, srr1 ) | ||
118 | ), | ||
119 | |||
120 | TP_fast_assign( | ||
121 | __entry->exit_nr = exit_nr; | ||
122 | __entry->pc = kvmppc_get_pc(vcpu); | ||
123 | __entry->dar = kvmppc_get_fault_dar(vcpu); | ||
124 | __entry->msr = vcpu->arch.shared->msr; | ||
125 | __entry->srr1 = to_svcpu(vcpu)->shadow_srr1; | ||
126 | ), | ||
127 | |||
128 | TP_printk("exit=0x%x | pc=0x%lx | msr=0x%lx | dar=0x%lx | srr1=0x%lx", | ||
129 | __entry->exit_nr, __entry->pc, __entry->msr, __entry->dar, | ||
130 | __entry->srr1) | ||
131 | ); | ||
132 | |||
133 | TRACE_EVENT(kvm_book3s_reenter, | ||
134 | TP_PROTO(int r, struct kvm_vcpu *vcpu), | ||
135 | TP_ARGS(r, vcpu), | ||
136 | |||
137 | TP_STRUCT__entry( | ||
138 | __field( unsigned int, r ) | ||
139 | __field( unsigned long, pc ) | ||
140 | ), | ||
141 | |||
142 | TP_fast_assign( | ||
143 | __entry->r = r; | ||
144 | __entry->pc = kvmppc_get_pc(vcpu); | ||
145 | ), | ||
146 | |||
147 | TP_printk("reentry r=%d | pc=0x%lx", __entry->r, __entry->pc) | ||
148 | ); | ||
149 | |||
150 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
151 | |||
152 | TRACE_EVENT(kvm_book3s_64_mmu_map, | ||
153 | TP_PROTO(int rflags, ulong hpteg, ulong va, pfn_t hpaddr, | ||
154 | struct kvmppc_pte *orig_pte), | ||
155 | TP_ARGS(rflags, hpteg, va, hpaddr, orig_pte), | ||
156 | |||
157 | TP_STRUCT__entry( | ||
158 | __field( unsigned char, flag_w ) | ||
159 | __field( unsigned char, flag_x ) | ||
160 | __field( unsigned long, eaddr ) | ||
161 | __field( unsigned long, hpteg ) | ||
162 | __field( unsigned long, va ) | ||
163 | __field( unsigned long long, vpage ) | ||
164 | __field( unsigned long, hpaddr ) | ||
165 | ), | ||
166 | |||
167 | TP_fast_assign( | ||
168 | __entry->flag_w = ((rflags & HPTE_R_PP) == 3) ? '-' : 'w'; | ||
169 | __entry->flag_x = (rflags & HPTE_R_N) ? '-' : 'x'; | ||
170 | __entry->eaddr = orig_pte->eaddr; | ||
171 | __entry->hpteg = hpteg; | ||
172 | __entry->va = va; | ||
173 | __entry->vpage = orig_pte->vpage; | ||
174 | __entry->hpaddr = hpaddr; | ||
175 | ), | ||
176 | |||
177 | TP_printk("KVM: %c%c Map 0x%lx: [%lx] 0x%lx (0x%llx) -> %lx", | ||
178 | __entry->flag_w, __entry->flag_x, __entry->eaddr, | ||
179 | __entry->hpteg, __entry->va, __entry->vpage, __entry->hpaddr) | ||
180 | ); | ||
181 | |||
182 | #endif /* CONFIG_PPC_BOOK3S_64 */ | ||
183 | |||
184 | TRACE_EVENT(kvm_book3s_mmu_map, | ||
185 | TP_PROTO(struct hpte_cache *pte), | ||
186 | TP_ARGS(pte), | ||
187 | |||
188 | TP_STRUCT__entry( | ||
189 | __field( u64, host_va ) | ||
190 | __field( u64, pfn ) | ||
191 | __field( ulong, eaddr ) | ||
192 | __field( u64, vpage ) | ||
193 | __field( ulong, raddr ) | ||
194 | __field( int, flags ) | ||
195 | ), | ||
196 | |||
197 | TP_fast_assign( | ||
198 | __entry->host_va = pte->host_va; | ||
199 | __entry->pfn = pte->pfn; | ||
200 | __entry->eaddr = pte->pte.eaddr; | ||
201 | __entry->vpage = pte->pte.vpage; | ||
202 | __entry->raddr = pte->pte.raddr; | ||
203 | __entry->flags = (pte->pte.may_read ? 0x4 : 0) | | ||
204 | (pte->pte.may_write ? 0x2 : 0) | | ||
205 | (pte->pte.may_execute ? 0x1 : 0); | ||
206 | ), | ||
207 | |||
208 | TP_printk("Map: hva=%llx pfn=%llx ea=%lx vp=%llx ra=%lx [%x]", | ||
209 | __entry->host_va, __entry->pfn, __entry->eaddr, | ||
210 | __entry->vpage, __entry->raddr, __entry->flags) | ||
211 | ); | ||
212 | |||
213 | TRACE_EVENT(kvm_book3s_mmu_invalidate, | ||
214 | TP_PROTO(struct hpte_cache *pte), | ||
215 | TP_ARGS(pte), | ||
216 | |||
217 | TP_STRUCT__entry( | ||
218 | __field( u64, host_va ) | ||
219 | __field( u64, pfn ) | ||
220 | __field( ulong, eaddr ) | ||
221 | __field( u64, vpage ) | ||
222 | __field( ulong, raddr ) | ||
223 | __field( int, flags ) | ||
224 | ), | ||
225 | |||
226 | TP_fast_assign( | ||
227 | __entry->host_va = pte->host_va; | ||
228 | __entry->pfn = pte->pfn; | ||
229 | __entry->eaddr = pte->pte.eaddr; | ||
230 | __entry->vpage = pte->pte.vpage; | ||
231 | __entry->raddr = pte->pte.raddr; | ||
232 | __entry->flags = (pte->pte.may_read ? 0x4 : 0) | | ||
233 | (pte->pte.may_write ? 0x2 : 0) | | ||
234 | (pte->pte.may_execute ? 0x1 : 0); | ||
235 | ), | ||
236 | |||
237 | TP_printk("Flush: hva=%llx pfn=%llx ea=%lx vp=%llx ra=%lx [%x]", | ||
238 | __entry->host_va, __entry->pfn, __entry->eaddr, | ||
239 | __entry->vpage, __entry->raddr, __entry->flags) | ||
240 | ); | ||
241 | |||
242 | TRACE_EVENT(kvm_book3s_mmu_flush, | ||
243 | TP_PROTO(const char *type, struct kvm_vcpu *vcpu, unsigned long long p1, | ||
244 | unsigned long long p2), | ||
245 | TP_ARGS(type, vcpu, p1, p2), | ||
246 | |||
247 | TP_STRUCT__entry( | ||
248 | __field( int, count ) | ||
249 | __field( unsigned long long, p1 ) | ||
250 | __field( unsigned long long, p2 ) | ||
251 | __field( const char *, type ) | ||
252 | ), | ||
253 | |||
254 | TP_fast_assign( | ||
255 | __entry->count = vcpu->arch.hpte_cache_count; | ||
256 | __entry->p1 = p1; | ||
257 | __entry->p2 = p2; | ||
258 | __entry->type = type; | ||
259 | ), | ||
260 | |||
261 | TP_printk("Flush %d %sPTEs: %llx - %llx", | ||
262 | __entry->count, __entry->type, __entry->p1, __entry->p2) | ||
263 | ); | ||
264 | |||
265 | TRACE_EVENT(kvm_book3s_slb_found, | ||
266 | TP_PROTO(unsigned long long gvsid, unsigned long long hvsid), | ||
267 | TP_ARGS(gvsid, hvsid), | ||
268 | |||
269 | TP_STRUCT__entry( | ||
270 | __field( unsigned long long, gvsid ) | ||
271 | __field( unsigned long long, hvsid ) | ||
272 | ), | ||
273 | |||
274 | TP_fast_assign( | ||
275 | __entry->gvsid = gvsid; | ||
276 | __entry->hvsid = hvsid; | ||
277 | ), | ||
278 | |||
279 | TP_printk("%llx -> %llx", __entry->gvsid, __entry->hvsid) | ||
280 | ); | ||
281 | |||
282 | TRACE_EVENT(kvm_book3s_slb_fail, | ||
283 | TP_PROTO(u16 sid_map_mask, unsigned long long gvsid), | ||
284 | TP_ARGS(sid_map_mask, gvsid), | ||
285 | |||
286 | TP_STRUCT__entry( | ||
287 | __field( unsigned short, sid_map_mask ) | ||
288 | __field( unsigned long long, gvsid ) | ||
289 | ), | ||
290 | |||
291 | TP_fast_assign( | ||
292 | __entry->sid_map_mask = sid_map_mask; | ||
293 | __entry->gvsid = gvsid; | ||
294 | ), | ||
295 | |||
296 | TP_printk("%x/%x: %llx", __entry->sid_map_mask, | ||
297 | SID_MAP_MASK - __entry->sid_map_mask, __entry->gvsid) | ||
298 | ); | ||
299 | |||
300 | TRACE_EVENT(kvm_book3s_slb_map, | ||
301 | TP_PROTO(u16 sid_map_mask, unsigned long long gvsid, | ||
302 | unsigned long long hvsid), | ||
303 | TP_ARGS(sid_map_mask, gvsid, hvsid), | ||
304 | |||
305 | TP_STRUCT__entry( | ||
306 | __field( unsigned short, sid_map_mask ) | ||
307 | __field( unsigned long long, guest_vsid ) | ||
308 | __field( unsigned long long, host_vsid ) | ||
309 | ), | ||
310 | |||
311 | TP_fast_assign( | ||
312 | __entry->sid_map_mask = sid_map_mask; | ||
313 | __entry->guest_vsid = gvsid; | ||
314 | __entry->host_vsid = hvsid; | ||
315 | ), | ||
316 | |||
317 | TP_printk("%x: %llx -> %llx", __entry->sid_map_mask, | ||
318 | __entry->guest_vsid, __entry->host_vsid) | ||
319 | ); | ||
320 | |||
321 | TRACE_EVENT(kvm_book3s_slbmte, | ||
322 | TP_PROTO(u64 slb_vsid, u64 slb_esid), | ||
323 | TP_ARGS(slb_vsid, slb_esid), | ||
324 | |||
325 | TP_STRUCT__entry( | ||
326 | __field( u64, slb_vsid ) | ||
327 | __field( u64, slb_esid ) | ||
328 | ), | ||
329 | |||
330 | TP_fast_assign( | ||
331 | __entry->slb_vsid = slb_vsid; | ||
332 | __entry->slb_esid = slb_esid; | ||
333 | ), | ||
334 | |||
335 | TP_printk("%llx, %llx", __entry->slb_vsid, __entry->slb_esid) | ||
336 | ); | ||
337 | |||
338 | #endif /* CONFIG_PPC_BOOK3S */ | ||
339 | |||
101 | #endif /* _TRACE_KVM_H */ | 340 | #endif /* _TRACE_KVM_H */ |
102 | 341 | ||
103 | /* This part must be outside protection */ | 342 | /* This part must be outside protection */ |
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile index 5bb89c828070..889f2bc106dd 100644 --- a/arch/powerpc/lib/Makefile +++ b/arch/powerpc/lib/Makefile | |||
@@ -4,9 +4,7 @@ | |||
4 | 4 | ||
5 | subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror | 5 | subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror |
6 | 6 | ||
7 | ifeq ($(CONFIG_PPC64),y) | 7 | ccflags-$(CONFIG_PPC64) := -mno-minimal-toc |
8 | EXTRA_CFLAGS += -mno-minimal-toc | ||
9 | endif | ||
10 | 8 | ||
11 | CFLAGS_REMOVE_code-patching.o = -pg | 9 | CFLAGS_REMOVE_code-patching.o = -pg |
12 | CFLAGS_REMOVE_feature-fixups.o = -pg | 10 | CFLAGS_REMOVE_feature-fixups.o = -pg |
@@ -17,7 +15,8 @@ obj-$(CONFIG_PPC32) += div64.o copy_32.o | |||
17 | obj-$(CONFIG_HAS_IOMEM) += devres.o | 15 | obj-$(CONFIG_HAS_IOMEM) += devres.o |
18 | 16 | ||
19 | obj-$(CONFIG_PPC64) += copypage_64.o copyuser_64.o \ | 17 | obj-$(CONFIG_PPC64) += copypage_64.o copyuser_64.o \ |
20 | memcpy_64.o usercopy_64.o mem_64.o string.o | 18 | memcpy_64.o usercopy_64.o mem_64.o string.o \ |
19 | checksum_wrappers_64.o | ||
21 | obj-$(CONFIG_XMON) += sstep.o ldstfp.o | 20 | obj-$(CONFIG_XMON) += sstep.o ldstfp.o |
22 | obj-$(CONFIG_KPROBES) += sstep.o ldstfp.o | 21 | obj-$(CONFIG_KPROBES) += sstep.o ldstfp.o |
23 | obj-$(CONFIG_HAVE_HW_BREAKPOINT) += sstep.o ldstfp.o | 22 | obj-$(CONFIG_HAVE_HW_BREAKPOINT) += sstep.o ldstfp.o |
diff --git a/arch/powerpc/lib/checksum_64.S b/arch/powerpc/lib/checksum_64.S index ef96c6c58efc..18245af38aea 100644 --- a/arch/powerpc/lib/checksum_64.S +++ b/arch/powerpc/lib/checksum_64.S | |||
@@ -65,165 +65,393 @@ _GLOBAL(csum_tcpudp_magic) | |||
65 | srwi r3,r3,16 | 65 | srwi r3,r3,16 |
66 | blr | 66 | blr |
67 | 67 | ||
68 | #define STACKFRAMESIZE 256 | ||
69 | #define STK_REG(i) (112 + ((i)-14)*8) | ||
70 | |||
68 | /* | 71 | /* |
69 | * Computes the checksum of a memory block at buff, length len, | 72 | * Computes the checksum of a memory block at buff, length len, |
70 | * and adds in "sum" (32-bit). | 73 | * and adds in "sum" (32-bit). |
71 | * | 74 | * |
72 | * This code assumes at least halfword alignment, though the length | ||
73 | * can be any number of bytes. The sum is accumulated in r5. | ||
74 | * | ||
75 | * csum_partial(r3=buff, r4=len, r5=sum) | 75 | * csum_partial(r3=buff, r4=len, r5=sum) |
76 | */ | 76 | */ |
77 | _GLOBAL(csum_partial) | 77 | _GLOBAL(csum_partial) |
78 | subi r3,r3,8 /* we'll offset by 8 for the loads */ | 78 | addic r0,r5,0 /* clear carry */ |
79 | srdi. r6,r4,3 /* divide by 8 for doubleword count */ | 79 | |
80 | addic r5,r5,0 /* clear carry */ | 80 | srdi. r6,r4,3 /* less than 8 bytes? */ |
81 | beq 3f /* if we're doing < 8 bytes */ | 81 | beq .Lcsum_tail_word |
82 | andi. r0,r3,2 /* aligned on a word boundary already? */ | 82 | |
83 | beq+ 1f | 83 | /* |
84 | lhz r6,8(r3) /* do 2 bytes to get aligned */ | 84 | * If only halfword aligned, align to a double word. Since odd |
85 | addi r3,r3,2 | 85 | * aligned addresses should be rare and they would require more |
86 | subi r4,r4,2 | 86 | * work to calculate the correct checksum, we ignore that case |
87 | addc r5,r5,r6 | 87 | * and take the potential slowdown of unaligned loads. |
88 | srdi. r6,r4,3 /* recompute number of doublewords */ | 88 | */ |
89 | beq 3f /* any left? */ | 89 | rldicl. r6,r3,64-1,64-2 /* r6 = (r3 & 0x3) >> 1 */ |
90 | 1: mtctr r6 | 90 | beq .Lcsum_aligned |
91 | 2: ldu r6,8(r3) /* main sum loop */ | 91 | |
92 | adde r5,r5,r6 | 92 | li r7,4 |
93 | bdnz 2b | 93 | sub r6,r7,r6 |
94 | andi. r4,r4,7 /* compute bytes left to sum after doublewords */ | 94 | mtctr r6 |
95 | 3: cmpwi 0,r4,4 /* is at least a full word left? */ | 95 | |
96 | blt 4f | 96 | 1: |
97 | lwz r6,8(r3) /* sum this word */ | 97 | lhz r6,0(r3) /* align to doubleword */ |
98 | subi r4,r4,2 | ||
99 | addi r3,r3,2 | ||
100 | adde r0,r0,r6 | ||
101 | bdnz 1b | ||
102 | |||
103 | .Lcsum_aligned: | ||
104 | /* | ||
105 | * We unroll the loop such that each iteration is 64 bytes with an | ||
106 | * entry and exit limb of 64 bytes, meaning a minimum size of | ||
107 | * 128 bytes. | ||
108 | */ | ||
109 | srdi. r6,r4,7 | ||
110 | beq .Lcsum_tail_doublewords /* len < 128 */ | ||
111 | |||
112 | srdi r6,r4,6 | ||
113 | subi r6,r6,1 | ||
114 | mtctr r6 | ||
115 | |||
116 | stdu r1,-STACKFRAMESIZE(r1) | ||
117 | std r14,STK_REG(r14)(r1) | ||
118 | std r15,STK_REG(r15)(r1) | ||
119 | std r16,STK_REG(r16)(r1) | ||
120 | |||
121 | ld r6,0(r3) | ||
122 | ld r9,8(r3) | ||
123 | |||
124 | ld r10,16(r3) | ||
125 | ld r11,24(r3) | ||
126 | |||
127 | /* | ||
128 | * On POWER6 and POWER7 back to back addes take 2 cycles because of | ||
129 | * the XER dependency. This means the fastest this loop can go is | ||
130 | * 16 cycles per iteration. The scheduling of the loop below has | ||
131 | * been shown to hit this on both POWER6 and POWER7. | ||
132 | */ | ||
133 | .align 5 | ||
134 | 2: | ||
135 | adde r0,r0,r6 | ||
136 | ld r12,32(r3) | ||
137 | ld r14,40(r3) | ||
138 | |||
139 | adde r0,r0,r9 | ||
140 | ld r15,48(r3) | ||
141 | ld r16,56(r3) | ||
142 | addi r3,r3,64 | ||
143 | |||
144 | adde r0,r0,r10 | ||
145 | |||
146 | adde r0,r0,r11 | ||
147 | |||
148 | adde r0,r0,r12 | ||
149 | |||
150 | adde r0,r0,r14 | ||
151 | |||
152 | adde r0,r0,r15 | ||
153 | ld r6,0(r3) | ||
154 | ld r9,8(r3) | ||
155 | |||
156 | adde r0,r0,r16 | ||
157 | ld r10,16(r3) | ||
158 | ld r11,24(r3) | ||
159 | bdnz 2b | ||
160 | |||
161 | |||
162 | adde r0,r0,r6 | ||
163 | ld r12,32(r3) | ||
164 | ld r14,40(r3) | ||
165 | |||
166 | adde r0,r0,r9 | ||
167 | ld r15,48(r3) | ||
168 | ld r16,56(r3) | ||
169 | addi r3,r3,64 | ||
170 | |||
171 | adde r0,r0,r10 | ||
172 | adde r0,r0,r11 | ||
173 | adde r0,r0,r12 | ||
174 | adde r0,r0,r14 | ||
175 | adde r0,r0,r15 | ||
176 | adde r0,r0,r16 | ||
177 | |||
178 | ld r14,STK_REG(r14)(r1) | ||
179 | ld r15,STK_REG(r15)(r1) | ||
180 | ld r16,STK_REG(r16)(r1) | ||
181 | addi r1,r1,STACKFRAMESIZE | ||
182 | |||
183 | andi. r4,r4,63 | ||
184 | |||
185 | .Lcsum_tail_doublewords: /* Up to 127 bytes to go */ | ||
186 | srdi. r6,r4,3 | ||
187 | beq .Lcsum_tail_word | ||
188 | |||
189 | mtctr r6 | ||
190 | 3: | ||
191 | ld r6,0(r3) | ||
192 | addi r3,r3,8 | ||
193 | adde r0,r0,r6 | ||
194 | bdnz 3b | ||
195 | |||
196 | andi. r4,r4,7 | ||
197 | |||
198 | .Lcsum_tail_word: /* Up to 7 bytes to go */ | ||
199 | srdi. r6,r4,2 | ||
200 | beq .Lcsum_tail_halfword | ||
201 | |||
202 | lwz r6,0(r3) | ||
98 | addi r3,r3,4 | 203 | addi r3,r3,4 |
204 | adde r0,r0,r6 | ||
99 | subi r4,r4,4 | 205 | subi r4,r4,4 |
100 | adde r5,r5,r6 | 206 | |
101 | 4: cmpwi 0,r4,2 /* is at least a halfword left? */ | 207 | .Lcsum_tail_halfword: /* Up to 3 bytes to go */ |
102 | blt+ 5f | 208 | srdi. r6,r4,1 |
103 | lhz r6,8(r3) /* sum this halfword */ | 209 | beq .Lcsum_tail_byte |
104 | addi r3,r3,2 | 210 | |
105 | subi r4,r4,2 | 211 | lhz r6,0(r3) |
106 | adde r5,r5,r6 | 212 | addi r3,r3,2 |
107 | 5: cmpwi 0,r4,1 /* is at least a byte left? */ | 213 | adde r0,r0,r6 |
108 | bne+ 6f | 214 | subi r4,r4,2 |
109 | lbz r6,8(r3) /* sum this byte */ | 215 | |
110 | slwi r6,r6,8 /* this byte is assumed to be the upper byte of a halfword */ | 216 | .Lcsum_tail_byte: /* Up to 1 byte to go */ |
111 | adde r5,r5,r6 | 217 | andi. r6,r4,1 |
112 | 6: addze r5,r5 /* add in final carry */ | 218 | beq .Lcsum_finish |
113 | rldicl r4,r5,32,0 /* fold two 32-bit halves together */ | 219 | |
114 | add r3,r4,r5 | 220 | lbz r6,0(r3) |
115 | srdi r3,r3,32 | 221 | sldi r9,r6,8 /* Pad the byte out to 16 bits */ |
116 | blr | 222 | adde r0,r0,r9 |
223 | |||
224 | .Lcsum_finish: | ||
225 | addze r0,r0 /* add in final carry */ | ||
226 | rldicl r4,r0,32,0 /* fold two 32 bit halves together */ | ||
227 | add r3,r4,r0 | ||
228 | srdi r3,r3,32 | ||
229 | blr | ||
230 | |||
231 | |||
232 | .macro source | ||
233 | 100: | ||
234 | .section __ex_table,"a" | ||
235 | .align 3 | ||
236 | .llong 100b,.Lsrc_error | ||
237 | .previous | ||
238 | .endm | ||
239 | |||
240 | .macro dest | ||
241 | 200: | ||
242 | .section __ex_table,"a" | ||
243 | .align 3 | ||
244 | .llong 200b,.Ldest_error | ||
245 | .previous | ||
246 | .endm | ||
117 | 247 | ||
118 | /* | 248 | /* |
119 | * Computes the checksum of a memory block at src, length len, | 249 | * Computes the checksum of a memory block at src, length len, |
120 | * and adds in "sum" (32-bit), while copying the block to dst. | 250 | * and adds in "sum" (32-bit), while copying the block to dst. |
121 | * If an access exception occurs on src or dst, it stores -EFAULT | 251 | * If an access exception occurs on src or dst, it stores -EFAULT |
122 | * to *src_err or *dst_err respectively, and (for an error on | 252 | * to *src_err or *dst_err respectively. The caller must take any action |
123 | * src) zeroes the rest of dst. | 253 | * required in this case (zeroing memory, recalculating partial checksum etc). |
124 | * | ||
125 | * This code needs to be reworked to take advantage of 64 bit sum+copy. | ||
126 | * However, due to tokenring halfword alignment problems this will be very | ||
127 | * tricky. For now we'll leave it until we instrument it somehow. | ||
128 | * | 254 | * |
129 | * csum_partial_copy_generic(r3=src, r4=dst, r5=len, r6=sum, r7=src_err, r8=dst_err) | 255 | * csum_partial_copy_generic(r3=src, r4=dst, r5=len, r6=sum, r7=src_err, r8=dst_err) |
130 | */ | 256 | */ |
131 | _GLOBAL(csum_partial_copy_generic) | 257 | _GLOBAL(csum_partial_copy_generic) |
132 | addic r0,r6,0 | 258 | addic r0,r6,0 /* clear carry */ |
133 | subi r3,r3,4 | 259 | |
134 | subi r4,r4,4 | 260 | srdi. r6,r5,3 /* less than 8 bytes? */ |
135 | srwi. r6,r5,2 | 261 | beq .Lcopy_tail_word |
136 | beq 3f /* if we're doing < 4 bytes */ | 262 | |
137 | andi. r9,r4,2 /* Align dst to longword boundary */ | 263 | /* |
138 | beq+ 1f | 264 | * If only halfword aligned, align to a double word. Since odd |
139 | 81: lhz r6,4(r3) /* do 2 bytes to get aligned */ | 265 | * aligned addresses should be rare and they would require more |
140 | addi r3,r3,2 | 266 | * work to calculate the correct checksum, we ignore that case |
267 | * and take the potential slowdown of unaligned loads. | ||
268 | * | ||
269 | * If the source and destination are relatively unaligned we only | ||
270 | * align the source. This keeps things simple. | ||
271 | */ | ||
272 | rldicl. r6,r3,64-1,64-2 /* r6 = (r3 & 0x3) >> 1 */ | ||
273 | beq .Lcopy_aligned | ||
274 | |||
275 | li r7,4 | ||
276 | sub r6,r7,r6 | ||
277 | mtctr r6 | ||
278 | |||
279 | 1: | ||
280 | source; lhz r6,0(r3) /* align to doubleword */ | ||
141 | subi r5,r5,2 | 281 | subi r5,r5,2 |
142 | 91: sth r6,4(r4) | ||
143 | addi r4,r4,2 | ||
144 | addc r0,r0,r6 | ||
145 | srwi. r6,r5,2 /* # words to do */ | ||
146 | beq 3f | ||
147 | 1: mtctr r6 | ||
148 | 82: lwzu r6,4(r3) /* the bdnz has zero overhead, so it should */ | ||
149 | 92: stwu r6,4(r4) /* be unnecessary to unroll this loop */ | ||
150 | adde r0,r0,r6 | ||
151 | bdnz 82b | ||
152 | andi. r5,r5,3 | ||
153 | 3: cmpwi 0,r5,2 | ||
154 | blt+ 4f | ||
155 | 83: lhz r6,4(r3) | ||
156 | addi r3,r3,2 | 282 | addi r3,r3,2 |
157 | subi r5,r5,2 | 283 | adde r0,r0,r6 |
158 | 93: sth r6,4(r4) | 284 | dest; sth r6,0(r4) |
159 | addi r4,r4,2 | 285 | addi r4,r4,2 |
286 | bdnz 1b | ||
287 | |||
288 | .Lcopy_aligned: | ||
289 | /* | ||
290 | * We unroll the loop such that each iteration is 64 bytes with an | ||
291 | * entry and exit limb of 64 bytes, meaning a minimum size of | ||
292 | * 128 bytes. | ||
293 | */ | ||
294 | srdi. r6,r5,7 | ||
295 | beq .Lcopy_tail_doublewords /* len < 128 */ | ||
296 | |||
297 | srdi r6,r5,6 | ||
298 | subi r6,r6,1 | ||
299 | mtctr r6 | ||
300 | |||
301 | stdu r1,-STACKFRAMESIZE(r1) | ||
302 | std r14,STK_REG(r14)(r1) | ||
303 | std r15,STK_REG(r15)(r1) | ||
304 | std r16,STK_REG(r16)(r1) | ||
305 | |||
306 | source; ld r6,0(r3) | ||
307 | source; ld r9,8(r3) | ||
308 | |||
309 | source; ld r10,16(r3) | ||
310 | source; ld r11,24(r3) | ||
311 | |||
312 | /* | ||
313 | * On POWER6 and POWER7 back to back addes take 2 cycles because of | ||
314 | * the XER dependency. This means the fastest this loop can go is | ||
315 | * 16 cycles per iteration. The scheduling of the loop below has | ||
316 | * been shown to hit this on both POWER6 and POWER7. | ||
317 | */ | ||
318 | .align 5 | ||
319 | 2: | ||
160 | adde r0,r0,r6 | 320 | adde r0,r0,r6 |
161 | 4: cmpwi 0,r5,1 | 321 | source; ld r12,32(r3) |
162 | bne+ 5f | 322 | source; ld r14,40(r3) |
163 | 84: lbz r6,4(r3) | 323 | |
164 | 94: stb r6,4(r4) | 324 | adde r0,r0,r9 |
165 | slwi r6,r6,8 /* Upper byte of word */ | 325 | source; ld r15,48(r3) |
326 | source; ld r16,56(r3) | ||
327 | addi r3,r3,64 | ||
328 | |||
329 | adde r0,r0,r10 | ||
330 | dest; std r6,0(r4) | ||
331 | dest; std r9,8(r4) | ||
332 | |||
333 | adde r0,r0,r11 | ||
334 | dest; std r10,16(r4) | ||
335 | dest; std r11,24(r4) | ||
336 | |||
337 | adde r0,r0,r12 | ||
338 | dest; std r12,32(r4) | ||
339 | dest; std r14,40(r4) | ||
340 | |||
341 | adde r0,r0,r14 | ||
342 | dest; std r15,48(r4) | ||
343 | dest; std r16,56(r4) | ||
344 | addi r4,r4,64 | ||
345 | |||
346 | adde r0,r0,r15 | ||
347 | source; ld r6,0(r3) | ||
348 | source; ld r9,8(r3) | ||
349 | |||
350 | adde r0,r0,r16 | ||
351 | source; ld r10,16(r3) | ||
352 | source; ld r11,24(r3) | ||
353 | bdnz 2b | ||
354 | |||
355 | |||
166 | adde r0,r0,r6 | 356 | adde r0,r0,r6 |
167 | 5: addze r3,r0 /* add in final carry (unlikely with 64-bit regs) */ | 357 | source; ld r12,32(r3) |
168 | rldicl r4,r3,32,0 /* fold 64 bit value */ | 358 | source; ld r14,40(r3) |
169 | add r3,r4,r3 | ||
170 | srdi r3,r3,32 | ||
171 | blr | ||
172 | 359 | ||
173 | /* These shouldn't go in the fixup section, since that would | 360 | adde r0,r0,r9 |
174 | cause the ex_table addresses to get out of order. */ | 361 | source; ld r15,48(r3) |
362 | source; ld r16,56(r3) | ||
363 | addi r3,r3,64 | ||
364 | |||
365 | adde r0,r0,r10 | ||
366 | dest; std r6,0(r4) | ||
367 | dest; std r9,8(r4) | ||
368 | |||
369 | adde r0,r0,r11 | ||
370 | dest; std r10,16(r4) | ||
371 | dest; std r11,24(r4) | ||
372 | |||
373 | adde r0,r0,r12 | ||
374 | dest; std r12,32(r4) | ||
375 | dest; std r14,40(r4) | ||
376 | |||
377 | adde r0,r0,r14 | ||
378 | dest; std r15,48(r4) | ||
379 | dest; std r16,56(r4) | ||
380 | addi r4,r4,64 | ||
381 | |||
382 | adde r0,r0,r15 | ||
383 | adde r0,r0,r16 | ||
384 | |||
385 | ld r14,STK_REG(r14)(r1) | ||
386 | ld r15,STK_REG(r15)(r1) | ||
387 | ld r16,STK_REG(r16)(r1) | ||
388 | addi r1,r1,STACKFRAMESIZE | ||
389 | |||
390 | andi. r5,r5,63 | ||
391 | |||
392 | .Lcopy_tail_doublewords: /* Up to 127 bytes to go */ | ||
393 | srdi. r6,r5,3 | ||
394 | beq .Lcopy_tail_word | ||
175 | 395 | ||
176 | .globl src_error_1 | ||
177 | src_error_1: | ||
178 | li r6,0 | ||
179 | subi r5,r5,2 | ||
180 | 95: sth r6,4(r4) | ||
181 | addi r4,r4,2 | ||
182 | srwi. r6,r5,2 | ||
183 | beq 3f | ||
184 | mtctr r6 | 396 | mtctr r6 |
185 | .globl src_error_2 | 397 | 3: |
186 | src_error_2: | 398 | source; ld r6,0(r3) |
187 | li r6,0 | 399 | addi r3,r3,8 |
188 | 96: stwu r6,4(r4) | 400 | adde r0,r0,r6 |
189 | bdnz 96b | 401 | dest; std r6,0(r4) |
190 | 3: andi. r5,r5,3 | 402 | addi r4,r4,8 |
191 | beq src_error | 403 | bdnz 3b |
192 | .globl src_error_3 | 404 | |
193 | src_error_3: | 405 | andi. r5,r5,7 |
194 | li r6,0 | 406 | |
195 | mtctr r5 | 407 | .Lcopy_tail_word: /* Up to 7 bytes to go */ |
196 | addi r4,r4,3 | 408 | srdi. r6,r5,2 |
197 | 97: stbu r6,1(r4) | 409 | beq .Lcopy_tail_halfword |
198 | bdnz 97b | 410 | |
199 | .globl src_error | 411 | source; lwz r6,0(r3) |
200 | src_error: | 412 | addi r3,r3,4 |
413 | adde r0,r0,r6 | ||
414 | dest; stw r6,0(r4) | ||
415 | addi r4,r4,4 | ||
416 | subi r5,r5,4 | ||
417 | |||
418 | .Lcopy_tail_halfword: /* Up to 3 bytes to go */ | ||
419 | srdi. r6,r5,1 | ||
420 | beq .Lcopy_tail_byte | ||
421 | |||
422 | source; lhz r6,0(r3) | ||
423 | addi r3,r3,2 | ||
424 | adde r0,r0,r6 | ||
425 | dest; sth r6,0(r4) | ||
426 | addi r4,r4,2 | ||
427 | subi r5,r5,2 | ||
428 | |||
429 | .Lcopy_tail_byte: /* Up to 1 byte to go */ | ||
430 | andi. r6,r5,1 | ||
431 | beq .Lcopy_finish | ||
432 | |||
433 | source; lbz r6,0(r3) | ||
434 | sldi r9,r6,8 /* Pad the byte out to 16 bits */ | ||
435 | adde r0,r0,r9 | ||
436 | dest; stb r6,0(r4) | ||
437 | |||
438 | .Lcopy_finish: | ||
439 | addze r0,r0 /* add in final carry */ | ||
440 | rldicl r4,r0,32,0 /* fold two 32 bit halves together */ | ||
441 | add r3,r4,r0 | ||
442 | srdi r3,r3,32 | ||
443 | blr | ||
444 | |||
445 | .Lsrc_error: | ||
201 | cmpdi 0,r7,0 | 446 | cmpdi 0,r7,0 |
202 | beq 1f | 447 | beqlr |
203 | li r6,-EFAULT | 448 | li r6,-EFAULT |
204 | stw r6,0(r7) | 449 | stw r6,0(r7) |
205 | 1: addze r3,r0 | ||
206 | blr | 450 | blr |
207 | 451 | ||
208 | .globl dst_error | 452 | .Ldest_error: |
209 | dst_error: | ||
210 | cmpdi 0,r8,0 | 453 | cmpdi 0,r8,0 |
211 | beq 1f | 454 | beqlr |
212 | li r6,-EFAULT | 455 | li r6,-EFAULT |
213 | stw r6,0(r8) | 456 | stw r6,0(r8) |
214 | 1: addze r3,r0 | ||
215 | blr | 457 | blr |
216 | |||
217 | .section __ex_table,"a" | ||
218 | .align 3 | ||
219 | .llong 81b,src_error_1 | ||
220 | .llong 91b,dst_error | ||
221 | .llong 82b,src_error_2 | ||
222 | .llong 92b,dst_error | ||
223 | .llong 83b,src_error_3 | ||
224 | .llong 93b,dst_error | ||
225 | .llong 84b,src_error_3 | ||
226 | .llong 94b,dst_error | ||
227 | .llong 95b,dst_error | ||
228 | .llong 96b,dst_error | ||
229 | .llong 97b,dst_error | ||
diff --git a/arch/powerpc/lib/checksum_wrappers_64.c b/arch/powerpc/lib/checksum_wrappers_64.c new file mode 100644 index 000000000000..769b817fbb32 --- /dev/null +++ b/arch/powerpc/lib/checksum_wrappers_64.c | |||
@@ -0,0 +1,102 @@ | |||
1 | /* | ||
2 | * This program is free software; you can redistribute it and/or modify | ||
3 | * it under the terms of the GNU General Public License as published by | ||
4 | * the Free Software Foundation; either version 2 of the License, or | ||
5 | * (at your option) any later version. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
15 | * | ||
16 | * Copyright (C) IBM Corporation, 2010 | ||
17 | * | ||
18 | * Author: Anton Blanchard <anton@au.ibm.com> | ||
19 | */ | ||
20 | #include <linux/module.h> | ||
21 | #include <linux/compiler.h> | ||
22 | #include <linux/types.h> | ||
23 | #include <asm/checksum.h> | ||
24 | #include <asm/uaccess.h> | ||
25 | |||
26 | __wsum csum_and_copy_from_user(const void __user *src, void *dst, | ||
27 | int len, __wsum sum, int *err_ptr) | ||
28 | { | ||
29 | unsigned int csum; | ||
30 | |||
31 | might_sleep(); | ||
32 | |||
33 | *err_ptr = 0; | ||
34 | |||
35 | if (!len) { | ||
36 | csum = 0; | ||
37 | goto out; | ||
38 | } | ||
39 | |||
40 | if (unlikely((len < 0) || !access_ok(VERIFY_READ, src, len))) { | ||
41 | *err_ptr = -EFAULT; | ||
42 | csum = (__force unsigned int)sum; | ||
43 | goto out; | ||
44 | } | ||
45 | |||
46 | csum = csum_partial_copy_generic((void __force *)src, dst, | ||
47 | len, sum, err_ptr, NULL); | ||
48 | |||
49 | if (unlikely(*err_ptr)) { | ||
50 | int missing = __copy_from_user(dst, src, len); | ||
51 | |||
52 | if (missing) { | ||
53 | memset(dst + len - missing, 0, missing); | ||
54 | *err_ptr = -EFAULT; | ||
55 | } else { | ||
56 | *err_ptr = 0; | ||
57 | } | ||
58 | |||
59 | csum = csum_partial(dst, len, sum); | ||
60 | } | ||
61 | |||
62 | out: | ||
63 | return (__force __wsum)csum; | ||
64 | } | ||
65 | EXPORT_SYMBOL(csum_and_copy_from_user); | ||
66 | |||
67 | __wsum csum_and_copy_to_user(const void *src, void __user *dst, int len, | ||
68 | __wsum sum, int *err_ptr) | ||
69 | { | ||
70 | unsigned int csum; | ||
71 | |||
72 | might_sleep(); | ||
73 | |||
74 | *err_ptr = 0; | ||
75 | |||
76 | if (!len) { | ||
77 | csum = 0; | ||
78 | goto out; | ||
79 | } | ||
80 | |||
81 | if (unlikely((len < 0) || !access_ok(VERIFY_WRITE, dst, len))) { | ||
82 | *err_ptr = -EFAULT; | ||
83 | csum = -1; /* invalid checksum */ | ||
84 | goto out; | ||
85 | } | ||
86 | |||
87 | csum = csum_partial_copy_generic(src, (void __force *)dst, | ||
88 | len, sum, NULL, err_ptr); | ||
89 | |||
90 | if (unlikely(*err_ptr)) { | ||
91 | csum = csum_partial(src, len, sum); | ||
92 | |||
93 | if (copy_to_user(dst, src, len)) { | ||
94 | *err_ptr = -EFAULT; | ||
95 | csum = -1; /* invalid checksum */ | ||
96 | } | ||
97 | } | ||
98 | |||
99 | out: | ||
100 | return (__force __wsum)csum; | ||
101 | } | ||
102 | EXPORT_SYMBOL(csum_and_copy_to_user); | ||
diff --git a/arch/powerpc/lib/copy_32.S b/arch/powerpc/lib/copy_32.S index 74a7f4130b4c..55f19f9fd708 100644 --- a/arch/powerpc/lib/copy_32.S +++ b/arch/powerpc/lib/copy_32.S | |||
@@ -62,7 +62,7 @@ | |||
62 | 62 | ||
63 | .text | 63 | .text |
64 | .stabs "arch/powerpc/lib/",N_SO,0,0,0f | 64 | .stabs "arch/powerpc/lib/",N_SO,0,0,0f |
65 | .stabs "copy32.S",N_SO,0,0,0f | 65 | .stabs "copy_32.S",N_SO,0,0,0f |
66 | 0: | 66 | 0: |
67 | 67 | ||
68 | CACHELINE_BYTES = L1_CACHE_BYTES | 68 | CACHELINE_BYTES = L1_CACHE_BYTES |
diff --git a/arch/powerpc/lib/ldstfp.S b/arch/powerpc/lib/ldstfp.S index f6448636baf5..6a85380520b6 100644 --- a/arch/powerpc/lib/ldstfp.S +++ b/arch/powerpc/lib/ldstfp.S | |||
@@ -17,6 +17,8 @@ | |||
17 | #include <asm/asm-offsets.h> | 17 | #include <asm/asm-offsets.h> |
18 | #include <linux/errno.h> | 18 | #include <linux/errno.h> |
19 | 19 | ||
20 | #ifdef CONFIG_PPC_FPU | ||
21 | |||
20 | #define STKFRM (PPC_MIN_STKFRM + 16) | 22 | #define STKFRM (PPC_MIN_STKFRM + 16) |
21 | 23 | ||
22 | .macro extab instr,handler | 24 | .macro extab instr,handler |
@@ -81,7 +83,7 @@ _GLOBAL(do_lfs) | |||
81 | mfmsr r6 | 83 | mfmsr r6 |
82 | ori r7,r6,MSR_FP | 84 | ori r7,r6,MSR_FP |
83 | cmpwi cr7,r3,0 | 85 | cmpwi cr7,r3,0 |
84 | mtmsrd r7 | 86 | MTMSRD(r7) |
85 | isync | 87 | isync |
86 | beq cr7,1f | 88 | beq cr7,1f |
87 | stfd fr0,STKFRM-16(r1) | 89 | stfd fr0,STKFRM-16(r1) |
@@ -93,7 +95,7 @@ _GLOBAL(do_lfs) | |||
93 | lfd fr0,STKFRM-16(r1) | 95 | lfd fr0,STKFRM-16(r1) |
94 | 4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) | 96 | 4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) |
95 | mtlr r0 | 97 | mtlr r0 |
96 | mtmsrd r6 | 98 | MTMSRD(r6) |
97 | isync | 99 | isync |
98 | mr r3,r9 | 100 | mr r3,r9 |
99 | addi r1,r1,STKFRM | 101 | addi r1,r1,STKFRM |
@@ -108,7 +110,7 @@ _GLOBAL(do_lfd) | |||
108 | mfmsr r6 | 110 | mfmsr r6 |
109 | ori r7,r6,MSR_FP | 111 | ori r7,r6,MSR_FP |
110 | cmpwi cr7,r3,0 | 112 | cmpwi cr7,r3,0 |
111 | mtmsrd r7 | 113 | MTMSRD(r7) |
112 | isync | 114 | isync |
113 | beq cr7,1f | 115 | beq cr7,1f |
114 | stfd fr0,STKFRM-16(r1) | 116 | stfd fr0,STKFRM-16(r1) |
@@ -120,7 +122,7 @@ _GLOBAL(do_lfd) | |||
120 | lfd fr0,STKFRM-16(r1) | 122 | lfd fr0,STKFRM-16(r1) |
121 | 4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) | 123 | 4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) |
122 | mtlr r0 | 124 | mtlr r0 |
123 | mtmsrd r6 | 125 | MTMSRD(r6) |
124 | isync | 126 | isync |
125 | mr r3,r9 | 127 | mr r3,r9 |
126 | addi r1,r1,STKFRM | 128 | addi r1,r1,STKFRM |
@@ -135,7 +137,7 @@ _GLOBAL(do_stfs) | |||
135 | mfmsr r6 | 137 | mfmsr r6 |
136 | ori r7,r6,MSR_FP | 138 | ori r7,r6,MSR_FP |
137 | cmpwi cr7,r3,0 | 139 | cmpwi cr7,r3,0 |
138 | mtmsrd r7 | 140 | MTMSRD(r7) |
139 | isync | 141 | isync |
140 | beq cr7,1f | 142 | beq cr7,1f |
141 | stfd fr0,STKFRM-16(r1) | 143 | stfd fr0,STKFRM-16(r1) |
@@ -147,7 +149,7 @@ _GLOBAL(do_stfs) | |||
147 | lfd fr0,STKFRM-16(r1) | 149 | lfd fr0,STKFRM-16(r1) |
148 | 4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) | 150 | 4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) |
149 | mtlr r0 | 151 | mtlr r0 |
150 | mtmsrd r6 | 152 | MTMSRD(r6) |
151 | isync | 153 | isync |
152 | mr r3,r9 | 154 | mr r3,r9 |
153 | addi r1,r1,STKFRM | 155 | addi r1,r1,STKFRM |
@@ -162,7 +164,7 @@ _GLOBAL(do_stfd) | |||
162 | mfmsr r6 | 164 | mfmsr r6 |
163 | ori r7,r6,MSR_FP | 165 | ori r7,r6,MSR_FP |
164 | cmpwi cr7,r3,0 | 166 | cmpwi cr7,r3,0 |
165 | mtmsrd r7 | 167 | MTMSRD(r7) |
166 | isync | 168 | isync |
167 | beq cr7,1f | 169 | beq cr7,1f |
168 | stfd fr0,STKFRM-16(r1) | 170 | stfd fr0,STKFRM-16(r1) |
@@ -174,7 +176,7 @@ _GLOBAL(do_stfd) | |||
174 | lfd fr0,STKFRM-16(r1) | 176 | lfd fr0,STKFRM-16(r1) |
175 | 4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) | 177 | 4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) |
176 | mtlr r0 | 178 | mtlr r0 |
177 | mtmsrd r6 | 179 | MTMSRD(r6) |
178 | isync | 180 | isync |
179 | mr r3,r9 | 181 | mr r3,r9 |
180 | addi r1,r1,STKFRM | 182 | addi r1,r1,STKFRM |
@@ -229,7 +231,7 @@ _GLOBAL(do_lvx) | |||
229 | oris r7,r6,MSR_VEC@h | 231 | oris r7,r6,MSR_VEC@h |
230 | cmpwi cr7,r3,0 | 232 | cmpwi cr7,r3,0 |
231 | li r8,STKFRM-16 | 233 | li r8,STKFRM-16 |
232 | mtmsrd r7 | 234 | MTMSRD(r7) |
233 | isync | 235 | isync |
234 | beq cr7,1f | 236 | beq cr7,1f |
235 | stvx vr0,r1,r8 | 237 | stvx vr0,r1,r8 |
@@ -241,7 +243,7 @@ _GLOBAL(do_lvx) | |||
241 | lvx vr0,r1,r8 | 243 | lvx vr0,r1,r8 |
242 | 4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) | 244 | 4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) |
243 | mtlr r0 | 245 | mtlr r0 |
244 | mtmsrd r6 | 246 | MTMSRD(r6) |
245 | isync | 247 | isync |
246 | mr r3,r9 | 248 | mr r3,r9 |
247 | addi r1,r1,STKFRM | 249 | addi r1,r1,STKFRM |
@@ -257,7 +259,7 @@ _GLOBAL(do_stvx) | |||
257 | oris r7,r6,MSR_VEC@h | 259 | oris r7,r6,MSR_VEC@h |
258 | cmpwi cr7,r3,0 | 260 | cmpwi cr7,r3,0 |
259 | li r8,STKFRM-16 | 261 | li r8,STKFRM-16 |
260 | mtmsrd r7 | 262 | MTMSRD(r7) |
261 | isync | 263 | isync |
262 | beq cr7,1f | 264 | beq cr7,1f |
263 | stvx vr0,r1,r8 | 265 | stvx vr0,r1,r8 |
@@ -269,7 +271,7 @@ _GLOBAL(do_stvx) | |||
269 | lvx vr0,r1,r8 | 271 | lvx vr0,r1,r8 |
270 | 4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) | 272 | 4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) |
271 | mtlr r0 | 273 | mtlr r0 |
272 | mtmsrd r6 | 274 | MTMSRD(r6) |
273 | isync | 275 | isync |
274 | mr r3,r9 | 276 | mr r3,r9 |
275 | addi r1,r1,STKFRM | 277 | addi r1,r1,STKFRM |
@@ -325,7 +327,7 @@ _GLOBAL(do_lxvd2x) | |||
325 | oris r7,r6,MSR_VSX@h | 327 | oris r7,r6,MSR_VSX@h |
326 | cmpwi cr7,r3,0 | 328 | cmpwi cr7,r3,0 |
327 | li r8,STKFRM-16 | 329 | li r8,STKFRM-16 |
328 | mtmsrd r7 | 330 | MTMSRD(r7) |
329 | isync | 331 | isync |
330 | beq cr7,1f | 332 | beq cr7,1f |
331 | STXVD2X(0,r1,r8) | 333 | STXVD2X(0,r1,r8) |
@@ -337,7 +339,7 @@ _GLOBAL(do_lxvd2x) | |||
337 | LXVD2X(0,r1,r8) | 339 | LXVD2X(0,r1,r8) |
338 | 4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) | 340 | 4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) |
339 | mtlr r0 | 341 | mtlr r0 |
340 | mtmsrd r6 | 342 | MTMSRD(r6) |
341 | isync | 343 | isync |
342 | mr r3,r9 | 344 | mr r3,r9 |
343 | addi r1,r1,STKFRM | 345 | addi r1,r1,STKFRM |
@@ -353,7 +355,7 @@ _GLOBAL(do_stxvd2x) | |||
353 | oris r7,r6,MSR_VSX@h | 355 | oris r7,r6,MSR_VSX@h |
354 | cmpwi cr7,r3,0 | 356 | cmpwi cr7,r3,0 |
355 | li r8,STKFRM-16 | 357 | li r8,STKFRM-16 |
356 | mtmsrd r7 | 358 | MTMSRD(r7) |
357 | isync | 359 | isync |
358 | beq cr7,1f | 360 | beq cr7,1f |
359 | STXVD2X(0,r1,r8) | 361 | STXVD2X(0,r1,r8) |
@@ -365,7 +367,7 @@ _GLOBAL(do_stxvd2x) | |||
365 | LXVD2X(0,r1,r8) | 367 | LXVD2X(0,r1,r8) |
366 | 4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) | 368 | 4: PPC_LL r0,STKFRM+PPC_LR_STKOFF(r1) |
367 | mtlr r0 | 369 | mtlr r0 |
368 | mtmsrd r6 | 370 | MTMSRD(r6) |
369 | isync | 371 | isync |
370 | mr r3,r9 | 372 | mr r3,r9 |
371 | addi r1,r1,STKFRM | 373 | addi r1,r1,STKFRM |
@@ -373,3 +375,5 @@ _GLOBAL(do_stxvd2x) | |||
373 | extab 2b,3b | 375 | extab 2b,3b |
374 | 376 | ||
375 | #endif /* CONFIG_VSX */ | 377 | #endif /* CONFIG_VSX */ |
378 | |||
379 | #endif /* CONFIG_PPC_FPU */ | ||
diff --git a/arch/powerpc/lib/locks.c b/arch/powerpc/lib/locks.c index 58e14fba11b1..9b8182e82166 100644 --- a/arch/powerpc/lib/locks.c +++ b/arch/powerpc/lib/locks.c | |||
@@ -34,7 +34,7 @@ void __spin_yield(arch_spinlock_t *lock) | |||
34 | return; | 34 | return; |
35 | holder_cpu = lock_value & 0xffff; | 35 | holder_cpu = lock_value & 0xffff; |
36 | BUG_ON(holder_cpu >= NR_CPUS); | 36 | BUG_ON(holder_cpu >= NR_CPUS); |
37 | yield_count = lppaca[holder_cpu].yield_count; | 37 | yield_count = lppaca_of(holder_cpu).yield_count; |
38 | if ((yield_count & 1) == 0) | 38 | if ((yield_count & 1) == 0) |
39 | return; /* virtual cpu is currently running */ | 39 | return; /* virtual cpu is currently running */ |
40 | rmb(); | 40 | rmb(); |
@@ -65,7 +65,7 @@ void __rw_yield(arch_rwlock_t *rw) | |||
65 | return; /* no write lock at present */ | 65 | return; /* no write lock at present */ |
66 | holder_cpu = lock_value & 0xffff; | 66 | holder_cpu = lock_value & 0xffff; |
67 | BUG_ON(holder_cpu >= NR_CPUS); | 67 | BUG_ON(holder_cpu >= NR_CPUS); |
68 | yield_count = lppaca[holder_cpu].yield_count; | 68 | yield_count = lppaca_of(holder_cpu).yield_count; |
69 | if ((yield_count & 1) == 0) | 69 | if ((yield_count & 1) == 0) |
70 | return; /* virtual cpu is currently running */ | 70 | return; /* virtual cpu is currently running */ |
71 | rmb(); | 71 | rmb(); |
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c index e0a9858d537e..ae5189ab0049 100644 --- a/arch/powerpc/lib/sstep.c +++ b/arch/powerpc/lib/sstep.c | |||
@@ -30,6 +30,7 @@ extern char system_call_common[]; | |||
30 | #define XER_OV 0x40000000U | 30 | #define XER_OV 0x40000000U |
31 | #define XER_CA 0x20000000U | 31 | #define XER_CA 0x20000000U |
32 | 32 | ||
33 | #ifdef CONFIG_PPC_FPU | ||
33 | /* | 34 | /* |
34 | * Functions in ldstfp.S | 35 | * Functions in ldstfp.S |
35 | */ | 36 | */ |
@@ -41,6 +42,7 @@ extern int do_lvx(int rn, unsigned long ea); | |||
41 | extern int do_stvx(int rn, unsigned long ea); | 42 | extern int do_stvx(int rn, unsigned long ea); |
42 | extern int do_lxvd2x(int rn, unsigned long ea); | 43 | extern int do_lxvd2x(int rn, unsigned long ea); |
43 | extern int do_stxvd2x(int rn, unsigned long ea); | 44 | extern int do_stxvd2x(int rn, unsigned long ea); |
45 | #endif | ||
44 | 46 | ||
45 | /* | 47 | /* |
46 | * Determine whether a conditional branch instruction would branch. | 48 | * Determine whether a conditional branch instruction would branch. |
@@ -290,6 +292,7 @@ static int __kprobes write_mem(unsigned long val, unsigned long ea, int nb, | |||
290 | return write_mem_unaligned(val, ea, nb, regs); | 292 | return write_mem_unaligned(val, ea, nb, regs); |
291 | } | 293 | } |
292 | 294 | ||
295 | #ifdef CONFIG_PPC_FPU | ||
293 | /* | 296 | /* |
294 | * Check the address and alignment, and call func to do the actual | 297 | * Check the address and alignment, and call func to do the actual |
295 | * load or store. | 298 | * load or store. |
@@ -351,6 +354,7 @@ static int __kprobes do_fp_store(int rn, int (*func)(int, unsigned long), | |||
351 | } | 354 | } |
352 | return err; | 355 | return err; |
353 | } | 356 | } |
357 | #endif | ||
354 | 358 | ||
355 | #ifdef CONFIG_ALTIVEC | 359 | #ifdef CONFIG_ALTIVEC |
356 | /* For Altivec/VMX, no need to worry about alignment */ | 360 | /* For Altivec/VMX, no need to worry about alignment */ |
@@ -1393,6 +1397,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) | |||
1393 | regs->gpr[rd] = byterev_4(val); | 1397 | regs->gpr[rd] = byterev_4(val); |
1394 | goto ldst_done; | 1398 | goto ldst_done; |
1395 | 1399 | ||
1400 | #ifdef CONFIG_PPC_CPU | ||
1396 | case 535: /* lfsx */ | 1401 | case 535: /* lfsx */ |
1397 | case 567: /* lfsux */ | 1402 | case 567: /* lfsux */ |
1398 | if (!(regs->msr & MSR_FP)) | 1403 | if (!(regs->msr & MSR_FP)) |
@@ -1424,6 +1429,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) | |||
1424 | ea = xform_ea(instr, regs, u); | 1429 | ea = xform_ea(instr, regs, u); |
1425 | err = do_fp_store(rd, do_stfd, ea, 8, regs); | 1430 | err = do_fp_store(rd, do_stfd, ea, 8, regs); |
1426 | goto ldst_done; | 1431 | goto ldst_done; |
1432 | #endif | ||
1427 | 1433 | ||
1428 | #ifdef __powerpc64__ | 1434 | #ifdef __powerpc64__ |
1429 | case 660: /* stdbrx */ | 1435 | case 660: /* stdbrx */ |
@@ -1534,6 +1540,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) | |||
1534 | } while (++rd < 32); | 1540 | } while (++rd < 32); |
1535 | goto instr_done; | 1541 | goto instr_done; |
1536 | 1542 | ||
1543 | #ifdef CONFIG_PPC_FPU | ||
1537 | case 48: /* lfs */ | 1544 | case 48: /* lfs */ |
1538 | case 49: /* lfsu */ | 1545 | case 49: /* lfsu */ |
1539 | if (!(regs->msr & MSR_FP)) | 1546 | if (!(regs->msr & MSR_FP)) |
@@ -1565,6 +1572,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) | |||
1565 | ea = dform_ea(instr, regs); | 1572 | ea = dform_ea(instr, regs); |
1566 | err = do_fp_store(rd, do_stfd, ea, 8, regs); | 1573 | err = do_fp_store(rd, do_stfd, ea, 8, regs); |
1567 | goto ldst_done; | 1574 | goto ldst_done; |
1575 | #endif | ||
1568 | 1576 | ||
1569 | #ifdef __powerpc64__ | 1577 | #ifdef __powerpc64__ |
1570 | case 58: /* ld[u], lwa */ | 1578 | case 58: /* ld[u], lwa */ |
diff --git a/arch/powerpc/math-emu/Makefile b/arch/powerpc/math-emu/Makefile index 0c16ab947f1f..7d1dba0d57f9 100644 --- a/arch/powerpc/math-emu/Makefile +++ b/arch/powerpc/math-emu/Makefile | |||
@@ -15,4 +15,4 @@ obj-$(CONFIG_SPE) += math_efp.o | |||
15 | CFLAGS_fabs.o = -fno-builtin-fabs | 15 | CFLAGS_fabs.o = -fno-builtin-fabs |
16 | CFLAGS_math.o = -fno-builtin-fabs | 16 | CFLAGS_math.o = -fno-builtin-fabs |
17 | 17 | ||
18 | EXTRA_CFLAGS = -I. -Iinclude/math-emu -w | 18 | ccflags-y = -I. -Iinclude/math-emu -w |
diff --git a/arch/powerpc/mm/40x_mmu.c b/arch/powerpc/mm/40x_mmu.c index 1dc2fa5ce1bd..5810967511d4 100644 --- a/arch/powerpc/mm/40x_mmu.c +++ b/arch/powerpc/mm/40x_mmu.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/init.h> | 35 | #include <linux/init.h> |
36 | #include <linux/delay.h> | 36 | #include <linux/delay.h> |
37 | #include <linux/highmem.h> | 37 | #include <linux/highmem.h> |
38 | #include <linux/memblock.h> | ||
38 | 39 | ||
39 | #include <asm/pgalloc.h> | 40 | #include <asm/pgalloc.h> |
40 | #include <asm/prom.h> | 41 | #include <asm/prom.h> |
@@ -47,6 +48,7 @@ | |||
47 | #include <asm/bootx.h> | 48 | #include <asm/bootx.h> |
48 | #include <asm/machdep.h> | 49 | #include <asm/machdep.h> |
49 | #include <asm/setup.h> | 50 | #include <asm/setup.h> |
51 | |||
50 | #include "mmu_decl.h" | 52 | #include "mmu_decl.h" |
51 | 53 | ||
52 | extern int __map_without_ltlbs; | 54 | extern int __map_without_ltlbs; |
@@ -139,8 +141,19 @@ unsigned long __init mmu_mapin_ram(unsigned long top) | |||
139 | * coverage with normal-sized pages (or other reasons) do not | 141 | * coverage with normal-sized pages (or other reasons) do not |
140 | * attempt to allocate outside the allowed range. | 142 | * attempt to allocate outside the allowed range. |
141 | */ | 143 | */ |
142 | 144 | memblock_set_current_limit(mapped); | |
143 | __initial_memory_limit_addr = memstart_addr + mapped; | ||
144 | 145 | ||
145 | return mapped; | 146 | return mapped; |
146 | } | 147 | } |
148 | |||
149 | void setup_initial_memory_limit(phys_addr_t first_memblock_base, | ||
150 | phys_addr_t first_memblock_size) | ||
151 | { | ||
152 | /* We don't currently support the first MEMBLOCK not mapping 0 | ||
153 | * physical on those processors | ||
154 | */ | ||
155 | BUG_ON(first_memblock_base != 0); | ||
156 | |||
157 | /* 40x can only access 16MB at the moment (see head_40x.S) */ | ||
158 | memblock_set_current_limit(min_t(u64, first_memblock_size, 0x00800000)); | ||
159 | } | ||
diff --git a/arch/powerpc/mm/44x_mmu.c b/arch/powerpc/mm/44x_mmu.c index d8c6efb32bc6..024acab588fd 100644 --- a/arch/powerpc/mm/44x_mmu.c +++ b/arch/powerpc/mm/44x_mmu.c | |||
@@ -24,6 +24,8 @@ | |||
24 | */ | 24 | */ |
25 | 25 | ||
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/memblock.h> | ||
28 | |||
27 | #include <asm/mmu.h> | 29 | #include <asm/mmu.h> |
28 | #include <asm/system.h> | 30 | #include <asm/system.h> |
29 | #include <asm/page.h> | 31 | #include <asm/page.h> |
@@ -213,6 +215,18 @@ unsigned long __init mmu_mapin_ram(unsigned long top) | |||
213 | return total_lowmem; | 215 | return total_lowmem; |
214 | } | 216 | } |
215 | 217 | ||
218 | void setup_initial_memory_limit(phys_addr_t first_memblock_base, | ||
219 | phys_addr_t first_memblock_size) | ||
220 | { | ||
221 | /* We don't currently support the first MEMBLOCK not mapping 0 | ||
222 | * physical on those processors | ||
223 | */ | ||
224 | BUG_ON(first_memblock_base != 0); | ||
225 | |||
226 | /* 44x has a 256M TLB entry pinned at boot */ | ||
227 | memblock_set_current_limit(min_t(u64, first_memblock_size, PPC_PIN_SIZE)); | ||
228 | } | ||
229 | |||
216 | #ifdef CONFIG_SMP | 230 | #ifdef CONFIG_SMP |
217 | void __cpuinit mmu_init_secondary(int cpu) | 231 | void __cpuinit mmu_init_secondary(int cpu) |
218 | { | 232 | { |
diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile index ce68708bbad5..bdca46e08382 100644 --- a/arch/powerpc/mm/Makefile +++ b/arch/powerpc/mm/Makefile | |||
@@ -4,9 +4,7 @@ | |||
4 | 4 | ||
5 | subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror | 5 | subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror |
6 | 6 | ||
7 | ifeq ($(CONFIG_PPC64),y) | 7 | ccflags-$(CONFIG_PPC64) := -mno-minimal-toc |
8 | EXTRA_CFLAGS += -mno-minimal-toc | ||
9 | endif | ||
10 | 8 | ||
11 | obj-y := fault.o mem.o pgtable.o gup.o \ | 9 | obj-y := fault.o mem.o pgtable.o gup.o \ |
12 | init_$(CONFIG_WORD_SIZE).o \ | 10 | init_$(CONFIG_WORD_SIZE).o \ |
@@ -25,7 +23,7 @@ obj-$(CONFIG_PPC_STD_MMU) += hash_low_$(CONFIG_WORD_SIZE).o \ | |||
25 | mmu_context_hash$(CONFIG_WORD_SIZE).o | 23 | mmu_context_hash$(CONFIG_WORD_SIZE).o |
26 | obj-$(CONFIG_40x) += 40x_mmu.o | 24 | obj-$(CONFIG_40x) += 40x_mmu.o |
27 | obj-$(CONFIG_44x) += 44x_mmu.o | 25 | obj-$(CONFIG_44x) += 44x_mmu.o |
28 | obj-$(CONFIG_FSL_BOOKE) += fsl_booke_mmu.o | 26 | obj-$(CONFIG_PPC_FSL_BOOK3E) += fsl_booke_mmu.o |
29 | obj-$(CONFIG_NEED_MULTIPLE_NODES) += numa.o | 27 | obj-$(CONFIG_NEED_MULTIPLE_NODES) += numa.o |
30 | obj-$(CONFIG_PPC_MM_SLICES) += slice.o | 28 | obj-$(CONFIG_PPC_MM_SLICES) += slice.o |
31 | ifeq ($(CONFIG_HUGETLB_PAGE),y) | 29 | ifeq ($(CONFIG_HUGETLB_PAGE),y) |
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index 1bd712c33ce2..54f4fb994e99 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/kprobes.h> | 30 | #include <linux/kprobes.h> |
31 | #include <linux/kdebug.h> | 31 | #include <linux/kdebug.h> |
32 | #include <linux/perf_event.h> | 32 | #include <linux/perf_event.h> |
33 | #include <linux/magic.h> | ||
33 | 34 | ||
34 | #include <asm/firmware.h> | 35 | #include <asm/firmware.h> |
35 | #include <asm/page.h> | 36 | #include <asm/page.h> |
@@ -385,6 +386,7 @@ do_sigbus: | |||
385 | void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig) | 386 | void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig) |
386 | { | 387 | { |
387 | const struct exception_table_entry *entry; | 388 | const struct exception_table_entry *entry; |
389 | unsigned long *stackend; | ||
388 | 390 | ||
389 | /* Are we prepared to handle this fault? */ | 391 | /* Are we prepared to handle this fault? */ |
390 | if ((entry = search_exception_tables(regs->nip)) != NULL) { | 392 | if ((entry = search_exception_tables(regs->nip)) != NULL) { |
@@ -413,5 +415,9 @@ void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig) | |||
413 | printk(KERN_ALERT "Faulting instruction address: 0x%08lx\n", | 415 | printk(KERN_ALERT "Faulting instruction address: 0x%08lx\n", |
414 | regs->nip); | 416 | regs->nip); |
415 | 417 | ||
418 | stackend = end_of_stack(current); | ||
419 | if (current != &init_task && *stackend != STACK_END_MAGIC) | ||
420 | printk(KERN_ALERT "Thread overran stack, or stack corrupted\n"); | ||
421 | |||
416 | die("Kernel access of bad area", regs, sig); | 422 | die("Kernel access of bad area", regs, sig); |
417 | } | 423 | } |
diff --git a/arch/powerpc/mm/fsl_booke_mmu.c b/arch/powerpc/mm/fsl_booke_mmu.c index 4b66a1ece6d8..f7802c8bba0a 100644 --- a/arch/powerpc/mm/fsl_booke_mmu.c +++ b/arch/powerpc/mm/fsl_booke_mmu.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/init.h> | 40 | #include <linux/init.h> |
41 | #include <linux/delay.h> | 41 | #include <linux/delay.h> |
42 | #include <linux/highmem.h> | 42 | #include <linux/highmem.h> |
43 | #include <linux/memblock.h> | ||
43 | 44 | ||
44 | #include <asm/pgalloc.h> | 45 | #include <asm/pgalloc.h> |
45 | #include <asm/prom.h> | 46 | #include <asm/prom.h> |
@@ -56,11 +57,6 @@ | |||
56 | 57 | ||
57 | unsigned int tlbcam_index; | 58 | unsigned int tlbcam_index; |
58 | 59 | ||
59 | |||
60 | #if defined(CONFIG_LOWMEM_CAM_NUM_BOOL) && (CONFIG_LOWMEM_CAM_NUM >= NUM_TLBCAMS) | ||
61 | #error "LOWMEM_CAM_NUM must be less than NUM_TLBCAMS" | ||
62 | #endif | ||
63 | |||
64 | #define NUM_TLBCAMS (64) | 60 | #define NUM_TLBCAMS (64) |
65 | struct tlbcam TLBCAM[NUM_TLBCAMS]; | 61 | struct tlbcam TLBCAM[NUM_TLBCAMS]; |
66 | 62 | ||
@@ -137,7 +133,8 @@ static void settlbcam(int index, unsigned long virt, phys_addr_t phys, | |||
137 | if (mmu_has_feature(MMU_FTR_BIG_PHYS)) | 133 | if (mmu_has_feature(MMU_FTR_BIG_PHYS)) |
138 | TLBCAM[index].MAS7 = (u64)phys >> 32; | 134 | TLBCAM[index].MAS7 = (u64)phys >> 32; |
139 | 135 | ||
140 | if (flags & _PAGE_USER) { | 136 | /* Below is unlikely -- only for large user pages or similar */ |
137 | if (pte_user(flags)) { | ||
141 | TLBCAM[index].MAS3 |= MAS3_UX | MAS3_UR; | 138 | TLBCAM[index].MAS3 |= MAS3_UX | MAS3_UR; |
142 | TLBCAM[index].MAS3 |= ((flags & _PAGE_RW) ? MAS3_UW : 0); | 139 | TLBCAM[index].MAS3 |= ((flags & _PAGE_RW) ? MAS3_UW : 0); |
143 | } | 140 | } |
@@ -184,6 +181,12 @@ unsigned long map_mem_in_cams(unsigned long ram, int max_cam_idx) | |||
184 | return amount_mapped; | 181 | return amount_mapped; |
185 | } | 182 | } |
186 | 183 | ||
184 | #ifdef CONFIG_PPC32 | ||
185 | |||
186 | #if defined(CONFIG_LOWMEM_CAM_NUM_BOOL) && (CONFIG_LOWMEM_CAM_NUM >= NUM_TLBCAMS) | ||
187 | #error "LOWMEM_CAM_NUM must be less than NUM_TLBCAMS" | ||
188 | #endif | ||
189 | |||
187 | unsigned long __init mmu_mapin_ram(unsigned long top) | 190 | unsigned long __init mmu_mapin_ram(unsigned long top) |
188 | { | 191 | { |
189 | return tlbcam_addrs[tlbcam_index - 1].limit - PAGE_OFFSET + 1; | 192 | return tlbcam_addrs[tlbcam_index - 1].limit - PAGE_OFFSET + 1; |
@@ -213,5 +216,15 @@ void __init adjust_total_lowmem(void) | |||
213 | pr_cont("%lu Mb, residual: %dMb\n", tlbcam_sz(tlbcam_index - 1) >> 20, | 216 | pr_cont("%lu Mb, residual: %dMb\n", tlbcam_sz(tlbcam_index - 1) >> 20, |
214 | (unsigned int)((total_lowmem - __max_low_memory) >> 20)); | 217 | (unsigned int)((total_lowmem - __max_low_memory) >> 20)); |
215 | 218 | ||
216 | __initial_memory_limit_addr = memstart_addr + __max_low_memory; | 219 | memblock_set_current_limit(memstart_addr + __max_low_memory); |
217 | } | 220 | } |
221 | |||
222 | void setup_initial_memory_limit(phys_addr_t first_memblock_base, | ||
223 | phys_addr_t first_memblock_size) | ||
224 | { | ||
225 | phys_addr_t limit = first_memblock_base + first_memblock_size; | ||
226 | |||
227 | /* 64M mapped initially according to head_fsl_booke.S */ | ||
228 | memblock_set_current_limit(min_t(u64, limit, 0x04000000)); | ||
229 | } | ||
230 | #endif | ||
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 09dffe6efa46..83f534d862db 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c | |||
@@ -588,7 +588,7 @@ static void __init htab_initialize(void) | |||
588 | unsigned long pteg_count; | 588 | unsigned long pteg_count; |
589 | unsigned long prot; | 589 | unsigned long prot; |
590 | unsigned long base = 0, size = 0, limit; | 590 | unsigned long base = 0, size = 0, limit; |
591 | int i; | 591 | struct memblock_region *reg; |
592 | 592 | ||
593 | DBG(" -> htab_initialize()\n"); | 593 | DBG(" -> htab_initialize()\n"); |
594 | 594 | ||
@@ -625,7 +625,7 @@ static void __init htab_initialize(void) | |||
625 | if (machine_is(cell)) | 625 | if (machine_is(cell)) |
626 | limit = 0x80000000; | 626 | limit = 0x80000000; |
627 | else | 627 | else |
628 | limit = 0; | 628 | limit = MEMBLOCK_ALLOC_ANYWHERE; |
629 | 629 | ||
630 | table = memblock_alloc_base(htab_size_bytes, htab_size_bytes, limit); | 630 | table = memblock_alloc_base(htab_size_bytes, htab_size_bytes, limit); |
631 | 631 | ||
@@ -649,7 +649,7 @@ static void __init htab_initialize(void) | |||
649 | #ifdef CONFIG_DEBUG_PAGEALLOC | 649 | #ifdef CONFIG_DEBUG_PAGEALLOC |
650 | linear_map_hash_count = memblock_end_of_DRAM() >> PAGE_SHIFT; | 650 | linear_map_hash_count = memblock_end_of_DRAM() >> PAGE_SHIFT; |
651 | linear_map_hash_slots = __va(memblock_alloc_base(linear_map_hash_count, | 651 | linear_map_hash_slots = __va(memblock_alloc_base(linear_map_hash_count, |
652 | 1, memblock.rmo_size)); | 652 | 1, ppc64_rma_size)); |
653 | memset(linear_map_hash_slots, 0, linear_map_hash_count); | 653 | memset(linear_map_hash_slots, 0, linear_map_hash_count); |
654 | #endif /* CONFIG_DEBUG_PAGEALLOC */ | 654 | #endif /* CONFIG_DEBUG_PAGEALLOC */ |
655 | 655 | ||
@@ -659,9 +659,9 @@ static void __init htab_initialize(void) | |||
659 | */ | 659 | */ |
660 | 660 | ||
661 | /* create bolted the linear mapping in the hash table */ | 661 | /* create bolted the linear mapping in the hash table */ |
662 | for (i=0; i < memblock.memory.cnt; i++) { | 662 | for_each_memblock(memory, reg) { |
663 | base = (unsigned long)__va(memblock.memory.region[i].base); | 663 | base = (unsigned long)__va(reg->base); |
664 | size = memblock.memory.region[i].size; | 664 | size = reg->size; |
665 | 665 | ||
666 | DBG("creating mapping for region: %lx..%lx (prot: %lx)\n", | 666 | DBG("creating mapping for region: %lx..%lx (prot: %lx)\n", |
667 | base, size, prot); | 667 | base, size, prot); |
@@ -696,7 +696,8 @@ static void __init htab_initialize(void) | |||
696 | #endif /* CONFIG_U3_DART */ | 696 | #endif /* CONFIG_U3_DART */ |
697 | BUG_ON(htab_bolt_mapping(base, base + size, __pa(base), | 697 | BUG_ON(htab_bolt_mapping(base, base + size, __pa(base), |
698 | prot, mmu_linear_psize, mmu_kernel_ssize)); | 698 | prot, mmu_linear_psize, mmu_kernel_ssize)); |
699 | } | 699 | } |
700 | memblock_set_current_limit(MEMBLOCK_ALLOC_ANYWHERE); | ||
700 | 701 | ||
701 | /* | 702 | /* |
702 | * If we have a memory_limit and we've allocated TCEs then we need to | 703 | * If we have a memory_limit and we've allocated TCEs then we need to |
@@ -1247,3 +1248,23 @@ void kernel_map_pages(struct page *page, int numpages, int enable) | |||
1247 | local_irq_restore(flags); | 1248 | local_irq_restore(flags); |
1248 | } | 1249 | } |
1249 | #endif /* CONFIG_DEBUG_PAGEALLOC */ | 1250 | #endif /* CONFIG_DEBUG_PAGEALLOC */ |
1251 | |||
1252 | void setup_initial_memory_limit(phys_addr_t first_memblock_base, | ||
1253 | phys_addr_t first_memblock_size) | ||
1254 | { | ||
1255 | /* We don't currently support the first MEMBLOCK not mapping 0 | ||
1256 | * physical on those processors | ||
1257 | */ | ||
1258 | BUG_ON(first_memblock_base != 0); | ||
1259 | |||
1260 | /* On LPAR systems, the first entry is our RMA region, | ||
1261 | * non-LPAR 64-bit hash MMU systems don't have a limitation | ||
1262 | * on real mode access, but using the first entry works well | ||
1263 | * enough. We also clamp it to 1G to avoid some funky things | ||
1264 | * such as RTAS bugs etc... | ||
1265 | */ | ||
1266 | ppc64_rma_size = min_t(u64, first_memblock_size, 0x40000000); | ||
1267 | |||
1268 | /* Finally limit subsequent allocations */ | ||
1269 | memblock_set_current_limit(ppc64_rma_size); | ||
1270 | } | ||
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c index 6a6975dc2654..742da43b4ab6 100644 --- a/arch/powerpc/mm/init_32.c +++ b/arch/powerpc/mm/init_32.c | |||
@@ -92,12 +92,6 @@ int __allow_ioremap_reserved; | |||
92 | unsigned long __max_low_memory = MAX_LOW_MEM; | 92 | unsigned long __max_low_memory = MAX_LOW_MEM; |
93 | 93 | ||
94 | /* | 94 | /* |
95 | * address of the limit of what is accessible with initial MMU setup - | ||
96 | * 256MB usually, but only 16MB on 601. | ||
97 | */ | ||
98 | phys_addr_t __initial_memory_limit_addr = (phys_addr_t)0x10000000; | ||
99 | |||
100 | /* | ||
101 | * Check for command-line options that affect what MMU_init will do. | 95 | * Check for command-line options that affect what MMU_init will do. |
102 | */ | 96 | */ |
103 | void MMU_setup(void) | 97 | void MMU_setup(void) |
@@ -126,13 +120,6 @@ void __init MMU_init(void) | |||
126 | if (ppc_md.progress) | 120 | if (ppc_md.progress) |
127 | ppc_md.progress("MMU:enter", 0x111); | 121 | ppc_md.progress("MMU:enter", 0x111); |
128 | 122 | ||
129 | /* 601 can only access 16MB at the moment */ | ||
130 | if (PVR_VER(mfspr(SPRN_PVR)) == 1) | ||
131 | __initial_memory_limit_addr = 0x01000000; | ||
132 | /* 8xx can only access 8MB at the moment */ | ||
133 | if (PVR_VER(mfspr(SPRN_PVR)) == 0x50) | ||
134 | __initial_memory_limit_addr = 0x00800000; | ||
135 | |||
136 | /* parse args from command line */ | 123 | /* parse args from command line */ |
137 | MMU_setup(); | 124 | MMU_setup(); |
138 | 125 | ||
@@ -190,20 +177,18 @@ void __init MMU_init(void) | |||
190 | #ifdef CONFIG_BOOTX_TEXT | 177 | #ifdef CONFIG_BOOTX_TEXT |
191 | btext_unmap(); | 178 | btext_unmap(); |
192 | #endif | 179 | #endif |
180 | |||
181 | /* Shortly after that, the entire linear mapping will be available */ | ||
182 | memblock_set_current_limit(lowmem_end_addr); | ||
193 | } | 183 | } |
194 | 184 | ||
195 | /* This is only called until mem_init is done. */ | 185 | /* This is only called until mem_init is done. */ |
196 | void __init *early_get_page(void) | 186 | void __init *early_get_page(void) |
197 | { | 187 | { |
198 | void *p; | 188 | if (init_bootmem_done) |
199 | 189 | return alloc_bootmem_pages(PAGE_SIZE); | |
200 | if (init_bootmem_done) { | 190 | else |
201 | p = alloc_bootmem_pages(PAGE_SIZE); | 191 | return __va(memblock_alloc(PAGE_SIZE, PAGE_SIZE)); |
202 | } else { | ||
203 | p = __va(memblock_alloc_base(PAGE_SIZE, PAGE_SIZE, | ||
204 | __initial_memory_limit_addr)); | ||
205 | } | ||
206 | return p; | ||
207 | } | 192 | } |
208 | 193 | ||
209 | /* Free up now-unused memory */ | 194 | /* Free up now-unused memory */ |
@@ -252,3 +237,17 @@ void free_initrd_mem(unsigned long start, unsigned long end) | |||
252 | } | 237 | } |
253 | #endif | 238 | #endif |
254 | 239 | ||
240 | |||
241 | #ifdef CONFIG_8xx /* No 8xx specific .c file to put that in ... */ | ||
242 | void setup_initial_memory_limit(phys_addr_t first_memblock_base, | ||
243 | phys_addr_t first_memblock_size) | ||
244 | { | ||
245 | /* We don't currently support the first MEMBLOCK not mapping 0 | ||
246 | * physical on those processors | ||
247 | */ | ||
248 | BUG_ON(first_memblock_base != 0); | ||
249 | |||
250 | /* 8xx can only access 8MB at the moment */ | ||
251 | memblock_set_current_limit(min_t(u64, first_memblock_size, 0x00800000)); | ||
252 | } | ||
253 | #endif /* CONFIG_8xx */ | ||
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index ace85fa74b29..6374b2196a17 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c | |||
@@ -330,3 +330,4 @@ int __meminit vmemmap_populate(struct page *start_page, | |||
330 | return 0; | 330 | return 0; |
331 | } | 331 | } |
332 | #endif /* CONFIG_SPARSEMEM_VMEMMAP */ | 332 | #endif /* CONFIG_SPARSEMEM_VMEMMAP */ |
333 | |||
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 1a84a8d00005..a66499650909 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c | |||
@@ -82,18 +82,11 @@ int page_is_ram(unsigned long pfn) | |||
82 | return pfn < max_pfn; | 82 | return pfn < max_pfn; |
83 | #else | 83 | #else |
84 | unsigned long paddr = (pfn << PAGE_SHIFT); | 84 | unsigned long paddr = (pfn << PAGE_SHIFT); |
85 | int i; | 85 | struct memblock_region *reg; |
86 | for (i=0; i < memblock.memory.cnt; i++) { | ||
87 | unsigned long base; | ||
88 | 86 | ||
89 | base = memblock.memory.region[i].base; | 87 | for_each_memblock(memory, reg) |
90 | 88 | if (paddr >= reg->base && paddr < (reg->base + reg->size)) | |
91 | if ((paddr >= base) && | ||
92 | (paddr < (base + memblock.memory.region[i].size))) { | ||
93 | return 1; | 89 | return 1; |
94 | } | ||
95 | } | ||
96 | |||
97 | return 0; | 90 | return 0; |
98 | #endif | 91 | #endif |
99 | } | 92 | } |
@@ -149,23 +142,19 @@ int | |||
149 | walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages, | 142 | walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages, |
150 | void *arg, int (*func)(unsigned long, unsigned long, void *)) | 143 | void *arg, int (*func)(unsigned long, unsigned long, void *)) |
151 | { | 144 | { |
152 | struct memblock_property res; | 145 | struct memblock_region *reg; |
153 | unsigned long pfn, len; | 146 | unsigned long end_pfn = start_pfn + nr_pages; |
154 | u64 end; | 147 | unsigned long tstart, tend; |
155 | int ret = -1; | 148 | int ret = -1; |
156 | 149 | ||
157 | res.base = (u64) start_pfn << PAGE_SHIFT; | 150 | for_each_memblock(memory, reg) { |
158 | res.size = (u64) nr_pages << PAGE_SHIFT; | 151 | tstart = max(start_pfn, memblock_region_memory_base_pfn(reg)); |
159 | 152 | tend = min(end_pfn, memblock_region_memory_end_pfn(reg)); | |
160 | end = res.base + res.size - 1; | 153 | if (tstart >= tend) |
161 | while ((res.base < end) && (memblock_find(&res) >= 0)) { | 154 | continue; |
162 | pfn = (unsigned long)(res.base >> PAGE_SHIFT); | 155 | ret = (*func)(tstart, tend - tstart, arg); |
163 | len = (unsigned long)(res.size >> PAGE_SHIFT); | ||
164 | ret = (*func)(pfn, len, arg); | ||
165 | if (ret) | 156 | if (ret) |
166 | break; | 157 | break; |
167 | res.base += (res.size + 1); | ||
168 | res.size = (end - res.base + 1); | ||
169 | } | 158 | } |
170 | return ret; | 159 | return ret; |
171 | } | 160 | } |
@@ -179,9 +168,9 @@ EXPORT_SYMBOL_GPL(walk_system_ram_range); | |||
179 | #ifndef CONFIG_NEED_MULTIPLE_NODES | 168 | #ifndef CONFIG_NEED_MULTIPLE_NODES |
180 | void __init do_init_bootmem(void) | 169 | void __init do_init_bootmem(void) |
181 | { | 170 | { |
182 | unsigned long i; | ||
183 | unsigned long start, bootmap_pages; | 171 | unsigned long start, bootmap_pages; |
184 | unsigned long total_pages; | 172 | unsigned long total_pages; |
173 | struct memblock_region *reg; | ||
185 | int boot_mapsize; | 174 | int boot_mapsize; |
186 | 175 | ||
187 | max_low_pfn = max_pfn = memblock_end_of_DRAM() >> PAGE_SHIFT; | 176 | max_low_pfn = max_pfn = memblock_end_of_DRAM() >> PAGE_SHIFT; |
@@ -204,10 +193,10 @@ void __init do_init_bootmem(void) | |||
204 | boot_mapsize = init_bootmem_node(NODE_DATA(0), start >> PAGE_SHIFT, min_low_pfn, max_low_pfn); | 193 | boot_mapsize = init_bootmem_node(NODE_DATA(0), start >> PAGE_SHIFT, min_low_pfn, max_low_pfn); |
205 | 194 | ||
206 | /* Add active regions with valid PFNs */ | 195 | /* Add active regions with valid PFNs */ |
207 | for (i = 0; i < memblock.memory.cnt; i++) { | 196 | for_each_memblock(memory, reg) { |
208 | unsigned long start_pfn, end_pfn; | 197 | unsigned long start_pfn, end_pfn; |
209 | start_pfn = memblock.memory.region[i].base >> PAGE_SHIFT; | 198 | start_pfn = memblock_region_memory_base_pfn(reg); |
210 | end_pfn = start_pfn + memblock_size_pages(&memblock.memory, i); | 199 | end_pfn = memblock_region_memory_end_pfn(reg); |
211 | add_active_range(0, start_pfn, end_pfn); | 200 | add_active_range(0, start_pfn, end_pfn); |
212 | } | 201 | } |
213 | 202 | ||
@@ -218,29 +207,21 @@ void __init do_init_bootmem(void) | |||
218 | free_bootmem_with_active_regions(0, lowmem_end_addr >> PAGE_SHIFT); | 207 | free_bootmem_with_active_regions(0, lowmem_end_addr >> PAGE_SHIFT); |
219 | 208 | ||
220 | /* reserve the sections we're already using */ | 209 | /* reserve the sections we're already using */ |
221 | for (i = 0; i < memblock.reserved.cnt; i++) { | 210 | for_each_memblock(reserved, reg) { |
222 | unsigned long addr = memblock.reserved.region[i].base + | 211 | unsigned long top = reg->base + reg->size - 1; |
223 | memblock_size_bytes(&memblock.reserved, i) - 1; | 212 | if (top < lowmem_end_addr) |
224 | if (addr < lowmem_end_addr) | 213 | reserve_bootmem(reg->base, reg->size, BOOTMEM_DEFAULT); |
225 | reserve_bootmem(memblock.reserved.region[i].base, | 214 | else if (reg->base < lowmem_end_addr) { |
226 | memblock_size_bytes(&memblock.reserved, i), | 215 | unsigned long trunc_size = lowmem_end_addr - reg->base; |
227 | BOOTMEM_DEFAULT); | 216 | reserve_bootmem(reg->base, trunc_size, BOOTMEM_DEFAULT); |
228 | else if (memblock.reserved.region[i].base < lowmem_end_addr) { | ||
229 | unsigned long adjusted_size = lowmem_end_addr - | ||
230 | memblock.reserved.region[i].base; | ||
231 | reserve_bootmem(memblock.reserved.region[i].base, | ||
232 | adjusted_size, BOOTMEM_DEFAULT); | ||
233 | } | 217 | } |
234 | } | 218 | } |
235 | #else | 219 | #else |
236 | free_bootmem_with_active_regions(0, max_pfn); | 220 | free_bootmem_with_active_regions(0, max_pfn); |
237 | 221 | ||
238 | /* reserve the sections we're already using */ | 222 | /* reserve the sections we're already using */ |
239 | for (i = 0; i < memblock.reserved.cnt; i++) | 223 | for_each_memblock(reserved, reg) |
240 | reserve_bootmem(memblock.reserved.region[i].base, | 224 | reserve_bootmem(reg->base, reg->size, BOOTMEM_DEFAULT); |
241 | memblock_size_bytes(&memblock.reserved, i), | ||
242 | BOOTMEM_DEFAULT); | ||
243 | |||
244 | #endif | 225 | #endif |
245 | /* XXX need to clip this if using highmem? */ | 226 | /* XXX need to clip this if using highmem? */ |
246 | sparse_memory_present_with_active_regions(0); | 227 | sparse_memory_present_with_active_regions(0); |
@@ -251,22 +232,15 @@ void __init do_init_bootmem(void) | |||
251 | /* mark pages that don't exist as nosave */ | 232 | /* mark pages that don't exist as nosave */ |
252 | static int __init mark_nonram_nosave(void) | 233 | static int __init mark_nonram_nosave(void) |
253 | { | 234 | { |
254 | unsigned long memblock_next_region_start_pfn, | 235 | struct memblock_region *reg, *prev = NULL; |
255 | memblock_region_max_pfn; | 236 | |
256 | int i; | 237 | for_each_memblock(memory, reg) { |
257 | 238 | if (prev && | |
258 | for (i = 0; i < memblock.memory.cnt - 1; i++) { | 239 | memblock_region_memory_end_pfn(prev) < memblock_region_memory_base_pfn(reg)) |
259 | memblock_region_max_pfn = | 240 | register_nosave_region(memblock_region_memory_end_pfn(prev), |
260 | (memblock.memory.region[i].base >> PAGE_SHIFT) + | 241 | memblock_region_memory_base_pfn(reg)); |
261 | (memblock.memory.region[i].size >> PAGE_SHIFT); | 242 | prev = reg; |
262 | memblock_next_region_start_pfn = | ||
263 | memblock.memory.region[i+1].base >> PAGE_SHIFT; | ||
264 | |||
265 | if (memblock_region_max_pfn < memblock_next_region_start_pfn) | ||
266 | register_nosave_region(memblock_region_max_pfn, | ||
267 | memblock_next_region_start_pfn); | ||
268 | } | 243 | } |
269 | |||
270 | return 0; | 244 | return 0; |
271 | } | 245 | } |
272 | 246 | ||
@@ -327,7 +301,7 @@ void __init mem_init(void) | |||
327 | swiotlb_init(1); | 301 | swiotlb_init(1); |
328 | #endif | 302 | #endif |
329 | 303 | ||
330 | num_physpages = memblock.memory.size >> PAGE_SHIFT; | 304 | num_physpages = memblock_phys_mem_size() >> PAGE_SHIFT; |
331 | high_memory = (void *) __va(max_low_pfn * PAGE_SIZE); | 305 | high_memory = (void *) __va(max_low_pfn * PAGE_SIZE); |
332 | 306 | ||
333 | #ifdef CONFIG_NEED_MULTIPLE_NODES | 307 | #ifdef CONFIG_NEED_MULTIPLE_NODES |
diff --git a/arch/powerpc/mm/mmu_context_nohash.c b/arch/powerpc/mm/mmu_context_nohash.c index ddfd7ad4e1d6..5ce99848d91e 100644 --- a/arch/powerpc/mm/mmu_context_nohash.c +++ b/arch/powerpc/mm/mmu_context_nohash.c | |||
@@ -334,7 +334,7 @@ static int __cpuinit mmu_context_cpu_notify(struct notifier_block *self, | |||
334 | /* We don't touch CPU 0 map, it's allocated at aboot and kept | 334 | /* We don't touch CPU 0 map, it's allocated at aboot and kept |
335 | * around forever | 335 | * around forever |
336 | */ | 336 | */ |
337 | if (cpu == 0) | 337 | if (cpu == boot_cpuid) |
338 | return NOTIFY_OK; | 338 | return NOTIFY_OK; |
339 | 339 | ||
340 | switch (action) { | 340 | switch (action) { |
@@ -420,9 +420,11 @@ void __init mmu_context_init(void) | |||
420 | */ | 420 | */ |
421 | context_map = alloc_bootmem(CTX_MAP_SIZE); | 421 | context_map = alloc_bootmem(CTX_MAP_SIZE); |
422 | context_mm = alloc_bootmem(sizeof(void *) * (last_context + 1)); | 422 | context_mm = alloc_bootmem(sizeof(void *) * (last_context + 1)); |
423 | #ifndef CONFIG_SMP | ||
423 | stale_map[0] = alloc_bootmem(CTX_MAP_SIZE); | 424 | stale_map[0] = alloc_bootmem(CTX_MAP_SIZE); |
425 | #else | ||
426 | stale_map[boot_cpuid] = alloc_bootmem(CTX_MAP_SIZE); | ||
424 | 427 | ||
425 | #ifdef CONFIG_SMP | ||
426 | register_cpu_notifier(&mmu_context_cpu_nb); | 428 | register_cpu_notifier(&mmu_context_cpu_nb); |
427 | #endif | 429 | #endif |
428 | 430 | ||
diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h index 63b84a0d3b10..dd0a2589591d 100644 --- a/arch/powerpc/mm/mmu_decl.h +++ b/arch/powerpc/mm/mmu_decl.h | |||
@@ -140,10 +140,13 @@ extern void wii_memory_fixups(void); | |||
140 | extern void MMU_init_hw(void); | 140 | extern void MMU_init_hw(void); |
141 | extern unsigned long mmu_mapin_ram(unsigned long top); | 141 | extern unsigned long mmu_mapin_ram(unsigned long top); |
142 | 142 | ||
143 | #elif defined(CONFIG_FSL_BOOKE) | 143 | #elif defined(CONFIG_PPC_FSL_BOOK3E) |
144 | extern unsigned long map_mem_in_cams(unsigned long ram, int max_cam_idx); | ||
145 | #ifdef CONFIG_PPC32 | ||
144 | extern void MMU_init_hw(void); | 146 | extern void MMU_init_hw(void); |
145 | extern unsigned long mmu_mapin_ram(unsigned long top); | 147 | extern unsigned long mmu_mapin_ram(unsigned long top); |
146 | extern void adjust_total_lowmem(void); | 148 | extern void adjust_total_lowmem(void); |
149 | #endif | ||
147 | extern void loadcam_entry(unsigned int index); | 150 | extern void loadcam_entry(unsigned int index); |
148 | 151 | ||
149 | struct tlbcam { | 152 | struct tlbcam { |
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 002878ccf90b..74505b245374 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c | |||
@@ -802,16 +802,17 @@ static void __init setup_nonnuma(void) | |||
802 | unsigned long top_of_ram = memblock_end_of_DRAM(); | 802 | unsigned long top_of_ram = memblock_end_of_DRAM(); |
803 | unsigned long total_ram = memblock_phys_mem_size(); | 803 | unsigned long total_ram = memblock_phys_mem_size(); |
804 | unsigned long start_pfn, end_pfn; | 804 | unsigned long start_pfn, end_pfn; |
805 | unsigned int i, nid = 0; | 805 | unsigned int nid = 0; |
806 | struct memblock_region *reg; | ||
806 | 807 | ||
807 | printk(KERN_DEBUG "Top of RAM: 0x%lx, Total RAM: 0x%lx\n", | 808 | printk(KERN_DEBUG "Top of RAM: 0x%lx, Total RAM: 0x%lx\n", |
808 | top_of_ram, total_ram); | 809 | top_of_ram, total_ram); |
809 | printk(KERN_DEBUG "Memory hole size: %ldMB\n", | 810 | printk(KERN_DEBUG "Memory hole size: %ldMB\n", |
810 | (top_of_ram - total_ram) >> 20); | 811 | (top_of_ram - total_ram) >> 20); |
811 | 812 | ||
812 | for (i = 0; i < memblock.memory.cnt; ++i) { | 813 | for_each_memblock(memory, reg) { |
813 | start_pfn = memblock.memory.region[i].base >> PAGE_SHIFT; | 814 | start_pfn = memblock_region_memory_base_pfn(reg); |
814 | end_pfn = start_pfn + memblock_size_pages(&memblock.memory, i); | 815 | end_pfn = memblock_region_memory_end_pfn(reg); |
815 | 816 | ||
816 | fake_numa_create_new_node(end_pfn, &nid); | 817 | fake_numa_create_new_node(end_pfn, &nid); |
817 | add_active_range(nid, start_pfn, end_pfn); | 818 | add_active_range(nid, start_pfn, end_pfn); |
@@ -947,11 +948,11 @@ static struct notifier_block __cpuinitdata ppc64_numa_nb = { | |||
947 | static void mark_reserved_regions_for_nid(int nid) | 948 | static void mark_reserved_regions_for_nid(int nid) |
948 | { | 949 | { |
949 | struct pglist_data *node = NODE_DATA(nid); | 950 | struct pglist_data *node = NODE_DATA(nid); |
950 | int i; | 951 | struct memblock_region *reg; |
951 | 952 | ||
952 | for (i = 0; i < memblock.reserved.cnt; i++) { | 953 | for_each_memblock(reserved, reg) { |
953 | unsigned long physbase = memblock.reserved.region[i].base; | 954 | unsigned long physbase = reg->base; |
954 | unsigned long size = memblock.reserved.region[i].size; | 955 | unsigned long size = reg->size; |
955 | unsigned long start_pfn = physbase >> PAGE_SHIFT; | 956 | unsigned long start_pfn = physbase >> PAGE_SHIFT; |
956 | unsigned long end_pfn = PFN_UP(physbase + size); | 957 | unsigned long end_pfn = PFN_UP(physbase + size); |
957 | struct node_active_region node_ar; | 958 | struct node_active_region node_ar; |
diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c index f8a01829d64f..11571e118831 100644 --- a/arch/powerpc/mm/ppc_mmu_32.c +++ b/arch/powerpc/mm/ppc_mmu_32.c | |||
@@ -223,8 +223,7 @@ void __init MMU_init_hw(void) | |||
223 | * Find some memory for the hash table. | 223 | * Find some memory for the hash table. |
224 | */ | 224 | */ |
225 | if ( ppc_md.progress ) ppc_md.progress("hash:find piece", 0x322); | 225 | if ( ppc_md.progress ) ppc_md.progress("hash:find piece", 0x322); |
226 | Hash = __va(memblock_alloc_base(Hash_size, Hash_size, | 226 | Hash = __va(memblock_alloc(Hash_size, Hash_size)); |
227 | __initial_memory_limit_addr)); | ||
228 | cacheable_memzero(Hash, Hash_size); | 227 | cacheable_memzero(Hash, Hash_size); |
229 | _SDR1 = __pa(Hash) | SDR1_LOW_BITS; | 228 | _SDR1 = __pa(Hash) | SDR1_LOW_BITS; |
230 | 229 | ||
@@ -272,3 +271,18 @@ void __init MMU_init_hw(void) | |||
272 | 271 | ||
273 | if ( ppc_md.progress ) ppc_md.progress("hash:done", 0x205); | 272 | if ( ppc_md.progress ) ppc_md.progress("hash:done", 0x205); |
274 | } | 273 | } |
274 | |||
275 | void setup_initial_memory_limit(phys_addr_t first_memblock_base, | ||
276 | phys_addr_t first_memblock_size) | ||
277 | { | ||
278 | /* We don't currently support the first MEMBLOCK not mapping 0 | ||
279 | * physical on those processors | ||
280 | */ | ||
281 | BUG_ON(first_memblock_base != 0); | ||
282 | |||
283 | /* 601 can only access 16MB at the moment */ | ||
284 | if (PVR_VER(mfspr(SPRN_PVR)) == 1) | ||
285 | memblock_set_current_limit(min_t(u64, first_memblock_size, 0x01000000)); | ||
286 | else /* Anything else has 256M mapped */ | ||
287 | memblock_set_current_limit(min_t(u64, first_memblock_size, 0x10000000)); | ||
288 | } | ||
diff --git a/arch/powerpc/mm/tlb_nohash.c b/arch/powerpc/mm/tlb_nohash.c index fe391e942521..36c0c449a899 100644 --- a/arch/powerpc/mm/tlb_nohash.c +++ b/arch/powerpc/mm/tlb_nohash.c | |||
@@ -349,11 +349,47 @@ void tlb_flush_pgtable(struct mmu_gather *tlb, unsigned long address) | |||
349 | 349 | ||
350 | static void setup_page_sizes(void) | 350 | static void setup_page_sizes(void) |
351 | { | 351 | { |
352 | unsigned int tlb0cfg = mfspr(SPRN_TLB0CFG); | 352 | unsigned int tlb0cfg; |
353 | unsigned int tlb0ps = mfspr(SPRN_TLB0PS); | 353 | unsigned int tlb0ps; |
354 | unsigned int eptcfg = mfspr(SPRN_EPTCFG); | 354 | unsigned int eptcfg; |
355 | int i, psize; | 355 | int i, psize; |
356 | 356 | ||
357 | #ifdef CONFIG_PPC_FSL_BOOK3E | ||
358 | unsigned int mmucfg = mfspr(SPRN_MMUCFG); | ||
359 | |||
360 | if (((mmucfg & MMUCFG_MAVN) == MMUCFG_MAVN_V1) && | ||
361 | (mmu_has_feature(MMU_FTR_TYPE_FSL_E))) { | ||
362 | unsigned int tlb1cfg = mfspr(SPRN_TLB1CFG); | ||
363 | unsigned int min_pg, max_pg; | ||
364 | |||
365 | min_pg = (tlb1cfg & TLBnCFG_MINSIZE) >> TLBnCFG_MINSIZE_SHIFT; | ||
366 | max_pg = (tlb1cfg & TLBnCFG_MAXSIZE) >> TLBnCFG_MAXSIZE_SHIFT; | ||
367 | |||
368 | for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) { | ||
369 | struct mmu_psize_def *def; | ||
370 | unsigned int shift; | ||
371 | |||
372 | def = &mmu_psize_defs[psize]; | ||
373 | shift = def->shift; | ||
374 | |||
375 | if (shift == 0) | ||
376 | continue; | ||
377 | |||
378 | /* adjust to be in terms of 4^shift Kb */ | ||
379 | shift = (shift - 10) >> 1; | ||
380 | |||
381 | if ((shift >= min_pg) && (shift <= max_pg)) | ||
382 | def->flags |= MMU_PAGE_SIZE_DIRECT; | ||
383 | } | ||
384 | |||
385 | goto no_indirect; | ||
386 | } | ||
387 | #endif | ||
388 | |||
389 | tlb0cfg = mfspr(SPRN_TLB0CFG); | ||
390 | tlb0ps = mfspr(SPRN_TLB0PS); | ||
391 | eptcfg = mfspr(SPRN_EPTCFG); | ||
392 | |||
357 | /* Look for supported direct sizes */ | 393 | /* Look for supported direct sizes */ |
358 | for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) { | 394 | for (psize = 0; psize < MMU_PAGE_COUNT; ++psize) { |
359 | struct mmu_psize_def *def = &mmu_psize_defs[psize]; | 395 | struct mmu_psize_def *def = &mmu_psize_defs[psize]; |
@@ -505,10 +541,26 @@ static void __early_init_mmu(int boot_cpu) | |||
505 | */ | 541 | */ |
506 | linear_map_top = memblock_end_of_DRAM(); | 542 | linear_map_top = memblock_end_of_DRAM(); |
507 | 543 | ||
544 | #ifdef CONFIG_PPC_FSL_BOOK3E | ||
545 | if (mmu_has_feature(MMU_FTR_TYPE_FSL_E)) { | ||
546 | unsigned int num_cams; | ||
547 | |||
548 | /* use a quarter of the TLBCAM for bolted linear map */ | ||
549 | num_cams = (mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY) / 4; | ||
550 | linear_map_top = map_mem_in_cams(linear_map_top, num_cams); | ||
551 | |||
552 | /* limit memory so we dont have linear faults */ | ||
553 | memblock_enforce_memory_limit(linear_map_top); | ||
554 | memblock_analyze(); | ||
555 | } | ||
556 | #endif | ||
557 | |||
508 | /* A sync won't hurt us after mucking around with | 558 | /* A sync won't hurt us after mucking around with |
509 | * the MMU configuration | 559 | * the MMU configuration |
510 | */ | 560 | */ |
511 | mb(); | 561 | mb(); |
562 | |||
563 | memblock_set_current_limit(linear_map_top); | ||
512 | } | 564 | } |
513 | 565 | ||
514 | void __init early_init_mmu(void) | 566 | void __init early_init_mmu(void) |
@@ -521,4 +573,18 @@ void __cpuinit early_init_mmu_secondary(void) | |||
521 | __early_init_mmu(0); | 573 | __early_init_mmu(0); |
522 | } | 574 | } |
523 | 575 | ||
576 | void setup_initial_memory_limit(phys_addr_t first_memblock_base, | ||
577 | phys_addr_t first_memblock_size) | ||
578 | { | ||
579 | /* On Embedded 64-bit, we adjust the RMA size to match | ||
580 | * the bolted TLB entry. We know for now that only 1G | ||
581 | * entries are supported though that may eventually | ||
582 | * change. We crop it to the size of the first MEMBLOCK to | ||
583 | * avoid going over total available memory just in case... | ||
584 | */ | ||
585 | ppc64_rma_size = min_t(u64, first_memblock_size, 0x40000000); | ||
586 | |||
587 | /* Finally limit subsequent allocations */ | ||
588 | memblock_set_current_limit(ppc64_memblock_base + ppc64_rma_size); | ||
589 | } | ||
524 | #endif /* CONFIG_PPC64 */ | 590 | #endif /* CONFIG_PPC64 */ |
diff --git a/arch/powerpc/mm/tlb_nohash_low.S b/arch/powerpc/mm/tlb_nohash_low.S index b9d9fed8f36e..af405eefe48d 100644 --- a/arch/powerpc/mm/tlb_nohash_low.S +++ b/arch/powerpc/mm/tlb_nohash_low.S | |||
@@ -367,7 +367,7 @@ _GLOBAL(set_context) | |||
367 | #error Unsupported processor type ! | 367 | #error Unsupported processor type ! |
368 | #endif | 368 | #endif |
369 | 369 | ||
370 | #if defined(CONFIG_FSL_BOOKE) | 370 | #if defined(CONFIG_PPC_FSL_BOOK3E) |
371 | /* | 371 | /* |
372 | * extern void loadcam_entry(unsigned int index) | 372 | * extern void loadcam_entry(unsigned int index) |
373 | * | 373 | * |
diff --git a/arch/powerpc/oprofile/Makefile b/arch/powerpc/oprofile/Makefile index e219ca43962d..73456c4cec28 100644 --- a/arch/powerpc/oprofile/Makefile +++ b/arch/powerpc/oprofile/Makefile | |||
@@ -1,8 +1,6 @@ | |||
1 | subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror | 1 | subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror |
2 | 2 | ||
3 | ifeq ($(CONFIG_PPC64),y) | 3 | ccflags-$(CONFIG_PPC64) := -mno-minimal-toc |
4 | EXTRA_CFLAGS += -mno-minimal-toc | ||
5 | endif | ||
6 | 4 | ||
7 | obj-$(CONFIG_OPROFILE) += oprofile.o | 5 | obj-$(CONFIG_OPROFILE) += oprofile.o |
8 | 6 | ||
diff --git a/arch/powerpc/oprofile/backtrace.c b/arch/powerpc/oprofile/backtrace.c index b4278cfd1f80..f75301f2c85f 100644 --- a/arch/powerpc/oprofile/backtrace.c +++ b/arch/powerpc/oprofile/backtrace.c | |||
@@ -105,7 +105,7 @@ void op_powerpc_backtrace(struct pt_regs * const regs, unsigned int depth) | |||
105 | } | 105 | } |
106 | } else { | 106 | } else { |
107 | #ifdef CONFIG_PPC64 | 107 | #ifdef CONFIG_PPC64 |
108 | if (!test_thread_flag(TIF_32BIT)) { | 108 | if (!is_32bit_task()) { |
109 | while (depth--) { | 109 | while (depth--) { |
110 | sp = user_getsp64(sp, first_frame); | 110 | sp = user_getsp64(sp, first_frame); |
111 | if (!sp) | 111 | if (!sp) |
diff --git a/arch/powerpc/oprofile/op_model_fsl_emb.c b/arch/powerpc/oprofile/op_model_fsl_emb.c index 62312abffa28..d4e6507277b5 100644 --- a/arch/powerpc/oprofile/op_model_fsl_emb.c +++ b/arch/powerpc/oprofile/op_model_fsl_emb.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * Freescale Embedded oprofile support, based on ppc64 oprofile support | 2 | * Freescale Embedded oprofile support, based on ppc64 oprofile support |
3 | * Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM | 3 | * Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM |
4 | * | 4 | * |
5 | * Copyright (c) 2004 Freescale Semiconductor, Inc | 5 | * Copyright (c) 2004, 2010 Freescale Semiconductor, Inc |
6 | * | 6 | * |
7 | * Author: Andy Fleming | 7 | * Author: Andy Fleming |
8 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> | 8 | * Maintainer: Kumar Gala <galak@kernel.crashing.org> |
@@ -321,9 +321,6 @@ static void fsl_emb_handle_interrupt(struct pt_regs *regs, | |||
321 | int val; | 321 | int val; |
322 | int i; | 322 | int i; |
323 | 323 | ||
324 | /* set the PMM bit (see comment below) */ | ||
325 | mtmsr(mfmsr() | MSR_PMM); | ||
326 | |||
327 | pc = regs->nip; | 324 | pc = regs->nip; |
328 | is_kernel = is_kernel_addr(pc); | 325 | is_kernel = is_kernel_addr(pc); |
329 | 326 | ||
@@ -340,9 +337,13 @@ static void fsl_emb_handle_interrupt(struct pt_regs *regs, | |||
340 | } | 337 | } |
341 | 338 | ||
342 | /* The freeze bit was set by the interrupt. */ | 339 | /* The freeze bit was set by the interrupt. */ |
343 | /* Clear the freeze bit, and reenable the interrupt. | 340 | /* Clear the freeze bit, and reenable the interrupt. The |
344 | * The counters won't actually start until the rfi clears | 341 | * counters won't actually start until the rfi clears the PMM |
345 | * the PMM bit */ | 342 | * bit. The PMM bit should not be set until after the interrupt |
343 | * is cleared to avoid it getting lost in some hypervisor | ||
344 | * environments. | ||
345 | */ | ||
346 | mtmsr(mfmsr() | MSR_PMM); | ||
346 | pmc_start_ctrs(1); | 347 | pmc_start_ctrs(1); |
347 | } | 348 | } |
348 | 349 | ||
diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig index 69d668c072ae..0f979c5c756b 100644 --- a/arch/powerpc/platforms/44x/Kconfig +++ b/arch/powerpc/platforms/44x/Kconfig | |||
@@ -17,6 +17,16 @@ config BAMBOO | |||
17 | help | 17 | help |
18 | This option enables support for the IBM PPC440EP evaluation board. | 18 | This option enables support for the IBM PPC440EP evaluation board. |
19 | 19 | ||
20 | config BLUESTONE | ||
21 | bool "Bluestone" | ||
22 | depends on 44x | ||
23 | default n | ||
24 | select PPC44x_SIMPLE | ||
25 | select APM821xx | ||
26 | select IBM_NEW_EMAC_RGMII | ||
27 | help | ||
28 | This option enables support for the APM APM821xx Evaluation board. | ||
29 | |||
20 | config EBONY | 30 | config EBONY |
21 | bool "Ebony" | 31 | bool "Ebony" |
22 | depends on 44x | 32 | depends on 44x |
@@ -293,6 +303,12 @@ config 460SX | |||
293 | select IBM_NEW_EMAC_ZMII | 303 | select IBM_NEW_EMAC_ZMII |
294 | select IBM_NEW_EMAC_TAH | 304 | select IBM_NEW_EMAC_TAH |
295 | 305 | ||
306 | config APM821xx | ||
307 | bool | ||
308 | select PPC_FPU | ||
309 | select IBM_NEW_EMAC_EMAC4 | ||
310 | select IBM_NEW_EMAC_TAH | ||
311 | |||
296 | # 44x errata/workaround config symbols, selected by the CPU models above | 312 | # 44x errata/workaround config symbols, selected by the CPU models above |
297 | config IBM440EP_ERR42 | 313 | config IBM440EP_ERR42 |
298 | bool | 314 | bool |
diff --git a/arch/powerpc/platforms/44x/ppc44x_simple.c b/arch/powerpc/platforms/44x/ppc44x_simple.c index 5f7a29d7f590..7ddcba3b9397 100644 --- a/arch/powerpc/platforms/44x/ppc44x_simple.c +++ b/arch/powerpc/platforms/44x/ppc44x_simple.c | |||
@@ -52,6 +52,7 @@ machine_device_initcall(ppc44x_simple, ppc44x_device_probe); | |||
52 | static char *board[] __initdata = { | 52 | static char *board[] __initdata = { |
53 | "amcc,arches", | 53 | "amcc,arches", |
54 | "amcc,bamboo", | 54 | "amcc,bamboo", |
55 | "amcc,bluestone", | ||
55 | "amcc,canyonlands", | 56 | "amcc,canyonlands", |
56 | "amcc,glacier", | 57 | "amcc,glacier", |
57 | "ibm,ebony", | 58 | "ibm,ebony", |
diff --git a/arch/powerpc/platforms/512x/clock.c b/arch/powerpc/platforms/512x/clock.c index 5b243bd3eb3b..3dc2a8d262b8 100644 --- a/arch/powerpc/platforms/512x/clock.c +++ b/arch/powerpc/platforms/512x/clock.c | |||
@@ -57,7 +57,7 @@ static struct clk *mpc5121_clk_get(struct device *dev, const char *id) | |||
57 | int id_match = 0; | 57 | int id_match = 0; |
58 | 58 | ||
59 | if (dev == NULL || id == NULL) | 59 | if (dev == NULL || id == NULL) |
60 | return NULL; | 60 | return clk; |
61 | 61 | ||
62 | mutex_lock(&clocks_mutex); | 62 | mutex_lock(&clocks_mutex); |
63 | list_for_each_entry(p, &clocks, node) { | 63 | list_for_each_entry(p, &clocks, node) { |
diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c index 45c0cb9b67e6..18c104820198 100644 --- a/arch/powerpc/platforms/52xx/efika.c +++ b/arch/powerpc/platforms/52xx/efika.c | |||
@@ -99,7 +99,7 @@ static void __init efika_pcisetup(void) | |||
99 | if (bus_range == NULL || len < 2 * sizeof(int)) { | 99 | if (bus_range == NULL || len < 2 * sizeof(int)) { |
100 | printk(KERN_WARNING EFIKA_PLATFORM_NAME | 100 | printk(KERN_WARNING EFIKA_PLATFORM_NAME |
101 | ": Can't get bus-range for %s\n", pcictrl->full_name); | 101 | ": Can't get bus-range for %s\n", pcictrl->full_name); |
102 | return; | 102 | goto out_put; |
103 | } | 103 | } |
104 | 104 | ||
105 | if (bus_range[1] == bus_range[0]) | 105 | if (bus_range[1] == bus_range[0]) |
@@ -111,12 +111,12 @@ static void __init efika_pcisetup(void) | |||
111 | printk(" controlled by %s\n", pcictrl->full_name); | 111 | printk(" controlled by %s\n", pcictrl->full_name); |
112 | printk("\n"); | 112 | printk("\n"); |
113 | 113 | ||
114 | hose = pcibios_alloc_controller(of_node_get(pcictrl)); | 114 | hose = pcibios_alloc_controller(pcictrl); |
115 | if (!hose) { | 115 | if (!hose) { |
116 | printk(KERN_WARNING EFIKA_PLATFORM_NAME | 116 | printk(KERN_WARNING EFIKA_PLATFORM_NAME |
117 | ": Can't allocate PCI controller structure for %s\n", | 117 | ": Can't allocate PCI controller structure for %s\n", |
118 | pcictrl->full_name); | 118 | pcictrl->full_name); |
119 | return; | 119 | goto out_put; |
120 | } | 120 | } |
121 | 121 | ||
122 | hose->first_busno = bus_range[0]; | 122 | hose->first_busno = bus_range[0]; |
@@ -124,6 +124,9 @@ static void __init efika_pcisetup(void) | |||
124 | hose->ops = &rtas_pci_ops; | 124 | hose->ops = &rtas_pci_ops; |
125 | 125 | ||
126 | pci_process_bridge_OF_ranges(hose, pcictrl, 0); | 126 | pci_process_bridge_OF_ranges(hose, pcictrl, 0); |
127 | return; | ||
128 | out_put: | ||
129 | of_node_put(pcictrl); | ||
127 | } | 130 | } |
128 | 131 | ||
129 | #else | 132 | #else |
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_common.c b/arch/powerpc/platforms/52xx/mpc52xx_common.c index 6e905314ad5d..41f3a7eda1de 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_common.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_common.c | |||
@@ -325,12 +325,16 @@ int mpc5200_psc_ac97_gpio_reset(int psc_number) | |||
325 | clrbits32(&simple_gpio->simple_dvo, sync | out); | 325 | clrbits32(&simple_gpio->simple_dvo, sync | out); |
326 | clrbits8(&wkup_gpio->wkup_dvo, reset); | 326 | clrbits8(&wkup_gpio->wkup_dvo, reset); |
327 | 327 | ||
328 | /* wait at lease 1 us */ | 328 | /* wait for 1 us */ |
329 | udelay(2); | 329 | udelay(1); |
330 | 330 | ||
331 | /* Deassert reset */ | 331 | /* Deassert reset */ |
332 | setbits8(&wkup_gpio->wkup_dvo, reset); | 332 | setbits8(&wkup_gpio->wkup_dvo, reset); |
333 | 333 | ||
334 | /* wait at least 200ns */ | ||
335 | /* 7 ~= (200ns * timebase) / ns2sec */ | ||
336 | __delay(7); | ||
337 | |||
334 | /* Restore pin-muxing */ | 338 | /* Restore pin-muxing */ |
335 | out_be32(&simple_gpio->port_config, mux); | 339 | out_be32(&simple_gpio->port_config, mux); |
336 | 340 | ||
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig index 021763a32c2f..73f4135f3a1a 100644 --- a/arch/powerpc/platforms/83xx/Kconfig +++ b/arch/powerpc/platforms/83xx/Kconfig | |||
@@ -10,12 +10,12 @@ menuconfig PPC_83xx | |||
10 | if PPC_83xx | 10 | if PPC_83xx |
11 | 11 | ||
12 | config MPC830x_RDB | 12 | config MPC830x_RDB |
13 | bool "Freescale MPC830x RDB" | 13 | bool "Freescale MPC830x RDB and derivatives" |
14 | select DEFAULT_UIMAGE | 14 | select DEFAULT_UIMAGE |
15 | select PPC_MPC831x | 15 | select PPC_MPC831x |
16 | select FSL_GTM | 16 | select FSL_GTM |
17 | help | 17 | help |
18 | This option enables support for the MPC8308 RDB board. | 18 | This option enables support for the MPC8308 RDB and MPC8308 P1M boards. |
19 | 19 | ||
20 | config MPC831x_RDB | 20 | config MPC831x_RDB |
21 | bool "Freescale MPC831x RDB" | 21 | bool "Freescale MPC831x RDB" |
diff --git a/arch/powerpc/platforms/83xx/mpc830x_rdb.c b/arch/powerpc/platforms/83xx/mpc830x_rdb.c index ac102ee9abe8..846831d495b5 100644 --- a/arch/powerpc/platforms/83xx/mpc830x_rdb.c +++ b/arch/powerpc/platforms/83xx/mpc830x_rdb.c | |||
@@ -65,7 +65,8 @@ static int __init mpc830x_rdb_probe(void) | |||
65 | unsigned long root = of_get_flat_dt_root(); | 65 | unsigned long root = of_get_flat_dt_root(); |
66 | 66 | ||
67 | return of_flat_dt_is_compatible(root, "MPC8308RDB") || | 67 | return of_flat_dt_is_compatible(root, "MPC8308RDB") || |
68 | of_flat_dt_is_compatible(root, "fsl,mpc8308rdb"); | 68 | of_flat_dt_is_compatible(root, "fsl,mpc8308rdb") || |
69 | of_flat_dt_is_compatible(root, "denx,mpc8308_p1m"); | ||
69 | } | 70 | } |
70 | 71 | ||
71 | static struct of_device_id __initdata of_bus_ids[] = { | 72 | static struct of_device_id __initdata of_bus_ids[] = { |
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig index bea1f5905ad4..b6976e1726e4 100644 --- a/arch/powerpc/platforms/85xx/Kconfig +++ b/arch/powerpc/platforms/85xx/Kconfig | |||
@@ -11,6 +11,8 @@ menuconfig FSL_SOC_BOOKE | |||
11 | 11 | ||
12 | if FSL_SOC_BOOKE | 12 | if FSL_SOC_BOOKE |
13 | 13 | ||
14 | if PPC32 | ||
15 | |||
14 | config MPC8540_ADS | 16 | config MPC8540_ADS |
15 | bool "Freescale MPC8540 ADS" | 17 | bool "Freescale MPC8540 ADS" |
16 | select DEFAULT_UIMAGE | 18 | select DEFAULT_UIMAGE |
@@ -153,10 +155,20 @@ config SBC8560 | |||
153 | help | 155 | help |
154 | This option enables support for the Wind River SBC8560 board | 156 | This option enables support for the Wind River SBC8560 board |
155 | 157 | ||
158 | config P3041_DS | ||
159 | bool "Freescale P3041 DS" | ||
160 | select DEFAULT_UIMAGE | ||
161 | select PPC_E500MC | ||
162 | select PHYS_64BIT | ||
163 | select SWIOTLB | ||
164 | select MPC8xxx_GPIO | ||
165 | select HAS_RAPIDIO | ||
166 | help | ||
167 | This option enables support for the P3041 DS board | ||
168 | |||
156 | config P4080_DS | 169 | config P4080_DS |
157 | bool "Freescale P4080 DS" | 170 | bool "Freescale P4080 DS" |
158 | select DEFAULT_UIMAGE | 171 | select DEFAULT_UIMAGE |
159 | select PPC_FSL_BOOK3E | ||
160 | select PPC_E500MC | 172 | select PPC_E500MC |
161 | select PHYS_64BIT | 173 | select PHYS_64BIT |
162 | select SWIOTLB | 174 | select SWIOTLB |
@@ -165,6 +177,20 @@ config P4080_DS | |||
165 | help | 177 | help |
166 | This option enables support for the P4080 DS board | 178 | This option enables support for the P4080 DS board |
167 | 179 | ||
180 | endif # PPC32 | ||
181 | |||
182 | config P5020_DS | ||
183 | bool "Freescale P5020 DS" | ||
184 | select DEFAULT_UIMAGE | ||
185 | select E500 | ||
186 | select PPC_E500MC | ||
187 | select PHYS_64BIT | ||
188 | select SWIOTLB | ||
189 | select MPC8xxx_GPIO | ||
190 | select HAS_RAPIDIO | ||
191 | help | ||
192 | This option enables support for the P5020 DS board | ||
193 | |||
168 | endif # FSL_SOC_BOOKE | 194 | endif # FSL_SOC_BOOKE |
169 | 195 | ||
170 | config TQM85xx | 196 | config TQM85xx |
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile index a2ec3f8f4d06..dd70db77d63e 100644 --- a/arch/powerpc/platforms/85xx/Makefile +++ b/arch/powerpc/platforms/85xx/Makefile | |||
@@ -11,7 +11,9 @@ obj-$(CONFIG_MPC85xx_DS) += mpc85xx_ds.o | |||
11 | obj-$(CONFIG_MPC85xx_MDS) += mpc85xx_mds.o | 11 | obj-$(CONFIG_MPC85xx_MDS) += mpc85xx_mds.o |
12 | obj-$(CONFIG_MPC85xx_RDB) += mpc85xx_rdb.o | 12 | obj-$(CONFIG_MPC85xx_RDB) += mpc85xx_rdb.o |
13 | obj-$(CONFIG_P1022_DS) += p1022_ds.o | 13 | obj-$(CONFIG_P1022_DS) += p1022_ds.o |
14 | obj-$(CONFIG_P3041_DS) += p3041_ds.o corenet_ds.o | ||
14 | obj-$(CONFIG_P4080_DS) += p4080_ds.o corenet_ds.o | 15 | obj-$(CONFIG_P4080_DS) += p4080_ds.o corenet_ds.o |
16 | obj-$(CONFIG_P5020_DS) += p5020_ds.o corenet_ds.o | ||
15 | obj-$(CONFIG_STX_GP3) += stx_gp3.o | 17 | obj-$(CONFIG_STX_GP3) += stx_gp3.o |
16 | obj-$(CONFIG_TQM85xx) += tqm85xx.o | 18 | obj-$(CONFIG_TQM85xx) += tqm85xx.o |
17 | obj-$(CONFIG_SBC8560) += sbc8560.o | 19 | obj-$(CONFIG_SBC8560) += sbc8560.o |
diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c index 34e00902ce86..2b390d19a1d1 100644 --- a/arch/powerpc/platforms/85xx/p1022_ds.c +++ b/arch/powerpc/platforms/85xx/p1022_ds.c | |||
@@ -112,6 +112,8 @@ static struct of_device_id __initdata p1022_ds_ids[] = { | |||
112 | { .compatible = "soc", }, | 112 | { .compatible = "soc", }, |
113 | { .compatible = "simple-bus", }, | 113 | { .compatible = "simple-bus", }, |
114 | { .compatible = "gianfar", }, | 114 | { .compatible = "gianfar", }, |
115 | /* So that the DMA channel nodes can be probed individually: */ | ||
116 | { .compatible = "fsl,eloplus-dma", }, | ||
115 | {}, | 117 | {}, |
116 | }; | 118 | }; |
117 | 119 | ||
diff --git a/arch/powerpc/platforms/85xx/p3041_ds.c b/arch/powerpc/platforms/85xx/p3041_ds.c new file mode 100644 index 000000000000..0ed52e18298c --- /dev/null +++ b/arch/powerpc/platforms/85xx/p3041_ds.c | |||
@@ -0,0 +1,64 @@ | |||
1 | /* | ||
2 | * P3041 DS Setup | ||
3 | * | ||
4 | * Maintained by Kumar Gala (see MAINTAINERS for contact information) | ||
5 | * | ||
6 | * Copyright 2009-2010 Freescale Semiconductor Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/pci.h> | ||
16 | #include <linux/kdev_t.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/phy.h> | ||
20 | |||
21 | #include <asm/system.h> | ||
22 | #include <asm/time.h> | ||
23 | #include <asm/machdep.h> | ||
24 | #include <asm/pci-bridge.h> | ||
25 | #include <mm/mmu_decl.h> | ||
26 | #include <asm/prom.h> | ||
27 | #include <asm/udbg.h> | ||
28 | #include <asm/mpic.h> | ||
29 | |||
30 | #include <linux/of_platform.h> | ||
31 | #include <sysdev/fsl_soc.h> | ||
32 | #include <sysdev/fsl_pci.h> | ||
33 | |||
34 | #include "corenet_ds.h" | ||
35 | |||
36 | /* | ||
37 | * Called very early, device-tree isn't unflattened | ||
38 | */ | ||
39 | static int __init p3041_ds_probe(void) | ||
40 | { | ||
41 | unsigned long root = of_get_flat_dt_root(); | ||
42 | |||
43 | return of_flat_dt_is_compatible(root, "fsl,P3041DS"); | ||
44 | } | ||
45 | |||
46 | define_machine(p3041_ds) { | ||
47 | .name = "P3041 DS", | ||
48 | .probe = p3041_ds_probe, | ||
49 | .setup_arch = corenet_ds_setup_arch, | ||
50 | .init_IRQ = corenet_ds_pic_init, | ||
51 | #ifdef CONFIG_PCI | ||
52 | .pcibios_fixup_bus = fsl_pcibios_fixup_bus, | ||
53 | #endif | ||
54 | .get_irq = mpic_get_coreint_irq, | ||
55 | .restart = fsl_rstcr_restart, | ||
56 | .calibrate_decr = generic_calibrate_decr, | ||
57 | .progress = udbg_progress, | ||
58 | }; | ||
59 | |||
60 | machine_device_initcall(p3041_ds, corenet_ds_publish_devices); | ||
61 | |||
62 | #ifdef CONFIG_SWIOTLB | ||
63 | machine_arch_initcall(p3041_ds, swiotlb_setup_bus_notifier); | ||
64 | #endif | ||
diff --git a/arch/powerpc/platforms/85xx/p5020_ds.c b/arch/powerpc/platforms/85xx/p5020_ds.c new file mode 100644 index 000000000000..7467b712ee00 --- /dev/null +++ b/arch/powerpc/platforms/85xx/p5020_ds.c | |||
@@ -0,0 +1,69 @@ | |||
1 | /* | ||
2 | * P5020 DS Setup | ||
3 | * | ||
4 | * Maintained by Kumar Gala (see MAINTAINERS for contact information) | ||
5 | * | ||
6 | * Copyright 2009-2010 Freescale Semiconductor Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/pci.h> | ||
16 | #include <linux/kdev_t.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/phy.h> | ||
20 | |||
21 | #include <asm/system.h> | ||
22 | #include <asm/time.h> | ||
23 | #include <asm/machdep.h> | ||
24 | #include <asm/pci-bridge.h> | ||
25 | #include <mm/mmu_decl.h> | ||
26 | #include <asm/prom.h> | ||
27 | #include <asm/udbg.h> | ||
28 | #include <asm/mpic.h> | ||
29 | |||
30 | #include <linux/of_platform.h> | ||
31 | #include <sysdev/fsl_soc.h> | ||
32 | #include <sysdev/fsl_pci.h> | ||
33 | |||
34 | #include "corenet_ds.h" | ||
35 | |||
36 | /* | ||
37 | * Called very early, device-tree isn't unflattened | ||
38 | */ | ||
39 | static int __init p5020_ds_probe(void) | ||
40 | { | ||
41 | unsigned long root = of_get_flat_dt_root(); | ||
42 | |||
43 | return of_flat_dt_is_compatible(root, "fsl,P5020DS"); | ||
44 | } | ||
45 | |||
46 | define_machine(p5020_ds) { | ||
47 | .name = "P5020 DS", | ||
48 | .probe = p5020_ds_probe, | ||
49 | .setup_arch = corenet_ds_setup_arch, | ||
50 | .init_IRQ = corenet_ds_pic_init, | ||
51 | #ifdef CONFIG_PCI | ||
52 | .pcibios_fixup_bus = fsl_pcibios_fixup_bus, | ||
53 | #endif | ||
54 | /* coreint doesn't play nice with lazy EE, use legacy mpic for now */ | ||
55 | #ifdef CONFIG_PPC64 | ||
56 | .get_irq = mpic_get_irq, | ||
57 | #else | ||
58 | .get_irq = mpic_get_coreint_irq, | ||
59 | #endif | ||
60 | .restart = fsl_rstcr_restart, | ||
61 | .calibrate_decr = generic_calibrate_decr, | ||
62 | .progress = udbg_progress, | ||
63 | }; | ||
64 | |||
65 | machine_device_initcall(p5020_ds, corenet_ds_publish_devices); | ||
66 | |||
67 | #ifdef CONFIG_SWIOTLB | ||
68 | machine_arch_initcall(p5020_ds, swiotlb_setup_bus_notifier); | ||
69 | #endif | ||
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c index a6b106557be4..5c91a992f02b 100644 --- a/arch/powerpc/platforms/85xx/smp.c +++ b/arch/powerpc/platforms/85xx/smp.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
17 | #include <linux/of.h> | 17 | #include <linux/of.h> |
18 | #include <linux/kexec.h> | 18 | #include <linux/kexec.h> |
19 | #include <linux/highmem.h> | ||
19 | 20 | ||
20 | #include <asm/machdep.h> | 21 | #include <asm/machdep.h> |
21 | #include <asm/pgtable.h> | 22 | #include <asm/pgtable.h> |
@@ -79,6 +80,7 @@ smp_85xx_kick_cpu(int nr) | |||
79 | local_irq_save(flags); | 80 | local_irq_save(flags); |
80 | 81 | ||
81 | out_be32(bptr_vaddr + BOOT_ENTRY_PIR, nr); | 82 | out_be32(bptr_vaddr + BOOT_ENTRY_PIR, nr); |
83 | #ifdef CONFIG_PPC32 | ||
82 | out_be32(bptr_vaddr + BOOT_ENTRY_ADDR_LOWER, __pa(__early_start)); | 84 | out_be32(bptr_vaddr + BOOT_ENTRY_ADDR_LOWER, __pa(__early_start)); |
83 | 85 | ||
84 | if (!ioremappable) | 86 | if (!ioremappable) |
@@ -88,6 +90,12 @@ smp_85xx_kick_cpu(int nr) | |||
88 | /* Wait a bit for the CPU to ack. */ | 90 | /* Wait a bit for the CPU to ack. */ |
89 | while ((__secondary_hold_acknowledge != nr) && (++n < 1000)) | 91 | while ((__secondary_hold_acknowledge != nr) && (++n < 1000)) |
90 | mdelay(1); | 92 | mdelay(1); |
93 | #else | ||
94 | out_be64((u64 *)(bptr_vaddr + BOOT_ENTRY_ADDR_UPPER), | ||
95 | __pa((u64)*((unsigned long long *) generic_secondary_smp_init))); | ||
96 | |||
97 | smp_generic_kick_cpu(nr); | ||
98 | #endif | ||
91 | 99 | ||
92 | local_irq_restore(flags); | 100 | local_irq_restore(flags); |
93 | 101 | ||
@@ -114,19 +122,15 @@ struct smp_ops_t smp_85xx_ops = { | |||
114 | }; | 122 | }; |
115 | 123 | ||
116 | #ifdef CONFIG_KEXEC | 124 | #ifdef CONFIG_KEXEC |
117 | static int kexec_down_cpus = 0; | 125 | atomic_t kexec_down_cpus = ATOMIC_INIT(0); |
118 | 126 | ||
119 | void mpc85xx_smp_kexec_cpu_down(int crash_shutdown, int secondary) | 127 | void mpc85xx_smp_kexec_cpu_down(int crash_shutdown, int secondary) |
120 | { | 128 | { |
121 | mpic_teardown_this_cpu(1); | 129 | local_irq_disable(); |
122 | |||
123 | /* When crashing, this gets called on all CPU's we only | ||
124 | * take down the non-boot cpus */ | ||
125 | if (smp_processor_id() != boot_cpuid) | ||
126 | { | ||
127 | local_irq_disable(); | ||
128 | kexec_down_cpus++; | ||
129 | 130 | ||
131 | if (secondary) { | ||
132 | atomic_inc(&kexec_down_cpus); | ||
133 | /* loop forever */ | ||
130 | while (1); | 134 | while (1); |
131 | } | 135 | } |
132 | } | 136 | } |
@@ -137,16 +141,65 @@ static void mpc85xx_smp_kexec_down(void *arg) | |||
137 | ppc_md.kexec_cpu_down(0,1); | 141 | ppc_md.kexec_cpu_down(0,1); |
138 | } | 142 | } |
139 | 143 | ||
140 | static void mpc85xx_smp_machine_kexec(struct kimage *image) | 144 | static void map_and_flush(unsigned long paddr) |
141 | { | 145 | { |
142 | int timeout = 2000; | 146 | struct page *page = pfn_to_page(paddr >> PAGE_SHIFT); |
147 | unsigned long kaddr = (unsigned long)kmap(page); | ||
148 | |||
149 | flush_dcache_range(kaddr, kaddr + PAGE_SIZE); | ||
150 | kunmap(page); | ||
151 | } | ||
152 | |||
153 | /** | ||
154 | * Before we reset the other cores, we need to flush relevant cache | ||
155 | * out to memory so we don't get anything corrupted, some of these flushes | ||
156 | * are performed out of an overabundance of caution as interrupts are not | ||
157 | * disabled yet and we can switch cores | ||
158 | */ | ||
159 | static void mpc85xx_smp_flush_dcache_kexec(struct kimage *image) | ||
160 | { | ||
161 | kimage_entry_t *ptr, entry; | ||
162 | unsigned long paddr; | ||
143 | int i; | 163 | int i; |
144 | 164 | ||
145 | set_cpus_allowed(current, cpumask_of_cpu(boot_cpuid)); | 165 | if (image->type == KEXEC_TYPE_DEFAULT) { |
166 | /* normal kexec images are stored in temporary pages */ | ||
167 | for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE); | ||
168 | ptr = (entry & IND_INDIRECTION) ? | ||
169 | phys_to_virt(entry & PAGE_MASK) : ptr + 1) { | ||
170 | if (!(entry & IND_DESTINATION)) { | ||
171 | map_and_flush(entry); | ||
172 | } | ||
173 | } | ||
174 | /* flush out last IND_DONE page */ | ||
175 | map_and_flush(entry); | ||
176 | } else { | ||
177 | /* crash type kexec images are copied to the crash region */ | ||
178 | for (i = 0; i < image->nr_segments; i++) { | ||
179 | struct kexec_segment *seg = &image->segment[i]; | ||
180 | for (paddr = seg->mem; paddr < seg->mem + seg->memsz; | ||
181 | paddr += PAGE_SIZE) { | ||
182 | map_and_flush(paddr); | ||
183 | } | ||
184 | } | ||
185 | } | ||
186 | |||
187 | /* also flush the kimage struct to be passed in as well */ | ||
188 | flush_dcache_range((unsigned long)image, | ||
189 | (unsigned long)image + sizeof(*image)); | ||
190 | } | ||
191 | |||
192 | static void mpc85xx_smp_machine_kexec(struct kimage *image) | ||
193 | { | ||
194 | int timeout = INT_MAX; | ||
195 | int i, num_cpus = num_present_cpus(); | ||
196 | |||
197 | mpc85xx_smp_flush_dcache_kexec(image); | ||
146 | 198 | ||
147 | smp_call_function(mpc85xx_smp_kexec_down, NULL, 0); | 199 | if (image->type == KEXEC_TYPE_DEFAULT) |
200 | smp_call_function(mpc85xx_smp_kexec_down, NULL, 0); | ||
148 | 201 | ||
149 | while ( (kexec_down_cpus != (num_online_cpus() - 1)) && | 202 | while ( (atomic_read(&kexec_down_cpus) != (num_cpus - 1)) && |
150 | ( timeout > 0 ) ) | 203 | ( timeout > 0 ) ) |
151 | { | 204 | { |
152 | timeout--; | 205 | timeout--; |
@@ -155,7 +208,7 @@ static void mpc85xx_smp_machine_kexec(struct kimage *image) | |||
155 | if ( !timeout ) | 208 | if ( !timeout ) |
156 | printk(KERN_ERR "Unable to bring down secondary cpu(s)"); | 209 | printk(KERN_ERR "Unable to bring down secondary cpu(s)"); |
157 | 210 | ||
158 | for (i = 0; i < num_present_cpus(); i++) | 211 | for (i = 0; i < num_cpus; i++) |
159 | { | 212 | { |
160 | if ( i == smp_processor_id() ) continue; | 213 | if ( i == smp_processor_id() ) continue; |
161 | mpic_reset_core(i); | 214 | mpic_reset_core(i); |
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index 81c9208025fa..956154f32cfe 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig | |||
@@ -21,6 +21,16 @@ source "arch/powerpc/platforms/44x/Kconfig" | |||
21 | source "arch/powerpc/platforms/40x/Kconfig" | 21 | source "arch/powerpc/platforms/40x/Kconfig" |
22 | source "arch/powerpc/platforms/amigaone/Kconfig" | 22 | source "arch/powerpc/platforms/amigaone/Kconfig" |
23 | 23 | ||
24 | config KVM_GUEST | ||
25 | bool "KVM Guest support" | ||
26 | default y | ||
27 | ---help--- | ||
28 | This option enables various optimizations for running under the KVM | ||
29 | hypervisor. Overhead for the kernel when not running inside KVM should | ||
30 | be minimal. | ||
31 | |||
32 | In case of doubt, say Y | ||
33 | |||
24 | config PPC_NATIVE | 34 | config PPC_NATIVE |
25 | bool | 35 | bool |
26 | depends on 6xx || PPC64 | 36 | depends on 6xx || PPC64 |
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype index d361f8119b1e..111138c55f9c 100644 --- a/arch/powerpc/platforms/Kconfig.cputype +++ b/arch/powerpc/platforms/Kconfig.cputype | |||
@@ -125,6 +125,7 @@ config 8xx | |||
125 | 125 | ||
126 | config E500 | 126 | config E500 |
127 | select FSL_EMB_PERFMON | 127 | select FSL_EMB_PERFMON |
128 | select PPC_FSL_BOOK3E | ||
128 | bool | 129 | bool |
129 | 130 | ||
130 | config PPC_E500MC | 131 | config PPC_E500MC |
@@ -166,9 +167,14 @@ config BOOKE | |||
166 | 167 | ||
167 | config FSL_BOOKE | 168 | config FSL_BOOKE |
168 | bool | 169 | bool |
169 | depends on E200 || E500 | 170 | depends on (E200 || E500) && PPC32 |
170 | default y | 171 | default y |
171 | 172 | ||
173 | # this is for common code between PPC32 & PPC64 FSL BOOKE | ||
174 | config PPC_FSL_BOOK3E | ||
175 | bool | ||
176 | select FSL_EMB_PERFMON | ||
177 | default y if FSL_BOOKE | ||
172 | 178 | ||
173 | config PTE_64BIT | 179 | config PTE_64BIT |
174 | bool | 180 | bool |
diff --git a/arch/powerpc/platforms/cell/axon_msi.c b/arch/powerpc/platforms/cell/axon_msi.c index 97085530aa63..e3e379c6caa7 100644 --- a/arch/powerpc/platforms/cell/axon_msi.c +++ b/arch/powerpc/platforms/cell/axon_msi.c | |||
@@ -310,9 +310,9 @@ static void axon_msi_teardown_msi_irqs(struct pci_dev *dev) | |||
310 | } | 310 | } |
311 | 311 | ||
312 | static struct irq_chip msic_irq_chip = { | 312 | static struct irq_chip msic_irq_chip = { |
313 | .mask = mask_msi_irq, | 313 | .irq_mask = mask_msi_irq, |
314 | .unmask = unmask_msi_irq, | 314 | .irq_unmask = unmask_msi_irq, |
315 | .shutdown = unmask_msi_irq, | 315 | .irq_shutdown = mask_msi_irq, |
316 | .name = "AXON-MSI", | 316 | .name = "AXON-MSI", |
317 | }; | 317 | }; |
318 | 318 | ||
diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c index 1d3c4effea10..5ec1e47a0d77 100644 --- a/arch/powerpc/platforms/cell/ras.c +++ b/arch/powerpc/platforms/cell/ras.c | |||
@@ -173,8 +173,10 @@ static int __init cbe_ptcal_enable(void) | |||
173 | return -ENODEV; | 173 | return -ENODEV; |
174 | 174 | ||
175 | size = of_get_property(np, "ibm,cbe-ptcal-size", NULL); | 175 | size = of_get_property(np, "ibm,cbe-ptcal-size", NULL); |
176 | if (!size) | 176 | if (!size) { |
177 | of_node_put(np); | ||
177 | return -ENODEV; | 178 | return -ENODEV; |
179 | } | ||
178 | 180 | ||
179 | pr_debug("%s: enabling PTCAL, size = 0x%x\n", __func__, *size); | 181 | pr_debug("%s: enabling PTCAL, size = 0x%x\n", __func__, *size); |
180 | order = get_order(*size); | 182 | order = get_order(*size); |
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c index 5876e888e412..3f2e557344a3 100644 --- a/arch/powerpc/platforms/cell/spider-pic.c +++ b/arch/powerpc/platforms/cell/spider-pic.c | |||
@@ -258,8 +258,10 @@ static unsigned int __init spider_find_cascade_and_node(struct spider_pic *pic) | |||
258 | return NO_IRQ; | 258 | return NO_IRQ; |
259 | imap += intsize + 1; | 259 | imap += intsize + 1; |
260 | tmp = of_get_property(iic, "#interrupt-cells", NULL); | 260 | tmp = of_get_property(iic, "#interrupt-cells", NULL); |
261 | if (tmp == NULL) | 261 | if (tmp == NULL) { |
262 | of_node_put(iic); | ||
262 | return NO_IRQ; | 263 | return NO_IRQ; |
264 | } | ||
263 | intsize = *tmp; | 265 | intsize = *tmp; |
264 | /* Assume unit is last entry of interrupt specifier */ | 266 | /* Assume unit is last entry of interrupt specifier */ |
265 | unit = imap[intsize - 1]; | 267 | unit = imap[intsize - 1]; |
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 1a40da92154c..02f7b113a31b 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c | |||
@@ -154,6 +154,7 @@ static const struct file_operations __fops = { \ | |||
154 | .release = spufs_attr_release, \ | 154 | .release = spufs_attr_release, \ |
155 | .read = spufs_attr_read, \ | 155 | .read = spufs_attr_read, \ |
156 | .write = spufs_attr_write, \ | 156 | .write = spufs_attr_write, \ |
157 | .llseek = generic_file_llseek, \ | ||
157 | }; | 158 | }; |
158 | 159 | ||
159 | 160 | ||
@@ -521,6 +522,7 @@ static const struct file_operations spufs_cntl_fops = { | |||
521 | .release = spufs_cntl_release, | 522 | .release = spufs_cntl_release, |
522 | .read = simple_attr_read, | 523 | .read = simple_attr_read, |
523 | .write = simple_attr_write, | 524 | .write = simple_attr_write, |
525 | .llseek = generic_file_llseek, | ||
524 | .mmap = spufs_cntl_mmap, | 526 | .mmap = spufs_cntl_mmap, |
525 | }; | 527 | }; |
526 | 528 | ||
@@ -714,6 +716,7 @@ static ssize_t spufs_mbox_read(struct file *file, char __user *buf, | |||
714 | static const struct file_operations spufs_mbox_fops = { | 716 | static const struct file_operations spufs_mbox_fops = { |
715 | .open = spufs_pipe_open, | 717 | .open = spufs_pipe_open, |
716 | .read = spufs_mbox_read, | 718 | .read = spufs_mbox_read, |
719 | .llseek = no_llseek, | ||
717 | }; | 720 | }; |
718 | 721 | ||
719 | static ssize_t spufs_mbox_stat_read(struct file *file, char __user *buf, | 722 | static ssize_t spufs_mbox_stat_read(struct file *file, char __user *buf, |
@@ -743,6 +746,7 @@ static ssize_t spufs_mbox_stat_read(struct file *file, char __user *buf, | |||
743 | static const struct file_operations spufs_mbox_stat_fops = { | 746 | static const struct file_operations spufs_mbox_stat_fops = { |
744 | .open = spufs_pipe_open, | 747 | .open = spufs_pipe_open, |
745 | .read = spufs_mbox_stat_read, | 748 | .read = spufs_mbox_stat_read, |
749 | .llseek = no_llseek, | ||
746 | }; | 750 | }; |
747 | 751 | ||
748 | /* low-level ibox access function */ | 752 | /* low-level ibox access function */ |
@@ -863,6 +867,7 @@ static const struct file_operations spufs_ibox_fops = { | |||
863 | .read = spufs_ibox_read, | 867 | .read = spufs_ibox_read, |
864 | .poll = spufs_ibox_poll, | 868 | .poll = spufs_ibox_poll, |
865 | .fasync = spufs_ibox_fasync, | 869 | .fasync = spufs_ibox_fasync, |
870 | .llseek = no_llseek, | ||
866 | }; | 871 | }; |
867 | 872 | ||
868 | static ssize_t spufs_ibox_stat_read(struct file *file, char __user *buf, | 873 | static ssize_t spufs_ibox_stat_read(struct file *file, char __user *buf, |
@@ -890,6 +895,7 @@ static ssize_t spufs_ibox_stat_read(struct file *file, char __user *buf, | |||
890 | static const struct file_operations spufs_ibox_stat_fops = { | 895 | static const struct file_operations spufs_ibox_stat_fops = { |
891 | .open = spufs_pipe_open, | 896 | .open = spufs_pipe_open, |
892 | .read = spufs_ibox_stat_read, | 897 | .read = spufs_ibox_stat_read, |
898 | .llseek = no_llseek, | ||
893 | }; | 899 | }; |
894 | 900 | ||
895 | /* low-level mailbox write */ | 901 | /* low-level mailbox write */ |
@@ -1011,6 +1017,7 @@ static const struct file_operations spufs_wbox_fops = { | |||
1011 | .write = spufs_wbox_write, | 1017 | .write = spufs_wbox_write, |
1012 | .poll = spufs_wbox_poll, | 1018 | .poll = spufs_wbox_poll, |
1013 | .fasync = spufs_wbox_fasync, | 1019 | .fasync = spufs_wbox_fasync, |
1020 | .llseek = no_llseek, | ||
1014 | }; | 1021 | }; |
1015 | 1022 | ||
1016 | static ssize_t spufs_wbox_stat_read(struct file *file, char __user *buf, | 1023 | static ssize_t spufs_wbox_stat_read(struct file *file, char __user *buf, |
@@ -1038,6 +1045,7 @@ static ssize_t spufs_wbox_stat_read(struct file *file, char __user *buf, | |||
1038 | static const struct file_operations spufs_wbox_stat_fops = { | 1045 | static const struct file_operations spufs_wbox_stat_fops = { |
1039 | .open = spufs_pipe_open, | 1046 | .open = spufs_pipe_open, |
1040 | .read = spufs_wbox_stat_read, | 1047 | .read = spufs_wbox_stat_read, |
1048 | .llseek = no_llseek, | ||
1041 | }; | 1049 | }; |
1042 | 1050 | ||
1043 | static int spufs_signal1_open(struct inode *inode, struct file *file) | 1051 | static int spufs_signal1_open(struct inode *inode, struct file *file) |
@@ -1166,6 +1174,7 @@ static const struct file_operations spufs_signal1_fops = { | |||
1166 | .read = spufs_signal1_read, | 1174 | .read = spufs_signal1_read, |
1167 | .write = spufs_signal1_write, | 1175 | .write = spufs_signal1_write, |
1168 | .mmap = spufs_signal1_mmap, | 1176 | .mmap = spufs_signal1_mmap, |
1177 | .llseek = no_llseek, | ||
1169 | }; | 1178 | }; |
1170 | 1179 | ||
1171 | static const struct file_operations spufs_signal1_nosched_fops = { | 1180 | static const struct file_operations spufs_signal1_nosched_fops = { |
@@ -1173,6 +1182,7 @@ static const struct file_operations spufs_signal1_nosched_fops = { | |||
1173 | .release = spufs_signal1_release, | 1182 | .release = spufs_signal1_release, |
1174 | .write = spufs_signal1_write, | 1183 | .write = spufs_signal1_write, |
1175 | .mmap = spufs_signal1_mmap, | 1184 | .mmap = spufs_signal1_mmap, |
1185 | .llseek = no_llseek, | ||
1176 | }; | 1186 | }; |
1177 | 1187 | ||
1178 | static int spufs_signal2_open(struct inode *inode, struct file *file) | 1188 | static int spufs_signal2_open(struct inode *inode, struct file *file) |
@@ -1305,6 +1315,7 @@ static const struct file_operations spufs_signal2_fops = { | |||
1305 | .read = spufs_signal2_read, | 1315 | .read = spufs_signal2_read, |
1306 | .write = spufs_signal2_write, | 1316 | .write = spufs_signal2_write, |
1307 | .mmap = spufs_signal2_mmap, | 1317 | .mmap = spufs_signal2_mmap, |
1318 | .llseek = no_llseek, | ||
1308 | }; | 1319 | }; |
1309 | 1320 | ||
1310 | static const struct file_operations spufs_signal2_nosched_fops = { | 1321 | static const struct file_operations spufs_signal2_nosched_fops = { |
@@ -1312,6 +1323,7 @@ static const struct file_operations spufs_signal2_nosched_fops = { | |||
1312 | .release = spufs_signal2_release, | 1323 | .release = spufs_signal2_release, |
1313 | .write = spufs_signal2_write, | 1324 | .write = spufs_signal2_write, |
1314 | .mmap = spufs_signal2_mmap, | 1325 | .mmap = spufs_signal2_mmap, |
1326 | .llseek = no_llseek, | ||
1315 | }; | 1327 | }; |
1316 | 1328 | ||
1317 | /* | 1329 | /* |
@@ -1451,6 +1463,7 @@ static const struct file_operations spufs_mss_fops = { | |||
1451 | .open = spufs_mss_open, | 1463 | .open = spufs_mss_open, |
1452 | .release = spufs_mss_release, | 1464 | .release = spufs_mss_release, |
1453 | .mmap = spufs_mss_mmap, | 1465 | .mmap = spufs_mss_mmap, |
1466 | .llseek = no_llseek, | ||
1454 | }; | 1467 | }; |
1455 | 1468 | ||
1456 | static int | 1469 | static int |
@@ -1508,6 +1521,7 @@ static const struct file_operations spufs_psmap_fops = { | |||
1508 | .open = spufs_psmap_open, | 1521 | .open = spufs_psmap_open, |
1509 | .release = spufs_psmap_release, | 1522 | .release = spufs_psmap_release, |
1510 | .mmap = spufs_psmap_mmap, | 1523 | .mmap = spufs_psmap_mmap, |
1524 | .llseek = no_llseek, | ||
1511 | }; | 1525 | }; |
1512 | 1526 | ||
1513 | 1527 | ||
@@ -1871,6 +1885,7 @@ static const struct file_operations spufs_mfc_fops = { | |||
1871 | .fsync = spufs_mfc_fsync, | 1885 | .fsync = spufs_mfc_fsync, |
1872 | .fasync = spufs_mfc_fasync, | 1886 | .fasync = spufs_mfc_fasync, |
1873 | .mmap = spufs_mfc_mmap, | 1887 | .mmap = spufs_mfc_mmap, |
1888 | .llseek = no_llseek, | ||
1874 | }; | 1889 | }; |
1875 | 1890 | ||
1876 | static int spufs_npc_set(void *data, u64 val) | 1891 | static int spufs_npc_set(void *data, u64 val) |
@@ -2246,6 +2261,7 @@ static ssize_t spufs_dma_info_read(struct file *file, char __user *buf, | |||
2246 | static const struct file_operations spufs_dma_info_fops = { | 2261 | static const struct file_operations spufs_dma_info_fops = { |
2247 | .open = spufs_info_open, | 2262 | .open = spufs_info_open, |
2248 | .read = spufs_dma_info_read, | 2263 | .read = spufs_dma_info_read, |
2264 | .llseek = no_llseek, | ||
2249 | }; | 2265 | }; |
2250 | 2266 | ||
2251 | static ssize_t __spufs_proxydma_info_read(struct spu_context *ctx, | 2267 | static ssize_t __spufs_proxydma_info_read(struct spu_context *ctx, |
@@ -2299,6 +2315,7 @@ static ssize_t spufs_proxydma_info_read(struct file *file, char __user *buf, | |||
2299 | static const struct file_operations spufs_proxydma_info_fops = { | 2315 | static const struct file_operations spufs_proxydma_info_fops = { |
2300 | .open = spufs_info_open, | 2316 | .open = spufs_info_open, |
2301 | .read = spufs_proxydma_info_read, | 2317 | .read = spufs_proxydma_info_read, |
2318 | .llseek = no_llseek, | ||
2302 | }; | 2319 | }; |
2303 | 2320 | ||
2304 | static int spufs_show_tid(struct seq_file *s, void *private) | 2321 | static int spufs_show_tid(struct seq_file *s, void *private) |
@@ -2585,6 +2602,7 @@ static const struct file_operations spufs_switch_log_fops = { | |||
2585 | .read = spufs_switch_log_read, | 2602 | .read = spufs_switch_log_read, |
2586 | .poll = spufs_switch_log_poll, | 2603 | .poll = spufs_switch_log_poll, |
2587 | .release = spufs_switch_log_release, | 2604 | .release = spufs_switch_log_release, |
2605 | .llseek = no_llseek, | ||
2588 | }; | 2606 | }; |
2589 | 2607 | ||
2590 | /** | 2608 | /** |
diff --git a/arch/powerpc/platforms/chrp/nvram.c b/arch/powerpc/platforms/chrp/nvram.c index ba3588f2d8e0..d3ceff04ffc7 100644 --- a/arch/powerpc/platforms/chrp/nvram.c +++ b/arch/powerpc/platforms/chrp/nvram.c | |||
@@ -74,8 +74,10 @@ void __init chrp_nvram_init(void) | |||
74 | return; | 74 | return; |
75 | 75 | ||
76 | nbytes_p = of_get_property(nvram, "#bytes", &proplen); | 76 | nbytes_p = of_get_property(nvram, "#bytes", &proplen); |
77 | if (nbytes_p == NULL || proplen != sizeof(unsigned int)) | 77 | if (nbytes_p == NULL || proplen != sizeof(unsigned int)) { |
78 | of_node_put(nvram); | ||
78 | return; | 79 | return; |
80 | } | ||
79 | 81 | ||
80 | nvram_size = *nbytes_p; | 82 | nvram_size = *nbytes_p; |
81 | 83 | ||
diff --git a/arch/powerpc/platforms/embedded6xx/wii.c b/arch/powerpc/platforms/embedded6xx/wii.c index 5cdcc7c8d973..649473a729b8 100644 --- a/arch/powerpc/platforms/embedded6xx/wii.c +++ b/arch/powerpc/platforms/embedded6xx/wii.c | |||
@@ -65,7 +65,7 @@ static int __init page_aligned(unsigned long x) | |||
65 | 65 | ||
66 | void __init wii_memory_fixups(void) | 66 | void __init wii_memory_fixups(void) |
67 | { | 67 | { |
68 | struct memblock_property *p = memblock.memory.region; | 68 | struct memblock_region *p = memblock.memory.regions; |
69 | 69 | ||
70 | /* | 70 | /* |
71 | * This is part of a workaround to allow the use of two | 71 | * This is part of a workaround to allow the use of two |
diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile index ce014928d460..a7602b11ed9d 100644 --- a/arch/powerpc/platforms/iseries/Makefile +++ b/arch/powerpc/platforms/iseries/Makefile | |||
@@ -1,4 +1,4 @@ | |||
1 | EXTRA_CFLAGS += -mno-minimal-toc | 1 | ccflags-y := -mno-minimal-toc |
2 | 2 | ||
3 | obj-y += exception.o | 3 | obj-y += exception.o |
4 | obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt.o mf.o lpevents.o \ | 4 | obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt.o mf.o lpevents.o \ |
diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c index 7f45a51fe793..fdb7384c0c4f 100644 --- a/arch/powerpc/platforms/iseries/dt.c +++ b/arch/powerpc/platforms/iseries/dt.c | |||
@@ -243,7 +243,7 @@ static void __init dt_cpus(struct iseries_flat_dt *dt) | |||
243 | pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE); | 243 | pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE); |
244 | 244 | ||
245 | for (i = 0; i < NR_CPUS; i++) { | 245 | for (i = 0; i < NR_CPUS; i++) { |
246 | if (lppaca[i].dyn_proc_status >= 2) | 246 | if (lppaca_of(i).dyn_proc_status >= 2) |
247 | continue; | 247 | continue; |
248 | 248 | ||
249 | snprintf(p, 32 - (p - buf), "@%d", i); | 249 | snprintf(p, 32 - (p - buf), "@%d", i); |
@@ -251,7 +251,7 @@ static void __init dt_cpus(struct iseries_flat_dt *dt) | |||
251 | 251 | ||
252 | dt_prop_str(dt, "device_type", device_type_cpu); | 252 | dt_prop_str(dt, "device_type", device_type_cpu); |
253 | 253 | ||
254 | index = lppaca[i].dyn_hv_phys_proc_index; | 254 | index = lppaca_of(i).dyn_hv_phys_proc_index; |
255 | d = &xIoHriProcessorVpd[index]; | 255 | d = &xIoHriProcessorVpd[index]; |
256 | 256 | ||
257 | dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024); | 257 | dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024); |
diff --git a/arch/powerpc/platforms/iseries/mf.c b/arch/powerpc/platforms/iseries/mf.c index 33e5fc7334fc..42d0a886de05 100644 --- a/arch/powerpc/platforms/iseries/mf.c +++ b/arch/powerpc/platforms/iseries/mf.c | |||
@@ -1249,6 +1249,7 @@ out: | |||
1249 | 1249 | ||
1250 | static const struct file_operations proc_vmlinux_operations = { | 1250 | static const struct file_operations proc_vmlinux_operations = { |
1251 | .write = proc_mf_change_vmlinux, | 1251 | .write = proc_mf_change_vmlinux, |
1252 | .llseek = default_llseek, | ||
1252 | }; | 1253 | }; |
1253 | 1254 | ||
1254 | static int __init mf_proc_init(void) | 1255 | static int __init mf_proc_init(void) |
diff --git a/arch/powerpc/platforms/iseries/smp.c b/arch/powerpc/platforms/iseries/smp.c index 6590850045af..6c6029914dbc 100644 --- a/arch/powerpc/platforms/iseries/smp.c +++ b/arch/powerpc/platforms/iseries/smp.c | |||
@@ -91,7 +91,7 @@ static void smp_iSeries_kick_cpu(int nr) | |||
91 | BUG_ON((nr < 0) || (nr >= NR_CPUS)); | 91 | BUG_ON((nr < 0) || (nr >= NR_CPUS)); |
92 | 92 | ||
93 | /* Verify that our partition has a processor nr */ | 93 | /* Verify that our partition has a processor nr */ |
94 | if (lppaca[nr].dyn_proc_status >= 2) | 94 | if (lppaca_of(nr).dyn_proc_status >= 2) |
95 | return; | 95 | return; |
96 | 96 | ||
97 | /* The processor is currently spinning, waiting | 97 | /* The processor is currently spinning, waiting |
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c index 3fff8d979b41..fe34c3d9bb74 100644 --- a/arch/powerpc/platforms/maple/setup.c +++ b/arch/powerpc/platforms/maple/setup.c | |||
@@ -358,6 +358,7 @@ static int __init maple_cpc925_edac_setup(void) | |||
358 | model = (const unsigned char *)of_get_property(np, "model", NULL); | 358 | model = (const unsigned char *)of_get_property(np, "model", NULL); |
359 | if (!model) { | 359 | if (!model) { |
360 | printk(KERN_ERR "%s: Unabel to get model info\n", __func__); | 360 | printk(KERN_ERR "%s: Unabel to get model info\n", __func__); |
361 | of_node_put(np); | ||
361 | return -ENODEV; | 362 | return -ENODEV; |
362 | } | 363 | } |
363 | 364 | ||
diff --git a/arch/powerpc/platforms/powermac/pfunc_core.c b/arch/powerpc/platforms/powermac/pfunc_core.c index cec635942657..b0c3777528a1 100644 --- a/arch/powerpc/platforms/powermac/pfunc_core.c +++ b/arch/powerpc/platforms/powermac/pfunc_core.c | |||
@@ -837,8 +837,10 @@ struct pmf_function *__pmf_find_function(struct device_node *target, | |||
837 | return NULL; | 837 | return NULL; |
838 | find_it: | 838 | find_it: |
839 | dev = pmf_find_device(actor); | 839 | dev = pmf_find_device(actor); |
840 | if (dev == NULL) | 840 | if (dev == NULL) { |
841 | return NULL; | 841 | result = NULL; |
842 | goto out; | ||
843 | } | ||
842 | 844 | ||
843 | list_for_each_entry(func, &dev->functions, link) { | 845 | list_for_each_entry(func, &dev->functions, link) { |
844 | if (name && strcmp(name, func->name)) | 846 | if (name && strcmp(name, func->name)) |
@@ -850,8 +852,9 @@ struct pmf_function *__pmf_find_function(struct device_node *target, | |||
850 | result = func; | 852 | result = func; |
851 | break; | 853 | break; |
852 | } | 854 | } |
853 | of_node_put(actor); | ||
854 | pmf_put_device(dev); | 855 | pmf_put_device(dev); |
856 | out: | ||
857 | of_node_put(actor); | ||
855 | return result; | 858 | return result; |
856 | } | 859 | } |
857 | 860 | ||
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index 046ace9c4381..59eb8bdaa79d 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile | |||
@@ -1,14 +1,9 @@ | |||
1 | ifeq ($(CONFIG_PPC64),y) | 1 | ccflags-$(CONFIG_PPC64) := -mno-minimal-toc |
2 | EXTRA_CFLAGS += -mno-minimal-toc | 2 | ccflags-$(CONFIG_PPC_PSERIES_DEBUG) += -DDEBUG |
3 | endif | ||
4 | |||
5 | ifeq ($(CONFIG_PPC_PSERIES_DEBUG),y) | ||
6 | EXTRA_CFLAGS += -DDEBUG | ||
7 | endif | ||
8 | 3 | ||
9 | obj-y := lpar.o hvCall.o nvram.o reconfig.o \ | 4 | obj-y := lpar.o hvCall.o nvram.o reconfig.o \ |
10 | setup.o iommu.o event_sources.o ras.o \ | 5 | setup.o iommu.o event_sources.o ras.o \ |
11 | firmware.o power.o dlpar.o | 6 | firmware.o power.o dlpar.o mobility.o |
12 | obj-$(CONFIG_SMP) += smp.o | 7 | obj-$(CONFIG_SMP) += smp.o |
13 | obj-$(CONFIG_XICS) += xics.o | 8 | obj-$(CONFIG_XICS) += xics.o |
14 | obj-$(CONFIG_SCANLOG) += scanlog.o | 9 | obj-$(CONFIG_SCANLOG) += scanlog.o |
@@ -23,7 +18,7 @@ obj-$(CONFIG_MEMORY_HOTPLUG) += hotplug-memory.o | |||
23 | obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o | 18 | obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o |
24 | obj-$(CONFIG_HVCS) += hvcserver.o | 19 | obj-$(CONFIG_HVCS) += hvcserver.o |
25 | obj-$(CONFIG_HCALL_STATS) += hvCall_inst.o | 20 | obj-$(CONFIG_HCALL_STATS) += hvCall_inst.o |
26 | obj-$(CONFIG_PHYP_DUMP) += phyp_dump.o | 21 | obj-$(CONFIG_PHYP_DUMP) += phyp_dump.o |
27 | obj-$(CONFIG_CMM) += cmm.o | 22 | obj-$(CONFIG_CMM) += cmm.o |
28 | obj-$(CONFIG_DTL) += dtl.o | 23 | obj-$(CONFIG_DTL) += dtl.o |
29 | 24 | ||
diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c index 72d8054fa739..b74a9230edc9 100644 --- a/arch/powerpc/platforms/pseries/dlpar.c +++ b/arch/powerpc/platforms/pseries/dlpar.c | |||
@@ -33,7 +33,7 @@ struct cc_workarea { | |||
33 | u32 prop_offset; | 33 | u32 prop_offset; |
34 | }; | 34 | }; |
35 | 35 | ||
36 | static void dlpar_free_cc_property(struct property *prop) | 36 | void dlpar_free_cc_property(struct property *prop) |
37 | { | 37 | { |
38 | kfree(prop->name); | 38 | kfree(prop->name); |
39 | kfree(prop->value); | 39 | kfree(prop->value); |
@@ -55,13 +55,12 @@ static struct property *dlpar_parse_cc_property(struct cc_workarea *ccwa) | |||
55 | 55 | ||
56 | prop->length = ccwa->prop_length; | 56 | prop->length = ccwa->prop_length; |
57 | value = (char *)ccwa + ccwa->prop_offset; | 57 | value = (char *)ccwa + ccwa->prop_offset; |
58 | prop->value = kzalloc(prop->length, GFP_KERNEL); | 58 | prop->value = kmemdup(value, prop->length, GFP_KERNEL); |
59 | if (!prop->value) { | 59 | if (!prop->value) { |
60 | dlpar_free_cc_property(prop); | 60 | dlpar_free_cc_property(prop); |
61 | return NULL; | 61 | return NULL; |
62 | } | 62 | } |
63 | 63 | ||
64 | memcpy(prop->value, value, prop->length); | ||
65 | return prop; | 64 | return prop; |
66 | } | 65 | } |
67 | 66 | ||
@@ -102,7 +101,7 @@ static void dlpar_free_one_cc_node(struct device_node *dn) | |||
102 | kfree(dn); | 101 | kfree(dn); |
103 | } | 102 | } |
104 | 103 | ||
105 | static void dlpar_free_cc_nodes(struct device_node *dn) | 104 | void dlpar_free_cc_nodes(struct device_node *dn) |
106 | { | 105 | { |
107 | if (dn->child) | 106 | if (dn->child) |
108 | dlpar_free_cc_nodes(dn->child); | 107 | dlpar_free_cc_nodes(dn->child); |
diff --git a/arch/powerpc/platforms/pseries/dtl.c b/arch/powerpc/platforms/pseries/dtl.c index a00addb55945..c371bc06434b 100644 --- a/arch/powerpc/platforms/pseries/dtl.c +++ b/arch/powerpc/platforms/pseries/dtl.c | |||
@@ -23,37 +23,22 @@ | |||
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/debugfs.h> | 25 | #include <linux/debugfs.h> |
26 | #include <linux/spinlock.h> | ||
26 | #include <asm/smp.h> | 27 | #include <asm/smp.h> |
27 | #include <asm/system.h> | 28 | #include <asm/system.h> |
28 | #include <asm/uaccess.h> | 29 | #include <asm/uaccess.h> |
29 | #include <asm/firmware.h> | 30 | #include <asm/firmware.h> |
31 | #include <asm/lppaca.h> | ||
30 | 32 | ||
31 | #include "plpar_wrappers.h" | 33 | #include "plpar_wrappers.h" |
32 | 34 | ||
33 | /* | ||
34 | * Layout of entries in the hypervisor's DTL buffer. Although we don't | ||
35 | * actually access the internals of an entry (we only need to know the size), | ||
36 | * we might as well define it here for reference. | ||
37 | */ | ||
38 | struct dtl_entry { | ||
39 | u8 dispatch_reason; | ||
40 | u8 preempt_reason; | ||
41 | u16 processor_id; | ||
42 | u32 enqueue_to_dispatch_time; | ||
43 | u32 ready_to_enqueue_time; | ||
44 | u32 waiting_to_ready_time; | ||
45 | u64 timebase; | ||
46 | u64 fault_addr; | ||
47 | u64 srr0; | ||
48 | u64 srr1; | ||
49 | }; | ||
50 | |||
51 | struct dtl { | 35 | struct dtl { |
52 | struct dtl_entry *buf; | 36 | struct dtl_entry *buf; |
53 | struct dentry *file; | 37 | struct dentry *file; |
54 | int cpu; | 38 | int cpu; |
55 | int buf_entries; | 39 | int buf_entries; |
56 | u64 last_idx; | 40 | u64 last_idx; |
41 | spinlock_t lock; | ||
57 | }; | 42 | }; |
58 | static DEFINE_PER_CPU(struct dtl, cpu_dtl); | 43 | static DEFINE_PER_CPU(struct dtl, cpu_dtl); |
59 | 44 | ||
@@ -72,25 +57,97 @@ static u8 dtl_event_mask = 0x7; | |||
72 | static int dtl_buf_entries = (16 * 85); | 57 | static int dtl_buf_entries = (16 * 85); |
73 | 58 | ||
74 | 59 | ||
75 | static int dtl_enable(struct dtl *dtl) | 60 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
61 | struct dtl_ring { | ||
62 | u64 write_index; | ||
63 | struct dtl_entry *write_ptr; | ||
64 | struct dtl_entry *buf; | ||
65 | struct dtl_entry *buf_end; | ||
66 | u8 saved_dtl_mask; | ||
67 | }; | ||
68 | |||
69 | static DEFINE_PER_CPU(struct dtl_ring, dtl_rings); | ||
70 | |||
71 | static atomic_t dtl_count; | ||
72 | |||
73 | /* | ||
74 | * The cpu accounting code controls the DTL ring buffer, and we get | ||
75 | * given entries as they are processed. | ||
76 | */ | ||
77 | static void consume_dtle(struct dtl_entry *dtle, u64 index) | ||
76 | { | 78 | { |
77 | unsigned long addr; | 79 | struct dtl_ring *dtlr = &__get_cpu_var(dtl_rings); |
78 | int ret, hwcpu; | 80 | struct dtl_entry *wp = dtlr->write_ptr; |
81 | struct lppaca *vpa = local_paca->lppaca_ptr; | ||
79 | 82 | ||
80 | /* only allow one reader */ | 83 | if (!wp) |
81 | if (dtl->buf) | 84 | return; |
82 | return -EBUSY; | ||
83 | 85 | ||
84 | /* we need to store the original allocation size for use during read */ | 86 | *wp = *dtle; |
85 | dtl->buf_entries = dtl_buf_entries; | 87 | barrier(); |
86 | 88 | ||
87 | dtl->buf = kmalloc_node(dtl->buf_entries * sizeof(struct dtl_entry), | 89 | /* check for hypervisor ring buffer overflow, ignore this entry if so */ |
88 | GFP_KERNEL, cpu_to_node(dtl->cpu)); | 90 | if (index + N_DISPATCH_LOG < vpa->dtl_idx) |
89 | if (!dtl->buf) { | 91 | return; |
90 | printk(KERN_WARNING "%s: buffer alloc failed for cpu %d\n", | 92 | |
91 | __func__, dtl->cpu); | 93 | ++wp; |
92 | return -ENOMEM; | 94 | if (wp == dtlr->buf_end) |
93 | } | 95 | wp = dtlr->buf; |
96 | dtlr->write_ptr = wp; | ||
97 | |||
98 | /* incrementing write_index makes the new entry visible */ | ||
99 | smp_wmb(); | ||
100 | ++dtlr->write_index; | ||
101 | } | ||
102 | |||
103 | static int dtl_start(struct dtl *dtl) | ||
104 | { | ||
105 | struct dtl_ring *dtlr = &per_cpu(dtl_rings, dtl->cpu); | ||
106 | |||
107 | dtlr->buf = dtl->buf; | ||
108 | dtlr->buf_end = dtl->buf + dtl->buf_entries; | ||
109 | dtlr->write_index = 0; | ||
110 | |||
111 | /* setting write_ptr enables logging into our buffer */ | ||
112 | smp_wmb(); | ||
113 | dtlr->write_ptr = dtl->buf; | ||
114 | |||
115 | /* enable event logging */ | ||
116 | dtlr->saved_dtl_mask = lppaca_of(dtl->cpu).dtl_enable_mask; | ||
117 | lppaca_of(dtl->cpu).dtl_enable_mask |= dtl_event_mask; | ||
118 | |||
119 | dtl_consumer = consume_dtle; | ||
120 | atomic_inc(&dtl_count); | ||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | static void dtl_stop(struct dtl *dtl) | ||
125 | { | ||
126 | struct dtl_ring *dtlr = &per_cpu(dtl_rings, dtl->cpu); | ||
127 | |||
128 | dtlr->write_ptr = NULL; | ||
129 | smp_wmb(); | ||
130 | |||
131 | dtlr->buf = NULL; | ||
132 | |||
133 | /* restore dtl_enable_mask */ | ||
134 | lppaca_of(dtl->cpu).dtl_enable_mask = dtlr->saved_dtl_mask; | ||
135 | |||
136 | if (atomic_dec_and_test(&dtl_count)) | ||
137 | dtl_consumer = NULL; | ||
138 | } | ||
139 | |||
140 | static u64 dtl_current_index(struct dtl *dtl) | ||
141 | { | ||
142 | return per_cpu(dtl_rings, dtl->cpu).write_index; | ||
143 | } | ||
144 | |||
145 | #else /* CONFIG_VIRT_CPU_ACCOUNTING */ | ||
146 | |||
147 | static int dtl_start(struct dtl *dtl) | ||
148 | { | ||
149 | unsigned long addr; | ||
150 | int ret, hwcpu; | ||
94 | 151 | ||
95 | /* Register our dtl buffer with the hypervisor. The HV expects the | 152 | /* Register our dtl buffer with the hypervisor. The HV expects the |
96 | * buffer size to be passed in the second word of the buffer */ | 153 | * buffer size to be passed in the second word of the buffer */ |
@@ -102,34 +159,82 @@ static int dtl_enable(struct dtl *dtl) | |||
102 | if (ret) { | 159 | if (ret) { |
103 | printk(KERN_WARNING "%s: DTL registration for cpu %d (hw %d) " | 160 | printk(KERN_WARNING "%s: DTL registration for cpu %d (hw %d) " |
104 | "failed with %d\n", __func__, dtl->cpu, hwcpu, ret); | 161 | "failed with %d\n", __func__, dtl->cpu, hwcpu, ret); |
105 | kfree(dtl->buf); | ||
106 | return -EIO; | 162 | return -EIO; |
107 | } | 163 | } |
108 | 164 | ||
109 | /* set our initial buffer indices */ | 165 | /* set our initial buffer indices */ |
110 | dtl->last_idx = lppaca[dtl->cpu].dtl_idx = 0; | 166 | lppaca_of(dtl->cpu).dtl_idx = 0; |
111 | 167 | ||
112 | /* ensure that our updates to the lppaca fields have occurred before | 168 | /* ensure that our updates to the lppaca fields have occurred before |
113 | * we actually enable the logging */ | 169 | * we actually enable the logging */ |
114 | smp_wmb(); | 170 | smp_wmb(); |
115 | 171 | ||
116 | /* enable event logging */ | 172 | /* enable event logging */ |
117 | lppaca[dtl->cpu].dtl_enable_mask = dtl_event_mask; | 173 | lppaca_of(dtl->cpu).dtl_enable_mask = dtl_event_mask; |
118 | 174 | ||
119 | return 0; | 175 | return 0; |
120 | } | 176 | } |
121 | 177 | ||
122 | static void dtl_disable(struct dtl *dtl) | 178 | static void dtl_stop(struct dtl *dtl) |
123 | { | 179 | { |
124 | int hwcpu = get_hard_smp_processor_id(dtl->cpu); | 180 | int hwcpu = get_hard_smp_processor_id(dtl->cpu); |
125 | 181 | ||
126 | lppaca[dtl->cpu].dtl_enable_mask = 0x0; | 182 | lppaca_of(dtl->cpu).dtl_enable_mask = 0x0; |
127 | 183 | ||
128 | unregister_dtl(hwcpu, __pa(dtl->buf)); | 184 | unregister_dtl(hwcpu, __pa(dtl->buf)); |
185 | } | ||
186 | |||
187 | static u64 dtl_current_index(struct dtl *dtl) | ||
188 | { | ||
189 | return lppaca_of(dtl->cpu).dtl_idx; | ||
190 | } | ||
191 | #endif /* CONFIG_VIRT_CPU_ACCOUNTING */ | ||
192 | |||
193 | static int dtl_enable(struct dtl *dtl) | ||
194 | { | ||
195 | long int n_entries; | ||
196 | long int rc; | ||
197 | struct dtl_entry *buf = NULL; | ||
129 | 198 | ||
199 | /* only allow one reader */ | ||
200 | if (dtl->buf) | ||
201 | return -EBUSY; | ||
202 | |||
203 | n_entries = dtl_buf_entries; | ||
204 | buf = kmalloc_node(n_entries * sizeof(struct dtl_entry), | ||
205 | GFP_KERNEL, cpu_to_node(dtl->cpu)); | ||
206 | if (!buf) { | ||
207 | printk(KERN_WARNING "%s: buffer alloc failed for cpu %d\n", | ||
208 | __func__, dtl->cpu); | ||
209 | return -ENOMEM; | ||
210 | } | ||
211 | |||
212 | spin_lock(&dtl->lock); | ||
213 | rc = -EBUSY; | ||
214 | if (!dtl->buf) { | ||
215 | /* store the original allocation size for use during read */ | ||
216 | dtl->buf_entries = n_entries; | ||
217 | dtl->buf = buf; | ||
218 | dtl->last_idx = 0; | ||
219 | rc = dtl_start(dtl); | ||
220 | if (rc) | ||
221 | dtl->buf = NULL; | ||
222 | } | ||
223 | spin_unlock(&dtl->lock); | ||
224 | |||
225 | if (rc) | ||
226 | kfree(buf); | ||
227 | return rc; | ||
228 | } | ||
229 | |||
230 | static void dtl_disable(struct dtl *dtl) | ||
231 | { | ||
232 | spin_lock(&dtl->lock); | ||
233 | dtl_stop(dtl); | ||
130 | kfree(dtl->buf); | 234 | kfree(dtl->buf); |
131 | dtl->buf = NULL; | 235 | dtl->buf = NULL; |
132 | dtl->buf_entries = 0; | 236 | dtl->buf_entries = 0; |
237 | spin_unlock(&dtl->lock); | ||
133 | } | 238 | } |
134 | 239 | ||
135 | /* file interface */ | 240 | /* file interface */ |
@@ -157,8 +262,9 @@ static int dtl_file_release(struct inode *inode, struct file *filp) | |||
157 | static ssize_t dtl_file_read(struct file *filp, char __user *buf, size_t len, | 262 | static ssize_t dtl_file_read(struct file *filp, char __user *buf, size_t len, |
158 | loff_t *pos) | 263 | loff_t *pos) |
159 | { | 264 | { |
160 | int rc, cur_idx, last_idx, n_read, n_req, read_size; | 265 | long int rc, n_read, n_req, read_size; |
161 | struct dtl *dtl; | 266 | struct dtl *dtl; |
267 | u64 cur_idx, last_idx, i; | ||
162 | 268 | ||
163 | if ((len % sizeof(struct dtl_entry)) != 0) | 269 | if ((len % sizeof(struct dtl_entry)) != 0) |
164 | return -EINVAL; | 270 | return -EINVAL; |
@@ -171,41 +277,48 @@ static ssize_t dtl_file_read(struct file *filp, char __user *buf, size_t len, | |||
171 | /* actual number of entries read */ | 277 | /* actual number of entries read */ |
172 | n_read = 0; | 278 | n_read = 0; |
173 | 279 | ||
174 | cur_idx = lppaca[dtl->cpu].dtl_idx; | 280 | spin_lock(&dtl->lock); |
281 | |||
282 | cur_idx = dtl_current_index(dtl); | ||
175 | last_idx = dtl->last_idx; | 283 | last_idx = dtl->last_idx; |
176 | 284 | ||
177 | if (cur_idx - last_idx > dtl->buf_entries) { | 285 | if (last_idx + dtl->buf_entries <= cur_idx) |
178 | pr_debug("%s: hv buffer overflow for cpu %d, samples lost\n", | 286 | last_idx = cur_idx - dtl->buf_entries + 1; |
179 | __func__, dtl->cpu); | 287 | |
180 | } | 288 | if (last_idx + n_req > cur_idx) |
289 | n_req = cur_idx - last_idx; | ||
290 | |||
291 | if (n_req > 0) | ||
292 | dtl->last_idx = last_idx + n_req; | ||
293 | |||
294 | spin_unlock(&dtl->lock); | ||
295 | |||
296 | if (n_req <= 0) | ||
297 | return 0; | ||
181 | 298 | ||
182 | cur_idx %= dtl->buf_entries; | 299 | i = last_idx % dtl->buf_entries; |
183 | last_idx %= dtl->buf_entries; | ||
184 | 300 | ||
185 | /* read the tail of the buffer if we've wrapped */ | 301 | /* read the tail of the buffer if we've wrapped */ |
186 | if (last_idx > cur_idx) { | 302 | if (i + n_req > dtl->buf_entries) { |
187 | read_size = min(n_req, dtl->buf_entries - last_idx); | 303 | read_size = dtl->buf_entries - i; |
188 | 304 | ||
189 | rc = copy_to_user(buf, &dtl->buf[last_idx], | 305 | rc = copy_to_user(buf, &dtl->buf[i], |
190 | read_size * sizeof(struct dtl_entry)); | 306 | read_size * sizeof(struct dtl_entry)); |
191 | if (rc) | 307 | if (rc) |
192 | return -EFAULT; | 308 | return -EFAULT; |
193 | 309 | ||
194 | last_idx = 0; | 310 | i = 0; |
195 | n_req -= read_size; | 311 | n_req -= read_size; |
196 | n_read += read_size; | 312 | n_read += read_size; |
197 | buf += read_size * sizeof(struct dtl_entry); | 313 | buf += read_size * sizeof(struct dtl_entry); |
198 | } | 314 | } |
199 | 315 | ||
200 | /* .. and now the head */ | 316 | /* .. and now the head */ |
201 | read_size = min(n_req, cur_idx - last_idx); | 317 | rc = copy_to_user(buf, &dtl->buf[i], n_req * sizeof(struct dtl_entry)); |
202 | rc = copy_to_user(buf, &dtl->buf[last_idx], | ||
203 | read_size * sizeof(struct dtl_entry)); | ||
204 | if (rc) | 318 | if (rc) |
205 | return -EFAULT; | 319 | return -EFAULT; |
206 | 320 | ||
207 | n_read += read_size; | 321 | n_read += n_req; |
208 | dtl->last_idx += n_read; | ||
209 | 322 | ||
210 | return n_read * sizeof(struct dtl_entry); | 323 | return n_read * sizeof(struct dtl_entry); |
211 | } | 324 | } |
@@ -263,6 +376,7 @@ static int dtl_init(void) | |||
263 | /* set up the per-cpu log structures */ | 376 | /* set up the per-cpu log structures */ |
264 | for_each_possible_cpu(i) { | 377 | for_each_possible_cpu(i) { |
265 | struct dtl *dtl = &per_cpu(cpu_dtl, i); | 378 | struct dtl *dtl = &per_cpu(cpu_dtl, i); |
379 | spin_lock_init(&dtl->lock); | ||
266 | dtl->cpu = i; | 380 | dtl->cpu = i; |
267 | 381 | ||
268 | rc = dtl_setup_file(dtl); | 382 | rc = dtl_setup_file(dtl); |
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index cf79b46d8f88..f129040d974c 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c | |||
@@ -248,11 +248,13 @@ void vpa_init(int cpu) | |||
248 | int hwcpu = get_hard_smp_processor_id(cpu); | 248 | int hwcpu = get_hard_smp_processor_id(cpu); |
249 | unsigned long addr; | 249 | unsigned long addr; |
250 | long ret; | 250 | long ret; |
251 | struct paca_struct *pp; | ||
252 | struct dtl_entry *dtl; | ||
251 | 253 | ||
252 | if (cpu_has_feature(CPU_FTR_ALTIVEC)) | 254 | if (cpu_has_feature(CPU_FTR_ALTIVEC)) |
253 | lppaca[cpu].vmxregs_in_use = 1; | 255 | lppaca_of(cpu).vmxregs_in_use = 1; |
254 | 256 | ||
255 | addr = __pa(&lppaca[cpu]); | 257 | addr = __pa(&lppaca_of(cpu)); |
256 | ret = register_vpa(hwcpu, addr); | 258 | ret = register_vpa(hwcpu, addr); |
257 | 259 | ||
258 | if (ret) { | 260 | if (ret) { |
@@ -274,6 +276,25 @@ void vpa_init(int cpu) | |||
274 | "registration for cpu %d (hw %d) of area %lx " | 276 | "registration for cpu %d (hw %d) of area %lx " |
275 | "returns %ld\n", cpu, hwcpu, addr, ret); | 277 | "returns %ld\n", cpu, hwcpu, addr, ret); |
276 | } | 278 | } |
279 | |||
280 | /* | ||
281 | * Register dispatch trace log, if one has been allocated. | ||
282 | */ | ||
283 | pp = &paca[cpu]; | ||
284 | dtl = pp->dispatch_log; | ||
285 | if (dtl) { | ||
286 | pp->dtl_ridx = 0; | ||
287 | pp->dtl_curr = dtl; | ||
288 | lppaca_of(cpu).dtl_idx = 0; | ||
289 | |||
290 | /* hypervisor reads buffer length from this field */ | ||
291 | dtl->enqueue_to_dispatch_time = DISPATCH_LOG_BYTES; | ||
292 | ret = register_dtl(hwcpu, __pa(dtl)); | ||
293 | if (ret) | ||
294 | pr_warn("DTL registration failed for cpu %d (%ld)\n", | ||
295 | cpu, ret); | ||
296 | lppaca_of(cpu).dtl_enable_mask = 2; | ||
297 | } | ||
277 | } | 298 | } |
278 | 299 | ||
279 | static long pSeries_lpar_hpte_insert(unsigned long hpte_group, | 300 | static long pSeries_lpar_hpte_insert(unsigned long hpte_group, |
diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c new file mode 100644 index 000000000000..3e7f651e50ac --- /dev/null +++ b/arch/powerpc/platforms/pseries/mobility.c | |||
@@ -0,0 +1,362 @@ | |||
1 | /* | ||
2 | * Support for Partition Mobility/Migration | ||
3 | * | ||
4 | * Copyright (C) 2010 Nathan Fontenot | ||
5 | * Copyright (C) 2010 IBM Corporation | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License version | ||
9 | * 2 as published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/kobject.h> | ||
14 | #include <linux/smp.h> | ||
15 | #include <linux/completion.h> | ||
16 | #include <linux/device.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/slab.h> | ||
19 | |||
20 | #include <asm/rtas.h> | ||
21 | #include "pseries.h" | ||
22 | |||
23 | static struct kobject *mobility_kobj; | ||
24 | |||
25 | struct update_props_workarea { | ||
26 | u32 phandle; | ||
27 | u32 state; | ||
28 | u64 reserved; | ||
29 | u32 nprops; | ||
30 | }; | ||
31 | |||
32 | #define NODE_ACTION_MASK 0xff000000 | ||
33 | #define NODE_COUNT_MASK 0x00ffffff | ||
34 | |||
35 | #define DELETE_DT_NODE 0x01000000 | ||
36 | #define UPDATE_DT_NODE 0x02000000 | ||
37 | #define ADD_DT_NODE 0x03000000 | ||
38 | |||
39 | static int mobility_rtas_call(int token, char *buf) | ||
40 | { | ||
41 | int rc; | ||
42 | |||
43 | spin_lock(&rtas_data_buf_lock); | ||
44 | |||
45 | memcpy(rtas_data_buf, buf, RTAS_DATA_BUF_SIZE); | ||
46 | rc = rtas_call(token, 2, 1, NULL, rtas_data_buf, 1); | ||
47 | memcpy(buf, rtas_data_buf, RTAS_DATA_BUF_SIZE); | ||
48 | |||
49 | spin_unlock(&rtas_data_buf_lock); | ||
50 | return rc; | ||
51 | } | ||
52 | |||
53 | static int delete_dt_node(u32 phandle) | ||
54 | { | ||
55 | struct device_node *dn; | ||
56 | |||
57 | dn = of_find_node_by_phandle(phandle); | ||
58 | if (!dn) | ||
59 | return -ENOENT; | ||
60 | |||
61 | dlpar_detach_node(dn); | ||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | static int update_dt_property(struct device_node *dn, struct property **prop, | ||
66 | const char *name, u32 vd, char *value) | ||
67 | { | ||
68 | struct property *new_prop = *prop; | ||
69 | struct property *old_prop; | ||
70 | int more = 0; | ||
71 | |||
72 | /* A negative 'vd' value indicates that only part of the new property | ||
73 | * value is contained in the buffer and we need to call | ||
74 | * ibm,update-properties again to get the rest of the value. | ||
75 | * | ||
76 | * A negative value is also the two's compliment of the actual value. | ||
77 | */ | ||
78 | if (vd & 0x80000000) { | ||
79 | vd = ~vd + 1; | ||
80 | more = 1; | ||
81 | } | ||
82 | |||
83 | if (new_prop) { | ||
84 | /* partial property fixup */ | ||
85 | char *new_data = kzalloc(new_prop->length + vd, GFP_KERNEL); | ||
86 | if (!new_data) | ||
87 | return -ENOMEM; | ||
88 | |||
89 | memcpy(new_data, new_prop->value, new_prop->length); | ||
90 | memcpy(new_data + new_prop->length, value, vd); | ||
91 | |||
92 | kfree(new_prop->value); | ||
93 | new_prop->value = new_data; | ||
94 | new_prop->length += vd; | ||
95 | } else { | ||
96 | new_prop = kzalloc(sizeof(*new_prop), GFP_KERNEL); | ||
97 | if (!new_prop) | ||
98 | return -ENOMEM; | ||
99 | |||
100 | new_prop->name = kstrdup(name, GFP_KERNEL); | ||
101 | if (!new_prop->name) { | ||
102 | kfree(new_prop); | ||
103 | return -ENOMEM; | ||
104 | } | ||
105 | |||
106 | new_prop->length = vd; | ||
107 | new_prop->value = kzalloc(new_prop->length, GFP_KERNEL); | ||
108 | if (!new_prop->value) { | ||
109 | kfree(new_prop->name); | ||
110 | kfree(new_prop); | ||
111 | return -ENOMEM; | ||
112 | } | ||
113 | |||
114 | memcpy(new_prop->value, value, vd); | ||
115 | *prop = new_prop; | ||
116 | } | ||
117 | |||
118 | if (!more) { | ||
119 | old_prop = of_find_property(dn, new_prop->name, NULL); | ||
120 | if (old_prop) | ||
121 | prom_update_property(dn, new_prop, old_prop); | ||
122 | else | ||
123 | prom_add_property(dn, new_prop); | ||
124 | |||
125 | new_prop = NULL; | ||
126 | } | ||
127 | |||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | static int update_dt_node(u32 phandle) | ||
132 | { | ||
133 | struct update_props_workarea *upwa; | ||
134 | struct device_node *dn; | ||
135 | struct property *prop = NULL; | ||
136 | int i, rc; | ||
137 | char *prop_data; | ||
138 | char *rtas_buf; | ||
139 | int update_properties_token; | ||
140 | |||
141 | update_properties_token = rtas_token("ibm,update-properties"); | ||
142 | if (update_properties_token == RTAS_UNKNOWN_SERVICE) | ||
143 | return -EINVAL; | ||
144 | |||
145 | rtas_buf = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL); | ||
146 | if (!rtas_buf) | ||
147 | return -ENOMEM; | ||
148 | |||
149 | dn = of_find_node_by_phandle(phandle); | ||
150 | if (!dn) { | ||
151 | kfree(rtas_buf); | ||
152 | return -ENOENT; | ||
153 | } | ||
154 | |||
155 | upwa = (struct update_props_workarea *)&rtas_buf[0]; | ||
156 | upwa->phandle = phandle; | ||
157 | |||
158 | do { | ||
159 | rc = mobility_rtas_call(update_properties_token, rtas_buf); | ||
160 | if (rc < 0) | ||
161 | break; | ||
162 | |||
163 | prop_data = rtas_buf + sizeof(*upwa); | ||
164 | |||
165 | for (i = 0; i < upwa->nprops; i++) { | ||
166 | char *prop_name; | ||
167 | u32 vd; | ||
168 | |||
169 | prop_name = prop_data + 1; | ||
170 | prop_data += strlen(prop_name) + 1; | ||
171 | vd = *prop_data++; | ||
172 | |||
173 | switch (vd) { | ||
174 | case 0x00000000: | ||
175 | /* name only property, nothing to do */ | ||
176 | break; | ||
177 | |||
178 | case 0x80000000: | ||
179 | prop = of_find_property(dn, prop_name, NULL); | ||
180 | prom_remove_property(dn, prop); | ||
181 | prop = NULL; | ||
182 | break; | ||
183 | |||
184 | default: | ||
185 | rc = update_dt_property(dn, &prop, prop_name, | ||
186 | vd, prop_data); | ||
187 | if (rc) { | ||
188 | printk(KERN_ERR "Could not update %s" | ||
189 | " property\n", prop_name); | ||
190 | } | ||
191 | |||
192 | prop_data += vd; | ||
193 | } | ||
194 | } | ||
195 | } while (rc == 1); | ||
196 | |||
197 | of_node_put(dn); | ||
198 | kfree(rtas_buf); | ||
199 | return 0; | ||
200 | } | ||
201 | |||
202 | static int add_dt_node(u32 parent_phandle, u32 drc_index) | ||
203 | { | ||
204 | struct device_node *dn; | ||
205 | struct device_node *parent_dn; | ||
206 | int rc; | ||
207 | |||
208 | dn = dlpar_configure_connector(drc_index); | ||
209 | if (!dn) | ||
210 | return -ENOENT; | ||
211 | |||
212 | parent_dn = of_find_node_by_phandle(parent_phandle); | ||
213 | if (!parent_dn) { | ||
214 | dlpar_free_cc_nodes(dn); | ||
215 | return -ENOENT; | ||
216 | } | ||
217 | |||
218 | dn->parent = parent_dn; | ||
219 | rc = dlpar_attach_node(dn); | ||
220 | if (rc) | ||
221 | dlpar_free_cc_nodes(dn); | ||
222 | |||
223 | of_node_put(parent_dn); | ||
224 | return rc; | ||
225 | } | ||
226 | |||
227 | static int pseries_devicetree_update(void) | ||
228 | { | ||
229 | char *rtas_buf; | ||
230 | u32 *data; | ||
231 | int update_nodes_token; | ||
232 | int rc; | ||
233 | |||
234 | update_nodes_token = rtas_token("ibm,update-nodes"); | ||
235 | if (update_nodes_token == RTAS_UNKNOWN_SERVICE) | ||
236 | return -EINVAL; | ||
237 | |||
238 | rtas_buf = kzalloc(RTAS_DATA_BUF_SIZE, GFP_KERNEL); | ||
239 | if (!rtas_buf) | ||
240 | return -ENOMEM; | ||
241 | |||
242 | do { | ||
243 | rc = mobility_rtas_call(update_nodes_token, rtas_buf); | ||
244 | if (rc && rc != 1) | ||
245 | break; | ||
246 | |||
247 | data = (u32 *)rtas_buf + 4; | ||
248 | while (*data & NODE_ACTION_MASK) { | ||
249 | int i; | ||
250 | u32 action = *data & NODE_ACTION_MASK; | ||
251 | int node_count = *data & NODE_COUNT_MASK; | ||
252 | |||
253 | data++; | ||
254 | |||
255 | for (i = 0; i < node_count; i++) { | ||
256 | u32 phandle = *data++; | ||
257 | u32 drc_index; | ||
258 | |||
259 | switch (action) { | ||
260 | case DELETE_DT_NODE: | ||
261 | delete_dt_node(phandle); | ||
262 | break; | ||
263 | case UPDATE_DT_NODE: | ||
264 | update_dt_node(phandle); | ||
265 | break; | ||
266 | case ADD_DT_NODE: | ||
267 | drc_index = *data++; | ||
268 | add_dt_node(phandle, drc_index); | ||
269 | break; | ||
270 | } | ||
271 | } | ||
272 | } | ||
273 | } while (rc == 1); | ||
274 | |||
275 | kfree(rtas_buf); | ||
276 | return rc; | ||
277 | } | ||
278 | |||
279 | void post_mobility_fixup(void) | ||
280 | { | ||
281 | int rc; | ||
282 | int activate_fw_token; | ||
283 | |||
284 | rc = pseries_devicetree_update(); | ||
285 | if (rc) { | ||
286 | printk(KERN_ERR "Initial post-mobility device tree update " | ||
287 | "failed: %d\n", rc); | ||
288 | return; | ||
289 | } | ||
290 | |||
291 | activate_fw_token = rtas_token("ibm,activate-firmware"); | ||
292 | if (activate_fw_token == RTAS_UNKNOWN_SERVICE) { | ||
293 | printk(KERN_ERR "Could not make post-mobility " | ||
294 | "activate-fw call.\n"); | ||
295 | return; | ||
296 | } | ||
297 | |||
298 | rc = rtas_call(activate_fw_token, 0, 1, NULL); | ||
299 | if (!rc) { | ||
300 | rc = pseries_devicetree_update(); | ||
301 | if (rc) | ||
302 | printk(KERN_ERR "Secondary post-mobility device tree " | ||
303 | "update failed: %d\n", rc); | ||
304 | } else { | ||
305 | printk(KERN_ERR "Post-mobility activate-fw failed: %d\n", rc); | ||
306 | return; | ||
307 | } | ||
308 | |||
309 | return; | ||
310 | } | ||
311 | |||
312 | static ssize_t migrate_store(struct class *class, struct class_attribute *attr, | ||
313 | const char *buf, size_t count) | ||
314 | { | ||
315 | struct rtas_args args; | ||
316 | u64 streamid; | ||
317 | int rc; | ||
318 | |||
319 | rc = strict_strtoull(buf, 0, &streamid); | ||
320 | if (rc) | ||
321 | return rc; | ||
322 | |||
323 | memset(&args, 0, sizeof(args)); | ||
324 | args.token = rtas_token("ibm,suspend-me"); | ||
325 | args.nargs = 2; | ||
326 | args.nret = 1; | ||
327 | |||
328 | args.args[0] = streamid >> 32 ; | ||
329 | args.args[1] = streamid & 0xffffffff; | ||
330 | args.rets = &args.args[args.nargs]; | ||
331 | |||
332 | do { | ||
333 | args.rets[0] = 0; | ||
334 | rc = rtas_ibm_suspend_me(&args); | ||
335 | if (!rc && args.rets[0] == RTAS_NOT_SUSPENDABLE) | ||
336 | ssleep(1); | ||
337 | } while (!rc && args.rets[0] == RTAS_NOT_SUSPENDABLE); | ||
338 | |||
339 | if (rc) | ||
340 | return rc; | ||
341 | else if (args.rets[0]) | ||
342 | return args.rets[0]; | ||
343 | |||
344 | post_mobility_fixup(); | ||
345 | return count; | ||
346 | } | ||
347 | |||
348 | static CLASS_ATTR(migration, S_IWUSR, NULL, migrate_store); | ||
349 | |||
350 | static int __init mobility_sysfs_init(void) | ||
351 | { | ||
352 | int rc; | ||
353 | |||
354 | mobility_kobj = kobject_create_and_add("mobility", kernel_kobj); | ||
355 | if (!mobility_kobj) | ||
356 | return -ENOMEM; | ||
357 | |||
358 | rc = sysfs_create_file(mobility_kobj, &class_attr_migration.attr); | ||
359 | |||
360 | return rc; | ||
361 | } | ||
362 | device_initcall(mobility_sysfs_init); | ||
diff --git a/arch/powerpc/platforms/pseries/pseries.h b/arch/powerpc/platforms/pseries/pseries.h index 40c93cad91d2..e9f6d2859c3c 100644 --- a/arch/powerpc/platforms/pseries/pseries.h +++ b/arch/powerpc/platforms/pseries/pseries.h | |||
@@ -17,6 +17,8 @@ struct device_node; | |||
17 | extern void request_event_sources_irqs(struct device_node *np, | 17 | extern void request_event_sources_irqs(struct device_node *np, |
18 | irq_handler_t handler, const char *name); | 18 | irq_handler_t handler, const char *name); |
19 | 19 | ||
20 | #include <linux/of.h> | ||
21 | |||
20 | extern void __init fw_feature_init(const char *hypertas, unsigned long len); | 22 | extern void __init fw_feature_init(const char *hypertas, unsigned long len); |
21 | 23 | ||
22 | struct pt_regs; | 24 | struct pt_regs; |
@@ -47,4 +49,11 @@ extern unsigned long rtas_poweron_auto; | |||
47 | 49 | ||
48 | extern void find_udbg_vterm(void); | 50 | extern void find_udbg_vterm(void); |
49 | 51 | ||
52 | /* Dynamic logical Partitioning/Mobility */ | ||
53 | extern void dlpar_free_cc_nodes(struct device_node *); | ||
54 | extern void dlpar_free_cc_property(struct property *); | ||
55 | extern struct device_node *dlpar_configure_connector(u32); | ||
56 | extern int dlpar_attach_node(struct device_node *); | ||
57 | extern int dlpar_detach_node(struct device_node *); | ||
58 | |||
50 | #endif /* _PSERIES_PSERIES_H */ | 59 | #endif /* _PSERIES_PSERIES_H */ |
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index 57ddbb43b33a..1de2cbb92303 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c | |||
@@ -539,7 +539,8 @@ out: | |||
539 | } | 539 | } |
540 | 540 | ||
541 | static const struct file_operations ofdt_fops = { | 541 | static const struct file_operations ofdt_fops = { |
542 | .write = ofdt_write | 542 | .write = ofdt_write, |
543 | .llseek = noop_llseek, | ||
543 | }; | 544 | }; |
544 | 545 | ||
545 | /* create /proc/powerpc/ofdt write-only by root */ | 546 | /* create /proc/powerpc/ofdt write-only by root */ |
diff --git a/arch/powerpc/platforms/pseries/scanlog.c b/arch/powerpc/platforms/pseries/scanlog.c index 80e9e7652a4d..554457294a2b 100644 --- a/arch/powerpc/platforms/pseries/scanlog.c +++ b/arch/powerpc/platforms/pseries/scanlog.c | |||
@@ -170,6 +170,7 @@ const struct file_operations scanlog_fops = { | |||
170 | .write = scanlog_write, | 170 | .write = scanlog_write, |
171 | .open = scanlog_open, | 171 | .open = scanlog_open, |
172 | .release = scanlog_release, | 172 | .release = scanlog_release, |
173 | .llseek = noop_llseek, | ||
173 | }; | 174 | }; |
174 | 175 | ||
175 | static int __init scanlog_init(void) | 176 | static int __init scanlog_init(void) |
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index a6d19e3a505e..d345bfd56bbe 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
@@ -273,6 +273,58 @@ static struct notifier_block pci_dn_reconfig_nb = { | |||
273 | .notifier_call = pci_dn_reconfig_notifier, | 273 | .notifier_call = pci_dn_reconfig_notifier, |
274 | }; | 274 | }; |
275 | 275 | ||
276 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
277 | /* | ||
278 | * Allocate space for the dispatch trace log for all possible cpus | ||
279 | * and register the buffers with the hypervisor. This is used for | ||
280 | * computing time stolen by the hypervisor. | ||
281 | */ | ||
282 | static int alloc_dispatch_logs(void) | ||
283 | { | ||
284 | int cpu, ret; | ||
285 | struct paca_struct *pp; | ||
286 | struct dtl_entry *dtl; | ||
287 | |||
288 | if (!firmware_has_feature(FW_FEATURE_SPLPAR)) | ||
289 | return 0; | ||
290 | |||
291 | for_each_possible_cpu(cpu) { | ||
292 | pp = &paca[cpu]; | ||
293 | dtl = kmalloc_node(DISPATCH_LOG_BYTES, GFP_KERNEL, | ||
294 | cpu_to_node(cpu)); | ||
295 | if (!dtl) { | ||
296 | pr_warn("Failed to allocate dispatch trace log for cpu %d\n", | ||
297 | cpu); | ||
298 | pr_warn("Stolen time statistics will be unreliable\n"); | ||
299 | break; | ||
300 | } | ||
301 | |||
302 | pp->dtl_ridx = 0; | ||
303 | pp->dispatch_log = dtl; | ||
304 | pp->dispatch_log_end = dtl + N_DISPATCH_LOG; | ||
305 | pp->dtl_curr = dtl; | ||
306 | } | ||
307 | |||
308 | /* Register the DTL for the current (boot) cpu */ | ||
309 | dtl = get_paca()->dispatch_log; | ||
310 | get_paca()->dtl_ridx = 0; | ||
311 | get_paca()->dtl_curr = dtl; | ||
312 | get_paca()->lppaca_ptr->dtl_idx = 0; | ||
313 | |||
314 | /* hypervisor reads buffer length from this field */ | ||
315 | dtl->enqueue_to_dispatch_time = DISPATCH_LOG_BYTES; | ||
316 | ret = register_dtl(hard_smp_processor_id(), __pa(dtl)); | ||
317 | if (ret) | ||
318 | pr_warn("DTL registration failed for boot cpu %d (%d)\n", | ||
319 | smp_processor_id(), ret); | ||
320 | get_paca()->lppaca_ptr->dtl_enable_mask = 2; | ||
321 | |||
322 | return 0; | ||
323 | } | ||
324 | |||
325 | early_initcall(alloc_dispatch_logs); | ||
326 | #endif /* CONFIG_VIRT_CPU_ACCOUNTING */ | ||
327 | |||
276 | static void __init pSeries_setup_arch(void) | 328 | static void __init pSeries_setup_arch(void) |
277 | { | 329 | { |
278 | /* Discover PIC type and setup ppc_md accordingly */ | 330 | /* Discover PIC type and setup ppc_md accordingly */ |
diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c index 93834b0d8272..7b96e5a270ce 100644 --- a/arch/powerpc/platforms/pseries/xics.c +++ b/arch/powerpc/platforms/pseries/xics.c | |||
@@ -178,7 +178,7 @@ static int get_irq_server(unsigned int virq, const struct cpumask *cpumask, | |||
178 | if (!distribute_irqs) | 178 | if (!distribute_irqs) |
179 | return default_server; | 179 | return default_server; |
180 | 180 | ||
181 | if (!cpumask_equal(cpumask, cpu_all_mask)) { | 181 | if (!cpumask_subset(cpu_possible_mask, cpumask)) { |
182 | int server = cpumask_first_and(cpu_online_mask, cpumask); | 182 | int server = cpumask_first_and(cpu_online_mask, cpumask); |
183 | 183 | ||
184 | if (server < nr_cpu_ids) | 184 | if (server < nr_cpu_ids) |
@@ -243,7 +243,7 @@ static unsigned int xics_startup(unsigned int virq) | |||
243 | * at that level, so we do it here by hand. | 243 | * at that level, so we do it here by hand. |
244 | */ | 244 | */ |
245 | if (irq_to_desc(virq)->msi_desc) | 245 | if (irq_to_desc(virq)->msi_desc) |
246 | unmask_msi_irq(virq); | 246 | unmask_msi_irq(irq_get_irq_data(virq)); |
247 | 247 | ||
248 | /* unmask it */ | 248 | /* unmask it */ |
249 | xics_unmask_irq(virq); | 249 | xics_unmask_irq(virq); |
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index 5642924fb9fb..0bef9dacb64e 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile | |||
@@ -1,8 +1,6 @@ | |||
1 | subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror | 1 | subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror |
2 | 2 | ||
3 | ifeq ($(CONFIG_PPC64),y) | 3 | ccflags-$(CONFIG_PPC64) := -mno-minimal-toc |
4 | EXTRA_CFLAGS += -mno-minimal-toc | ||
5 | endif | ||
6 | 4 | ||
7 | mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_u3msi.o mpic_pasemi_msi.o | 5 | mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_u3msi.o mpic_pasemi_msi.o |
8 | obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y) | 6 | obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y) |
@@ -20,6 +18,7 @@ obj-$(CONFIG_FSL_PMC) += fsl_pmc.o | |||
20 | obj-$(CONFIG_FSL_LBC) += fsl_lbc.o | 18 | obj-$(CONFIG_FSL_LBC) += fsl_lbc.o |
21 | obj-$(CONFIG_FSL_GTM) += fsl_gtm.o | 19 | obj-$(CONFIG_FSL_GTM) += fsl_gtm.o |
22 | obj-$(CONFIG_MPC8xxx_GPIO) += mpc8xxx_gpio.o | 20 | obj-$(CONFIG_MPC8xxx_GPIO) += mpc8xxx_gpio.o |
21 | obj-$(CONFIG_FSL_85XX_CACHE_SRAM) += fsl_85xx_l2ctlr.o fsl_85xx_cache_sram.o | ||
23 | obj-$(CONFIG_SIMPLE_GPIO) += simple_gpio.o | 22 | obj-$(CONFIG_SIMPLE_GPIO) += simple_gpio.o |
24 | obj-$(CONFIG_RAPIDIO) += fsl_rio.o | 23 | obj-$(CONFIG_RAPIDIO) += fsl_rio.o |
25 | obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o | 24 | obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o |
diff --git a/arch/powerpc/sysdev/dart_iommu.c b/arch/powerpc/sysdev/dart_iommu.c index 559db2b846a9..17cf15ec38be 100644 --- a/arch/powerpc/sysdev/dart_iommu.c +++ b/arch/powerpc/sysdev/dart_iommu.c | |||
@@ -70,6 +70,8 @@ static int iommu_table_dart_inited; | |||
70 | static int dart_dirty; | 70 | static int dart_dirty; |
71 | static int dart_is_u4; | 71 | static int dart_is_u4; |
72 | 72 | ||
73 | #define DART_U4_BYPASS_BASE 0x8000000000ull | ||
74 | |||
73 | #define DBG(...) | 75 | #define DBG(...) |
74 | 76 | ||
75 | static inline void dart_tlb_invalidate_all(void) | 77 | static inline void dart_tlb_invalidate_all(void) |
@@ -292,12 +294,20 @@ static void iommu_table_dart_setup(void) | |||
292 | set_bit(iommu_table_dart.it_size - 1, iommu_table_dart.it_map); | 294 | set_bit(iommu_table_dart.it_size - 1, iommu_table_dart.it_map); |
293 | } | 295 | } |
294 | 296 | ||
295 | static void pci_dma_dev_setup_dart(struct pci_dev *dev) | 297 | static void dma_dev_setup_dart(struct device *dev) |
296 | { | 298 | { |
297 | /* We only have one iommu table on the mac for now, which makes | 299 | /* We only have one iommu table on the mac for now, which makes |
298 | * things simple. Setup all PCI devices to point to this table | 300 | * things simple. Setup all PCI devices to point to this table |
299 | */ | 301 | */ |
300 | set_iommu_table_base(&dev->dev, &iommu_table_dart); | 302 | if (get_dma_ops(dev) == &dma_direct_ops) |
303 | set_dma_offset(dev, DART_U4_BYPASS_BASE); | ||
304 | else | ||
305 | set_iommu_table_base(dev, &iommu_table_dart); | ||
306 | } | ||
307 | |||
308 | static void pci_dma_dev_setup_dart(struct pci_dev *dev) | ||
309 | { | ||
310 | dma_dev_setup_dart(&dev->dev); | ||
301 | } | 311 | } |
302 | 312 | ||
303 | static void pci_dma_bus_setup_dart(struct pci_bus *bus) | 313 | static void pci_dma_bus_setup_dart(struct pci_bus *bus) |
@@ -315,6 +325,45 @@ static void pci_dma_bus_setup_dart(struct pci_bus *bus) | |||
315 | PCI_DN(dn)->iommu_table = &iommu_table_dart; | 325 | PCI_DN(dn)->iommu_table = &iommu_table_dart; |
316 | } | 326 | } |
317 | 327 | ||
328 | static bool dart_device_on_pcie(struct device *dev) | ||
329 | { | ||
330 | struct device_node *np = of_node_get(dev->of_node); | ||
331 | |||
332 | while(np) { | ||
333 | if (of_device_is_compatible(np, "U4-pcie") || | ||
334 | of_device_is_compatible(np, "u4-pcie")) { | ||
335 | of_node_put(np); | ||
336 | return true; | ||
337 | } | ||
338 | np = of_get_next_parent(np); | ||
339 | } | ||
340 | return false; | ||
341 | } | ||
342 | |||
343 | static int dart_dma_set_mask(struct device *dev, u64 dma_mask) | ||
344 | { | ||
345 | if (!dev->dma_mask || !dma_supported(dev, dma_mask)) | ||
346 | return -EIO; | ||
347 | |||
348 | /* U4 supports a DART bypass, we use it for 64-bit capable | ||
349 | * devices to improve performances. However, that only works | ||
350 | * for devices connected to U4 own PCIe interface, not bridged | ||
351 | * through hypertransport. We need the device to support at | ||
352 | * least 40 bits of addresses. | ||
353 | */ | ||
354 | if (dart_device_on_pcie(dev) && dma_mask >= DMA_BIT_MASK(40)) { | ||
355 | dev_info(dev, "Using 64-bit DMA iommu bypass\n"); | ||
356 | set_dma_ops(dev, &dma_direct_ops); | ||
357 | } else { | ||
358 | dev_info(dev, "Using 32-bit DMA via iommu\n"); | ||
359 | set_dma_ops(dev, &dma_iommu_ops); | ||
360 | } | ||
361 | dma_dev_setup_dart(dev); | ||
362 | |||
363 | *dev->dma_mask = dma_mask; | ||
364 | return 0; | ||
365 | } | ||
366 | |||
318 | void __init iommu_init_early_dart(void) | 367 | void __init iommu_init_early_dart(void) |
319 | { | 368 | { |
320 | struct device_node *dn; | 369 | struct device_node *dn; |
@@ -328,20 +377,25 @@ void __init iommu_init_early_dart(void) | |||
328 | dart_is_u4 = 1; | 377 | dart_is_u4 = 1; |
329 | } | 378 | } |
330 | 379 | ||
380 | /* Initialize the DART HW */ | ||
381 | if (dart_init(dn) != 0) | ||
382 | goto bail; | ||
383 | |||
331 | /* Setup low level TCE operations for the core IOMMU code */ | 384 | /* Setup low level TCE operations for the core IOMMU code */ |
332 | ppc_md.tce_build = dart_build; | 385 | ppc_md.tce_build = dart_build; |
333 | ppc_md.tce_free = dart_free; | 386 | ppc_md.tce_free = dart_free; |
334 | ppc_md.tce_flush = dart_flush; | 387 | ppc_md.tce_flush = dart_flush; |
335 | 388 | ||
336 | /* Initialize the DART HW */ | 389 | /* Setup bypass if supported */ |
337 | if (dart_init(dn) == 0) { | 390 | if (dart_is_u4) |
338 | ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_dart; | 391 | ppc_md.dma_set_mask = dart_dma_set_mask; |
339 | ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_dart; | ||
340 | 392 | ||
341 | /* Setup pci_dma ops */ | 393 | ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_dart; |
342 | set_pci_dma_ops(&dma_iommu_ops); | 394 | ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_dart; |
343 | return; | 395 | |
344 | } | 396 | /* Setup pci_dma ops */ |
397 | set_pci_dma_ops(&dma_iommu_ops); | ||
398 | return; | ||
345 | 399 | ||
346 | bail: | 400 | bail: |
347 | /* If init failed, use direct iommu and null setup functions */ | 401 | /* If init failed, use direct iommu and null setup functions */ |
diff --git a/arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h b/arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h new file mode 100644 index 000000000000..60c9c0bd5ba2 --- /dev/null +++ b/arch/powerpc/sysdev/fsl_85xx_cache_ctlr.h | |||
@@ -0,0 +1,101 @@ | |||
1 | /* | ||
2 | * Copyright 2009-2010 Freescale Semiconductor, Inc | ||
3 | * | ||
4 | * QorIQ based Cache Controller Memory Mapped Registers | ||
5 | * | ||
6 | * Author: Vivek Mahajan <vivek.mahajan@freescale.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #ifndef __FSL_85XX_CACHE_CTLR_H__ | ||
24 | #define __FSL_85XX_CACHE_CTLR_H__ | ||
25 | |||
26 | #define L2CR_L2FI 0x40000000 /* L2 flash invalidate */ | ||
27 | #define L2CR_L2IO 0x00200000 /* L2 instruction only */ | ||
28 | #define L2CR_SRAM_ZERO 0x00000000 /* L2SRAM zero size */ | ||
29 | #define L2CR_SRAM_FULL 0x00010000 /* L2SRAM full size */ | ||
30 | #define L2CR_SRAM_HALF 0x00020000 /* L2SRAM half size */ | ||
31 | #define L2CR_SRAM_TWO_HALFS 0x00030000 /* L2SRAM two half sizes */ | ||
32 | #define L2CR_SRAM_QUART 0x00040000 /* L2SRAM one quarter size */ | ||
33 | #define L2CR_SRAM_TWO_QUARTS 0x00050000 /* L2SRAM two quarter size */ | ||
34 | #define L2CR_SRAM_EIGHTH 0x00060000 /* L2SRAM one eighth size */ | ||
35 | #define L2CR_SRAM_TWO_EIGHTH 0x00070000 /* L2SRAM two eighth size */ | ||
36 | |||
37 | #define L2SRAM_OPTIMAL_SZ_SHIFT 0x00000003 /* Optimum size for L2SRAM */ | ||
38 | |||
39 | #define L2SRAM_BAR_MSK_LO18 0xFFFFC000 /* Lower 18 bits */ | ||
40 | #define L2SRAM_BARE_MSK_HI4 0x0000000F /* Upper 4 bits */ | ||
41 | |||
42 | enum cache_sram_lock_ways { | ||
43 | LOCK_WAYS_ZERO, | ||
44 | LOCK_WAYS_EIGHTH, | ||
45 | LOCK_WAYS_TWO_EIGHTH, | ||
46 | LOCK_WAYS_HALF = 4, | ||
47 | LOCK_WAYS_FULL = 8, | ||
48 | }; | ||
49 | |||
50 | struct mpc85xx_l2ctlr { | ||
51 | u32 ctl; /* 0x000 - L2 control */ | ||
52 | u8 res1[0xC]; | ||
53 | u32 ewar0; /* 0x010 - External write address 0 */ | ||
54 | u32 ewarea0; /* 0x014 - External write address extended 0 */ | ||
55 | u32 ewcr0; /* 0x018 - External write ctrl */ | ||
56 | u8 res2[4]; | ||
57 | u32 ewar1; /* 0x020 - External write address 1 */ | ||
58 | u32 ewarea1; /* 0x024 - External write address extended 1 */ | ||
59 | u32 ewcr1; /* 0x028 - External write ctrl 1 */ | ||
60 | u8 res3[4]; | ||
61 | u32 ewar2; /* 0x030 - External write address 2 */ | ||
62 | u32 ewarea2; /* 0x034 - External write address extended 2 */ | ||
63 | u32 ewcr2; /* 0x038 - External write ctrl 2 */ | ||
64 | u8 res4[4]; | ||
65 | u32 ewar3; /* 0x040 - External write address 3 */ | ||
66 | u32 ewarea3; /* 0x044 - External write address extended 3 */ | ||
67 | u32 ewcr3; /* 0x048 - External write ctrl 3 */ | ||
68 | u8 res5[0xB4]; | ||
69 | u32 srbar0; /* 0x100 - SRAM base address 0 */ | ||
70 | u32 srbarea0; /* 0x104 - SRAM base addr reg ext address 0 */ | ||
71 | u32 srbar1; /* 0x108 - SRAM base address 1 */ | ||
72 | u32 srbarea1; /* 0x10C - SRAM base addr reg ext address 1 */ | ||
73 | u8 res6[0xCF0]; | ||
74 | u32 errinjhi; /* 0xE00 - Error injection mask high */ | ||
75 | u32 errinjlo; /* 0xE04 - Error injection mask low */ | ||
76 | u32 errinjctl; /* 0xE08 - Error injection tag/ecc control */ | ||
77 | u8 res7[0x14]; | ||
78 | u32 captdatahi; /* 0xE20 - Error data high capture */ | ||
79 | u32 captdatalo; /* 0xE24 - Error data low capture */ | ||
80 | u32 captecc; /* 0xE28 - Error syndrome */ | ||
81 | u8 res8[0x14]; | ||
82 | u32 errdet; /* 0xE40 - Error detect */ | ||
83 | u32 errdis; /* 0xE44 - Error disable */ | ||
84 | u32 errinten; /* 0xE48 - Error interrupt enable */ | ||
85 | u32 errattr; /* 0xE4c - Error attribute capture */ | ||
86 | u32 erradrrl; /* 0xE50 - Error address capture low */ | ||
87 | u32 erradrrh; /* 0xE54 - Error address capture high */ | ||
88 | u32 errctl; /* 0xE58 - Error control */ | ||
89 | u8 res9[0x1A4]; | ||
90 | }; | ||
91 | |||
92 | struct sram_parameters { | ||
93 | unsigned int sram_size; | ||
94 | uint64_t sram_offset; | ||
95 | }; | ||
96 | |||
97 | extern int instantiate_cache_sram(struct platform_device *dev, | ||
98 | struct sram_parameters sram_params); | ||
99 | extern void remove_cache_sram(struct platform_device *dev); | ||
100 | |||
101 | #endif /* __FSL_85XX_CACHE_CTLR_H__ */ | ||
diff --git a/arch/powerpc/sysdev/fsl_85xx_cache_sram.c b/arch/powerpc/sysdev/fsl_85xx_cache_sram.c new file mode 100644 index 000000000000..54fb1922fe30 --- /dev/null +++ b/arch/powerpc/sysdev/fsl_85xx_cache_sram.c | |||
@@ -0,0 +1,159 @@ | |||
1 | /* | ||
2 | * Copyright 2009-2010 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * Simple memory allocator abstraction for QorIQ (P1/P2) based Cache-SRAM | ||
5 | * | ||
6 | * Author: Vivek Mahajan <vivek.mahajan@freescale.com> | ||
7 | * | ||
8 | * This file is derived from the original work done | ||
9 | * by Sylvain Munaut for the Bestcomm SRAM allocator. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the | ||
13 | * Free Software Foundation; either version 2 of the License, or (at your | ||
14 | * option) any later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
19 | * GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with this program; if not, write to the Free Software | ||
23 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
24 | */ | ||
25 | |||
26 | #include <linux/kernel.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <linux/err.h> | ||
29 | #include <linux/of_platform.h> | ||
30 | #include <asm/pgtable.h> | ||
31 | #include <asm/fsl_85xx_cache_sram.h> | ||
32 | |||
33 | #include "fsl_85xx_cache_ctlr.h" | ||
34 | |||
35 | struct mpc85xx_cache_sram *cache_sram; | ||
36 | |||
37 | void *mpc85xx_cache_sram_alloc(unsigned int size, | ||
38 | phys_addr_t *phys, unsigned int align) | ||
39 | { | ||
40 | unsigned long offset; | ||
41 | unsigned long flags; | ||
42 | |||
43 | if (unlikely(cache_sram == NULL)) | ||
44 | return NULL; | ||
45 | |||
46 | if (!size || (size > cache_sram->size) || (align > cache_sram->size)) { | ||
47 | pr_err("%s(): size(=%x) or align(=%x) zero or too big\n", | ||
48 | __func__, size, align); | ||
49 | return NULL; | ||
50 | } | ||
51 | |||
52 | if ((align & (align - 1)) || align <= 1) { | ||
53 | pr_err("%s(): align(=%x) must be power of two and >1\n", | ||
54 | __func__, align); | ||
55 | return NULL; | ||
56 | } | ||
57 | |||
58 | spin_lock_irqsave(&cache_sram->lock, flags); | ||
59 | offset = rh_alloc_align(cache_sram->rh, size, align, NULL); | ||
60 | spin_unlock_irqrestore(&cache_sram->lock, flags); | ||
61 | |||
62 | if (IS_ERR_VALUE(offset)) | ||
63 | return NULL; | ||
64 | |||
65 | *phys = cache_sram->base_phys + offset; | ||
66 | |||
67 | return (unsigned char *)cache_sram->base_virt + offset; | ||
68 | } | ||
69 | EXPORT_SYMBOL(mpc85xx_cache_sram_alloc); | ||
70 | |||
71 | void mpc85xx_cache_sram_free(void *ptr) | ||
72 | { | ||
73 | unsigned long flags; | ||
74 | BUG_ON(!ptr); | ||
75 | |||
76 | spin_lock_irqsave(&cache_sram->lock, flags); | ||
77 | rh_free(cache_sram->rh, ptr - cache_sram->base_virt); | ||
78 | spin_unlock_irqrestore(&cache_sram->lock, flags); | ||
79 | } | ||
80 | EXPORT_SYMBOL(mpc85xx_cache_sram_free); | ||
81 | |||
82 | int __init instantiate_cache_sram(struct platform_device *dev, | ||
83 | struct sram_parameters sram_params) | ||
84 | { | ||
85 | int ret = 0; | ||
86 | |||
87 | if (cache_sram) { | ||
88 | dev_err(&dev->dev, "Already initialized cache-sram\n"); | ||
89 | return -EBUSY; | ||
90 | } | ||
91 | |||
92 | cache_sram = kzalloc(sizeof(struct mpc85xx_cache_sram), GFP_KERNEL); | ||
93 | if (!cache_sram) { | ||
94 | dev_err(&dev->dev, "Out of memory for cache_sram structure\n"); | ||
95 | return -ENOMEM; | ||
96 | } | ||
97 | |||
98 | cache_sram->base_phys = sram_params.sram_offset; | ||
99 | cache_sram->size = sram_params.sram_size; | ||
100 | |||
101 | if (!request_mem_region(cache_sram->base_phys, cache_sram->size, | ||
102 | "fsl_85xx_cache_sram")) { | ||
103 | dev_err(&dev->dev, "%s: request memory failed\n", | ||
104 | dev->dev.of_node->full_name); | ||
105 | ret = -ENXIO; | ||
106 | goto out_free; | ||
107 | } | ||
108 | |||
109 | cache_sram->base_virt = ioremap_flags(cache_sram->base_phys, | ||
110 | cache_sram->size, _PAGE_COHERENT | PAGE_KERNEL); | ||
111 | if (!cache_sram->base_virt) { | ||
112 | dev_err(&dev->dev, "%s: ioremap_flags failed\n", | ||
113 | dev->dev.of_node->full_name); | ||
114 | ret = -ENOMEM; | ||
115 | goto out_release; | ||
116 | } | ||
117 | |||
118 | cache_sram->rh = rh_create(sizeof(unsigned int)); | ||
119 | if (IS_ERR(cache_sram->rh)) { | ||
120 | dev_err(&dev->dev, "%s: Unable to create remote heap\n", | ||
121 | dev->dev.of_node->full_name); | ||
122 | ret = PTR_ERR(cache_sram->rh); | ||
123 | goto out_unmap; | ||
124 | } | ||
125 | |||
126 | rh_attach_region(cache_sram->rh, 0, cache_sram->size); | ||
127 | spin_lock_init(&cache_sram->lock); | ||
128 | |||
129 | dev_info(&dev->dev, "[base:0x%llx, size:0x%x] configured and loaded\n", | ||
130 | (unsigned long long)cache_sram->base_phys, cache_sram->size); | ||
131 | |||
132 | return 0; | ||
133 | |||
134 | out_unmap: | ||
135 | iounmap(cache_sram->base_virt); | ||
136 | |||
137 | out_release: | ||
138 | release_mem_region(cache_sram->base_phys, cache_sram->size); | ||
139 | |||
140 | out_free: | ||
141 | kfree(cache_sram); | ||
142 | return ret; | ||
143 | } | ||
144 | |||
145 | void remove_cache_sram(struct platform_device *dev) | ||
146 | { | ||
147 | BUG_ON(!cache_sram); | ||
148 | |||
149 | rh_detach_region(cache_sram->rh, 0, cache_sram->size); | ||
150 | rh_destroy(cache_sram->rh); | ||
151 | |||
152 | iounmap(cache_sram->base_virt); | ||
153 | release_mem_region(cache_sram->base_phys, cache_sram->size); | ||
154 | |||
155 | kfree(cache_sram); | ||
156 | cache_sram = NULL; | ||
157 | |||
158 | dev_info(&dev->dev, "MPC85xx Cache-SRAM driver unloaded\n"); | ||
159 | } | ||
diff --git a/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c b/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c new file mode 100644 index 000000000000..cc8d6556d799 --- /dev/null +++ b/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c | |||
@@ -0,0 +1,231 @@ | |||
1 | /* | ||
2 | * Copyright 2009-2010 Freescale Semiconductor, Inc. | ||
3 | * | ||
4 | * QorIQ (P1/P2) L2 controller init for Cache-SRAM instantiation | ||
5 | * | ||
6 | * Author: Vivek Mahajan <vivek.mahajan@freescale.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | * | ||
13 | * This program is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | * GNU General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU General Public License | ||
19 | * along with this program; if not, write to the Free Software | ||
20 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
21 | */ | ||
22 | |||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/of_platform.h> | ||
25 | #include <asm/io.h> | ||
26 | |||
27 | #include "fsl_85xx_cache_ctlr.h" | ||
28 | |||
29 | static char *sram_size; | ||
30 | static char *sram_offset; | ||
31 | struct mpc85xx_l2ctlr __iomem *l2ctlr; | ||
32 | |||
33 | static long get_cache_sram_size(void) | ||
34 | { | ||
35 | unsigned long val; | ||
36 | |||
37 | if (!sram_size || (strict_strtoul(sram_size, 0, &val) < 0)) | ||
38 | return -EINVAL; | ||
39 | |||
40 | return val; | ||
41 | } | ||
42 | |||
43 | static long get_cache_sram_offset(void) | ||
44 | { | ||
45 | unsigned long val; | ||
46 | |||
47 | if (!sram_offset || (strict_strtoul(sram_offset, 0, &val) < 0)) | ||
48 | return -EINVAL; | ||
49 | |||
50 | return val; | ||
51 | } | ||
52 | |||
53 | static int __init get_size_from_cmdline(char *str) | ||
54 | { | ||
55 | if (!str) | ||
56 | return 0; | ||
57 | |||
58 | sram_size = str; | ||
59 | return 1; | ||
60 | } | ||
61 | |||
62 | static int __init get_offset_from_cmdline(char *str) | ||
63 | { | ||
64 | if (!str) | ||
65 | return 0; | ||
66 | |||
67 | sram_offset = str; | ||
68 | return 1; | ||
69 | } | ||
70 | |||
71 | __setup("cache-sram-size=", get_size_from_cmdline); | ||
72 | __setup("cache-sram-offset=", get_offset_from_cmdline); | ||
73 | |||
74 | static int __devinit mpc85xx_l2ctlr_of_probe(struct platform_device *dev, | ||
75 | const struct of_device_id *match) | ||
76 | { | ||
77 | long rval; | ||
78 | unsigned int rem; | ||
79 | unsigned char ways; | ||
80 | const unsigned int *prop; | ||
81 | unsigned int l2cache_size; | ||
82 | struct sram_parameters sram_params; | ||
83 | |||
84 | if (!dev->dev.of_node) { | ||
85 | dev_err(&dev->dev, "Device's OF-node is NULL\n"); | ||
86 | return -EINVAL; | ||
87 | } | ||
88 | |||
89 | prop = of_get_property(dev->dev.of_node, "cache-size", NULL); | ||
90 | if (!prop) { | ||
91 | dev_err(&dev->dev, "Missing L2 cache-size\n"); | ||
92 | return -EINVAL; | ||
93 | } | ||
94 | l2cache_size = *prop; | ||
95 | |||
96 | sram_params.sram_size = get_cache_sram_size(); | ||
97 | if (sram_params.sram_size <= 0) { | ||
98 | dev_err(&dev->dev, | ||
99 | "Entire L2 as cache, Aborting Cache-SRAM stuff\n"); | ||
100 | return -EINVAL; | ||
101 | } | ||
102 | |||
103 | sram_params.sram_offset = get_cache_sram_offset(); | ||
104 | if (sram_params.sram_offset <= 0) { | ||
105 | dev_err(&dev->dev, | ||
106 | "Entire L2 as cache, provide a valid sram offset\n"); | ||
107 | return -EINVAL; | ||
108 | } | ||
109 | |||
110 | |||
111 | rem = l2cache_size % sram_params.sram_size; | ||
112 | ways = LOCK_WAYS_FULL * sram_params.sram_size / l2cache_size; | ||
113 | if (rem || (ways & (ways - 1))) { | ||
114 | dev_err(&dev->dev, "Illegal cache-sram-size in command line\n"); | ||
115 | return -EINVAL; | ||
116 | } | ||
117 | |||
118 | l2ctlr = of_iomap(dev->dev.of_node, 0); | ||
119 | if (!l2ctlr) { | ||
120 | dev_err(&dev->dev, "Can't map L2 controller\n"); | ||
121 | return -EINVAL; | ||
122 | } | ||
123 | |||
124 | /* | ||
125 | * Write bits[0-17] to srbar0 | ||
126 | */ | ||
127 | out_be32(&l2ctlr->srbar0, | ||
128 | sram_params.sram_offset & L2SRAM_BAR_MSK_LO18); | ||
129 | |||
130 | /* | ||
131 | * Write bits[18-21] to srbare0 | ||
132 | */ | ||
133 | #ifdef CONFIG_PHYS_64BIT | ||
134 | out_be32(&l2ctlr->srbarea0, | ||
135 | (sram_params.sram_offset >> 32) & L2SRAM_BARE_MSK_HI4); | ||
136 | #endif | ||
137 | |||
138 | clrsetbits_be32(&l2ctlr->ctl, L2CR_L2E, L2CR_L2FI); | ||
139 | |||
140 | switch (ways) { | ||
141 | case LOCK_WAYS_EIGHTH: | ||
142 | setbits32(&l2ctlr->ctl, | ||
143 | L2CR_L2E | L2CR_L2FI | L2CR_SRAM_EIGHTH); | ||
144 | break; | ||
145 | |||
146 | case LOCK_WAYS_TWO_EIGHTH: | ||
147 | setbits32(&l2ctlr->ctl, | ||
148 | L2CR_L2E | L2CR_L2FI | L2CR_SRAM_QUART); | ||
149 | break; | ||
150 | |||
151 | case LOCK_WAYS_HALF: | ||
152 | setbits32(&l2ctlr->ctl, | ||
153 | L2CR_L2E | L2CR_L2FI | L2CR_SRAM_HALF); | ||
154 | break; | ||
155 | |||
156 | case LOCK_WAYS_FULL: | ||
157 | default: | ||
158 | setbits32(&l2ctlr->ctl, | ||
159 | L2CR_L2E | L2CR_L2FI | L2CR_SRAM_FULL); | ||
160 | break; | ||
161 | } | ||
162 | eieio(); | ||
163 | |||
164 | rval = instantiate_cache_sram(dev, sram_params); | ||
165 | if (rval < 0) { | ||
166 | dev_err(&dev->dev, "Can't instantiate Cache-SRAM\n"); | ||
167 | iounmap(l2ctlr); | ||
168 | return -EINVAL; | ||
169 | } | ||
170 | |||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | static int __devexit mpc85xx_l2ctlr_of_remove(struct platform_device *dev) | ||
175 | { | ||
176 | BUG_ON(!l2ctlr); | ||
177 | |||
178 | iounmap(l2ctlr); | ||
179 | remove_cache_sram(dev); | ||
180 | dev_info(&dev->dev, "MPC85xx L2 controller unloaded\n"); | ||
181 | |||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | static struct of_device_id mpc85xx_l2ctlr_of_match[] = { | ||
186 | { | ||
187 | .compatible = "fsl,p2020-l2-cache-controller", | ||
188 | }, | ||
189 | { | ||
190 | .compatible = "fsl,p2010-l2-cache-controller", | ||
191 | }, | ||
192 | { | ||
193 | .compatible = "fsl,p1020-l2-cache-controller", | ||
194 | }, | ||
195 | { | ||
196 | .compatible = "fsl,p1011-l2-cache-controller", | ||
197 | }, | ||
198 | { | ||
199 | .compatible = "fsl,p1013-l2-cache-controller", | ||
200 | }, | ||
201 | { | ||
202 | .compatible = "fsl,p1022-l2-cache-controller", | ||
203 | }, | ||
204 | {}, | ||
205 | }; | ||
206 | |||
207 | static struct of_platform_driver mpc85xx_l2ctlr_of_platform_driver = { | ||
208 | .driver = { | ||
209 | .name = "fsl-l2ctlr", | ||
210 | .owner = THIS_MODULE, | ||
211 | .of_match_table = mpc85xx_l2ctlr_of_match, | ||
212 | }, | ||
213 | .probe = mpc85xx_l2ctlr_of_probe, | ||
214 | .remove = __devexit_p(mpc85xx_l2ctlr_of_remove), | ||
215 | }; | ||
216 | |||
217 | static __init int mpc85xx_l2ctlr_of_init(void) | ||
218 | { | ||
219 | return of_register_platform_driver(&mpc85xx_l2ctlr_of_platform_driver); | ||
220 | } | ||
221 | |||
222 | static void __exit mpc85xx_l2ctlr_of_exit(void) | ||
223 | { | ||
224 | of_unregister_platform_driver(&mpc85xx_l2ctlr_of_platform_driver); | ||
225 | } | ||
226 | |||
227 | subsys_initcall(mpc85xx_l2ctlr_of_init); | ||
228 | module_exit(mpc85xx_l2ctlr_of_exit); | ||
229 | |||
230 | MODULE_DESCRIPTION("Freescale MPC85xx L2 controller init"); | ||
231 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/arch/powerpc/sysdev/fsl_msi.c b/arch/powerpc/sysdev/fsl_msi.c index 87991d3abbab..108d76fa8f1c 100644 --- a/arch/powerpc/sysdev/fsl_msi.c +++ b/arch/powerpc/sysdev/fsl_msi.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <asm/ppc-pci.h> | 24 | #include <asm/ppc-pci.h> |
25 | #include <asm/mpic.h> | 25 | #include <asm/mpic.h> |
26 | #include "fsl_msi.h" | 26 | #include "fsl_msi.h" |
27 | #include "fsl_pci.h" | ||
27 | 28 | ||
28 | LIST_HEAD(msi_head); | 29 | LIST_HEAD(msi_head); |
29 | 30 | ||
@@ -51,8 +52,8 @@ static void fsl_msi_end_irq(unsigned int virq) | |||
51 | } | 52 | } |
52 | 53 | ||
53 | static struct irq_chip fsl_msi_chip = { | 54 | static struct irq_chip fsl_msi_chip = { |
54 | .mask = mask_msi_irq, | 55 | .irq_mask = mask_msi_irq, |
55 | .unmask = unmask_msi_irq, | 56 | .irq_unmask = unmask_msi_irq, |
56 | .ack = fsl_msi_end_irq, | 57 | .ack = fsl_msi_end_irq, |
57 | .name = "FSL-MSI", | 58 | .name = "FSL-MSI", |
58 | }; | 59 | }; |
@@ -125,13 +126,11 @@ static void fsl_compose_msi_msg(struct pci_dev *pdev, int hwirq, | |||
125 | { | 126 | { |
126 | struct fsl_msi *msi_data = fsl_msi_data; | 127 | struct fsl_msi *msi_data = fsl_msi_data; |
127 | struct pci_controller *hose = pci_bus_to_host(pdev->bus); | 128 | struct pci_controller *hose = pci_bus_to_host(pdev->bus); |
128 | u32 base = 0; | 129 | u64 base = fsl_pci_immrbar_base(hose); |
129 | 130 | ||
130 | pci_bus_read_config_dword(hose->bus, | 131 | msg->address_lo = msi_data->msi_addr_lo + lower_32_bits(base); |
131 | PCI_DEVFN(0, 0), PCI_BASE_ADDRESS_0, &base); | 132 | msg->address_hi = msi_data->msi_addr_hi + upper_32_bits(base); |
132 | 133 | ||
133 | msg->address_lo = msi_data->msi_addr_lo + base; | ||
134 | msg->address_hi = msi_data->msi_addr_hi; | ||
135 | msg->data = hwirq; | 134 | msg->data = hwirq; |
136 | 135 | ||
137 | pr_debug("%s: allocated srs: %d, ibs: %d\n", | 136 | pr_debug("%s: allocated srs: %d, ibs: %d\n", |
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 4ae933225251..818f7c6c8fa1 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * MPC83xx/85xx/86xx PCI/PCIE support routing. | 2 | * MPC83xx/85xx/86xx PCI/PCIE support routing. |
3 | * | 3 | * |
4 | * Copyright 2007-2009 Freescale Semiconductor, Inc. | 4 | * Copyright 2007-2010 Freescale Semiconductor, Inc. |
5 | * Copyright 2008-2009 MontaVista Software, Inc. | 5 | * Copyright 2008-2009 MontaVista Software, Inc. |
6 | * | 6 | * |
7 | * Initial author: Xianghua Xiao <x.xiao@freescale.com> | 7 | * Initial author: Xianghua Xiao <x.xiao@freescale.com> |
@@ -34,7 +34,7 @@ | |||
34 | #include <sysdev/fsl_soc.h> | 34 | #include <sysdev/fsl_soc.h> |
35 | #include <sysdev/fsl_pci.h> | 35 | #include <sysdev/fsl_pci.h> |
36 | 36 | ||
37 | static int fsl_pcie_bus_fixup; | 37 | static int fsl_pcie_bus_fixup, is_mpc83xx_pci; |
38 | 38 | ||
39 | static void __init quirk_fsl_pcie_header(struct pci_dev *dev) | 39 | static void __init quirk_fsl_pcie_header(struct pci_dev *dev) |
40 | { | 40 | { |
@@ -407,10 +407,18 @@ DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2010E, quirk_fsl_pcie_header); | |||
407 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2010, quirk_fsl_pcie_header); | 407 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2010, quirk_fsl_pcie_header); |
408 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2020E, quirk_fsl_pcie_header); | 408 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2020E, quirk_fsl_pcie_header); |
409 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2020, quirk_fsl_pcie_header); | 409 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2020, quirk_fsl_pcie_header); |
410 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2040E, quirk_fsl_pcie_header); | ||
411 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P2040, quirk_fsl_pcie_header); | ||
412 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P3041E, quirk_fsl_pcie_header); | ||
413 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P3041, quirk_fsl_pcie_header); | ||
410 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4040E, quirk_fsl_pcie_header); | 414 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4040E, quirk_fsl_pcie_header); |
411 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4040, quirk_fsl_pcie_header); | 415 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4040, quirk_fsl_pcie_header); |
412 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4080E, quirk_fsl_pcie_header); | 416 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4080E, quirk_fsl_pcie_header); |
413 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4080, quirk_fsl_pcie_header); | 417 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P4080, quirk_fsl_pcie_header); |
418 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P5010E, quirk_fsl_pcie_header); | ||
419 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P5010, quirk_fsl_pcie_header); | ||
420 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P5020E, quirk_fsl_pcie_header); | ||
421 | DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_P5020, quirk_fsl_pcie_header); | ||
414 | #endif /* CONFIG_FSL_SOC_BOOKE || CONFIG_PPC_86xx */ | 422 | #endif /* CONFIG_FSL_SOC_BOOKE || CONFIG_PPC_86xx */ |
415 | 423 | ||
416 | #if defined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_MPC512x) | 424 | #if defined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_MPC512x) |
@@ -430,6 +438,13 @@ struct mpc83xx_pcie_priv { | |||
430 | u32 dev_base; | 438 | u32 dev_base; |
431 | }; | 439 | }; |
432 | 440 | ||
441 | struct pex_inbound_window { | ||
442 | u32 ar; | ||
443 | u32 tar; | ||
444 | u32 barl; | ||
445 | u32 barh; | ||
446 | }; | ||
447 | |||
433 | /* | 448 | /* |
434 | * With the convention of u-boot, the PCIE outbound window 0 serves | 449 | * With the convention of u-boot, the PCIE outbound window 0 serves |
435 | * as configuration transactions outbound. | 450 | * as configuration transactions outbound. |
@@ -437,6 +452,8 @@ struct mpc83xx_pcie_priv { | |||
437 | #define PEX_OUTWIN0_BAR 0xCA4 | 452 | #define PEX_OUTWIN0_BAR 0xCA4 |
438 | #define PEX_OUTWIN0_TAL 0xCA8 | 453 | #define PEX_OUTWIN0_TAL 0xCA8 |
439 | #define PEX_OUTWIN0_TAH 0xCAC | 454 | #define PEX_OUTWIN0_TAH 0xCAC |
455 | #define PEX_RC_INWIN_BASE 0xE60 | ||
456 | #define PEX_RCIWARn_EN 0x1 | ||
440 | 457 | ||
441 | static int mpc83xx_pcie_exclude_device(struct pci_bus *bus, unsigned int devfn) | 458 | static int mpc83xx_pcie_exclude_device(struct pci_bus *bus, unsigned int devfn) |
442 | { | 459 | { |
@@ -604,6 +621,8 @@ int __init mpc83xx_add_bridge(struct device_node *dev) | |||
604 | const int *bus_range; | 621 | const int *bus_range; |
605 | int primary; | 622 | int primary; |
606 | 623 | ||
624 | is_mpc83xx_pci = 1; | ||
625 | |||
607 | if (!of_device_is_available(dev)) { | 626 | if (!of_device_is_available(dev)) { |
608 | pr_warning("%s: disabled by the firmware.\n", | 627 | pr_warning("%s: disabled by the firmware.\n", |
609 | dev->full_name); | 628 | dev->full_name); |
@@ -683,3 +702,40 @@ err0: | |||
683 | return ret; | 702 | return ret; |
684 | } | 703 | } |
685 | #endif /* CONFIG_PPC_83xx */ | 704 | #endif /* CONFIG_PPC_83xx */ |
705 | |||
706 | u64 fsl_pci_immrbar_base(struct pci_controller *hose) | ||
707 | { | ||
708 | #ifdef CONFIG_PPC_83xx | ||
709 | if (is_mpc83xx_pci) { | ||
710 | struct mpc83xx_pcie_priv *pcie = hose->dn->data; | ||
711 | struct pex_inbound_window *in; | ||
712 | int i; | ||
713 | |||
714 | /* Walk the Root Complex Inbound windows to match IMMR base */ | ||
715 | in = pcie->cfg_type0 + PEX_RC_INWIN_BASE; | ||
716 | for (i = 0; i < 4; i++) { | ||
717 | /* not enabled, skip */ | ||
718 | if (!in_le32(&in[i].ar) & PEX_RCIWARn_EN) | ||
719 | continue; | ||
720 | |||
721 | if (get_immrbase() == in_le32(&in[i].tar)) | ||
722 | return (u64)in_le32(&in[i].barh) << 32 | | ||
723 | in_le32(&in[i].barl); | ||
724 | } | ||
725 | |||
726 | printk(KERN_WARNING "could not find PCI BAR matching IMMR\n"); | ||
727 | } | ||
728 | #endif | ||
729 | |||
730 | #if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx) | ||
731 | if (!is_mpc83xx_pci) { | ||
732 | u32 base; | ||
733 | |||
734 | pci_bus_read_config_dword(hose->bus, | ||
735 | PCI_DEVFN(0, 0), PCI_BASE_ADDRESS_0, &base); | ||
736 | return base; | ||
737 | } | ||
738 | #endif | ||
739 | |||
740 | return 0; | ||
741 | } | ||
diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h index a9d8bbebed80..8ad72a11f77b 100644 --- a/arch/powerpc/sysdev/fsl_pci.h +++ b/arch/powerpc/sysdev/fsl_pci.h | |||
@@ -88,6 +88,7 @@ struct ccsr_pci { | |||
88 | extern int fsl_add_bridge(struct device_node *dev, int is_primary); | 88 | extern int fsl_add_bridge(struct device_node *dev, int is_primary); |
89 | extern void fsl_pcibios_fixup_bus(struct pci_bus *bus); | 89 | extern void fsl_pcibios_fixup_bus(struct pci_bus *bus); |
90 | extern int mpc83xx_add_bridge(struct device_node *dev); | 90 | extern int mpc83xx_add_bridge(struct device_node *dev); |
91 | u64 fsl_pci_immrbar_base(struct pci_controller *hose); | ||
91 | 92 | ||
92 | #endif /* __POWERPC_FSL_PCI_H */ | 93 | #endif /* __POWERPC_FSL_PCI_H */ |
93 | #endif /* __KERNEL__ */ | 94 | #endif /* __KERNEL__ */ |
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index 3017532319c8..412763672d23 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c | |||
@@ -117,44 +117,59 @@ struct rio_atmu_regs { | |||
117 | }; | 117 | }; |
118 | 118 | ||
119 | struct rio_msg_regs { | 119 | struct rio_msg_regs { |
120 | u32 omr; | 120 | u32 omr; /* 0xD_3000 - Outbound message 0 mode register */ |
121 | u32 osr; | 121 | u32 osr; /* 0xD_3004 - Outbound message 0 status register */ |
122 | u32 pad1; | 122 | u32 pad1; |
123 | u32 odqdpar; | 123 | u32 odqdpar; /* 0xD_300C - Outbound message 0 descriptor queue |
124 | dequeue pointer address register */ | ||
124 | u32 pad2; | 125 | u32 pad2; |
125 | u32 osar; | 126 | u32 osar; /* 0xD_3014 - Outbound message 0 source address |
126 | u32 odpr; | 127 | register */ |
127 | u32 odatr; | 128 | u32 odpr; /* 0xD_3018 - Outbound message 0 destination port |
128 | u32 odcr; | 129 | register */ |
130 | u32 odatr; /* 0xD_301C - Outbound message 0 destination attributes | ||
131 | Register*/ | ||
132 | u32 odcr; /* 0xD_3020 - Outbound message 0 double-word count | ||
133 | register */ | ||
129 | u32 pad3; | 134 | u32 pad3; |
130 | u32 odqepar; | 135 | u32 odqepar; /* 0xD_3028 - Outbound message 0 descriptor queue |
136 | enqueue pointer address register */ | ||
131 | u32 pad4[13]; | 137 | u32 pad4[13]; |
132 | u32 imr; | 138 | u32 imr; /* 0xD_3060 - Inbound message 0 mode register */ |
133 | u32 isr; | 139 | u32 isr; /* 0xD_3064 - Inbound message 0 status register */ |
134 | u32 pad5; | 140 | u32 pad5; |
135 | u32 ifqdpar; | 141 | u32 ifqdpar; /* 0xD_306C - Inbound message 0 frame queue dequeue |
142 | pointer address register*/ | ||
136 | u32 pad6; | 143 | u32 pad6; |
137 | u32 ifqepar; | 144 | u32 ifqepar; /* 0xD_3074 - Inbound message 0 frame queue enqueue |
145 | pointer address register */ | ||
138 | u32 pad7[226]; | 146 | u32 pad7[226]; |
139 | u32 odmr; | 147 | u32 odmr; /* 0xD_3400 - Outbound doorbell mode register */ |
140 | u32 odsr; | 148 | u32 odsr; /* 0xD_3404 - Outbound doorbell status register */ |
141 | u32 res0[4]; | 149 | u32 res0[4]; |
142 | u32 oddpr; | 150 | u32 oddpr; /* 0xD_3418 - Outbound doorbell destination port |
143 | u32 oddatr; | 151 | register */ |
152 | u32 oddatr; /* 0xD_341c - Outbound doorbell destination attributes | ||
153 | register */ | ||
144 | u32 res1[3]; | 154 | u32 res1[3]; |
145 | u32 odretcr; | 155 | u32 odretcr; /* 0xD_342C - Outbound doorbell retry error threshold |
156 | configuration register */ | ||
146 | u32 res2[12]; | 157 | u32 res2[12]; |
147 | u32 dmr; | 158 | u32 dmr; /* 0xD_3460 - Inbound doorbell mode register */ |
148 | u32 dsr; | 159 | u32 dsr; /* 0xD_3464 - Inbound doorbell status register */ |
149 | u32 pad8; | 160 | u32 pad8; |
150 | u32 dqdpar; | 161 | u32 dqdpar; /* 0xD_346C - Inbound doorbell queue dequeue Pointer |
162 | address register */ | ||
151 | u32 pad9; | 163 | u32 pad9; |
152 | u32 dqepar; | 164 | u32 dqepar; /* 0xD_3474 - Inbound doorbell Queue enqueue pointer |
165 | address register */ | ||
153 | u32 pad10[26]; | 166 | u32 pad10[26]; |
154 | u32 pwmr; | 167 | u32 pwmr; /* 0xD_34E0 - Inbound port-write mode register */ |
155 | u32 pwsr; | 168 | u32 pwsr; /* 0xD_34E4 - Inbound port-write status register */ |
156 | u32 epwqbar; | 169 | u32 epwqbar; /* 0xD_34E8 - Extended Port-Write Queue Base Address |
157 | u32 pwqbar; | 170 | register */ |
171 | u32 pwqbar; /* 0xD_34EC - Inbound port-write queue base address | ||
172 | register */ | ||
158 | }; | 173 | }; |
159 | 174 | ||
160 | struct rio_tx_desc { | 175 | struct rio_tx_desc { |
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c index b91f7acdda6f..19e5015e039b 100644 --- a/arch/powerpc/sysdev/fsl_soc.c +++ b/arch/powerpc/sysdev/fsl_soc.c | |||
@@ -209,186 +209,29 @@ static int __init of_add_fixed_phys(void) | |||
209 | arch_initcall(of_add_fixed_phys); | 209 | arch_initcall(of_add_fixed_phys); |
210 | #endif /* CONFIG_FIXED_PHY */ | 210 | #endif /* CONFIG_FIXED_PHY */ |
211 | 211 | ||
212 | static enum fsl_usb2_phy_modes determine_usb_phy(const char *phy_type) | 212 | #if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx) |
213 | { | 213 | static __be32 __iomem *rstcr; |
214 | if (!phy_type) | ||
215 | return FSL_USB2_PHY_NONE; | ||
216 | if (!strcasecmp(phy_type, "ulpi")) | ||
217 | return FSL_USB2_PHY_ULPI; | ||
218 | if (!strcasecmp(phy_type, "utmi")) | ||
219 | return FSL_USB2_PHY_UTMI; | ||
220 | if (!strcasecmp(phy_type, "utmi_wide")) | ||
221 | return FSL_USB2_PHY_UTMI_WIDE; | ||
222 | if (!strcasecmp(phy_type, "serial")) | ||
223 | return FSL_USB2_PHY_SERIAL; | ||
224 | |||
225 | return FSL_USB2_PHY_NONE; | ||
226 | } | ||
227 | 214 | ||
228 | static int __init fsl_usb_of_init(void) | 215 | static int __init setup_rstcr(void) |
229 | { | 216 | { |
230 | struct device_node *np; | 217 | struct device_node *np; |
231 | unsigned int i = 0; | ||
232 | struct platform_device *usb_dev_mph = NULL, *usb_dev_dr_host = NULL, | ||
233 | *usb_dev_dr_client = NULL; | ||
234 | int ret; | ||
235 | |||
236 | for_each_compatible_node(np, NULL, "fsl-usb2-mph") { | ||
237 | struct resource r[2]; | ||
238 | struct fsl_usb2_platform_data usb_data; | ||
239 | const unsigned char *prop = NULL; | ||
240 | |||
241 | memset(&r, 0, sizeof(r)); | ||
242 | memset(&usb_data, 0, sizeof(usb_data)); | ||
243 | |||
244 | ret = of_address_to_resource(np, 0, &r[0]); | ||
245 | if (ret) | ||
246 | goto err; | ||
247 | |||
248 | of_irq_to_resource(np, 0, &r[1]); | ||
249 | |||
250 | usb_dev_mph = | ||
251 | platform_device_register_simple("fsl-ehci", i, r, 2); | ||
252 | if (IS_ERR(usb_dev_mph)) { | ||
253 | ret = PTR_ERR(usb_dev_mph); | ||
254 | goto err; | ||
255 | } | ||
256 | |||
257 | usb_dev_mph->dev.coherent_dma_mask = 0xffffffffUL; | ||
258 | usb_dev_mph->dev.dma_mask = &usb_dev_mph->dev.coherent_dma_mask; | ||
259 | |||
260 | usb_data.operating_mode = FSL_USB2_MPH_HOST; | ||
261 | |||
262 | prop = of_get_property(np, "port0", NULL); | ||
263 | if (prop) | ||
264 | usb_data.port_enables |= FSL_USB2_PORT0_ENABLED; | ||
265 | |||
266 | prop = of_get_property(np, "port1", NULL); | ||
267 | if (prop) | ||
268 | usb_data.port_enables |= FSL_USB2_PORT1_ENABLED; | ||
269 | |||
270 | prop = of_get_property(np, "phy_type", NULL); | ||
271 | usb_data.phy_mode = determine_usb_phy(prop); | ||
272 | |||
273 | ret = | ||
274 | platform_device_add_data(usb_dev_mph, &usb_data, | ||
275 | sizeof(struct | ||
276 | fsl_usb2_platform_data)); | ||
277 | if (ret) | ||
278 | goto unreg_mph; | ||
279 | i++; | ||
280 | } | ||
281 | |||
282 | for_each_compatible_node(np, NULL, "fsl-usb2-dr") { | ||
283 | struct resource r[2]; | ||
284 | struct fsl_usb2_platform_data usb_data; | ||
285 | const unsigned char *prop = NULL; | ||
286 | 218 | ||
287 | if (!of_device_is_available(np)) | 219 | for_each_node_by_name(np, "global-utilities") { |
288 | continue; | 220 | if ((of_get_property(np, "fsl,has-rstcr", NULL))) { |
289 | 221 | rstcr = of_iomap(np, 0) + 0xb0; | |
290 | memset(&r, 0, sizeof(r)); | 222 | if (!rstcr) |
291 | memset(&usb_data, 0, sizeof(usb_data)); | 223 | printk (KERN_ERR "Error: reset control " |
292 | 224 | "register not mapped!\n"); | |
293 | ret = of_address_to_resource(np, 0, &r[0]); | 225 | break; |
294 | if (ret) | ||
295 | goto unreg_mph; | ||
296 | |||
297 | of_irq_to_resource(np, 0, &r[1]); | ||
298 | |||
299 | prop = of_get_property(np, "dr_mode", NULL); | ||
300 | |||
301 | if (!prop || !strcmp(prop, "host")) { | ||
302 | usb_data.operating_mode = FSL_USB2_DR_HOST; | ||
303 | usb_dev_dr_host = platform_device_register_simple( | ||
304 | "fsl-ehci", i, r, 2); | ||
305 | if (IS_ERR(usb_dev_dr_host)) { | ||
306 | ret = PTR_ERR(usb_dev_dr_host); | ||
307 | goto err; | ||
308 | } | ||
309 | } else if (prop && !strcmp(prop, "peripheral")) { | ||
310 | usb_data.operating_mode = FSL_USB2_DR_DEVICE; | ||
311 | usb_dev_dr_client = platform_device_register_simple( | ||
312 | "fsl-usb2-udc", i, r, 2); | ||
313 | if (IS_ERR(usb_dev_dr_client)) { | ||
314 | ret = PTR_ERR(usb_dev_dr_client); | ||
315 | goto err; | ||
316 | } | ||
317 | } else if (prop && !strcmp(prop, "otg")) { | ||
318 | usb_data.operating_mode = FSL_USB2_DR_OTG; | ||
319 | usb_dev_dr_host = platform_device_register_simple( | ||
320 | "fsl-ehci", i, r, 2); | ||
321 | if (IS_ERR(usb_dev_dr_host)) { | ||
322 | ret = PTR_ERR(usb_dev_dr_host); | ||
323 | goto err; | ||
324 | } | ||
325 | usb_dev_dr_client = platform_device_register_simple( | ||
326 | "fsl-usb2-udc", i, r, 2); | ||
327 | if (IS_ERR(usb_dev_dr_client)) { | ||
328 | ret = PTR_ERR(usb_dev_dr_client); | ||
329 | goto err; | ||
330 | } | ||
331 | } else { | ||
332 | ret = -EINVAL; | ||
333 | goto err; | ||
334 | } | 226 | } |
335 | |||
336 | prop = of_get_property(np, "phy_type", NULL); | ||
337 | usb_data.phy_mode = determine_usb_phy(prop); | ||
338 | |||
339 | if (usb_dev_dr_host) { | ||
340 | usb_dev_dr_host->dev.coherent_dma_mask = 0xffffffffUL; | ||
341 | usb_dev_dr_host->dev.dma_mask = &usb_dev_dr_host-> | ||
342 | dev.coherent_dma_mask; | ||
343 | if ((ret = platform_device_add_data(usb_dev_dr_host, | ||
344 | &usb_data, sizeof(struct | ||
345 | fsl_usb2_platform_data)))) | ||
346 | goto unreg_dr; | ||
347 | } | ||
348 | if (usb_dev_dr_client) { | ||
349 | usb_dev_dr_client->dev.coherent_dma_mask = 0xffffffffUL; | ||
350 | usb_dev_dr_client->dev.dma_mask = &usb_dev_dr_client-> | ||
351 | dev.coherent_dma_mask; | ||
352 | if ((ret = platform_device_add_data(usb_dev_dr_client, | ||
353 | &usb_data, sizeof(struct | ||
354 | fsl_usb2_platform_data)))) | ||
355 | goto unreg_dr; | ||
356 | } | ||
357 | i++; | ||
358 | } | 227 | } |
359 | return 0; | ||
360 | |||
361 | unreg_dr: | ||
362 | if (usb_dev_dr_host) | ||
363 | platform_device_unregister(usb_dev_dr_host); | ||
364 | if (usb_dev_dr_client) | ||
365 | platform_device_unregister(usb_dev_dr_client); | ||
366 | unreg_mph: | ||
367 | if (usb_dev_mph) | ||
368 | platform_device_unregister(usb_dev_mph); | ||
369 | err: | ||
370 | return ret; | ||
371 | } | ||
372 | |||
373 | arch_initcall(fsl_usb_of_init); | ||
374 | |||
375 | #if defined(CONFIG_FSL_SOC_BOOKE) || defined(CONFIG_PPC_86xx) | ||
376 | static __be32 __iomem *rstcr; | ||
377 | 228 | ||
378 | static int __init setup_rstcr(void) | 229 | if (!rstcr && ppc_md.restart == fsl_rstcr_restart) |
379 | { | ||
380 | struct device_node *np; | ||
381 | np = of_find_node_by_name(NULL, "global-utilities"); | ||
382 | if ((np && of_get_property(np, "fsl,has-rstcr", NULL))) { | ||
383 | rstcr = of_iomap(np, 0) + 0xb0; | ||
384 | if (!rstcr) | ||
385 | printk (KERN_EMERG "Error: reset control register " | ||
386 | "not mapped!\n"); | ||
387 | } else if (ppc_md.restart == fsl_rstcr_restart) | ||
388 | printk(KERN_ERR "No RSTCR register, warm reboot won't work\n"); | 230 | printk(KERN_ERR "No RSTCR register, warm reboot won't work\n"); |
389 | 231 | ||
390 | if (np) | 232 | if (np) |
391 | of_node_put(np); | 233 | of_node_put(np); |
234 | |||
392 | return 0; | 235 | return 0; |
393 | } | 236 | } |
394 | 237 | ||
diff --git a/arch/powerpc/sysdev/mpc8xxx_gpio.c b/arch/powerpc/sysdev/mpc8xxx_gpio.c index 2b69084d0f0c..c0ea05e87f1d 100644 --- a/arch/powerpc/sysdev/mpc8xxx_gpio.c +++ b/arch/powerpc/sysdev/mpc8xxx_gpio.c | |||
@@ -330,6 +330,9 @@ static int __init mpc8xxx_add_gpiochips(void) | |||
330 | for_each_compatible_node(np, NULL, "fsl,mpc8610-gpio") | 330 | for_each_compatible_node(np, NULL, "fsl,mpc8610-gpio") |
331 | mpc8xxx_add_controller(np); | 331 | mpc8xxx_add_controller(np); |
332 | 332 | ||
333 | for_each_compatible_node(np, NULL, "fsl,qoriq-gpio") | ||
334 | mpc8xxx_add_controller(np); | ||
335 | |||
333 | return 0; | 336 | return 0; |
334 | } | 337 | } |
335 | arch_initcall(mpc8xxx_add_gpiochips); | 338 | arch_initcall(mpc8xxx_add_gpiochips); |
diff --git a/arch/powerpc/sysdev/mpic_pasemi_msi.c b/arch/powerpc/sysdev/mpic_pasemi_msi.c index 3b6a9a43718f..320ad5a9a25d 100644 --- a/arch/powerpc/sysdev/mpic_pasemi_msi.c +++ b/arch/powerpc/sysdev/mpic_pasemi_msi.c | |||
@@ -39,24 +39,24 @@ | |||
39 | static struct mpic *msi_mpic; | 39 | static struct mpic *msi_mpic; |
40 | 40 | ||
41 | 41 | ||
42 | static void mpic_pasemi_msi_mask_irq(unsigned int irq) | 42 | static void mpic_pasemi_msi_mask_irq(struct irq_data *data) |
43 | { | 43 | { |
44 | pr_debug("mpic_pasemi_msi_mask_irq %d\n", irq); | 44 | pr_debug("mpic_pasemi_msi_mask_irq %d\n", data->irq); |
45 | mask_msi_irq(irq); | 45 | mask_msi_irq(data); |
46 | mpic_mask_irq(irq); | 46 | mpic_mask_irq(data->irq); |
47 | } | 47 | } |
48 | 48 | ||
49 | static void mpic_pasemi_msi_unmask_irq(unsigned int irq) | 49 | static void mpic_pasemi_msi_unmask_irq(struct irq_data *data) |
50 | { | 50 | { |
51 | pr_debug("mpic_pasemi_msi_unmask_irq %d\n", irq); | 51 | pr_debug("mpic_pasemi_msi_unmask_irq %d\n", data->irq); |
52 | mpic_unmask_irq(irq); | 52 | mpic_unmask_irq(data->irq); |
53 | unmask_msi_irq(irq); | 53 | unmask_msi_irq(data); |
54 | } | 54 | } |
55 | 55 | ||
56 | static struct irq_chip mpic_pasemi_msi_chip = { | 56 | static struct irq_chip mpic_pasemi_msi_chip = { |
57 | .shutdown = mpic_pasemi_msi_mask_irq, | 57 | .irq_shutdown = mpic_pasemi_msi_mask_irq, |
58 | .mask = mpic_pasemi_msi_mask_irq, | 58 | .irq_mask = mpic_pasemi_msi_mask_irq, |
59 | .unmask = mpic_pasemi_msi_unmask_irq, | 59 | .irq_unmask = mpic_pasemi_msi_unmask_irq, |
60 | .eoi = mpic_end_irq, | 60 | .eoi = mpic_end_irq, |
61 | .set_type = mpic_set_irq_type, | 61 | .set_type = mpic_set_irq_type, |
62 | .set_affinity = mpic_set_affinity, | 62 | .set_affinity = mpic_set_affinity, |
diff --git a/arch/powerpc/sysdev/mpic_u3msi.c b/arch/powerpc/sysdev/mpic_u3msi.c index bcbfe79c704b..a2b028b4a202 100644 --- a/arch/powerpc/sysdev/mpic_u3msi.c +++ b/arch/powerpc/sysdev/mpic_u3msi.c | |||
@@ -23,22 +23,22 @@ | |||
23 | /* A bit ugly, can we get this from the pci_dev somehow? */ | 23 | /* A bit ugly, can we get this from the pci_dev somehow? */ |
24 | static struct mpic *msi_mpic; | 24 | static struct mpic *msi_mpic; |
25 | 25 | ||
26 | static void mpic_u3msi_mask_irq(unsigned int irq) | 26 | static void mpic_u3msi_mask_irq(struct irq_data *data) |
27 | { | 27 | { |
28 | mask_msi_irq(irq); | 28 | mask_msi_irq(data); |
29 | mpic_mask_irq(irq); | 29 | mpic_mask_irq(data->irq); |
30 | } | 30 | } |
31 | 31 | ||
32 | static void mpic_u3msi_unmask_irq(unsigned int irq) | 32 | static void mpic_u3msi_unmask_irq(struct irq_data *data) |
33 | { | 33 | { |
34 | mpic_unmask_irq(irq); | 34 | mpic_unmask_irq(data->irq); |
35 | unmask_msi_irq(irq); | 35 | unmask_msi_irq(data); |
36 | } | 36 | } |
37 | 37 | ||
38 | static struct irq_chip mpic_u3msi_chip = { | 38 | static struct irq_chip mpic_u3msi_chip = { |
39 | .shutdown = mpic_u3msi_mask_irq, | 39 | .irq_shutdown = mpic_u3msi_mask_irq, |
40 | .mask = mpic_u3msi_mask_irq, | 40 | .irq_mask = mpic_u3msi_mask_irq, |
41 | .unmask = mpic_u3msi_unmask_irq, | 41 | .irq_unmask = mpic_u3msi_unmask_irq, |
42 | .eoi = mpic_end_irq, | 42 | .eoi = mpic_end_irq, |
43 | .set_type = mpic_set_irq_type, | 43 | .set_type = mpic_set_irq_type, |
44 | .set_affinity = mpic_set_affinity, | 44 | .set_affinity = mpic_set_affinity, |
diff --git a/arch/powerpc/sysdev/pmi.c b/arch/powerpc/sysdev/pmi.c index 24a0bb955b18..4260f368db52 100644 --- a/arch/powerpc/sysdev/pmi.c +++ b/arch/powerpc/sysdev/pmi.c | |||
@@ -114,7 +114,7 @@ static void pmi_notify_handlers(struct work_struct *work) | |||
114 | 114 | ||
115 | spin_lock(&data->handler_spinlock); | 115 | spin_lock(&data->handler_spinlock); |
116 | list_for_each_entry(handler, &data->handler, node) { | 116 | list_for_each_entry(handler, &data->handler, node) { |
117 | pr_debug(KERN_INFO "pmi: notifying handler %p\n", handler); | 117 | pr_debug("pmi: notifying handler %p\n", handler); |
118 | if (handler->type == data->msg.type) | 118 | if (handler->type == data->msg.type) |
119 | handler->handle_pmi_message(data->msg); | 119 | handler->handle_pmi_message(data->msg); |
120 | } | 120 | } |
diff --git a/arch/powerpc/xmon/Makefile b/arch/powerpc/xmon/Makefile index faa81b6a6612..c168c54e3c40 100644 --- a/arch/powerpc/xmon/Makefile +++ b/arch/powerpc/xmon/Makefile | |||
@@ -4,9 +4,7 @@ subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror | |||
4 | 4 | ||
5 | GCOV_PROFILE := n | 5 | GCOV_PROFILE := n |
6 | 6 | ||
7 | ifdef CONFIG_PPC64 | 7 | ccflags-$(CONFIG_PPC64) := -mno-minimal-toc |
8 | EXTRA_CFLAGS += -mno-minimal-toc | ||
9 | endif | ||
10 | 8 | ||
11 | obj-y += xmon.o start.o nonstdio.o | 9 | obj-y += xmon.o start.o nonstdio.o |
12 | 10 | ||