diff options
Diffstat (limited to 'arch/powerpc')
222 files changed, 6557 insertions, 4461 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 80b94b0add1f..a577609f8ed6 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -111,6 +111,7 @@ config PPC | |||
111 | select HAVE_DMA_API_DEBUG | 111 | select HAVE_DMA_API_DEBUG |
112 | select HAVE_OPROFILE | 112 | select HAVE_OPROFILE |
113 | select HAVE_DEBUG_KMEMLEAK | 113 | select HAVE_DEBUG_KMEMLEAK |
114 | select ARCH_HAS_SG_CHAIN | ||
114 | select GENERIC_ATOMIC64 if PPC32 | 115 | select GENERIC_ATOMIC64 if PPC32 |
115 | select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE | 116 | select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE |
116 | select HAVE_PERF_EVENTS | 117 | select HAVE_PERF_EVENTS |
@@ -398,6 +399,8 @@ config PPC64_SUPPORTS_MEMORY_FAILURE | |||
398 | config KEXEC | 399 | config KEXEC |
399 | bool "kexec system call" | 400 | bool "kexec system call" |
400 | depends on (PPC_BOOK3S || FSL_BOOKE || (44x && !SMP)) | 401 | depends on (PPC_BOOK3S || FSL_BOOKE || (44x && !SMP)) |
402 | select CRYPTO | ||
403 | select CRYPTO_SHA256 | ||
401 | help | 404 | help |
402 | kexec is a system call that implements the ability to shutdown your | 405 | kexec is a system call that implements the ability to shutdown your |
403 | current kernel, and to start another kernel. It is like a reboot | 406 | current kernel, and to start another kernel. It is like a reboot |
diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug index 35d16bd2760b..ec2e40f2cc11 100644 --- a/arch/powerpc/Kconfig.debug +++ b/arch/powerpc/Kconfig.debug | |||
@@ -202,9 +202,7 @@ config PPC_EARLY_DEBUG_BEAT | |||
202 | 202 | ||
203 | config PPC_EARLY_DEBUG_44x | 203 | config PPC_EARLY_DEBUG_44x |
204 | bool "Early serial debugging for IBM/AMCC 44x CPUs" | 204 | bool "Early serial debugging for IBM/AMCC 44x CPUs" |
205 | # PPC_EARLY_DEBUG on 440 leaves AS=1 mappings above the TLB high water | 205 | depends on 44x |
206 | # mark, which doesn't work with current 440 KVM. | ||
207 | depends on 44x && !KVM | ||
208 | help | 206 | help |
209 | Select this to enable early debugging for IBM 44x chips via the | 207 | Select this to enable early debugging for IBM 44x chips via the |
210 | inbuilt serial port. If you enable this, ensure you set | 208 | inbuilt serial port. If you enable this, ensure you set |
diff --git a/arch/powerpc/boot/dts/fsl/p2041si-post.dtsi b/arch/powerpc/boot/dts/fsl/p2041si-post.dtsi index 5290df83ff30..69ce1026c948 100644 --- a/arch/powerpc/boot/dts/fsl/p2041si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/p2041si-post.dtsi | |||
@@ -359,6 +359,7 @@ | |||
359 | compatible = "fsl,qoriq-core-mux-1.0"; | 359 | compatible = "fsl,qoriq-core-mux-1.0"; |
360 | clocks = <&pll0 0>, <&pll0 1>, <&pll1 0>, <&pll1 1>; | 360 | clocks = <&pll0 0>, <&pll0 1>, <&pll1 0>, <&pll1 1>; |
361 | clock-names = "pll0", "pll0-div2", "pll1", "pll1-div2"; | 361 | clock-names = "pll0", "pll0-div2", "pll1", "pll1-div2"; |
362 | clock-output-names = "cmux2"; | ||
362 | }; | 363 | }; |
363 | 364 | ||
364 | mux3: mux3@60 { | 365 | mux3: mux3@60 { |
diff --git a/arch/powerpc/boot/dts/fsl/t2080si-post.dtsi b/arch/powerpc/boot/dts/fsl/t2080si-post.dtsi new file mode 100644 index 000000000000..082ec2044060 --- /dev/null +++ b/arch/powerpc/boot/dts/fsl/t2080si-post.dtsi | |||
@@ -0,0 +1,69 @@ | |||
1 | /* | ||
2 | * T2080 Silicon/SoC Device Tree Source (post include) | ||
3 | * | ||
4 | * Copyright 2013 Freescale Semiconductor Inc. | ||
5 | * | ||
6 | * Redistribution and use in source and binary forms, with or without | ||
7 | * modification, are permitted provided that the following conditions are met: | ||
8 | * * Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions and the following disclaimer. | ||
10 | * * Redistributions in binary form must reproduce the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer in the | ||
12 | * documentation and/or other materials provided with the distribution. | ||
13 | * * Neither the name of Freescale Semiconductor nor the | ||
14 | * names of its contributors may be used to endorse or promote products | ||
15 | * derived from this software without specific prior written permission. | ||
16 | * | ||
17 | * | ||
18 | * ALTERNATIVELY, this software may be distributed under the terms of the | ||
19 | * GNU General Public License ("GPL") as published by the Free Software | ||
20 | * Foundation, either version 2 of that License or (at your option) any | ||
21 | * later version. | ||
22 | * | ||
23 | * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY | ||
24 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
25 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
26 | * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY | ||
27 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
28 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
29 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
30 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
32 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
33 | */ | ||
34 | |||
35 | /include/ "t2081si-post.dtsi" | ||
36 | |||
37 | &soc { | ||
38 | /include/ "qoriq-sata2-0.dtsi" | ||
39 | sata@220000 { | ||
40 | fsl,iommu-parent = <&pamu1>; | ||
41 | fsl,liodn-reg = <&guts 0x550>; /* SATA1LIODNR */ | ||
42 | }; | ||
43 | |||
44 | /include/ "qoriq-sata2-1.dtsi" | ||
45 | sata@221000 { | ||
46 | fsl,iommu-parent = <&pamu1>; | ||
47 | fsl,liodn-reg = <&guts 0x554>; /* SATA2LIODNR */ | ||
48 | }; | ||
49 | }; | ||
50 | |||
51 | &rio { | ||
52 | compatible = "fsl,srio"; | ||
53 | interrupts = <16 2 1 11>; | ||
54 | #address-cells = <2>; | ||
55 | #size-cells = <2>; | ||
56 | ranges; | ||
57 | |||
58 | port1 { | ||
59 | #address-cells = <2>; | ||
60 | #size-cells = <2>; | ||
61 | cell-index = <1>; | ||
62 | }; | ||
63 | |||
64 | port2 { | ||
65 | #address-cells = <2>; | ||
66 | #size-cells = <2>; | ||
67 | cell-index = <2>; | ||
68 | }; | ||
69 | }; | ||
diff --git a/arch/powerpc/boot/dts/fsl/t2081si-post.dtsi b/arch/powerpc/boot/dts/fsl/t2081si-post.dtsi new file mode 100644 index 000000000000..97479f0ce630 --- /dev/null +++ b/arch/powerpc/boot/dts/fsl/t2081si-post.dtsi | |||
@@ -0,0 +1,435 @@ | |||
1 | /* | ||
2 | * T2081 Silicon/SoC Device Tree Source (post include) | ||
3 | * | ||
4 | * Copyright 2013 Freescale Semiconductor Inc. | ||
5 | * | ||
6 | * Redistribution and use in source and binary forms, with or without | ||
7 | * modification, are permitted provided that the following conditions are met: | ||
8 | * * Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions and the following disclaimer. | ||
10 | * * Redistributions in binary form must reproduce the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer in the | ||
12 | * documentation and/or other materials provided with the distribution. | ||
13 | * * Neither the name of Freescale Semiconductor nor the | ||
14 | * names of its contributors may be used to endorse or promote products | ||
15 | * derived from this software without specific prior written permission. | ||
16 | * | ||
17 | * | ||
18 | * ALTERNATIVELY, this software may be distributed under the terms of the | ||
19 | * GNU General Public License ("GPL") as published by the Free Software | ||
20 | * Foundation, either version 2 of that License or (at your option) any | ||
21 | * later version. | ||
22 | * | ||
23 | * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY | ||
24 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
25 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
26 | * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY | ||
27 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
28 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
29 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
30 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
32 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
33 | */ | ||
34 | |||
35 | &ifc { | ||
36 | #address-cells = <2>; | ||
37 | #size-cells = <1>; | ||
38 | compatible = "fsl,ifc", "simple-bus"; | ||
39 | interrupts = <25 2 0 0>; | ||
40 | }; | ||
41 | |||
42 | /* controller at 0x240000 */ | ||
43 | &pci0 { | ||
44 | compatible = "fsl,t2080-pcie", "fsl,qoriq-pcie-v3.0", "fsl,qoriq-pcie"; | ||
45 | device_type = "pci"; | ||
46 | #size-cells = <2>; | ||
47 | #address-cells = <3>; | ||
48 | bus-range = <0x0 0xff>; | ||
49 | interrupts = <20 2 0 0>; | ||
50 | fsl,iommu-parent = <&pamu0>; | ||
51 | pcie@0 { | ||
52 | reg = <0 0 0 0 0>; | ||
53 | #interrupt-cells = <1>; | ||
54 | #size-cells = <2>; | ||
55 | #address-cells = <3>; | ||
56 | device_type = "pci"; | ||
57 | interrupts = <20 2 0 0>; | ||
58 | interrupt-map-mask = <0xf800 0 0 7>; | ||
59 | interrupt-map = < | ||
60 | /* IDSEL 0x0 */ | ||
61 | 0000 0 0 1 &mpic 40 1 0 0 | ||
62 | 0000 0 0 2 &mpic 1 1 0 0 | ||
63 | 0000 0 0 3 &mpic 2 1 0 0 | ||
64 | 0000 0 0 4 &mpic 3 1 0 0 | ||
65 | >; | ||
66 | }; | ||
67 | }; | ||
68 | |||
69 | /* controller at 0x250000 */ | ||
70 | &pci1 { | ||
71 | compatible = "fsl,t2080-pcie", "fsl,qoriq-pcie-v3.0", "fsl,qoriq-pcie"; | ||
72 | device_type = "pci"; | ||
73 | #size-cells = <2>; | ||
74 | #address-cells = <3>; | ||
75 | bus-range = <0 0xff>; | ||
76 | interrupts = <21 2 0 0>; | ||
77 | fsl,iommu-parent = <&pamu0>; | ||
78 | pcie@0 { | ||
79 | reg = <0 0 0 0 0>; | ||
80 | #interrupt-cells = <1>; | ||
81 | #size-cells = <2>; | ||
82 | #address-cells = <3>; | ||
83 | device_type = "pci"; | ||
84 | interrupts = <21 2 0 0>; | ||
85 | interrupt-map-mask = <0xf800 0 0 7>; | ||
86 | interrupt-map = < | ||
87 | /* IDSEL 0x0 */ | ||
88 | 0000 0 0 1 &mpic 41 1 0 0 | ||
89 | 0000 0 0 2 &mpic 5 1 0 0 | ||
90 | 0000 0 0 3 &mpic 6 1 0 0 | ||
91 | 0000 0 0 4 &mpic 7 1 0 0 | ||
92 | >; | ||
93 | }; | ||
94 | }; | ||
95 | |||
96 | /* controller at 0x260000 */ | ||
97 | &pci2 { | ||
98 | compatible = "fsl,t2080-pcie", "fsl,qoriq-pcie-v3.0", "fsl,qoriq-pcie"; | ||
99 | device_type = "pci"; | ||
100 | #size-cells = <2>; | ||
101 | #address-cells = <3>; | ||
102 | bus-range = <0x0 0xff>; | ||
103 | interrupts = <22 2 0 0>; | ||
104 | fsl,iommu-parent = <&pamu0>; | ||
105 | pcie@0 { | ||
106 | reg = <0 0 0 0 0>; | ||
107 | #interrupt-cells = <1>; | ||
108 | #size-cells = <2>; | ||
109 | #address-cells = <3>; | ||
110 | device_type = "pci"; | ||
111 | interrupts = <22 2 0 0>; | ||
112 | interrupt-map-mask = <0xf800 0 0 7>; | ||
113 | interrupt-map = < | ||
114 | /* IDSEL 0x0 */ | ||
115 | 0000 0 0 1 &mpic 42 1 0 0 | ||
116 | 0000 0 0 2 &mpic 9 1 0 0 | ||
117 | 0000 0 0 3 &mpic 10 1 0 0 | ||
118 | 0000 0 0 4 &mpic 11 1 0 0 | ||
119 | >; | ||
120 | }; | ||
121 | }; | ||
122 | |||
123 | /* controller at 0x270000 */ | ||
124 | &pci3 { | ||
125 | compatible = "fsl,t2080-pcie", "fsl,qoriq-pcie-v3.0", "fsl,qoriq-pcie"; | ||
126 | device_type = "pci"; | ||
127 | #size-cells = <2>; | ||
128 | #address-cells = <3>; | ||
129 | bus-range = <0x0 0xff>; | ||
130 | interrupts = <23 2 0 0>; | ||
131 | fsl,iommu-parent = <&pamu0>; | ||
132 | pcie@0 { | ||
133 | reg = <0 0 0 0 0>; | ||
134 | #interrupt-cells = <1>; | ||
135 | #size-cells = <2>; | ||
136 | #address-cells = <3>; | ||
137 | device_type = "pci"; | ||
138 | interrupts = <23 2 0 0>; | ||
139 | interrupt-map-mask = <0xf800 0 0 7>; | ||
140 | interrupt-map = < | ||
141 | /* IDSEL 0x0 */ | ||
142 | 0000 0 0 1 &mpic 43 1 0 0 | ||
143 | 0000 0 0 2 &mpic 0 1 0 0 | ||
144 | 0000 0 0 3 &mpic 4 1 0 0 | ||
145 | 0000 0 0 4 &mpic 8 1 0 0 | ||
146 | >; | ||
147 | }; | ||
148 | }; | ||
149 | |||
150 | &dcsr { | ||
151 | #address-cells = <1>; | ||
152 | #size-cells = <1>; | ||
153 | compatible = "fsl,dcsr", "simple-bus"; | ||
154 | |||
155 | dcsr-epu@0 { | ||
156 | compatible = "fsl,t2080-dcsr-epu", "fsl,dcsr-epu"; | ||
157 | interrupts = <52 2 0 0 | ||
158 | 84 2 0 0 | ||
159 | 85 2 0 0 | ||
160 | 94 2 0 0 | ||
161 | 95 2 0 0>; | ||
162 | reg = <0x0 0x1000>; | ||
163 | }; | ||
164 | dcsr-npc { | ||
165 | compatible = "fsl,t2080-dcsr-cnpc", "fsl,dcsr-cnpc"; | ||
166 | reg = <0x1000 0x1000 0x1002000 0x10000>; | ||
167 | }; | ||
168 | dcsr-nxc@2000 { | ||
169 | compatible = "fsl,dcsr-nxc"; | ||
170 | reg = <0x2000 0x1000>; | ||
171 | }; | ||
172 | dcsr-corenet { | ||
173 | compatible = "fsl,dcsr-corenet"; | ||
174 | reg = <0x8000 0x1000 0x1A000 0x1000>; | ||
175 | }; | ||
176 | dcsr-ocn@11000 { | ||
177 | compatible = "fsl,t2080-dcsr-ocn", "fsl,dcsr-ocn"; | ||
178 | reg = <0x11000 0x1000>; | ||
179 | }; | ||
180 | dcsr-ddr@12000 { | ||
181 | compatible = "fsl,dcsr-ddr"; | ||
182 | dev-handle = <&ddr1>; | ||
183 | reg = <0x12000 0x1000>; | ||
184 | }; | ||
185 | dcsr-nal@18000 { | ||
186 | compatible = "fsl,t2080-dcsr-nal", "fsl,dcsr-nal"; | ||
187 | reg = <0x18000 0x1000>; | ||
188 | }; | ||
189 | dcsr-rcpm@22000 { | ||
190 | compatible = "fsl,t2080-dcsr-rcpm", "fsl,dcsr-rcpm"; | ||
191 | reg = <0x22000 0x1000>; | ||
192 | }; | ||
193 | dcsr-snpc@30000 { | ||
194 | compatible = "fsl,t2080-dcsr-snpc", "fsl,dcsr-snpc"; | ||
195 | reg = <0x30000 0x1000 0x1022000 0x10000>; | ||
196 | }; | ||
197 | dcsr-snpc@31000 { | ||
198 | compatible = "fsl,t2080-dcsr-snpc", "fsl,dcsr-snpc"; | ||
199 | reg = <0x31000 0x1000 0x1042000 0x10000>; | ||
200 | }; | ||
201 | dcsr-snpc@32000 { | ||
202 | compatible = "fsl,t2080-dcsr-snpc", "fsl,dcsr-snpc"; | ||
203 | reg = <0x32000 0x1000 0x1062000 0x10000>; | ||
204 | }; | ||
205 | dcsr-cpu-sb-proxy@100000 { | ||
206 | compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; | ||
207 | cpu-handle = <&cpu0>; | ||
208 | reg = <0x100000 0x1000 0x101000 0x1000>; | ||
209 | }; | ||
210 | dcsr-cpu-sb-proxy@108000 { | ||
211 | compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; | ||
212 | cpu-handle = <&cpu1>; | ||
213 | reg = <0x108000 0x1000 0x109000 0x1000>; | ||
214 | }; | ||
215 | dcsr-cpu-sb-proxy@110000 { | ||
216 | compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; | ||
217 | cpu-handle = <&cpu2>; | ||
218 | reg = <0x110000 0x1000 0x111000 0x1000>; | ||
219 | }; | ||
220 | dcsr-cpu-sb-proxy@118000 { | ||
221 | compatible = "fsl,dcsr-e6500-sb-proxy", "fsl,dcsr-cpu-sb-proxy"; | ||
222 | cpu-handle = <&cpu3>; | ||
223 | reg = <0x118000 0x1000 0x119000 0x1000>; | ||
224 | }; | ||
225 | }; | ||
226 | |||
227 | &soc { | ||
228 | #address-cells = <1>; | ||
229 | #size-cells = <1>; | ||
230 | device_type = "soc"; | ||
231 | compatible = "simple-bus"; | ||
232 | |||
233 | soc-sram-error { | ||
234 | compatible = "fsl,soc-sram-error"; | ||
235 | interrupts = <16 2 1 29>; | ||
236 | }; | ||
237 | |||
238 | corenet-law@0 { | ||
239 | compatible = "fsl,corenet-law"; | ||
240 | reg = <0x0 0x1000>; | ||
241 | fsl,num-laws = <32>; | ||
242 | }; | ||
243 | |||
244 | ddr1: memory-controller@8000 { | ||
245 | compatible = "fsl,qoriq-memory-controller-v4.7", | ||
246 | "fsl,qoriq-memory-controller"; | ||
247 | reg = <0x8000 0x1000>; | ||
248 | interrupts = <16 2 1 23>; | ||
249 | }; | ||
250 | |||
251 | cpc: l3-cache-controller@10000 { | ||
252 | compatible = "fsl,t2080-l3-cache-controller", "cache"; | ||
253 | reg = <0x10000 0x1000 | ||
254 | 0x11000 0x1000 | ||
255 | 0x12000 0x1000>; | ||
256 | interrupts = <16 2 1 27 | ||
257 | 16 2 1 26 | ||
258 | 16 2 1 25>; | ||
259 | }; | ||
260 | |||
261 | corenet-cf@18000 { | ||
262 | compatible = "fsl,corenet2-cf", "fsl,corenet-cf"; | ||
263 | reg = <0x18000 0x1000>; | ||
264 | interrupts = <16 2 1 31>; | ||
265 | fsl,ccf-num-csdids = <32>; | ||
266 | fsl,ccf-num-snoopids = <32>; | ||
267 | }; | ||
268 | |||
269 | iommu@20000 { | ||
270 | compatible = "fsl,pamu-v1.0", "fsl,pamu"; | ||
271 | reg = <0x20000 0x3000>; | ||
272 | fsl,portid-mapping = <0x8000>; | ||
273 | ranges = <0 0x20000 0x3000>; | ||
274 | #address-cells = <1>; | ||
275 | #size-cells = <1>; | ||
276 | interrupts = < | ||
277 | 24 2 0 0 | ||
278 | 16 2 1 30>; | ||
279 | |||
280 | pamu0: pamu@0 { | ||
281 | reg = <0 0x1000>; | ||
282 | fsl,primary-cache-geometry = <32 1>; | ||
283 | fsl,secondary-cache-geometry = <128 2>; | ||
284 | }; | ||
285 | |||
286 | pamu1: pamu@1000 { | ||
287 | reg = <0x1000 0x1000>; | ||
288 | fsl,primary-cache-geometry = <32 1>; | ||
289 | fsl,secondary-cache-geometry = <128 2>; | ||
290 | }; | ||
291 | |||
292 | pamu2: pamu@2000 { | ||
293 | reg = <0x2000 0x1000>; | ||
294 | fsl,primary-cache-geometry = <32 1>; | ||
295 | fsl,secondary-cache-geometry = <128 2>; | ||
296 | }; | ||
297 | }; | ||
298 | |||
299 | /include/ "qoriq-mpic4.3.dtsi" | ||
300 | |||
301 | guts: global-utilities@e0000 { | ||
302 | compatible = "fsl,t2080-device-config", "fsl,qoriq-device-config-2.0"; | ||
303 | reg = <0xe0000 0xe00>; | ||
304 | fsl,has-rstcr; | ||
305 | fsl,liodn-bits = <12>; | ||
306 | }; | ||
307 | |||
308 | clockgen: global-utilities@e1000 { | ||
309 | compatible = "fsl,t2080-clockgen", "fsl,qoriq-clockgen-2.0"; | ||
310 | ranges = <0x0 0xe1000 0x1000>; | ||
311 | reg = <0xe1000 0x1000>; | ||
312 | #address-cells = <1>; | ||
313 | #size-cells = <1>; | ||
314 | |||
315 | sysclk: sysclk { | ||
316 | #clock-cells = <0>; | ||
317 | compatible = "fsl,qoriq-sysclk-2.0"; | ||
318 | clock-output-names = "sysclk", "fixed-clock"; | ||
319 | }; | ||
320 | |||
321 | pll0: pll0@800 { | ||
322 | #clock-cells = <1>; | ||
323 | reg = <0x800 4>; | ||
324 | compatible = "fsl,qoriq-core-pll-2.0"; | ||
325 | clocks = <&sysclk>; | ||
326 | clock-output-names = "pll0", "pll0-div2", "pll0-div4"; | ||
327 | }; | ||
328 | |||
329 | pll1: pll1@820 { | ||
330 | #clock-cells = <1>; | ||
331 | reg = <0x820 4>; | ||
332 | compatible = "fsl,qoriq-core-pll-2.0"; | ||
333 | clocks = <&sysclk>; | ||
334 | clock-output-names = "pll1", "pll1-div2", "pll1-div4"; | ||
335 | }; | ||
336 | |||
337 | mux0: mux0@0 { | ||
338 | #clock-cells = <0>; | ||
339 | reg = <0x0 4>; | ||
340 | compatible = "fsl,qoriq-core-mux-2.0"; | ||
341 | clocks = <&pll0 0>, <&pll0 1>, <&pll0 2>, | ||
342 | <&pll1 0>, <&pll1 1>, <&pll1 2>; | ||
343 | clock-names = "pll0", "pll0-div2", "pll1-div4", | ||
344 | "pll1", "pll1-div2", "pll1-div4"; | ||
345 | clock-output-names = "cmux0"; | ||
346 | }; | ||
347 | |||
348 | mux1: mux1@20 { | ||
349 | #clock-cells = <0>; | ||
350 | reg = <0x20 4>; | ||
351 | compatible = "fsl,qoriq-core-mux-2.0"; | ||
352 | clocks = <&pll0 0>, <&pll0 1>, <&pll0 2>, | ||
353 | <&pll1 0>, <&pll1 1>, <&pll1 2>; | ||
354 | clock-names = "pll0", "pll0-div2", "pll1-div4", | ||
355 | "pll1", "pll1-div2", "pll1-div4"; | ||
356 | clock-output-names = "cmux1"; | ||
357 | }; | ||
358 | }; | ||
359 | |||
360 | rcpm: global-utilities@e2000 { | ||
361 | compatible = "fsl,t2080-rcpm", "fsl,qoriq-rcpm-2.0"; | ||
362 | reg = <0xe2000 0x1000>; | ||
363 | }; | ||
364 | |||
365 | sfp: sfp@e8000 { | ||
366 | compatible = "fsl,t2080-sfp"; | ||
367 | reg = <0xe8000 0x1000>; | ||
368 | }; | ||
369 | |||
370 | serdes: serdes@ea000 { | ||
371 | compatible = "fsl,t2080-serdes"; | ||
372 | reg = <0xea000 0x4000>; | ||
373 | }; | ||
374 | |||
375 | /include/ "elo3-dma-0.dtsi" | ||
376 | dma@100300 { | ||
377 | fsl,iommu-parent = <&pamu0>; | ||
378 | fsl,liodn-reg = <&guts 0x580>; /* DMA1LIODNR */ | ||
379 | }; | ||
380 | /include/ "elo3-dma-1.dtsi" | ||
381 | dma@101300 { | ||
382 | fsl,iommu-parent = <&pamu0>; | ||
383 | fsl,liodn-reg = <&guts 0x584>; /* DMA2LIODNR */ | ||
384 | }; | ||
385 | /include/ "elo3-dma-2.dtsi" | ||
386 | dma@102300 { | ||
387 | fsl,iommu-parent = <&pamu0>; | ||
388 | fsl,liodn-reg = <&guts 0x588>; /* DMA3LIODNR */ | ||
389 | }; | ||
390 | |||
391 | /include/ "qoriq-espi-0.dtsi" | ||
392 | spi@110000 { | ||
393 | fsl,espi-num-chipselects = <4>; | ||
394 | }; | ||
395 | |||
396 | /include/ "qoriq-esdhc-0.dtsi" | ||
397 | sdhc@114000 { | ||
398 | compatible = "fsl,t2080-esdhc", "fsl,esdhc"; | ||
399 | fsl,iommu-parent = <&pamu1>; | ||
400 | fsl,liodn-reg = <&guts 0x530>; /* SDMMCLIODNR */ | ||
401 | sdhci,auto-cmd12; | ||
402 | }; | ||
403 | /include/ "qoriq-i2c-0.dtsi" | ||
404 | /include/ "qoriq-i2c-1.dtsi" | ||
405 | /include/ "qoriq-duart-0.dtsi" | ||
406 | /include/ "qoriq-duart-1.dtsi" | ||
407 | /include/ "qoriq-gpio-0.dtsi" | ||
408 | /include/ "qoriq-gpio-1.dtsi" | ||
409 | /include/ "qoriq-gpio-2.dtsi" | ||
410 | /include/ "qoriq-gpio-3.dtsi" | ||
411 | /include/ "qoriq-usb2-mph-0.dtsi" | ||
412 | usb0: usb@210000 { | ||
413 | compatible = "fsl-usb2-mph-v2.4", "fsl-usb2-mph"; | ||
414 | fsl,iommu-parent = <&pamu1>; | ||
415 | fsl,liodn-reg = <&guts 0x520>; /* USB1LIODNR */ | ||
416 | phy_type = "utmi"; | ||
417 | port0; | ||
418 | }; | ||
419 | /include/ "qoriq-usb2-dr-0.dtsi" | ||
420 | usb1: usb@211000 { | ||
421 | compatible = "fsl-usb2-dr-v2.4", "fsl-usb2-dr"; | ||
422 | fsl,iommu-parent = <&pamu1>; | ||
423 | fsl,liodn-reg = <&guts 0x524>; /* USB1LIODNR */ | ||
424 | dr_mode = "host"; | ||
425 | phy_type = "utmi"; | ||
426 | }; | ||
427 | /include/ "qoriq-sec5.2-0.dtsi" | ||
428 | |||
429 | L2_1: l2-cache-controller@c20000 { | ||
430 | /* Cluster 0 L2 cache */ | ||
431 | compatible = "fsl,t2080-l2-cache-controller"; | ||
432 | reg = <0xc20000 0x40000>; | ||
433 | next-level-cache = <&cpc>; | ||
434 | }; | ||
435 | }; | ||
diff --git a/arch/powerpc/boot/dts/fsl/t208xsi-pre.dtsi b/arch/powerpc/boot/dts/fsl/t208xsi-pre.dtsi new file mode 100644 index 000000000000..e71ceb0e1100 --- /dev/null +++ b/arch/powerpc/boot/dts/fsl/t208xsi-pre.dtsi | |||
@@ -0,0 +1,99 @@ | |||
1 | /* | ||
2 | * T2080/T2081 Silicon/SoC Device Tree Source (pre include) | ||
3 | * | ||
4 | * Copyright 2013 Freescale Semiconductor Inc. | ||
5 | * | ||
6 | * Redistribution and use in source and binary forms, with or without | ||
7 | * modification, are permitted provided that the following conditions are met: | ||
8 | * * Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions and the following disclaimer. | ||
10 | * * Redistributions in binary form must reproduce the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer in the | ||
12 | * documentation and/or other materials provided with the distribution. | ||
13 | * * Neither the name of Freescale Semiconductor nor the | ||
14 | * names of its contributors may be used to endorse or promote products | ||
15 | * derived from this software without specific prior written permission. | ||
16 | * | ||
17 | * | ||
18 | * ALTERNATIVELY, this software may be distributed under the terms of the | ||
19 | * GNU General Public License ("GPL") as published by the Free Software | ||
20 | * Foundation, either version 2 of that License or (at your option) any | ||
21 | * later version. | ||
22 | * | ||
23 | * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY | ||
24 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
25 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
26 | * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY | ||
27 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
28 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
29 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
30 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
32 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
33 | */ | ||
34 | |||
35 | /dts-v1/; | ||
36 | |||
37 | /include/ "e6500_power_isa.dtsi" | ||
38 | |||
39 | / { | ||
40 | #address-cells = <2>; | ||
41 | #size-cells = <2>; | ||
42 | interrupt-parent = <&mpic>; | ||
43 | |||
44 | aliases { | ||
45 | ccsr = &soc; | ||
46 | dcsr = &dcsr; | ||
47 | |||
48 | serial0 = &serial0; | ||
49 | serial1 = &serial1; | ||
50 | serial2 = &serial2; | ||
51 | serial3 = &serial3; | ||
52 | |||
53 | crypto = &crypto; | ||
54 | pci0 = &pci0; | ||
55 | pci1 = &pci1; | ||
56 | pci2 = &pci2; | ||
57 | pci3 = &pci3; | ||
58 | usb0 = &usb0; | ||
59 | usb1 = &usb1; | ||
60 | dma0 = &dma0; | ||
61 | dma1 = &dma1; | ||
62 | dma2 = &dma2; | ||
63 | sdhc = &sdhc; | ||
64 | }; | ||
65 | |||
66 | cpus { | ||
67 | #address-cells = <1>; | ||
68 | #size-cells = <0>; | ||
69 | |||
70 | cpu0: PowerPC,e6500@0 { | ||
71 | device_type = "cpu"; | ||
72 | reg = <0 1>; | ||
73 | clocks = <&mux0>; | ||
74 | next-level-cache = <&L2_1>; | ||
75 | fsl,portid-mapping = <0x80000000>; | ||
76 | }; | ||
77 | cpu1: PowerPC,e6500@2 { | ||
78 | device_type = "cpu"; | ||
79 | reg = <2 3>; | ||
80 | clocks = <&mux0>; | ||
81 | next-level-cache = <&L2_1>; | ||
82 | fsl,portid-mapping = <0x80000000>; | ||
83 | }; | ||
84 | cpu2: PowerPC,e6500@4 { | ||
85 | device_type = "cpu"; | ||
86 | reg = <4 5>; | ||
87 | clocks = <&mux0>; | ||
88 | next-level-cache = <&L2_1>; | ||
89 | fsl,portid-mapping = <0x80000000>; | ||
90 | }; | ||
91 | cpu3: PowerPC,e6500@6 { | ||
92 | device_type = "cpu"; | ||
93 | reg = <6 7>; | ||
94 | clocks = <&mux0>; | ||
95 | next-level-cache = <&L2_1>; | ||
96 | fsl,portid-mapping = <0x80000000>; | ||
97 | }; | ||
98 | }; | ||
99 | }; | ||
diff --git a/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi b/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi index 793669baa13e..a3d582e0361a 100644 --- a/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/t4240si-post.dtsi | |||
@@ -476,6 +476,7 @@ | |||
476 | 476 | ||
477 | /include/ "elo3-dma-0.dtsi" | 477 | /include/ "elo3-dma-0.dtsi" |
478 | /include/ "elo3-dma-1.dtsi" | 478 | /include/ "elo3-dma-1.dtsi" |
479 | /include/ "elo3-dma-2.dtsi" | ||
479 | 480 | ||
480 | /include/ "qoriq-espi-0.dtsi" | 481 | /include/ "qoriq-espi-0.dtsi" |
481 | spi@110000 { | 482 | spi@110000 { |
diff --git a/arch/powerpc/boot/dts/fsl/t4240si-pre.dtsi b/arch/powerpc/boot/dts/fsl/t4240si-pre.dtsi index d2f157edbe81..261a3abb1a55 100644 --- a/arch/powerpc/boot/dts/fsl/t4240si-pre.dtsi +++ b/arch/powerpc/boot/dts/fsl/t4240si-pre.dtsi | |||
@@ -57,6 +57,7 @@ | |||
57 | pci3 = &pci3; | 57 | pci3 = &pci3; |
58 | dma0 = &dma0; | 58 | dma0 = &dma0; |
59 | dma1 = &dma1; | 59 | dma1 = &dma1; |
60 | dma2 = &dma2; | ||
60 | sdhc = &sdhc; | 61 | sdhc = &sdhc; |
61 | }; | 62 | }; |
62 | 63 | ||
diff --git a/arch/powerpc/boot/dts/mpc5121.dtsi b/arch/powerpc/boot/dts/mpc5121.dtsi index 2c0e1552d20b..7f9d14f5c4da 100644 --- a/arch/powerpc/boot/dts/mpc5121.dtsi +++ b/arch/powerpc/boot/dts/mpc5121.dtsi | |||
@@ -498,6 +498,7 @@ | |||
498 | compatible = "fsl,mpc5121-dma"; | 498 | compatible = "fsl,mpc5121-dma"; |
499 | reg = <0x14000 0x1800>; | 499 | reg = <0x14000 0x1800>; |
500 | interrupts = <65 0x8>; | 500 | interrupts = <65 0x8>; |
501 | #dma-cells = <1>; | ||
501 | }; | 502 | }; |
502 | }; | 503 | }; |
503 | 504 | ||
diff --git a/arch/powerpc/boot/dts/t2080qds.dts b/arch/powerpc/boot/dts/t2080qds.dts new file mode 100644 index 000000000000..aa1d6d8c169b --- /dev/null +++ b/arch/powerpc/boot/dts/t2080qds.dts | |||
@@ -0,0 +1,57 @@ | |||
1 | /* | ||
2 | * T2080QDS Device Tree Source | ||
3 | * | ||
4 | * Copyright 2013 Freescale Semiconductor Inc. | ||
5 | * | ||
6 | * Redistribution and use in source and binary forms, with or without | ||
7 | * modification, are permitted provided that the following conditions are met: | ||
8 | * * Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions and the following disclaimer. | ||
10 | * * Redistributions in binary form must reproduce the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer in the | ||
12 | * documentation and/or other materials provided with the distribution. | ||
13 | * * Neither the name of Freescale Semiconductor nor the | ||
14 | * names of its contributors may be used to endorse or promote products | ||
15 | * derived from this software without specific prior written permission. | ||
16 | * | ||
17 | * | ||
18 | * ALTERNATIVELY, this software may be distributed under the terms of the | ||
19 | * GNU General Public License ("GPL") as published by the Free Software | ||
20 | * Foundation, either version 2 of that License or (at your option) any | ||
21 | * later version. | ||
22 | * | ||
23 | * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY | ||
24 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
25 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
26 | * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY | ||
27 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
28 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
29 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
30 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
32 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
33 | */ | ||
34 | |||
35 | /include/ "fsl/t208xsi-pre.dtsi" | ||
36 | /include/ "t208xqds.dtsi" | ||
37 | |||
38 | / { | ||
39 | model = "fsl,T2080QDS"; | ||
40 | compatible = "fsl,T2080QDS"; | ||
41 | #address-cells = <2>; | ||
42 | #size-cells = <2>; | ||
43 | interrupt-parent = <&mpic>; | ||
44 | |||
45 | rio: rapidio@ffe0c0000 { | ||
46 | reg = <0xf 0xfe0c0000 0 0x11000>; | ||
47 | |||
48 | port1 { | ||
49 | ranges = <0 0 0xc 0x20000000 0 0x10000000>; | ||
50 | }; | ||
51 | port2 { | ||
52 | ranges = <0 0 0xc 0x30000000 0 0x10000000>; | ||
53 | }; | ||
54 | }; | ||
55 | }; | ||
56 | |||
57 | /include/ "fsl/t2080si-post.dtsi" | ||
diff --git a/arch/powerpc/boot/dts/t2080rdb.dts b/arch/powerpc/boot/dts/t2080rdb.dts new file mode 100644 index 000000000000..e8891047600c --- /dev/null +++ b/arch/powerpc/boot/dts/t2080rdb.dts | |||
@@ -0,0 +1,57 @@ | |||
1 | /* | ||
2 | * T2080PCIe-RDB Board Device Tree Source | ||
3 | * | ||
4 | * Copyright 2014 Freescale Semiconductor Inc. | ||
5 | * | ||
6 | * Redistribution and use in source and binary forms, with or without | ||
7 | * modification, are permitted provided that the following conditions are met: | ||
8 | * * Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions and the following disclaimer. | ||
10 | * * Redistributions in binary form must reproduce the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer in the | ||
12 | * documentation and/or other materials provided with the distribution. | ||
13 | * * Neither the name of Freescale Semiconductor nor the | ||
14 | * names of its contributors may be used to endorse or promote products | ||
15 | * derived from this software without specific prior written permission. | ||
16 | * | ||
17 | * | ||
18 | * ALTERNATIVELY, this software may be distributed under the terms of the | ||
19 | * GNU General Public License ("GPL") as published by the Free Software | ||
20 | * Foundation, either version 2 of that License or (at your option) any | ||
21 | * later version. | ||
22 | * | ||
23 | * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY | ||
24 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
25 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
26 | * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY | ||
27 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
28 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
29 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
30 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
32 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
33 | */ | ||
34 | |||
35 | /include/ "fsl/t208xsi-pre.dtsi" | ||
36 | /include/ "t208xrdb.dtsi" | ||
37 | |||
38 | / { | ||
39 | model = "fsl,T2080RDB"; | ||
40 | compatible = "fsl,T2080RDB"; | ||
41 | #address-cells = <2>; | ||
42 | #size-cells = <2>; | ||
43 | interrupt-parent = <&mpic>; | ||
44 | |||
45 | rio: rapidio@ffe0c0000 { | ||
46 | reg = <0xf 0xfe0c0000 0 0x11000>; | ||
47 | |||
48 | port1 { | ||
49 | ranges = <0 0 0xc 0x20000000 0 0x10000000>; | ||
50 | }; | ||
51 | port2 { | ||
52 | ranges = <0 0 0xc 0x30000000 0 0x10000000>; | ||
53 | }; | ||
54 | }; | ||
55 | }; | ||
56 | |||
57 | /include/ "fsl/t2080si-post.dtsi" | ||
diff --git a/arch/powerpc/boot/dts/t2081qds.dts b/arch/powerpc/boot/dts/t2081qds.dts new file mode 100644 index 000000000000..8ec80a71e102 --- /dev/null +++ b/arch/powerpc/boot/dts/t2081qds.dts | |||
@@ -0,0 +1,46 @@ | |||
1 | /* | ||
2 | * T2081QDS Device Tree Source | ||
3 | * | ||
4 | * Copyright 2013 Freescale Semiconductor Inc. | ||
5 | * | ||
6 | * Redistribution and use in source and binary forms, with or without | ||
7 | * modification, are permitted provided that the following conditions are met: | ||
8 | * * Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions and the following disclaimer. | ||
10 | * * Redistributions in binary form must reproduce the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer in the | ||
12 | * documentation and/or other materials provided with the distribution. | ||
13 | * * Neither the name of Freescale Semiconductor nor the | ||
14 | * names of its contributors may be used to endorse or promote products | ||
15 | * derived from this software without specific prior written permission. | ||
16 | * | ||
17 | * | ||
18 | * ALTERNATIVELY, this software may be distributed under the terms of the | ||
19 | * GNU General Public License ("GPL") as published by the Free Software | ||
20 | * Foundation, either version 2 of that License or (at your option) any | ||
21 | * later version. | ||
22 | * | ||
23 | * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY | ||
24 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
25 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
26 | * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY | ||
27 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
28 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
29 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
30 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
32 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
33 | */ | ||
34 | |||
35 | /include/ "fsl/t208xsi-pre.dtsi" | ||
36 | /include/ "t208xqds.dtsi" | ||
37 | |||
38 | / { | ||
39 | model = "fsl,T2081QDS"; | ||
40 | compatible = "fsl,T2081QDS"; | ||
41 | #address-cells = <2>; | ||
42 | #size-cells = <2>; | ||
43 | interrupt-parent = <&mpic>; | ||
44 | }; | ||
45 | |||
46 | /include/ "fsl/t2081si-post.dtsi" | ||
diff --git a/arch/powerpc/boot/dts/t208xqds.dtsi b/arch/powerpc/boot/dts/t208xqds.dtsi new file mode 100644 index 000000000000..555dc6e03d89 --- /dev/null +++ b/arch/powerpc/boot/dts/t208xqds.dtsi | |||
@@ -0,0 +1,239 @@ | |||
1 | /* | ||
2 | * T2080/T2081 QDS Device Tree Source | ||
3 | * | ||
4 | * Copyright 2013 Freescale Semiconductor Inc. | ||
5 | * | ||
6 | * Redistribution and use in source and binary forms, with or without | ||
7 | * modification, are permitted provided that the following conditions are met: | ||
8 | * * Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions and the following disclaimer. | ||
10 | * * Redistributions in binary form must reproduce the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer in the | ||
12 | * documentation and/or other materials provided with the distribution. | ||
13 | * * Neither the name of Freescale Semiconductor nor the | ||
14 | * names of its contributors may be used to endorse or promote products | ||
15 | * derived from this software without specific prior written permission. | ||
16 | * | ||
17 | * | ||
18 | * ALTERNATIVELY, this software may be distributed under the terms of the | ||
19 | * GNU General Public License ("GPL") as published by the Free Software | ||
20 | * Foundation, either version 2 of that License or (at your option) any | ||
21 | * later version. | ||
22 | * | ||
23 | * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY | ||
24 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
25 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
26 | * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY | ||
27 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
28 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
29 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
30 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
32 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
33 | */ | ||
34 | |||
35 | / { | ||
36 | model = "fsl,T2080QDS"; | ||
37 | compatible = "fsl,T2080QDS"; | ||
38 | #address-cells = <2>; | ||
39 | #size-cells = <2>; | ||
40 | interrupt-parent = <&mpic>; | ||
41 | |||
42 | ifc: localbus@ffe124000 { | ||
43 | reg = <0xf 0xfe124000 0 0x2000>; | ||
44 | ranges = <0 0 0xf 0xe8000000 0x08000000 | ||
45 | 2 0 0xf 0xff800000 0x00010000 | ||
46 | 3 0 0xf 0xffdf0000 0x00008000>; | ||
47 | |||
48 | nor@0,0 { | ||
49 | #address-cells = <1>; | ||
50 | #size-cells = <1>; | ||
51 | compatible = "cfi-flash"; | ||
52 | reg = <0x0 0x0 0x8000000>; | ||
53 | bank-width = <2>; | ||
54 | device-width = <1>; | ||
55 | }; | ||
56 | |||
57 | nand@2,0 { | ||
58 | #address-cells = <1>; | ||
59 | #size-cells = <1>; | ||
60 | compatible = "fsl,ifc-nand"; | ||
61 | reg = <0x2 0x0 0x10000>; | ||
62 | }; | ||
63 | |||
64 | boardctrl: board-control@3,0 { | ||
65 | #address-cells = <1>; | ||
66 | #size-cells = <1>; | ||
67 | compatible = "fsl,fpga-qixis"; | ||
68 | reg = <3 0 0x300>; | ||
69 | ranges = <0 3 0 0x300>; | ||
70 | }; | ||
71 | }; | ||
72 | |||
73 | memory { | ||
74 | device_type = "memory"; | ||
75 | }; | ||
76 | |||
77 | dcsr: dcsr@f00000000 { | ||
78 | ranges = <0x00000000 0xf 0x00000000 0x01072000>; | ||
79 | }; | ||
80 | |||
81 | soc: soc@ffe000000 { | ||
82 | ranges = <0x00000000 0xf 0xfe000000 0x1000000>; | ||
83 | reg = <0xf 0xfe000000 0 0x00001000>; | ||
84 | spi@110000 { | ||
85 | flash@0 { | ||
86 | #address-cells = <1>; | ||
87 | #size-cells = <1>; | ||
88 | compatible = "micron,n25q128a11"; /* 16MB */ | ||
89 | reg = <0>; | ||
90 | spi-max-frequency = <40000000>; /* input clock */ | ||
91 | }; | ||
92 | |||
93 | flash@1 { | ||
94 | #address-cells = <1>; | ||
95 | #size-cells = <1>; | ||
96 | compatible = "sst,sst25wf040"; | ||
97 | reg = <1>; | ||
98 | spi-max-frequency = <35000000>; | ||
99 | }; | ||
100 | |||
101 | flash@2 { | ||
102 | #address-cells = <1>; | ||
103 | #size-cells = <1>; | ||
104 | compatible = "eon,en25s64"; | ||
105 | reg = <2>; | ||
106 | spi-max-frequency = <35000000>; | ||
107 | }; | ||
108 | }; | ||
109 | |||
110 | i2c@118000 { | ||
111 | pca9547@77 { | ||
112 | compatible = "nxp,pca9547"; | ||
113 | reg = <0x77>; | ||
114 | #address-cells = <1>; | ||
115 | #size-cells = <0>; | ||
116 | |||
117 | i2c@0 { | ||
118 | #address-cells = <1>; | ||
119 | #size-cells = <0>; | ||
120 | reg = <0x0>; | ||
121 | |||
122 | eeprom@50 { | ||
123 | compatible = "at24,24c512"; | ||
124 | reg = <0x50>; | ||
125 | }; | ||
126 | |||
127 | eeprom@51 { | ||
128 | compatible = "at24,24c02"; | ||
129 | reg = <0x51>; | ||
130 | }; | ||
131 | |||
132 | eeprom@57 { | ||
133 | compatible = "at24,24c02"; | ||
134 | reg = <0x57>; | ||
135 | }; | ||
136 | |||
137 | rtc@68 { | ||
138 | compatible = "dallas,ds3232"; | ||
139 | reg = <0x68>; | ||
140 | interrupts = <0x1 0x1 0 0>; | ||
141 | }; | ||
142 | }; | ||
143 | |||
144 | i2c@1 { | ||
145 | #address-cells = <1>; | ||
146 | #size-cells = <0>; | ||
147 | reg = <0x1>; | ||
148 | |||
149 | eeprom@55 { | ||
150 | compatible = "at24,24c02"; | ||
151 | reg = <0x55>; | ||
152 | }; | ||
153 | }; | ||
154 | |||
155 | i2c@2 { | ||
156 | #address-cells = <1>; | ||
157 | #size-cells = <0>; | ||
158 | reg = <0x2>; | ||
159 | |||
160 | ina220@40 { | ||
161 | compatible = "ti,ina220"; | ||
162 | reg = <0x40>; | ||
163 | shunt-resistor = <1000>; | ||
164 | }; | ||
165 | |||
166 | ina220@41 { | ||
167 | compatible = "ti,ina220"; | ||
168 | reg = <0x41>; | ||
169 | shunt-resistor = <1000>; | ||
170 | }; | ||
171 | }; | ||
172 | }; | ||
173 | }; | ||
174 | |||
175 | sdhc@114000 { | ||
176 | voltage-ranges = <1800 1800 3300 3300>; | ||
177 | }; | ||
178 | }; | ||
179 | |||
180 | pci0: pcie@ffe240000 { | ||
181 | reg = <0xf 0xfe240000 0 0x10000>; | ||
182 | ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000 | ||
183 | 0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>; | ||
184 | pcie@0 { | ||
185 | ranges = <0x02000000 0 0xe0000000 | ||
186 | 0x02000000 0 0xe0000000 | ||
187 | 0 0x20000000 | ||
188 | |||
189 | 0x01000000 0 0x00000000 | ||
190 | 0x01000000 0 0x00000000 | ||
191 | 0 0x00010000>; | ||
192 | }; | ||
193 | }; | ||
194 | |||
195 | pci1: pcie@ffe250000 { | ||
196 | reg = <0xf 0xfe250000 0 0x10000>; | ||
197 | ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x10000000 | ||
198 | 0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>; | ||
199 | pcie@0 { | ||
200 | ranges = <0x02000000 0 0xe0000000 | ||
201 | 0x02000000 0 0xe0000000 | ||
202 | 0 0x20000000 | ||
203 | |||
204 | 0x01000000 0 0x00000000 | ||
205 | 0x01000000 0 0x00000000 | ||
206 | 0 0x00010000>; | ||
207 | }; | ||
208 | }; | ||
209 | |||
210 | pci2: pcie@ffe260000 { | ||
211 | reg = <0xf 0xfe260000 0 0x1000>; | ||
212 | ranges = <0x02000000 0 0xe0000000 0xc 0x30000000 0 0x10000000 | ||
213 | 0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>; | ||
214 | pcie@0 { | ||
215 | ranges = <0x02000000 0 0xe0000000 | ||
216 | 0x02000000 0 0xe0000000 | ||
217 | 0 0x20000000 | ||
218 | |||
219 | 0x01000000 0 0x00000000 | ||
220 | 0x01000000 0 0x00000000 | ||
221 | 0 0x00010000>; | ||
222 | }; | ||
223 | }; | ||
224 | |||
225 | pci3: pcie@ffe270000 { | ||
226 | reg = <0xf 0xfe270000 0 0x10000>; | ||
227 | ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x10000000 | ||
228 | 0x01000000 0 0x00000000 0xf 0xf8030000 0 0x00010000>; | ||
229 | pcie@0 { | ||
230 | ranges = <0x02000000 0 0xe0000000 | ||
231 | 0x02000000 0 0xe0000000 | ||
232 | 0 0x20000000 | ||
233 | |||
234 | 0x01000000 0 0x00000000 | ||
235 | 0x01000000 0 0x00000000 | ||
236 | 0 0x00010000>; | ||
237 | }; | ||
238 | }; | ||
239 | }; | ||
diff --git a/arch/powerpc/boot/dts/t208xrdb.dtsi b/arch/powerpc/boot/dts/t208xrdb.dtsi new file mode 100644 index 000000000000..1481e192e783 --- /dev/null +++ b/arch/powerpc/boot/dts/t208xrdb.dtsi | |||
@@ -0,0 +1,184 @@ | |||
1 | /* | ||
2 | * T2080PCIe-RDB Board Device Tree Source | ||
3 | * | ||
4 | * Copyright 2014 Freescale Semiconductor Inc. | ||
5 | * | ||
6 | * Redistribution and use in source and binary forms, with or without | ||
7 | * modification, are permitted provided that the following conditions are met: | ||
8 | * * Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions and the following disclaimer. | ||
10 | * * Redistributions in binary form must reproduce the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer in the | ||
12 | * documentation and/or other materials provided with the distribution. | ||
13 | * * Neither the name of Freescale Semiconductor nor the | ||
14 | * names of its contributors may be used to endorse or promote products | ||
15 | * derived from this software without specific prior written permission. | ||
16 | * | ||
17 | * | ||
18 | * ALTERNATIVELY, this software may be distributed under the terms of the | ||
19 | * GNU General Public License ("GPL") as published by the Free Software | ||
20 | * Foundation, either version 2 of that License or (at your option) any | ||
21 | * later version. | ||
22 | * | ||
23 | * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY | ||
24 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
25 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
26 | * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY | ||
27 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
28 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
29 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
30 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
32 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
33 | */ | ||
34 | |||
35 | / { | ||
36 | model = "fsl,T2080RDB"; | ||
37 | compatible = "fsl,T2080RDB"; | ||
38 | #address-cells = <2>; | ||
39 | #size-cells = <2>; | ||
40 | interrupt-parent = <&mpic>; | ||
41 | |||
42 | ifc: localbus@ffe124000 { | ||
43 | reg = <0xf 0xfe124000 0 0x2000>; | ||
44 | ranges = <0 0 0xf 0xe8000000 0x08000000 | ||
45 | 2 0 0xf 0xff800000 0x00010000 | ||
46 | 3 0 0xf 0xffdf0000 0x00008000>; | ||
47 | |||
48 | nor@0,0 { | ||
49 | #address-cells = <1>; | ||
50 | #size-cells = <1>; | ||
51 | compatible = "cfi-flash"; | ||
52 | reg = <0x0 0x0 0x8000000>; | ||
53 | |||
54 | bank-width = <2>; | ||
55 | device-width = <1>; | ||
56 | }; | ||
57 | |||
58 | nand@1,0 { | ||
59 | #address-cells = <1>; | ||
60 | #size-cells = <1>; | ||
61 | compatible = "fsl,ifc-nand"; | ||
62 | reg = <0x2 0x0 0x10000>; | ||
63 | }; | ||
64 | |||
65 | boardctrl: board-control@2,0 { | ||
66 | #address-cells = <1>; | ||
67 | #size-cells = <1>; | ||
68 | compatible = "fsl,t2080-cpld"; | ||
69 | reg = <3 0 0x300>; | ||
70 | ranges = <0 3 0 0x300>; | ||
71 | }; | ||
72 | }; | ||
73 | |||
74 | memory { | ||
75 | device_type = "memory"; | ||
76 | }; | ||
77 | |||
78 | dcsr: dcsr@f00000000 { | ||
79 | ranges = <0x00000000 0xf 0x00000000 0x01072000>; | ||
80 | }; | ||
81 | |||
82 | soc: soc@ffe000000 { | ||
83 | ranges = <0x00000000 0xf 0xfe000000 0x1000000>; | ||
84 | reg = <0xf 0xfe000000 0 0x00001000>; | ||
85 | spi@110000 { | ||
86 | flash@0 { | ||
87 | #address-cells = <1>; | ||
88 | #size-cells = <1>; | ||
89 | compatible = "micron,n25q512a"; | ||
90 | reg = <0>; | ||
91 | spi-max-frequency = <10000000>; /* input clock */ | ||
92 | }; | ||
93 | }; | ||
94 | |||
95 | i2c@118000 { | ||
96 | adt7481@4c { | ||
97 | compatible = "adi,adt7481"; | ||
98 | reg = <0x4c>; | ||
99 | }; | ||
100 | |||
101 | rtc@68 { | ||
102 | compatible = "dallas,ds1339"; | ||
103 | reg = <0x68>; | ||
104 | interrupts = <0x1 0x1 0 0>; | ||
105 | }; | ||
106 | |||
107 | eeprom@50 { | ||
108 | compatible = "atmel,24c256"; | ||
109 | reg = <0x50>; | ||
110 | }; | ||
111 | }; | ||
112 | |||
113 | i2c@118100 { | ||
114 | pca9546@77 { | ||
115 | compatible = "nxp,pca9546"; | ||
116 | reg = <0x77>; | ||
117 | }; | ||
118 | }; | ||
119 | |||
120 | sdhc@114000 { | ||
121 | voltage-ranges = <1800 1800 3300 3300>; | ||
122 | }; | ||
123 | }; | ||
124 | |||
125 | pci0: pcie@ffe240000 { | ||
126 | reg = <0xf 0xfe240000 0 0x10000>; | ||
127 | ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000 | ||
128 | 0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>; | ||
129 | pcie@0 { | ||
130 | ranges = <0x02000000 0 0xe0000000 | ||
131 | 0x02000000 0 0xe0000000 | ||
132 | 0 0x20000000 | ||
133 | |||
134 | 0x01000000 0 0x00000000 | ||
135 | 0x01000000 0 0x00000000 | ||
136 | 0 0x00010000>; | ||
137 | }; | ||
138 | }; | ||
139 | |||
140 | pci1: pcie@ffe250000 { | ||
141 | reg = <0xf 0xfe250000 0 0x10000>; | ||
142 | ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x10000000 | ||
143 | 0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>; | ||
144 | pcie@0 { | ||
145 | ranges = <0x02000000 0 0xe0000000 | ||
146 | 0x02000000 0 0xe0000000 | ||
147 | 0 0x20000000 | ||
148 | |||
149 | 0x01000000 0 0x00000000 | ||
150 | 0x01000000 0 0x00000000 | ||
151 | 0 0x00010000>; | ||
152 | }; | ||
153 | }; | ||
154 | |||
155 | pci2: pcie@ffe260000 { | ||
156 | reg = <0xf 0xfe260000 0 0x1000>; | ||
157 | ranges = <0x02000000 0 0xe0000000 0xc 0x30000000 0 0x10000000 | ||
158 | 0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>; | ||
159 | pcie@0 { | ||
160 | ranges = <0x02000000 0 0xe0000000 | ||
161 | 0x02000000 0 0xe0000000 | ||
162 | 0 0x20000000 | ||
163 | |||
164 | 0x01000000 0 0x00000000 | ||
165 | 0x01000000 0 0x00000000 | ||
166 | 0 0x00010000>; | ||
167 | }; | ||
168 | }; | ||
169 | |||
170 | pci3: pcie@ffe270000 { | ||
171 | reg = <0xf 0xfe270000 0 0x10000>; | ||
172 | ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x10000000 | ||
173 | 0x01000000 0 0x00000000 0xf 0xf8030000 0 0x00010000>; | ||
174 | pcie@0 { | ||
175 | ranges = <0x02000000 0 0xe0000000 | ||
176 | 0x02000000 0 0xe0000000 | ||
177 | 0 0x20000000 | ||
178 | |||
179 | 0x01000000 0 0x00000000 | ||
180 | 0x01000000 0 0x00000000 | ||
181 | 0 0x00010000>; | ||
182 | }; | ||
183 | }; | ||
184 | }; | ||
diff --git a/arch/powerpc/boot/dts/t4240rdb.dts b/arch/powerpc/boot/dts/t4240rdb.dts new file mode 100644 index 000000000000..53761d4e8c51 --- /dev/null +++ b/arch/powerpc/boot/dts/t4240rdb.dts | |||
@@ -0,0 +1,186 @@ | |||
1 | /* | ||
2 | * T4240RDB Device Tree Source | ||
3 | * | ||
4 | * Copyright 2014 Freescale Semiconductor Inc. | ||
5 | * | ||
6 | * Redistribution and use in source and binary forms, with or without | ||
7 | * modification, are permitted provided that the following conditions are met: | ||
8 | * * Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions and the following disclaimer. | ||
10 | * * Redistributions in binary form must reproduce the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer in the | ||
12 | * documentation and/or other materials provided with the distribution. | ||
13 | * * Neither the name of Freescale Semiconductor nor the | ||
14 | * names of its contributors may be used to endorse or promote products | ||
15 | * derived from this software without specific prior written permission. | ||
16 | * | ||
17 | * | ||
18 | * ALTERNATIVELY, this software may be distributed under the terms of the | ||
19 | * GNU General Public License ("GPL") as published by the Free Software | ||
20 | * Foundation, either version 2 of that License or (at your option) any | ||
21 | * later version. | ||
22 | * | ||
23 | * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY | ||
24 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
25 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
26 | * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY | ||
27 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
28 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
29 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
30 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
32 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
33 | */ | ||
34 | |||
35 | /include/ "fsl/t4240si-pre.dtsi" | ||
36 | |||
37 | / { | ||
38 | model = "fsl,T4240RDB"; | ||
39 | compatible = "fsl,T4240RDB"; | ||
40 | #address-cells = <2>; | ||
41 | #size-cells = <2>; | ||
42 | interrupt-parent = <&mpic>; | ||
43 | |||
44 | ifc: localbus@ffe124000 { | ||
45 | reg = <0xf 0xfe124000 0 0x2000>; | ||
46 | ranges = <0 0 0xf 0xe8000000 0x08000000 | ||
47 | 2 0 0xf 0xff800000 0x00010000 | ||
48 | 3 0 0xf 0xffdf0000 0x00008000>; | ||
49 | |||
50 | nor@0,0 { | ||
51 | #address-cells = <1>; | ||
52 | #size-cells = <1>; | ||
53 | compatible = "cfi-flash"; | ||
54 | reg = <0x0 0x0 0x8000000>; | ||
55 | |||
56 | bank-width = <2>; | ||
57 | device-width = <1>; | ||
58 | }; | ||
59 | |||
60 | nand@2,0 { | ||
61 | #address-cells = <1>; | ||
62 | #size-cells = <1>; | ||
63 | compatible = "fsl,ifc-nand"; | ||
64 | reg = <0x2 0x0 0x10000>; | ||
65 | }; | ||
66 | }; | ||
67 | |||
68 | memory { | ||
69 | device_type = "memory"; | ||
70 | }; | ||
71 | |||
72 | dcsr: dcsr@f00000000 { | ||
73 | ranges = <0x00000000 0xf 0x00000000 0x01072000>; | ||
74 | }; | ||
75 | |||
76 | soc: soc@ffe000000 { | ||
77 | ranges = <0x00000000 0xf 0xfe000000 0x1000000>; | ||
78 | reg = <0xf 0xfe000000 0 0x00001000>; | ||
79 | spi@110000 { | ||
80 | flash@0 { | ||
81 | #address-cells = <1>; | ||
82 | #size-cells = <1>; | ||
83 | compatible = "sst,sst25wf040"; | ||
84 | reg = <0>; | ||
85 | spi-max-frequency = <40000000>; /* input clock */ | ||
86 | }; | ||
87 | }; | ||
88 | |||
89 | i2c@118000 { | ||
90 | eeprom@52 { | ||
91 | compatible = "at24,24c256"; | ||
92 | reg = <0x52>; | ||
93 | }; | ||
94 | eeprom@54 { | ||
95 | compatible = "at24,24c256"; | ||
96 | reg = <0x54>; | ||
97 | }; | ||
98 | eeprom@56 { | ||
99 | compatible = "at24,24c256"; | ||
100 | reg = <0x56>; | ||
101 | }; | ||
102 | rtc@68 { | ||
103 | compatible = "dallas,ds1374"; | ||
104 | reg = <0x68>; | ||
105 | interrupts = <0x1 0x1 0 0>; | ||
106 | }; | ||
107 | }; | ||
108 | |||
109 | sdhc@114000 { | ||
110 | voltage-ranges = <1800 1800 3300 3300>; | ||
111 | }; | ||
112 | }; | ||
113 | |||
114 | pci0: pcie@ffe240000 { | ||
115 | reg = <0xf 0xfe240000 0 0x10000>; | ||
116 | ranges = <0x02000000 0 0xe0000000 0xc 0x00000000 0x0 0x20000000 | ||
117 | 0x01000000 0 0x00000000 0xf 0xf8000000 0x0 0x00010000>; | ||
118 | pcie@0 { | ||
119 | ranges = <0x02000000 0 0xe0000000 | ||
120 | 0x02000000 0 0xe0000000 | ||
121 | 0 0x20000000 | ||
122 | |||
123 | 0x01000000 0 0x00000000 | ||
124 | 0x01000000 0 0x00000000 | ||
125 | 0 0x00010000>; | ||
126 | }; | ||
127 | }; | ||
128 | |||
129 | pci1: pcie@ffe250000 { | ||
130 | reg = <0xf 0xfe250000 0 0x10000>; | ||
131 | ranges = <0x02000000 0x0 0xe0000000 0xc 0x20000000 0x0 0x20000000 | ||
132 | 0x01000000 0x0 0x00000000 0xf 0xf8010000 0x0 0x00010000>; | ||
133 | pcie@0 { | ||
134 | ranges = <0x02000000 0 0xe0000000 | ||
135 | 0x02000000 0 0xe0000000 | ||
136 | 0 0x20000000 | ||
137 | |||
138 | 0x01000000 0 0x00000000 | ||
139 | 0x01000000 0 0x00000000 | ||
140 | 0 0x00010000>; | ||
141 | }; | ||
142 | }; | ||
143 | |||
144 | pci2: pcie@ffe260000 { | ||
145 | reg = <0xf 0xfe260000 0 0x1000>; | ||
146 | ranges = <0x02000000 0 0xe0000000 0xc 0x40000000 0 0x20000000 | ||
147 | 0x01000000 0 0x00000000 0xf 0xf8020000 0 0x00010000>; | ||
148 | pcie@0 { | ||
149 | ranges = <0x02000000 0 0xe0000000 | ||
150 | 0x02000000 0 0xe0000000 | ||
151 | 0 0x20000000 | ||
152 | |||
153 | 0x01000000 0 0x00000000 | ||
154 | 0x01000000 0 0x00000000 | ||
155 | 0 0x00010000>; | ||
156 | }; | ||
157 | }; | ||
158 | |||
159 | pci3: pcie@ffe270000 { | ||
160 | reg = <0xf 0xfe270000 0 0x10000>; | ||
161 | ranges = <0x02000000 0 0xe0000000 0xc 0x60000000 0 0x20000000 | ||
162 | 0x01000000 0 0x00000000 0xf 0xf8030000 0 0x00010000>; | ||
163 | pcie@0 { | ||
164 | ranges = <0x02000000 0 0xe0000000 | ||
165 | 0x02000000 0 0xe0000000 | ||
166 | 0 0x20000000 | ||
167 | |||
168 | 0x01000000 0 0x00000000 | ||
169 | 0x01000000 0 0x00000000 | ||
170 | 0 0x00010000>; | ||
171 | }; | ||
172 | }; | ||
173 | |||
174 | rio: rapidio@ffe0c0000 { | ||
175 | reg = <0xf 0xfe0c0000 0 0x11000>; | ||
176 | |||
177 | port1 { | ||
178 | ranges = <0 0 0xc 0x20000000 0 0x10000000>; | ||
179 | }; | ||
180 | port2 { | ||
181 | ranges = <0 0 0xc 0x30000000 0 0x10000000>; | ||
182 | }; | ||
183 | }; | ||
184 | }; | ||
185 | |||
186 | /include/ "fsl/t4240si-post.dtsi" | ||
diff --git a/arch/powerpc/boot/gunzip_util.c b/arch/powerpc/boot/gunzip_util.c index ef2aed0f63ca..9dc52501de83 100644 --- a/arch/powerpc/boot/gunzip_util.c +++ b/arch/powerpc/boot/gunzip_util.c | |||
@@ -112,10 +112,10 @@ int gunzip_partial(struct gunzip_state *state, void *dst, int dstlen) | |||
112 | r = zlib_inflate(&state->s, Z_FULL_FLUSH); | 112 | r = zlib_inflate(&state->s, Z_FULL_FLUSH); |
113 | if (r != Z_OK && r != Z_STREAM_END) | 113 | if (r != Z_OK && r != Z_STREAM_END) |
114 | fatal("inflate returned %d msg: %s\n\r", r, state->s.msg); | 114 | fatal("inflate returned %d msg: %s\n\r", r, state->s.msg); |
115 | len = state->s.next_out - (unsigned char *)dst; | 115 | len = state->s.next_out - (Byte *)dst; |
116 | } else { | 116 | } else { |
117 | /* uncompressed image */ | 117 | /* uncompressed image */ |
118 | len = min(state->s.avail_in, (unsigned)dstlen); | 118 | len = min(state->s.avail_in, (uLong)dstlen); |
119 | memcpy(dst, state->s.next_in, len); | 119 | memcpy(dst, state->s.next_in, len); |
120 | state->s.next_in += len; | 120 | state->s.next_in += len; |
121 | state->s.avail_in -= len; | 121 | state->s.avail_in -= len; |
diff --git a/arch/powerpc/boot/io.h b/arch/powerpc/boot/io.h index 7c09f4861fe1..394da5500466 100644 --- a/arch/powerpc/boot/io.h +++ b/arch/powerpc/boot/io.h | |||
@@ -1,5 +1,5 @@ | |||
1 | #ifndef _IO_H | 1 | #ifndef _IO_H |
2 | #define __IO_H | 2 | #define _IO_H |
3 | 3 | ||
4 | #include "types.h" | 4 | #include "types.h" |
5 | 5 | ||
diff --git a/arch/powerpc/configs/52xx/motionpro_defconfig b/arch/powerpc/configs/52xx/motionpro_defconfig index c05310a913be..c936fab9ec4a 100644 --- a/arch/powerpc/configs/52xx/motionpro_defconfig +++ b/arch/powerpc/configs/52xx/motionpro_defconfig | |||
@@ -43,7 +43,6 @@ CONFIG_BLK_DEV_RAM=y | |||
43 | CONFIG_BLK_DEV_RAM_SIZE=32768 | 43 | CONFIG_BLK_DEV_RAM_SIZE=32768 |
44 | CONFIG_MISC_DEVICES=y | 44 | CONFIG_MISC_DEVICES=y |
45 | CONFIG_EEPROM_LEGACY=y | 45 | CONFIG_EEPROM_LEGACY=y |
46 | CONFIG_SCSI_TGT=y | ||
47 | CONFIG_BLK_DEV_SD=y | 46 | CONFIG_BLK_DEV_SD=y |
48 | CONFIG_CHR_DEV_SG=y | 47 | CONFIG_CHR_DEV_SG=y |
49 | CONFIG_ATA=y | 48 | CONFIG_ATA=y |
diff --git a/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig b/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig index bcbe74716689..9b192bb6bd3d 100644 --- a/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig +++ b/arch/powerpc/configs/86xx/mpc8610_hpcd_defconfig | |||
@@ -54,7 +54,6 @@ CONFIG_BLK_DEV_LOOP=y | |||
54 | CONFIG_BLK_DEV_RAM=y | 54 | CONFIG_BLK_DEV_RAM=y |
55 | CONFIG_BLK_DEV_RAM_SIZE=131072 | 55 | CONFIG_BLK_DEV_RAM_SIZE=131072 |
56 | CONFIG_IDE=y | 56 | CONFIG_IDE=y |
57 | CONFIG_SCSI_TGT=y | ||
58 | CONFIG_BLK_DEV_SD=y | 57 | CONFIG_BLK_DEV_SD=y |
59 | CONFIG_CHR_DEV_SG=y | 58 | CONFIG_CHR_DEV_SG=y |
60 | CONFIG_ATA=y | 59 | CONFIG_ATA=y |
diff --git a/arch/powerpc/configs/corenet32_smp_defconfig b/arch/powerpc/configs/corenet32_smp_defconfig index c19ff057d0f9..6a3c58adf253 100644 --- a/arch/powerpc/configs/corenet32_smp_defconfig +++ b/arch/powerpc/configs/corenet32_smp_defconfig | |||
@@ -139,8 +139,9 @@ CONFIG_EDAC=y | |||
139 | CONFIG_EDAC_MM_EDAC=y | 139 | CONFIG_EDAC_MM_EDAC=y |
140 | CONFIG_EDAC_MPC85XX=y | 140 | CONFIG_EDAC_MPC85XX=y |
141 | CONFIG_RTC_CLASS=y | 141 | CONFIG_RTC_CLASS=y |
142 | CONFIG_RTC_DRV_DS1307=y | ||
143 | CONFIG_RTC_DRV_DS1374=y | ||
142 | CONFIG_RTC_DRV_DS3232=y | 144 | CONFIG_RTC_DRV_DS3232=y |
143 | CONFIG_RTC_DRV_CMOS=y | ||
144 | CONFIG_UIO=y | 145 | CONFIG_UIO=y |
145 | CONFIG_STAGING=y | 146 | CONFIG_STAGING=y |
146 | CONFIG_VIRT_DRIVERS=y | 147 | CONFIG_VIRT_DRIVERS=y |
@@ -179,3 +180,4 @@ CONFIG_CRYPTO_SHA512=y | |||
179 | CONFIG_CRYPTO_AES=y | 180 | CONFIG_CRYPTO_AES=y |
180 | # CONFIG_CRYPTO_ANSI_CPRNG is not set | 181 | # CONFIG_CRYPTO_ANSI_CPRNG is not set |
181 | CONFIG_CRYPTO_DEV_FSL_CAAM=y | 182 | CONFIG_CRYPTO_DEV_FSL_CAAM=y |
183 | CONFIG_FSL_CORENET_CF=y | ||
diff --git a/arch/powerpc/configs/corenet64_smp_defconfig b/arch/powerpc/configs/corenet64_smp_defconfig index 5c7fa19ae4ef..4b07bade1ba9 100644 --- a/arch/powerpc/configs/corenet64_smp_defconfig +++ b/arch/powerpc/configs/corenet64_smp_defconfig | |||
@@ -123,6 +123,10 @@ CONFIG_USB_EHCI_FSL=y | |||
123 | CONFIG_USB_STORAGE=y | 123 | CONFIG_USB_STORAGE=y |
124 | CONFIG_MMC=y | 124 | CONFIG_MMC=y |
125 | CONFIG_MMC_SDHCI=y | 125 | CONFIG_MMC_SDHCI=y |
126 | CONFIG_RTC_CLASS=y | ||
127 | CONFIG_RTC_DRV_DS1307=y | ||
128 | CONFIG_RTC_DRV_DS1374=y | ||
129 | CONFIG_RTC_DRV_DS3232=y | ||
126 | CONFIG_EDAC=y | 130 | CONFIG_EDAC=y |
127 | CONFIG_EDAC_MM_EDAC=y | 131 | CONFIG_EDAC_MM_EDAC=y |
128 | CONFIG_DMADEVICES=y | 132 | CONFIG_DMADEVICES=y |
@@ -175,3 +179,4 @@ CONFIG_CRYPTO_SHA256=y | |||
175 | CONFIG_CRYPTO_SHA512=y | 179 | CONFIG_CRYPTO_SHA512=y |
176 | # CONFIG_CRYPTO_ANSI_CPRNG is not set | 180 | # CONFIG_CRYPTO_ANSI_CPRNG is not set |
177 | CONFIG_CRYPTO_DEV_FSL_CAAM=y | 181 | CONFIG_CRYPTO_DEV_FSL_CAAM=y |
182 | CONFIG_FSL_CORENET_CF=y | ||
diff --git a/arch/powerpc/configs/mpc5200_defconfig b/arch/powerpc/configs/mpc5200_defconfig index 530601e8ccfe..69fd8adf9f5e 100644 --- a/arch/powerpc/configs/mpc5200_defconfig +++ b/arch/powerpc/configs/mpc5200_defconfig | |||
@@ -47,7 +47,6 @@ CONFIG_BLK_DEV_LOOP=y | |||
47 | CONFIG_BLK_DEV_RAM=y | 47 | CONFIG_BLK_DEV_RAM=y |
48 | CONFIG_BLK_DEV_RAM_SIZE=32768 | 48 | CONFIG_BLK_DEV_RAM_SIZE=32768 |
49 | CONFIG_EEPROM_AT24=y | 49 | CONFIG_EEPROM_AT24=y |
50 | CONFIG_SCSI_TGT=y | ||
51 | CONFIG_BLK_DEV_SD=y | 50 | CONFIG_BLK_DEV_SD=y |
52 | CONFIG_CHR_DEV_SG=y | 51 | CONFIG_CHR_DEV_SG=y |
53 | CONFIG_ATA=y | 52 | CONFIG_ATA=y |
diff --git a/arch/powerpc/configs/mpc85xx_defconfig b/arch/powerpc/configs/mpc85xx_defconfig index 55765c8cb08f..fa1bfd37f1ec 100644 --- a/arch/powerpc/configs/mpc85xx_defconfig +++ b/arch/powerpc/configs/mpc85xx_defconfig | |||
@@ -209,6 +209,9 @@ CONFIG_MMC_SDHCI_OF_ESDHC=y | |||
209 | CONFIG_EDAC=y | 209 | CONFIG_EDAC=y |
210 | CONFIG_EDAC_MM_EDAC=y | 210 | CONFIG_EDAC_MM_EDAC=y |
211 | CONFIG_RTC_CLASS=y | 211 | CONFIG_RTC_CLASS=y |
212 | CONFIG_RTC_DRV_DS1307=y | ||
213 | CONFIG_RTC_DRV_DS1374=y | ||
214 | CONFIG_RTC_DRV_DS3232=y | ||
212 | CONFIG_RTC_DRV_CMOS=y | 215 | CONFIG_RTC_DRV_CMOS=y |
213 | CONFIG_RTC_DRV_DS1307=y | 216 | CONFIG_RTC_DRV_DS1307=y |
214 | CONFIG_DMADEVICES=y | 217 | CONFIG_DMADEVICES=y |
diff --git a/arch/powerpc/configs/mpc85xx_smp_defconfig b/arch/powerpc/configs/mpc85xx_smp_defconfig index 5c6ecdc0f70e..0b452ebd8b3d 100644 --- a/arch/powerpc/configs/mpc85xx_smp_defconfig +++ b/arch/powerpc/configs/mpc85xx_smp_defconfig | |||
@@ -210,6 +210,9 @@ CONFIG_MMC_SDHCI_OF_ESDHC=y | |||
210 | CONFIG_EDAC=y | 210 | CONFIG_EDAC=y |
211 | CONFIG_EDAC_MM_EDAC=y | 211 | CONFIG_EDAC_MM_EDAC=y |
212 | CONFIG_RTC_CLASS=y | 212 | CONFIG_RTC_CLASS=y |
213 | CONFIG_RTC_DRV_DS1307=y | ||
214 | CONFIG_RTC_DRV_DS1374=y | ||
215 | CONFIG_RTC_DRV_DS3232=y | ||
213 | CONFIG_RTC_DRV_CMOS=y | 216 | CONFIG_RTC_DRV_CMOS=y |
214 | CONFIG_RTC_DRV_DS1307=y | 217 | CONFIG_RTC_DRV_DS1307=y |
215 | CONFIG_DMADEVICES=y | 218 | CONFIG_DMADEVICES=y |
diff --git a/arch/powerpc/configs/ppc44x_defconfig b/arch/powerpc/configs/ppc44x_defconfig index ccf66b9060a6..924e10df1844 100644 --- a/arch/powerpc/configs/ppc44x_defconfig +++ b/arch/powerpc/configs/ppc44x_defconfig | |||
@@ -127,4 +127,3 @@ CONFIG_CRYPTO_PCBC=y | |||
127 | # CONFIG_CRYPTO_ANSI_CPRNG is not set | 127 | # CONFIG_CRYPTO_ANSI_CPRNG is not set |
128 | # CONFIG_CRYPTO_HW is not set | 128 | # CONFIG_CRYPTO_HW is not set |
129 | CONFIG_VIRTUALIZATION=y | 129 | CONFIG_VIRTUALIZATION=y |
130 | CONFIG_KVM_440=y | ||
diff --git a/arch/powerpc/configs/ppc6xx_defconfig b/arch/powerpc/configs/ppc6xx_defconfig index c91066944842..fec5870f1818 100644 --- a/arch/powerpc/configs/ppc6xx_defconfig +++ b/arch/powerpc/configs/ppc6xx_defconfig | |||
@@ -425,10 +425,8 @@ CONFIG_SCSI_LOGGING=y | |||
425 | CONFIG_SCSI_SCAN_ASYNC=y | 425 | CONFIG_SCSI_SCAN_ASYNC=y |
426 | CONFIG_SCSI_SPI_ATTRS=m | 426 | CONFIG_SCSI_SPI_ATTRS=m |
427 | CONFIG_SCSI_SRP_ATTRS=m | 427 | CONFIG_SCSI_SRP_ATTRS=m |
428 | CONFIG_SCSI_SRP_TGT_ATTRS=y | ||
429 | CONFIG_SCSI_MESH=m | 428 | CONFIG_SCSI_MESH=m |
430 | CONFIG_SCSI_MAC53C94=m | 429 | CONFIG_SCSI_MAC53C94=m |
431 | CONFIG_SCSI_SRP=m | ||
432 | CONFIG_SCSI_LOWLEVEL_PCMCIA=y | 430 | CONFIG_SCSI_LOWLEVEL_PCMCIA=y |
433 | CONFIG_SCSI_DH=y | 431 | CONFIG_SCSI_DH=y |
434 | CONFIG_SCSI_DH_RDAC=m | 432 | CONFIG_SCSI_DH_RDAC=m |
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild index 3fb1bc432f4f..7f23f162ce9c 100644 --- a/arch/powerpc/include/asm/Kbuild +++ b/arch/powerpc/include/asm/Kbuild | |||
@@ -4,5 +4,6 @@ generic-y += hash.h | |||
4 | generic-y += mcs_spinlock.h | 4 | generic-y += mcs_spinlock.h |
5 | generic-y += preempt.h | 5 | generic-y += preempt.h |
6 | generic-y += rwsem.h | 6 | generic-y += rwsem.h |
7 | generic-y += scatterlist.h | ||
7 | generic-y += trace_clock.h | 8 | generic-y += trace_clock.h |
8 | generic-y += vtime.h | 9 | generic-y += vtime.h |
diff --git a/arch/powerpc/include/asm/asm-compat.h b/arch/powerpc/include/asm/asm-compat.h index 4b237aa35660..21be8ae8f809 100644 --- a/arch/powerpc/include/asm/asm-compat.h +++ b/arch/powerpc/include/asm/asm-compat.h | |||
@@ -34,10 +34,14 @@ | |||
34 | #define PPC_MIN_STKFRM 112 | 34 | #define PPC_MIN_STKFRM 112 |
35 | 35 | ||
36 | #ifdef __BIG_ENDIAN__ | 36 | #ifdef __BIG_ENDIAN__ |
37 | #define LWZX_BE stringify_in_c(lwzx) | ||
37 | #define LDX_BE stringify_in_c(ldx) | 38 | #define LDX_BE stringify_in_c(ldx) |
39 | #define STWX_BE stringify_in_c(stwx) | ||
38 | #define STDX_BE stringify_in_c(stdx) | 40 | #define STDX_BE stringify_in_c(stdx) |
39 | #else | 41 | #else |
42 | #define LWZX_BE stringify_in_c(lwbrx) | ||
40 | #define LDX_BE stringify_in_c(ldbrx) | 43 | #define LDX_BE stringify_in_c(ldbrx) |
44 | #define STWX_BE stringify_in_c(stwbrx) | ||
41 | #define STDX_BE stringify_in_c(stdbrx) | 45 | #define STDX_BE stringify_in_c(stdbrx) |
42 | #endif | 46 | #endif |
43 | 47 | ||
diff --git a/arch/powerpc/include/asm/cache.h b/arch/powerpc/include/asm/cache.h index ed0afc1e44a4..34a05a1a990b 100644 --- a/arch/powerpc/include/asm/cache.h +++ b/arch/powerpc/include/asm/cache.h | |||
@@ -3,6 +3,7 @@ | |||
3 | 3 | ||
4 | #ifdef __KERNEL__ | 4 | #ifdef __KERNEL__ |
5 | 5 | ||
6 | #include <asm/reg.h> | ||
6 | 7 | ||
7 | /* bytes per L1 cache line */ | 8 | /* bytes per L1 cache line */ |
8 | #if defined(CONFIG_8xx) || defined(CONFIG_403GCX) | 9 | #if defined(CONFIG_8xx) || defined(CONFIG_403GCX) |
@@ -39,6 +40,12 @@ struct ppc64_caches { | |||
39 | }; | 40 | }; |
40 | 41 | ||
41 | extern struct ppc64_caches ppc64_caches; | 42 | extern struct ppc64_caches ppc64_caches; |
43 | |||
44 | static inline void logmpp(u64 x) | ||
45 | { | ||
46 | asm volatile(PPC_LOGMPP(R1) : : "r" (x)); | ||
47 | } | ||
48 | |||
42 | #endif /* __powerpc64__ && ! __ASSEMBLY__ */ | 49 | #endif /* __powerpc64__ && ! __ASSEMBLY__ */ |
43 | 50 | ||
44 | #if defined(__ASSEMBLY__) | 51 | #if defined(__ASSEMBLY__) |
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h index 0fdd7eece6d9..daa5af91163c 100644 --- a/arch/powerpc/include/asm/cputable.h +++ b/arch/powerpc/include/asm/cputable.h | |||
@@ -195,8 +195,7 @@ extern const char *powerpc_base_platform; | |||
195 | 195 | ||
196 | #define CPU_FTR_PPCAS_ARCH_V2 (CPU_FTR_NOEXECUTE | CPU_FTR_NODSISRALIGN) | 196 | #define CPU_FTR_PPCAS_ARCH_V2 (CPU_FTR_NOEXECUTE | CPU_FTR_NODSISRALIGN) |
197 | 197 | ||
198 | #define MMU_FTR_PPCAS_ARCH_V2 (MMU_FTR_SLB | MMU_FTR_TLBIEL | \ | 198 | #define MMU_FTR_PPCAS_ARCH_V2 (MMU_FTR_TLBIEL | MMU_FTR_16M_PAGE) |
199 | MMU_FTR_16M_PAGE) | ||
200 | 199 | ||
201 | /* We only set the altivec features if the kernel was compiled with altivec | 200 | /* We only set the altivec features if the kernel was compiled with altivec |
202 | * support | 201 | * support |
@@ -268,10 +267,6 @@ extern const char *powerpc_base_platform; | |||
268 | #define CPU_FTR_MAYBE_CAN_NAP 0 | 267 | #define CPU_FTR_MAYBE_CAN_NAP 0 |
269 | #endif | 268 | #endif |
270 | 269 | ||
271 | #define CLASSIC_PPC (!defined(CONFIG_8xx) && !defined(CONFIG_4xx) && \ | ||
272 | !defined(CONFIG_POWER3) && !defined(CONFIG_POWER4) && \ | ||
273 | !defined(CONFIG_BOOKE)) | ||
274 | |||
275 | #define CPU_FTRS_PPC601 (CPU_FTR_COMMON | CPU_FTR_601 | \ | 270 | #define CPU_FTRS_PPC601 (CPU_FTR_COMMON | CPU_FTR_601 | \ |
276 | CPU_FTR_COHERENT_ICACHE | CPU_FTR_UNIFIED_ID_CACHE) | 271 | CPU_FTR_COHERENT_ICACHE | CPU_FTR_UNIFIED_ID_CACHE) |
277 | #define CPU_FTRS_603 (CPU_FTR_COMMON | \ | 272 | #define CPU_FTRS_603 (CPU_FTR_COMMON | \ |
@@ -396,15 +391,10 @@ extern const char *powerpc_base_platform; | |||
396 | CPU_FTR_L2CSR | CPU_FTR_LWSYNC | CPU_FTR_NOEXECUTE | \ | 391 | CPU_FTR_L2CSR | CPU_FTR_LWSYNC | CPU_FTR_NOEXECUTE | \ |
397 | CPU_FTR_DBELL | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \ | 392 | CPU_FTR_DBELL | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \ |
398 | CPU_FTR_DEBUG_LVL_EXC | CPU_FTR_EMB_HV | CPU_FTR_ALTIVEC_COMP | \ | 393 | CPU_FTR_DEBUG_LVL_EXC | CPU_FTR_EMB_HV | CPU_FTR_ALTIVEC_COMP | \ |
399 | CPU_FTR_CELL_TB_BUG) | 394 | CPU_FTR_CELL_TB_BUG | CPU_FTR_SMT) |
400 | #define CPU_FTRS_GENERIC_32 (CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN) | 395 | #define CPU_FTRS_GENERIC_32 (CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN) |
401 | 396 | ||
402 | /* 64-bit CPUs */ | 397 | /* 64-bit CPUs */ |
403 | #define CPU_FTRS_POWER3 (CPU_FTR_USE_TB | \ | ||
404 | CPU_FTR_IABR | CPU_FTR_PPC_LE) | ||
405 | #define CPU_FTRS_RS64 (CPU_FTR_USE_TB | \ | ||
406 | CPU_FTR_IABR | \ | ||
407 | CPU_FTR_MMCRA | CPU_FTR_CTRL) | ||
408 | #define CPU_FTRS_POWER4 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \ | 398 | #define CPU_FTRS_POWER4 (CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \ |
409 | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ | 399 | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ |
410 | CPU_FTR_MMCRA | CPU_FTR_CP_USE_DCBTZ | \ | 400 | CPU_FTR_MMCRA | CPU_FTR_CP_USE_DCBTZ | \ |
@@ -467,15 +457,15 @@ extern const char *powerpc_base_platform; | |||
467 | #define CPU_FTRS_POSSIBLE (CPU_FTRS_E6500 | CPU_FTRS_E5500 | CPU_FTRS_A2) | 457 | #define CPU_FTRS_POSSIBLE (CPU_FTRS_E6500 | CPU_FTRS_E5500 | CPU_FTRS_A2) |
468 | #else | 458 | #else |
469 | #define CPU_FTRS_POSSIBLE \ | 459 | #define CPU_FTRS_POSSIBLE \ |
470 | (CPU_FTRS_POWER3 | CPU_FTRS_RS64 | CPU_FTRS_POWER4 | \ | 460 | (CPU_FTRS_POWER4 | CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | \ |
471 | CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | CPU_FTRS_POWER6 | \ | 461 | CPU_FTRS_POWER6 | CPU_FTRS_POWER7 | CPU_FTRS_POWER8E | \ |
472 | CPU_FTRS_POWER7 | CPU_FTRS_POWER8E | CPU_FTRS_POWER8 | \ | 462 | CPU_FTRS_POWER8 | CPU_FTRS_POWER8_DD1 | CPU_FTRS_CELL | \ |
473 | CPU_FTRS_CELL | CPU_FTRS_PA6T | CPU_FTR_VSX) | 463 | CPU_FTRS_PA6T | CPU_FTR_VSX) |
474 | #endif | 464 | #endif |
475 | #else | 465 | #else |
476 | enum { | 466 | enum { |
477 | CPU_FTRS_POSSIBLE = | 467 | CPU_FTRS_POSSIBLE = |
478 | #if CLASSIC_PPC | 468 | #ifdef CONFIG_PPC_BOOK3S_32 |
479 | CPU_FTRS_PPC601 | CPU_FTRS_603 | CPU_FTRS_604 | CPU_FTRS_740_NOTAU | | 469 | CPU_FTRS_PPC601 | CPU_FTRS_603 | CPU_FTRS_604 | CPU_FTRS_740_NOTAU | |
480 | CPU_FTRS_740 | CPU_FTRS_750 | CPU_FTRS_750FX1 | | 470 | CPU_FTRS_740 | CPU_FTRS_750 | CPU_FTRS_750FX1 | |
481 | CPU_FTRS_750FX2 | CPU_FTRS_750FX | CPU_FTRS_750GX | | 471 | CPU_FTRS_750FX2 | CPU_FTRS_750FX | CPU_FTRS_750GX | |
@@ -518,14 +508,15 @@ enum { | |||
518 | #define CPU_FTRS_ALWAYS (CPU_FTRS_E6500 & CPU_FTRS_E5500 & CPU_FTRS_A2) | 508 | #define CPU_FTRS_ALWAYS (CPU_FTRS_E6500 & CPU_FTRS_E5500 & CPU_FTRS_A2) |
519 | #else | 509 | #else |
520 | #define CPU_FTRS_ALWAYS \ | 510 | #define CPU_FTRS_ALWAYS \ |
521 | (CPU_FTRS_POWER3 & CPU_FTRS_RS64 & CPU_FTRS_POWER4 & \ | 511 | (CPU_FTRS_POWER4 & CPU_FTRS_PPC970 & CPU_FTRS_POWER5 & \ |
522 | CPU_FTRS_PPC970 & CPU_FTRS_POWER5 & CPU_FTRS_POWER6 & \ | 512 | CPU_FTRS_POWER6 & CPU_FTRS_POWER7 & CPU_FTRS_CELL & \ |
523 | CPU_FTRS_POWER7 & CPU_FTRS_CELL & CPU_FTRS_PA6T & CPU_FTRS_POSSIBLE) | 513 | CPU_FTRS_PA6T & CPU_FTRS_POWER8 & CPU_FTRS_POWER8E & \ |
514 | CPU_FTRS_POWER8_DD1 & CPU_FTRS_POSSIBLE) | ||
524 | #endif | 515 | #endif |
525 | #else | 516 | #else |
526 | enum { | 517 | enum { |
527 | CPU_FTRS_ALWAYS = | 518 | CPU_FTRS_ALWAYS = |
528 | #if CLASSIC_PPC | 519 | #ifdef CONFIG_PPC_BOOK3S_32 |
529 | CPU_FTRS_PPC601 & CPU_FTRS_603 & CPU_FTRS_604 & CPU_FTRS_740_NOTAU & | 520 | CPU_FTRS_PPC601 & CPU_FTRS_603 & CPU_FTRS_604 & CPU_FTRS_740_NOTAU & |
530 | CPU_FTRS_740 & CPU_FTRS_750 & CPU_FTRS_750FX1 & | 521 | CPU_FTRS_740 & CPU_FTRS_750 & CPU_FTRS_750FX1 & |
531 | CPU_FTRS_750FX2 & CPU_FTRS_750FX & CPU_FTRS_750GX & | 522 | CPU_FTRS_750FX2 & CPU_FTRS_750FX & CPU_FTRS_750GX & |
diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h index fab7743c2640..9983c3d26bca 100644 --- a/arch/powerpc/include/asm/eeh.h +++ b/arch/powerpc/include/asm/eeh.h | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/list.h> | 25 | #include <linux/list.h> |
26 | #include <linux/string.h> | 26 | #include <linux/string.h> |
27 | #include <linux/time.h> | 27 | #include <linux/time.h> |
28 | #include <linux/atomic.h> | ||
28 | 29 | ||
29 | struct pci_dev; | 30 | struct pci_dev; |
30 | struct pci_bus; | 31 | struct pci_bus; |
@@ -33,10 +34,11 @@ struct device_node; | |||
33 | #ifdef CONFIG_EEH | 34 | #ifdef CONFIG_EEH |
34 | 35 | ||
35 | /* EEH subsystem flags */ | 36 | /* EEH subsystem flags */ |
36 | #define EEH_ENABLED 0x1 /* EEH enabled */ | 37 | #define EEH_ENABLED 0x01 /* EEH enabled */ |
37 | #define EEH_FORCE_DISABLED 0x2 /* EEH disabled */ | 38 | #define EEH_FORCE_DISABLED 0x02 /* EEH disabled */ |
38 | #define EEH_PROBE_MODE_DEV 0x4 /* From PCI device */ | 39 | #define EEH_PROBE_MODE_DEV 0x04 /* From PCI device */ |
39 | #define EEH_PROBE_MODE_DEVTREE 0x8 /* From device tree */ | 40 | #define EEH_PROBE_MODE_DEVTREE 0x08 /* From device tree */ |
41 | #define EEH_ENABLE_IO_FOR_LOG 0x10 /* Enable IO for log */ | ||
40 | 42 | ||
41 | /* | 43 | /* |
42 | * Delay for PE reset, all in ms | 44 | * Delay for PE reset, all in ms |
@@ -84,7 +86,9 @@ struct eeh_pe { | |||
84 | int freeze_count; /* Times of froze up */ | 86 | int freeze_count; /* Times of froze up */ |
85 | struct timeval tstamp; /* Time on first-time freeze */ | 87 | struct timeval tstamp; /* Time on first-time freeze */ |
86 | int false_positives; /* Times of reported #ff's */ | 88 | int false_positives; /* Times of reported #ff's */ |
89 | atomic_t pass_dev_cnt; /* Count of passed through devs */ | ||
87 | struct eeh_pe *parent; /* Parent PE */ | 90 | struct eeh_pe *parent; /* Parent PE */ |
91 | void *data; /* PE auxillary data */ | ||
88 | struct list_head child_list; /* Link PE to the child list */ | 92 | struct list_head child_list; /* Link PE to the child list */ |
89 | struct list_head edevs; /* Link list of EEH devices */ | 93 | struct list_head edevs; /* Link list of EEH devices */ |
90 | struct list_head child; /* Child PEs */ | 94 | struct list_head child; /* Child PEs */ |
@@ -93,6 +97,11 @@ struct eeh_pe { | |||
93 | #define eeh_pe_for_each_dev(pe, edev, tmp) \ | 97 | #define eeh_pe_for_each_dev(pe, edev, tmp) \ |
94 | list_for_each_entry_safe(edev, tmp, &pe->edevs, list) | 98 | list_for_each_entry_safe(edev, tmp, &pe->edevs, list) |
95 | 99 | ||
100 | static inline bool eeh_pe_passed(struct eeh_pe *pe) | ||
101 | { | ||
102 | return pe ? !!atomic_read(&pe->pass_dev_cnt) : false; | ||
103 | } | ||
104 | |||
96 | /* | 105 | /* |
97 | * The struct is used to trace EEH state for the associated | 106 | * The struct is used to trace EEH state for the associated |
98 | * PCI device node or PCI device. In future, it might | 107 | * PCI device node or PCI device. In future, it might |
@@ -165,6 +174,11 @@ enum { | |||
165 | #define EEH_STATE_DMA_ACTIVE (1 << 4) /* Active DMA */ | 174 | #define EEH_STATE_DMA_ACTIVE (1 << 4) /* Active DMA */ |
166 | #define EEH_STATE_MMIO_ENABLED (1 << 5) /* MMIO enabled */ | 175 | #define EEH_STATE_MMIO_ENABLED (1 << 5) /* MMIO enabled */ |
167 | #define EEH_STATE_DMA_ENABLED (1 << 6) /* DMA enabled */ | 176 | #define EEH_STATE_DMA_ENABLED (1 << 6) /* DMA enabled */ |
177 | #define EEH_PE_STATE_NORMAL 0 /* Normal state */ | ||
178 | #define EEH_PE_STATE_RESET 1 /* PE reset asserted */ | ||
179 | #define EEH_PE_STATE_STOPPED_IO_DMA 2 /* Frozen PE */ | ||
180 | #define EEH_PE_STATE_STOPPED_DMA 4 /* Stopped DMA, Enabled IO */ | ||
181 | #define EEH_PE_STATE_UNAVAIL 5 /* Unavailable */ | ||
168 | #define EEH_RESET_DEACTIVATE 0 /* Deactivate the PE reset */ | 182 | #define EEH_RESET_DEACTIVATE 0 /* Deactivate the PE reset */ |
169 | #define EEH_RESET_HOT 1 /* Hot reset */ | 183 | #define EEH_RESET_HOT 1 /* Hot reset */ |
170 | #define EEH_RESET_FUNDAMENTAL 3 /* Fundamental reset */ | 184 | #define EEH_RESET_FUNDAMENTAL 3 /* Fundamental reset */ |
@@ -194,36 +208,28 @@ extern int eeh_subsystem_flags; | |||
194 | extern struct eeh_ops *eeh_ops; | 208 | extern struct eeh_ops *eeh_ops; |
195 | extern raw_spinlock_t confirm_error_lock; | 209 | extern raw_spinlock_t confirm_error_lock; |
196 | 210 | ||
197 | static inline bool eeh_enabled(void) | 211 | static inline void eeh_add_flag(int flag) |
198 | { | 212 | { |
199 | if ((eeh_subsystem_flags & EEH_FORCE_DISABLED) || | 213 | eeh_subsystem_flags |= flag; |
200 | !(eeh_subsystem_flags & EEH_ENABLED)) | ||
201 | return false; | ||
202 | |||
203 | return true; | ||
204 | } | 214 | } |
205 | 215 | ||
206 | static inline void eeh_set_enable(bool mode) | 216 | static inline void eeh_clear_flag(int flag) |
207 | { | 217 | { |
208 | if (mode) | 218 | eeh_subsystem_flags &= ~flag; |
209 | eeh_subsystem_flags |= EEH_ENABLED; | ||
210 | else | ||
211 | eeh_subsystem_flags &= ~EEH_ENABLED; | ||
212 | } | 219 | } |
213 | 220 | ||
214 | static inline void eeh_probe_mode_set(int flag) | 221 | static inline bool eeh_has_flag(int flag) |
215 | { | 222 | { |
216 | eeh_subsystem_flags |= flag; | 223 | return !!(eeh_subsystem_flags & flag); |
217 | } | 224 | } |
218 | 225 | ||
219 | static inline int eeh_probe_mode_devtree(void) | 226 | static inline bool eeh_enabled(void) |
220 | { | 227 | { |
221 | return (eeh_subsystem_flags & EEH_PROBE_MODE_DEVTREE); | 228 | if (eeh_has_flag(EEH_FORCE_DISABLED) || |
222 | } | 229 | !eeh_has_flag(EEH_ENABLED)) |
230 | return false; | ||
223 | 231 | ||
224 | static inline int eeh_probe_mode_dev(void) | 232 | return true; |
225 | { | ||
226 | return (eeh_subsystem_flags & EEH_PROBE_MODE_DEV); | ||
227 | } | 233 | } |
228 | 234 | ||
229 | static inline void eeh_serialize_lock(unsigned long *flags) | 235 | static inline void eeh_serialize_lock(unsigned long *flags) |
@@ -243,6 +249,7 @@ static inline void eeh_serialize_unlock(unsigned long flags) | |||
243 | #define EEH_MAX_ALLOWED_FREEZES 5 | 249 | #define EEH_MAX_ALLOWED_FREEZES 5 |
244 | 250 | ||
245 | typedef void *(*eeh_traverse_func)(void *data, void *flag); | 251 | typedef void *(*eeh_traverse_func)(void *data, void *flag); |
252 | void eeh_set_pe_aux_size(int size); | ||
246 | int eeh_phb_pe_create(struct pci_controller *phb); | 253 | int eeh_phb_pe_create(struct pci_controller *phb); |
247 | struct eeh_pe *eeh_phb_pe_get(struct pci_controller *phb); | 254 | struct eeh_pe *eeh_phb_pe_get(struct pci_controller *phb); |
248 | struct eeh_pe *eeh_pe_get(struct eeh_dev *edev); | 255 | struct eeh_pe *eeh_pe_get(struct eeh_dev *edev); |
@@ -272,6 +279,13 @@ void eeh_add_device_late(struct pci_dev *); | |||
272 | void eeh_add_device_tree_late(struct pci_bus *); | 279 | void eeh_add_device_tree_late(struct pci_bus *); |
273 | void eeh_add_sysfs_files(struct pci_bus *); | 280 | void eeh_add_sysfs_files(struct pci_bus *); |
274 | void eeh_remove_device(struct pci_dev *); | 281 | void eeh_remove_device(struct pci_dev *); |
282 | int eeh_dev_open(struct pci_dev *pdev); | ||
283 | void eeh_dev_release(struct pci_dev *pdev); | ||
284 | struct eeh_pe *eeh_iommu_group_to_pe(struct iommu_group *group); | ||
285 | int eeh_pe_set_option(struct eeh_pe *pe, int option); | ||
286 | int eeh_pe_get_state(struct eeh_pe *pe); | ||
287 | int eeh_pe_reset(struct eeh_pe *pe, int option); | ||
288 | int eeh_pe_configure(struct eeh_pe *pe); | ||
275 | 289 | ||
276 | /** | 290 | /** |
277 | * EEH_POSSIBLE_ERROR() -- test for possible MMIO failure. | 291 | * EEH_POSSIBLE_ERROR() -- test for possible MMIO failure. |
@@ -295,8 +309,6 @@ static inline bool eeh_enabled(void) | |||
295 | return false; | 309 | return false; |
296 | } | 310 | } |
297 | 311 | ||
298 | static inline void eeh_set_enable(bool mode) { } | ||
299 | |||
300 | static inline int eeh_init(void) | 312 | static inline int eeh_init(void) |
301 | { | 313 | { |
302 | return 0; | 314 | return 0; |
diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h index 8f35cd7d59cc..77f52b26dad6 100644 --- a/arch/powerpc/include/asm/exception-64s.h +++ b/arch/powerpc/include/asm/exception-64s.h | |||
@@ -425,6 +425,8 @@ label##_relon_hv: \ | |||
425 | #define SOFTEN_VALUE_0xa00 PACA_IRQ_DBELL | 425 | #define SOFTEN_VALUE_0xa00 PACA_IRQ_DBELL |
426 | #define SOFTEN_VALUE_0xe80 PACA_IRQ_DBELL | 426 | #define SOFTEN_VALUE_0xe80 PACA_IRQ_DBELL |
427 | #define SOFTEN_VALUE_0xe82 PACA_IRQ_DBELL | 427 | #define SOFTEN_VALUE_0xe82 PACA_IRQ_DBELL |
428 | #define SOFTEN_VALUE_0xe60 PACA_IRQ_HMI | ||
429 | #define SOFTEN_VALUE_0xe62 PACA_IRQ_HMI | ||
428 | 430 | ||
429 | #define __SOFTEN_TEST(h, vec) \ | 431 | #define __SOFTEN_TEST(h, vec) \ |
430 | lbz r10,PACASOFTIRQEN(r13); \ | 432 | lbz r10,PACASOFTIRQEN(r13); \ |
@@ -513,8 +515,11 @@ label##_relon_hv: \ | |||
513 | * runlatch, etc... | 515 | * runlatch, etc... |
514 | */ | 516 | */ |
515 | 517 | ||
516 | /* Exception addition: Hard disable interrupts */ | 518 | /* |
517 | #define DISABLE_INTS RECONCILE_IRQ_STATE(r10,r11) | 519 | * This addition reconciles our actual IRQ state with the various software |
520 | * flags that track it. This may call C code. | ||
521 | */ | ||
522 | #define ADD_RECONCILE RECONCILE_IRQ_STATE(r10,r11) | ||
518 | 523 | ||
519 | #define ADD_NVGPRS \ | 524 | #define ADD_NVGPRS \ |
520 | bl save_nvgprs | 525 | bl save_nvgprs |
@@ -532,6 +537,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_CTRL) | |||
532 | .globl label##_common; \ | 537 | .globl label##_common; \ |
533 | label##_common: \ | 538 | label##_common: \ |
534 | EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN); \ | 539 | EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN); \ |
540 | /* Volatile regs are potentially clobbered here */ \ | ||
535 | additions; \ | 541 | additions; \ |
536 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | 542 | addi r3,r1,STACK_FRAME_OVERHEAD; \ |
537 | bl hdlr; \ | 543 | bl hdlr; \ |
@@ -539,7 +545,7 @@ label##_common: \ | |||
539 | 545 | ||
540 | #define STD_EXCEPTION_COMMON(trap, label, hdlr) \ | 546 | #define STD_EXCEPTION_COMMON(trap, label, hdlr) \ |
541 | EXCEPTION_COMMON(trap, label, hdlr, ret_from_except, \ | 547 | EXCEPTION_COMMON(trap, label, hdlr, ret_from_except, \ |
542 | ADD_NVGPRS;DISABLE_INTS) | 548 | ADD_NVGPRS;ADD_RECONCILE) |
543 | 549 | ||
544 | /* | 550 | /* |
545 | * Like STD_EXCEPTION_COMMON, but for exceptions that can occur | 551 | * Like STD_EXCEPTION_COMMON, but for exceptions that can occur |
@@ -548,7 +554,7 @@ label##_common: \ | |||
548 | */ | 554 | */ |
549 | #define STD_EXCEPTION_COMMON_ASYNC(trap, label, hdlr) \ | 555 | #define STD_EXCEPTION_COMMON_ASYNC(trap, label, hdlr) \ |
550 | EXCEPTION_COMMON(trap, label, hdlr, ret_from_except_lite, \ | 556 | EXCEPTION_COMMON(trap, label, hdlr, ret_from_except_lite, \ |
551 | FINISH_NAP;DISABLE_INTS;RUNLATCH_ON) | 557 | FINISH_NAP;ADD_RECONCILE;RUNLATCH_ON) |
552 | 558 | ||
553 | /* | 559 | /* |
554 | * When the idle code in power4_idle puts the CPU into NAP mode, | 560 | * When the idle code in power4_idle puts the CPU into NAP mode, |
diff --git a/arch/powerpc/include/asm/fs_pd.h b/arch/powerpc/include/asm/fs_pd.h index 9361cd5342cc..f79d6c74eb2a 100644 --- a/arch/powerpc/include/asm/fs_pd.h +++ b/arch/powerpc/include/asm/fs_pd.h | |||
@@ -28,7 +28,6 @@ | |||
28 | 28 | ||
29 | #ifdef CONFIG_8xx | 29 | #ifdef CONFIG_8xx |
30 | #include <asm/8xx_immap.h> | 30 | #include <asm/8xx_immap.h> |
31 | #include <asm/mpc8xx.h> | ||
32 | 31 | ||
33 | extern immap_t __iomem *mpc8xx_immr; | 32 | extern immap_t __iomem *mpc8xx_immr; |
34 | 33 | ||
diff --git a/arch/powerpc/include/asm/hardirq.h b/arch/powerpc/include/asm/hardirq.h index 418fb654370d..1bbb3013d6aa 100644 --- a/arch/powerpc/include/asm/hardirq.h +++ b/arch/powerpc/include/asm/hardirq.h | |||
@@ -11,6 +11,7 @@ typedef struct { | |||
11 | unsigned int pmu_irqs; | 11 | unsigned int pmu_irqs; |
12 | unsigned int mce_exceptions; | 12 | unsigned int mce_exceptions; |
13 | unsigned int spurious_irqs; | 13 | unsigned int spurious_irqs; |
14 | unsigned int hmi_exceptions; | ||
14 | #ifdef CONFIG_PPC_DOORBELL | 15 | #ifdef CONFIG_PPC_DOORBELL |
15 | unsigned int doorbell_irqs; | 16 | unsigned int doorbell_irqs; |
16 | #endif | 17 | #endif |
diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h index 5dbbb29f5c3e..85bc8c0d257b 100644 --- a/arch/powerpc/include/asm/hvcall.h +++ b/arch/powerpc/include/asm/hvcall.h | |||
@@ -279,6 +279,12 @@ | |||
279 | #define H_GET_24X7_DATA 0xF07C | 279 | #define H_GET_24X7_DATA 0xF07C |
280 | #define H_GET_PERF_COUNTER_INFO 0xF080 | 280 | #define H_GET_PERF_COUNTER_INFO 0xF080 |
281 | 281 | ||
282 | /* Values for 2nd argument to H_SET_MODE */ | ||
283 | #define H_SET_MODE_RESOURCE_SET_CIABR 1 | ||
284 | #define H_SET_MODE_RESOURCE_SET_DAWR 2 | ||
285 | #define H_SET_MODE_RESOURCE_ADDR_TRANS_MODE 3 | ||
286 | #define H_SET_MODE_RESOURCE_LE 4 | ||
287 | |||
282 | #ifndef __ASSEMBLY__ | 288 | #ifndef __ASSEMBLY__ |
283 | 289 | ||
284 | /** | 290 | /** |
diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h index 10be1dd01c6b..b59ac27a6b7d 100644 --- a/arch/powerpc/include/asm/hw_irq.h +++ b/arch/powerpc/include/asm/hw_irq.h | |||
@@ -25,6 +25,7 @@ | |||
25 | #define PACA_IRQ_EE 0x04 | 25 | #define PACA_IRQ_EE 0x04 |
26 | #define PACA_IRQ_DEC 0x08 /* Or FIT */ | 26 | #define PACA_IRQ_DEC 0x08 /* Or FIT */ |
27 | #define PACA_IRQ_EE_EDGE 0x10 /* BookE only */ | 27 | #define PACA_IRQ_EE_EDGE 0x10 /* BookE only */ |
28 | #define PACA_IRQ_HMI 0x20 | ||
28 | 29 | ||
29 | #endif /* CONFIG_PPC64 */ | 30 | #endif /* CONFIG_PPC64 */ |
30 | 31 | ||
diff --git a/arch/powerpc/include/asm/irqflags.h b/arch/powerpc/include/asm/irqflags.h index e20eb95429a8..f2149066fe5d 100644 --- a/arch/powerpc/include/asm/irqflags.h +++ b/arch/powerpc/include/asm/irqflags.h | |||
@@ -32,9 +32,8 @@ | |||
32 | #endif | 32 | #endif |
33 | 33 | ||
34 | /* | 34 | /* |
35 | * Most of the CPU's IRQ-state tracing is done from assembly code; we | 35 | * These are calls to C code, so the caller must be prepared for volatiles to |
36 | * have to call a C function so call a wrapper that saves all the | 36 | * be clobbered. |
37 | * C-clobbered registers. | ||
38 | */ | 37 | */ |
39 | #define TRACE_ENABLE_INTS TRACE_WITH_FRAME_BUFFER(trace_hardirqs_on) | 38 | #define TRACE_ENABLE_INTS TRACE_WITH_FRAME_BUFFER(trace_hardirqs_on) |
40 | #define TRACE_DISABLE_INTS TRACE_WITH_FRAME_BUFFER(trace_hardirqs_off) | 39 | #define TRACE_DISABLE_INTS TRACE_WITH_FRAME_BUFFER(trace_hardirqs_off) |
@@ -42,6 +41,9 @@ | |||
42 | /* | 41 | /* |
43 | * This is used by assembly code to soft-disable interrupts first and | 42 | * This is used by assembly code to soft-disable interrupts first and |
44 | * reconcile irq state. | 43 | * reconcile irq state. |
44 | * | ||
45 | * NB: This may call C code, so the caller must be prepared for volatiles to | ||
46 | * be clobbered. | ||
45 | */ | 47 | */ |
46 | #define RECONCILE_IRQ_STATE(__rA, __rB) \ | 48 | #define RECONCILE_IRQ_STATE(__rA, __rB) \ |
47 | lbz __rA,PACASOFTIRQEN(r13); \ | 49 | lbz __rA,PACASOFTIRQEN(r13); \ |
diff --git a/arch/powerpc/include/asm/jump_label.h b/arch/powerpc/include/asm/jump_label.h index f016bb699b5f..efbf9a322a23 100644 --- a/arch/powerpc/include/asm/jump_label.h +++ b/arch/powerpc/include/asm/jump_label.h | |||
@@ -10,6 +10,7 @@ | |||
10 | * 2 of the License, or (at your option) any later version. | 10 | * 2 of the License, or (at your option) any later version. |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #ifndef __ASSEMBLY__ | ||
13 | #include <linux/types.h> | 14 | #include <linux/types.h> |
14 | 15 | ||
15 | #include <asm/feature-fixups.h> | 16 | #include <asm/feature-fixups.h> |
@@ -42,4 +43,12 @@ struct jump_entry { | |||
42 | jump_label_t key; | 43 | jump_label_t key; |
43 | }; | 44 | }; |
44 | 45 | ||
46 | #else | ||
47 | #define ARCH_STATIC_BRANCH(LABEL, KEY) \ | ||
48 | 1098: nop; \ | ||
49 | .pushsection __jump_table, "aw"; \ | ||
50 | FTR_ENTRY_LONG 1098b, LABEL, KEY; \ | ||
51 | .popsection | ||
52 | #endif | ||
53 | |||
45 | #endif /* _ASM_POWERPC_JUMP_LABEL_H */ | 54 | #endif /* _ASM_POWERPC_JUMP_LABEL_H */ |
diff --git a/arch/powerpc/include/asm/kvm_44x.h b/arch/powerpc/include/asm/kvm_44x.h deleted file mode 100644 index a0e57618ff33..000000000000 --- a/arch/powerpc/include/asm/kvm_44x.h +++ /dev/null | |||
@@ -1,67 +0,0 @@ | |||
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 IBM Corp. 2008 | ||
16 | * | ||
17 | * Authors: Hollis Blanchard <hollisb@us.ibm.com> | ||
18 | */ | ||
19 | |||
20 | #ifndef __ASM_44X_H__ | ||
21 | #define __ASM_44X_H__ | ||
22 | |||
23 | #include <linux/kvm_host.h> | ||
24 | |||
25 | #define PPC44x_TLB_SIZE 64 | ||
26 | |||
27 | /* If the guest is expecting it, this can be as large as we like; we'd just | ||
28 | * need to find some way of advertising it. */ | ||
29 | #define KVM44x_GUEST_TLB_SIZE 64 | ||
30 | |||
31 | struct kvmppc_44x_tlbe { | ||
32 | u32 tid; /* Only the low 8 bits are used. */ | ||
33 | u32 word0; | ||
34 | u32 word1; | ||
35 | u32 word2; | ||
36 | }; | ||
37 | |||
38 | struct kvmppc_44x_shadow_ref { | ||
39 | struct page *page; | ||
40 | u16 gtlb_index; | ||
41 | u8 writeable; | ||
42 | u8 tid; | ||
43 | }; | ||
44 | |||
45 | struct kvmppc_vcpu_44x { | ||
46 | /* Unmodified copy of the guest's TLB. */ | ||
47 | struct kvmppc_44x_tlbe guest_tlb[KVM44x_GUEST_TLB_SIZE]; | ||
48 | |||
49 | /* References to guest pages in the hardware TLB. */ | ||
50 | struct kvmppc_44x_shadow_ref shadow_refs[PPC44x_TLB_SIZE]; | ||
51 | |||
52 | /* State of the shadow TLB at guest context switch time. */ | ||
53 | struct kvmppc_44x_tlbe shadow_tlb[PPC44x_TLB_SIZE]; | ||
54 | u8 shadow_tlb_mod[PPC44x_TLB_SIZE]; | ||
55 | |||
56 | struct kvm_vcpu vcpu; | ||
57 | }; | ||
58 | |||
59 | static inline struct kvmppc_vcpu_44x *to_44x(struct kvm_vcpu *vcpu) | ||
60 | { | ||
61 | return container_of(vcpu, struct kvmppc_vcpu_44x, vcpu); | ||
62 | } | ||
63 | |||
64 | void kvmppc_44x_tlb_put(struct kvm_vcpu *vcpu); | ||
65 | void kvmppc_44x_tlb_load(struct kvm_vcpu *vcpu); | ||
66 | |||
67 | #endif /* __ASM_44X_H__ */ | ||
diff --git a/arch/powerpc/include/asm/kvm_asm.h b/arch/powerpc/include/asm/kvm_asm.h index 9601741080e5..465dfcb82c92 100644 --- a/arch/powerpc/include/asm/kvm_asm.h +++ b/arch/powerpc/include/asm/kvm_asm.h | |||
@@ -33,7 +33,6 @@ | |||
33 | /* IVPR must be 64KiB-aligned. */ | 33 | /* IVPR must be 64KiB-aligned. */ |
34 | #define VCPU_SIZE_ORDER 4 | 34 | #define VCPU_SIZE_ORDER 4 |
35 | #define VCPU_SIZE_LOG (VCPU_SIZE_ORDER + 12) | 35 | #define VCPU_SIZE_LOG (VCPU_SIZE_ORDER + 12) |
36 | #define VCPU_TLB_PGSZ PPC44x_TLB_64K | ||
37 | #define VCPU_SIZE_BYTES (1<<VCPU_SIZE_LOG) | 36 | #define VCPU_SIZE_BYTES (1<<VCPU_SIZE_LOG) |
38 | 37 | ||
39 | #define BOOKE_INTERRUPT_CRITICAL 0 | 38 | #define BOOKE_INTERRUPT_CRITICAL 0 |
@@ -98,6 +97,7 @@ | |||
98 | #define BOOK3S_INTERRUPT_H_DATA_STORAGE 0xe00 | 97 | #define BOOK3S_INTERRUPT_H_DATA_STORAGE 0xe00 |
99 | #define BOOK3S_INTERRUPT_H_INST_STORAGE 0xe20 | 98 | #define BOOK3S_INTERRUPT_H_INST_STORAGE 0xe20 |
100 | #define BOOK3S_INTERRUPT_H_EMUL_ASSIST 0xe40 | 99 | #define BOOK3S_INTERRUPT_H_EMUL_ASSIST 0xe40 |
100 | #define BOOK3S_INTERRUPT_HMI 0xe60 | ||
101 | #define BOOK3S_INTERRUPT_H_DOORBELL 0xe80 | 101 | #define BOOK3S_INTERRUPT_H_DOORBELL 0xe80 |
102 | #define BOOK3S_INTERRUPT_PERFMON 0xf00 | 102 | #define BOOK3S_INTERRUPT_PERFMON 0xf00 |
103 | #define BOOK3S_INTERRUPT_ALTIVEC 0xf20 | 103 | #define BOOK3S_INTERRUPT_ALTIVEC 0xf20 |
@@ -131,6 +131,7 @@ | |||
131 | #define BOOK3S_HFLAG_NATIVE_PS 0x8 | 131 | #define BOOK3S_HFLAG_NATIVE_PS 0x8 |
132 | #define BOOK3S_HFLAG_MULTI_PGSIZE 0x10 | 132 | #define BOOK3S_HFLAG_MULTI_PGSIZE 0x10 |
133 | #define BOOK3S_HFLAG_NEW_TLBIE 0x20 | 133 | #define BOOK3S_HFLAG_NEW_TLBIE 0x20 |
134 | #define BOOK3S_HFLAG_SPLIT_HACK 0x40 | ||
134 | 135 | ||
135 | #define RESUME_FLAG_NV (1<<0) /* Reload guest nonvolatile state? */ | 136 | #define RESUME_FLAG_NV (1<<0) /* Reload guest nonvolatile state? */ |
136 | #define RESUME_FLAG_HOST (1<<1) /* Resume host? */ | 137 | #define RESUME_FLAG_HOST (1<<1) /* Resume host? */ |
diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h index f52f65694527..6acf0c2a0f99 100644 --- a/arch/powerpc/include/asm/kvm_book3s.h +++ b/arch/powerpc/include/asm/kvm_book3s.h | |||
@@ -83,8 +83,6 @@ struct kvmppc_vcpu_book3s { | |||
83 | u64 sdr1; | 83 | u64 sdr1; |
84 | u64 hior; | 84 | u64 hior; |
85 | u64 msr_mask; | 85 | u64 msr_mask; |
86 | u64 purr_offset; | ||
87 | u64 spurr_offset; | ||
88 | #ifdef CONFIG_PPC_BOOK3S_32 | 86 | #ifdef CONFIG_PPC_BOOK3S_32 |
89 | u32 vsid_pool[VSID_POOL_SIZE]; | 87 | u32 vsid_pool[VSID_POOL_SIZE]; |
90 | u32 vsid_next; | 88 | u32 vsid_next; |
@@ -148,9 +146,10 @@ extern void kvmppc_mmu_invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache * | |||
148 | extern int kvmppc_mmu_hpte_sysinit(void); | 146 | extern int kvmppc_mmu_hpte_sysinit(void); |
149 | extern void kvmppc_mmu_hpte_sysexit(void); | 147 | extern void kvmppc_mmu_hpte_sysexit(void); |
150 | extern int kvmppc_mmu_hv_init(void); | 148 | extern int kvmppc_mmu_hv_init(void); |
149 | extern int kvmppc_book3s_hcall_implemented(struct kvm *kvm, unsigned long hc); | ||
151 | 150 | ||
151 | /* XXX remove this export when load_last_inst() is generic */ | ||
152 | extern int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr, bool data); | 152 | extern int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr, bool data); |
153 | extern int kvmppc_st(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr, bool data); | ||
154 | extern void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec); | 153 | extern void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec); |
155 | extern void kvmppc_book3s_dequeue_irqprio(struct kvm_vcpu *vcpu, | 154 | extern void kvmppc_book3s_dequeue_irqprio(struct kvm_vcpu *vcpu, |
156 | unsigned int vec); | 155 | unsigned int vec); |
@@ -159,13 +158,13 @@ extern void kvmppc_set_bat(struct kvm_vcpu *vcpu, struct kvmppc_bat *bat, | |||
159 | bool upper, u32 val); | 158 | bool upper, u32 val); |
160 | extern void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr); | 159 | extern void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr); |
161 | extern int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu); | 160 | extern int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu); |
162 | extern pfn_t kvmppc_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn, bool writing, | 161 | extern pfn_t kvmppc_gpa_to_pfn(struct kvm_vcpu *vcpu, gpa_t gpa, bool writing, |
163 | bool *writable); | 162 | bool *writable); |
164 | extern void kvmppc_add_revmap_chain(struct kvm *kvm, struct revmap_entry *rev, | 163 | extern void kvmppc_add_revmap_chain(struct kvm *kvm, struct revmap_entry *rev, |
165 | unsigned long *rmap, long pte_index, int realmode); | 164 | unsigned long *rmap, long pte_index, int realmode); |
166 | extern void kvmppc_invalidate_hpte(struct kvm *kvm, unsigned long *hptep, | 165 | extern void kvmppc_invalidate_hpte(struct kvm *kvm, __be64 *hptep, |
167 | unsigned long pte_index); | 166 | unsigned long pte_index); |
168 | void kvmppc_clear_ref_hpte(struct kvm *kvm, unsigned long *hptep, | 167 | void kvmppc_clear_ref_hpte(struct kvm *kvm, __be64 *hptep, |
169 | unsigned long pte_index); | 168 | unsigned long pte_index); |
170 | extern void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long addr, | 169 | extern void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long addr, |
171 | unsigned long *nb_ret); | 170 | unsigned long *nb_ret); |
@@ -183,12 +182,16 @@ extern long kvmppc_hv_get_dirty_log(struct kvm *kvm, | |||
183 | struct kvm_memory_slot *memslot, unsigned long *map); | 182 | struct kvm_memory_slot *memslot, unsigned long *map); |
184 | extern void kvmppc_update_lpcr(struct kvm *kvm, unsigned long lpcr, | 183 | extern void kvmppc_update_lpcr(struct kvm *kvm, unsigned long lpcr, |
185 | unsigned long mask); | 184 | unsigned long mask); |
185 | extern void kvmppc_set_fscr(struct kvm_vcpu *vcpu, u64 fscr); | ||
186 | 186 | ||
187 | extern void kvmppc_entry_trampoline(void); | 187 | extern void kvmppc_entry_trampoline(void); |
188 | extern void kvmppc_hv_entry_trampoline(void); | 188 | extern void kvmppc_hv_entry_trampoline(void); |
189 | extern u32 kvmppc_alignment_dsisr(struct kvm_vcpu *vcpu, unsigned int inst); | 189 | extern u32 kvmppc_alignment_dsisr(struct kvm_vcpu *vcpu, unsigned int inst); |
190 | extern ulong kvmppc_alignment_dar(struct kvm_vcpu *vcpu, unsigned int inst); | 190 | extern ulong kvmppc_alignment_dar(struct kvm_vcpu *vcpu, unsigned int inst); |
191 | extern int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd); | 191 | extern int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd); |
192 | extern void kvmppc_pr_init_default_hcalls(struct kvm *kvm); | ||
193 | extern int kvmppc_hcall_impl_pr(unsigned long cmd); | ||
194 | extern int kvmppc_hcall_impl_hv_realmode(unsigned long cmd); | ||
192 | extern void kvmppc_copy_to_svcpu(struct kvmppc_book3s_shadow_vcpu *svcpu, | 195 | extern void kvmppc_copy_to_svcpu(struct kvmppc_book3s_shadow_vcpu *svcpu, |
193 | struct kvm_vcpu *vcpu); | 196 | struct kvm_vcpu *vcpu); |
194 | extern void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu, | 197 | extern void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu, |
@@ -274,32 +277,6 @@ static inline bool kvmppc_need_byteswap(struct kvm_vcpu *vcpu) | |||
274 | return (kvmppc_get_msr(vcpu) & MSR_LE) != (MSR_KERNEL & MSR_LE); | 277 | return (kvmppc_get_msr(vcpu) & MSR_LE) != (MSR_KERNEL & MSR_LE); |
275 | } | 278 | } |
276 | 279 | ||
277 | static inline u32 kvmppc_get_last_inst_internal(struct kvm_vcpu *vcpu, ulong pc) | ||
278 | { | ||
279 | /* Load the instruction manually if it failed to do so in the | ||
280 | * exit path */ | ||
281 | if (vcpu->arch.last_inst == KVM_INST_FETCH_FAILED) | ||
282 | kvmppc_ld(vcpu, &pc, sizeof(u32), &vcpu->arch.last_inst, false); | ||
283 | |||
284 | return kvmppc_need_byteswap(vcpu) ? swab32(vcpu->arch.last_inst) : | ||
285 | vcpu->arch.last_inst; | ||
286 | } | ||
287 | |||
288 | static inline u32 kvmppc_get_last_inst(struct kvm_vcpu *vcpu) | ||
289 | { | ||
290 | return kvmppc_get_last_inst_internal(vcpu, kvmppc_get_pc(vcpu)); | ||
291 | } | ||
292 | |||
293 | /* | ||
294 | * Like kvmppc_get_last_inst(), but for fetching a sc instruction. | ||
295 | * Because the sc instruction sets SRR0 to point to the following | ||
296 | * instruction, we have to fetch from pc - 4. | ||
297 | */ | ||
298 | static inline u32 kvmppc_get_last_sc(struct kvm_vcpu *vcpu) | ||
299 | { | ||
300 | return kvmppc_get_last_inst_internal(vcpu, kvmppc_get_pc(vcpu) - 4); | ||
301 | } | ||
302 | |||
303 | static inline ulong kvmppc_get_fault_dar(struct kvm_vcpu *vcpu) | 280 | static inline ulong kvmppc_get_fault_dar(struct kvm_vcpu *vcpu) |
304 | { | 281 | { |
305 | return vcpu->arch.fault_dar; | 282 | return vcpu->arch.fault_dar; |
@@ -310,6 +287,13 @@ static inline bool is_kvmppc_resume_guest(int r) | |||
310 | return (r == RESUME_GUEST || r == RESUME_GUEST_NV); | 287 | return (r == RESUME_GUEST || r == RESUME_GUEST_NV); |
311 | } | 288 | } |
312 | 289 | ||
290 | static inline bool is_kvmppc_hv_enabled(struct kvm *kvm); | ||
291 | static inline bool kvmppc_supports_magic_page(struct kvm_vcpu *vcpu) | ||
292 | { | ||
293 | /* Only PR KVM supports the magic page */ | ||
294 | return !is_kvmppc_hv_enabled(vcpu->kvm); | ||
295 | } | ||
296 | |||
313 | /* Magic register values loaded into r3 and r4 before the 'sc' assembly | 297 | /* Magic register values loaded into r3 and r4 before the 'sc' assembly |
314 | * instruction for the OSI hypercalls */ | 298 | * instruction for the OSI hypercalls */ |
315 | #define OSI_SC_MAGIC_R3 0x113724FA | 299 | #define OSI_SC_MAGIC_R3 0x113724FA |
@@ -322,4 +306,7 @@ static inline bool is_kvmppc_resume_guest(int r) | |||
322 | /* LPIDs we support with this build -- runtime limit may be lower */ | 306 | /* LPIDs we support with this build -- runtime limit may be lower */ |
323 | #define KVMPPC_NR_LPIDS (LPID_RSVD + 1) | 307 | #define KVMPPC_NR_LPIDS (LPID_RSVD + 1) |
324 | 308 | ||
309 | #define SPLIT_HACK_MASK 0xff000000 | ||
310 | #define SPLIT_HACK_OFFS 0xfb000000 | ||
311 | |||
325 | #endif /* __ASM_KVM_BOOK3S_H__ */ | 312 | #endif /* __ASM_KVM_BOOK3S_H__ */ |
diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h index d645428a65a4..0aa817933e6a 100644 --- a/arch/powerpc/include/asm/kvm_book3s_64.h +++ b/arch/powerpc/include/asm/kvm_book3s_64.h | |||
@@ -59,20 +59,29 @@ extern unsigned long kvm_rma_pages; | |||
59 | /* These bits are reserved in the guest view of the HPTE */ | 59 | /* These bits are reserved in the guest view of the HPTE */ |
60 | #define HPTE_GR_RESERVED HPTE_GR_MODIFIED | 60 | #define HPTE_GR_RESERVED HPTE_GR_MODIFIED |
61 | 61 | ||
62 | static inline long try_lock_hpte(unsigned long *hpte, unsigned long bits) | 62 | static inline long try_lock_hpte(__be64 *hpte, unsigned long bits) |
63 | { | 63 | { |
64 | unsigned long tmp, old; | 64 | unsigned long tmp, old; |
65 | __be64 be_lockbit, be_bits; | ||
66 | |||
67 | /* | ||
68 | * We load/store in native endian, but the HTAB is in big endian. If | ||
69 | * we byte swap all data we apply on the PTE we're implicitly correct | ||
70 | * again. | ||
71 | */ | ||
72 | be_lockbit = cpu_to_be64(HPTE_V_HVLOCK); | ||
73 | be_bits = cpu_to_be64(bits); | ||
65 | 74 | ||
66 | asm volatile(" ldarx %0,0,%2\n" | 75 | asm volatile(" ldarx %0,0,%2\n" |
67 | " and. %1,%0,%3\n" | 76 | " and. %1,%0,%3\n" |
68 | " bne 2f\n" | 77 | " bne 2f\n" |
69 | " ori %0,%0,%4\n" | 78 | " or %0,%0,%4\n" |
70 | " stdcx. %0,0,%2\n" | 79 | " stdcx. %0,0,%2\n" |
71 | " beq+ 2f\n" | 80 | " beq+ 2f\n" |
72 | " mr %1,%3\n" | 81 | " mr %1,%3\n" |
73 | "2: isync" | 82 | "2: isync" |
74 | : "=&r" (tmp), "=&r" (old) | 83 | : "=&r" (tmp), "=&r" (old) |
75 | : "r" (hpte), "r" (bits), "i" (HPTE_V_HVLOCK) | 84 | : "r" (hpte), "r" (be_bits), "r" (be_lockbit) |
76 | : "cc", "memory"); | 85 | : "cc", "memory"); |
77 | return old == 0; | 86 | return old == 0; |
78 | } | 87 | } |
@@ -110,16 +119,12 @@ static inline int __hpte_actual_psize(unsigned int lp, int psize) | |||
110 | static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r, | 119 | static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r, |
111 | unsigned long pte_index) | 120 | unsigned long pte_index) |
112 | { | 121 | { |
113 | int b_psize, a_psize; | 122 | int b_psize = MMU_PAGE_4K, a_psize = MMU_PAGE_4K; |
114 | unsigned int penc; | 123 | unsigned int penc; |
115 | unsigned long rb = 0, va_low, sllp; | 124 | unsigned long rb = 0, va_low, sllp; |
116 | unsigned int lp = (r >> LP_SHIFT) & ((1 << LP_BITS) - 1); | 125 | unsigned int lp = (r >> LP_SHIFT) & ((1 << LP_BITS) - 1); |
117 | 126 | ||
118 | if (!(v & HPTE_V_LARGE)) { | 127 | if (v & HPTE_V_LARGE) { |
119 | /* both base and actual psize is 4k */ | ||
120 | b_psize = MMU_PAGE_4K; | ||
121 | a_psize = MMU_PAGE_4K; | ||
122 | } else { | ||
123 | for (b_psize = 0; b_psize < MMU_PAGE_COUNT; b_psize++) { | 128 | for (b_psize = 0; b_psize < MMU_PAGE_COUNT; b_psize++) { |
124 | 129 | ||
125 | /* valid entries have a shift value */ | 130 | /* valid entries have a shift value */ |
@@ -142,6 +147,8 @@ static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r, | |||
142 | */ | 147 | */ |
143 | /* This covers 14..54 bits of va*/ | 148 | /* This covers 14..54 bits of va*/ |
144 | rb = (v & ~0x7fUL) << 16; /* AVA field */ | 149 | rb = (v & ~0x7fUL) << 16; /* AVA field */ |
150 | |||
151 | rb |= v >> (62 - 8); /* B field */ | ||
145 | /* | 152 | /* |
146 | * AVA in v had cleared lower 23 bits. We need to derive | 153 | * AVA in v had cleared lower 23 bits. We need to derive |
147 | * that from pteg index | 154 | * that from pteg index |
@@ -172,10 +179,10 @@ static inline unsigned long compute_tlbie_rb(unsigned long v, unsigned long r, | |||
172 | { | 179 | { |
173 | int aval_shift; | 180 | int aval_shift; |
174 | /* | 181 | /* |
175 | * remaining 7bits of AVA/LP fields | 182 | * remaining bits of AVA/LP fields |
176 | * Also contain the rr bits of LP | 183 | * Also contain the rr bits of LP |
177 | */ | 184 | */ |
178 | rb |= (va_low & 0x7f) << 16; | 185 | rb |= (va_low << mmu_psize_defs[b_psize].shift) & 0x7ff000; |
179 | /* | 186 | /* |
180 | * Now clear not needed LP bits based on actual psize | 187 | * Now clear not needed LP bits based on actual psize |
181 | */ | 188 | */ |
diff --git a/arch/powerpc/include/asm/kvm_booke.h b/arch/powerpc/include/asm/kvm_booke.h index c7aed6105ff9..f7aa5cc395c4 100644 --- a/arch/powerpc/include/asm/kvm_booke.h +++ b/arch/powerpc/include/asm/kvm_booke.h | |||
@@ -69,11 +69,6 @@ static inline bool kvmppc_need_byteswap(struct kvm_vcpu *vcpu) | |||
69 | return false; | 69 | return false; |
70 | } | 70 | } |
71 | 71 | ||
72 | static inline u32 kvmppc_get_last_inst(struct kvm_vcpu *vcpu) | ||
73 | { | ||
74 | return vcpu->arch.last_inst; | ||
75 | } | ||
76 | |||
77 | static inline void kvmppc_set_ctr(struct kvm_vcpu *vcpu, ulong val) | 72 | static inline void kvmppc_set_ctr(struct kvm_vcpu *vcpu, ulong val) |
78 | { | 73 | { |
79 | vcpu->arch.ctr = val; | 74 | vcpu->arch.ctr = val; |
@@ -108,4 +103,14 @@ static inline ulong kvmppc_get_fault_dar(struct kvm_vcpu *vcpu) | |||
108 | { | 103 | { |
109 | return vcpu->arch.fault_dear; | 104 | return vcpu->arch.fault_dear; |
110 | } | 105 | } |
106 | |||
107 | static inline bool kvmppc_supports_magic_page(struct kvm_vcpu *vcpu) | ||
108 | { | ||
109 | /* Magic page is only supported on e500v2 */ | ||
110 | #ifdef CONFIG_KVM_E500V2 | ||
111 | return true; | ||
112 | #else | ||
113 | return false; | ||
114 | #endif | ||
115 | } | ||
111 | #endif /* __ASM_KVM_BOOKE_H__ */ | 116 | #endif /* __ASM_KVM_BOOKE_H__ */ |
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index bb66d8b8efdf..98d9dd50d063 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <asm/processor.h> | 34 | #include <asm/processor.h> |
35 | #include <asm/page.h> | 35 | #include <asm/page.h> |
36 | #include <asm/cacheflush.h> | 36 | #include <asm/cacheflush.h> |
37 | #include <asm/hvcall.h> | ||
37 | 38 | ||
38 | #define KVM_MAX_VCPUS NR_CPUS | 39 | #define KVM_MAX_VCPUS NR_CPUS |
39 | #define KVM_MAX_VCORES NR_CPUS | 40 | #define KVM_MAX_VCORES NR_CPUS |
@@ -48,7 +49,6 @@ | |||
48 | #define KVM_NR_IRQCHIPS 1 | 49 | #define KVM_NR_IRQCHIPS 1 |
49 | #define KVM_IRQCHIP_NUM_PINS 256 | 50 | #define KVM_IRQCHIP_NUM_PINS 256 |
50 | 51 | ||
51 | #if !defined(CONFIG_KVM_440) | ||
52 | #include <linux/mmu_notifier.h> | 52 | #include <linux/mmu_notifier.h> |
53 | 53 | ||
54 | #define KVM_ARCH_WANT_MMU_NOTIFIER | 54 | #define KVM_ARCH_WANT_MMU_NOTIFIER |
@@ -61,8 +61,6 @@ extern int kvm_age_hva(struct kvm *kvm, unsigned long hva); | |||
61 | extern int kvm_test_age_hva(struct kvm *kvm, unsigned long hva); | 61 | extern int kvm_test_age_hva(struct kvm *kvm, unsigned long hva); |
62 | extern void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte); | 62 | extern void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte); |
63 | 63 | ||
64 | #endif | ||
65 | |||
66 | #define HPTEG_CACHE_NUM (1 << 15) | 64 | #define HPTEG_CACHE_NUM (1 << 15) |
67 | #define HPTEG_HASH_BITS_PTE 13 | 65 | #define HPTEG_HASH_BITS_PTE 13 |
68 | #define HPTEG_HASH_BITS_PTE_LONG 12 | 66 | #define HPTEG_HASH_BITS_PTE_LONG 12 |
@@ -96,7 +94,6 @@ struct kvm_vm_stat { | |||
96 | struct kvm_vcpu_stat { | 94 | struct kvm_vcpu_stat { |
97 | u32 sum_exits; | 95 | u32 sum_exits; |
98 | u32 mmio_exits; | 96 | u32 mmio_exits; |
99 | u32 dcr_exits; | ||
100 | u32 signal_exits; | 97 | u32 signal_exits; |
101 | u32 light_exits; | 98 | u32 light_exits; |
102 | /* Account for special types of light exits: */ | 99 | /* Account for special types of light exits: */ |
@@ -113,22 +110,21 @@ struct kvm_vcpu_stat { | |||
113 | u32 halt_wakeup; | 110 | u32 halt_wakeup; |
114 | u32 dbell_exits; | 111 | u32 dbell_exits; |
115 | u32 gdbell_exits; | 112 | u32 gdbell_exits; |
113 | u32 ld; | ||
114 | u32 st; | ||
116 | #ifdef CONFIG_PPC_BOOK3S | 115 | #ifdef CONFIG_PPC_BOOK3S |
117 | u32 pf_storage; | 116 | u32 pf_storage; |
118 | u32 pf_instruc; | 117 | u32 pf_instruc; |
119 | u32 sp_storage; | 118 | u32 sp_storage; |
120 | u32 sp_instruc; | 119 | u32 sp_instruc; |
121 | u32 queue_intr; | 120 | u32 queue_intr; |
122 | u32 ld; | ||
123 | u32 ld_slow; | 121 | u32 ld_slow; |
124 | u32 st; | ||
125 | u32 st_slow; | 122 | u32 st_slow; |
126 | #endif | 123 | #endif |
127 | }; | 124 | }; |
128 | 125 | ||
129 | enum kvm_exit_types { | 126 | enum kvm_exit_types { |
130 | MMIO_EXITS, | 127 | MMIO_EXITS, |
131 | DCR_EXITS, | ||
132 | SIGNAL_EXITS, | 128 | SIGNAL_EXITS, |
133 | ITLB_REAL_MISS_EXITS, | 129 | ITLB_REAL_MISS_EXITS, |
134 | ITLB_VIRT_MISS_EXITS, | 130 | ITLB_VIRT_MISS_EXITS, |
@@ -254,7 +250,6 @@ struct kvm_arch { | |||
254 | atomic_t hpte_mod_interest; | 250 | atomic_t hpte_mod_interest; |
255 | spinlock_t slot_phys_lock; | 251 | spinlock_t slot_phys_lock; |
256 | cpumask_t need_tlb_flush; | 252 | cpumask_t need_tlb_flush; |
257 | struct kvmppc_vcore *vcores[KVM_MAX_VCORES]; | ||
258 | int hpt_cma_alloc; | 253 | int hpt_cma_alloc; |
259 | #endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */ | 254 | #endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */ |
260 | #ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE | 255 | #ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE |
@@ -263,6 +258,7 @@ struct kvm_arch { | |||
263 | #ifdef CONFIG_PPC_BOOK3S_64 | 258 | #ifdef CONFIG_PPC_BOOK3S_64 |
264 | struct list_head spapr_tce_tables; | 259 | struct list_head spapr_tce_tables; |
265 | struct list_head rtas_tokens; | 260 | struct list_head rtas_tokens; |
261 | DECLARE_BITMAP(enabled_hcalls, MAX_HCALL_OPCODE/4 + 1); | ||
266 | #endif | 262 | #endif |
267 | #ifdef CONFIG_KVM_MPIC | 263 | #ifdef CONFIG_KVM_MPIC |
268 | struct openpic *mpic; | 264 | struct openpic *mpic; |
@@ -271,6 +267,10 @@ struct kvm_arch { | |||
271 | struct kvmppc_xics *xics; | 267 | struct kvmppc_xics *xics; |
272 | #endif | 268 | #endif |
273 | struct kvmppc_ops *kvm_ops; | 269 | struct kvmppc_ops *kvm_ops; |
270 | #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE | ||
271 | /* This array can grow quite large, keep it at the end */ | ||
272 | struct kvmppc_vcore *vcores[KVM_MAX_VCORES]; | ||
273 | #endif | ||
274 | }; | 274 | }; |
275 | 275 | ||
276 | /* | 276 | /* |
@@ -305,6 +305,8 @@ struct kvmppc_vcore { | |||
305 | u32 arch_compat; | 305 | u32 arch_compat; |
306 | ulong pcr; | 306 | ulong pcr; |
307 | ulong dpdes; /* doorbell state (POWER8) */ | 307 | ulong dpdes; /* doorbell state (POWER8) */ |
308 | void *mpp_buffer; /* Micro Partition Prefetch buffer */ | ||
309 | bool mpp_buffer_is_valid; | ||
308 | }; | 310 | }; |
309 | 311 | ||
310 | #define VCORE_ENTRY_COUNT(vc) ((vc)->entry_exit_count & 0xff) | 312 | #define VCORE_ENTRY_COUNT(vc) ((vc)->entry_exit_count & 0xff) |
@@ -503,8 +505,10 @@ struct kvm_vcpu_arch { | |||
503 | #ifdef CONFIG_BOOKE | 505 | #ifdef CONFIG_BOOKE |
504 | u32 decar; | 506 | u32 decar; |
505 | #endif | 507 | #endif |
506 | u32 tbl; | 508 | /* Time base value when we entered the guest */ |
507 | u32 tbu; | 509 | u64 entry_tb; |
510 | u64 entry_vtb; | ||
511 | u64 entry_ic; | ||
508 | u32 tcr; | 512 | u32 tcr; |
509 | ulong tsr; /* we need to perform set/clr_bits() which requires ulong */ | 513 | ulong tsr; /* we need to perform set/clr_bits() which requires ulong */ |
510 | u32 ivor[64]; | 514 | u32 ivor[64]; |
@@ -580,6 +584,8 @@ struct kvm_vcpu_arch { | |||
580 | u32 mmucfg; | 584 | u32 mmucfg; |
581 | u32 eptcfg; | 585 | u32 eptcfg; |
582 | u32 epr; | 586 | u32 epr; |
587 | u64 sprg9; | ||
588 | u32 pwrmgtcr0; | ||
583 | u32 crit_save; | 589 | u32 crit_save; |
584 | /* guest debug registers*/ | 590 | /* guest debug registers*/ |
585 | struct debug_reg dbg_reg; | 591 | struct debug_reg dbg_reg; |
@@ -593,8 +599,6 @@ struct kvm_vcpu_arch { | |||
593 | u8 io_gpr; /* GPR used as IO source/target */ | 599 | u8 io_gpr; /* GPR used as IO source/target */ |
594 | u8 mmio_is_bigendian; | 600 | u8 mmio_is_bigendian; |
595 | u8 mmio_sign_extend; | 601 | u8 mmio_sign_extend; |
596 | u8 dcr_needed; | ||
597 | u8 dcr_is_write; | ||
598 | u8 osi_needed; | 602 | u8 osi_needed; |
599 | u8 osi_enabled; | 603 | u8 osi_enabled; |
600 | u8 papr_enabled; | 604 | u8 papr_enabled; |
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h index 9c89cdd067a6..fb86a2299d8a 100644 --- a/arch/powerpc/include/asm/kvm_ppc.h +++ b/arch/powerpc/include/asm/kvm_ppc.h | |||
@@ -41,12 +41,26 @@ | |||
41 | enum emulation_result { | 41 | enum emulation_result { |
42 | EMULATE_DONE, /* no further processing */ | 42 | EMULATE_DONE, /* no further processing */ |
43 | EMULATE_DO_MMIO, /* kvm_run filled with MMIO request */ | 43 | EMULATE_DO_MMIO, /* kvm_run filled with MMIO request */ |
44 | EMULATE_DO_DCR, /* kvm_run filled with DCR request */ | ||
45 | EMULATE_FAIL, /* can't emulate this instruction */ | 44 | EMULATE_FAIL, /* can't emulate this instruction */ |
46 | EMULATE_AGAIN, /* something went wrong. go again */ | 45 | EMULATE_AGAIN, /* something went wrong. go again */ |
47 | EMULATE_EXIT_USER, /* emulation requires exit to user-space */ | 46 | EMULATE_EXIT_USER, /* emulation requires exit to user-space */ |
48 | }; | 47 | }; |
49 | 48 | ||
49 | enum instruction_type { | ||
50 | INST_GENERIC, | ||
51 | INST_SC, /* system call */ | ||
52 | }; | ||
53 | |||
54 | enum xlate_instdata { | ||
55 | XLATE_INST, /* translate instruction address */ | ||
56 | XLATE_DATA /* translate data address */ | ||
57 | }; | ||
58 | |||
59 | enum xlate_readwrite { | ||
60 | XLATE_READ, /* check for read permissions */ | ||
61 | XLATE_WRITE /* check for write permissions */ | ||
62 | }; | ||
63 | |||
50 | extern int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu); | 64 | extern int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu); |
51 | extern int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu); | 65 | extern int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu); |
52 | extern void kvmppc_handler_highmem(void); | 66 | extern void kvmppc_handler_highmem(void); |
@@ -62,8 +76,16 @@ extern int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
62 | u64 val, unsigned int bytes, | 76 | u64 val, unsigned int bytes, |
63 | int is_default_endian); | 77 | int is_default_endian); |
64 | 78 | ||
79 | extern int kvmppc_load_last_inst(struct kvm_vcpu *vcpu, | ||
80 | enum instruction_type type, u32 *inst); | ||
81 | |||
82 | extern int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr, | ||
83 | bool data); | ||
84 | extern int kvmppc_st(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr, | ||
85 | bool data); | ||
65 | extern int kvmppc_emulate_instruction(struct kvm_run *run, | 86 | extern int kvmppc_emulate_instruction(struct kvm_run *run, |
66 | struct kvm_vcpu *vcpu); | 87 | struct kvm_vcpu *vcpu); |
88 | extern int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu); | ||
67 | extern int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu); | 89 | extern int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu); |
68 | extern void kvmppc_emulate_dec(struct kvm_vcpu *vcpu); | 90 | extern void kvmppc_emulate_dec(struct kvm_vcpu *vcpu); |
69 | extern u32 kvmppc_get_dec(struct kvm_vcpu *vcpu, u64 tb); | 91 | extern u32 kvmppc_get_dec(struct kvm_vcpu *vcpu, u64 tb); |
@@ -86,6 +108,9 @@ extern gpa_t kvmppc_mmu_xlate(struct kvm_vcpu *vcpu, unsigned int gtlb_index, | |||
86 | gva_t eaddr); | 108 | gva_t eaddr); |
87 | extern void kvmppc_mmu_dtlb_miss(struct kvm_vcpu *vcpu); | 109 | extern void kvmppc_mmu_dtlb_miss(struct kvm_vcpu *vcpu); |
88 | extern void kvmppc_mmu_itlb_miss(struct kvm_vcpu *vcpu); | 110 | extern void kvmppc_mmu_itlb_miss(struct kvm_vcpu *vcpu); |
111 | extern int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, | ||
112 | enum xlate_instdata xlid, enum xlate_readwrite xlrw, | ||
113 | struct kvmppc_pte *pte); | ||
89 | 114 | ||
90 | extern struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, | 115 | extern struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, |
91 | unsigned int id); | 116 | unsigned int id); |
@@ -106,6 +131,14 @@ extern void kvmppc_core_dequeue_dec(struct kvm_vcpu *vcpu); | |||
106 | extern void kvmppc_core_queue_external(struct kvm_vcpu *vcpu, | 131 | extern void kvmppc_core_queue_external(struct kvm_vcpu *vcpu, |
107 | struct kvm_interrupt *irq); | 132 | struct kvm_interrupt *irq); |
108 | extern void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu); | 133 | extern void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu); |
134 | extern void kvmppc_core_queue_dtlb_miss(struct kvm_vcpu *vcpu, ulong dear_flags, | ||
135 | ulong esr_flags); | ||
136 | extern void kvmppc_core_queue_data_storage(struct kvm_vcpu *vcpu, | ||
137 | ulong dear_flags, | ||
138 | ulong esr_flags); | ||
139 | extern void kvmppc_core_queue_itlb_miss(struct kvm_vcpu *vcpu); | ||
140 | extern void kvmppc_core_queue_inst_storage(struct kvm_vcpu *vcpu, | ||
141 | ulong esr_flags); | ||
109 | extern void kvmppc_core_flush_tlb(struct kvm_vcpu *vcpu); | 142 | extern void kvmppc_core_flush_tlb(struct kvm_vcpu *vcpu); |
110 | extern int kvmppc_core_check_requests(struct kvm_vcpu *vcpu); | 143 | extern int kvmppc_core_check_requests(struct kvm_vcpu *vcpu); |
111 | 144 | ||
@@ -228,12 +261,35 @@ struct kvmppc_ops { | |||
228 | void (*fast_vcpu_kick)(struct kvm_vcpu *vcpu); | 261 | void (*fast_vcpu_kick)(struct kvm_vcpu *vcpu); |
229 | long (*arch_vm_ioctl)(struct file *filp, unsigned int ioctl, | 262 | long (*arch_vm_ioctl)(struct file *filp, unsigned int ioctl, |
230 | unsigned long arg); | 263 | unsigned long arg); |
231 | 264 | int (*hcall_implemented)(unsigned long hcall); | |
232 | }; | 265 | }; |
233 | 266 | ||
234 | extern struct kvmppc_ops *kvmppc_hv_ops; | 267 | extern struct kvmppc_ops *kvmppc_hv_ops; |
235 | extern struct kvmppc_ops *kvmppc_pr_ops; | 268 | extern struct kvmppc_ops *kvmppc_pr_ops; |
236 | 269 | ||
270 | static inline int kvmppc_get_last_inst(struct kvm_vcpu *vcpu, | ||
271 | enum instruction_type type, u32 *inst) | ||
272 | { | ||
273 | int ret = EMULATE_DONE; | ||
274 | u32 fetched_inst; | ||
275 | |||
276 | /* Load the instruction manually if it failed to do so in the | ||
277 | * exit path */ | ||
278 | if (vcpu->arch.last_inst == KVM_INST_FETCH_FAILED) | ||
279 | ret = kvmppc_load_last_inst(vcpu, type, &vcpu->arch.last_inst); | ||
280 | |||
281 | /* Write fetch_failed unswapped if the fetch failed */ | ||
282 | if (ret == EMULATE_DONE) | ||
283 | fetched_inst = kvmppc_need_byteswap(vcpu) ? | ||
284 | swab32(vcpu->arch.last_inst) : | ||
285 | vcpu->arch.last_inst; | ||
286 | else | ||
287 | fetched_inst = vcpu->arch.last_inst; | ||
288 | |||
289 | *inst = fetched_inst; | ||
290 | return ret; | ||
291 | } | ||
292 | |||
237 | static inline bool is_kvmppc_hv_enabled(struct kvm *kvm) | 293 | static inline bool is_kvmppc_hv_enabled(struct kvm *kvm) |
238 | { | 294 | { |
239 | return kvm->arch.kvm_ops == kvmppc_hv_ops; | 295 | return kvm->arch.kvm_ops == kvmppc_hv_ops; |
@@ -392,6 +448,17 @@ static inline int kvmppc_xics_hcall(struct kvm_vcpu *vcpu, u32 cmd) | |||
392 | { return 0; } | 448 | { return 0; } |
393 | #endif | 449 | #endif |
394 | 450 | ||
451 | static inline unsigned long kvmppc_get_epr(struct kvm_vcpu *vcpu) | ||
452 | { | ||
453 | #ifdef CONFIG_KVM_BOOKE_HV | ||
454 | return mfspr(SPRN_GEPR); | ||
455 | #elif defined(CONFIG_BOOKE) | ||
456 | return vcpu->arch.epr; | ||
457 | #else | ||
458 | return 0; | ||
459 | #endif | ||
460 | } | ||
461 | |||
395 | static inline void kvmppc_set_epr(struct kvm_vcpu *vcpu, u32 epr) | 462 | static inline void kvmppc_set_epr(struct kvm_vcpu *vcpu, u32 epr) |
396 | { | 463 | { |
397 | #ifdef CONFIG_KVM_BOOKE_HV | 464 | #ifdef CONFIG_KVM_BOOKE_HV |
@@ -472,8 +539,20 @@ static inline bool kvmppc_shared_big_endian(struct kvm_vcpu *vcpu) | |||
472 | #endif | 539 | #endif |
473 | } | 540 | } |
474 | 541 | ||
542 | #define SPRNG_WRAPPER_GET(reg, bookehv_spr) \ | ||
543 | static inline ulong kvmppc_get_##reg(struct kvm_vcpu *vcpu) \ | ||
544 | { \ | ||
545 | return mfspr(bookehv_spr); \ | ||
546 | } \ | ||
547 | |||
548 | #define SPRNG_WRAPPER_SET(reg, bookehv_spr) \ | ||
549 | static inline void kvmppc_set_##reg(struct kvm_vcpu *vcpu, ulong val) \ | ||
550 | { \ | ||
551 | mtspr(bookehv_spr, val); \ | ||
552 | } \ | ||
553 | |||
475 | #define SHARED_WRAPPER_GET(reg, size) \ | 554 | #define SHARED_WRAPPER_GET(reg, size) \ |
476 | static inline u##size kvmppc_get_##reg(struct kvm_vcpu *vcpu) \ | 555 | static inline u##size kvmppc_get_##reg(struct kvm_vcpu *vcpu) \ |
477 | { \ | 556 | { \ |
478 | if (kvmppc_shared_big_endian(vcpu)) \ | 557 | if (kvmppc_shared_big_endian(vcpu)) \ |
479 | return be##size##_to_cpu(vcpu->arch.shared->reg); \ | 558 | return be##size##_to_cpu(vcpu->arch.shared->reg); \ |
@@ -494,14 +573,31 @@ static inline void kvmppc_set_##reg(struct kvm_vcpu *vcpu, u##size val) \ | |||
494 | SHARED_WRAPPER_GET(reg, size) \ | 573 | SHARED_WRAPPER_GET(reg, size) \ |
495 | SHARED_WRAPPER_SET(reg, size) \ | 574 | SHARED_WRAPPER_SET(reg, size) \ |
496 | 575 | ||
576 | #define SPRNG_WRAPPER(reg, bookehv_spr) \ | ||
577 | SPRNG_WRAPPER_GET(reg, bookehv_spr) \ | ||
578 | SPRNG_WRAPPER_SET(reg, bookehv_spr) \ | ||
579 | |||
580 | #ifdef CONFIG_KVM_BOOKE_HV | ||
581 | |||
582 | #define SHARED_SPRNG_WRAPPER(reg, size, bookehv_spr) \ | ||
583 | SPRNG_WRAPPER(reg, bookehv_spr) \ | ||
584 | |||
585 | #else | ||
586 | |||
587 | #define SHARED_SPRNG_WRAPPER(reg, size, bookehv_spr) \ | ||
588 | SHARED_WRAPPER(reg, size) \ | ||
589 | |||
590 | #endif | ||
591 | |||
497 | SHARED_WRAPPER(critical, 64) | 592 | SHARED_WRAPPER(critical, 64) |
498 | SHARED_WRAPPER(sprg0, 64) | 593 | SHARED_SPRNG_WRAPPER(sprg0, 64, SPRN_GSPRG0) |
499 | SHARED_WRAPPER(sprg1, 64) | 594 | SHARED_SPRNG_WRAPPER(sprg1, 64, SPRN_GSPRG1) |
500 | SHARED_WRAPPER(sprg2, 64) | 595 | SHARED_SPRNG_WRAPPER(sprg2, 64, SPRN_GSPRG2) |
501 | SHARED_WRAPPER(sprg3, 64) | 596 | SHARED_SPRNG_WRAPPER(sprg3, 64, SPRN_GSPRG3) |
502 | SHARED_WRAPPER(srr0, 64) | 597 | SHARED_SPRNG_WRAPPER(srr0, 64, SPRN_GSRR0) |
503 | SHARED_WRAPPER(srr1, 64) | 598 | SHARED_SPRNG_WRAPPER(srr1, 64, SPRN_GSRR1) |
504 | SHARED_WRAPPER(dar, 64) | 599 | SHARED_SPRNG_WRAPPER(dar, 64, SPRN_GDEAR) |
600 | SHARED_SPRNG_WRAPPER(esr, 64, SPRN_GESR) | ||
505 | SHARED_WRAPPER_GET(msr, 64) | 601 | SHARED_WRAPPER_GET(msr, 64) |
506 | static inline void kvmppc_set_msr_fast(struct kvm_vcpu *vcpu, u64 val) | 602 | static inline void kvmppc_set_msr_fast(struct kvm_vcpu *vcpu, u64 val) |
507 | { | 603 | { |
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h index f92b0b54e921..b125ceab149c 100644 --- a/arch/powerpc/include/asm/machdep.h +++ b/arch/powerpc/include/asm/machdep.h | |||
@@ -57,10 +57,10 @@ struct machdep_calls { | |||
57 | void (*hpte_removebolted)(unsigned long ea, | 57 | void (*hpte_removebolted)(unsigned long ea, |
58 | int psize, int ssize); | 58 | int psize, int ssize); |
59 | void (*flush_hash_range)(unsigned long number, int local); | 59 | void (*flush_hash_range)(unsigned long number, int local); |
60 | void (*hugepage_invalidate)(struct mm_struct *mm, | 60 | void (*hugepage_invalidate)(unsigned long vsid, |
61 | unsigned long addr, | ||
61 | unsigned char *hpte_slot_array, | 62 | unsigned char *hpte_slot_array, |
62 | unsigned long addr, int psize); | 63 | int psize, int ssize); |
63 | |||
64 | /* special for kexec, to be called in real mode, linear mapping is | 64 | /* special for kexec, to be called in real mode, linear mapping is |
65 | * destroyed as well */ | 65 | * destroyed as well */ |
66 | void (*hpte_clear_all)(void); | 66 | void (*hpte_clear_all)(void); |
@@ -174,6 +174,10 @@ struct machdep_calls { | |||
174 | /* Exception handlers */ | 174 | /* Exception handlers */ |
175 | int (*system_reset_exception)(struct pt_regs *regs); | 175 | int (*system_reset_exception)(struct pt_regs *regs); |
176 | int (*machine_check_exception)(struct pt_regs *regs); | 176 | int (*machine_check_exception)(struct pt_regs *regs); |
177 | int (*handle_hmi_exception)(struct pt_regs *regs); | ||
178 | |||
179 | /* Early exception handlers called in realmode */ | ||
180 | int (*hmi_exception_early)(struct pt_regs *regs); | ||
177 | 181 | ||
178 | /* Called during machine check exception to retrive fixup address. */ | 182 | /* Called during machine check exception to retrive fixup address. */ |
179 | bool (*mce_check_early_recovery)(struct pt_regs *regs); | 183 | bool (*mce_check_early_recovery)(struct pt_regs *regs); |
@@ -366,6 +370,7 @@ static inline void log_error(char *buf, unsigned int err_type, int fatal) | |||
366 | } \ | 370 | } \ |
367 | __define_initcall(__machine_initcall_##mach##_##fn, id); | 371 | __define_initcall(__machine_initcall_##mach##_##fn, id); |
368 | 372 | ||
373 | #define machine_early_initcall(mach, fn) __define_machine_initcall(mach, fn, early) | ||
369 | #define machine_core_initcall(mach, fn) __define_machine_initcall(mach, fn, 1) | 374 | #define machine_core_initcall(mach, fn) __define_machine_initcall(mach, fn, 1) |
370 | #define machine_core_initcall_sync(mach, fn) __define_machine_initcall(mach, fn, 1s) | 375 | #define machine_core_initcall_sync(mach, fn) __define_machine_initcall(mach, fn, 1s) |
371 | #define machine_postcore_initcall(mach, fn) __define_machine_initcall(mach, fn, 2) | 376 | #define machine_postcore_initcall(mach, fn) __define_machine_initcall(mach, fn, 2) |
diff --git a/arch/powerpc/include/asm/mmu-book3e.h b/arch/powerpc/include/asm/mmu-book3e.h index d0918e09557f..cd4f04a74802 100644 --- a/arch/powerpc/include/asm/mmu-book3e.h +++ b/arch/powerpc/include/asm/mmu-book3e.h | |||
@@ -40,7 +40,11 @@ | |||
40 | 40 | ||
41 | /* MAS registers bit definitions */ | 41 | /* MAS registers bit definitions */ |
42 | 42 | ||
43 | #define MAS0_TLBSEL(x) (((x) << 28) & 0x30000000) | 43 | #define MAS0_TLBSEL_MASK 0x30000000 |
44 | #define MAS0_TLBSEL_SHIFT 28 | ||
45 | #define MAS0_TLBSEL(x) (((x) << MAS0_TLBSEL_SHIFT) & MAS0_TLBSEL_MASK) | ||
46 | #define MAS0_GET_TLBSEL(mas0) (((mas0) & MAS0_TLBSEL_MASK) >> \ | ||
47 | MAS0_TLBSEL_SHIFT) | ||
44 | #define MAS0_ESEL_MASK 0x0FFF0000 | 48 | #define MAS0_ESEL_MASK 0x0FFF0000 |
45 | #define MAS0_ESEL_SHIFT 16 | 49 | #define MAS0_ESEL_SHIFT 16 |
46 | #define MAS0_ESEL(x) (((x) << MAS0_ESEL_SHIFT) & MAS0_ESEL_MASK) | 50 | #define MAS0_ESEL(x) (((x) << MAS0_ESEL_SHIFT) & MAS0_ESEL_MASK) |
@@ -58,6 +62,7 @@ | |||
58 | #define MAS1_TSIZE_MASK 0x00000f80 | 62 | #define MAS1_TSIZE_MASK 0x00000f80 |
59 | #define MAS1_TSIZE_SHIFT 7 | 63 | #define MAS1_TSIZE_SHIFT 7 |
60 | #define MAS1_TSIZE(x) (((x) << MAS1_TSIZE_SHIFT) & MAS1_TSIZE_MASK) | 64 | #define MAS1_TSIZE(x) (((x) << MAS1_TSIZE_SHIFT) & MAS1_TSIZE_MASK) |
65 | #define MAS1_GET_TSIZE(mas1) (((mas1) & MAS1_TSIZE_MASK) >> MAS1_TSIZE_SHIFT) | ||
61 | 66 | ||
62 | #define MAS2_EPN (~0xFFFUL) | 67 | #define MAS2_EPN (~0xFFFUL) |
63 | #define MAS2_X0 0x00000040 | 68 | #define MAS2_X0 0x00000040 |
@@ -86,6 +91,7 @@ | |||
86 | #define MAS3_SPSIZE 0x0000003e | 91 | #define MAS3_SPSIZE 0x0000003e |
87 | #define MAS3_SPSIZE_SHIFT 1 | 92 | #define MAS3_SPSIZE_SHIFT 1 |
88 | 93 | ||
94 | #define MAS4_TLBSEL_MASK MAS0_TLBSEL_MASK | ||
89 | #define MAS4_TLBSELD(x) MAS0_TLBSEL(x) | 95 | #define MAS4_TLBSELD(x) MAS0_TLBSEL(x) |
90 | #define MAS4_INDD 0x00008000 /* Default IND */ | 96 | #define MAS4_INDD 0x00008000 /* Default IND */ |
91 | #define MAS4_TSIZED(x) MAS1_TSIZE(x) | 97 | #define MAS4_TSIZED(x) MAS1_TSIZE(x) |
diff --git a/arch/powerpc/include/asm/mmu-hash64.h b/arch/powerpc/include/asm/mmu-hash64.h index c2b4dcf23d03..d76514487d6f 100644 --- a/arch/powerpc/include/asm/mmu-hash64.h +++ b/arch/powerpc/include/asm/mmu-hash64.h | |||
@@ -25,26 +25,6 @@ | |||
25 | #include <asm/processor.h> | 25 | #include <asm/processor.h> |
26 | 26 | ||
27 | /* | 27 | /* |
28 | * Segment table | ||
29 | */ | ||
30 | |||
31 | #define STE_ESID_V 0x80 | ||
32 | #define STE_ESID_KS 0x20 | ||
33 | #define STE_ESID_KP 0x10 | ||
34 | #define STE_ESID_N 0x08 | ||
35 | |||
36 | #define STE_VSID_SHIFT 12 | ||
37 | |||
38 | /* Location of cpu0's segment table */ | ||
39 | #define STAB0_PAGE 0x8 | ||
40 | #define STAB0_OFFSET (STAB0_PAGE << 12) | ||
41 | #define STAB0_PHYS_ADDR (STAB0_OFFSET + PHYSICAL_START) | ||
42 | |||
43 | #ifndef __ASSEMBLY__ | ||
44 | extern char initial_stab[]; | ||
45 | #endif /* ! __ASSEMBLY */ | ||
46 | |||
47 | /* | ||
48 | * SLB | 28 | * SLB |
49 | */ | 29 | */ |
50 | 30 | ||
@@ -370,10 +350,8 @@ extern void hpte_init_lpar(void); | |||
370 | extern void hpte_init_beat(void); | 350 | extern void hpte_init_beat(void); |
371 | extern void hpte_init_beat_v3(void); | 351 | extern void hpte_init_beat_v3(void); |
372 | 352 | ||
373 | extern void stabs_alloc(void); | ||
374 | extern void slb_initialize(void); | 353 | extern void slb_initialize(void); |
375 | extern void slb_flush_and_rebolt(void); | 354 | extern void slb_flush_and_rebolt(void); |
376 | extern void stab_initialize(unsigned long stab); | ||
377 | 355 | ||
378 | extern void slb_vmalloc_update(void); | 356 | extern void slb_vmalloc_update(void); |
379 | extern void slb_set_size(u16 size); | 357 | extern void slb_set_size(u16 size); |
diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h index e61f24ed4e65..3d5abfe6ba67 100644 --- a/arch/powerpc/include/asm/mmu.h +++ b/arch/powerpc/include/asm/mmu.h | |||
@@ -64,9 +64,9 @@ | |||
64 | */ | 64 | */ |
65 | #define MMU_FTR_USE_PAIRED_MAS ASM_CONST(0x01000000) | 65 | #define MMU_FTR_USE_PAIRED_MAS ASM_CONST(0x01000000) |
66 | 66 | ||
67 | /* MMU is SLB-based | 67 | /* Doesn't support the B bit (1T segment) in SLBIE |
68 | */ | 68 | */ |
69 | #define MMU_FTR_SLB ASM_CONST(0x02000000) | 69 | #define MMU_FTR_NO_SLBIE_B ASM_CONST(0x02000000) |
70 | 70 | ||
71 | /* Support 16M large pages | 71 | /* Support 16M large pages |
72 | */ | 72 | */ |
@@ -88,10 +88,6 @@ | |||
88 | */ | 88 | */ |
89 | #define MMU_FTR_1T_SEGMENT ASM_CONST(0x40000000) | 89 | #define MMU_FTR_1T_SEGMENT ASM_CONST(0x40000000) |
90 | 90 | ||
91 | /* Doesn't support the B bit (1T segment) in SLBIE | ||
92 | */ | ||
93 | #define MMU_FTR_NO_SLBIE_B ASM_CONST(0x80000000) | ||
94 | |||
95 | /* MMU feature bit sets for various CPUs */ | 91 | /* MMU feature bit sets for various CPUs */ |
96 | #define MMU_FTRS_DEFAULT_HPTE_ARCH_V2 \ | 92 | #define MMU_FTRS_DEFAULT_HPTE_ARCH_V2 \ |
97 | MMU_FTR_HPTE_TABLE | MMU_FTR_PPCAS_ARCH_V2 | 93 | MMU_FTR_HPTE_TABLE | MMU_FTR_PPCAS_ARCH_V2 |
diff --git a/arch/powerpc/include/asm/mmu_context.h b/arch/powerpc/include/asm/mmu_context.h index b467530e2485..73382eba02dc 100644 --- a/arch/powerpc/include/asm/mmu_context.h +++ b/arch/powerpc/include/asm/mmu_context.h | |||
@@ -18,7 +18,6 @@ extern int init_new_context(struct task_struct *tsk, struct mm_struct *mm); | |||
18 | extern void destroy_context(struct mm_struct *mm); | 18 | extern void destroy_context(struct mm_struct *mm); |
19 | 19 | ||
20 | extern void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next); | 20 | extern void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next); |
21 | extern void switch_stab(struct task_struct *tsk, struct mm_struct *mm); | ||
22 | extern void switch_slb(struct task_struct *tsk, struct mm_struct *mm); | 21 | extern void switch_slb(struct task_struct *tsk, struct mm_struct *mm); |
23 | extern void set_context(unsigned long id, pgd_t *pgd); | 22 | extern void set_context(unsigned long id, pgd_t *pgd); |
24 | 23 | ||
@@ -77,10 +76,7 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, | |||
77 | * sub architectures. | 76 | * sub architectures. |
78 | */ | 77 | */ |
79 | #ifdef CONFIG_PPC_STD_MMU_64 | 78 | #ifdef CONFIG_PPC_STD_MMU_64 |
80 | if (mmu_has_feature(MMU_FTR_SLB)) | 79 | switch_slb(tsk, next); |
81 | switch_slb(tsk, next); | ||
82 | else | ||
83 | switch_stab(tsk, next); | ||
84 | #else | 80 | #else |
85 | /* Out of line for now */ | 81 | /* Out of line for now */ |
86 | switch_mmu_context(prev, next); | 82 | switch_mmu_context(prev, next); |
diff --git a/arch/powerpc/include/asm/mpc85xx.h b/arch/powerpc/include/asm/mpc85xx.h index 736d4acc05a8..3bef74a9914b 100644 --- a/arch/powerpc/include/asm/mpc85xx.h +++ b/arch/powerpc/include/asm/mpc85xx.h | |||
@@ -77,6 +77,8 @@ | |||
77 | #define SVR_T1020 0x852100 | 77 | #define SVR_T1020 0x852100 |
78 | #define SVR_T1021 0x852101 | 78 | #define SVR_T1021 0x852101 |
79 | #define SVR_T1022 0x852102 | 79 | #define SVR_T1022 0x852102 |
80 | #define SVR_T2080 0x853000 | ||
81 | #define SVR_T2081 0x853100 | ||
80 | 82 | ||
81 | #define SVR_8610 0x80A000 | 83 | #define SVR_8610 0x80A000 |
82 | #define SVR_8641 0x809000 | 84 | #define SVR_8641 0x809000 |
diff --git a/arch/powerpc/include/asm/mpc8xx.h b/arch/powerpc/include/asm/mpc8xx.h deleted file mode 100644 index 98f3c4f17328..000000000000 --- a/arch/powerpc/include/asm/mpc8xx.h +++ /dev/null | |||
@@ -1,12 +0,0 @@ | |||
1 | /* This is the single file included by all MPC8xx build options. | ||
2 | * Since there are many different boards and no standard configuration, | ||
3 | * we have a unique include file for each. Rather than change every | ||
4 | * file that has to include MPC8xx configuration, they all include | ||
5 | * this one and the configuration switching is done here. | ||
6 | */ | ||
7 | #ifndef __CONFIG_8xx_DEFS | ||
8 | #define __CONFIG_8xx_DEFS | ||
9 | |||
10 | extern struct mpc8xx_pcmcia_ops m8xx_pcmcia_ops; | ||
11 | |||
12 | #endif /* __CONFIG_8xx_DEFS */ | ||
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h index 0da1dbd42e02..86055e598269 100644 --- a/arch/powerpc/include/asm/opal.h +++ b/arch/powerpc/include/asm/opal.h | |||
@@ -147,6 +147,10 @@ struct opal_sg_list { | |||
147 | #define OPAL_SET_PARAM 90 | 147 | #define OPAL_SET_PARAM 90 |
148 | #define OPAL_DUMP_RESEND 91 | 148 | #define OPAL_DUMP_RESEND 91 |
149 | #define OPAL_DUMP_INFO2 94 | 149 | #define OPAL_DUMP_INFO2 94 |
150 | #define OPAL_PCI_EEH_FREEZE_SET 97 | ||
151 | #define OPAL_HANDLE_HMI 98 | ||
152 | #define OPAL_REGISTER_DUMP_REGION 101 | ||
153 | #define OPAL_UNREGISTER_DUMP_REGION 102 | ||
150 | 154 | ||
151 | #ifndef __ASSEMBLY__ | 155 | #ifndef __ASSEMBLY__ |
152 | 156 | ||
@@ -170,7 +174,11 @@ enum OpalFreezeState { | |||
170 | enum OpalEehFreezeActionToken { | 174 | enum OpalEehFreezeActionToken { |
171 | OPAL_EEH_ACTION_CLEAR_FREEZE_MMIO = 1, | 175 | OPAL_EEH_ACTION_CLEAR_FREEZE_MMIO = 1, |
172 | OPAL_EEH_ACTION_CLEAR_FREEZE_DMA = 2, | 176 | OPAL_EEH_ACTION_CLEAR_FREEZE_DMA = 2, |
173 | OPAL_EEH_ACTION_CLEAR_FREEZE_ALL = 3 | 177 | OPAL_EEH_ACTION_CLEAR_FREEZE_ALL = 3, |
178 | |||
179 | OPAL_EEH_ACTION_SET_FREEZE_MMIO = 1, | ||
180 | OPAL_EEH_ACTION_SET_FREEZE_DMA = 2, | ||
181 | OPAL_EEH_ACTION_SET_FREEZE_ALL = 3 | ||
174 | }; | 182 | }; |
175 | 183 | ||
176 | enum OpalPciStatusToken { | 184 | enum OpalPciStatusToken { |
@@ -240,6 +248,7 @@ enum OpalMessageType { | |||
240 | OPAL_MSG_MEM_ERR, | 248 | OPAL_MSG_MEM_ERR, |
241 | OPAL_MSG_EPOW, | 249 | OPAL_MSG_EPOW, |
242 | OPAL_MSG_SHUTDOWN, | 250 | OPAL_MSG_SHUTDOWN, |
251 | OPAL_MSG_HMI_EVT, | ||
243 | OPAL_MSG_TYPE_MAX, | 252 | OPAL_MSG_TYPE_MAX, |
244 | }; | 253 | }; |
245 | 254 | ||
@@ -340,6 +349,12 @@ enum OpalMveEnableAction { | |||
340 | OPAL_ENABLE_MVE = 1 | 349 | OPAL_ENABLE_MVE = 1 |
341 | }; | 350 | }; |
342 | 351 | ||
352 | enum OpalM64EnableAction { | ||
353 | OPAL_DISABLE_M64 = 0, | ||
354 | OPAL_ENABLE_M64_SPLIT = 1, | ||
355 | OPAL_ENABLE_M64_NON_SPLIT = 2 | ||
356 | }; | ||
357 | |||
343 | enum OpalPciResetScope { | 358 | enum OpalPciResetScope { |
344 | OPAL_PHB_COMPLETE = 1, OPAL_PCI_LINK = 2, OPAL_PHB_ERROR = 3, | 359 | OPAL_PHB_COMPLETE = 1, OPAL_PCI_LINK = 2, OPAL_PHB_ERROR = 3, |
345 | OPAL_PCI_HOT_RESET = 4, OPAL_PCI_FUNDAMENTAL_RESET = 5, | 360 | OPAL_PCI_HOT_RESET = 4, OPAL_PCI_FUNDAMENTAL_RESET = 5, |
@@ -502,6 +517,50 @@ struct OpalMemoryErrorData { | |||
502 | } u; | 517 | } u; |
503 | }; | 518 | }; |
504 | 519 | ||
520 | /* HMI interrupt event */ | ||
521 | enum OpalHMI_Version { | ||
522 | OpalHMIEvt_V1 = 1, | ||
523 | }; | ||
524 | |||
525 | enum OpalHMI_Severity { | ||
526 | OpalHMI_SEV_NO_ERROR = 0, | ||
527 | OpalHMI_SEV_WARNING = 1, | ||
528 | OpalHMI_SEV_ERROR_SYNC = 2, | ||
529 | OpalHMI_SEV_FATAL = 3, | ||
530 | }; | ||
531 | |||
532 | enum OpalHMI_Disposition { | ||
533 | OpalHMI_DISPOSITION_RECOVERED = 0, | ||
534 | OpalHMI_DISPOSITION_NOT_RECOVERED = 1, | ||
535 | }; | ||
536 | |||
537 | enum OpalHMI_ErrType { | ||
538 | OpalHMI_ERROR_MALFUNC_ALERT = 0, | ||
539 | OpalHMI_ERROR_PROC_RECOV_DONE, | ||
540 | OpalHMI_ERROR_PROC_RECOV_DONE_AGAIN, | ||
541 | OpalHMI_ERROR_PROC_RECOV_MASKED, | ||
542 | OpalHMI_ERROR_TFAC, | ||
543 | OpalHMI_ERROR_TFMR_PARITY, | ||
544 | OpalHMI_ERROR_HA_OVERFLOW_WARN, | ||
545 | OpalHMI_ERROR_XSCOM_FAIL, | ||
546 | OpalHMI_ERROR_XSCOM_DONE, | ||
547 | OpalHMI_ERROR_SCOM_FIR, | ||
548 | OpalHMI_ERROR_DEBUG_TRIG_FIR, | ||
549 | OpalHMI_ERROR_HYP_RESOURCE, | ||
550 | }; | ||
551 | |||
552 | struct OpalHMIEvent { | ||
553 | uint8_t version; /* 0x00 */ | ||
554 | uint8_t severity; /* 0x01 */ | ||
555 | uint8_t type; /* 0x02 */ | ||
556 | uint8_t disposition; /* 0x03 */ | ||
557 | uint8_t reserved_1[4]; /* 0x04 */ | ||
558 | |||
559 | __be64 hmer; | ||
560 | /* TFMR register. Valid only for TFAC and TFMR_PARITY error type. */ | ||
561 | __be64 tfmr; | ||
562 | }; | ||
563 | |||
505 | enum { | 564 | enum { |
506 | OPAL_P7IOC_DIAG_TYPE_NONE = 0, | 565 | OPAL_P7IOC_DIAG_TYPE_NONE = 0, |
507 | OPAL_P7IOC_DIAG_TYPE_RGC = 1, | 566 | OPAL_P7IOC_DIAG_TYPE_RGC = 1, |
@@ -513,40 +572,40 @@ enum { | |||
513 | }; | 572 | }; |
514 | 573 | ||
515 | struct OpalIoP7IOCErrorData { | 574 | struct OpalIoP7IOCErrorData { |
516 | uint16_t type; | 575 | __be16 type; |
517 | 576 | ||
518 | /* GEM */ | 577 | /* GEM */ |
519 | uint64_t gemXfir; | 578 | __be64 gemXfir; |
520 | uint64_t gemRfir; | 579 | __be64 gemRfir; |
521 | uint64_t gemRirqfir; | 580 | __be64 gemRirqfir; |
522 | uint64_t gemMask; | 581 | __be64 gemMask; |
523 | uint64_t gemRwof; | 582 | __be64 gemRwof; |
524 | 583 | ||
525 | /* LEM */ | 584 | /* LEM */ |
526 | uint64_t lemFir; | 585 | __be64 lemFir; |
527 | uint64_t lemErrMask; | 586 | __be64 lemErrMask; |
528 | uint64_t lemAction0; | 587 | __be64 lemAction0; |
529 | uint64_t lemAction1; | 588 | __be64 lemAction1; |
530 | uint64_t lemWof; | 589 | __be64 lemWof; |
531 | 590 | ||
532 | union { | 591 | union { |
533 | struct OpalIoP7IOCRgcErrorData { | 592 | struct OpalIoP7IOCRgcErrorData { |
534 | uint64_t rgcStatus; /* 3E1C10 */ | 593 | __be64 rgcStatus; /* 3E1C10 */ |
535 | uint64_t rgcLdcp; /* 3E1C18 */ | 594 | __be64 rgcLdcp; /* 3E1C18 */ |
536 | }rgc; | 595 | }rgc; |
537 | struct OpalIoP7IOCBiErrorData { | 596 | struct OpalIoP7IOCBiErrorData { |
538 | uint64_t biLdcp0; /* 3C0100, 3C0118 */ | 597 | __be64 biLdcp0; /* 3C0100, 3C0118 */ |
539 | uint64_t biLdcp1; /* 3C0108, 3C0120 */ | 598 | __be64 biLdcp1; /* 3C0108, 3C0120 */ |
540 | uint64_t biLdcp2; /* 3C0110, 3C0128 */ | 599 | __be64 biLdcp2; /* 3C0110, 3C0128 */ |
541 | uint64_t biFenceStatus; /* 3C0130, 3C0130 */ | 600 | __be64 biFenceStatus; /* 3C0130, 3C0130 */ |
542 | 601 | ||
543 | uint8_t biDownbound; /* BI Downbound or Upbound */ | 602 | u8 biDownbound; /* BI Downbound or Upbound */ |
544 | }bi; | 603 | }bi; |
545 | struct OpalIoP7IOCCiErrorData { | 604 | struct OpalIoP7IOCCiErrorData { |
546 | uint64_t ciPortStatus; /* 3Dn008 */ | 605 | __be64 ciPortStatus; /* 3Dn008 */ |
547 | uint64_t ciPortLdcp; /* 3Dn010 */ | 606 | __be64 ciPortLdcp; /* 3Dn010 */ |
548 | 607 | ||
549 | uint8_t ciPort; /* Index of CI port: 0/1 */ | 608 | u8 ciPort; /* Index of CI port: 0/1 */ |
550 | }ci; | 609 | }ci; |
551 | }; | 610 | }; |
552 | }; | 611 | }; |
@@ -578,60 +637,60 @@ struct OpalIoPhbErrorCommon { | |||
578 | struct OpalIoP7IOCPhbErrorData { | 637 | struct OpalIoP7IOCPhbErrorData { |
579 | struct OpalIoPhbErrorCommon common; | 638 | struct OpalIoPhbErrorCommon common; |
580 | 639 | ||
581 | uint32_t brdgCtl; | 640 | __be32 brdgCtl; |
582 | 641 | ||
583 | // P7IOC utl regs | 642 | // P7IOC utl regs |
584 | uint32_t portStatusReg; | 643 | __be32 portStatusReg; |
585 | uint32_t rootCmplxStatus; | 644 | __be32 rootCmplxStatus; |
586 | uint32_t busAgentStatus; | 645 | __be32 busAgentStatus; |
587 | 646 | ||
588 | // P7IOC cfg regs | 647 | // P7IOC cfg regs |
589 | uint32_t deviceStatus; | 648 | __be32 deviceStatus; |
590 | uint32_t slotStatus; | 649 | __be32 slotStatus; |
591 | uint32_t linkStatus; | 650 | __be32 linkStatus; |
592 | uint32_t devCmdStatus; | 651 | __be32 devCmdStatus; |
593 | uint32_t devSecStatus; | 652 | __be32 devSecStatus; |
594 | 653 | ||
595 | // cfg AER regs | 654 | // cfg AER regs |
596 | uint32_t rootErrorStatus; | 655 | __be32 rootErrorStatus; |
597 | uint32_t uncorrErrorStatus; | 656 | __be32 uncorrErrorStatus; |
598 | uint32_t corrErrorStatus; | 657 | __be32 corrErrorStatus; |
599 | uint32_t tlpHdr1; | 658 | __be32 tlpHdr1; |
600 | uint32_t tlpHdr2; | 659 | __be32 tlpHdr2; |
601 | uint32_t tlpHdr3; | 660 | __be32 tlpHdr3; |
602 | uint32_t tlpHdr4; | 661 | __be32 tlpHdr4; |
603 | uint32_t sourceId; | 662 | __be32 sourceId; |
604 | 663 | ||
605 | uint32_t rsv3; | 664 | __be32 rsv3; |
606 | 665 | ||
607 | // Record data about the call to allocate a buffer. | 666 | // Record data about the call to allocate a buffer. |
608 | uint64_t errorClass; | 667 | __be64 errorClass; |
609 | uint64_t correlator; | 668 | __be64 correlator; |
610 | 669 | ||
611 | //P7IOC MMIO Error Regs | 670 | //P7IOC MMIO Error Regs |
612 | uint64_t p7iocPlssr; // n120 | 671 | __be64 p7iocPlssr; // n120 |
613 | uint64_t p7iocCsr; // n110 | 672 | __be64 p7iocCsr; // n110 |
614 | uint64_t lemFir; // nC00 | 673 | __be64 lemFir; // nC00 |
615 | uint64_t lemErrorMask; // nC18 | 674 | __be64 lemErrorMask; // nC18 |
616 | uint64_t lemWOF; // nC40 | 675 | __be64 lemWOF; // nC40 |
617 | uint64_t phbErrorStatus; // nC80 | 676 | __be64 phbErrorStatus; // nC80 |
618 | uint64_t phbFirstErrorStatus; // nC88 | 677 | __be64 phbFirstErrorStatus; // nC88 |
619 | uint64_t phbErrorLog0; // nCC0 | 678 | __be64 phbErrorLog0; // nCC0 |
620 | uint64_t phbErrorLog1; // nCC8 | 679 | __be64 phbErrorLog1; // nCC8 |
621 | uint64_t mmioErrorStatus; // nD00 | 680 | __be64 mmioErrorStatus; // nD00 |
622 | uint64_t mmioFirstErrorStatus; // nD08 | 681 | __be64 mmioFirstErrorStatus; // nD08 |
623 | uint64_t mmioErrorLog0; // nD40 | 682 | __be64 mmioErrorLog0; // nD40 |
624 | uint64_t mmioErrorLog1; // nD48 | 683 | __be64 mmioErrorLog1; // nD48 |
625 | uint64_t dma0ErrorStatus; // nD80 | 684 | __be64 dma0ErrorStatus; // nD80 |
626 | uint64_t dma0FirstErrorStatus; // nD88 | 685 | __be64 dma0FirstErrorStatus; // nD88 |
627 | uint64_t dma0ErrorLog0; // nDC0 | 686 | __be64 dma0ErrorLog0; // nDC0 |
628 | uint64_t dma0ErrorLog1; // nDC8 | 687 | __be64 dma0ErrorLog1; // nDC8 |
629 | uint64_t dma1ErrorStatus; // nE00 | 688 | __be64 dma1ErrorStatus; // nE00 |
630 | uint64_t dma1FirstErrorStatus; // nE08 | 689 | __be64 dma1FirstErrorStatus; // nE08 |
631 | uint64_t dma1ErrorLog0; // nE40 | 690 | __be64 dma1ErrorLog0; // nE40 |
632 | uint64_t dma1ErrorLog1; // nE48 | 691 | __be64 dma1ErrorLog1; // nE48 |
633 | uint64_t pestA[OPAL_P7IOC_NUM_PEST_REGS]; | 692 | __be64 pestA[OPAL_P7IOC_NUM_PEST_REGS]; |
634 | uint64_t pestB[OPAL_P7IOC_NUM_PEST_REGS]; | 693 | __be64 pestB[OPAL_P7IOC_NUM_PEST_REGS]; |
635 | }; | 694 | }; |
636 | 695 | ||
637 | struct OpalIoPhb3ErrorData { | 696 | struct OpalIoPhb3ErrorData { |
@@ -758,6 +817,8 @@ int64_t opal_pci_eeh_freeze_status(uint64_t phb_id, uint64_t pe_number, | |||
758 | __be64 *phb_status); | 817 | __be64 *phb_status); |
759 | int64_t opal_pci_eeh_freeze_clear(uint64_t phb_id, uint64_t pe_number, | 818 | int64_t opal_pci_eeh_freeze_clear(uint64_t phb_id, uint64_t pe_number, |
760 | uint64_t eeh_action_token); | 819 | uint64_t eeh_action_token); |
820 | int64_t opal_pci_eeh_freeze_set(uint64_t phb_id, uint64_t pe_number, | ||
821 | uint64_t eeh_action_token); | ||
761 | int64_t opal_pci_shpc(uint64_t phb_id, uint64_t shpc_action, uint8_t *state); | 822 | int64_t opal_pci_shpc(uint64_t phb_id, uint64_t shpc_action, uint8_t *state); |
762 | 823 | ||
763 | 824 | ||
@@ -768,7 +829,7 @@ int64_t opal_pci_set_phb_mem_window(uint64_t phb_id, uint16_t window_type, | |||
768 | uint16_t window_num, | 829 | uint16_t window_num, |
769 | uint64_t starting_real_address, | 830 | uint64_t starting_real_address, |
770 | uint64_t starting_pci_address, | 831 | uint64_t starting_pci_address, |
771 | uint16_t segment_size); | 832 | uint64_t size); |
772 | int64_t opal_pci_map_pe_mmio_window(uint64_t phb_id, uint16_t pe_number, | 833 | int64_t opal_pci_map_pe_mmio_window(uint64_t phb_id, uint16_t pe_number, |
773 | uint16_t window_type, uint16_t window_num, | 834 | uint16_t window_type, uint16_t window_num, |
774 | uint16_t segment_num); | 835 | uint16_t segment_num); |
@@ -860,6 +921,9 @@ int64_t opal_get_param(uint64_t token, uint32_t param_id, uint64_t buffer, | |||
860 | int64_t opal_set_param(uint64_t token, uint32_t param_id, uint64_t buffer, | 921 | int64_t opal_set_param(uint64_t token, uint32_t param_id, uint64_t buffer, |
861 | uint64_t length); | 922 | uint64_t length); |
862 | int64_t opal_sensor_read(uint32_t sensor_hndl, int token, __be32 *sensor_data); | 923 | int64_t opal_sensor_read(uint32_t sensor_hndl, int token, __be32 *sensor_data); |
924 | int64_t opal_handle_hmi(void); | ||
925 | int64_t opal_register_dump_region(uint32_t id, uint64_t start, uint64_t end); | ||
926 | int64_t opal_unregister_dump_region(uint32_t id); | ||
863 | 927 | ||
864 | /* Internal functions */ | 928 | /* Internal functions */ |
865 | extern int early_init_dt_scan_opal(unsigned long node, const char *uname, | 929 | extern int early_init_dt_scan_opal(unsigned long node, const char *uname, |
@@ -902,6 +966,8 @@ extern void opal_msglog_init(void); | |||
902 | 966 | ||
903 | extern int opal_machine_check(struct pt_regs *regs); | 967 | extern int opal_machine_check(struct pt_regs *regs); |
904 | extern bool opal_mce_check_early_recovery(struct pt_regs *regs); | 968 | extern bool opal_mce_check_early_recovery(struct pt_regs *regs); |
969 | extern int opal_hmi_exception_early(struct pt_regs *regs); | ||
970 | extern int opal_handle_hmi_exception(struct pt_regs *regs); | ||
905 | 971 | ||
906 | extern void opal_shutdown(void); | 972 | extern void opal_shutdown(void); |
907 | extern int opal_resync_timebase(void); | 973 | extern int opal_resync_timebase(void); |
@@ -912,6 +978,13 @@ struct opal_sg_list *opal_vmalloc_to_sg_list(void *vmalloc_addr, | |||
912 | unsigned long vmalloc_size); | 978 | unsigned long vmalloc_size); |
913 | void opal_free_sg_list(struct opal_sg_list *sg); | 979 | void opal_free_sg_list(struct opal_sg_list *sg); |
914 | 980 | ||
981 | /* | ||
982 | * Dump region ID range usable by the OS | ||
983 | */ | ||
984 | #define OPAL_DUMP_REGION_HOST_START 0x80 | ||
985 | #define OPAL_DUMP_REGION_LOG_BUF 0x80 | ||
986 | #define OPAL_DUMP_REGION_HOST_END 0xFF | ||
987 | |||
915 | #endif /* __ASSEMBLY__ */ | 988 | #endif /* __ASSEMBLY__ */ |
916 | 989 | ||
917 | #endif /* __OPAL_H */ | 990 | #endif /* __OPAL_H */ |
diff --git a/arch/powerpc/include/asm/oprofile_impl.h b/arch/powerpc/include/asm/oprofile_impl.h index d697b08994c9..61fe5d6f18e1 100644 --- a/arch/powerpc/include/asm/oprofile_impl.h +++ b/arch/powerpc/include/asm/oprofile_impl.h | |||
@@ -61,7 +61,6 @@ struct op_powerpc_model { | |||
61 | }; | 61 | }; |
62 | 62 | ||
63 | extern struct op_powerpc_model op_model_fsl_emb; | 63 | extern struct op_powerpc_model op_model_fsl_emb; |
64 | extern struct op_powerpc_model op_model_rs64; | ||
65 | extern struct op_powerpc_model op_model_power4; | 64 | extern struct op_powerpc_model op_model_power4; |
66 | extern struct op_powerpc_model op_model_7450; | 65 | extern struct op_powerpc_model op_model_7450; |
67 | extern struct op_powerpc_model op_model_cell; | 66 | extern struct op_powerpc_model op_model_cell; |
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h index bb0bd25f20d0..a5139ea6910b 100644 --- a/arch/powerpc/include/asm/paca.h +++ b/arch/powerpc/include/asm/paca.h | |||
@@ -78,10 +78,6 @@ struct paca_struct { | |||
78 | u64 kernel_toc; /* Kernel TOC address */ | 78 | u64 kernel_toc; /* Kernel TOC address */ |
79 | u64 kernelbase; /* Base address of kernel */ | 79 | u64 kernelbase; /* Base address of kernel */ |
80 | u64 kernel_msr; /* MSR while running in kernel */ | 80 | u64 kernel_msr; /* MSR while running in kernel */ |
81 | #ifdef CONFIG_PPC_STD_MMU_64 | ||
82 | u64 stab_real; /* Absolute address of segment table */ | ||
83 | u64 stab_addr; /* Virtual address of segment table */ | ||
84 | #endif /* CONFIG_PPC_STD_MMU_64 */ | ||
85 | void *emergency_sp; /* pointer to emergency stack */ | 81 | void *emergency_sp; /* pointer to emergency stack */ |
86 | u64 data_offset; /* per cpu data offset */ | 82 | u64 data_offset; /* per cpu data offset */ |
87 | s16 hw_cpu_id; /* Physical processor number */ | 83 | s16 hw_cpu_id; /* Physical processor number */ |
@@ -171,6 +167,7 @@ struct paca_struct { | |||
171 | * and already using emergency stack. | 167 | * and already using emergency stack. |
172 | */ | 168 | */ |
173 | u16 in_mce; | 169 | u16 in_mce; |
170 | u8 hmi_event_available; /* HMI event is available */ | ||
174 | #endif | 171 | #endif |
175 | 172 | ||
176 | /* Stuff for accurate time accounting */ | 173 | /* Stuff for accurate time accounting */ |
diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h index 32e4e212b9c1..26fe1ae15212 100644 --- a/arch/powerpc/include/asm/page.h +++ b/arch/powerpc/include/asm/page.h | |||
@@ -48,9 +48,6 @@ extern unsigned int HPAGE_SHIFT; | |||
48 | #define HUGE_MAX_HSTATE (MMU_PAGE_COUNT-1) | 48 | #define HUGE_MAX_HSTATE (MMU_PAGE_COUNT-1) |
49 | #endif | 49 | #endif |
50 | 50 | ||
51 | /* We do define AT_SYSINFO_EHDR but don't use the gate mechanism */ | ||
52 | #define __HAVE_ARCH_GATE_AREA 1 | ||
53 | |||
54 | /* | 51 | /* |
55 | * Subtle: (1 << PAGE_SHIFT) is an int, not an unsigned long. So if we | 52 | * Subtle: (1 << PAGE_SHIFT) is an int, not an unsigned long. So if we |
56 | * assign PAGE_MASK to a larger type it gets extended the way we want | 53 | * assign PAGE_MASK to a larger type it gets extended the way we want |
diff --git a/arch/powerpc/include/asm/perf_event_server.h b/arch/powerpc/include/asm/perf_event_server.h index b3e936027b26..814622146d5a 100644 --- a/arch/powerpc/include/asm/perf_event_server.h +++ b/arch/powerpc/include/asm/perf_event_server.h | |||
@@ -19,6 +19,8 @@ | |||
19 | #define MAX_EVENT_ALTERNATIVES 8 | 19 | #define MAX_EVENT_ALTERNATIVES 8 |
20 | #define MAX_LIMITED_HWCOUNTERS 2 | 20 | #define MAX_LIMITED_HWCOUNTERS 2 |
21 | 21 | ||
22 | struct perf_event; | ||
23 | |||
22 | /* | 24 | /* |
23 | * This struct provides the constants and functions needed to | 25 | * This struct provides the constants and functions needed to |
24 | * describe the PMU on a particular POWER-family CPU. | 26 | * describe the PMU on a particular POWER-family CPU. |
@@ -30,7 +32,8 @@ struct power_pmu { | |||
30 | unsigned long add_fields; | 32 | unsigned long add_fields; |
31 | unsigned long test_adder; | 33 | unsigned long test_adder; |
32 | int (*compute_mmcr)(u64 events[], int n_ev, | 34 | int (*compute_mmcr)(u64 events[], int n_ev, |
33 | unsigned int hwc[], unsigned long mmcr[]); | 35 | unsigned int hwc[], unsigned long mmcr[], |
36 | struct perf_event *pevents[]); | ||
34 | int (*get_constraint)(u64 event_id, unsigned long *mskp, | 37 | int (*get_constraint)(u64 event_id, unsigned long *mskp, |
35 | unsigned long *valp); | 38 | unsigned long *valp); |
36 | int (*get_alternatives)(u64 event_id, unsigned int flags, | 39 | int (*get_alternatives)(u64 event_id, unsigned int flags, |
diff --git a/arch/powerpc/include/asm/pgtable-ppc64.h b/arch/powerpc/include/asm/pgtable-ppc64.h index eb9261024f51..7b3d54fae46f 100644 --- a/arch/powerpc/include/asm/pgtable-ppc64.h +++ b/arch/powerpc/include/asm/pgtable-ppc64.h | |||
@@ -413,7 +413,7 @@ static inline char *get_hpte_slot_array(pmd_t *pmdp) | |||
413 | } | 413 | } |
414 | 414 | ||
415 | extern void hpte_do_hugepage_flush(struct mm_struct *mm, unsigned long addr, | 415 | extern void hpte_do_hugepage_flush(struct mm_struct *mm, unsigned long addr, |
416 | pmd_t *pmdp); | 416 | pmd_t *pmdp, unsigned long old_pmd); |
417 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | 417 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE |
418 | extern pmd_t pfn_pmd(unsigned long pfn, pgprot_t pgprot); | 418 | extern pmd_t pfn_pmd(unsigned long pfn, pgprot_t pgprot); |
419 | extern pmd_t mk_pmd(struct page *page, pgprot_t pgprot); | 419 | extern pmd_t mk_pmd(struct page *page, pgprot_t pgprot); |
diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h index 3132bb9365f3..6f8536208049 100644 --- a/arch/powerpc/include/asm/ppc-opcode.h +++ b/arch/powerpc/include/asm/ppc-opcode.h | |||
@@ -139,6 +139,7 @@ | |||
139 | #define PPC_INST_ISEL 0x7c00001e | 139 | #define PPC_INST_ISEL 0x7c00001e |
140 | #define PPC_INST_ISEL_MASK 0xfc00003e | 140 | #define PPC_INST_ISEL_MASK 0xfc00003e |
141 | #define PPC_INST_LDARX 0x7c0000a8 | 141 | #define PPC_INST_LDARX 0x7c0000a8 |
142 | #define PPC_INST_LOGMPP 0x7c0007e4 | ||
142 | #define PPC_INST_LSWI 0x7c0004aa | 143 | #define PPC_INST_LSWI 0x7c0004aa |
143 | #define PPC_INST_LSWX 0x7c00042a | 144 | #define PPC_INST_LSWX 0x7c00042a |
144 | #define PPC_INST_LWARX 0x7c000028 | 145 | #define PPC_INST_LWARX 0x7c000028 |
@@ -150,8 +151,10 @@ | |||
150 | #define PPC_INST_MCRXR_MASK 0xfc0007fe | 151 | #define PPC_INST_MCRXR_MASK 0xfc0007fe |
151 | #define PPC_INST_MFSPR_PVR 0x7c1f42a6 | 152 | #define PPC_INST_MFSPR_PVR 0x7c1f42a6 |
152 | #define PPC_INST_MFSPR_PVR_MASK 0xfc1fffff | 153 | #define PPC_INST_MFSPR_PVR_MASK 0xfc1fffff |
154 | #define PPC_INST_MFTMR 0x7c0002dc | ||
153 | #define PPC_INST_MSGSND 0x7c00019c | 155 | #define PPC_INST_MSGSND 0x7c00019c |
154 | #define PPC_INST_MSGSNDP 0x7c00011c | 156 | #define PPC_INST_MSGSNDP 0x7c00011c |
157 | #define PPC_INST_MTTMR 0x7c0003dc | ||
155 | #define PPC_INST_NOP 0x60000000 | 158 | #define PPC_INST_NOP 0x60000000 |
156 | #define PPC_INST_POPCNTB 0x7c0000f4 | 159 | #define PPC_INST_POPCNTB 0x7c0000f4 |
157 | #define PPC_INST_POPCNTB_MASK 0xfc0007fe | 160 | #define PPC_INST_POPCNTB_MASK 0xfc0007fe |
@@ -275,6 +278,20 @@ | |||
275 | #define __PPC_EH(eh) 0 | 278 | #define __PPC_EH(eh) 0 |
276 | #endif | 279 | #endif |
277 | 280 | ||
281 | /* POWER8 Micro Partition Prefetch (MPP) parameters */ | ||
282 | /* Address mask is common for LOGMPP instruction and MPPR SPR */ | ||
283 | #define PPC_MPPE_ADDRESS_MASK 0xffffffffc000 | ||
284 | |||
285 | /* Bits 60 and 61 of MPP SPR should be set to one of the following */ | ||
286 | /* Aborting the fetch is indeed setting 00 in the table size bits */ | ||
287 | #define PPC_MPPR_FETCH_ABORT (0x0ULL << 60) | ||
288 | #define PPC_MPPR_FETCH_WHOLE_TABLE (0x2ULL << 60) | ||
289 | |||
290 | /* Bits 54 and 55 of register for LOGMPP instruction should be set to: */ | ||
291 | #define PPC_LOGMPP_LOG_L2 (0x02ULL << 54) | ||
292 | #define PPC_LOGMPP_LOG_L2L3 (0x01ULL << 54) | ||
293 | #define PPC_LOGMPP_LOG_ABORT (0x03ULL << 54) | ||
294 | |||
278 | /* Deal with instructions that older assemblers aren't aware of */ | 295 | /* Deal with instructions that older assemblers aren't aware of */ |
279 | #define PPC_DCBAL(a, b) stringify_in_c(.long PPC_INST_DCBAL | \ | 296 | #define PPC_DCBAL(a, b) stringify_in_c(.long PPC_INST_DCBAL | \ |
280 | __PPC_RA(a) | __PPC_RB(b)) | 297 | __PPC_RA(a) | __PPC_RB(b)) |
@@ -283,6 +300,8 @@ | |||
283 | #define PPC_LDARX(t, a, b, eh) stringify_in_c(.long PPC_INST_LDARX | \ | 300 | #define PPC_LDARX(t, a, b, eh) stringify_in_c(.long PPC_INST_LDARX | \ |
284 | ___PPC_RT(t) | ___PPC_RA(a) | \ | 301 | ___PPC_RT(t) | ___PPC_RA(a) | \ |
285 | ___PPC_RB(b) | __PPC_EH(eh)) | 302 | ___PPC_RB(b) | __PPC_EH(eh)) |
303 | #define PPC_LOGMPP(b) stringify_in_c(.long PPC_INST_LOGMPP | \ | ||
304 | __PPC_RB(b)) | ||
286 | #define PPC_LWARX(t, a, b, eh) stringify_in_c(.long PPC_INST_LWARX | \ | 305 | #define PPC_LWARX(t, a, b, eh) stringify_in_c(.long PPC_INST_LWARX | \ |
287 | ___PPC_RT(t) | ___PPC_RA(a) | \ | 306 | ___PPC_RT(t) | ___PPC_RA(a) | \ |
288 | ___PPC_RB(b) | __PPC_EH(eh)) | 307 | ___PPC_RB(b) | __PPC_EH(eh)) |
@@ -369,4 +388,11 @@ | |||
369 | #define TABORT(r) stringify_in_c(.long PPC_INST_TABORT \ | 388 | #define TABORT(r) stringify_in_c(.long PPC_INST_TABORT \ |
370 | | __PPC_RA(r)) | 389 | | __PPC_RA(r)) |
371 | 390 | ||
391 | /* book3e thread control instructions */ | ||
392 | #define TMRN(x) ((((x) & 0x1f) << 16) | (((x) & 0x3e0) << 6)) | ||
393 | #define MTTMR(tmr, r) stringify_in_c(.long PPC_INST_MTTMR | \ | ||
394 | TMRN(tmr) | ___PPC_RS(r)) | ||
395 | #define MFTMR(tmr, r) stringify_in_c(.long PPC_INST_MFTMR | \ | ||
396 | TMRN(tmr) | ___PPC_RT(r)) | ||
397 | |||
372 | #endif /* _ASM_POWERPC_PPC_OPCODE_H */ | 398 | #endif /* _ASM_POWERPC_PPC_OPCODE_H */ |
diff --git a/arch/powerpc/include/asm/pte-fsl-booke.h b/arch/powerpc/include/asm/pte-fsl-booke.h index 2c12be5f677a..e84dd7ed505e 100644 --- a/arch/powerpc/include/asm/pte-fsl-booke.h +++ b/arch/powerpc/include/asm/pte-fsl-booke.h | |||
@@ -37,5 +37,7 @@ | |||
37 | #define _PMD_PRESENT_MASK (PAGE_MASK) | 37 | #define _PMD_PRESENT_MASK (PAGE_MASK) |
38 | #define _PMD_BAD (~PAGE_MASK) | 38 | #define _PMD_BAD (~PAGE_MASK) |
39 | 39 | ||
40 | #define PTE_WIMGE_SHIFT (6) | ||
41 | |||
40 | #endif /* __KERNEL__ */ | 42 | #endif /* __KERNEL__ */ |
41 | #endif /* _ASM_POWERPC_PTE_FSL_BOOKE_H */ | 43 | #endif /* _ASM_POWERPC_PTE_FSL_BOOKE_H */ |
diff --git a/arch/powerpc/include/asm/pte-hash64-64k.h b/arch/powerpc/include/asm/pte-hash64-64k.h index d836d945068d..4f4ec2ab45c9 100644 --- a/arch/powerpc/include/asm/pte-hash64-64k.h +++ b/arch/powerpc/include/asm/pte-hash64-64k.h | |||
@@ -46,11 +46,31 @@ | |||
46 | * in order to deal with 64K made of 4K HW pages. Thus we override the | 46 | * in order to deal with 64K made of 4K HW pages. Thus we override the |
47 | * generic accessors and iterators here | 47 | * generic accessors and iterators here |
48 | */ | 48 | */ |
49 | #define __real_pte(e,p) ((real_pte_t) { \ | 49 | #define __real_pte __real_pte |
50 | (e), (pte_val(e) & _PAGE_COMBO) ? \ | 50 | static inline real_pte_t __real_pte(pte_t pte, pte_t *ptep) |
51 | (pte_val(*((p) + PTRS_PER_PTE))) : 0 }) | 51 | { |
52 | #define __rpte_to_hidx(r,index) ((pte_val((r).pte) & _PAGE_COMBO) ? \ | 52 | real_pte_t rpte; |
53 | (((r).hidx >> ((index)<<2)) & 0xf) : ((pte_val((r).pte) >> 12) & 0xf)) | 53 | |
54 | rpte.pte = pte; | ||
55 | rpte.hidx = 0; | ||
56 | if (pte_val(pte) & _PAGE_COMBO) { | ||
57 | /* | ||
58 | * Make sure we order the hidx load against the _PAGE_COMBO | ||
59 | * check. The store side ordering is done in __hash_page_4K | ||
60 | */ | ||
61 | smp_rmb(); | ||
62 | rpte.hidx = pte_val(*((ptep) + PTRS_PER_PTE)); | ||
63 | } | ||
64 | return rpte; | ||
65 | } | ||
66 | |||
67 | static inline unsigned long __rpte_to_hidx(real_pte_t rpte, unsigned long index) | ||
68 | { | ||
69 | if ((pte_val(rpte.pte) & _PAGE_COMBO)) | ||
70 | return (rpte.hidx >> (index<<2)) & 0xf; | ||
71 | return (pte_val(rpte.pte) >> 12) & 0xf; | ||
72 | } | ||
73 | |||
54 | #define __rpte_to_pte(r) ((r).pte) | 74 | #define __rpte_to_pte(r) ((r).pte) |
55 | #define __rpte_sub_valid(rpte, index) \ | 75 | #define __rpte_sub_valid(rpte, index) \ |
56 | (pte_val(rpte.pte) & (_PAGE_HPTE_SUB0 >> (index))) | 76 | (pte_val(rpte.pte) & (_PAGE_HPTE_SUB0 >> (index))) |
@@ -75,7 +95,8 @@ | |||
75 | (((pte) & _PAGE_COMBO)? MMU_PAGE_4K: MMU_PAGE_64K) | 95 | (((pte) & _PAGE_COMBO)? MMU_PAGE_4K: MMU_PAGE_64K) |
76 | 96 | ||
77 | #define remap_4k_pfn(vma, addr, pfn, prot) \ | 97 | #define remap_4k_pfn(vma, addr, pfn, prot) \ |
78 | remap_pfn_range((vma), (addr), (pfn), PAGE_SIZE, \ | 98 | (WARN_ON(((pfn) >= (1UL << (64 - PTE_RPN_SHIFT)))) ? -EINVAL : \ |
79 | __pgprot(pgprot_val((prot)) | _PAGE_4K_PFN)) | 99 | remap_pfn_range((vma), (addr), (pfn), PAGE_SIZE, \ |
100 | __pgprot(pgprot_val((prot)) | _PAGE_4K_PFN))) | ||
80 | 101 | ||
81 | #endif /* __ASSEMBLY__ */ | 102 | #endif /* __ASSEMBLY__ */ |
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index bffd89d27301..0c0505956a29 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h | |||
@@ -213,9 +213,8 @@ | |||
213 | #define SPRN_ACOP 0x1F /* Available Coprocessor Register */ | 213 | #define SPRN_ACOP 0x1F /* Available Coprocessor Register */ |
214 | #define SPRN_TFIAR 0x81 /* Transaction Failure Inst Addr */ | 214 | #define SPRN_TFIAR 0x81 /* Transaction Failure Inst Addr */ |
215 | #define SPRN_TEXASR 0x82 /* Transaction EXception & Summary */ | 215 | #define SPRN_TEXASR 0x82 /* Transaction EXception & Summary */ |
216 | #define TEXASR_FS __MASK(63-36) /* Transaction Failure Summary */ | ||
217 | #define SPRN_TEXASRU 0x83 /* '' '' '' Upper 32 */ | 216 | #define SPRN_TEXASRU 0x83 /* '' '' '' Upper 32 */ |
218 | #define TEXASR_FS __MASK(63-36) /* TEXASR Failure Summary */ | 217 | #define TEXASR_FS __MASK(63-36) /* TEXASR Failure Summary */ |
219 | #define SPRN_TFHAR 0x80 /* Transaction Failure Handler Addr */ | 218 | #define SPRN_TFHAR 0x80 /* Transaction Failure Handler Addr */ |
220 | #define SPRN_CTRLF 0x088 | 219 | #define SPRN_CTRLF 0x088 |
221 | #define SPRN_CTRLT 0x098 | 220 | #define SPRN_CTRLT 0x098 |
@@ -225,6 +224,7 @@ | |||
225 | #define CTRL_TE 0x00c00000 /* thread enable */ | 224 | #define CTRL_TE 0x00c00000 /* thread enable */ |
226 | #define CTRL_RUNLATCH 0x1 | 225 | #define CTRL_RUNLATCH 0x1 |
227 | #define SPRN_DAWR 0xB4 | 226 | #define SPRN_DAWR 0xB4 |
227 | #define SPRN_MPPR 0xB8 /* Micro Partition Prefetch Register */ | ||
228 | #define SPRN_RPR 0xBA /* Relative Priority Register */ | 228 | #define SPRN_RPR 0xBA /* Relative Priority Register */ |
229 | #define SPRN_CIABR 0xBB | 229 | #define SPRN_CIABR 0xBB |
230 | #define CIABR_PRIV 0x3 | 230 | #define CIABR_PRIV 0x3 |
@@ -254,7 +254,7 @@ | |||
254 | #define DSISR_PROTFAULT 0x08000000 /* protection fault */ | 254 | #define DSISR_PROTFAULT 0x08000000 /* protection fault */ |
255 | #define DSISR_ISSTORE 0x02000000 /* access was a store */ | 255 | #define DSISR_ISSTORE 0x02000000 /* access was a store */ |
256 | #define DSISR_DABRMATCH 0x00400000 /* hit data breakpoint */ | 256 | #define DSISR_DABRMATCH 0x00400000 /* hit data breakpoint */ |
257 | #define DSISR_NOSEGMENT 0x00200000 /* STAB/SLB miss */ | 257 | #define DSISR_NOSEGMENT 0x00200000 /* SLB miss */ |
258 | #define DSISR_KEYFAULT 0x00200000 /* Key fault */ | 258 | #define DSISR_KEYFAULT 0x00200000 /* Key fault */ |
259 | #define SPRN_TBRL 0x10C /* Time Base Read Lower Register (user, R/O) */ | 259 | #define SPRN_TBRL 0x10C /* Time Base Read Lower Register (user, R/O) */ |
260 | #define SPRN_TBRU 0x10D /* Time Base Read Upper Register (user, R/O) */ | 260 | #define SPRN_TBRU 0x10D /* Time Base Read Upper Register (user, R/O) */ |
@@ -944,9 +944,6 @@ | |||
944 | * readable variant for reads, which can avoid a fault | 944 | * readable variant for reads, which can avoid a fault |
945 | * with KVM type virtualization. | 945 | * with KVM type virtualization. |
946 | * | 946 | * |
947 | * (*) Under KVM, the host SPRG1 is used to point to | ||
948 | * the current VCPU data structure | ||
949 | * | ||
950 | * 32-bit 8xx: | 947 | * 32-bit 8xx: |
951 | * - SPRG0 scratch for exception vectors | 948 | * - SPRG0 scratch for exception vectors |
952 | * - SPRG1 scratch for exception vectors | 949 | * - SPRG1 scratch for exception vectors |
@@ -1203,6 +1200,15 @@ | |||
1203 | : "r" ((unsigned long)(v)) \ | 1200 | : "r" ((unsigned long)(v)) \ |
1204 | : "memory") | 1201 | : "memory") |
1205 | 1202 | ||
1203 | static inline unsigned long mfvtb (void) | ||
1204 | { | ||
1205 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
1206 | if (cpu_has_feature(CPU_FTR_ARCH_207S)) | ||
1207 | return mfspr(SPRN_VTB); | ||
1208 | #endif | ||
1209 | return 0; | ||
1210 | } | ||
1211 | |||
1206 | #ifdef __powerpc64__ | 1212 | #ifdef __powerpc64__ |
1207 | #if defined(CONFIG_PPC_CELL) || defined(CONFIG_PPC_FSL_BOOK3E) | 1213 | #if defined(CONFIG_PPC_CELL) || defined(CONFIG_PPC_FSL_BOOK3E) |
1208 | #define mftb() ({unsigned long rval; \ | 1214 | #define mftb() ({unsigned long rval; \ |
diff --git a/arch/powerpc/include/asm/reg_booke.h b/arch/powerpc/include/asm/reg_booke.h index 464f1089b532..1d653308a33c 100644 --- a/arch/powerpc/include/asm/reg_booke.h +++ b/arch/powerpc/include/asm/reg_booke.h | |||
@@ -15,16 +15,28 @@ | |||
15 | #ifndef __ASM_POWERPC_REG_BOOKE_H__ | 15 | #ifndef __ASM_POWERPC_REG_BOOKE_H__ |
16 | #define __ASM_POWERPC_REG_BOOKE_H__ | 16 | #define __ASM_POWERPC_REG_BOOKE_H__ |
17 | 17 | ||
18 | #include <asm/ppc-opcode.h> | ||
19 | |||
18 | /* Machine State Register (MSR) Fields */ | 20 | /* Machine State Register (MSR) Fields */ |
19 | #define MSR_GS (1<<28) /* Guest state */ | 21 | #define MSR_GS_LG 28 /* Guest state */ |
20 | #define MSR_UCLE (1<<26) /* User-mode cache lock enable */ | 22 | #define MSR_UCLE_LG 26 /* User-mode cache lock enable */ |
21 | #define MSR_SPE (1<<25) /* Enable SPE */ | 23 | #define MSR_SPE_LG 25 /* Enable SPE */ |
22 | #define MSR_DWE (1<<10) /* Debug Wait Enable */ | 24 | #define MSR_DWE_LG 10 /* Debug Wait Enable */ |
23 | #define MSR_UBLE (1<<10) /* BTB lock enable (e500) */ | 25 | #define MSR_UBLE_LG 10 /* BTB lock enable (e500) */ |
24 | #define MSR_IS MSR_IR /* Instruction Space */ | 26 | #define MSR_IS_LG MSR_IR_LG /* Instruction Space */ |
25 | #define MSR_DS MSR_DR /* Data Space */ | 27 | #define MSR_DS_LG MSR_DR_LG /* Data Space */ |
26 | #define MSR_PMM (1<<2) /* Performance monitor mark bit */ | 28 | #define MSR_PMM_LG 2 /* Performance monitor mark bit */ |
27 | #define MSR_CM (1<<31) /* Computation Mode (0=32-bit, 1=64-bit) */ | 29 | #define MSR_CM_LG 31 /* Computation Mode (0=32-bit, 1=64-bit) */ |
30 | |||
31 | #define MSR_GS __MASK(MSR_GS_LG) | ||
32 | #define MSR_UCLE __MASK(MSR_UCLE_LG) | ||
33 | #define MSR_SPE __MASK(MSR_SPE_LG) | ||
34 | #define MSR_DWE __MASK(MSR_DWE_LG) | ||
35 | #define MSR_UBLE __MASK(MSR_UBLE_LG) | ||
36 | #define MSR_IS __MASK(MSR_IS_LG) | ||
37 | #define MSR_DS __MASK(MSR_DS_LG) | ||
38 | #define MSR_PMM __MASK(MSR_PMM_LG) | ||
39 | #define MSR_CM __MASK(MSR_CM_LG) | ||
28 | 40 | ||
29 | #if defined(CONFIG_PPC_BOOK3E_64) | 41 | #if defined(CONFIG_PPC_BOOK3E_64) |
30 | #define MSR_64BIT MSR_CM | 42 | #define MSR_64BIT MSR_CM |
@@ -260,7 +272,7 @@ | |||
260 | 272 | ||
261 | /* e500mc */ | 273 | /* e500mc */ |
262 | #define MCSR_DCPERR_MC 0x20000000UL /* D-Cache Parity Error */ | 274 | #define MCSR_DCPERR_MC 0x20000000UL /* D-Cache Parity Error */ |
263 | #define MCSR_L2MMU_MHIT 0x04000000UL /* Hit on multiple TLB entries */ | 275 | #define MCSR_L2MMU_MHIT 0x08000000UL /* Hit on multiple TLB entries */ |
264 | #define MCSR_NMI 0x00100000UL /* Non-Maskable Interrupt */ | 276 | #define MCSR_NMI 0x00100000UL /* Non-Maskable Interrupt */ |
265 | #define MCSR_MAV 0x00080000UL /* MCAR address valid */ | 277 | #define MCSR_MAV 0x00080000UL /* MCAR address valid */ |
266 | #define MCSR_MEA 0x00040000UL /* MCAR is effective address */ | 278 | #define MCSR_MEA 0x00040000UL /* MCAR is effective address */ |
@@ -598,6 +610,13 @@ | |||
598 | /* Bit definitions for L1CSR2. */ | 610 | /* Bit definitions for L1CSR2. */ |
599 | #define L1CSR2_DCWS 0x40000000 /* Data Cache write shadow */ | 611 | #define L1CSR2_DCWS 0x40000000 /* Data Cache write shadow */ |
600 | 612 | ||
613 | /* Bit definitions for BUCSR. */ | ||
614 | #define BUCSR_STAC_EN 0x01000000 /* Segment Target Address Cache */ | ||
615 | #define BUCSR_LS_EN 0x00400000 /* Link Stack */ | ||
616 | #define BUCSR_BBFI 0x00000200 /* Branch Buffer flash invalidate */ | ||
617 | #define BUCSR_BPEN 0x00000001 /* Branch prediction enable */ | ||
618 | #define BUCSR_INIT (BUCSR_STAC_EN | BUCSR_LS_EN | BUCSR_BBFI | BUCSR_BPEN) | ||
619 | |||
601 | /* Bit definitions for L2CSR0. */ | 620 | /* Bit definitions for L2CSR0. */ |
602 | #define L2CSR0_L2E 0x80000000 /* L2 Cache Enable */ | 621 | #define L2CSR0_L2E 0x80000000 /* L2 Cache Enable */ |
603 | #define L2CSR0_L2PE 0x40000000 /* L2 Cache Parity/ECC Enable */ | 622 | #define L2CSR0_L2PE 0x40000000 /* L2 Cache Parity/ECC Enable */ |
@@ -721,5 +740,23 @@ | |||
721 | #define MMUBE1_VBE4 0x00000002 | 740 | #define MMUBE1_VBE4 0x00000002 |
722 | #define MMUBE1_VBE5 0x00000001 | 741 | #define MMUBE1_VBE5 0x00000001 |
723 | 742 | ||
743 | #define TMRN_IMSR0 0x120 /* Initial MSR Register 0 (e6500) */ | ||
744 | #define TMRN_IMSR1 0x121 /* Initial MSR Register 1 (e6500) */ | ||
745 | #define TMRN_INIA0 0x140 /* Next Instruction Address Register 0 */ | ||
746 | #define TMRN_INIA1 0x141 /* Next Instruction Address Register 1 */ | ||
747 | #define SPRN_TENSR 0x1b5 /* Thread Enable Status Register */ | ||
748 | #define SPRN_TENS 0x1b6 /* Thread Enable Set Register */ | ||
749 | #define SPRN_TENC 0x1b7 /* Thread Enable Clear Register */ | ||
750 | |||
751 | #define TEN_THREAD(x) (1 << (x)) | ||
752 | |||
753 | #ifndef __ASSEMBLY__ | ||
754 | #define mftmr(rn) ({unsigned long rval; \ | ||
755 | asm volatile(MFTMR(rn, %0) : "=r" (rval)); rval;}) | ||
756 | #define mttmr(rn, v) asm volatile(MTTMR(rn, %0) : \ | ||
757 | : "r" ((unsigned long)(v)) \ | ||
758 | : "memory") | ||
759 | #endif /* !__ASSEMBLY__ */ | ||
760 | |||
724 | #endif /* __ASM_POWERPC_REG_BOOKE_H__ */ | 761 | #endif /* __ASM_POWERPC_REG_BOOKE_H__ */ |
725 | #endif /* __KERNEL__ */ | 762 | #endif /* __KERNEL__ */ |
diff --git a/arch/powerpc/include/asm/scatterlist.h b/arch/powerpc/include/asm/scatterlist.h deleted file mode 100644 index de1f620bd5c9..000000000000 --- a/arch/powerpc/include/asm/scatterlist.h +++ /dev/null | |||
@@ -1,17 +0,0 @@ | |||
1 | #ifndef _ASM_POWERPC_SCATTERLIST_H | ||
2 | #define _ASM_POWERPC_SCATTERLIST_H | ||
3 | /* | ||
4 | * Copyright (C) 2001 PPC64 Team, IBM Corp | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <asm/dma.h> | ||
13 | #include <asm-generic/scatterlist.h> | ||
14 | |||
15 | #define ARCH_HAS_SG_CHAIN | ||
16 | |||
17 | #endif /* _ASM_POWERPC_SCATTERLIST_H */ | ||
diff --git a/arch/powerpc/include/asm/spinlock.h b/arch/powerpc/include/asm/spinlock.h index 35aa339410bd..4dbe072eecbe 100644 --- a/arch/powerpc/include/asm/spinlock.h +++ b/arch/powerpc/include/asm/spinlock.h | |||
@@ -61,6 +61,7 @@ static __always_inline int arch_spin_value_unlocked(arch_spinlock_t lock) | |||
61 | 61 | ||
62 | static inline int arch_spin_is_locked(arch_spinlock_t *lock) | 62 | static inline int arch_spin_is_locked(arch_spinlock_t *lock) |
63 | { | 63 | { |
64 | smp_mb(); | ||
64 | return !arch_spin_value_unlocked(*lock); | 65 | return !arch_spin_value_unlocked(*lock); |
65 | } | 66 | } |
66 | 67 | ||
diff --git a/arch/powerpc/include/asm/systbl.h b/arch/powerpc/include/asm/systbl.h index babbeca6850f..542bc0f0673f 100644 --- a/arch/powerpc/include/asm/systbl.h +++ b/arch/powerpc/include/asm/systbl.h | |||
@@ -77,10 +77,10 @@ SYSCALL_SPU(setreuid) | |||
77 | SYSCALL_SPU(setregid) | 77 | SYSCALL_SPU(setregid) |
78 | #define compat_sys_sigsuspend sys_sigsuspend | 78 | #define compat_sys_sigsuspend sys_sigsuspend |
79 | SYS32ONLY(sigsuspend) | 79 | SYS32ONLY(sigsuspend) |
80 | COMPAT_SYS(sigpending) | 80 | SYSX(sys_ni_syscall,compat_sys_sigpending,sys_sigpending) |
81 | SYSCALL_SPU(sethostname) | 81 | SYSCALL_SPU(sethostname) |
82 | COMPAT_SYS_SPU(setrlimit) | 82 | COMPAT_SYS_SPU(setrlimit) |
83 | COMPAT_SYS(old_getrlimit) | 83 | SYSX(sys_ni_syscall,compat_sys_old_getrlimit,sys_old_getrlimit) |
84 | COMPAT_SYS_SPU(getrusage) | 84 | COMPAT_SYS_SPU(getrusage) |
85 | COMPAT_SYS_SPU(gettimeofday) | 85 | COMPAT_SYS_SPU(gettimeofday) |
86 | COMPAT_SYS_SPU(settimeofday) | 86 | COMPAT_SYS_SPU(settimeofday) |
diff --git a/arch/powerpc/include/asm/time.h b/arch/powerpc/include/asm/time.h index 1d428e6007ca..03cbada59d3a 100644 --- a/arch/powerpc/include/asm/time.h +++ b/arch/powerpc/include/asm/time.h | |||
@@ -102,6 +102,15 @@ static inline u64 get_rtc(void) | |||
102 | return (u64)hi * 1000000000 + lo; | 102 | return (u64)hi * 1000000000 + lo; |
103 | } | 103 | } |
104 | 104 | ||
105 | static inline u64 get_vtb(void) | ||
106 | { | ||
107 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
108 | if (cpu_has_feature(CPU_FTR_ARCH_207S)) | ||
109 | return mfvtb(); | ||
110 | #endif | ||
111 | return 0; | ||
112 | } | ||
113 | |||
105 | #ifdef CONFIG_PPC64 | 114 | #ifdef CONFIG_PPC64 |
106 | static inline u64 get_tb(void) | 115 | static inline u64 get_tb(void) |
107 | { | 116 | { |
diff --git a/arch/powerpc/include/asm/trace.h b/arch/powerpc/include/asm/trace.h index 5712f06905a9..c15da6073cb8 100644 --- a/arch/powerpc/include/asm/trace.h +++ b/arch/powerpc/include/asm/trace.h | |||
@@ -99,6 +99,51 @@ TRACE_EVENT_FN(hcall_exit, | |||
99 | ); | 99 | ); |
100 | #endif | 100 | #endif |
101 | 101 | ||
102 | #ifdef CONFIG_PPC_POWERNV | ||
103 | extern void opal_tracepoint_regfunc(void); | ||
104 | extern void opal_tracepoint_unregfunc(void); | ||
105 | |||
106 | TRACE_EVENT_FN(opal_entry, | ||
107 | |||
108 | TP_PROTO(unsigned long opcode, unsigned long *args), | ||
109 | |||
110 | TP_ARGS(opcode, args), | ||
111 | |||
112 | TP_STRUCT__entry( | ||
113 | __field(unsigned long, opcode) | ||
114 | ), | ||
115 | |||
116 | TP_fast_assign( | ||
117 | __entry->opcode = opcode; | ||
118 | ), | ||
119 | |||
120 | TP_printk("opcode=%lu", __entry->opcode), | ||
121 | |||
122 | opal_tracepoint_regfunc, opal_tracepoint_unregfunc | ||
123 | ); | ||
124 | |||
125 | TRACE_EVENT_FN(opal_exit, | ||
126 | |||
127 | TP_PROTO(unsigned long opcode, unsigned long retval), | ||
128 | |||
129 | TP_ARGS(opcode, retval), | ||
130 | |||
131 | TP_STRUCT__entry( | ||
132 | __field(unsigned long, opcode) | ||
133 | __field(unsigned long, retval) | ||
134 | ), | ||
135 | |||
136 | TP_fast_assign( | ||
137 | __entry->opcode = opcode; | ||
138 | __entry->retval = retval; | ||
139 | ), | ||
140 | |||
141 | TP_printk("opcode=%lu retval=%lu", __entry->opcode, __entry->retval), | ||
142 | |||
143 | opal_tracepoint_regfunc, opal_tracepoint_unregfunc | ||
144 | ); | ||
145 | #endif | ||
146 | |||
102 | #endif /* _TRACE_POWERPC_H */ | 147 | #endif /* _TRACE_POWERPC_H */ |
103 | 148 | ||
104 | #undef TRACE_INCLUDE_PATH | 149 | #undef TRACE_INCLUDE_PATH |
diff --git a/arch/powerpc/include/uapi/asm/kvm.h b/arch/powerpc/include/uapi/asm/kvm.h index 2bc4a9409a93..e0e49dbb145d 100644 --- a/arch/powerpc/include/uapi/asm/kvm.h +++ b/arch/powerpc/include/uapi/asm/kvm.h | |||
@@ -548,6 +548,7 @@ struct kvm_get_htab_header { | |||
548 | 548 | ||
549 | #define KVM_REG_PPC_VRSAVE (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb4) | 549 | #define KVM_REG_PPC_VRSAVE (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb4) |
550 | #define KVM_REG_PPC_LPCR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb5) | 550 | #define KVM_REG_PPC_LPCR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb5) |
551 | #define KVM_REG_PPC_LPCR_64 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb5) | ||
551 | #define KVM_REG_PPC_PPR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb6) | 552 | #define KVM_REG_PPC_PPR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb6) |
552 | 553 | ||
553 | /* Architecture compatibility level */ | 554 | /* Architecture compatibility level */ |
@@ -555,6 +556,7 @@ struct kvm_get_htab_header { | |||
555 | 556 | ||
556 | #define KVM_REG_PPC_DABRX (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb8) | 557 | #define KVM_REG_PPC_DABRX (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb8) |
557 | #define KVM_REG_PPC_WORT (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb9) | 558 | #define KVM_REG_PPC_WORT (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb9) |
559 | #define KVM_REG_PPC_SPRG9 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xba) | ||
558 | 560 | ||
559 | /* Transactional Memory checkpointed state: | 561 | /* Transactional Memory checkpointed state: |
560 | * This is all GPRs, all VSX regs and a subset of SPRs | 562 | * This is all GPRs, all VSX regs and a subset of SPRs |
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index f5995a912213..9d7dede2847c 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
@@ -216,8 +216,6 @@ int main(void) | |||
216 | #endif /* CONFIG_PPC_BOOK3E */ | 216 | #endif /* CONFIG_PPC_BOOK3E */ |
217 | 217 | ||
218 | #ifdef CONFIG_PPC_STD_MMU_64 | 218 | #ifdef CONFIG_PPC_STD_MMU_64 |
219 | DEFINE(PACASTABREAL, offsetof(struct paca_struct, stab_real)); | ||
220 | DEFINE(PACASTABVIRT, offsetof(struct paca_struct, stab_addr)); | ||
221 | DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache)); | 219 | DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache)); |
222 | DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr)); | 220 | DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr)); |
223 | DEFINE(PACAVMALLOCSLLP, offsetof(struct paca_struct, vmalloc_sllp)); | 221 | DEFINE(PACAVMALLOCSLLP, offsetof(struct paca_struct, vmalloc_sllp)); |
@@ -493,6 +491,7 @@ int main(void) | |||
493 | DEFINE(KVM_HOST_SDR1, offsetof(struct kvm, arch.host_sdr1)); | 491 | DEFINE(KVM_HOST_SDR1, offsetof(struct kvm, arch.host_sdr1)); |
494 | DEFINE(KVM_TLBIE_LOCK, offsetof(struct kvm, arch.tlbie_lock)); | 492 | DEFINE(KVM_TLBIE_LOCK, offsetof(struct kvm, arch.tlbie_lock)); |
495 | DEFINE(KVM_NEED_FLUSH, offsetof(struct kvm, arch.need_tlb_flush.bits)); | 493 | DEFINE(KVM_NEED_FLUSH, offsetof(struct kvm, arch.need_tlb_flush.bits)); |
494 | DEFINE(KVM_ENABLED_HCALLS, offsetof(struct kvm, arch.enabled_hcalls)); | ||
496 | DEFINE(KVM_LPCR, offsetof(struct kvm, arch.lpcr)); | 495 | DEFINE(KVM_LPCR, offsetof(struct kvm, arch.lpcr)); |
497 | DEFINE(KVM_RMOR, offsetof(struct kvm, arch.rmor)); | 496 | DEFINE(KVM_RMOR, offsetof(struct kvm, arch.rmor)); |
498 | DEFINE(KVM_VRMA_SLB_V, offsetof(struct kvm, arch.vrma_slb_v)); | 497 | DEFINE(KVM_VRMA_SLB_V, offsetof(struct kvm, arch.vrma_slb_v)); |
@@ -667,6 +666,7 @@ int main(void) | |||
667 | DEFINE(VCPU_LR, offsetof(struct kvm_vcpu, arch.lr)); | 666 | DEFINE(VCPU_LR, offsetof(struct kvm_vcpu, arch.lr)); |
668 | DEFINE(VCPU_CTR, offsetof(struct kvm_vcpu, arch.ctr)); | 667 | DEFINE(VCPU_CTR, offsetof(struct kvm_vcpu, arch.ctr)); |
669 | DEFINE(VCPU_PC, offsetof(struct kvm_vcpu, arch.pc)); | 668 | DEFINE(VCPU_PC, offsetof(struct kvm_vcpu, arch.pc)); |
669 | DEFINE(VCPU_SPRG9, offsetof(struct kvm_vcpu, arch.sprg9)); | ||
670 | DEFINE(VCPU_LAST_INST, offsetof(struct kvm_vcpu, arch.last_inst)); | 670 | DEFINE(VCPU_LAST_INST, offsetof(struct kvm_vcpu, arch.last_inst)); |
671 | DEFINE(VCPU_FAULT_DEAR, offsetof(struct kvm_vcpu, arch.fault_dear)); | 671 | DEFINE(VCPU_FAULT_DEAR, offsetof(struct kvm_vcpu, arch.fault_dear)); |
672 | DEFINE(VCPU_FAULT_ESR, offsetof(struct kvm_vcpu, arch.fault_esr)); | 672 | DEFINE(VCPU_FAULT_ESR, offsetof(struct kvm_vcpu, arch.fault_esr)); |
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 0c157642c2a1..9b6dcaaec1a3 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c | |||
@@ -123,96 +123,6 @@ extern void __restore_cpu_e6500(void); | |||
123 | 123 | ||
124 | static struct cpu_spec __initdata cpu_specs[] = { | 124 | static struct cpu_spec __initdata cpu_specs[] = { |
125 | #ifdef CONFIG_PPC_BOOK3S_64 | 125 | #ifdef CONFIG_PPC_BOOK3S_64 |
126 | { /* Power3 */ | ||
127 | .pvr_mask = 0xffff0000, | ||
128 | .pvr_value = 0x00400000, | ||
129 | .cpu_name = "POWER3 (630)", | ||
130 | .cpu_features = CPU_FTRS_POWER3, | ||
131 | .cpu_user_features = COMMON_USER_PPC64|PPC_FEATURE_PPC_LE, | ||
132 | .mmu_features = MMU_FTR_HPTE_TABLE, | ||
133 | .icache_bsize = 128, | ||
134 | .dcache_bsize = 128, | ||
135 | .num_pmcs = 8, | ||
136 | .pmc_type = PPC_PMC_IBM, | ||
137 | .oprofile_cpu_type = "ppc64/power3", | ||
138 | .oprofile_type = PPC_OPROFILE_RS64, | ||
139 | .platform = "power3", | ||
140 | }, | ||
141 | { /* Power3+ */ | ||
142 | .pvr_mask = 0xffff0000, | ||
143 | .pvr_value = 0x00410000, | ||
144 | .cpu_name = "POWER3 (630+)", | ||
145 | .cpu_features = CPU_FTRS_POWER3, | ||
146 | .cpu_user_features = COMMON_USER_PPC64|PPC_FEATURE_PPC_LE, | ||
147 | .mmu_features = MMU_FTR_HPTE_TABLE, | ||
148 | .icache_bsize = 128, | ||
149 | .dcache_bsize = 128, | ||
150 | .num_pmcs = 8, | ||
151 | .pmc_type = PPC_PMC_IBM, | ||
152 | .oprofile_cpu_type = "ppc64/power3", | ||
153 | .oprofile_type = PPC_OPROFILE_RS64, | ||
154 | .platform = "power3", | ||
155 | }, | ||
156 | { /* Northstar */ | ||
157 | .pvr_mask = 0xffff0000, | ||
158 | .pvr_value = 0x00330000, | ||
159 | .cpu_name = "RS64-II (northstar)", | ||
160 | .cpu_features = CPU_FTRS_RS64, | ||
161 | .cpu_user_features = COMMON_USER_PPC64, | ||
162 | .mmu_features = MMU_FTR_HPTE_TABLE, | ||
163 | .icache_bsize = 128, | ||
164 | .dcache_bsize = 128, | ||
165 | .num_pmcs = 8, | ||
166 | .pmc_type = PPC_PMC_IBM, | ||
167 | .oprofile_cpu_type = "ppc64/rs64", | ||
168 | .oprofile_type = PPC_OPROFILE_RS64, | ||
169 | .platform = "rs64", | ||
170 | }, | ||
171 | { /* Pulsar */ | ||
172 | .pvr_mask = 0xffff0000, | ||
173 | .pvr_value = 0x00340000, | ||
174 | .cpu_name = "RS64-III (pulsar)", | ||
175 | .cpu_features = CPU_FTRS_RS64, | ||
176 | .cpu_user_features = COMMON_USER_PPC64, | ||
177 | .mmu_features = MMU_FTR_HPTE_TABLE, | ||
178 | .icache_bsize = 128, | ||
179 | .dcache_bsize = 128, | ||
180 | .num_pmcs = 8, | ||
181 | .pmc_type = PPC_PMC_IBM, | ||
182 | .oprofile_cpu_type = "ppc64/rs64", | ||
183 | .oprofile_type = PPC_OPROFILE_RS64, | ||
184 | .platform = "rs64", | ||
185 | }, | ||
186 | { /* I-star */ | ||
187 | .pvr_mask = 0xffff0000, | ||
188 | .pvr_value = 0x00360000, | ||
189 | .cpu_name = "RS64-III (icestar)", | ||
190 | .cpu_features = CPU_FTRS_RS64, | ||
191 | .cpu_user_features = COMMON_USER_PPC64, | ||
192 | .mmu_features = MMU_FTR_HPTE_TABLE, | ||
193 | .icache_bsize = 128, | ||
194 | .dcache_bsize = 128, | ||
195 | .num_pmcs = 8, | ||
196 | .pmc_type = PPC_PMC_IBM, | ||
197 | .oprofile_cpu_type = "ppc64/rs64", | ||
198 | .oprofile_type = PPC_OPROFILE_RS64, | ||
199 | .platform = "rs64", | ||
200 | }, | ||
201 | { /* S-star */ | ||
202 | .pvr_mask = 0xffff0000, | ||
203 | .pvr_value = 0x00370000, | ||
204 | .cpu_name = "RS64-IV (sstar)", | ||
205 | .cpu_features = CPU_FTRS_RS64, | ||
206 | .cpu_user_features = COMMON_USER_PPC64, | ||
207 | .mmu_features = MMU_FTR_HPTE_TABLE, | ||
208 | .icache_bsize = 128, | ||
209 | .dcache_bsize = 128, | ||
210 | .num_pmcs = 8, | ||
211 | .pmc_type = PPC_PMC_IBM, | ||
212 | .oprofile_cpu_type = "ppc64/rs64", | ||
213 | .oprofile_type = PPC_OPROFILE_RS64, | ||
214 | .platform = "rs64", | ||
215 | }, | ||
216 | { /* Power4 */ | 126 | { /* Power4 */ |
217 | .pvr_mask = 0xffff0000, | 127 | .pvr_mask = 0xffff0000, |
218 | .pvr_value = 0x00350000, | 128 | .pvr_value = 0x00350000, |
@@ -617,7 +527,7 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
617 | #endif /* CONFIG_PPC_BOOK3S_64 */ | 527 | #endif /* CONFIG_PPC_BOOK3S_64 */ |
618 | 528 | ||
619 | #ifdef CONFIG_PPC32 | 529 | #ifdef CONFIG_PPC32 |
620 | #if CLASSIC_PPC | 530 | #ifdef CONFIG_PPC_BOOK3S_32 |
621 | { /* 601 */ | 531 | { /* 601 */ |
622 | .pvr_mask = 0xffff0000, | 532 | .pvr_mask = 0xffff0000, |
623 | .pvr_value = 0x00010000, | 533 | .pvr_value = 0x00010000, |
@@ -1257,7 +1167,7 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
1257 | .machine_check = machine_check_generic, | 1167 | .machine_check = machine_check_generic, |
1258 | .platform = "ppc603", | 1168 | .platform = "ppc603", |
1259 | }, | 1169 | }, |
1260 | #endif /* CLASSIC_PPC */ | 1170 | #endif /* CONFIG_PPC_BOOK3S_32 */ |
1261 | #ifdef CONFIG_8xx | 1171 | #ifdef CONFIG_8xx |
1262 | { /* 8xx */ | 1172 | { /* 8xx */ |
1263 | .pvr_mask = 0xffff0000, | 1173 | .pvr_mask = 0xffff0000, |
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c index 86e25702aaca..59a64f8dc85f 100644 --- a/arch/powerpc/kernel/eeh.c +++ b/arch/powerpc/kernel/eeh.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
28 | #include <linux/list.h> | 28 | #include <linux/list.h> |
29 | #include <linux/pci.h> | 29 | #include <linux/pci.h> |
30 | #include <linux/iommu.h> | ||
30 | #include <linux/proc_fs.h> | 31 | #include <linux/proc_fs.h> |
31 | #include <linux/rbtree.h> | 32 | #include <linux/rbtree.h> |
32 | #include <linux/reboot.h> | 33 | #include <linux/reboot.h> |
@@ -40,6 +41,7 @@ | |||
40 | #include <asm/eeh.h> | 41 | #include <asm/eeh.h> |
41 | #include <asm/eeh_event.h> | 42 | #include <asm/eeh_event.h> |
42 | #include <asm/io.h> | 43 | #include <asm/io.h> |
44 | #include <asm/iommu.h> | ||
43 | #include <asm/machdep.h> | 45 | #include <asm/machdep.h> |
44 | #include <asm/ppc-pci.h> | 46 | #include <asm/ppc-pci.h> |
45 | #include <asm/rtas.h> | 47 | #include <asm/rtas.h> |
@@ -108,6 +110,9 @@ struct eeh_ops *eeh_ops = NULL; | |||
108 | /* Lock to avoid races due to multiple reports of an error */ | 110 | /* Lock to avoid races due to multiple reports of an error */ |
109 | DEFINE_RAW_SPINLOCK(confirm_error_lock); | 111 | DEFINE_RAW_SPINLOCK(confirm_error_lock); |
110 | 112 | ||
113 | /* Lock to protect passed flags */ | ||
114 | static DEFINE_MUTEX(eeh_dev_mutex); | ||
115 | |||
111 | /* Buffer for reporting pci register dumps. Its here in BSS, and | 116 | /* Buffer for reporting pci register dumps. Its here in BSS, and |
112 | * not dynamically alloced, so that it ends up in RMO where RTAS | 117 | * not dynamically alloced, so that it ends up in RMO where RTAS |
113 | * can access it. | 118 | * can access it. |
@@ -137,7 +142,7 @@ static struct eeh_stats eeh_stats; | |||
137 | static int __init eeh_setup(char *str) | 142 | static int __init eeh_setup(char *str) |
138 | { | 143 | { |
139 | if (!strcmp(str, "off")) | 144 | if (!strcmp(str, "off")) |
140 | eeh_subsystem_flags |= EEH_FORCE_DISABLED; | 145 | eeh_add_flag(EEH_FORCE_DISABLED); |
141 | 146 | ||
142 | return 1; | 147 | return 1; |
143 | } | 148 | } |
@@ -152,12 +157,13 @@ __setup("eeh=", eeh_setup); | |||
152 | * This routine captures assorted PCI configuration space data, | 157 | * This routine captures assorted PCI configuration space data, |
153 | * and puts them into a buffer for RTAS error logging. | 158 | * and puts them into a buffer for RTAS error logging. |
154 | */ | 159 | */ |
155 | static size_t eeh_gather_pci_data(struct eeh_dev *edev, char * buf, size_t len) | 160 | static size_t eeh_gather_pci_data(struct eeh_dev *edev, char *buf, size_t len) |
156 | { | 161 | { |
157 | struct device_node *dn = eeh_dev_to_of_node(edev); | 162 | struct device_node *dn = eeh_dev_to_of_node(edev); |
158 | u32 cfg; | 163 | u32 cfg; |
159 | int cap, i; | 164 | int cap, i; |
160 | int n = 0; | 165 | int n = 0, l = 0; |
166 | char buffer[128]; | ||
161 | 167 | ||
162 | n += scnprintf(buf+n, len-n, "%s\n", dn->full_name); | 168 | n += scnprintf(buf+n, len-n, "%s\n", dn->full_name); |
163 | pr_warn("EEH: of node=%s\n", dn->full_name); | 169 | pr_warn("EEH: of node=%s\n", dn->full_name); |
@@ -202,8 +208,22 @@ static size_t eeh_gather_pci_data(struct eeh_dev *edev, char * buf, size_t len) | |||
202 | for (i=0; i<=8; i++) { | 208 | for (i=0; i<=8; i++) { |
203 | eeh_ops->read_config(dn, cap+4*i, 4, &cfg); | 209 | eeh_ops->read_config(dn, cap+4*i, 4, &cfg); |
204 | n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg); | 210 | n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg); |
205 | pr_warn("EEH: PCI-E %02x: %08x\n", i, cfg); | 211 | |
212 | if ((i % 4) == 0) { | ||
213 | if (i != 0) | ||
214 | pr_warn("%s\n", buffer); | ||
215 | |||
216 | l = scnprintf(buffer, sizeof(buffer), | ||
217 | "EEH: PCI-E %02x: %08x ", | ||
218 | 4*i, cfg); | ||
219 | } else { | ||
220 | l += scnprintf(buffer+l, sizeof(buffer)-l, | ||
221 | "%08x ", cfg); | ||
222 | } | ||
223 | |||
206 | } | 224 | } |
225 | |||
226 | pr_warn("%s\n", buffer); | ||
207 | } | 227 | } |
208 | 228 | ||
209 | /* If AER capable, dump it */ | 229 | /* If AER capable, dump it */ |
@@ -212,11 +232,24 @@ static size_t eeh_gather_pci_data(struct eeh_dev *edev, char * buf, size_t len) | |||
212 | n += scnprintf(buf+n, len-n, "pci-e AER:\n"); | 232 | n += scnprintf(buf+n, len-n, "pci-e AER:\n"); |
213 | pr_warn("EEH: PCI-E AER capability register set follows:\n"); | 233 | pr_warn("EEH: PCI-E AER capability register set follows:\n"); |
214 | 234 | ||
215 | for (i=0; i<14; i++) { | 235 | for (i=0; i<=13; i++) { |
216 | eeh_ops->read_config(dn, cap+4*i, 4, &cfg); | 236 | eeh_ops->read_config(dn, cap+4*i, 4, &cfg); |
217 | n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg); | 237 | n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg); |
218 | pr_warn("EEH: PCI-E AER %02x: %08x\n", i, cfg); | 238 | |
239 | if ((i % 4) == 0) { | ||
240 | if (i != 0) | ||
241 | pr_warn("%s\n", buffer); | ||
242 | |||
243 | l = scnprintf(buffer, sizeof(buffer), | ||
244 | "EEH: PCI-E AER %02x: %08x ", | ||
245 | 4*i, cfg); | ||
246 | } else { | ||
247 | l += scnprintf(buffer+l, sizeof(buffer)-l, | ||
248 | "%08x ", cfg); | ||
249 | } | ||
219 | } | 250 | } |
251 | |||
252 | pr_warn("%s\n", buffer); | ||
220 | } | 253 | } |
221 | 254 | ||
222 | return n; | 255 | return n; |
@@ -247,7 +280,7 @@ void eeh_slot_error_detail(struct eeh_pe *pe, int severity) | |||
247 | * 0xFF's is always returned from PCI config space. | 280 | * 0xFF's is always returned from PCI config space. |
248 | */ | 281 | */ |
249 | if (!(pe->type & EEH_PE_PHB)) { | 282 | if (!(pe->type & EEH_PE_PHB)) { |
250 | if (eeh_probe_mode_devtree()) | 283 | if (eeh_has_flag(EEH_ENABLE_IO_FOR_LOG)) |
251 | eeh_pci_enable(pe, EEH_OPT_THAW_MMIO); | 284 | eeh_pci_enable(pe, EEH_OPT_THAW_MMIO); |
252 | eeh_ops->configure_bridge(pe); | 285 | eeh_ops->configure_bridge(pe); |
253 | eeh_pe_restore_bars(pe); | 286 | eeh_pe_restore_bars(pe); |
@@ -298,14 +331,14 @@ static int eeh_phb_check_failure(struct eeh_pe *pe) | |||
298 | unsigned long flags; | 331 | unsigned long flags; |
299 | int ret; | 332 | int ret; |
300 | 333 | ||
301 | if (!eeh_probe_mode_dev()) | 334 | if (!eeh_has_flag(EEH_PROBE_MODE_DEV)) |
302 | return -EPERM; | 335 | return -EPERM; |
303 | 336 | ||
304 | /* Find the PHB PE */ | 337 | /* Find the PHB PE */ |
305 | phb_pe = eeh_phb_pe_get(pe->phb); | 338 | phb_pe = eeh_phb_pe_get(pe->phb); |
306 | if (!phb_pe) { | 339 | if (!phb_pe) { |
307 | pr_warning("%s Can't find PE for PHB#%d\n", | 340 | pr_warn("%s Can't find PE for PHB#%d\n", |
308 | __func__, pe->phb->global_number); | 341 | __func__, pe->phb->global_number); |
309 | return -EEXIST; | 342 | return -EEXIST; |
310 | } | 343 | } |
311 | 344 | ||
@@ -400,6 +433,14 @@ int eeh_dev_check_failure(struct eeh_dev *edev) | |||
400 | if (ret > 0) | 433 | if (ret > 0) |
401 | return ret; | 434 | return ret; |
402 | 435 | ||
436 | /* | ||
437 | * If the PE isn't owned by us, we shouldn't check the | ||
438 | * state. Instead, let the owner handle it if the PE has | ||
439 | * been frozen. | ||
440 | */ | ||
441 | if (eeh_pe_passed(pe)) | ||
442 | return 0; | ||
443 | |||
403 | /* If we already have a pending isolation event for this | 444 | /* If we already have a pending isolation event for this |
404 | * slot, we know it's bad already, we don't need to check. | 445 | * slot, we know it's bad already, we don't need to check. |
405 | * Do this checking under a lock; as multiple PCI devices | 446 | * Do this checking under a lock; as multiple PCI devices |
@@ -746,13 +787,13 @@ void eeh_save_bars(struct eeh_dev *edev) | |||
746 | int __init eeh_ops_register(struct eeh_ops *ops) | 787 | int __init eeh_ops_register(struct eeh_ops *ops) |
747 | { | 788 | { |
748 | if (!ops->name) { | 789 | if (!ops->name) { |
749 | pr_warning("%s: Invalid EEH ops name for %p\n", | 790 | pr_warn("%s: Invalid EEH ops name for %p\n", |
750 | __func__, ops); | 791 | __func__, ops); |
751 | return -EINVAL; | 792 | return -EINVAL; |
752 | } | 793 | } |
753 | 794 | ||
754 | if (eeh_ops && eeh_ops != ops) { | 795 | if (eeh_ops && eeh_ops != ops) { |
755 | pr_warning("%s: EEH ops of platform %s already existing (%s)\n", | 796 | pr_warn("%s: EEH ops of platform %s already existing (%s)\n", |
756 | __func__, eeh_ops->name, ops->name); | 797 | __func__, eeh_ops->name, ops->name); |
757 | return -EEXIST; | 798 | return -EEXIST; |
758 | } | 799 | } |
@@ -772,7 +813,7 @@ int __init eeh_ops_register(struct eeh_ops *ops) | |||
772 | int __exit eeh_ops_unregister(const char *name) | 813 | int __exit eeh_ops_unregister(const char *name) |
773 | { | 814 | { |
774 | if (!name || !strlen(name)) { | 815 | if (!name || !strlen(name)) { |
775 | pr_warning("%s: Invalid EEH ops name\n", | 816 | pr_warn("%s: Invalid EEH ops name\n", |
776 | __func__); | 817 | __func__); |
777 | return -EINVAL; | 818 | return -EINVAL; |
778 | } | 819 | } |
@@ -788,7 +829,7 @@ int __exit eeh_ops_unregister(const char *name) | |||
788 | static int eeh_reboot_notifier(struct notifier_block *nb, | 829 | static int eeh_reboot_notifier(struct notifier_block *nb, |
789 | unsigned long action, void *unused) | 830 | unsigned long action, void *unused) |
790 | { | 831 | { |
791 | eeh_set_enable(false); | 832 | eeh_clear_flag(EEH_ENABLED); |
792 | return NOTIFY_DONE; | 833 | return NOTIFY_DONE; |
793 | } | 834 | } |
794 | 835 | ||
@@ -837,11 +878,11 @@ int eeh_init(void) | |||
837 | 878 | ||
838 | /* call platform initialization function */ | 879 | /* call platform initialization function */ |
839 | if (!eeh_ops) { | 880 | if (!eeh_ops) { |
840 | pr_warning("%s: Platform EEH operation not found\n", | 881 | pr_warn("%s: Platform EEH operation not found\n", |
841 | __func__); | 882 | __func__); |
842 | return -EEXIST; | 883 | return -EEXIST; |
843 | } else if ((ret = eeh_ops->init())) { | 884 | } else if ((ret = eeh_ops->init())) { |
844 | pr_warning("%s: Failed to call platform init function (%d)\n", | 885 | pr_warn("%s: Failed to call platform init function (%d)\n", |
845 | __func__, ret); | 886 | __func__, ret); |
846 | return ret; | 887 | return ret; |
847 | } | 888 | } |
@@ -852,13 +893,13 @@ int eeh_init(void) | |||
852 | return ret; | 893 | return ret; |
853 | 894 | ||
854 | /* Enable EEH for all adapters */ | 895 | /* Enable EEH for all adapters */ |
855 | if (eeh_probe_mode_devtree()) { | 896 | if (eeh_has_flag(EEH_PROBE_MODE_DEVTREE)) { |
856 | list_for_each_entry_safe(hose, tmp, | 897 | list_for_each_entry_safe(hose, tmp, |
857 | &hose_list, list_node) { | 898 | &hose_list, list_node) { |
858 | phb = hose->dn; | 899 | phb = hose->dn; |
859 | traverse_pci_devices(phb, eeh_ops->of_probe, NULL); | 900 | traverse_pci_devices(phb, eeh_ops->of_probe, NULL); |
860 | } | 901 | } |
861 | } else if (eeh_probe_mode_dev()) { | 902 | } else if (eeh_has_flag(EEH_PROBE_MODE_DEV)) { |
862 | list_for_each_entry_safe(hose, tmp, | 903 | list_for_each_entry_safe(hose, tmp, |
863 | &hose_list, list_node) | 904 | &hose_list, list_node) |
864 | pci_walk_bus(hose->bus, eeh_ops->dev_probe, NULL); | 905 | pci_walk_bus(hose->bus, eeh_ops->dev_probe, NULL); |
@@ -882,7 +923,7 @@ int eeh_init(void) | |||
882 | if (eeh_enabled()) | 923 | if (eeh_enabled()) |
883 | pr_info("EEH: PCI Enhanced I/O Error Handling Enabled\n"); | 924 | pr_info("EEH: PCI Enhanced I/O Error Handling Enabled\n"); |
884 | else | 925 | else |
885 | pr_warning("EEH: No capable adapters found\n"); | 926 | pr_warn("EEH: No capable adapters found\n"); |
886 | 927 | ||
887 | return ret; | 928 | return ret; |
888 | } | 929 | } |
@@ -910,7 +951,7 @@ void eeh_add_device_early(struct device_node *dn) | |||
910 | * would delay the probe until late stage because | 951 | * would delay the probe until late stage because |
911 | * the PCI device isn't available this moment. | 952 | * the PCI device isn't available this moment. |
912 | */ | 953 | */ |
913 | if (!eeh_probe_mode_devtree()) | 954 | if (!eeh_has_flag(EEH_PROBE_MODE_DEVTREE)) |
914 | return; | 955 | return; |
915 | 956 | ||
916 | if (!of_node_to_eeh_dev(dn)) | 957 | if (!of_node_to_eeh_dev(dn)) |
@@ -996,7 +1037,7 @@ void eeh_add_device_late(struct pci_dev *dev) | |||
996 | * We have to do the EEH probe here because the PCI device | 1037 | * We have to do the EEH probe here because the PCI device |
997 | * hasn't been created yet in the early stage. | 1038 | * hasn't been created yet in the early stage. |
998 | */ | 1039 | */ |
999 | if (eeh_probe_mode_dev()) | 1040 | if (eeh_has_flag(EEH_PROBE_MODE_DEV)) |
1000 | eeh_ops->dev_probe(dev, NULL); | 1041 | eeh_ops->dev_probe(dev, NULL); |
1001 | 1042 | ||
1002 | eeh_addr_cache_insert_dev(dev); | 1043 | eeh_addr_cache_insert_dev(dev); |
@@ -1100,6 +1141,285 @@ void eeh_remove_device(struct pci_dev *dev) | |||
1100 | edev->mode &= ~EEH_DEV_SYSFS; | 1141 | edev->mode &= ~EEH_DEV_SYSFS; |
1101 | } | 1142 | } |
1102 | 1143 | ||
1144 | /** | ||
1145 | * eeh_dev_open - Increase count of pass through devices for PE | ||
1146 | * @pdev: PCI device | ||
1147 | * | ||
1148 | * Increase count of passed through devices for the indicated | ||
1149 | * PE. In the result, the EEH errors detected on the PE won't be | ||
1150 | * reported. The PE owner will be responsible for detection | ||
1151 | * and recovery. | ||
1152 | */ | ||
1153 | int eeh_dev_open(struct pci_dev *pdev) | ||
1154 | { | ||
1155 | struct eeh_dev *edev; | ||
1156 | |||
1157 | mutex_lock(&eeh_dev_mutex); | ||
1158 | |||
1159 | /* No PCI device ? */ | ||
1160 | if (!pdev) | ||
1161 | goto out; | ||
1162 | |||
1163 | /* No EEH device or PE ? */ | ||
1164 | edev = pci_dev_to_eeh_dev(pdev); | ||
1165 | if (!edev || !edev->pe) | ||
1166 | goto out; | ||
1167 | |||
1168 | /* Increase PE's pass through count */ | ||
1169 | atomic_inc(&edev->pe->pass_dev_cnt); | ||
1170 | mutex_unlock(&eeh_dev_mutex); | ||
1171 | |||
1172 | return 0; | ||
1173 | out: | ||
1174 | mutex_unlock(&eeh_dev_mutex); | ||
1175 | return -ENODEV; | ||
1176 | } | ||
1177 | EXPORT_SYMBOL_GPL(eeh_dev_open); | ||
1178 | |||
1179 | /** | ||
1180 | * eeh_dev_release - Decrease count of pass through devices for PE | ||
1181 | * @pdev: PCI device | ||
1182 | * | ||
1183 | * Decrease count of pass through devices for the indicated PE. If | ||
1184 | * there is no passed through device in PE, the EEH errors detected | ||
1185 | * on the PE will be reported and handled as usual. | ||
1186 | */ | ||
1187 | void eeh_dev_release(struct pci_dev *pdev) | ||
1188 | { | ||
1189 | struct eeh_dev *edev; | ||
1190 | |||
1191 | mutex_lock(&eeh_dev_mutex); | ||
1192 | |||
1193 | /* No PCI device ? */ | ||
1194 | if (!pdev) | ||
1195 | goto out; | ||
1196 | |||
1197 | /* No EEH device ? */ | ||
1198 | edev = pci_dev_to_eeh_dev(pdev); | ||
1199 | if (!edev || !edev->pe || !eeh_pe_passed(edev->pe)) | ||
1200 | goto out; | ||
1201 | |||
1202 | /* Decrease PE's pass through count */ | ||
1203 | atomic_dec(&edev->pe->pass_dev_cnt); | ||
1204 | WARN_ON(atomic_read(&edev->pe->pass_dev_cnt) < 0); | ||
1205 | out: | ||
1206 | mutex_unlock(&eeh_dev_mutex); | ||
1207 | } | ||
1208 | EXPORT_SYMBOL(eeh_dev_release); | ||
1209 | |||
1210 | #ifdef CONFIG_IOMMU_API | ||
1211 | |||
1212 | static int dev_has_iommu_table(struct device *dev, void *data) | ||
1213 | { | ||
1214 | struct pci_dev *pdev = to_pci_dev(dev); | ||
1215 | struct pci_dev **ppdev = data; | ||
1216 | struct iommu_table *tbl; | ||
1217 | |||
1218 | if (!dev) | ||
1219 | return 0; | ||
1220 | |||
1221 | tbl = get_iommu_table_base(dev); | ||
1222 | if (tbl && tbl->it_group) { | ||
1223 | *ppdev = pdev; | ||
1224 | return 1; | ||
1225 | } | ||
1226 | |||
1227 | return 0; | ||
1228 | } | ||
1229 | |||
1230 | /** | ||
1231 | * eeh_iommu_group_to_pe - Convert IOMMU group to EEH PE | ||
1232 | * @group: IOMMU group | ||
1233 | * | ||
1234 | * The routine is called to convert IOMMU group to EEH PE. | ||
1235 | */ | ||
1236 | struct eeh_pe *eeh_iommu_group_to_pe(struct iommu_group *group) | ||
1237 | { | ||
1238 | struct pci_dev *pdev = NULL; | ||
1239 | struct eeh_dev *edev; | ||
1240 | int ret; | ||
1241 | |||
1242 | /* No IOMMU group ? */ | ||
1243 | if (!group) | ||
1244 | return NULL; | ||
1245 | |||
1246 | ret = iommu_group_for_each_dev(group, &pdev, dev_has_iommu_table); | ||
1247 | if (!ret || !pdev) | ||
1248 | return NULL; | ||
1249 | |||
1250 | /* No EEH device or PE ? */ | ||
1251 | edev = pci_dev_to_eeh_dev(pdev); | ||
1252 | if (!edev || !edev->pe) | ||
1253 | return NULL; | ||
1254 | |||
1255 | return edev->pe; | ||
1256 | } | ||
1257 | EXPORT_SYMBOL_GPL(eeh_iommu_group_to_pe); | ||
1258 | |||
1259 | #endif /* CONFIG_IOMMU_API */ | ||
1260 | |||
1261 | /** | ||
1262 | * eeh_pe_set_option - Set options for the indicated PE | ||
1263 | * @pe: EEH PE | ||
1264 | * @option: requested option | ||
1265 | * | ||
1266 | * The routine is called to enable or disable EEH functionality | ||
1267 | * on the indicated PE, to enable IO or DMA for the frozen PE. | ||
1268 | */ | ||
1269 | int eeh_pe_set_option(struct eeh_pe *pe, int option) | ||
1270 | { | ||
1271 | int ret = 0; | ||
1272 | |||
1273 | /* Invalid PE ? */ | ||
1274 | if (!pe) | ||
1275 | return -ENODEV; | ||
1276 | |||
1277 | /* | ||
1278 | * EEH functionality could possibly be disabled, just | ||
1279 | * return error for the case. And the EEH functinality | ||
1280 | * isn't expected to be disabled on one specific PE. | ||
1281 | */ | ||
1282 | switch (option) { | ||
1283 | case EEH_OPT_ENABLE: | ||
1284 | if (eeh_enabled()) | ||
1285 | break; | ||
1286 | ret = -EIO; | ||
1287 | break; | ||
1288 | case EEH_OPT_DISABLE: | ||
1289 | break; | ||
1290 | case EEH_OPT_THAW_MMIO: | ||
1291 | case EEH_OPT_THAW_DMA: | ||
1292 | if (!eeh_ops || !eeh_ops->set_option) { | ||
1293 | ret = -ENOENT; | ||
1294 | break; | ||
1295 | } | ||
1296 | |||
1297 | ret = eeh_ops->set_option(pe, option); | ||
1298 | break; | ||
1299 | default: | ||
1300 | pr_debug("%s: Option %d out of range (%d, %d)\n", | ||
1301 | __func__, option, EEH_OPT_DISABLE, EEH_OPT_THAW_DMA); | ||
1302 | ret = -EINVAL; | ||
1303 | } | ||
1304 | |||
1305 | return ret; | ||
1306 | } | ||
1307 | EXPORT_SYMBOL_GPL(eeh_pe_set_option); | ||
1308 | |||
1309 | /** | ||
1310 | * eeh_pe_get_state - Retrieve PE's state | ||
1311 | * @pe: EEH PE | ||
1312 | * | ||
1313 | * Retrieve the PE's state, which includes 3 aspects: enabled | ||
1314 | * DMA, enabled IO and asserted reset. | ||
1315 | */ | ||
1316 | int eeh_pe_get_state(struct eeh_pe *pe) | ||
1317 | { | ||
1318 | int result, ret = 0; | ||
1319 | bool rst_active, dma_en, mmio_en; | ||
1320 | |||
1321 | /* Existing PE ? */ | ||
1322 | if (!pe) | ||
1323 | return -ENODEV; | ||
1324 | |||
1325 | if (!eeh_ops || !eeh_ops->get_state) | ||
1326 | return -ENOENT; | ||
1327 | |||
1328 | result = eeh_ops->get_state(pe, NULL); | ||
1329 | rst_active = !!(result & EEH_STATE_RESET_ACTIVE); | ||
1330 | dma_en = !!(result & EEH_STATE_DMA_ENABLED); | ||
1331 | mmio_en = !!(result & EEH_STATE_MMIO_ENABLED); | ||
1332 | |||
1333 | if (rst_active) | ||
1334 | ret = EEH_PE_STATE_RESET; | ||
1335 | else if (dma_en && mmio_en) | ||
1336 | ret = EEH_PE_STATE_NORMAL; | ||
1337 | else if (!dma_en && !mmio_en) | ||
1338 | ret = EEH_PE_STATE_STOPPED_IO_DMA; | ||
1339 | else if (!dma_en && mmio_en) | ||
1340 | ret = EEH_PE_STATE_STOPPED_DMA; | ||
1341 | else | ||
1342 | ret = EEH_PE_STATE_UNAVAIL; | ||
1343 | |||
1344 | return ret; | ||
1345 | } | ||
1346 | EXPORT_SYMBOL_GPL(eeh_pe_get_state); | ||
1347 | |||
1348 | /** | ||
1349 | * eeh_pe_reset - Issue PE reset according to specified type | ||
1350 | * @pe: EEH PE | ||
1351 | * @option: reset type | ||
1352 | * | ||
1353 | * The routine is called to reset the specified PE with the | ||
1354 | * indicated type, either fundamental reset or hot reset. | ||
1355 | * PE reset is the most important part for error recovery. | ||
1356 | */ | ||
1357 | int eeh_pe_reset(struct eeh_pe *pe, int option) | ||
1358 | { | ||
1359 | int ret = 0; | ||
1360 | |||
1361 | /* Invalid PE ? */ | ||
1362 | if (!pe) | ||
1363 | return -ENODEV; | ||
1364 | |||
1365 | if (!eeh_ops || !eeh_ops->set_option || !eeh_ops->reset) | ||
1366 | return -ENOENT; | ||
1367 | |||
1368 | switch (option) { | ||
1369 | case EEH_RESET_DEACTIVATE: | ||
1370 | ret = eeh_ops->reset(pe, option); | ||
1371 | if (ret) | ||
1372 | break; | ||
1373 | |||
1374 | /* | ||
1375 | * The PE is still in frozen state and we need to clear | ||
1376 | * that. It's good to clear frozen state after deassert | ||
1377 | * to avoid messy IO access during reset, which might | ||
1378 | * cause recursive frozen PE. | ||
1379 | */ | ||
1380 | ret = eeh_ops->set_option(pe, EEH_OPT_THAW_MMIO); | ||
1381 | if (!ret) | ||
1382 | ret = eeh_ops->set_option(pe, EEH_OPT_THAW_DMA); | ||
1383 | if (!ret) | ||
1384 | eeh_pe_state_clear(pe, EEH_PE_ISOLATED); | ||
1385 | break; | ||
1386 | case EEH_RESET_HOT: | ||
1387 | case EEH_RESET_FUNDAMENTAL: | ||
1388 | ret = eeh_ops->reset(pe, option); | ||
1389 | break; | ||
1390 | default: | ||
1391 | pr_debug("%s: Unsupported option %d\n", | ||
1392 | __func__, option); | ||
1393 | ret = -EINVAL; | ||
1394 | } | ||
1395 | |||
1396 | return ret; | ||
1397 | } | ||
1398 | EXPORT_SYMBOL_GPL(eeh_pe_reset); | ||
1399 | |||
1400 | /** | ||
1401 | * eeh_pe_configure - Configure PCI bridges after PE reset | ||
1402 | * @pe: EEH PE | ||
1403 | * | ||
1404 | * The routine is called to restore the PCI config space for | ||
1405 | * those PCI devices, especially PCI bridges affected by PE | ||
1406 | * reset issued previously. | ||
1407 | */ | ||
1408 | int eeh_pe_configure(struct eeh_pe *pe) | ||
1409 | { | ||
1410 | int ret = 0; | ||
1411 | |||
1412 | /* Invalid PE ? */ | ||
1413 | if (!pe) | ||
1414 | return -ENODEV; | ||
1415 | |||
1416 | /* Restore config space for the affected devices */ | ||
1417 | eeh_pe_restore_bars(pe); | ||
1418 | |||
1419 | return ret; | ||
1420 | } | ||
1421 | EXPORT_SYMBOL_GPL(eeh_pe_configure); | ||
1422 | |||
1103 | static int proc_eeh_show(struct seq_file *m, void *v) | 1423 | static int proc_eeh_show(struct seq_file *m, void *v) |
1104 | { | 1424 | { |
1105 | if (!eeh_enabled()) { | 1425 | if (!eeh_enabled()) { |
@@ -1143,9 +1463,9 @@ static const struct file_operations proc_eeh_operations = { | |||
1143 | static int eeh_enable_dbgfs_set(void *data, u64 val) | 1463 | static int eeh_enable_dbgfs_set(void *data, u64 val) |
1144 | { | 1464 | { |
1145 | if (val) | 1465 | if (val) |
1146 | eeh_subsystem_flags &= ~EEH_FORCE_DISABLED; | 1466 | eeh_clear_flag(EEH_FORCE_DISABLED); |
1147 | else | 1467 | else |
1148 | eeh_subsystem_flags |= EEH_FORCE_DISABLED; | 1468 | eeh_add_flag(EEH_FORCE_DISABLED); |
1149 | 1469 | ||
1150 | /* Notify the backend */ | 1470 | /* Notify the backend */ |
1151 | if (eeh_ops->post_init) | 1471 | if (eeh_ops->post_init) |
diff --git a/arch/powerpc/kernel/eeh_cache.c b/arch/powerpc/kernel/eeh_cache.c index e8c9fd546a5c..07d8a2423a61 100644 --- a/arch/powerpc/kernel/eeh_cache.c +++ b/arch/powerpc/kernel/eeh_cache.c | |||
@@ -143,7 +143,7 @@ eeh_addr_cache_insert(struct pci_dev *dev, unsigned long alo, | |||
143 | } else { | 143 | } else { |
144 | if (dev != piar->pcidev || | 144 | if (dev != piar->pcidev || |
145 | alo != piar->addr_lo || ahi != piar->addr_hi) { | 145 | alo != piar->addr_lo || ahi != piar->addr_hi) { |
146 | pr_warning("PIAR: overlapping address range\n"); | 146 | pr_warn("PIAR: overlapping address range\n"); |
147 | } | 147 | } |
148 | return piar; | 148 | return piar; |
149 | } | 149 | } |
@@ -177,19 +177,20 @@ static void __eeh_addr_cache_insert_dev(struct pci_dev *dev) | |||
177 | 177 | ||
178 | dn = pci_device_to_OF_node(dev); | 178 | dn = pci_device_to_OF_node(dev); |
179 | if (!dn) { | 179 | if (!dn) { |
180 | pr_warning("PCI: no pci dn found for dev=%s\n", pci_name(dev)); | 180 | pr_warn("PCI: no pci dn found for dev=%s\n", |
181 | pci_name(dev)); | ||
181 | return; | 182 | return; |
182 | } | 183 | } |
183 | 184 | ||
184 | edev = of_node_to_eeh_dev(dn); | 185 | edev = of_node_to_eeh_dev(dn); |
185 | if (!edev) { | 186 | if (!edev) { |
186 | pr_warning("PCI: no EEH dev found for dn=%s\n", | 187 | pr_warn("PCI: no EEH dev found for dn=%s\n", |
187 | dn->full_name); | 188 | dn->full_name); |
188 | return; | 189 | return; |
189 | } | 190 | } |
190 | 191 | ||
191 | /* Skip any devices for which EEH is not enabled. */ | 192 | /* Skip any devices for which EEH is not enabled. */ |
192 | if (!eeh_probe_mode_dev() && !edev->pe) { | 193 | if (!edev->pe) { |
193 | #ifdef DEBUG | 194 | #ifdef DEBUG |
194 | pr_info("PCI: skip building address cache for=%s - %s\n", | 195 | pr_info("PCI: skip building address cache for=%s - %s\n", |
195 | pci_name(dev), dn->full_name); | 196 | pci_name(dev), dn->full_name); |
diff --git a/arch/powerpc/kernel/eeh_dev.c b/arch/powerpc/kernel/eeh_dev.c index 1efa28f5fc54..e5274ee9a75f 100644 --- a/arch/powerpc/kernel/eeh_dev.c +++ b/arch/powerpc/kernel/eeh_dev.c | |||
@@ -57,7 +57,8 @@ void *eeh_dev_init(struct device_node *dn, void *data) | |||
57 | /* Allocate EEH device */ | 57 | /* Allocate EEH device */ |
58 | edev = kzalloc(sizeof(*edev), GFP_KERNEL); | 58 | edev = kzalloc(sizeof(*edev), GFP_KERNEL); |
59 | if (!edev) { | 59 | if (!edev) { |
60 | pr_warning("%s: out of memory\n", __func__); | 60 | pr_warn("%s: out of memory\n", |
61 | __func__); | ||
61 | return NULL; | 62 | return NULL; |
62 | } | 63 | } |
63 | 64 | ||
diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c index 420da61d4ce0..6a0dcee8e931 100644 --- a/arch/powerpc/kernel/eeh_driver.c +++ b/arch/powerpc/kernel/eeh_driver.c | |||
@@ -599,7 +599,7 @@ static void eeh_handle_normal_event(struct eeh_pe *pe) | |||
599 | pe->freeze_count++; | 599 | pe->freeze_count++; |
600 | if (pe->freeze_count > EEH_MAX_ALLOWED_FREEZES) | 600 | if (pe->freeze_count > EEH_MAX_ALLOWED_FREEZES) |
601 | goto excess_failures; | 601 | goto excess_failures; |
602 | pr_warning("EEH: This PCI device has failed %d times in the last hour\n", | 602 | pr_warn("EEH: This PCI device has failed %d times in the last hour\n", |
603 | pe->freeze_count); | 603 | pe->freeze_count); |
604 | 604 | ||
605 | /* Walk the various device drivers attached to this slot through | 605 | /* Walk the various device drivers attached to this slot through |
@@ -616,7 +616,7 @@ static void eeh_handle_normal_event(struct eeh_pe *pe) | |||
616 | */ | 616 | */ |
617 | rc = eeh_ops->wait_state(pe, MAX_WAIT_FOR_RECOVERY*1000); | 617 | rc = eeh_ops->wait_state(pe, MAX_WAIT_FOR_RECOVERY*1000); |
618 | if (rc < 0 || rc == EEH_STATE_NOT_SUPPORT) { | 618 | if (rc < 0 || rc == EEH_STATE_NOT_SUPPORT) { |
619 | pr_warning("EEH: Permanent failure\n"); | 619 | pr_warn("EEH: Permanent failure\n"); |
620 | goto hard_fail; | 620 | goto hard_fail; |
621 | } | 621 | } |
622 | 622 | ||
@@ -635,8 +635,8 @@ static void eeh_handle_normal_event(struct eeh_pe *pe) | |||
635 | pr_info("EEH: Reset with hotplug activity\n"); | 635 | pr_info("EEH: Reset with hotplug activity\n"); |
636 | rc = eeh_reset_device(pe, frozen_bus); | 636 | rc = eeh_reset_device(pe, frozen_bus); |
637 | if (rc) { | 637 | if (rc) { |
638 | pr_warning("%s: Unable to reset, err=%d\n", | 638 | pr_warn("%s: Unable to reset, err=%d\n", |
639 | __func__, rc); | 639 | __func__, rc); |
640 | goto hard_fail; | 640 | goto hard_fail; |
641 | } | 641 | } |
642 | } | 642 | } |
@@ -678,7 +678,7 @@ static void eeh_handle_normal_event(struct eeh_pe *pe) | |||
678 | 678 | ||
679 | /* If any device has a hard failure, then shut off everything. */ | 679 | /* If any device has a hard failure, then shut off everything. */ |
680 | if (result == PCI_ERS_RESULT_DISCONNECT) { | 680 | if (result == PCI_ERS_RESULT_DISCONNECT) { |
681 | pr_warning("EEH: Device driver gave up\n"); | 681 | pr_warn("EEH: Device driver gave up\n"); |
682 | goto hard_fail; | 682 | goto hard_fail; |
683 | } | 683 | } |
684 | 684 | ||
@@ -687,8 +687,8 @@ static void eeh_handle_normal_event(struct eeh_pe *pe) | |||
687 | pr_info("EEH: Reset without hotplug activity\n"); | 687 | pr_info("EEH: Reset without hotplug activity\n"); |
688 | rc = eeh_reset_device(pe, NULL); | 688 | rc = eeh_reset_device(pe, NULL); |
689 | if (rc) { | 689 | if (rc) { |
690 | pr_warning("%s: Cannot reset, err=%d\n", | 690 | pr_warn("%s: Cannot reset, err=%d\n", |
691 | __func__, rc); | 691 | __func__, rc); |
692 | goto hard_fail; | 692 | goto hard_fail; |
693 | } | 693 | } |
694 | 694 | ||
@@ -701,7 +701,7 @@ static void eeh_handle_normal_event(struct eeh_pe *pe) | |||
701 | /* All devices should claim they have recovered by now. */ | 701 | /* All devices should claim they have recovered by now. */ |
702 | if ((result != PCI_ERS_RESULT_RECOVERED) && | 702 | if ((result != PCI_ERS_RESULT_RECOVERED) && |
703 | (result != PCI_ERS_RESULT_NONE)) { | 703 | (result != PCI_ERS_RESULT_NONE)) { |
704 | pr_warning("EEH: Not recovered\n"); | 704 | pr_warn("EEH: Not recovered\n"); |
705 | goto hard_fail; | 705 | goto hard_fail; |
706 | } | 706 | } |
707 | 707 | ||
diff --git a/arch/powerpc/kernel/eeh_pe.c b/arch/powerpc/kernel/eeh_pe.c index fbd01eba4473..00e3844525a6 100644 --- a/arch/powerpc/kernel/eeh_pe.c +++ b/arch/powerpc/kernel/eeh_pe.c | |||
@@ -32,9 +32,24 @@ | |||
32 | #include <asm/pci-bridge.h> | 32 | #include <asm/pci-bridge.h> |
33 | #include <asm/ppc-pci.h> | 33 | #include <asm/ppc-pci.h> |
34 | 34 | ||
35 | static int eeh_pe_aux_size = 0; | ||
35 | static LIST_HEAD(eeh_phb_pe); | 36 | static LIST_HEAD(eeh_phb_pe); |
36 | 37 | ||
37 | /** | 38 | /** |
39 | * eeh_set_pe_aux_size - Set PE auxillary data size | ||
40 | * @size: PE auxillary data size | ||
41 | * | ||
42 | * Set PE auxillary data size | ||
43 | */ | ||
44 | void eeh_set_pe_aux_size(int size) | ||
45 | { | ||
46 | if (size < 0) | ||
47 | return; | ||
48 | |||
49 | eeh_pe_aux_size = size; | ||
50 | } | ||
51 | |||
52 | /** | ||
38 | * eeh_pe_alloc - Allocate PE | 53 | * eeh_pe_alloc - Allocate PE |
39 | * @phb: PCI controller | 54 | * @phb: PCI controller |
40 | * @type: PE type | 55 | * @type: PE type |
@@ -44,9 +59,16 @@ static LIST_HEAD(eeh_phb_pe); | |||
44 | static struct eeh_pe *eeh_pe_alloc(struct pci_controller *phb, int type) | 59 | static struct eeh_pe *eeh_pe_alloc(struct pci_controller *phb, int type) |
45 | { | 60 | { |
46 | struct eeh_pe *pe; | 61 | struct eeh_pe *pe; |
62 | size_t alloc_size; | ||
63 | |||
64 | alloc_size = sizeof(struct eeh_pe); | ||
65 | if (eeh_pe_aux_size) { | ||
66 | alloc_size = ALIGN(alloc_size, cache_line_size()); | ||
67 | alloc_size += eeh_pe_aux_size; | ||
68 | } | ||
47 | 69 | ||
48 | /* Allocate PHB PE */ | 70 | /* Allocate PHB PE */ |
49 | pe = kzalloc(sizeof(struct eeh_pe), GFP_KERNEL); | 71 | pe = kzalloc(alloc_size, GFP_KERNEL); |
50 | if (!pe) return NULL; | 72 | if (!pe) return NULL; |
51 | 73 | ||
52 | /* Initialize PHB PE */ | 74 | /* Initialize PHB PE */ |
@@ -56,6 +78,8 @@ static struct eeh_pe *eeh_pe_alloc(struct pci_controller *phb, int type) | |||
56 | INIT_LIST_HEAD(&pe->child); | 78 | INIT_LIST_HEAD(&pe->child); |
57 | INIT_LIST_HEAD(&pe->edevs); | 79 | INIT_LIST_HEAD(&pe->edevs); |
58 | 80 | ||
81 | pe->data = (void *)pe + ALIGN(sizeof(struct eeh_pe), | ||
82 | cache_line_size()); | ||
59 | return pe; | 83 | return pe; |
60 | } | 84 | } |
61 | 85 | ||
@@ -179,7 +203,8 @@ void *eeh_pe_dev_traverse(struct eeh_pe *root, | |||
179 | void *ret; | 203 | void *ret; |
180 | 204 | ||
181 | if (!root) { | 205 | if (!root) { |
182 | pr_warning("%s: Invalid PE %p\n", __func__, root); | 206 | pr_warn("%s: Invalid PE %p\n", |
207 | __func__, root); | ||
183 | return NULL; | 208 | return NULL; |
184 | } | 209 | } |
185 | 210 | ||
@@ -351,17 +376,6 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev) | |||
351 | pe->config_addr = edev->config_addr; | 376 | pe->config_addr = edev->config_addr; |
352 | 377 | ||
353 | /* | 378 | /* |
354 | * While doing PE reset, we probably hot-reset the | ||
355 | * upstream bridge. However, the PCI devices including | ||
356 | * the associated EEH devices might be removed when EEH | ||
357 | * core is doing recovery. So that won't safe to retrieve | ||
358 | * the bridge through downstream EEH device. We have to | ||
359 | * trace the parent PCI bus, then the upstream bridge. | ||
360 | */ | ||
361 | if (eeh_probe_mode_dev()) | ||
362 | pe->bus = eeh_dev_to_pci_dev(edev)->bus; | ||
363 | |||
364 | /* | ||
365 | * Put the new EEH PE into hierarchy tree. If the parent | 379 | * Put the new EEH PE into hierarchy tree. If the parent |
366 | * can't be found, the newly created PE will be attached | 380 | * can't be found, the newly created PE will be attached |
367 | * to PHB directly. Otherwise, we have to associate the | 381 | * to PHB directly. Otherwise, we have to associate the |
@@ -802,53 +816,33 @@ void eeh_pe_restore_bars(struct eeh_pe *pe) | |||
802 | */ | 816 | */ |
803 | const char *eeh_pe_loc_get(struct eeh_pe *pe) | 817 | const char *eeh_pe_loc_get(struct eeh_pe *pe) |
804 | { | 818 | { |
805 | struct pci_controller *hose; | ||
806 | struct pci_bus *bus = eeh_pe_bus_get(pe); | 819 | struct pci_bus *bus = eeh_pe_bus_get(pe); |
807 | struct pci_dev *pdev; | 820 | struct device_node *dn = pci_bus_to_OF_node(bus); |
808 | struct device_node *dn; | 821 | const char *loc = NULL; |
809 | const char *loc; | ||
810 | 822 | ||
811 | if (!bus) | 823 | if (!dn) |
812 | return "N/A"; | 824 | goto out; |
813 | 825 | ||
814 | /* PHB PE or root PE ? */ | 826 | /* PHB PE or root PE ? */ |
815 | if (pci_is_root_bus(bus)) { | 827 | if (pci_is_root_bus(bus)) { |
816 | hose = pci_bus_to_host(bus); | 828 | loc = of_get_property(dn, "ibm,loc-code", NULL); |
817 | loc = of_get_property(hose->dn, | 829 | if (!loc) |
818 | "ibm,loc-code", NULL); | 830 | loc = of_get_property(dn, "ibm,io-base-loc-code", NULL); |
819 | if (loc) | 831 | if (loc) |
820 | return loc; | 832 | goto out; |
821 | loc = of_get_property(hose->dn, | ||
822 | "ibm,io-base-loc-code", NULL); | ||
823 | if (loc) | ||
824 | return loc; | ||
825 | |||
826 | pdev = pci_get_slot(bus, 0x0); | ||
827 | } else { | ||
828 | pdev = bus->self; | ||
829 | } | ||
830 | |||
831 | if (!pdev) { | ||
832 | loc = "N/A"; | ||
833 | goto out; | ||
834 | } | ||
835 | 833 | ||
836 | dn = pci_device_to_OF_node(pdev); | 834 | /* Check the root port */ |
837 | if (!dn) { | 835 | dn = dn->child; |
838 | loc = "N/A"; | 836 | if (!dn) |
839 | goto out; | 837 | goto out; |
840 | } | 838 | } |
841 | 839 | ||
842 | loc = of_get_property(dn, "ibm,loc-code", NULL); | 840 | loc = of_get_property(dn, "ibm,loc-code", NULL); |
843 | if (!loc) | 841 | if (!loc) |
844 | loc = of_get_property(dn, "ibm,slot-location-code", NULL); | 842 | loc = of_get_property(dn, "ibm,slot-location-code", NULL); |
845 | if (!loc) | ||
846 | loc = "N/A"; | ||
847 | 843 | ||
848 | out: | 844 | out: |
849 | if (pci_is_root_bus(bus) && pdev) | 845 | return loc ? loc : "N/A"; |
850 | pci_dev_put(pdev); | ||
851 | return loc; | ||
852 | } | 846 | } |
853 | 847 | ||
854 | /** | 848 | /** |
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 6528c5e2cc44..5bbd1bc8c3b0 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S | |||
@@ -482,16 +482,12 @@ END_FTR_SECTION_IFSET(CPU_FTR_STCX_CHECKS_ADDRESS) | |||
482 | ld r8,KSP(r4) /* new stack pointer */ | 482 | ld r8,KSP(r4) /* new stack pointer */ |
483 | #ifdef CONFIG_PPC_BOOK3S | 483 | #ifdef CONFIG_PPC_BOOK3S |
484 | BEGIN_FTR_SECTION | 484 | BEGIN_FTR_SECTION |
485 | BEGIN_FTR_SECTION_NESTED(95) | ||
486 | clrrdi r6,r8,28 /* get its ESID */ | 485 | clrrdi r6,r8,28 /* get its ESID */ |
487 | clrrdi r9,r1,28 /* get current sp ESID */ | 486 | clrrdi r9,r1,28 /* get current sp ESID */ |
488 | FTR_SECTION_ELSE_NESTED(95) | 487 | FTR_SECTION_ELSE |
489 | clrrdi r6,r8,40 /* get its 1T ESID */ | 488 | clrrdi r6,r8,40 /* get its 1T ESID */ |
490 | clrrdi r9,r1,40 /* get current sp 1T ESID */ | 489 | clrrdi r9,r1,40 /* get current sp 1T ESID */ |
491 | ALT_MMU_FTR_SECTION_END_NESTED_IFCLR(MMU_FTR_1T_SEGMENT, 95) | 490 | ALT_MMU_FTR_SECTION_END_IFCLR(MMU_FTR_1T_SEGMENT) |
492 | FTR_SECTION_ELSE | ||
493 | b 2f | ||
494 | ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_SLB) | ||
495 | clrldi. r0,r6,2 /* is new ESID c00000000? */ | 491 | clrldi. r0,r6,2 /* is new ESID c00000000? */ |
496 | cmpd cr1,r6,r9 /* or is new ESID the same as current ESID? */ | 492 | cmpd cr1,r6,r9 /* or is new ESID the same as current ESID? */ |
497 | cror eq,4*cr1+eq,eq | 493 | cror eq,4*cr1+eq,eq |
@@ -919,6 +915,11 @@ restore_check_irq_replay: | |||
919 | addi r3,r1,STACK_FRAME_OVERHEAD; | 915 | addi r3,r1,STACK_FRAME_OVERHEAD; |
920 | bl do_IRQ | 916 | bl do_IRQ |
921 | b ret_from_except | 917 | b ret_from_except |
918 | 1: cmpwi cr0,r3,0xe60 | ||
919 | bne 1f | ||
920 | addi r3,r1,STACK_FRAME_OVERHEAD; | ||
921 | bl handle_hmi_exception | ||
922 | b ret_from_except | ||
922 | 1: cmpwi cr0,r3,0x900 | 923 | 1: cmpwi cr0,r3,0x900 |
923 | bne 1f | 924 | bne 1f |
924 | addi r3,r1,STACK_FRAME_OVERHEAD; | 925 | addi r3,r1,STACK_FRAME_OVERHEAD; |
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index a7d36b19221d..050f79a4a168 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S | |||
@@ -188,10 +188,6 @@ ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE) | |||
188 | data_access_pSeries: | 188 | data_access_pSeries: |
189 | HMT_MEDIUM_PPR_DISCARD | 189 | HMT_MEDIUM_PPR_DISCARD |
190 | SET_SCRATCH0(r13) | 190 | SET_SCRATCH0(r13) |
191 | BEGIN_FTR_SECTION | ||
192 | b data_access_check_stab | ||
193 | data_access_not_stab: | ||
194 | END_MMU_FTR_SECTION_IFCLR(MMU_FTR_SLB) | ||
195 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, data_access_common, EXC_STD, | 191 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, data_access_common, EXC_STD, |
196 | KVMTEST, 0x300) | 192 | KVMTEST, 0x300) |
197 | 193 | ||
@@ -339,7 +335,7 @@ emulation_assist_trampoline: | |||
339 | hv_exception_trampoline: | 335 | hv_exception_trampoline: |
340 | SET_SCRATCH0(r13) | 336 | SET_SCRATCH0(r13) |
341 | EXCEPTION_PROLOG_0(PACA_EXGEN) | 337 | EXCEPTION_PROLOG_0(PACA_EXGEN) |
342 | b hmi_exception_hv | 338 | b hmi_exception_early |
343 | 339 | ||
344 | . = 0xe80 | 340 | . = 0xe80 |
345 | hv_doorbell_trampoline: | 341 | hv_doorbell_trampoline: |
@@ -514,34 +510,6 @@ machine_check_pSeries_0: | |||
514 | EXCEPTION_PROLOG_1(PACA_EXMC, KVMTEST, 0x200) | 510 | EXCEPTION_PROLOG_1(PACA_EXMC, KVMTEST, 0x200) |
515 | EXCEPTION_PROLOG_PSERIES_1(machine_check_common, EXC_STD) | 511 | EXCEPTION_PROLOG_PSERIES_1(machine_check_common, EXC_STD) |
516 | KVM_HANDLER_SKIP(PACA_EXMC, EXC_STD, 0x200) | 512 | KVM_HANDLER_SKIP(PACA_EXMC, EXC_STD, 0x200) |
517 | |||
518 | /* moved from 0x300 */ | ||
519 | data_access_check_stab: | ||
520 | GET_PACA(r13) | ||
521 | std r9,PACA_EXSLB+EX_R9(r13) | ||
522 | std r10,PACA_EXSLB+EX_R10(r13) | ||
523 | mfspr r10,SPRN_DAR | ||
524 | mfspr r9,SPRN_DSISR | ||
525 | srdi r10,r10,60 | ||
526 | rlwimi r10,r9,16,0x20 | ||
527 | #ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE | ||
528 | lbz r9,HSTATE_IN_GUEST(r13) | ||
529 | rlwimi r10,r9,8,0x300 | ||
530 | #endif | ||
531 | mfcr r9 | ||
532 | cmpwi r10,0x2c | ||
533 | beq do_stab_bolted_pSeries | ||
534 | mtcrf 0x80,r9 | ||
535 | ld r9,PACA_EXSLB+EX_R9(r13) | ||
536 | ld r10,PACA_EXSLB+EX_R10(r13) | ||
537 | b data_access_not_stab | ||
538 | do_stab_bolted_pSeries: | ||
539 | std r11,PACA_EXSLB+EX_R11(r13) | ||
540 | std r12,PACA_EXSLB+EX_R12(r13) | ||
541 | GET_SCRATCH0(r10) | ||
542 | std r10,PACA_EXSLB+EX_R13(r13) | ||
543 | EXCEPTION_PROLOG_PSERIES_1(do_stab_bolted, EXC_STD) | ||
544 | |||
545 | KVM_HANDLER_SKIP(PACA_EXGEN, EXC_STD, 0x300) | 513 | KVM_HANDLER_SKIP(PACA_EXGEN, EXC_STD, 0x300) |
546 | KVM_HANDLER_SKIP(PACA_EXSLB, EXC_STD, 0x380) | 514 | KVM_HANDLER_SKIP(PACA_EXSLB, EXC_STD, 0x380) |
547 | KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0x400) | 515 | KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0x400) |
@@ -621,8 +589,9 @@ END_FTR_SECTION_IFSET(CPU_FTR_CFAR) | |||
621 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe22) | 589 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe22) |
622 | STD_EXCEPTION_HV_OOL(0xe42, emulation_assist) | 590 | STD_EXCEPTION_HV_OOL(0xe42, emulation_assist) |
623 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe42) | 591 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe42) |
624 | STD_EXCEPTION_HV_OOL(0xe62, hmi_exception) /* need to flush cache ? */ | 592 | MASKABLE_EXCEPTION_HV_OOL(0xe62, hmi_exception) |
625 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe62) | 593 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe62) |
594 | |||
626 | MASKABLE_EXCEPTION_HV_OOL(0xe82, h_doorbell) | 595 | MASKABLE_EXCEPTION_HV_OOL(0xe82, h_doorbell) |
627 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe82) | 596 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe82) |
628 | 597 | ||
@@ -643,6 +612,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_CFAR) | |||
643 | * - If it was a decrementer interrupt, we bump the dec to max and and return. | 612 | * - If it was a decrementer interrupt, we bump the dec to max and and return. |
644 | * - If it was a doorbell we return immediately since doorbells are edge | 613 | * - If it was a doorbell we return immediately since doorbells are edge |
645 | * triggered and won't automatically refire. | 614 | * triggered and won't automatically refire. |
615 | * - If it was a HMI we return immediately since we handled it in realmode | ||
616 | * and it won't refire. | ||
646 | * - else we hard disable and return. | 617 | * - else we hard disable and return. |
647 | * This is called with r10 containing the value to OR to the paca field. | 618 | * This is called with r10 containing the value to OR to the paca field. |
648 | */ | 619 | */ |
@@ -660,6 +631,8 @@ masked_##_H##interrupt: \ | |||
660 | b 2f; \ | 631 | b 2f; \ |
661 | 1: cmpwi r10,PACA_IRQ_DBELL; \ | 632 | 1: cmpwi r10,PACA_IRQ_DBELL; \ |
662 | beq 2f; \ | 633 | beq 2f; \ |
634 | cmpwi r10,PACA_IRQ_HMI; \ | ||
635 | beq 2f; \ | ||
663 | mfspr r10,SPRN_##_H##SRR1; \ | 636 | mfspr r10,SPRN_##_H##SRR1; \ |
664 | rldicl r10,r10,48,1; /* clear MSR_EE */ \ | 637 | rldicl r10,r10,48,1; /* clear MSR_EE */ \ |
665 | rotldi r10,r10,16; \ | 638 | rotldi r10,r10,16; \ |
@@ -799,7 +772,7 @@ kvmppc_skip_Hinterrupt: | |||
799 | STD_EXCEPTION_COMMON(0xd00, single_step, single_step_exception) | 772 | STD_EXCEPTION_COMMON(0xd00, single_step, single_step_exception) |
800 | STD_EXCEPTION_COMMON(0xe00, trap_0e, unknown_exception) | 773 | STD_EXCEPTION_COMMON(0xe00, trap_0e, unknown_exception) |
801 | STD_EXCEPTION_COMMON(0xe40, emulation_assist, emulation_assist_interrupt) | 774 | STD_EXCEPTION_COMMON(0xe40, emulation_assist, emulation_assist_interrupt) |
802 | STD_EXCEPTION_COMMON(0xe60, hmi_exception, unknown_exception) | 775 | STD_EXCEPTION_COMMON_ASYNC(0xe60, hmi_exception, handle_hmi_exception) |
803 | #ifdef CONFIG_PPC_DOORBELL | 776 | #ifdef CONFIG_PPC_DOORBELL |
804 | STD_EXCEPTION_COMMON_ASYNC(0xe80, h_doorbell, doorbell_exception) | 777 | STD_EXCEPTION_COMMON_ASYNC(0xe80, h_doorbell, doorbell_exception) |
805 | #else | 778 | #else |
@@ -985,66 +958,6 @@ ppc64_runlatch_on_trampoline: | |||
985 | b __ppc64_runlatch_on | 958 | b __ppc64_runlatch_on |
986 | 959 | ||
987 | /* | 960 | /* |
988 | * Here we have detected that the kernel stack pointer is bad. | ||
989 | * R9 contains the saved CR, r13 points to the paca, | ||
990 | * r10 contains the (bad) kernel stack pointer, | ||
991 | * r11 and r12 contain the saved SRR0 and SRR1. | ||
992 | * We switch to using an emergency stack, save the registers there, | ||
993 | * and call kernel_bad_stack(), which panics. | ||
994 | */ | ||
995 | bad_stack: | ||
996 | ld r1,PACAEMERGSP(r13) | ||
997 | subi r1,r1,64+INT_FRAME_SIZE | ||
998 | std r9,_CCR(r1) | ||
999 | std r10,GPR1(r1) | ||
1000 | std r11,_NIP(r1) | ||
1001 | std r12,_MSR(r1) | ||
1002 | mfspr r11,SPRN_DAR | ||
1003 | mfspr r12,SPRN_DSISR | ||
1004 | std r11,_DAR(r1) | ||
1005 | std r12,_DSISR(r1) | ||
1006 | mflr r10 | ||
1007 | mfctr r11 | ||
1008 | mfxer r12 | ||
1009 | std r10,_LINK(r1) | ||
1010 | std r11,_CTR(r1) | ||
1011 | std r12,_XER(r1) | ||
1012 | SAVE_GPR(0,r1) | ||
1013 | SAVE_GPR(2,r1) | ||
1014 | ld r10,EX_R3(r3) | ||
1015 | std r10,GPR3(r1) | ||
1016 | SAVE_GPR(4,r1) | ||
1017 | SAVE_4GPRS(5,r1) | ||
1018 | ld r9,EX_R9(r3) | ||
1019 | ld r10,EX_R10(r3) | ||
1020 | SAVE_2GPRS(9,r1) | ||
1021 | ld r9,EX_R11(r3) | ||
1022 | ld r10,EX_R12(r3) | ||
1023 | ld r11,EX_R13(r3) | ||
1024 | std r9,GPR11(r1) | ||
1025 | std r10,GPR12(r1) | ||
1026 | std r11,GPR13(r1) | ||
1027 | BEGIN_FTR_SECTION | ||
1028 | ld r10,EX_CFAR(r3) | ||
1029 | std r10,ORIG_GPR3(r1) | ||
1030 | END_FTR_SECTION_IFSET(CPU_FTR_CFAR) | ||
1031 | SAVE_8GPRS(14,r1) | ||
1032 | SAVE_10GPRS(22,r1) | ||
1033 | lhz r12,PACA_TRAP_SAVE(r13) | ||
1034 | std r12,_TRAP(r1) | ||
1035 | addi r11,r1,INT_FRAME_SIZE | ||
1036 | std r11,0(r1) | ||
1037 | li r12,0 | ||
1038 | std r12,0(r11) | ||
1039 | ld r2,PACATOC(r13) | ||
1040 | ld r11,exception_marker@toc(r2) | ||
1041 | std r12,RESULT(r1) | ||
1042 | std r11,STACK_FRAME_OVERHEAD-16(r1) | ||
1043 | 1: addi r3,r1,STACK_FRAME_OVERHEAD | ||
1044 | bl kernel_bad_stack | ||
1045 | b 1b | ||
1046 | |||
1047 | /* | ||
1048 | * Here r13 points to the paca, r9 contains the saved CR, | 961 | * Here r13 points to the paca, r9 contains the saved CR, |
1049 | * SRR0 and SRR1 are saved in r11 and r12, | 962 | * SRR0 and SRR1 are saved in r11 and r12, |
1050 | * r9 - r13 are saved in paca->exgen. | 963 | * r9 - r13 are saved in paca->exgen. |
@@ -1057,7 +970,7 @@ data_access_common: | |||
1057 | mfspr r10,SPRN_DSISR | 970 | mfspr r10,SPRN_DSISR |
1058 | stw r10,PACA_EXGEN+EX_DSISR(r13) | 971 | stw r10,PACA_EXGEN+EX_DSISR(r13) |
1059 | EXCEPTION_PROLOG_COMMON(0x300, PACA_EXGEN) | 972 | EXCEPTION_PROLOG_COMMON(0x300, PACA_EXGEN) |
1060 | DISABLE_INTS | 973 | RECONCILE_IRQ_STATE(r10, r11) |
1061 | ld r12,_MSR(r1) | 974 | ld r12,_MSR(r1) |
1062 | ld r3,PACA_EXGEN+EX_DAR(r13) | 975 | ld r3,PACA_EXGEN+EX_DAR(r13) |
1063 | lwz r4,PACA_EXGEN+EX_DSISR(r13) | 976 | lwz r4,PACA_EXGEN+EX_DSISR(r13) |
@@ -1073,7 +986,7 @@ h_data_storage_common: | |||
1073 | stw r10,PACA_EXGEN+EX_DSISR(r13) | 986 | stw r10,PACA_EXGEN+EX_DSISR(r13) |
1074 | EXCEPTION_PROLOG_COMMON(0xe00, PACA_EXGEN) | 987 | EXCEPTION_PROLOG_COMMON(0xe00, PACA_EXGEN) |
1075 | bl save_nvgprs | 988 | bl save_nvgprs |
1076 | DISABLE_INTS | 989 | RECONCILE_IRQ_STATE(r10, r11) |
1077 | addi r3,r1,STACK_FRAME_OVERHEAD | 990 | addi r3,r1,STACK_FRAME_OVERHEAD |
1078 | bl unknown_exception | 991 | bl unknown_exception |
1079 | b ret_from_except | 992 | b ret_from_except |
@@ -1082,7 +995,7 @@ h_data_storage_common: | |||
1082 | .globl instruction_access_common | 995 | .globl instruction_access_common |
1083 | instruction_access_common: | 996 | instruction_access_common: |
1084 | EXCEPTION_PROLOG_COMMON(0x400, PACA_EXGEN) | 997 | EXCEPTION_PROLOG_COMMON(0x400, PACA_EXGEN) |
1085 | DISABLE_INTS | 998 | RECONCILE_IRQ_STATE(r10, r11) |
1086 | ld r12,_MSR(r1) | 999 | ld r12,_MSR(r1) |
1087 | ld r3,_NIP(r1) | 1000 | ld r3,_NIP(r1) |
1088 | andis. r4,r12,0x5820 | 1001 | andis. r4,r12,0x5820 |
@@ -1146,7 +1059,7 @@ slb_miss_fault: | |||
1146 | 1059 | ||
1147 | unrecov_user_slb: | 1060 | unrecov_user_slb: |
1148 | EXCEPTION_PROLOG_COMMON(0x4200, PACA_EXGEN) | 1061 | EXCEPTION_PROLOG_COMMON(0x4200, PACA_EXGEN) |
1149 | DISABLE_INTS | 1062 | RECONCILE_IRQ_STATE(r10, r11) |
1150 | bl save_nvgprs | 1063 | bl save_nvgprs |
1151 | 1: addi r3,r1,STACK_FRAME_OVERHEAD | 1064 | 1: addi r3,r1,STACK_FRAME_OVERHEAD |
1152 | bl unrecoverable_exception | 1065 | bl unrecoverable_exception |
@@ -1169,7 +1082,7 @@ machine_check_common: | |||
1169 | stw r10,PACA_EXGEN+EX_DSISR(r13) | 1082 | stw r10,PACA_EXGEN+EX_DSISR(r13) |
1170 | EXCEPTION_PROLOG_COMMON(0x200, PACA_EXMC) | 1083 | EXCEPTION_PROLOG_COMMON(0x200, PACA_EXMC) |
1171 | FINISH_NAP | 1084 | FINISH_NAP |
1172 | DISABLE_INTS | 1085 | RECONCILE_IRQ_STATE(r10, r11) |
1173 | ld r3,PACA_EXGEN+EX_DAR(r13) | 1086 | ld r3,PACA_EXGEN+EX_DAR(r13) |
1174 | lwz r4,PACA_EXGEN+EX_DSISR(r13) | 1087 | lwz r4,PACA_EXGEN+EX_DSISR(r13) |
1175 | std r3,_DAR(r1) | 1088 | std r3,_DAR(r1) |
@@ -1192,7 +1105,7 @@ alignment_common: | |||
1192 | std r3,_DAR(r1) | 1105 | std r3,_DAR(r1) |
1193 | std r4,_DSISR(r1) | 1106 | std r4,_DSISR(r1) |
1194 | bl save_nvgprs | 1107 | bl save_nvgprs |
1195 | DISABLE_INTS | 1108 | RECONCILE_IRQ_STATE(r10, r11) |
1196 | addi r3,r1,STACK_FRAME_OVERHEAD | 1109 | addi r3,r1,STACK_FRAME_OVERHEAD |
1197 | bl alignment_exception | 1110 | bl alignment_exception |
1198 | b ret_from_except | 1111 | b ret_from_except |
@@ -1202,7 +1115,7 @@ alignment_common: | |||
1202 | program_check_common: | 1115 | program_check_common: |
1203 | EXCEPTION_PROLOG_COMMON(0x700, PACA_EXGEN) | 1116 | EXCEPTION_PROLOG_COMMON(0x700, PACA_EXGEN) |
1204 | bl save_nvgprs | 1117 | bl save_nvgprs |
1205 | DISABLE_INTS | 1118 | RECONCILE_IRQ_STATE(r10, r11) |
1206 | addi r3,r1,STACK_FRAME_OVERHEAD | 1119 | addi r3,r1,STACK_FRAME_OVERHEAD |
1207 | bl program_check_exception | 1120 | bl program_check_exception |
1208 | b ret_from_except | 1121 | b ret_from_except |
@@ -1213,7 +1126,7 @@ fp_unavailable_common: | |||
1213 | EXCEPTION_PROLOG_COMMON(0x800, PACA_EXGEN) | 1126 | EXCEPTION_PROLOG_COMMON(0x800, PACA_EXGEN) |
1214 | bne 1f /* if from user, just load it up */ | 1127 | bne 1f /* if from user, just load it up */ |
1215 | bl save_nvgprs | 1128 | bl save_nvgprs |
1216 | DISABLE_INTS | 1129 | RECONCILE_IRQ_STATE(r10, r11) |
1217 | addi r3,r1,STACK_FRAME_OVERHEAD | 1130 | addi r3,r1,STACK_FRAME_OVERHEAD |
1218 | bl kernel_fp_unavailable_exception | 1131 | bl kernel_fp_unavailable_exception |
1219 | BUG_OPCODE | 1132 | BUG_OPCODE |
@@ -1232,7 +1145,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_TM) | |||
1232 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | 1145 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM |
1233 | 2: /* User process was in a transaction */ | 1146 | 2: /* User process was in a transaction */ |
1234 | bl save_nvgprs | 1147 | bl save_nvgprs |
1235 | DISABLE_INTS | 1148 | RECONCILE_IRQ_STATE(r10, r11) |
1236 | addi r3,r1,STACK_FRAME_OVERHEAD | 1149 | addi r3,r1,STACK_FRAME_OVERHEAD |
1237 | bl fp_unavailable_tm | 1150 | bl fp_unavailable_tm |
1238 | b ret_from_except | 1151 | b ret_from_except |
@@ -1258,7 +1171,7 @@ BEGIN_FTR_SECTION | |||
1258 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | 1171 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM |
1259 | 2: /* User process was in a transaction */ | 1172 | 2: /* User process was in a transaction */ |
1260 | bl save_nvgprs | 1173 | bl save_nvgprs |
1261 | DISABLE_INTS | 1174 | RECONCILE_IRQ_STATE(r10, r11) |
1262 | addi r3,r1,STACK_FRAME_OVERHEAD | 1175 | addi r3,r1,STACK_FRAME_OVERHEAD |
1263 | bl altivec_unavailable_tm | 1176 | bl altivec_unavailable_tm |
1264 | b ret_from_except | 1177 | b ret_from_except |
@@ -1267,7 +1180,7 @@ BEGIN_FTR_SECTION | |||
1267 | END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | 1180 | END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) |
1268 | #endif | 1181 | #endif |
1269 | bl save_nvgprs | 1182 | bl save_nvgprs |
1270 | DISABLE_INTS | 1183 | RECONCILE_IRQ_STATE(r10, r11) |
1271 | addi r3,r1,STACK_FRAME_OVERHEAD | 1184 | addi r3,r1,STACK_FRAME_OVERHEAD |
1272 | bl altivec_unavailable_exception | 1185 | bl altivec_unavailable_exception |
1273 | b ret_from_except | 1186 | b ret_from_except |
@@ -1292,7 +1205,7 @@ BEGIN_FTR_SECTION | |||
1292 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | 1205 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM |
1293 | 2: /* User process was in a transaction */ | 1206 | 2: /* User process was in a transaction */ |
1294 | bl save_nvgprs | 1207 | bl save_nvgprs |
1295 | DISABLE_INTS | 1208 | RECONCILE_IRQ_STATE(r10, r11) |
1296 | addi r3,r1,STACK_FRAME_OVERHEAD | 1209 | addi r3,r1,STACK_FRAME_OVERHEAD |
1297 | bl vsx_unavailable_tm | 1210 | bl vsx_unavailable_tm |
1298 | b ret_from_except | 1211 | b ret_from_except |
@@ -1301,7 +1214,7 @@ BEGIN_FTR_SECTION | |||
1301 | END_FTR_SECTION_IFSET(CPU_FTR_VSX) | 1214 | END_FTR_SECTION_IFSET(CPU_FTR_VSX) |
1302 | #endif | 1215 | #endif |
1303 | bl save_nvgprs | 1216 | bl save_nvgprs |
1304 | DISABLE_INTS | 1217 | RECONCILE_IRQ_STATE(r10, r11) |
1305 | addi r3,r1,STACK_FRAME_OVERHEAD | 1218 | addi r3,r1,STACK_FRAME_OVERHEAD |
1306 | bl vsx_unavailable_exception | 1219 | bl vsx_unavailable_exception |
1307 | b ret_from_except | 1220 | b ret_from_except |
@@ -1338,11 +1251,60 @@ fwnmi_data_area: | |||
1338 | . = 0x8000 | 1251 | . = 0x8000 |
1339 | #endif /* defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) */ | 1252 | #endif /* defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) */ |
1340 | 1253 | ||
1341 | /* Space for CPU0's segment table */ | 1254 | .globl hmi_exception_early |
1342 | .balign 4096 | 1255 | hmi_exception_early: |
1343 | .globl initial_stab | 1256 | EXCEPTION_PROLOG_1(PACA_EXGEN, NOTEST, 0xe60) |
1344 | initial_stab: | 1257 | mr r10,r1 /* Save r1 */ |
1345 | .space 4096 | 1258 | ld r1,PACAEMERGSP(r13) /* Use emergency stack */ |
1259 | subi r1,r1,INT_FRAME_SIZE /* alloc stack frame */ | ||
1260 | std r9,_CCR(r1) /* save CR in stackframe */ | ||
1261 | mfspr r11,SPRN_HSRR0 /* Save HSRR0 */ | ||
1262 | std r11,_NIP(r1) /* save HSRR0 in stackframe */ | ||
1263 | mfspr r12,SPRN_HSRR1 /* Save SRR1 */ | ||
1264 | std r12,_MSR(r1) /* save SRR1 in stackframe */ | ||
1265 | std r10,0(r1) /* make stack chain pointer */ | ||
1266 | std r0,GPR0(r1) /* save r0 in stackframe */ | ||
1267 | std r10,GPR1(r1) /* save r1 in stackframe */ | ||
1268 | EXCEPTION_PROLOG_COMMON_2(PACA_EXGEN) | ||
1269 | EXCEPTION_PROLOG_COMMON_3(0xe60) | ||
1270 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
1271 | bl hmi_exception_realmode | ||
1272 | /* Windup the stack. */ | ||
1273 | /* Clear MSR_RI before setting SRR0 and SRR1. */ | ||
1274 | li r0,MSR_RI | ||
1275 | mfmsr r9 /* get MSR value */ | ||
1276 | andc r9,r9,r0 | ||
1277 | mtmsrd r9,1 /* Clear MSR_RI */ | ||
1278 | /* Move original HSRR0 and HSRR1 into the respective regs */ | ||
1279 | ld r9,_MSR(r1) | ||
1280 | mtspr SPRN_HSRR1,r9 | ||
1281 | ld r3,_NIP(r1) | ||
1282 | mtspr SPRN_HSRR0,r3 | ||
1283 | ld r9,_CTR(r1) | ||
1284 | mtctr r9 | ||
1285 | ld r9,_XER(r1) | ||
1286 | mtxer r9 | ||
1287 | ld r9,_LINK(r1) | ||
1288 | mtlr r9 | ||
1289 | REST_GPR(0, r1) | ||
1290 | REST_8GPRS(2, r1) | ||
1291 | REST_GPR(10, r1) | ||
1292 | ld r11,_CCR(r1) | ||
1293 | mtcr r11 | ||
1294 | REST_GPR(11, r1) | ||
1295 | REST_2GPRS(12, r1) | ||
1296 | /* restore original r1. */ | ||
1297 | ld r1,GPR1(r1) | ||
1298 | |||
1299 | /* | ||
1300 | * Go to virtual mode and pull the HMI event information from | ||
1301 | * firmware. | ||
1302 | */ | ||
1303 | .globl hmi_exception_after_realmode | ||
1304 | hmi_exception_after_realmode: | ||
1305 | SET_SCRATCH0(r13) | ||
1306 | EXCEPTION_PROLOG_0(PACA_EXGEN) | ||
1307 | b hmi_exception_hv | ||
1346 | 1308 | ||
1347 | #ifdef CONFIG_PPC_POWERNV | 1309 | #ifdef CONFIG_PPC_POWERNV |
1348 | _GLOBAL(opal_mc_secondary_handler) | 1310 | _GLOBAL(opal_mc_secondary_handler) |
@@ -1566,7 +1528,7 @@ slb_miss_realmode: | |||
1566 | 1528 | ||
1567 | unrecov_slb: | 1529 | unrecov_slb: |
1568 | EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB) | 1530 | EXCEPTION_PROLOG_COMMON(0x4100, PACA_EXSLB) |
1569 | DISABLE_INTS | 1531 | RECONCILE_IRQ_STATE(r10, r11) |
1570 | bl save_nvgprs | 1532 | bl save_nvgprs |
1571 | 1: addi r3,r1,STACK_FRAME_OVERHEAD | 1533 | 1: addi r3,r1,STACK_FRAME_OVERHEAD |
1572 | bl unrecoverable_exception | 1534 | bl unrecoverable_exception |
@@ -1594,12 +1556,6 @@ do_hash_page: | |||
1594 | bne- handle_page_fault /* if not, try to insert a HPTE */ | 1556 | bne- handle_page_fault /* if not, try to insert a HPTE */ |
1595 | andis. r0,r4,DSISR_DABRMATCH@h | 1557 | andis. r0,r4,DSISR_DABRMATCH@h |
1596 | bne- handle_dabr_fault | 1558 | bne- handle_dabr_fault |
1597 | |||
1598 | BEGIN_FTR_SECTION | ||
1599 | andis. r0,r4,0x0020 /* Is it a segment table fault? */ | ||
1600 | bne- do_ste_alloc /* If so handle it */ | ||
1601 | END_MMU_FTR_SECTION_IFCLR(MMU_FTR_SLB) | ||
1602 | |||
1603 | CURRENT_THREAD_INFO(r11, r1) | 1559 | CURRENT_THREAD_INFO(r11, r1) |
1604 | lwz r0,TI_PREEMPT(r11) /* If we're in an "NMI" */ | 1560 | lwz r0,TI_PREEMPT(r11) /* If we're in an "NMI" */ |
1605 | andis. r0,r0,NMI_MASK@h /* (i.e. an irq when soft-disabled) */ | 1561 | andis. r0,r0,NMI_MASK@h /* (i.e. an irq when soft-disabled) */ |
@@ -1681,113 +1637,62 @@ handle_dabr_fault: | |||
1681 | bl bad_page_fault | 1637 | bl bad_page_fault |
1682 | b ret_from_except | 1638 | b ret_from_except |
1683 | 1639 | ||
1684 | /* here we have a segment miss */ | ||
1685 | do_ste_alloc: | ||
1686 | bl ste_allocate /* try to insert stab entry */ | ||
1687 | cmpdi r3,0 | ||
1688 | bne- handle_page_fault | ||
1689 | b fast_exception_return | ||
1690 | |||
1691 | /* | 1640 | /* |
1692 | * r13 points to the PACA, r9 contains the saved CR, | 1641 | * Here we have detected that the kernel stack pointer is bad. |
1642 | * R9 contains the saved CR, r13 points to the paca, | ||
1643 | * r10 contains the (bad) kernel stack pointer, | ||
1693 | * r11 and r12 contain the saved SRR0 and SRR1. | 1644 | * r11 and r12 contain the saved SRR0 and SRR1. |
1694 | * r9 - r13 are saved in paca->exslb. | 1645 | * We switch to using an emergency stack, save the registers there, |
1695 | * We assume we aren't going to take any exceptions during this procedure. | 1646 | * and call kernel_bad_stack(), which panics. |
1696 | * We assume (DAR >> 60) == 0xc. | ||
1697 | */ | 1647 | */ |
1698 | .align 7 | 1648 | bad_stack: |
1699 | do_stab_bolted: | 1649 | ld r1,PACAEMERGSP(r13) |
1700 | stw r9,PACA_EXSLB+EX_CCR(r13) /* save CR in exc. frame */ | 1650 | subi r1,r1,64+INT_FRAME_SIZE |
1701 | std r11,PACA_EXSLB+EX_SRR0(r13) /* save SRR0 in exc. frame */ | 1651 | std r9,_CCR(r1) |
1702 | mfspr r11,SPRN_DAR /* ea */ | 1652 | std r10,GPR1(r1) |
1703 | 1653 | std r11,_NIP(r1) | |
1704 | /* | 1654 | std r12,_MSR(r1) |
1705 | * check for bad kernel/user address | 1655 | mfspr r11,SPRN_DAR |
1706 | * (ea & ~REGION_MASK) >= PGTABLE_RANGE | 1656 | mfspr r12,SPRN_DSISR |
1707 | */ | 1657 | std r11,_DAR(r1) |
1708 | rldicr. r9,r11,4,(63 - 46 - 4) | 1658 | std r12,_DSISR(r1) |
1709 | li r9,0 /* VSID = 0 for bad address */ | 1659 | mflr r10 |
1710 | bne- 0f | 1660 | mfctr r11 |
1711 | 1661 | mfxer r12 | |
1712 | /* | 1662 | std r10,_LINK(r1) |
1713 | * Calculate VSID: | 1663 | std r11,_CTR(r1) |
1714 | * This is the kernel vsid, we take the top for context from | 1664 | std r12,_XER(r1) |
1715 | * the range. context = (MAX_USER_CONTEXT) + ((ea >> 60) - 0xc) + 1 | 1665 | SAVE_GPR(0,r1) |
1716 | * Here we know that (ea >> 60) == 0xc | 1666 | SAVE_GPR(2,r1) |
1717 | */ | 1667 | ld r10,EX_R3(r3) |
1718 | lis r9,(MAX_USER_CONTEXT + 1)@ha | 1668 | std r10,GPR3(r1) |
1719 | addi r9,r9,(MAX_USER_CONTEXT + 1)@l | 1669 | SAVE_GPR(4,r1) |
1720 | 1670 | SAVE_4GPRS(5,r1) | |
1721 | srdi r10,r11,SID_SHIFT | 1671 | ld r9,EX_R9(r3) |
1722 | rldimi r10,r9,ESID_BITS,0 /* proto vsid */ | 1672 | ld r10,EX_R10(r3) |
1723 | ASM_VSID_SCRAMBLE(r10, r9, 256M) | 1673 | SAVE_2GPRS(9,r1) |
1724 | rldic r9,r10,12,16 /* r9 = vsid << 12 */ | 1674 | ld r9,EX_R11(r3) |
1725 | 1675 | ld r10,EX_R12(r3) | |
1726 | 0: | 1676 | ld r11,EX_R13(r3) |
1727 | /* Hash to the primary group */ | 1677 | std r9,GPR11(r1) |
1728 | ld r10,PACASTABVIRT(r13) | 1678 | std r10,GPR12(r1) |
1729 | srdi r11,r11,SID_SHIFT | 1679 | std r11,GPR13(r1) |
1730 | rldimi r10,r11,7,52 /* r10 = first ste of the group */ | 1680 | BEGIN_FTR_SECTION |
1731 | 1681 | ld r10,EX_CFAR(r3) | |
1732 | /* Search the primary group for a free entry */ | 1682 | std r10,ORIG_GPR3(r1) |
1733 | 1: ld r11,0(r10) /* Test valid bit of the current ste */ | 1683 | END_FTR_SECTION_IFSET(CPU_FTR_CFAR) |
1734 | andi. r11,r11,0x80 | 1684 | SAVE_8GPRS(14,r1) |
1735 | beq 2f | 1685 | SAVE_10GPRS(22,r1) |
1736 | addi r10,r10,16 | 1686 | lhz r12,PACA_TRAP_SAVE(r13) |
1737 | andi. r11,r10,0x70 | 1687 | std r12,_TRAP(r1) |
1738 | bne 1b | 1688 | addi r11,r1,INT_FRAME_SIZE |
1739 | 1689 | std r11,0(r1) | |
1740 | /* Stick for only searching the primary group for now. */ | 1690 | li r12,0 |
1741 | /* At least for now, we use a very simple random castout scheme */ | 1691 | std r12,0(r11) |
1742 | /* Use the TB as a random number ; OR in 1 to avoid entry 0 */ | 1692 | ld r2,PACATOC(r13) |
1743 | mftb r11 | 1693 | ld r11,exception_marker@toc(r2) |
1744 | rldic r11,r11,4,57 /* r11 = (r11 << 4) & 0x70 */ | 1694 | std r12,RESULT(r1) |
1745 | ori r11,r11,0x10 | 1695 | std r11,STACK_FRAME_OVERHEAD-16(r1) |
1746 | 1696 | 1: addi r3,r1,STACK_FRAME_OVERHEAD | |
1747 | /* r10 currently points to an ste one past the group of interest */ | 1697 | bl kernel_bad_stack |
1748 | /* make it point to the randomly selected entry */ | 1698 | b 1b |
1749 | subi r10,r10,128 | ||
1750 | or r10,r10,r11 /* r10 is the entry to invalidate */ | ||
1751 | |||
1752 | isync /* mark the entry invalid */ | ||
1753 | ld r11,0(r10) | ||
1754 | rldicl r11,r11,56,1 /* clear the valid bit */ | ||
1755 | rotldi r11,r11,8 | ||
1756 | std r11,0(r10) | ||
1757 | sync | ||
1758 | |||
1759 | clrrdi r11,r11,28 /* Get the esid part of the ste */ | ||
1760 | slbie r11 | ||
1761 | |||
1762 | 2: std r9,8(r10) /* Store the vsid part of the ste */ | ||
1763 | eieio | ||
1764 | |||
1765 | mfspr r11,SPRN_DAR /* Get the new esid */ | ||
1766 | clrrdi r11,r11,28 /* Permits a full 32b of ESID */ | ||
1767 | ori r11,r11,0x90 /* Turn on valid and kp */ | ||
1768 | std r11,0(r10) /* Put new entry back into the stab */ | ||
1769 | |||
1770 | sync | ||
1771 | |||
1772 | /* All done -- return from exception. */ | ||
1773 | lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */ | ||
1774 | ld r11,PACA_EXSLB+EX_SRR0(r13) /* get saved SRR0 */ | ||
1775 | |||
1776 | andi. r10,r12,MSR_RI | ||
1777 | beq- unrecov_slb | ||
1778 | |||
1779 | mtcrf 0x80,r9 /* restore CR */ | ||
1780 | |||
1781 | mfmsr r10 | ||
1782 | clrrdi r10,r10,2 | ||
1783 | mtmsrd r10,1 | ||
1784 | |||
1785 | mtspr SPRN_SRR0,r11 | ||
1786 | mtspr SPRN_SRR1,r12 | ||
1787 | ld r9,PACA_EXSLB+EX_R9(r13) | ||
1788 | ld r10,PACA_EXSLB+EX_R10(r13) | ||
1789 | ld r11,PACA_EXSLB+EX_R11(r13) | ||
1790 | ld r12,PACA_EXSLB+EX_R12(r13) | ||
1791 | ld r13,PACA_EXSLB+EX_R13(r13) | ||
1792 | rfid | ||
1793 | b . /* prevent speculative execution */ | ||
diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S index c334f53453f7..b5061abbd2e0 100644 --- a/arch/powerpc/kernel/head_44x.S +++ b/arch/powerpc/kernel/head_44x.S | |||
@@ -1210,10 +1210,12 @@ clear_utlb_entry: | |||
1210 | 1210 | ||
1211 | /* We configure icbi to invalidate 128 bytes at a time since the | 1211 | /* We configure icbi to invalidate 128 bytes at a time since the |
1212 | * current 32-bit kernel code isn't too happy with icache != dcache | 1212 | * current 32-bit kernel code isn't too happy with icache != dcache |
1213 | * block size | 1213 | * block size. We also disable the BTAC as this can cause errors |
1214 | * in some circumstances (see IBM Erratum 47). | ||
1214 | */ | 1215 | */ |
1215 | mfspr r3,SPRN_CCR0 | 1216 | mfspr r3,SPRN_CCR0 |
1216 | oris r3,r3,0x0020 | 1217 | oris r3,r3,0x0020 |
1218 | ori r3,r3,0x0040 | ||
1217 | mtspr SPRN_CCR0,r3 | 1219 | mtspr SPRN_CCR0,r3 |
1218 | isync | 1220 | isync |
1219 | 1221 | ||
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index a95145d7f61b..d48125d0c048 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S | |||
@@ -180,6 +180,28 @@ exception_marker: | |||
180 | #include "exceptions-64s.S" | 180 | #include "exceptions-64s.S" |
181 | #endif | 181 | #endif |
182 | 182 | ||
183 | #ifdef CONFIG_PPC_BOOK3E | ||
184 | _GLOBAL(fsl_secondary_thread_init) | ||
185 | /* Enable branch prediction */ | ||
186 | lis r3,BUCSR_INIT@h | ||
187 | ori r3,r3,BUCSR_INIT@l | ||
188 | mtspr SPRN_BUCSR,r3 | ||
189 | isync | ||
190 | |||
191 | /* | ||
192 | * Fix PIR to match the linear numbering in the device tree. | ||
193 | * | ||
194 | * On e6500, the reset value of PIR uses the low three bits for | ||
195 | * the thread within a core, and the upper bits for the core | ||
196 | * number. There are two threads per core, so shift everything | ||
197 | * but the low bit right by two bits so that the cpu numbering is | ||
198 | * continuous. | ||
199 | */ | ||
200 | mfspr r3, SPRN_PIR | ||
201 | rlwimi r3, r3, 30, 2, 30 | ||
202 | mtspr SPRN_PIR, r3 | ||
203 | #endif | ||
204 | |||
183 | _GLOBAL(generic_secondary_thread_init) | 205 | _GLOBAL(generic_secondary_thread_init) |
184 | mr r24,r3 | 206 | mr r24,r3 |
185 | 207 | ||
@@ -618,7 +640,7 @@ __secondary_start: | |||
618 | addi r14,r14,THREAD_SIZE-STACK_FRAME_OVERHEAD | 640 | addi r14,r14,THREAD_SIZE-STACK_FRAME_OVERHEAD |
619 | std r14,PACAKSAVE(r13) | 641 | std r14,PACAKSAVE(r13) |
620 | 642 | ||
621 | /* Do early setup for that CPU (stab, slb, hash table pointer) */ | 643 | /* Do early setup for that CPU (SLB and hash table pointer) */ |
622 | bl early_setup_secondary | 644 | bl early_setup_secondary |
623 | 645 | ||
624 | /* | 646 | /* |
@@ -771,8 +793,10 @@ start_here_multiplatform: | |||
771 | li r0,0 | 793 | li r0,0 |
772 | stdu r0,-STACK_FRAME_OVERHEAD(r1) | 794 | stdu r0,-STACK_FRAME_OVERHEAD(r1) |
773 | 795 | ||
774 | /* Do very early kernel initializations, including initial hash table, | 796 | /* |
775 | * stab and slb setup before we turn on relocation. */ | 797 | * Do very early kernel initializations, including initial hash table |
798 | * and SLB setup before we turn on relocation. | ||
799 | */ | ||
776 | 800 | ||
777 | /* Restore parameters passed from prom_init/kexec */ | 801 | /* Restore parameters passed from prom_init/kexec */ |
778 | mr r3,r31 | 802 | mr r3,r31 |
diff --git a/arch/powerpc/kernel/idle_power7.S b/arch/powerpc/kernel/idle_power7.S index 5cf3d367190d..be05841396cf 100644 --- a/arch/powerpc/kernel/idle_power7.S +++ b/arch/powerpc/kernel/idle_power7.S | |||
@@ -135,17 +135,68 @@ _GLOBAL(power7_sleep) | |||
135 | b power7_powersave_common | 135 | b power7_powersave_common |
136 | /* No return */ | 136 | /* No return */ |
137 | 137 | ||
138 | /* | ||
139 | * Make opal call in realmode. This is a generic function to be called | ||
140 | * from realmode from reset vector. It handles endianess. | ||
141 | * | ||
142 | * r13 - paca pointer | ||
143 | * r1 - stack pointer | ||
144 | * r3 - opal token | ||
145 | */ | ||
146 | opal_call_realmode: | ||
147 | mflr r12 | ||
148 | std r12,_LINK(r1) | ||
149 | ld r2,PACATOC(r13) | ||
150 | /* Set opal return address */ | ||
151 | LOAD_REG_ADDR(r0,return_from_opal_call) | ||
152 | mtlr r0 | ||
153 | /* Handle endian-ness */ | ||
154 | li r0,MSR_LE | ||
155 | mfmsr r12 | ||
156 | andc r12,r12,r0 | ||
157 | mtspr SPRN_HSRR1,r12 | ||
158 | mr r0,r3 /* Move opal token to r0 */ | ||
159 | LOAD_REG_ADDR(r11,opal) | ||
160 | ld r12,8(r11) | ||
161 | ld r2,0(r11) | ||
162 | mtspr SPRN_HSRR0,r12 | ||
163 | hrfid | ||
164 | |||
165 | return_from_opal_call: | ||
166 | FIXUP_ENDIAN | ||
167 | ld r0,_LINK(r1) | ||
168 | mtlr r0 | ||
169 | blr | ||
170 | |||
171 | #define CHECK_HMI_INTERRUPT \ | ||
172 | mfspr r0,SPRN_SRR1; \ | ||
173 | BEGIN_FTR_SECTION_NESTED(66); \ | ||
174 | rlwinm r0,r0,45-31,0xf; /* extract wake reason field (P8) */ \ | ||
175 | FTR_SECTION_ELSE_NESTED(66); \ | ||
176 | rlwinm r0,r0,45-31,0xe; /* P7 wake reason field is 3 bits */ \ | ||
177 | ALT_FTR_SECTION_END_NESTED_IFSET(CPU_FTR_ARCH_207S, 66); \ | ||
178 | cmpwi r0,0xa; /* Hypervisor maintenance ? */ \ | ||
179 | bne 20f; \ | ||
180 | /* Invoke opal call to handle hmi */ \ | ||
181 | ld r2,PACATOC(r13); \ | ||
182 | ld r1,PACAR1(r13); \ | ||
183 | std r3,ORIG_GPR3(r1); /* Save original r3 */ \ | ||
184 | li r3,OPAL_HANDLE_HMI; /* Pass opal token argument*/ \ | ||
185 | bl opal_call_realmode; \ | ||
186 | ld r3,ORIG_GPR3(r1); /* Restore original r3 */ \ | ||
187 | 20: nop; | ||
188 | |||
189 | |||
138 | _GLOBAL(power7_wakeup_tb_loss) | 190 | _GLOBAL(power7_wakeup_tb_loss) |
139 | ld r2,PACATOC(r13); | 191 | ld r2,PACATOC(r13); |
140 | ld r1,PACAR1(r13) | 192 | ld r1,PACAR1(r13) |
141 | 193 | ||
194 | BEGIN_FTR_SECTION | ||
195 | CHECK_HMI_INTERRUPT | ||
196 | END_FTR_SECTION_IFSET(CPU_FTR_HVMODE) | ||
142 | /* Time base re-sync */ | 197 | /* Time base re-sync */ |
143 | li r0,OPAL_RESYNC_TIMEBASE | 198 | li r3,OPAL_RESYNC_TIMEBASE |
144 | LOAD_REG_ADDR(r11,opal); | 199 | bl opal_call_realmode; |
145 | ld r12,8(r11); | ||
146 | ld r2,0(r11); | ||
147 | mtctr r12 | ||
148 | bctrl | ||
149 | 200 | ||
150 | /* TODO: Check r3 for failure */ | 201 | /* TODO: Check r3 for failure */ |
151 | 202 | ||
@@ -163,6 +214,9 @@ _GLOBAL(power7_wakeup_tb_loss) | |||
163 | 214 | ||
164 | _GLOBAL(power7_wakeup_loss) | 215 | _GLOBAL(power7_wakeup_loss) |
165 | ld r1,PACAR1(r13) | 216 | ld r1,PACAR1(r13) |
217 | BEGIN_FTR_SECTION | ||
218 | CHECK_HMI_INTERRUPT | ||
219 | END_FTR_SECTION_IFSET(CPU_FTR_HVMODE) | ||
166 | REST_NVGPRS(r1) | 220 | REST_NVGPRS(r1) |
167 | REST_GPR(2, r1) | 221 | REST_GPR(2, r1) |
168 | ld r3,_CCR(r1) | 222 | ld r3,_CCR(r1) |
@@ -178,6 +232,9 @@ _GLOBAL(power7_wakeup_noloss) | |||
178 | lbz r0,PACA_NAPSTATELOST(r13) | 232 | lbz r0,PACA_NAPSTATELOST(r13) |
179 | cmpwi r0,0 | 233 | cmpwi r0,0 |
180 | bne power7_wakeup_loss | 234 | bne power7_wakeup_loss |
235 | BEGIN_FTR_SECTION | ||
236 | CHECK_HMI_INTERRUPT | ||
237 | END_FTR_SECTION_IFSET(CPU_FTR_HVMODE) | ||
181 | ld r1,PACAR1(r13) | 238 | ld r1,PACAR1(r13) |
182 | ld r4,_MSR(r1) | 239 | ld r4,_MSR(r1) |
183 | ld r5,_NIP(r1) | 240 | ld r5,_NIP(r1) |
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index 88e3ec6e1d96..a10642a0d861 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c | |||
@@ -1037,7 +1037,7 @@ int iommu_tce_build(struct iommu_table *tbl, unsigned long entry, | |||
1037 | 1037 | ||
1038 | /* if (unlikely(ret)) | 1038 | /* if (unlikely(ret)) |
1039 | pr_err("iommu_tce: %s failed on hwaddr=%lx ioba=%lx kva=%lx ret=%d\n", | 1039 | pr_err("iommu_tce: %s failed on hwaddr=%lx ioba=%lx kva=%lx ret=%d\n", |
1040 | __func__, hwaddr, entry << IOMMU_PAGE_SHIFT(tbl), | 1040 | __func__, hwaddr, entry << tbl->it_page_shift, |
1041 | hwaddr, ret); */ | 1041 | hwaddr, ret); */ |
1042 | 1042 | ||
1043 | return ret; | 1043 | return ret; |
@@ -1056,7 +1056,7 @@ int iommu_put_tce_user_mode(struct iommu_table *tbl, unsigned long entry, | |||
1056 | direction != DMA_TO_DEVICE, &page); | 1056 | direction != DMA_TO_DEVICE, &page); |
1057 | if (unlikely(ret != 1)) { | 1057 | if (unlikely(ret != 1)) { |
1058 | /* pr_err("iommu_tce: get_user_pages_fast failed tce=%lx ioba=%lx ret=%d\n", | 1058 | /* pr_err("iommu_tce: get_user_pages_fast failed tce=%lx ioba=%lx ret=%d\n", |
1059 | tce, entry << IOMMU_PAGE_SHIFT(tbl), ret); */ | 1059 | tce, entry << tbl->it_page_shift, ret); */ |
1060 | return -EFAULT; | 1060 | return -EFAULT; |
1061 | } | 1061 | } |
1062 | hwaddr = (unsigned long) page_address(page) + offset; | 1062 | hwaddr = (unsigned long) page_address(page) + offset; |
@@ -1120,37 +1120,41 @@ EXPORT_SYMBOL_GPL(iommu_release_ownership); | |||
1120 | int iommu_add_device(struct device *dev) | 1120 | int iommu_add_device(struct device *dev) |
1121 | { | 1121 | { |
1122 | struct iommu_table *tbl; | 1122 | struct iommu_table *tbl; |
1123 | int ret = 0; | ||
1124 | 1123 | ||
1125 | if (WARN_ON(dev->iommu_group)) { | 1124 | /* |
1126 | pr_warn("iommu_tce: device %s is already in iommu group %d, skipping\n", | 1125 | * The sysfs entries should be populated before |
1127 | dev_name(dev), | 1126 | * binding IOMMU group. If sysfs entries isn't |
1128 | iommu_group_id(dev->iommu_group)); | 1127 | * ready, we simply bail. |
1128 | */ | ||
1129 | if (!device_is_registered(dev)) | ||
1130 | return -ENOENT; | ||
1131 | |||
1132 | if (dev->iommu_group) { | ||
1133 | pr_debug("%s: Skipping device %s with iommu group %d\n", | ||
1134 | __func__, dev_name(dev), | ||
1135 | iommu_group_id(dev->iommu_group)); | ||
1129 | return -EBUSY; | 1136 | return -EBUSY; |
1130 | } | 1137 | } |
1131 | 1138 | ||
1132 | tbl = get_iommu_table_base(dev); | 1139 | tbl = get_iommu_table_base(dev); |
1133 | if (!tbl || !tbl->it_group) { | 1140 | if (!tbl || !tbl->it_group) { |
1134 | pr_debug("iommu_tce: skipping device %s with no tbl\n", | 1141 | pr_debug("%s: Skipping device %s with no tbl\n", |
1135 | dev_name(dev)); | 1142 | __func__, dev_name(dev)); |
1136 | return 0; | 1143 | return 0; |
1137 | } | 1144 | } |
1138 | 1145 | ||
1139 | pr_debug("iommu_tce: adding %s to iommu group %d\n", | 1146 | pr_debug("%s: Adding %s to iommu group %d\n", |
1140 | dev_name(dev), iommu_group_id(tbl->it_group)); | 1147 | __func__, dev_name(dev), |
1148 | iommu_group_id(tbl->it_group)); | ||
1141 | 1149 | ||
1142 | if (PAGE_SIZE < IOMMU_PAGE_SIZE(tbl)) { | 1150 | if (PAGE_SIZE < IOMMU_PAGE_SIZE(tbl)) { |
1143 | pr_err("iommu_tce: unsupported iommu page size."); | 1151 | pr_err("%s: Invalid IOMMU page size %lx (%lx) on %s\n", |
1144 | pr_err("%s has not been added\n", dev_name(dev)); | 1152 | __func__, IOMMU_PAGE_SIZE(tbl), |
1153 | PAGE_SIZE, dev_name(dev)); | ||
1145 | return -EINVAL; | 1154 | return -EINVAL; |
1146 | } | 1155 | } |
1147 | 1156 | ||
1148 | ret = iommu_group_add_device(tbl->it_group, dev); | 1157 | return iommu_group_add_device(tbl->it_group, dev); |
1149 | if (ret < 0) | ||
1150 | pr_err("iommu_tce: %s has not been added, ret=%d\n", | ||
1151 | dev_name(dev), ret); | ||
1152 | |||
1153 | return ret; | ||
1154 | } | 1158 | } |
1155 | EXPORT_SYMBOL_GPL(iommu_add_device); | 1159 | EXPORT_SYMBOL_GPL(iommu_add_device); |
1156 | 1160 | ||
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 248ee7e5bebd..4c5891de162e 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c | |||
@@ -189,6 +189,11 @@ notrace unsigned int __check_irq_replay(void) | |||
189 | } | 189 | } |
190 | #endif /* CONFIG_PPC_BOOK3E */ | 190 | #endif /* CONFIG_PPC_BOOK3E */ |
191 | 191 | ||
192 | /* Check if an hypervisor Maintenance interrupt happened */ | ||
193 | local_paca->irq_happened &= ~PACA_IRQ_HMI; | ||
194 | if (happened & PACA_IRQ_HMI) | ||
195 | return 0xe60; | ||
196 | |||
192 | /* There should be nothing left ! */ | 197 | /* There should be nothing left ! */ |
193 | BUG_ON(local_paca->irq_happened != 0); | 198 | BUG_ON(local_paca->irq_happened != 0); |
194 | 199 | ||
@@ -377,6 +382,14 @@ int arch_show_interrupts(struct seq_file *p, int prec) | |||
377 | seq_printf(p, "%10u ", per_cpu(irq_stat, j).mce_exceptions); | 382 | seq_printf(p, "%10u ", per_cpu(irq_stat, j).mce_exceptions); |
378 | seq_printf(p, " Machine check exceptions\n"); | 383 | seq_printf(p, " Machine check exceptions\n"); |
379 | 384 | ||
385 | if (cpu_has_feature(CPU_FTR_HVMODE)) { | ||
386 | seq_printf(p, "%*s: ", prec, "HMI"); | ||
387 | for_each_online_cpu(j) | ||
388 | seq_printf(p, "%10u ", | ||
389 | per_cpu(irq_stat, j).hmi_exceptions); | ||
390 | seq_printf(p, " Hypervisor Maintenance Interrupts\n"); | ||
391 | } | ||
392 | |||
380 | #ifdef CONFIG_PPC_DOORBELL | 393 | #ifdef CONFIG_PPC_DOORBELL |
381 | if (cpu_has_feature(CPU_FTR_DBELL)) { | 394 | if (cpu_has_feature(CPU_FTR_DBELL)) { |
382 | seq_printf(p, "%*s: ", prec, "DBL"); | 395 | seq_printf(p, "%*s: ", prec, "DBL"); |
@@ -400,6 +413,7 @@ u64 arch_irq_stat_cpu(unsigned int cpu) | |||
400 | sum += per_cpu(irq_stat, cpu).mce_exceptions; | 413 | sum += per_cpu(irq_stat, cpu).mce_exceptions; |
401 | sum += per_cpu(irq_stat, cpu).spurious_irqs; | 414 | sum += per_cpu(irq_stat, cpu).spurious_irqs; |
402 | sum += per_cpu(irq_stat, cpu).timer_irqs_others; | 415 | sum += per_cpu(irq_stat, cpu).timer_irqs_others; |
416 | sum += per_cpu(irq_stat, cpu).hmi_exceptions; | ||
403 | #ifdef CONFIG_PPC_DOORBELL | 417 | #ifdef CONFIG_PPC_DOORBELL |
404 | sum += per_cpu(irq_stat, cpu).doorbell_irqs; | 418 | sum += per_cpu(irq_stat, cpu).doorbell_irqs; |
405 | #endif | 419 | #endif |
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index be99774d3f44..bf44ae962ab8 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
@@ -1095,6 +1095,23 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) | |||
1095 | return 0; | 1095 | return 0; |
1096 | } | 1096 | } |
1097 | 1097 | ||
1098 | static void setup_ksp_vsid(struct task_struct *p, unsigned long sp) | ||
1099 | { | ||
1100 | #ifdef CONFIG_PPC_STD_MMU_64 | ||
1101 | unsigned long sp_vsid; | ||
1102 | unsigned long llp = mmu_psize_defs[mmu_linear_psize].sllp; | ||
1103 | |||
1104 | if (mmu_has_feature(MMU_FTR_1T_SEGMENT)) | ||
1105 | sp_vsid = get_kernel_vsid(sp, MMU_SEGSIZE_1T) | ||
1106 | << SLB_VSID_SHIFT_1T; | ||
1107 | else | ||
1108 | sp_vsid = get_kernel_vsid(sp, MMU_SEGSIZE_256M) | ||
1109 | << SLB_VSID_SHIFT; | ||
1110 | sp_vsid |= SLB_VSID_KERNEL | llp; | ||
1111 | p->thread.ksp_vsid = sp_vsid; | ||
1112 | #endif | ||
1113 | } | ||
1114 | |||
1098 | /* | 1115 | /* |
1099 | * Copy a thread.. | 1116 | * Copy a thread.. |
1100 | */ | 1117 | */ |
@@ -1174,21 +1191,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
1174 | p->thread.vr_save_area = NULL; | 1191 | p->thread.vr_save_area = NULL; |
1175 | #endif | 1192 | #endif |
1176 | 1193 | ||
1177 | #ifdef CONFIG_PPC_STD_MMU_64 | 1194 | setup_ksp_vsid(p, sp); |
1178 | if (mmu_has_feature(MMU_FTR_SLB)) { | ||
1179 | unsigned long sp_vsid; | ||
1180 | unsigned long llp = mmu_psize_defs[mmu_linear_psize].sllp; | ||
1181 | 1195 | ||
1182 | if (mmu_has_feature(MMU_FTR_1T_SEGMENT)) | ||
1183 | sp_vsid = get_kernel_vsid(sp, MMU_SEGSIZE_1T) | ||
1184 | << SLB_VSID_SHIFT_1T; | ||
1185 | else | ||
1186 | sp_vsid = get_kernel_vsid(sp, MMU_SEGSIZE_256M) | ||
1187 | << SLB_VSID_SHIFT; | ||
1188 | sp_vsid |= SLB_VSID_KERNEL | llp; | ||
1189 | p->thread.ksp_vsid = sp_vsid; | ||
1190 | } | ||
1191 | #endif /* CONFIG_PPC_STD_MMU_64 */ | ||
1192 | #ifdef CONFIG_PPC64 | 1196 | #ifdef CONFIG_PPC64 |
1193 | if (cpu_has_feature(CPU_FTR_DSCR)) { | 1197 | if (cpu_has_feature(CPU_FTR_DSCR)) { |
1194 | p->thread.dscr_inherit = current->thread.dscr_inherit; | 1198 | p->thread.dscr_inherit = current->thread.dscr_inherit; |
@@ -1577,7 +1581,7 @@ void show_stack(struct task_struct *tsk, unsigned long *stack) | |||
1577 | struct pt_regs *regs = (struct pt_regs *) | 1581 | struct pt_regs *regs = (struct pt_regs *) |
1578 | (sp + STACK_FRAME_OVERHEAD); | 1582 | (sp + STACK_FRAME_OVERHEAD); |
1579 | lr = regs->link; | 1583 | lr = regs->link; |
1580 | printk("--- Exception: %lx at %pS\n LR = %pS\n", | 1584 | printk("--- interrupt: %lx at %pS\n LR = %pS\n", |
1581 | regs->trap, (void *)regs->nip, (void *)lr); | 1585 | regs->trap, (void *)regs->nip, (void *)lr); |
1582 | firstframe = 1; | 1586 | firstframe = 1; |
1583 | } | 1587 | } |
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index b694b0730971..4e139f8a69ef 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
@@ -155,7 +155,6 @@ static struct ibm_pa_feature { | |||
155 | } ibm_pa_features[] __initdata = { | 155 | } ibm_pa_features[] __initdata = { |
156 | {0, 0, PPC_FEATURE_HAS_MMU, 0, 0, 0}, | 156 | {0, 0, PPC_FEATURE_HAS_MMU, 0, 0, 0}, |
157 | {0, 0, PPC_FEATURE_HAS_FPU, 0, 1, 0}, | 157 | {0, 0, PPC_FEATURE_HAS_FPU, 0, 1, 0}, |
158 | {0, MMU_FTR_SLB, 0, 0, 2, 0}, | ||
159 | {CPU_FTR_CTRL, 0, 0, 0, 3, 0}, | 158 | {CPU_FTR_CTRL, 0, 0, 0, 3, 0}, |
160 | {CPU_FTR_NOEXECUTE, 0, 0, 0, 6, 0}, | 159 | {CPU_FTR_NOEXECUTE, 0, 0, 0, 6, 0}, |
161 | {CPU_FTR_NODSISRALIGN, 0, 0, 1, 1, 1}, | 160 | {CPU_FTR_NODSISRALIGN, 0, 0, 1, 1, 1}, |
@@ -309,12 +308,10 @@ static int __init early_init_dt_scan_cpus(unsigned long node, | |||
309 | 308 | ||
310 | /* Get physical cpuid */ | 309 | /* Get physical cpuid */ |
311 | intserv = of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s", &len); | 310 | intserv = of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s", &len); |
312 | if (intserv) { | 311 | if (!intserv) |
313 | nthreads = len / sizeof(int); | 312 | intserv = of_get_flat_dt_prop(node, "reg", &len); |
314 | } else { | 313 | |
315 | intserv = of_get_flat_dt_prop(node, "reg", NULL); | 314 | nthreads = len / sizeof(int); |
316 | nthreads = 1; | ||
317 | } | ||
318 | 315 | ||
319 | /* | 316 | /* |
320 | * Now see if any of these threads match our boot cpu. | 317 | * Now see if any of these threads match our boot cpu. |
@@ -821,76 +818,6 @@ int cpu_to_chip_id(int cpu) | |||
821 | } | 818 | } |
822 | EXPORT_SYMBOL(cpu_to_chip_id); | 819 | EXPORT_SYMBOL(cpu_to_chip_id); |
823 | 820 | ||
824 | #ifdef CONFIG_PPC_PSERIES | ||
825 | /* | ||
826 | * Fix up the uninitialized fields in a new device node: | ||
827 | * name, type and pci-specific fields | ||
828 | */ | ||
829 | |||
830 | static int of_finish_dynamic_node(struct device_node *node) | ||
831 | { | ||
832 | struct device_node *parent = of_get_parent(node); | ||
833 | int err = 0; | ||
834 | const phandle *ibm_phandle; | ||
835 | |||
836 | node->name = of_get_property(node, "name", NULL); | ||
837 | node->type = of_get_property(node, "device_type", NULL); | ||
838 | |||
839 | if (!node->name) | ||
840 | node->name = "<NULL>"; | ||
841 | if (!node->type) | ||
842 | node->type = "<NULL>"; | ||
843 | |||
844 | if (!parent) { | ||
845 | err = -ENODEV; | ||
846 | goto out; | ||
847 | } | ||
848 | |||
849 | /* We don't support that function on PowerMac, at least | ||
850 | * not yet | ||
851 | */ | ||
852 | if (machine_is(powermac)) | ||
853 | return -ENODEV; | ||
854 | |||
855 | /* fix up new node's phandle field */ | ||
856 | if ((ibm_phandle = of_get_property(node, "ibm,phandle", NULL))) | ||
857 | node->phandle = *ibm_phandle; | ||
858 | |||
859 | out: | ||
860 | of_node_put(parent); | ||
861 | return err; | ||
862 | } | ||
863 | |||
864 | static int prom_reconfig_notifier(struct notifier_block *nb, | ||
865 | unsigned long action, void *node) | ||
866 | { | ||
867 | int err; | ||
868 | |||
869 | switch (action) { | ||
870 | case OF_RECONFIG_ATTACH_NODE: | ||
871 | err = of_finish_dynamic_node(node); | ||
872 | if (err < 0) | ||
873 | printk(KERN_ERR "finish_node returned %d\n", err); | ||
874 | break; | ||
875 | default: | ||
876 | err = 0; | ||
877 | break; | ||
878 | } | ||
879 | return notifier_from_errno(err); | ||
880 | } | ||
881 | |||
882 | static struct notifier_block prom_reconfig_nb = { | ||
883 | .notifier_call = prom_reconfig_notifier, | ||
884 | .priority = 10, /* This one needs to run first */ | ||
885 | }; | ||
886 | |||
887 | static int __init prom_reconfig_setup(void) | ||
888 | { | ||
889 | return of_reconfig_notifier_register(&prom_reconfig_nb); | ||
890 | } | ||
891 | __initcall(prom_reconfig_setup); | ||
892 | #endif | ||
893 | |||
894 | bool arch_match_cpu_phys_id(int cpu, u64 phys_id) | 821 | bool arch_match_cpu_phys_id(int cpu, u64 phys_id) |
895 | { | 822 | { |
896 | return (int)phys_id == get_hard_smp_processor_id(cpu); | 823 | return (int)phys_id == get_hard_smp_processor_id(cpu); |
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index e5b022c55ccd..1b0e26013a62 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c | |||
@@ -456,18 +456,20 @@ void __init smp_setup_cpu_maps(void) | |||
456 | intserv = of_get_property(dn, "ibm,ppc-interrupt-server#s", | 456 | intserv = of_get_property(dn, "ibm,ppc-interrupt-server#s", |
457 | &len); | 457 | &len); |
458 | if (intserv) { | 458 | if (intserv) { |
459 | nthreads = len / sizeof(int); | ||
460 | DBG(" ibm,ppc-interrupt-server#s -> %d threads\n", | 459 | DBG(" ibm,ppc-interrupt-server#s -> %d threads\n", |
461 | nthreads); | 460 | nthreads); |
462 | } else { | 461 | } else { |
463 | DBG(" no ibm,ppc-interrupt-server#s -> 1 thread\n"); | 462 | DBG(" no ibm,ppc-interrupt-server#s -> 1 thread\n"); |
464 | intserv = of_get_property(dn, "reg", NULL); | 463 | intserv = of_get_property(dn, "reg", &len); |
465 | if (!intserv) { | 464 | if (!intserv) { |
466 | cpu_be = cpu_to_be32(cpu); | 465 | cpu_be = cpu_to_be32(cpu); |
467 | intserv = &cpu_be; /* assume logical == phys */ | 466 | intserv = &cpu_be; /* assume logical == phys */ |
467 | len = 4; | ||
468 | } | 468 | } |
469 | } | 469 | } |
470 | 470 | ||
471 | nthreads = len / sizeof(int); | ||
472 | |||
471 | for (j = 0; j < nthreads && cpu < nr_cpu_ids; j++) { | 473 | for (j = 0; j < nthreads && cpu < nr_cpu_ids; j++) { |
472 | bool avail; | 474 | bool avail; |
473 | 475 | ||
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index ee082d771178..75d62d63fe68 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
@@ -149,13 +149,13 @@ static void check_smt_enabled(void) | |||
149 | else if (!strcmp(smt_enabled_cmdline, "off")) | 149 | else if (!strcmp(smt_enabled_cmdline, "off")) |
150 | smt_enabled_at_boot = 0; | 150 | smt_enabled_at_boot = 0; |
151 | else { | 151 | else { |
152 | long smt; | 152 | int smt; |
153 | int rc; | 153 | int rc; |
154 | 154 | ||
155 | rc = strict_strtol(smt_enabled_cmdline, 10, &smt); | 155 | rc = kstrtoint(smt_enabled_cmdline, 10, &smt); |
156 | if (!rc) | 156 | if (!rc) |
157 | smt_enabled_at_boot = | 157 | smt_enabled_at_boot = |
158 | min(threads_per_core, (int)smt); | 158 | min(threads_per_core, smt); |
159 | } | 159 | } |
160 | } else { | 160 | } else { |
161 | dn = of_find_node_by_path("/options"); | 161 | dn = of_find_node_by_path("/options"); |
@@ -201,7 +201,11 @@ static void cpu_ready_for_interrupts(void) | |||
201 | /* Set IR and DR in PACA MSR */ | 201 | /* Set IR and DR in PACA MSR */ |
202 | get_paca()->kernel_msr = MSR_KERNEL; | 202 | get_paca()->kernel_msr = MSR_KERNEL; |
203 | 203 | ||
204 | /* Enable AIL if supported */ | 204 | /* |
205 | * Enable AIL if supported, and we are in hypervisor mode. If we are | ||
206 | * not in hypervisor mode, we enable relocation-on interrupts later | ||
207 | * in pSeries_setup_arch() using the H_SET_MODE hcall. | ||
208 | */ | ||
205 | if (cpu_has_feature(CPU_FTR_HVMODE) && | 209 | if (cpu_has_feature(CPU_FTR_HVMODE) && |
206 | cpu_has_feature(CPU_FTR_ARCH_207S)) { | 210 | cpu_has_feature(CPU_FTR_ARCH_207S)) { |
207 | unsigned long lpcr = mfspr(SPRN_LPCR); | 211 | unsigned long lpcr = mfspr(SPRN_LPCR); |
@@ -507,7 +511,11 @@ void __init setup_system(void) | |||
507 | check_smt_enabled(); | 511 | check_smt_enabled(); |
508 | setup_tlb_core_data(); | 512 | setup_tlb_core_data(); |
509 | 513 | ||
510 | #ifdef CONFIG_SMP | 514 | /* |
515 | * Freescale Book3e parts spin in a loop provided by firmware, | ||
516 | * so smp_release_cpus() does nothing for them | ||
517 | */ | ||
518 | #if defined(CONFIG_SMP) && !defined(CONFIG_PPC_FSL_BOOK3E) | ||
511 | /* Release secondary cpus out of their spinloops at 0x60 now that | 519 | /* Release secondary cpus out of their spinloops at 0x60 now that |
512 | * we can map physical -> logical CPU ids | 520 | * we can map physical -> logical CPU ids |
513 | */ | 521 | */ |
@@ -673,9 +681,6 @@ void __init setup_arch(char **cmdline_p) | |||
673 | exc_lvl_early_init(); | 681 | exc_lvl_early_init(); |
674 | emergency_stack_init(); | 682 | emergency_stack_init(); |
675 | 683 | ||
676 | #ifdef CONFIG_PPC_STD_MMU_64 | ||
677 | stabs_alloc(); | ||
678 | #endif | ||
679 | /* set up the bootmem stuff with available memory */ | 684 | /* set up the bootmem stuff with available memory */ |
680 | do_init_bootmem(); | 685 | do_init_bootmem(); |
681 | sparse_init(); | 686 | sparse_init(); |
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c index 1c794cef2883..cf8c7e4e0b21 100644 --- a/arch/powerpc/kernel/signal.c +++ b/arch/powerpc/kernel/signal.c | |||
@@ -31,20 +31,14 @@ int show_unhandled_signals = 1; | |||
31 | /* | 31 | /* |
32 | * Allocate space for the signal frame | 32 | * Allocate space for the signal frame |
33 | */ | 33 | */ |
34 | void __user * get_sigframe(struct k_sigaction *ka, unsigned long sp, | 34 | void __user *get_sigframe(struct ksignal *ksig, unsigned long sp, |
35 | size_t frame_size, int is_32) | 35 | size_t frame_size, int is_32) |
36 | { | 36 | { |
37 | unsigned long oldsp, newsp; | 37 | unsigned long oldsp, newsp; |
38 | 38 | ||
39 | /* Default to using normal stack */ | 39 | /* Default to using normal stack */ |
40 | oldsp = get_clean_sp(sp, is_32); | 40 | oldsp = get_clean_sp(sp, is_32); |
41 | 41 | oldsp = sigsp(oldsp, ksig); | |
42 | /* Check for alt stack */ | ||
43 | if ((ka->sa.sa_flags & SA_ONSTACK) && | ||
44 | current->sas_ss_size && !on_sig_stack(oldsp)) | ||
45 | oldsp = (current->sas_ss_sp + current->sas_ss_size); | ||
46 | |||
47 | /* Get aligned frame */ | ||
48 | newsp = (oldsp - frame_size) & ~0xFUL; | 42 | newsp = (oldsp - frame_size) & ~0xFUL; |
49 | 43 | ||
50 | /* Check access */ | 44 | /* Check access */ |
@@ -105,25 +99,23 @@ static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka, | |||
105 | } | 99 | } |
106 | } | 100 | } |
107 | 101 | ||
108 | static int do_signal(struct pt_regs *regs) | 102 | static void do_signal(struct pt_regs *regs) |
109 | { | 103 | { |
110 | sigset_t *oldset = sigmask_to_save(); | 104 | sigset_t *oldset = sigmask_to_save(); |
111 | siginfo_t info; | 105 | struct ksignal ksig; |
112 | int signr; | ||
113 | struct k_sigaction ka; | ||
114 | int ret; | 106 | int ret; |
115 | int is32 = is_32bit_task(); | 107 | int is32 = is_32bit_task(); |
116 | 108 | ||
117 | signr = get_signal_to_deliver(&info, &ka, regs, NULL); | 109 | get_signal(&ksig); |
118 | 110 | ||
119 | /* Is there any syscall restart business here ? */ | 111 | /* Is there any syscall restart business here ? */ |
120 | check_syscall_restart(regs, &ka, signr > 0); | 112 | check_syscall_restart(regs, &ksig.ka, ksig.sig > 0); |
121 | 113 | ||
122 | if (signr <= 0) { | 114 | if (ksig.sig <= 0) { |
123 | /* No signal to deliver -- put the saved sigmask back */ | 115 | /* No signal to deliver -- put the saved sigmask back */ |
124 | restore_saved_sigmask(); | 116 | restore_saved_sigmask(); |
125 | regs->trap = 0; | 117 | regs->trap = 0; |
126 | return 0; /* no signals delivered */ | 118 | return; /* no signals delivered */ |
127 | } | 119 | } |
128 | 120 | ||
129 | #ifndef CONFIG_PPC_ADV_DEBUG_REGS | 121 | #ifndef CONFIG_PPC_ADV_DEBUG_REGS |
@@ -140,23 +132,16 @@ static int do_signal(struct pt_regs *regs) | |||
140 | thread_change_pc(current, regs); | 132 | thread_change_pc(current, regs); |
141 | 133 | ||
142 | if (is32) { | 134 | if (is32) { |
143 | if (ka.sa.sa_flags & SA_SIGINFO) | 135 | if (ksig.ka.sa.sa_flags & SA_SIGINFO) |
144 | ret = handle_rt_signal32(signr, &ka, &info, oldset, | 136 | ret = handle_rt_signal32(&ksig, oldset, regs); |
145 | regs); | ||
146 | else | 137 | else |
147 | ret = handle_signal32(signr, &ka, &info, oldset, | 138 | ret = handle_signal32(&ksig, oldset, regs); |
148 | regs); | ||
149 | } else { | 139 | } else { |
150 | ret = handle_rt_signal64(signr, &ka, &info, oldset, regs); | 140 | ret = handle_rt_signal64(&ksig, oldset, regs); |
151 | } | 141 | } |
152 | 142 | ||
153 | regs->trap = 0; | 143 | regs->trap = 0; |
154 | if (ret) { | 144 | signal_setup_done(ret, &ksig, test_thread_flag(TIF_SINGLESTEP)); |
155 | signal_delivered(signr, &info, &ka, regs, | ||
156 | test_thread_flag(TIF_SINGLESTEP)); | ||
157 | } | ||
158 | |||
159 | return ret; | ||
160 | } | 145 | } |
161 | 146 | ||
162 | void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) | 147 | void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) |
diff --git a/arch/powerpc/kernel/signal.h b/arch/powerpc/kernel/signal.h index c69b9aeb9f23..51b274199dd9 100644 --- a/arch/powerpc/kernel/signal.h +++ b/arch/powerpc/kernel/signal.h | |||
@@ -12,15 +12,13 @@ | |||
12 | 12 | ||
13 | extern void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags); | 13 | extern void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags); |
14 | 14 | ||
15 | extern void __user * get_sigframe(struct k_sigaction *ka, unsigned long sp, | 15 | extern void __user *get_sigframe(struct ksignal *ksig, unsigned long sp, |
16 | size_t frame_size, int is_32); | 16 | size_t frame_size, int is_32); |
17 | 17 | ||
18 | extern int handle_signal32(unsigned long sig, struct k_sigaction *ka, | 18 | extern int handle_signal32(struct ksignal *ksig, sigset_t *oldset, |
19 | siginfo_t *info, sigset_t *oldset, | ||
20 | struct pt_regs *regs); | 19 | struct pt_regs *regs); |
21 | 20 | ||
22 | extern int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, | 21 | extern int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset, |
23 | siginfo_t *info, sigset_t *oldset, | ||
24 | struct pt_regs *regs); | 22 | struct pt_regs *regs); |
25 | 23 | ||
26 | extern unsigned long copy_fpr_to_user(void __user *to, | 24 | extern unsigned long copy_fpr_to_user(void __user *to, |
@@ -44,14 +42,12 @@ extern unsigned long copy_transact_vsx_from_user(struct task_struct *task, | |||
44 | 42 | ||
45 | #ifdef CONFIG_PPC64 | 43 | #ifdef CONFIG_PPC64 |
46 | 44 | ||
47 | extern int handle_rt_signal64(int signr, struct k_sigaction *ka, | 45 | extern int handle_rt_signal64(struct ksignal *ksig, sigset_t *set, |
48 | siginfo_t *info, sigset_t *set, | ||
49 | struct pt_regs *regs); | 46 | struct pt_regs *regs); |
50 | 47 | ||
51 | #else /* CONFIG_PPC64 */ | 48 | #else /* CONFIG_PPC64 */ |
52 | 49 | ||
53 | static inline int handle_rt_signal64(int signr, struct k_sigaction *ka, | 50 | static inline int handle_rt_signal64(struct ksignal *ksig, sigset_t *set, |
54 | siginfo_t *info, sigset_t *set, | ||
55 | struct pt_regs *regs) | 51 | struct pt_regs *regs) |
56 | { | 52 | { |
57 | return -EFAULT; | 53 | return -EFAULT; |
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 1bc5a1755ed4..b171001698ff 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c | |||
@@ -981,9 +981,8 @@ int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from) | |||
981 | * Set up a signal frame for a "real-time" signal handler | 981 | * Set up a signal frame for a "real-time" signal handler |
982 | * (one which gets siginfo). | 982 | * (one which gets siginfo). |
983 | */ | 983 | */ |
984 | int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, | 984 | int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset, |
985 | siginfo_t *info, sigset_t *oldset, | 985 | struct pt_regs *regs) |
986 | struct pt_regs *regs) | ||
987 | { | 986 | { |
988 | struct rt_sigframe __user *rt_sf; | 987 | struct rt_sigframe __user *rt_sf; |
989 | struct mcontext __user *frame; | 988 | struct mcontext __user *frame; |
@@ -995,13 +994,13 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, | |||
995 | 994 | ||
996 | /* Set up Signal Frame */ | 995 | /* Set up Signal Frame */ |
997 | /* Put a Real Time Context onto stack */ | 996 | /* Put a Real Time Context onto stack */ |
998 | rt_sf = get_sigframe(ka, get_tm_stackpointer(regs), sizeof(*rt_sf), 1); | 997 | rt_sf = get_sigframe(ksig, get_tm_stackpointer(regs), sizeof(*rt_sf), 1); |
999 | addr = rt_sf; | 998 | addr = rt_sf; |
1000 | if (unlikely(rt_sf == NULL)) | 999 | if (unlikely(rt_sf == NULL)) |
1001 | goto badframe; | 1000 | goto badframe; |
1002 | 1001 | ||
1003 | /* Put the siginfo & fill in most of the ucontext */ | 1002 | /* Put the siginfo & fill in most of the ucontext */ |
1004 | if (copy_siginfo_to_user(&rt_sf->info, info) | 1003 | if (copy_siginfo_to_user(&rt_sf->info, &ksig->info) |
1005 | || __put_user(0, &rt_sf->uc.uc_flags) | 1004 | || __put_user(0, &rt_sf->uc.uc_flags) |
1006 | || __save_altstack(&rt_sf->uc.uc_stack, regs->gpr[1]) | 1005 | || __save_altstack(&rt_sf->uc.uc_stack, regs->gpr[1]) |
1007 | || __put_user(to_user_ptr(&rt_sf->uc.uc_mcontext), | 1006 | || __put_user(to_user_ptr(&rt_sf->uc.uc_mcontext), |
@@ -1051,15 +1050,15 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, | |||
1051 | 1050 | ||
1052 | /* Fill registers for signal handler */ | 1051 | /* Fill registers for signal handler */ |
1053 | regs->gpr[1] = newsp; | 1052 | regs->gpr[1] = newsp; |
1054 | regs->gpr[3] = sig; | 1053 | regs->gpr[3] = ksig->sig; |
1055 | regs->gpr[4] = (unsigned long) &rt_sf->info; | 1054 | regs->gpr[4] = (unsigned long) &rt_sf->info; |
1056 | regs->gpr[5] = (unsigned long) &rt_sf->uc; | 1055 | regs->gpr[5] = (unsigned long) &rt_sf->uc; |
1057 | regs->gpr[6] = (unsigned long) rt_sf; | 1056 | regs->gpr[6] = (unsigned long) rt_sf; |
1058 | regs->nip = (unsigned long) ka->sa.sa_handler; | 1057 | regs->nip = (unsigned long) ksig->ka.sa.sa_handler; |
1059 | /* enter the signal handler in native-endian mode */ | 1058 | /* enter the signal handler in native-endian mode */ |
1060 | regs->msr &= ~MSR_LE; | 1059 | regs->msr &= ~MSR_LE; |
1061 | regs->msr |= (MSR_KERNEL & MSR_LE); | 1060 | regs->msr |= (MSR_KERNEL & MSR_LE); |
1062 | return 1; | 1061 | return 0; |
1063 | 1062 | ||
1064 | badframe: | 1063 | badframe: |
1065 | if (show_unhandled_signals) | 1064 | if (show_unhandled_signals) |
@@ -1069,8 +1068,7 @@ badframe: | |||
1069 | current->comm, current->pid, | 1068 | current->comm, current->pid, |
1070 | addr, regs->nip, regs->link); | 1069 | addr, regs->nip, regs->link); |
1071 | 1070 | ||
1072 | force_sigsegv(sig, current); | 1071 | return 1; |
1073 | return 0; | ||
1074 | } | 1072 | } |
1075 | 1073 | ||
1076 | static int do_setcontext(struct ucontext __user *ucp, struct pt_regs *regs, int sig) | 1074 | static int do_setcontext(struct ucontext __user *ucp, struct pt_regs *regs, int sig) |
@@ -1409,8 +1407,7 @@ int sys_debug_setcontext(struct ucontext __user *ctx, | |||
1409 | /* | 1407 | /* |
1410 | * OK, we're invoking a handler | 1408 | * OK, we're invoking a handler |
1411 | */ | 1409 | */ |
1412 | int handle_signal32(unsigned long sig, struct k_sigaction *ka, | 1410 | int handle_signal32(struct ksignal *ksig, sigset_t *oldset, struct pt_regs *regs) |
1413 | siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) | ||
1414 | { | 1411 | { |
1415 | struct sigcontext __user *sc; | 1412 | struct sigcontext __user *sc; |
1416 | struct sigframe __user *frame; | 1413 | struct sigframe __user *frame; |
@@ -1420,7 +1417,7 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka, | |||
1420 | unsigned long tramp; | 1417 | unsigned long tramp; |
1421 | 1418 | ||
1422 | /* Set up Signal Frame */ | 1419 | /* Set up Signal Frame */ |
1423 | frame = get_sigframe(ka, get_tm_stackpointer(regs), sizeof(*frame), 1); | 1420 | frame = get_sigframe(ksig, get_tm_stackpointer(regs), sizeof(*frame), 1); |
1424 | if (unlikely(frame == NULL)) | 1421 | if (unlikely(frame == NULL)) |
1425 | goto badframe; | 1422 | goto badframe; |
1426 | sc = (struct sigcontext __user *) &frame->sctx; | 1423 | sc = (struct sigcontext __user *) &frame->sctx; |
@@ -1428,7 +1425,7 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka, | |||
1428 | #if _NSIG != 64 | 1425 | #if _NSIG != 64 |
1429 | #error "Please adjust handle_signal()" | 1426 | #error "Please adjust handle_signal()" |
1430 | #endif | 1427 | #endif |
1431 | if (__put_user(to_user_ptr(ka->sa.sa_handler), &sc->handler) | 1428 | if (__put_user(to_user_ptr(ksig->ka.sa.sa_handler), &sc->handler) |
1432 | || __put_user(oldset->sig[0], &sc->oldmask) | 1429 | || __put_user(oldset->sig[0], &sc->oldmask) |
1433 | #ifdef CONFIG_PPC64 | 1430 | #ifdef CONFIG_PPC64 |
1434 | || __put_user((oldset->sig[0] >> 32), &sc->_unused[3]) | 1431 | || __put_user((oldset->sig[0] >> 32), &sc->_unused[3]) |
@@ -1436,7 +1433,7 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka, | |||
1436 | || __put_user(oldset->sig[1], &sc->_unused[3]) | 1433 | || __put_user(oldset->sig[1], &sc->_unused[3]) |
1437 | #endif | 1434 | #endif |
1438 | || __put_user(to_user_ptr(&frame->mctx), &sc->regs) | 1435 | || __put_user(to_user_ptr(&frame->mctx), &sc->regs) |
1439 | || __put_user(sig, &sc->signal)) | 1436 | || __put_user(ksig->sig, &sc->signal)) |
1440 | goto badframe; | 1437 | goto badframe; |
1441 | 1438 | ||
1442 | if (vdso32_sigtramp && current->mm->context.vdso_base) { | 1439 | if (vdso32_sigtramp && current->mm->context.vdso_base) { |
@@ -1471,12 +1468,12 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka, | |||
1471 | goto badframe; | 1468 | goto badframe; |
1472 | 1469 | ||
1473 | regs->gpr[1] = newsp; | 1470 | regs->gpr[1] = newsp; |
1474 | regs->gpr[3] = sig; | 1471 | regs->gpr[3] = ksig->sig; |
1475 | regs->gpr[4] = (unsigned long) sc; | 1472 | regs->gpr[4] = (unsigned long) sc; |
1476 | regs->nip = (unsigned long) ka->sa.sa_handler; | 1473 | regs->nip = (unsigned long) (unsigned long)ksig->ka.sa.sa_handler; |
1477 | /* enter the signal handler in big-endian mode */ | 1474 | /* enter the signal handler in big-endian mode */ |
1478 | regs->msr &= ~MSR_LE; | 1475 | regs->msr &= ~MSR_LE; |
1479 | return 1; | 1476 | return 0; |
1480 | 1477 | ||
1481 | badframe: | 1478 | badframe: |
1482 | if (show_unhandled_signals) | 1479 | if (show_unhandled_signals) |
@@ -1486,8 +1483,7 @@ badframe: | |||
1486 | current->comm, current->pid, | 1483 | current->comm, current->pid, |
1487 | frame, regs->nip, regs->link); | 1484 | frame, regs->nip, regs->link); |
1488 | 1485 | ||
1489 | force_sigsegv(sig, current); | 1486 | return 1; |
1490 | return 0; | ||
1491 | } | 1487 | } |
1492 | 1488 | ||
1493 | /* | 1489 | /* |
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index 97c1e4b683fc..2cb0c94cafa5 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c | |||
@@ -708,20 +708,19 @@ badframe: | |||
708 | return 0; | 708 | return 0; |
709 | } | 709 | } |
710 | 710 | ||
711 | int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info, | 711 | int handle_rt_signal64(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs) |
712 | sigset_t *set, struct pt_regs *regs) | ||
713 | { | 712 | { |
714 | struct rt_sigframe __user *frame; | 713 | struct rt_sigframe __user *frame; |
715 | unsigned long newsp = 0; | 714 | unsigned long newsp = 0; |
716 | long err = 0; | 715 | long err = 0; |
717 | 716 | ||
718 | frame = get_sigframe(ka, get_tm_stackpointer(regs), sizeof(*frame), 0); | 717 | frame = get_sigframe(ksig, get_tm_stackpointer(regs), sizeof(*frame), 0); |
719 | if (unlikely(frame == NULL)) | 718 | if (unlikely(frame == NULL)) |
720 | goto badframe; | 719 | goto badframe; |
721 | 720 | ||
722 | err |= __put_user(&frame->info, &frame->pinfo); | 721 | err |= __put_user(&frame->info, &frame->pinfo); |
723 | err |= __put_user(&frame->uc, &frame->puc); | 722 | err |= __put_user(&frame->uc, &frame->puc); |
724 | err |= copy_siginfo_to_user(&frame->info, info); | 723 | err |= copy_siginfo_to_user(&frame->info, &ksig->info); |
725 | if (err) | 724 | if (err) |
726 | goto badframe; | 725 | goto badframe; |
727 | 726 | ||
@@ -736,15 +735,15 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info, | |||
736 | err |= __put_user(&frame->uc_transact, &frame->uc.uc_link); | 735 | err |= __put_user(&frame->uc_transact, &frame->uc.uc_link); |
737 | err |= setup_tm_sigcontexts(&frame->uc.uc_mcontext, | 736 | err |= setup_tm_sigcontexts(&frame->uc.uc_mcontext, |
738 | &frame->uc_transact.uc_mcontext, | 737 | &frame->uc_transact.uc_mcontext, |
739 | regs, signr, | 738 | regs, ksig->sig, |
740 | NULL, | 739 | NULL, |
741 | (unsigned long)ka->sa.sa_handler); | 740 | (unsigned long)ksig->ka.sa.sa_handler); |
742 | } else | 741 | } else |
743 | #endif | 742 | #endif |
744 | { | 743 | { |
745 | err |= __put_user(0, &frame->uc.uc_link); | 744 | err |= __put_user(0, &frame->uc.uc_link); |
746 | err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, signr, | 745 | err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, ksig->sig, |
747 | NULL, (unsigned long)ka->sa.sa_handler, | 746 | NULL, (unsigned long)ksig->ka.sa.sa_handler, |
748 | 1); | 747 | 1); |
749 | } | 748 | } |
750 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); | 749 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); |
@@ -770,7 +769,7 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info, | |||
770 | 769 | ||
771 | /* Set up "regs" so we "return" to the signal handler. */ | 770 | /* Set up "regs" so we "return" to the signal handler. */ |
772 | if (is_elf2_task()) { | 771 | if (is_elf2_task()) { |
773 | regs->nip = (unsigned long) ka->sa.sa_handler; | 772 | regs->nip = (unsigned long) ksig->ka.sa.sa_handler; |
774 | regs->gpr[12] = regs->nip; | 773 | regs->gpr[12] = regs->nip; |
775 | } else { | 774 | } else { |
776 | /* Handler is *really* a pointer to the function descriptor for | 775 | /* Handler is *really* a pointer to the function descriptor for |
@@ -779,7 +778,7 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info, | |||
779 | * entry is the TOC value we need to use. | 778 | * entry is the TOC value we need to use. |
780 | */ | 779 | */ |
781 | func_descr_t __user *funct_desc_ptr = | 780 | func_descr_t __user *funct_desc_ptr = |
782 | (func_descr_t __user *) ka->sa.sa_handler; | 781 | (func_descr_t __user *) ksig->ka.sa.sa_handler; |
783 | 782 | ||
784 | err |= get_user(regs->nip, &funct_desc_ptr->entry); | 783 | err |= get_user(regs->nip, &funct_desc_ptr->entry); |
785 | err |= get_user(regs->gpr[2], &funct_desc_ptr->toc); | 784 | err |= get_user(regs->gpr[2], &funct_desc_ptr->toc); |
@@ -789,9 +788,9 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info, | |||
789 | regs->msr &= ~MSR_LE; | 788 | regs->msr &= ~MSR_LE; |
790 | regs->msr |= (MSR_KERNEL & MSR_LE); | 789 | regs->msr |= (MSR_KERNEL & MSR_LE); |
791 | regs->gpr[1] = newsp; | 790 | regs->gpr[1] = newsp; |
792 | regs->gpr[3] = signr; | 791 | regs->gpr[3] = ksig->sig; |
793 | regs->result = 0; | 792 | regs->result = 0; |
794 | if (ka->sa.sa_flags & SA_SIGINFO) { | 793 | if (ksig->ka.sa.sa_flags & SA_SIGINFO) { |
795 | err |= get_user(regs->gpr[4], (unsigned long __user *)&frame->pinfo); | 794 | err |= get_user(regs->gpr[4], (unsigned long __user *)&frame->pinfo); |
796 | err |= get_user(regs->gpr[5], (unsigned long __user *)&frame->puc); | 795 | err |= get_user(regs->gpr[5], (unsigned long __user *)&frame->puc); |
797 | regs->gpr[6] = (unsigned long) frame; | 796 | regs->gpr[6] = (unsigned long) frame; |
@@ -801,7 +800,7 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info, | |||
801 | if (err) | 800 | if (err) |
802 | goto badframe; | 801 | goto badframe; |
803 | 802 | ||
804 | return 1; | 803 | return 0; |
805 | 804 | ||
806 | badframe: | 805 | badframe: |
807 | if (show_unhandled_signals) | 806 | if (show_unhandled_signals) |
@@ -809,6 +808,5 @@ badframe: | |||
809 | current->comm, current->pid, "setup_rt_frame", | 808 | current->comm, current->pid, "setup_rt_frame", |
810 | (long)frame, regs->nip, regs->link); | 809 | (long)frame, regs->nip, regs->link); |
811 | 810 | ||
812 | force_sigsegv(signr, current); | 811 | return 1; |
813 | return 0; | ||
814 | } | 812 | } |
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 1007fb802e6b..a0738af4aba6 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c | |||
@@ -376,6 +376,11 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
376 | GFP_KERNEL, cpu_to_node(cpu)); | 376 | GFP_KERNEL, cpu_to_node(cpu)); |
377 | zalloc_cpumask_var_node(&per_cpu(cpu_core_map, cpu), | 377 | zalloc_cpumask_var_node(&per_cpu(cpu_core_map, cpu), |
378 | GFP_KERNEL, cpu_to_node(cpu)); | 378 | GFP_KERNEL, cpu_to_node(cpu)); |
379 | /* | ||
380 | * numa_node_id() works after this. | ||
381 | */ | ||
382 | set_cpu_numa_node(cpu, numa_cpu_lookup_table[cpu]); | ||
383 | set_cpu_numa_mem(cpu, local_memory_node(numa_cpu_lookup_table[cpu])); | ||
379 | } | 384 | } |
380 | 385 | ||
381 | cpumask_set_cpu(boot_cpuid, cpu_sibling_mask(boot_cpuid)); | 386 | cpumask_set_cpu(boot_cpuid, cpu_sibling_mask(boot_cpuid)); |
@@ -723,12 +728,6 @@ void start_secondary(void *unused) | |||
723 | } | 728 | } |
724 | traverse_core_siblings(cpu, true); | 729 | traverse_core_siblings(cpu, true); |
725 | 730 | ||
726 | /* | ||
727 | * numa_node_id() works after this. | ||
728 | */ | ||
729 | set_numa_node(numa_cpu_lookup_table[cpu]); | ||
730 | set_numa_mem(local_memory_node(numa_cpu_lookup_table[cpu])); | ||
731 | |||
732 | smp_wmb(); | 731 | smp_wmb(); |
733 | notify_cpu_starting(cpu); | 732 | notify_cpu_starting(cpu); |
734 | set_cpu_online(cpu, true); | 733 | set_cpu_online(cpu, true); |
diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S index 895c50ca943c..7ab5d434e2ee 100644 --- a/arch/powerpc/kernel/systbl.S +++ b/arch/powerpc/kernel/systbl.S | |||
@@ -39,9 +39,6 @@ | |||
39 | .section .rodata,"a" | 39 | .section .rodata,"a" |
40 | 40 | ||
41 | #ifdef CONFIG_PPC64 | 41 | #ifdef CONFIG_PPC64 |
42 | #define sys_sigpending sys_ni_syscall | ||
43 | #define sys_old_getrlimit sys_ni_syscall | ||
44 | |||
45 | .p2align 3 | 42 | .p2align 3 |
46 | #endif | 43 | #endif |
47 | 44 | ||
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 239f1cde3fff..0dc43f9932cf 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
@@ -302,6 +302,16 @@ long machine_check_early(struct pt_regs *regs) | |||
302 | return handled; | 302 | return handled; |
303 | } | 303 | } |
304 | 304 | ||
305 | long hmi_exception_realmode(struct pt_regs *regs) | ||
306 | { | ||
307 | __get_cpu_var(irq_stat).hmi_exceptions++; | ||
308 | |||
309 | if (ppc_md.hmi_exception_early) | ||
310 | ppc_md.hmi_exception_early(regs); | ||
311 | |||
312 | return 0; | ||
313 | } | ||
314 | |||
305 | #endif | 315 | #endif |
306 | 316 | ||
307 | /* | 317 | /* |
@@ -609,7 +619,7 @@ int machine_check_e500(struct pt_regs *regs) | |||
609 | if (reason & MCSR_BUS_RBERR) | 619 | if (reason & MCSR_BUS_RBERR) |
610 | printk("Bus - Read Data Bus Error\n"); | 620 | printk("Bus - Read Data Bus Error\n"); |
611 | if (reason & MCSR_BUS_WBERR) | 621 | if (reason & MCSR_BUS_WBERR) |
612 | printk("Bus - Read Data Bus Error\n"); | 622 | printk("Bus - Write Data Bus Error\n"); |
613 | if (reason & MCSR_BUS_IPERR) | 623 | if (reason & MCSR_BUS_IPERR) |
614 | printk("Bus - Instruction Parity Error\n"); | 624 | printk("Bus - Instruction Parity Error\n"); |
615 | if (reason & MCSR_BUS_RPERR) | 625 | if (reason & MCSR_BUS_RPERR) |
@@ -738,6 +748,20 @@ void SMIException(struct pt_regs *regs) | |||
738 | die("System Management Interrupt", regs, SIGABRT); | 748 | die("System Management Interrupt", regs, SIGABRT); |
739 | } | 749 | } |
740 | 750 | ||
751 | void handle_hmi_exception(struct pt_regs *regs) | ||
752 | { | ||
753 | struct pt_regs *old_regs; | ||
754 | |||
755 | old_regs = set_irq_regs(regs); | ||
756 | irq_enter(); | ||
757 | |||
758 | if (ppc_md.handle_hmi_exception) | ||
759 | ppc_md.handle_hmi_exception(regs); | ||
760 | |||
761 | irq_exit(); | ||
762 | set_irq_regs(old_regs); | ||
763 | } | ||
764 | |||
741 | void unknown_exception(struct pt_regs *regs) | 765 | void unknown_exception(struct pt_regs *regs) |
742 | { | 766 | { |
743 | enum ctx_state prev_state = exception_enter(); | 767 | enum ctx_state prev_state = exception_enter(); |
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index ce74c335a6a4..f174351842cf 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c | |||
@@ -840,19 +840,3 @@ static int __init vdso_init(void) | |||
840 | return 0; | 840 | return 0; |
841 | } | 841 | } |
842 | arch_initcall(vdso_init); | 842 | arch_initcall(vdso_init); |
843 | |||
844 | int in_gate_area_no_mm(unsigned long addr) | ||
845 | { | ||
846 | return 0; | ||
847 | } | ||
848 | |||
849 | int in_gate_area(struct mm_struct *mm, unsigned long addr) | ||
850 | { | ||
851 | return 0; | ||
852 | } | ||
853 | |||
854 | struct vm_area_struct *get_gate_vma(struct mm_struct *mm) | ||
855 | { | ||
856 | return NULL; | ||
857 | } | ||
858 | |||
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index 904c66128fae..5bfdab9047be 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c | |||
@@ -977,7 +977,7 @@ static ssize_t viodev_cmo_desired_set(struct device *dev, | |||
977 | size_t new_desired; | 977 | size_t new_desired; |
978 | int ret; | 978 | int ret; |
979 | 979 | ||
980 | ret = strict_strtoul(buf, 10, &new_desired); | 980 | ret = kstrtoul(buf, 10, &new_desired); |
981 | if (ret) | 981 | if (ret) |
982 | return ret; | 982 | return ret; |
983 | 983 | ||
diff --git a/arch/powerpc/kvm/44x.c b/arch/powerpc/kvm/44x.c deleted file mode 100644 index 9cb4b0a36031..000000000000 --- a/arch/powerpc/kvm/44x.c +++ /dev/null | |||
@@ -1,237 +0,0 @@ | |||
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 IBM Corp. 2008 | ||
16 | * | ||
17 | * Authors: Hollis Blanchard <hollisb@us.ibm.com> | ||
18 | */ | ||
19 | |||
20 | #include <linux/kvm_host.h> | ||
21 | #include <linux/slab.h> | ||
22 | #include <linux/err.h> | ||
23 | #include <linux/export.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <linux/miscdevice.h> | ||
26 | |||
27 | #include <asm/reg.h> | ||
28 | #include <asm/cputable.h> | ||
29 | #include <asm/tlbflush.h> | ||
30 | #include <asm/kvm_44x.h> | ||
31 | #include <asm/kvm_ppc.h> | ||
32 | |||
33 | #include "44x_tlb.h" | ||
34 | #include "booke.h" | ||
35 | |||
36 | static void kvmppc_core_vcpu_load_44x(struct kvm_vcpu *vcpu, int cpu) | ||
37 | { | ||
38 | kvmppc_booke_vcpu_load(vcpu, cpu); | ||
39 | kvmppc_44x_tlb_load(vcpu); | ||
40 | } | ||
41 | |||
42 | static void kvmppc_core_vcpu_put_44x(struct kvm_vcpu *vcpu) | ||
43 | { | ||
44 | kvmppc_44x_tlb_put(vcpu); | ||
45 | kvmppc_booke_vcpu_put(vcpu); | ||
46 | } | ||
47 | |||
48 | int kvmppc_core_check_processor_compat(void) | ||
49 | { | ||
50 | int r; | ||
51 | |||
52 | if (strncmp(cur_cpu_spec->platform, "ppc440", 6) == 0) | ||
53 | r = 0; | ||
54 | else | ||
55 | r = -ENOTSUPP; | ||
56 | |||
57 | return r; | ||
58 | } | ||
59 | |||
60 | int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu) | ||
61 | { | ||
62 | struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); | ||
63 | struct kvmppc_44x_tlbe *tlbe = &vcpu_44x->guest_tlb[0]; | ||
64 | int i; | ||
65 | |||
66 | tlbe->tid = 0; | ||
67 | tlbe->word0 = PPC44x_TLB_16M | PPC44x_TLB_VALID; | ||
68 | tlbe->word1 = 0; | ||
69 | tlbe->word2 = PPC44x_TLB_SX | PPC44x_TLB_SW | PPC44x_TLB_SR; | ||
70 | |||
71 | tlbe++; | ||
72 | tlbe->tid = 0; | ||
73 | tlbe->word0 = 0xef600000 | PPC44x_TLB_4K | PPC44x_TLB_VALID; | ||
74 | tlbe->word1 = 0xef600000; | ||
75 | tlbe->word2 = PPC44x_TLB_SX | PPC44x_TLB_SW | PPC44x_TLB_SR | ||
76 | | PPC44x_TLB_I | PPC44x_TLB_G; | ||
77 | |||
78 | /* Since the guest can directly access the timebase, it must know the | ||
79 | * real timebase frequency. Accordingly, it must see the state of | ||
80 | * CCR1[TCS]. */ | ||
81 | /* XXX CCR1 doesn't exist on all 440 SoCs. */ | ||
82 | vcpu->arch.ccr1 = mfspr(SPRN_CCR1); | ||
83 | |||
84 | for (i = 0; i < ARRAY_SIZE(vcpu_44x->shadow_refs); i++) | ||
85 | vcpu_44x->shadow_refs[i].gtlb_index = -1; | ||
86 | |||
87 | vcpu->arch.cpu_type = KVM_CPU_440; | ||
88 | vcpu->arch.pvr = mfspr(SPRN_PVR); | ||
89 | |||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | /* 'linear_address' is actually an encoding of AS|PID|EADDR . */ | ||
94 | int kvmppc_core_vcpu_translate(struct kvm_vcpu *vcpu, | ||
95 | struct kvm_translation *tr) | ||
96 | { | ||
97 | int index; | ||
98 | gva_t eaddr; | ||
99 | u8 pid; | ||
100 | u8 as; | ||
101 | |||
102 | eaddr = tr->linear_address; | ||
103 | pid = (tr->linear_address >> 32) & 0xff; | ||
104 | as = (tr->linear_address >> 40) & 0x1; | ||
105 | |||
106 | index = kvmppc_44x_tlb_index(vcpu, eaddr, pid, as); | ||
107 | if (index == -1) { | ||
108 | tr->valid = 0; | ||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | tr->physical_address = kvmppc_mmu_xlate(vcpu, index, eaddr); | ||
113 | /* XXX what does "writeable" and "usermode" even mean? */ | ||
114 | tr->valid = 1; | ||
115 | |||
116 | return 0; | ||
117 | } | ||
118 | |||
119 | static int kvmppc_core_get_sregs_44x(struct kvm_vcpu *vcpu, | ||
120 | struct kvm_sregs *sregs) | ||
121 | { | ||
122 | return kvmppc_get_sregs_ivor(vcpu, sregs); | ||
123 | } | ||
124 | |||
125 | static int kvmppc_core_set_sregs_44x(struct kvm_vcpu *vcpu, | ||
126 | struct kvm_sregs *sregs) | ||
127 | { | ||
128 | return kvmppc_set_sregs_ivor(vcpu, sregs); | ||
129 | } | ||
130 | |||
131 | static int kvmppc_get_one_reg_44x(struct kvm_vcpu *vcpu, u64 id, | ||
132 | union kvmppc_one_reg *val) | ||
133 | { | ||
134 | return -EINVAL; | ||
135 | } | ||
136 | |||
137 | static int kvmppc_set_one_reg_44x(struct kvm_vcpu *vcpu, u64 id, | ||
138 | union kvmppc_one_reg *val) | ||
139 | { | ||
140 | return -EINVAL; | ||
141 | } | ||
142 | |||
143 | static struct kvm_vcpu *kvmppc_core_vcpu_create_44x(struct kvm *kvm, | ||
144 | unsigned int id) | ||
145 | { | ||
146 | struct kvmppc_vcpu_44x *vcpu_44x; | ||
147 | struct kvm_vcpu *vcpu; | ||
148 | int err; | ||
149 | |||
150 | vcpu_44x = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL); | ||
151 | if (!vcpu_44x) { | ||
152 | err = -ENOMEM; | ||
153 | goto out; | ||
154 | } | ||
155 | |||
156 | vcpu = &vcpu_44x->vcpu; | ||
157 | err = kvm_vcpu_init(vcpu, kvm, id); | ||
158 | if (err) | ||
159 | goto free_vcpu; | ||
160 | |||
161 | vcpu->arch.shared = (void*)__get_free_page(GFP_KERNEL|__GFP_ZERO); | ||
162 | if (!vcpu->arch.shared) | ||
163 | goto uninit_vcpu; | ||
164 | |||
165 | return vcpu; | ||
166 | |||
167 | uninit_vcpu: | ||
168 | kvm_vcpu_uninit(vcpu); | ||
169 | free_vcpu: | ||
170 | kmem_cache_free(kvm_vcpu_cache, vcpu_44x); | ||
171 | out: | ||
172 | return ERR_PTR(err); | ||
173 | } | ||
174 | |||
175 | static void kvmppc_core_vcpu_free_44x(struct kvm_vcpu *vcpu) | ||
176 | { | ||
177 | struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); | ||
178 | |||
179 | free_page((unsigned long)vcpu->arch.shared); | ||
180 | kvm_vcpu_uninit(vcpu); | ||
181 | kmem_cache_free(kvm_vcpu_cache, vcpu_44x); | ||
182 | } | ||
183 | |||
184 | static int kvmppc_core_init_vm_44x(struct kvm *kvm) | ||
185 | { | ||
186 | return 0; | ||
187 | } | ||
188 | |||
189 | static void kvmppc_core_destroy_vm_44x(struct kvm *kvm) | ||
190 | { | ||
191 | } | ||
192 | |||
193 | static struct kvmppc_ops kvm_ops_44x = { | ||
194 | .get_sregs = kvmppc_core_get_sregs_44x, | ||
195 | .set_sregs = kvmppc_core_set_sregs_44x, | ||
196 | .get_one_reg = kvmppc_get_one_reg_44x, | ||
197 | .set_one_reg = kvmppc_set_one_reg_44x, | ||
198 | .vcpu_load = kvmppc_core_vcpu_load_44x, | ||
199 | .vcpu_put = kvmppc_core_vcpu_put_44x, | ||
200 | .vcpu_create = kvmppc_core_vcpu_create_44x, | ||
201 | .vcpu_free = kvmppc_core_vcpu_free_44x, | ||
202 | .mmu_destroy = kvmppc_mmu_destroy_44x, | ||
203 | .init_vm = kvmppc_core_init_vm_44x, | ||
204 | .destroy_vm = kvmppc_core_destroy_vm_44x, | ||
205 | .emulate_op = kvmppc_core_emulate_op_44x, | ||
206 | .emulate_mtspr = kvmppc_core_emulate_mtspr_44x, | ||
207 | .emulate_mfspr = kvmppc_core_emulate_mfspr_44x, | ||
208 | }; | ||
209 | |||
210 | static int __init kvmppc_44x_init(void) | ||
211 | { | ||
212 | int r; | ||
213 | |||
214 | r = kvmppc_booke_init(); | ||
215 | if (r) | ||
216 | goto err_out; | ||
217 | |||
218 | r = kvm_init(NULL, sizeof(struct kvmppc_vcpu_44x), 0, THIS_MODULE); | ||
219 | if (r) | ||
220 | goto err_out; | ||
221 | kvm_ops_44x.owner = THIS_MODULE; | ||
222 | kvmppc_pr_ops = &kvm_ops_44x; | ||
223 | |||
224 | err_out: | ||
225 | return r; | ||
226 | } | ||
227 | |||
228 | static void __exit kvmppc_44x_exit(void) | ||
229 | { | ||
230 | kvmppc_pr_ops = NULL; | ||
231 | kvmppc_booke_exit(); | ||
232 | } | ||
233 | |||
234 | module_init(kvmppc_44x_init); | ||
235 | module_exit(kvmppc_44x_exit); | ||
236 | MODULE_ALIAS_MISCDEV(KVM_MINOR); | ||
237 | MODULE_ALIAS("devname:kvm"); | ||
diff --git a/arch/powerpc/kvm/44x_emulate.c b/arch/powerpc/kvm/44x_emulate.c deleted file mode 100644 index 92c9ab4bcfec..000000000000 --- a/arch/powerpc/kvm/44x_emulate.c +++ /dev/null | |||
@@ -1,194 +0,0 @@ | |||
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 IBM Corp. 2008 | ||
16 | * | ||
17 | * Authors: Hollis Blanchard <hollisb@us.ibm.com> | ||
18 | */ | ||
19 | |||
20 | #include <asm/kvm_ppc.h> | ||
21 | #include <asm/dcr.h> | ||
22 | #include <asm/dcr-regs.h> | ||
23 | #include <asm/disassemble.h> | ||
24 | #include <asm/kvm_44x.h> | ||
25 | #include "timing.h" | ||
26 | |||
27 | #include "booke.h" | ||
28 | #include "44x_tlb.h" | ||
29 | |||
30 | #define XOP_MFDCRX 259 | ||
31 | #define XOP_MFDCR 323 | ||
32 | #define XOP_MTDCRX 387 | ||
33 | #define XOP_MTDCR 451 | ||
34 | #define XOP_TLBSX 914 | ||
35 | #define XOP_ICCCI 966 | ||
36 | #define XOP_TLBWE 978 | ||
37 | |||
38 | static int emulate_mtdcr(struct kvm_vcpu *vcpu, int rs, int dcrn) | ||
39 | { | ||
40 | /* emulate some access in kernel */ | ||
41 | switch (dcrn) { | ||
42 | case DCRN_CPR0_CONFIG_ADDR: | ||
43 | vcpu->arch.cpr0_cfgaddr = kvmppc_get_gpr(vcpu, rs); | ||
44 | return EMULATE_DONE; | ||
45 | default: | ||
46 | vcpu->run->dcr.dcrn = dcrn; | ||
47 | vcpu->run->dcr.data = kvmppc_get_gpr(vcpu, rs); | ||
48 | vcpu->run->dcr.is_write = 1; | ||
49 | vcpu->arch.dcr_is_write = 1; | ||
50 | vcpu->arch.dcr_needed = 1; | ||
51 | kvmppc_account_exit(vcpu, DCR_EXITS); | ||
52 | return EMULATE_DO_DCR; | ||
53 | } | ||
54 | } | ||
55 | |||
56 | static int emulate_mfdcr(struct kvm_vcpu *vcpu, int rt, int dcrn) | ||
57 | { | ||
58 | /* The guest may access CPR0 registers to determine the timebase | ||
59 | * frequency, and it must know the real host frequency because it | ||
60 | * can directly access the timebase registers. | ||
61 | * | ||
62 | * It would be possible to emulate those accesses in userspace, | ||
63 | * but userspace can really only figure out the end frequency. | ||
64 | * We could decompose that into the factors that compute it, but | ||
65 | * that's tricky math, and it's easier to just report the real | ||
66 | * CPR0 values. | ||
67 | */ | ||
68 | switch (dcrn) { | ||
69 | case DCRN_CPR0_CONFIG_ADDR: | ||
70 | kvmppc_set_gpr(vcpu, rt, vcpu->arch.cpr0_cfgaddr); | ||
71 | break; | ||
72 | case DCRN_CPR0_CONFIG_DATA: | ||
73 | local_irq_disable(); | ||
74 | mtdcr(DCRN_CPR0_CONFIG_ADDR, | ||
75 | vcpu->arch.cpr0_cfgaddr); | ||
76 | kvmppc_set_gpr(vcpu, rt, | ||
77 | mfdcr(DCRN_CPR0_CONFIG_DATA)); | ||
78 | local_irq_enable(); | ||
79 | break; | ||
80 | default: | ||
81 | vcpu->run->dcr.dcrn = dcrn; | ||
82 | vcpu->run->dcr.data = 0; | ||
83 | vcpu->run->dcr.is_write = 0; | ||
84 | vcpu->arch.dcr_is_write = 0; | ||
85 | vcpu->arch.io_gpr = rt; | ||
86 | vcpu->arch.dcr_needed = 1; | ||
87 | kvmppc_account_exit(vcpu, DCR_EXITS); | ||
88 | return EMULATE_DO_DCR; | ||
89 | } | ||
90 | |||
91 | return EMULATE_DONE; | ||
92 | } | ||
93 | |||
94 | int kvmppc_core_emulate_op_44x(struct kvm_run *run, struct kvm_vcpu *vcpu, | ||
95 | unsigned int inst, int *advance) | ||
96 | { | ||
97 | int emulated = EMULATE_DONE; | ||
98 | int dcrn = get_dcrn(inst); | ||
99 | int ra = get_ra(inst); | ||
100 | int rb = get_rb(inst); | ||
101 | int rc = get_rc(inst); | ||
102 | int rs = get_rs(inst); | ||
103 | int rt = get_rt(inst); | ||
104 | int ws = get_ws(inst); | ||
105 | |||
106 | switch (get_op(inst)) { | ||
107 | case 31: | ||
108 | switch (get_xop(inst)) { | ||
109 | |||
110 | case XOP_MFDCR: | ||
111 | emulated = emulate_mfdcr(vcpu, rt, dcrn); | ||
112 | break; | ||
113 | |||
114 | case XOP_MFDCRX: | ||
115 | emulated = emulate_mfdcr(vcpu, rt, | ||
116 | kvmppc_get_gpr(vcpu, ra)); | ||
117 | break; | ||
118 | |||
119 | case XOP_MTDCR: | ||
120 | emulated = emulate_mtdcr(vcpu, rs, dcrn); | ||
121 | break; | ||
122 | |||
123 | case XOP_MTDCRX: | ||
124 | emulated = emulate_mtdcr(vcpu, rs, | ||
125 | kvmppc_get_gpr(vcpu, ra)); | ||
126 | break; | ||
127 | |||
128 | case XOP_TLBWE: | ||
129 | emulated = kvmppc_44x_emul_tlbwe(vcpu, ra, rs, ws); | ||
130 | break; | ||
131 | |||
132 | case XOP_TLBSX: | ||
133 | emulated = kvmppc_44x_emul_tlbsx(vcpu, rt, ra, rb, rc); | ||
134 | break; | ||
135 | |||
136 | case XOP_ICCCI: | ||
137 | break; | ||
138 | |||
139 | default: | ||
140 | emulated = EMULATE_FAIL; | ||
141 | } | ||
142 | |||
143 | break; | ||
144 | |||
145 | default: | ||
146 | emulated = EMULATE_FAIL; | ||
147 | } | ||
148 | |||
149 | if (emulated == EMULATE_FAIL) | ||
150 | emulated = kvmppc_booke_emulate_op(run, vcpu, inst, advance); | ||
151 | |||
152 | return emulated; | ||
153 | } | ||
154 | |||
155 | int kvmppc_core_emulate_mtspr_44x(struct kvm_vcpu *vcpu, int sprn, ulong spr_val) | ||
156 | { | ||
157 | int emulated = EMULATE_DONE; | ||
158 | |||
159 | switch (sprn) { | ||
160 | case SPRN_PID: | ||
161 | kvmppc_set_pid(vcpu, spr_val); break; | ||
162 | case SPRN_MMUCR: | ||
163 | vcpu->arch.mmucr = spr_val; break; | ||
164 | case SPRN_CCR0: | ||
165 | vcpu->arch.ccr0 = spr_val; break; | ||
166 | case SPRN_CCR1: | ||
167 | vcpu->arch.ccr1 = spr_val; break; | ||
168 | default: | ||
169 | emulated = kvmppc_booke_emulate_mtspr(vcpu, sprn, spr_val); | ||
170 | } | ||
171 | |||
172 | return emulated; | ||
173 | } | ||
174 | |||
175 | int kvmppc_core_emulate_mfspr_44x(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val) | ||
176 | { | ||
177 | int emulated = EMULATE_DONE; | ||
178 | |||
179 | switch (sprn) { | ||
180 | case SPRN_PID: | ||
181 | *spr_val = vcpu->arch.pid; break; | ||
182 | case SPRN_MMUCR: | ||
183 | *spr_val = vcpu->arch.mmucr; break; | ||
184 | case SPRN_CCR0: | ||
185 | *spr_val = vcpu->arch.ccr0; break; | ||
186 | case SPRN_CCR1: | ||
187 | *spr_val = vcpu->arch.ccr1; break; | ||
188 | default: | ||
189 | emulated = kvmppc_booke_emulate_mfspr(vcpu, sprn, spr_val); | ||
190 | } | ||
191 | |||
192 | return emulated; | ||
193 | } | ||
194 | |||
diff --git a/arch/powerpc/kvm/44x_tlb.c b/arch/powerpc/kvm/44x_tlb.c deleted file mode 100644 index 0deef1082e02..000000000000 --- a/arch/powerpc/kvm/44x_tlb.c +++ /dev/null | |||
@@ -1,528 +0,0 @@ | |||
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 IBM Corp. 2007 | ||
16 | * | ||
17 | * Authors: Hollis Blanchard <hollisb@us.ibm.com> | ||
18 | */ | ||
19 | |||
20 | #include <linux/types.h> | ||
21 | #include <linux/string.h> | ||
22 | #include <linux/kvm.h> | ||
23 | #include <linux/kvm_host.h> | ||
24 | #include <linux/highmem.h> | ||
25 | |||
26 | #include <asm/tlbflush.h> | ||
27 | #include <asm/mmu-44x.h> | ||
28 | #include <asm/kvm_ppc.h> | ||
29 | #include <asm/kvm_44x.h> | ||
30 | #include "timing.h" | ||
31 | |||
32 | #include "44x_tlb.h" | ||
33 | #include "trace.h" | ||
34 | |||
35 | #ifndef PPC44x_TLBE_SIZE | ||
36 | #define PPC44x_TLBE_SIZE PPC44x_TLB_4K | ||
37 | #endif | ||
38 | |||
39 | #define PAGE_SIZE_4K (1<<12) | ||
40 | #define PAGE_MASK_4K (~(PAGE_SIZE_4K - 1)) | ||
41 | |||
42 | #define PPC44x_TLB_UATTR_MASK \ | ||
43 | (PPC44x_TLB_U0|PPC44x_TLB_U1|PPC44x_TLB_U2|PPC44x_TLB_U3) | ||
44 | #define PPC44x_TLB_USER_PERM_MASK (PPC44x_TLB_UX|PPC44x_TLB_UR|PPC44x_TLB_UW) | ||
45 | #define PPC44x_TLB_SUPER_PERM_MASK (PPC44x_TLB_SX|PPC44x_TLB_SR|PPC44x_TLB_SW) | ||
46 | |||
47 | #ifdef DEBUG | ||
48 | void kvmppc_dump_tlbs(struct kvm_vcpu *vcpu) | ||
49 | { | ||
50 | struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); | ||
51 | struct kvmppc_44x_tlbe *tlbe; | ||
52 | int i; | ||
53 | |||
54 | printk("vcpu %d TLB dump:\n", vcpu->vcpu_id); | ||
55 | printk("| %2s | %3s | %8s | %8s | %8s |\n", | ||
56 | "nr", "tid", "word0", "word1", "word2"); | ||
57 | |||
58 | for (i = 0; i < ARRAY_SIZE(vcpu_44x->guest_tlb); i++) { | ||
59 | tlbe = &vcpu_44x->guest_tlb[i]; | ||
60 | if (tlbe->word0 & PPC44x_TLB_VALID) | ||
61 | printk(" G%2d | %02X | %08X | %08X | %08X |\n", | ||
62 | i, tlbe->tid, tlbe->word0, tlbe->word1, | ||
63 | tlbe->word2); | ||
64 | } | ||
65 | } | ||
66 | #endif | ||
67 | |||
68 | static inline void kvmppc_44x_tlbie(unsigned int index) | ||
69 | { | ||
70 | /* 0 <= index < 64, so the V bit is clear and we can use the index as | ||
71 | * word0. */ | ||
72 | asm volatile( | ||
73 | "tlbwe %[index], %[index], 0\n" | ||
74 | : | ||
75 | : [index] "r"(index) | ||
76 | ); | ||
77 | } | ||
78 | |||
79 | static inline void kvmppc_44x_tlbre(unsigned int index, | ||
80 | struct kvmppc_44x_tlbe *tlbe) | ||
81 | { | ||
82 | asm volatile( | ||
83 | "tlbre %[word0], %[index], 0\n" | ||
84 | "mfspr %[tid], %[sprn_mmucr]\n" | ||
85 | "andi. %[tid], %[tid], 0xff\n" | ||
86 | "tlbre %[word1], %[index], 1\n" | ||
87 | "tlbre %[word2], %[index], 2\n" | ||
88 | : [word0] "=r"(tlbe->word0), | ||
89 | [word1] "=r"(tlbe->word1), | ||
90 | [word2] "=r"(tlbe->word2), | ||
91 | [tid] "=r"(tlbe->tid) | ||
92 | : [index] "r"(index), | ||
93 | [sprn_mmucr] "i"(SPRN_MMUCR) | ||
94 | : "cc" | ||
95 | ); | ||
96 | } | ||
97 | |||
98 | static inline void kvmppc_44x_tlbwe(unsigned int index, | ||
99 | struct kvmppc_44x_tlbe *stlbe) | ||
100 | { | ||
101 | unsigned long tmp; | ||
102 | |||
103 | asm volatile( | ||
104 | "mfspr %[tmp], %[sprn_mmucr]\n" | ||
105 | "rlwimi %[tmp], %[tid], 0, 0xff\n" | ||
106 | "mtspr %[sprn_mmucr], %[tmp]\n" | ||
107 | "tlbwe %[word0], %[index], 0\n" | ||
108 | "tlbwe %[word1], %[index], 1\n" | ||
109 | "tlbwe %[word2], %[index], 2\n" | ||
110 | : [tmp] "=&r"(tmp) | ||
111 | : [word0] "r"(stlbe->word0), | ||
112 | [word1] "r"(stlbe->word1), | ||
113 | [word2] "r"(stlbe->word2), | ||
114 | [tid] "r"(stlbe->tid), | ||
115 | [index] "r"(index), | ||
116 | [sprn_mmucr] "i"(SPRN_MMUCR) | ||
117 | ); | ||
118 | } | ||
119 | |||
120 | static u32 kvmppc_44x_tlb_shadow_attrib(u32 attrib, int usermode) | ||
121 | { | ||
122 | /* We only care about the guest's permission and user bits. */ | ||
123 | attrib &= PPC44x_TLB_PERM_MASK|PPC44x_TLB_UATTR_MASK; | ||
124 | |||
125 | if (!usermode) { | ||
126 | /* Guest is in supervisor mode, so we need to translate guest | ||
127 | * supervisor permissions into user permissions. */ | ||
128 | attrib &= ~PPC44x_TLB_USER_PERM_MASK; | ||
129 | attrib |= (attrib & PPC44x_TLB_SUPER_PERM_MASK) << 3; | ||
130 | } | ||
131 | |||
132 | /* Make sure host can always access this memory. */ | ||
133 | attrib |= PPC44x_TLB_SX|PPC44x_TLB_SR|PPC44x_TLB_SW; | ||
134 | |||
135 | /* WIMGE = 0b00100 */ | ||
136 | attrib |= PPC44x_TLB_M; | ||
137 | |||
138 | return attrib; | ||
139 | } | ||
140 | |||
141 | /* Load shadow TLB back into hardware. */ | ||
142 | void kvmppc_44x_tlb_load(struct kvm_vcpu *vcpu) | ||
143 | { | ||
144 | struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); | ||
145 | int i; | ||
146 | |||
147 | for (i = 0; i <= tlb_44x_hwater; i++) { | ||
148 | struct kvmppc_44x_tlbe *stlbe = &vcpu_44x->shadow_tlb[i]; | ||
149 | |||
150 | if (get_tlb_v(stlbe) && get_tlb_ts(stlbe)) | ||
151 | kvmppc_44x_tlbwe(i, stlbe); | ||
152 | } | ||
153 | } | ||
154 | |||
155 | static void kvmppc_44x_tlbe_set_modified(struct kvmppc_vcpu_44x *vcpu_44x, | ||
156 | unsigned int i) | ||
157 | { | ||
158 | vcpu_44x->shadow_tlb_mod[i] = 1; | ||
159 | } | ||
160 | |||
161 | /* Save hardware TLB to the vcpu, and invalidate all guest mappings. */ | ||
162 | void kvmppc_44x_tlb_put(struct kvm_vcpu *vcpu) | ||
163 | { | ||
164 | struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); | ||
165 | int i; | ||
166 | |||
167 | for (i = 0; i <= tlb_44x_hwater; i++) { | ||
168 | struct kvmppc_44x_tlbe *stlbe = &vcpu_44x->shadow_tlb[i]; | ||
169 | |||
170 | if (vcpu_44x->shadow_tlb_mod[i]) | ||
171 | kvmppc_44x_tlbre(i, stlbe); | ||
172 | |||
173 | if (get_tlb_v(stlbe) && get_tlb_ts(stlbe)) | ||
174 | kvmppc_44x_tlbie(i); | ||
175 | } | ||
176 | } | ||
177 | |||
178 | |||
179 | /* Search the guest TLB for a matching entry. */ | ||
180 | int kvmppc_44x_tlb_index(struct kvm_vcpu *vcpu, gva_t eaddr, unsigned int pid, | ||
181 | unsigned int as) | ||
182 | { | ||
183 | struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); | ||
184 | int i; | ||
185 | |||
186 | /* XXX Replace loop with fancy data structures. */ | ||
187 | for (i = 0; i < ARRAY_SIZE(vcpu_44x->guest_tlb); i++) { | ||
188 | struct kvmppc_44x_tlbe *tlbe = &vcpu_44x->guest_tlb[i]; | ||
189 | unsigned int tid; | ||
190 | |||
191 | if (eaddr < get_tlb_eaddr(tlbe)) | ||
192 | continue; | ||
193 | |||
194 | if (eaddr > get_tlb_end(tlbe)) | ||
195 | continue; | ||
196 | |||
197 | tid = get_tlb_tid(tlbe); | ||
198 | if (tid && (tid != pid)) | ||
199 | continue; | ||
200 | |||
201 | if (!get_tlb_v(tlbe)) | ||
202 | continue; | ||
203 | |||
204 | if (get_tlb_ts(tlbe) != as) | ||
205 | continue; | ||
206 | |||
207 | return i; | ||
208 | } | ||
209 | |||
210 | return -1; | ||
211 | } | ||
212 | |||
213 | gpa_t kvmppc_mmu_xlate(struct kvm_vcpu *vcpu, unsigned int gtlb_index, | ||
214 | gva_t eaddr) | ||
215 | { | ||
216 | struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); | ||
217 | struct kvmppc_44x_tlbe *gtlbe = &vcpu_44x->guest_tlb[gtlb_index]; | ||
218 | unsigned int pgmask = get_tlb_bytes(gtlbe) - 1; | ||
219 | |||
220 | return get_tlb_raddr(gtlbe) | (eaddr & pgmask); | ||
221 | } | ||
222 | |||
223 | int kvmppc_mmu_itlb_index(struct kvm_vcpu *vcpu, gva_t eaddr) | ||
224 | { | ||
225 | unsigned int as = !!(vcpu->arch.shared->msr & MSR_IS); | ||
226 | |||
227 | return kvmppc_44x_tlb_index(vcpu, eaddr, vcpu->arch.pid, as); | ||
228 | } | ||
229 | |||
230 | int kvmppc_mmu_dtlb_index(struct kvm_vcpu *vcpu, gva_t eaddr) | ||
231 | { | ||
232 | unsigned int as = !!(vcpu->arch.shared->msr & MSR_DS); | ||
233 | |||
234 | return kvmppc_44x_tlb_index(vcpu, eaddr, vcpu->arch.pid, as); | ||
235 | } | ||
236 | |||
237 | void kvmppc_mmu_itlb_miss(struct kvm_vcpu *vcpu) | ||
238 | { | ||
239 | } | ||
240 | |||
241 | void kvmppc_mmu_dtlb_miss(struct kvm_vcpu *vcpu) | ||
242 | { | ||
243 | } | ||
244 | |||
245 | static void kvmppc_44x_shadow_release(struct kvmppc_vcpu_44x *vcpu_44x, | ||
246 | unsigned int stlb_index) | ||
247 | { | ||
248 | struct kvmppc_44x_shadow_ref *ref = &vcpu_44x->shadow_refs[stlb_index]; | ||
249 | |||
250 | if (!ref->page) | ||
251 | return; | ||
252 | |||
253 | /* Discard from the TLB. */ | ||
254 | /* Note: we could actually invalidate a host mapping, if the host overwrote | ||
255 | * this TLB entry since we inserted a guest mapping. */ | ||
256 | kvmppc_44x_tlbie(stlb_index); | ||
257 | |||
258 | /* Now release the page. */ | ||
259 | if (ref->writeable) | ||
260 | kvm_release_page_dirty(ref->page); | ||
261 | else | ||
262 | kvm_release_page_clean(ref->page); | ||
263 | |||
264 | ref->page = NULL; | ||
265 | |||
266 | /* XXX set tlb_44x_index to stlb_index? */ | ||
267 | |||
268 | trace_kvm_stlb_inval(stlb_index); | ||
269 | } | ||
270 | |||
271 | void kvmppc_mmu_destroy_44x(struct kvm_vcpu *vcpu) | ||
272 | { | ||
273 | struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); | ||
274 | int i; | ||
275 | |||
276 | for (i = 0; i <= tlb_44x_hwater; i++) | ||
277 | kvmppc_44x_shadow_release(vcpu_44x, i); | ||
278 | } | ||
279 | |||
280 | /** | ||
281 | * kvmppc_mmu_map -- create a host mapping for guest memory | ||
282 | * | ||
283 | * If the guest wanted a larger page than the host supports, only the first | ||
284 | * host page is mapped here and the rest are demand faulted. | ||
285 | * | ||
286 | * If the guest wanted a smaller page than the host page size, we map only the | ||
287 | * guest-size page (i.e. not a full host page mapping). | ||
288 | * | ||
289 | * Caller must ensure that the specified guest TLB entry is safe to insert into | ||
290 | * the shadow TLB. | ||
291 | */ | ||
292 | void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gpa_t gpaddr, | ||
293 | unsigned int gtlb_index) | ||
294 | { | ||
295 | struct kvmppc_44x_tlbe stlbe; | ||
296 | struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); | ||
297 | struct kvmppc_44x_tlbe *gtlbe = &vcpu_44x->guest_tlb[gtlb_index]; | ||
298 | struct kvmppc_44x_shadow_ref *ref; | ||
299 | struct page *new_page; | ||
300 | hpa_t hpaddr; | ||
301 | gfn_t gfn; | ||
302 | u32 asid = gtlbe->tid; | ||
303 | u32 flags = gtlbe->word2; | ||
304 | u32 max_bytes = get_tlb_bytes(gtlbe); | ||
305 | unsigned int victim; | ||
306 | |||
307 | /* Select TLB entry to clobber. Indirectly guard against races with the TLB | ||
308 | * miss handler by disabling interrupts. */ | ||
309 | local_irq_disable(); | ||
310 | victim = ++tlb_44x_index; | ||
311 | if (victim > tlb_44x_hwater) | ||
312 | victim = 0; | ||
313 | tlb_44x_index = victim; | ||
314 | local_irq_enable(); | ||
315 | |||
316 | /* Get reference to new page. */ | ||
317 | gfn = gpaddr >> PAGE_SHIFT; | ||
318 | new_page = gfn_to_page(vcpu->kvm, gfn); | ||
319 | if (is_error_page(new_page)) { | ||
320 | printk(KERN_ERR "Couldn't get guest page for gfn %llx!\n", | ||
321 | (unsigned long long)gfn); | ||
322 | return; | ||
323 | } | ||
324 | hpaddr = page_to_phys(new_page); | ||
325 | |||
326 | /* Invalidate any previous shadow mappings. */ | ||
327 | kvmppc_44x_shadow_release(vcpu_44x, victim); | ||
328 | |||
329 | /* XXX Make sure (va, size) doesn't overlap any other | ||
330 | * entries. 440x6 user manual says the result would be | ||
331 | * "undefined." */ | ||
332 | |||
333 | /* XXX what about AS? */ | ||
334 | |||
335 | /* Force TS=1 for all guest mappings. */ | ||
336 | stlbe.word0 = PPC44x_TLB_VALID | PPC44x_TLB_TS; | ||
337 | |||
338 | if (max_bytes >= PAGE_SIZE) { | ||
339 | /* Guest mapping is larger than or equal to host page size. We can use | ||
340 | * a "native" host mapping. */ | ||
341 | stlbe.word0 |= (gvaddr & PAGE_MASK) | PPC44x_TLBE_SIZE; | ||
342 | } else { | ||
343 | /* Guest mapping is smaller than host page size. We must restrict the | ||
344 | * size of the mapping to be at most the smaller of the two, but for | ||
345 | * simplicity we fall back to a 4K mapping (this is probably what the | ||
346 | * guest is using anyways). */ | ||
347 | stlbe.word0 |= (gvaddr & PAGE_MASK_4K) | PPC44x_TLB_4K; | ||
348 | |||
349 | /* 'hpaddr' is a host page, which is larger than the mapping we're | ||
350 | * inserting here. To compensate, we must add the in-page offset to the | ||
351 | * sub-page. */ | ||
352 | hpaddr |= gpaddr & (PAGE_MASK ^ PAGE_MASK_4K); | ||
353 | } | ||
354 | |||
355 | stlbe.word1 = (hpaddr & 0xfffffc00) | ((hpaddr >> 32) & 0xf); | ||
356 | stlbe.word2 = kvmppc_44x_tlb_shadow_attrib(flags, | ||
357 | vcpu->arch.shared->msr & MSR_PR); | ||
358 | stlbe.tid = !(asid & 0xff); | ||
359 | |||
360 | /* Keep track of the reference so we can properly release it later. */ | ||
361 | ref = &vcpu_44x->shadow_refs[victim]; | ||
362 | ref->page = new_page; | ||
363 | ref->gtlb_index = gtlb_index; | ||
364 | ref->writeable = !!(stlbe.word2 & PPC44x_TLB_UW); | ||
365 | ref->tid = stlbe.tid; | ||
366 | |||
367 | /* Insert shadow mapping into hardware TLB. */ | ||
368 | kvmppc_44x_tlbe_set_modified(vcpu_44x, victim); | ||
369 | kvmppc_44x_tlbwe(victim, &stlbe); | ||
370 | trace_kvm_stlb_write(victim, stlbe.tid, stlbe.word0, stlbe.word1, | ||
371 | stlbe.word2); | ||
372 | } | ||
373 | |||
374 | /* For a particular guest TLB entry, invalidate the corresponding host TLB | ||
375 | * mappings and release the host pages. */ | ||
376 | static void kvmppc_44x_invalidate(struct kvm_vcpu *vcpu, | ||
377 | unsigned int gtlb_index) | ||
378 | { | ||
379 | struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); | ||
380 | int i; | ||
381 | |||
382 | for (i = 0; i < ARRAY_SIZE(vcpu_44x->shadow_refs); i++) { | ||
383 | struct kvmppc_44x_shadow_ref *ref = &vcpu_44x->shadow_refs[i]; | ||
384 | if (ref->gtlb_index == gtlb_index) | ||
385 | kvmppc_44x_shadow_release(vcpu_44x, i); | ||
386 | } | ||
387 | } | ||
388 | |||
389 | void kvmppc_mmu_msr_notify(struct kvm_vcpu *vcpu, u32 old_msr) | ||
390 | { | ||
391 | int usermode = vcpu->arch.shared->msr & MSR_PR; | ||
392 | |||
393 | vcpu->arch.shadow_pid = !usermode; | ||
394 | } | ||
395 | |||
396 | void kvmppc_set_pid(struct kvm_vcpu *vcpu, u32 new_pid) | ||
397 | { | ||
398 | struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); | ||
399 | int i; | ||
400 | |||
401 | if (unlikely(vcpu->arch.pid == new_pid)) | ||
402 | return; | ||
403 | |||
404 | vcpu->arch.pid = new_pid; | ||
405 | |||
406 | /* Guest userspace runs with TID=0 mappings and PID=0, to make sure it | ||
407 | * can't access guest kernel mappings (TID=1). When we switch to a new | ||
408 | * guest PID, which will also use host PID=0, we must discard the old guest | ||
409 | * userspace mappings. */ | ||
410 | for (i = 0; i < ARRAY_SIZE(vcpu_44x->shadow_refs); i++) { | ||
411 | struct kvmppc_44x_shadow_ref *ref = &vcpu_44x->shadow_refs[i]; | ||
412 | |||
413 | if (ref->tid == 0) | ||
414 | kvmppc_44x_shadow_release(vcpu_44x, i); | ||
415 | } | ||
416 | } | ||
417 | |||
418 | static int tlbe_is_host_safe(const struct kvm_vcpu *vcpu, | ||
419 | const struct kvmppc_44x_tlbe *tlbe) | ||
420 | { | ||
421 | gpa_t gpa; | ||
422 | |||
423 | if (!get_tlb_v(tlbe)) | ||
424 | return 0; | ||
425 | |||
426 | /* Does it match current guest AS? */ | ||
427 | /* XXX what about IS != DS? */ | ||
428 | if (get_tlb_ts(tlbe) != !!(vcpu->arch.shared->msr & MSR_IS)) | ||
429 | return 0; | ||
430 | |||
431 | gpa = get_tlb_raddr(tlbe); | ||
432 | if (!gfn_to_memslot(vcpu->kvm, gpa >> PAGE_SHIFT)) | ||
433 | /* Mapping is not for RAM. */ | ||
434 | return 0; | ||
435 | |||
436 | return 1; | ||
437 | } | ||
438 | |||
439 | int kvmppc_44x_emul_tlbwe(struct kvm_vcpu *vcpu, u8 ra, u8 rs, u8 ws) | ||
440 | { | ||
441 | struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); | ||
442 | struct kvmppc_44x_tlbe *tlbe; | ||
443 | unsigned int gtlb_index; | ||
444 | int idx; | ||
445 | |||
446 | gtlb_index = kvmppc_get_gpr(vcpu, ra); | ||
447 | if (gtlb_index >= KVM44x_GUEST_TLB_SIZE) { | ||
448 | printk("%s: index %d\n", __func__, gtlb_index); | ||
449 | kvmppc_dump_vcpu(vcpu); | ||
450 | return EMULATE_FAIL; | ||
451 | } | ||
452 | |||
453 | tlbe = &vcpu_44x->guest_tlb[gtlb_index]; | ||
454 | |||
455 | /* Invalidate shadow mappings for the about-to-be-clobbered TLB entry. */ | ||
456 | if (tlbe->word0 & PPC44x_TLB_VALID) | ||
457 | kvmppc_44x_invalidate(vcpu, gtlb_index); | ||
458 | |||
459 | switch (ws) { | ||
460 | case PPC44x_TLB_PAGEID: | ||
461 | tlbe->tid = get_mmucr_stid(vcpu); | ||
462 | tlbe->word0 = kvmppc_get_gpr(vcpu, rs); | ||
463 | break; | ||
464 | |||
465 | case PPC44x_TLB_XLAT: | ||
466 | tlbe->word1 = kvmppc_get_gpr(vcpu, rs); | ||
467 | break; | ||
468 | |||
469 | case PPC44x_TLB_ATTRIB: | ||
470 | tlbe->word2 = kvmppc_get_gpr(vcpu, rs); | ||
471 | break; | ||
472 | |||
473 | default: | ||
474 | return EMULATE_FAIL; | ||
475 | } | ||
476 | |||
477 | idx = srcu_read_lock(&vcpu->kvm->srcu); | ||
478 | |||
479 | if (tlbe_is_host_safe(vcpu, tlbe)) { | ||
480 | gva_t eaddr; | ||
481 | gpa_t gpaddr; | ||
482 | u32 bytes; | ||
483 | |||
484 | eaddr = get_tlb_eaddr(tlbe); | ||
485 | gpaddr = get_tlb_raddr(tlbe); | ||
486 | |||
487 | /* Use the advertised page size to mask effective and real addrs. */ | ||
488 | bytes = get_tlb_bytes(tlbe); | ||
489 | eaddr &= ~(bytes - 1); | ||
490 | gpaddr &= ~(bytes - 1); | ||
491 | |||
492 | kvmppc_mmu_map(vcpu, eaddr, gpaddr, gtlb_index); | ||
493 | } | ||
494 | |||
495 | srcu_read_unlock(&vcpu->kvm->srcu, idx); | ||
496 | |||
497 | trace_kvm_gtlb_write(gtlb_index, tlbe->tid, tlbe->word0, tlbe->word1, | ||
498 | tlbe->word2); | ||
499 | |||
500 | kvmppc_set_exit_type(vcpu, EMULATED_TLBWE_EXITS); | ||
501 | return EMULATE_DONE; | ||
502 | } | ||
503 | |||
504 | int kvmppc_44x_emul_tlbsx(struct kvm_vcpu *vcpu, u8 rt, u8 ra, u8 rb, u8 rc) | ||
505 | { | ||
506 | u32 ea; | ||
507 | int gtlb_index; | ||
508 | unsigned int as = get_mmucr_sts(vcpu); | ||
509 | unsigned int pid = get_mmucr_stid(vcpu); | ||
510 | |||
511 | ea = kvmppc_get_gpr(vcpu, rb); | ||
512 | if (ra) | ||
513 | ea += kvmppc_get_gpr(vcpu, ra); | ||
514 | |||
515 | gtlb_index = kvmppc_44x_tlb_index(vcpu, ea, pid, as); | ||
516 | if (rc) { | ||
517 | u32 cr = kvmppc_get_cr(vcpu); | ||
518 | |||
519 | if (gtlb_index < 0) | ||
520 | kvmppc_set_cr(vcpu, cr & ~0x20000000); | ||
521 | else | ||
522 | kvmppc_set_cr(vcpu, cr | 0x20000000); | ||
523 | } | ||
524 | kvmppc_set_gpr(vcpu, rt, gtlb_index); | ||
525 | |||
526 | kvmppc_set_exit_type(vcpu, EMULATED_TLBSX_EXITS); | ||
527 | return EMULATE_DONE; | ||
528 | } | ||
diff --git a/arch/powerpc/kvm/44x_tlb.h b/arch/powerpc/kvm/44x_tlb.h deleted file mode 100644 index a9ff80e51526..000000000000 --- a/arch/powerpc/kvm/44x_tlb.h +++ /dev/null | |||
@@ -1,86 +0,0 @@ | |||
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 IBM Corp. 2007 | ||
16 | * | ||
17 | * Authors: Hollis Blanchard <hollisb@us.ibm.com> | ||
18 | */ | ||
19 | |||
20 | #ifndef __KVM_POWERPC_TLB_H__ | ||
21 | #define __KVM_POWERPC_TLB_H__ | ||
22 | |||
23 | #include <linux/kvm_host.h> | ||
24 | #include <asm/mmu-44x.h> | ||
25 | |||
26 | extern int kvmppc_44x_tlb_index(struct kvm_vcpu *vcpu, gva_t eaddr, | ||
27 | unsigned int pid, unsigned int as); | ||
28 | |||
29 | extern int kvmppc_44x_emul_tlbsx(struct kvm_vcpu *vcpu, u8 rt, u8 ra, u8 rb, | ||
30 | u8 rc); | ||
31 | extern int kvmppc_44x_emul_tlbwe(struct kvm_vcpu *vcpu, u8 ra, u8 rs, u8 ws); | ||
32 | |||
33 | /* TLB helper functions */ | ||
34 | static inline unsigned int get_tlb_size(const struct kvmppc_44x_tlbe *tlbe) | ||
35 | { | ||
36 | return (tlbe->word0 >> 4) & 0xf; | ||
37 | } | ||
38 | |||
39 | static inline gva_t get_tlb_eaddr(const struct kvmppc_44x_tlbe *tlbe) | ||
40 | { | ||
41 | return tlbe->word0 & 0xfffffc00; | ||
42 | } | ||
43 | |||
44 | static inline gva_t get_tlb_bytes(const struct kvmppc_44x_tlbe *tlbe) | ||
45 | { | ||
46 | unsigned int pgsize = get_tlb_size(tlbe); | ||
47 | return 1 << 10 << (pgsize << 1); | ||
48 | } | ||
49 | |||
50 | static inline gva_t get_tlb_end(const struct kvmppc_44x_tlbe *tlbe) | ||
51 | { | ||
52 | return get_tlb_eaddr(tlbe) + get_tlb_bytes(tlbe) - 1; | ||
53 | } | ||
54 | |||
55 | static inline u64 get_tlb_raddr(const struct kvmppc_44x_tlbe *tlbe) | ||
56 | { | ||
57 | u64 word1 = tlbe->word1; | ||
58 | return ((word1 & 0xf) << 32) | (word1 & 0xfffffc00); | ||
59 | } | ||
60 | |||
61 | static inline unsigned int get_tlb_tid(const struct kvmppc_44x_tlbe *tlbe) | ||
62 | { | ||
63 | return tlbe->tid & 0xff; | ||
64 | } | ||
65 | |||
66 | static inline unsigned int get_tlb_ts(const struct kvmppc_44x_tlbe *tlbe) | ||
67 | { | ||
68 | return (tlbe->word0 >> 8) & 0x1; | ||
69 | } | ||
70 | |||
71 | static inline unsigned int get_tlb_v(const struct kvmppc_44x_tlbe *tlbe) | ||
72 | { | ||
73 | return (tlbe->word0 >> 9) & 0x1; | ||
74 | } | ||
75 | |||
76 | static inline unsigned int get_mmucr_stid(const struct kvm_vcpu *vcpu) | ||
77 | { | ||
78 | return vcpu->arch.mmucr & 0xff; | ||
79 | } | ||
80 | |||
81 | static inline unsigned int get_mmucr_sts(const struct kvm_vcpu *vcpu) | ||
82 | { | ||
83 | return (vcpu->arch.mmucr >> 16) & 0x1; | ||
84 | } | ||
85 | |||
86 | #endif /* __KVM_POWERPC_TLB_H__ */ | ||
diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig index d6a53b95de94..602eb51d20bc 100644 --- a/arch/powerpc/kvm/Kconfig +++ b/arch/powerpc/kvm/Kconfig | |||
@@ -75,7 +75,6 @@ config KVM_BOOK3S_64 | |||
75 | config KVM_BOOK3S_64_HV | 75 | config KVM_BOOK3S_64_HV |
76 | tristate "KVM support for POWER7 and PPC970 using hypervisor mode in host" | 76 | tristate "KVM support for POWER7 and PPC970 using hypervisor mode in host" |
77 | depends on KVM_BOOK3S_64 | 77 | depends on KVM_BOOK3S_64 |
78 | depends on !CPU_LITTLE_ENDIAN | ||
79 | select KVM_BOOK3S_HV_POSSIBLE | 78 | select KVM_BOOK3S_HV_POSSIBLE |
80 | select MMU_NOTIFIER | 79 | select MMU_NOTIFIER |
81 | select CMA | 80 | select CMA |
@@ -113,23 +112,9 @@ config KVM_BOOK3S_64_PR | |||
113 | config KVM_BOOKE_HV | 112 | config KVM_BOOKE_HV |
114 | bool | 113 | bool |
115 | 114 | ||
116 | config KVM_440 | ||
117 | bool "KVM support for PowerPC 440 processors" | ||
118 | depends on 44x | ||
119 | select KVM | ||
120 | select KVM_MMIO | ||
121 | ---help--- | ||
122 | Support running unmodified 440 guest kernels in virtual machines on | ||
123 | 440 host processors. | ||
124 | |||
125 | This module provides access to the hardware capabilities through | ||
126 | a character device node named /dev/kvm. | ||
127 | |||
128 | If unsure, say N. | ||
129 | |||
130 | config KVM_EXIT_TIMING | 115 | config KVM_EXIT_TIMING |
131 | bool "Detailed exit timing" | 116 | bool "Detailed exit timing" |
132 | depends on KVM_440 || KVM_E500V2 || KVM_E500MC | 117 | depends on KVM_E500V2 || KVM_E500MC |
133 | ---help--- | 118 | ---help--- |
134 | Calculate elapsed time for every exit/enter cycle. A per-vcpu | 119 | Calculate elapsed time for every exit/enter cycle. A per-vcpu |
135 | report is available in debugfs kvm/vm#_vcpu#_timing. | 120 | report is available in debugfs kvm/vm#_vcpu#_timing. |
@@ -173,6 +158,7 @@ config KVM_MPIC | |||
173 | bool "KVM in-kernel MPIC emulation" | 158 | bool "KVM in-kernel MPIC emulation" |
174 | depends on KVM && E500 | 159 | depends on KVM && E500 |
175 | select HAVE_KVM_IRQCHIP | 160 | select HAVE_KVM_IRQCHIP |
161 | select HAVE_KVM_IRQFD | ||
176 | select HAVE_KVM_IRQ_ROUTING | 162 | select HAVE_KVM_IRQ_ROUTING |
177 | select HAVE_KVM_MSI | 163 | select HAVE_KVM_MSI |
178 | help | 164 | help |
@@ -184,6 +170,8 @@ config KVM_MPIC | |||
184 | config KVM_XICS | 170 | config KVM_XICS |
185 | bool "KVM in-kernel XICS emulation" | 171 | bool "KVM in-kernel XICS emulation" |
186 | depends on KVM_BOOK3S_64 && !KVM_MPIC | 172 | depends on KVM_BOOK3S_64 && !KVM_MPIC |
173 | select HAVE_KVM_IRQCHIP | ||
174 | select HAVE_KVM_IRQFD | ||
187 | ---help--- | 175 | ---help--- |
188 | Include support for the XICS (eXternal Interrupt Controller | 176 | Include support for the XICS (eXternal Interrupt Controller |
189 | Specification) interrupt controller architecture used on | 177 | Specification) interrupt controller architecture used on |
diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile index ce569b6bf4d8..0570eef83fba 100644 --- a/arch/powerpc/kvm/Makefile +++ b/arch/powerpc/kvm/Makefile | |||
@@ -10,27 +10,17 @@ KVM := ../../../virt/kvm | |||
10 | common-objs-y = $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o \ | 10 | common-objs-y = $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o \ |
11 | $(KVM)/eventfd.o | 11 | $(KVM)/eventfd.o |
12 | 12 | ||
13 | CFLAGS_44x_tlb.o := -I. | ||
14 | CFLAGS_e500_mmu.o := -I. | 13 | CFLAGS_e500_mmu.o := -I. |
15 | CFLAGS_e500_mmu_host.o := -I. | 14 | CFLAGS_e500_mmu_host.o := -I. |
16 | CFLAGS_emulate.o := -I. | 15 | CFLAGS_emulate.o := -I. |
16 | CFLAGS_emulate_loadstore.o := -I. | ||
17 | 17 | ||
18 | common-objs-y += powerpc.o emulate.o | 18 | common-objs-y += powerpc.o emulate.o emulate_loadstore.o |
19 | obj-$(CONFIG_KVM_EXIT_TIMING) += timing.o | 19 | obj-$(CONFIG_KVM_EXIT_TIMING) += timing.o |
20 | obj-$(CONFIG_KVM_BOOK3S_HANDLER) += book3s_exports.o | 20 | obj-$(CONFIG_KVM_BOOK3S_HANDLER) += book3s_exports.o |
21 | 21 | ||
22 | AFLAGS_booke_interrupts.o := -I$(obj) | 22 | AFLAGS_booke_interrupts.o := -I$(obj) |
23 | 23 | ||
24 | kvm-440-objs := \ | ||
25 | $(common-objs-y) \ | ||
26 | booke.o \ | ||
27 | booke_emulate.o \ | ||
28 | booke_interrupts.o \ | ||
29 | 44x.o \ | ||
30 | 44x_tlb.o \ | ||
31 | 44x_emulate.o | ||
32 | kvm-objs-$(CONFIG_KVM_440) := $(kvm-440-objs) | ||
33 | |||
34 | kvm-e500-objs := \ | 24 | kvm-e500-objs := \ |
35 | $(common-objs-y) \ | 25 | $(common-objs-y) \ |
36 | booke.o \ | 26 | booke.o \ |
@@ -58,6 +48,7 @@ kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HANDLER) := \ | |||
58 | 48 | ||
59 | kvm-pr-y := \ | 49 | kvm-pr-y := \ |
60 | fpu.o \ | 50 | fpu.o \ |
51 | emulate.o \ | ||
61 | book3s_paired_singles.o \ | 52 | book3s_paired_singles.o \ |
62 | book3s_pr.o \ | 53 | book3s_pr.o \ |
63 | book3s_pr_papr.o \ | 54 | book3s_pr_papr.o \ |
@@ -90,7 +81,6 @@ kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HANDLER) += \ | |||
90 | book3s_hv_rm_mmu.o \ | 81 | book3s_hv_rm_mmu.o \ |
91 | book3s_hv_ras.o \ | 82 | book3s_hv_ras.o \ |
92 | book3s_hv_builtin.o \ | 83 | book3s_hv_builtin.o \ |
93 | book3s_hv_cma.o \ | ||
94 | $(kvm-book3s_64-builtin-xics-objs-y) | 84 | $(kvm-book3s_64-builtin-xics-objs-y) |
95 | endif | 85 | endif |
96 | 86 | ||
@@ -101,7 +91,7 @@ kvm-book3s_64-module-objs += \ | |||
101 | $(KVM)/kvm_main.o \ | 91 | $(KVM)/kvm_main.o \ |
102 | $(KVM)/eventfd.o \ | 92 | $(KVM)/eventfd.o \ |
103 | powerpc.o \ | 93 | powerpc.o \ |
104 | emulate.o \ | 94 | emulate_loadstore.o \ |
105 | book3s.o \ | 95 | book3s.o \ |
106 | book3s_64_vio.o \ | 96 | book3s_64_vio.o \ |
107 | book3s_rtas.o \ | 97 | book3s_rtas.o \ |
@@ -127,7 +117,6 @@ kvm-objs-$(CONFIG_HAVE_KVM_IRQ_ROUTING) += $(KVM)/irqchip.o | |||
127 | 117 | ||
128 | kvm-objs := $(kvm-objs-m) $(kvm-objs-y) | 118 | kvm-objs := $(kvm-objs-m) $(kvm-objs-y) |
129 | 119 | ||
130 | obj-$(CONFIG_KVM_440) += kvm.o | ||
131 | obj-$(CONFIG_KVM_E500V2) += kvm.o | 120 | obj-$(CONFIG_KVM_E500V2) += kvm.o |
132 | obj-$(CONFIG_KVM_E500MC) += kvm.o | 121 | obj-$(CONFIG_KVM_E500MC) += kvm.o |
133 | obj-$(CONFIG_KVM_BOOK3S_64) += kvm.o | 122 | obj-$(CONFIG_KVM_BOOK3S_64) += kvm.o |
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c index c254c27f240e..dd03f6b299ba 100644 --- a/arch/powerpc/kvm/book3s.c +++ b/arch/powerpc/kvm/book3s.c | |||
@@ -72,6 +72,17 @@ void kvmppc_core_load_guest_debugstate(struct kvm_vcpu *vcpu) | |||
72 | { | 72 | { |
73 | } | 73 | } |
74 | 74 | ||
75 | void kvmppc_unfixup_split_real(struct kvm_vcpu *vcpu) | ||
76 | { | ||
77 | if (vcpu->arch.hflags & BOOK3S_HFLAG_SPLIT_HACK) { | ||
78 | ulong pc = kvmppc_get_pc(vcpu); | ||
79 | if ((pc & SPLIT_HACK_MASK) == SPLIT_HACK_OFFS) | ||
80 | kvmppc_set_pc(vcpu, pc & ~SPLIT_HACK_MASK); | ||
81 | vcpu->arch.hflags &= ~BOOK3S_HFLAG_SPLIT_HACK; | ||
82 | } | ||
83 | } | ||
84 | EXPORT_SYMBOL_GPL(kvmppc_unfixup_split_real); | ||
85 | |||
75 | static inline unsigned long kvmppc_interrupt_offset(struct kvm_vcpu *vcpu) | 86 | static inline unsigned long kvmppc_interrupt_offset(struct kvm_vcpu *vcpu) |
76 | { | 87 | { |
77 | if (!is_kvmppc_hv_enabled(vcpu->kvm)) | 88 | if (!is_kvmppc_hv_enabled(vcpu->kvm)) |
@@ -118,6 +129,7 @@ static inline bool kvmppc_critical_section(struct kvm_vcpu *vcpu) | |||
118 | 129 | ||
119 | void kvmppc_inject_interrupt(struct kvm_vcpu *vcpu, int vec, u64 flags) | 130 | void kvmppc_inject_interrupt(struct kvm_vcpu *vcpu, int vec, u64 flags) |
120 | { | 131 | { |
132 | kvmppc_unfixup_split_real(vcpu); | ||
121 | kvmppc_set_srr0(vcpu, kvmppc_get_pc(vcpu)); | 133 | kvmppc_set_srr0(vcpu, kvmppc_get_pc(vcpu)); |
122 | kvmppc_set_srr1(vcpu, kvmppc_get_msr(vcpu) | flags); | 134 | kvmppc_set_srr1(vcpu, kvmppc_get_msr(vcpu) | flags); |
123 | kvmppc_set_pc(vcpu, kvmppc_interrupt_offset(vcpu) + vec); | 135 | kvmppc_set_pc(vcpu, kvmppc_interrupt_offset(vcpu) + vec); |
@@ -218,6 +230,23 @@ void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu) | |||
218 | kvmppc_book3s_dequeue_irqprio(vcpu, BOOK3S_INTERRUPT_EXTERNAL_LEVEL); | 230 | kvmppc_book3s_dequeue_irqprio(vcpu, BOOK3S_INTERRUPT_EXTERNAL_LEVEL); |
219 | } | 231 | } |
220 | 232 | ||
233 | void kvmppc_core_queue_data_storage(struct kvm_vcpu *vcpu, ulong dar, | ||
234 | ulong flags) | ||
235 | { | ||
236 | kvmppc_set_dar(vcpu, dar); | ||
237 | kvmppc_set_dsisr(vcpu, flags); | ||
238 | kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_DATA_STORAGE); | ||
239 | } | ||
240 | |||
241 | void kvmppc_core_queue_inst_storage(struct kvm_vcpu *vcpu, ulong flags) | ||
242 | { | ||
243 | u64 msr = kvmppc_get_msr(vcpu); | ||
244 | msr &= ~(SRR1_ISI_NOPT | SRR1_ISI_N_OR_G | SRR1_ISI_PROT); | ||
245 | msr |= flags & (SRR1_ISI_NOPT | SRR1_ISI_N_OR_G | SRR1_ISI_PROT); | ||
246 | kvmppc_set_msr_fast(vcpu, msr); | ||
247 | kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_INST_STORAGE); | ||
248 | } | ||
249 | |||
221 | int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority) | 250 | int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority) |
222 | { | 251 | { |
223 | int deliver = 1; | 252 | int deliver = 1; |
@@ -342,18 +371,18 @@ int kvmppc_core_prepare_to_enter(struct kvm_vcpu *vcpu) | |||
342 | } | 371 | } |
343 | EXPORT_SYMBOL_GPL(kvmppc_core_prepare_to_enter); | 372 | EXPORT_SYMBOL_GPL(kvmppc_core_prepare_to_enter); |
344 | 373 | ||
345 | pfn_t kvmppc_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn, bool writing, | 374 | pfn_t kvmppc_gpa_to_pfn(struct kvm_vcpu *vcpu, gpa_t gpa, bool writing, |
346 | bool *writable) | 375 | bool *writable) |
347 | { | 376 | { |
348 | ulong mp_pa = vcpu->arch.magic_page_pa; | 377 | ulong mp_pa = vcpu->arch.magic_page_pa & KVM_PAM; |
378 | gfn_t gfn = gpa >> PAGE_SHIFT; | ||
349 | 379 | ||
350 | if (!(kvmppc_get_msr(vcpu) & MSR_SF)) | 380 | if (!(kvmppc_get_msr(vcpu) & MSR_SF)) |
351 | mp_pa = (uint32_t)mp_pa; | 381 | mp_pa = (uint32_t)mp_pa; |
352 | 382 | ||
353 | /* Magic page override */ | 383 | /* Magic page override */ |
354 | if (unlikely(mp_pa) && | 384 | gpa &= ~0xFFFULL; |
355 | unlikely(((gfn << PAGE_SHIFT) & KVM_PAM) == | 385 | if (unlikely(mp_pa) && unlikely((gpa & KVM_PAM) == mp_pa)) { |
356 | ((mp_pa & PAGE_MASK) & KVM_PAM))) { | ||
357 | ulong shared_page = ((ulong)vcpu->arch.shared) & PAGE_MASK; | 386 | ulong shared_page = ((ulong)vcpu->arch.shared) & PAGE_MASK; |
358 | pfn_t pfn; | 387 | pfn_t pfn; |
359 | 388 | ||
@@ -366,11 +395,13 @@ pfn_t kvmppc_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn, bool writing, | |||
366 | 395 | ||
367 | return gfn_to_pfn_prot(vcpu->kvm, gfn, writing, writable); | 396 | return gfn_to_pfn_prot(vcpu->kvm, gfn, writing, writable); |
368 | } | 397 | } |
369 | EXPORT_SYMBOL_GPL(kvmppc_gfn_to_pfn); | 398 | EXPORT_SYMBOL_GPL(kvmppc_gpa_to_pfn); |
370 | 399 | ||
371 | static int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, bool data, | 400 | int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, enum xlate_instdata xlid, |
372 | bool iswrite, struct kvmppc_pte *pte) | 401 | enum xlate_readwrite xlrw, struct kvmppc_pte *pte) |
373 | { | 402 | { |
403 | bool data = (xlid == XLATE_DATA); | ||
404 | bool iswrite = (xlrw == XLATE_WRITE); | ||
374 | int relocated = (kvmppc_get_msr(vcpu) & (data ? MSR_DR : MSR_IR)); | 405 | int relocated = (kvmppc_get_msr(vcpu) & (data ? MSR_DR : MSR_IR)); |
375 | int r; | 406 | int r; |
376 | 407 | ||
@@ -384,88 +415,34 @@ static int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, bool data, | |||
384 | pte->may_write = true; | 415 | pte->may_write = true; |
385 | pte->may_execute = true; | 416 | pte->may_execute = true; |
386 | r = 0; | 417 | r = 0; |
418 | |||
419 | if ((kvmppc_get_msr(vcpu) & (MSR_IR | MSR_DR)) == MSR_DR && | ||
420 | !data) { | ||
421 | if ((vcpu->arch.hflags & BOOK3S_HFLAG_SPLIT_HACK) && | ||
422 | ((eaddr & SPLIT_HACK_MASK) == SPLIT_HACK_OFFS)) | ||
423 | pte->raddr &= ~SPLIT_HACK_MASK; | ||
424 | } | ||
387 | } | 425 | } |
388 | 426 | ||
389 | return r; | 427 | return r; |
390 | } | 428 | } |
391 | 429 | ||
392 | static hva_t kvmppc_bad_hva(void) | 430 | int kvmppc_load_last_inst(struct kvm_vcpu *vcpu, enum instruction_type type, |
393 | { | 431 | u32 *inst) |
394 | return PAGE_OFFSET; | ||
395 | } | ||
396 | |||
397 | static hva_t kvmppc_pte_to_hva(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte, | ||
398 | bool read) | ||
399 | { | ||
400 | hva_t hpage; | ||
401 | |||
402 | if (read && !pte->may_read) | ||
403 | goto err; | ||
404 | |||
405 | if (!read && !pte->may_write) | ||
406 | goto err; | ||
407 | |||
408 | hpage = gfn_to_hva(vcpu->kvm, pte->raddr >> PAGE_SHIFT); | ||
409 | if (kvm_is_error_hva(hpage)) | ||
410 | goto err; | ||
411 | |||
412 | return hpage | (pte->raddr & ~PAGE_MASK); | ||
413 | err: | ||
414 | return kvmppc_bad_hva(); | ||
415 | } | ||
416 | |||
417 | int kvmppc_st(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr, | ||
418 | bool data) | ||
419 | { | ||
420 | struct kvmppc_pte pte; | ||
421 | |||
422 | vcpu->stat.st++; | ||
423 | |||
424 | if (kvmppc_xlate(vcpu, *eaddr, data, true, &pte)) | ||
425 | return -ENOENT; | ||
426 | |||
427 | *eaddr = pte.raddr; | ||
428 | |||
429 | if (!pte.may_write) | ||
430 | return -EPERM; | ||
431 | |||
432 | if (kvm_write_guest(vcpu->kvm, pte.raddr, ptr, size)) | ||
433 | return EMULATE_DO_MMIO; | ||
434 | |||
435 | return EMULATE_DONE; | ||
436 | } | ||
437 | EXPORT_SYMBOL_GPL(kvmppc_st); | ||
438 | |||
439 | int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr, | ||
440 | bool data) | ||
441 | { | 432 | { |
442 | struct kvmppc_pte pte; | 433 | ulong pc = kvmppc_get_pc(vcpu); |
443 | hva_t hva = *eaddr; | 434 | int r; |
444 | |||
445 | vcpu->stat.ld++; | ||
446 | |||
447 | if (kvmppc_xlate(vcpu, *eaddr, data, false, &pte)) | ||
448 | goto nopte; | ||
449 | |||
450 | *eaddr = pte.raddr; | ||
451 | |||
452 | hva = kvmppc_pte_to_hva(vcpu, &pte, true); | ||
453 | if (kvm_is_error_hva(hva)) | ||
454 | goto mmio; | ||
455 | |||
456 | if (copy_from_user(ptr, (void __user *)hva, size)) { | ||
457 | printk(KERN_INFO "kvmppc_ld at 0x%lx failed\n", hva); | ||
458 | goto mmio; | ||
459 | } | ||
460 | 435 | ||
461 | return EMULATE_DONE; | 436 | if (type == INST_SC) |
437 | pc -= 4; | ||
462 | 438 | ||
463 | nopte: | 439 | r = kvmppc_ld(vcpu, &pc, sizeof(u32), inst, false); |
464 | return -ENOENT; | 440 | if (r == EMULATE_DONE) |
465 | mmio: | 441 | return r; |
466 | return EMULATE_DO_MMIO; | 442 | else |
443 | return EMULATE_AGAIN; | ||
467 | } | 444 | } |
468 | EXPORT_SYMBOL_GPL(kvmppc_ld); | 445 | EXPORT_SYMBOL_GPL(kvmppc_load_last_inst); |
469 | 446 | ||
470 | int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) | 447 | int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) |
471 | { | 448 | { |
@@ -646,6 +623,12 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) | |||
646 | case KVM_REG_PPC_BESCR: | 623 | case KVM_REG_PPC_BESCR: |
647 | val = get_reg_val(reg->id, vcpu->arch.bescr); | 624 | val = get_reg_val(reg->id, vcpu->arch.bescr); |
648 | break; | 625 | break; |
626 | case KVM_REG_PPC_VTB: | ||
627 | val = get_reg_val(reg->id, vcpu->arch.vtb); | ||
628 | break; | ||
629 | case KVM_REG_PPC_IC: | ||
630 | val = get_reg_val(reg->id, vcpu->arch.ic); | ||
631 | break; | ||
649 | default: | 632 | default: |
650 | r = -EINVAL; | 633 | r = -EINVAL; |
651 | break; | 634 | break; |
@@ -750,6 +733,12 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) | |||
750 | case KVM_REG_PPC_BESCR: | 733 | case KVM_REG_PPC_BESCR: |
751 | vcpu->arch.bescr = set_reg_val(reg->id, val); | 734 | vcpu->arch.bescr = set_reg_val(reg->id, val); |
752 | break; | 735 | break; |
736 | case KVM_REG_PPC_VTB: | ||
737 | vcpu->arch.vtb = set_reg_val(reg->id, val); | ||
738 | break; | ||
739 | case KVM_REG_PPC_IC: | ||
740 | vcpu->arch.ic = set_reg_val(reg->id, val); | ||
741 | break; | ||
753 | default: | 742 | default: |
754 | r = -EINVAL; | 743 | r = -EINVAL; |
755 | break; | 744 | break; |
@@ -913,6 +902,11 @@ int kvmppc_core_check_processor_compat(void) | |||
913 | return 0; | 902 | return 0; |
914 | } | 903 | } |
915 | 904 | ||
905 | int kvmppc_book3s_hcall_implemented(struct kvm *kvm, unsigned long hcall) | ||
906 | { | ||
907 | return kvm->arch.kvm_ops->hcall_implemented(hcall); | ||
908 | } | ||
909 | |||
916 | static int kvmppc_book3s_init(void) | 910 | static int kvmppc_book3s_init(void) |
917 | { | 911 | { |
918 | int r; | 912 | int r; |
diff --git a/arch/powerpc/kvm/book3s_32_mmu.c b/arch/powerpc/kvm/book3s_32_mmu.c index 93503bbdae43..cd0b0730e29e 100644 --- a/arch/powerpc/kvm/book3s_32_mmu.c +++ b/arch/powerpc/kvm/book3s_32_mmu.c | |||
@@ -335,7 +335,7 @@ static int kvmppc_mmu_book3s_32_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, | |||
335 | if (r < 0) | 335 | if (r < 0) |
336 | r = kvmppc_mmu_book3s_32_xlate_pte(vcpu, eaddr, pte, | 336 | r = kvmppc_mmu_book3s_32_xlate_pte(vcpu, eaddr, pte, |
337 | data, iswrite, true); | 337 | data, iswrite, true); |
338 | if (r < 0) | 338 | if (r == -ENOENT) |
339 | r = kvmppc_mmu_book3s_32_xlate_pte(vcpu, eaddr, pte, | 339 | r = kvmppc_mmu_book3s_32_xlate_pte(vcpu, eaddr, pte, |
340 | data, iswrite, false); | 340 | data, iswrite, false); |
341 | 341 | ||
diff --git a/arch/powerpc/kvm/book3s_32_mmu_host.c b/arch/powerpc/kvm/book3s_32_mmu_host.c index 678e75370495..2035d16a9262 100644 --- a/arch/powerpc/kvm/book3s_32_mmu_host.c +++ b/arch/powerpc/kvm/book3s_32_mmu_host.c | |||
@@ -156,11 +156,10 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte, | |||
156 | bool writable; | 156 | bool writable; |
157 | 157 | ||
158 | /* Get host physical address for gpa */ | 158 | /* Get host physical address for gpa */ |
159 | hpaddr = kvmppc_gfn_to_pfn(vcpu, orig_pte->raddr >> PAGE_SHIFT, | 159 | hpaddr = kvmppc_gpa_to_pfn(vcpu, orig_pte->raddr, iswrite, &writable); |
160 | iswrite, &writable); | ||
161 | if (is_error_noslot_pfn(hpaddr)) { | 160 | if (is_error_noslot_pfn(hpaddr)) { |
162 | printk(KERN_INFO "Couldn't get guest page for gfn %lx!\n", | 161 | printk(KERN_INFO "Couldn't get guest page for gpa %lx!\n", |
163 | orig_pte->eaddr); | 162 | orig_pte->raddr); |
164 | r = -EINVAL; | 163 | r = -EINVAL; |
165 | goto out; | 164 | goto out; |
166 | } | 165 | } |
diff --git a/arch/powerpc/kvm/book3s_64_mmu_host.c b/arch/powerpc/kvm/book3s_64_mmu_host.c index 0ac98392f363..b982d925c710 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_host.c +++ b/arch/powerpc/kvm/book3s_64_mmu_host.c | |||
@@ -104,9 +104,10 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte, | |||
104 | smp_rmb(); | 104 | smp_rmb(); |
105 | 105 | ||
106 | /* Get host physical address for gpa */ | 106 | /* Get host physical address for gpa */ |
107 | pfn = kvmppc_gfn_to_pfn(vcpu, gfn, iswrite, &writable); | 107 | pfn = kvmppc_gpa_to_pfn(vcpu, orig_pte->raddr, iswrite, &writable); |
108 | if (is_error_noslot_pfn(pfn)) { | 108 | if (is_error_noslot_pfn(pfn)) { |
109 | printk(KERN_INFO "Couldn't get guest page for gfn %lx!\n", gfn); | 109 | printk(KERN_INFO "Couldn't get guest page for gpa %lx!\n", |
110 | orig_pte->raddr); | ||
110 | r = -EINVAL; | 111 | r = -EINVAL; |
111 | goto out; | 112 | goto out; |
112 | } | 113 | } |
diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c index 68468d695f12..72c20bb16d26 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_hv.c +++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c | |||
@@ -37,8 +37,6 @@ | |||
37 | #include <asm/ppc-opcode.h> | 37 | #include <asm/ppc-opcode.h> |
38 | #include <asm/cputable.h> | 38 | #include <asm/cputable.h> |
39 | 39 | ||
40 | #include "book3s_hv_cma.h" | ||
41 | |||
42 | /* POWER7 has 10-bit LPIDs, PPC970 has 6-bit LPIDs */ | 40 | /* POWER7 has 10-bit LPIDs, PPC970 has 6-bit LPIDs */ |
43 | #define MAX_LPID_970 63 | 41 | #define MAX_LPID_970 63 |
44 | 42 | ||
@@ -64,10 +62,10 @@ long kvmppc_alloc_hpt(struct kvm *kvm, u32 *htab_orderp) | |||
64 | } | 62 | } |
65 | 63 | ||
66 | kvm->arch.hpt_cma_alloc = 0; | 64 | kvm->arch.hpt_cma_alloc = 0; |
67 | VM_BUG_ON(order < KVM_CMA_CHUNK_ORDER); | ||
68 | page = kvm_alloc_hpt(1 << (order - PAGE_SHIFT)); | 65 | page = kvm_alloc_hpt(1 << (order - PAGE_SHIFT)); |
69 | if (page) { | 66 | if (page) { |
70 | hpt = (unsigned long)pfn_to_kaddr(page_to_pfn(page)); | 67 | hpt = (unsigned long)pfn_to_kaddr(page_to_pfn(page)); |
68 | memset((void *)hpt, 0, (1 << order)); | ||
71 | kvm->arch.hpt_cma_alloc = 1; | 69 | kvm->arch.hpt_cma_alloc = 1; |
72 | } | 70 | } |
73 | 71 | ||
@@ -450,7 +448,7 @@ static int kvmppc_mmu_book3s_64_hv_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, | |||
450 | unsigned long slb_v; | 448 | unsigned long slb_v; |
451 | unsigned long pp, key; | 449 | unsigned long pp, key; |
452 | unsigned long v, gr; | 450 | unsigned long v, gr; |
453 | unsigned long *hptep; | 451 | __be64 *hptep; |
454 | int index; | 452 | int index; |
455 | int virtmode = vcpu->arch.shregs.msr & (data ? MSR_DR : MSR_IR); | 453 | int virtmode = vcpu->arch.shregs.msr & (data ? MSR_DR : MSR_IR); |
456 | 454 | ||
@@ -473,13 +471,13 @@ static int kvmppc_mmu_book3s_64_hv_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, | |||
473 | preempt_enable(); | 471 | preempt_enable(); |
474 | return -ENOENT; | 472 | return -ENOENT; |
475 | } | 473 | } |
476 | hptep = (unsigned long *)(kvm->arch.hpt_virt + (index << 4)); | 474 | hptep = (__be64 *)(kvm->arch.hpt_virt + (index << 4)); |
477 | v = hptep[0] & ~HPTE_V_HVLOCK; | 475 | v = be64_to_cpu(hptep[0]) & ~HPTE_V_HVLOCK; |
478 | gr = kvm->arch.revmap[index].guest_rpte; | 476 | gr = kvm->arch.revmap[index].guest_rpte; |
479 | 477 | ||
480 | /* Unlock the HPTE */ | 478 | /* Unlock the HPTE */ |
481 | asm volatile("lwsync" : : : "memory"); | 479 | asm volatile("lwsync" : : : "memory"); |
482 | hptep[0] = v; | 480 | hptep[0] = cpu_to_be64(v); |
483 | preempt_enable(); | 481 | preempt_enable(); |
484 | 482 | ||
485 | gpte->eaddr = eaddr; | 483 | gpte->eaddr = eaddr; |
@@ -530,21 +528,14 @@ static int instruction_is_store(unsigned int instr) | |||
530 | static int kvmppc_hv_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu, | 528 | static int kvmppc_hv_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu, |
531 | unsigned long gpa, gva_t ea, int is_store) | 529 | unsigned long gpa, gva_t ea, int is_store) |
532 | { | 530 | { |
533 | int ret; | ||
534 | u32 last_inst; | 531 | u32 last_inst; |
535 | unsigned long srr0 = kvmppc_get_pc(vcpu); | ||
536 | 532 | ||
537 | /* We try to load the last instruction. We don't let | 533 | /* |
538 | * emulate_instruction do it as it doesn't check what | ||
539 | * kvmppc_ld returns. | ||
540 | * If we fail, we just return to the guest and try executing it again. | 534 | * If we fail, we just return to the guest and try executing it again. |
541 | */ | 535 | */ |
542 | if (vcpu->arch.last_inst == KVM_INST_FETCH_FAILED) { | 536 | if (kvmppc_get_last_inst(vcpu, INST_GENERIC, &last_inst) != |
543 | ret = kvmppc_ld(vcpu, &srr0, sizeof(u32), &last_inst, false); | 537 | EMULATE_DONE) |
544 | if (ret != EMULATE_DONE || last_inst == KVM_INST_FETCH_FAILED) | 538 | return RESUME_GUEST; |
545 | return RESUME_GUEST; | ||
546 | vcpu->arch.last_inst = last_inst; | ||
547 | } | ||
548 | 539 | ||
549 | /* | 540 | /* |
550 | * WARNING: We do not know for sure whether the instruction we just | 541 | * WARNING: We do not know for sure whether the instruction we just |
@@ -558,7 +549,7 @@ static int kvmppc_hv_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
558 | * we just return and retry the instruction. | 549 | * we just return and retry the instruction. |
559 | */ | 550 | */ |
560 | 551 | ||
561 | if (instruction_is_store(kvmppc_get_last_inst(vcpu)) != !!is_store) | 552 | if (instruction_is_store(last_inst) != !!is_store) |
562 | return RESUME_GUEST; | 553 | return RESUME_GUEST; |
563 | 554 | ||
564 | /* | 555 | /* |
@@ -583,7 +574,8 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
583 | unsigned long ea, unsigned long dsisr) | 574 | unsigned long ea, unsigned long dsisr) |
584 | { | 575 | { |
585 | struct kvm *kvm = vcpu->kvm; | 576 | struct kvm *kvm = vcpu->kvm; |
586 | unsigned long *hptep, hpte[3], r; | 577 | unsigned long hpte[3], r; |
578 | __be64 *hptep; | ||
587 | unsigned long mmu_seq, psize, pte_size; | 579 | unsigned long mmu_seq, psize, pte_size; |
588 | unsigned long gpa_base, gfn_base; | 580 | unsigned long gpa_base, gfn_base; |
589 | unsigned long gpa, gfn, hva, pfn; | 581 | unsigned long gpa, gfn, hva, pfn; |
@@ -606,16 +598,16 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
606 | if (ea != vcpu->arch.pgfault_addr) | 598 | if (ea != vcpu->arch.pgfault_addr) |
607 | return RESUME_GUEST; | 599 | return RESUME_GUEST; |
608 | index = vcpu->arch.pgfault_index; | 600 | index = vcpu->arch.pgfault_index; |
609 | hptep = (unsigned long *)(kvm->arch.hpt_virt + (index << 4)); | 601 | hptep = (__be64 *)(kvm->arch.hpt_virt + (index << 4)); |
610 | rev = &kvm->arch.revmap[index]; | 602 | rev = &kvm->arch.revmap[index]; |
611 | preempt_disable(); | 603 | preempt_disable(); |
612 | while (!try_lock_hpte(hptep, HPTE_V_HVLOCK)) | 604 | while (!try_lock_hpte(hptep, HPTE_V_HVLOCK)) |
613 | cpu_relax(); | 605 | cpu_relax(); |
614 | hpte[0] = hptep[0] & ~HPTE_V_HVLOCK; | 606 | hpte[0] = be64_to_cpu(hptep[0]) & ~HPTE_V_HVLOCK; |
615 | hpte[1] = hptep[1]; | 607 | hpte[1] = be64_to_cpu(hptep[1]); |
616 | hpte[2] = r = rev->guest_rpte; | 608 | hpte[2] = r = rev->guest_rpte; |
617 | asm volatile("lwsync" : : : "memory"); | 609 | asm volatile("lwsync" : : : "memory"); |
618 | hptep[0] = hpte[0]; | 610 | hptep[0] = cpu_to_be64(hpte[0]); |
619 | preempt_enable(); | 611 | preempt_enable(); |
620 | 612 | ||
621 | if (hpte[0] != vcpu->arch.pgfault_hpte[0] || | 613 | if (hpte[0] != vcpu->arch.pgfault_hpte[0] || |
@@ -731,8 +723,9 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
731 | preempt_disable(); | 723 | preempt_disable(); |
732 | while (!try_lock_hpte(hptep, HPTE_V_HVLOCK)) | 724 | while (!try_lock_hpte(hptep, HPTE_V_HVLOCK)) |
733 | cpu_relax(); | 725 | cpu_relax(); |
734 | if ((hptep[0] & ~HPTE_V_HVLOCK) != hpte[0] || hptep[1] != hpte[1] || | 726 | if ((be64_to_cpu(hptep[0]) & ~HPTE_V_HVLOCK) != hpte[0] || |
735 | rev->guest_rpte != hpte[2]) | 727 | be64_to_cpu(hptep[1]) != hpte[1] || |
728 | rev->guest_rpte != hpte[2]) | ||
736 | /* HPTE has been changed under us; let the guest retry */ | 729 | /* HPTE has been changed under us; let the guest retry */ |
737 | goto out_unlock; | 730 | goto out_unlock; |
738 | hpte[0] = (hpte[0] & ~HPTE_V_ABSENT) | HPTE_V_VALID; | 731 | hpte[0] = (hpte[0] & ~HPTE_V_ABSENT) | HPTE_V_VALID; |
@@ -752,20 +745,20 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
752 | rcbits = *rmap >> KVMPPC_RMAP_RC_SHIFT; | 745 | rcbits = *rmap >> KVMPPC_RMAP_RC_SHIFT; |
753 | r &= rcbits | ~(HPTE_R_R | HPTE_R_C); | 746 | r &= rcbits | ~(HPTE_R_R | HPTE_R_C); |
754 | 747 | ||
755 | if (hptep[0] & HPTE_V_VALID) { | 748 | if (be64_to_cpu(hptep[0]) & HPTE_V_VALID) { |
756 | /* HPTE was previously valid, so we need to invalidate it */ | 749 | /* HPTE was previously valid, so we need to invalidate it */ |
757 | unlock_rmap(rmap); | 750 | unlock_rmap(rmap); |
758 | hptep[0] |= HPTE_V_ABSENT; | 751 | hptep[0] |= cpu_to_be64(HPTE_V_ABSENT); |
759 | kvmppc_invalidate_hpte(kvm, hptep, index); | 752 | kvmppc_invalidate_hpte(kvm, hptep, index); |
760 | /* don't lose previous R and C bits */ | 753 | /* don't lose previous R and C bits */ |
761 | r |= hptep[1] & (HPTE_R_R | HPTE_R_C); | 754 | r |= be64_to_cpu(hptep[1]) & (HPTE_R_R | HPTE_R_C); |
762 | } else { | 755 | } else { |
763 | kvmppc_add_revmap_chain(kvm, rev, rmap, index, 0); | 756 | kvmppc_add_revmap_chain(kvm, rev, rmap, index, 0); |
764 | } | 757 | } |
765 | 758 | ||
766 | hptep[1] = r; | 759 | hptep[1] = cpu_to_be64(r); |
767 | eieio(); | 760 | eieio(); |
768 | hptep[0] = hpte[0]; | 761 | hptep[0] = cpu_to_be64(hpte[0]); |
769 | asm volatile("ptesync" : : : "memory"); | 762 | asm volatile("ptesync" : : : "memory"); |
770 | preempt_enable(); | 763 | preempt_enable(); |
771 | if (page && hpte_is_writable(r)) | 764 | if (page && hpte_is_writable(r)) |
@@ -784,7 +777,7 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
784 | return ret; | 777 | return ret; |
785 | 778 | ||
786 | out_unlock: | 779 | out_unlock: |
787 | hptep[0] &= ~HPTE_V_HVLOCK; | 780 | hptep[0] &= ~cpu_to_be64(HPTE_V_HVLOCK); |
788 | preempt_enable(); | 781 | preempt_enable(); |
789 | goto out_put; | 782 | goto out_put; |
790 | } | 783 | } |
@@ -860,7 +853,7 @@ static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp, | |||
860 | { | 853 | { |
861 | struct revmap_entry *rev = kvm->arch.revmap; | 854 | struct revmap_entry *rev = kvm->arch.revmap; |
862 | unsigned long h, i, j; | 855 | unsigned long h, i, j; |
863 | unsigned long *hptep; | 856 | __be64 *hptep; |
864 | unsigned long ptel, psize, rcbits; | 857 | unsigned long ptel, psize, rcbits; |
865 | 858 | ||
866 | for (;;) { | 859 | for (;;) { |
@@ -876,11 +869,11 @@ static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp, | |||
876 | * rmap chain lock. | 869 | * rmap chain lock. |
877 | */ | 870 | */ |
878 | i = *rmapp & KVMPPC_RMAP_INDEX; | 871 | i = *rmapp & KVMPPC_RMAP_INDEX; |
879 | hptep = (unsigned long *) (kvm->arch.hpt_virt + (i << 4)); | 872 | hptep = (__be64 *) (kvm->arch.hpt_virt + (i << 4)); |
880 | if (!try_lock_hpte(hptep, HPTE_V_HVLOCK)) { | 873 | if (!try_lock_hpte(hptep, HPTE_V_HVLOCK)) { |
881 | /* unlock rmap before spinning on the HPTE lock */ | 874 | /* unlock rmap before spinning on the HPTE lock */ |
882 | unlock_rmap(rmapp); | 875 | unlock_rmap(rmapp); |
883 | while (hptep[0] & HPTE_V_HVLOCK) | 876 | while (be64_to_cpu(hptep[0]) & HPTE_V_HVLOCK) |
884 | cpu_relax(); | 877 | cpu_relax(); |
885 | continue; | 878 | continue; |
886 | } | 879 | } |
@@ -899,14 +892,14 @@ static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp, | |||
899 | 892 | ||
900 | /* Now check and modify the HPTE */ | 893 | /* Now check and modify the HPTE */ |
901 | ptel = rev[i].guest_rpte; | 894 | ptel = rev[i].guest_rpte; |
902 | psize = hpte_page_size(hptep[0], ptel); | 895 | psize = hpte_page_size(be64_to_cpu(hptep[0]), ptel); |
903 | if ((hptep[0] & HPTE_V_VALID) && | 896 | if ((be64_to_cpu(hptep[0]) & HPTE_V_VALID) && |
904 | hpte_rpn(ptel, psize) == gfn) { | 897 | hpte_rpn(ptel, psize) == gfn) { |
905 | if (kvm->arch.using_mmu_notifiers) | 898 | if (kvm->arch.using_mmu_notifiers) |
906 | hptep[0] |= HPTE_V_ABSENT; | 899 | hptep[0] |= cpu_to_be64(HPTE_V_ABSENT); |
907 | kvmppc_invalidate_hpte(kvm, hptep, i); | 900 | kvmppc_invalidate_hpte(kvm, hptep, i); |
908 | /* Harvest R and C */ | 901 | /* Harvest R and C */ |
909 | rcbits = hptep[1] & (HPTE_R_R | HPTE_R_C); | 902 | rcbits = be64_to_cpu(hptep[1]) & (HPTE_R_R | HPTE_R_C); |
910 | *rmapp |= rcbits << KVMPPC_RMAP_RC_SHIFT; | 903 | *rmapp |= rcbits << KVMPPC_RMAP_RC_SHIFT; |
911 | if (rcbits & ~rev[i].guest_rpte) { | 904 | if (rcbits & ~rev[i].guest_rpte) { |
912 | rev[i].guest_rpte = ptel | rcbits; | 905 | rev[i].guest_rpte = ptel | rcbits; |
@@ -914,7 +907,7 @@ static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp, | |||
914 | } | 907 | } |
915 | } | 908 | } |
916 | unlock_rmap(rmapp); | 909 | unlock_rmap(rmapp); |
917 | hptep[0] &= ~HPTE_V_HVLOCK; | 910 | hptep[0] &= ~cpu_to_be64(HPTE_V_HVLOCK); |
918 | } | 911 | } |
919 | return 0; | 912 | return 0; |
920 | } | 913 | } |
@@ -961,7 +954,7 @@ static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp, | |||
961 | { | 954 | { |
962 | struct revmap_entry *rev = kvm->arch.revmap; | 955 | struct revmap_entry *rev = kvm->arch.revmap; |
963 | unsigned long head, i, j; | 956 | unsigned long head, i, j; |
964 | unsigned long *hptep; | 957 | __be64 *hptep; |
965 | int ret = 0; | 958 | int ret = 0; |
966 | 959 | ||
967 | retry: | 960 | retry: |
@@ -977,23 +970,24 @@ static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp, | |||
977 | 970 | ||
978 | i = head = *rmapp & KVMPPC_RMAP_INDEX; | 971 | i = head = *rmapp & KVMPPC_RMAP_INDEX; |
979 | do { | 972 | do { |
980 | hptep = (unsigned long *) (kvm->arch.hpt_virt + (i << 4)); | 973 | hptep = (__be64 *) (kvm->arch.hpt_virt + (i << 4)); |
981 | j = rev[i].forw; | 974 | j = rev[i].forw; |
982 | 975 | ||
983 | /* If this HPTE isn't referenced, ignore it */ | 976 | /* If this HPTE isn't referenced, ignore it */ |
984 | if (!(hptep[1] & HPTE_R_R)) | 977 | if (!(be64_to_cpu(hptep[1]) & HPTE_R_R)) |
985 | continue; | 978 | continue; |
986 | 979 | ||
987 | if (!try_lock_hpte(hptep, HPTE_V_HVLOCK)) { | 980 | if (!try_lock_hpte(hptep, HPTE_V_HVLOCK)) { |
988 | /* unlock rmap before spinning on the HPTE lock */ | 981 | /* unlock rmap before spinning on the HPTE lock */ |
989 | unlock_rmap(rmapp); | 982 | unlock_rmap(rmapp); |
990 | while (hptep[0] & HPTE_V_HVLOCK) | 983 | while (be64_to_cpu(hptep[0]) & HPTE_V_HVLOCK) |
991 | cpu_relax(); | 984 | cpu_relax(); |
992 | goto retry; | 985 | goto retry; |
993 | } | 986 | } |
994 | 987 | ||
995 | /* Now check and modify the HPTE */ | 988 | /* Now check and modify the HPTE */ |
996 | if ((hptep[0] & HPTE_V_VALID) && (hptep[1] & HPTE_R_R)) { | 989 | if ((be64_to_cpu(hptep[0]) & HPTE_V_VALID) && |
990 | (be64_to_cpu(hptep[1]) & HPTE_R_R)) { | ||
997 | kvmppc_clear_ref_hpte(kvm, hptep, i); | 991 | kvmppc_clear_ref_hpte(kvm, hptep, i); |
998 | if (!(rev[i].guest_rpte & HPTE_R_R)) { | 992 | if (!(rev[i].guest_rpte & HPTE_R_R)) { |
999 | rev[i].guest_rpte |= HPTE_R_R; | 993 | rev[i].guest_rpte |= HPTE_R_R; |
@@ -1001,7 +995,7 @@ static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp, | |||
1001 | } | 995 | } |
1002 | ret = 1; | 996 | ret = 1; |
1003 | } | 997 | } |
1004 | hptep[0] &= ~HPTE_V_HVLOCK; | 998 | hptep[0] &= ~cpu_to_be64(HPTE_V_HVLOCK); |
1005 | } while ((i = j) != head); | 999 | } while ((i = j) != head); |
1006 | 1000 | ||
1007 | unlock_rmap(rmapp); | 1001 | unlock_rmap(rmapp); |
@@ -1035,7 +1029,7 @@ static int kvm_test_age_rmapp(struct kvm *kvm, unsigned long *rmapp, | |||
1035 | do { | 1029 | do { |
1036 | hp = (unsigned long *)(kvm->arch.hpt_virt + (i << 4)); | 1030 | hp = (unsigned long *)(kvm->arch.hpt_virt + (i << 4)); |
1037 | j = rev[i].forw; | 1031 | j = rev[i].forw; |
1038 | if (hp[1] & HPTE_R_R) | 1032 | if (be64_to_cpu(hp[1]) & HPTE_R_R) |
1039 | goto out; | 1033 | goto out; |
1040 | } while ((i = j) != head); | 1034 | } while ((i = j) != head); |
1041 | } | 1035 | } |
@@ -1075,7 +1069,7 @@ static int kvm_test_clear_dirty_npages(struct kvm *kvm, unsigned long *rmapp) | |||
1075 | unsigned long head, i, j; | 1069 | unsigned long head, i, j; |
1076 | unsigned long n; | 1070 | unsigned long n; |
1077 | unsigned long v, r; | 1071 | unsigned long v, r; |
1078 | unsigned long *hptep; | 1072 | __be64 *hptep; |
1079 | int npages_dirty = 0; | 1073 | int npages_dirty = 0; |
1080 | 1074 | ||
1081 | retry: | 1075 | retry: |
@@ -1091,7 +1085,8 @@ static int kvm_test_clear_dirty_npages(struct kvm *kvm, unsigned long *rmapp) | |||
1091 | 1085 | ||
1092 | i = head = *rmapp & KVMPPC_RMAP_INDEX; | 1086 | i = head = *rmapp & KVMPPC_RMAP_INDEX; |
1093 | do { | 1087 | do { |
1094 | hptep = (unsigned long *) (kvm->arch.hpt_virt + (i << 4)); | 1088 | unsigned long hptep1; |
1089 | hptep = (__be64 *) (kvm->arch.hpt_virt + (i << 4)); | ||
1095 | j = rev[i].forw; | 1090 | j = rev[i].forw; |
1096 | 1091 | ||
1097 | /* | 1092 | /* |
@@ -1108,29 +1103,30 @@ static int kvm_test_clear_dirty_npages(struct kvm *kvm, unsigned long *rmapp) | |||
1108 | * Otherwise we need to do the tlbie even if C==0 in | 1103 | * Otherwise we need to do the tlbie even if C==0 in |
1109 | * order to pick up any delayed writeback of C. | 1104 | * order to pick up any delayed writeback of C. |
1110 | */ | 1105 | */ |
1111 | if (!(hptep[1] & HPTE_R_C) && | 1106 | hptep1 = be64_to_cpu(hptep[1]); |
1112 | (!hpte_is_writable(hptep[1]) || vcpus_running(kvm))) | 1107 | if (!(hptep1 & HPTE_R_C) && |
1108 | (!hpte_is_writable(hptep1) || vcpus_running(kvm))) | ||
1113 | continue; | 1109 | continue; |
1114 | 1110 | ||
1115 | if (!try_lock_hpte(hptep, HPTE_V_HVLOCK)) { | 1111 | if (!try_lock_hpte(hptep, HPTE_V_HVLOCK)) { |
1116 | /* unlock rmap before spinning on the HPTE lock */ | 1112 | /* unlock rmap before spinning on the HPTE lock */ |
1117 | unlock_rmap(rmapp); | 1113 | unlock_rmap(rmapp); |
1118 | while (hptep[0] & HPTE_V_HVLOCK) | 1114 | while (hptep[0] & cpu_to_be64(HPTE_V_HVLOCK)) |
1119 | cpu_relax(); | 1115 | cpu_relax(); |
1120 | goto retry; | 1116 | goto retry; |
1121 | } | 1117 | } |
1122 | 1118 | ||
1123 | /* Now check and modify the HPTE */ | 1119 | /* Now check and modify the HPTE */ |
1124 | if (!(hptep[0] & HPTE_V_VALID)) | 1120 | if (!(hptep[0] & cpu_to_be64(HPTE_V_VALID))) |
1125 | continue; | 1121 | continue; |
1126 | 1122 | ||
1127 | /* need to make it temporarily absent so C is stable */ | 1123 | /* need to make it temporarily absent so C is stable */ |
1128 | hptep[0] |= HPTE_V_ABSENT; | 1124 | hptep[0] |= cpu_to_be64(HPTE_V_ABSENT); |
1129 | kvmppc_invalidate_hpte(kvm, hptep, i); | 1125 | kvmppc_invalidate_hpte(kvm, hptep, i); |
1130 | v = hptep[0]; | 1126 | v = be64_to_cpu(hptep[0]); |
1131 | r = hptep[1]; | 1127 | r = be64_to_cpu(hptep[1]); |
1132 | if (r & HPTE_R_C) { | 1128 | if (r & HPTE_R_C) { |
1133 | hptep[1] = r & ~HPTE_R_C; | 1129 | hptep[1] = cpu_to_be64(r & ~HPTE_R_C); |
1134 | if (!(rev[i].guest_rpte & HPTE_R_C)) { | 1130 | if (!(rev[i].guest_rpte & HPTE_R_C)) { |
1135 | rev[i].guest_rpte |= HPTE_R_C; | 1131 | rev[i].guest_rpte |= HPTE_R_C; |
1136 | note_hpte_modification(kvm, &rev[i]); | 1132 | note_hpte_modification(kvm, &rev[i]); |
@@ -1143,7 +1139,7 @@ static int kvm_test_clear_dirty_npages(struct kvm *kvm, unsigned long *rmapp) | |||
1143 | } | 1139 | } |
1144 | v &= ~(HPTE_V_ABSENT | HPTE_V_HVLOCK); | 1140 | v &= ~(HPTE_V_ABSENT | HPTE_V_HVLOCK); |
1145 | v |= HPTE_V_VALID; | 1141 | v |= HPTE_V_VALID; |
1146 | hptep[0] = v; | 1142 | hptep[0] = cpu_to_be64(v); |
1147 | } while ((i = j) != head); | 1143 | } while ((i = j) != head); |
1148 | 1144 | ||
1149 | unlock_rmap(rmapp); | 1145 | unlock_rmap(rmapp); |
@@ -1307,7 +1303,7 @@ struct kvm_htab_ctx { | |||
1307 | * Returns 1 if this HPT entry has been modified or has pending | 1303 | * Returns 1 if this HPT entry has been modified or has pending |
1308 | * R/C bit changes. | 1304 | * R/C bit changes. |
1309 | */ | 1305 | */ |
1310 | static int hpte_dirty(struct revmap_entry *revp, unsigned long *hptp) | 1306 | static int hpte_dirty(struct revmap_entry *revp, __be64 *hptp) |
1311 | { | 1307 | { |
1312 | unsigned long rcbits_unset; | 1308 | unsigned long rcbits_unset; |
1313 | 1309 | ||
@@ -1316,13 +1312,14 @@ static int hpte_dirty(struct revmap_entry *revp, unsigned long *hptp) | |||
1316 | 1312 | ||
1317 | /* Also need to consider changes in reference and changed bits */ | 1313 | /* Also need to consider changes in reference and changed bits */ |
1318 | rcbits_unset = ~revp->guest_rpte & (HPTE_R_R | HPTE_R_C); | 1314 | rcbits_unset = ~revp->guest_rpte & (HPTE_R_R | HPTE_R_C); |
1319 | if ((hptp[0] & HPTE_V_VALID) && (hptp[1] & rcbits_unset)) | 1315 | if ((be64_to_cpu(hptp[0]) & HPTE_V_VALID) && |
1316 | (be64_to_cpu(hptp[1]) & rcbits_unset)) | ||
1320 | return 1; | 1317 | return 1; |
1321 | 1318 | ||
1322 | return 0; | 1319 | return 0; |
1323 | } | 1320 | } |
1324 | 1321 | ||
1325 | static long record_hpte(unsigned long flags, unsigned long *hptp, | 1322 | static long record_hpte(unsigned long flags, __be64 *hptp, |
1326 | unsigned long *hpte, struct revmap_entry *revp, | 1323 | unsigned long *hpte, struct revmap_entry *revp, |
1327 | int want_valid, int first_pass) | 1324 | int want_valid, int first_pass) |
1328 | { | 1325 | { |
@@ -1337,10 +1334,10 @@ static long record_hpte(unsigned long flags, unsigned long *hptp, | |||
1337 | return 0; | 1334 | return 0; |
1338 | 1335 | ||
1339 | valid = 0; | 1336 | valid = 0; |
1340 | if (hptp[0] & (HPTE_V_VALID | HPTE_V_ABSENT)) { | 1337 | if (be64_to_cpu(hptp[0]) & (HPTE_V_VALID | HPTE_V_ABSENT)) { |
1341 | valid = 1; | 1338 | valid = 1; |
1342 | if ((flags & KVM_GET_HTAB_BOLTED_ONLY) && | 1339 | if ((flags & KVM_GET_HTAB_BOLTED_ONLY) && |
1343 | !(hptp[0] & HPTE_V_BOLTED)) | 1340 | !(be64_to_cpu(hptp[0]) & HPTE_V_BOLTED)) |
1344 | valid = 0; | 1341 | valid = 0; |
1345 | } | 1342 | } |
1346 | if (valid != want_valid) | 1343 | if (valid != want_valid) |
@@ -1352,7 +1349,7 @@ static long record_hpte(unsigned long flags, unsigned long *hptp, | |||
1352 | preempt_disable(); | 1349 | preempt_disable(); |
1353 | while (!try_lock_hpte(hptp, HPTE_V_HVLOCK)) | 1350 | while (!try_lock_hpte(hptp, HPTE_V_HVLOCK)) |
1354 | cpu_relax(); | 1351 | cpu_relax(); |
1355 | v = hptp[0]; | 1352 | v = be64_to_cpu(hptp[0]); |
1356 | 1353 | ||
1357 | /* re-evaluate valid and dirty from synchronized HPTE value */ | 1354 | /* re-evaluate valid and dirty from synchronized HPTE value */ |
1358 | valid = !!(v & HPTE_V_VALID); | 1355 | valid = !!(v & HPTE_V_VALID); |
@@ -1360,9 +1357,9 @@ static long record_hpte(unsigned long flags, unsigned long *hptp, | |||
1360 | 1357 | ||
1361 | /* Harvest R and C into guest view if necessary */ | 1358 | /* Harvest R and C into guest view if necessary */ |
1362 | rcbits_unset = ~revp->guest_rpte & (HPTE_R_R | HPTE_R_C); | 1359 | rcbits_unset = ~revp->guest_rpte & (HPTE_R_R | HPTE_R_C); |
1363 | if (valid && (rcbits_unset & hptp[1])) { | 1360 | if (valid && (rcbits_unset & be64_to_cpu(hptp[1]))) { |
1364 | revp->guest_rpte |= (hptp[1] & (HPTE_R_R | HPTE_R_C)) | | 1361 | revp->guest_rpte |= (be64_to_cpu(hptp[1]) & |
1365 | HPTE_GR_MODIFIED; | 1362 | (HPTE_R_R | HPTE_R_C)) | HPTE_GR_MODIFIED; |
1366 | dirty = 1; | 1363 | dirty = 1; |
1367 | } | 1364 | } |
1368 | 1365 | ||
@@ -1381,13 +1378,13 @@ static long record_hpte(unsigned long flags, unsigned long *hptp, | |||
1381 | revp->guest_rpte = r; | 1378 | revp->guest_rpte = r; |
1382 | } | 1379 | } |
1383 | asm volatile(PPC_RELEASE_BARRIER "" : : : "memory"); | 1380 | asm volatile(PPC_RELEASE_BARRIER "" : : : "memory"); |
1384 | hptp[0] &= ~HPTE_V_HVLOCK; | 1381 | hptp[0] &= ~cpu_to_be64(HPTE_V_HVLOCK); |
1385 | preempt_enable(); | 1382 | preempt_enable(); |
1386 | if (!(valid == want_valid && (first_pass || dirty))) | 1383 | if (!(valid == want_valid && (first_pass || dirty))) |
1387 | ok = 0; | 1384 | ok = 0; |
1388 | } | 1385 | } |
1389 | hpte[0] = v; | 1386 | hpte[0] = cpu_to_be64(v); |
1390 | hpte[1] = r; | 1387 | hpte[1] = cpu_to_be64(r); |
1391 | return ok; | 1388 | return ok; |
1392 | } | 1389 | } |
1393 | 1390 | ||
@@ -1397,7 +1394,7 @@ static ssize_t kvm_htab_read(struct file *file, char __user *buf, | |||
1397 | struct kvm_htab_ctx *ctx = file->private_data; | 1394 | struct kvm_htab_ctx *ctx = file->private_data; |
1398 | struct kvm *kvm = ctx->kvm; | 1395 | struct kvm *kvm = ctx->kvm; |
1399 | struct kvm_get_htab_header hdr; | 1396 | struct kvm_get_htab_header hdr; |
1400 | unsigned long *hptp; | 1397 | __be64 *hptp; |
1401 | struct revmap_entry *revp; | 1398 | struct revmap_entry *revp; |
1402 | unsigned long i, nb, nw; | 1399 | unsigned long i, nb, nw; |
1403 | unsigned long __user *lbuf; | 1400 | unsigned long __user *lbuf; |
@@ -1413,7 +1410,7 @@ static ssize_t kvm_htab_read(struct file *file, char __user *buf, | |||
1413 | flags = ctx->flags; | 1410 | flags = ctx->flags; |
1414 | 1411 | ||
1415 | i = ctx->index; | 1412 | i = ctx->index; |
1416 | hptp = (unsigned long *)(kvm->arch.hpt_virt + (i * HPTE_SIZE)); | 1413 | hptp = (__be64 *)(kvm->arch.hpt_virt + (i * HPTE_SIZE)); |
1417 | revp = kvm->arch.revmap + i; | 1414 | revp = kvm->arch.revmap + i; |
1418 | lbuf = (unsigned long __user *)buf; | 1415 | lbuf = (unsigned long __user *)buf; |
1419 | 1416 | ||
@@ -1497,7 +1494,7 @@ static ssize_t kvm_htab_write(struct file *file, const char __user *buf, | |||
1497 | unsigned long i, j; | 1494 | unsigned long i, j; |
1498 | unsigned long v, r; | 1495 | unsigned long v, r; |
1499 | unsigned long __user *lbuf; | 1496 | unsigned long __user *lbuf; |
1500 | unsigned long *hptp; | 1497 | __be64 *hptp; |
1501 | unsigned long tmp[2]; | 1498 | unsigned long tmp[2]; |
1502 | ssize_t nb; | 1499 | ssize_t nb; |
1503 | long int err, ret; | 1500 | long int err, ret; |
@@ -1539,7 +1536,7 @@ static ssize_t kvm_htab_write(struct file *file, const char __user *buf, | |||
1539 | i + hdr.n_valid + hdr.n_invalid > kvm->arch.hpt_npte) | 1536 | i + hdr.n_valid + hdr.n_invalid > kvm->arch.hpt_npte) |
1540 | break; | 1537 | break; |
1541 | 1538 | ||
1542 | hptp = (unsigned long *)(kvm->arch.hpt_virt + (i * HPTE_SIZE)); | 1539 | hptp = (__be64 *)(kvm->arch.hpt_virt + (i * HPTE_SIZE)); |
1543 | lbuf = (unsigned long __user *)buf; | 1540 | lbuf = (unsigned long __user *)buf; |
1544 | for (j = 0; j < hdr.n_valid; ++j) { | 1541 | for (j = 0; j < hdr.n_valid; ++j) { |
1545 | err = -EFAULT; | 1542 | err = -EFAULT; |
@@ -1551,7 +1548,7 @@ static ssize_t kvm_htab_write(struct file *file, const char __user *buf, | |||
1551 | lbuf += 2; | 1548 | lbuf += 2; |
1552 | nb += HPTE_SIZE; | 1549 | nb += HPTE_SIZE; |
1553 | 1550 | ||
1554 | if (hptp[0] & (HPTE_V_VALID | HPTE_V_ABSENT)) | 1551 | if (be64_to_cpu(hptp[0]) & (HPTE_V_VALID | HPTE_V_ABSENT)) |
1555 | kvmppc_do_h_remove(kvm, 0, i, 0, tmp); | 1552 | kvmppc_do_h_remove(kvm, 0, i, 0, tmp); |
1556 | err = -EIO; | 1553 | err = -EIO; |
1557 | ret = kvmppc_virtmode_do_h_enter(kvm, H_EXACT, i, v, r, | 1554 | ret = kvmppc_virtmode_do_h_enter(kvm, H_EXACT, i, v, r, |
@@ -1577,7 +1574,7 @@ static ssize_t kvm_htab_write(struct file *file, const char __user *buf, | |||
1577 | } | 1574 | } |
1578 | 1575 | ||
1579 | for (j = 0; j < hdr.n_invalid; ++j) { | 1576 | for (j = 0; j < hdr.n_invalid; ++j) { |
1580 | if (hptp[0] & (HPTE_V_VALID | HPTE_V_ABSENT)) | 1577 | if (be64_to_cpu(hptp[0]) & (HPTE_V_VALID | HPTE_V_ABSENT)) |
1581 | kvmppc_do_h_remove(kvm, 0, i, 0, tmp); | 1578 | kvmppc_do_h_remove(kvm, 0, i, 0, tmp); |
1582 | ++i; | 1579 | ++i; |
1583 | hptp += 2; | 1580 | hptp += 2; |
diff --git a/arch/powerpc/kvm/book3s_emulate.c b/arch/powerpc/kvm/book3s_emulate.c index 3f295269af37..5a2bc4b0dfe5 100644 --- a/arch/powerpc/kvm/book3s_emulate.c +++ b/arch/powerpc/kvm/book3s_emulate.c | |||
@@ -439,12 +439,6 @@ int kvmppc_core_emulate_mtspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val) | |||
439 | (mfmsr() & MSR_HV)) | 439 | (mfmsr() & MSR_HV)) |
440 | vcpu->arch.hflags |= BOOK3S_HFLAG_DCBZ32; | 440 | vcpu->arch.hflags |= BOOK3S_HFLAG_DCBZ32; |
441 | break; | 441 | break; |
442 | case SPRN_PURR: | ||
443 | to_book3s(vcpu)->purr_offset = spr_val - get_tb(); | ||
444 | break; | ||
445 | case SPRN_SPURR: | ||
446 | to_book3s(vcpu)->spurr_offset = spr_val - get_tb(); | ||
447 | break; | ||
448 | case SPRN_GQR0: | 442 | case SPRN_GQR0: |
449 | case SPRN_GQR1: | 443 | case SPRN_GQR1: |
450 | case SPRN_GQR2: | 444 | case SPRN_GQR2: |
@@ -455,10 +449,10 @@ int kvmppc_core_emulate_mtspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val) | |||
455 | case SPRN_GQR7: | 449 | case SPRN_GQR7: |
456 | to_book3s(vcpu)->gqr[sprn - SPRN_GQR0] = spr_val; | 450 | to_book3s(vcpu)->gqr[sprn - SPRN_GQR0] = spr_val; |
457 | break; | 451 | break; |
452 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
458 | case SPRN_FSCR: | 453 | case SPRN_FSCR: |
459 | vcpu->arch.fscr = spr_val; | 454 | kvmppc_set_fscr(vcpu, spr_val); |
460 | break; | 455 | break; |
461 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
462 | case SPRN_BESCR: | 456 | case SPRN_BESCR: |
463 | vcpu->arch.bescr = spr_val; | 457 | vcpu->arch.bescr = spr_val; |
464 | break; | 458 | break; |
@@ -572,10 +566,22 @@ int kvmppc_core_emulate_mfspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val | |||
572 | *spr_val = 0; | 566 | *spr_val = 0; |
573 | break; | 567 | break; |
574 | case SPRN_PURR: | 568 | case SPRN_PURR: |
575 | *spr_val = get_tb() + to_book3s(vcpu)->purr_offset; | 569 | /* |
570 | * On exit we would have updated purr | ||
571 | */ | ||
572 | *spr_val = vcpu->arch.purr; | ||
576 | break; | 573 | break; |
577 | case SPRN_SPURR: | 574 | case SPRN_SPURR: |
578 | *spr_val = get_tb() + to_book3s(vcpu)->purr_offset; | 575 | /* |
576 | * On exit we would have updated spurr | ||
577 | */ | ||
578 | *spr_val = vcpu->arch.spurr; | ||
579 | break; | ||
580 | case SPRN_VTB: | ||
581 | *spr_val = vcpu->arch.vtb; | ||
582 | break; | ||
583 | case SPRN_IC: | ||
584 | *spr_val = vcpu->arch.ic; | ||
579 | break; | 585 | break; |
580 | case SPRN_GQR0: | 586 | case SPRN_GQR0: |
581 | case SPRN_GQR1: | 587 | case SPRN_GQR1: |
@@ -587,10 +593,10 @@ int kvmppc_core_emulate_mfspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val | |||
587 | case SPRN_GQR7: | 593 | case SPRN_GQR7: |
588 | *spr_val = to_book3s(vcpu)->gqr[sprn - SPRN_GQR0]; | 594 | *spr_val = to_book3s(vcpu)->gqr[sprn - SPRN_GQR0]; |
589 | break; | 595 | break; |
596 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
590 | case SPRN_FSCR: | 597 | case SPRN_FSCR: |
591 | *spr_val = vcpu->arch.fscr; | 598 | *spr_val = vcpu->arch.fscr; |
592 | break; | 599 | break; |
593 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
594 | case SPRN_BESCR: | 600 | case SPRN_BESCR: |
595 | *spr_val = vcpu->arch.bescr; | 601 | *spr_val = vcpu->arch.bescr; |
596 | break; | 602 | break; |
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index 7a12edbb61e7..27cced9c7249 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c | |||
@@ -35,6 +35,7 @@ | |||
35 | 35 | ||
36 | #include <asm/reg.h> | 36 | #include <asm/reg.h> |
37 | #include <asm/cputable.h> | 37 | #include <asm/cputable.h> |
38 | #include <asm/cache.h> | ||
38 | #include <asm/cacheflush.h> | 39 | #include <asm/cacheflush.h> |
39 | #include <asm/tlbflush.h> | 40 | #include <asm/tlbflush.h> |
40 | #include <asm/uaccess.h> | 41 | #include <asm/uaccess.h> |
@@ -67,6 +68,15 @@ | |||
67 | /* Used as a "null" value for timebase values */ | 68 | /* Used as a "null" value for timebase values */ |
68 | #define TB_NIL (~(u64)0) | 69 | #define TB_NIL (~(u64)0) |
69 | 70 | ||
71 | static DECLARE_BITMAP(default_enabled_hcalls, MAX_HCALL_OPCODE/4 + 1); | ||
72 | |||
73 | #if defined(CONFIG_PPC_64K_PAGES) | ||
74 | #define MPP_BUFFER_ORDER 0 | ||
75 | #elif defined(CONFIG_PPC_4K_PAGES) | ||
76 | #define MPP_BUFFER_ORDER 3 | ||
77 | #endif | ||
78 | |||
79 | |||
70 | static void kvmppc_end_cede(struct kvm_vcpu *vcpu); | 80 | static void kvmppc_end_cede(struct kvm_vcpu *vcpu); |
71 | static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu); | 81 | static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu); |
72 | 82 | ||
@@ -270,7 +280,7 @@ struct kvm_vcpu *kvmppc_find_vcpu(struct kvm *kvm, int id) | |||
270 | static void init_vpa(struct kvm_vcpu *vcpu, struct lppaca *vpa) | 280 | static void init_vpa(struct kvm_vcpu *vcpu, struct lppaca *vpa) |
271 | { | 281 | { |
272 | vpa->__old_status |= LPPACA_OLD_SHARED_PROC; | 282 | vpa->__old_status |= LPPACA_OLD_SHARED_PROC; |
273 | vpa->yield_count = 1; | 283 | vpa->yield_count = cpu_to_be32(1); |
274 | } | 284 | } |
275 | 285 | ||
276 | static int set_vpa(struct kvm_vcpu *vcpu, struct kvmppc_vpa *v, | 286 | static int set_vpa(struct kvm_vcpu *vcpu, struct kvmppc_vpa *v, |
@@ -293,8 +303,8 @@ static int set_vpa(struct kvm_vcpu *vcpu, struct kvmppc_vpa *v, | |||
293 | struct reg_vpa { | 303 | struct reg_vpa { |
294 | u32 dummy; | 304 | u32 dummy; |
295 | union { | 305 | union { |
296 | u16 hword; | 306 | __be16 hword; |
297 | u32 word; | 307 | __be32 word; |
298 | } length; | 308 | } length; |
299 | }; | 309 | }; |
300 | 310 | ||
@@ -333,9 +343,9 @@ static unsigned long do_h_register_vpa(struct kvm_vcpu *vcpu, | |||
333 | if (va == NULL) | 343 | if (va == NULL) |
334 | return H_PARAMETER; | 344 | return H_PARAMETER; |
335 | if (subfunc == H_VPA_REG_VPA) | 345 | if (subfunc == H_VPA_REG_VPA) |
336 | len = ((struct reg_vpa *)va)->length.hword; | 346 | len = be16_to_cpu(((struct reg_vpa *)va)->length.hword); |
337 | else | 347 | else |
338 | len = ((struct reg_vpa *)va)->length.word; | 348 | len = be32_to_cpu(((struct reg_vpa *)va)->length.word); |
339 | kvmppc_unpin_guest_page(kvm, va, vpa, false); | 349 | kvmppc_unpin_guest_page(kvm, va, vpa, false); |
340 | 350 | ||
341 | /* Check length */ | 351 | /* Check length */ |
@@ -540,21 +550,63 @@ static void kvmppc_create_dtl_entry(struct kvm_vcpu *vcpu, | |||
540 | return; | 550 | return; |
541 | memset(dt, 0, sizeof(struct dtl_entry)); | 551 | memset(dt, 0, sizeof(struct dtl_entry)); |
542 | dt->dispatch_reason = 7; | 552 | dt->dispatch_reason = 7; |
543 | dt->processor_id = vc->pcpu + vcpu->arch.ptid; | 553 | dt->processor_id = cpu_to_be16(vc->pcpu + vcpu->arch.ptid); |
544 | dt->timebase = now + vc->tb_offset; | 554 | dt->timebase = cpu_to_be64(now + vc->tb_offset); |
545 | dt->enqueue_to_dispatch_time = stolen; | 555 | dt->enqueue_to_dispatch_time = cpu_to_be32(stolen); |
546 | dt->srr0 = kvmppc_get_pc(vcpu); | 556 | dt->srr0 = cpu_to_be64(kvmppc_get_pc(vcpu)); |
547 | dt->srr1 = vcpu->arch.shregs.msr; | 557 | dt->srr1 = cpu_to_be64(vcpu->arch.shregs.msr); |
548 | ++dt; | 558 | ++dt; |
549 | if (dt == vcpu->arch.dtl.pinned_end) | 559 | if (dt == vcpu->arch.dtl.pinned_end) |
550 | dt = vcpu->arch.dtl.pinned_addr; | 560 | dt = vcpu->arch.dtl.pinned_addr; |
551 | vcpu->arch.dtl_ptr = dt; | 561 | vcpu->arch.dtl_ptr = dt; |
552 | /* order writing *dt vs. writing vpa->dtl_idx */ | 562 | /* order writing *dt vs. writing vpa->dtl_idx */ |
553 | smp_wmb(); | 563 | smp_wmb(); |
554 | vpa->dtl_idx = ++vcpu->arch.dtl_index; | 564 | vpa->dtl_idx = cpu_to_be64(++vcpu->arch.dtl_index); |
555 | vcpu->arch.dtl.dirty = true; | 565 | vcpu->arch.dtl.dirty = true; |
556 | } | 566 | } |
557 | 567 | ||
568 | static bool kvmppc_power8_compatible(struct kvm_vcpu *vcpu) | ||
569 | { | ||
570 | if (vcpu->arch.vcore->arch_compat >= PVR_ARCH_207) | ||
571 | return true; | ||
572 | if ((!vcpu->arch.vcore->arch_compat) && | ||
573 | cpu_has_feature(CPU_FTR_ARCH_207S)) | ||
574 | return true; | ||
575 | return false; | ||
576 | } | ||
577 | |||
578 | static int kvmppc_h_set_mode(struct kvm_vcpu *vcpu, unsigned long mflags, | ||
579 | unsigned long resource, unsigned long value1, | ||
580 | unsigned long value2) | ||
581 | { | ||
582 | switch (resource) { | ||
583 | case H_SET_MODE_RESOURCE_SET_CIABR: | ||
584 | if (!kvmppc_power8_compatible(vcpu)) | ||
585 | return H_P2; | ||
586 | if (value2) | ||
587 | return H_P4; | ||
588 | if (mflags) | ||
589 | return H_UNSUPPORTED_FLAG_START; | ||
590 | /* Guests can't breakpoint the hypervisor */ | ||
591 | if ((value1 & CIABR_PRIV) == CIABR_PRIV_HYPER) | ||
592 | return H_P3; | ||
593 | vcpu->arch.ciabr = value1; | ||
594 | return H_SUCCESS; | ||
595 | case H_SET_MODE_RESOURCE_SET_DAWR: | ||
596 | if (!kvmppc_power8_compatible(vcpu)) | ||
597 | return H_P2; | ||
598 | if (mflags) | ||
599 | return H_UNSUPPORTED_FLAG_START; | ||
600 | if (value2 & DABRX_HYP) | ||
601 | return H_P4; | ||
602 | vcpu->arch.dawr = value1; | ||
603 | vcpu->arch.dawrx = value2; | ||
604 | return H_SUCCESS; | ||
605 | default: | ||
606 | return H_TOO_HARD; | ||
607 | } | ||
608 | } | ||
609 | |||
558 | int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu) | 610 | int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu) |
559 | { | 611 | { |
560 | unsigned long req = kvmppc_get_gpr(vcpu, 3); | 612 | unsigned long req = kvmppc_get_gpr(vcpu, 3); |
@@ -562,6 +614,10 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu) | |||
562 | struct kvm_vcpu *tvcpu; | 614 | struct kvm_vcpu *tvcpu; |
563 | int idx, rc; | 615 | int idx, rc; |
564 | 616 | ||
617 | if (req <= MAX_HCALL_OPCODE && | ||
618 | !test_bit(req/4, vcpu->kvm->arch.enabled_hcalls)) | ||
619 | return RESUME_HOST; | ||
620 | |||
565 | switch (req) { | 621 | switch (req) { |
566 | case H_ENTER: | 622 | case H_ENTER: |
567 | idx = srcu_read_lock(&vcpu->kvm->srcu); | 623 | idx = srcu_read_lock(&vcpu->kvm->srcu); |
@@ -620,7 +676,14 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu) | |||
620 | 676 | ||
621 | /* Send the error out to userspace via KVM_RUN */ | 677 | /* Send the error out to userspace via KVM_RUN */ |
622 | return rc; | 678 | return rc; |
623 | 679 | case H_SET_MODE: | |
680 | ret = kvmppc_h_set_mode(vcpu, kvmppc_get_gpr(vcpu, 4), | ||
681 | kvmppc_get_gpr(vcpu, 5), | ||
682 | kvmppc_get_gpr(vcpu, 6), | ||
683 | kvmppc_get_gpr(vcpu, 7)); | ||
684 | if (ret == H_TOO_HARD) | ||
685 | return RESUME_HOST; | ||
686 | break; | ||
624 | case H_XIRR: | 687 | case H_XIRR: |
625 | case H_CPPR: | 688 | case H_CPPR: |
626 | case H_EOI: | 689 | case H_EOI: |
@@ -639,6 +702,29 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu) | |||
639 | return RESUME_GUEST; | 702 | return RESUME_GUEST; |
640 | } | 703 | } |
641 | 704 | ||
705 | static int kvmppc_hcall_impl_hv(unsigned long cmd) | ||
706 | { | ||
707 | switch (cmd) { | ||
708 | case H_CEDE: | ||
709 | case H_PROD: | ||
710 | case H_CONFER: | ||
711 | case H_REGISTER_VPA: | ||
712 | case H_SET_MODE: | ||
713 | #ifdef CONFIG_KVM_XICS | ||
714 | case H_XIRR: | ||
715 | case H_CPPR: | ||
716 | case H_EOI: | ||
717 | case H_IPI: | ||
718 | case H_IPOLL: | ||
719 | case H_XIRR_X: | ||
720 | #endif | ||
721 | return 1; | ||
722 | } | ||
723 | |||
724 | /* See if it's in the real-mode table */ | ||
725 | return kvmppc_hcall_impl_hv_realmode(cmd); | ||
726 | } | ||
727 | |||
642 | static int kvmppc_handle_exit_hv(struct kvm_run *run, struct kvm_vcpu *vcpu, | 728 | static int kvmppc_handle_exit_hv(struct kvm_run *run, struct kvm_vcpu *vcpu, |
643 | struct task_struct *tsk) | 729 | struct task_struct *tsk) |
644 | { | 730 | { |
@@ -785,7 +871,8 @@ static int kvm_arch_vcpu_ioctl_set_sregs_hv(struct kvm_vcpu *vcpu, | |||
785 | return 0; | 871 | return 0; |
786 | } | 872 | } |
787 | 873 | ||
788 | static void kvmppc_set_lpcr(struct kvm_vcpu *vcpu, u64 new_lpcr) | 874 | static void kvmppc_set_lpcr(struct kvm_vcpu *vcpu, u64 new_lpcr, |
875 | bool preserve_top32) | ||
789 | { | 876 | { |
790 | struct kvmppc_vcore *vc = vcpu->arch.vcore; | 877 | struct kvmppc_vcore *vc = vcpu->arch.vcore; |
791 | u64 mask; | 878 | u64 mask; |
@@ -820,6 +907,10 @@ static void kvmppc_set_lpcr(struct kvm_vcpu *vcpu, u64 new_lpcr) | |||
820 | mask = LPCR_DPFD | LPCR_ILE | LPCR_TC; | 907 | mask = LPCR_DPFD | LPCR_ILE | LPCR_TC; |
821 | if (cpu_has_feature(CPU_FTR_ARCH_207S)) | 908 | if (cpu_has_feature(CPU_FTR_ARCH_207S)) |
822 | mask |= LPCR_AIL; | 909 | mask |= LPCR_AIL; |
910 | |||
911 | /* Broken 32-bit version of LPCR must not clear top bits */ | ||
912 | if (preserve_top32) | ||
913 | mask &= 0xFFFFFFFF; | ||
823 | vc->lpcr = (vc->lpcr & ~mask) | (new_lpcr & mask); | 914 | vc->lpcr = (vc->lpcr & ~mask) | (new_lpcr & mask); |
824 | spin_unlock(&vc->lock); | 915 | spin_unlock(&vc->lock); |
825 | } | 916 | } |
@@ -894,12 +985,6 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id, | |||
894 | case KVM_REG_PPC_CIABR: | 985 | case KVM_REG_PPC_CIABR: |
895 | *val = get_reg_val(id, vcpu->arch.ciabr); | 986 | *val = get_reg_val(id, vcpu->arch.ciabr); |
896 | break; | 987 | break; |
897 | case KVM_REG_PPC_IC: | ||
898 | *val = get_reg_val(id, vcpu->arch.ic); | ||
899 | break; | ||
900 | case KVM_REG_PPC_VTB: | ||
901 | *val = get_reg_val(id, vcpu->arch.vtb); | ||
902 | break; | ||
903 | case KVM_REG_PPC_CSIGR: | 988 | case KVM_REG_PPC_CSIGR: |
904 | *val = get_reg_val(id, vcpu->arch.csigr); | 989 | *val = get_reg_val(id, vcpu->arch.csigr); |
905 | break; | 990 | break; |
@@ -939,6 +1024,7 @@ static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id, | |||
939 | *val = get_reg_val(id, vcpu->arch.vcore->tb_offset); | 1024 | *val = get_reg_val(id, vcpu->arch.vcore->tb_offset); |
940 | break; | 1025 | break; |
941 | case KVM_REG_PPC_LPCR: | 1026 | case KVM_REG_PPC_LPCR: |
1027 | case KVM_REG_PPC_LPCR_64: | ||
942 | *val = get_reg_val(id, vcpu->arch.vcore->lpcr); | 1028 | *val = get_reg_val(id, vcpu->arch.vcore->lpcr); |
943 | break; | 1029 | break; |
944 | case KVM_REG_PPC_PPR: | 1030 | case KVM_REG_PPC_PPR: |
@@ -1094,12 +1180,6 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id, | |||
1094 | if ((vcpu->arch.ciabr & CIABR_PRIV) == CIABR_PRIV_HYPER) | 1180 | if ((vcpu->arch.ciabr & CIABR_PRIV) == CIABR_PRIV_HYPER) |
1095 | vcpu->arch.ciabr &= ~CIABR_PRIV; /* disable */ | 1181 | vcpu->arch.ciabr &= ~CIABR_PRIV; /* disable */ |
1096 | break; | 1182 | break; |
1097 | case KVM_REG_PPC_IC: | ||
1098 | vcpu->arch.ic = set_reg_val(id, *val); | ||
1099 | break; | ||
1100 | case KVM_REG_PPC_VTB: | ||
1101 | vcpu->arch.vtb = set_reg_val(id, *val); | ||
1102 | break; | ||
1103 | case KVM_REG_PPC_CSIGR: | 1183 | case KVM_REG_PPC_CSIGR: |
1104 | vcpu->arch.csigr = set_reg_val(id, *val); | 1184 | vcpu->arch.csigr = set_reg_val(id, *val); |
1105 | break; | 1185 | break; |
@@ -1150,7 +1230,10 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id, | |||
1150 | ALIGN(set_reg_val(id, *val), 1UL << 24); | 1230 | ALIGN(set_reg_val(id, *val), 1UL << 24); |
1151 | break; | 1231 | break; |
1152 | case KVM_REG_PPC_LPCR: | 1232 | case KVM_REG_PPC_LPCR: |
1153 | kvmppc_set_lpcr(vcpu, set_reg_val(id, *val)); | 1233 | kvmppc_set_lpcr(vcpu, set_reg_val(id, *val), true); |
1234 | break; | ||
1235 | case KVM_REG_PPC_LPCR_64: | ||
1236 | kvmppc_set_lpcr(vcpu, set_reg_val(id, *val), false); | ||
1154 | break; | 1237 | break; |
1155 | case KVM_REG_PPC_PPR: | 1238 | case KVM_REG_PPC_PPR: |
1156 | vcpu->arch.ppr = set_reg_val(id, *val); | 1239 | vcpu->arch.ppr = set_reg_val(id, *val); |
@@ -1228,6 +1311,33 @@ static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id, | |||
1228 | return r; | 1311 | return r; |
1229 | } | 1312 | } |
1230 | 1313 | ||
1314 | static struct kvmppc_vcore *kvmppc_vcore_create(struct kvm *kvm, int core) | ||
1315 | { | ||
1316 | struct kvmppc_vcore *vcore; | ||
1317 | |||
1318 | vcore = kzalloc(sizeof(struct kvmppc_vcore), GFP_KERNEL); | ||
1319 | |||
1320 | if (vcore == NULL) | ||
1321 | return NULL; | ||
1322 | |||
1323 | INIT_LIST_HEAD(&vcore->runnable_threads); | ||
1324 | spin_lock_init(&vcore->lock); | ||
1325 | init_waitqueue_head(&vcore->wq); | ||
1326 | vcore->preempt_tb = TB_NIL; | ||
1327 | vcore->lpcr = kvm->arch.lpcr; | ||
1328 | vcore->first_vcpuid = core * threads_per_subcore; | ||
1329 | vcore->kvm = kvm; | ||
1330 | |||
1331 | vcore->mpp_buffer_is_valid = false; | ||
1332 | |||
1333 | if (cpu_has_feature(CPU_FTR_ARCH_207S)) | ||
1334 | vcore->mpp_buffer = (void *)__get_free_pages( | ||
1335 | GFP_KERNEL|__GFP_ZERO, | ||
1336 | MPP_BUFFER_ORDER); | ||
1337 | |||
1338 | return vcore; | ||
1339 | } | ||
1340 | |||
1231 | static struct kvm_vcpu *kvmppc_core_vcpu_create_hv(struct kvm *kvm, | 1341 | static struct kvm_vcpu *kvmppc_core_vcpu_create_hv(struct kvm *kvm, |
1232 | unsigned int id) | 1342 | unsigned int id) |
1233 | { | 1343 | { |
@@ -1279,16 +1389,7 @@ static struct kvm_vcpu *kvmppc_core_vcpu_create_hv(struct kvm *kvm, | |||
1279 | mutex_lock(&kvm->lock); | 1389 | mutex_lock(&kvm->lock); |
1280 | vcore = kvm->arch.vcores[core]; | 1390 | vcore = kvm->arch.vcores[core]; |
1281 | if (!vcore) { | 1391 | if (!vcore) { |
1282 | vcore = kzalloc(sizeof(struct kvmppc_vcore), GFP_KERNEL); | 1392 | vcore = kvmppc_vcore_create(kvm, core); |
1283 | if (vcore) { | ||
1284 | INIT_LIST_HEAD(&vcore->runnable_threads); | ||
1285 | spin_lock_init(&vcore->lock); | ||
1286 | init_waitqueue_head(&vcore->wq); | ||
1287 | vcore->preempt_tb = TB_NIL; | ||
1288 | vcore->lpcr = kvm->arch.lpcr; | ||
1289 | vcore->first_vcpuid = core * threads_per_subcore; | ||
1290 | vcore->kvm = kvm; | ||
1291 | } | ||
1292 | kvm->arch.vcores[core] = vcore; | 1393 | kvm->arch.vcores[core] = vcore; |
1293 | kvm->arch.online_vcores++; | 1394 | kvm->arch.online_vcores++; |
1294 | } | 1395 | } |
@@ -1500,6 +1601,33 @@ static int on_primary_thread(void) | |||
1500 | return 1; | 1601 | return 1; |
1501 | } | 1602 | } |
1502 | 1603 | ||
1604 | static void kvmppc_start_saving_l2_cache(struct kvmppc_vcore *vc) | ||
1605 | { | ||
1606 | phys_addr_t phy_addr, mpp_addr; | ||
1607 | |||
1608 | phy_addr = (phys_addr_t)virt_to_phys(vc->mpp_buffer); | ||
1609 | mpp_addr = phy_addr & PPC_MPPE_ADDRESS_MASK; | ||
1610 | |||
1611 | mtspr(SPRN_MPPR, mpp_addr | PPC_MPPR_FETCH_ABORT); | ||
1612 | logmpp(mpp_addr | PPC_LOGMPP_LOG_L2); | ||
1613 | |||
1614 | vc->mpp_buffer_is_valid = true; | ||
1615 | } | ||
1616 | |||
1617 | static void kvmppc_start_restoring_l2_cache(const struct kvmppc_vcore *vc) | ||
1618 | { | ||
1619 | phys_addr_t phy_addr, mpp_addr; | ||
1620 | |||
1621 | phy_addr = virt_to_phys(vc->mpp_buffer); | ||
1622 | mpp_addr = phy_addr & PPC_MPPE_ADDRESS_MASK; | ||
1623 | |||
1624 | /* We must abort any in-progress save operations to ensure | ||
1625 | * the table is valid so that prefetch engine knows when to | ||
1626 | * stop prefetching. */ | ||
1627 | logmpp(mpp_addr | PPC_LOGMPP_LOG_ABORT); | ||
1628 | mtspr(SPRN_MPPR, mpp_addr | PPC_MPPR_FETCH_WHOLE_TABLE); | ||
1629 | } | ||
1630 | |||
1503 | /* | 1631 | /* |
1504 | * Run a set of guest threads on a physical core. | 1632 | * Run a set of guest threads on a physical core. |
1505 | * Called with vc->lock held. | 1633 | * Called with vc->lock held. |
@@ -1577,9 +1705,16 @@ static void kvmppc_run_core(struct kvmppc_vcore *vc) | |||
1577 | 1705 | ||
1578 | srcu_idx = srcu_read_lock(&vc->kvm->srcu); | 1706 | srcu_idx = srcu_read_lock(&vc->kvm->srcu); |
1579 | 1707 | ||
1708 | if (vc->mpp_buffer_is_valid) | ||
1709 | kvmppc_start_restoring_l2_cache(vc); | ||
1710 | |||
1580 | __kvmppc_vcore_entry(); | 1711 | __kvmppc_vcore_entry(); |
1581 | 1712 | ||
1582 | spin_lock(&vc->lock); | 1713 | spin_lock(&vc->lock); |
1714 | |||
1715 | if (vc->mpp_buffer) | ||
1716 | kvmppc_start_saving_l2_cache(vc); | ||
1717 | |||
1583 | /* disable sending of IPIs on virtual external irqs */ | 1718 | /* disable sending of IPIs on virtual external irqs */ |
1584 | list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list) | 1719 | list_for_each_entry(vcpu, &vc->runnable_threads, arch.run_list) |
1585 | vcpu->cpu = -1; | 1720 | vcpu->cpu = -1; |
@@ -1929,12 +2064,6 @@ static void kvmppc_add_seg_page_size(struct kvm_ppc_one_seg_page_size **sps, | |||
1929 | (*sps)->page_shift = def->shift; | 2064 | (*sps)->page_shift = def->shift; |
1930 | (*sps)->slb_enc = def->sllp; | 2065 | (*sps)->slb_enc = def->sllp; |
1931 | (*sps)->enc[0].page_shift = def->shift; | 2066 | (*sps)->enc[0].page_shift = def->shift; |
1932 | /* | ||
1933 | * Only return base page encoding. We don't want to return | ||
1934 | * all the supporting pte_enc, because our H_ENTER doesn't | ||
1935 | * support MPSS yet. Once they do, we can start passing all | ||
1936 | * support pte_enc here | ||
1937 | */ | ||
1938 | (*sps)->enc[0].pte_enc = def->penc[linux_psize]; | 2067 | (*sps)->enc[0].pte_enc = def->penc[linux_psize]; |
1939 | /* | 2068 | /* |
1940 | * Add 16MB MPSS support if host supports it | 2069 | * Add 16MB MPSS support if host supports it |
@@ -2281,6 +2410,10 @@ static int kvmppc_core_init_vm_hv(struct kvm *kvm) | |||
2281 | */ | 2410 | */ |
2282 | cpumask_setall(&kvm->arch.need_tlb_flush); | 2411 | cpumask_setall(&kvm->arch.need_tlb_flush); |
2283 | 2412 | ||
2413 | /* Start out with the default set of hcalls enabled */ | ||
2414 | memcpy(kvm->arch.enabled_hcalls, default_enabled_hcalls, | ||
2415 | sizeof(kvm->arch.enabled_hcalls)); | ||
2416 | |||
2284 | kvm->arch.rma = NULL; | 2417 | kvm->arch.rma = NULL; |
2285 | 2418 | ||
2286 | kvm->arch.host_sdr1 = mfspr(SPRN_SDR1); | 2419 | kvm->arch.host_sdr1 = mfspr(SPRN_SDR1); |
@@ -2323,8 +2456,14 @@ static void kvmppc_free_vcores(struct kvm *kvm) | |||
2323 | { | 2456 | { |
2324 | long int i; | 2457 | long int i; |
2325 | 2458 | ||
2326 | for (i = 0; i < KVM_MAX_VCORES; ++i) | 2459 | for (i = 0; i < KVM_MAX_VCORES; ++i) { |
2460 | if (kvm->arch.vcores[i] && kvm->arch.vcores[i]->mpp_buffer) { | ||
2461 | struct kvmppc_vcore *vc = kvm->arch.vcores[i]; | ||
2462 | free_pages((unsigned long)vc->mpp_buffer, | ||
2463 | MPP_BUFFER_ORDER); | ||
2464 | } | ||
2327 | kfree(kvm->arch.vcores[i]); | 2465 | kfree(kvm->arch.vcores[i]); |
2466 | } | ||
2328 | kvm->arch.online_vcores = 0; | 2467 | kvm->arch.online_vcores = 0; |
2329 | } | 2468 | } |
2330 | 2469 | ||
@@ -2419,6 +2558,49 @@ static long kvm_arch_vm_ioctl_hv(struct file *filp, | |||
2419 | return r; | 2558 | return r; |
2420 | } | 2559 | } |
2421 | 2560 | ||
2561 | /* | ||
2562 | * List of hcall numbers to enable by default. | ||
2563 | * For compatibility with old userspace, we enable by default | ||
2564 | * all hcalls that were implemented before the hcall-enabling | ||
2565 | * facility was added. Note this list should not include H_RTAS. | ||
2566 | */ | ||
2567 | static unsigned int default_hcall_list[] = { | ||
2568 | H_REMOVE, | ||
2569 | H_ENTER, | ||
2570 | H_READ, | ||
2571 | H_PROTECT, | ||
2572 | H_BULK_REMOVE, | ||
2573 | H_GET_TCE, | ||
2574 | H_PUT_TCE, | ||
2575 | H_SET_DABR, | ||
2576 | H_SET_XDABR, | ||
2577 | H_CEDE, | ||
2578 | H_PROD, | ||
2579 | H_CONFER, | ||
2580 | H_REGISTER_VPA, | ||
2581 | #ifdef CONFIG_KVM_XICS | ||
2582 | H_EOI, | ||
2583 | H_CPPR, | ||
2584 | H_IPI, | ||
2585 | H_IPOLL, | ||
2586 | H_XIRR, | ||
2587 | H_XIRR_X, | ||
2588 | #endif | ||
2589 | 0 | ||
2590 | }; | ||
2591 | |||
2592 | static void init_default_hcalls(void) | ||
2593 | { | ||
2594 | int i; | ||
2595 | unsigned int hcall; | ||
2596 | |||
2597 | for (i = 0; default_hcall_list[i]; ++i) { | ||
2598 | hcall = default_hcall_list[i]; | ||
2599 | WARN_ON(!kvmppc_hcall_impl_hv(hcall)); | ||
2600 | __set_bit(hcall / 4, default_enabled_hcalls); | ||
2601 | } | ||
2602 | } | ||
2603 | |||
2422 | static struct kvmppc_ops kvm_ops_hv = { | 2604 | static struct kvmppc_ops kvm_ops_hv = { |
2423 | .get_sregs = kvm_arch_vcpu_ioctl_get_sregs_hv, | 2605 | .get_sregs = kvm_arch_vcpu_ioctl_get_sregs_hv, |
2424 | .set_sregs = kvm_arch_vcpu_ioctl_set_sregs_hv, | 2606 | .set_sregs = kvm_arch_vcpu_ioctl_set_sregs_hv, |
@@ -2451,6 +2633,7 @@ static struct kvmppc_ops kvm_ops_hv = { | |||
2451 | .emulate_mfspr = kvmppc_core_emulate_mfspr_hv, | 2633 | .emulate_mfspr = kvmppc_core_emulate_mfspr_hv, |
2452 | .fast_vcpu_kick = kvmppc_fast_vcpu_kick_hv, | 2634 | .fast_vcpu_kick = kvmppc_fast_vcpu_kick_hv, |
2453 | .arch_vm_ioctl = kvm_arch_vm_ioctl_hv, | 2635 | .arch_vm_ioctl = kvm_arch_vm_ioctl_hv, |
2636 | .hcall_implemented = kvmppc_hcall_impl_hv, | ||
2454 | }; | 2637 | }; |
2455 | 2638 | ||
2456 | static int kvmppc_book3s_init_hv(void) | 2639 | static int kvmppc_book3s_init_hv(void) |
@@ -2466,6 +2649,8 @@ static int kvmppc_book3s_init_hv(void) | |||
2466 | kvm_ops_hv.owner = THIS_MODULE; | 2649 | kvm_ops_hv.owner = THIS_MODULE; |
2467 | kvmppc_hv_ops = &kvm_ops_hv; | 2650 | kvmppc_hv_ops = &kvm_ops_hv; |
2468 | 2651 | ||
2652 | init_default_hcalls(); | ||
2653 | |||
2469 | r = kvmppc_mmu_hv_init(); | 2654 | r = kvmppc_mmu_hv_init(); |
2470 | return r; | 2655 | return r; |
2471 | } | 2656 | } |
diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c index 7cde8a665205..329d7fdd0a6a 100644 --- a/arch/powerpc/kvm/book3s_hv_builtin.c +++ b/arch/powerpc/kvm/book3s_hv_builtin.c | |||
@@ -16,12 +16,14 @@ | |||
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/memblock.h> | 17 | #include <linux/memblock.h> |
18 | #include <linux/sizes.h> | 18 | #include <linux/sizes.h> |
19 | #include <linux/cma.h> | ||
19 | 20 | ||
20 | #include <asm/cputable.h> | 21 | #include <asm/cputable.h> |
21 | #include <asm/kvm_ppc.h> | 22 | #include <asm/kvm_ppc.h> |
22 | #include <asm/kvm_book3s.h> | 23 | #include <asm/kvm_book3s.h> |
23 | 24 | ||
24 | #include "book3s_hv_cma.h" | 25 | #define KVM_CMA_CHUNK_ORDER 18 |
26 | |||
25 | /* | 27 | /* |
26 | * Hash page table alignment on newer cpus(CPU_FTR_ARCH_206) | 28 | * Hash page table alignment on newer cpus(CPU_FTR_ARCH_206) |
27 | * should be power of 2. | 29 | * should be power of 2. |
@@ -43,6 +45,8 @@ static unsigned long kvm_cma_resv_ratio = 5; | |||
43 | unsigned long kvm_rma_pages = (1 << 27) >> PAGE_SHIFT; /* 128MB */ | 45 | unsigned long kvm_rma_pages = (1 << 27) >> PAGE_SHIFT; /* 128MB */ |
44 | EXPORT_SYMBOL_GPL(kvm_rma_pages); | 46 | EXPORT_SYMBOL_GPL(kvm_rma_pages); |
45 | 47 | ||
48 | static struct cma *kvm_cma; | ||
49 | |||
46 | /* Work out RMLS (real mode limit selector) field value for a given RMA size. | 50 | /* Work out RMLS (real mode limit selector) field value for a given RMA size. |
47 | Assumes POWER7 or PPC970. */ | 51 | Assumes POWER7 or PPC970. */ |
48 | static inline int lpcr_rmls(unsigned long rma_size) | 52 | static inline int lpcr_rmls(unsigned long rma_size) |
@@ -97,7 +101,7 @@ struct kvm_rma_info *kvm_alloc_rma() | |||
97 | ri = kmalloc(sizeof(struct kvm_rma_info), GFP_KERNEL); | 101 | ri = kmalloc(sizeof(struct kvm_rma_info), GFP_KERNEL); |
98 | if (!ri) | 102 | if (!ri) |
99 | return NULL; | 103 | return NULL; |
100 | page = kvm_alloc_cma(kvm_rma_pages, kvm_rma_pages); | 104 | page = cma_alloc(kvm_cma, kvm_rma_pages, get_order(kvm_rma_pages)); |
101 | if (!page) | 105 | if (!page) |
102 | goto err_out; | 106 | goto err_out; |
103 | atomic_set(&ri->use_count, 1); | 107 | atomic_set(&ri->use_count, 1); |
@@ -112,7 +116,7 @@ EXPORT_SYMBOL_GPL(kvm_alloc_rma); | |||
112 | void kvm_release_rma(struct kvm_rma_info *ri) | 116 | void kvm_release_rma(struct kvm_rma_info *ri) |
113 | { | 117 | { |
114 | if (atomic_dec_and_test(&ri->use_count)) { | 118 | if (atomic_dec_and_test(&ri->use_count)) { |
115 | kvm_release_cma(pfn_to_page(ri->base_pfn), kvm_rma_pages); | 119 | cma_release(kvm_cma, pfn_to_page(ri->base_pfn), kvm_rma_pages); |
116 | kfree(ri); | 120 | kfree(ri); |
117 | } | 121 | } |
118 | } | 122 | } |
@@ -131,16 +135,18 @@ struct page *kvm_alloc_hpt(unsigned long nr_pages) | |||
131 | { | 135 | { |
132 | unsigned long align_pages = HPT_ALIGN_PAGES; | 136 | unsigned long align_pages = HPT_ALIGN_PAGES; |
133 | 137 | ||
138 | VM_BUG_ON(get_order(nr_pages) < KVM_CMA_CHUNK_ORDER - PAGE_SHIFT); | ||
139 | |||
134 | /* Old CPUs require HPT aligned on a multiple of its size */ | 140 | /* Old CPUs require HPT aligned on a multiple of its size */ |
135 | if (!cpu_has_feature(CPU_FTR_ARCH_206)) | 141 | if (!cpu_has_feature(CPU_FTR_ARCH_206)) |
136 | align_pages = nr_pages; | 142 | align_pages = nr_pages; |
137 | return kvm_alloc_cma(nr_pages, align_pages); | 143 | return cma_alloc(kvm_cma, nr_pages, get_order(align_pages)); |
138 | } | 144 | } |
139 | EXPORT_SYMBOL_GPL(kvm_alloc_hpt); | 145 | EXPORT_SYMBOL_GPL(kvm_alloc_hpt); |
140 | 146 | ||
141 | void kvm_release_hpt(struct page *page, unsigned long nr_pages) | 147 | void kvm_release_hpt(struct page *page, unsigned long nr_pages) |
142 | { | 148 | { |
143 | kvm_release_cma(page, nr_pages); | 149 | cma_release(kvm_cma, page, nr_pages); |
144 | } | 150 | } |
145 | EXPORT_SYMBOL_GPL(kvm_release_hpt); | 151 | EXPORT_SYMBOL_GPL(kvm_release_hpt); |
146 | 152 | ||
@@ -179,7 +185,8 @@ void __init kvm_cma_reserve(void) | |||
179 | align_size = HPT_ALIGN_PAGES << PAGE_SHIFT; | 185 | align_size = HPT_ALIGN_PAGES << PAGE_SHIFT; |
180 | 186 | ||
181 | align_size = max(kvm_rma_pages << PAGE_SHIFT, align_size); | 187 | align_size = max(kvm_rma_pages << PAGE_SHIFT, align_size); |
182 | kvm_cma_declare_contiguous(selected_size, align_size); | 188 | cma_declare_contiguous(0, selected_size, 0, align_size, |
189 | KVM_CMA_CHUNK_ORDER - PAGE_SHIFT, false, &kvm_cma); | ||
183 | } | 190 | } |
184 | } | 191 | } |
185 | 192 | ||
@@ -212,3 +219,16 @@ bool kvm_hv_mode_active(void) | |||
212 | { | 219 | { |
213 | return atomic_read(&hv_vm_count) != 0; | 220 | return atomic_read(&hv_vm_count) != 0; |
214 | } | 221 | } |
222 | |||
223 | extern int hcall_real_table[], hcall_real_table_end[]; | ||
224 | |||
225 | int kvmppc_hcall_impl_hv_realmode(unsigned long cmd) | ||
226 | { | ||
227 | cmd /= 4; | ||
228 | if (cmd < hcall_real_table_end - hcall_real_table && | ||
229 | hcall_real_table[cmd]) | ||
230 | return 1; | ||
231 | |||
232 | return 0; | ||
233 | } | ||
234 | EXPORT_SYMBOL_GPL(kvmppc_hcall_impl_hv_realmode); | ||
diff --git a/arch/powerpc/kvm/book3s_hv_cma.c b/arch/powerpc/kvm/book3s_hv_cma.c deleted file mode 100644 index d9d3d8553d51..000000000000 --- a/arch/powerpc/kvm/book3s_hv_cma.c +++ /dev/null | |||
@@ -1,240 +0,0 @@ | |||
1 | /* | ||
2 | * Contiguous Memory Allocator for ppc KVM hash pagetable based on CMA | ||
3 | * for DMA mapping framework | ||
4 | * | ||
5 | * Copyright IBM Corporation, 2013 | ||
6 | * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License as | ||
10 | * published by the Free Software Foundation; either version 2 of the | ||
11 | * License or (at your optional) any later version of the license. | ||
12 | * | ||
13 | */ | ||
14 | #define pr_fmt(fmt) "kvm_cma: " fmt | ||
15 | |||
16 | #ifdef CONFIG_CMA_DEBUG | ||
17 | #ifndef DEBUG | ||
18 | # define DEBUG | ||
19 | #endif | ||
20 | #endif | ||
21 | |||
22 | #include <linux/memblock.h> | ||
23 | #include <linux/mutex.h> | ||
24 | #include <linux/sizes.h> | ||
25 | #include <linux/slab.h> | ||
26 | |||
27 | #include "book3s_hv_cma.h" | ||
28 | |||
29 | struct kvm_cma { | ||
30 | unsigned long base_pfn; | ||
31 | unsigned long count; | ||
32 | unsigned long *bitmap; | ||
33 | }; | ||
34 | |||
35 | static DEFINE_MUTEX(kvm_cma_mutex); | ||
36 | static struct kvm_cma kvm_cma_area; | ||
37 | |||
38 | /** | ||
39 | * kvm_cma_declare_contiguous() - reserve area for contiguous memory handling | ||
40 | * for kvm hash pagetable | ||
41 | * @size: Size of the reserved memory. | ||
42 | * @alignment: Alignment for the contiguous memory area | ||
43 | * | ||
44 | * This function reserves memory for kvm cma area. It should be | ||
45 | * called by arch code when early allocator (memblock or bootmem) | ||
46 | * is still activate. | ||
47 | */ | ||
48 | long __init kvm_cma_declare_contiguous(phys_addr_t size, phys_addr_t alignment) | ||
49 | { | ||
50 | long base_pfn; | ||
51 | phys_addr_t addr; | ||
52 | struct kvm_cma *cma = &kvm_cma_area; | ||
53 | |||
54 | pr_debug("%s(size %lx)\n", __func__, (unsigned long)size); | ||
55 | |||
56 | if (!size) | ||
57 | return -EINVAL; | ||
58 | /* | ||
59 | * Sanitise input arguments. | ||
60 | * We should be pageblock aligned for CMA. | ||
61 | */ | ||
62 | alignment = max(alignment, (phys_addr_t)(PAGE_SIZE << pageblock_order)); | ||
63 | size = ALIGN(size, alignment); | ||
64 | /* | ||
65 | * Reserve memory | ||
66 | * Use __memblock_alloc_base() since | ||
67 | * memblock_alloc_base() panic()s. | ||
68 | */ | ||
69 | addr = __memblock_alloc_base(size, alignment, 0); | ||
70 | if (!addr) { | ||
71 | base_pfn = -ENOMEM; | ||
72 | goto err; | ||
73 | } else | ||
74 | base_pfn = PFN_DOWN(addr); | ||
75 | |||
76 | /* | ||
77 | * Each reserved area must be initialised later, when more kernel | ||
78 | * subsystems (like slab allocator) are available. | ||
79 | */ | ||
80 | cma->base_pfn = base_pfn; | ||
81 | cma->count = size >> PAGE_SHIFT; | ||
82 | pr_info("CMA: reserved %ld MiB\n", (unsigned long)size / SZ_1M); | ||
83 | return 0; | ||
84 | err: | ||
85 | pr_err("CMA: failed to reserve %ld MiB\n", (unsigned long)size / SZ_1M); | ||
86 | return base_pfn; | ||
87 | } | ||
88 | |||
89 | /** | ||
90 | * kvm_alloc_cma() - allocate pages from contiguous area | ||
91 | * @nr_pages: Requested number of pages. | ||
92 | * @align_pages: Requested alignment in number of pages | ||
93 | * | ||
94 | * This function allocates memory buffer for hash pagetable. | ||
95 | */ | ||
96 | struct page *kvm_alloc_cma(unsigned long nr_pages, unsigned long align_pages) | ||
97 | { | ||
98 | int ret; | ||
99 | struct page *page = NULL; | ||
100 | struct kvm_cma *cma = &kvm_cma_area; | ||
101 | unsigned long chunk_count, nr_chunk; | ||
102 | unsigned long mask, pfn, pageno, start = 0; | ||
103 | |||
104 | |||
105 | if (!cma || !cma->count) | ||
106 | return NULL; | ||
107 | |||
108 | pr_debug("%s(cma %p, count %lu, align pages %lu)\n", __func__, | ||
109 | (void *)cma, nr_pages, align_pages); | ||
110 | |||
111 | if (!nr_pages) | ||
112 | return NULL; | ||
113 | /* | ||
114 | * align mask with chunk size. The bit tracks pages in chunk size | ||
115 | */ | ||
116 | VM_BUG_ON(!is_power_of_2(align_pages)); | ||
117 | mask = (align_pages >> (KVM_CMA_CHUNK_ORDER - PAGE_SHIFT)) - 1; | ||
118 | BUILD_BUG_ON(PAGE_SHIFT > KVM_CMA_CHUNK_ORDER); | ||
119 | |||
120 | chunk_count = cma->count >> (KVM_CMA_CHUNK_ORDER - PAGE_SHIFT); | ||
121 | nr_chunk = nr_pages >> (KVM_CMA_CHUNK_ORDER - PAGE_SHIFT); | ||
122 | |||
123 | mutex_lock(&kvm_cma_mutex); | ||
124 | for (;;) { | ||
125 | pageno = bitmap_find_next_zero_area(cma->bitmap, chunk_count, | ||
126 | start, nr_chunk, mask); | ||
127 | if (pageno >= chunk_count) | ||
128 | break; | ||
129 | |||
130 | pfn = cma->base_pfn + (pageno << (KVM_CMA_CHUNK_ORDER - PAGE_SHIFT)); | ||
131 | ret = alloc_contig_range(pfn, pfn + nr_pages, MIGRATE_CMA); | ||
132 | if (ret == 0) { | ||
133 | bitmap_set(cma->bitmap, pageno, nr_chunk); | ||
134 | page = pfn_to_page(pfn); | ||
135 | memset(pfn_to_kaddr(pfn), 0, nr_pages << PAGE_SHIFT); | ||
136 | break; | ||
137 | } else if (ret != -EBUSY) { | ||
138 | break; | ||
139 | } | ||
140 | pr_debug("%s(): memory range at %p is busy, retrying\n", | ||
141 | __func__, pfn_to_page(pfn)); | ||
142 | /* try again with a bit different memory target */ | ||
143 | start = pageno + mask + 1; | ||
144 | } | ||
145 | mutex_unlock(&kvm_cma_mutex); | ||
146 | pr_debug("%s(): returned %p\n", __func__, page); | ||
147 | return page; | ||
148 | } | ||
149 | |||
150 | /** | ||
151 | * kvm_release_cma() - release allocated pages for hash pagetable | ||
152 | * @pages: Allocated pages. | ||
153 | * @nr_pages: Number of allocated pages. | ||
154 | * | ||
155 | * This function releases memory allocated by kvm_alloc_cma(). | ||
156 | * It returns false when provided pages do not belong to contiguous area and | ||
157 | * true otherwise. | ||
158 | */ | ||
159 | bool kvm_release_cma(struct page *pages, unsigned long nr_pages) | ||
160 | { | ||
161 | unsigned long pfn; | ||
162 | unsigned long nr_chunk; | ||
163 | struct kvm_cma *cma = &kvm_cma_area; | ||
164 | |||
165 | if (!cma || !pages) | ||
166 | return false; | ||
167 | |||
168 | pr_debug("%s(page %p count %lu)\n", __func__, (void *)pages, nr_pages); | ||
169 | |||
170 | pfn = page_to_pfn(pages); | ||
171 | |||
172 | if (pfn < cma->base_pfn || pfn >= cma->base_pfn + cma->count) | ||
173 | return false; | ||
174 | |||
175 | VM_BUG_ON(pfn + nr_pages > cma->base_pfn + cma->count); | ||
176 | nr_chunk = nr_pages >> (KVM_CMA_CHUNK_ORDER - PAGE_SHIFT); | ||
177 | |||
178 | mutex_lock(&kvm_cma_mutex); | ||
179 | bitmap_clear(cma->bitmap, | ||
180 | (pfn - cma->base_pfn) >> (KVM_CMA_CHUNK_ORDER - PAGE_SHIFT), | ||
181 | nr_chunk); | ||
182 | free_contig_range(pfn, nr_pages); | ||
183 | mutex_unlock(&kvm_cma_mutex); | ||
184 | |||
185 | return true; | ||
186 | } | ||
187 | |||
188 | static int __init kvm_cma_activate_area(unsigned long base_pfn, | ||
189 | unsigned long count) | ||
190 | { | ||
191 | unsigned long pfn = base_pfn; | ||
192 | unsigned i = count >> pageblock_order; | ||
193 | struct zone *zone; | ||
194 | |||
195 | WARN_ON_ONCE(!pfn_valid(pfn)); | ||
196 | zone = page_zone(pfn_to_page(pfn)); | ||
197 | do { | ||
198 | unsigned j; | ||
199 | base_pfn = pfn; | ||
200 | for (j = pageblock_nr_pages; j; --j, pfn++) { | ||
201 | WARN_ON_ONCE(!pfn_valid(pfn)); | ||
202 | /* | ||
203 | * alloc_contig_range requires the pfn range | ||
204 | * specified to be in the same zone. Make this | ||
205 | * simple by forcing the entire CMA resv range | ||
206 | * to be in the same zone. | ||
207 | */ | ||
208 | if (page_zone(pfn_to_page(pfn)) != zone) | ||
209 | return -EINVAL; | ||
210 | } | ||
211 | init_cma_reserved_pageblock(pfn_to_page(base_pfn)); | ||
212 | } while (--i); | ||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | static int __init kvm_cma_init_reserved_areas(void) | ||
217 | { | ||
218 | int bitmap_size, ret; | ||
219 | unsigned long chunk_count; | ||
220 | struct kvm_cma *cma = &kvm_cma_area; | ||
221 | |||
222 | pr_debug("%s()\n", __func__); | ||
223 | if (!cma->count) | ||
224 | return 0; | ||
225 | chunk_count = cma->count >> (KVM_CMA_CHUNK_ORDER - PAGE_SHIFT); | ||
226 | bitmap_size = BITS_TO_LONGS(chunk_count) * sizeof(long); | ||
227 | cma->bitmap = kzalloc(bitmap_size, GFP_KERNEL); | ||
228 | if (!cma->bitmap) | ||
229 | return -ENOMEM; | ||
230 | |||
231 | ret = kvm_cma_activate_area(cma->base_pfn, cma->count); | ||
232 | if (ret) | ||
233 | goto error; | ||
234 | return 0; | ||
235 | |||
236 | error: | ||
237 | kfree(cma->bitmap); | ||
238 | return ret; | ||
239 | } | ||
240 | core_initcall(kvm_cma_init_reserved_areas); | ||
diff --git a/arch/powerpc/kvm/book3s_hv_cma.h b/arch/powerpc/kvm/book3s_hv_cma.h deleted file mode 100644 index 655144f75fa5..000000000000 --- a/arch/powerpc/kvm/book3s_hv_cma.h +++ /dev/null | |||
@@ -1,27 +0,0 @@ | |||
1 | /* | ||
2 | * Contiguous Memory Allocator for ppc KVM hash pagetable based on CMA | ||
3 | * for DMA mapping framework | ||
4 | * | ||
5 | * Copyright IBM Corporation, 2013 | ||
6 | * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License as | ||
10 | * published by the Free Software Foundation; either version 2 of the | ||
11 | * License or (at your optional) any later version of the license. | ||
12 | * | ||
13 | */ | ||
14 | |||
15 | #ifndef __POWERPC_KVM_CMA_ALLOC_H__ | ||
16 | #define __POWERPC_KVM_CMA_ALLOC_H__ | ||
17 | /* | ||
18 | * Both RMA and Hash page allocation will be multiple of 256K. | ||
19 | */ | ||
20 | #define KVM_CMA_CHUNK_ORDER 18 | ||
21 | |||
22 | extern struct page *kvm_alloc_cma(unsigned long nr_pages, | ||
23 | unsigned long align_pages); | ||
24 | extern bool kvm_release_cma(struct page *pages, unsigned long nr_pages); | ||
25 | extern long kvm_cma_declare_contiguous(phys_addr_t size, | ||
26 | phys_addr_t alignment) __init; | ||
27 | #endif | ||
diff --git a/arch/powerpc/kvm/book3s_hv_ras.c b/arch/powerpc/kvm/book3s_hv_ras.c index 3a5c568b1e89..d562c8e2bc30 100644 --- a/arch/powerpc/kvm/book3s_hv_ras.c +++ b/arch/powerpc/kvm/book3s_hv_ras.c | |||
@@ -45,14 +45,14 @@ static void reload_slb(struct kvm_vcpu *vcpu) | |||
45 | return; | 45 | return; |
46 | 46 | ||
47 | /* Sanity check */ | 47 | /* Sanity check */ |
48 | n = min_t(u32, slb->persistent, SLB_MIN_SIZE); | 48 | n = min_t(u32, be32_to_cpu(slb->persistent), SLB_MIN_SIZE); |
49 | if ((void *) &slb->save_area[n] > vcpu->arch.slb_shadow.pinned_end) | 49 | if ((void *) &slb->save_area[n] > vcpu->arch.slb_shadow.pinned_end) |
50 | return; | 50 | return; |
51 | 51 | ||
52 | /* Load up the SLB from that */ | 52 | /* Load up the SLB from that */ |
53 | for (i = 0; i < n; ++i) { | 53 | for (i = 0; i < n; ++i) { |
54 | unsigned long rb = slb->save_area[i].esid; | 54 | unsigned long rb = be64_to_cpu(slb->save_area[i].esid); |
55 | unsigned long rs = slb->save_area[i].vsid; | 55 | unsigned long rs = be64_to_cpu(slb->save_area[i].vsid); |
56 | 56 | ||
57 | rb = (rb & ~0xFFFul) | i; /* insert entry number */ | 57 | rb = (rb & ~0xFFFul) | i; /* insert entry number */ |
58 | asm volatile("slbmte %0,%1" : : "r" (rs), "r" (rb)); | 58 | asm volatile("slbmte %0,%1" : : "r" (rs), "r" (rb)); |
diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c index 5a24d3c2b6b8..084ad54c73cd 100644 --- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c +++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c | |||
@@ -154,10 +154,10 @@ static pte_t lookup_linux_pte_and_update(pgd_t *pgdir, unsigned long hva, | |||
154 | return kvmppc_read_update_linux_pte(ptep, writing, hugepage_shift); | 154 | return kvmppc_read_update_linux_pte(ptep, writing, hugepage_shift); |
155 | } | 155 | } |
156 | 156 | ||
157 | static inline void unlock_hpte(unsigned long *hpte, unsigned long hpte_v) | 157 | static inline void unlock_hpte(__be64 *hpte, unsigned long hpte_v) |
158 | { | 158 | { |
159 | asm volatile(PPC_RELEASE_BARRIER "" : : : "memory"); | 159 | asm volatile(PPC_RELEASE_BARRIER "" : : : "memory"); |
160 | hpte[0] = hpte_v; | 160 | hpte[0] = cpu_to_be64(hpte_v); |
161 | } | 161 | } |
162 | 162 | ||
163 | long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags, | 163 | long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags, |
@@ -166,7 +166,7 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags, | |||
166 | { | 166 | { |
167 | unsigned long i, pa, gpa, gfn, psize; | 167 | unsigned long i, pa, gpa, gfn, psize; |
168 | unsigned long slot_fn, hva; | 168 | unsigned long slot_fn, hva; |
169 | unsigned long *hpte; | 169 | __be64 *hpte; |
170 | struct revmap_entry *rev; | 170 | struct revmap_entry *rev; |
171 | unsigned long g_ptel; | 171 | unsigned long g_ptel; |
172 | struct kvm_memory_slot *memslot; | 172 | struct kvm_memory_slot *memslot; |
@@ -275,9 +275,9 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags, | |||
275 | return H_PARAMETER; | 275 | return H_PARAMETER; |
276 | if (likely((flags & H_EXACT) == 0)) { | 276 | if (likely((flags & H_EXACT) == 0)) { |
277 | pte_index &= ~7UL; | 277 | pte_index &= ~7UL; |
278 | hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4)); | 278 | hpte = (__be64 *)(kvm->arch.hpt_virt + (pte_index << 4)); |
279 | for (i = 0; i < 8; ++i) { | 279 | for (i = 0; i < 8; ++i) { |
280 | if ((*hpte & HPTE_V_VALID) == 0 && | 280 | if ((be64_to_cpu(*hpte) & HPTE_V_VALID) == 0 && |
281 | try_lock_hpte(hpte, HPTE_V_HVLOCK | HPTE_V_VALID | | 281 | try_lock_hpte(hpte, HPTE_V_HVLOCK | HPTE_V_VALID | |
282 | HPTE_V_ABSENT)) | 282 | HPTE_V_ABSENT)) |
283 | break; | 283 | break; |
@@ -292,11 +292,13 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags, | |||
292 | */ | 292 | */ |
293 | hpte -= 16; | 293 | hpte -= 16; |
294 | for (i = 0; i < 8; ++i) { | 294 | for (i = 0; i < 8; ++i) { |
295 | u64 pte; | ||
295 | while (!try_lock_hpte(hpte, HPTE_V_HVLOCK)) | 296 | while (!try_lock_hpte(hpte, HPTE_V_HVLOCK)) |
296 | cpu_relax(); | 297 | cpu_relax(); |
297 | if (!(*hpte & (HPTE_V_VALID | HPTE_V_ABSENT))) | 298 | pte = be64_to_cpu(*hpte); |
299 | if (!(pte & (HPTE_V_VALID | HPTE_V_ABSENT))) | ||
298 | break; | 300 | break; |
299 | *hpte &= ~HPTE_V_HVLOCK; | 301 | *hpte &= ~cpu_to_be64(HPTE_V_HVLOCK); |
300 | hpte += 2; | 302 | hpte += 2; |
301 | } | 303 | } |
302 | if (i == 8) | 304 | if (i == 8) |
@@ -304,14 +306,17 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags, | |||
304 | } | 306 | } |
305 | pte_index += i; | 307 | pte_index += i; |
306 | } else { | 308 | } else { |
307 | hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4)); | 309 | hpte = (__be64 *)(kvm->arch.hpt_virt + (pte_index << 4)); |
308 | if (!try_lock_hpte(hpte, HPTE_V_HVLOCK | HPTE_V_VALID | | 310 | if (!try_lock_hpte(hpte, HPTE_V_HVLOCK | HPTE_V_VALID | |
309 | HPTE_V_ABSENT)) { | 311 | HPTE_V_ABSENT)) { |
310 | /* Lock the slot and check again */ | 312 | /* Lock the slot and check again */ |
313 | u64 pte; | ||
314 | |||
311 | while (!try_lock_hpte(hpte, HPTE_V_HVLOCK)) | 315 | while (!try_lock_hpte(hpte, HPTE_V_HVLOCK)) |
312 | cpu_relax(); | 316 | cpu_relax(); |
313 | if (*hpte & (HPTE_V_VALID | HPTE_V_ABSENT)) { | 317 | pte = be64_to_cpu(*hpte); |
314 | *hpte &= ~HPTE_V_HVLOCK; | 318 | if (pte & (HPTE_V_VALID | HPTE_V_ABSENT)) { |
319 | *hpte &= ~cpu_to_be64(HPTE_V_HVLOCK); | ||
315 | return H_PTEG_FULL; | 320 | return H_PTEG_FULL; |
316 | } | 321 | } |
317 | } | 322 | } |
@@ -347,11 +352,11 @@ long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags, | |||
347 | } | 352 | } |
348 | } | 353 | } |
349 | 354 | ||
350 | hpte[1] = ptel; | 355 | hpte[1] = cpu_to_be64(ptel); |
351 | 356 | ||
352 | /* Write the first HPTE dword, unlocking the HPTE and making it valid */ | 357 | /* Write the first HPTE dword, unlocking the HPTE and making it valid */ |
353 | eieio(); | 358 | eieio(); |
354 | hpte[0] = pteh; | 359 | hpte[0] = cpu_to_be64(pteh); |
355 | asm volatile("ptesync" : : : "memory"); | 360 | asm volatile("ptesync" : : : "memory"); |
356 | 361 | ||
357 | *pte_idx_ret = pte_index; | 362 | *pte_idx_ret = pte_index; |
@@ -468,30 +473,35 @@ long kvmppc_do_h_remove(struct kvm *kvm, unsigned long flags, | |||
468 | unsigned long pte_index, unsigned long avpn, | 473 | unsigned long pte_index, unsigned long avpn, |
469 | unsigned long *hpret) | 474 | unsigned long *hpret) |
470 | { | 475 | { |
471 | unsigned long *hpte; | 476 | __be64 *hpte; |
472 | unsigned long v, r, rb; | 477 | unsigned long v, r, rb; |
473 | struct revmap_entry *rev; | 478 | struct revmap_entry *rev; |
479 | u64 pte; | ||
474 | 480 | ||
475 | if (pte_index >= kvm->arch.hpt_npte) | 481 | if (pte_index >= kvm->arch.hpt_npte) |
476 | return H_PARAMETER; | 482 | return H_PARAMETER; |
477 | hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4)); | 483 | hpte = (__be64 *)(kvm->arch.hpt_virt + (pte_index << 4)); |
478 | while (!try_lock_hpte(hpte, HPTE_V_HVLOCK)) | 484 | while (!try_lock_hpte(hpte, HPTE_V_HVLOCK)) |
479 | cpu_relax(); | 485 | cpu_relax(); |
480 | if ((hpte[0] & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 || | 486 | pte = be64_to_cpu(hpte[0]); |
481 | ((flags & H_AVPN) && (hpte[0] & ~0x7fUL) != avpn) || | 487 | if ((pte & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 || |
482 | ((flags & H_ANDCOND) && (hpte[0] & avpn) != 0)) { | 488 | ((flags & H_AVPN) && (pte & ~0x7fUL) != avpn) || |
483 | hpte[0] &= ~HPTE_V_HVLOCK; | 489 | ((flags & H_ANDCOND) && (pte & avpn) != 0)) { |
490 | hpte[0] &= ~cpu_to_be64(HPTE_V_HVLOCK); | ||
484 | return H_NOT_FOUND; | 491 | return H_NOT_FOUND; |
485 | } | 492 | } |
486 | 493 | ||
487 | rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]); | 494 | rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]); |
488 | v = hpte[0] & ~HPTE_V_HVLOCK; | 495 | v = pte & ~HPTE_V_HVLOCK; |
489 | if (v & HPTE_V_VALID) { | 496 | if (v & HPTE_V_VALID) { |
490 | hpte[0] &= ~HPTE_V_VALID; | 497 | u64 pte1; |
491 | rb = compute_tlbie_rb(v, hpte[1], pte_index); | 498 | |
499 | pte1 = be64_to_cpu(hpte[1]); | ||
500 | hpte[0] &= ~cpu_to_be64(HPTE_V_VALID); | ||
501 | rb = compute_tlbie_rb(v, pte1, pte_index); | ||
492 | do_tlbies(kvm, &rb, 1, global_invalidates(kvm, flags), true); | 502 | do_tlbies(kvm, &rb, 1, global_invalidates(kvm, flags), true); |
493 | /* Read PTE low word after tlbie to get final R/C values */ | 503 | /* Read PTE low word after tlbie to get final R/C values */ |
494 | remove_revmap_chain(kvm, pte_index, rev, v, hpte[1]); | 504 | remove_revmap_chain(kvm, pte_index, rev, v, pte1); |
495 | } | 505 | } |
496 | r = rev->guest_rpte & ~HPTE_GR_RESERVED; | 506 | r = rev->guest_rpte & ~HPTE_GR_RESERVED; |
497 | note_hpte_modification(kvm, rev); | 507 | note_hpte_modification(kvm, rev); |
@@ -514,12 +524,14 @@ long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu) | |||
514 | { | 524 | { |
515 | struct kvm *kvm = vcpu->kvm; | 525 | struct kvm *kvm = vcpu->kvm; |
516 | unsigned long *args = &vcpu->arch.gpr[4]; | 526 | unsigned long *args = &vcpu->arch.gpr[4]; |
517 | unsigned long *hp, *hptes[4], tlbrb[4]; | 527 | __be64 *hp, *hptes[4]; |
528 | unsigned long tlbrb[4]; | ||
518 | long int i, j, k, n, found, indexes[4]; | 529 | long int i, j, k, n, found, indexes[4]; |
519 | unsigned long flags, req, pte_index, rcbits; | 530 | unsigned long flags, req, pte_index, rcbits; |
520 | int global; | 531 | int global; |
521 | long int ret = H_SUCCESS; | 532 | long int ret = H_SUCCESS; |
522 | struct revmap_entry *rev, *revs[4]; | 533 | struct revmap_entry *rev, *revs[4]; |
534 | u64 hp0; | ||
523 | 535 | ||
524 | global = global_invalidates(kvm, 0); | 536 | global = global_invalidates(kvm, 0); |
525 | for (i = 0; i < 4 && ret == H_SUCCESS; ) { | 537 | for (i = 0; i < 4 && ret == H_SUCCESS; ) { |
@@ -542,8 +554,7 @@ long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu) | |||
542 | ret = H_PARAMETER; | 554 | ret = H_PARAMETER; |
543 | break; | 555 | break; |
544 | } | 556 | } |
545 | hp = (unsigned long *) | 557 | hp = (__be64 *) (kvm->arch.hpt_virt + (pte_index << 4)); |
546 | (kvm->arch.hpt_virt + (pte_index << 4)); | ||
547 | /* to avoid deadlock, don't spin except for first */ | 558 | /* to avoid deadlock, don't spin except for first */ |
548 | if (!try_lock_hpte(hp, HPTE_V_HVLOCK)) { | 559 | if (!try_lock_hpte(hp, HPTE_V_HVLOCK)) { |
549 | if (n) | 560 | if (n) |
@@ -552,23 +563,24 @@ long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu) | |||
552 | cpu_relax(); | 563 | cpu_relax(); |
553 | } | 564 | } |
554 | found = 0; | 565 | found = 0; |
555 | if (hp[0] & (HPTE_V_ABSENT | HPTE_V_VALID)) { | 566 | hp0 = be64_to_cpu(hp[0]); |
567 | if (hp0 & (HPTE_V_ABSENT | HPTE_V_VALID)) { | ||
556 | switch (flags & 3) { | 568 | switch (flags & 3) { |
557 | case 0: /* absolute */ | 569 | case 0: /* absolute */ |
558 | found = 1; | 570 | found = 1; |
559 | break; | 571 | break; |
560 | case 1: /* andcond */ | 572 | case 1: /* andcond */ |
561 | if (!(hp[0] & args[j + 1])) | 573 | if (!(hp0 & args[j + 1])) |
562 | found = 1; | 574 | found = 1; |
563 | break; | 575 | break; |
564 | case 2: /* AVPN */ | 576 | case 2: /* AVPN */ |
565 | if ((hp[0] & ~0x7fUL) == args[j + 1]) | 577 | if ((hp0 & ~0x7fUL) == args[j + 1]) |
566 | found = 1; | 578 | found = 1; |
567 | break; | 579 | break; |
568 | } | 580 | } |
569 | } | 581 | } |
570 | if (!found) { | 582 | if (!found) { |
571 | hp[0] &= ~HPTE_V_HVLOCK; | 583 | hp[0] &= ~cpu_to_be64(HPTE_V_HVLOCK); |
572 | args[j] = ((0x90 | flags) << 56) + pte_index; | 584 | args[j] = ((0x90 | flags) << 56) + pte_index; |
573 | continue; | 585 | continue; |
574 | } | 586 | } |
@@ -577,7 +589,7 @@ long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu) | |||
577 | rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]); | 589 | rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]); |
578 | note_hpte_modification(kvm, rev); | 590 | note_hpte_modification(kvm, rev); |
579 | 591 | ||
580 | if (!(hp[0] & HPTE_V_VALID)) { | 592 | if (!(hp0 & HPTE_V_VALID)) { |
581 | /* insert R and C bits from PTE */ | 593 | /* insert R and C bits from PTE */ |
582 | rcbits = rev->guest_rpte & (HPTE_R_R|HPTE_R_C); | 594 | rcbits = rev->guest_rpte & (HPTE_R_R|HPTE_R_C); |
583 | args[j] |= rcbits << (56 - 5); | 595 | args[j] |= rcbits << (56 - 5); |
@@ -585,8 +597,10 @@ long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu) | |||
585 | continue; | 597 | continue; |
586 | } | 598 | } |
587 | 599 | ||
588 | hp[0] &= ~HPTE_V_VALID; /* leave it locked */ | 600 | /* leave it locked */ |
589 | tlbrb[n] = compute_tlbie_rb(hp[0], hp[1], pte_index); | 601 | hp[0] &= ~cpu_to_be64(HPTE_V_VALID); |
602 | tlbrb[n] = compute_tlbie_rb(be64_to_cpu(hp[0]), | ||
603 | be64_to_cpu(hp[1]), pte_index); | ||
590 | indexes[n] = j; | 604 | indexes[n] = j; |
591 | hptes[n] = hp; | 605 | hptes[n] = hp; |
592 | revs[n] = rev; | 606 | revs[n] = rev; |
@@ -605,7 +619,8 @@ long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu) | |||
605 | pte_index = args[j] & ((1ul << 56) - 1); | 619 | pte_index = args[j] & ((1ul << 56) - 1); |
606 | hp = hptes[k]; | 620 | hp = hptes[k]; |
607 | rev = revs[k]; | 621 | rev = revs[k]; |
608 | remove_revmap_chain(kvm, pte_index, rev, hp[0], hp[1]); | 622 | remove_revmap_chain(kvm, pte_index, rev, |
623 | be64_to_cpu(hp[0]), be64_to_cpu(hp[1])); | ||
609 | rcbits = rev->guest_rpte & (HPTE_R_R|HPTE_R_C); | 624 | rcbits = rev->guest_rpte & (HPTE_R_R|HPTE_R_C); |
610 | args[j] |= rcbits << (56 - 5); | 625 | args[j] |= rcbits << (56 - 5); |
611 | hp[0] = 0; | 626 | hp[0] = 0; |
@@ -620,23 +635,25 @@ long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags, | |||
620 | unsigned long va) | 635 | unsigned long va) |
621 | { | 636 | { |
622 | struct kvm *kvm = vcpu->kvm; | 637 | struct kvm *kvm = vcpu->kvm; |
623 | unsigned long *hpte; | 638 | __be64 *hpte; |
624 | struct revmap_entry *rev; | 639 | struct revmap_entry *rev; |
625 | unsigned long v, r, rb, mask, bits; | 640 | unsigned long v, r, rb, mask, bits; |
641 | u64 pte; | ||
626 | 642 | ||
627 | if (pte_index >= kvm->arch.hpt_npte) | 643 | if (pte_index >= kvm->arch.hpt_npte) |
628 | return H_PARAMETER; | 644 | return H_PARAMETER; |
629 | 645 | ||
630 | hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4)); | 646 | hpte = (__be64 *)(kvm->arch.hpt_virt + (pte_index << 4)); |
631 | while (!try_lock_hpte(hpte, HPTE_V_HVLOCK)) | 647 | while (!try_lock_hpte(hpte, HPTE_V_HVLOCK)) |
632 | cpu_relax(); | 648 | cpu_relax(); |
633 | if ((hpte[0] & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 || | 649 | pte = be64_to_cpu(hpte[0]); |
634 | ((flags & H_AVPN) && (hpte[0] & ~0x7fUL) != avpn)) { | 650 | if ((pte & (HPTE_V_ABSENT | HPTE_V_VALID)) == 0 || |
635 | hpte[0] &= ~HPTE_V_HVLOCK; | 651 | ((flags & H_AVPN) && (pte & ~0x7fUL) != avpn)) { |
652 | hpte[0] &= ~cpu_to_be64(HPTE_V_HVLOCK); | ||
636 | return H_NOT_FOUND; | 653 | return H_NOT_FOUND; |
637 | } | 654 | } |
638 | 655 | ||
639 | v = hpte[0]; | 656 | v = pte; |
640 | bits = (flags << 55) & HPTE_R_PP0; | 657 | bits = (flags << 55) & HPTE_R_PP0; |
641 | bits |= (flags << 48) & HPTE_R_KEY_HI; | 658 | bits |= (flags << 48) & HPTE_R_KEY_HI; |
642 | bits |= flags & (HPTE_R_PP | HPTE_R_N | HPTE_R_KEY_LO); | 659 | bits |= flags & (HPTE_R_PP | HPTE_R_N | HPTE_R_KEY_LO); |
@@ -650,12 +667,12 @@ long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags, | |||
650 | rev->guest_rpte = r; | 667 | rev->guest_rpte = r; |
651 | note_hpte_modification(kvm, rev); | 668 | note_hpte_modification(kvm, rev); |
652 | } | 669 | } |
653 | r = (hpte[1] & ~mask) | bits; | 670 | r = (be64_to_cpu(hpte[1]) & ~mask) | bits; |
654 | 671 | ||
655 | /* Update HPTE */ | 672 | /* Update HPTE */ |
656 | if (v & HPTE_V_VALID) { | 673 | if (v & HPTE_V_VALID) { |
657 | rb = compute_tlbie_rb(v, r, pte_index); | 674 | rb = compute_tlbie_rb(v, r, pte_index); |
658 | hpte[0] = v & ~HPTE_V_VALID; | 675 | hpte[0] = cpu_to_be64(v & ~HPTE_V_VALID); |
659 | do_tlbies(kvm, &rb, 1, global_invalidates(kvm, flags), true); | 676 | do_tlbies(kvm, &rb, 1, global_invalidates(kvm, flags), true); |
660 | /* | 677 | /* |
661 | * If the host has this page as readonly but the guest | 678 | * If the host has this page as readonly but the guest |
@@ -681,9 +698,9 @@ long kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags, | |||
681 | } | 698 | } |
682 | } | 699 | } |
683 | } | 700 | } |
684 | hpte[1] = r; | 701 | hpte[1] = cpu_to_be64(r); |
685 | eieio(); | 702 | eieio(); |
686 | hpte[0] = v & ~HPTE_V_HVLOCK; | 703 | hpte[0] = cpu_to_be64(v & ~HPTE_V_HVLOCK); |
687 | asm volatile("ptesync" : : : "memory"); | 704 | asm volatile("ptesync" : : : "memory"); |
688 | return H_SUCCESS; | 705 | return H_SUCCESS; |
689 | } | 706 | } |
@@ -692,7 +709,8 @@ long kvmppc_h_read(struct kvm_vcpu *vcpu, unsigned long flags, | |||
692 | unsigned long pte_index) | 709 | unsigned long pte_index) |
693 | { | 710 | { |
694 | struct kvm *kvm = vcpu->kvm; | 711 | struct kvm *kvm = vcpu->kvm; |
695 | unsigned long *hpte, v, r; | 712 | __be64 *hpte; |
713 | unsigned long v, r; | ||
696 | int i, n = 1; | 714 | int i, n = 1; |
697 | struct revmap_entry *rev = NULL; | 715 | struct revmap_entry *rev = NULL; |
698 | 716 | ||
@@ -704,9 +722,9 @@ long kvmppc_h_read(struct kvm_vcpu *vcpu, unsigned long flags, | |||
704 | } | 722 | } |
705 | rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]); | 723 | rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]); |
706 | for (i = 0; i < n; ++i, ++pte_index) { | 724 | for (i = 0; i < n; ++i, ++pte_index) { |
707 | hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4)); | 725 | hpte = (__be64 *)(kvm->arch.hpt_virt + (pte_index << 4)); |
708 | v = hpte[0] & ~HPTE_V_HVLOCK; | 726 | v = be64_to_cpu(hpte[0]) & ~HPTE_V_HVLOCK; |
709 | r = hpte[1]; | 727 | r = be64_to_cpu(hpte[1]); |
710 | if (v & HPTE_V_ABSENT) { | 728 | if (v & HPTE_V_ABSENT) { |
711 | v &= ~HPTE_V_ABSENT; | 729 | v &= ~HPTE_V_ABSENT; |
712 | v |= HPTE_V_VALID; | 730 | v |= HPTE_V_VALID; |
@@ -721,25 +739,27 @@ long kvmppc_h_read(struct kvm_vcpu *vcpu, unsigned long flags, | |||
721 | return H_SUCCESS; | 739 | return H_SUCCESS; |
722 | } | 740 | } |
723 | 741 | ||
724 | void kvmppc_invalidate_hpte(struct kvm *kvm, unsigned long *hptep, | 742 | void kvmppc_invalidate_hpte(struct kvm *kvm, __be64 *hptep, |
725 | unsigned long pte_index) | 743 | unsigned long pte_index) |
726 | { | 744 | { |
727 | unsigned long rb; | 745 | unsigned long rb; |
728 | 746 | ||
729 | hptep[0] &= ~HPTE_V_VALID; | 747 | hptep[0] &= ~cpu_to_be64(HPTE_V_VALID); |
730 | rb = compute_tlbie_rb(hptep[0], hptep[1], pte_index); | 748 | rb = compute_tlbie_rb(be64_to_cpu(hptep[0]), be64_to_cpu(hptep[1]), |
749 | pte_index); | ||
731 | do_tlbies(kvm, &rb, 1, 1, true); | 750 | do_tlbies(kvm, &rb, 1, 1, true); |
732 | } | 751 | } |
733 | EXPORT_SYMBOL_GPL(kvmppc_invalidate_hpte); | 752 | EXPORT_SYMBOL_GPL(kvmppc_invalidate_hpte); |
734 | 753 | ||
735 | void kvmppc_clear_ref_hpte(struct kvm *kvm, unsigned long *hptep, | 754 | void kvmppc_clear_ref_hpte(struct kvm *kvm, __be64 *hptep, |
736 | unsigned long pte_index) | 755 | unsigned long pte_index) |
737 | { | 756 | { |
738 | unsigned long rb; | 757 | unsigned long rb; |
739 | unsigned char rbyte; | 758 | unsigned char rbyte; |
740 | 759 | ||
741 | rb = compute_tlbie_rb(hptep[0], hptep[1], pte_index); | 760 | rb = compute_tlbie_rb(be64_to_cpu(hptep[0]), be64_to_cpu(hptep[1]), |
742 | rbyte = (hptep[1] & ~HPTE_R_R) >> 8; | 761 | pte_index); |
762 | rbyte = (be64_to_cpu(hptep[1]) & ~HPTE_R_R) >> 8; | ||
743 | /* modify only the second-last byte, which contains the ref bit */ | 763 | /* modify only the second-last byte, which contains the ref bit */ |
744 | *((char *)hptep + 14) = rbyte; | 764 | *((char *)hptep + 14) = rbyte; |
745 | do_tlbies(kvm, &rb, 1, 1, false); | 765 | do_tlbies(kvm, &rb, 1, 1, false); |
@@ -765,7 +785,7 @@ long kvmppc_hv_find_lock_hpte(struct kvm *kvm, gva_t eaddr, unsigned long slb_v, | |||
765 | unsigned long somask; | 785 | unsigned long somask; |
766 | unsigned long vsid, hash; | 786 | unsigned long vsid, hash; |
767 | unsigned long avpn; | 787 | unsigned long avpn; |
768 | unsigned long *hpte; | 788 | __be64 *hpte; |
769 | unsigned long mask, val; | 789 | unsigned long mask, val; |
770 | unsigned long v, r; | 790 | unsigned long v, r; |
771 | 791 | ||
@@ -797,11 +817,11 @@ long kvmppc_hv_find_lock_hpte(struct kvm *kvm, gva_t eaddr, unsigned long slb_v, | |||
797 | val |= avpn; | 817 | val |= avpn; |
798 | 818 | ||
799 | for (;;) { | 819 | for (;;) { |
800 | hpte = (unsigned long *)(kvm->arch.hpt_virt + (hash << 7)); | 820 | hpte = (__be64 *)(kvm->arch.hpt_virt + (hash << 7)); |
801 | 821 | ||
802 | for (i = 0; i < 16; i += 2) { | 822 | for (i = 0; i < 16; i += 2) { |
803 | /* Read the PTE racily */ | 823 | /* Read the PTE racily */ |
804 | v = hpte[i] & ~HPTE_V_HVLOCK; | 824 | v = be64_to_cpu(hpte[i]) & ~HPTE_V_HVLOCK; |
805 | 825 | ||
806 | /* Check valid/absent, hash, segment size and AVPN */ | 826 | /* Check valid/absent, hash, segment size and AVPN */ |
807 | if (!(v & valid) || (v & mask) != val) | 827 | if (!(v & valid) || (v & mask) != val) |
@@ -810,8 +830,8 @@ long kvmppc_hv_find_lock_hpte(struct kvm *kvm, gva_t eaddr, unsigned long slb_v, | |||
810 | /* Lock the PTE and read it under the lock */ | 830 | /* Lock the PTE and read it under the lock */ |
811 | while (!try_lock_hpte(&hpte[i], HPTE_V_HVLOCK)) | 831 | while (!try_lock_hpte(&hpte[i], HPTE_V_HVLOCK)) |
812 | cpu_relax(); | 832 | cpu_relax(); |
813 | v = hpte[i] & ~HPTE_V_HVLOCK; | 833 | v = be64_to_cpu(hpte[i]) & ~HPTE_V_HVLOCK; |
814 | r = hpte[i+1]; | 834 | r = be64_to_cpu(hpte[i+1]); |
815 | 835 | ||
816 | /* | 836 | /* |
817 | * Check the HPTE again, including base page size | 837 | * Check the HPTE again, including base page size |
@@ -822,7 +842,7 @@ long kvmppc_hv_find_lock_hpte(struct kvm *kvm, gva_t eaddr, unsigned long slb_v, | |||
822 | return (hash << 3) + (i >> 1); | 842 | return (hash << 3) + (i >> 1); |
823 | 843 | ||
824 | /* Unlock and move on */ | 844 | /* Unlock and move on */ |
825 | hpte[i] = v; | 845 | hpte[i] = cpu_to_be64(v); |
826 | } | 846 | } |
827 | 847 | ||
828 | if (val & HPTE_V_SECONDARY) | 848 | if (val & HPTE_V_SECONDARY) |
@@ -851,7 +871,7 @@ long kvmppc_hpte_hv_fault(struct kvm_vcpu *vcpu, unsigned long addr, | |||
851 | struct kvm *kvm = vcpu->kvm; | 871 | struct kvm *kvm = vcpu->kvm; |
852 | long int index; | 872 | long int index; |
853 | unsigned long v, r, gr; | 873 | unsigned long v, r, gr; |
854 | unsigned long *hpte; | 874 | __be64 *hpte; |
855 | unsigned long valid; | 875 | unsigned long valid; |
856 | struct revmap_entry *rev; | 876 | struct revmap_entry *rev; |
857 | unsigned long pp, key; | 877 | unsigned long pp, key; |
@@ -867,9 +887,9 @@ long kvmppc_hpte_hv_fault(struct kvm_vcpu *vcpu, unsigned long addr, | |||
867 | return status; /* there really was no HPTE */ | 887 | return status; /* there really was no HPTE */ |
868 | return 0; /* for prot fault, HPTE disappeared */ | 888 | return 0; /* for prot fault, HPTE disappeared */ |
869 | } | 889 | } |
870 | hpte = (unsigned long *)(kvm->arch.hpt_virt + (index << 4)); | 890 | hpte = (__be64 *)(kvm->arch.hpt_virt + (index << 4)); |
871 | v = hpte[0] & ~HPTE_V_HVLOCK; | 891 | v = be64_to_cpu(hpte[0]) & ~HPTE_V_HVLOCK; |
872 | r = hpte[1]; | 892 | r = be64_to_cpu(hpte[1]); |
873 | rev = real_vmalloc_addr(&kvm->arch.revmap[index]); | 893 | rev = real_vmalloc_addr(&kvm->arch.revmap[index]); |
874 | gr = rev->guest_rpte; | 894 | gr = rev->guest_rpte; |
875 | 895 | ||
diff --git a/arch/powerpc/kvm/book3s_hv_rm_xics.c b/arch/powerpc/kvm/book3s_hv_rm_xics.c index b4b0082f761c..3ee38e6e884f 100644 --- a/arch/powerpc/kvm/book3s_hv_rm_xics.c +++ b/arch/powerpc/kvm/book3s_hv_rm_xics.c | |||
@@ -401,6 +401,11 @@ int kvmppc_rm_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr) | |||
401 | icp->rm_action |= XICS_RM_REJECT; | 401 | icp->rm_action |= XICS_RM_REJECT; |
402 | icp->rm_reject = irq; | 402 | icp->rm_reject = irq; |
403 | } | 403 | } |
404 | |||
405 | if (!hlist_empty(&vcpu->kvm->irq_ack_notifier_list)) { | ||
406 | icp->rm_action |= XICS_RM_NOTIFY_EOI; | ||
407 | icp->rm_eoied_irq = irq; | ||
408 | } | ||
404 | bail: | 409 | bail: |
405 | return check_too_hard(xics, icp); | 410 | return check_too_hard(xics, icp); |
406 | } | 411 | } |
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S index 558a67df8126..f0c4db7704c3 100644 --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S | |||
@@ -32,10 +32,6 @@ | |||
32 | 32 | ||
33 | #define VCPU_GPRS_TM(reg) (((reg) * ULONG_SIZE) + VCPU_GPR_TM) | 33 | #define VCPU_GPRS_TM(reg) (((reg) * ULONG_SIZE) + VCPU_GPR_TM) |
34 | 34 | ||
35 | #ifdef __LITTLE_ENDIAN__ | ||
36 | #error Need to fix lppaca and SLB shadow accesses in little endian mode | ||
37 | #endif | ||
38 | |||
39 | /* Values in HSTATE_NAPPING(r13) */ | 35 | /* Values in HSTATE_NAPPING(r13) */ |
40 | #define NAPPING_CEDE 1 | 36 | #define NAPPING_CEDE 1 |
41 | #define NAPPING_NOVCPU 2 | 37 | #define NAPPING_NOVCPU 2 |
@@ -159,6 +155,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) | |||
159 | cmpwi r12, BOOK3S_INTERRUPT_EXTERNAL | 155 | cmpwi r12, BOOK3S_INTERRUPT_EXTERNAL |
160 | BEGIN_FTR_SECTION | 156 | BEGIN_FTR_SECTION |
161 | beq 11f | 157 | beq 11f |
158 | cmpwi cr2, r12, BOOK3S_INTERRUPT_HMI | ||
159 | beq cr2, 14f /* HMI check */ | ||
162 | END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206) | 160 | END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206) |
163 | 161 | ||
164 | /* RFI into the highmem handler, or branch to interrupt handler */ | 162 | /* RFI into the highmem handler, or branch to interrupt handler */ |
@@ -179,6 +177,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206) | |||
179 | 177 | ||
180 | 13: b machine_check_fwnmi | 178 | 13: b machine_check_fwnmi |
181 | 179 | ||
180 | 14: mtspr SPRN_HSRR0, r8 | ||
181 | mtspr SPRN_HSRR1, r7 | ||
182 | b hmi_exception_after_realmode | ||
183 | |||
182 | kvmppc_primary_no_guest: | 184 | kvmppc_primary_no_guest: |
183 | /* We handle this much like a ceded vcpu */ | 185 | /* We handle this much like a ceded vcpu */ |
184 | /* set our bit in napping_threads */ | 186 | /* set our bit in napping_threads */ |
@@ -595,9 +597,10 @@ kvmppc_got_guest: | |||
595 | ld r3, VCPU_VPA(r4) | 597 | ld r3, VCPU_VPA(r4) |
596 | cmpdi r3, 0 | 598 | cmpdi r3, 0 |
597 | beq 25f | 599 | beq 25f |
598 | lwz r5, LPPACA_YIELDCOUNT(r3) | 600 | li r6, LPPACA_YIELDCOUNT |
601 | LWZX_BE r5, r3, r6 | ||
599 | addi r5, r5, 1 | 602 | addi r5, r5, 1 |
600 | stw r5, LPPACA_YIELDCOUNT(r3) | 603 | STWX_BE r5, r3, r6 |
601 | li r6, 1 | 604 | li r6, 1 |
602 | stb r6, VCPU_VPA_DIRTY(r4) | 605 | stb r6, VCPU_VPA_DIRTY(r4) |
603 | 25: | 606 | 25: |
@@ -671,9 +674,9 @@ END_FTR_SECTION_IFCLR(CPU_FTR_TM) | |||
671 | 674 | ||
672 | mr r31, r4 | 675 | mr r31, r4 |
673 | addi r3, r31, VCPU_FPRS_TM | 676 | addi r3, r31, VCPU_FPRS_TM |
674 | bl .load_fp_state | 677 | bl load_fp_state |
675 | addi r3, r31, VCPU_VRS_TM | 678 | addi r3, r31, VCPU_VRS_TM |
676 | bl .load_vr_state | 679 | bl load_vr_state |
677 | mr r4, r31 | 680 | mr r4, r31 |
678 | lwz r7, VCPU_VRSAVE_TM(r4) | 681 | lwz r7, VCPU_VRSAVE_TM(r4) |
679 | mtspr SPRN_VRSAVE, r7 | 682 | mtspr SPRN_VRSAVE, r7 |
@@ -1417,9 +1420,9 @@ END_FTR_SECTION_IFCLR(CPU_FTR_TM) | |||
1417 | 1420 | ||
1418 | /* Save FP/VSX. */ | 1421 | /* Save FP/VSX. */ |
1419 | addi r3, r9, VCPU_FPRS_TM | 1422 | addi r3, r9, VCPU_FPRS_TM |
1420 | bl .store_fp_state | 1423 | bl store_fp_state |
1421 | addi r3, r9, VCPU_VRS_TM | 1424 | addi r3, r9, VCPU_VRS_TM |
1422 | bl .store_vr_state | 1425 | bl store_vr_state |
1423 | mfspr r6, SPRN_VRSAVE | 1426 | mfspr r6, SPRN_VRSAVE |
1424 | stw r6, VCPU_VRSAVE_TM(r9) | 1427 | stw r6, VCPU_VRSAVE_TM(r9) |
1425 | 1: | 1428 | 1: |
@@ -1442,9 +1445,10 @@ END_FTR_SECTION_IFCLR(CPU_FTR_TM) | |||
1442 | ld r8, VCPU_VPA(r9) /* do they have a VPA? */ | 1445 | ld r8, VCPU_VPA(r9) /* do they have a VPA? */ |
1443 | cmpdi r8, 0 | 1446 | cmpdi r8, 0 |
1444 | beq 25f | 1447 | beq 25f |
1445 | lwz r3, LPPACA_YIELDCOUNT(r8) | 1448 | li r4, LPPACA_YIELDCOUNT |
1449 | LWZX_BE r3, r8, r4 | ||
1446 | addi r3, r3, 1 | 1450 | addi r3, r3, 1 |
1447 | stw r3, LPPACA_YIELDCOUNT(r8) | 1451 | STWX_BE r3, r8, r4 |
1448 | li r3, 1 | 1452 | li r3, 1 |
1449 | stb r3, VCPU_VPA_DIRTY(r9) | 1453 | stb r3, VCPU_VPA_DIRTY(r9) |
1450 | 25: | 1454 | 25: |
@@ -1757,8 +1761,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) | |||
1757 | 33: ld r8,PACA_SLBSHADOWPTR(r13) | 1761 | 33: ld r8,PACA_SLBSHADOWPTR(r13) |
1758 | 1762 | ||
1759 | .rept SLB_NUM_BOLTED | 1763 | .rept SLB_NUM_BOLTED |
1760 | ld r5,SLBSHADOW_SAVEAREA(r8) | 1764 | li r3, SLBSHADOW_SAVEAREA |
1761 | ld r6,SLBSHADOW_SAVEAREA+8(r8) | 1765 | LDX_BE r5, r8, r3 |
1766 | addi r3, r3, 8 | ||
1767 | LDX_BE r6, r8, r3 | ||
1762 | andis. r7,r5,SLB_ESID_V@h | 1768 | andis. r7,r5,SLB_ESID_V@h |
1763 | beq 1f | 1769 | beq 1f |
1764 | slbmte r6,r5 | 1770 | slbmte r6,r5 |
@@ -1909,12 +1915,23 @@ hcall_try_real_mode: | |||
1909 | clrrdi r3,r3,2 | 1915 | clrrdi r3,r3,2 |
1910 | cmpldi r3,hcall_real_table_end - hcall_real_table | 1916 | cmpldi r3,hcall_real_table_end - hcall_real_table |
1911 | bge guest_exit_cont | 1917 | bge guest_exit_cont |
1918 | /* See if this hcall is enabled for in-kernel handling */ | ||
1919 | ld r4, VCPU_KVM(r9) | ||
1920 | srdi r0, r3, 8 /* r0 = (r3 / 4) >> 6 */ | ||
1921 | sldi r0, r0, 3 /* index into kvm->arch.enabled_hcalls[] */ | ||
1922 | add r4, r4, r0 | ||
1923 | ld r0, KVM_ENABLED_HCALLS(r4) | ||
1924 | rlwinm r4, r3, 32-2, 0x3f /* r4 = (r3 / 4) & 0x3f */ | ||
1925 | srd r0, r0, r4 | ||
1926 | andi. r0, r0, 1 | ||
1927 | beq guest_exit_cont | ||
1928 | /* Get pointer to handler, if any, and call it */ | ||
1912 | LOAD_REG_ADDR(r4, hcall_real_table) | 1929 | LOAD_REG_ADDR(r4, hcall_real_table) |
1913 | lwax r3,r3,r4 | 1930 | lwax r3,r3,r4 |
1914 | cmpwi r3,0 | 1931 | cmpwi r3,0 |
1915 | beq guest_exit_cont | 1932 | beq guest_exit_cont |
1916 | add r3,r3,r4 | 1933 | add r12,r3,r4 |
1917 | mtctr r3 | 1934 | mtctr r12 |
1918 | mr r3,r9 /* get vcpu pointer */ | 1935 | mr r3,r9 /* get vcpu pointer */ |
1919 | ld r4,VCPU_GPR(R4)(r9) | 1936 | ld r4,VCPU_GPR(R4)(r9) |
1920 | bctrl | 1937 | bctrl |
@@ -2031,6 +2048,7 @@ hcall_real_table: | |||
2031 | .long 0 /* 0x12c */ | 2048 | .long 0 /* 0x12c */ |
2032 | .long 0 /* 0x130 */ | 2049 | .long 0 /* 0x130 */ |
2033 | .long DOTSYM(kvmppc_h_set_xdabr) - hcall_real_table | 2050 | .long DOTSYM(kvmppc_h_set_xdabr) - hcall_real_table |
2051 | .globl hcall_real_table_end | ||
2034 | hcall_real_table_end: | 2052 | hcall_real_table_end: |
2035 | 2053 | ||
2036 | ignore_hdec: | 2054 | ignore_hdec: |
@@ -2338,7 +2356,18 @@ kvmppc_read_intr: | |||
2338 | cmpdi r6, 0 | 2356 | cmpdi r6, 0 |
2339 | beq- 1f | 2357 | beq- 1f |
2340 | lwzcix r0, r6, r7 | 2358 | lwzcix r0, r6, r7 |
2341 | rlwinm. r3, r0, 0, 0xffffff | 2359 | /* |
2360 | * Save XIRR for later. Since we get in in reverse endian on LE | ||
2361 | * systems, save it byte reversed and fetch it back in host endian. | ||
2362 | */ | ||
2363 | li r3, HSTATE_SAVED_XIRR | ||
2364 | STWX_BE r0, r3, r13 | ||
2365 | #ifdef __LITTLE_ENDIAN__ | ||
2366 | lwz r3, HSTATE_SAVED_XIRR(r13) | ||
2367 | #else | ||
2368 | mr r3, r0 | ||
2369 | #endif | ||
2370 | rlwinm. r3, r3, 0, 0xffffff | ||
2342 | sync | 2371 | sync |
2343 | beq 1f /* if nothing pending in the ICP */ | 2372 | beq 1f /* if nothing pending in the ICP */ |
2344 | 2373 | ||
@@ -2370,10 +2399,9 @@ kvmppc_read_intr: | |||
2370 | li r3, -1 | 2399 | li r3, -1 |
2371 | 1: blr | 2400 | 1: blr |
2372 | 2401 | ||
2373 | 42: /* It's not an IPI and it's for the host, stash it in the PACA | 2402 | 42: /* It's not an IPI and it's for the host. We saved a copy of XIRR in |
2374 | * before exit, it will be picked up by the host ICP driver | 2403 | * the PACA earlier, it will be picked up by the host ICP driver |
2375 | */ | 2404 | */ |
2376 | stw r0, HSTATE_SAVED_XIRR(r13) | ||
2377 | li r3, 1 | 2405 | li r3, 1 |
2378 | b 1b | 2406 | b 1b |
2379 | 2407 | ||
@@ -2408,11 +2436,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX) | |||
2408 | mtmsrd r8 | 2436 | mtmsrd r8 |
2409 | isync | 2437 | isync |
2410 | addi r3,r3,VCPU_FPRS | 2438 | addi r3,r3,VCPU_FPRS |
2411 | bl .store_fp_state | 2439 | bl store_fp_state |
2412 | #ifdef CONFIG_ALTIVEC | 2440 | #ifdef CONFIG_ALTIVEC |
2413 | BEGIN_FTR_SECTION | 2441 | BEGIN_FTR_SECTION |
2414 | addi r3,r31,VCPU_VRS | 2442 | addi r3,r31,VCPU_VRS |
2415 | bl .store_vr_state | 2443 | bl store_vr_state |
2416 | END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | 2444 | END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) |
2417 | #endif | 2445 | #endif |
2418 | mfspr r6,SPRN_VRSAVE | 2446 | mfspr r6,SPRN_VRSAVE |
@@ -2444,11 +2472,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX) | |||
2444 | mtmsrd r8 | 2472 | mtmsrd r8 |
2445 | isync | 2473 | isync |
2446 | addi r3,r4,VCPU_FPRS | 2474 | addi r3,r4,VCPU_FPRS |
2447 | bl .load_fp_state | 2475 | bl load_fp_state |
2448 | #ifdef CONFIG_ALTIVEC | 2476 | #ifdef CONFIG_ALTIVEC |
2449 | BEGIN_FTR_SECTION | 2477 | BEGIN_FTR_SECTION |
2450 | addi r3,r31,VCPU_VRS | 2478 | addi r3,r31,VCPU_VRS |
2451 | bl .load_vr_state | 2479 | bl load_vr_state |
2452 | END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | 2480 | END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) |
2453 | #endif | 2481 | #endif |
2454 | lwz r7,VCPU_VRSAVE(r31) | 2482 | lwz r7,VCPU_VRSAVE(r31) |
diff --git a/arch/powerpc/kvm/book3s_paired_singles.c b/arch/powerpc/kvm/book3s_paired_singles.c index 6c8011fd57e6..bfb8035314e3 100644 --- a/arch/powerpc/kvm/book3s_paired_singles.c +++ b/arch/powerpc/kvm/book3s_paired_singles.c | |||
@@ -639,26 +639,36 @@ static int kvmppc_ps_one_in(struct kvm_vcpu *vcpu, bool rc, | |||
639 | 639 | ||
640 | int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu) | 640 | int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu) |
641 | { | 641 | { |
642 | u32 inst = kvmppc_get_last_inst(vcpu); | 642 | u32 inst; |
643 | enum emulation_result emulated = EMULATE_DONE; | 643 | enum emulation_result emulated = EMULATE_DONE; |
644 | int ax_rd, ax_ra, ax_rb, ax_rc; | ||
645 | short full_d; | ||
646 | u64 *fpr_d, *fpr_a, *fpr_b, *fpr_c; | ||
644 | 647 | ||
645 | int ax_rd = inst_get_field(inst, 6, 10); | 648 | bool rcomp; |
646 | int ax_ra = inst_get_field(inst, 11, 15); | 649 | u32 cr; |
647 | int ax_rb = inst_get_field(inst, 16, 20); | ||
648 | int ax_rc = inst_get_field(inst, 21, 25); | ||
649 | short full_d = inst_get_field(inst, 16, 31); | ||
650 | |||
651 | u64 *fpr_d = &VCPU_FPR(vcpu, ax_rd); | ||
652 | u64 *fpr_a = &VCPU_FPR(vcpu, ax_ra); | ||
653 | u64 *fpr_b = &VCPU_FPR(vcpu, ax_rb); | ||
654 | u64 *fpr_c = &VCPU_FPR(vcpu, ax_rc); | ||
655 | |||
656 | bool rcomp = (inst & 1) ? true : false; | ||
657 | u32 cr = kvmppc_get_cr(vcpu); | ||
658 | #ifdef DEBUG | 650 | #ifdef DEBUG |
659 | int i; | 651 | int i; |
660 | #endif | 652 | #endif |
661 | 653 | ||
654 | emulated = kvmppc_get_last_inst(vcpu, INST_GENERIC, &inst); | ||
655 | if (emulated != EMULATE_DONE) | ||
656 | return emulated; | ||
657 | |||
658 | ax_rd = inst_get_field(inst, 6, 10); | ||
659 | ax_ra = inst_get_field(inst, 11, 15); | ||
660 | ax_rb = inst_get_field(inst, 16, 20); | ||
661 | ax_rc = inst_get_field(inst, 21, 25); | ||
662 | full_d = inst_get_field(inst, 16, 31); | ||
663 | |||
664 | fpr_d = &VCPU_FPR(vcpu, ax_rd); | ||
665 | fpr_a = &VCPU_FPR(vcpu, ax_ra); | ||
666 | fpr_b = &VCPU_FPR(vcpu, ax_rb); | ||
667 | fpr_c = &VCPU_FPR(vcpu, ax_rc); | ||
668 | |||
669 | rcomp = (inst & 1) ? true : false; | ||
670 | cr = kvmppc_get_cr(vcpu); | ||
671 | |||
662 | if (!kvmppc_inst_is_paired_single(vcpu, inst)) | 672 | if (!kvmppc_inst_is_paired_single(vcpu, inst)) |
663 | return EMULATE_FAIL; | 673 | return EMULATE_FAIL; |
664 | 674 | ||
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c index 8eef1e519077..faffb27badd9 100644 --- a/arch/powerpc/kvm/book3s_pr.c +++ b/arch/powerpc/kvm/book3s_pr.c | |||
@@ -62,6 +62,35 @@ static void kvmppc_giveup_fac(struct kvm_vcpu *vcpu, ulong fac); | |||
62 | #define HW_PAGE_SIZE PAGE_SIZE | 62 | #define HW_PAGE_SIZE PAGE_SIZE |
63 | #endif | 63 | #endif |
64 | 64 | ||
65 | static bool kvmppc_is_split_real(struct kvm_vcpu *vcpu) | ||
66 | { | ||
67 | ulong msr = kvmppc_get_msr(vcpu); | ||
68 | return (msr & (MSR_IR|MSR_DR)) == MSR_DR; | ||
69 | } | ||
70 | |||
71 | static void kvmppc_fixup_split_real(struct kvm_vcpu *vcpu) | ||
72 | { | ||
73 | ulong msr = kvmppc_get_msr(vcpu); | ||
74 | ulong pc = kvmppc_get_pc(vcpu); | ||
75 | |||
76 | /* We are in DR only split real mode */ | ||
77 | if ((msr & (MSR_IR|MSR_DR)) != MSR_DR) | ||
78 | return; | ||
79 | |||
80 | /* We have not fixed up the guest already */ | ||
81 | if (vcpu->arch.hflags & BOOK3S_HFLAG_SPLIT_HACK) | ||
82 | return; | ||
83 | |||
84 | /* The code is in fixupable address space */ | ||
85 | if (pc & SPLIT_HACK_MASK) | ||
86 | return; | ||
87 | |||
88 | vcpu->arch.hflags |= BOOK3S_HFLAG_SPLIT_HACK; | ||
89 | kvmppc_set_pc(vcpu, pc | SPLIT_HACK_OFFS); | ||
90 | } | ||
91 | |||
92 | void kvmppc_unfixup_split_real(struct kvm_vcpu *vcpu); | ||
93 | |||
65 | static void kvmppc_core_vcpu_load_pr(struct kvm_vcpu *vcpu, int cpu) | 94 | static void kvmppc_core_vcpu_load_pr(struct kvm_vcpu *vcpu, int cpu) |
66 | { | 95 | { |
67 | #ifdef CONFIG_PPC_BOOK3S_64 | 96 | #ifdef CONFIG_PPC_BOOK3S_64 |
@@ -71,10 +100,19 @@ static void kvmppc_core_vcpu_load_pr(struct kvm_vcpu *vcpu, int cpu) | |||
71 | svcpu->in_use = 0; | 100 | svcpu->in_use = 0; |
72 | svcpu_put(svcpu); | 101 | svcpu_put(svcpu); |
73 | #endif | 102 | #endif |
103 | |||
104 | /* Disable AIL if supported */ | ||
105 | if (cpu_has_feature(CPU_FTR_HVMODE) && | ||
106 | cpu_has_feature(CPU_FTR_ARCH_207S)) | ||
107 | mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) & ~LPCR_AIL); | ||
108 | |||
74 | vcpu->cpu = smp_processor_id(); | 109 | vcpu->cpu = smp_processor_id(); |
75 | #ifdef CONFIG_PPC_BOOK3S_32 | 110 | #ifdef CONFIG_PPC_BOOK3S_32 |
76 | current->thread.kvm_shadow_vcpu = vcpu->arch.shadow_vcpu; | 111 | current->thread.kvm_shadow_vcpu = vcpu->arch.shadow_vcpu; |
77 | #endif | 112 | #endif |
113 | |||
114 | if (kvmppc_is_split_real(vcpu)) | ||
115 | kvmppc_fixup_split_real(vcpu); | ||
78 | } | 116 | } |
79 | 117 | ||
80 | static void kvmppc_core_vcpu_put_pr(struct kvm_vcpu *vcpu) | 118 | static void kvmppc_core_vcpu_put_pr(struct kvm_vcpu *vcpu) |
@@ -89,8 +127,17 @@ static void kvmppc_core_vcpu_put_pr(struct kvm_vcpu *vcpu) | |||
89 | svcpu_put(svcpu); | 127 | svcpu_put(svcpu); |
90 | #endif | 128 | #endif |
91 | 129 | ||
130 | if (kvmppc_is_split_real(vcpu)) | ||
131 | kvmppc_unfixup_split_real(vcpu); | ||
132 | |||
92 | kvmppc_giveup_ext(vcpu, MSR_FP | MSR_VEC | MSR_VSX); | 133 | kvmppc_giveup_ext(vcpu, MSR_FP | MSR_VEC | MSR_VSX); |
93 | kvmppc_giveup_fac(vcpu, FSCR_TAR_LG); | 134 | kvmppc_giveup_fac(vcpu, FSCR_TAR_LG); |
135 | |||
136 | /* Enable AIL if supported */ | ||
137 | if (cpu_has_feature(CPU_FTR_HVMODE) && | ||
138 | cpu_has_feature(CPU_FTR_ARCH_207S)) | ||
139 | mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) | LPCR_AIL_3); | ||
140 | |||
94 | vcpu->cpu = -1; | 141 | vcpu->cpu = -1; |
95 | } | 142 | } |
96 | 143 | ||
@@ -120,6 +167,14 @@ void kvmppc_copy_to_svcpu(struct kvmppc_book3s_shadow_vcpu *svcpu, | |||
120 | #ifdef CONFIG_PPC_BOOK3S_64 | 167 | #ifdef CONFIG_PPC_BOOK3S_64 |
121 | svcpu->shadow_fscr = vcpu->arch.shadow_fscr; | 168 | svcpu->shadow_fscr = vcpu->arch.shadow_fscr; |
122 | #endif | 169 | #endif |
170 | /* | ||
171 | * Now also save the current time base value. We use this | ||
172 | * to find the guest purr and spurr value. | ||
173 | */ | ||
174 | vcpu->arch.entry_tb = get_tb(); | ||
175 | vcpu->arch.entry_vtb = get_vtb(); | ||
176 | if (cpu_has_feature(CPU_FTR_ARCH_207S)) | ||
177 | vcpu->arch.entry_ic = mfspr(SPRN_IC); | ||
123 | svcpu->in_use = true; | 178 | svcpu->in_use = true; |
124 | } | 179 | } |
125 | 180 | ||
@@ -166,6 +221,14 @@ void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu, | |||
166 | #ifdef CONFIG_PPC_BOOK3S_64 | 221 | #ifdef CONFIG_PPC_BOOK3S_64 |
167 | vcpu->arch.shadow_fscr = svcpu->shadow_fscr; | 222 | vcpu->arch.shadow_fscr = svcpu->shadow_fscr; |
168 | #endif | 223 | #endif |
224 | /* | ||
225 | * Update purr and spurr using time base on exit. | ||
226 | */ | ||
227 | vcpu->arch.purr += get_tb() - vcpu->arch.entry_tb; | ||
228 | vcpu->arch.spurr += get_tb() - vcpu->arch.entry_tb; | ||
229 | vcpu->arch.vtb += get_vtb() - vcpu->arch.entry_vtb; | ||
230 | if (cpu_has_feature(CPU_FTR_ARCH_207S)) | ||
231 | vcpu->arch.ic += mfspr(SPRN_IC) - vcpu->arch.entry_ic; | ||
169 | svcpu->in_use = false; | 232 | svcpu->in_use = false; |
170 | 233 | ||
171 | out: | 234 | out: |
@@ -294,6 +357,11 @@ static void kvmppc_set_msr_pr(struct kvm_vcpu *vcpu, u64 msr) | |||
294 | } | 357 | } |
295 | } | 358 | } |
296 | 359 | ||
360 | if (kvmppc_is_split_real(vcpu)) | ||
361 | kvmppc_fixup_split_real(vcpu); | ||
362 | else | ||
363 | kvmppc_unfixup_split_real(vcpu); | ||
364 | |||
297 | if ((kvmppc_get_msr(vcpu) & (MSR_PR|MSR_IR|MSR_DR)) != | 365 | if ((kvmppc_get_msr(vcpu) & (MSR_PR|MSR_IR|MSR_DR)) != |
298 | (old_msr & (MSR_PR|MSR_IR|MSR_DR))) { | 366 | (old_msr & (MSR_PR|MSR_IR|MSR_DR))) { |
299 | kvmppc_mmu_flush_segments(vcpu); | 367 | kvmppc_mmu_flush_segments(vcpu); |
@@ -443,19 +511,19 @@ static void kvmppc_patch_dcbz(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte) | |||
443 | put_page(hpage); | 511 | put_page(hpage); |
444 | } | 512 | } |
445 | 513 | ||
446 | static int kvmppc_visible_gfn(struct kvm_vcpu *vcpu, gfn_t gfn) | 514 | static int kvmppc_visible_gpa(struct kvm_vcpu *vcpu, gpa_t gpa) |
447 | { | 515 | { |
448 | ulong mp_pa = vcpu->arch.magic_page_pa; | 516 | ulong mp_pa = vcpu->arch.magic_page_pa; |
449 | 517 | ||
450 | if (!(kvmppc_get_msr(vcpu) & MSR_SF)) | 518 | if (!(kvmppc_get_msr(vcpu) & MSR_SF)) |
451 | mp_pa = (uint32_t)mp_pa; | 519 | mp_pa = (uint32_t)mp_pa; |
452 | 520 | ||
453 | if (unlikely(mp_pa) && | 521 | gpa &= ~0xFFFULL; |
454 | unlikely((mp_pa & KVM_PAM) >> PAGE_SHIFT == gfn)) { | 522 | if (unlikely(mp_pa) && unlikely((mp_pa & KVM_PAM) == (gpa & KVM_PAM))) { |
455 | return 1; | 523 | return 1; |
456 | } | 524 | } |
457 | 525 | ||
458 | return kvm_is_visible_gfn(vcpu->kvm, gfn); | 526 | return kvm_is_visible_gfn(vcpu->kvm, gpa >> PAGE_SHIFT); |
459 | } | 527 | } |
460 | 528 | ||
461 | int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu, | 529 | int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu, |
@@ -494,6 +562,11 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
494 | pte.vpage |= ((u64)VSID_REAL << (SID_SHIFT - 12)); | 562 | pte.vpage |= ((u64)VSID_REAL << (SID_SHIFT - 12)); |
495 | break; | 563 | break; |
496 | case MSR_DR: | 564 | case MSR_DR: |
565 | if (!data && | ||
566 | (vcpu->arch.hflags & BOOK3S_HFLAG_SPLIT_HACK) && | ||
567 | ((pte.raddr & SPLIT_HACK_MASK) == SPLIT_HACK_OFFS)) | ||
568 | pte.raddr &= ~SPLIT_HACK_MASK; | ||
569 | /* fall through */ | ||
497 | case MSR_IR: | 570 | case MSR_IR: |
498 | vcpu->arch.mmu.esid_to_vsid(vcpu, eaddr >> SID_SHIFT, &vsid); | 571 | vcpu->arch.mmu.esid_to_vsid(vcpu, eaddr >> SID_SHIFT, &vsid); |
499 | 572 | ||
@@ -541,7 +614,7 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
541 | kvmppc_set_dar(vcpu, kvmppc_get_fault_dar(vcpu)); | 614 | kvmppc_set_dar(vcpu, kvmppc_get_fault_dar(vcpu)); |
542 | kvmppc_book3s_queue_irqprio(vcpu, vec + 0x80); | 615 | kvmppc_book3s_queue_irqprio(vcpu, vec + 0x80); |
543 | } else if (!is_mmio && | 616 | } else if (!is_mmio && |
544 | kvmppc_visible_gfn(vcpu, pte.raddr >> PAGE_SHIFT)) { | 617 | kvmppc_visible_gpa(vcpu, pte.raddr)) { |
545 | if (data && !(vcpu->arch.fault_dsisr & DSISR_NOHPTE)) { | 618 | if (data && !(vcpu->arch.fault_dsisr & DSISR_NOHPTE)) { |
546 | /* | 619 | /* |
547 | * There is already a host HPTE there, presumably | 620 | * There is already a host HPTE there, presumably |
@@ -637,42 +710,6 @@ static void kvmppc_giveup_fac(struct kvm_vcpu *vcpu, ulong fac) | |||
637 | #endif | 710 | #endif |
638 | } | 711 | } |
639 | 712 | ||
640 | static int kvmppc_read_inst(struct kvm_vcpu *vcpu) | ||
641 | { | ||
642 | ulong srr0 = kvmppc_get_pc(vcpu); | ||
643 | u32 last_inst = kvmppc_get_last_inst(vcpu); | ||
644 | int ret; | ||
645 | |||
646 | ret = kvmppc_ld(vcpu, &srr0, sizeof(u32), &last_inst, false); | ||
647 | if (ret == -ENOENT) { | ||
648 | ulong msr = kvmppc_get_msr(vcpu); | ||
649 | |||
650 | msr = kvmppc_set_field(msr, 33, 33, 1); | ||
651 | msr = kvmppc_set_field(msr, 34, 36, 0); | ||
652 | msr = kvmppc_set_field(msr, 42, 47, 0); | ||
653 | kvmppc_set_msr_fast(vcpu, msr); | ||
654 | kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_INST_STORAGE); | ||
655 | return EMULATE_AGAIN; | ||
656 | } | ||
657 | |||
658 | return EMULATE_DONE; | ||
659 | } | ||
660 | |||
661 | static int kvmppc_check_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr) | ||
662 | { | ||
663 | |||
664 | /* Need to do paired single emulation? */ | ||
665 | if (!(vcpu->arch.hflags & BOOK3S_HFLAG_PAIRED_SINGLE)) | ||
666 | return EMULATE_DONE; | ||
667 | |||
668 | /* Read out the instruction */ | ||
669 | if (kvmppc_read_inst(vcpu) == EMULATE_DONE) | ||
670 | /* Need to emulate */ | ||
671 | return EMULATE_FAIL; | ||
672 | |||
673 | return EMULATE_AGAIN; | ||
674 | } | ||
675 | |||
676 | /* Handle external providers (FPU, Altivec, VSX) */ | 713 | /* Handle external providers (FPU, Altivec, VSX) */ |
677 | static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr, | 714 | static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr, |
678 | ulong msr) | 715 | ulong msr) |
@@ -834,6 +871,15 @@ static int kvmppc_handle_fac(struct kvm_vcpu *vcpu, ulong fac) | |||
834 | 871 | ||
835 | return RESUME_GUEST; | 872 | return RESUME_GUEST; |
836 | } | 873 | } |
874 | |||
875 | void kvmppc_set_fscr(struct kvm_vcpu *vcpu, u64 fscr) | ||
876 | { | ||
877 | if ((vcpu->arch.fscr & FSCR_TAR) && !(fscr & FSCR_TAR)) { | ||
878 | /* TAR got dropped, drop it in shadow too */ | ||
879 | kvmppc_giveup_fac(vcpu, FSCR_TAR_LG); | ||
880 | } | ||
881 | vcpu->arch.fscr = fscr; | ||
882 | } | ||
837 | #endif | 883 | #endif |
838 | 884 | ||
839 | int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu, | 885 | int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu, |
@@ -858,6 +904,9 @@ int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
858 | ulong shadow_srr1 = vcpu->arch.shadow_srr1; | 904 | ulong shadow_srr1 = vcpu->arch.shadow_srr1; |
859 | vcpu->stat.pf_instruc++; | 905 | vcpu->stat.pf_instruc++; |
860 | 906 | ||
907 | if (kvmppc_is_split_real(vcpu)) | ||
908 | kvmppc_fixup_split_real(vcpu); | ||
909 | |||
861 | #ifdef CONFIG_PPC_BOOK3S_32 | 910 | #ifdef CONFIG_PPC_BOOK3S_32 |
862 | /* We set segments as unused segments when invalidating them. So | 911 | /* We set segments as unused segments when invalidating them. So |
863 | * treat the respective fault as segment fault. */ | 912 | * treat the respective fault as segment fault. */ |
@@ -960,6 +1009,7 @@ int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
960 | case BOOK3S_INTERRUPT_DECREMENTER: | 1009 | case BOOK3S_INTERRUPT_DECREMENTER: |
961 | case BOOK3S_INTERRUPT_HV_DECREMENTER: | 1010 | case BOOK3S_INTERRUPT_HV_DECREMENTER: |
962 | case BOOK3S_INTERRUPT_DOORBELL: | 1011 | case BOOK3S_INTERRUPT_DOORBELL: |
1012 | case BOOK3S_INTERRUPT_H_DOORBELL: | ||
963 | vcpu->stat.dec_exits++; | 1013 | vcpu->stat.dec_exits++; |
964 | r = RESUME_GUEST; | 1014 | r = RESUME_GUEST; |
965 | break; | 1015 | break; |
@@ -977,15 +1027,24 @@ int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
977 | { | 1027 | { |
978 | enum emulation_result er; | 1028 | enum emulation_result er; |
979 | ulong flags; | 1029 | ulong flags; |
1030 | u32 last_inst; | ||
1031 | int emul; | ||
980 | 1032 | ||
981 | program_interrupt: | 1033 | program_interrupt: |
982 | flags = vcpu->arch.shadow_srr1 & 0x1f0000ull; | 1034 | flags = vcpu->arch.shadow_srr1 & 0x1f0000ull; |
983 | 1035 | ||
1036 | emul = kvmppc_get_last_inst(vcpu, INST_GENERIC, &last_inst); | ||
1037 | if (emul != EMULATE_DONE) { | ||
1038 | r = RESUME_GUEST; | ||
1039 | break; | ||
1040 | } | ||
1041 | |||
984 | if (kvmppc_get_msr(vcpu) & MSR_PR) { | 1042 | if (kvmppc_get_msr(vcpu) & MSR_PR) { |
985 | #ifdef EXIT_DEBUG | 1043 | #ifdef EXIT_DEBUG |
986 | printk(KERN_INFO "Userspace triggered 0x700 exception at 0x%lx (0x%x)\n", kvmppc_get_pc(vcpu), kvmppc_get_last_inst(vcpu)); | 1044 | pr_info("Userspace triggered 0x700 exception at\n 0x%lx (0x%x)\n", |
1045 | kvmppc_get_pc(vcpu), last_inst); | ||
987 | #endif | 1046 | #endif |
988 | if ((kvmppc_get_last_inst(vcpu) & 0xff0007ff) != | 1047 | if ((last_inst & 0xff0007ff) != |
989 | (INS_DCBZ & 0xfffffff7)) { | 1048 | (INS_DCBZ & 0xfffffff7)) { |
990 | kvmppc_core_queue_program(vcpu, flags); | 1049 | kvmppc_core_queue_program(vcpu, flags); |
991 | r = RESUME_GUEST; | 1050 | r = RESUME_GUEST; |
@@ -1004,7 +1063,7 @@ program_interrupt: | |||
1004 | break; | 1063 | break; |
1005 | case EMULATE_FAIL: | 1064 | case EMULATE_FAIL: |
1006 | printk(KERN_CRIT "%s: emulation at %lx failed (%08x)\n", | 1065 | printk(KERN_CRIT "%s: emulation at %lx failed (%08x)\n", |
1007 | __func__, kvmppc_get_pc(vcpu), kvmppc_get_last_inst(vcpu)); | 1066 | __func__, kvmppc_get_pc(vcpu), last_inst); |
1008 | kvmppc_core_queue_program(vcpu, flags); | 1067 | kvmppc_core_queue_program(vcpu, flags); |
1009 | r = RESUME_GUEST; | 1068 | r = RESUME_GUEST; |
1010 | break; | 1069 | break; |
@@ -1021,8 +1080,23 @@ program_interrupt: | |||
1021 | break; | 1080 | break; |
1022 | } | 1081 | } |
1023 | case BOOK3S_INTERRUPT_SYSCALL: | 1082 | case BOOK3S_INTERRUPT_SYSCALL: |
1083 | { | ||
1084 | u32 last_sc; | ||
1085 | int emul; | ||
1086 | |||
1087 | /* Get last sc for papr */ | ||
1088 | if (vcpu->arch.papr_enabled) { | ||
1089 | /* The sc instuction points SRR0 to the next inst */ | ||
1090 | emul = kvmppc_get_last_inst(vcpu, INST_SC, &last_sc); | ||
1091 | if (emul != EMULATE_DONE) { | ||
1092 | kvmppc_set_pc(vcpu, kvmppc_get_pc(vcpu) - 4); | ||
1093 | r = RESUME_GUEST; | ||
1094 | break; | ||
1095 | } | ||
1096 | } | ||
1097 | |||
1024 | if (vcpu->arch.papr_enabled && | 1098 | if (vcpu->arch.papr_enabled && |
1025 | (kvmppc_get_last_sc(vcpu) == 0x44000022) && | 1099 | (last_sc == 0x44000022) && |
1026 | !(kvmppc_get_msr(vcpu) & MSR_PR)) { | 1100 | !(kvmppc_get_msr(vcpu) & MSR_PR)) { |
1027 | /* SC 1 papr hypercalls */ | 1101 | /* SC 1 papr hypercalls */ |
1028 | ulong cmd = kvmppc_get_gpr(vcpu, 3); | 1102 | ulong cmd = kvmppc_get_gpr(vcpu, 3); |
@@ -1067,36 +1141,51 @@ program_interrupt: | |||
1067 | r = RESUME_GUEST; | 1141 | r = RESUME_GUEST; |
1068 | } | 1142 | } |
1069 | break; | 1143 | break; |
1144 | } | ||
1070 | case BOOK3S_INTERRUPT_FP_UNAVAIL: | 1145 | case BOOK3S_INTERRUPT_FP_UNAVAIL: |
1071 | case BOOK3S_INTERRUPT_ALTIVEC: | 1146 | case BOOK3S_INTERRUPT_ALTIVEC: |
1072 | case BOOK3S_INTERRUPT_VSX: | 1147 | case BOOK3S_INTERRUPT_VSX: |
1073 | { | 1148 | { |
1074 | int ext_msr = 0; | 1149 | int ext_msr = 0; |
1150 | int emul; | ||
1151 | u32 last_inst; | ||
1152 | |||
1153 | if (vcpu->arch.hflags & BOOK3S_HFLAG_PAIRED_SINGLE) { | ||
1154 | /* Do paired single instruction emulation */ | ||
1155 | emul = kvmppc_get_last_inst(vcpu, INST_GENERIC, | ||
1156 | &last_inst); | ||
1157 | if (emul == EMULATE_DONE) | ||
1158 | goto program_interrupt; | ||
1159 | else | ||
1160 | r = RESUME_GUEST; | ||
1075 | 1161 | ||
1076 | switch (exit_nr) { | 1162 | break; |
1077 | case BOOK3S_INTERRUPT_FP_UNAVAIL: ext_msr = MSR_FP; break; | ||
1078 | case BOOK3S_INTERRUPT_ALTIVEC: ext_msr = MSR_VEC; break; | ||
1079 | case BOOK3S_INTERRUPT_VSX: ext_msr = MSR_VSX; break; | ||
1080 | } | 1163 | } |
1081 | 1164 | ||
1082 | switch (kvmppc_check_ext(vcpu, exit_nr)) { | 1165 | /* Enable external provider */ |
1083 | case EMULATE_DONE: | 1166 | switch (exit_nr) { |
1084 | /* everything ok - let's enable the ext */ | 1167 | case BOOK3S_INTERRUPT_FP_UNAVAIL: |
1085 | r = kvmppc_handle_ext(vcpu, exit_nr, ext_msr); | 1168 | ext_msr = MSR_FP; |
1086 | break; | 1169 | break; |
1087 | case EMULATE_FAIL: | 1170 | |
1088 | /* we need to emulate this instruction */ | 1171 | case BOOK3S_INTERRUPT_ALTIVEC: |
1089 | goto program_interrupt; | 1172 | ext_msr = MSR_VEC; |
1090 | break; | 1173 | break; |
1091 | default: | 1174 | |
1092 | /* nothing to worry about - go again */ | 1175 | case BOOK3S_INTERRUPT_VSX: |
1176 | ext_msr = MSR_VSX; | ||
1093 | break; | 1177 | break; |
1094 | } | 1178 | } |
1179 | |||
1180 | r = kvmppc_handle_ext(vcpu, exit_nr, ext_msr); | ||
1095 | break; | 1181 | break; |
1096 | } | 1182 | } |
1097 | case BOOK3S_INTERRUPT_ALIGNMENT: | 1183 | case BOOK3S_INTERRUPT_ALIGNMENT: |
1098 | if (kvmppc_read_inst(vcpu) == EMULATE_DONE) { | 1184 | { |
1099 | u32 last_inst = kvmppc_get_last_inst(vcpu); | 1185 | u32 last_inst; |
1186 | int emul = kvmppc_get_last_inst(vcpu, INST_GENERIC, &last_inst); | ||
1187 | |||
1188 | if (emul == EMULATE_DONE) { | ||
1100 | u32 dsisr; | 1189 | u32 dsisr; |
1101 | u64 dar; | 1190 | u64 dar; |
1102 | 1191 | ||
@@ -1110,6 +1199,7 @@ program_interrupt: | |||
1110 | } | 1199 | } |
1111 | r = RESUME_GUEST; | 1200 | r = RESUME_GUEST; |
1112 | break; | 1201 | break; |
1202 | } | ||
1113 | #ifdef CONFIG_PPC_BOOK3S_64 | 1203 | #ifdef CONFIG_PPC_BOOK3S_64 |
1114 | case BOOK3S_INTERRUPT_FAC_UNAVAIL: | 1204 | case BOOK3S_INTERRUPT_FAC_UNAVAIL: |
1115 | kvmppc_handle_fac(vcpu, vcpu->arch.shadow_fscr >> 56); | 1205 | kvmppc_handle_fac(vcpu, vcpu->arch.shadow_fscr >> 56); |
@@ -1233,6 +1323,7 @@ static int kvmppc_get_one_reg_pr(struct kvm_vcpu *vcpu, u64 id, | |||
1233 | *val = get_reg_val(id, to_book3s(vcpu)->hior); | 1323 | *val = get_reg_val(id, to_book3s(vcpu)->hior); |
1234 | break; | 1324 | break; |
1235 | case KVM_REG_PPC_LPCR: | 1325 | case KVM_REG_PPC_LPCR: |
1326 | case KVM_REG_PPC_LPCR_64: | ||
1236 | /* | 1327 | /* |
1237 | * We are only interested in the LPCR_ILE bit | 1328 | * We are only interested in the LPCR_ILE bit |
1238 | */ | 1329 | */ |
@@ -1268,6 +1359,7 @@ static int kvmppc_set_one_reg_pr(struct kvm_vcpu *vcpu, u64 id, | |||
1268 | to_book3s(vcpu)->hior_explicit = true; | 1359 | to_book3s(vcpu)->hior_explicit = true; |
1269 | break; | 1360 | break; |
1270 | case KVM_REG_PPC_LPCR: | 1361 | case KVM_REG_PPC_LPCR: |
1362 | case KVM_REG_PPC_LPCR_64: | ||
1271 | kvmppc_set_lpcr_pr(vcpu, set_reg_val(id, *val)); | 1363 | kvmppc_set_lpcr_pr(vcpu, set_reg_val(id, *val)); |
1272 | break; | 1364 | break; |
1273 | default: | 1365 | default: |
@@ -1310,8 +1402,7 @@ static struct kvm_vcpu *kvmppc_core_vcpu_create_pr(struct kvm *kvm, | |||
1310 | p = __get_free_page(GFP_KERNEL|__GFP_ZERO); | 1402 | p = __get_free_page(GFP_KERNEL|__GFP_ZERO); |
1311 | if (!p) | 1403 | if (!p) |
1312 | goto uninit_vcpu; | 1404 | goto uninit_vcpu; |
1313 | /* the real shared page fills the last 4k of our page */ | 1405 | vcpu->arch.shared = (void *)p; |
1314 | vcpu->arch.shared = (void *)(p + PAGE_SIZE - 4096); | ||
1315 | #ifdef CONFIG_PPC_BOOK3S_64 | 1406 | #ifdef CONFIG_PPC_BOOK3S_64 |
1316 | /* Always start the shared struct in native endian mode */ | 1407 | /* Always start the shared struct in native endian mode */ |
1317 | #ifdef __BIG_ENDIAN__ | 1408 | #ifdef __BIG_ENDIAN__ |
@@ -1568,6 +1659,11 @@ static int kvmppc_core_init_vm_pr(struct kvm *kvm) | |||
1568 | { | 1659 | { |
1569 | mutex_init(&kvm->arch.hpt_mutex); | 1660 | mutex_init(&kvm->arch.hpt_mutex); |
1570 | 1661 | ||
1662 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
1663 | /* Start out with the default set of hcalls enabled */ | ||
1664 | kvmppc_pr_init_default_hcalls(kvm); | ||
1665 | #endif | ||
1666 | |||
1571 | if (firmware_has_feature(FW_FEATURE_SET_MODE)) { | 1667 | if (firmware_has_feature(FW_FEATURE_SET_MODE)) { |
1572 | spin_lock(&kvm_global_user_count_lock); | 1668 | spin_lock(&kvm_global_user_count_lock); |
1573 | if (++kvm_global_user_count == 1) | 1669 | if (++kvm_global_user_count == 1) |
@@ -1636,6 +1732,9 @@ static struct kvmppc_ops kvm_ops_pr = { | |||
1636 | .emulate_mfspr = kvmppc_core_emulate_mfspr_pr, | 1732 | .emulate_mfspr = kvmppc_core_emulate_mfspr_pr, |
1637 | .fast_vcpu_kick = kvm_vcpu_kick, | 1733 | .fast_vcpu_kick = kvm_vcpu_kick, |
1638 | .arch_vm_ioctl = kvm_arch_vm_ioctl_pr, | 1734 | .arch_vm_ioctl = kvm_arch_vm_ioctl_pr, |
1735 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
1736 | .hcall_implemented = kvmppc_hcall_impl_pr, | ||
1737 | #endif | ||
1639 | }; | 1738 | }; |
1640 | 1739 | ||
1641 | 1740 | ||
diff --git a/arch/powerpc/kvm/book3s_pr_papr.c b/arch/powerpc/kvm/book3s_pr_papr.c index 52a63bfe3f07..ce3c893d509b 100644 --- a/arch/powerpc/kvm/book3s_pr_papr.c +++ b/arch/powerpc/kvm/book3s_pr_papr.c | |||
@@ -40,8 +40,9 @@ static int kvmppc_h_pr_enter(struct kvm_vcpu *vcpu) | |||
40 | { | 40 | { |
41 | long flags = kvmppc_get_gpr(vcpu, 4); | 41 | long flags = kvmppc_get_gpr(vcpu, 4); |
42 | long pte_index = kvmppc_get_gpr(vcpu, 5); | 42 | long pte_index = kvmppc_get_gpr(vcpu, 5); |
43 | unsigned long pteg[2 * 8]; | 43 | __be64 pteg[2 * 8]; |
44 | unsigned long pteg_addr, i, *hpte; | 44 | __be64 *hpte; |
45 | unsigned long pteg_addr, i; | ||
45 | long int ret; | 46 | long int ret; |
46 | 47 | ||
47 | i = pte_index & 7; | 48 | i = pte_index & 7; |
@@ -93,8 +94,8 @@ static int kvmppc_h_pr_remove(struct kvm_vcpu *vcpu) | |||
93 | pteg = get_pteg_addr(vcpu, pte_index); | 94 | pteg = get_pteg_addr(vcpu, pte_index); |
94 | mutex_lock(&vcpu->kvm->arch.hpt_mutex); | 95 | mutex_lock(&vcpu->kvm->arch.hpt_mutex); |
95 | copy_from_user(pte, (void __user *)pteg, sizeof(pte)); | 96 | copy_from_user(pte, (void __user *)pteg, sizeof(pte)); |
96 | pte[0] = be64_to_cpu(pte[0]); | 97 | pte[0] = be64_to_cpu((__force __be64)pte[0]); |
97 | pte[1] = be64_to_cpu(pte[1]); | 98 | pte[1] = be64_to_cpu((__force __be64)pte[1]); |
98 | 99 | ||
99 | ret = H_NOT_FOUND; | 100 | ret = H_NOT_FOUND; |
100 | if ((pte[0] & HPTE_V_VALID) == 0 || | 101 | if ((pte[0] & HPTE_V_VALID) == 0 || |
@@ -171,8 +172,8 @@ static int kvmppc_h_pr_bulk_remove(struct kvm_vcpu *vcpu) | |||
171 | 172 | ||
172 | pteg = get_pteg_addr(vcpu, tsh & H_BULK_REMOVE_PTEX); | 173 | pteg = get_pteg_addr(vcpu, tsh & H_BULK_REMOVE_PTEX); |
173 | copy_from_user(pte, (void __user *)pteg, sizeof(pte)); | 174 | copy_from_user(pte, (void __user *)pteg, sizeof(pte)); |
174 | pte[0] = be64_to_cpu(pte[0]); | 175 | pte[0] = be64_to_cpu((__force __be64)pte[0]); |
175 | pte[1] = be64_to_cpu(pte[1]); | 176 | pte[1] = be64_to_cpu((__force __be64)pte[1]); |
176 | 177 | ||
177 | /* tsl = AVPN */ | 178 | /* tsl = AVPN */ |
178 | flags = (tsh & H_BULK_REMOVE_FLAGS) >> 26; | 179 | flags = (tsh & H_BULK_REMOVE_FLAGS) >> 26; |
@@ -211,8 +212,8 @@ static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu) | |||
211 | pteg = get_pteg_addr(vcpu, pte_index); | 212 | pteg = get_pteg_addr(vcpu, pte_index); |
212 | mutex_lock(&vcpu->kvm->arch.hpt_mutex); | 213 | mutex_lock(&vcpu->kvm->arch.hpt_mutex); |
213 | copy_from_user(pte, (void __user *)pteg, sizeof(pte)); | 214 | copy_from_user(pte, (void __user *)pteg, sizeof(pte)); |
214 | pte[0] = be64_to_cpu(pte[0]); | 215 | pte[0] = be64_to_cpu((__force __be64)pte[0]); |
215 | pte[1] = be64_to_cpu(pte[1]); | 216 | pte[1] = be64_to_cpu((__force __be64)pte[1]); |
216 | 217 | ||
217 | ret = H_NOT_FOUND; | 218 | ret = H_NOT_FOUND; |
218 | if ((pte[0] & HPTE_V_VALID) == 0 || | 219 | if ((pte[0] & HPTE_V_VALID) == 0 || |
@@ -231,8 +232,8 @@ static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu) | |||
231 | 232 | ||
232 | rb = compute_tlbie_rb(v, r, pte_index); | 233 | rb = compute_tlbie_rb(v, r, pte_index); |
233 | vcpu->arch.mmu.tlbie(vcpu, rb, rb & 1 ? true : false); | 234 | vcpu->arch.mmu.tlbie(vcpu, rb, rb & 1 ? true : false); |
234 | pte[0] = cpu_to_be64(pte[0]); | 235 | pte[0] = (__force u64)cpu_to_be64(pte[0]); |
235 | pte[1] = cpu_to_be64(pte[1]); | 236 | pte[1] = (__force u64)cpu_to_be64(pte[1]); |
236 | copy_to_user((void __user *)pteg, pte, sizeof(pte)); | 237 | copy_to_user((void __user *)pteg, pte, sizeof(pte)); |
237 | ret = H_SUCCESS; | 238 | ret = H_SUCCESS; |
238 | 239 | ||
@@ -266,6 +267,12 @@ static int kvmppc_h_pr_xics_hcall(struct kvm_vcpu *vcpu, u32 cmd) | |||
266 | 267 | ||
267 | int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd) | 268 | int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd) |
268 | { | 269 | { |
270 | int rc, idx; | ||
271 | |||
272 | if (cmd <= MAX_HCALL_OPCODE && | ||
273 | !test_bit(cmd/4, vcpu->kvm->arch.enabled_hcalls)) | ||
274 | return EMULATE_FAIL; | ||
275 | |||
269 | switch (cmd) { | 276 | switch (cmd) { |
270 | case H_ENTER: | 277 | case H_ENTER: |
271 | return kvmppc_h_pr_enter(vcpu); | 278 | return kvmppc_h_pr_enter(vcpu); |
@@ -294,8 +301,11 @@ int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd) | |||
294 | break; | 301 | break; |
295 | case H_RTAS: | 302 | case H_RTAS: |
296 | if (list_empty(&vcpu->kvm->arch.rtas_tokens)) | 303 | if (list_empty(&vcpu->kvm->arch.rtas_tokens)) |
297 | return RESUME_HOST; | 304 | break; |
298 | if (kvmppc_rtas_hcall(vcpu)) | 305 | idx = srcu_read_lock(&vcpu->kvm->srcu); |
306 | rc = kvmppc_rtas_hcall(vcpu); | ||
307 | srcu_read_unlock(&vcpu->kvm->srcu, idx); | ||
308 | if (rc) | ||
299 | break; | 309 | break; |
300 | kvmppc_set_gpr(vcpu, 3, 0); | 310 | kvmppc_set_gpr(vcpu, 3, 0); |
301 | return EMULATE_DONE; | 311 | return EMULATE_DONE; |
@@ -303,3 +313,61 @@ int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd) | |||
303 | 313 | ||
304 | return EMULATE_FAIL; | 314 | return EMULATE_FAIL; |
305 | } | 315 | } |
316 | |||
317 | int kvmppc_hcall_impl_pr(unsigned long cmd) | ||
318 | { | ||
319 | switch (cmd) { | ||
320 | case H_ENTER: | ||
321 | case H_REMOVE: | ||
322 | case H_PROTECT: | ||
323 | case H_BULK_REMOVE: | ||
324 | case H_PUT_TCE: | ||
325 | case H_CEDE: | ||
326 | #ifdef CONFIG_KVM_XICS | ||
327 | case H_XIRR: | ||
328 | case H_CPPR: | ||
329 | case H_EOI: | ||
330 | case H_IPI: | ||
331 | case H_IPOLL: | ||
332 | case H_XIRR_X: | ||
333 | #endif | ||
334 | return 1; | ||
335 | } | ||
336 | return 0; | ||
337 | } | ||
338 | |||
339 | /* | ||
340 | * List of hcall numbers to enable by default. | ||
341 | * For compatibility with old userspace, we enable by default | ||
342 | * all hcalls that were implemented before the hcall-enabling | ||
343 | * facility was added. Note this list should not include H_RTAS. | ||
344 | */ | ||
345 | static unsigned int default_hcall_list[] = { | ||
346 | H_ENTER, | ||
347 | H_REMOVE, | ||
348 | H_PROTECT, | ||
349 | H_BULK_REMOVE, | ||
350 | H_PUT_TCE, | ||
351 | H_CEDE, | ||
352 | #ifdef CONFIG_KVM_XICS | ||
353 | H_XIRR, | ||
354 | H_CPPR, | ||
355 | H_EOI, | ||
356 | H_IPI, | ||
357 | H_IPOLL, | ||
358 | H_XIRR_X, | ||
359 | #endif | ||
360 | 0 | ||
361 | }; | ||
362 | |||
363 | void kvmppc_pr_init_default_hcalls(struct kvm *kvm) | ||
364 | { | ||
365 | int i; | ||
366 | unsigned int hcall; | ||
367 | |||
368 | for (i = 0; default_hcall_list[i]; ++i) { | ||
369 | hcall = default_hcall_list[i]; | ||
370 | WARN_ON(!kvmppc_hcall_impl_pr(hcall)); | ||
371 | __set_bit(hcall / 4, kvm->arch.enabled_hcalls); | ||
372 | } | ||
373 | } | ||
diff --git a/arch/powerpc/kvm/book3s_xics.c b/arch/powerpc/kvm/book3s_xics.c index d1acd32a64c0..eaeb78047fb8 100644 --- a/arch/powerpc/kvm/book3s_xics.c +++ b/arch/powerpc/kvm/book3s_xics.c | |||
@@ -64,8 +64,12 @@ | |||
64 | static void icp_deliver_irq(struct kvmppc_xics *xics, struct kvmppc_icp *icp, | 64 | static void icp_deliver_irq(struct kvmppc_xics *xics, struct kvmppc_icp *icp, |
65 | u32 new_irq); | 65 | u32 new_irq); |
66 | 66 | ||
67 | static int ics_deliver_irq(struct kvmppc_xics *xics, u32 irq, u32 level, | 67 | /* |
68 | bool report_status) | 68 | * Return value ideally indicates how the interrupt was handled, but no |
69 | * callers look at it (given that we don't implement KVM_IRQ_LINE_STATUS), | ||
70 | * so just return 0. | ||
71 | */ | ||
72 | static int ics_deliver_irq(struct kvmppc_xics *xics, u32 irq, u32 level) | ||
69 | { | 73 | { |
70 | struct ics_irq_state *state; | 74 | struct ics_irq_state *state; |
71 | struct kvmppc_ics *ics; | 75 | struct kvmppc_ics *ics; |
@@ -82,17 +86,14 @@ static int ics_deliver_irq(struct kvmppc_xics *xics, u32 irq, u32 level, | |||
82 | if (!state->exists) | 86 | if (!state->exists) |
83 | return -EINVAL; | 87 | return -EINVAL; |
84 | 88 | ||
85 | if (report_status) | ||
86 | return state->asserted; | ||
87 | |||
88 | /* | 89 | /* |
89 | * We set state->asserted locklessly. This should be fine as | 90 | * We set state->asserted locklessly. This should be fine as |
90 | * we are the only setter, thus concurrent access is undefined | 91 | * we are the only setter, thus concurrent access is undefined |
91 | * to begin with. | 92 | * to begin with. |
92 | */ | 93 | */ |
93 | if (level == KVM_INTERRUPT_SET_LEVEL) | 94 | if (level == 1 || level == KVM_INTERRUPT_SET_LEVEL) |
94 | state->asserted = 1; | 95 | state->asserted = 1; |
95 | else if (level == KVM_INTERRUPT_UNSET) { | 96 | else if (level == 0 || level == KVM_INTERRUPT_UNSET) { |
96 | state->asserted = 0; | 97 | state->asserted = 0; |
97 | return 0; | 98 | return 0; |
98 | } | 99 | } |
@@ -100,7 +101,7 @@ static int ics_deliver_irq(struct kvmppc_xics *xics, u32 irq, u32 level, | |||
100 | /* Attempt delivery */ | 101 | /* Attempt delivery */ |
101 | icp_deliver_irq(xics, NULL, irq); | 102 | icp_deliver_irq(xics, NULL, irq); |
102 | 103 | ||
103 | return state->asserted; | 104 | return 0; |
104 | } | 105 | } |
105 | 106 | ||
106 | static void ics_check_resend(struct kvmppc_xics *xics, struct kvmppc_ics *ics, | 107 | static void ics_check_resend(struct kvmppc_xics *xics, struct kvmppc_ics *ics, |
@@ -772,6 +773,8 @@ static noinline int kvmppc_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr) | |||
772 | if (state->asserted) | 773 | if (state->asserted) |
773 | icp_deliver_irq(xics, icp, irq); | 774 | icp_deliver_irq(xics, icp, irq); |
774 | 775 | ||
776 | kvm_notify_acked_irq(vcpu->kvm, 0, irq); | ||
777 | |||
775 | return H_SUCCESS; | 778 | return H_SUCCESS; |
776 | } | 779 | } |
777 | 780 | ||
@@ -789,6 +792,8 @@ static noinline int kvmppc_xics_rm_complete(struct kvm_vcpu *vcpu, u32 hcall) | |||
789 | icp_check_resend(xics, icp); | 792 | icp_check_resend(xics, icp); |
790 | if (icp->rm_action & XICS_RM_REJECT) | 793 | if (icp->rm_action & XICS_RM_REJECT) |
791 | icp_deliver_irq(xics, icp, icp->rm_reject); | 794 | icp_deliver_irq(xics, icp, icp->rm_reject); |
795 | if (icp->rm_action & XICS_RM_NOTIFY_EOI) | ||
796 | kvm_notify_acked_irq(vcpu->kvm, 0, icp->rm_eoied_irq); | ||
792 | 797 | ||
793 | icp->rm_action = 0; | 798 | icp->rm_action = 0; |
794 | 799 | ||
@@ -1170,7 +1175,16 @@ int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level, | |||
1170 | { | 1175 | { |
1171 | struct kvmppc_xics *xics = kvm->arch.xics; | 1176 | struct kvmppc_xics *xics = kvm->arch.xics; |
1172 | 1177 | ||
1173 | return ics_deliver_irq(xics, irq, level, line_status); | 1178 | return ics_deliver_irq(xics, irq, level); |
1179 | } | ||
1180 | |||
1181 | int kvm_set_msi(struct kvm_kernel_irq_routing_entry *irq_entry, struct kvm *kvm, | ||
1182 | int irq_source_id, int level, bool line_status) | ||
1183 | { | ||
1184 | if (!level) | ||
1185 | return -1; | ||
1186 | return kvm_set_irq(kvm, irq_source_id, irq_entry->gsi, | ||
1187 | level, line_status); | ||
1174 | } | 1188 | } |
1175 | 1189 | ||
1176 | static int xics_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr) | 1190 | static int xics_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr) |
@@ -1301,3 +1315,26 @@ void kvmppc_xics_free_icp(struct kvm_vcpu *vcpu) | |||
1301 | vcpu->arch.icp = NULL; | 1315 | vcpu->arch.icp = NULL; |
1302 | vcpu->arch.irq_type = KVMPPC_IRQ_DEFAULT; | 1316 | vcpu->arch.irq_type = KVMPPC_IRQ_DEFAULT; |
1303 | } | 1317 | } |
1318 | |||
1319 | static int xics_set_irq(struct kvm_kernel_irq_routing_entry *e, | ||
1320 | struct kvm *kvm, int irq_source_id, int level, | ||
1321 | bool line_status) | ||
1322 | { | ||
1323 | return kvm_set_irq(kvm, irq_source_id, e->gsi, level, line_status); | ||
1324 | } | ||
1325 | |||
1326 | int kvm_irq_map_gsi(struct kvm *kvm, | ||
1327 | struct kvm_kernel_irq_routing_entry *entries, int gsi) | ||
1328 | { | ||
1329 | entries->gsi = gsi; | ||
1330 | entries->type = KVM_IRQ_ROUTING_IRQCHIP; | ||
1331 | entries->set = xics_set_irq; | ||
1332 | entries->irqchip.irqchip = 0; | ||
1333 | entries->irqchip.pin = gsi; | ||
1334 | return 1; | ||
1335 | } | ||
1336 | |||
1337 | int kvm_irq_map_chip_pin(struct kvm *kvm, unsigned irqchip, unsigned pin) | ||
1338 | { | ||
1339 | return pin; | ||
1340 | } | ||
diff --git a/arch/powerpc/kvm/book3s_xics.h b/arch/powerpc/kvm/book3s_xics.h index dd9326c5c19b..e8aaa7a3f209 100644 --- a/arch/powerpc/kvm/book3s_xics.h +++ b/arch/powerpc/kvm/book3s_xics.h | |||
@@ -71,9 +71,11 @@ struct kvmppc_icp { | |||
71 | #define XICS_RM_KICK_VCPU 0x1 | 71 | #define XICS_RM_KICK_VCPU 0x1 |
72 | #define XICS_RM_CHECK_RESEND 0x2 | 72 | #define XICS_RM_CHECK_RESEND 0x2 |
73 | #define XICS_RM_REJECT 0x4 | 73 | #define XICS_RM_REJECT 0x4 |
74 | #define XICS_RM_NOTIFY_EOI 0x8 | ||
74 | u32 rm_action; | 75 | u32 rm_action; |
75 | struct kvm_vcpu *rm_kick_target; | 76 | struct kvm_vcpu *rm_kick_target; |
76 | u32 rm_reject; | 77 | u32 rm_reject; |
78 | u32 rm_eoied_irq; | ||
77 | 79 | ||
78 | /* Debug stuff for real mode */ | 80 | /* Debug stuff for real mode */ |
79 | union kvmppc_icp_state rm_dbgstate; | 81 | union kvmppc_icp_state rm_dbgstate; |
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index ab62109fdfa3..b4c89fa6f109 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c | |||
@@ -51,7 +51,6 @@ unsigned long kvmppc_booke_handlers; | |||
51 | 51 | ||
52 | struct kvm_stats_debugfs_item debugfs_entries[] = { | 52 | struct kvm_stats_debugfs_item debugfs_entries[] = { |
53 | { "mmio", VCPU_STAT(mmio_exits) }, | 53 | { "mmio", VCPU_STAT(mmio_exits) }, |
54 | { "dcr", VCPU_STAT(dcr_exits) }, | ||
55 | { "sig", VCPU_STAT(signal_exits) }, | 54 | { "sig", VCPU_STAT(signal_exits) }, |
56 | { "itlb_r", VCPU_STAT(itlb_real_miss_exits) }, | 55 | { "itlb_r", VCPU_STAT(itlb_real_miss_exits) }, |
57 | { "itlb_v", VCPU_STAT(itlb_virt_miss_exits) }, | 56 | { "itlb_v", VCPU_STAT(itlb_virt_miss_exits) }, |
@@ -185,24 +184,28 @@ static void kvmppc_booke_queue_irqprio(struct kvm_vcpu *vcpu, | |||
185 | set_bit(priority, &vcpu->arch.pending_exceptions); | 184 | set_bit(priority, &vcpu->arch.pending_exceptions); |
186 | } | 185 | } |
187 | 186 | ||
188 | static void kvmppc_core_queue_dtlb_miss(struct kvm_vcpu *vcpu, | 187 | void kvmppc_core_queue_dtlb_miss(struct kvm_vcpu *vcpu, |
189 | ulong dear_flags, ulong esr_flags) | 188 | ulong dear_flags, ulong esr_flags) |
190 | { | 189 | { |
191 | vcpu->arch.queued_dear = dear_flags; | 190 | vcpu->arch.queued_dear = dear_flags; |
192 | vcpu->arch.queued_esr = esr_flags; | 191 | vcpu->arch.queued_esr = esr_flags; |
193 | kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_DTLB_MISS); | 192 | kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_DTLB_MISS); |
194 | } | 193 | } |
195 | 194 | ||
196 | static void kvmppc_core_queue_data_storage(struct kvm_vcpu *vcpu, | 195 | void kvmppc_core_queue_data_storage(struct kvm_vcpu *vcpu, |
197 | ulong dear_flags, ulong esr_flags) | 196 | ulong dear_flags, ulong esr_flags) |
198 | { | 197 | { |
199 | vcpu->arch.queued_dear = dear_flags; | 198 | vcpu->arch.queued_dear = dear_flags; |
200 | vcpu->arch.queued_esr = esr_flags; | 199 | vcpu->arch.queued_esr = esr_flags; |
201 | kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_DATA_STORAGE); | 200 | kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_DATA_STORAGE); |
202 | } | 201 | } |
203 | 202 | ||
204 | static void kvmppc_core_queue_inst_storage(struct kvm_vcpu *vcpu, | 203 | void kvmppc_core_queue_itlb_miss(struct kvm_vcpu *vcpu) |
205 | ulong esr_flags) | 204 | { |
205 | kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_ITLB_MISS); | ||
206 | } | ||
207 | |||
208 | void kvmppc_core_queue_inst_storage(struct kvm_vcpu *vcpu, ulong esr_flags) | ||
206 | { | 209 | { |
207 | vcpu->arch.queued_esr = esr_flags; | 210 | vcpu->arch.queued_esr = esr_flags; |
208 | kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_INST_STORAGE); | 211 | kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_INST_STORAGE); |
@@ -266,13 +269,8 @@ static void kvmppc_core_dequeue_watchdog(struct kvm_vcpu *vcpu) | |||
266 | 269 | ||
267 | static void set_guest_srr(struct kvm_vcpu *vcpu, unsigned long srr0, u32 srr1) | 270 | static void set_guest_srr(struct kvm_vcpu *vcpu, unsigned long srr0, u32 srr1) |
268 | { | 271 | { |
269 | #ifdef CONFIG_KVM_BOOKE_HV | 272 | kvmppc_set_srr0(vcpu, srr0); |
270 | mtspr(SPRN_GSRR0, srr0); | 273 | kvmppc_set_srr1(vcpu, srr1); |
271 | mtspr(SPRN_GSRR1, srr1); | ||
272 | #else | ||
273 | vcpu->arch.shared->srr0 = srr0; | ||
274 | vcpu->arch.shared->srr1 = srr1; | ||
275 | #endif | ||
276 | } | 274 | } |
277 | 275 | ||
278 | static void set_guest_csrr(struct kvm_vcpu *vcpu, unsigned long srr0, u32 srr1) | 276 | static void set_guest_csrr(struct kvm_vcpu *vcpu, unsigned long srr0, u32 srr1) |
@@ -297,51 +295,6 @@ static void set_guest_mcsrr(struct kvm_vcpu *vcpu, unsigned long srr0, u32 srr1) | |||
297 | vcpu->arch.mcsrr1 = srr1; | 295 | vcpu->arch.mcsrr1 = srr1; |
298 | } | 296 | } |
299 | 297 | ||
300 | static unsigned long get_guest_dear(struct kvm_vcpu *vcpu) | ||
301 | { | ||
302 | #ifdef CONFIG_KVM_BOOKE_HV | ||
303 | return mfspr(SPRN_GDEAR); | ||
304 | #else | ||
305 | return vcpu->arch.shared->dar; | ||
306 | #endif | ||
307 | } | ||
308 | |||
309 | static void set_guest_dear(struct kvm_vcpu *vcpu, unsigned long dear) | ||
310 | { | ||
311 | #ifdef CONFIG_KVM_BOOKE_HV | ||
312 | mtspr(SPRN_GDEAR, dear); | ||
313 | #else | ||
314 | vcpu->arch.shared->dar = dear; | ||
315 | #endif | ||
316 | } | ||
317 | |||
318 | static unsigned long get_guest_esr(struct kvm_vcpu *vcpu) | ||
319 | { | ||
320 | #ifdef CONFIG_KVM_BOOKE_HV | ||
321 | return mfspr(SPRN_GESR); | ||
322 | #else | ||
323 | return vcpu->arch.shared->esr; | ||
324 | #endif | ||
325 | } | ||
326 | |||
327 | static void set_guest_esr(struct kvm_vcpu *vcpu, u32 esr) | ||
328 | { | ||
329 | #ifdef CONFIG_KVM_BOOKE_HV | ||
330 | mtspr(SPRN_GESR, esr); | ||
331 | #else | ||
332 | vcpu->arch.shared->esr = esr; | ||
333 | #endif | ||
334 | } | ||
335 | |||
336 | static unsigned long get_guest_epr(struct kvm_vcpu *vcpu) | ||
337 | { | ||
338 | #ifdef CONFIG_KVM_BOOKE_HV | ||
339 | return mfspr(SPRN_GEPR); | ||
340 | #else | ||
341 | return vcpu->arch.epr; | ||
342 | #endif | ||
343 | } | ||
344 | |||
345 | /* Deliver the interrupt of the corresponding priority, if possible. */ | 298 | /* Deliver the interrupt of the corresponding priority, if possible. */ |
346 | static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu, | 299 | static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu, |
347 | unsigned int priority) | 300 | unsigned int priority) |
@@ -450,9 +403,9 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu, | |||
450 | 403 | ||
451 | vcpu->arch.pc = vcpu->arch.ivpr | vcpu->arch.ivor[priority]; | 404 | vcpu->arch.pc = vcpu->arch.ivpr | vcpu->arch.ivor[priority]; |
452 | if (update_esr == true) | 405 | if (update_esr == true) |
453 | set_guest_esr(vcpu, vcpu->arch.queued_esr); | 406 | kvmppc_set_esr(vcpu, vcpu->arch.queued_esr); |
454 | if (update_dear == true) | 407 | if (update_dear == true) |
455 | set_guest_dear(vcpu, vcpu->arch.queued_dear); | 408 | kvmppc_set_dar(vcpu, vcpu->arch.queued_dear); |
456 | if (update_epr == true) { | 409 | if (update_epr == true) { |
457 | if (vcpu->arch.epr_flags & KVMPPC_EPR_USER) | 410 | if (vcpu->arch.epr_flags & KVMPPC_EPR_USER) |
458 | kvm_make_request(KVM_REQ_EPR_EXIT, vcpu); | 411 | kvm_make_request(KVM_REQ_EPR_EXIT, vcpu); |
@@ -752,9 +705,8 @@ static int emulation_exit(struct kvm_run *run, struct kvm_vcpu *vcpu) | |||
752 | * they were actually modified by emulation. */ | 705 | * they were actually modified by emulation. */ |
753 | return RESUME_GUEST_NV; | 706 | return RESUME_GUEST_NV; |
754 | 707 | ||
755 | case EMULATE_DO_DCR: | 708 | case EMULATE_AGAIN: |
756 | run->exit_reason = KVM_EXIT_DCR; | 709 | return RESUME_GUEST; |
757 | return RESUME_HOST; | ||
758 | 710 | ||
759 | case EMULATE_FAIL: | 711 | case EMULATE_FAIL: |
760 | printk(KERN_CRIT "%s: emulation at %lx failed (%08x)\n", | 712 | printk(KERN_CRIT "%s: emulation at %lx failed (%08x)\n", |
@@ -866,6 +818,28 @@ static void kvmppc_restart_interrupt(struct kvm_vcpu *vcpu, | |||
866 | } | 818 | } |
867 | } | 819 | } |
868 | 820 | ||
821 | static int kvmppc_resume_inst_load(struct kvm_run *run, struct kvm_vcpu *vcpu, | ||
822 | enum emulation_result emulated, u32 last_inst) | ||
823 | { | ||
824 | switch (emulated) { | ||
825 | case EMULATE_AGAIN: | ||
826 | return RESUME_GUEST; | ||
827 | |||
828 | case EMULATE_FAIL: | ||
829 | pr_debug("%s: load instruction from guest address %lx failed\n", | ||
830 | __func__, vcpu->arch.pc); | ||
831 | /* For debugging, encode the failing instruction and | ||
832 | * report it to userspace. */ | ||
833 | run->hw.hardware_exit_reason = ~0ULL << 32; | ||
834 | run->hw.hardware_exit_reason |= last_inst; | ||
835 | kvmppc_core_queue_program(vcpu, ESR_PIL); | ||
836 | return RESUME_HOST; | ||
837 | |||
838 | default: | ||
839 | BUG(); | ||
840 | } | ||
841 | } | ||
842 | |||
869 | /** | 843 | /** |
870 | * kvmppc_handle_exit | 844 | * kvmppc_handle_exit |
871 | * | 845 | * |
@@ -877,6 +851,8 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
877 | int r = RESUME_HOST; | 851 | int r = RESUME_HOST; |
878 | int s; | 852 | int s; |
879 | int idx; | 853 | int idx; |
854 | u32 last_inst = KVM_INST_FETCH_FAILED; | ||
855 | enum emulation_result emulated = EMULATE_DONE; | ||
880 | 856 | ||
881 | /* update before a new last_exit_type is rewritten */ | 857 | /* update before a new last_exit_type is rewritten */ |
882 | kvmppc_update_timing_stats(vcpu); | 858 | kvmppc_update_timing_stats(vcpu); |
@@ -884,6 +860,20 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
884 | /* restart interrupts if they were meant for the host */ | 860 | /* restart interrupts if they were meant for the host */ |
885 | kvmppc_restart_interrupt(vcpu, exit_nr); | 861 | kvmppc_restart_interrupt(vcpu, exit_nr); |
886 | 862 | ||
863 | /* | ||
864 | * get last instruction before beeing preempted | ||
865 | * TODO: for e6500 check also BOOKE_INTERRUPT_LRAT_ERROR & ESR_DATA | ||
866 | */ | ||
867 | switch (exit_nr) { | ||
868 | case BOOKE_INTERRUPT_DATA_STORAGE: | ||
869 | case BOOKE_INTERRUPT_DTLB_MISS: | ||
870 | case BOOKE_INTERRUPT_HV_PRIV: | ||
871 | emulated = kvmppc_get_last_inst(vcpu, false, &last_inst); | ||
872 | break; | ||
873 | default: | ||
874 | break; | ||
875 | } | ||
876 | |||
887 | local_irq_enable(); | 877 | local_irq_enable(); |
888 | 878 | ||
889 | trace_kvm_exit(exit_nr, vcpu); | 879 | trace_kvm_exit(exit_nr, vcpu); |
@@ -892,6 +882,11 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
892 | run->exit_reason = KVM_EXIT_UNKNOWN; | 882 | run->exit_reason = KVM_EXIT_UNKNOWN; |
893 | run->ready_for_interrupt_injection = 1; | 883 | run->ready_for_interrupt_injection = 1; |
894 | 884 | ||
885 | if (emulated != EMULATE_DONE) { | ||
886 | r = kvmppc_resume_inst_load(run, vcpu, emulated, last_inst); | ||
887 | goto out; | ||
888 | } | ||
889 | |||
895 | switch (exit_nr) { | 890 | switch (exit_nr) { |
896 | case BOOKE_INTERRUPT_MACHINE_CHECK: | 891 | case BOOKE_INTERRUPT_MACHINE_CHECK: |
897 | printk("MACHINE CHECK: %lx\n", mfspr(SPRN_MCSR)); | 892 | printk("MACHINE CHECK: %lx\n", mfspr(SPRN_MCSR)); |
@@ -1181,6 +1176,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
1181 | BUG(); | 1176 | BUG(); |
1182 | } | 1177 | } |
1183 | 1178 | ||
1179 | out: | ||
1184 | /* | 1180 | /* |
1185 | * To avoid clobbering exit_reason, only check for signals if we | 1181 | * To avoid clobbering exit_reason, only check for signals if we |
1186 | * aren't already exiting to userspace for some other reason. | 1182 | * aren't already exiting to userspace for some other reason. |
@@ -1265,17 +1261,17 @@ int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) | |||
1265 | regs->lr = vcpu->arch.lr; | 1261 | regs->lr = vcpu->arch.lr; |
1266 | regs->xer = kvmppc_get_xer(vcpu); | 1262 | regs->xer = kvmppc_get_xer(vcpu); |
1267 | regs->msr = vcpu->arch.shared->msr; | 1263 | regs->msr = vcpu->arch.shared->msr; |
1268 | regs->srr0 = vcpu->arch.shared->srr0; | 1264 | regs->srr0 = kvmppc_get_srr0(vcpu); |
1269 | regs->srr1 = vcpu->arch.shared->srr1; | 1265 | regs->srr1 = kvmppc_get_srr1(vcpu); |
1270 | regs->pid = vcpu->arch.pid; | 1266 | regs->pid = vcpu->arch.pid; |
1271 | regs->sprg0 = vcpu->arch.shared->sprg0; | 1267 | regs->sprg0 = kvmppc_get_sprg0(vcpu); |
1272 | regs->sprg1 = vcpu->arch.shared->sprg1; | 1268 | regs->sprg1 = kvmppc_get_sprg1(vcpu); |
1273 | regs->sprg2 = vcpu->arch.shared->sprg2; | 1269 | regs->sprg2 = kvmppc_get_sprg2(vcpu); |
1274 | regs->sprg3 = vcpu->arch.shared->sprg3; | 1270 | regs->sprg3 = kvmppc_get_sprg3(vcpu); |
1275 | regs->sprg4 = vcpu->arch.shared->sprg4; | 1271 | regs->sprg4 = kvmppc_get_sprg4(vcpu); |
1276 | regs->sprg5 = vcpu->arch.shared->sprg5; | 1272 | regs->sprg5 = kvmppc_get_sprg5(vcpu); |
1277 | regs->sprg6 = vcpu->arch.shared->sprg6; | 1273 | regs->sprg6 = kvmppc_get_sprg6(vcpu); |
1278 | regs->sprg7 = vcpu->arch.shared->sprg7; | 1274 | regs->sprg7 = kvmppc_get_sprg7(vcpu); |
1279 | 1275 | ||
1280 | for (i = 0; i < ARRAY_SIZE(regs->gpr); i++) | 1276 | for (i = 0; i < ARRAY_SIZE(regs->gpr); i++) |
1281 | regs->gpr[i] = kvmppc_get_gpr(vcpu, i); | 1277 | regs->gpr[i] = kvmppc_get_gpr(vcpu, i); |
@@ -1293,17 +1289,17 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) | |||
1293 | vcpu->arch.lr = regs->lr; | 1289 | vcpu->arch.lr = regs->lr; |
1294 | kvmppc_set_xer(vcpu, regs->xer); | 1290 | kvmppc_set_xer(vcpu, regs->xer); |
1295 | kvmppc_set_msr(vcpu, regs->msr); | 1291 | kvmppc_set_msr(vcpu, regs->msr); |
1296 | vcpu->arch.shared->srr0 = regs->srr0; | 1292 | kvmppc_set_srr0(vcpu, regs->srr0); |
1297 | vcpu->arch.shared->srr1 = regs->srr1; | 1293 | kvmppc_set_srr1(vcpu, regs->srr1); |
1298 | kvmppc_set_pid(vcpu, regs->pid); | 1294 | kvmppc_set_pid(vcpu, regs->pid); |
1299 | vcpu->arch.shared->sprg0 = regs->sprg0; | 1295 | kvmppc_set_sprg0(vcpu, regs->sprg0); |
1300 | vcpu->arch.shared->sprg1 = regs->sprg1; | 1296 | kvmppc_set_sprg1(vcpu, regs->sprg1); |
1301 | vcpu->arch.shared->sprg2 = regs->sprg2; | 1297 | kvmppc_set_sprg2(vcpu, regs->sprg2); |
1302 | vcpu->arch.shared->sprg3 = regs->sprg3; | 1298 | kvmppc_set_sprg3(vcpu, regs->sprg3); |
1303 | vcpu->arch.shared->sprg4 = regs->sprg4; | 1299 | kvmppc_set_sprg4(vcpu, regs->sprg4); |
1304 | vcpu->arch.shared->sprg5 = regs->sprg5; | 1300 | kvmppc_set_sprg5(vcpu, regs->sprg5); |
1305 | vcpu->arch.shared->sprg6 = regs->sprg6; | 1301 | kvmppc_set_sprg6(vcpu, regs->sprg6); |
1306 | vcpu->arch.shared->sprg7 = regs->sprg7; | 1302 | kvmppc_set_sprg7(vcpu, regs->sprg7); |
1307 | 1303 | ||
1308 | for (i = 0; i < ARRAY_SIZE(regs->gpr); i++) | 1304 | for (i = 0; i < ARRAY_SIZE(regs->gpr); i++) |
1309 | kvmppc_set_gpr(vcpu, i, regs->gpr[i]); | 1305 | kvmppc_set_gpr(vcpu, i, regs->gpr[i]); |
@@ -1321,8 +1317,8 @@ static void get_sregs_base(struct kvm_vcpu *vcpu, | |||
1321 | sregs->u.e.csrr0 = vcpu->arch.csrr0; | 1317 | sregs->u.e.csrr0 = vcpu->arch.csrr0; |
1322 | sregs->u.e.csrr1 = vcpu->arch.csrr1; | 1318 | sregs->u.e.csrr1 = vcpu->arch.csrr1; |
1323 | sregs->u.e.mcsr = vcpu->arch.mcsr; | 1319 | sregs->u.e.mcsr = vcpu->arch.mcsr; |
1324 | sregs->u.e.esr = get_guest_esr(vcpu); | 1320 | sregs->u.e.esr = kvmppc_get_esr(vcpu); |
1325 | sregs->u.e.dear = get_guest_dear(vcpu); | 1321 | sregs->u.e.dear = kvmppc_get_dar(vcpu); |
1326 | sregs->u.e.tsr = vcpu->arch.tsr; | 1322 | sregs->u.e.tsr = vcpu->arch.tsr; |
1327 | sregs->u.e.tcr = vcpu->arch.tcr; | 1323 | sregs->u.e.tcr = vcpu->arch.tcr; |
1328 | sregs->u.e.dec = kvmppc_get_dec(vcpu, tb); | 1324 | sregs->u.e.dec = kvmppc_get_dec(vcpu, tb); |
@@ -1339,8 +1335,8 @@ static int set_sregs_base(struct kvm_vcpu *vcpu, | |||
1339 | vcpu->arch.csrr0 = sregs->u.e.csrr0; | 1335 | vcpu->arch.csrr0 = sregs->u.e.csrr0; |
1340 | vcpu->arch.csrr1 = sregs->u.e.csrr1; | 1336 | vcpu->arch.csrr1 = sregs->u.e.csrr1; |
1341 | vcpu->arch.mcsr = sregs->u.e.mcsr; | 1337 | vcpu->arch.mcsr = sregs->u.e.mcsr; |
1342 | set_guest_esr(vcpu, sregs->u.e.esr); | 1338 | kvmppc_set_esr(vcpu, sregs->u.e.esr); |
1343 | set_guest_dear(vcpu, sregs->u.e.dear); | 1339 | kvmppc_set_dar(vcpu, sregs->u.e.dear); |
1344 | vcpu->arch.vrsave = sregs->u.e.vrsave; | 1340 | vcpu->arch.vrsave = sregs->u.e.vrsave; |
1345 | kvmppc_set_tcr(vcpu, sregs->u.e.tcr); | 1341 | kvmppc_set_tcr(vcpu, sregs->u.e.tcr); |
1346 | 1342 | ||
@@ -1493,7 +1489,7 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) | |||
1493 | val = get_reg_val(reg->id, vcpu->arch.dbg_reg.dac2); | 1489 | val = get_reg_val(reg->id, vcpu->arch.dbg_reg.dac2); |
1494 | break; | 1490 | break; |
1495 | case KVM_REG_PPC_EPR: { | 1491 | case KVM_REG_PPC_EPR: { |
1496 | u32 epr = get_guest_epr(vcpu); | 1492 | u32 epr = kvmppc_get_epr(vcpu); |
1497 | val = get_reg_val(reg->id, epr); | 1493 | val = get_reg_val(reg->id, epr); |
1498 | break; | 1494 | break; |
1499 | } | 1495 | } |
@@ -1788,6 +1784,57 @@ void kvm_guest_protect_msr(struct kvm_vcpu *vcpu, ulong prot_bitmap, bool set) | |||
1788 | #endif | 1784 | #endif |
1789 | } | 1785 | } |
1790 | 1786 | ||
1787 | int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, enum xlate_instdata xlid, | ||
1788 | enum xlate_readwrite xlrw, struct kvmppc_pte *pte) | ||
1789 | { | ||
1790 | int gtlb_index; | ||
1791 | gpa_t gpaddr; | ||
1792 | |||
1793 | #ifdef CONFIG_KVM_E500V2 | ||
1794 | if (!(vcpu->arch.shared->msr & MSR_PR) && | ||
1795 | (eaddr & PAGE_MASK) == vcpu->arch.magic_page_ea) { | ||
1796 | pte->eaddr = eaddr; | ||
1797 | pte->raddr = (vcpu->arch.magic_page_pa & PAGE_MASK) | | ||
1798 | (eaddr & ~PAGE_MASK); | ||
1799 | pte->vpage = eaddr >> PAGE_SHIFT; | ||
1800 | pte->may_read = true; | ||
1801 | pte->may_write = true; | ||
1802 | pte->may_execute = true; | ||
1803 | |||
1804 | return 0; | ||
1805 | } | ||
1806 | #endif | ||
1807 | |||
1808 | /* Check the guest TLB. */ | ||
1809 | switch (xlid) { | ||
1810 | case XLATE_INST: | ||
1811 | gtlb_index = kvmppc_mmu_itlb_index(vcpu, eaddr); | ||
1812 | break; | ||
1813 | case XLATE_DATA: | ||
1814 | gtlb_index = kvmppc_mmu_dtlb_index(vcpu, eaddr); | ||
1815 | break; | ||
1816 | default: | ||
1817 | BUG(); | ||
1818 | } | ||
1819 | |||
1820 | /* Do we have a TLB entry at all? */ | ||
1821 | if (gtlb_index < 0) | ||
1822 | return -ENOENT; | ||
1823 | |||
1824 | gpaddr = kvmppc_mmu_xlate(vcpu, gtlb_index, eaddr); | ||
1825 | |||
1826 | pte->eaddr = eaddr; | ||
1827 | pte->raddr = (gpaddr & PAGE_MASK) | (eaddr & ~PAGE_MASK); | ||
1828 | pte->vpage = eaddr >> PAGE_SHIFT; | ||
1829 | |||
1830 | /* XXX read permissions from the guest TLB */ | ||
1831 | pte->may_read = true; | ||
1832 | pte->may_write = true; | ||
1833 | pte->may_execute = true; | ||
1834 | |||
1835 | return 0; | ||
1836 | } | ||
1837 | |||
1791 | int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, | 1838 | int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, |
1792 | struct kvm_guest_debug *dbg) | 1839 | struct kvm_guest_debug *dbg) |
1793 | { | 1840 | { |
diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h index b632cd35919b..f753543c56fa 100644 --- a/arch/powerpc/kvm/booke.h +++ b/arch/powerpc/kvm/booke.h | |||
@@ -99,13 +99,6 @@ enum int_class { | |||
99 | 99 | ||
100 | void kvmppc_set_pending_interrupt(struct kvm_vcpu *vcpu, enum int_class type); | 100 | void kvmppc_set_pending_interrupt(struct kvm_vcpu *vcpu, enum int_class type); |
101 | 101 | ||
102 | extern void kvmppc_mmu_destroy_44x(struct kvm_vcpu *vcpu); | ||
103 | extern int kvmppc_core_emulate_op_44x(struct kvm_run *run, struct kvm_vcpu *vcpu, | ||
104 | unsigned int inst, int *advance); | ||
105 | extern int kvmppc_core_emulate_mtspr_44x(struct kvm_vcpu *vcpu, int sprn, | ||
106 | ulong spr_val); | ||
107 | extern int kvmppc_core_emulate_mfspr_44x(struct kvm_vcpu *vcpu, int sprn, | ||
108 | ulong *spr_val); | ||
109 | extern void kvmppc_mmu_destroy_e500(struct kvm_vcpu *vcpu); | 102 | extern void kvmppc_mmu_destroy_e500(struct kvm_vcpu *vcpu); |
110 | extern int kvmppc_core_emulate_op_e500(struct kvm_run *run, | 103 | extern int kvmppc_core_emulate_op_e500(struct kvm_run *run, |
111 | struct kvm_vcpu *vcpu, | 104 | struct kvm_vcpu *vcpu, |
diff --git a/arch/powerpc/kvm/booke_emulate.c b/arch/powerpc/kvm/booke_emulate.c index 27a4b2877c10..28c158881d23 100644 --- a/arch/powerpc/kvm/booke_emulate.c +++ b/arch/powerpc/kvm/booke_emulate.c | |||
@@ -165,16 +165,16 @@ int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val) | |||
165 | * guest (PR-mode only). | 165 | * guest (PR-mode only). |
166 | */ | 166 | */ |
167 | case SPRN_SPRG4: | 167 | case SPRN_SPRG4: |
168 | vcpu->arch.shared->sprg4 = spr_val; | 168 | kvmppc_set_sprg4(vcpu, spr_val); |
169 | break; | 169 | break; |
170 | case SPRN_SPRG5: | 170 | case SPRN_SPRG5: |
171 | vcpu->arch.shared->sprg5 = spr_val; | 171 | kvmppc_set_sprg5(vcpu, spr_val); |
172 | break; | 172 | break; |
173 | case SPRN_SPRG6: | 173 | case SPRN_SPRG6: |
174 | vcpu->arch.shared->sprg6 = spr_val; | 174 | kvmppc_set_sprg6(vcpu, spr_val); |
175 | break; | 175 | break; |
176 | case SPRN_SPRG7: | 176 | case SPRN_SPRG7: |
177 | vcpu->arch.shared->sprg7 = spr_val; | 177 | kvmppc_set_sprg7(vcpu, spr_val); |
178 | break; | 178 | break; |
179 | 179 | ||
180 | case SPRN_IVPR: | 180 | case SPRN_IVPR: |
diff --git a/arch/powerpc/kvm/booke_interrupts.S b/arch/powerpc/kvm/booke_interrupts.S index 2c6deb5ef2fe..84c308a9a371 100644 --- a/arch/powerpc/kvm/booke_interrupts.S +++ b/arch/powerpc/kvm/booke_interrupts.S | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <asm/ppc_asm.h> | 21 | #include <asm/ppc_asm.h> |
22 | #include <asm/kvm_asm.h> | 22 | #include <asm/kvm_asm.h> |
23 | #include <asm/reg.h> | 23 | #include <asm/reg.h> |
24 | #include <asm/mmu-44x.h> | ||
25 | #include <asm/page.h> | 24 | #include <asm/page.h> |
26 | #include <asm/asm-offsets.h> | 25 | #include <asm/asm-offsets.h> |
27 | 26 | ||
@@ -424,10 +423,6 @@ lightweight_exit: | |||
424 | mtspr SPRN_PID1, r3 | 423 | mtspr SPRN_PID1, r3 |
425 | #endif | 424 | #endif |
426 | 425 | ||
427 | #ifdef CONFIG_44x | ||
428 | iccci 0, 0 /* XXX hack */ | ||
429 | #endif | ||
430 | |||
431 | /* Load some guest volatiles. */ | 426 | /* Load some guest volatiles. */ |
432 | lwz r0, VCPU_GPR(R0)(r4) | 427 | lwz r0, VCPU_GPR(R0)(r4) |
433 | lwz r2, VCPU_GPR(R2)(r4) | 428 | lwz r2, VCPU_GPR(R2)(r4) |
diff --git a/arch/powerpc/kvm/bookehv_interrupts.S b/arch/powerpc/kvm/bookehv_interrupts.S index a1712b818a5f..e9fa56a911fd 100644 --- a/arch/powerpc/kvm/bookehv_interrupts.S +++ b/arch/powerpc/kvm/bookehv_interrupts.S | |||
@@ -24,12 +24,10 @@ | |||
24 | #include <asm/ppc_asm.h> | 24 | #include <asm/ppc_asm.h> |
25 | #include <asm/kvm_asm.h> | 25 | #include <asm/kvm_asm.h> |
26 | #include <asm/reg.h> | 26 | #include <asm/reg.h> |
27 | #include <asm/mmu-44x.h> | ||
28 | #include <asm/page.h> | 27 | #include <asm/page.h> |
29 | #include <asm/asm-compat.h> | 28 | #include <asm/asm-compat.h> |
30 | #include <asm/asm-offsets.h> | 29 | #include <asm/asm-offsets.h> |
31 | #include <asm/bitsperlong.h> | 30 | #include <asm/bitsperlong.h> |
32 | #include <asm/thread_info.h> | ||
33 | 31 | ||
34 | #ifdef CONFIG_64BIT | 32 | #ifdef CONFIG_64BIT |
35 | #include <asm/exception-64e.h> | 33 | #include <asm/exception-64e.h> |
@@ -122,38 +120,14 @@ | |||
122 | 1: | 120 | 1: |
123 | 121 | ||
124 | .if \flags & NEED_EMU | 122 | .if \flags & NEED_EMU |
125 | /* | ||
126 | * This assumes you have external PID support. | ||
127 | * To support a bookehv CPU without external PID, you'll | ||
128 | * need to look up the TLB entry and create a temporary mapping. | ||
129 | * | ||
130 | * FIXME: we don't currently handle if the lwepx faults. PR-mode | ||
131 | * booke doesn't handle it either. Since Linux doesn't use | ||
132 | * broadcast tlbivax anymore, the only way this should happen is | ||
133 | * if the guest maps its memory execute-but-not-read, or if we | ||
134 | * somehow take a TLB miss in the middle of this entry code and | ||
135 | * evict the relevant entry. On e500mc, all kernel lowmem is | ||
136 | * bolted into TLB1 large page mappings, and we don't use | ||
137 | * broadcast invalidates, so we should not take a TLB miss here. | ||
138 | * | ||
139 | * Later we'll need to deal with faults here. Disallowing guest | ||
140 | * mappings that are execute-but-not-read could be an option on | ||
141 | * e500mc, but not on chips with an LRAT if it is used. | ||
142 | */ | ||
143 | |||
144 | mfspr r3, SPRN_EPLC /* will already have correct ELPID and EGS */ | ||
145 | PPC_STL r15, VCPU_GPR(R15)(r4) | 123 | PPC_STL r15, VCPU_GPR(R15)(r4) |
146 | PPC_STL r16, VCPU_GPR(R16)(r4) | 124 | PPC_STL r16, VCPU_GPR(R16)(r4) |
147 | PPC_STL r17, VCPU_GPR(R17)(r4) | 125 | PPC_STL r17, VCPU_GPR(R17)(r4) |
148 | PPC_STL r18, VCPU_GPR(R18)(r4) | 126 | PPC_STL r18, VCPU_GPR(R18)(r4) |
149 | PPC_STL r19, VCPU_GPR(R19)(r4) | 127 | PPC_STL r19, VCPU_GPR(R19)(r4) |
150 | mr r8, r3 | ||
151 | PPC_STL r20, VCPU_GPR(R20)(r4) | 128 | PPC_STL r20, VCPU_GPR(R20)(r4) |
152 | rlwimi r8, r6, EPC_EAS_SHIFT - MSR_IR_LG, EPC_EAS | ||
153 | PPC_STL r21, VCPU_GPR(R21)(r4) | 129 | PPC_STL r21, VCPU_GPR(R21)(r4) |
154 | rlwimi r8, r6, EPC_EPR_SHIFT - MSR_PR_LG, EPC_EPR | ||
155 | PPC_STL r22, VCPU_GPR(R22)(r4) | 130 | PPC_STL r22, VCPU_GPR(R22)(r4) |
156 | rlwimi r8, r10, EPC_EPID_SHIFT, EPC_EPID | ||
157 | PPC_STL r23, VCPU_GPR(R23)(r4) | 131 | PPC_STL r23, VCPU_GPR(R23)(r4) |
158 | PPC_STL r24, VCPU_GPR(R24)(r4) | 132 | PPC_STL r24, VCPU_GPR(R24)(r4) |
159 | PPC_STL r25, VCPU_GPR(R25)(r4) | 133 | PPC_STL r25, VCPU_GPR(R25)(r4) |
@@ -163,33 +137,15 @@ | |||
163 | PPC_STL r29, VCPU_GPR(R29)(r4) | 137 | PPC_STL r29, VCPU_GPR(R29)(r4) |
164 | PPC_STL r30, VCPU_GPR(R30)(r4) | 138 | PPC_STL r30, VCPU_GPR(R30)(r4) |
165 | PPC_STL r31, VCPU_GPR(R31)(r4) | 139 | PPC_STL r31, VCPU_GPR(R31)(r4) |
166 | mtspr SPRN_EPLC, r8 | ||
167 | |||
168 | /* disable preemption, so we are sure we hit the fixup handler */ | ||
169 | CURRENT_THREAD_INFO(r8, r1) | ||
170 | li r7, 1 | ||
171 | stw r7, TI_PREEMPT(r8) | ||
172 | |||
173 | isync | ||
174 | 140 | ||
175 | /* | 141 | /* |
176 | * In case the read goes wrong, we catch it and write an invalid value | 142 | * We don't use external PID support. lwepx faults would need to be |
177 | * in LAST_INST instead. | 143 | * handled by KVM and this implies aditional code in DO_KVM (for |
144 | * DTB_MISS, DSI and LRAT) to check ESR[EPID] and EPLC[EGS] which | ||
145 | * is too intrusive for the host. Get last instuction in | ||
146 | * kvmppc_get_last_inst(). | ||
178 | */ | 147 | */ |
179 | 1: lwepx r9, 0, r5 | 148 | li r9, KVM_INST_FETCH_FAILED |
180 | 2: | ||
181 | .section .fixup, "ax" | ||
182 | 3: li r9, KVM_INST_FETCH_FAILED | ||
183 | b 2b | ||
184 | .previous | ||
185 | .section __ex_table,"a" | ||
186 | PPC_LONG_ALIGN | ||
187 | PPC_LONG 1b,3b | ||
188 | .previous | ||
189 | |||
190 | mtspr SPRN_EPLC, r3 | ||
191 | li r7, 0 | ||
192 | stw r7, TI_PREEMPT(r8) | ||
193 | stw r9, VCPU_LAST_INST(r4) | 149 | stw r9, VCPU_LAST_INST(r4) |
194 | .endif | 150 | .endif |
195 | 151 | ||
@@ -441,6 +397,7 @@ _GLOBAL(kvmppc_resume_host) | |||
441 | #ifdef CONFIG_64BIT | 397 | #ifdef CONFIG_64BIT |
442 | PPC_LL r3, PACA_SPRG_VDSO(r13) | 398 | PPC_LL r3, PACA_SPRG_VDSO(r13) |
443 | #endif | 399 | #endif |
400 | mfspr r5, SPRN_SPRG9 | ||
444 | PPC_STD(r6, VCPU_SHARED_SPRG4, r11) | 401 | PPC_STD(r6, VCPU_SHARED_SPRG4, r11) |
445 | mfspr r8, SPRN_SPRG6 | 402 | mfspr r8, SPRN_SPRG6 |
446 | PPC_STD(r7, VCPU_SHARED_SPRG5, r11) | 403 | PPC_STD(r7, VCPU_SHARED_SPRG5, r11) |
@@ -448,6 +405,7 @@ _GLOBAL(kvmppc_resume_host) | |||
448 | #ifdef CONFIG_64BIT | 405 | #ifdef CONFIG_64BIT |
449 | mtspr SPRN_SPRG_VDSO_WRITE, r3 | 406 | mtspr SPRN_SPRG_VDSO_WRITE, r3 |
450 | #endif | 407 | #endif |
408 | PPC_STD(r5, VCPU_SPRG9, r4) | ||
451 | PPC_STD(r8, VCPU_SHARED_SPRG6, r11) | 409 | PPC_STD(r8, VCPU_SHARED_SPRG6, r11) |
452 | mfxer r3 | 410 | mfxer r3 |
453 | PPC_STD(r9, VCPU_SHARED_SPRG7, r11) | 411 | PPC_STD(r9, VCPU_SHARED_SPRG7, r11) |
@@ -682,7 +640,9 @@ lightweight_exit: | |||
682 | mtspr SPRN_SPRG5W, r6 | 640 | mtspr SPRN_SPRG5W, r6 |
683 | PPC_LD(r8, VCPU_SHARED_SPRG7, r11) | 641 | PPC_LD(r8, VCPU_SHARED_SPRG7, r11) |
684 | mtspr SPRN_SPRG6W, r7 | 642 | mtspr SPRN_SPRG6W, r7 |
643 | PPC_LD(r5, VCPU_SPRG9, r4) | ||
685 | mtspr SPRN_SPRG7W, r8 | 644 | mtspr SPRN_SPRG7W, r8 |
645 | mtspr SPRN_SPRG9, r5 | ||
686 | 646 | ||
687 | /* Load some guest volatiles. */ | 647 | /* Load some guest volatiles. */ |
688 | PPC_LL r3, VCPU_LR(r4) | 648 | PPC_LL r3, VCPU_LR(r4) |
diff --git a/arch/powerpc/kvm/e500_emulate.c b/arch/powerpc/kvm/e500_emulate.c index 002d51764143..c99c40e9182a 100644 --- a/arch/powerpc/kvm/e500_emulate.c +++ b/arch/powerpc/kvm/e500_emulate.c | |||
@@ -250,6 +250,14 @@ int kvmppc_core_emulate_mtspr_e500(struct kvm_vcpu *vcpu, int sprn, ulong spr_va | |||
250 | spr_val); | 250 | spr_val); |
251 | break; | 251 | break; |
252 | 252 | ||
253 | case SPRN_PWRMGTCR0: | ||
254 | /* | ||
255 | * Guest relies on host power management configurations | ||
256 | * Treat the request as a general store | ||
257 | */ | ||
258 | vcpu->arch.pwrmgtcr0 = spr_val; | ||
259 | break; | ||
260 | |||
253 | /* extra exceptions */ | 261 | /* extra exceptions */ |
254 | case SPRN_IVOR32: | 262 | case SPRN_IVOR32: |
255 | vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL] = spr_val; | 263 | vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL] = spr_val; |
@@ -368,6 +376,10 @@ int kvmppc_core_emulate_mfspr_e500(struct kvm_vcpu *vcpu, int sprn, ulong *spr_v | |||
368 | *spr_val = vcpu->arch.eptcfg; | 376 | *spr_val = vcpu->arch.eptcfg; |
369 | break; | 377 | break; |
370 | 378 | ||
379 | case SPRN_PWRMGTCR0: | ||
380 | *spr_val = vcpu->arch.pwrmgtcr0; | ||
381 | break; | ||
382 | |||
371 | /* extra exceptions */ | 383 | /* extra exceptions */ |
372 | case SPRN_IVOR32: | 384 | case SPRN_IVOR32: |
373 | *spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL]; | 385 | *spr_val = vcpu->arch.ivor[BOOKE_IRQPRIO_SPE_UNAVAIL]; |
diff --git a/arch/powerpc/kvm/e500_mmu_host.c b/arch/powerpc/kvm/e500_mmu_host.c index 86903d3f5a03..08f14bb57897 100644 --- a/arch/powerpc/kvm/e500_mmu_host.c +++ b/arch/powerpc/kvm/e500_mmu_host.c | |||
@@ -107,11 +107,15 @@ static u32 get_host_mas0(unsigned long eaddr) | |||
107 | { | 107 | { |
108 | unsigned long flags; | 108 | unsigned long flags; |
109 | u32 mas0; | 109 | u32 mas0; |
110 | u32 mas4; | ||
110 | 111 | ||
111 | local_irq_save(flags); | 112 | local_irq_save(flags); |
112 | mtspr(SPRN_MAS6, 0); | 113 | mtspr(SPRN_MAS6, 0); |
114 | mas4 = mfspr(SPRN_MAS4); | ||
115 | mtspr(SPRN_MAS4, mas4 & ~MAS4_TLBSEL_MASK); | ||
113 | asm volatile("tlbsx 0, %0" : : "b" (eaddr & ~CONFIG_PAGE_OFFSET)); | 116 | asm volatile("tlbsx 0, %0" : : "b" (eaddr & ~CONFIG_PAGE_OFFSET)); |
114 | mas0 = mfspr(SPRN_MAS0); | 117 | mas0 = mfspr(SPRN_MAS0); |
118 | mtspr(SPRN_MAS4, mas4); | ||
115 | local_irq_restore(flags); | 119 | local_irq_restore(flags); |
116 | 120 | ||
117 | return mas0; | 121 | return mas0; |
@@ -607,6 +611,104 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 eaddr, gpa_t gpaddr, | |||
607 | } | 611 | } |
608 | } | 612 | } |
609 | 613 | ||
614 | #ifdef CONFIG_KVM_BOOKE_HV | ||
615 | int kvmppc_load_last_inst(struct kvm_vcpu *vcpu, enum instruction_type type, | ||
616 | u32 *instr) | ||
617 | { | ||
618 | gva_t geaddr; | ||
619 | hpa_t addr; | ||
620 | hfn_t pfn; | ||
621 | hva_t eaddr; | ||
622 | u32 mas1, mas2, mas3; | ||
623 | u64 mas7_mas3; | ||
624 | struct page *page; | ||
625 | unsigned int addr_space, psize_shift; | ||
626 | bool pr; | ||
627 | unsigned long flags; | ||
628 | |||
629 | /* Search TLB for guest pc to get the real address */ | ||
630 | geaddr = kvmppc_get_pc(vcpu); | ||
631 | |||
632 | addr_space = (vcpu->arch.shared->msr & MSR_IS) >> MSR_IR_LG; | ||
633 | |||
634 | local_irq_save(flags); | ||
635 | mtspr(SPRN_MAS6, (vcpu->arch.pid << MAS6_SPID_SHIFT) | addr_space); | ||
636 | mtspr(SPRN_MAS5, MAS5_SGS | vcpu->kvm->arch.lpid); | ||
637 | asm volatile("tlbsx 0, %[geaddr]\n" : : | ||
638 | [geaddr] "r" (geaddr)); | ||
639 | mtspr(SPRN_MAS5, 0); | ||
640 | mtspr(SPRN_MAS8, 0); | ||
641 | mas1 = mfspr(SPRN_MAS1); | ||
642 | mas2 = mfspr(SPRN_MAS2); | ||
643 | mas3 = mfspr(SPRN_MAS3); | ||
644 | #ifdef CONFIG_64BIT | ||
645 | mas7_mas3 = mfspr(SPRN_MAS7_MAS3); | ||
646 | #else | ||
647 | mas7_mas3 = ((u64)mfspr(SPRN_MAS7) << 32) | mas3; | ||
648 | #endif | ||
649 | local_irq_restore(flags); | ||
650 | |||
651 | /* | ||
652 | * If the TLB entry for guest pc was evicted, return to the guest. | ||
653 | * There are high chances to find a valid TLB entry next time. | ||
654 | */ | ||
655 | if (!(mas1 & MAS1_VALID)) | ||
656 | return EMULATE_AGAIN; | ||
657 | |||
658 | /* | ||
659 | * Another thread may rewrite the TLB entry in parallel, don't | ||
660 | * execute from the address if the execute permission is not set | ||
661 | */ | ||
662 | pr = vcpu->arch.shared->msr & MSR_PR; | ||
663 | if (unlikely((pr && !(mas3 & MAS3_UX)) || | ||
664 | (!pr && !(mas3 & MAS3_SX)))) { | ||
665 | pr_err_ratelimited( | ||
666 | "%s: Instuction emulation from guest addres %08lx without execute permission\n", | ||
667 | __func__, geaddr); | ||
668 | return EMULATE_AGAIN; | ||
669 | } | ||
670 | |||
671 | /* | ||
672 | * The real address will be mapped by a cacheable, memory coherent, | ||
673 | * write-back page. Check for mismatches when LRAT is used. | ||
674 | */ | ||
675 | if (has_feature(vcpu, VCPU_FTR_MMU_V2) && | ||
676 | unlikely((mas2 & MAS2_I) || (mas2 & MAS2_W) || !(mas2 & MAS2_M))) { | ||
677 | pr_err_ratelimited( | ||
678 | "%s: Instuction emulation from guest addres %08lx mismatches storage attributes\n", | ||
679 | __func__, geaddr); | ||
680 | return EMULATE_AGAIN; | ||
681 | } | ||
682 | |||
683 | /* Get pfn */ | ||
684 | psize_shift = MAS1_GET_TSIZE(mas1) + 10; | ||
685 | addr = (mas7_mas3 & (~0ULL << psize_shift)) | | ||
686 | (geaddr & ((1ULL << psize_shift) - 1ULL)); | ||
687 | pfn = addr >> PAGE_SHIFT; | ||
688 | |||
689 | /* Guard against emulation from devices area */ | ||
690 | if (unlikely(!page_is_ram(pfn))) { | ||
691 | pr_err_ratelimited("%s: Instruction emulation from non-RAM host addres %08llx is not supported\n", | ||
692 | __func__, addr); | ||
693 | return EMULATE_AGAIN; | ||
694 | } | ||
695 | |||
696 | /* Map a page and get guest's instruction */ | ||
697 | page = pfn_to_page(pfn); | ||
698 | eaddr = (unsigned long)kmap_atomic(page); | ||
699 | *instr = *(u32 *)(eaddr | (unsigned long)(addr & ~PAGE_MASK)); | ||
700 | kunmap_atomic((u32 *)eaddr); | ||
701 | |||
702 | return EMULATE_DONE; | ||
703 | } | ||
704 | #else | ||
705 | int kvmppc_load_last_inst(struct kvm_vcpu *vcpu, enum instruction_type type, | ||
706 | u32 *instr) | ||
707 | { | ||
708 | return EMULATE_AGAIN; | ||
709 | } | ||
710 | #endif | ||
711 | |||
610 | /************* MMU Notifiers *************/ | 712 | /************* MMU Notifiers *************/ |
611 | 713 | ||
612 | int kvm_unmap_hva(struct kvm *kvm, unsigned long hva) | 714 | int kvm_unmap_hva(struct kvm *kvm, unsigned long hva) |
diff --git a/arch/powerpc/kvm/e500mc.c b/arch/powerpc/kvm/e500mc.c index 17e456279224..164bad2a19bf 100644 --- a/arch/powerpc/kvm/e500mc.c +++ b/arch/powerpc/kvm/e500mc.c | |||
@@ -110,7 +110,7 @@ void kvmppc_mmu_msr_notify(struct kvm_vcpu *vcpu, u32 old_msr) | |||
110 | { | 110 | { |
111 | } | 111 | } |
112 | 112 | ||
113 | static DEFINE_PER_CPU(struct kvm_vcpu *, last_vcpu_on_cpu); | 113 | static DEFINE_PER_CPU(struct kvm_vcpu *[KVMPPC_NR_LPIDS], last_vcpu_of_lpid); |
114 | 114 | ||
115 | static void kvmppc_core_vcpu_load_e500mc(struct kvm_vcpu *vcpu, int cpu) | 115 | static void kvmppc_core_vcpu_load_e500mc(struct kvm_vcpu *vcpu, int cpu) |
116 | { | 116 | { |
@@ -141,9 +141,9 @@ static void kvmppc_core_vcpu_load_e500mc(struct kvm_vcpu *vcpu, int cpu) | |||
141 | mtspr(SPRN_GESR, vcpu->arch.shared->esr); | 141 | mtspr(SPRN_GESR, vcpu->arch.shared->esr); |
142 | 142 | ||
143 | if (vcpu->arch.oldpir != mfspr(SPRN_PIR) || | 143 | if (vcpu->arch.oldpir != mfspr(SPRN_PIR) || |
144 | __get_cpu_var(last_vcpu_on_cpu) != vcpu) { | 144 | __get_cpu_var(last_vcpu_of_lpid)[vcpu->kvm->arch.lpid] != vcpu) { |
145 | kvmppc_e500_tlbil_all(vcpu_e500); | 145 | kvmppc_e500_tlbil_all(vcpu_e500); |
146 | __get_cpu_var(last_vcpu_on_cpu) = vcpu; | 146 | __get_cpu_var(last_vcpu_of_lpid)[vcpu->kvm->arch.lpid] = vcpu; |
147 | } | 147 | } |
148 | 148 | ||
149 | kvmppc_load_guest_fp(vcpu); | 149 | kvmppc_load_guest_fp(vcpu); |
@@ -267,14 +267,32 @@ static int kvmppc_core_set_sregs_e500mc(struct kvm_vcpu *vcpu, | |||
267 | static int kvmppc_get_one_reg_e500mc(struct kvm_vcpu *vcpu, u64 id, | 267 | static int kvmppc_get_one_reg_e500mc(struct kvm_vcpu *vcpu, u64 id, |
268 | union kvmppc_one_reg *val) | 268 | union kvmppc_one_reg *val) |
269 | { | 269 | { |
270 | int r = kvmppc_get_one_reg_e500_tlb(vcpu, id, val); | 270 | int r = 0; |
271 | |||
272 | switch (id) { | ||
273 | case KVM_REG_PPC_SPRG9: | ||
274 | *val = get_reg_val(id, vcpu->arch.sprg9); | ||
275 | break; | ||
276 | default: | ||
277 | r = kvmppc_get_one_reg_e500_tlb(vcpu, id, val); | ||
278 | } | ||
279 | |||
271 | return r; | 280 | return r; |
272 | } | 281 | } |
273 | 282 | ||
274 | static int kvmppc_set_one_reg_e500mc(struct kvm_vcpu *vcpu, u64 id, | 283 | static int kvmppc_set_one_reg_e500mc(struct kvm_vcpu *vcpu, u64 id, |
275 | union kvmppc_one_reg *val) | 284 | union kvmppc_one_reg *val) |
276 | { | 285 | { |
277 | int r = kvmppc_set_one_reg_e500_tlb(vcpu, id, val); | 286 | int r = 0; |
287 | |||
288 | switch (id) { | ||
289 | case KVM_REG_PPC_SPRG9: | ||
290 | vcpu->arch.sprg9 = set_reg_val(id, *val); | ||
291 | break; | ||
292 | default: | ||
293 | r = kvmppc_set_one_reg_e500_tlb(vcpu, id, val); | ||
294 | } | ||
295 | |||
278 | return r; | 296 | return r; |
279 | } | 297 | } |
280 | 298 | ||
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c index da86d9ba3476..e96b50d0bdab 100644 --- a/arch/powerpc/kvm/emulate.c +++ b/arch/powerpc/kvm/emulate.c | |||
@@ -207,36 +207,28 @@ static int kvmppc_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt) | |||
207 | return emulated; | 207 | return emulated; |
208 | } | 208 | } |
209 | 209 | ||
210 | /* XXX to do: | ||
211 | * lhax | ||
212 | * lhaux | ||
213 | * lswx | ||
214 | * lswi | ||
215 | * stswx | ||
216 | * stswi | ||
217 | * lha | ||
218 | * lhau | ||
219 | * lmw | ||
220 | * stmw | ||
221 | * | ||
222 | */ | ||
223 | /* XXX Should probably auto-generate instruction decoding for a particular core | 210 | /* XXX Should probably auto-generate instruction decoding for a particular core |
224 | * from opcode tables in the future. */ | 211 | * from opcode tables in the future. */ |
225 | int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) | 212 | int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) |
226 | { | 213 | { |
227 | u32 inst = kvmppc_get_last_inst(vcpu); | 214 | u32 inst; |
228 | int ra = get_ra(inst); | 215 | int rs, rt, sprn; |
229 | int rs = get_rs(inst); | 216 | enum emulation_result emulated; |
230 | int rt = get_rt(inst); | ||
231 | int sprn = get_sprn(inst); | ||
232 | enum emulation_result emulated = EMULATE_DONE; | ||
233 | int advance = 1; | 217 | int advance = 1; |
234 | 218 | ||
235 | /* this default type might be overwritten by subcategories */ | 219 | /* this default type might be overwritten by subcategories */ |
236 | kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS); | 220 | kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS); |
237 | 221 | ||
222 | emulated = kvmppc_get_last_inst(vcpu, false, &inst); | ||
223 | if (emulated != EMULATE_DONE) | ||
224 | return emulated; | ||
225 | |||
238 | pr_debug("Emulating opcode %d / %d\n", get_op(inst), get_xop(inst)); | 226 | pr_debug("Emulating opcode %d / %d\n", get_op(inst), get_xop(inst)); |
239 | 227 | ||
228 | rs = get_rs(inst); | ||
229 | rt = get_rt(inst); | ||
230 | sprn = get_sprn(inst); | ||
231 | |||
240 | switch (get_op(inst)) { | 232 | switch (get_op(inst)) { |
241 | case OP_TRAP: | 233 | case OP_TRAP: |
242 | #ifdef CONFIG_PPC_BOOK3S | 234 | #ifdef CONFIG_PPC_BOOK3S |
@@ -264,200 +256,24 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) | |||
264 | #endif | 256 | #endif |
265 | advance = 0; | 257 | advance = 0; |
266 | break; | 258 | break; |
267 | case OP_31_XOP_LWZX: | ||
268 | emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1); | ||
269 | break; | ||
270 | |||
271 | case OP_31_XOP_LBZX: | ||
272 | emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1); | ||
273 | break; | ||
274 | |||
275 | case OP_31_XOP_LBZUX: | ||
276 | emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1); | ||
277 | kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); | ||
278 | break; | ||
279 | |||
280 | case OP_31_XOP_STWX: | ||
281 | emulated = kvmppc_handle_store(run, vcpu, | ||
282 | kvmppc_get_gpr(vcpu, rs), | ||
283 | 4, 1); | ||
284 | break; | ||
285 | |||
286 | case OP_31_XOP_STBX: | ||
287 | emulated = kvmppc_handle_store(run, vcpu, | ||
288 | kvmppc_get_gpr(vcpu, rs), | ||
289 | 1, 1); | ||
290 | break; | ||
291 | |||
292 | case OP_31_XOP_STBUX: | ||
293 | emulated = kvmppc_handle_store(run, vcpu, | ||
294 | kvmppc_get_gpr(vcpu, rs), | ||
295 | 1, 1); | ||
296 | kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); | ||
297 | break; | ||
298 | |||
299 | case OP_31_XOP_LHAX: | ||
300 | emulated = kvmppc_handle_loads(run, vcpu, rt, 2, 1); | ||
301 | break; | ||
302 | |||
303 | case OP_31_XOP_LHZX: | ||
304 | emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1); | ||
305 | break; | ||
306 | |||
307 | case OP_31_XOP_LHZUX: | ||
308 | emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1); | ||
309 | kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); | ||
310 | break; | ||
311 | 259 | ||
312 | case OP_31_XOP_MFSPR: | 260 | case OP_31_XOP_MFSPR: |
313 | emulated = kvmppc_emulate_mfspr(vcpu, sprn, rt); | 261 | emulated = kvmppc_emulate_mfspr(vcpu, sprn, rt); |
314 | break; | 262 | break; |
315 | 263 | ||
316 | case OP_31_XOP_STHX: | ||
317 | emulated = kvmppc_handle_store(run, vcpu, | ||
318 | kvmppc_get_gpr(vcpu, rs), | ||
319 | 2, 1); | ||
320 | break; | ||
321 | |||
322 | case OP_31_XOP_STHUX: | ||
323 | emulated = kvmppc_handle_store(run, vcpu, | ||
324 | kvmppc_get_gpr(vcpu, rs), | ||
325 | 2, 1); | ||
326 | kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); | ||
327 | break; | ||
328 | |||
329 | case OP_31_XOP_MTSPR: | 264 | case OP_31_XOP_MTSPR: |
330 | emulated = kvmppc_emulate_mtspr(vcpu, sprn, rs); | 265 | emulated = kvmppc_emulate_mtspr(vcpu, sprn, rs); |
331 | break; | 266 | break; |
332 | 267 | ||
333 | case OP_31_XOP_DCBST: | ||
334 | case OP_31_XOP_DCBF: | ||
335 | case OP_31_XOP_DCBI: | ||
336 | /* Do nothing. The guest is performing dcbi because | ||
337 | * hardware DMA is not snooped by the dcache, but | ||
338 | * emulated DMA either goes through the dcache as | ||
339 | * normal writes, or the host kernel has handled dcache | ||
340 | * coherence. */ | ||
341 | break; | ||
342 | |||
343 | case OP_31_XOP_LWBRX: | ||
344 | emulated = kvmppc_handle_load(run, vcpu, rt, 4, 0); | ||
345 | break; | ||
346 | |||
347 | case OP_31_XOP_TLBSYNC: | 268 | case OP_31_XOP_TLBSYNC: |
348 | break; | 269 | break; |
349 | 270 | ||
350 | case OP_31_XOP_STWBRX: | ||
351 | emulated = kvmppc_handle_store(run, vcpu, | ||
352 | kvmppc_get_gpr(vcpu, rs), | ||
353 | 4, 0); | ||
354 | break; | ||
355 | |||
356 | case OP_31_XOP_LHBRX: | ||
357 | emulated = kvmppc_handle_load(run, vcpu, rt, 2, 0); | ||
358 | break; | ||
359 | |||
360 | case OP_31_XOP_STHBRX: | ||
361 | emulated = kvmppc_handle_store(run, vcpu, | ||
362 | kvmppc_get_gpr(vcpu, rs), | ||
363 | 2, 0); | ||
364 | break; | ||
365 | |||
366 | default: | 271 | default: |
367 | /* Attempt core-specific emulation below. */ | 272 | /* Attempt core-specific emulation below. */ |
368 | emulated = EMULATE_FAIL; | 273 | emulated = EMULATE_FAIL; |
369 | } | 274 | } |
370 | break; | 275 | break; |
371 | 276 | ||
372 | case OP_LWZ: | ||
373 | emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1); | ||
374 | break; | ||
375 | |||
376 | /* TBD: Add support for other 64 bit load variants like ldu, ldux, ldx etc. */ | ||
377 | case OP_LD: | ||
378 | rt = get_rt(inst); | ||
379 | emulated = kvmppc_handle_load(run, vcpu, rt, 8, 1); | ||
380 | break; | ||
381 | |||
382 | case OP_LWZU: | ||
383 | emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1); | ||
384 | kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); | ||
385 | break; | ||
386 | |||
387 | case OP_LBZ: | ||
388 | emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1); | ||
389 | break; | ||
390 | |||
391 | case OP_LBZU: | ||
392 | emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1); | ||
393 | kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); | ||
394 | break; | ||
395 | |||
396 | case OP_STW: | ||
397 | emulated = kvmppc_handle_store(run, vcpu, | ||
398 | kvmppc_get_gpr(vcpu, rs), | ||
399 | 4, 1); | ||
400 | break; | ||
401 | |||
402 | /* TBD: Add support for other 64 bit store variants like stdu, stdux, stdx etc. */ | ||
403 | case OP_STD: | ||
404 | rs = get_rs(inst); | ||
405 | emulated = kvmppc_handle_store(run, vcpu, | ||
406 | kvmppc_get_gpr(vcpu, rs), | ||
407 | 8, 1); | ||
408 | break; | ||
409 | |||
410 | case OP_STWU: | ||
411 | emulated = kvmppc_handle_store(run, vcpu, | ||
412 | kvmppc_get_gpr(vcpu, rs), | ||
413 | 4, 1); | ||
414 | kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); | ||
415 | break; | ||
416 | |||
417 | case OP_STB: | ||
418 | emulated = kvmppc_handle_store(run, vcpu, | ||
419 | kvmppc_get_gpr(vcpu, rs), | ||
420 | 1, 1); | ||
421 | break; | ||
422 | |||
423 | case OP_STBU: | ||
424 | emulated = kvmppc_handle_store(run, vcpu, | ||
425 | kvmppc_get_gpr(vcpu, rs), | ||
426 | 1, 1); | ||
427 | kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); | ||
428 | break; | ||
429 | |||
430 | case OP_LHZ: | ||
431 | emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1); | ||
432 | break; | ||
433 | |||
434 | case OP_LHZU: | ||
435 | emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1); | ||
436 | kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); | ||
437 | break; | ||
438 | |||
439 | case OP_LHA: | ||
440 | emulated = kvmppc_handle_loads(run, vcpu, rt, 2, 1); | ||
441 | break; | ||
442 | |||
443 | case OP_LHAU: | ||
444 | emulated = kvmppc_handle_loads(run, vcpu, rt, 2, 1); | ||
445 | kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); | ||
446 | break; | ||
447 | |||
448 | case OP_STH: | ||
449 | emulated = kvmppc_handle_store(run, vcpu, | ||
450 | kvmppc_get_gpr(vcpu, rs), | ||
451 | 2, 1); | ||
452 | break; | ||
453 | |||
454 | case OP_STHU: | ||
455 | emulated = kvmppc_handle_store(run, vcpu, | ||
456 | kvmppc_get_gpr(vcpu, rs), | ||
457 | 2, 1); | ||
458 | kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); | ||
459 | break; | ||
460 | |||
461 | default: | 277 | default: |
462 | emulated = EMULATE_FAIL; | 278 | emulated = EMULATE_FAIL; |
463 | } | 279 | } |
diff --git a/arch/powerpc/kvm/emulate_loadstore.c b/arch/powerpc/kvm/emulate_loadstore.c new file mode 100644 index 000000000000..0de4ffa175a9 --- /dev/null +++ b/arch/powerpc/kvm/emulate_loadstore.c | |||
@@ -0,0 +1,272 @@ | |||
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 IBM Corp. 2007 | ||
16 | * Copyright 2011 Freescale Semiconductor, Inc. | ||
17 | * | ||
18 | * Authors: Hollis Blanchard <hollisb@us.ibm.com> | ||
19 | */ | ||
20 | |||
21 | #include <linux/jiffies.h> | ||
22 | #include <linux/hrtimer.h> | ||
23 | #include <linux/types.h> | ||
24 | #include <linux/string.h> | ||
25 | #include <linux/kvm_host.h> | ||
26 | #include <linux/clockchips.h> | ||
27 | |||
28 | #include <asm/reg.h> | ||
29 | #include <asm/time.h> | ||
30 | #include <asm/byteorder.h> | ||
31 | #include <asm/kvm_ppc.h> | ||
32 | #include <asm/disassemble.h> | ||
33 | #include <asm/ppc-opcode.h> | ||
34 | #include "timing.h" | ||
35 | #include "trace.h" | ||
36 | |||
37 | /* XXX to do: | ||
38 | * lhax | ||
39 | * lhaux | ||
40 | * lswx | ||
41 | * lswi | ||
42 | * stswx | ||
43 | * stswi | ||
44 | * lha | ||
45 | * lhau | ||
46 | * lmw | ||
47 | * stmw | ||
48 | * | ||
49 | */ | ||
50 | int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu) | ||
51 | { | ||
52 | struct kvm_run *run = vcpu->run; | ||
53 | u32 inst; | ||
54 | int ra, rs, rt; | ||
55 | enum emulation_result emulated; | ||
56 | int advance = 1; | ||
57 | |||
58 | /* this default type might be overwritten by subcategories */ | ||
59 | kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS); | ||
60 | |||
61 | emulated = kvmppc_get_last_inst(vcpu, false, &inst); | ||
62 | if (emulated != EMULATE_DONE) | ||
63 | return emulated; | ||
64 | |||
65 | ra = get_ra(inst); | ||
66 | rs = get_rs(inst); | ||
67 | rt = get_rt(inst); | ||
68 | |||
69 | switch (get_op(inst)) { | ||
70 | case 31: | ||
71 | switch (get_xop(inst)) { | ||
72 | case OP_31_XOP_LWZX: | ||
73 | emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1); | ||
74 | break; | ||
75 | |||
76 | case OP_31_XOP_LBZX: | ||
77 | emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1); | ||
78 | break; | ||
79 | |||
80 | case OP_31_XOP_LBZUX: | ||
81 | emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1); | ||
82 | kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); | ||
83 | break; | ||
84 | |||
85 | case OP_31_XOP_STWX: | ||
86 | emulated = kvmppc_handle_store(run, vcpu, | ||
87 | kvmppc_get_gpr(vcpu, rs), | ||
88 | 4, 1); | ||
89 | break; | ||
90 | |||
91 | case OP_31_XOP_STBX: | ||
92 | emulated = kvmppc_handle_store(run, vcpu, | ||
93 | kvmppc_get_gpr(vcpu, rs), | ||
94 | 1, 1); | ||
95 | break; | ||
96 | |||
97 | case OP_31_XOP_STBUX: | ||
98 | emulated = kvmppc_handle_store(run, vcpu, | ||
99 | kvmppc_get_gpr(vcpu, rs), | ||
100 | 1, 1); | ||
101 | kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); | ||
102 | break; | ||
103 | |||
104 | case OP_31_XOP_LHAX: | ||
105 | emulated = kvmppc_handle_loads(run, vcpu, rt, 2, 1); | ||
106 | break; | ||
107 | |||
108 | case OP_31_XOP_LHZX: | ||
109 | emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1); | ||
110 | break; | ||
111 | |||
112 | case OP_31_XOP_LHZUX: | ||
113 | emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1); | ||
114 | kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); | ||
115 | break; | ||
116 | |||
117 | case OP_31_XOP_STHX: | ||
118 | emulated = kvmppc_handle_store(run, vcpu, | ||
119 | kvmppc_get_gpr(vcpu, rs), | ||
120 | 2, 1); | ||
121 | break; | ||
122 | |||
123 | case OP_31_XOP_STHUX: | ||
124 | emulated = kvmppc_handle_store(run, vcpu, | ||
125 | kvmppc_get_gpr(vcpu, rs), | ||
126 | 2, 1); | ||
127 | kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); | ||
128 | break; | ||
129 | |||
130 | case OP_31_XOP_DCBST: | ||
131 | case OP_31_XOP_DCBF: | ||
132 | case OP_31_XOP_DCBI: | ||
133 | /* Do nothing. The guest is performing dcbi because | ||
134 | * hardware DMA is not snooped by the dcache, but | ||
135 | * emulated DMA either goes through the dcache as | ||
136 | * normal writes, or the host kernel has handled dcache | ||
137 | * coherence. */ | ||
138 | break; | ||
139 | |||
140 | case OP_31_XOP_LWBRX: | ||
141 | emulated = kvmppc_handle_load(run, vcpu, rt, 4, 0); | ||
142 | break; | ||
143 | |||
144 | case OP_31_XOP_STWBRX: | ||
145 | emulated = kvmppc_handle_store(run, vcpu, | ||
146 | kvmppc_get_gpr(vcpu, rs), | ||
147 | 4, 0); | ||
148 | break; | ||
149 | |||
150 | case OP_31_XOP_LHBRX: | ||
151 | emulated = kvmppc_handle_load(run, vcpu, rt, 2, 0); | ||
152 | break; | ||
153 | |||
154 | case OP_31_XOP_STHBRX: | ||
155 | emulated = kvmppc_handle_store(run, vcpu, | ||
156 | kvmppc_get_gpr(vcpu, rs), | ||
157 | 2, 0); | ||
158 | break; | ||
159 | |||
160 | default: | ||
161 | emulated = EMULATE_FAIL; | ||
162 | break; | ||
163 | } | ||
164 | break; | ||
165 | |||
166 | case OP_LWZ: | ||
167 | emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1); | ||
168 | break; | ||
169 | |||
170 | /* TBD: Add support for other 64 bit load variants like ldu, ldux, ldx etc. */ | ||
171 | case OP_LD: | ||
172 | rt = get_rt(inst); | ||
173 | emulated = kvmppc_handle_load(run, vcpu, rt, 8, 1); | ||
174 | break; | ||
175 | |||
176 | case OP_LWZU: | ||
177 | emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1); | ||
178 | kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); | ||
179 | break; | ||
180 | |||
181 | case OP_LBZ: | ||
182 | emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1); | ||
183 | break; | ||
184 | |||
185 | case OP_LBZU: | ||
186 | emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1); | ||
187 | kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); | ||
188 | break; | ||
189 | |||
190 | case OP_STW: | ||
191 | emulated = kvmppc_handle_store(run, vcpu, | ||
192 | kvmppc_get_gpr(vcpu, rs), | ||
193 | 4, 1); | ||
194 | break; | ||
195 | |||
196 | /* TBD: Add support for other 64 bit store variants like stdu, stdux, stdx etc. */ | ||
197 | case OP_STD: | ||
198 | rs = get_rs(inst); | ||
199 | emulated = kvmppc_handle_store(run, vcpu, | ||
200 | kvmppc_get_gpr(vcpu, rs), | ||
201 | 8, 1); | ||
202 | break; | ||
203 | |||
204 | case OP_STWU: | ||
205 | emulated = kvmppc_handle_store(run, vcpu, | ||
206 | kvmppc_get_gpr(vcpu, rs), | ||
207 | 4, 1); | ||
208 | kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); | ||
209 | break; | ||
210 | |||
211 | case OP_STB: | ||
212 | emulated = kvmppc_handle_store(run, vcpu, | ||
213 | kvmppc_get_gpr(vcpu, rs), | ||
214 | 1, 1); | ||
215 | break; | ||
216 | |||
217 | case OP_STBU: | ||
218 | emulated = kvmppc_handle_store(run, vcpu, | ||
219 | kvmppc_get_gpr(vcpu, rs), | ||
220 | 1, 1); | ||
221 | kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); | ||
222 | break; | ||
223 | |||
224 | case OP_LHZ: | ||
225 | emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1); | ||
226 | break; | ||
227 | |||
228 | case OP_LHZU: | ||
229 | emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1); | ||
230 | kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); | ||
231 | break; | ||
232 | |||
233 | case OP_LHA: | ||
234 | emulated = kvmppc_handle_loads(run, vcpu, rt, 2, 1); | ||
235 | break; | ||
236 | |||
237 | case OP_LHAU: | ||
238 | emulated = kvmppc_handle_loads(run, vcpu, rt, 2, 1); | ||
239 | kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); | ||
240 | break; | ||
241 | |||
242 | case OP_STH: | ||
243 | emulated = kvmppc_handle_store(run, vcpu, | ||
244 | kvmppc_get_gpr(vcpu, rs), | ||
245 | 2, 1); | ||
246 | break; | ||
247 | |||
248 | case OP_STHU: | ||
249 | emulated = kvmppc_handle_store(run, vcpu, | ||
250 | kvmppc_get_gpr(vcpu, rs), | ||
251 | 2, 1); | ||
252 | kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); | ||
253 | break; | ||
254 | |||
255 | default: | ||
256 | emulated = EMULATE_FAIL; | ||
257 | break; | ||
258 | } | ||
259 | |||
260 | if (emulated == EMULATE_FAIL) { | ||
261 | advance = 0; | ||
262 | kvmppc_core_queue_program(vcpu, 0); | ||
263 | } | ||
264 | |||
265 | trace_kvm_ppc_instr(inst, kvmppc_get_pc(vcpu), emulated); | ||
266 | |||
267 | /* Advance past emulated instruction. */ | ||
268 | if (advance) | ||
269 | kvmppc_set_pc(vcpu, kvmppc_get_pc(vcpu) + 4); | ||
270 | |||
271 | return emulated; | ||
272 | } | ||
diff --git a/arch/powerpc/kvm/mpic.c b/arch/powerpc/kvm/mpic.c index b68d0dc9479a..39b3a8f816f2 100644 --- a/arch/powerpc/kvm/mpic.c +++ b/arch/powerpc/kvm/mpic.c | |||
@@ -1826,8 +1826,7 @@ int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, | |||
1826 | return 0; | 1826 | return 0; |
1827 | } | 1827 | } |
1828 | 1828 | ||
1829 | int kvm_set_routing_entry(struct kvm_irq_routing_table *rt, | 1829 | int kvm_set_routing_entry(struct kvm_kernel_irq_routing_entry *e, |
1830 | struct kvm_kernel_irq_routing_entry *e, | ||
1831 | const struct kvm_irq_routing_entry *ue) | 1830 | const struct kvm_irq_routing_entry *ue) |
1832 | { | 1831 | { |
1833 | int r = -EINVAL; | 1832 | int r = -EINVAL; |
@@ -1839,7 +1838,6 @@ int kvm_set_routing_entry(struct kvm_irq_routing_table *rt, | |||
1839 | e->irqchip.pin = ue->u.irqchip.pin; | 1838 | e->irqchip.pin = ue->u.irqchip.pin; |
1840 | if (e->irqchip.pin >= KVM_IRQCHIP_NUM_PINS) | 1839 | if (e->irqchip.pin >= KVM_IRQCHIP_NUM_PINS) |
1841 | goto out; | 1840 | goto out; |
1842 | rt->chip[ue->u.irqchip.irqchip][e->irqchip.pin] = ue->gsi; | ||
1843 | break; | 1841 | break; |
1844 | case KVM_IRQ_ROUTING_MSI: | 1842 | case KVM_IRQ_ROUTING_MSI: |
1845 | e->set = kvm_set_msi; | 1843 | e->set = kvm_set_msi; |
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index 61c738ab1283..4c79284b58be 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c | |||
@@ -190,6 +190,25 @@ int kvmppc_kvm_pv(struct kvm_vcpu *vcpu) | |||
190 | vcpu->arch.magic_page_pa = param1 & ~0xfffULL; | 190 | vcpu->arch.magic_page_pa = param1 & ~0xfffULL; |
191 | vcpu->arch.magic_page_ea = param2 & ~0xfffULL; | 191 | vcpu->arch.magic_page_ea = param2 & ~0xfffULL; |
192 | 192 | ||
193 | #ifdef CONFIG_PPC_64K_PAGES | ||
194 | /* | ||
195 | * Make sure our 4k magic page is in the same window of a 64k | ||
196 | * page within the guest and within the host's page. | ||
197 | */ | ||
198 | if ((vcpu->arch.magic_page_pa & 0xf000) != | ||
199 | ((ulong)vcpu->arch.shared & 0xf000)) { | ||
200 | void *old_shared = vcpu->arch.shared; | ||
201 | ulong shared = (ulong)vcpu->arch.shared; | ||
202 | void *new_shared; | ||
203 | |||
204 | shared &= PAGE_MASK; | ||
205 | shared |= vcpu->arch.magic_page_pa & 0xf000; | ||
206 | new_shared = (void*)shared; | ||
207 | memcpy(new_shared, old_shared, 0x1000); | ||
208 | vcpu->arch.shared = new_shared; | ||
209 | } | ||
210 | #endif | ||
211 | |||
193 | r2 = KVM_MAGIC_FEAT_SR | KVM_MAGIC_FEAT_MAS0_TO_SPRG7; | 212 | r2 = KVM_MAGIC_FEAT_SR | KVM_MAGIC_FEAT_MAS0_TO_SPRG7; |
194 | 213 | ||
195 | r = EV_SUCCESS; | 214 | r = EV_SUCCESS; |
@@ -198,7 +217,6 @@ int kvmppc_kvm_pv(struct kvm_vcpu *vcpu) | |||
198 | case KVM_HCALL_TOKEN(KVM_HC_FEATURES): | 217 | case KVM_HCALL_TOKEN(KVM_HC_FEATURES): |
199 | r = EV_SUCCESS; | 218 | r = EV_SUCCESS; |
200 | #if defined(CONFIG_PPC_BOOK3S) || defined(CONFIG_KVM_E500V2) | 219 | #if defined(CONFIG_PPC_BOOK3S) || defined(CONFIG_KVM_E500V2) |
201 | /* XXX Missing magic page on 44x */ | ||
202 | r2 |= (1 << KVM_FEATURE_MAGIC_PAGE); | 220 | r2 |= (1 << KVM_FEATURE_MAGIC_PAGE); |
203 | #endif | 221 | #endif |
204 | 222 | ||
@@ -254,13 +272,16 @@ int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu) | |||
254 | enum emulation_result er; | 272 | enum emulation_result er; |
255 | int r; | 273 | int r; |
256 | 274 | ||
257 | er = kvmppc_emulate_instruction(run, vcpu); | 275 | er = kvmppc_emulate_loadstore(vcpu); |
258 | switch (er) { | 276 | switch (er) { |
259 | case EMULATE_DONE: | 277 | case EMULATE_DONE: |
260 | /* Future optimization: only reload non-volatiles if they were | 278 | /* Future optimization: only reload non-volatiles if they were |
261 | * actually modified. */ | 279 | * actually modified. */ |
262 | r = RESUME_GUEST_NV; | 280 | r = RESUME_GUEST_NV; |
263 | break; | 281 | break; |
282 | case EMULATE_AGAIN: | ||
283 | r = RESUME_GUEST; | ||
284 | break; | ||
264 | case EMULATE_DO_MMIO: | 285 | case EMULATE_DO_MMIO: |
265 | run->exit_reason = KVM_EXIT_MMIO; | 286 | run->exit_reason = KVM_EXIT_MMIO; |
266 | /* We must reload nonvolatiles because "update" load/store | 287 | /* We must reload nonvolatiles because "update" load/store |
@@ -270,11 +291,15 @@ int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu) | |||
270 | r = RESUME_HOST_NV; | 291 | r = RESUME_HOST_NV; |
271 | break; | 292 | break; |
272 | case EMULATE_FAIL: | 293 | case EMULATE_FAIL: |
294 | { | ||
295 | u32 last_inst; | ||
296 | |||
297 | kvmppc_get_last_inst(vcpu, false, &last_inst); | ||
273 | /* XXX Deliver Program interrupt to guest. */ | 298 | /* XXX Deliver Program interrupt to guest. */ |
274 | printk(KERN_EMERG "%s: emulation failed (%08x)\n", __func__, | 299 | pr_emerg("%s: emulation failed (%08x)\n", __func__, last_inst); |
275 | kvmppc_get_last_inst(vcpu)); | ||
276 | r = RESUME_HOST; | 300 | r = RESUME_HOST; |
277 | break; | 301 | break; |
302 | } | ||
278 | default: | 303 | default: |
279 | WARN_ON(1); | 304 | WARN_ON(1); |
280 | r = RESUME_GUEST; | 305 | r = RESUME_GUEST; |
@@ -284,6 +309,81 @@ int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu) | |||
284 | } | 309 | } |
285 | EXPORT_SYMBOL_GPL(kvmppc_emulate_mmio); | 310 | EXPORT_SYMBOL_GPL(kvmppc_emulate_mmio); |
286 | 311 | ||
312 | int kvmppc_st(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr, | ||
313 | bool data) | ||
314 | { | ||
315 | ulong mp_pa = vcpu->arch.magic_page_pa & KVM_PAM & PAGE_MASK; | ||
316 | struct kvmppc_pte pte; | ||
317 | int r; | ||
318 | |||
319 | vcpu->stat.st++; | ||
320 | |||
321 | r = kvmppc_xlate(vcpu, *eaddr, data ? XLATE_DATA : XLATE_INST, | ||
322 | XLATE_WRITE, &pte); | ||
323 | if (r < 0) | ||
324 | return r; | ||
325 | |||
326 | *eaddr = pte.raddr; | ||
327 | |||
328 | if (!pte.may_write) | ||
329 | return -EPERM; | ||
330 | |||
331 | /* Magic page override */ | ||
332 | if (kvmppc_supports_magic_page(vcpu) && mp_pa && | ||
333 | ((pte.raddr & KVM_PAM & PAGE_MASK) == mp_pa) && | ||
334 | !(kvmppc_get_msr(vcpu) & MSR_PR)) { | ||
335 | void *magic = vcpu->arch.shared; | ||
336 | magic += pte.eaddr & 0xfff; | ||
337 | memcpy(magic, ptr, size); | ||
338 | return EMULATE_DONE; | ||
339 | } | ||
340 | |||
341 | if (kvm_write_guest(vcpu->kvm, pte.raddr, ptr, size)) | ||
342 | return EMULATE_DO_MMIO; | ||
343 | |||
344 | return EMULATE_DONE; | ||
345 | } | ||
346 | EXPORT_SYMBOL_GPL(kvmppc_st); | ||
347 | |||
348 | int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr, | ||
349 | bool data) | ||
350 | { | ||
351 | ulong mp_pa = vcpu->arch.magic_page_pa & KVM_PAM & PAGE_MASK; | ||
352 | struct kvmppc_pte pte; | ||
353 | int rc; | ||
354 | |||
355 | vcpu->stat.ld++; | ||
356 | |||
357 | rc = kvmppc_xlate(vcpu, *eaddr, data ? XLATE_DATA : XLATE_INST, | ||
358 | XLATE_READ, &pte); | ||
359 | if (rc) | ||
360 | return rc; | ||
361 | |||
362 | *eaddr = pte.raddr; | ||
363 | |||
364 | if (!pte.may_read) | ||
365 | return -EPERM; | ||
366 | |||
367 | if (!data && !pte.may_execute) | ||
368 | return -ENOEXEC; | ||
369 | |||
370 | /* Magic page override */ | ||
371 | if (kvmppc_supports_magic_page(vcpu) && mp_pa && | ||
372 | ((pte.raddr & KVM_PAM & PAGE_MASK) == mp_pa) && | ||
373 | !(kvmppc_get_msr(vcpu) & MSR_PR)) { | ||
374 | void *magic = vcpu->arch.shared; | ||
375 | magic += pte.eaddr & 0xfff; | ||
376 | memcpy(ptr, magic, size); | ||
377 | return EMULATE_DONE; | ||
378 | } | ||
379 | |||
380 | if (kvm_read_guest(vcpu->kvm, pte.raddr, ptr, size)) | ||
381 | return EMULATE_DO_MMIO; | ||
382 | |||
383 | return EMULATE_DONE; | ||
384 | } | ||
385 | EXPORT_SYMBOL_GPL(kvmppc_ld); | ||
386 | |||
287 | int kvm_arch_hardware_enable(void *garbage) | 387 | int kvm_arch_hardware_enable(void *garbage) |
288 | { | 388 | { |
289 | return 0; | 389 | return 0; |
@@ -366,14 +466,20 @@ void kvm_arch_sync_events(struct kvm *kvm) | |||
366 | { | 466 | { |
367 | } | 467 | } |
368 | 468 | ||
369 | int kvm_dev_ioctl_check_extension(long ext) | 469 | int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) |
370 | { | 470 | { |
371 | int r; | 471 | int r; |
372 | /* FIXME!! | 472 | /* Assume we're using HV mode when the HV module is loaded */ |
373 | * Should some of this be vm ioctl ? is it possible now ? | ||
374 | */ | ||
375 | int hv_enabled = kvmppc_hv_ops ? 1 : 0; | 473 | int hv_enabled = kvmppc_hv_ops ? 1 : 0; |
376 | 474 | ||
475 | if (kvm) { | ||
476 | /* | ||
477 | * Hooray - we know which VM type we're running on. Depend on | ||
478 | * that rather than the guess above. | ||
479 | */ | ||
480 | hv_enabled = is_kvmppc_hv_enabled(kvm); | ||
481 | } | ||
482 | |||
377 | switch (ext) { | 483 | switch (ext) { |
378 | #ifdef CONFIG_BOOKE | 484 | #ifdef CONFIG_BOOKE |
379 | case KVM_CAP_PPC_BOOKE_SREGS: | 485 | case KVM_CAP_PPC_BOOKE_SREGS: |
@@ -387,6 +493,7 @@ int kvm_dev_ioctl_check_extension(long ext) | |||
387 | case KVM_CAP_PPC_UNSET_IRQ: | 493 | case KVM_CAP_PPC_UNSET_IRQ: |
388 | case KVM_CAP_PPC_IRQ_LEVEL: | 494 | case KVM_CAP_PPC_IRQ_LEVEL: |
389 | case KVM_CAP_ENABLE_CAP: | 495 | case KVM_CAP_ENABLE_CAP: |
496 | case KVM_CAP_ENABLE_CAP_VM: | ||
390 | case KVM_CAP_ONE_REG: | 497 | case KVM_CAP_ONE_REG: |
391 | case KVM_CAP_IOEVENTFD: | 498 | case KVM_CAP_IOEVENTFD: |
392 | case KVM_CAP_DEVICE_CTRL: | 499 | case KVM_CAP_DEVICE_CTRL: |
@@ -417,6 +524,7 @@ int kvm_dev_ioctl_check_extension(long ext) | |||
417 | case KVM_CAP_PPC_ALLOC_HTAB: | 524 | case KVM_CAP_PPC_ALLOC_HTAB: |
418 | case KVM_CAP_PPC_RTAS: | 525 | case KVM_CAP_PPC_RTAS: |
419 | case KVM_CAP_PPC_FIXUP_HCALL: | 526 | case KVM_CAP_PPC_FIXUP_HCALL: |
527 | case KVM_CAP_PPC_ENABLE_HCALL: | ||
420 | #ifdef CONFIG_KVM_XICS | 528 | #ifdef CONFIG_KVM_XICS |
421 | case KVM_CAP_IRQ_XICS: | 529 | case KVM_CAP_IRQ_XICS: |
422 | #endif | 530 | #endif |
@@ -635,12 +743,6 @@ void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) | |||
635 | #endif | 743 | #endif |
636 | } | 744 | } |
637 | 745 | ||
638 | static void kvmppc_complete_dcr_load(struct kvm_vcpu *vcpu, | ||
639 | struct kvm_run *run) | ||
640 | { | ||
641 | kvmppc_set_gpr(vcpu, vcpu->arch.io_gpr, run->dcr.data); | ||
642 | } | ||
643 | |||
644 | static void kvmppc_complete_mmio_load(struct kvm_vcpu *vcpu, | 746 | static void kvmppc_complete_mmio_load(struct kvm_vcpu *vcpu, |
645 | struct kvm_run *run) | 747 | struct kvm_run *run) |
646 | { | 748 | { |
@@ -837,10 +939,6 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) | |||
837 | if (!vcpu->mmio_is_write) | 939 | if (!vcpu->mmio_is_write) |
838 | kvmppc_complete_mmio_load(vcpu, run); | 940 | kvmppc_complete_mmio_load(vcpu, run); |
839 | vcpu->mmio_needed = 0; | 941 | vcpu->mmio_needed = 0; |
840 | } else if (vcpu->arch.dcr_needed) { | ||
841 | if (!vcpu->arch.dcr_is_write) | ||
842 | kvmppc_complete_dcr_load(vcpu, run); | ||
843 | vcpu->arch.dcr_needed = 0; | ||
844 | } else if (vcpu->arch.osi_needed) { | 942 | } else if (vcpu->arch.osi_needed) { |
845 | u64 *gprs = run->osi.gprs; | 943 | u64 *gprs = run->osi.gprs; |
846 | int i; | 944 | int i; |
@@ -1099,6 +1197,42 @@ int kvm_vm_ioctl_irq_line(struct kvm *kvm, struct kvm_irq_level *irq_event, | |||
1099 | return 0; | 1197 | return 0; |
1100 | } | 1198 | } |
1101 | 1199 | ||
1200 | |||
1201 | static int kvm_vm_ioctl_enable_cap(struct kvm *kvm, | ||
1202 | struct kvm_enable_cap *cap) | ||
1203 | { | ||
1204 | int r; | ||
1205 | |||
1206 | if (cap->flags) | ||
1207 | return -EINVAL; | ||
1208 | |||
1209 | switch (cap->cap) { | ||
1210 | #ifdef CONFIG_KVM_BOOK3S_64_HANDLER | ||
1211 | case KVM_CAP_PPC_ENABLE_HCALL: { | ||
1212 | unsigned long hcall = cap->args[0]; | ||
1213 | |||
1214 | r = -EINVAL; | ||
1215 | if (hcall > MAX_HCALL_OPCODE || (hcall & 3) || | ||
1216 | cap->args[1] > 1) | ||
1217 | break; | ||
1218 | if (!kvmppc_book3s_hcall_implemented(kvm, hcall)) | ||
1219 | break; | ||
1220 | if (cap->args[1]) | ||
1221 | set_bit(hcall / 4, kvm->arch.enabled_hcalls); | ||
1222 | else | ||
1223 | clear_bit(hcall / 4, kvm->arch.enabled_hcalls); | ||
1224 | r = 0; | ||
1225 | break; | ||
1226 | } | ||
1227 | #endif | ||
1228 | default: | ||
1229 | r = -EINVAL; | ||
1230 | break; | ||
1231 | } | ||
1232 | |||
1233 | return r; | ||
1234 | } | ||
1235 | |||
1102 | long kvm_arch_vm_ioctl(struct file *filp, | 1236 | long kvm_arch_vm_ioctl(struct file *filp, |
1103 | unsigned int ioctl, unsigned long arg) | 1237 | unsigned int ioctl, unsigned long arg) |
1104 | { | 1238 | { |
@@ -1118,6 +1252,15 @@ long kvm_arch_vm_ioctl(struct file *filp, | |||
1118 | 1252 | ||
1119 | break; | 1253 | break; |
1120 | } | 1254 | } |
1255 | case KVM_ENABLE_CAP: | ||
1256 | { | ||
1257 | struct kvm_enable_cap cap; | ||
1258 | r = -EFAULT; | ||
1259 | if (copy_from_user(&cap, argp, sizeof(cap))) | ||
1260 | goto out; | ||
1261 | r = kvm_vm_ioctl_enable_cap(kvm, &cap); | ||
1262 | break; | ||
1263 | } | ||
1121 | #ifdef CONFIG_PPC_BOOK3S_64 | 1264 | #ifdef CONFIG_PPC_BOOK3S_64 |
1122 | case KVM_CREATE_SPAPR_TCE: { | 1265 | case KVM_CREATE_SPAPR_TCE: { |
1123 | struct kvm_create_spapr_tce create_tce; | 1266 | struct kvm_create_spapr_tce create_tce; |
@@ -1204,3 +1347,5 @@ void kvm_arch_exit(void) | |||
1204 | { | 1347 | { |
1205 | 1348 | ||
1206 | } | 1349 | } |
1350 | |||
1351 | EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_ppc_instr); | ||
diff --git a/arch/powerpc/kvm/timing.c b/arch/powerpc/kvm/timing.c index 07b6110a4bb7..e44d2b2ea97e 100644 --- a/arch/powerpc/kvm/timing.c +++ b/arch/powerpc/kvm/timing.c | |||
@@ -110,7 +110,6 @@ void kvmppc_update_timing_stats(struct kvm_vcpu *vcpu) | |||
110 | 110 | ||
111 | static const char *kvm_exit_names[__NUMBER_OF_KVM_EXIT_TYPES] = { | 111 | static const char *kvm_exit_names[__NUMBER_OF_KVM_EXIT_TYPES] = { |
112 | [MMIO_EXITS] = "MMIO", | 112 | [MMIO_EXITS] = "MMIO", |
113 | [DCR_EXITS] = "DCR", | ||
114 | [SIGNAL_EXITS] = "SIGNAL", | 113 | [SIGNAL_EXITS] = "SIGNAL", |
115 | [ITLB_REAL_MISS_EXITS] = "ITLBREAL", | 114 | [ITLB_REAL_MISS_EXITS] = "ITLBREAL", |
116 | [ITLB_VIRT_MISS_EXITS] = "ITLBVIRT", | 115 | [ITLB_VIRT_MISS_EXITS] = "ITLBVIRT", |
diff --git a/arch/powerpc/kvm/timing.h b/arch/powerpc/kvm/timing.h index bf191e72b2d8..3123690c82dc 100644 --- a/arch/powerpc/kvm/timing.h +++ b/arch/powerpc/kvm/timing.h | |||
@@ -63,9 +63,6 @@ static inline void kvmppc_account_exit_stat(struct kvm_vcpu *vcpu, int type) | |||
63 | case EMULATED_INST_EXITS: | 63 | case EMULATED_INST_EXITS: |
64 | vcpu->stat.emulated_inst_exits++; | 64 | vcpu->stat.emulated_inst_exits++; |
65 | break; | 65 | break; |
66 | case DCR_EXITS: | ||
67 | vcpu->stat.dcr_exits++; | ||
68 | break; | ||
69 | case DSI_EXITS: | 66 | case DSI_EXITS: |
70 | vcpu->stat.dsi_exits++; | 67 | vcpu->stat.dsi_exits++; |
71 | break; | 68 | break; |
diff --git a/arch/powerpc/lib/copyuser_64.S b/arch/powerpc/lib/copyuser_64.S index 0860ee46013c..f09899e35991 100644 --- a/arch/powerpc/lib/copyuser_64.S +++ b/arch/powerpc/lib/copyuser_64.S | |||
@@ -461,8 +461,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_UNALIGNED_LD_STD) | |||
461 | /* | 461 | /* |
462 | * Routine to copy a whole page of data, optimized for POWER4. | 462 | * Routine to copy a whole page of data, optimized for POWER4. |
463 | * On POWER4 it is more than 50% faster than the simple loop | 463 | * On POWER4 it is more than 50% faster than the simple loop |
464 | * above (following the .Ldst_aligned label) but it runs slightly | 464 | * above (following the .Ldst_aligned label). |
465 | * slower on POWER3. | ||
466 | */ | 465 | */ |
467 | .Lcopy_page_4K: | 466 | .Lcopy_page_4K: |
468 | std r31,-32(1) | 467 | std r31,-32(1) |
diff --git a/arch/powerpc/lib/locks.c b/arch/powerpc/lib/locks.c index 0c9c8d7d0734..170a0346f756 100644 --- a/arch/powerpc/lib/locks.c +++ b/arch/powerpc/lib/locks.c | |||
@@ -70,12 +70,16 @@ void __rw_yield(arch_rwlock_t *rw) | |||
70 | 70 | ||
71 | void arch_spin_unlock_wait(arch_spinlock_t *lock) | 71 | void arch_spin_unlock_wait(arch_spinlock_t *lock) |
72 | { | 72 | { |
73 | smp_mb(); | ||
74 | |||
73 | while (lock->slock) { | 75 | while (lock->slock) { |
74 | HMT_low(); | 76 | HMT_low(); |
75 | if (SHARED_PROCESSOR) | 77 | if (SHARED_PROCESSOR) |
76 | __spin_yield(lock); | 78 | __spin_yield(lock); |
77 | } | 79 | } |
78 | HMT_medium(); | 80 | HMT_medium(); |
81 | |||
82 | smp_mb(); | ||
79 | } | 83 | } |
80 | 84 | ||
81 | EXPORT_SYMBOL(arch_spin_unlock_wait); | 85 | EXPORT_SYMBOL(arch_spin_unlock_wait); |
diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile index 51230ee6a407..d0130fff20e5 100644 --- a/arch/powerpc/mm/Makefile +++ b/arch/powerpc/mm/Makefile | |||
@@ -13,9 +13,7 @@ obj-$(CONFIG_PPC_MMU_NOHASH) += mmu_context_nohash.o tlb_nohash.o \ | |||
13 | tlb_nohash_low.o | 13 | tlb_nohash_low.o |
14 | obj-$(CONFIG_PPC_BOOK3E) += tlb_low_$(CONFIG_WORD_SIZE)e.o | 14 | obj-$(CONFIG_PPC_BOOK3E) += tlb_low_$(CONFIG_WORD_SIZE)e.o |
15 | hash64-$(CONFIG_PPC_NATIVE) := hash_native_64.o | 15 | hash64-$(CONFIG_PPC_NATIVE) := hash_native_64.o |
16 | obj-$(CONFIG_PPC_STD_MMU_64) += hash_utils_64.o \ | 16 | obj-$(CONFIG_PPC_STD_MMU_64) += hash_utils_64.o slb_low.o slb.o $(hash64-y) |
17 | slb_low.o slb.o stab.o \ | ||
18 | $(hash64-y) | ||
19 | obj-$(CONFIG_PPC_STD_MMU_32) += ppc_mmu_32.o | 17 | obj-$(CONFIG_PPC_STD_MMU_32) += ppc_mmu_32.o |
20 | obj-$(CONFIG_PPC_STD_MMU) += hash_low_$(CONFIG_WORD_SIZE).o \ | 18 | obj-$(CONFIG_PPC_STD_MMU) += hash_low_$(CONFIG_WORD_SIZE).o \ |
21 | tlb_hash$(CONFIG_WORD_SIZE).o \ | 19 | tlb_hash$(CONFIG_WORD_SIZE).o \ |
diff --git a/arch/powerpc/mm/dma-noncoherent.c b/arch/powerpc/mm/dma-noncoherent.c index 7b6c10750179..d85e86aac7fb 100644 --- a/arch/powerpc/mm/dma-noncoherent.c +++ b/arch/powerpc/mm/dma-noncoherent.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/export.h> | 33 | #include <linux/export.h> |
34 | 34 | ||
35 | #include <asm/tlbflush.h> | 35 | #include <asm/tlbflush.h> |
36 | #include <asm/dma.h> | ||
36 | 37 | ||
37 | #include "mmu_decl.h" | 38 | #include "mmu_decl.h" |
38 | 39 | ||
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c index cf1d325eae8b..afc0a8295f84 100644 --- a/arch/powerpc/mm/hash_native_64.c +++ b/arch/powerpc/mm/hash_native_64.c | |||
@@ -412,18 +412,18 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long vpn, | |||
412 | local_irq_restore(flags); | 412 | local_irq_restore(flags); |
413 | } | 413 | } |
414 | 414 | ||
415 | static void native_hugepage_invalidate(struct mm_struct *mm, | 415 | static void native_hugepage_invalidate(unsigned long vsid, |
416 | unsigned long addr, | ||
416 | unsigned char *hpte_slot_array, | 417 | unsigned char *hpte_slot_array, |
417 | unsigned long addr, int psize) | 418 | int psize, int ssize) |
418 | { | 419 | { |
419 | int ssize = 0, i; | 420 | int i; |
420 | int lock_tlbie; | ||
421 | struct hash_pte *hptep; | 421 | struct hash_pte *hptep; |
422 | int actual_psize = MMU_PAGE_16M; | 422 | int actual_psize = MMU_PAGE_16M; |
423 | unsigned int max_hpte_count, valid; | 423 | unsigned int max_hpte_count, valid; |
424 | unsigned long flags, s_addr = addr; | 424 | unsigned long flags, s_addr = addr; |
425 | unsigned long hpte_v, want_v, shift; | 425 | unsigned long hpte_v, want_v, shift; |
426 | unsigned long hidx, vpn = 0, vsid, hash, slot; | 426 | unsigned long hidx, vpn = 0, hash, slot; |
427 | 427 | ||
428 | shift = mmu_psize_defs[psize].shift; | 428 | shift = mmu_psize_defs[psize].shift; |
429 | max_hpte_count = 1U << (PMD_SHIFT - shift); | 429 | max_hpte_count = 1U << (PMD_SHIFT - shift); |
@@ -437,15 +437,6 @@ static void native_hugepage_invalidate(struct mm_struct *mm, | |||
437 | 437 | ||
438 | /* get the vpn */ | 438 | /* get the vpn */ |
439 | addr = s_addr + (i * (1ul << shift)); | 439 | addr = s_addr + (i * (1ul << shift)); |
440 | if (!is_kernel_addr(addr)) { | ||
441 | ssize = user_segment_size(addr); | ||
442 | vsid = get_vsid(mm->context.id, addr, ssize); | ||
443 | WARN_ON(vsid == 0); | ||
444 | } else { | ||
445 | vsid = get_kernel_vsid(addr, mmu_kernel_ssize); | ||
446 | ssize = mmu_kernel_ssize; | ||
447 | } | ||
448 | |||
449 | vpn = hpt_vpn(addr, vsid, ssize); | 440 | vpn = hpt_vpn(addr, vsid, ssize); |
450 | hash = hpt_hash(vpn, shift, ssize); | 441 | hash = hpt_hash(vpn, shift, ssize); |
451 | if (hidx & _PTEIDX_SECONDARY) | 442 | if (hidx & _PTEIDX_SECONDARY) |
@@ -465,22 +456,13 @@ static void native_hugepage_invalidate(struct mm_struct *mm, | |||
465 | else | 456 | else |
466 | /* Invalidate the hpte. NOTE: this also unlocks it */ | 457 | /* Invalidate the hpte. NOTE: this also unlocks it */ |
467 | hptep->v = 0; | 458 | hptep->v = 0; |
459 | /* | ||
460 | * We need to do tlb invalidate for all the address, tlbie | ||
461 | * instruction compares entry_VA in tlb with the VA specified | ||
462 | * here | ||
463 | */ | ||
464 | tlbie(vpn, psize, actual_psize, ssize, 0); | ||
468 | } | 465 | } |
469 | /* | ||
470 | * Since this is a hugepage, we just need a single tlbie. | ||
471 | * use the last vpn. | ||
472 | */ | ||
473 | lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE); | ||
474 | if (lock_tlbie) | ||
475 | raw_spin_lock(&native_tlbie_lock); | ||
476 | |||
477 | asm volatile("ptesync":::"memory"); | ||
478 | __tlbie(vpn, psize, actual_psize, ssize); | ||
479 | asm volatile("eieio; tlbsync; ptesync":::"memory"); | ||
480 | |||
481 | if (lock_tlbie) | ||
482 | raw_spin_unlock(&native_tlbie_lock); | ||
483 | |||
484 | local_irq_restore(flags); | 466 | local_irq_restore(flags); |
485 | } | 467 | } |
486 | 468 | ||
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 88fdd9d25077..daee7f4e5a14 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c | |||
@@ -243,7 +243,7 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend, | |||
243 | } | 243 | } |
244 | 244 | ||
245 | #ifdef CONFIG_MEMORY_HOTPLUG | 245 | #ifdef CONFIG_MEMORY_HOTPLUG |
246 | static int htab_remove_mapping(unsigned long vstart, unsigned long vend, | 246 | int htab_remove_mapping(unsigned long vstart, unsigned long vend, |
247 | int psize, int ssize) | 247 | int psize, int ssize) |
248 | { | 248 | { |
249 | unsigned long vaddr; | 249 | unsigned long vaddr; |
@@ -821,21 +821,14 @@ static void __init htab_initialize(void) | |||
821 | 821 | ||
822 | void __init early_init_mmu(void) | 822 | void __init early_init_mmu(void) |
823 | { | 823 | { |
824 | /* Setup initial STAB address in the PACA */ | ||
825 | get_paca()->stab_real = __pa((u64)&initial_stab); | ||
826 | get_paca()->stab_addr = (u64)&initial_stab; | ||
827 | |||
828 | /* Initialize the MMU Hash table and create the linear mapping | 824 | /* Initialize the MMU Hash table and create the linear mapping |
829 | * of memory. Has to be done before stab/slb initialization as | 825 | * of memory. Has to be done before SLB initialization as this is |
830 | * this is currently where the page size encoding is obtained | 826 | * currently where the page size encoding is obtained. |
831 | */ | 827 | */ |
832 | htab_initialize(); | 828 | htab_initialize(); |
833 | 829 | ||
834 | /* Initialize stab / SLB management */ | 830 | /* Initialize SLB management */ |
835 | if (mmu_has_feature(MMU_FTR_SLB)) | 831 | slb_initialize(); |
836 | slb_initialize(); | ||
837 | else | ||
838 | stab_initialize(get_paca()->stab_real); | ||
839 | } | 832 | } |
840 | 833 | ||
841 | #ifdef CONFIG_SMP | 834 | #ifdef CONFIG_SMP |
@@ -845,13 +838,8 @@ void early_init_mmu_secondary(void) | |||
845 | if (!firmware_has_feature(FW_FEATURE_LPAR)) | 838 | if (!firmware_has_feature(FW_FEATURE_LPAR)) |
846 | mtspr(SPRN_SDR1, _SDR1); | 839 | mtspr(SPRN_SDR1, _SDR1); |
847 | 840 | ||
848 | /* Initialize STAB/SLB. We use a virtual address as it works | 841 | /* Initialize SLB */ |
849 | * in real mode on pSeries. | 842 | slb_initialize(); |
850 | */ | ||
851 | if (mmu_has_feature(MMU_FTR_SLB)) | ||
852 | slb_initialize(); | ||
853 | else | ||
854 | stab_initialize(get_paca()->stab_addr); | ||
855 | } | 843 | } |
856 | #endif /* CONFIG_SMP */ | 844 | #endif /* CONFIG_SMP */ |
857 | 845 | ||
diff --git a/arch/powerpc/mm/hugepage-hash64.c b/arch/powerpc/mm/hugepage-hash64.c index 826893fcb3a7..5f5e6328c21c 100644 --- a/arch/powerpc/mm/hugepage-hash64.c +++ b/arch/powerpc/mm/hugepage-hash64.c | |||
@@ -18,6 +18,57 @@ | |||
18 | #include <linux/mm.h> | 18 | #include <linux/mm.h> |
19 | #include <asm/machdep.h> | 19 | #include <asm/machdep.h> |
20 | 20 | ||
21 | static void invalidate_old_hpte(unsigned long vsid, unsigned long addr, | ||
22 | pmd_t *pmdp, unsigned int psize, int ssize) | ||
23 | { | ||
24 | int i, max_hpte_count, valid; | ||
25 | unsigned long s_addr; | ||
26 | unsigned char *hpte_slot_array; | ||
27 | unsigned long hidx, shift, vpn, hash, slot; | ||
28 | |||
29 | s_addr = addr & HPAGE_PMD_MASK; | ||
30 | hpte_slot_array = get_hpte_slot_array(pmdp); | ||
31 | /* | ||
32 | * IF we try to do a HUGE PTE update after a withdraw is done. | ||
33 | * we will find the below NULL. This happens when we do | ||
34 | * split_huge_page_pmd | ||
35 | */ | ||
36 | if (!hpte_slot_array) | ||
37 | return; | ||
38 | |||
39 | if (ppc_md.hugepage_invalidate) | ||
40 | return ppc_md.hugepage_invalidate(vsid, s_addr, hpte_slot_array, | ||
41 | psize, ssize); | ||
42 | /* | ||
43 | * No bluk hpte removal support, invalidate each entry | ||
44 | */ | ||
45 | shift = mmu_psize_defs[psize].shift; | ||
46 | max_hpte_count = HPAGE_PMD_SIZE >> shift; | ||
47 | for (i = 0; i < max_hpte_count; i++) { | ||
48 | /* | ||
49 | * 8 bits per each hpte entries | ||
50 | * 000| [ secondary group (one bit) | hidx (3 bits) | valid bit] | ||
51 | */ | ||
52 | valid = hpte_valid(hpte_slot_array, i); | ||
53 | if (!valid) | ||
54 | continue; | ||
55 | hidx = hpte_hash_index(hpte_slot_array, i); | ||
56 | |||
57 | /* get the vpn */ | ||
58 | addr = s_addr + (i * (1ul << shift)); | ||
59 | vpn = hpt_vpn(addr, vsid, ssize); | ||
60 | hash = hpt_hash(vpn, shift, ssize); | ||
61 | if (hidx & _PTEIDX_SECONDARY) | ||
62 | hash = ~hash; | ||
63 | |||
64 | slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; | ||
65 | slot += hidx & _PTEIDX_GROUP_IX; | ||
66 | ppc_md.hpte_invalidate(slot, vpn, psize, | ||
67 | MMU_PAGE_16M, ssize, 0); | ||
68 | } | ||
69 | } | ||
70 | |||
71 | |||
21 | int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid, | 72 | int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid, |
22 | pmd_t *pmdp, unsigned long trap, int local, int ssize, | 73 | pmd_t *pmdp, unsigned long trap, int local, int ssize, |
23 | unsigned int psize) | 74 | unsigned int psize) |
@@ -33,7 +84,9 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid, | |||
33 | * atomically mark the linux large page PMD busy and dirty | 84 | * atomically mark the linux large page PMD busy and dirty |
34 | */ | 85 | */ |
35 | do { | 86 | do { |
36 | old_pmd = pmd_val(*pmdp); | 87 | pmd_t pmd = ACCESS_ONCE(*pmdp); |
88 | |||
89 | old_pmd = pmd_val(pmd); | ||
37 | /* If PMD busy, retry the access */ | 90 | /* If PMD busy, retry the access */ |
38 | if (unlikely(old_pmd & _PAGE_BUSY)) | 91 | if (unlikely(old_pmd & _PAGE_BUSY)) |
39 | return 0; | 92 | return 0; |
@@ -85,6 +138,15 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid, | |||
85 | vpn = hpt_vpn(ea, vsid, ssize); | 138 | vpn = hpt_vpn(ea, vsid, ssize); |
86 | hash = hpt_hash(vpn, shift, ssize); | 139 | hash = hpt_hash(vpn, shift, ssize); |
87 | hpte_slot_array = get_hpte_slot_array(pmdp); | 140 | hpte_slot_array = get_hpte_slot_array(pmdp); |
141 | if (psize == MMU_PAGE_4K) { | ||
142 | /* | ||
143 | * invalidate the old hpte entry if we have that mapped via 64K | ||
144 | * base page size. This is because demote_segment won't flush | ||
145 | * hash page table entries. | ||
146 | */ | ||
147 | if ((old_pmd & _PAGE_HASHPTE) && !(old_pmd & _PAGE_COMBO)) | ||
148 | invalidate_old_hpte(vsid, ea, pmdp, MMU_PAGE_64K, ssize); | ||
149 | } | ||
88 | 150 | ||
89 | valid = hpte_valid(hpte_slot_array, index); | 151 | valid = hpte_valid(hpte_slot_array, index); |
90 | if (valid) { | 152 | if (valid) { |
@@ -107,11 +169,8 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid, | |||
107 | * safely update this here. | 169 | * safely update this here. |
108 | */ | 170 | */ |
109 | valid = 0; | 171 | valid = 0; |
110 | new_pmd &= ~_PAGE_HPTEFLAGS; | ||
111 | hpte_slot_array[index] = 0; | 172 | hpte_slot_array[index] = 0; |
112 | } else | 173 | } |
113 | /* clear the busy bits and set the hash pte bits */ | ||
114 | new_pmd = (new_pmd & ~_PAGE_HPTEFLAGS) | _PAGE_HASHPTE; | ||
115 | } | 174 | } |
116 | 175 | ||
117 | if (!valid) { | 176 | if (!valid) { |
@@ -119,11 +178,7 @@ int __hash_page_thp(unsigned long ea, unsigned long access, unsigned long vsid, | |||
119 | 178 | ||
120 | /* insert new entry */ | 179 | /* insert new entry */ |
121 | pa = pmd_pfn(__pmd(old_pmd)) << PAGE_SHIFT; | 180 | pa = pmd_pfn(__pmd(old_pmd)) << PAGE_SHIFT; |
122 | repeat: | 181 | new_pmd |= _PAGE_HASHPTE; |
123 | hpte_group = ((hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; | ||
124 | |||
125 | /* clear the busy bits and set the hash pte bits */ | ||
126 | new_pmd = (new_pmd & ~_PAGE_HPTEFLAGS) | _PAGE_HASHPTE; | ||
127 | 182 | ||
128 | /* Add in WIMG bits */ | 183 | /* Add in WIMG bits */ |
129 | rflags |= (new_pmd & (_PAGE_WRITETHRU | _PAGE_NO_CACHE | | 184 | rflags |= (new_pmd & (_PAGE_WRITETHRU | _PAGE_NO_CACHE | |
@@ -132,6 +187,8 @@ repeat: | |||
132 | * enable the memory coherence always | 187 | * enable the memory coherence always |
133 | */ | 188 | */ |
134 | rflags |= HPTE_R_M; | 189 | rflags |= HPTE_R_M; |
190 | repeat: | ||
191 | hpte_group = ((hash & htab_hash_mask) * HPTES_PER_GROUP) & ~0x7UL; | ||
135 | 192 | ||
136 | /* Insert into the hash table, primary slot */ | 193 | /* Insert into the hash table, primary slot */ |
137 | slot = ppc_md.hpte_insert(hpte_group, vpn, pa, rflags, 0, | 194 | slot = ppc_md.hpte_insert(hpte_group, vpn, pa, rflags, 0, |
@@ -172,8 +229,17 @@ repeat: | |||
172 | mark_hpte_slot_valid(hpte_slot_array, index, slot); | 229 | mark_hpte_slot_valid(hpte_slot_array, index, slot); |
173 | } | 230 | } |
174 | /* | 231 | /* |
175 | * No need to use ldarx/stdcx here | 232 | * Mark the pte with _PAGE_COMBO, if we are trying to hash it with |
233 | * base page size 4k. | ||
234 | */ | ||
235 | if (psize == MMU_PAGE_4K) | ||
236 | new_pmd |= _PAGE_COMBO; | ||
237 | /* | ||
238 | * The hpte valid is stored in the pgtable whose address is in the | ||
239 | * second half of the PMD. Order this against clearing of the busy bit in | ||
240 | * huge pmd. | ||
176 | */ | 241 | */ |
242 | smp_wmb(); | ||
177 | *pmdp = __pmd(new_pmd & ~_PAGE_BUSY); | 243 | *pmdp = __pmd(new_pmd & ~_PAGE_BUSY); |
178 | return 0; | 244 | return 0; |
179 | } | 245 | } |
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index e3734edffa69..253b4b971c8a 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c | |||
@@ -175,9 +175,10 @@ static unsigned long __meminit vmemmap_section_start(unsigned long page) | |||
175 | static int __meminit vmemmap_populated(unsigned long start, int page_size) | 175 | static int __meminit vmemmap_populated(unsigned long start, int page_size) |
176 | { | 176 | { |
177 | unsigned long end = start + page_size; | 177 | unsigned long end = start + page_size; |
178 | start = (unsigned long)(pfn_to_page(vmemmap_section_start(start))); | ||
178 | 179 | ||
179 | for (; start < end; start += (PAGES_PER_SECTION * sizeof(struct page))) | 180 | for (; start < end; start += (PAGES_PER_SECTION * sizeof(struct page))) |
180 | if (pfn_valid(vmemmap_section_start(start))) | 181 | if (pfn_valid(page_to_pfn((struct page *)start))) |
181 | return 1; | 182 | return 1; |
182 | 183 | ||
183 | return 0; | 184 | return 0; |
@@ -212,6 +213,13 @@ static void __meminit vmemmap_create_mapping(unsigned long start, | |||
212 | for (i = 0; i < page_size; i += PAGE_SIZE) | 213 | for (i = 0; i < page_size; i += PAGE_SIZE) |
213 | BUG_ON(map_kernel_page(start + i, phys, flags)); | 214 | BUG_ON(map_kernel_page(start + i, phys, flags)); |
214 | } | 215 | } |
216 | |||
217 | #ifdef CONFIG_MEMORY_HOTPLUG | ||
218 | static void vmemmap_remove_mapping(unsigned long start, | ||
219 | unsigned long page_size) | ||
220 | { | ||
221 | } | ||
222 | #endif | ||
215 | #else /* CONFIG_PPC_BOOK3E */ | 223 | #else /* CONFIG_PPC_BOOK3E */ |
216 | static void __meminit vmemmap_create_mapping(unsigned long start, | 224 | static void __meminit vmemmap_create_mapping(unsigned long start, |
217 | unsigned long page_size, | 225 | unsigned long page_size, |
@@ -223,17 +231,42 @@ static void __meminit vmemmap_create_mapping(unsigned long start, | |||
223 | mmu_kernel_ssize); | 231 | mmu_kernel_ssize); |
224 | BUG_ON(mapped < 0); | 232 | BUG_ON(mapped < 0); |
225 | } | 233 | } |
234 | |||
235 | #ifdef CONFIG_MEMORY_HOTPLUG | ||
236 | extern int htab_remove_mapping(unsigned long vstart, unsigned long vend, | ||
237 | int psize, int ssize); | ||
238 | |||
239 | static void vmemmap_remove_mapping(unsigned long start, | ||
240 | unsigned long page_size) | ||
241 | { | ||
242 | int mapped = htab_remove_mapping(start, start + page_size, | ||
243 | mmu_vmemmap_psize, | ||
244 | mmu_kernel_ssize); | ||
245 | BUG_ON(mapped < 0); | ||
246 | } | ||
247 | #endif | ||
248 | |||
226 | #endif /* CONFIG_PPC_BOOK3E */ | 249 | #endif /* CONFIG_PPC_BOOK3E */ |
227 | 250 | ||
228 | struct vmemmap_backing *vmemmap_list; | 251 | struct vmemmap_backing *vmemmap_list; |
252 | static struct vmemmap_backing *next; | ||
253 | static int num_left; | ||
254 | static int num_freed; | ||
229 | 255 | ||
230 | static __meminit struct vmemmap_backing * vmemmap_list_alloc(int node) | 256 | static __meminit struct vmemmap_backing * vmemmap_list_alloc(int node) |
231 | { | 257 | { |
232 | static struct vmemmap_backing *next; | 258 | struct vmemmap_backing *vmem_back; |
233 | static int num_left; | 259 | /* get from freed entries first */ |
260 | if (num_freed) { | ||
261 | num_freed--; | ||
262 | vmem_back = next; | ||
263 | next = next->list; | ||
264 | |||
265 | return vmem_back; | ||
266 | } | ||
234 | 267 | ||
235 | /* allocate a page when required and hand out chunks */ | 268 | /* allocate a page when required and hand out chunks */ |
236 | if (!next || !num_left) { | 269 | if (!num_left) { |
237 | next = vmemmap_alloc_block(PAGE_SIZE, node); | 270 | next = vmemmap_alloc_block(PAGE_SIZE, node); |
238 | if (unlikely(!next)) { | 271 | if (unlikely(!next)) { |
239 | WARN_ON(1); | 272 | WARN_ON(1); |
@@ -296,10 +329,85 @@ int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node) | |||
296 | return 0; | 329 | return 0; |
297 | } | 330 | } |
298 | 331 | ||
299 | void vmemmap_free(unsigned long start, unsigned long end) | 332 | #ifdef CONFIG_MEMORY_HOTPLUG |
333 | static unsigned long vmemmap_list_free(unsigned long start) | ||
300 | { | 334 | { |
335 | struct vmemmap_backing *vmem_back, *vmem_back_prev; | ||
336 | |||
337 | vmem_back_prev = vmem_back = vmemmap_list; | ||
338 | |||
339 | /* look for it with prev pointer recorded */ | ||
340 | for (; vmem_back; vmem_back = vmem_back->list) { | ||
341 | if (vmem_back->virt_addr == start) | ||
342 | break; | ||
343 | vmem_back_prev = vmem_back; | ||
344 | } | ||
345 | |||
346 | if (unlikely(!vmem_back)) { | ||
347 | WARN_ON(1); | ||
348 | return 0; | ||
349 | } | ||
350 | |||
351 | /* remove it from vmemmap_list */ | ||
352 | if (vmem_back == vmemmap_list) /* remove head */ | ||
353 | vmemmap_list = vmem_back->list; | ||
354 | else | ||
355 | vmem_back_prev->list = vmem_back->list; | ||
356 | |||
357 | /* next point to this freed entry */ | ||
358 | vmem_back->list = next; | ||
359 | next = vmem_back; | ||
360 | num_freed++; | ||
361 | |||
362 | return vmem_back->phys; | ||
301 | } | 363 | } |
302 | 364 | ||
365 | void __ref vmemmap_free(unsigned long start, unsigned long end) | ||
366 | { | ||
367 | unsigned long page_size = 1 << mmu_psize_defs[mmu_vmemmap_psize].shift; | ||
368 | |||
369 | start = _ALIGN_DOWN(start, page_size); | ||
370 | |||
371 | pr_debug("vmemmap_free %lx...%lx\n", start, end); | ||
372 | |||
373 | for (; start < end; start += page_size) { | ||
374 | unsigned long addr; | ||
375 | |||
376 | /* | ||
377 | * the section has already be marked as invalid, so | ||
378 | * vmemmap_populated() true means some other sections still | ||
379 | * in this page, so skip it. | ||
380 | */ | ||
381 | if (vmemmap_populated(start, page_size)) | ||
382 | continue; | ||
383 | |||
384 | addr = vmemmap_list_free(start); | ||
385 | if (addr) { | ||
386 | struct page *page = pfn_to_page(addr >> PAGE_SHIFT); | ||
387 | |||
388 | if (PageReserved(page)) { | ||
389 | /* allocated from bootmem */ | ||
390 | if (page_size < PAGE_SIZE) { | ||
391 | /* | ||
392 | * this shouldn't happen, but if it is | ||
393 | * the case, leave the memory there | ||
394 | */ | ||
395 | WARN_ON_ONCE(1); | ||
396 | } else { | ||
397 | unsigned int nr_pages = | ||
398 | 1 << get_order(page_size); | ||
399 | while (nr_pages--) | ||
400 | free_reserved_page(page++); | ||
401 | } | ||
402 | } else | ||
403 | free_pages((unsigned long)(__va(addr)), | ||
404 | get_order(page_size)); | ||
405 | |||
406 | vmemmap_remove_mapping(start, page_size); | ||
407 | } | ||
408 | } | ||
409 | } | ||
410 | #endif | ||
303 | void register_page_bootmem_memmap(unsigned long section_nr, | 411 | void register_page_bootmem_memmap(unsigned long section_nr, |
304 | struct page *start_page, unsigned long size) | 412 | struct page *start_page, unsigned long size) |
305 | { | 413 | { |
@@ -331,16 +439,16 @@ struct page *realmode_pfn_to_page(unsigned long pfn) | |||
331 | if (pg_va < vmem_back->virt_addr) | 439 | if (pg_va < vmem_back->virt_addr) |
332 | continue; | 440 | continue; |
333 | 441 | ||
334 | /* Check that page struct is not split between real pages */ | 442 | /* After vmemmap_list entry free is possible, need check all */ |
335 | if ((pg_va + sizeof(struct page)) > | 443 | if ((pg_va + sizeof(struct page)) <= |
336 | (vmem_back->virt_addr + page_size)) | 444 | (vmem_back->virt_addr + page_size)) { |
337 | return NULL; | 445 | page = (struct page *) (vmem_back->phys + pg_va - |
338 | |||
339 | page = (struct page *) (vmem_back->phys + pg_va - | ||
340 | vmem_back->virt_addr); | 446 | vmem_back->virt_addr); |
341 | return page; | 447 | return page; |
448 | } | ||
342 | } | 449 | } |
343 | 450 | ||
451 | /* Probably that page struct is split between real pages */ | ||
344 | return NULL; | 452 | return NULL; |
345 | } | 453 | } |
346 | EXPORT_SYMBOL_GPL(realmode_pfn_to_page); | 454 | EXPORT_SYMBOL_GPL(realmode_pfn_to_page); |
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 2c8e90f5789e..e0f7a189c48e 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c | |||
@@ -128,7 +128,8 @@ int arch_add_memory(int nid, u64 start, u64 size) | |||
128 | return -EINVAL; | 128 | return -EINVAL; |
129 | 129 | ||
130 | /* this should work for most non-highmem platforms */ | 130 | /* this should work for most non-highmem platforms */ |
131 | zone = pgdata->node_zones; | 131 | zone = pgdata->node_zones + |
132 | zone_for_memory(nid, start, size, 0); | ||
132 | 133 | ||
133 | return __add_pages(nid, zone, start_pfn, nr_pages); | 134 | return __add_pages(nid, zone, start_pfn, nr_pages); |
134 | } | 135 | } |
diff --git a/arch/powerpc/mm/mmu_context_hash32.c b/arch/powerpc/mm/mmu_context_hash32.c index 78fef6726e10..aa5a7fd89461 100644 --- a/arch/powerpc/mm/mmu_context_hash32.c +++ b/arch/powerpc/mm/mmu_context_hash32.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * This file contains the routines for handling the MMU on those | 2 | * This file contains the routines for handling the MMU on those |
3 | * PowerPC implementations where the MMU substantially follows the | 3 | * PowerPC implementations where the MMU substantially follows the |
4 | * architecture specification. This includes the 6xx, 7xx, 7xxx, | 4 | * architecture specification. This includes the 6xx, 7xx, 7xxx, |
5 | * 8260, and POWER3 implementations but excludes the 8xx and 4xx. | 5 | * and 8260 implementations but excludes the 8xx and 4xx. |
6 | * -- paulus | 6 | * -- paulus |
7 | * | 7 | * |
8 | * Derived from arch/ppc/mm/init.c: | 8 | * Derived from arch/ppc/mm/init.c: |
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index 3b181b22cd46..d7737a542fd7 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c | |||
@@ -611,8 +611,8 @@ static int cpu_numa_callback(struct notifier_block *nfb, unsigned long action, | |||
611 | case CPU_UP_CANCELED: | 611 | case CPU_UP_CANCELED: |
612 | case CPU_UP_CANCELED_FROZEN: | 612 | case CPU_UP_CANCELED_FROZEN: |
613 | unmap_cpu_from_node(lcpu); | 613 | unmap_cpu_from_node(lcpu); |
614 | break; | ||
615 | ret = NOTIFY_OK; | 614 | ret = NOTIFY_OK; |
615 | break; | ||
616 | #endif | 616 | #endif |
617 | } | 617 | } |
618 | return ret; | 618 | return ret; |
@@ -1049,7 +1049,7 @@ static void __init mark_reserved_regions_for_nid(int nid) | |||
1049 | 1049 | ||
1050 | void __init do_init_bootmem(void) | 1050 | void __init do_init_bootmem(void) |
1051 | { | 1051 | { |
1052 | int nid; | 1052 | int nid, cpu; |
1053 | 1053 | ||
1054 | min_low_pfn = 0; | 1054 | min_low_pfn = 0; |
1055 | max_low_pfn = memblock_end_of_DRAM() >> PAGE_SHIFT; | 1055 | max_low_pfn = memblock_end_of_DRAM() >> PAGE_SHIFT; |
@@ -1122,8 +1122,15 @@ void __init do_init_bootmem(void) | |||
1122 | 1122 | ||
1123 | reset_numa_cpu_lookup_table(); | 1123 | reset_numa_cpu_lookup_table(); |
1124 | register_cpu_notifier(&ppc64_numa_nb); | 1124 | register_cpu_notifier(&ppc64_numa_nb); |
1125 | cpu_numa_callback(&ppc64_numa_nb, CPU_UP_PREPARE, | 1125 | /* |
1126 | (void *)(unsigned long)boot_cpuid); | 1126 | * We need the numa_cpu_lookup_table to be accurate for all CPUs, |
1127 | * even before we online them, so that we can use cpu_to_{node,mem} | ||
1128 | * early in boot, cf. smp_prepare_cpus(). | ||
1129 | */ | ||
1130 | for_each_possible_cpu(cpu) { | ||
1131 | cpu_numa_callback(&ppc64_numa_nb, CPU_UP_PREPARE, | ||
1132 | (void *)(unsigned long)cpu); | ||
1133 | } | ||
1127 | } | 1134 | } |
1128 | 1135 | ||
1129 | void __init paging_init(void) | 1136 | void __init paging_init(void) |
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c index 343a87fa78b5..cf11342bf519 100644 --- a/arch/powerpc/mm/pgtable_32.c +++ b/arch/powerpc/mm/pgtable_32.c | |||
@@ -41,7 +41,7 @@ unsigned long ioremap_base; | |||
41 | unsigned long ioremap_bot; | 41 | unsigned long ioremap_bot; |
42 | EXPORT_SYMBOL(ioremap_bot); /* aka VMALLOC_END */ | 42 | EXPORT_SYMBOL(ioremap_bot); /* aka VMALLOC_END */ |
43 | 43 | ||
44 | #if defined(CONFIG_6xx) || defined(CONFIG_POWER3) | 44 | #ifdef CONFIG_6xx |
45 | #define HAVE_BATS 1 | 45 | #define HAVE_BATS 1 |
46 | #endif | 46 | #endif |
47 | 47 | ||
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c index f6ce1f111f5b..c8d709ab489d 100644 --- a/arch/powerpc/mm/pgtable_64.c +++ b/arch/powerpc/mm/pgtable_64.c | |||
@@ -54,6 +54,9 @@ | |||
54 | 54 | ||
55 | #include "mmu_decl.h" | 55 | #include "mmu_decl.h" |
56 | 56 | ||
57 | #define CREATE_TRACE_POINTS | ||
58 | #include <trace/events/thp.h> | ||
59 | |||
57 | /* Some sanity checking */ | 60 | /* Some sanity checking */ |
58 | #if TASK_SIZE_USER64 > PGTABLE_RANGE | 61 | #if TASK_SIZE_USER64 > PGTABLE_RANGE |
59 | #error TASK_SIZE_USER64 exceeds pagetable range | 62 | #error TASK_SIZE_USER64 exceeds pagetable range |
@@ -68,7 +71,7 @@ | |||
68 | unsigned long ioremap_bot = IOREMAP_BASE; | 71 | unsigned long ioremap_bot = IOREMAP_BASE; |
69 | 72 | ||
70 | #ifdef CONFIG_PPC_MMU_NOHASH | 73 | #ifdef CONFIG_PPC_MMU_NOHASH |
71 | static void *early_alloc_pgtable(unsigned long size) | 74 | static __ref void *early_alloc_pgtable(unsigned long size) |
72 | { | 75 | { |
73 | void *pt; | 76 | void *pt; |
74 | 77 | ||
@@ -537,8 +540,9 @@ unsigned long pmd_hugepage_update(struct mm_struct *mm, unsigned long addr, | |||
537 | old = pmd_val(*pmdp); | 540 | old = pmd_val(*pmdp); |
538 | *pmdp = __pmd((old & ~clr) | set); | 541 | *pmdp = __pmd((old & ~clr) | set); |
539 | #endif | 542 | #endif |
543 | trace_hugepage_update(addr, old, clr, set); | ||
540 | if (old & _PAGE_HASHPTE) | 544 | if (old & _PAGE_HASHPTE) |
541 | hpte_do_hugepage_flush(mm, addr, pmdp); | 545 | hpte_do_hugepage_flush(mm, addr, pmdp, old); |
542 | return old; | 546 | return old; |
543 | } | 547 | } |
544 | 548 | ||
@@ -642,10 +646,11 @@ void pmdp_splitting_flush(struct vm_area_struct *vma, | |||
642 | * If we didn't had the splitting flag set, go and flush the | 646 | * If we didn't had the splitting flag set, go and flush the |
643 | * HPTE entries. | 647 | * HPTE entries. |
644 | */ | 648 | */ |
649 | trace_hugepage_splitting(address, old); | ||
645 | if (!(old & _PAGE_SPLITTING)) { | 650 | if (!(old & _PAGE_SPLITTING)) { |
646 | /* We need to flush the hpte */ | 651 | /* We need to flush the hpte */ |
647 | if (old & _PAGE_HASHPTE) | 652 | if (old & _PAGE_HASHPTE) |
648 | hpte_do_hugepage_flush(vma->vm_mm, address, pmdp); | 653 | hpte_do_hugepage_flush(vma->vm_mm, address, pmdp, old); |
649 | } | 654 | } |
650 | /* | 655 | /* |
651 | * This ensures that generic code that rely on IRQ disabling | 656 | * This ensures that generic code that rely on IRQ disabling |
@@ -709,6 +714,7 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr, | |||
709 | assert_spin_locked(&mm->page_table_lock); | 714 | assert_spin_locked(&mm->page_table_lock); |
710 | WARN_ON(!pmd_trans_huge(pmd)); | 715 | WARN_ON(!pmd_trans_huge(pmd)); |
711 | #endif | 716 | #endif |
717 | trace_hugepage_set_pmd(addr, pmd); | ||
712 | return set_pte_at(mm, addr, pmdp_ptep(pmdp), pmd_pte(pmd)); | 718 | return set_pte_at(mm, addr, pmdp_ptep(pmdp), pmd_pte(pmd)); |
713 | } | 719 | } |
714 | 720 | ||
@@ -723,7 +729,7 @@ void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address, | |||
723 | * neesd to be flushed. | 729 | * neesd to be flushed. |
724 | */ | 730 | */ |
725 | void hpte_do_hugepage_flush(struct mm_struct *mm, unsigned long addr, | 731 | void hpte_do_hugepage_flush(struct mm_struct *mm, unsigned long addr, |
726 | pmd_t *pmdp) | 732 | pmd_t *pmdp, unsigned long old_pmd) |
727 | { | 733 | { |
728 | int ssize, i; | 734 | int ssize, i; |
729 | unsigned long s_addr; | 735 | unsigned long s_addr; |
@@ -745,12 +751,29 @@ void hpte_do_hugepage_flush(struct mm_struct *mm, unsigned long addr, | |||
745 | if (!hpte_slot_array) | 751 | if (!hpte_slot_array) |
746 | return; | 752 | return; |
747 | 753 | ||
748 | /* get the base page size */ | 754 | /* get the base page size,vsid and segment size */ |
755 | #ifdef CONFIG_DEBUG_VM | ||
749 | psize = get_slice_psize(mm, s_addr); | 756 | psize = get_slice_psize(mm, s_addr); |
757 | BUG_ON(psize == MMU_PAGE_16M); | ||
758 | #endif | ||
759 | if (old_pmd & _PAGE_COMBO) | ||
760 | psize = MMU_PAGE_4K; | ||
761 | else | ||
762 | psize = MMU_PAGE_64K; | ||
763 | |||
764 | if (!is_kernel_addr(s_addr)) { | ||
765 | ssize = user_segment_size(s_addr); | ||
766 | vsid = get_vsid(mm->context.id, s_addr, ssize); | ||
767 | WARN_ON(vsid == 0); | ||
768 | } else { | ||
769 | vsid = get_kernel_vsid(s_addr, mmu_kernel_ssize); | ||
770 | ssize = mmu_kernel_ssize; | ||
771 | } | ||
750 | 772 | ||
751 | if (ppc_md.hugepage_invalidate) | 773 | if (ppc_md.hugepage_invalidate) |
752 | return ppc_md.hugepage_invalidate(mm, hpte_slot_array, | 774 | return ppc_md.hugepage_invalidate(vsid, s_addr, |
753 | s_addr, psize); | 775 | hpte_slot_array, |
776 | psize, ssize); | ||
754 | /* | 777 | /* |
755 | * No bluk hpte removal support, invalidate each entry | 778 | * No bluk hpte removal support, invalidate each entry |
756 | */ | 779 | */ |
@@ -768,15 +791,6 @@ void hpte_do_hugepage_flush(struct mm_struct *mm, unsigned long addr, | |||
768 | 791 | ||
769 | /* get the vpn */ | 792 | /* get the vpn */ |
770 | addr = s_addr + (i * (1ul << shift)); | 793 | addr = s_addr + (i * (1ul << shift)); |
771 | if (!is_kernel_addr(addr)) { | ||
772 | ssize = user_segment_size(addr); | ||
773 | vsid = get_vsid(mm->context.id, addr, ssize); | ||
774 | WARN_ON(vsid == 0); | ||
775 | } else { | ||
776 | vsid = get_kernel_vsid(addr, mmu_kernel_ssize); | ||
777 | ssize = mmu_kernel_ssize; | ||
778 | } | ||
779 | |||
780 | vpn = hpt_vpn(addr, vsid, ssize); | 794 | vpn = hpt_vpn(addr, vsid, ssize); |
781 | hash = hpt_hash(vpn, shift, ssize); | 795 | hash = hpt_hash(vpn, shift, ssize); |
782 | if (hidx & _PTEIDX_SECONDARY) | 796 | if (hidx & _PTEIDX_SECONDARY) |
diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c index 11571e118831..5029dc19b517 100644 --- a/arch/powerpc/mm/ppc_mmu_32.c +++ b/arch/powerpc/mm/ppc_mmu_32.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * This file contains the routines for handling the MMU on those | 2 | * This file contains the routines for handling the MMU on those |
3 | * PowerPC implementations where the MMU substantially follows the | 3 | * PowerPC implementations where the MMU substantially follows the |
4 | * architecture specification. This includes the 6xx, 7xx, 7xxx, | 4 | * architecture specification. This includes the 6xx, 7xx, 7xxx, |
5 | * 8260, and POWER3 implementations but excludes the 8xx and 4xx. | 5 | * and 8260 implementations but excludes the 8xx and 4xx. |
6 | * -- paulus | 6 | * -- paulus |
7 | * | 7 | * |
8 | * Derived from arch/ppc/mm/init.c: | 8 | * Derived from arch/ppc/mm/init.c: |
diff --git a/arch/powerpc/mm/stab.c b/arch/powerpc/mm/stab.c deleted file mode 100644 index 3f8efa6f2997..000000000000 --- a/arch/powerpc/mm/stab.c +++ /dev/null | |||
@@ -1,286 +0,0 @@ | |||
1 | /* | ||
2 | * PowerPC64 Segment Translation Support. | ||
3 | * | ||
4 | * Dave Engebretsen and Mike Corrigan {engebret|mikejc}@us.ibm.com | ||
5 | * Copyright (c) 2001 Dave Engebretsen | ||
6 | * | ||
7 | * Copyright (C) 2002 Anton Blanchard <anton@au.ibm.com>, IBM | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or | ||
10 | * modify it under the terms of the GNU General Public License | ||
11 | * as published by the Free Software Foundation; either version | ||
12 | * 2 of the License, or (at your option) any later version. | ||
13 | */ | ||
14 | |||
15 | #include <linux/memblock.h> | ||
16 | |||
17 | #include <asm/pgtable.h> | ||
18 | #include <asm/mmu.h> | ||
19 | #include <asm/mmu_context.h> | ||
20 | #include <asm/paca.h> | ||
21 | #include <asm/cputable.h> | ||
22 | #include <asm/prom.h> | ||
23 | |||
24 | struct stab_entry { | ||
25 | unsigned long esid_data; | ||
26 | unsigned long vsid_data; | ||
27 | }; | ||
28 | |||
29 | #define NR_STAB_CACHE_ENTRIES 8 | ||
30 | static DEFINE_PER_CPU(long, stab_cache_ptr); | ||
31 | static DEFINE_PER_CPU(long [NR_STAB_CACHE_ENTRIES], stab_cache); | ||
32 | |||
33 | /* | ||
34 | * Create a segment table entry for the given esid/vsid pair. | ||
35 | */ | ||
36 | static int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid) | ||
37 | { | ||
38 | unsigned long esid_data, vsid_data; | ||
39 | unsigned long entry, group, old_esid, castout_entry, i; | ||
40 | unsigned int global_entry; | ||
41 | struct stab_entry *ste, *castout_ste; | ||
42 | unsigned long kernel_segment = (esid << SID_SHIFT) >= PAGE_OFFSET; | ||
43 | |||
44 | vsid_data = vsid << STE_VSID_SHIFT; | ||
45 | esid_data = esid << SID_SHIFT | STE_ESID_KP | STE_ESID_V; | ||
46 | if (! kernel_segment) | ||
47 | esid_data |= STE_ESID_KS; | ||
48 | |||
49 | /* Search the primary group first. */ | ||
50 | global_entry = (esid & 0x1f) << 3; | ||
51 | ste = (struct stab_entry *)(stab | ((esid & 0x1f) << 7)); | ||
52 | |||
53 | /* Find an empty entry, if one exists. */ | ||
54 | for (group = 0; group < 2; group++) { | ||
55 | for (entry = 0; entry < 8; entry++, ste++) { | ||
56 | if (!(ste->esid_data & STE_ESID_V)) { | ||
57 | ste->vsid_data = vsid_data; | ||
58 | eieio(); | ||
59 | ste->esid_data = esid_data; | ||
60 | return (global_entry | entry); | ||
61 | } | ||
62 | } | ||
63 | /* Now search the secondary group. */ | ||
64 | global_entry = ((~esid) & 0x1f) << 3; | ||
65 | ste = (struct stab_entry *)(stab | (((~esid) & 0x1f) << 7)); | ||
66 | } | ||
67 | |||
68 | /* | ||
69 | * Could not find empty entry, pick one with a round robin selection. | ||
70 | * Search all entries in the two groups. | ||
71 | */ | ||
72 | castout_entry = get_paca()->stab_rr; | ||
73 | for (i = 0; i < 16; i++) { | ||
74 | if (castout_entry < 8) { | ||
75 | global_entry = (esid & 0x1f) << 3; | ||
76 | ste = (struct stab_entry *)(stab | ((esid & 0x1f) << 7)); | ||
77 | castout_ste = ste + castout_entry; | ||
78 | } else { | ||
79 | global_entry = ((~esid) & 0x1f) << 3; | ||
80 | ste = (struct stab_entry *)(stab | (((~esid) & 0x1f) << 7)); | ||
81 | castout_ste = ste + (castout_entry - 8); | ||
82 | } | ||
83 | |||
84 | /* Dont cast out the first kernel segment */ | ||
85 | if ((castout_ste->esid_data & ESID_MASK) != PAGE_OFFSET) | ||
86 | break; | ||
87 | |||
88 | castout_entry = (castout_entry + 1) & 0xf; | ||
89 | } | ||
90 | |||
91 | get_paca()->stab_rr = (castout_entry + 1) & 0xf; | ||
92 | |||
93 | /* Modify the old entry to the new value. */ | ||
94 | |||
95 | /* Force previous translations to complete. DRENG */ | ||
96 | asm volatile("isync" : : : "memory"); | ||
97 | |||
98 | old_esid = castout_ste->esid_data >> SID_SHIFT; | ||
99 | castout_ste->esid_data = 0; /* Invalidate old entry */ | ||
100 | |||
101 | asm volatile("sync" : : : "memory"); /* Order update */ | ||
102 | |||
103 | castout_ste->vsid_data = vsid_data; | ||
104 | eieio(); /* Order update */ | ||
105 | castout_ste->esid_data = esid_data; | ||
106 | |||
107 | asm volatile("slbie %0" : : "r" (old_esid << SID_SHIFT)); | ||
108 | /* Ensure completion of slbie */ | ||
109 | asm volatile("sync" : : : "memory"); | ||
110 | |||
111 | return (global_entry | (castout_entry & 0x7)); | ||
112 | } | ||
113 | |||
114 | /* | ||
115 | * Allocate a segment table entry for the given ea and mm | ||
116 | */ | ||
117 | static int __ste_allocate(unsigned long ea, struct mm_struct *mm) | ||
118 | { | ||
119 | unsigned long vsid; | ||
120 | unsigned char stab_entry; | ||
121 | unsigned long offset; | ||
122 | |||
123 | /* Kernel or user address? */ | ||
124 | if (is_kernel_addr(ea)) { | ||
125 | vsid = get_kernel_vsid(ea, MMU_SEGSIZE_256M); | ||
126 | } else { | ||
127 | if ((ea >= TASK_SIZE_USER64) || (! mm)) | ||
128 | return 1; | ||
129 | |||
130 | vsid = get_vsid(mm->context.id, ea, MMU_SEGSIZE_256M); | ||
131 | } | ||
132 | |||
133 | stab_entry = make_ste(get_paca()->stab_addr, GET_ESID(ea), vsid); | ||
134 | |||
135 | if (!is_kernel_addr(ea)) { | ||
136 | offset = __get_cpu_var(stab_cache_ptr); | ||
137 | if (offset < NR_STAB_CACHE_ENTRIES) | ||
138 | __get_cpu_var(stab_cache[offset++]) = stab_entry; | ||
139 | else | ||
140 | offset = NR_STAB_CACHE_ENTRIES+1; | ||
141 | __get_cpu_var(stab_cache_ptr) = offset; | ||
142 | |||
143 | /* Order update */ | ||
144 | asm volatile("sync":::"memory"); | ||
145 | } | ||
146 | |||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | int ste_allocate(unsigned long ea) | ||
151 | { | ||
152 | return __ste_allocate(ea, current->mm); | ||
153 | } | ||
154 | |||
155 | /* | ||
156 | * Do the segment table work for a context switch: flush all user | ||
157 | * entries from the table, then preload some probably useful entries | ||
158 | * for the new task | ||
159 | */ | ||
160 | void switch_stab(struct task_struct *tsk, struct mm_struct *mm) | ||
161 | { | ||
162 | struct stab_entry *stab = (struct stab_entry *) get_paca()->stab_addr; | ||
163 | struct stab_entry *ste; | ||
164 | unsigned long offset; | ||
165 | unsigned long pc = KSTK_EIP(tsk); | ||
166 | unsigned long stack = KSTK_ESP(tsk); | ||
167 | unsigned long unmapped_base; | ||
168 | |||
169 | /* Force previous translations to complete. DRENG */ | ||
170 | asm volatile("isync" : : : "memory"); | ||
171 | |||
172 | /* | ||
173 | * We need interrupts hard-disabled here, not just soft-disabled, | ||
174 | * so that a PMU interrupt can't occur, which might try to access | ||
175 | * user memory (to get a stack trace) and possible cause an STAB miss | ||
176 | * which would update the stab_cache/stab_cache_ptr per-cpu variables. | ||
177 | */ | ||
178 | hard_irq_disable(); | ||
179 | |||
180 | offset = __get_cpu_var(stab_cache_ptr); | ||
181 | if (offset <= NR_STAB_CACHE_ENTRIES) { | ||
182 | int i; | ||
183 | |||
184 | for (i = 0; i < offset; i++) { | ||
185 | ste = stab + __get_cpu_var(stab_cache[i]); | ||
186 | ste->esid_data = 0; /* invalidate entry */ | ||
187 | } | ||
188 | } else { | ||
189 | unsigned long entry; | ||
190 | |||
191 | /* Invalidate all entries. */ | ||
192 | ste = stab; | ||
193 | |||
194 | /* Never flush the first entry. */ | ||
195 | ste += 1; | ||
196 | for (entry = 1; | ||
197 | entry < (HW_PAGE_SIZE / sizeof(struct stab_entry)); | ||
198 | entry++, ste++) { | ||
199 | unsigned long ea; | ||
200 | ea = ste->esid_data & ESID_MASK; | ||
201 | if (!is_kernel_addr(ea)) { | ||
202 | ste->esid_data = 0; | ||
203 | } | ||
204 | } | ||
205 | } | ||
206 | |||
207 | asm volatile("sync; slbia; sync":::"memory"); | ||
208 | |||
209 | __get_cpu_var(stab_cache_ptr) = 0; | ||
210 | |||
211 | /* Now preload some entries for the new task */ | ||
212 | if (test_tsk_thread_flag(tsk, TIF_32BIT)) | ||
213 | unmapped_base = TASK_UNMAPPED_BASE_USER32; | ||
214 | else | ||
215 | unmapped_base = TASK_UNMAPPED_BASE_USER64; | ||
216 | |||
217 | __ste_allocate(pc, mm); | ||
218 | |||
219 | if (GET_ESID(pc) == GET_ESID(stack)) | ||
220 | return; | ||
221 | |||
222 | __ste_allocate(stack, mm); | ||
223 | |||
224 | if ((GET_ESID(pc) == GET_ESID(unmapped_base)) | ||
225 | || (GET_ESID(stack) == GET_ESID(unmapped_base))) | ||
226 | return; | ||
227 | |||
228 | __ste_allocate(unmapped_base, mm); | ||
229 | |||
230 | /* Order update */ | ||
231 | asm volatile("sync" : : : "memory"); | ||
232 | } | ||
233 | |||
234 | /* | ||
235 | * Allocate segment tables for secondary CPUs. These must all go in | ||
236 | * the first (bolted) segment, so that do_stab_bolted won't get a | ||
237 | * recursive segment miss on the segment table itself. | ||
238 | */ | ||
239 | void __init stabs_alloc(void) | ||
240 | { | ||
241 | int cpu; | ||
242 | |||
243 | if (mmu_has_feature(MMU_FTR_SLB)) | ||
244 | return; | ||
245 | |||
246 | for_each_possible_cpu(cpu) { | ||
247 | unsigned long newstab; | ||
248 | |||
249 | if (cpu == 0) | ||
250 | continue; /* stab for CPU 0 is statically allocated */ | ||
251 | |||
252 | newstab = memblock_alloc_base(HW_PAGE_SIZE, HW_PAGE_SIZE, | ||
253 | 1<<SID_SHIFT); | ||
254 | newstab = (unsigned long)__va(newstab); | ||
255 | |||
256 | memset((void *)newstab, 0, HW_PAGE_SIZE); | ||
257 | |||
258 | paca[cpu].stab_addr = newstab; | ||
259 | paca[cpu].stab_real = __pa(newstab); | ||
260 | printk(KERN_INFO "Segment table for CPU %d at 0x%llx " | ||
261 | "virtual, 0x%llx absolute\n", | ||
262 | cpu, paca[cpu].stab_addr, paca[cpu].stab_real); | ||
263 | } | ||
264 | } | ||
265 | |||
266 | /* | ||
267 | * Build an entry for the base kernel segment and put it into | ||
268 | * the segment table or SLB. All other segment table or SLB | ||
269 | * entries are faulted in. | ||
270 | */ | ||
271 | void stab_initialize(unsigned long stab) | ||
272 | { | ||
273 | unsigned long vsid = get_kernel_vsid(PAGE_OFFSET, MMU_SEGSIZE_256M); | ||
274 | unsigned long stabreal; | ||
275 | |||
276 | asm volatile("isync; slbia; isync":::"memory"); | ||
277 | make_ste(stab, GET_ESID(PAGE_OFFSET), vsid); | ||
278 | |||
279 | /* Order update */ | ||
280 | asm volatile("sync":::"memory"); | ||
281 | |||
282 | /* Set ASR */ | ||
283 | stabreal = get_paca()->stab_real | 0x1ul; | ||
284 | |||
285 | mtspr(SPRN_ASR, stabreal); | ||
286 | } | ||
diff --git a/arch/powerpc/mm/tlb_hash64.c b/arch/powerpc/mm/tlb_hash64.c index c99f6510a0b2..d2a94b85dbc2 100644 --- a/arch/powerpc/mm/tlb_hash64.c +++ b/arch/powerpc/mm/tlb_hash64.c | |||
@@ -30,6 +30,8 @@ | |||
30 | #include <asm/tlb.h> | 30 | #include <asm/tlb.h> |
31 | #include <asm/bug.h> | 31 | #include <asm/bug.h> |
32 | 32 | ||
33 | #include <trace/events/thp.h> | ||
34 | |||
33 | DEFINE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch); | 35 | DEFINE_PER_CPU(struct ppc64_tlb_batch, ppc64_tlb_batch); |
34 | 36 | ||
35 | /* | 37 | /* |
@@ -213,10 +215,12 @@ void __flush_hash_table_range(struct mm_struct *mm, unsigned long start, | |||
213 | if (ptep == NULL) | 215 | if (ptep == NULL) |
214 | continue; | 216 | continue; |
215 | pte = pte_val(*ptep); | 217 | pte = pte_val(*ptep); |
218 | if (hugepage_shift) | ||
219 | trace_hugepage_invalidate(start, pte_val(pte)); | ||
216 | if (!(pte & _PAGE_HASHPTE)) | 220 | if (!(pte & _PAGE_HASHPTE)) |
217 | continue; | 221 | continue; |
218 | if (unlikely(hugepage_shift && pmd_trans_huge(*(pmd_t *)pte))) | 222 | if (unlikely(hugepage_shift && pmd_trans_huge(*(pmd_t *)pte))) |
219 | hpte_do_hugepage_flush(mm, start, (pmd_t *)pte); | 223 | hpte_do_hugepage_flush(mm, start, (pmd_t *)ptep, pte); |
220 | else | 224 | else |
221 | hpte_need_flush(mm, start, ptep, pte, 0); | 225 | hpte_need_flush(mm, start, ptep, pte, 0); |
222 | } | 226 | } |
diff --git a/arch/powerpc/mm/tlb_low_64e.S b/arch/powerpc/mm/tlb_low_64e.S index 356e8b41fb09..89bf95bd63b1 100644 --- a/arch/powerpc/mm/tlb_low_64e.S +++ b/arch/powerpc/mm/tlb_low_64e.S | |||
@@ -296,9 +296,12 @@ itlb_miss_fault_bolted: | |||
296 | * r14 = page table base | 296 | * r14 = page table base |
297 | * r13 = PACA | 297 | * r13 = PACA |
298 | * r11 = tlb_per_core ptr | 298 | * r11 = tlb_per_core ptr |
299 | * r10 = cpu number | 299 | * r10 = crap (free to use) |
300 | */ | 300 | */ |
301 | tlb_miss_common_e6500: | 301 | tlb_miss_common_e6500: |
302 | crmove cr2*4+2,cr0*4+2 /* cr2.eq != 0 if kernel address */ | ||
303 | |||
304 | BEGIN_FTR_SECTION /* CPU_FTR_SMT */ | ||
302 | /* | 305 | /* |
303 | * Search if we already have an indirect entry for that virtual | 306 | * Search if we already have an indirect entry for that virtual |
304 | * address, and if we do, bail out. | 307 | * address, and if we do, bail out. |
@@ -309,6 +312,7 @@ tlb_miss_common_e6500: | |||
309 | lhz r10,PACAPACAINDEX(r13) | 312 | lhz r10,PACAPACAINDEX(r13) |
310 | cmpdi r15,0 | 313 | cmpdi r15,0 |
311 | cmpdi cr1,r15,1 /* set cr1.eq = 0 for non-recursive */ | 314 | cmpdi cr1,r15,1 /* set cr1.eq = 0 for non-recursive */ |
315 | addi r10,r10,1 | ||
312 | bne 2f | 316 | bne 2f |
313 | stbcx. r10,0,r11 | 317 | stbcx. r10,0,r11 |
314 | bne 1b | 318 | bne 1b |
@@ -322,18 +326,62 @@ tlb_miss_common_e6500: | |||
322 | b 1b | 326 | b 1b |
323 | .previous | 327 | .previous |
324 | 328 | ||
329 | /* | ||
330 | * Erratum A-008139 says that we can't use tlbwe to change | ||
331 | * an indirect entry in any way (including replacing or | ||
332 | * invalidating) if the other thread could be in the process | ||
333 | * of a lookup. The workaround is to invalidate the entry | ||
334 | * with tlbilx before overwriting. | ||
335 | */ | ||
336 | |||
337 | lbz r15,TCD_ESEL_NEXT(r11) | ||
338 | rlwinm r10,r15,16,0xff0000 | ||
339 | oris r10,r10,MAS0_TLBSEL(1)@h | ||
340 | mtspr SPRN_MAS0,r10 | ||
341 | isync | ||
342 | tlbre | ||
343 | mfspr r15,SPRN_MAS1 | ||
344 | andis. r15,r15,MAS1_VALID@h | ||
345 | beq 5f | ||
346 | |||
347 | BEGIN_FTR_SECTION_NESTED(532) | ||
348 | mfspr r10,SPRN_MAS8 | ||
349 | rlwinm r10,r10,0,0x80000fff /* tgs,tlpid -> sgs,slpid */ | ||
350 | mtspr SPRN_MAS5,r10 | ||
351 | END_FTR_SECTION_NESTED(CPU_FTR_EMB_HV,CPU_FTR_EMB_HV,532) | ||
352 | |||
353 | mfspr r10,SPRN_MAS1 | ||
354 | rlwinm r15,r10,0,0x3fff0000 /* tid -> spid */ | ||
355 | rlwimi r15,r10,20,0x00000003 /* ind,ts -> sind,sas */ | ||
356 | mfspr r10,SPRN_MAS6 | ||
357 | mtspr SPRN_MAS6,r15 | ||
358 | |||
325 | mfspr r15,SPRN_MAS2 | 359 | mfspr r15,SPRN_MAS2 |
360 | isync | ||
361 | tlbilxva 0,r15 | ||
362 | isync | ||
363 | |||
364 | mtspr SPRN_MAS6,r10 | ||
365 | |||
366 | 5: | ||
367 | BEGIN_FTR_SECTION_NESTED(532) | ||
368 | li r10,0 | ||
369 | mtspr SPRN_MAS8,r10 | ||
370 | mtspr SPRN_MAS5,r10 | ||
371 | END_FTR_SECTION_NESTED(CPU_FTR_EMB_HV,CPU_FTR_EMB_HV,532) | ||
326 | 372 | ||
327 | tlbsx 0,r16 | 373 | tlbsx 0,r16 |
328 | mfspr r10,SPRN_MAS1 | 374 | mfspr r10,SPRN_MAS1 |
329 | andis. r10,r10,MAS1_VALID@h | 375 | andis. r15,r10,MAS1_VALID@h |
330 | bne tlb_miss_done_e6500 | 376 | bne tlb_miss_done_e6500 |
331 | 377 | FTR_SECTION_ELSE | |
332 | /* Undo MAS-damage from the tlbsx */ | ||
333 | mfspr r10,SPRN_MAS1 | 378 | mfspr r10,SPRN_MAS1 |
379 | ALT_FTR_SECTION_END_IFSET(CPU_FTR_SMT) | ||
380 | |||
334 | oris r10,r10,MAS1_VALID@h | 381 | oris r10,r10,MAS1_VALID@h |
335 | mtspr SPRN_MAS1,r10 | 382 | beq cr2,4f |
336 | mtspr SPRN_MAS2,r15 | 383 | rlwinm r10,r10,0,16,1 /* Clear TID */ |
384 | 4: mtspr SPRN_MAS1,r10 | ||
337 | 385 | ||
338 | /* Now, we need to walk the page tables. First check if we are in | 386 | /* Now, we need to walk the page tables. First check if we are in |
339 | * range. | 387 | * range. |
@@ -394,11 +442,13 @@ tlb_miss_common_e6500: | |||
394 | 442 | ||
395 | tlb_miss_done_e6500: | 443 | tlb_miss_done_e6500: |
396 | .macro tlb_unlock_e6500 | 444 | .macro tlb_unlock_e6500 |
445 | BEGIN_FTR_SECTION | ||
397 | beq cr1,1f /* no unlock if lock was recursively grabbed */ | 446 | beq cr1,1f /* no unlock if lock was recursively grabbed */ |
398 | li r15,0 | 447 | li r15,0 |
399 | isync | 448 | isync |
400 | stb r15,0(r11) | 449 | stb r15,0(r11) |
401 | 1: | 450 | 1: |
451 | END_FTR_SECTION_IFSET(CPU_FTR_SMT) | ||
402 | .endm | 452 | .endm |
403 | 453 | ||
404 | tlb_unlock_e6500 | 454 | tlb_unlock_e6500 |
@@ -407,12 +457,9 @@ tlb_miss_done_e6500: | |||
407 | rfi | 457 | rfi |
408 | 458 | ||
409 | tlb_miss_kernel_e6500: | 459 | tlb_miss_kernel_e6500: |
410 | mfspr r10,SPRN_MAS1 | ||
411 | ld r14,PACA_KERNELPGD(r13) | 460 | ld r14,PACA_KERNELPGD(r13) |
412 | cmpldi cr0,r15,8 /* Check for vmalloc region */ | 461 | cmpldi cr1,r15,8 /* Check for vmalloc region */ |
413 | rlwinm r10,r10,0,16,1 /* Clear TID */ | 462 | beq+ cr1,tlb_miss_common_e6500 |
414 | mtspr SPRN_MAS1,r10 | ||
415 | beq+ tlb_miss_common_e6500 | ||
416 | 463 | ||
417 | tlb_miss_fault_e6500: | 464 | tlb_miss_fault_e6500: |
418 | tlb_unlock_e6500 | 465 | tlb_unlock_e6500 |
diff --git a/arch/powerpc/mm/tlb_nohash.c b/arch/powerpc/mm/tlb_nohash.c index 92cb18d52ea8..f38ea4df6a85 100644 --- a/arch/powerpc/mm/tlb_nohash.c +++ b/arch/powerpc/mm/tlb_nohash.c | |||
@@ -581,42 +581,10 @@ static void setup_mmu_htw(void) | |||
581 | /* | 581 | /* |
582 | * Early initialization of the MMU TLB code | 582 | * Early initialization of the MMU TLB code |
583 | */ | 583 | */ |
584 | static void __early_init_mmu(int boot_cpu) | 584 | static void early_init_this_mmu(void) |
585 | { | 585 | { |
586 | unsigned int mas4; | 586 | unsigned int mas4; |
587 | 587 | ||
588 | /* XXX This will have to be decided at runtime, but right | ||
589 | * now our boot and TLB miss code hard wires it. Ideally | ||
590 | * we should find out a suitable page size and patch the | ||
591 | * TLB miss code (either that or use the PACA to store | ||
592 | * the value we want) | ||
593 | */ | ||
594 | mmu_linear_psize = MMU_PAGE_1G; | ||
595 | |||
596 | /* XXX This should be decided at runtime based on supported | ||
597 | * page sizes in the TLB, but for now let's assume 16M is | ||
598 | * always there and a good fit (which it probably is) | ||
599 | * | ||
600 | * Freescale booke only supports 4K pages in TLB0, so use that. | ||
601 | */ | ||
602 | if (mmu_has_feature(MMU_FTR_TYPE_FSL_E)) | ||
603 | mmu_vmemmap_psize = MMU_PAGE_4K; | ||
604 | else | ||
605 | mmu_vmemmap_psize = MMU_PAGE_16M; | ||
606 | |||
607 | /* XXX This code only checks for TLB 0 capabilities and doesn't | ||
608 | * check what page size combos are supported by the HW. It | ||
609 | * also doesn't handle the case where a separate array holds | ||
610 | * the IND entries from the array loaded by the PT. | ||
611 | */ | ||
612 | if (boot_cpu) { | ||
613 | /* Look for supported page sizes */ | ||
614 | setup_page_sizes(); | ||
615 | |||
616 | /* Look for HW tablewalk support */ | ||
617 | setup_mmu_htw(); | ||
618 | } | ||
619 | |||
620 | /* Set MAS4 based on page table setting */ | 588 | /* Set MAS4 based on page table setting */ |
621 | 589 | ||
622 | mas4 = 0x4 << MAS4_WIMGED_SHIFT; | 590 | mas4 = 0x4 << MAS4_WIMGED_SHIFT; |
@@ -650,11 +618,6 @@ static void __early_init_mmu(int boot_cpu) | |||
650 | } | 618 | } |
651 | mtspr(SPRN_MAS4, mas4); | 619 | mtspr(SPRN_MAS4, mas4); |
652 | 620 | ||
653 | /* Set the global containing the top of the linear mapping | ||
654 | * for use by the TLB miss code | ||
655 | */ | ||
656 | linear_map_top = memblock_end_of_DRAM(); | ||
657 | |||
658 | #ifdef CONFIG_PPC_FSL_BOOK3E | 621 | #ifdef CONFIG_PPC_FSL_BOOK3E |
659 | if (mmu_has_feature(MMU_FTR_TYPE_FSL_E)) { | 622 | if (mmu_has_feature(MMU_FTR_TYPE_FSL_E)) { |
660 | unsigned int num_cams; | 623 | unsigned int num_cams; |
@@ -662,10 +625,49 @@ static void __early_init_mmu(int boot_cpu) | |||
662 | /* use a quarter of the TLBCAM for bolted linear map */ | 625 | /* use a quarter of the TLBCAM for bolted linear map */ |
663 | num_cams = (mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY) / 4; | 626 | num_cams = (mfspr(SPRN_TLB1CFG) & TLBnCFG_N_ENTRY) / 4; |
664 | linear_map_top = map_mem_in_cams(linear_map_top, num_cams); | 627 | linear_map_top = map_mem_in_cams(linear_map_top, num_cams); |
628 | } | ||
629 | #endif | ||
665 | 630 | ||
666 | /* limit memory so we dont have linear faults */ | 631 | /* A sync won't hurt us after mucking around with |
667 | memblock_enforce_memory_limit(linear_map_top); | 632 | * the MMU configuration |
633 | */ | ||
634 | mb(); | ||
635 | } | ||
668 | 636 | ||
637 | static void __init early_init_mmu_global(void) | ||
638 | { | ||
639 | /* XXX This will have to be decided at runtime, but right | ||
640 | * now our boot and TLB miss code hard wires it. Ideally | ||
641 | * we should find out a suitable page size and patch the | ||
642 | * TLB miss code (either that or use the PACA to store | ||
643 | * the value we want) | ||
644 | */ | ||
645 | mmu_linear_psize = MMU_PAGE_1G; | ||
646 | |||
647 | /* XXX This should be decided at runtime based on supported | ||
648 | * page sizes in the TLB, but for now let's assume 16M is | ||
649 | * always there and a good fit (which it probably is) | ||
650 | * | ||
651 | * Freescale booke only supports 4K pages in TLB0, so use that. | ||
652 | */ | ||
653 | if (mmu_has_feature(MMU_FTR_TYPE_FSL_E)) | ||
654 | mmu_vmemmap_psize = MMU_PAGE_4K; | ||
655 | else | ||
656 | mmu_vmemmap_psize = MMU_PAGE_16M; | ||
657 | |||
658 | /* XXX This code only checks for TLB 0 capabilities and doesn't | ||
659 | * check what page size combos are supported by the HW. It | ||
660 | * also doesn't handle the case where a separate array holds | ||
661 | * the IND entries from the array loaded by the PT. | ||
662 | */ | ||
663 | /* Look for supported page sizes */ | ||
664 | setup_page_sizes(); | ||
665 | |||
666 | /* Look for HW tablewalk support */ | ||
667 | setup_mmu_htw(); | ||
668 | |||
669 | #ifdef CONFIG_PPC_FSL_BOOK3E | ||
670 | if (mmu_has_feature(MMU_FTR_TYPE_FSL_E)) { | ||
669 | if (book3e_htw_mode == PPC_HTW_NONE) { | 671 | if (book3e_htw_mode == PPC_HTW_NONE) { |
670 | extlb_level_exc = EX_TLB_SIZE; | 672 | extlb_level_exc = EX_TLB_SIZE; |
671 | patch_exception(0x1c0, exc_data_tlb_miss_bolted_book3e); | 673 | patch_exception(0x1c0, exc_data_tlb_miss_bolted_book3e); |
@@ -675,22 +677,41 @@ static void __early_init_mmu(int boot_cpu) | |||
675 | } | 677 | } |
676 | #endif | 678 | #endif |
677 | 679 | ||
678 | /* A sync won't hurt us after mucking around with | 680 | /* Set the global containing the top of the linear mapping |
679 | * the MMU configuration | 681 | * for use by the TLB miss code |
680 | */ | 682 | */ |
681 | mb(); | 683 | linear_map_top = memblock_end_of_DRAM(); |
684 | } | ||
685 | |||
686 | static void __init early_mmu_set_memory_limit(void) | ||
687 | { | ||
688 | #ifdef CONFIG_PPC_FSL_BOOK3E | ||
689 | if (mmu_has_feature(MMU_FTR_TYPE_FSL_E)) { | ||
690 | /* | ||
691 | * Limit memory so we dont have linear faults. | ||
692 | * Unlike memblock_set_current_limit, which limits | ||
693 | * memory available during early boot, this permanently | ||
694 | * reduces the memory available to Linux. We need to | ||
695 | * do this because highmem is not supported on 64-bit. | ||
696 | */ | ||
697 | memblock_enforce_memory_limit(linear_map_top); | ||
698 | } | ||
699 | #endif | ||
682 | 700 | ||
683 | memblock_set_current_limit(linear_map_top); | 701 | memblock_set_current_limit(linear_map_top); |
684 | } | 702 | } |
685 | 703 | ||
704 | /* boot cpu only */ | ||
686 | void __init early_init_mmu(void) | 705 | void __init early_init_mmu(void) |
687 | { | 706 | { |
688 | __early_init_mmu(1); | 707 | early_init_mmu_global(); |
708 | early_init_this_mmu(); | ||
709 | early_mmu_set_memory_limit(); | ||
689 | } | 710 | } |
690 | 711 | ||
691 | void early_init_mmu_secondary(void) | 712 | void early_init_mmu_secondary(void) |
692 | { | 713 | { |
693 | __early_init_mmu(0); | 714 | early_init_this_mmu(); |
694 | } | 715 | } |
695 | 716 | ||
696 | void setup_initial_memory_limit(phys_addr_t first_memblock_base, | 717 | void setup_initial_memory_limit(phys_addr_t first_memblock_base, |
diff --git a/arch/powerpc/oprofile/Makefile b/arch/powerpc/oprofile/Makefile index 751ec7bd5018..cedbbeced632 100644 --- a/arch/powerpc/oprofile/Makefile +++ b/arch/powerpc/oprofile/Makefile | |||
@@ -14,6 +14,6 @@ oprofile-y := $(DRIVER_OBJS) common.o backtrace.o | |||
14 | oprofile-$(CONFIG_OPROFILE_CELL) += op_model_cell.o \ | 14 | oprofile-$(CONFIG_OPROFILE_CELL) += op_model_cell.o \ |
15 | cell/spu_profiler.o cell/vma_map.o \ | 15 | cell/spu_profiler.o cell/vma_map.o \ |
16 | cell/spu_task_sync.o | 16 | cell/spu_task_sync.o |
17 | oprofile-$(CONFIG_PPC_BOOK3S_64) += op_model_rs64.o op_model_power4.o op_model_pa6t.o | 17 | oprofile-$(CONFIG_PPC_BOOK3S_64) += op_model_power4.o op_model_pa6t.o |
18 | oprofile-$(CONFIG_FSL_EMB_PERFMON) += op_model_fsl_emb.o | 18 | oprofile-$(CONFIG_FSL_EMB_PERFMON) += op_model_fsl_emb.o |
19 | oprofile-$(CONFIG_6xx) += op_model_7450.o | 19 | oprofile-$(CONFIG_6xx) += op_model_7450.o |
diff --git a/arch/powerpc/oprofile/common.c b/arch/powerpc/oprofile/common.c index c77348c5d463..bf094c5a4bd9 100644 --- a/arch/powerpc/oprofile/common.c +++ b/arch/powerpc/oprofile/common.c | |||
@@ -205,9 +205,6 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) | |||
205 | ops->sync_stop = model->sync_stop; | 205 | ops->sync_stop = model->sync_stop; |
206 | break; | 206 | break; |
207 | #endif | 207 | #endif |
208 | case PPC_OPROFILE_RS64: | ||
209 | model = &op_model_rs64; | ||
210 | break; | ||
211 | case PPC_OPROFILE_POWER4: | 208 | case PPC_OPROFILE_POWER4: |
212 | model = &op_model_power4; | 209 | model = &op_model_power4; |
213 | break; | 210 | break; |
diff --git a/arch/powerpc/oprofile/op_model_rs64.c b/arch/powerpc/oprofile/op_model_rs64.c deleted file mode 100644 index 7e5b8ed3a1b7..000000000000 --- a/arch/powerpc/oprofile/op_model_rs64.c +++ /dev/null | |||
@@ -1,222 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004 Anton Blanchard <anton@au.ibm.com>, IBM | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | */ | ||
9 | |||
10 | #include <linux/oprofile.h> | ||
11 | #include <linux/smp.h> | ||
12 | #include <asm/ptrace.h> | ||
13 | #include <asm/processor.h> | ||
14 | #include <asm/cputable.h> | ||
15 | #include <asm/oprofile_impl.h> | ||
16 | |||
17 | #define dbg(args...) | ||
18 | |||
19 | static void ctrl_write(unsigned int i, unsigned int val) | ||
20 | { | ||
21 | unsigned int tmp = 0; | ||
22 | unsigned long shift = 0, mask = 0; | ||
23 | |||
24 | dbg("ctrl_write %d %x\n", i, val); | ||
25 | |||
26 | switch(i) { | ||
27 | case 0: | ||
28 | tmp = mfspr(SPRN_MMCR0); | ||
29 | shift = 6; | ||
30 | mask = 0x7F; | ||
31 | break; | ||
32 | case 1: | ||
33 | tmp = mfspr(SPRN_MMCR0); | ||
34 | shift = 0; | ||
35 | mask = 0x3F; | ||
36 | break; | ||
37 | case 2: | ||
38 | tmp = mfspr(SPRN_MMCR1); | ||
39 | shift = 31 - 4; | ||
40 | mask = 0x1F; | ||
41 | break; | ||
42 | case 3: | ||
43 | tmp = mfspr(SPRN_MMCR1); | ||
44 | shift = 31 - 9; | ||
45 | mask = 0x1F; | ||
46 | break; | ||
47 | case 4: | ||
48 | tmp = mfspr(SPRN_MMCR1); | ||
49 | shift = 31 - 14; | ||
50 | mask = 0x1F; | ||
51 | break; | ||
52 | case 5: | ||
53 | tmp = mfspr(SPRN_MMCR1); | ||
54 | shift = 31 - 19; | ||
55 | mask = 0x1F; | ||
56 | break; | ||
57 | case 6: | ||
58 | tmp = mfspr(SPRN_MMCR1); | ||
59 | shift = 31 - 24; | ||
60 | mask = 0x1F; | ||
61 | break; | ||
62 | case 7: | ||
63 | tmp = mfspr(SPRN_MMCR1); | ||
64 | shift = 31 - 28; | ||
65 | mask = 0xF; | ||
66 | break; | ||
67 | } | ||
68 | |||
69 | tmp = tmp & ~(mask << shift); | ||
70 | tmp |= val << shift; | ||
71 | |||
72 | switch(i) { | ||
73 | case 0: | ||
74 | case 1: | ||
75 | mtspr(SPRN_MMCR0, tmp); | ||
76 | break; | ||
77 | default: | ||
78 | mtspr(SPRN_MMCR1, tmp); | ||
79 | } | ||
80 | |||
81 | dbg("ctrl_write mmcr0 %lx mmcr1 %lx\n", mfspr(SPRN_MMCR0), | ||
82 | mfspr(SPRN_MMCR1)); | ||
83 | } | ||
84 | |||
85 | static unsigned long reset_value[OP_MAX_COUNTER]; | ||
86 | |||
87 | static int num_counters; | ||
88 | |||
89 | static int rs64_reg_setup(struct op_counter_config *ctr, | ||
90 | struct op_system_config *sys, | ||
91 | int num_ctrs) | ||
92 | { | ||
93 | int i; | ||
94 | |||
95 | num_counters = num_ctrs; | ||
96 | |||
97 | for (i = 0; i < num_counters; ++i) | ||
98 | reset_value[i] = 0x80000000UL - ctr[i].count; | ||
99 | |||
100 | /* XXX setup user and kernel profiling */ | ||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | static int rs64_cpu_setup(struct op_counter_config *ctr) | ||
105 | { | ||
106 | unsigned int mmcr0; | ||
107 | |||
108 | /* reset MMCR0 and set the freeze bit */ | ||
109 | mmcr0 = MMCR0_FC; | ||
110 | mtspr(SPRN_MMCR0, mmcr0); | ||
111 | |||
112 | /* reset MMCR1, MMCRA */ | ||
113 | mtspr(SPRN_MMCR1, 0); | ||
114 | |||
115 | if (cpu_has_feature(CPU_FTR_MMCRA)) | ||
116 | mtspr(SPRN_MMCRA, 0); | ||
117 | |||
118 | mmcr0 |= MMCR0_FCM1|MMCR0_PMXE|MMCR0_FCECE; | ||
119 | /* Only applies to POWER3, but should be safe on RS64 */ | ||
120 | mmcr0 |= MMCR0_PMC1CE|MMCR0_PMCjCE; | ||
121 | mtspr(SPRN_MMCR0, mmcr0); | ||
122 | |||
123 | dbg("setup on cpu %d, mmcr0 %lx\n", smp_processor_id(), | ||
124 | mfspr(SPRN_MMCR0)); | ||
125 | dbg("setup on cpu %d, mmcr1 %lx\n", smp_processor_id(), | ||
126 | mfspr(SPRN_MMCR1)); | ||
127 | |||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | static int rs64_start(struct op_counter_config *ctr) | ||
132 | { | ||
133 | int i; | ||
134 | unsigned int mmcr0; | ||
135 | |||
136 | /* set the PMM bit (see comment below) */ | ||
137 | mtmsrd(mfmsr() | MSR_PMM); | ||
138 | |||
139 | for (i = 0; i < num_counters; ++i) { | ||
140 | if (ctr[i].enabled) { | ||
141 | classic_ctr_write(i, reset_value[i]); | ||
142 | ctrl_write(i, ctr[i].event); | ||
143 | } else { | ||
144 | classic_ctr_write(i, 0); | ||
145 | } | ||
146 | } | ||
147 | |||
148 | mmcr0 = mfspr(SPRN_MMCR0); | ||
149 | |||
150 | /* | ||
151 | * now clear the freeze bit, counting will not start until we | ||
152 | * rfid from this excetion, because only at that point will | ||
153 | * the PMM bit be cleared | ||
154 | */ | ||
155 | mmcr0 &= ~MMCR0_FC; | ||
156 | mtspr(SPRN_MMCR0, mmcr0); | ||
157 | |||
158 | dbg("start on cpu %d, mmcr0 %x\n", smp_processor_id(), mmcr0); | ||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | static void rs64_stop(void) | ||
163 | { | ||
164 | unsigned int mmcr0; | ||
165 | |||
166 | /* freeze counters */ | ||
167 | mmcr0 = mfspr(SPRN_MMCR0); | ||
168 | mmcr0 |= MMCR0_FC; | ||
169 | mtspr(SPRN_MMCR0, mmcr0); | ||
170 | |||
171 | dbg("stop on cpu %d, mmcr0 %x\n", smp_processor_id(), mmcr0); | ||
172 | |||
173 | mb(); | ||
174 | } | ||
175 | |||
176 | static void rs64_handle_interrupt(struct pt_regs *regs, | ||
177 | struct op_counter_config *ctr) | ||
178 | { | ||
179 | unsigned int mmcr0; | ||
180 | int is_kernel; | ||
181 | int val; | ||
182 | int i; | ||
183 | unsigned long pc = mfspr(SPRN_SIAR); | ||
184 | |||
185 | is_kernel = is_kernel_addr(pc); | ||
186 | |||
187 | /* set the PMM bit (see comment below) */ | ||
188 | mtmsrd(mfmsr() | MSR_PMM); | ||
189 | |||
190 | for (i = 0; i < num_counters; ++i) { | ||
191 | val = classic_ctr_read(i); | ||
192 | if (val < 0) { | ||
193 | if (ctr[i].enabled) { | ||
194 | oprofile_add_ext_sample(pc, regs, i, is_kernel); | ||
195 | classic_ctr_write(i, reset_value[i]); | ||
196 | } else { | ||
197 | classic_ctr_write(i, 0); | ||
198 | } | ||
199 | } | ||
200 | } | ||
201 | |||
202 | mmcr0 = mfspr(SPRN_MMCR0); | ||
203 | |||
204 | /* reset the perfmon trigger */ | ||
205 | mmcr0 |= MMCR0_PMXE; | ||
206 | |||
207 | /* | ||
208 | * now clear the freeze bit, counting will not start until we | ||
209 | * rfid from this exception, because only at that point will | ||
210 | * the PMM bit be cleared | ||
211 | */ | ||
212 | mmcr0 &= ~MMCR0_FC; | ||
213 | mtspr(SPRN_MMCR0, mmcr0); | ||
214 | } | ||
215 | |||
216 | struct op_powerpc_model op_model_rs64 = { | ||
217 | .reg_setup = rs64_reg_setup, | ||
218 | .cpu_setup = rs64_cpu_setup, | ||
219 | .start = rs64_start, | ||
220 | .stop = rs64_stop, | ||
221 | .handle_interrupt = rs64_handle_interrupt, | ||
222 | }; | ||
diff --git a/arch/powerpc/perf/core-book3s.c b/arch/powerpc/perf/core-book3s.c index fe52db2eea6a..b7cd00b0171e 100644 --- a/arch/powerpc/perf/core-book3s.c +++ b/arch/powerpc/perf/core-book3s.c | |||
@@ -36,7 +36,12 @@ struct cpu_hw_events { | |||
36 | struct perf_event *event[MAX_HWEVENTS]; | 36 | struct perf_event *event[MAX_HWEVENTS]; |
37 | u64 events[MAX_HWEVENTS]; | 37 | u64 events[MAX_HWEVENTS]; |
38 | unsigned int flags[MAX_HWEVENTS]; | 38 | unsigned int flags[MAX_HWEVENTS]; |
39 | unsigned long mmcr[3]; | 39 | /* |
40 | * The order of the MMCR array is: | ||
41 | * - 64-bit, MMCR0, MMCR1, MMCRA, MMCR2 | ||
42 | * - 32-bit, MMCR0, MMCR1, MMCR2 | ||
43 | */ | ||
44 | unsigned long mmcr[4]; | ||
40 | struct perf_event *limited_counter[MAX_LIMITED_HWCOUNTERS]; | 45 | struct perf_event *limited_counter[MAX_LIMITED_HWCOUNTERS]; |
41 | u8 limited_hwidx[MAX_LIMITED_HWCOUNTERS]; | 46 | u8 limited_hwidx[MAX_LIMITED_HWCOUNTERS]; |
42 | u64 alternatives[MAX_HWEVENTS][MAX_EVENT_ALTERNATIVES]; | 47 | u64 alternatives[MAX_HWEVENTS][MAX_EVENT_ALTERNATIVES]; |
@@ -112,9 +117,9 @@ static bool is_ebb_event(struct perf_event *event) { return false; } | |||
112 | static int ebb_event_check(struct perf_event *event) { return 0; } | 117 | static int ebb_event_check(struct perf_event *event) { return 0; } |
113 | static void ebb_event_add(struct perf_event *event) { } | 118 | static void ebb_event_add(struct perf_event *event) { } |
114 | static void ebb_switch_out(unsigned long mmcr0) { } | 119 | static void ebb_switch_out(unsigned long mmcr0) { } |
115 | static unsigned long ebb_switch_in(bool ebb, unsigned long mmcr0) | 120 | static unsigned long ebb_switch_in(bool ebb, struct cpu_hw_events *cpuhw) |
116 | { | 121 | { |
117 | return mmcr0; | 122 | return cpuhw->mmcr[0]; |
118 | } | 123 | } |
119 | 124 | ||
120 | static inline void power_pmu_bhrb_enable(struct perf_event *event) {} | 125 | static inline void power_pmu_bhrb_enable(struct perf_event *event) {} |
@@ -542,8 +547,10 @@ static void ebb_switch_out(unsigned long mmcr0) | |||
542 | current->thread.mmcr2 = mfspr(SPRN_MMCR2) & MMCR2_USER_MASK; | 547 | current->thread.mmcr2 = mfspr(SPRN_MMCR2) & MMCR2_USER_MASK; |
543 | } | 548 | } |
544 | 549 | ||
545 | static unsigned long ebb_switch_in(bool ebb, unsigned long mmcr0) | 550 | static unsigned long ebb_switch_in(bool ebb, struct cpu_hw_events *cpuhw) |
546 | { | 551 | { |
552 | unsigned long mmcr0 = cpuhw->mmcr[0]; | ||
553 | |||
547 | if (!ebb) | 554 | if (!ebb) |
548 | goto out; | 555 | goto out; |
549 | 556 | ||
@@ -568,7 +575,15 @@ static unsigned long ebb_switch_in(bool ebb, unsigned long mmcr0) | |||
568 | mtspr(SPRN_SIAR, current->thread.siar); | 575 | mtspr(SPRN_SIAR, current->thread.siar); |
569 | mtspr(SPRN_SIER, current->thread.sier); | 576 | mtspr(SPRN_SIER, current->thread.sier); |
570 | mtspr(SPRN_SDAR, current->thread.sdar); | 577 | mtspr(SPRN_SDAR, current->thread.sdar); |
571 | mtspr(SPRN_MMCR2, current->thread.mmcr2); | 578 | |
579 | /* | ||
580 | * Merge the kernel & user values of MMCR2. The semantics we implement | ||
581 | * are that the user MMCR2 can set bits, ie. cause counters to freeze, | ||
582 | * but not clear bits. If a task wants to be able to clear bits, ie. | ||
583 | * unfreeze counters, it should not set exclude_xxx in its events and | ||
584 | * instead manage the MMCR2 entirely by itself. | ||
585 | */ | ||
586 | mtspr(SPRN_MMCR2, cpuhw->mmcr[3] | current->thread.mmcr2); | ||
572 | out: | 587 | out: |
573 | return mmcr0; | 588 | return mmcr0; |
574 | } | 589 | } |
@@ -915,6 +930,14 @@ static int check_excludes(struct perf_event **ctrs, unsigned int cflags[], | |||
915 | int i, n, first; | 930 | int i, n, first; |
916 | struct perf_event *event; | 931 | struct perf_event *event; |
917 | 932 | ||
933 | /* | ||
934 | * If the PMU we're on supports per event exclude settings then we | ||
935 | * don't need to do any of this logic. NB. This assumes no PMU has both | ||
936 | * per event exclude and limited PMCs. | ||
937 | */ | ||
938 | if (ppmu->flags & PPMU_ARCH_207S) | ||
939 | return 0; | ||
940 | |||
918 | n = n_prev + n_new; | 941 | n = n_prev + n_new; |
919 | if (n <= 1) | 942 | if (n <= 1) |
920 | return 0; | 943 | return 0; |
@@ -1219,28 +1242,31 @@ static void power_pmu_enable(struct pmu *pmu) | |||
1219 | } | 1242 | } |
1220 | 1243 | ||
1221 | /* | 1244 | /* |
1222 | * Compute MMCR* values for the new set of events | 1245 | * Clear all MMCR settings and recompute them for the new set of events. |
1223 | */ | 1246 | */ |
1247 | memset(cpuhw->mmcr, 0, sizeof(cpuhw->mmcr)); | ||
1248 | |||
1224 | if (ppmu->compute_mmcr(cpuhw->events, cpuhw->n_events, hwc_index, | 1249 | if (ppmu->compute_mmcr(cpuhw->events, cpuhw->n_events, hwc_index, |
1225 | cpuhw->mmcr)) { | 1250 | cpuhw->mmcr, cpuhw->event)) { |
1226 | /* shouldn't ever get here */ | 1251 | /* shouldn't ever get here */ |
1227 | printk(KERN_ERR "oops compute_mmcr failed\n"); | 1252 | printk(KERN_ERR "oops compute_mmcr failed\n"); |
1228 | goto out; | 1253 | goto out; |
1229 | } | 1254 | } |
1230 | 1255 | ||
1231 | /* | 1256 | if (!(ppmu->flags & PPMU_ARCH_207S)) { |
1232 | * Add in MMCR0 freeze bits corresponding to the | 1257 | /* |
1233 | * attr.exclude_* bits for the first event. | 1258 | * Add in MMCR0 freeze bits corresponding to the attr.exclude_* |
1234 | * We have already checked that all events have the | 1259 | * bits for the first event. We have already checked that all |
1235 | * same values for these bits as the first event. | 1260 | * events have the same value for these bits as the first event. |
1236 | */ | 1261 | */ |
1237 | event = cpuhw->event[0]; | 1262 | event = cpuhw->event[0]; |
1238 | if (event->attr.exclude_user) | 1263 | if (event->attr.exclude_user) |
1239 | cpuhw->mmcr[0] |= MMCR0_FCP; | 1264 | cpuhw->mmcr[0] |= MMCR0_FCP; |
1240 | if (event->attr.exclude_kernel) | 1265 | if (event->attr.exclude_kernel) |
1241 | cpuhw->mmcr[0] |= freeze_events_kernel; | 1266 | cpuhw->mmcr[0] |= freeze_events_kernel; |
1242 | if (event->attr.exclude_hv) | 1267 | if (event->attr.exclude_hv) |
1243 | cpuhw->mmcr[0] |= MMCR0_FCHV; | 1268 | cpuhw->mmcr[0] |= MMCR0_FCHV; |
1269 | } | ||
1244 | 1270 | ||
1245 | /* | 1271 | /* |
1246 | * Write the new configuration to MMCR* with the freeze | 1272 | * Write the new configuration to MMCR* with the freeze |
@@ -1252,6 +1278,8 @@ static void power_pmu_enable(struct pmu *pmu) | |||
1252 | mtspr(SPRN_MMCR1, cpuhw->mmcr[1]); | 1278 | mtspr(SPRN_MMCR1, cpuhw->mmcr[1]); |
1253 | mtspr(SPRN_MMCR0, (cpuhw->mmcr[0] & ~(MMCR0_PMC1CE | MMCR0_PMCjCE)) | 1279 | mtspr(SPRN_MMCR0, (cpuhw->mmcr[0] & ~(MMCR0_PMC1CE | MMCR0_PMCjCE)) |
1254 | | MMCR0_FC); | 1280 | | MMCR0_FC); |
1281 | if (ppmu->flags & PPMU_ARCH_207S) | ||
1282 | mtspr(SPRN_MMCR2, cpuhw->mmcr[3]); | ||
1255 | 1283 | ||
1256 | /* | 1284 | /* |
1257 | * Read off any pre-existing events that need to move | 1285 | * Read off any pre-existing events that need to move |
@@ -1307,10 +1335,7 @@ static void power_pmu_enable(struct pmu *pmu) | |||
1307 | out_enable: | 1335 | out_enable: |
1308 | pmao_restore_workaround(ebb); | 1336 | pmao_restore_workaround(ebb); |
1309 | 1337 | ||
1310 | if (ppmu->flags & PPMU_ARCH_207S) | 1338 | mmcr0 = ebb_switch_in(ebb, cpuhw); |
1311 | mtspr(SPRN_MMCR2, 0); | ||
1312 | |||
1313 | mmcr0 = ebb_switch_in(ebb, cpuhw->mmcr[0]); | ||
1314 | 1339 | ||
1315 | mb(); | 1340 | mb(); |
1316 | if (cpuhw->bhrb_users) | 1341 | if (cpuhw->bhrb_users) |
diff --git a/arch/powerpc/perf/hv-24x7.c b/arch/powerpc/perf/hv-24x7.c index 66d0f179650f..70d4f748b54b 100644 --- a/arch/powerpc/perf/hv-24x7.c +++ b/arch/powerpc/perf/hv-24x7.c | |||
@@ -223,7 +223,7 @@ e_free: | |||
223 | pr_err("h_get_24x7_catalog_page(ver=%lld, page=%lld) failed:" | 223 | pr_err("h_get_24x7_catalog_page(ver=%lld, page=%lld) failed:" |
224 | " rc=%ld\n", | 224 | " rc=%ld\n", |
225 | catalog_version_num, page_offset, hret); | 225 | catalog_version_num, page_offset, hret); |
226 | kfree(page); | 226 | kmem_cache_free(hv_page_cache, page); |
227 | 227 | ||
228 | pr_devel("catalog_read: offset=%lld(%lld) count=%zu(%zu) catalog_len=%zu(%zu) => %zd\n", | 228 | pr_devel("catalog_read: offset=%lld(%lld) count=%zu(%zu) catalog_len=%zu(%zu) => %zd\n", |
229 | offset, page_offset, count, page_count, catalog_len, | 229 | offset, page_offset, count, page_count, catalog_len, |
diff --git a/arch/powerpc/perf/mpc7450-pmu.c b/arch/powerpc/perf/mpc7450-pmu.c index fe21b515ca44..d115c5635bf3 100644 --- a/arch/powerpc/perf/mpc7450-pmu.c +++ b/arch/powerpc/perf/mpc7450-pmu.c | |||
@@ -260,8 +260,9 @@ static const u32 pmcsel_mask[N_COUNTER] = { | |||
260 | /* | 260 | /* |
261 | * Compute MMCR0/1/2 values for a set of events. | 261 | * Compute MMCR0/1/2 values for a set of events. |
262 | */ | 262 | */ |
263 | static int mpc7450_compute_mmcr(u64 event[], int n_ev, | 263 | static int mpc7450_compute_mmcr(u64 event[], int n_ev, unsigned int hwc[], |
264 | unsigned int hwc[], unsigned long mmcr[]) | 264 | unsigned long mmcr[], |
265 | struct perf_event *pevents[]) | ||
265 | { | 266 | { |
266 | u8 event_index[N_CLASSES][N_COUNTER]; | 267 | u8 event_index[N_CLASSES][N_COUNTER]; |
267 | int n_classevent[N_CLASSES]; | 268 | int n_classevent[N_CLASSES]; |
diff --git a/arch/powerpc/perf/power4-pmu.c b/arch/powerpc/perf/power4-pmu.c index 9103a1de864d..ce6072fa481b 100644 --- a/arch/powerpc/perf/power4-pmu.c +++ b/arch/powerpc/perf/power4-pmu.c | |||
@@ -356,7 +356,7 @@ static int p4_get_alternatives(u64 event, unsigned int flags, u64 alt[]) | |||
356 | } | 356 | } |
357 | 357 | ||
358 | static int p4_compute_mmcr(u64 event[], int n_ev, | 358 | static int p4_compute_mmcr(u64 event[], int n_ev, |
359 | unsigned int hwc[], unsigned long mmcr[]) | 359 | unsigned int hwc[], unsigned long mmcr[], struct perf_event *pevents[]) |
360 | { | 360 | { |
361 | unsigned long mmcr0 = 0, mmcr1 = 0, mmcra = 0; | 361 | unsigned long mmcr0 = 0, mmcr1 = 0, mmcra = 0; |
362 | unsigned int pmc, unit, byte, psel, lower; | 362 | unsigned int pmc, unit, byte, psel, lower; |
diff --git a/arch/powerpc/perf/power5+-pmu.c b/arch/powerpc/perf/power5+-pmu.c index b03b6dc0172d..0526dac66007 100644 --- a/arch/powerpc/perf/power5+-pmu.c +++ b/arch/powerpc/perf/power5+-pmu.c | |||
@@ -452,7 +452,7 @@ static int power5p_marked_instr_event(u64 event) | |||
452 | } | 452 | } |
453 | 453 | ||
454 | static int power5p_compute_mmcr(u64 event[], int n_ev, | 454 | static int power5p_compute_mmcr(u64 event[], int n_ev, |
455 | unsigned int hwc[], unsigned long mmcr[]) | 455 | unsigned int hwc[], unsigned long mmcr[], struct perf_event *pevents[]) |
456 | { | 456 | { |
457 | unsigned long mmcr1 = 0; | 457 | unsigned long mmcr1 = 0; |
458 | unsigned long mmcra = 0; | 458 | unsigned long mmcra = 0; |
diff --git a/arch/powerpc/perf/power5-pmu.c b/arch/powerpc/perf/power5-pmu.c index 1e8ce423c3af..4dc99f9f7962 100644 --- a/arch/powerpc/perf/power5-pmu.c +++ b/arch/powerpc/perf/power5-pmu.c | |||
@@ -383,7 +383,7 @@ static int power5_marked_instr_event(u64 event) | |||
383 | } | 383 | } |
384 | 384 | ||
385 | static int power5_compute_mmcr(u64 event[], int n_ev, | 385 | static int power5_compute_mmcr(u64 event[], int n_ev, |
386 | unsigned int hwc[], unsigned long mmcr[]) | 386 | unsigned int hwc[], unsigned long mmcr[], struct perf_event *pevents[]) |
387 | { | 387 | { |
388 | unsigned long mmcr1 = 0; | 388 | unsigned long mmcr1 = 0; |
389 | unsigned long mmcra = MMCRA_SDAR_DCACHE_MISS | MMCRA_SDAR_ERAT_MISS; | 389 | unsigned long mmcra = MMCRA_SDAR_DCACHE_MISS | MMCRA_SDAR_ERAT_MISS; |
diff --git a/arch/powerpc/perf/power6-pmu.c b/arch/powerpc/perf/power6-pmu.c index 31128e086fed..9c9d646b68a1 100644 --- a/arch/powerpc/perf/power6-pmu.c +++ b/arch/powerpc/perf/power6-pmu.c | |||
@@ -175,7 +175,7 @@ static int power6_marked_instr_event(u64 event) | |||
175 | * Assign PMC numbers and compute MMCR1 value for a set of events | 175 | * Assign PMC numbers and compute MMCR1 value for a set of events |
176 | */ | 176 | */ |
177 | static int p6_compute_mmcr(u64 event[], int n_ev, | 177 | static int p6_compute_mmcr(u64 event[], int n_ev, |
178 | unsigned int hwc[], unsigned long mmcr[]) | 178 | unsigned int hwc[], unsigned long mmcr[], struct perf_event *pevents[]) |
179 | { | 179 | { |
180 | unsigned long mmcr1 = 0; | 180 | unsigned long mmcr1 = 0; |
181 | unsigned long mmcra = MMCRA_SDAR_DCACHE_MISS | MMCRA_SDAR_ERAT_MISS; | 181 | unsigned long mmcra = MMCRA_SDAR_DCACHE_MISS | MMCRA_SDAR_ERAT_MISS; |
diff --git a/arch/powerpc/perf/power7-pmu.c b/arch/powerpc/perf/power7-pmu.c index 56c67bca2f75..5b62f2389290 100644 --- a/arch/powerpc/perf/power7-pmu.c +++ b/arch/powerpc/perf/power7-pmu.c | |||
@@ -245,7 +245,7 @@ static int power7_marked_instr_event(u64 event) | |||
245 | } | 245 | } |
246 | 246 | ||
247 | static int power7_compute_mmcr(u64 event[], int n_ev, | 247 | static int power7_compute_mmcr(u64 event[], int n_ev, |
248 | unsigned int hwc[], unsigned long mmcr[]) | 248 | unsigned int hwc[], unsigned long mmcr[], struct perf_event *pevents[]) |
249 | { | 249 | { |
250 | unsigned long mmcr1 = 0; | 250 | unsigned long mmcr1 = 0; |
251 | unsigned long mmcra = MMCRA_SDAR_DCACHE_MISS | MMCRA_SDAR_ERAT_MISS; | 251 | unsigned long mmcra = MMCRA_SDAR_DCACHE_MISS | MMCRA_SDAR_ERAT_MISS; |
diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c index 639cd9156585..396351db601b 100644 --- a/arch/powerpc/perf/power8-pmu.c +++ b/arch/powerpc/perf/power8-pmu.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/perf_event.h> | 16 | #include <linux/perf_event.h> |
17 | #include <asm/firmware.h> | 17 | #include <asm/firmware.h> |
18 | #include <asm/cputable.h> | ||
18 | 19 | ||
19 | 20 | ||
20 | /* | 21 | /* |
@@ -266,6 +267,11 @@ | |||
266 | #define MMCRA_SDAR_MODE_TLB (1ull << 42) | 267 | #define MMCRA_SDAR_MODE_TLB (1ull << 42) |
267 | #define MMCRA_IFM_SHIFT 30 | 268 | #define MMCRA_IFM_SHIFT 30 |
268 | 269 | ||
270 | /* Bits in MMCR2 for POWER8 */ | ||
271 | #define MMCR2_FCS(pmc) (1ull << (63 - (((pmc) - 1) * 9))) | ||
272 | #define MMCR2_FCP(pmc) (1ull << (62 - (((pmc) - 1) * 9))) | ||
273 | #define MMCR2_FCH(pmc) (1ull << (57 - (((pmc) - 1) * 9))) | ||
274 | |||
269 | 275 | ||
270 | static inline bool event_is_fab_match(u64 event) | 276 | static inline bool event_is_fab_match(u64 event) |
271 | { | 277 | { |
@@ -393,9 +399,10 @@ static int power8_get_constraint(u64 event, unsigned long *maskp, unsigned long | |||
393 | } | 399 | } |
394 | 400 | ||
395 | static int power8_compute_mmcr(u64 event[], int n_ev, | 401 | static int power8_compute_mmcr(u64 event[], int n_ev, |
396 | unsigned int hwc[], unsigned long mmcr[]) | 402 | unsigned int hwc[], unsigned long mmcr[], |
403 | struct perf_event *pevents[]) | ||
397 | { | 404 | { |
398 | unsigned long mmcra, mmcr1, unit, combine, psel, cache, val; | 405 | unsigned long mmcra, mmcr1, mmcr2, unit, combine, psel, cache, val; |
399 | unsigned int pmc, pmc_inuse; | 406 | unsigned int pmc, pmc_inuse; |
400 | int i; | 407 | int i; |
401 | 408 | ||
@@ -410,7 +417,7 @@ static int power8_compute_mmcr(u64 event[], int n_ev, | |||
410 | 417 | ||
411 | /* In continous sampling mode, update SDAR on TLB miss */ | 418 | /* In continous sampling mode, update SDAR on TLB miss */ |
412 | mmcra = MMCRA_SDAR_MODE_TLB; | 419 | mmcra = MMCRA_SDAR_MODE_TLB; |
413 | mmcr1 = 0; | 420 | mmcr1 = mmcr2 = 0; |
414 | 421 | ||
415 | /* Second pass: assign PMCs, set all MMCR1 fields */ | 422 | /* Second pass: assign PMCs, set all MMCR1 fields */ |
416 | for (i = 0; i < n_ev; ++i) { | 423 | for (i = 0; i < n_ev; ++i) { |
@@ -472,6 +479,19 @@ static int power8_compute_mmcr(u64 event[], int n_ev, | |||
472 | mmcra |= val << MMCRA_IFM_SHIFT; | 479 | mmcra |= val << MMCRA_IFM_SHIFT; |
473 | } | 480 | } |
474 | 481 | ||
482 | if (pevents[i]->attr.exclude_user) | ||
483 | mmcr2 |= MMCR2_FCP(pmc); | ||
484 | |||
485 | if (pevents[i]->attr.exclude_hv) | ||
486 | mmcr2 |= MMCR2_FCH(pmc); | ||
487 | |||
488 | if (pevents[i]->attr.exclude_kernel) { | ||
489 | if (cpu_has_feature(CPU_FTR_HVMODE)) | ||
490 | mmcr2 |= MMCR2_FCH(pmc); | ||
491 | else | ||
492 | mmcr2 |= MMCR2_FCS(pmc); | ||
493 | } | ||
494 | |||
475 | hwc[i] = pmc - 1; | 495 | hwc[i] = pmc - 1; |
476 | } | 496 | } |
477 | 497 | ||
@@ -491,6 +511,7 @@ static int power8_compute_mmcr(u64 event[], int n_ev, | |||
491 | 511 | ||
492 | mmcr[1] = mmcr1; | 512 | mmcr[1] = mmcr1; |
493 | mmcr[2] = mmcra; | 513 | mmcr[2] = mmcra; |
514 | mmcr[3] = mmcr2; | ||
494 | 515 | ||
495 | return 0; | 516 | return 0; |
496 | } | 517 | } |
diff --git a/arch/powerpc/perf/ppc970-pmu.c b/arch/powerpc/perf/ppc970-pmu.c index 20139ceeacf6..8b6a8a36fa38 100644 --- a/arch/powerpc/perf/ppc970-pmu.c +++ b/arch/powerpc/perf/ppc970-pmu.c | |||
@@ -257,7 +257,7 @@ static int p970_get_alternatives(u64 event, unsigned int flags, u64 alt[]) | |||
257 | } | 257 | } |
258 | 258 | ||
259 | static int p970_compute_mmcr(u64 event[], int n_ev, | 259 | static int p970_compute_mmcr(u64 event[], int n_ev, |
260 | unsigned int hwc[], unsigned long mmcr[]) | 260 | unsigned int hwc[], unsigned long mmcr[], struct perf_event *pevents[]) |
261 | { | 261 | { |
262 | unsigned long mmcr0 = 0, mmcr1 = 0, mmcra = 0; | 262 | unsigned long mmcr0 = 0, mmcr1 = 0, mmcra = 0; |
263 | unsigned int pmc, unit, byte, psel; | 263 | unsigned int pmc, unit, byte, psel; |
diff --git a/arch/powerpc/platforms/44x/warp.c b/arch/powerpc/platforms/44x/warp.c index 534574a97ec9..3a104284b338 100644 --- a/arch/powerpc/platforms/44x/warp.c +++ b/arch/powerpc/platforms/44x/warp.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <asm/time.h> | 25 | #include <asm/time.h> |
26 | #include <asm/uic.h> | 26 | #include <asm/uic.h> |
27 | #include <asm/ppc4xx.h> | 27 | #include <asm/ppc4xx.h> |
28 | #include <asm/dma.h> | ||
28 | 29 | ||
29 | 30 | ||
30 | static __initdata struct of_device_id warp_of_bus[] = { | 31 | static __initdata struct of_device_id warp_of_bus[] = { |
diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c index 6e19b0ad5d26..3feffde9128d 100644 --- a/arch/powerpc/platforms/52xx/efika.c +++ b/arch/powerpc/platforms/52xx/efika.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <generated/utsrelease.h> | 13 | #include <generated/utsrelease.h> |
14 | #include <linux/pci.h> | 14 | #include <linux/pci.h> |
15 | #include <linux/of.h> | 15 | #include <linux/of.h> |
16 | #include <asm/dma.h> | ||
16 | #include <asm/prom.h> | 17 | #include <asm/prom.h> |
17 | #include <asm/time.h> | 18 | #include <asm/time.h> |
18 | #include <asm/machdep.h> | 19 | #include <asm/machdep.h> |
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig index f442120e0033..0c1e6903597e 100644 --- a/arch/powerpc/platforms/85xx/Kconfig +++ b/arch/powerpc/platforms/85xx/Kconfig | |||
@@ -274,7 +274,7 @@ config CORENET_GENERIC | |||
274 | For 32bit kernel, the following boards are supported: | 274 | For 32bit kernel, the following boards are supported: |
275 | P2041 RDB, P3041 DS, P4080 DS, kmcoge4, and OCA4080 | 275 | P2041 RDB, P3041 DS, P4080 DS, kmcoge4, and OCA4080 |
276 | For 64bit kernel, the following boards are supported: | 276 | For 64bit kernel, the following boards are supported: |
277 | T4240 QDS and B4 QDS | 277 | T208x QDS/RDB, T4240 QDS/RDB and B4 QDS |
278 | The following boards are supported for both 32bit and 64bit kernel: | 278 | The following boards are supported for both 32bit and 64bit kernel: |
279 | P5020 DS, P5040 DS and T104xQDS | 279 | P5020 DS, P5040 DS and T104xQDS |
280 | 280 | ||
diff --git a/arch/powerpc/platforms/85xx/corenet_generic.c b/arch/powerpc/platforms/85xx/corenet_generic.c index 5db1e117fdde..d22dd85e50bf 100644 --- a/arch/powerpc/platforms/85xx/corenet_generic.c +++ b/arch/powerpc/platforms/85xx/corenet_generic.c | |||
@@ -119,7 +119,11 @@ static const char * const boards[] __initconst = { | |||
119 | "fsl,P4080DS", | 119 | "fsl,P4080DS", |
120 | "fsl,P5020DS", | 120 | "fsl,P5020DS", |
121 | "fsl,P5040DS", | 121 | "fsl,P5040DS", |
122 | "fsl,T2080QDS", | ||
123 | "fsl,T2080RDB", | ||
124 | "fsl,T2081QDS", | ||
122 | "fsl,T4240QDS", | 125 | "fsl,T4240QDS", |
126 | "fsl,T4240RDB", | ||
123 | "fsl,B4860QDS", | 127 | "fsl,B4860QDS", |
124 | "fsl,B4420QDS", | 128 | "fsl,B4420QDS", |
125 | "fsl,B4220QDS", | 129 | "fsl,B4220QDS", |
@@ -129,28 +133,14 @@ static const char * const boards[] __initconst = { | |||
129 | NULL | 133 | NULL |
130 | }; | 134 | }; |
131 | 135 | ||
132 | static const char * const hv_boards[] __initconst = { | ||
133 | "fsl,P2041RDB-hv", | ||
134 | "fsl,P3041DS-hv", | ||
135 | "fsl,OCA4080-hv", | ||
136 | "fsl,P4080DS-hv", | ||
137 | "fsl,P5020DS-hv", | ||
138 | "fsl,P5040DS-hv", | ||
139 | "fsl,T4240QDS-hv", | ||
140 | "fsl,B4860QDS-hv", | ||
141 | "fsl,B4420QDS-hv", | ||
142 | "fsl,B4220QDS-hv", | ||
143 | "fsl,T1040QDS-hv", | ||
144 | "fsl,T1042QDS-hv", | ||
145 | NULL | ||
146 | }; | ||
147 | |||
148 | /* | 136 | /* |
149 | * Called very early, device-tree isn't unflattened | 137 | * Called very early, device-tree isn't unflattened |
150 | */ | 138 | */ |
151 | static int __init corenet_generic_probe(void) | 139 | static int __init corenet_generic_probe(void) |
152 | { | 140 | { |
153 | unsigned long root = of_get_flat_dt_root(); | 141 | unsigned long root = of_get_flat_dt_root(); |
142 | char hv_compat[24]; | ||
143 | int i; | ||
154 | #ifdef CONFIG_SMP | 144 | #ifdef CONFIG_SMP |
155 | extern struct smp_ops_t smp_85xx_ops; | 145 | extern struct smp_ops_t smp_85xx_ops; |
156 | #endif | 146 | #endif |
@@ -159,21 +149,26 @@ static int __init corenet_generic_probe(void) | |||
159 | return 1; | 149 | return 1; |
160 | 150 | ||
161 | /* Check if we're running under the Freescale hypervisor */ | 151 | /* Check if we're running under the Freescale hypervisor */ |
162 | if (of_flat_dt_match(root, hv_boards)) { | 152 | for (i = 0; boards[i]; i++) { |
163 | ppc_md.init_IRQ = ehv_pic_init; | 153 | snprintf(hv_compat, sizeof(hv_compat), "%s-hv", boards[i]); |
164 | ppc_md.get_irq = ehv_pic_get_irq; | 154 | if (of_flat_dt_is_compatible(root, hv_compat)) { |
165 | ppc_md.restart = fsl_hv_restart; | 155 | ppc_md.init_IRQ = ehv_pic_init; |
166 | ppc_md.power_off = fsl_hv_halt; | 156 | |
167 | ppc_md.halt = fsl_hv_halt; | 157 | ppc_md.get_irq = ehv_pic_get_irq; |
158 | ppc_md.restart = fsl_hv_restart; | ||
159 | ppc_md.power_off = fsl_hv_halt; | ||
160 | ppc_md.halt = fsl_hv_halt; | ||
168 | #ifdef CONFIG_SMP | 161 | #ifdef CONFIG_SMP |
169 | /* | 162 | /* |
170 | * Disable the timebase sync operations because we can't write | 163 | * Disable the timebase sync operations because we |
171 | * to the timebase registers under the hypervisor. | 164 | * can't write to the timebase registers under the |
172 | */ | 165 | * hypervisor. |
173 | smp_85xx_ops.give_timebase = NULL; | 166 | */ |
174 | smp_85xx_ops.take_timebase = NULL; | 167 | smp_85xx_ops.give_timebase = NULL; |
168 | smp_85xx_ops.take_timebase = NULL; | ||
175 | #endif | 169 | #endif |
176 | return 1; | 170 | return 1; |
171 | } | ||
177 | } | 172 | } |
178 | 173 | ||
179 | return 0; | 174 | return 0; |
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c index ba093f553678..d7c1e69f3070 100644 --- a/arch/powerpc/platforms/85xx/smp.c +++ b/arch/powerpc/platforms/85xx/smp.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <asm/dbell.h> | 28 | #include <asm/dbell.h> |
29 | #include <asm/fsl_guts.h> | 29 | #include <asm/fsl_guts.h> |
30 | #include <asm/code-patching.h> | 30 | #include <asm/code-patching.h> |
31 | #include <asm/cputhreads.h> | ||
31 | 32 | ||
32 | #include <sysdev/fsl_soc.h> | 33 | #include <sysdev/fsl_soc.h> |
33 | #include <sysdev/mpic.h> | 34 | #include <sysdev/mpic.h> |
@@ -168,6 +169,24 @@ static inline u32 read_spin_table_addr_l(void *spin_table) | |||
168 | return in_be32(&((struct epapr_spin_table *)spin_table)->addr_l); | 169 | return in_be32(&((struct epapr_spin_table *)spin_table)->addr_l); |
169 | } | 170 | } |
170 | 171 | ||
172 | #ifdef CONFIG_PPC64 | ||
173 | static void wake_hw_thread(void *info) | ||
174 | { | ||
175 | void fsl_secondary_thread_init(void); | ||
176 | unsigned long imsr1, inia1; | ||
177 | int nr = *(const int *)info; | ||
178 | |||
179 | imsr1 = MSR_KERNEL; | ||
180 | inia1 = *(unsigned long *)fsl_secondary_thread_init; | ||
181 | |||
182 | mttmr(TMRN_IMSR1, imsr1); | ||
183 | mttmr(TMRN_INIA1, inia1); | ||
184 | mtspr(SPRN_TENS, TEN_THREAD(1)); | ||
185 | |||
186 | smp_generic_kick_cpu(nr); | ||
187 | } | ||
188 | #endif | ||
189 | |||
171 | static int smp_85xx_kick_cpu(int nr) | 190 | static int smp_85xx_kick_cpu(int nr) |
172 | { | 191 | { |
173 | unsigned long flags; | 192 | unsigned long flags; |
@@ -183,6 +202,31 @@ static int smp_85xx_kick_cpu(int nr) | |||
183 | 202 | ||
184 | pr_debug("smp_85xx_kick_cpu: kick CPU #%d\n", nr); | 203 | pr_debug("smp_85xx_kick_cpu: kick CPU #%d\n", nr); |
185 | 204 | ||
205 | #ifdef CONFIG_PPC64 | ||
206 | /* Threads don't use the spin table */ | ||
207 | if (cpu_thread_in_core(nr) != 0) { | ||
208 | int primary = cpu_first_thread_sibling(nr); | ||
209 | |||
210 | if (WARN_ON_ONCE(!cpu_has_feature(CPU_FTR_SMT))) | ||
211 | return -ENOENT; | ||
212 | |||
213 | if (cpu_thread_in_core(nr) != 1) { | ||
214 | pr_err("%s: cpu %d: invalid hw thread %d\n", | ||
215 | __func__, nr, cpu_thread_in_core(nr)); | ||
216 | return -ENOENT; | ||
217 | } | ||
218 | |||
219 | if (!cpu_online(primary)) { | ||
220 | pr_err("%s: cpu %d: primary %d not online\n", | ||
221 | __func__, nr, primary); | ||
222 | return -ENOENT; | ||
223 | } | ||
224 | |||
225 | smp_call_function_single(primary, wake_hw_thread, &nr, 0); | ||
226 | return 0; | ||
227 | } | ||
228 | #endif | ||
229 | |||
186 | np = of_get_cpu_node(nr, NULL); | 230 | np = of_get_cpu_node(nr, NULL); |
187 | cpu_rel_addr = of_get_property(np, "cpu-release-addr", NULL); | 231 | cpu_rel_addr = of_get_property(np, "cpu-release-addr", NULL); |
188 | 232 | ||
diff --git a/arch/powerpc/platforms/8xx/m8xx_setup.c b/arch/powerpc/platforms/8xx/m8xx_setup.c index 587a2828b06c..d3037747031d 100644 --- a/arch/powerpc/platforms/8xx/m8xx_setup.c +++ b/arch/powerpc/platforms/8xx/m8xx_setup.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include <linux/fsl_devices.h> | 18 | #include <linux/fsl_devices.h> |
19 | 19 | ||
20 | #include <asm/io.h> | 20 | #include <asm/io.h> |
21 | #include <asm/mpc8xx.h> | ||
22 | #include <asm/8xx_immap.h> | 21 | #include <asm/8xx_immap.h> |
23 | #include <asm/prom.h> | 22 | #include <asm/prom.h> |
24 | #include <asm/fs_pd.h> | 23 | #include <asm/fs_pd.h> |
@@ -28,8 +27,6 @@ | |||
28 | 27 | ||
29 | #include "mpc8xx.h" | 28 | #include "mpc8xx.h" |
30 | 29 | ||
31 | struct mpc8xx_pcmcia_ops m8xx_pcmcia_ops; | ||
32 | |||
33 | extern int cpm_pic_init(void); | 30 | extern int cpm_pic_init(void); |
34 | extern int cpm_get_irq(void); | 31 | extern int cpm_get_irq(void); |
35 | 32 | ||
diff --git a/arch/powerpc/platforms/8xx/mpc885ads_setup.c b/arch/powerpc/platforms/8xx/mpc885ads_setup.c index c1262581b63c..5921dcb498fd 100644 --- a/arch/powerpc/platforms/8xx/mpc885ads_setup.c +++ b/arch/powerpc/platforms/8xx/mpc885ads_setup.c | |||
@@ -35,7 +35,6 @@ | |||
35 | #include <asm/page.h> | 35 | #include <asm/page.h> |
36 | #include <asm/processor.h> | 36 | #include <asm/processor.h> |
37 | #include <asm/time.h> | 37 | #include <asm/time.h> |
38 | #include <asm/mpc8xx.h> | ||
39 | #include <asm/8xx_immap.h> | 38 | #include <asm/8xx_immap.h> |
40 | #include <asm/cpm1.h> | 39 | #include <asm/cpm1.h> |
41 | #include <asm/fs_pd.h> | 40 | #include <asm/fs_pd.h> |
@@ -46,61 +45,6 @@ | |||
46 | 45 | ||
47 | static u32 __iomem *bcsr, *bcsr5; | 46 | static u32 __iomem *bcsr, *bcsr5; |
48 | 47 | ||
49 | #ifdef CONFIG_PCMCIA_M8XX | ||
50 | static void pcmcia_hw_setup(int slot, int enable) | ||
51 | { | ||
52 | if (enable) | ||
53 | clrbits32(&bcsr[1], BCSR1_PCCEN); | ||
54 | else | ||
55 | setbits32(&bcsr[1], BCSR1_PCCEN); | ||
56 | } | ||
57 | |||
58 | static int pcmcia_set_voltage(int slot, int vcc, int vpp) | ||
59 | { | ||
60 | u32 reg = 0; | ||
61 | |||
62 | switch (vcc) { | ||
63 | case 0: | ||
64 | break; | ||
65 | case 33: | ||
66 | reg |= BCSR1_PCCVCC0; | ||
67 | break; | ||
68 | case 50: | ||
69 | reg |= BCSR1_PCCVCC1; | ||
70 | break; | ||
71 | default: | ||
72 | return 1; | ||
73 | } | ||
74 | |||
75 | switch (vpp) { | ||
76 | case 0: | ||
77 | break; | ||
78 | case 33: | ||
79 | case 50: | ||
80 | if (vcc == vpp) | ||
81 | reg |= BCSR1_PCCVPP1; | ||
82 | else | ||
83 | return 1; | ||
84 | break; | ||
85 | case 120: | ||
86 | if ((vcc == 33) || (vcc == 50)) | ||
87 | reg |= BCSR1_PCCVPP0; | ||
88 | else | ||
89 | return 1; | ||
90 | default: | ||
91 | return 1; | ||
92 | } | ||
93 | |||
94 | /* first, turn off all power */ | ||
95 | clrbits32(&bcsr[1], 0x00610000); | ||
96 | |||
97 | /* enable new powersettings */ | ||
98 | setbits32(&bcsr[1], reg); | ||
99 | |||
100 | return 0; | ||
101 | } | ||
102 | #endif | ||
103 | |||
104 | struct cpm_pin { | 48 | struct cpm_pin { |
105 | int port, pin, flags; | 49 | int port, pin, flags; |
106 | }; | 50 | }; |
@@ -245,12 +189,6 @@ static void __init mpc885ads_setup_arch(void) | |||
245 | of_detach_node(np); | 189 | of_detach_node(np); |
246 | of_node_put(np); | 190 | of_node_put(np); |
247 | } | 191 | } |
248 | |||
249 | #ifdef CONFIG_PCMCIA_M8XX | ||
250 | /* Set up board specific hook-ups.*/ | ||
251 | m8xx_pcmcia_ops.hw_ctrl = pcmcia_hw_setup; | ||
252 | m8xx_pcmcia_ops.voltage_set = pcmcia_set_voltage; | ||
253 | #endif | ||
254 | } | 192 | } |
255 | 193 | ||
256 | static int __init mpc885ads_probe(void) | 194 | static int __init mpc885ads_probe(void) |
diff --git a/arch/powerpc/platforms/8xx/tqm8xx_setup.c b/arch/powerpc/platforms/8xx/tqm8xx_setup.c index 251aba8759e4..dda607807def 100644 --- a/arch/powerpc/platforms/8xx/tqm8xx_setup.c +++ b/arch/powerpc/platforms/8xx/tqm8xx_setup.c | |||
@@ -37,7 +37,6 @@ | |||
37 | #include <asm/page.h> | 37 | #include <asm/page.h> |
38 | #include <asm/processor.h> | 38 | #include <asm/processor.h> |
39 | #include <asm/time.h> | 39 | #include <asm/time.h> |
40 | #include <asm/mpc8xx.h> | ||
41 | #include <asm/8xx_immap.h> | 40 | #include <asm/8xx_immap.h> |
42 | #include <asm/cpm1.h> | 41 | #include <asm/cpm1.h> |
43 | #include <asm/fs_pd.h> | 42 | #include <asm/fs_pd.h> |
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype index a41bd023647a..e8bc40869cbd 100644 --- a/arch/powerpc/platforms/Kconfig.cputype +++ b/arch/powerpc/platforms/Kconfig.cputype | |||
@@ -61,7 +61,7 @@ choice | |||
61 | help | 61 | help |
62 | There are two families of 64 bit PowerPC chips supported. | 62 | There are two families of 64 bit PowerPC chips supported. |
63 | The most common ones are the desktop and server CPUs | 63 | The most common ones are the desktop and server CPUs |
64 | (POWER3, RS64, POWER4, POWER5, POWER5+, POWER6, ...) | 64 | (POWER4, POWER5, 970, POWER5+, POWER6, POWER7, POWER8 ...) |
65 | 65 | ||
66 | The other are the "embedded" processors compliant with the | 66 | The other are the "embedded" processors compliant with the |
67 | "Book 3E" variant of the architecture | 67 | "Book 3E" variant of the architecture |
@@ -140,14 +140,6 @@ config 6xx | |||
140 | depends on PPC32 && PPC_BOOK3S | 140 | depends on PPC32 && PPC_BOOK3S |
141 | select PPC_HAVE_PMU_SUPPORT | 141 | select PPC_HAVE_PMU_SUPPORT |
142 | 142 | ||
143 | config POWER3 | ||
144 | depends on PPC64 && PPC_BOOK3S | ||
145 | def_bool y | ||
146 | |||
147 | config POWER4 | ||
148 | depends on PPC64 && PPC_BOOK3S | ||
149 | def_bool y | ||
150 | |||
151 | config TUNE_CELL | 143 | config TUNE_CELL |
152 | bool "Optimize for Cell Broadband Engine" | 144 | bool "Optimize for Cell Broadband Engine" |
153 | depends on PPC64 && PPC_BOOK3S | 145 | depends on PPC64 && PPC_BOOK3S |
@@ -244,7 +236,7 @@ config PHYS_64BIT | |||
244 | 236 | ||
245 | config ALTIVEC | 237 | config ALTIVEC |
246 | bool "AltiVec Support" | 238 | bool "AltiVec Support" |
247 | depends on 6xx || POWER4 || (PPC_E500MC && PPC64) | 239 | depends on 6xx || PPC_BOOK3S_64 || (PPC_E500MC && PPC64) |
248 | ---help--- | 240 | ---help--- |
249 | This option enables kernel support for the Altivec extensions to the | 241 | This option enables kernel support for the Altivec extensions to the |
250 | PowerPC processor. The kernel currently supports saving and restoring | 242 | PowerPC processor. The kernel currently supports saving and restoring |
@@ -260,7 +252,7 @@ config ALTIVEC | |||
260 | 252 | ||
261 | config VSX | 253 | config VSX |
262 | bool "VSX Support" | 254 | bool "VSX Support" |
263 | depends on POWER4 && ALTIVEC && PPC_FPU | 255 | depends on PPC_BOOK3S_64 && ALTIVEC && PPC_FPU |
264 | ---help--- | 256 | ---help--- |
265 | 257 | ||
266 | This option enables kernel support for the Vector Scaler extensions | 258 | This option enables kernel support for the Vector Scaler extensions |
@@ -276,7 +268,7 @@ config VSX | |||
276 | 268 | ||
277 | config PPC_ICSWX | 269 | config PPC_ICSWX |
278 | bool "Support for PowerPC icswx coprocessor instruction" | 270 | bool "Support for PowerPC icswx coprocessor instruction" |
279 | depends on POWER4 | 271 | depends on PPC_BOOK3S_64 |
280 | default n | 272 | default n |
281 | ---help--- | 273 | ---help--- |
282 | 274 | ||
@@ -294,7 +286,7 @@ config PPC_ICSWX | |||
294 | 286 | ||
295 | config PPC_ICSWX_PID | 287 | config PPC_ICSWX_PID |
296 | bool "icswx requires direct PID management" | 288 | bool "icswx requires direct PID management" |
297 | depends on PPC_ICSWX && POWER4 | 289 | depends on PPC_ICSWX |
298 | default y | 290 | default y |
299 | ---help--- | 291 | ---help--- |
300 | The PID register in server is used explicitly for ICSWX. In | 292 | The PID register in server is used explicitly for ICSWX. In |
diff --git a/arch/powerpc/platforms/amigaone/setup.c b/arch/powerpc/platforms/amigaone/setup.c index 03aabc0e16ac..2fe12046279e 100644 --- a/arch/powerpc/platforms/amigaone/setup.c +++ b/arch/powerpc/platforms/amigaone/setup.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <asm/i8259.h> | 24 | #include <asm/i8259.h> |
25 | #include <asm/time.h> | 25 | #include <asm/time.h> |
26 | #include <asm/udbg.h> | 26 | #include <asm/udbg.h> |
27 | #include <asm/dma.h> | ||
27 | 28 | ||
28 | extern void __flush_disable_L1(void); | 29 | extern void __flush_disable_L1(void); |
29 | 30 | ||
diff --git a/arch/powerpc/platforms/powermac/Kconfig b/arch/powerpc/platforms/powermac/Kconfig index 1afd10f67858..607124bae2e7 100644 --- a/arch/powerpc/platforms/powermac/Kconfig +++ b/arch/powerpc/platforms/powermac/Kconfig | |||
@@ -10,7 +10,7 @@ config PPC_PMAC | |||
10 | 10 | ||
11 | config PPC_PMAC64 | 11 | config PPC_PMAC64 |
12 | bool | 12 | bool |
13 | depends on PPC_PMAC && POWER4 | 13 | depends on PPC_PMAC && PPC64 |
14 | select MPIC | 14 | select MPIC |
15 | select U3_DART | 15 | select U3_DART |
16 | select MPIC_U3_HT_IRQS | 16 | select MPIC_U3_HT_IRQS |
diff --git a/arch/powerpc/platforms/powermac/feature.c b/arch/powerpc/platforms/powermac/feature.c index 63d82bbc05e9..4882bfd90e27 100644 --- a/arch/powerpc/platforms/powermac/feature.c +++ b/arch/powerpc/platforms/powermac/feature.c | |||
@@ -158,7 +158,7 @@ static inline int simple_feature_tweak(struct device_node *node, int type, | |||
158 | return 0; | 158 | return 0; |
159 | } | 159 | } |
160 | 160 | ||
161 | #ifndef CONFIG_POWER4 | 161 | #ifndef CONFIG_PPC64 |
162 | 162 | ||
163 | static long ohare_htw_scc_enable(struct device_node *node, long param, | 163 | static long ohare_htw_scc_enable(struct device_node *node, long param, |
164 | long value) | 164 | long value) |
@@ -1318,7 +1318,7 @@ intrepid_aack_delay_enable(struct device_node *node, long param, long value) | |||
1318 | } | 1318 | } |
1319 | 1319 | ||
1320 | 1320 | ||
1321 | #endif /* CONFIG_POWER4 */ | 1321 | #endif /* CONFIG_PPC64 */ |
1322 | 1322 | ||
1323 | static long | 1323 | static long |
1324 | core99_read_gpio(struct device_node *node, long param, long value) | 1324 | core99_read_gpio(struct device_node *node, long param, long value) |
@@ -1338,7 +1338,7 @@ core99_write_gpio(struct device_node *node, long param, long value) | |||
1338 | return 0; | 1338 | return 0; |
1339 | } | 1339 | } |
1340 | 1340 | ||
1341 | #ifdef CONFIG_POWER4 | 1341 | #ifdef CONFIG_PPC64 |
1342 | static long g5_gmac_enable(struct device_node *node, long param, long value) | 1342 | static long g5_gmac_enable(struct device_node *node, long param, long value) |
1343 | { | 1343 | { |
1344 | struct macio_chip *macio = &macio_chips[0]; | 1344 | struct macio_chip *macio = &macio_chips[0]; |
@@ -1550,9 +1550,9 @@ void g5_phy_disable_cpu1(void) | |||
1550 | if (uninorth_maj == 3) | 1550 | if (uninorth_maj == 3) |
1551 | UN_OUT(U3_API_PHY_CONFIG_1, 0); | 1551 | UN_OUT(U3_API_PHY_CONFIG_1, 0); |
1552 | } | 1552 | } |
1553 | #endif /* CONFIG_POWER4 */ | 1553 | #endif /* CONFIG_PPC64 */ |
1554 | 1554 | ||
1555 | #ifndef CONFIG_POWER4 | 1555 | #ifndef CONFIG_PPC64 |
1556 | 1556 | ||
1557 | 1557 | ||
1558 | #ifdef CONFIG_PM | 1558 | #ifdef CONFIG_PM |
@@ -1864,7 +1864,7 @@ core99_sleep_state(struct device_node *node, long param, long value) | |||
1864 | return 0; | 1864 | return 0; |
1865 | } | 1865 | } |
1866 | 1866 | ||
1867 | #endif /* CONFIG_POWER4 */ | 1867 | #endif /* CONFIG_PPC64 */ |
1868 | 1868 | ||
1869 | static long | 1869 | static long |
1870 | generic_dev_can_wake(struct device_node *node, long param, long value) | 1870 | generic_dev_can_wake(struct device_node *node, long param, long value) |
@@ -1906,7 +1906,7 @@ static struct feature_table_entry any_features[] = { | |||
1906 | { 0, NULL } | 1906 | { 0, NULL } |
1907 | }; | 1907 | }; |
1908 | 1908 | ||
1909 | #ifndef CONFIG_POWER4 | 1909 | #ifndef CONFIG_PPC64 |
1910 | 1910 | ||
1911 | /* OHare based motherboards. Currently, we only use these on the | 1911 | /* OHare based motherboards. Currently, we only use these on the |
1912 | * 2400,3400 and 3500 series powerbooks. Some older desktops seem | 1912 | * 2400,3400 and 3500 series powerbooks. Some older desktops seem |
@@ -2056,7 +2056,7 @@ static struct feature_table_entry intrepid_features[] = { | |||
2056 | { 0, NULL } | 2056 | { 0, NULL } |
2057 | }; | 2057 | }; |
2058 | 2058 | ||
2059 | #else /* CONFIG_POWER4 */ | 2059 | #else /* CONFIG_PPC64 */ |
2060 | 2060 | ||
2061 | /* G5 features | 2061 | /* G5 features |
2062 | */ | 2062 | */ |
@@ -2074,10 +2074,10 @@ static struct feature_table_entry g5_features[] = { | |||
2074 | { 0, NULL } | 2074 | { 0, NULL } |
2075 | }; | 2075 | }; |
2076 | 2076 | ||
2077 | #endif /* CONFIG_POWER4 */ | 2077 | #endif /* CONFIG_PPC64 */ |
2078 | 2078 | ||
2079 | static struct pmac_mb_def pmac_mb_defs[] = { | 2079 | static struct pmac_mb_def pmac_mb_defs[] = { |
2080 | #ifndef CONFIG_POWER4 | 2080 | #ifndef CONFIG_PPC64 |
2081 | /* | 2081 | /* |
2082 | * Desktops | 2082 | * Desktops |
2083 | */ | 2083 | */ |
@@ -2342,7 +2342,7 @@ static struct pmac_mb_def pmac_mb_defs[] = { | |||
2342 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, | 2342 | PMAC_TYPE_UNKNOWN_INTREPID, intrepid_features, |
2343 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, | 2343 | PMAC_MB_MAY_SLEEP | PMAC_MB_HAS_FW_POWER | PMAC_MB_MOBILE, |
2344 | }, | 2344 | }, |
2345 | #else /* CONFIG_POWER4 */ | 2345 | #else /* CONFIG_PPC64 */ |
2346 | { "PowerMac7,2", "PowerMac G5", | 2346 | { "PowerMac7,2", "PowerMac G5", |
2347 | PMAC_TYPE_POWERMAC_G5, g5_features, | 2347 | PMAC_TYPE_POWERMAC_G5, g5_features, |
2348 | 0, | 2348 | 0, |
@@ -2373,7 +2373,7 @@ static struct pmac_mb_def pmac_mb_defs[] = { | |||
2373 | 0, | 2373 | 0, |
2374 | }, | 2374 | }, |
2375 | #endif /* CONFIG_PPC64 */ | 2375 | #endif /* CONFIG_PPC64 */ |
2376 | #endif /* CONFIG_POWER4 */ | 2376 | #endif /* CONFIG_PPC64 */ |
2377 | }; | 2377 | }; |
2378 | 2378 | ||
2379 | /* | 2379 | /* |
@@ -2441,7 +2441,7 @@ static int __init probe_motherboard(void) | |||
2441 | 2441 | ||
2442 | /* Fallback to selection depending on mac-io chip type */ | 2442 | /* Fallback to selection depending on mac-io chip type */ |
2443 | switch(macio->type) { | 2443 | switch(macio->type) { |
2444 | #ifndef CONFIG_POWER4 | 2444 | #ifndef CONFIG_PPC64 |
2445 | case macio_grand_central: | 2445 | case macio_grand_central: |
2446 | pmac_mb.model_id = PMAC_TYPE_PSURGE; | 2446 | pmac_mb.model_id = PMAC_TYPE_PSURGE; |
2447 | pmac_mb.model_name = "Unknown PowerSurge"; | 2447 | pmac_mb.model_name = "Unknown PowerSurge"; |
@@ -2475,7 +2475,7 @@ static int __init probe_motherboard(void) | |||
2475 | pmac_mb.model_name = "Unknown Intrepid-based"; | 2475 | pmac_mb.model_name = "Unknown Intrepid-based"; |
2476 | pmac_mb.features = intrepid_features; | 2476 | pmac_mb.features = intrepid_features; |
2477 | break; | 2477 | break; |
2478 | #else /* CONFIG_POWER4 */ | 2478 | #else /* CONFIG_PPC64 */ |
2479 | case macio_keylargo2: | 2479 | case macio_keylargo2: |
2480 | pmac_mb.model_id = PMAC_TYPE_UNKNOWN_K2; | 2480 | pmac_mb.model_id = PMAC_TYPE_UNKNOWN_K2; |
2481 | pmac_mb.model_name = "Unknown K2-based"; | 2481 | pmac_mb.model_name = "Unknown K2-based"; |
@@ -2486,13 +2486,13 @@ static int __init probe_motherboard(void) | |||
2486 | pmac_mb.model_name = "Unknown Shasta-based"; | 2486 | pmac_mb.model_name = "Unknown Shasta-based"; |
2487 | pmac_mb.features = g5_features; | 2487 | pmac_mb.features = g5_features; |
2488 | break; | 2488 | break; |
2489 | #endif /* CONFIG_POWER4 */ | 2489 | #endif /* CONFIG_PPC64 */ |
2490 | default: | 2490 | default: |
2491 | ret = -ENODEV; | 2491 | ret = -ENODEV; |
2492 | goto done; | 2492 | goto done; |
2493 | } | 2493 | } |
2494 | found: | 2494 | found: |
2495 | #ifndef CONFIG_POWER4 | 2495 | #ifndef CONFIG_PPC64 |
2496 | /* Fixup Hooper vs. Comet */ | 2496 | /* Fixup Hooper vs. Comet */ |
2497 | if (pmac_mb.model_id == PMAC_TYPE_HOOPER) { | 2497 | if (pmac_mb.model_id == PMAC_TYPE_HOOPER) { |
2498 | u32 __iomem * mach_id_ptr = ioremap(0xf3000034, 4); | 2498 | u32 __iomem * mach_id_ptr = ioremap(0xf3000034, 4); |
@@ -2546,9 +2546,9 @@ found: | |||
2546 | */ | 2546 | */ |
2547 | powersave_lowspeed = 1; | 2547 | powersave_lowspeed = 1; |
2548 | 2548 | ||
2549 | #else /* CONFIG_POWER4 */ | 2549 | #else /* CONFIG_PPC64 */ |
2550 | powersave_nap = 1; | 2550 | powersave_nap = 1; |
2551 | #endif /* CONFIG_POWER4 */ | 2551 | #endif /* CONFIG_PPC64 */ |
2552 | 2552 | ||
2553 | /* Check for "mobile" machine */ | 2553 | /* Check for "mobile" machine */ |
2554 | if (model && (strncmp(model, "PowerBook", 9) == 0 | 2554 | if (model && (strncmp(model, "PowerBook", 9) == 0 |
@@ -2786,7 +2786,7 @@ set_initial_features(void) | |||
2786 | MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE); | 2786 | MACIO_BIS(OHARE_FCR, OH_IOBUS_ENABLE); |
2787 | } | 2787 | } |
2788 | 2788 | ||
2789 | #ifdef CONFIG_POWER4 | 2789 | #ifdef CONFIG_PPC64 |
2790 | if (macio_chips[0].type == macio_keylargo2 || | 2790 | if (macio_chips[0].type == macio_keylargo2 || |
2791 | macio_chips[0].type == macio_shasta) { | 2791 | macio_chips[0].type == macio_shasta) { |
2792 | #ifndef CONFIG_SMP | 2792 | #ifndef CONFIG_SMP |
@@ -2805,28 +2805,23 @@ set_initial_features(void) | |||
2805 | /* Enable GMAC for now for PCI probing. It will be disabled | 2805 | /* Enable GMAC for now for PCI probing. It will be disabled |
2806 | * later on after PCI probe | 2806 | * later on after PCI probe |
2807 | */ | 2807 | */ |
2808 | np = of_find_node_by_name(NULL, "ethernet"); | 2808 | for_each_node_by_name(np, "ethernet") |
2809 | while(np) { | ||
2810 | if (of_device_is_compatible(np, "K2-GMAC")) | 2809 | if (of_device_is_compatible(np, "K2-GMAC")) |
2811 | g5_gmac_enable(np, 0, 1); | 2810 | g5_gmac_enable(np, 0, 1); |
2812 | np = of_find_node_by_name(np, "ethernet"); | ||
2813 | } | ||
2814 | 2811 | ||
2815 | /* Enable FW before PCI probe. Will be disabled later on | 2812 | /* Enable FW before PCI probe. Will be disabled later on |
2816 | * Note: We should have a batter way to check that we are | 2813 | * Note: We should have a batter way to check that we are |
2817 | * dealing with uninorth internal cell and not a PCI cell | 2814 | * dealing with uninorth internal cell and not a PCI cell |
2818 | * on the external PCI. The code below works though. | 2815 | * on the external PCI. The code below works though. |
2819 | */ | 2816 | */ |
2820 | np = of_find_node_by_name(NULL, "firewire"); | 2817 | for_each_node_by_name(np, "firewire") { |
2821 | while(np) { | ||
2822 | if (of_device_is_compatible(np, "pci106b,5811")) { | 2818 | if (of_device_is_compatible(np, "pci106b,5811")) { |
2823 | macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED; | 2819 | macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED; |
2824 | g5_fw_enable(np, 0, 1); | 2820 | g5_fw_enable(np, 0, 1); |
2825 | } | 2821 | } |
2826 | np = of_find_node_by_name(np, "firewire"); | ||
2827 | } | 2822 | } |
2828 | } | 2823 | } |
2829 | #else /* CONFIG_POWER4 */ | 2824 | #else /* CONFIG_PPC64 */ |
2830 | 2825 | ||
2831 | if (macio_chips[0].type == macio_keylargo || | 2826 | if (macio_chips[0].type == macio_keylargo || |
2832 | macio_chips[0].type == macio_pangea || | 2827 | macio_chips[0].type == macio_pangea || |
@@ -2834,13 +2829,11 @@ set_initial_features(void) | |||
2834 | /* Enable GMAC for now for PCI probing. It will be disabled | 2829 | /* Enable GMAC for now for PCI probing. It will be disabled |
2835 | * later on after PCI probe | 2830 | * later on after PCI probe |
2836 | */ | 2831 | */ |
2837 | np = of_find_node_by_name(NULL, "ethernet"); | 2832 | for_each_node_by_name(np, "ethernet") { |
2838 | while(np) { | ||
2839 | if (np->parent | 2833 | if (np->parent |
2840 | && of_device_is_compatible(np->parent, "uni-north") | 2834 | && of_device_is_compatible(np->parent, "uni-north") |
2841 | && of_device_is_compatible(np, "gmac")) | 2835 | && of_device_is_compatible(np, "gmac")) |
2842 | core99_gmac_enable(np, 0, 1); | 2836 | core99_gmac_enable(np, 0, 1); |
2843 | np = of_find_node_by_name(np, "ethernet"); | ||
2844 | } | 2837 | } |
2845 | 2838 | ||
2846 | /* Enable FW before PCI probe. Will be disabled later on | 2839 | /* Enable FW before PCI probe. Will be disabled later on |
@@ -2848,8 +2841,7 @@ set_initial_features(void) | |||
2848 | * dealing with uninorth internal cell and not a PCI cell | 2841 | * dealing with uninorth internal cell and not a PCI cell |
2849 | * on the external PCI. The code below works though. | 2842 | * on the external PCI. The code below works though. |
2850 | */ | 2843 | */ |
2851 | np = of_find_node_by_name(NULL, "firewire"); | 2844 | for_each_node_by_name(np, "firewire") { |
2852 | while(np) { | ||
2853 | if (np->parent | 2845 | if (np->parent |
2854 | && of_device_is_compatible(np->parent, "uni-north") | 2846 | && of_device_is_compatible(np->parent, "uni-north") |
2855 | && (of_device_is_compatible(np, "pci106b,18") || | 2847 | && (of_device_is_compatible(np, "pci106b,18") || |
@@ -2858,18 +2850,16 @@ set_initial_features(void) | |||
2858 | macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED; | 2850 | macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED; |
2859 | core99_firewire_enable(np, 0, 1); | 2851 | core99_firewire_enable(np, 0, 1); |
2860 | } | 2852 | } |
2861 | np = of_find_node_by_name(np, "firewire"); | ||
2862 | } | 2853 | } |
2863 | 2854 | ||
2864 | /* Enable ATA-100 before PCI probe. */ | 2855 | /* Enable ATA-100 before PCI probe. */ |
2865 | np = of_find_node_by_name(NULL, "ata-6"); | 2856 | np = of_find_node_by_name(NULL, "ata-6"); |
2866 | while(np) { | 2857 | for_each_node_by_name(np, "ata-6") { |
2867 | if (np->parent | 2858 | if (np->parent |
2868 | && of_device_is_compatible(np->parent, "uni-north") | 2859 | && of_device_is_compatible(np->parent, "uni-north") |
2869 | && of_device_is_compatible(np, "kauai-ata")) { | 2860 | && of_device_is_compatible(np, "kauai-ata")) { |
2870 | core99_ata100_enable(np, 1); | 2861 | core99_ata100_enable(np, 1); |
2871 | } | 2862 | } |
2872 | np = of_find_node_by_name(np, "ata-6"); | ||
2873 | } | 2863 | } |
2874 | 2864 | ||
2875 | /* Switch airport off */ | 2865 | /* Switch airport off */ |
@@ -2895,7 +2885,7 @@ set_initial_features(void) | |||
2895 | MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N); | 2885 | MACIO_BIC(HEATHROW_FCR, HRW_SOUND_POWER_N); |
2896 | } | 2886 | } |
2897 | 2887 | ||
2898 | #endif /* CONFIG_POWER4 */ | 2888 | #endif /* CONFIG_PPC64 */ |
2899 | 2889 | ||
2900 | /* On all machines, switch modem & serial ports off */ | 2890 | /* On all machines, switch modem & serial ports off */ |
2901 | for_each_node_by_name(np, "ch-a") | 2891 | for_each_node_by_name(np, "ch-a") |
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c index cf7009b8c7b6..7e868ccf3b0d 100644 --- a/arch/powerpc/platforms/powermac/pci.c +++ b/arch/powerpc/platforms/powermac/pci.c | |||
@@ -698,7 +698,7 @@ static void __init fixup_nec_usb2(void) | |||
698 | { | 698 | { |
699 | struct device_node *nec; | 699 | struct device_node *nec; |
700 | 700 | ||
701 | for (nec = NULL; (nec = of_find_node_by_name(nec, "usb")) != NULL;) { | 701 | for_each_node_by_name(nec, "usb") { |
702 | struct pci_controller *hose; | 702 | struct pci_controller *hose; |
703 | u32 data; | 703 | u32 data; |
704 | const u32 *prop; | 704 | const u32 *prop; |
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c index 5cbd4d67d5c4..af094ae03dbb 100644 --- a/arch/powerpc/platforms/powermac/smp.c +++ b/arch/powerpc/platforms/powermac/smp.c | |||
@@ -577,7 +577,7 @@ static void __init smp_core99_setup_i2c_hwsync(int ncpus) | |||
577 | int ok; | 577 | int ok; |
578 | 578 | ||
579 | /* Look for the clock chip */ | 579 | /* Look for the clock chip */ |
580 | while ((cc = of_find_node_by_name(cc, "i2c-hwclock")) != NULL) { | 580 | for_each_node_by_name(cc, "i2c-hwclock") { |
581 | p = of_get_parent(cc); | 581 | p = of_get_parent(cc); |
582 | ok = p && of_device_is_compatible(p, "uni-n-i2c"); | 582 | ok = p && of_device_is_compatible(p, "uni-n-i2c"); |
583 | of_node_put(p); | 583 | of_node_put(p); |
diff --git a/arch/powerpc/platforms/powermac/udbg_adb.c b/arch/powerpc/platforms/powermac/udbg_adb.c index 44e0b55a2a02..366bd221edec 100644 --- a/arch/powerpc/platforms/powermac/udbg_adb.c +++ b/arch/powerpc/platforms/powermac/udbg_adb.c | |||
@@ -191,7 +191,7 @@ int __init udbg_adb_init(int force_btext) | |||
191 | * of type "adb". If not, we return a failure, but we keep the | 191 | * of type "adb". If not, we return a failure, but we keep the |
192 | * bext output set for now | 192 | * bext output set for now |
193 | */ | 193 | */ |
194 | for (np = NULL; (np = of_find_node_by_name(np, "keyboard")) != NULL;) { | 194 | for_each_node_by_name(np, "keyboard") { |
195 | struct device_node *parent = of_get_parent(np); | 195 | struct device_node *parent = of_get_parent(np); |
196 | int found = (parent && strcmp(parent->type, "adb") == 0); | 196 | int found = (parent && strcmp(parent->type, "adb") == 0); |
197 | of_node_put(parent); | 197 | of_node_put(parent); |
diff --git a/arch/powerpc/platforms/powernv/Makefile b/arch/powerpc/platforms/powernv/Makefile index 4ad227d04c1a..f241accc053d 100644 --- a/arch/powerpc/platforms/powernv/Makefile +++ b/arch/powerpc/platforms/powernv/Makefile | |||
@@ -1,10 +1,11 @@ | |||
1 | obj-y += setup.o opal-wrappers.o opal.o opal-async.o | 1 | obj-y += setup.o opal-wrappers.o opal.o opal-async.o |
2 | obj-y += opal-rtc.o opal-nvram.o opal-lpc.o opal-flash.o | 2 | obj-y += opal-rtc.o opal-nvram.o opal-lpc.o opal-flash.o |
3 | obj-y += rng.o opal-elog.o opal-dump.o opal-sysparam.o opal-sensor.o | 3 | obj-y += rng.o opal-elog.o opal-dump.o opal-sysparam.o opal-sensor.o |
4 | obj-y += opal-msglog.o | 4 | obj-y += opal-msglog.o opal-hmi.o |
5 | 5 | ||
6 | obj-$(CONFIG_SMP) += smp.o subcore.o subcore-asm.o | 6 | obj-$(CONFIG_SMP) += smp.o subcore.o subcore-asm.o |
7 | obj-$(CONFIG_PCI) += pci.o pci-p5ioc2.o pci-ioda.o | 7 | obj-$(CONFIG_PCI) += pci.o pci-p5ioc2.o pci-ioda.o |
8 | obj-$(CONFIG_EEH) += eeh-ioda.o eeh-powernv.o | 8 | obj-$(CONFIG_EEH) += eeh-ioda.o eeh-powernv.o |
9 | obj-$(CONFIG_PPC_SCOM) += opal-xscom.o | 9 | obj-$(CONFIG_PPC_SCOM) += opal-xscom.o |
10 | obj-$(CONFIG_MEMORY_FAILURE) += opal-memory-errors.o | 10 | obj-$(CONFIG_MEMORY_FAILURE) += opal-memory-errors.o |
11 | obj-$(CONFIG_TRACEPOINTS) += opal-tracepoints.o | ||
diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c b/arch/powerpc/platforms/powernv/eeh-ioda.c index 8ad0c5b891f4..c945bed4dc9e 100644 --- a/arch/powerpc/platforms/powernv/eeh-ioda.c +++ b/arch/powerpc/platforms/powernv/eeh-ioda.c | |||
@@ -187,10 +187,10 @@ static int ioda_eeh_post_init(struct pci_controller *hose) | |||
187 | */ | 187 | */ |
188 | static int ioda_eeh_set_option(struct eeh_pe *pe, int option) | 188 | static int ioda_eeh_set_option(struct eeh_pe *pe, int option) |
189 | { | 189 | { |
190 | s64 ret; | ||
191 | u32 pe_no; | ||
192 | struct pci_controller *hose = pe->phb; | 190 | struct pci_controller *hose = pe->phb; |
193 | struct pnv_phb *phb = hose->private_data; | 191 | struct pnv_phb *phb = hose->private_data; |
192 | int enable, ret = 0; | ||
193 | s64 rc; | ||
194 | 194 | ||
195 | /* Check on PE number */ | 195 | /* Check on PE number */ |
196 | if (pe->addr < 0 || pe->addr >= phb->ioda.total_pe) { | 196 | if (pe->addr < 0 || pe->addr >= phb->ioda.total_pe) { |
@@ -201,184 +201,214 @@ static int ioda_eeh_set_option(struct eeh_pe *pe, int option) | |||
201 | return -EINVAL; | 201 | return -EINVAL; |
202 | } | 202 | } |
203 | 203 | ||
204 | pe_no = pe->addr; | ||
205 | switch (option) { | 204 | switch (option) { |
206 | case EEH_OPT_DISABLE: | 205 | case EEH_OPT_DISABLE: |
207 | ret = -EEXIST; | 206 | return -EPERM; |
208 | break; | ||
209 | case EEH_OPT_ENABLE: | 207 | case EEH_OPT_ENABLE: |
210 | ret = 0; | 208 | return 0; |
211 | break; | ||
212 | case EEH_OPT_THAW_MMIO: | 209 | case EEH_OPT_THAW_MMIO: |
213 | ret = opal_pci_eeh_freeze_clear(phb->opal_id, pe_no, | 210 | enable = OPAL_EEH_ACTION_CLEAR_FREEZE_MMIO; |
214 | OPAL_EEH_ACTION_CLEAR_FREEZE_MMIO); | ||
215 | if (ret) { | ||
216 | pr_warning("%s: Failed to enable MMIO for " | ||
217 | "PHB#%x-PE#%x, err=%lld\n", | ||
218 | __func__, hose->global_number, pe_no, ret); | ||
219 | return -EIO; | ||
220 | } | ||
221 | |||
222 | break; | 211 | break; |
223 | case EEH_OPT_THAW_DMA: | 212 | case EEH_OPT_THAW_DMA: |
224 | ret = opal_pci_eeh_freeze_clear(phb->opal_id, pe_no, | 213 | enable = OPAL_EEH_ACTION_CLEAR_FREEZE_DMA; |
225 | OPAL_EEH_ACTION_CLEAR_FREEZE_DMA); | ||
226 | if (ret) { | ||
227 | pr_warning("%s: Failed to enable DMA for " | ||
228 | "PHB#%x-PE#%x, err=%lld\n", | ||
229 | __func__, hose->global_number, pe_no, ret); | ||
230 | return -EIO; | ||
231 | } | ||
232 | |||
233 | break; | 214 | break; |
234 | default: | 215 | default: |
235 | pr_warning("%s: Invalid option %d\n", __func__, option); | 216 | pr_warn("%s: Invalid option %d\n", |
217 | __func__, option); | ||
236 | return -EINVAL; | 218 | return -EINVAL; |
237 | } | 219 | } |
238 | 220 | ||
221 | /* If PHB supports compound PE, to handle it */ | ||
222 | if (phb->unfreeze_pe) { | ||
223 | ret = phb->unfreeze_pe(phb, pe->addr, enable); | ||
224 | } else { | ||
225 | rc = opal_pci_eeh_freeze_clear(phb->opal_id, | ||
226 | pe->addr, | ||
227 | enable); | ||
228 | if (rc != OPAL_SUCCESS) { | ||
229 | pr_warn("%s: Failure %lld enable %d for PHB#%x-PE#%x\n", | ||
230 | __func__, rc, option, phb->hose->global_number, | ||
231 | pe->addr); | ||
232 | ret = -EIO; | ||
233 | } | ||
234 | } | ||
235 | |||
239 | return ret; | 236 | return ret; |
240 | } | 237 | } |
241 | 238 | ||
242 | static void ioda_eeh_phb_diag(struct pci_controller *hose) | 239 | static void ioda_eeh_phb_diag(struct eeh_pe *pe) |
243 | { | 240 | { |
244 | struct pnv_phb *phb = hose->private_data; | 241 | struct pnv_phb *phb = pe->phb->private_data; |
245 | long rc; | 242 | long rc; |
246 | 243 | ||
247 | rc = opal_pci_get_phb_diag_data2(phb->opal_id, phb->diag.blob, | 244 | rc = opal_pci_get_phb_diag_data2(phb->opal_id, pe->data, |
248 | PNV_PCI_DIAG_BUF_SIZE); | 245 | PNV_PCI_DIAG_BUF_SIZE); |
249 | if (rc != OPAL_SUCCESS) { | 246 | if (rc != OPAL_SUCCESS) |
250 | pr_warning("%s: Failed to get diag-data for PHB#%x (%ld)\n", | 247 | pr_warn("%s: Failed to get diag-data for PHB#%x (%ld)\n", |
251 | __func__, hose->global_number, rc); | 248 | __func__, pe->phb->global_number, rc); |
252 | return; | ||
253 | } | ||
254 | |||
255 | pnv_pci_dump_phb_diag_data(hose, phb->diag.blob); | ||
256 | } | 249 | } |
257 | 250 | ||
258 | /** | 251 | static int ioda_eeh_get_phb_state(struct eeh_pe *pe) |
259 | * ioda_eeh_get_state - Retrieve the state of PE | ||
260 | * @pe: EEH PE | ||
261 | * | ||
262 | * The PE's state should be retrieved from the PEEV, PEST | ||
263 | * IODA tables. Since the OPAL has exported the function | ||
264 | * to do it, it'd better to use that. | ||
265 | */ | ||
266 | static int ioda_eeh_get_state(struct eeh_pe *pe) | ||
267 | { | 252 | { |
268 | s64 ret = 0; | 253 | struct pnv_phb *phb = pe->phb->private_data; |
269 | u8 fstate; | 254 | u8 fstate; |
270 | __be16 pcierr; | 255 | __be16 pcierr; |
271 | u32 pe_no; | 256 | s64 rc; |
272 | int result; | 257 | int result = 0; |
273 | struct pci_controller *hose = pe->phb; | 258 | |
274 | struct pnv_phb *phb = hose->private_data; | 259 | rc = opal_pci_eeh_freeze_status(phb->opal_id, |
260 | pe->addr, | ||
261 | &fstate, | ||
262 | &pcierr, | ||
263 | NULL); | ||
264 | if (rc != OPAL_SUCCESS) { | ||
265 | pr_warn("%s: Failure %lld getting PHB#%x state\n", | ||
266 | __func__, rc, phb->hose->global_number); | ||
267 | return EEH_STATE_NOT_SUPPORT; | ||
268 | } | ||
275 | 269 | ||
276 | /* | 270 | /* |
277 | * Sanity check on PE address. The PHB PE address should | 271 | * Check PHB state. If the PHB is frozen for the |
278 | * be zero. | 272 | * first time, to dump the PHB diag-data. |
279 | */ | 273 | */ |
280 | if (pe->addr < 0 || pe->addr >= phb->ioda.total_pe) { | 274 | if (be16_to_cpu(pcierr) != OPAL_EEH_PHB_ERROR) { |
281 | pr_err("%s: PE address %x out of range [0, %x] " | 275 | result = (EEH_STATE_MMIO_ACTIVE | |
282 | "on PHB#%x\n", | 276 | EEH_STATE_DMA_ACTIVE | |
283 | __func__, pe->addr, phb->ioda.total_pe, | 277 | EEH_STATE_MMIO_ENABLED | |
284 | hose->global_number); | 278 | EEH_STATE_DMA_ENABLED); |
285 | return EEH_STATE_NOT_SUPPORT; | 279 | } else if (!(pe->state & EEH_PE_ISOLATED)) { |
280 | eeh_pe_state_mark(pe, EEH_PE_ISOLATED); | ||
281 | ioda_eeh_phb_diag(pe); | ||
286 | } | 282 | } |
287 | 283 | ||
284 | return result; | ||
285 | } | ||
286 | |||
287 | static int ioda_eeh_get_pe_state(struct eeh_pe *pe) | ||
288 | { | ||
289 | struct pnv_phb *phb = pe->phb->private_data; | ||
290 | u8 fstate; | ||
291 | __be16 pcierr; | ||
292 | s64 rc; | ||
293 | int result; | ||
294 | |||
288 | /* | 295 | /* |
289 | * If we're in middle of PE reset, return normal | 296 | * We don't clobber hardware frozen state until PE |
290 | * state to keep EEH core going. For PHB reset, we | 297 | * reset is completed. In order to keep EEH core |
291 | * still expect to have fenced PHB cleared with | 298 | * moving forward, we have to return operational |
292 | * PHB reset. | 299 | * state during PE reset. |
293 | */ | 300 | */ |
294 | if (!(pe->type & EEH_PE_PHB) && | 301 | if (pe->state & EEH_PE_RESET) { |
295 | (pe->state & EEH_PE_RESET)) { | 302 | result = (EEH_STATE_MMIO_ACTIVE | |
296 | result = (EEH_STATE_MMIO_ACTIVE | | 303 | EEH_STATE_DMA_ACTIVE | |
297 | EEH_STATE_DMA_ACTIVE | | ||
298 | EEH_STATE_MMIO_ENABLED | | 304 | EEH_STATE_MMIO_ENABLED | |
299 | EEH_STATE_DMA_ENABLED); | 305 | EEH_STATE_DMA_ENABLED); |
300 | return result; | 306 | return result; |
301 | } | 307 | } |
302 | 308 | ||
303 | /* Retrieve PE status through OPAL */ | 309 | /* |
304 | pe_no = pe->addr; | 310 | * Fetch PE state from hardware. If the PHB |
305 | ret = opal_pci_eeh_freeze_status(phb->opal_id, pe_no, | 311 | * supports compound PE, let it handle that. |
306 | &fstate, &pcierr, NULL); | 312 | */ |
307 | if (ret) { | 313 | if (phb->get_pe_state) { |
308 | pr_err("%s: Failed to get EEH status on " | 314 | fstate = phb->get_pe_state(phb, pe->addr); |
309 | "PHB#%x-PE#%x\n, err=%lld\n", | 315 | } else { |
310 | __func__, hose->global_number, pe_no, ret); | 316 | rc = opal_pci_eeh_freeze_status(phb->opal_id, |
311 | return EEH_STATE_NOT_SUPPORT; | 317 | pe->addr, |
312 | } | 318 | &fstate, |
313 | 319 | &pcierr, | |
314 | /* Check PHB status */ | 320 | NULL); |
315 | if (pe->type & EEH_PE_PHB) { | 321 | if (rc != OPAL_SUCCESS) { |
316 | result = 0; | 322 | pr_warn("%s: Failure %lld getting PHB#%x-PE%x state\n", |
317 | result &= ~EEH_STATE_RESET_ACTIVE; | 323 | __func__, rc, phb->hose->global_number, pe->addr); |
318 | 324 | return EEH_STATE_NOT_SUPPORT; | |
319 | if (be16_to_cpu(pcierr) != OPAL_EEH_PHB_ERROR) { | ||
320 | result |= EEH_STATE_MMIO_ACTIVE; | ||
321 | result |= EEH_STATE_DMA_ACTIVE; | ||
322 | result |= EEH_STATE_MMIO_ENABLED; | ||
323 | result |= EEH_STATE_DMA_ENABLED; | ||
324 | } else if (!(pe->state & EEH_PE_ISOLATED)) { | ||
325 | eeh_pe_state_mark(pe, EEH_PE_ISOLATED); | ||
326 | ioda_eeh_phb_diag(hose); | ||
327 | } | 325 | } |
328 | |||
329 | return result; | ||
330 | } | 326 | } |
331 | 327 | ||
332 | /* Parse result out */ | 328 | /* Figure out state */ |
333 | result = 0; | ||
334 | switch (fstate) { | 329 | switch (fstate) { |
335 | case OPAL_EEH_STOPPED_NOT_FROZEN: | 330 | case OPAL_EEH_STOPPED_NOT_FROZEN: |
336 | result &= ~EEH_STATE_RESET_ACTIVE; | 331 | result = (EEH_STATE_MMIO_ACTIVE | |
337 | result |= EEH_STATE_MMIO_ACTIVE; | 332 | EEH_STATE_DMA_ACTIVE | |
338 | result |= EEH_STATE_DMA_ACTIVE; | 333 | EEH_STATE_MMIO_ENABLED | |
339 | result |= EEH_STATE_MMIO_ENABLED; | 334 | EEH_STATE_DMA_ENABLED); |
340 | result |= EEH_STATE_DMA_ENABLED; | ||
341 | break; | 335 | break; |
342 | case OPAL_EEH_STOPPED_MMIO_FREEZE: | 336 | case OPAL_EEH_STOPPED_MMIO_FREEZE: |
343 | result &= ~EEH_STATE_RESET_ACTIVE; | 337 | result = (EEH_STATE_DMA_ACTIVE | |
344 | result |= EEH_STATE_DMA_ACTIVE; | 338 | EEH_STATE_DMA_ENABLED); |
345 | result |= EEH_STATE_DMA_ENABLED; | ||
346 | break; | 339 | break; |
347 | case OPAL_EEH_STOPPED_DMA_FREEZE: | 340 | case OPAL_EEH_STOPPED_DMA_FREEZE: |
348 | result &= ~EEH_STATE_RESET_ACTIVE; | 341 | result = (EEH_STATE_MMIO_ACTIVE | |
349 | result |= EEH_STATE_MMIO_ACTIVE; | 342 | EEH_STATE_MMIO_ENABLED); |
350 | result |= EEH_STATE_MMIO_ENABLED; | ||
351 | break; | 343 | break; |
352 | case OPAL_EEH_STOPPED_MMIO_DMA_FREEZE: | 344 | case OPAL_EEH_STOPPED_MMIO_DMA_FREEZE: |
353 | result &= ~EEH_STATE_RESET_ACTIVE; | 345 | result = 0; |
354 | break; | 346 | break; |
355 | case OPAL_EEH_STOPPED_RESET: | 347 | case OPAL_EEH_STOPPED_RESET: |
356 | result |= EEH_STATE_RESET_ACTIVE; | 348 | result = EEH_STATE_RESET_ACTIVE; |
357 | break; | 349 | break; |
358 | case OPAL_EEH_STOPPED_TEMP_UNAVAIL: | 350 | case OPAL_EEH_STOPPED_TEMP_UNAVAIL: |
359 | result |= EEH_STATE_UNAVAILABLE; | 351 | result = EEH_STATE_UNAVAILABLE; |
360 | break; | 352 | break; |
361 | case OPAL_EEH_STOPPED_PERM_UNAVAIL: | 353 | case OPAL_EEH_STOPPED_PERM_UNAVAIL: |
362 | result |= EEH_STATE_NOT_SUPPORT; | 354 | result = EEH_STATE_NOT_SUPPORT; |
363 | break; | 355 | break; |
364 | default: | 356 | default: |
365 | pr_warning("%s: Unexpected EEH status 0x%x " | 357 | result = EEH_STATE_NOT_SUPPORT; |
366 | "on PHB#%x-PE#%x\n", | 358 | pr_warn("%s: Invalid PHB#%x-PE#%x state %x\n", |
367 | __func__, fstate, hose->global_number, pe_no); | 359 | __func__, phb->hose->global_number, |
360 | pe->addr, fstate); | ||
368 | } | 361 | } |
369 | 362 | ||
370 | /* Dump PHB diag-data for frozen PE */ | 363 | /* |
371 | if (result != EEH_STATE_NOT_SUPPORT && | 364 | * If PHB supports compound PE, to freeze all |
372 | (result & (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE)) != | 365 | * slave PEs for consistency. |
373 | (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE) && | 366 | * |
367 | * If the PE is switching to frozen state for the | ||
368 | * first time, to dump the PHB diag-data. | ||
369 | */ | ||
370 | if (!(result & EEH_STATE_NOT_SUPPORT) && | ||
371 | !(result & EEH_STATE_UNAVAILABLE) && | ||
372 | !(result & EEH_STATE_MMIO_ACTIVE) && | ||
373 | !(result & EEH_STATE_DMA_ACTIVE) && | ||
374 | !(pe->state & EEH_PE_ISOLATED)) { | 374 | !(pe->state & EEH_PE_ISOLATED)) { |
375 | if (phb->freeze_pe) | ||
376 | phb->freeze_pe(phb, pe->addr); | ||
377 | |||
375 | eeh_pe_state_mark(pe, EEH_PE_ISOLATED); | 378 | eeh_pe_state_mark(pe, EEH_PE_ISOLATED); |
376 | ioda_eeh_phb_diag(hose); | 379 | ioda_eeh_phb_diag(pe); |
377 | } | 380 | } |
378 | 381 | ||
379 | return result; | 382 | return result; |
380 | } | 383 | } |
381 | 384 | ||
385 | /** | ||
386 | * ioda_eeh_get_state - Retrieve the state of PE | ||
387 | * @pe: EEH PE | ||
388 | * | ||
389 | * The PE's state should be retrieved from the PEEV, PEST | ||
390 | * IODA tables. Since the OPAL has exported the function | ||
391 | * to do it, it'd better to use that. | ||
392 | */ | ||
393 | static int ioda_eeh_get_state(struct eeh_pe *pe) | ||
394 | { | ||
395 | struct pnv_phb *phb = pe->phb->private_data; | ||
396 | |||
397 | /* Sanity check on PE number. PHB PE should have 0 */ | ||
398 | if (pe->addr < 0 || | ||
399 | pe->addr >= phb->ioda.total_pe) { | ||
400 | pr_warn("%s: PHB#%x-PE#%x out of range [0, %x]\n", | ||
401 | __func__, phb->hose->global_number, | ||
402 | pe->addr, phb->ioda.total_pe); | ||
403 | return EEH_STATE_NOT_SUPPORT; | ||
404 | } | ||
405 | |||
406 | if (pe->type & EEH_PE_PHB) | ||
407 | return ioda_eeh_get_phb_state(pe); | ||
408 | |||
409 | return ioda_eeh_get_pe_state(pe); | ||
410 | } | ||
411 | |||
382 | static s64 ioda_eeh_phb_poll(struct pnv_phb *phb) | 412 | static s64 ioda_eeh_phb_poll(struct pnv_phb *phb) |
383 | { | 413 | { |
384 | s64 rc = OPAL_HARDWARE; | 414 | s64 rc = OPAL_HARDWARE; |
@@ -589,6 +619,24 @@ static int ioda_eeh_reset(struct eeh_pe *pe, int option) | |||
589 | } | 619 | } |
590 | 620 | ||
591 | /** | 621 | /** |
622 | * ioda_eeh_get_log - Retrieve error log | ||
623 | * @pe: frozen PE | ||
624 | * @severity: permanent or temporary error | ||
625 | * @drv_log: device driver log | ||
626 | * @len: length of device driver log | ||
627 | * | ||
628 | * Retrieve error log, which contains log from device driver | ||
629 | * and firmware. | ||
630 | */ | ||
631 | int ioda_eeh_get_log(struct eeh_pe *pe, int severity, | ||
632 | char *drv_log, unsigned long len) | ||
633 | { | ||
634 | pnv_pci_dump_phb_diag_data(pe->phb, pe->data); | ||
635 | |||
636 | return 0; | ||
637 | } | ||
638 | |||
639 | /** | ||
592 | * ioda_eeh_configure_bridge - Configure the PCI bridges for the indicated PE | 640 | * ioda_eeh_configure_bridge - Configure the PCI bridges for the indicated PE |
593 | * @pe: EEH PE | 641 | * @pe: EEH PE |
594 | * | 642 | * |
@@ -605,18 +653,24 @@ static int ioda_eeh_configure_bridge(struct eeh_pe *pe) | |||
605 | static void ioda_eeh_hub_diag_common(struct OpalIoP7IOCErrorData *data) | 653 | static void ioda_eeh_hub_diag_common(struct OpalIoP7IOCErrorData *data) |
606 | { | 654 | { |
607 | /* GEM */ | 655 | /* GEM */ |
608 | pr_info(" GEM XFIR: %016llx\n", data->gemXfir); | 656 | if (data->gemXfir || data->gemRfir || |
609 | pr_info(" GEM RFIR: %016llx\n", data->gemRfir); | 657 | data->gemRirqfir || data->gemMask || data->gemRwof) |
610 | pr_info(" GEM RIRQFIR: %016llx\n", data->gemRirqfir); | 658 | pr_info(" GEM: %016llx %016llx %016llx %016llx %016llx\n", |
611 | pr_info(" GEM Mask: %016llx\n", data->gemMask); | 659 | be64_to_cpu(data->gemXfir), |
612 | pr_info(" GEM RWOF: %016llx\n", data->gemRwof); | 660 | be64_to_cpu(data->gemRfir), |
661 | be64_to_cpu(data->gemRirqfir), | ||
662 | be64_to_cpu(data->gemMask), | ||
663 | be64_to_cpu(data->gemRwof)); | ||
613 | 664 | ||
614 | /* LEM */ | 665 | /* LEM */ |
615 | pr_info(" LEM FIR: %016llx\n", data->lemFir); | 666 | if (data->lemFir || data->lemErrMask || |
616 | pr_info(" LEM Error Mask: %016llx\n", data->lemErrMask); | 667 | data->lemAction0 || data->lemAction1 || data->lemWof) |
617 | pr_info(" LEM Action 0: %016llx\n", data->lemAction0); | 668 | pr_info(" LEM: %016llx %016llx %016llx %016llx %016llx\n", |
618 | pr_info(" LEM Action 1: %016llx\n", data->lemAction1); | 669 | be64_to_cpu(data->lemFir), |
619 | pr_info(" LEM WOF: %016llx\n", data->lemWof); | 670 | be64_to_cpu(data->lemErrMask), |
671 | be64_to_cpu(data->lemAction0), | ||
672 | be64_to_cpu(data->lemAction1), | ||
673 | be64_to_cpu(data->lemWof)); | ||
620 | } | 674 | } |
621 | 675 | ||
622 | static void ioda_eeh_hub_diag(struct pci_controller *hose) | 676 | static void ioda_eeh_hub_diag(struct pci_controller *hose) |
@@ -627,8 +681,8 @@ static void ioda_eeh_hub_diag(struct pci_controller *hose) | |||
627 | 681 | ||
628 | rc = opal_pci_get_hub_diag_data(phb->hub_id, data, sizeof(*data)); | 682 | rc = opal_pci_get_hub_diag_data(phb->hub_id, data, sizeof(*data)); |
629 | if (rc != OPAL_SUCCESS) { | 683 | if (rc != OPAL_SUCCESS) { |
630 | pr_warning("%s: Failed to get HUB#%llx diag-data (%ld)\n", | 684 | pr_warn("%s: Failed to get HUB#%llx diag-data (%ld)\n", |
631 | __func__, phb->hub_id, rc); | 685 | __func__, phb->hub_id, rc); |
632 | return; | 686 | return; |
633 | } | 687 | } |
634 | 688 | ||
@@ -636,24 +690,31 @@ static void ioda_eeh_hub_diag(struct pci_controller *hose) | |||
636 | case OPAL_P7IOC_DIAG_TYPE_RGC: | 690 | case OPAL_P7IOC_DIAG_TYPE_RGC: |
637 | pr_info("P7IOC diag-data for RGC\n\n"); | 691 | pr_info("P7IOC diag-data for RGC\n\n"); |
638 | ioda_eeh_hub_diag_common(data); | 692 | ioda_eeh_hub_diag_common(data); |
639 | pr_info(" RGC Status: %016llx\n", data->rgc.rgcStatus); | 693 | if (data->rgc.rgcStatus || data->rgc.rgcLdcp) |
640 | pr_info(" RGC LDCP: %016llx\n", data->rgc.rgcLdcp); | 694 | pr_info(" RGC: %016llx %016llx\n", |
695 | be64_to_cpu(data->rgc.rgcStatus), | ||
696 | be64_to_cpu(data->rgc.rgcLdcp)); | ||
641 | break; | 697 | break; |
642 | case OPAL_P7IOC_DIAG_TYPE_BI: | 698 | case OPAL_P7IOC_DIAG_TYPE_BI: |
643 | pr_info("P7IOC diag-data for BI %s\n\n", | 699 | pr_info("P7IOC diag-data for BI %s\n\n", |
644 | data->bi.biDownbound ? "Downbound" : "Upbound"); | 700 | data->bi.biDownbound ? "Downbound" : "Upbound"); |
645 | ioda_eeh_hub_diag_common(data); | 701 | ioda_eeh_hub_diag_common(data); |
646 | pr_info(" BI LDCP 0: %016llx\n", data->bi.biLdcp0); | 702 | if (data->bi.biLdcp0 || data->bi.biLdcp1 || |
647 | pr_info(" BI LDCP 1: %016llx\n", data->bi.biLdcp1); | 703 | data->bi.biLdcp2 || data->bi.biFenceStatus) |
648 | pr_info(" BI LDCP 2: %016llx\n", data->bi.biLdcp2); | 704 | pr_info(" BI: %016llx %016llx %016llx %016llx\n", |
649 | pr_info(" BI Fence Status: %016llx\n", data->bi.biFenceStatus); | 705 | be64_to_cpu(data->bi.biLdcp0), |
706 | be64_to_cpu(data->bi.biLdcp1), | ||
707 | be64_to_cpu(data->bi.biLdcp2), | ||
708 | be64_to_cpu(data->bi.biFenceStatus)); | ||
650 | break; | 709 | break; |
651 | case OPAL_P7IOC_DIAG_TYPE_CI: | 710 | case OPAL_P7IOC_DIAG_TYPE_CI: |
652 | pr_info("P7IOC diag-data for CI Port %d\\nn", | 711 | pr_info("P7IOC diag-data for CI Port %d\n\n", |
653 | data->ci.ciPort); | 712 | data->ci.ciPort); |
654 | ioda_eeh_hub_diag_common(data); | 713 | ioda_eeh_hub_diag_common(data); |
655 | pr_info(" CI Port Status: %016llx\n", data->ci.ciPortStatus); | 714 | if (data->ci.ciPortStatus || data->ci.ciPortLdcp) |
656 | pr_info(" CI Port LDCP: %016llx\n", data->ci.ciPortLdcp); | 715 | pr_info(" CI: %016llx %016llx\n", |
716 | be64_to_cpu(data->ci.ciPortStatus), | ||
717 | be64_to_cpu(data->ci.ciPortLdcp)); | ||
657 | break; | 718 | break; |
658 | case OPAL_P7IOC_DIAG_TYPE_MISC: | 719 | case OPAL_P7IOC_DIAG_TYPE_MISC: |
659 | pr_info("P7IOC diag-data for MISC\n\n"); | 720 | pr_info("P7IOC diag-data for MISC\n\n"); |
@@ -664,30 +725,51 @@ static void ioda_eeh_hub_diag(struct pci_controller *hose) | |||
664 | ioda_eeh_hub_diag_common(data); | 725 | ioda_eeh_hub_diag_common(data); |
665 | break; | 726 | break; |
666 | default: | 727 | default: |
667 | pr_warning("%s: Invalid type of HUB#%llx diag-data (%d)\n", | 728 | pr_warn("%s: Invalid type of HUB#%llx diag-data (%d)\n", |
668 | __func__, phb->hub_id, data->type); | 729 | __func__, phb->hub_id, data->type); |
669 | } | 730 | } |
670 | } | 731 | } |
671 | 732 | ||
672 | static int ioda_eeh_get_pe(struct pci_controller *hose, | 733 | static int ioda_eeh_get_pe(struct pci_controller *hose, |
673 | u16 pe_no, struct eeh_pe **pe) | 734 | u16 pe_no, struct eeh_pe **pe) |
674 | { | 735 | { |
675 | struct eeh_pe *phb_pe, *dev_pe; | 736 | struct pnv_phb *phb = hose->private_data; |
676 | struct eeh_dev dev; | 737 | struct pnv_ioda_pe *pnv_pe; |
738 | struct eeh_pe *dev_pe; | ||
739 | struct eeh_dev edev; | ||
677 | 740 | ||
678 | /* Find the PHB PE */ | 741 | /* |
679 | phb_pe = eeh_phb_pe_get(hose); | 742 | * If PHB supports compound PE, to fetch |
680 | if (!phb_pe) | 743 | * the master PE because slave PE is invisible |
681 | return -EEXIST; | 744 | * to EEH core. |
745 | */ | ||
746 | if (phb->get_pe_state) { | ||
747 | pnv_pe = &phb->ioda.pe_array[pe_no]; | ||
748 | if (pnv_pe->flags & PNV_IODA_PE_SLAVE) { | ||
749 | pnv_pe = pnv_pe->master; | ||
750 | WARN_ON(!pnv_pe || | ||
751 | !(pnv_pe->flags & PNV_IODA_PE_MASTER)); | ||
752 | pe_no = pnv_pe->pe_number; | ||
753 | } | ||
754 | } | ||
682 | 755 | ||
683 | /* Find the PE according to PE# */ | 756 | /* Find the PE according to PE# */ |
684 | memset(&dev, 0, sizeof(struct eeh_dev)); | 757 | memset(&edev, 0, sizeof(struct eeh_dev)); |
685 | dev.phb = hose; | 758 | edev.phb = hose; |
686 | dev.pe_config_addr = pe_no; | 759 | edev.pe_config_addr = pe_no; |
687 | dev_pe = eeh_pe_get(&dev); | 760 | dev_pe = eeh_pe_get(&edev); |
688 | if (!dev_pe) return -EEXIST; | 761 | if (!dev_pe) |
762 | return -EEXIST; | ||
689 | 763 | ||
764 | /* | ||
765 | * At this point, we're sure the compound PE should | ||
766 | * be put into frozen state. | ||
767 | */ | ||
690 | *pe = dev_pe; | 768 | *pe = dev_pe; |
769 | if (phb->freeze_pe && | ||
770 | !(dev_pe->state & EEH_PE_ISOLATED)) | ||
771 | phb->freeze_pe(phb, pe_no); | ||
772 | |||
691 | return 0; | 773 | return 0; |
692 | } | 774 | } |
693 | 775 | ||
@@ -792,7 +874,8 @@ static int ioda_eeh_next_error(struct eeh_pe **pe) | |||
792 | "detected, location: %s\n", | 874 | "detected, location: %s\n", |
793 | hose->global_number, | 875 | hose->global_number, |
794 | eeh_pe_loc_get(phb_pe)); | 876 | eeh_pe_loc_get(phb_pe)); |
795 | ioda_eeh_phb_diag(hose); | 877 | ioda_eeh_phb_diag(phb_pe); |
878 | pnv_pci_dump_phb_diag_data(hose, phb_pe->data); | ||
796 | ret = EEH_NEXT_ERR_NONE; | 879 | ret = EEH_NEXT_ERR_NONE; |
797 | } | 880 | } |
798 | 881 | ||
@@ -812,7 +895,8 @@ static int ioda_eeh_next_error(struct eeh_pe **pe) | |||
812 | opal_pci_eeh_freeze_clear(phb->opal_id, frozen_pe_no, | 895 | opal_pci_eeh_freeze_clear(phb->opal_id, frozen_pe_no, |
813 | OPAL_EEH_ACTION_CLEAR_FREEZE_ALL); | 896 | OPAL_EEH_ACTION_CLEAR_FREEZE_ALL); |
814 | ret = EEH_NEXT_ERR_NONE; | 897 | ret = EEH_NEXT_ERR_NONE; |
815 | } else if ((*pe)->state & EEH_PE_ISOLATED) { | 898 | } else if ((*pe)->state & EEH_PE_ISOLATED || |
899 | eeh_pe_passed(*pe)) { | ||
816 | ret = EEH_NEXT_ERR_NONE; | 900 | ret = EEH_NEXT_ERR_NONE; |
817 | } else { | 901 | } else { |
818 | pr_err("EEH: Frozen PE#%x on PHB#%x detected\n", | 902 | pr_err("EEH: Frozen PE#%x on PHB#%x detected\n", |
@@ -839,7 +923,7 @@ static int ioda_eeh_next_error(struct eeh_pe **pe) | |||
839 | ret == EEH_NEXT_ERR_FENCED_PHB) && | 923 | ret == EEH_NEXT_ERR_FENCED_PHB) && |
840 | !((*pe)->state & EEH_PE_ISOLATED)) { | 924 | !((*pe)->state & EEH_PE_ISOLATED)) { |
841 | eeh_pe_state_mark(*pe, EEH_PE_ISOLATED); | 925 | eeh_pe_state_mark(*pe, EEH_PE_ISOLATED); |
842 | ioda_eeh_phb_diag(hose); | 926 | ioda_eeh_phb_diag(*pe); |
843 | } | 927 | } |
844 | 928 | ||
845 | /* | 929 | /* |
@@ -885,6 +969,7 @@ struct pnv_eeh_ops ioda_eeh_ops = { | |||
885 | .set_option = ioda_eeh_set_option, | 969 | .set_option = ioda_eeh_set_option, |
886 | .get_state = ioda_eeh_get_state, | 970 | .get_state = ioda_eeh_get_state, |
887 | .reset = ioda_eeh_reset, | 971 | .reset = ioda_eeh_reset, |
972 | .get_log = ioda_eeh_get_log, | ||
888 | .configure_bridge = ioda_eeh_configure_bridge, | 973 | .configure_bridge = ioda_eeh_configure_bridge, |
889 | .next_error = ioda_eeh_next_error | 974 | .next_error = ioda_eeh_next_error |
890 | }; | 975 | }; |
diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c index 56a206f32f77..fd7a16f855ed 100644 --- a/arch/powerpc/platforms/powernv/eeh-powernv.c +++ b/arch/powerpc/platforms/powernv/eeh-powernv.c | |||
@@ -45,14 +45,31 @@ | |||
45 | */ | 45 | */ |
46 | static int powernv_eeh_init(void) | 46 | static int powernv_eeh_init(void) |
47 | { | 47 | { |
48 | struct pci_controller *hose; | ||
49 | struct pnv_phb *phb; | ||
50 | |||
48 | /* We require OPALv3 */ | 51 | /* We require OPALv3 */ |
49 | if (!firmware_has_feature(FW_FEATURE_OPALv3)) { | 52 | if (!firmware_has_feature(FW_FEATURE_OPALv3)) { |
50 | pr_warning("%s: OPALv3 is required !\n", __func__); | 53 | pr_warn("%s: OPALv3 is required !\n", |
54 | __func__); | ||
51 | return -EINVAL; | 55 | return -EINVAL; |
52 | } | 56 | } |
53 | 57 | ||
54 | /* Set EEH probe mode */ | 58 | /* Set probe mode */ |
55 | eeh_probe_mode_set(EEH_PROBE_MODE_DEV); | 59 | eeh_add_flag(EEH_PROBE_MODE_DEV); |
60 | |||
61 | /* | ||
62 | * P7IOC blocks PCI config access to frozen PE, but PHB3 | ||
63 | * doesn't do that. So we have to selectively enable I/O | ||
64 | * prior to collecting error log. | ||
65 | */ | ||
66 | list_for_each_entry(hose, &hose_list, list_node) { | ||
67 | phb = hose->private_data; | ||
68 | |||
69 | if (phb->model == PNV_PHB_MODEL_P7IOC) | ||
70 | eeh_add_flag(EEH_ENABLE_IO_FOR_LOG); | ||
71 | break; | ||
72 | } | ||
56 | 73 | ||
57 | return 0; | 74 | return 0; |
58 | } | 75 | } |
@@ -107,6 +124,7 @@ static int powernv_eeh_dev_probe(struct pci_dev *dev, void *flag) | |||
107 | struct pnv_phb *phb = hose->private_data; | 124 | struct pnv_phb *phb = hose->private_data; |
108 | struct device_node *dn = pci_device_to_OF_node(dev); | 125 | struct device_node *dn = pci_device_to_OF_node(dev); |
109 | struct eeh_dev *edev = of_node_to_eeh_dev(dn); | 126 | struct eeh_dev *edev = of_node_to_eeh_dev(dn); |
127 | int ret; | ||
110 | 128 | ||
111 | /* | 129 | /* |
112 | * When probing the root bridge, which doesn't have any | 130 | * When probing the root bridge, which doesn't have any |
@@ -143,13 +161,27 @@ static int powernv_eeh_dev_probe(struct pci_dev *dev, void *flag) | |||
143 | edev->pe_config_addr = phb->bdfn_to_pe(phb, dev->bus, dev->devfn & 0xff); | 161 | edev->pe_config_addr = phb->bdfn_to_pe(phb, dev->bus, dev->devfn & 0xff); |
144 | 162 | ||
145 | /* Create PE */ | 163 | /* Create PE */ |
146 | eeh_add_to_parent_pe(edev); | 164 | ret = eeh_add_to_parent_pe(edev); |
165 | if (ret) { | ||
166 | pr_warn("%s: Can't add PCI dev %s to parent PE (%d)\n", | ||
167 | __func__, pci_name(dev), ret); | ||
168 | return ret; | ||
169 | } | ||
170 | |||
171 | /* | ||
172 | * Cache the PE primary bus, which can't be fetched when | ||
173 | * full hotplug is in progress. In that case, all child | ||
174 | * PCI devices of the PE are expected to be removed prior | ||
175 | * to PE reset. | ||
176 | */ | ||
177 | if (!edev->pe->bus) | ||
178 | edev->pe->bus = dev->bus; | ||
147 | 179 | ||
148 | /* | 180 | /* |
149 | * Enable EEH explicitly so that we will do EEH check | 181 | * Enable EEH explicitly so that we will do EEH check |
150 | * while accessing I/O stuff | 182 | * while accessing I/O stuff |
151 | */ | 183 | */ |
152 | eeh_set_enable(true); | 184 | eeh_add_flag(EEH_ENABLED); |
153 | 185 | ||
154 | /* Save memory bars */ | 186 | /* Save memory bars */ |
155 | eeh_save_bars(edev); | 187 | eeh_save_bars(edev); |
@@ -273,8 +305,8 @@ static int powernv_eeh_wait_state(struct eeh_pe *pe, int max_wait) | |||
273 | 305 | ||
274 | max_wait -= mwait; | 306 | max_wait -= mwait; |
275 | if (max_wait <= 0) { | 307 | if (max_wait <= 0) { |
276 | pr_warning("%s: Timeout getting PE#%x's state (%d)\n", | 308 | pr_warn("%s: Timeout getting PE#%x's state (%d)\n", |
277 | __func__, pe->addr, max_wait); | 309 | __func__, pe->addr, max_wait); |
278 | return EEH_STATE_NOT_SUPPORT; | 310 | return EEH_STATE_NOT_SUPPORT; |
279 | } | 311 | } |
280 | 312 | ||
@@ -294,7 +326,7 @@ static int powernv_eeh_wait_state(struct eeh_pe *pe, int max_wait) | |||
294 | * Retrieve the temporary or permanent error from the PE. | 326 | * Retrieve the temporary or permanent error from the PE. |
295 | */ | 327 | */ |
296 | static int powernv_eeh_get_log(struct eeh_pe *pe, int severity, | 328 | static int powernv_eeh_get_log(struct eeh_pe *pe, int severity, |
297 | char *drv_log, unsigned long len) | 329 | char *drv_log, unsigned long len) |
298 | { | 330 | { |
299 | struct pci_controller *hose = pe->phb; | 331 | struct pci_controller *hose = pe->phb; |
300 | struct pnv_phb *phb = hose->private_data; | 332 | struct pnv_phb *phb = hose->private_data; |
@@ -398,9 +430,7 @@ static int __init eeh_powernv_init(void) | |||
398 | { | 430 | { |
399 | int ret = -EINVAL; | 431 | int ret = -EINVAL; |
400 | 432 | ||
401 | if (!machine_is(powernv)) | 433 | eeh_set_pe_aux_size(PNV_PCI_DIAG_BUF_SIZE); |
402 | return ret; | ||
403 | |||
404 | ret = eeh_ops_register(&powernv_eeh_ops); | 434 | ret = eeh_ops_register(&powernv_eeh_ops); |
405 | if (!ret) | 435 | if (!ret) |
406 | pr_info("EEH: PowerNV platform initialized\n"); | 436 | pr_info("EEH: PowerNV platform initialized\n"); |
@@ -409,5 +439,4 @@ static int __init eeh_powernv_init(void) | |||
409 | 439 | ||
410 | return ret; | 440 | return ret; |
411 | } | 441 | } |
412 | 442 | machine_early_initcall(powernv, eeh_powernv_init); | |
413 | early_initcall(eeh_powernv_init); | ||
diff --git a/arch/powerpc/platforms/powernv/opal-async.c b/arch/powerpc/platforms/powernv/opal-async.c index 32e2adfa5320..e462ab947d16 100644 --- a/arch/powerpc/platforms/powernv/opal-async.c +++ b/arch/powerpc/platforms/powernv/opal-async.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/wait.h> | 20 | #include <linux/wait.h> |
21 | #include <linux/gfp.h> | 21 | #include <linux/gfp.h> |
22 | #include <linux/of.h> | 22 | #include <linux/of.h> |
23 | #include <asm/machdep.h> | ||
23 | #include <asm/opal.h> | 24 | #include <asm/opal.h> |
24 | 25 | ||
25 | #define N_ASYNC_COMPLETIONS 64 | 26 | #define N_ASYNC_COMPLETIONS 64 |
@@ -201,4 +202,4 @@ out_opal_node: | |||
201 | out: | 202 | out: |
202 | return err; | 203 | return err; |
203 | } | 204 | } |
204 | subsys_initcall(opal_async_comp_init); | 205 | machine_subsys_initcall(powernv, opal_async_comp_init); |
diff --git a/arch/powerpc/platforms/powernv/opal-dump.c b/arch/powerpc/platforms/powernv/opal-dump.c index 788a1977b9a5..85bb8fff7947 100644 --- a/arch/powerpc/platforms/powernv/opal-dump.c +++ b/arch/powerpc/platforms/powernv/opal-dump.c | |||
@@ -102,9 +102,9 @@ static ssize_t dump_ack_store(struct dump_obj *dump_obj, | |||
102 | * due to the dynamic size of the dump | 102 | * due to the dynamic size of the dump |
103 | */ | 103 | */ |
104 | static struct dump_attribute id_attribute = | 104 | static struct dump_attribute id_attribute = |
105 | __ATTR(id, 0666, dump_id_show, NULL); | 105 | __ATTR(id, S_IRUGO, dump_id_show, NULL); |
106 | static struct dump_attribute type_attribute = | 106 | static struct dump_attribute type_attribute = |
107 | __ATTR(type, 0666, dump_type_show, NULL); | 107 | __ATTR(type, S_IRUGO, dump_type_show, NULL); |
108 | static struct dump_attribute ack_attribute = | 108 | static struct dump_attribute ack_attribute = |
109 | __ATTR(acknowledge, 0660, dump_ack_show, dump_ack_store); | 109 | __ATTR(acknowledge, 0660, dump_ack_show, dump_ack_store); |
110 | 110 | ||
diff --git a/arch/powerpc/platforms/powernv/opal-elog.c b/arch/powerpc/platforms/powernv/opal-elog.c index 0ad533b617f7..bbdb3ffaab98 100644 --- a/arch/powerpc/platforms/powernv/opal-elog.c +++ b/arch/powerpc/platforms/powernv/opal-elog.c | |||
@@ -82,9 +82,9 @@ static ssize_t elog_ack_store(struct elog_obj *elog_obj, | |||
82 | } | 82 | } |
83 | 83 | ||
84 | static struct elog_attribute id_attribute = | 84 | static struct elog_attribute id_attribute = |
85 | __ATTR(id, 0666, elog_id_show, NULL); | 85 | __ATTR(id, S_IRUGO, elog_id_show, NULL); |
86 | static struct elog_attribute type_attribute = | 86 | static struct elog_attribute type_attribute = |
87 | __ATTR(type, 0666, elog_type_show, NULL); | 87 | __ATTR(type, S_IRUGO, elog_type_show, NULL); |
88 | static struct elog_attribute ack_attribute = | 88 | static struct elog_attribute ack_attribute = |
89 | __ATTR(acknowledge, 0660, elog_ack_show, elog_ack_store); | 89 | __ATTR(acknowledge, 0660, elog_ack_show, elog_ack_store); |
90 | 90 | ||
diff --git a/arch/powerpc/platforms/powernv/opal-hmi.c b/arch/powerpc/platforms/powernv/opal-hmi.c new file mode 100644 index 000000000000..97ac8dc33667 --- /dev/null +++ b/arch/powerpc/platforms/powernv/opal-hmi.c | |||
@@ -0,0 +1,188 @@ | |||
1 | /* | ||
2 | * OPAL hypervisor Maintenance interrupt handling support in PowreNV. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; If not, see <http://www.gnu.org/licenses/>. | ||
16 | * | ||
17 | * Copyright 2014 IBM Corporation | ||
18 | * Author: Mahesh Salgaonkar <mahesh@linux.vnet.ibm.com> | ||
19 | */ | ||
20 | |||
21 | #undef DEBUG | ||
22 | |||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/of.h> | ||
26 | #include <linux/mm.h> | ||
27 | #include <linux/slab.h> | ||
28 | |||
29 | #include <asm/opal.h> | ||
30 | #include <asm/cputable.h> | ||
31 | |||
32 | static int opal_hmi_handler_nb_init; | ||
33 | struct OpalHmiEvtNode { | ||
34 | struct list_head list; | ||
35 | struct OpalHMIEvent hmi_evt; | ||
36 | }; | ||
37 | static LIST_HEAD(opal_hmi_evt_list); | ||
38 | static DEFINE_SPINLOCK(opal_hmi_evt_lock); | ||
39 | |||
40 | static void print_hmi_event_info(struct OpalHMIEvent *hmi_evt) | ||
41 | { | ||
42 | const char *level, *sevstr, *error_info; | ||
43 | static const char *hmi_error_types[] = { | ||
44 | "Malfunction Alert", | ||
45 | "Processor Recovery done", | ||
46 | "Processor recovery occurred again", | ||
47 | "Processor recovery occurred for masked error", | ||
48 | "Timer facility experienced an error", | ||
49 | "TFMR SPR is corrupted", | ||
50 | "UPS (Uniterrupted Power System) Overflow indication", | ||
51 | "An XSCOM operation failure", | ||
52 | "An XSCOM operation completed", | ||
53 | "SCOM has set a reserved FIR bit to cause recovery", | ||
54 | "Debug trigger has set a reserved FIR bit to cause recovery", | ||
55 | "A hypervisor resource error occurred" | ||
56 | }; | ||
57 | |||
58 | /* Print things out */ | ||
59 | if (hmi_evt->version != OpalHMIEvt_V1) { | ||
60 | pr_err("HMI Interrupt, Unknown event version %d !\n", | ||
61 | hmi_evt->version); | ||
62 | return; | ||
63 | } | ||
64 | switch (hmi_evt->severity) { | ||
65 | case OpalHMI_SEV_NO_ERROR: | ||
66 | level = KERN_INFO; | ||
67 | sevstr = "Harmless"; | ||
68 | break; | ||
69 | case OpalHMI_SEV_WARNING: | ||
70 | level = KERN_WARNING; | ||
71 | sevstr = ""; | ||
72 | break; | ||
73 | case OpalHMI_SEV_ERROR_SYNC: | ||
74 | level = KERN_ERR; | ||
75 | sevstr = "Severe"; | ||
76 | break; | ||
77 | case OpalHMI_SEV_FATAL: | ||
78 | default: | ||
79 | level = KERN_ERR; | ||
80 | sevstr = "Fatal"; | ||
81 | break; | ||
82 | } | ||
83 | |||
84 | printk("%s%s Hypervisor Maintenance interrupt [%s]\n", | ||
85 | level, sevstr, | ||
86 | hmi_evt->disposition == OpalHMI_DISPOSITION_RECOVERED ? | ||
87 | "Recovered" : "Not recovered"); | ||
88 | error_info = hmi_evt->type < ARRAY_SIZE(hmi_error_types) ? | ||
89 | hmi_error_types[hmi_evt->type] | ||
90 | : "Unknown"; | ||
91 | printk("%s Error detail: %s\n", level, error_info); | ||
92 | printk("%s HMER: %016llx\n", level, be64_to_cpu(hmi_evt->hmer)); | ||
93 | if ((hmi_evt->type == OpalHMI_ERROR_TFAC) || | ||
94 | (hmi_evt->type == OpalHMI_ERROR_TFMR_PARITY)) | ||
95 | printk("%s TFMR: %016llx\n", level, | ||
96 | be64_to_cpu(hmi_evt->tfmr)); | ||
97 | } | ||
98 | |||
99 | static void hmi_event_handler(struct work_struct *work) | ||
100 | { | ||
101 | unsigned long flags; | ||
102 | struct OpalHMIEvent *hmi_evt; | ||
103 | struct OpalHmiEvtNode *msg_node; | ||
104 | uint8_t disposition; | ||
105 | |||
106 | spin_lock_irqsave(&opal_hmi_evt_lock, flags); | ||
107 | while (!list_empty(&opal_hmi_evt_list)) { | ||
108 | msg_node = list_entry(opal_hmi_evt_list.next, | ||
109 | struct OpalHmiEvtNode, list); | ||
110 | list_del(&msg_node->list); | ||
111 | spin_unlock_irqrestore(&opal_hmi_evt_lock, flags); | ||
112 | |||
113 | hmi_evt = (struct OpalHMIEvent *) &msg_node->hmi_evt; | ||
114 | print_hmi_event_info(hmi_evt); | ||
115 | disposition = hmi_evt->disposition; | ||
116 | kfree(msg_node); | ||
117 | |||
118 | /* | ||
119 | * Check if HMI event has been recovered or not. If not | ||
120 | * then we can't continue, invoke panic. | ||
121 | */ | ||
122 | if (disposition != OpalHMI_DISPOSITION_RECOVERED) | ||
123 | panic("Unrecoverable HMI exception"); | ||
124 | |||
125 | spin_lock_irqsave(&opal_hmi_evt_lock, flags); | ||
126 | } | ||
127 | spin_unlock_irqrestore(&opal_hmi_evt_lock, flags); | ||
128 | } | ||
129 | |||
130 | static DECLARE_WORK(hmi_event_work, hmi_event_handler); | ||
131 | /* | ||
132 | * opal_handle_hmi_event - notifier handler that queues up HMI events | ||
133 | * to be preocessed later. | ||
134 | */ | ||
135 | static int opal_handle_hmi_event(struct notifier_block *nb, | ||
136 | unsigned long msg_type, void *msg) | ||
137 | { | ||
138 | unsigned long flags; | ||
139 | struct OpalHMIEvent *hmi_evt; | ||
140 | struct opal_msg *hmi_msg = msg; | ||
141 | struct OpalHmiEvtNode *msg_node; | ||
142 | |||
143 | /* Sanity Checks */ | ||
144 | if (msg_type != OPAL_MSG_HMI_EVT) | ||
145 | return 0; | ||
146 | |||
147 | /* HMI event info starts from param[0] */ | ||
148 | hmi_evt = (struct OpalHMIEvent *)&hmi_msg->params[0]; | ||
149 | |||
150 | /* Delay the logging of HMI events to workqueue. */ | ||
151 | msg_node = kzalloc(sizeof(*msg_node), GFP_ATOMIC); | ||
152 | if (!msg_node) { | ||
153 | pr_err("HMI: out of memory, Opal message event not handled\n"); | ||
154 | return -ENOMEM; | ||
155 | } | ||
156 | memcpy(&msg_node->hmi_evt, hmi_evt, sizeof(struct OpalHMIEvent)); | ||
157 | |||
158 | spin_lock_irqsave(&opal_hmi_evt_lock, flags); | ||
159 | list_add(&msg_node->list, &opal_hmi_evt_list); | ||
160 | spin_unlock_irqrestore(&opal_hmi_evt_lock, flags); | ||
161 | |||
162 | schedule_work(&hmi_event_work); | ||
163 | return 0; | ||
164 | } | ||
165 | |||
166 | static struct notifier_block opal_hmi_handler_nb = { | ||
167 | .notifier_call = opal_handle_hmi_event, | ||
168 | .next = NULL, | ||
169 | .priority = 0, | ||
170 | }; | ||
171 | |||
172 | static int __init opal_hmi_handler_init(void) | ||
173 | { | ||
174 | int ret; | ||
175 | |||
176 | if (!opal_hmi_handler_nb_init) { | ||
177 | ret = opal_message_notifier_register( | ||
178 | OPAL_MSG_HMI_EVT, &opal_hmi_handler_nb); | ||
179 | if (ret) { | ||
180 | pr_err("%s: Can't register OPAL event notifier (%d)\n", | ||
181 | __func__, ret); | ||
182 | return ret; | ||
183 | } | ||
184 | opal_hmi_handler_nb_init = 1; | ||
185 | } | ||
186 | return 0; | ||
187 | } | ||
188 | subsys_initcall(opal_hmi_handler_init); | ||
diff --git a/arch/powerpc/platforms/powernv/opal-lpc.c b/arch/powerpc/platforms/powernv/opal-lpc.c index f04b4d8aca5a..ad4b31df779a 100644 --- a/arch/powerpc/platforms/powernv/opal-lpc.c +++ b/arch/powerpc/platforms/powernv/opal-lpc.c | |||
@@ -324,7 +324,7 @@ static int opal_lpc_init_debugfs(void) | |||
324 | rc |= opal_lpc_debugfs_create_type(root, "fw", OPAL_LPC_FW); | 324 | rc |= opal_lpc_debugfs_create_type(root, "fw", OPAL_LPC_FW); |
325 | return rc; | 325 | return rc; |
326 | } | 326 | } |
327 | device_initcall(opal_lpc_init_debugfs); | 327 | machine_device_initcall(powernv, opal_lpc_init_debugfs); |
328 | #endif /* CONFIG_DEBUG_FS */ | 328 | #endif /* CONFIG_DEBUG_FS */ |
329 | 329 | ||
330 | void opal_lpc_init(void) | 330 | void opal_lpc_init(void) |
diff --git a/arch/powerpc/platforms/powernv/opal-memory-errors.c b/arch/powerpc/platforms/powernv/opal-memory-errors.c index b17a34b695ef..43db2136dbff 100644 --- a/arch/powerpc/platforms/powernv/opal-memory-errors.c +++ b/arch/powerpc/platforms/powernv/opal-memory-errors.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/mm.h> | 27 | #include <linux/mm.h> |
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | 29 | ||
30 | #include <asm/machdep.h> | ||
30 | #include <asm/opal.h> | 31 | #include <asm/opal.h> |
31 | #include <asm/cputable.h> | 32 | #include <asm/cputable.h> |
32 | 33 | ||
@@ -143,4 +144,4 @@ static int __init opal_mem_err_init(void) | |||
143 | } | 144 | } |
144 | return 0; | 145 | return 0; |
145 | } | 146 | } |
146 | subsys_initcall(opal_mem_err_init); | 147 | machine_subsys_initcall(powernv, opal_mem_err_init); |
diff --git a/arch/powerpc/platforms/powernv/opal-tracepoints.c b/arch/powerpc/platforms/powernv/opal-tracepoints.c new file mode 100644 index 000000000000..d8a000a9988b --- /dev/null +++ b/arch/powerpc/platforms/powernv/opal-tracepoints.c | |||
@@ -0,0 +1,84 @@ | |||
1 | #include <linux/percpu.h> | ||
2 | #include <linux/jump_label.h> | ||
3 | #include <asm/trace.h> | ||
4 | |||
5 | #ifdef CONFIG_JUMP_LABEL | ||
6 | struct static_key opal_tracepoint_key = STATIC_KEY_INIT; | ||
7 | |||
8 | void opal_tracepoint_regfunc(void) | ||
9 | { | ||
10 | static_key_slow_inc(&opal_tracepoint_key); | ||
11 | } | ||
12 | |||
13 | void opal_tracepoint_unregfunc(void) | ||
14 | { | ||
15 | static_key_slow_dec(&opal_tracepoint_key); | ||
16 | } | ||
17 | #else | ||
18 | /* | ||
19 | * We optimise OPAL calls by placing opal_tracepoint_refcount | ||
20 | * directly in the TOC so we can check if the opal tracepoints are | ||
21 | * enabled via a single load. | ||
22 | */ | ||
23 | |||
24 | /* NB: reg/unreg are called while guarded with the tracepoints_mutex */ | ||
25 | extern long opal_tracepoint_refcount; | ||
26 | |||
27 | void opal_tracepoint_regfunc(void) | ||
28 | { | ||
29 | opal_tracepoint_refcount++; | ||
30 | } | ||
31 | |||
32 | void opal_tracepoint_unregfunc(void) | ||
33 | { | ||
34 | opal_tracepoint_refcount--; | ||
35 | } | ||
36 | #endif | ||
37 | |||
38 | /* | ||
39 | * Since the tracing code might execute OPAL calls we need to guard against | ||
40 | * recursion. | ||
41 | */ | ||
42 | static DEFINE_PER_CPU(unsigned int, opal_trace_depth); | ||
43 | |||
44 | void __trace_opal_entry(unsigned long opcode, unsigned long *args) | ||
45 | { | ||
46 | unsigned long flags; | ||
47 | unsigned int *depth; | ||
48 | |||
49 | local_irq_save(flags); | ||
50 | |||
51 | depth = &__get_cpu_var(opal_trace_depth); | ||
52 | |||
53 | if (*depth) | ||
54 | goto out; | ||
55 | |||
56 | (*depth)++; | ||
57 | preempt_disable(); | ||
58 | trace_opal_entry(opcode, args); | ||
59 | (*depth)--; | ||
60 | |||
61 | out: | ||
62 | local_irq_restore(flags); | ||
63 | } | ||
64 | |||
65 | void __trace_opal_exit(long opcode, unsigned long retval) | ||
66 | { | ||
67 | unsigned long flags; | ||
68 | unsigned int *depth; | ||
69 | |||
70 | local_irq_save(flags); | ||
71 | |||
72 | depth = &__get_cpu_var(opal_trace_depth); | ||
73 | |||
74 | if (*depth) | ||
75 | goto out; | ||
76 | |||
77 | (*depth)++; | ||
78 | trace_opal_exit(opcode, retval); | ||
79 | preempt_enable(); | ||
80 | (*depth)--; | ||
81 | |||
82 | out: | ||
83 | local_irq_restore(flags); | ||
84 | } | ||
diff --git a/arch/powerpc/platforms/powernv/opal-wrappers.S b/arch/powerpc/platforms/powernv/opal-wrappers.S index 4abbff22a61f..2e6ce1b8dc8f 100644 --- a/arch/powerpc/platforms/powernv/opal-wrappers.S +++ b/arch/powerpc/platforms/powernv/opal-wrappers.S | |||
@@ -13,30 +13,69 @@ | |||
13 | #include <asm/hvcall.h> | 13 | #include <asm/hvcall.h> |
14 | #include <asm/asm-offsets.h> | 14 | #include <asm/asm-offsets.h> |
15 | #include <asm/opal.h> | 15 | #include <asm/opal.h> |
16 | #include <asm/jump_label.h> | ||
17 | |||
18 | .section ".text" | ||
19 | |||
20 | #ifdef CONFIG_TRACEPOINTS | ||
21 | #ifdef CONFIG_JUMP_LABEL | ||
22 | #define OPAL_BRANCH(LABEL) \ | ||
23 | ARCH_STATIC_BRANCH(LABEL, opal_tracepoint_key) | ||
24 | #else | ||
25 | |||
26 | .section ".toc","aw" | ||
27 | |||
28 | .globl opal_tracepoint_refcount | ||
29 | opal_tracepoint_refcount: | ||
30 | .llong 0 | ||
31 | |||
32 | .section ".text" | ||
33 | |||
34 | /* | ||
35 | * We branch around this in early init by using an unconditional cpu | ||
36 | * feature. | ||
37 | */ | ||
38 | #define OPAL_BRANCH(LABEL) \ | ||
39 | BEGIN_FTR_SECTION; \ | ||
40 | b 1f; \ | ||
41 | END_FTR_SECTION(0, 1); \ | ||
42 | ld r12,opal_tracepoint_refcount@toc(r2); \ | ||
43 | std r12,32(r1); \ | ||
44 | cmpdi r12,0; \ | ||
45 | bne- LABEL; \ | ||
46 | 1: | ||
47 | |||
48 | #endif | ||
49 | |||
50 | #else | ||
51 | #define OPAL_BRANCH(LABEL) | ||
52 | #endif | ||
16 | 53 | ||
17 | /* TODO: | 54 | /* TODO: |
18 | * | 55 | * |
19 | * - Trace irqs in/off (needs saving/restoring all args, argh...) | 56 | * - Trace irqs in/off (needs saving/restoring all args, argh...) |
20 | * - Get r11 feed up by Dave so I can have better register usage | 57 | * - Get r11 feed up by Dave so I can have better register usage |
21 | */ | 58 | */ |
59 | |||
22 | #define OPAL_CALL(name, token) \ | 60 | #define OPAL_CALL(name, token) \ |
23 | _GLOBAL(name); \ | 61 | _GLOBAL(name); \ |
24 | mflr r0; \ | 62 | mflr r0; \ |
25 | mfcr r12; \ | ||
26 | std r0,16(r1); \ | 63 | std r0,16(r1); \ |
64 | li r0,token; \ | ||
65 | OPAL_BRANCH(opal_tracepoint_entry) \ | ||
66 | mfcr r12; \ | ||
27 | stw r12,8(r1); \ | 67 | stw r12,8(r1); \ |
28 | std r1,PACAR1(r13); \ | 68 | std r1,PACAR1(r13); \ |
29 | li r0,0; \ | 69 | li r11,0; \ |
30 | mfmsr r12; \ | 70 | mfmsr r12; \ |
31 | ori r0,r0,MSR_EE; \ | 71 | ori r11,r11,MSR_EE; \ |
32 | std r12,PACASAVEDMSR(r13); \ | 72 | std r12,PACASAVEDMSR(r13); \ |
33 | andc r12,r12,r0; \ | 73 | andc r12,r12,r11; \ |
34 | mtmsrd r12,1; \ | 74 | mtmsrd r12,1; \ |
35 | LOAD_REG_ADDR(r0,opal_return); \ | 75 | LOAD_REG_ADDR(r11,opal_return); \ |
36 | mtlr r0; \ | 76 | mtlr r11; \ |
37 | li r0,MSR_DR|MSR_IR|MSR_LE;\ | 77 | li r11,MSR_DR|MSR_IR|MSR_LE;\ |
38 | andc r12,r12,r0; \ | 78 | andc r12,r12,r11; \ |
39 | li r0,token; \ | ||
40 | mtspr SPRN_HSRR1,r12; \ | 79 | mtspr SPRN_HSRR1,r12; \ |
41 | LOAD_REG_ADDR(r11,opal); \ | 80 | LOAD_REG_ADDR(r11,opal); \ |
42 | ld r12,8(r11); \ | 81 | ld r12,8(r11); \ |
@@ -61,6 +100,64 @@ opal_return: | |||
61 | mtcr r4; | 100 | mtcr r4; |
62 | rfid | 101 | rfid |
63 | 102 | ||
103 | #ifdef CONFIG_TRACEPOINTS | ||
104 | opal_tracepoint_entry: | ||
105 | stdu r1,-STACKFRAMESIZE(r1) | ||
106 | std r0,STK_REG(R23)(r1) | ||
107 | std r3,STK_REG(R24)(r1) | ||
108 | std r4,STK_REG(R25)(r1) | ||
109 | std r5,STK_REG(R26)(r1) | ||
110 | std r6,STK_REG(R27)(r1) | ||
111 | std r7,STK_REG(R28)(r1) | ||
112 | std r8,STK_REG(R29)(r1) | ||
113 | std r9,STK_REG(R30)(r1) | ||
114 | std r10,STK_REG(R31)(r1) | ||
115 | mr r3,r0 | ||
116 | addi r4,r1,STK_REG(R24) | ||
117 | bl __trace_opal_entry | ||
118 | ld r0,STK_REG(R23)(r1) | ||
119 | ld r3,STK_REG(R24)(r1) | ||
120 | ld r4,STK_REG(R25)(r1) | ||
121 | ld r5,STK_REG(R26)(r1) | ||
122 | ld r6,STK_REG(R27)(r1) | ||
123 | ld r7,STK_REG(R28)(r1) | ||
124 | ld r8,STK_REG(R29)(r1) | ||
125 | ld r9,STK_REG(R30)(r1) | ||
126 | ld r10,STK_REG(R31)(r1) | ||
127 | LOAD_REG_ADDR(r11,opal_tracepoint_return) | ||
128 | mfcr r12 | ||
129 | std r11,16(r1) | ||
130 | stw r12,8(r1) | ||
131 | std r1,PACAR1(r13) | ||
132 | li r11,0 | ||
133 | mfmsr r12 | ||
134 | ori r11,r11,MSR_EE | ||
135 | std r12,PACASAVEDMSR(r13) | ||
136 | andc r12,r12,r11 | ||
137 | mtmsrd r12,1 | ||
138 | LOAD_REG_ADDR(r11,opal_return) | ||
139 | mtlr r11 | ||
140 | li r11,MSR_DR|MSR_IR|MSR_LE | ||
141 | andc r12,r12,r11 | ||
142 | mtspr SPRN_HSRR1,r12 | ||
143 | LOAD_REG_ADDR(r11,opal) | ||
144 | ld r12,8(r11) | ||
145 | ld r2,0(r11) | ||
146 | mtspr SPRN_HSRR0,r12 | ||
147 | hrfid | ||
148 | |||
149 | opal_tracepoint_return: | ||
150 | std r3,STK_REG(R31)(r1) | ||
151 | mr r4,r3 | ||
152 | ld r0,STK_REG(R23)(r1) | ||
153 | bl __trace_opal_exit | ||
154 | ld r3,STK_REG(R31)(r1) | ||
155 | addi r1,r1,STACKFRAMESIZE | ||
156 | ld r0,16(r1) | ||
157 | mtlr r0 | ||
158 | blr | ||
159 | #endif | ||
160 | |||
64 | OPAL_CALL(opal_invalid_call, OPAL_INVALID_CALL); | 161 | OPAL_CALL(opal_invalid_call, OPAL_INVALID_CALL); |
65 | OPAL_CALL(opal_console_write, OPAL_CONSOLE_WRITE); | 162 | OPAL_CALL(opal_console_write, OPAL_CONSOLE_WRITE); |
66 | OPAL_CALL(opal_console_read, OPAL_CONSOLE_READ); | 163 | OPAL_CALL(opal_console_read, OPAL_CONSOLE_READ); |
@@ -86,6 +183,7 @@ OPAL_CALL(opal_get_xive, OPAL_GET_XIVE); | |||
86 | OPAL_CALL(opal_register_exception_handler, OPAL_REGISTER_OPAL_EXCEPTION_HANDLER); | 183 | OPAL_CALL(opal_register_exception_handler, OPAL_REGISTER_OPAL_EXCEPTION_HANDLER); |
87 | OPAL_CALL(opal_pci_eeh_freeze_status, OPAL_PCI_EEH_FREEZE_STATUS); | 184 | OPAL_CALL(opal_pci_eeh_freeze_status, OPAL_PCI_EEH_FREEZE_STATUS); |
88 | OPAL_CALL(opal_pci_eeh_freeze_clear, OPAL_PCI_EEH_FREEZE_CLEAR); | 185 | OPAL_CALL(opal_pci_eeh_freeze_clear, OPAL_PCI_EEH_FREEZE_CLEAR); |
186 | OPAL_CALL(opal_pci_eeh_freeze_set, OPAL_PCI_EEH_FREEZE_SET); | ||
89 | OPAL_CALL(opal_pci_shpc, OPAL_PCI_SHPC); | 187 | OPAL_CALL(opal_pci_shpc, OPAL_PCI_SHPC); |
90 | OPAL_CALL(opal_pci_phb_mmio_enable, OPAL_PCI_PHB_MMIO_ENABLE); | 188 | OPAL_CALL(opal_pci_phb_mmio_enable, OPAL_PCI_PHB_MMIO_ENABLE); |
91 | OPAL_CALL(opal_pci_set_phb_mem_window, OPAL_PCI_SET_PHB_MEM_WINDOW); | 189 | OPAL_CALL(opal_pci_set_phb_mem_window, OPAL_PCI_SET_PHB_MEM_WINDOW); |
@@ -146,3 +244,6 @@ OPAL_CALL(opal_sync_host_reboot, OPAL_SYNC_HOST_REBOOT); | |||
146 | OPAL_CALL(opal_sensor_read, OPAL_SENSOR_READ); | 244 | OPAL_CALL(opal_sensor_read, OPAL_SENSOR_READ); |
147 | OPAL_CALL(opal_get_param, OPAL_GET_PARAM); | 245 | OPAL_CALL(opal_get_param, OPAL_GET_PARAM); |
148 | OPAL_CALL(opal_set_param, OPAL_SET_PARAM); | 246 | OPAL_CALL(opal_set_param, OPAL_SET_PARAM); |
247 | OPAL_CALL(opal_handle_hmi, OPAL_HANDLE_HMI); | ||
248 | OPAL_CALL(opal_register_dump_region, OPAL_REGISTER_DUMP_REGION); | ||
249 | OPAL_CALL(opal_unregister_dump_region, OPAL_UNREGISTER_DUMP_REGION); | ||
diff --git a/arch/powerpc/platforms/powernv/opal-xscom.c b/arch/powerpc/platforms/powernv/opal-xscom.c index 4cd2ea6c0dbe..7634d1c62299 100644 --- a/arch/powerpc/platforms/powernv/opal-xscom.c +++ b/arch/powerpc/platforms/powernv/opal-xscom.c | |||
@@ -130,4 +130,4 @@ static int opal_xscom_init(void) | |||
130 | scom_init(&opal_scom_controller); | 130 | scom_init(&opal_scom_controller); |
131 | return 0; | 131 | return 0; |
132 | } | 132 | } |
133 | arch_initcall(opal_xscom_init); | 133 | machine_arch_initcall(powernv, opal_xscom_init); |
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c index 199975613fe9..b44eec3e8dbd 100644 --- a/arch/powerpc/platforms/powernv/opal.c +++ b/arch/powerpc/platforms/powernv/opal.c | |||
@@ -22,6 +22,8 @@ | |||
22 | #include <linux/kobject.h> | 22 | #include <linux/kobject.h> |
23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
24 | #include <linux/memblock.h> | 24 | #include <linux/memblock.h> |
25 | |||
26 | #include <asm/machdep.h> | ||
25 | #include <asm/opal.h> | 27 | #include <asm/opal.h> |
26 | #include <asm/firmware.h> | 28 | #include <asm/firmware.h> |
27 | #include <asm/mce.h> | 29 | #include <asm/mce.h> |
@@ -192,16 +194,12 @@ static int __init opal_register_exception_handlers(void) | |||
192 | * fwnmi area at 0x7000 to provide the glue space to OPAL | 194 | * fwnmi area at 0x7000 to provide the glue space to OPAL |
193 | */ | 195 | */ |
194 | glue = 0x7000; | 196 | glue = 0x7000; |
195 | opal_register_exception_handler(OPAL_HYPERVISOR_MAINTENANCE_HANDLER, | ||
196 | 0, glue); | ||
197 | glue += 128; | ||
198 | opal_register_exception_handler(OPAL_SOFTPATCH_HANDLER, 0, glue); | 197 | opal_register_exception_handler(OPAL_SOFTPATCH_HANDLER, 0, glue); |
199 | #endif | 198 | #endif |
200 | 199 | ||
201 | return 0; | 200 | return 0; |
202 | } | 201 | } |
203 | 202 | machine_early_initcall(powernv, opal_register_exception_handlers); | |
204 | early_initcall(opal_register_exception_handlers); | ||
205 | 203 | ||
206 | int opal_notifier_register(struct notifier_block *nb) | 204 | int opal_notifier_register(struct notifier_block *nb) |
207 | { | 205 | { |
@@ -368,7 +366,7 @@ static int __init opal_message_init(void) | |||
368 | } | 366 | } |
369 | return 0; | 367 | return 0; |
370 | } | 368 | } |
371 | early_initcall(opal_message_init); | 369 | machine_early_initcall(powernv, opal_message_init); |
372 | 370 | ||
373 | int opal_get_chars(uint32_t vtermno, char *buf, int count) | 371 | int opal_get_chars(uint32_t vtermno, char *buf, int count) |
374 | { | 372 | { |
@@ -513,6 +511,46 @@ int opal_machine_check(struct pt_regs *regs) | |||
513 | return 0; | 511 | return 0; |
514 | } | 512 | } |
515 | 513 | ||
514 | /* Early hmi handler called in real mode. */ | ||
515 | int opal_hmi_exception_early(struct pt_regs *regs) | ||
516 | { | ||
517 | s64 rc; | ||
518 | |||
519 | /* | ||
520 | * call opal hmi handler. Pass paca address as token. | ||
521 | * The return value OPAL_SUCCESS is an indication that there is | ||
522 | * an HMI event generated waiting to pull by Linux. | ||
523 | */ | ||
524 | rc = opal_handle_hmi(); | ||
525 | if (rc == OPAL_SUCCESS) { | ||
526 | local_paca->hmi_event_available = 1; | ||
527 | return 1; | ||
528 | } | ||
529 | return 0; | ||
530 | } | ||
531 | |||
532 | /* HMI exception handler called in virtual mode during check_irq_replay. */ | ||
533 | int opal_handle_hmi_exception(struct pt_regs *regs) | ||
534 | { | ||
535 | s64 rc; | ||
536 | __be64 evt = 0; | ||
537 | |||
538 | /* | ||
539 | * Check if HMI event is available. | ||
540 | * if Yes, then call opal_poll_events to pull opal messages and | ||
541 | * process them. | ||
542 | */ | ||
543 | if (!local_paca->hmi_event_available) | ||
544 | return 0; | ||
545 | |||
546 | local_paca->hmi_event_available = 0; | ||
547 | rc = opal_poll_events(&evt); | ||
548 | if (rc == OPAL_SUCCESS && evt) | ||
549 | opal_do_notifier(be64_to_cpu(evt)); | ||
550 | |||
551 | return 1; | ||
552 | } | ||
553 | |||
516 | static uint64_t find_recovery_address(uint64_t nip) | 554 | static uint64_t find_recovery_address(uint64_t nip) |
517 | { | 555 | { |
518 | int i; | 556 | int i; |
@@ -567,6 +605,24 @@ static int opal_sysfs_init(void) | |||
567 | return 0; | 605 | return 0; |
568 | } | 606 | } |
569 | 607 | ||
608 | static void __init opal_dump_region_init(void) | ||
609 | { | ||
610 | void *addr; | ||
611 | uint64_t size; | ||
612 | int rc; | ||
613 | |||
614 | /* Register kernel log buffer */ | ||
615 | addr = log_buf_addr_get(); | ||
616 | size = log_buf_len_get(); | ||
617 | rc = opal_register_dump_region(OPAL_DUMP_REGION_LOG_BUF, | ||
618 | __pa(addr), size); | ||
619 | /* Don't warn if this is just an older OPAL that doesn't | ||
620 | * know about that call | ||
621 | */ | ||
622 | if (rc && rc != OPAL_UNSUPPORTED) | ||
623 | pr_warn("DUMP: Failed to register kernel log buffer. " | ||
624 | "rc = %d\n", rc); | ||
625 | } | ||
570 | static int __init opal_init(void) | 626 | static int __init opal_init(void) |
571 | { | 627 | { |
572 | struct device_node *np, *consoles; | 628 | struct device_node *np, *consoles; |
@@ -616,6 +672,8 @@ static int __init opal_init(void) | |||
616 | /* Create "opal" kobject under /sys/firmware */ | 672 | /* Create "opal" kobject under /sys/firmware */ |
617 | rc = opal_sysfs_init(); | 673 | rc = opal_sysfs_init(); |
618 | if (rc == 0) { | 674 | if (rc == 0) { |
675 | /* Setup dump region interface */ | ||
676 | opal_dump_region_init(); | ||
619 | /* Setup error log interface */ | 677 | /* Setup error log interface */ |
620 | rc = opal_elog_init(); | 678 | rc = opal_elog_init(); |
621 | /* Setup code update interface */ | 679 | /* Setup code update interface */ |
@@ -630,7 +688,7 @@ static int __init opal_init(void) | |||
630 | 688 | ||
631 | return 0; | 689 | return 0; |
632 | } | 690 | } |
633 | subsys_initcall(opal_init); | 691 | machine_subsys_initcall(powernv, opal_init); |
634 | 692 | ||
635 | void opal_shutdown(void) | 693 | void opal_shutdown(void) |
636 | { | 694 | { |
@@ -656,6 +714,9 @@ void opal_shutdown(void) | |||
656 | else | 714 | else |
657 | mdelay(10); | 715 | mdelay(10); |
658 | } | 716 | } |
717 | |||
718 | /* Unregister memory dump region */ | ||
719 | opal_unregister_dump_region(OPAL_DUMP_REGION_LOG_BUF); | ||
659 | } | 720 | } |
660 | 721 | ||
661 | /* Export this so that test modules can use it */ | 722 | /* Export this so that test modules can use it */ |
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index de19edeaa7a7..df241b11d4f7 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <asm/tce.h> | 36 | #include <asm/tce.h> |
37 | #include <asm/xics.h> | 37 | #include <asm/xics.h> |
38 | #include <asm/debug.h> | 38 | #include <asm/debug.h> |
39 | #include <asm/firmware.h> | ||
39 | 40 | ||
40 | #include "powernv.h" | 41 | #include "powernv.h" |
41 | #include "pci.h" | 42 | #include "pci.h" |
@@ -82,6 +83,12 @@ static inline void __raw_rm_writeq(u64 val, volatile void __iomem *paddr) | |||
82 | : : "r" (val), "r" (paddr) : "memory"); | 83 | : : "r" (val), "r" (paddr) : "memory"); |
83 | } | 84 | } |
84 | 85 | ||
86 | static inline bool pnv_pci_is_mem_pref_64(unsigned long flags) | ||
87 | { | ||
88 | return ((flags & (IORESOURCE_MEM_64 | IORESOURCE_PREFETCH)) == | ||
89 | (IORESOURCE_MEM_64 | IORESOURCE_PREFETCH)); | ||
90 | } | ||
91 | |||
85 | static int pnv_ioda_alloc_pe(struct pnv_phb *phb) | 92 | static int pnv_ioda_alloc_pe(struct pnv_phb *phb) |
86 | { | 93 | { |
87 | unsigned long pe; | 94 | unsigned long pe; |
@@ -106,6 +113,380 @@ static void pnv_ioda_free_pe(struct pnv_phb *phb, int pe) | |||
106 | clear_bit(pe, phb->ioda.pe_alloc); | 113 | clear_bit(pe, phb->ioda.pe_alloc); |
107 | } | 114 | } |
108 | 115 | ||
116 | /* The default M64 BAR is shared by all PEs */ | ||
117 | static int pnv_ioda2_init_m64(struct pnv_phb *phb) | ||
118 | { | ||
119 | const char *desc; | ||
120 | struct resource *r; | ||
121 | s64 rc; | ||
122 | |||
123 | /* Configure the default M64 BAR */ | ||
124 | rc = opal_pci_set_phb_mem_window(phb->opal_id, | ||
125 | OPAL_M64_WINDOW_TYPE, | ||
126 | phb->ioda.m64_bar_idx, | ||
127 | phb->ioda.m64_base, | ||
128 | 0, /* unused */ | ||
129 | phb->ioda.m64_size); | ||
130 | if (rc != OPAL_SUCCESS) { | ||
131 | desc = "configuring"; | ||
132 | goto fail; | ||
133 | } | ||
134 | |||
135 | /* Enable the default M64 BAR */ | ||
136 | rc = opal_pci_phb_mmio_enable(phb->opal_id, | ||
137 | OPAL_M64_WINDOW_TYPE, | ||
138 | phb->ioda.m64_bar_idx, | ||
139 | OPAL_ENABLE_M64_SPLIT); | ||
140 | if (rc != OPAL_SUCCESS) { | ||
141 | desc = "enabling"; | ||
142 | goto fail; | ||
143 | } | ||
144 | |||
145 | /* Mark the M64 BAR assigned */ | ||
146 | set_bit(phb->ioda.m64_bar_idx, &phb->ioda.m64_bar_alloc); | ||
147 | |||
148 | /* | ||
149 | * Strip off the segment used by the reserved PE, which is | ||
150 | * expected to be 0 or last one of PE capabicity. | ||
151 | */ | ||
152 | r = &phb->hose->mem_resources[1]; | ||
153 | if (phb->ioda.reserved_pe == 0) | ||
154 | r->start += phb->ioda.m64_segsize; | ||
155 | else if (phb->ioda.reserved_pe == (phb->ioda.total_pe - 1)) | ||
156 | r->end -= phb->ioda.m64_segsize; | ||
157 | else | ||
158 | pr_warn(" Cannot strip M64 segment for reserved PE#%d\n", | ||
159 | phb->ioda.reserved_pe); | ||
160 | |||
161 | return 0; | ||
162 | |||
163 | fail: | ||
164 | pr_warn(" Failure %lld %s M64 BAR#%d\n", | ||
165 | rc, desc, phb->ioda.m64_bar_idx); | ||
166 | opal_pci_phb_mmio_enable(phb->opal_id, | ||
167 | OPAL_M64_WINDOW_TYPE, | ||
168 | phb->ioda.m64_bar_idx, | ||
169 | OPAL_DISABLE_M64); | ||
170 | return -EIO; | ||
171 | } | ||
172 | |||
173 | static void pnv_ioda2_alloc_m64_pe(struct pnv_phb *phb) | ||
174 | { | ||
175 | resource_size_t sgsz = phb->ioda.m64_segsize; | ||
176 | struct pci_dev *pdev; | ||
177 | struct resource *r; | ||
178 | int base, step, i; | ||
179 | |||
180 | /* | ||
181 | * Root bus always has full M64 range and root port has | ||
182 | * M64 range used in reality. So we're checking root port | ||
183 | * instead of root bus. | ||
184 | */ | ||
185 | list_for_each_entry(pdev, &phb->hose->bus->devices, bus_list) { | ||
186 | for (i = PCI_BRIDGE_RESOURCES; | ||
187 | i <= PCI_BRIDGE_RESOURCE_END; i++) { | ||
188 | r = &pdev->resource[i]; | ||
189 | if (!r->parent || | ||
190 | !pnv_pci_is_mem_pref_64(r->flags)) | ||
191 | continue; | ||
192 | |||
193 | base = (r->start - phb->ioda.m64_base) / sgsz; | ||
194 | for (step = 0; step < resource_size(r) / sgsz; step++) | ||
195 | set_bit(base + step, phb->ioda.pe_alloc); | ||
196 | } | ||
197 | } | ||
198 | } | ||
199 | |||
200 | static int pnv_ioda2_pick_m64_pe(struct pnv_phb *phb, | ||
201 | struct pci_bus *bus, int all) | ||
202 | { | ||
203 | resource_size_t segsz = phb->ioda.m64_segsize; | ||
204 | struct pci_dev *pdev; | ||
205 | struct resource *r; | ||
206 | struct pnv_ioda_pe *master_pe, *pe; | ||
207 | unsigned long size, *pe_alloc; | ||
208 | bool found; | ||
209 | int start, i, j; | ||
210 | |||
211 | /* Root bus shouldn't use M64 */ | ||
212 | if (pci_is_root_bus(bus)) | ||
213 | return IODA_INVALID_PE; | ||
214 | |||
215 | /* We support only one M64 window on each bus */ | ||
216 | found = false; | ||
217 | pci_bus_for_each_resource(bus, r, i) { | ||
218 | if (r && r->parent && | ||
219 | pnv_pci_is_mem_pref_64(r->flags)) { | ||
220 | found = true; | ||
221 | break; | ||
222 | } | ||
223 | } | ||
224 | |||
225 | /* No M64 window found ? */ | ||
226 | if (!found) | ||
227 | return IODA_INVALID_PE; | ||
228 | |||
229 | /* Allocate bitmap */ | ||
230 | size = _ALIGN_UP(phb->ioda.total_pe / 8, sizeof(unsigned long)); | ||
231 | pe_alloc = kzalloc(size, GFP_KERNEL); | ||
232 | if (!pe_alloc) { | ||
233 | pr_warn("%s: Out of memory !\n", | ||
234 | __func__); | ||
235 | return IODA_INVALID_PE; | ||
236 | } | ||
237 | |||
238 | /* | ||
239 | * Figure out reserved PE numbers by the PE | ||
240 | * the its child PEs. | ||
241 | */ | ||
242 | start = (r->start - phb->ioda.m64_base) / segsz; | ||
243 | for (i = 0; i < resource_size(r) / segsz; i++) | ||
244 | set_bit(start + i, pe_alloc); | ||
245 | |||
246 | if (all) | ||
247 | goto done; | ||
248 | |||
249 | /* | ||
250 | * If the PE doesn't cover all subordinate buses, | ||
251 | * we need subtract from reserved PEs for children. | ||
252 | */ | ||
253 | list_for_each_entry(pdev, &bus->devices, bus_list) { | ||
254 | if (!pdev->subordinate) | ||
255 | continue; | ||
256 | |||
257 | pci_bus_for_each_resource(pdev->subordinate, r, i) { | ||
258 | if (!r || !r->parent || | ||
259 | !pnv_pci_is_mem_pref_64(r->flags)) | ||
260 | continue; | ||
261 | |||
262 | start = (r->start - phb->ioda.m64_base) / segsz; | ||
263 | for (j = 0; j < resource_size(r) / segsz ; j++) | ||
264 | clear_bit(start + j, pe_alloc); | ||
265 | } | ||
266 | } | ||
267 | |||
268 | /* | ||
269 | * the current bus might not own M64 window and that's all | ||
270 | * contributed by its child buses. For the case, we needn't | ||
271 | * pick M64 dependent PE#. | ||
272 | */ | ||
273 | if (bitmap_empty(pe_alloc, phb->ioda.total_pe)) { | ||
274 | kfree(pe_alloc); | ||
275 | return IODA_INVALID_PE; | ||
276 | } | ||
277 | |||
278 | /* | ||
279 | * Figure out the master PE and put all slave PEs to master | ||
280 | * PE's list to form compound PE. | ||
281 | */ | ||
282 | done: | ||
283 | master_pe = NULL; | ||
284 | i = -1; | ||
285 | while ((i = find_next_bit(pe_alloc, phb->ioda.total_pe, i + 1)) < | ||
286 | phb->ioda.total_pe) { | ||
287 | pe = &phb->ioda.pe_array[i]; | ||
288 | pe->phb = phb; | ||
289 | pe->pe_number = i; | ||
290 | |||
291 | if (!master_pe) { | ||
292 | pe->flags |= PNV_IODA_PE_MASTER; | ||
293 | INIT_LIST_HEAD(&pe->slaves); | ||
294 | master_pe = pe; | ||
295 | } else { | ||
296 | pe->flags |= PNV_IODA_PE_SLAVE; | ||
297 | pe->master = master_pe; | ||
298 | list_add_tail(&pe->list, &master_pe->slaves); | ||
299 | } | ||
300 | } | ||
301 | |||
302 | kfree(pe_alloc); | ||
303 | return master_pe->pe_number; | ||
304 | } | ||
305 | |||
306 | static void __init pnv_ioda_parse_m64_window(struct pnv_phb *phb) | ||
307 | { | ||
308 | struct pci_controller *hose = phb->hose; | ||
309 | struct device_node *dn = hose->dn; | ||
310 | struct resource *res; | ||
311 | const u32 *r; | ||
312 | u64 pci_addr; | ||
313 | |||
314 | if (!firmware_has_feature(FW_FEATURE_OPALv3)) { | ||
315 | pr_info(" Firmware too old to support M64 window\n"); | ||
316 | return; | ||
317 | } | ||
318 | |||
319 | r = of_get_property(dn, "ibm,opal-m64-window", NULL); | ||
320 | if (!r) { | ||
321 | pr_info(" No <ibm,opal-m64-window> on %s\n", | ||
322 | dn->full_name); | ||
323 | return; | ||
324 | } | ||
325 | |||
326 | /* FIXME: Support M64 for P7IOC */ | ||
327 | if (phb->type != PNV_PHB_IODA2) { | ||
328 | pr_info(" Not support M64 window\n"); | ||
329 | return; | ||
330 | } | ||
331 | |||
332 | res = &hose->mem_resources[1]; | ||
333 | res->start = of_translate_address(dn, r + 2); | ||
334 | res->end = res->start + of_read_number(r + 4, 2) - 1; | ||
335 | res->flags = (IORESOURCE_MEM | IORESOURCE_MEM_64 | IORESOURCE_PREFETCH); | ||
336 | pci_addr = of_read_number(r, 2); | ||
337 | hose->mem_offset[1] = res->start - pci_addr; | ||
338 | |||
339 | phb->ioda.m64_size = resource_size(res); | ||
340 | phb->ioda.m64_segsize = phb->ioda.m64_size / phb->ioda.total_pe; | ||
341 | phb->ioda.m64_base = pci_addr; | ||
342 | |||
343 | /* Use last M64 BAR to cover M64 window */ | ||
344 | phb->ioda.m64_bar_idx = 15; | ||
345 | phb->init_m64 = pnv_ioda2_init_m64; | ||
346 | phb->alloc_m64_pe = pnv_ioda2_alloc_m64_pe; | ||
347 | phb->pick_m64_pe = pnv_ioda2_pick_m64_pe; | ||
348 | } | ||
349 | |||
350 | static void pnv_ioda_freeze_pe(struct pnv_phb *phb, int pe_no) | ||
351 | { | ||
352 | struct pnv_ioda_pe *pe = &phb->ioda.pe_array[pe_no]; | ||
353 | struct pnv_ioda_pe *slave; | ||
354 | s64 rc; | ||
355 | |||
356 | /* Fetch master PE */ | ||
357 | if (pe->flags & PNV_IODA_PE_SLAVE) { | ||
358 | pe = pe->master; | ||
359 | WARN_ON(!pe || !(pe->flags & PNV_IODA_PE_MASTER)); | ||
360 | pe_no = pe->pe_number; | ||
361 | } | ||
362 | |||
363 | /* Freeze master PE */ | ||
364 | rc = opal_pci_eeh_freeze_set(phb->opal_id, | ||
365 | pe_no, | ||
366 | OPAL_EEH_ACTION_SET_FREEZE_ALL); | ||
367 | if (rc != OPAL_SUCCESS) { | ||
368 | pr_warn("%s: Failure %lld freezing PHB#%x-PE#%x\n", | ||
369 | __func__, rc, phb->hose->global_number, pe_no); | ||
370 | return; | ||
371 | } | ||
372 | |||
373 | /* Freeze slave PEs */ | ||
374 | if (!(pe->flags & PNV_IODA_PE_MASTER)) | ||
375 | return; | ||
376 | |||
377 | list_for_each_entry(slave, &pe->slaves, list) { | ||
378 | rc = opal_pci_eeh_freeze_set(phb->opal_id, | ||
379 | slave->pe_number, | ||
380 | OPAL_EEH_ACTION_SET_FREEZE_ALL); | ||
381 | if (rc != OPAL_SUCCESS) | ||
382 | pr_warn("%s: Failure %lld freezing PHB#%x-PE#%x\n", | ||
383 | __func__, rc, phb->hose->global_number, | ||
384 | slave->pe_number); | ||
385 | } | ||
386 | } | ||
387 | |||
388 | int pnv_ioda_unfreeze_pe(struct pnv_phb *phb, int pe_no, int opt) | ||
389 | { | ||
390 | struct pnv_ioda_pe *pe, *slave; | ||
391 | s64 rc; | ||
392 | |||
393 | /* Find master PE */ | ||
394 | pe = &phb->ioda.pe_array[pe_no]; | ||
395 | if (pe->flags & PNV_IODA_PE_SLAVE) { | ||
396 | pe = pe->master; | ||
397 | WARN_ON(!pe || !(pe->flags & PNV_IODA_PE_MASTER)); | ||
398 | pe_no = pe->pe_number; | ||
399 | } | ||
400 | |||
401 | /* Clear frozen state for master PE */ | ||
402 | rc = opal_pci_eeh_freeze_clear(phb->opal_id, pe_no, opt); | ||
403 | if (rc != OPAL_SUCCESS) { | ||
404 | pr_warn("%s: Failure %lld clear %d on PHB#%x-PE#%x\n", | ||
405 | __func__, rc, opt, phb->hose->global_number, pe_no); | ||
406 | return -EIO; | ||
407 | } | ||
408 | |||
409 | if (!(pe->flags & PNV_IODA_PE_MASTER)) | ||
410 | return 0; | ||
411 | |||
412 | /* Clear frozen state for slave PEs */ | ||
413 | list_for_each_entry(slave, &pe->slaves, list) { | ||
414 | rc = opal_pci_eeh_freeze_clear(phb->opal_id, | ||
415 | slave->pe_number, | ||
416 | opt); | ||
417 | if (rc != OPAL_SUCCESS) { | ||
418 | pr_warn("%s: Failure %lld clear %d on PHB#%x-PE#%x\n", | ||
419 | __func__, rc, opt, phb->hose->global_number, | ||
420 | slave->pe_number); | ||
421 | return -EIO; | ||
422 | } | ||
423 | } | ||
424 | |||
425 | return 0; | ||
426 | } | ||
427 | |||
428 | static int pnv_ioda_get_pe_state(struct pnv_phb *phb, int pe_no) | ||
429 | { | ||
430 | struct pnv_ioda_pe *slave, *pe; | ||
431 | u8 fstate, state; | ||
432 | __be16 pcierr; | ||
433 | s64 rc; | ||
434 | |||
435 | /* Sanity check on PE number */ | ||
436 | if (pe_no < 0 || pe_no >= phb->ioda.total_pe) | ||
437 | return OPAL_EEH_STOPPED_PERM_UNAVAIL; | ||
438 | |||
439 | /* | ||
440 | * Fetch the master PE and the PE instance might be | ||
441 | * not initialized yet. | ||
442 | */ | ||
443 | pe = &phb->ioda.pe_array[pe_no]; | ||
444 | if (pe->flags & PNV_IODA_PE_SLAVE) { | ||
445 | pe = pe->master; | ||
446 | WARN_ON(!pe || !(pe->flags & PNV_IODA_PE_MASTER)); | ||
447 | pe_no = pe->pe_number; | ||
448 | } | ||
449 | |||
450 | /* Check the master PE */ | ||
451 | rc = opal_pci_eeh_freeze_status(phb->opal_id, pe_no, | ||
452 | &state, &pcierr, NULL); | ||
453 | if (rc != OPAL_SUCCESS) { | ||
454 | pr_warn("%s: Failure %lld getting " | ||
455 | "PHB#%x-PE#%x state\n", | ||
456 | __func__, rc, | ||
457 | phb->hose->global_number, pe_no); | ||
458 | return OPAL_EEH_STOPPED_TEMP_UNAVAIL; | ||
459 | } | ||
460 | |||
461 | /* Check the slave PE */ | ||
462 | if (!(pe->flags & PNV_IODA_PE_MASTER)) | ||
463 | return state; | ||
464 | |||
465 | list_for_each_entry(slave, &pe->slaves, list) { | ||
466 | rc = opal_pci_eeh_freeze_status(phb->opal_id, | ||
467 | slave->pe_number, | ||
468 | &fstate, | ||
469 | &pcierr, | ||
470 | NULL); | ||
471 | if (rc != OPAL_SUCCESS) { | ||
472 | pr_warn("%s: Failure %lld getting " | ||
473 | "PHB#%x-PE#%x state\n", | ||
474 | __func__, rc, | ||
475 | phb->hose->global_number, slave->pe_number); | ||
476 | return OPAL_EEH_STOPPED_TEMP_UNAVAIL; | ||
477 | } | ||
478 | |||
479 | /* | ||
480 | * Override the result based on the ascending | ||
481 | * priority. | ||
482 | */ | ||
483 | if (fstate > state) | ||
484 | state = fstate; | ||
485 | } | ||
486 | |||
487 | return state; | ||
488 | } | ||
489 | |||
109 | /* Currently those 2 are only used when MSIs are enabled, this will change | 490 | /* Currently those 2 are only used when MSIs are enabled, this will change |
110 | * but in the meantime, we need to protect them to avoid warnings | 491 | * but in the meantime, we need to protect them to avoid warnings |
111 | */ | 492 | */ |
@@ -363,9 +744,16 @@ static void pnv_ioda_setup_bus_PE(struct pci_bus *bus, int all) | |||
363 | struct pci_controller *hose = pci_bus_to_host(bus); | 744 | struct pci_controller *hose = pci_bus_to_host(bus); |
364 | struct pnv_phb *phb = hose->private_data; | 745 | struct pnv_phb *phb = hose->private_data; |
365 | struct pnv_ioda_pe *pe; | 746 | struct pnv_ioda_pe *pe; |
366 | int pe_num; | 747 | int pe_num = IODA_INVALID_PE; |
748 | |||
749 | /* Check if PE is determined by M64 */ | ||
750 | if (phb->pick_m64_pe) | ||
751 | pe_num = phb->pick_m64_pe(phb, bus, all); | ||
752 | |||
753 | /* The PE number isn't pinned by M64 */ | ||
754 | if (pe_num == IODA_INVALID_PE) | ||
755 | pe_num = pnv_ioda_alloc_pe(phb); | ||
367 | 756 | ||
368 | pe_num = pnv_ioda_alloc_pe(phb); | ||
369 | if (pe_num == IODA_INVALID_PE) { | 757 | if (pe_num == IODA_INVALID_PE) { |
370 | pr_warning("%s: Not enough PE# available for PCI bus %04x:%02x\n", | 758 | pr_warning("%s: Not enough PE# available for PCI bus %04x:%02x\n", |
371 | __func__, pci_domain_nr(bus), bus->number); | 759 | __func__, pci_domain_nr(bus), bus->number); |
@@ -373,7 +761,7 @@ static void pnv_ioda_setup_bus_PE(struct pci_bus *bus, int all) | |||
373 | } | 761 | } |
374 | 762 | ||
375 | pe = &phb->ioda.pe_array[pe_num]; | 763 | pe = &phb->ioda.pe_array[pe_num]; |
376 | pe->flags = (all ? PNV_IODA_PE_BUS_ALL : PNV_IODA_PE_BUS); | 764 | pe->flags |= (all ? PNV_IODA_PE_BUS_ALL : PNV_IODA_PE_BUS); |
377 | pe->pbus = bus; | 765 | pe->pbus = bus; |
378 | pe->pdev = NULL; | 766 | pe->pdev = NULL; |
379 | pe->tce32_seg = -1; | 767 | pe->tce32_seg = -1; |
@@ -441,8 +829,15 @@ static void pnv_ioda_setup_PEs(struct pci_bus *bus) | |||
441 | static void pnv_pci_ioda_setup_PEs(void) | 829 | static void pnv_pci_ioda_setup_PEs(void) |
442 | { | 830 | { |
443 | struct pci_controller *hose, *tmp; | 831 | struct pci_controller *hose, *tmp; |
832 | struct pnv_phb *phb; | ||
444 | 833 | ||
445 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { | 834 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { |
835 | phb = hose->private_data; | ||
836 | |||
837 | /* M64 layout might affect PE allocation */ | ||
838 | if (phb->alloc_m64_pe) | ||
839 | phb->alloc_m64_pe(phb); | ||
840 | |||
446 | pnv_ioda_setup_PEs(hose->bus); | 841 | pnv_ioda_setup_PEs(hose->bus); |
447 | } | 842 | } |
448 | } | 843 | } |
@@ -462,7 +857,7 @@ static void pnv_pci_ioda_dma_dev_setup(struct pnv_phb *phb, struct pci_dev *pdev | |||
462 | 857 | ||
463 | pe = &phb->ioda.pe_array[pdn->pe_number]; | 858 | pe = &phb->ioda.pe_array[pdn->pe_number]; |
464 | WARN_ON(get_dma_ops(&pdev->dev) != &dma_iommu_ops); | 859 | WARN_ON(get_dma_ops(&pdev->dev) != &dma_iommu_ops); |
465 | set_iommu_table_base(&pdev->dev, &pe->tce32_table); | 860 | set_iommu_table_base_and_group(&pdev->dev, &pe->tce32_table); |
466 | } | 861 | } |
467 | 862 | ||
468 | static int pnv_pci_ioda_dma_set_mask(struct pnv_phb *phb, | 863 | static int pnv_pci_ioda_dma_set_mask(struct pnv_phb *phb, |
@@ -491,17 +886,26 @@ static int pnv_pci_ioda_dma_set_mask(struct pnv_phb *phb, | |||
491 | set_dma_ops(&pdev->dev, &dma_iommu_ops); | 886 | set_dma_ops(&pdev->dev, &dma_iommu_ops); |
492 | set_iommu_table_base(&pdev->dev, &pe->tce32_table); | 887 | set_iommu_table_base(&pdev->dev, &pe->tce32_table); |
493 | } | 888 | } |
889 | *pdev->dev.dma_mask = dma_mask; | ||
494 | return 0; | 890 | return 0; |
495 | } | 891 | } |
496 | 892 | ||
497 | static void pnv_ioda_setup_bus_dma(struct pnv_ioda_pe *pe, struct pci_bus *bus) | 893 | static void pnv_ioda_setup_bus_dma(struct pnv_ioda_pe *pe, |
894 | struct pci_bus *bus, | ||
895 | bool add_to_iommu_group) | ||
498 | { | 896 | { |
499 | struct pci_dev *dev; | 897 | struct pci_dev *dev; |
500 | 898 | ||
501 | list_for_each_entry(dev, &bus->devices, bus_list) { | 899 | list_for_each_entry(dev, &bus->devices, bus_list) { |
502 | set_iommu_table_base_and_group(&dev->dev, &pe->tce32_table); | 900 | if (add_to_iommu_group) |
901 | set_iommu_table_base_and_group(&dev->dev, | ||
902 | &pe->tce32_table); | ||
903 | else | ||
904 | set_iommu_table_base(&dev->dev, &pe->tce32_table); | ||
905 | |||
503 | if (dev->subordinate) | 906 | if (dev->subordinate) |
504 | pnv_ioda_setup_bus_dma(pe, dev->subordinate); | 907 | pnv_ioda_setup_bus_dma(pe, dev->subordinate, |
908 | add_to_iommu_group); | ||
505 | } | 909 | } |
506 | } | 910 | } |
507 | 911 | ||
@@ -513,15 +917,16 @@ static void pnv_pci_ioda1_tce_invalidate(struct pnv_ioda_pe *pe, | |||
513 | (__be64 __iomem *)pe->tce_inval_reg_phys : | 917 | (__be64 __iomem *)pe->tce_inval_reg_phys : |
514 | (__be64 __iomem *)tbl->it_index; | 918 | (__be64 __iomem *)tbl->it_index; |
515 | unsigned long start, end, inc; | 919 | unsigned long start, end, inc; |
920 | const unsigned shift = tbl->it_page_shift; | ||
516 | 921 | ||
517 | start = __pa(startp); | 922 | start = __pa(startp); |
518 | end = __pa(endp); | 923 | end = __pa(endp); |
519 | 924 | ||
520 | /* BML uses this case for p6/p7/galaxy2: Shift addr and put in node */ | 925 | /* BML uses this case for p6/p7/galaxy2: Shift addr and put in node */ |
521 | if (tbl->it_busno) { | 926 | if (tbl->it_busno) { |
522 | start <<= 12; | 927 | start <<= shift; |
523 | end <<= 12; | 928 | end <<= shift; |
524 | inc = 128 << 12; | 929 | inc = 128ull << shift; |
525 | start |= tbl->it_busno; | 930 | start |= tbl->it_busno; |
526 | end |= tbl->it_busno; | 931 | end |= tbl->it_busno; |
527 | } else if (tbl->it_type & TCE_PCI_SWINV_PAIR) { | 932 | } else if (tbl->it_type & TCE_PCI_SWINV_PAIR) { |
@@ -559,18 +964,19 @@ static void pnv_pci_ioda2_tce_invalidate(struct pnv_ioda_pe *pe, | |||
559 | __be64 __iomem *invalidate = rm ? | 964 | __be64 __iomem *invalidate = rm ? |
560 | (__be64 __iomem *)pe->tce_inval_reg_phys : | 965 | (__be64 __iomem *)pe->tce_inval_reg_phys : |
561 | (__be64 __iomem *)tbl->it_index; | 966 | (__be64 __iomem *)tbl->it_index; |
967 | const unsigned shift = tbl->it_page_shift; | ||
562 | 968 | ||
563 | /* We'll invalidate DMA address in PE scope */ | 969 | /* We'll invalidate DMA address in PE scope */ |
564 | start = 0x2ul << 60; | 970 | start = 0x2ull << 60; |
565 | start |= (pe->pe_number & 0xFF); | 971 | start |= (pe->pe_number & 0xFF); |
566 | end = start; | 972 | end = start; |
567 | 973 | ||
568 | /* Figure out the start, end and step */ | 974 | /* Figure out the start, end and step */ |
569 | inc = tbl->it_offset + (((u64)startp - tbl->it_base) / sizeof(u64)); | 975 | inc = tbl->it_offset + (((u64)startp - tbl->it_base) / sizeof(u64)); |
570 | start |= (inc << 12); | 976 | start |= (inc << shift); |
571 | inc = tbl->it_offset + (((u64)endp - tbl->it_base) / sizeof(u64)); | 977 | inc = tbl->it_offset + (((u64)endp - tbl->it_base) / sizeof(u64)); |
572 | end |= (inc << 12); | 978 | end |= (inc << shift); |
573 | inc = (0x1ul << 12); | 979 | inc = (0x1ull << shift); |
574 | mb(); | 980 | mb(); |
575 | 981 | ||
576 | while (start <= end) { | 982 | while (start <= end) { |
@@ -654,7 +1060,7 @@ static void pnv_pci_ioda_setup_dma_pe(struct pnv_phb *phb, | |||
654 | /* Setup linux iommu table */ | 1060 | /* Setup linux iommu table */ |
655 | tbl = &pe->tce32_table; | 1061 | tbl = &pe->tce32_table; |
656 | pnv_pci_setup_iommu_table(tbl, addr, TCE32_TABLE_SIZE * segs, | 1062 | pnv_pci_setup_iommu_table(tbl, addr, TCE32_TABLE_SIZE * segs, |
657 | base << 28); | 1063 | base << 28, IOMMU_PAGE_SHIFT_4K); |
658 | 1064 | ||
659 | /* OPAL variant of P7IOC SW invalidated TCEs */ | 1065 | /* OPAL variant of P7IOC SW invalidated TCEs */ |
660 | swinvp = of_get_property(phb->hose->dn, "ibm,opal-tce-kill", NULL); | 1066 | swinvp = of_get_property(phb->hose->dn, "ibm,opal-tce-kill", NULL); |
@@ -677,7 +1083,7 @@ static void pnv_pci_ioda_setup_dma_pe(struct pnv_phb *phb, | |||
677 | if (pe->pdev) | 1083 | if (pe->pdev) |
678 | set_iommu_table_base_and_group(&pe->pdev->dev, tbl); | 1084 | set_iommu_table_base_and_group(&pe->pdev->dev, tbl); |
679 | else | 1085 | else |
680 | pnv_ioda_setup_bus_dma(pe, pe->pbus); | 1086 | pnv_ioda_setup_bus_dma(pe, pe->pbus, true); |
681 | 1087 | ||
682 | return; | 1088 | return; |
683 | fail: | 1089 | fail: |
@@ -713,11 +1119,15 @@ static void pnv_pci_ioda2_set_bypass(struct iommu_table *tbl, bool enable) | |||
713 | 0); | 1119 | 0); |
714 | 1120 | ||
715 | /* | 1121 | /* |
716 | * We might want to reset the DMA ops of all devices on | 1122 | * EEH needs the mapping between IOMMU table and group |
717 | * this PE. However in theory, that shouldn't be necessary | 1123 | * of those VFIO/KVM pass-through devices. We can postpone |
718 | * as this is used for VFIO/KVM pass-through and the device | 1124 | * resetting DMA ops until the DMA mask is configured in |
719 | * hasn't yet been returned to its kernel driver | 1125 | * host side. |
720 | */ | 1126 | */ |
1127 | if (pe->pdev) | ||
1128 | set_iommu_table_base(&pe->pdev->dev, tbl); | ||
1129 | else | ||
1130 | pnv_ioda_setup_bus_dma(pe, pe->pbus, false); | ||
721 | } | 1131 | } |
722 | if (rc) | 1132 | if (rc) |
723 | pe_err(pe, "OPAL error %lld configuring bypass window\n", rc); | 1133 | pe_err(pe, "OPAL error %lld configuring bypass window\n", rc); |
@@ -784,7 +1194,8 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb, | |||
784 | 1194 | ||
785 | /* Setup linux iommu table */ | 1195 | /* Setup linux iommu table */ |
786 | tbl = &pe->tce32_table; | 1196 | tbl = &pe->tce32_table; |
787 | pnv_pci_setup_iommu_table(tbl, addr, tce_table_size, 0); | 1197 | pnv_pci_setup_iommu_table(tbl, addr, tce_table_size, 0, |
1198 | IOMMU_PAGE_SHIFT_4K); | ||
788 | 1199 | ||
789 | /* OPAL variant of PHB3 invalidated TCEs */ | 1200 | /* OPAL variant of PHB3 invalidated TCEs */ |
790 | swinvp = of_get_property(phb->hose->dn, "ibm,opal-tce-kill", NULL); | 1201 | swinvp = of_get_property(phb->hose->dn, "ibm,opal-tce-kill", NULL); |
@@ -805,7 +1216,7 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb, | |||
805 | if (pe->pdev) | 1216 | if (pe->pdev) |
806 | set_iommu_table_base_and_group(&pe->pdev->dev, tbl); | 1217 | set_iommu_table_base_and_group(&pe->pdev->dev, tbl); |
807 | else | 1218 | else |
808 | pnv_ioda_setup_bus_dma(pe, pe->pbus); | 1219 | pnv_ioda_setup_bus_dma(pe, pe->pbus, true); |
809 | 1220 | ||
810 | /* Also create a bypass window */ | 1221 | /* Also create a bypass window */ |
811 | pnv_pci_ioda2_setup_bypass_pe(phb, pe); | 1222 | pnv_pci_ioda2_setup_bypass_pe(phb, pe); |
@@ -1055,9 +1466,6 @@ static void pnv_ioda_setup_pe_seg(struct pci_controller *hose, | |||
1055 | index++; | 1466 | index++; |
1056 | } | 1467 | } |
1057 | } else if (res->flags & IORESOURCE_MEM) { | 1468 | } else if (res->flags & IORESOURCE_MEM) { |
1058 | /* WARNING: Assumes M32 is mem region 0 in PHB. We need to | ||
1059 | * harden that algorithm when we start supporting M64 | ||
1060 | */ | ||
1061 | region.start = res->start - | 1469 | region.start = res->start - |
1062 | hose->mem_offset[0] - | 1470 | hose->mem_offset[0] - |
1063 | phb->ioda.m32_pci_base; | 1471 | phb->ioda.m32_pci_base; |
@@ -1141,9 +1549,8 @@ static void pnv_pci_ioda_fixup(void) | |||
1141 | pnv_pci_ioda_create_dbgfs(); | 1549 | pnv_pci_ioda_create_dbgfs(); |
1142 | 1550 | ||
1143 | #ifdef CONFIG_EEH | 1551 | #ifdef CONFIG_EEH |
1144 | eeh_probe_mode_set(EEH_PROBE_MODE_DEV); | ||
1145 | eeh_addr_cache_build(); | ||
1146 | eeh_init(); | 1552 | eeh_init(); |
1553 | eeh_addr_cache_build(); | ||
1147 | #endif | 1554 | #endif |
1148 | } | 1555 | } |
1149 | 1556 | ||
@@ -1178,7 +1585,10 @@ static resource_size_t pnv_pci_window_alignment(struct pci_bus *bus, | |||
1178 | bridge = bridge->bus->self; | 1585 | bridge = bridge->bus->self; |
1179 | } | 1586 | } |
1180 | 1587 | ||
1181 | /* We need support prefetchable memory window later */ | 1588 | /* We fail back to M32 if M64 isn't supported */ |
1589 | if (phb->ioda.m64_segsize && | ||
1590 | pnv_pci_is_mem_pref_64(type)) | ||
1591 | return phb->ioda.m64_segsize; | ||
1182 | if (type & IORESOURCE_MEM) | 1592 | if (type & IORESOURCE_MEM) |
1183 | return phb->ioda.m32_segsize; | 1593 | return phb->ioda.m32_segsize; |
1184 | 1594 | ||
@@ -1299,6 +1709,10 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np, | |||
1299 | prop32 = of_get_property(np, "ibm,opal-reserved-pe", NULL); | 1709 | prop32 = of_get_property(np, "ibm,opal-reserved-pe", NULL); |
1300 | if (prop32) | 1710 | if (prop32) |
1301 | phb->ioda.reserved_pe = be32_to_cpup(prop32); | 1711 | phb->ioda.reserved_pe = be32_to_cpup(prop32); |
1712 | |||
1713 | /* Parse 64-bit MMIO range */ | ||
1714 | pnv_ioda_parse_m64_window(phb); | ||
1715 | |||
1302 | phb->ioda.m32_size = resource_size(&hose->mem_resources[0]); | 1716 | phb->ioda.m32_size = resource_size(&hose->mem_resources[0]); |
1303 | /* FW Has already off top 64k of M32 space (MSI space) */ | 1717 | /* FW Has already off top 64k of M32 space (MSI space) */ |
1304 | phb->ioda.m32_size += 0x10000; | 1718 | phb->ioda.m32_size += 0x10000; |
@@ -1334,14 +1748,6 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np, | |||
1334 | /* Calculate how many 32-bit TCE segments we have */ | 1748 | /* Calculate how many 32-bit TCE segments we have */ |
1335 | phb->ioda.tce32_count = phb->ioda.m32_pci_base >> 28; | 1749 | phb->ioda.tce32_count = phb->ioda.m32_pci_base >> 28; |
1336 | 1750 | ||
1337 | /* Clear unusable m64 */ | ||
1338 | hose->mem_resources[1].flags = 0; | ||
1339 | hose->mem_resources[1].start = 0; | ||
1340 | hose->mem_resources[1].end = 0; | ||
1341 | hose->mem_resources[2].flags = 0; | ||
1342 | hose->mem_resources[2].start = 0; | ||
1343 | hose->mem_resources[2].end = 0; | ||
1344 | |||
1345 | #if 0 /* We should really do that ... */ | 1751 | #if 0 /* We should really do that ... */ |
1346 | rc = opal_pci_set_phb_mem_window(opal->phb_id, | 1752 | rc = opal_pci_set_phb_mem_window(opal->phb_id, |
1347 | window_type, | 1753 | window_type, |
@@ -1351,14 +1757,21 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np, | |||
1351 | segment_size); | 1757 | segment_size); |
1352 | #endif | 1758 | #endif |
1353 | 1759 | ||
1354 | pr_info(" %d (%d) PE's M32: 0x%x [segment=0x%x]" | 1760 | pr_info(" %03d (%03d) PE's M32: 0x%x [segment=0x%x]\n", |
1355 | " IO: 0x%x [segment=0x%x]\n", | 1761 | phb->ioda.total_pe, phb->ioda.reserved_pe, |
1356 | phb->ioda.total_pe, | 1762 | phb->ioda.m32_size, phb->ioda.m32_segsize); |
1357 | phb->ioda.reserved_pe, | 1763 | if (phb->ioda.m64_size) |
1358 | phb->ioda.m32_size, phb->ioda.m32_segsize, | 1764 | pr_info(" M64: 0x%lx [segment=0x%lx]\n", |
1359 | phb->ioda.io_size, phb->ioda.io_segsize); | 1765 | phb->ioda.m64_size, phb->ioda.m64_segsize); |
1766 | if (phb->ioda.io_size) | ||
1767 | pr_info(" IO: 0x%x [segment=0x%x]\n", | ||
1768 | phb->ioda.io_size, phb->ioda.io_segsize); | ||
1769 | |||
1360 | 1770 | ||
1361 | phb->hose->ops = &pnv_pci_ops; | 1771 | phb->hose->ops = &pnv_pci_ops; |
1772 | phb->get_pe_state = pnv_ioda_get_pe_state; | ||
1773 | phb->freeze_pe = pnv_ioda_freeze_pe; | ||
1774 | phb->unfreeze_pe = pnv_ioda_unfreeze_pe; | ||
1362 | #ifdef CONFIG_EEH | 1775 | #ifdef CONFIG_EEH |
1363 | phb->eeh_ops = &ioda_eeh_ops; | 1776 | phb->eeh_ops = &ioda_eeh_ops; |
1364 | #endif | 1777 | #endif |
@@ -1404,6 +1817,10 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np, | |||
1404 | ioda_eeh_phb_reset(hose, EEH_RESET_FUNDAMENTAL); | 1817 | ioda_eeh_phb_reset(hose, EEH_RESET_FUNDAMENTAL); |
1405 | ioda_eeh_phb_reset(hose, OPAL_DEASSERT_RESET); | 1818 | ioda_eeh_phb_reset(hose, OPAL_DEASSERT_RESET); |
1406 | } | 1819 | } |
1820 | |||
1821 | /* Configure M64 window */ | ||
1822 | if (phb->init_m64 && phb->init_m64(phb)) | ||
1823 | hose->mem_resources[1].flags = 0; | ||
1407 | } | 1824 | } |
1408 | 1825 | ||
1409 | void __init pnv_pci_init_ioda2_phb(struct device_node *np) | 1826 | void __init pnv_pci_init_ioda2_phb(struct device_node *np) |
diff --git a/arch/powerpc/platforms/powernv/pci-p5ioc2.c b/arch/powerpc/platforms/powernv/pci-p5ioc2.c index e3807d69393e..94ce3481490b 100644 --- a/arch/powerpc/platforms/powernv/pci-p5ioc2.c +++ b/arch/powerpc/platforms/powernv/pci-p5ioc2.c | |||
@@ -172,7 +172,8 @@ static void __init pnv_pci_init_p5ioc2_phb(struct device_node *np, u64 hub_id, | |||
172 | /* Setup TCEs */ | 172 | /* Setup TCEs */ |
173 | phb->dma_dev_setup = pnv_pci_p5ioc2_dma_dev_setup; | 173 | phb->dma_dev_setup = pnv_pci_p5ioc2_dma_dev_setup; |
174 | pnv_pci_setup_iommu_table(&phb->p5ioc2.iommu_table, | 174 | pnv_pci_setup_iommu_table(&phb->p5ioc2.iommu_table, |
175 | tce_mem, tce_size, 0); | 175 | tce_mem, tce_size, 0, |
176 | IOMMU_PAGE_SHIFT_4K); | ||
176 | } | 177 | } |
177 | 178 | ||
178 | void __init pnv_pci_init_p5ioc2_hub(struct device_node *np) | 179 | void __init pnv_pci_init_p5ioc2_hub(struct device_node *np) |
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c index f91a4e5d872e..b854b57ed5e1 100644 --- a/arch/powerpc/platforms/powernv/pci.c +++ b/arch/powerpc/platforms/powernv/pci.c | |||
@@ -132,61 +132,78 @@ static void pnv_pci_dump_p7ioc_diag_data(struct pci_controller *hose, | |||
132 | 132 | ||
133 | data = (struct OpalIoP7IOCPhbErrorData *)common; | 133 | data = (struct OpalIoP7IOCPhbErrorData *)common; |
134 | pr_info("P7IOC PHB#%d Diag-data (Version: %d)\n", | 134 | pr_info("P7IOC PHB#%d Diag-data (Version: %d)\n", |
135 | hose->global_number, common->version); | 135 | hose->global_number, be32_to_cpu(common->version)); |
136 | 136 | ||
137 | if (data->brdgCtl) | 137 | if (data->brdgCtl) |
138 | pr_info("brdgCtl: %08x\n", | 138 | pr_info("brdgCtl: %08x\n", |
139 | data->brdgCtl); | 139 | be32_to_cpu(data->brdgCtl)); |
140 | if (data->portStatusReg || data->rootCmplxStatus || | 140 | if (data->portStatusReg || data->rootCmplxStatus || |
141 | data->busAgentStatus) | 141 | data->busAgentStatus) |
142 | pr_info("UtlSts: %08x %08x %08x\n", | 142 | pr_info("UtlSts: %08x %08x %08x\n", |
143 | data->portStatusReg, data->rootCmplxStatus, | 143 | be32_to_cpu(data->portStatusReg), |
144 | data->busAgentStatus); | 144 | be32_to_cpu(data->rootCmplxStatus), |
145 | be32_to_cpu(data->busAgentStatus)); | ||
145 | if (data->deviceStatus || data->slotStatus || | 146 | if (data->deviceStatus || data->slotStatus || |
146 | data->linkStatus || data->devCmdStatus || | 147 | data->linkStatus || data->devCmdStatus || |
147 | data->devSecStatus) | 148 | data->devSecStatus) |
148 | pr_info("RootSts: %08x %08x %08x %08x %08x\n", | 149 | pr_info("RootSts: %08x %08x %08x %08x %08x\n", |
149 | data->deviceStatus, data->slotStatus, | 150 | be32_to_cpu(data->deviceStatus), |
150 | data->linkStatus, data->devCmdStatus, | 151 | be32_to_cpu(data->slotStatus), |
151 | data->devSecStatus); | 152 | be32_to_cpu(data->linkStatus), |
153 | be32_to_cpu(data->devCmdStatus), | ||
154 | be32_to_cpu(data->devSecStatus)); | ||
152 | if (data->rootErrorStatus || data->uncorrErrorStatus || | 155 | if (data->rootErrorStatus || data->uncorrErrorStatus || |
153 | data->corrErrorStatus) | 156 | data->corrErrorStatus) |
154 | pr_info("RootErrSts: %08x %08x %08x\n", | 157 | pr_info("RootErrSts: %08x %08x %08x\n", |
155 | data->rootErrorStatus, data->uncorrErrorStatus, | 158 | be32_to_cpu(data->rootErrorStatus), |
156 | data->corrErrorStatus); | 159 | be32_to_cpu(data->uncorrErrorStatus), |
160 | be32_to_cpu(data->corrErrorStatus)); | ||
157 | if (data->tlpHdr1 || data->tlpHdr2 || | 161 | if (data->tlpHdr1 || data->tlpHdr2 || |
158 | data->tlpHdr3 || data->tlpHdr4) | 162 | data->tlpHdr3 || data->tlpHdr4) |
159 | pr_info("RootErrLog: %08x %08x %08x %08x\n", | 163 | pr_info("RootErrLog: %08x %08x %08x %08x\n", |
160 | data->tlpHdr1, data->tlpHdr2, | 164 | be32_to_cpu(data->tlpHdr1), |
161 | data->tlpHdr3, data->tlpHdr4); | 165 | be32_to_cpu(data->tlpHdr2), |
166 | be32_to_cpu(data->tlpHdr3), | ||
167 | be32_to_cpu(data->tlpHdr4)); | ||
162 | if (data->sourceId || data->errorClass || | 168 | if (data->sourceId || data->errorClass || |
163 | data->correlator) | 169 | data->correlator) |
164 | pr_info("RootErrLog1: %08x %016llx %016llx\n", | 170 | pr_info("RootErrLog1: %08x %016llx %016llx\n", |
165 | data->sourceId, data->errorClass, | 171 | be32_to_cpu(data->sourceId), |
166 | data->correlator); | 172 | be64_to_cpu(data->errorClass), |
173 | be64_to_cpu(data->correlator)); | ||
167 | if (data->p7iocPlssr || data->p7iocCsr) | 174 | if (data->p7iocPlssr || data->p7iocCsr) |
168 | pr_info("PhbSts: %016llx %016llx\n", | 175 | pr_info("PhbSts: %016llx %016llx\n", |
169 | data->p7iocPlssr, data->p7iocCsr); | 176 | be64_to_cpu(data->p7iocPlssr), |
177 | be64_to_cpu(data->p7iocCsr)); | ||
170 | if (data->lemFir) | 178 | if (data->lemFir) |
171 | pr_info("Lem: %016llx %016llx %016llx\n", | 179 | pr_info("Lem: %016llx %016llx %016llx\n", |
172 | data->lemFir, data->lemErrorMask, | 180 | be64_to_cpu(data->lemFir), |
173 | data->lemWOF); | 181 | be64_to_cpu(data->lemErrorMask), |
182 | be64_to_cpu(data->lemWOF)); | ||
174 | if (data->phbErrorStatus) | 183 | if (data->phbErrorStatus) |
175 | pr_info("PhbErr: %016llx %016llx %016llx %016llx\n", | 184 | pr_info("PhbErr: %016llx %016llx %016llx %016llx\n", |
176 | data->phbErrorStatus, data->phbFirstErrorStatus, | 185 | be64_to_cpu(data->phbErrorStatus), |
177 | data->phbErrorLog0, data->phbErrorLog1); | 186 | be64_to_cpu(data->phbFirstErrorStatus), |
187 | be64_to_cpu(data->phbErrorLog0), | ||
188 | be64_to_cpu(data->phbErrorLog1)); | ||
178 | if (data->mmioErrorStatus) | 189 | if (data->mmioErrorStatus) |
179 | pr_info("OutErr: %016llx %016llx %016llx %016llx\n", | 190 | pr_info("OutErr: %016llx %016llx %016llx %016llx\n", |
180 | data->mmioErrorStatus, data->mmioFirstErrorStatus, | 191 | be64_to_cpu(data->mmioErrorStatus), |
181 | data->mmioErrorLog0, data->mmioErrorLog1); | 192 | be64_to_cpu(data->mmioFirstErrorStatus), |
193 | be64_to_cpu(data->mmioErrorLog0), | ||
194 | be64_to_cpu(data->mmioErrorLog1)); | ||
182 | if (data->dma0ErrorStatus) | 195 | if (data->dma0ErrorStatus) |
183 | pr_info("InAErr: %016llx %016llx %016llx %016llx\n", | 196 | pr_info("InAErr: %016llx %016llx %016llx %016llx\n", |
184 | data->dma0ErrorStatus, data->dma0FirstErrorStatus, | 197 | be64_to_cpu(data->dma0ErrorStatus), |
185 | data->dma0ErrorLog0, data->dma0ErrorLog1); | 198 | be64_to_cpu(data->dma0FirstErrorStatus), |
199 | be64_to_cpu(data->dma0ErrorLog0), | ||
200 | be64_to_cpu(data->dma0ErrorLog1)); | ||
186 | if (data->dma1ErrorStatus) | 201 | if (data->dma1ErrorStatus) |
187 | pr_info("InBErr: %016llx %016llx %016llx %016llx\n", | 202 | pr_info("InBErr: %016llx %016llx %016llx %016llx\n", |
188 | data->dma1ErrorStatus, data->dma1FirstErrorStatus, | 203 | be64_to_cpu(data->dma1ErrorStatus), |
189 | data->dma1ErrorLog0, data->dma1ErrorLog1); | 204 | be64_to_cpu(data->dma1FirstErrorStatus), |
205 | be64_to_cpu(data->dma1ErrorLog0), | ||
206 | be64_to_cpu(data->dma1ErrorLog1)); | ||
190 | 207 | ||
191 | for (i = 0; i < OPAL_P7IOC_NUM_PEST_REGS; i++) { | 208 | for (i = 0; i < OPAL_P7IOC_NUM_PEST_REGS; i++) { |
192 | if ((data->pestA[i] >> 63) == 0 && | 209 | if ((data->pestA[i] >> 63) == 0 && |
@@ -194,7 +211,8 @@ static void pnv_pci_dump_p7ioc_diag_data(struct pci_controller *hose, | |||
194 | continue; | 211 | continue; |
195 | 212 | ||
196 | pr_info("PE[%3d] A/B: %016llx %016llx\n", | 213 | pr_info("PE[%3d] A/B: %016llx %016llx\n", |
197 | i, data->pestA[i], data->pestB[i]); | 214 | i, be64_to_cpu(data->pestA[i]), |
215 | be64_to_cpu(data->pestB[i])); | ||
198 | } | 216 | } |
199 | } | 217 | } |
200 | 218 | ||
@@ -319,43 +337,52 @@ void pnv_pci_dump_phb_diag_data(struct pci_controller *hose, | |||
319 | static void pnv_pci_handle_eeh_config(struct pnv_phb *phb, u32 pe_no) | 337 | static void pnv_pci_handle_eeh_config(struct pnv_phb *phb, u32 pe_no) |
320 | { | 338 | { |
321 | unsigned long flags, rc; | 339 | unsigned long flags, rc; |
322 | int has_diag; | 340 | int has_diag, ret = 0; |
323 | 341 | ||
324 | spin_lock_irqsave(&phb->lock, flags); | 342 | spin_lock_irqsave(&phb->lock, flags); |
325 | 343 | ||
344 | /* Fetch PHB diag-data */ | ||
326 | rc = opal_pci_get_phb_diag_data2(phb->opal_id, phb->diag.blob, | 345 | rc = opal_pci_get_phb_diag_data2(phb->opal_id, phb->diag.blob, |
327 | PNV_PCI_DIAG_BUF_SIZE); | 346 | PNV_PCI_DIAG_BUF_SIZE); |
328 | has_diag = (rc == OPAL_SUCCESS); | 347 | has_diag = (rc == OPAL_SUCCESS); |
329 | 348 | ||
330 | rc = opal_pci_eeh_freeze_clear(phb->opal_id, pe_no, | 349 | /* If PHB supports compound PE, to handle it */ |
350 | if (phb->unfreeze_pe) { | ||
351 | ret = phb->unfreeze_pe(phb, | ||
352 | pe_no, | ||
331 | OPAL_EEH_ACTION_CLEAR_FREEZE_ALL); | 353 | OPAL_EEH_ACTION_CLEAR_FREEZE_ALL); |
332 | if (rc) { | 354 | } else { |
333 | pr_warning("PCI %d: Failed to clear EEH freeze state" | 355 | rc = opal_pci_eeh_freeze_clear(phb->opal_id, |
334 | " for PE#%d, err %ld\n", | 356 | pe_no, |
335 | phb->hose->global_number, pe_no, rc); | 357 | OPAL_EEH_ACTION_CLEAR_FREEZE_ALL); |
336 | 358 | if (rc) { | |
337 | /* For now, let's only display the diag buffer when we fail to clear | 359 | pr_warn("%s: Failure %ld clearing frozen " |
338 | * the EEH status. We'll do more sensible things later when we have | 360 | "PHB#%x-PE#%x\n", |
339 | * proper EEH support. We need to make sure we don't pollute ourselves | 361 | __func__, rc, phb->hose->global_number, |
340 | * with the normal errors generated when probing empty slots | 362 | pe_no); |
341 | */ | 363 | ret = -EIO; |
342 | if (has_diag) | 364 | } |
343 | pnv_pci_dump_phb_diag_data(phb->hose, phb->diag.blob); | ||
344 | else | ||
345 | pr_warning("PCI %d: No diag data available\n", | ||
346 | phb->hose->global_number); | ||
347 | } | 365 | } |
348 | 366 | ||
367 | /* | ||
368 | * For now, let's only display the diag buffer when we fail to clear | ||
369 | * the EEH status. We'll do more sensible things later when we have | ||
370 | * proper EEH support. We need to make sure we don't pollute ourselves | ||
371 | * with the normal errors generated when probing empty slots | ||
372 | */ | ||
373 | if (has_diag && ret) | ||
374 | pnv_pci_dump_phb_diag_data(phb->hose, phb->diag.blob); | ||
375 | |||
349 | spin_unlock_irqrestore(&phb->lock, flags); | 376 | spin_unlock_irqrestore(&phb->lock, flags); |
350 | } | 377 | } |
351 | 378 | ||
352 | static void pnv_pci_config_check_eeh(struct pnv_phb *phb, | 379 | static void pnv_pci_config_check_eeh(struct pnv_phb *phb, |
353 | struct device_node *dn) | 380 | struct device_node *dn) |
354 | { | 381 | { |
355 | s64 rc; | ||
356 | u8 fstate; | 382 | u8 fstate; |
357 | __be16 pcierr; | 383 | __be16 pcierr; |
358 | u32 pe_no; | 384 | int pe_no; |
385 | s64 rc; | ||
359 | 386 | ||
360 | /* | 387 | /* |
361 | * Get the PE#. During the PCI probe stage, we might not | 388 | * Get the PE#. During the PCI probe stage, we might not |
@@ -370,20 +397,42 @@ static void pnv_pci_config_check_eeh(struct pnv_phb *phb, | |||
370 | pe_no = phb->ioda.reserved_pe; | 397 | pe_no = phb->ioda.reserved_pe; |
371 | } | 398 | } |
372 | 399 | ||
373 | /* Read freeze status */ | 400 | /* |
374 | rc = opal_pci_eeh_freeze_status(phb->opal_id, pe_no, &fstate, &pcierr, | 401 | * Fetch frozen state. If the PHB support compound PE, |
375 | NULL); | 402 | * we need handle that case. |
376 | if (rc) { | 403 | */ |
377 | pr_warning("%s: Can't read EEH status (PE#%d) for " | 404 | if (phb->get_pe_state) { |
378 | "%s, err %lld\n", | 405 | fstate = phb->get_pe_state(phb, pe_no); |
379 | __func__, pe_no, dn->full_name, rc); | 406 | } else { |
380 | return; | 407 | rc = opal_pci_eeh_freeze_status(phb->opal_id, |
408 | pe_no, | ||
409 | &fstate, | ||
410 | &pcierr, | ||
411 | NULL); | ||
412 | if (rc) { | ||
413 | pr_warn("%s: Failure %lld getting PHB#%x-PE#%x state\n", | ||
414 | __func__, rc, phb->hose->global_number, pe_no); | ||
415 | return; | ||
416 | } | ||
381 | } | 417 | } |
418 | |||
382 | cfg_dbg(" -> EEH check, bdfn=%04x PE#%d fstate=%x\n", | 419 | cfg_dbg(" -> EEH check, bdfn=%04x PE#%d fstate=%x\n", |
383 | (PCI_DN(dn)->busno << 8) | (PCI_DN(dn)->devfn), | 420 | (PCI_DN(dn)->busno << 8) | (PCI_DN(dn)->devfn), |
384 | pe_no, fstate); | 421 | pe_no, fstate); |
385 | if (fstate != 0) | 422 | |
423 | /* Clear the frozen state if applicable */ | ||
424 | if (fstate == OPAL_EEH_STOPPED_MMIO_FREEZE || | ||
425 | fstate == OPAL_EEH_STOPPED_DMA_FREEZE || | ||
426 | fstate == OPAL_EEH_STOPPED_MMIO_DMA_FREEZE) { | ||
427 | /* | ||
428 | * If PHB supports compound PE, freeze it for | ||
429 | * consistency. | ||
430 | */ | ||
431 | if (phb->freeze_pe) | ||
432 | phb->freeze_pe(phb, pe_no); | ||
433 | |||
386 | pnv_pci_handle_eeh_config(phb, pe_no); | 434 | pnv_pci_handle_eeh_config(phb, pe_no); |
435 | } | ||
387 | } | 436 | } |
388 | 437 | ||
389 | int pnv_pci_cfg_read(struct device_node *dn, | 438 | int pnv_pci_cfg_read(struct device_node *dn, |
@@ -564,10 +613,11 @@ static int pnv_tce_build(struct iommu_table *tbl, long index, long npages, | |||
564 | proto_tce |= TCE_PCI_WRITE; | 613 | proto_tce |= TCE_PCI_WRITE; |
565 | 614 | ||
566 | tces = tcep = ((__be64 *)tbl->it_base) + index - tbl->it_offset; | 615 | tces = tcep = ((__be64 *)tbl->it_base) + index - tbl->it_offset; |
567 | rpn = __pa(uaddr) >> TCE_SHIFT; | 616 | rpn = __pa(uaddr) >> tbl->it_page_shift; |
568 | 617 | ||
569 | while (npages--) | 618 | while (npages--) |
570 | *(tcep++) = cpu_to_be64(proto_tce | (rpn++ << TCE_RPN_SHIFT)); | 619 | *(tcep++) = cpu_to_be64(proto_tce | |
620 | (rpn++ << tbl->it_page_shift)); | ||
571 | 621 | ||
572 | /* Some implementations won't cache invalid TCEs and thus may not | 622 | /* Some implementations won't cache invalid TCEs and thus may not |
573 | * need that flush. We'll probably turn it_type into a bit mask | 623 | * need that flush. We'll probably turn it_type into a bit mask |
@@ -627,11 +677,11 @@ static void pnv_tce_free_rm(struct iommu_table *tbl, long index, long npages) | |||
627 | 677 | ||
628 | void pnv_pci_setup_iommu_table(struct iommu_table *tbl, | 678 | void pnv_pci_setup_iommu_table(struct iommu_table *tbl, |
629 | void *tce_mem, u64 tce_size, | 679 | void *tce_mem, u64 tce_size, |
630 | u64 dma_offset) | 680 | u64 dma_offset, unsigned page_shift) |
631 | { | 681 | { |
632 | tbl->it_blocksize = 16; | 682 | tbl->it_blocksize = 16; |
633 | tbl->it_base = (unsigned long)tce_mem; | 683 | tbl->it_base = (unsigned long)tce_mem; |
634 | tbl->it_page_shift = IOMMU_PAGE_SHIFT_4K; | 684 | tbl->it_page_shift = page_shift; |
635 | tbl->it_offset = dma_offset >> tbl->it_page_shift; | 685 | tbl->it_offset = dma_offset >> tbl->it_page_shift; |
636 | tbl->it_index = 0; | 686 | tbl->it_index = 0; |
637 | tbl->it_size = tce_size >> 3; | 687 | tbl->it_size = tce_size >> 3; |
@@ -656,7 +706,7 @@ static struct iommu_table *pnv_pci_setup_bml_iommu(struct pci_controller *hose) | |||
656 | if (WARN_ON(!tbl)) | 706 | if (WARN_ON(!tbl)) |
657 | return NULL; | 707 | return NULL; |
658 | pnv_pci_setup_iommu_table(tbl, __va(be64_to_cpup(basep)), | 708 | pnv_pci_setup_iommu_table(tbl, __va(be64_to_cpup(basep)), |
659 | be32_to_cpup(sizep), 0); | 709 | be32_to_cpup(sizep), 0, IOMMU_PAGE_SHIFT_4K); |
660 | iommu_init_table(tbl, hose->node); | 710 | iommu_init_table(tbl, hose->node); |
661 | iommu_register_group(tbl, pci_domain_nr(hose->bus), 0); | 711 | iommu_register_group(tbl, pci_domain_nr(hose->bus), 0); |
662 | 712 | ||
@@ -842,5 +892,4 @@ static int __init tce_iommu_bus_notifier_init(void) | |||
842 | bus_register_notifier(&pci_bus_type, &tce_iommu_bus_nb); | 892 | bus_register_notifier(&pci_bus_type, &tce_iommu_bus_nb); |
843 | return 0; | 893 | return 0; |
844 | } | 894 | } |
845 | 895 | machine_subsys_initcall_sync(powernv, tce_iommu_bus_notifier_init); | |
846 | subsys_initcall_sync(tce_iommu_bus_notifier_init); | ||
diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h index 676232c34328..48494d4b6058 100644 --- a/arch/powerpc/platforms/powernv/pci.h +++ b/arch/powerpc/platforms/powernv/pci.h | |||
@@ -21,6 +21,8 @@ enum pnv_phb_model { | |||
21 | #define PNV_IODA_PE_DEV (1 << 0) /* PE has single PCI device */ | 21 | #define PNV_IODA_PE_DEV (1 << 0) /* PE has single PCI device */ |
22 | #define PNV_IODA_PE_BUS (1 << 1) /* PE has primary PCI bus */ | 22 | #define PNV_IODA_PE_BUS (1 << 1) /* PE has primary PCI bus */ |
23 | #define PNV_IODA_PE_BUS_ALL (1 << 2) /* PE has subordinate buses */ | 23 | #define PNV_IODA_PE_BUS_ALL (1 << 2) /* PE has subordinate buses */ |
24 | #define PNV_IODA_PE_MASTER (1 << 3) /* Master PE in compound case */ | ||
25 | #define PNV_IODA_PE_SLAVE (1 << 4) /* Slave PE in compound case */ | ||
24 | 26 | ||
25 | /* Data associated with a PE, including IOMMU tracking etc.. */ | 27 | /* Data associated with a PE, including IOMMU tracking etc.. */ |
26 | struct pnv_phb; | 28 | struct pnv_phb; |
@@ -64,6 +66,10 @@ struct pnv_ioda_pe { | |||
64 | */ | 66 | */ |
65 | int mve_number; | 67 | int mve_number; |
66 | 68 | ||
69 | /* PEs in compound case */ | ||
70 | struct pnv_ioda_pe *master; | ||
71 | struct list_head slaves; | ||
72 | |||
67 | /* Link in list of PE#s */ | 73 | /* Link in list of PE#s */ |
68 | struct list_head dma_link; | 74 | struct list_head dma_link; |
69 | struct list_head list; | 75 | struct list_head list; |
@@ -119,6 +125,12 @@ struct pnv_phb { | |||
119 | void (*fixup_phb)(struct pci_controller *hose); | 125 | void (*fixup_phb)(struct pci_controller *hose); |
120 | u32 (*bdfn_to_pe)(struct pnv_phb *phb, struct pci_bus *bus, u32 devfn); | 126 | u32 (*bdfn_to_pe)(struct pnv_phb *phb, struct pci_bus *bus, u32 devfn); |
121 | void (*shutdown)(struct pnv_phb *phb); | 127 | void (*shutdown)(struct pnv_phb *phb); |
128 | int (*init_m64)(struct pnv_phb *phb); | ||
129 | void (*alloc_m64_pe)(struct pnv_phb *phb); | ||
130 | int (*pick_m64_pe)(struct pnv_phb *phb, struct pci_bus *bus, int all); | ||
131 | int (*get_pe_state)(struct pnv_phb *phb, int pe_no); | ||
132 | void (*freeze_pe)(struct pnv_phb *phb, int pe_no); | ||
133 | int (*unfreeze_pe)(struct pnv_phb *phb, int pe_no, int opt); | ||
122 | 134 | ||
123 | union { | 135 | union { |
124 | struct { | 136 | struct { |
@@ -129,9 +141,20 @@ struct pnv_phb { | |||
129 | /* Global bridge info */ | 141 | /* Global bridge info */ |
130 | unsigned int total_pe; | 142 | unsigned int total_pe; |
131 | unsigned int reserved_pe; | 143 | unsigned int reserved_pe; |
144 | |||
145 | /* 32-bit MMIO window */ | ||
132 | unsigned int m32_size; | 146 | unsigned int m32_size; |
133 | unsigned int m32_segsize; | 147 | unsigned int m32_segsize; |
134 | unsigned int m32_pci_base; | 148 | unsigned int m32_pci_base; |
149 | |||
150 | /* 64-bit MMIO window */ | ||
151 | unsigned int m64_bar_idx; | ||
152 | unsigned long m64_size; | ||
153 | unsigned long m64_segsize; | ||
154 | unsigned long m64_base; | ||
155 | unsigned long m64_bar_alloc; | ||
156 | |||
157 | /* IO ports */ | ||
135 | unsigned int io_size; | 158 | unsigned int io_size; |
136 | unsigned int io_segsize; | 159 | unsigned int io_segsize; |
137 | unsigned int io_pci_base; | 160 | unsigned int io_pci_base; |
@@ -198,7 +221,7 @@ int pnv_pci_cfg_write(struct device_node *dn, | |||
198 | int where, int size, u32 val); | 221 | int where, int size, u32 val); |
199 | extern void pnv_pci_setup_iommu_table(struct iommu_table *tbl, | 222 | extern void pnv_pci_setup_iommu_table(struct iommu_table *tbl, |
200 | void *tce_mem, u64 tce_size, | 223 | void *tce_mem, u64 tce_size, |
201 | u64 dma_offset); | 224 | u64 dma_offset, unsigned page_shift); |
202 | extern void pnv_pci_init_p5ioc2_hub(struct device_node *np); | 225 | extern void pnv_pci_init_p5ioc2_hub(struct device_node *np); |
203 | extern void pnv_pci_init_ioda_hub(struct device_node *np); | 226 | extern void pnv_pci_init_ioda_hub(struct device_node *np); |
204 | extern void pnv_pci_init_ioda2_phb(struct device_node *np); | 227 | extern void pnv_pci_init_ioda2_phb(struct device_node *np); |
diff --git a/arch/powerpc/platforms/powernv/rng.c b/arch/powerpc/platforms/powernv/rng.c index 1cb160dc1609..80db43944afe 100644 --- a/arch/powerpc/platforms/powernv/rng.c +++ b/arch/powerpc/platforms/powernv/rng.c | |||
@@ -123,4 +123,4 @@ static __init int rng_init(void) | |||
123 | 123 | ||
124 | return 0; | 124 | return 0; |
125 | } | 125 | } |
126 | subsys_initcall(rng_init); | 126 | machine_subsys_initcall(powernv, rng_init); |
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c index d9b88fa7c5a3..5a0e2dc6de5f 100644 --- a/arch/powerpc/platforms/powernv/setup.c +++ b/arch/powerpc/platforms/powernv/setup.c | |||
@@ -264,6 +264,8 @@ static void __init pnv_setup_machdep_opal(void) | |||
264 | ppc_md.halt = pnv_halt; | 264 | ppc_md.halt = pnv_halt; |
265 | ppc_md.machine_check_exception = opal_machine_check; | 265 | ppc_md.machine_check_exception = opal_machine_check; |
266 | ppc_md.mce_check_early_recovery = opal_mce_check_early_recovery; | 266 | ppc_md.mce_check_early_recovery = opal_mce_check_early_recovery; |
267 | ppc_md.hmi_exception_early = opal_hmi_exception_early; | ||
268 | ppc_md.handle_hmi_exception = opal_handle_hmi_exception; | ||
267 | } | 269 | } |
268 | 270 | ||
269 | #ifdef CONFIG_PPC_POWERNV_RTAS | 271 | #ifdef CONFIG_PPC_POWERNV_RTAS |
diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c index 2d0b4d68a40a..a2450b8a50a5 100644 --- a/arch/powerpc/platforms/pseries/dlpar.c +++ b/arch/powerpc/platforms/pseries/dlpar.c | |||
@@ -400,10 +400,10 @@ out: | |||
400 | static ssize_t dlpar_cpu_probe(const char *buf, size_t count) | 400 | static ssize_t dlpar_cpu_probe(const char *buf, size_t count) |
401 | { | 401 | { |
402 | struct device_node *dn, *parent; | 402 | struct device_node *dn, *parent; |
403 | unsigned long drc_index; | 403 | u32 drc_index; |
404 | int rc; | 404 | int rc; |
405 | 405 | ||
406 | rc = strict_strtoul(buf, 0, &drc_index); | 406 | rc = kstrtou32(buf, 0, &drc_index); |
407 | if (rc) | 407 | if (rc) |
408 | return -EINVAL; | 408 | return -EINVAL; |
409 | 409 | ||
diff --git a/arch/powerpc/platforms/pseries/dtl.c b/arch/powerpc/platforms/pseries/dtl.c index 7d61498e45c0..1062f71f5a85 100644 --- a/arch/powerpc/platforms/pseries/dtl.c +++ b/arch/powerpc/platforms/pseries/dtl.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <asm/lppaca.h> | 29 | #include <asm/lppaca.h> |
30 | #include <asm/debug.h> | 30 | #include <asm/debug.h> |
31 | #include <asm/plpar_wrappers.h> | 31 | #include <asm/plpar_wrappers.h> |
32 | #include <asm/machdep.h> | ||
32 | 33 | ||
33 | struct dtl { | 34 | struct dtl { |
34 | struct dtl_entry *buf; | 35 | struct dtl_entry *buf; |
@@ -391,4 +392,4 @@ err_remove_dir: | |||
391 | err: | 392 | err: |
392 | return rc; | 393 | return rc; |
393 | } | 394 | } |
394 | arch_initcall(dtl_init); | 395 | machine_arch_initcall(pseries, dtl_init); |
diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c index 0bec0c02c5e7..b08053819d99 100644 --- a/arch/powerpc/platforms/pseries/eeh_pseries.c +++ b/arch/powerpc/platforms/pseries/eeh_pseries.c | |||
@@ -89,26 +89,26 @@ static int pseries_eeh_init(void) | |||
89 | * of domain/bus/slot/function for EEH RTAS operations. | 89 | * of domain/bus/slot/function for EEH RTAS operations. |
90 | */ | 90 | */ |
91 | if (ibm_set_eeh_option == RTAS_UNKNOWN_SERVICE) { | 91 | if (ibm_set_eeh_option == RTAS_UNKNOWN_SERVICE) { |
92 | pr_warning("%s: RTAS service <ibm,set-eeh-option> invalid\n", | 92 | pr_warn("%s: RTAS service <ibm,set-eeh-option> invalid\n", |
93 | __func__); | 93 | __func__); |
94 | return -EINVAL; | 94 | return -EINVAL; |
95 | } else if (ibm_set_slot_reset == RTAS_UNKNOWN_SERVICE) { | 95 | } else if (ibm_set_slot_reset == RTAS_UNKNOWN_SERVICE) { |
96 | pr_warning("%s: RTAS service <ibm,set-slot-reset> invalid\n", | 96 | pr_warn("%s: RTAS service <ibm,set-slot-reset> invalid\n", |
97 | __func__); | 97 | __func__); |
98 | return -EINVAL; | 98 | return -EINVAL; |
99 | } else if (ibm_read_slot_reset_state2 == RTAS_UNKNOWN_SERVICE && | 99 | } else if (ibm_read_slot_reset_state2 == RTAS_UNKNOWN_SERVICE && |
100 | ibm_read_slot_reset_state == RTAS_UNKNOWN_SERVICE) { | 100 | ibm_read_slot_reset_state == RTAS_UNKNOWN_SERVICE) { |
101 | pr_warning("%s: RTAS service <ibm,read-slot-reset-state2> and " | 101 | pr_warn("%s: RTAS service <ibm,read-slot-reset-state2> and " |
102 | "<ibm,read-slot-reset-state> invalid\n", | 102 | "<ibm,read-slot-reset-state> invalid\n", |
103 | __func__); | 103 | __func__); |
104 | return -EINVAL; | 104 | return -EINVAL; |
105 | } else if (ibm_slot_error_detail == RTAS_UNKNOWN_SERVICE) { | 105 | } else if (ibm_slot_error_detail == RTAS_UNKNOWN_SERVICE) { |
106 | pr_warning("%s: RTAS service <ibm,slot-error-detail> invalid\n", | 106 | pr_warn("%s: RTAS service <ibm,slot-error-detail> invalid\n", |
107 | __func__); | 107 | __func__); |
108 | return -EINVAL; | 108 | return -EINVAL; |
109 | } else if (ibm_configure_pe == RTAS_UNKNOWN_SERVICE && | 109 | } else if (ibm_configure_pe == RTAS_UNKNOWN_SERVICE && |
110 | ibm_configure_bridge == RTAS_UNKNOWN_SERVICE) { | 110 | ibm_configure_bridge == RTAS_UNKNOWN_SERVICE) { |
111 | pr_warning("%s: RTAS service <ibm,configure-pe> and " | 111 | pr_warn("%s: RTAS service <ibm,configure-pe> and " |
112 | "<ibm,configure-bridge> invalid\n", | 112 | "<ibm,configure-bridge> invalid\n", |
113 | __func__); | 113 | __func__); |
114 | return -EINVAL; | 114 | return -EINVAL; |
@@ -118,17 +118,17 @@ static int pseries_eeh_init(void) | |||
118 | spin_lock_init(&slot_errbuf_lock); | 118 | spin_lock_init(&slot_errbuf_lock); |
119 | eeh_error_buf_size = rtas_token("rtas-error-log-max"); | 119 | eeh_error_buf_size = rtas_token("rtas-error-log-max"); |
120 | if (eeh_error_buf_size == RTAS_UNKNOWN_SERVICE) { | 120 | if (eeh_error_buf_size == RTAS_UNKNOWN_SERVICE) { |
121 | pr_warning("%s: unknown EEH error log size\n", | 121 | pr_warn("%s: unknown EEH error log size\n", |
122 | __func__); | 122 | __func__); |
123 | eeh_error_buf_size = 1024; | 123 | eeh_error_buf_size = 1024; |
124 | } else if (eeh_error_buf_size > RTAS_ERROR_LOG_MAX) { | 124 | } else if (eeh_error_buf_size > RTAS_ERROR_LOG_MAX) { |
125 | pr_warning("%s: EEH error log size %d exceeds the maximal %d\n", | 125 | pr_warn("%s: EEH error log size %d exceeds the maximal %d\n", |
126 | __func__, eeh_error_buf_size, RTAS_ERROR_LOG_MAX); | 126 | __func__, eeh_error_buf_size, RTAS_ERROR_LOG_MAX); |
127 | eeh_error_buf_size = RTAS_ERROR_LOG_MAX; | 127 | eeh_error_buf_size = RTAS_ERROR_LOG_MAX; |
128 | } | 128 | } |
129 | 129 | ||
130 | /* Set EEH probe mode */ | 130 | /* Set EEH probe mode */ |
131 | eeh_probe_mode_set(EEH_PROBE_MODE_DEVTREE); | 131 | eeh_add_flag(EEH_PROBE_MODE_DEVTREE | EEH_ENABLE_IO_FOR_LOG); |
132 | 132 | ||
133 | return 0; | 133 | return 0; |
134 | } | 134 | } |
@@ -270,7 +270,7 @@ static void *pseries_eeh_of_probe(struct device_node *dn, void *flag) | |||
270 | /* Retrieve the device address */ | 270 | /* Retrieve the device address */ |
271 | regs = of_get_property(dn, "reg", NULL); | 271 | regs = of_get_property(dn, "reg", NULL); |
272 | if (!regs) { | 272 | if (!regs) { |
273 | pr_warning("%s: OF node property %s::reg not found\n", | 273 | pr_warn("%s: OF node property %s::reg not found\n", |
274 | __func__, dn->full_name); | 274 | __func__, dn->full_name); |
275 | return NULL; | 275 | return NULL; |
276 | } | 276 | } |
@@ -297,7 +297,7 @@ static void *pseries_eeh_of_probe(struct device_node *dn, void *flag) | |||
297 | enable = 1; | 297 | enable = 1; |
298 | 298 | ||
299 | if (enable) { | 299 | if (enable) { |
300 | eeh_set_enable(true); | 300 | eeh_add_flag(EEH_ENABLED); |
301 | eeh_add_to_parent_pe(edev); | 301 | eeh_add_to_parent_pe(edev); |
302 | 302 | ||
303 | pr_debug("%s: EEH enabled on %s PHB#%d-PE#%x, config addr#%x\n", | 303 | pr_debug("%s: EEH enabled on %s PHB#%d-PE#%x, config addr#%x\n", |
@@ -398,7 +398,7 @@ static int pseries_eeh_get_pe_addr(struct eeh_pe *pe) | |||
398 | pe->config_addr, BUID_HI(pe->phb->buid), | 398 | pe->config_addr, BUID_HI(pe->phb->buid), |
399 | BUID_LO(pe->phb->buid), 0); | 399 | BUID_LO(pe->phb->buid), 0); |
400 | if (ret) { | 400 | if (ret) { |
401 | pr_warning("%s: Failed to get address for PHB#%d-PE#%x\n", | 401 | pr_warn("%s: Failed to get address for PHB#%d-PE#%x\n", |
402 | __func__, pe->phb->global_number, pe->config_addr); | 402 | __func__, pe->phb->global_number, pe->config_addr); |
403 | return 0; | 403 | return 0; |
404 | } | 404 | } |
@@ -411,7 +411,7 @@ static int pseries_eeh_get_pe_addr(struct eeh_pe *pe) | |||
411 | pe->config_addr, BUID_HI(pe->phb->buid), | 411 | pe->config_addr, BUID_HI(pe->phb->buid), |
412 | BUID_LO(pe->phb->buid), 0); | 412 | BUID_LO(pe->phb->buid), 0); |
413 | if (ret) { | 413 | if (ret) { |
414 | pr_warning("%s: Failed to get address for PHB#%d-PE#%x\n", | 414 | pr_warn("%s: Failed to get address for PHB#%d-PE#%x\n", |
415 | __func__, pe->phb->global_number, pe->config_addr); | 415 | __func__, pe->phb->global_number, pe->config_addr); |
416 | return 0; | 416 | return 0; |
417 | } | 417 | } |
@@ -584,17 +584,17 @@ static int pseries_eeh_wait_state(struct eeh_pe *pe, int max_wait) | |||
584 | return ret; | 584 | return ret; |
585 | 585 | ||
586 | if (max_wait <= 0) { | 586 | if (max_wait <= 0) { |
587 | pr_warning("%s: Timeout when getting PE's state (%d)\n", | 587 | pr_warn("%s: Timeout when getting PE's state (%d)\n", |
588 | __func__, max_wait); | 588 | __func__, max_wait); |
589 | return EEH_STATE_NOT_SUPPORT; | 589 | return EEH_STATE_NOT_SUPPORT; |
590 | } | 590 | } |
591 | 591 | ||
592 | if (mwait <= 0) { | 592 | if (mwait <= 0) { |
593 | pr_warning("%s: Firmware returned bad wait value %d\n", | 593 | pr_warn("%s: Firmware returned bad wait value %d\n", |
594 | __func__, mwait); | 594 | __func__, mwait); |
595 | mwait = EEH_STATE_MIN_WAIT_TIME; | 595 | mwait = EEH_STATE_MIN_WAIT_TIME; |
596 | } else if (mwait > EEH_STATE_MAX_WAIT_TIME) { | 596 | } else if (mwait > EEH_STATE_MAX_WAIT_TIME) { |
597 | pr_warning("%s: Firmware returned too long wait value %d\n", | 597 | pr_warn("%s: Firmware returned too long wait value %d\n", |
598 | __func__, mwait); | 598 | __func__, mwait); |
599 | mwait = EEH_STATE_MAX_WAIT_TIME; | 599 | mwait = EEH_STATE_MAX_WAIT_TIME; |
600 | } | 600 | } |
@@ -675,7 +675,7 @@ static int pseries_eeh_configure_bridge(struct eeh_pe *pe) | |||
675 | } | 675 | } |
676 | 676 | ||
677 | if (ret) | 677 | if (ret) |
678 | pr_warning("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n", | 678 | pr_warn("%s: Unable to configure bridge PHB#%d-PE#%x (%d)\n", |
679 | __func__, pe->phb->global_number, pe->addr, ret); | 679 | __func__, pe->phb->global_number, pe->addr, ret); |
680 | 680 | ||
681 | return ret; | 681 | return ret; |
@@ -743,10 +743,7 @@ static struct eeh_ops pseries_eeh_ops = { | |||
743 | */ | 743 | */ |
744 | static int __init eeh_pseries_init(void) | 744 | static int __init eeh_pseries_init(void) |
745 | { | 745 | { |
746 | int ret = -EINVAL; | 746 | int ret; |
747 | |||
748 | if (!machine_is(pseries)) | ||
749 | return ret; | ||
750 | 747 | ||
751 | ret = eeh_ops_register(&pseries_eeh_ops); | 748 | ret = eeh_ops_register(&pseries_eeh_ops); |
752 | if (!ret) | 749 | if (!ret) |
@@ -757,5 +754,4 @@ static int __init eeh_pseries_init(void) | |||
757 | 754 | ||
758 | return ret; | 755 | return ret; |
759 | } | 756 | } |
760 | 757 | machine_early_initcall(pseries, eeh_pseries_init); | |
761 | early_initcall(eeh_pseries_init); | ||
diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c index 7995135170a3..c904583baf4b 100644 --- a/arch/powerpc/platforms/pseries/hotplug-memory.c +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c | |||
@@ -146,7 +146,7 @@ static inline int pseries_remove_memblock(unsigned long base, | |||
146 | } | 146 | } |
147 | static inline int pseries_remove_mem_node(struct device_node *np) | 147 | static inline int pseries_remove_mem_node(struct device_node *np) |
148 | { | 148 | { |
149 | return -EOPNOTSUPP; | 149 | return 0; |
150 | } | 150 | } |
151 | #endif /* CONFIG_MEMORY_HOTREMOVE */ | 151 | #endif /* CONFIG_MEMORY_HOTREMOVE */ |
152 | 152 | ||
@@ -194,7 +194,7 @@ static int pseries_update_drconf_memory(struct of_prop_reconfig *pr) | |||
194 | if (!memblock_size) | 194 | if (!memblock_size) |
195 | return -EINVAL; | 195 | return -EINVAL; |
196 | 196 | ||
197 | p = (u32 *)of_get_property(pr->dn, "ibm,dynamic-memory", NULL); | 197 | p = (u32 *) pr->old_prop->value; |
198 | if (!p) | 198 | if (!p) |
199 | return -EINVAL; | 199 | return -EINVAL; |
200 | 200 | ||
diff --git a/arch/powerpc/platforms/pseries/hvCall.S b/arch/powerpc/platforms/pseries/hvCall.S index 99ecf0a5a929..3fda3f17b84e 100644 --- a/arch/powerpc/platforms/pseries/hvCall.S +++ b/arch/powerpc/platforms/pseries/hvCall.S | |||
@@ -12,9 +12,13 @@ | |||
12 | #include <asm/ppc_asm.h> | 12 | #include <asm/ppc_asm.h> |
13 | #include <asm/asm-offsets.h> | 13 | #include <asm/asm-offsets.h> |
14 | #include <asm/ptrace.h> | 14 | #include <asm/ptrace.h> |
15 | #include <asm/jump_label.h> | ||
16 | |||
17 | .section ".text" | ||
15 | 18 | ||
16 | #ifdef CONFIG_TRACEPOINTS | 19 | #ifdef CONFIG_TRACEPOINTS |
17 | 20 | ||
21 | #ifndef CONFIG_JUMP_LABEL | ||
18 | .section ".toc","aw" | 22 | .section ".toc","aw" |
19 | 23 | ||
20 | .globl hcall_tracepoint_refcount | 24 | .globl hcall_tracepoint_refcount |
@@ -22,21 +26,13 @@ hcall_tracepoint_refcount: | |||
22 | .llong 0 | 26 | .llong 0 |
23 | 27 | ||
24 | .section ".text" | 28 | .section ".text" |
29 | #endif | ||
25 | 30 | ||
26 | /* | 31 | /* |
27 | * precall must preserve all registers. use unused STK_PARAM() | 32 | * precall must preserve all registers. use unused STK_PARAM() |
28 | * areas to save snapshots and opcode. We branch around this | 33 | * areas to save snapshots and opcode. |
29 | * in early init (eg when populating the MMU hashtable) by using an | ||
30 | * unconditional cpu feature. | ||
31 | */ | 34 | */ |
32 | #define HCALL_INST_PRECALL(FIRST_REG) \ | 35 | #define HCALL_INST_PRECALL(FIRST_REG) \ |
33 | BEGIN_FTR_SECTION; \ | ||
34 | b 1f; \ | ||
35 | END_FTR_SECTION(0, 1); \ | ||
36 | ld r12,hcall_tracepoint_refcount@toc(r2); \ | ||
37 | std r12,32(r1); \ | ||
38 | cmpdi r12,0; \ | ||
39 | beq+ 1f; \ | ||
40 | mflr r0; \ | 36 | mflr r0; \ |
41 | std r3,STK_PARAM(R3)(r1); \ | 37 | std r3,STK_PARAM(R3)(r1); \ |
42 | std r4,STK_PARAM(R4)(r1); \ | 38 | std r4,STK_PARAM(R4)(r1); \ |
@@ -50,45 +46,29 @@ END_FTR_SECTION(0, 1); \ | |||
50 | addi r4,r1,STK_PARAM(FIRST_REG); \ | 46 | addi r4,r1,STK_PARAM(FIRST_REG); \ |
51 | stdu r1,-STACK_FRAME_OVERHEAD(r1); \ | 47 | stdu r1,-STACK_FRAME_OVERHEAD(r1); \ |
52 | bl __trace_hcall_entry; \ | 48 | bl __trace_hcall_entry; \ |
53 | addi r1,r1,STACK_FRAME_OVERHEAD; \ | 49 | ld r3,STACK_FRAME_OVERHEAD+STK_PARAM(R3)(r1); \ |
54 | ld r0,16(r1); \ | 50 | ld r4,STACK_FRAME_OVERHEAD+STK_PARAM(R4)(r1); \ |
55 | ld r3,STK_PARAM(R3)(r1); \ | 51 | ld r5,STACK_FRAME_OVERHEAD+STK_PARAM(R5)(r1); \ |
56 | ld r4,STK_PARAM(R4)(r1); \ | 52 | ld r6,STACK_FRAME_OVERHEAD+STK_PARAM(R6)(r1); \ |
57 | ld r5,STK_PARAM(R5)(r1); \ | 53 | ld r7,STACK_FRAME_OVERHEAD+STK_PARAM(R7)(r1); \ |
58 | ld r6,STK_PARAM(R6)(r1); \ | 54 | ld r8,STACK_FRAME_OVERHEAD+STK_PARAM(R8)(r1); \ |
59 | ld r7,STK_PARAM(R7)(r1); \ | 55 | ld r9,STACK_FRAME_OVERHEAD+STK_PARAM(R9)(r1); \ |
60 | ld r8,STK_PARAM(R8)(r1); \ | 56 | ld r10,STACK_FRAME_OVERHEAD+STK_PARAM(R10)(r1) |
61 | ld r9,STK_PARAM(R9)(r1); \ | ||
62 | ld r10,STK_PARAM(R10)(r1); \ | ||
63 | mtlr r0; \ | ||
64 | 1: | ||
65 | 57 | ||
66 | /* | 58 | /* |
67 | * postcall is performed immediately before function return which | 59 | * postcall is performed immediately before function return which |
68 | * allows liberal use of volatile registers. We branch around this | 60 | * allows liberal use of volatile registers. |
69 | * in early init (eg when populating the MMU hashtable) by using an | ||
70 | * unconditional cpu feature. | ||
71 | */ | 61 | */ |
72 | #define __HCALL_INST_POSTCALL \ | 62 | #define __HCALL_INST_POSTCALL \ |
73 | BEGIN_FTR_SECTION; \ | 63 | ld r0,STACK_FRAME_OVERHEAD+STK_PARAM(R3)(r1); \ |
74 | b 1f; \ | 64 | std r3,STACK_FRAME_OVERHEAD+STK_PARAM(R3)(r1); \ |
75 | END_FTR_SECTION(0, 1); \ | ||
76 | ld r12,32(r1); \ | ||
77 | cmpdi r12,0; \ | ||
78 | beq+ 1f; \ | ||
79 | mflr r0; \ | ||
80 | ld r6,STK_PARAM(R3)(r1); \ | ||
81 | std r3,STK_PARAM(R3)(r1); \ | ||
82 | mr r4,r3; \ | 65 | mr r4,r3; \ |
83 | mr r3,r6; \ | 66 | mr r3,r0; \ |
84 | std r0,16(r1); \ | ||
85 | stdu r1,-STACK_FRAME_OVERHEAD(r1); \ | ||
86 | bl __trace_hcall_exit; \ | 67 | bl __trace_hcall_exit; \ |
68 | ld r0,STACK_FRAME_OVERHEAD+16(r1); \ | ||
87 | addi r1,r1,STACK_FRAME_OVERHEAD; \ | 69 | addi r1,r1,STACK_FRAME_OVERHEAD; \ |
88 | ld r0,16(r1); \ | ||
89 | ld r3,STK_PARAM(R3)(r1); \ | 70 | ld r3,STK_PARAM(R3)(r1); \ |
90 | mtlr r0; \ | 71 | mtlr r0 |
91 | 1: | ||
92 | 72 | ||
93 | #define HCALL_INST_POSTCALL_NORETS \ | 73 | #define HCALL_INST_POSTCALL_NORETS \ |
94 | li r5,0; \ | 74 | li r5,0; \ |
@@ -98,37 +78,62 @@ END_FTR_SECTION(0, 1); \ | |||
98 | mr r5,BUFREG; \ | 78 | mr r5,BUFREG; \ |
99 | __HCALL_INST_POSTCALL | 79 | __HCALL_INST_POSTCALL |
100 | 80 | ||
81 | #ifdef CONFIG_JUMP_LABEL | ||
82 | #define HCALL_BRANCH(LABEL) \ | ||
83 | ARCH_STATIC_BRANCH(LABEL, hcall_tracepoint_key) | ||
84 | #else | ||
85 | |||
86 | /* | ||
87 | * We branch around this in early init (eg when populating the MMU | ||
88 | * hashtable) by using an unconditional cpu feature. | ||
89 | */ | ||
90 | #define HCALL_BRANCH(LABEL) \ | ||
91 | BEGIN_FTR_SECTION; \ | ||
92 | b 1f; \ | ||
93 | END_FTR_SECTION(0, 1); \ | ||
94 | ld r12,hcall_tracepoint_refcount@toc(r2); \ | ||
95 | std r12,32(r1); \ | ||
96 | cmpdi r12,0; \ | ||
97 | bne- LABEL; \ | ||
98 | 1: | ||
99 | #endif | ||
100 | |||
101 | #else | 101 | #else |
102 | #define HCALL_INST_PRECALL(FIRST_ARG) | 102 | #define HCALL_INST_PRECALL(FIRST_ARG) |
103 | #define HCALL_INST_POSTCALL_NORETS | 103 | #define HCALL_INST_POSTCALL_NORETS |
104 | #define HCALL_INST_POSTCALL(BUFREG) | 104 | #define HCALL_INST_POSTCALL(BUFREG) |
105 | #define HCALL_BRANCH(LABEL) | ||
105 | #endif | 106 | #endif |
106 | 107 | ||
107 | .text | ||
108 | |||
109 | _GLOBAL_TOC(plpar_hcall_norets) | 108 | _GLOBAL_TOC(plpar_hcall_norets) |
110 | HMT_MEDIUM | 109 | HMT_MEDIUM |
111 | 110 | ||
112 | mfcr r0 | 111 | mfcr r0 |
113 | stw r0,8(r1) | 112 | stw r0,8(r1) |
114 | 113 | HCALL_BRANCH(plpar_hcall_norets_trace) | |
115 | HCALL_INST_PRECALL(R4) | ||
116 | |||
117 | HVSC /* invoke the hypervisor */ | 114 | HVSC /* invoke the hypervisor */ |
118 | 115 | ||
119 | HCALL_INST_POSTCALL_NORETS | ||
120 | |||
121 | lwz r0,8(r1) | 116 | lwz r0,8(r1) |
122 | mtcrf 0xff,r0 | 117 | mtcrf 0xff,r0 |
123 | blr /* return r3 = status */ | 118 | blr /* return r3 = status */ |
124 | 119 | ||
120 | #ifdef CONFIG_TRACEPOINTS | ||
121 | plpar_hcall_norets_trace: | ||
122 | HCALL_INST_PRECALL(R4) | ||
123 | HVSC | ||
124 | HCALL_INST_POSTCALL_NORETS | ||
125 | lwz r0,8(r1) | ||
126 | mtcrf 0xff,r0 | ||
127 | blr | ||
128 | #endif | ||
129 | |||
125 | _GLOBAL_TOC(plpar_hcall) | 130 | _GLOBAL_TOC(plpar_hcall) |
126 | HMT_MEDIUM | 131 | HMT_MEDIUM |
127 | 132 | ||
128 | mfcr r0 | 133 | mfcr r0 |
129 | stw r0,8(r1) | 134 | stw r0,8(r1) |
130 | 135 | ||
131 | HCALL_INST_PRECALL(R5) | 136 | HCALL_BRANCH(plpar_hcall_trace) |
132 | 137 | ||
133 | std r4,STK_PARAM(R4)(r1) /* Save ret buffer */ | 138 | std r4,STK_PARAM(R4)(r1) /* Save ret buffer */ |
134 | 139 | ||
@@ -147,12 +152,40 @@ _GLOBAL_TOC(plpar_hcall) | |||
147 | std r6, 16(r12) | 152 | std r6, 16(r12) |
148 | std r7, 24(r12) | 153 | std r7, 24(r12) |
149 | 154 | ||
155 | lwz r0,8(r1) | ||
156 | mtcrf 0xff,r0 | ||
157 | |||
158 | blr /* return r3 = status */ | ||
159 | |||
160 | #ifdef CONFIG_TRACEPOINTS | ||
161 | plpar_hcall_trace: | ||
162 | HCALL_INST_PRECALL(R5) | ||
163 | |||
164 | std r4,STK_PARAM(R4)(r1) | ||
165 | mr r0,r4 | ||
166 | |||
167 | mr r4,r5 | ||
168 | mr r5,r6 | ||
169 | mr r6,r7 | ||
170 | mr r7,r8 | ||
171 | mr r8,r9 | ||
172 | mr r9,r10 | ||
173 | |||
174 | HVSC | ||
175 | |||
176 | ld r12,STK_PARAM(R4)(r1) | ||
177 | std r4,0(r12) | ||
178 | std r5,8(r12) | ||
179 | std r6,16(r12) | ||
180 | std r7,24(r12) | ||
181 | |||
150 | HCALL_INST_POSTCALL(r12) | 182 | HCALL_INST_POSTCALL(r12) |
151 | 183 | ||
152 | lwz r0,8(r1) | 184 | lwz r0,8(r1) |
153 | mtcrf 0xff,r0 | 185 | mtcrf 0xff,r0 |
154 | 186 | ||
155 | blr /* return r3 = status */ | 187 | blr |
188 | #endif | ||
156 | 189 | ||
157 | /* | 190 | /* |
158 | * plpar_hcall_raw can be called in real mode. kexec/kdump need some | 191 | * plpar_hcall_raw can be called in real mode. kexec/kdump need some |
@@ -194,7 +227,7 @@ _GLOBAL_TOC(plpar_hcall9) | |||
194 | mfcr r0 | 227 | mfcr r0 |
195 | stw r0,8(r1) | 228 | stw r0,8(r1) |
196 | 229 | ||
197 | HCALL_INST_PRECALL(R5) | 230 | HCALL_BRANCH(plpar_hcall9_trace) |
198 | 231 | ||
199 | std r4,STK_PARAM(R4)(r1) /* Save ret buffer */ | 232 | std r4,STK_PARAM(R4)(r1) /* Save ret buffer */ |
200 | 233 | ||
@@ -222,12 +255,49 @@ _GLOBAL_TOC(plpar_hcall9) | |||
222 | std r11,56(r12) | 255 | std r11,56(r12) |
223 | std r0, 64(r12) | 256 | std r0, 64(r12) |
224 | 257 | ||
258 | lwz r0,8(r1) | ||
259 | mtcrf 0xff,r0 | ||
260 | |||
261 | blr /* return r3 = status */ | ||
262 | |||
263 | #ifdef CONFIG_TRACEPOINTS | ||
264 | plpar_hcall9_trace: | ||
265 | HCALL_INST_PRECALL(R5) | ||
266 | |||
267 | std r4,STK_PARAM(R4)(r1) | ||
268 | mr r0,r4 | ||
269 | |||
270 | mr r4,r5 | ||
271 | mr r5,r6 | ||
272 | mr r6,r7 | ||
273 | mr r7,r8 | ||
274 | mr r8,r9 | ||
275 | mr r9,r10 | ||
276 | ld r10,STACK_FRAME_OVERHEAD+STK_PARAM(R11)(r1) | ||
277 | ld r11,STACK_FRAME_OVERHEAD+STK_PARAM(R12)(r1) | ||
278 | ld r12,STACK_FRAME_OVERHEAD+STK_PARAM(R13)(r1) | ||
279 | |||
280 | HVSC | ||
281 | |||
282 | mr r0,r12 | ||
283 | ld r12,STACK_FRAME_OVERHEAD+STK_PARAM(R4)(r1) | ||
284 | std r4,0(r12) | ||
285 | std r5,8(r12) | ||
286 | std r6,16(r12) | ||
287 | std r7,24(r12) | ||
288 | std r8,32(r12) | ||
289 | std r9,40(r12) | ||
290 | std r10,48(r12) | ||
291 | std r11,56(r12) | ||
292 | std r0,64(r12) | ||
293 | |||
225 | HCALL_INST_POSTCALL(r12) | 294 | HCALL_INST_POSTCALL(r12) |
226 | 295 | ||
227 | lwz r0,8(r1) | 296 | lwz r0,8(r1) |
228 | mtcrf 0xff,r0 | 297 | mtcrf 0xff,r0 |
229 | 298 | ||
230 | blr /* return r3 = status */ | 299 | blr |
300 | #endif | ||
231 | 301 | ||
232 | /* See plpar_hcall_raw to see why this is needed */ | 302 | /* See plpar_hcall_raw to see why this is needed */ |
233 | _GLOBAL(plpar_hcall9_raw) | 303 | _GLOBAL(plpar_hcall9_raw) |
diff --git a/arch/powerpc/platforms/pseries/hvCall_inst.c b/arch/powerpc/platforms/pseries/hvCall_inst.c index cf4e7736e4f1..4575f0c9e521 100644 --- a/arch/powerpc/platforms/pseries/hvCall_inst.c +++ b/arch/powerpc/platforms/pseries/hvCall_inst.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <asm/firmware.h> | 27 | #include <asm/firmware.h> |
28 | #include <asm/cputable.h> | 28 | #include <asm/cputable.h> |
29 | #include <asm/trace.h> | 29 | #include <asm/trace.h> |
30 | #include <asm/machdep.h> | ||
30 | 31 | ||
31 | DEFINE_PER_CPU(struct hcall_stats[HCALL_STAT_ARRAY_SIZE], hcall_stats); | 32 | DEFINE_PER_CPU(struct hcall_stats[HCALL_STAT_ARRAY_SIZE], hcall_stats); |
32 | 33 | ||
@@ -162,4 +163,4 @@ static int __init hcall_inst_init(void) | |||
162 | 163 | ||
163 | return 0; | 164 | return 0; |
164 | } | 165 | } |
165 | __initcall(hcall_inst_init); | 166 | machine_device_initcall(pseries, hcall_inst_init); |
diff --git a/arch/powerpc/platforms/pseries/hvcserver.c b/arch/powerpc/platforms/pseries/hvcserver.c index 4557e91626c4..eedb64594dc5 100644 --- a/arch/powerpc/platforms/pseries/hvcserver.c +++ b/arch/powerpc/platforms/pseries/hvcserver.c | |||
@@ -163,8 +163,8 @@ int hvcs_get_partner_info(uint32_t unit_address, struct list_head *head, | |||
163 | return retval; | 163 | return retval; |
164 | } | 164 | } |
165 | 165 | ||
166 | last_p_partition_ID = pi_buff[0]; | 166 | last_p_partition_ID = be64_to_cpu(pi_buff[0]); |
167 | last_p_unit_address = pi_buff[1]; | 167 | last_p_unit_address = be64_to_cpu(pi_buff[1]); |
168 | 168 | ||
169 | /* This indicates that there are no further partners */ | 169 | /* This indicates that there are no further partners */ |
170 | if (last_p_partition_ID == ~0UL | 170 | if (last_p_partition_ID == ~0UL |
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 33b552ffbe57..4642d6a4d356 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c | |||
@@ -721,13 +721,13 @@ static int __init disable_ddw_setup(char *str) | |||
721 | 721 | ||
722 | early_param("disable_ddw", disable_ddw_setup); | 722 | early_param("disable_ddw", disable_ddw_setup); |
723 | 723 | ||
724 | static void remove_ddw(struct device_node *np) | 724 | static void remove_ddw(struct device_node *np, bool remove_prop) |
725 | { | 725 | { |
726 | struct dynamic_dma_window_prop *dwp; | 726 | struct dynamic_dma_window_prop *dwp; |
727 | struct property *win64; | 727 | struct property *win64; |
728 | const u32 *ddw_avail; | 728 | const u32 *ddw_avail; |
729 | u64 liobn; | 729 | u64 liobn; |
730 | int len, ret; | 730 | int len, ret = 0; |
731 | 731 | ||
732 | ddw_avail = of_get_property(np, "ibm,ddw-applicable", &len); | 732 | ddw_avail = of_get_property(np, "ibm,ddw-applicable", &len); |
733 | win64 = of_find_property(np, DIRECT64_PROPNAME, NULL); | 733 | win64 = of_find_property(np, DIRECT64_PROPNAME, NULL); |
@@ -761,7 +761,8 @@ static void remove_ddw(struct device_node *np) | |||
761 | np->full_name, ret, ddw_avail[2], liobn); | 761 | np->full_name, ret, ddw_avail[2], liobn); |
762 | 762 | ||
763 | delprop: | 763 | delprop: |
764 | ret = of_remove_property(np, win64); | 764 | if (remove_prop) |
765 | ret = of_remove_property(np, win64); | ||
765 | if (ret) | 766 | if (ret) |
766 | pr_warning("%s: failed to remove direct window property: %d\n", | 767 | pr_warning("%s: failed to remove direct window property: %d\n", |
767 | np->full_name, ret); | 768 | np->full_name, ret); |
@@ -805,7 +806,7 @@ static int find_existing_ddw_windows(void) | |||
805 | window = kzalloc(sizeof(*window), GFP_KERNEL); | 806 | window = kzalloc(sizeof(*window), GFP_KERNEL); |
806 | if (!window || len < sizeof(struct dynamic_dma_window_prop)) { | 807 | if (!window || len < sizeof(struct dynamic_dma_window_prop)) { |
807 | kfree(window); | 808 | kfree(window); |
808 | remove_ddw(pdn); | 809 | remove_ddw(pdn, true); |
809 | continue; | 810 | continue; |
810 | } | 811 | } |
811 | 812 | ||
@@ -1045,7 +1046,7 @@ out_free_window: | |||
1045 | kfree(window); | 1046 | kfree(window); |
1046 | 1047 | ||
1047 | out_clear_window: | 1048 | out_clear_window: |
1048 | remove_ddw(pdn); | 1049 | remove_ddw(pdn, true); |
1049 | 1050 | ||
1050 | out_free_prop: | 1051 | out_free_prop: |
1051 | kfree(win64->name); | 1052 | kfree(win64->name); |
@@ -1255,7 +1256,14 @@ static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long acti | |||
1255 | 1256 | ||
1256 | switch (action) { | 1257 | switch (action) { |
1257 | case OF_RECONFIG_DETACH_NODE: | 1258 | case OF_RECONFIG_DETACH_NODE: |
1258 | remove_ddw(np); | 1259 | /* |
1260 | * Removing the property will invoke the reconfig | ||
1261 | * notifier again, which causes dead-lock on the | ||
1262 | * read-write semaphore of the notifier chain. So | ||
1263 | * we have to remove the property when releasing | ||
1264 | * the device node. | ||
1265 | */ | ||
1266 | remove_ddw(np, false); | ||
1259 | if (pci && pci->iommu_table) | 1267 | if (pci && pci->iommu_table) |
1260 | iommu_free_table(pci->iommu_table, np->full_name); | 1268 | iommu_free_table(pci->iommu_table, np->full_name); |
1261 | 1269 | ||
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index b02af9ef3ff6..34e64237fff9 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/dma-mapping.h> | 26 | #include <linux/dma-mapping.h> |
27 | #include <linux/console.h> | 27 | #include <linux/console.h> |
28 | #include <linux/export.h> | 28 | #include <linux/export.h> |
29 | #include <linux/static_key.h> | ||
29 | #include <asm/processor.h> | 30 | #include <asm/processor.h> |
30 | #include <asm/mmu.h> | 31 | #include <asm/mmu.h> |
31 | #include <asm/page.h> | 32 | #include <asm/page.h> |
@@ -430,16 +431,17 @@ static void __pSeries_lpar_hugepage_invalidate(unsigned long *slot, | |||
430 | spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags); | 431 | spin_unlock_irqrestore(&pSeries_lpar_tlbie_lock, flags); |
431 | } | 432 | } |
432 | 433 | ||
433 | static void pSeries_lpar_hugepage_invalidate(struct mm_struct *mm, | 434 | static void pSeries_lpar_hugepage_invalidate(unsigned long vsid, |
434 | unsigned char *hpte_slot_array, | 435 | unsigned long addr, |
435 | unsigned long addr, int psize) | 436 | unsigned char *hpte_slot_array, |
437 | int psize, int ssize) | ||
436 | { | 438 | { |
437 | int ssize = 0, i, index = 0; | 439 | int i, index = 0; |
438 | unsigned long s_addr = addr; | 440 | unsigned long s_addr = addr; |
439 | unsigned int max_hpte_count, valid; | 441 | unsigned int max_hpte_count, valid; |
440 | unsigned long vpn_array[PPC64_HUGE_HPTE_BATCH]; | 442 | unsigned long vpn_array[PPC64_HUGE_HPTE_BATCH]; |
441 | unsigned long slot_array[PPC64_HUGE_HPTE_BATCH]; | 443 | unsigned long slot_array[PPC64_HUGE_HPTE_BATCH]; |
442 | unsigned long shift, hidx, vpn = 0, vsid, hash, slot; | 444 | unsigned long shift, hidx, vpn = 0, hash, slot; |
443 | 445 | ||
444 | shift = mmu_psize_defs[psize].shift; | 446 | shift = mmu_psize_defs[psize].shift; |
445 | max_hpte_count = 1U << (PMD_SHIFT - shift); | 447 | max_hpte_count = 1U << (PMD_SHIFT - shift); |
@@ -452,15 +454,6 @@ static void pSeries_lpar_hugepage_invalidate(struct mm_struct *mm, | |||
452 | 454 | ||
453 | /* get the vpn */ | 455 | /* get the vpn */ |
454 | addr = s_addr + (i * (1ul << shift)); | 456 | addr = s_addr + (i * (1ul << shift)); |
455 | if (!is_kernel_addr(addr)) { | ||
456 | ssize = user_segment_size(addr); | ||
457 | vsid = get_vsid(mm->context.id, addr, ssize); | ||
458 | WARN_ON(vsid == 0); | ||
459 | } else { | ||
460 | vsid = get_kernel_vsid(addr, mmu_kernel_ssize); | ||
461 | ssize = mmu_kernel_ssize; | ||
462 | } | ||
463 | |||
464 | vpn = hpt_vpn(addr, vsid, ssize); | 457 | vpn = hpt_vpn(addr, vsid, ssize); |
465 | hash = hpt_hash(vpn, shift, ssize); | 458 | hash = hpt_hash(vpn, shift, ssize); |
466 | if (hidx & _PTEIDX_SECONDARY) | 459 | if (hidx & _PTEIDX_SECONDARY) |
@@ -649,6 +642,19 @@ EXPORT_SYMBOL(arch_free_page); | |||
649 | #endif | 642 | #endif |
650 | 643 | ||
651 | #ifdef CONFIG_TRACEPOINTS | 644 | #ifdef CONFIG_TRACEPOINTS |
645 | #ifdef CONFIG_JUMP_LABEL | ||
646 | struct static_key hcall_tracepoint_key = STATIC_KEY_INIT; | ||
647 | |||
648 | void hcall_tracepoint_regfunc(void) | ||
649 | { | ||
650 | static_key_slow_inc(&hcall_tracepoint_key); | ||
651 | } | ||
652 | |||
653 | void hcall_tracepoint_unregfunc(void) | ||
654 | { | ||
655 | static_key_slow_dec(&hcall_tracepoint_key); | ||
656 | } | ||
657 | #else | ||
652 | /* | 658 | /* |
653 | * We optimise our hcall path by placing hcall_tracepoint_refcount | 659 | * We optimise our hcall path by placing hcall_tracepoint_refcount |
654 | * directly in the TOC so we can check if the hcall tracepoints are | 660 | * directly in the TOC so we can check if the hcall tracepoints are |
@@ -658,13 +664,6 @@ EXPORT_SYMBOL(arch_free_page); | |||
658 | /* NB: reg/unreg are called while guarded with the tracepoints_mutex */ | 664 | /* NB: reg/unreg are called while guarded with the tracepoints_mutex */ |
659 | extern long hcall_tracepoint_refcount; | 665 | extern long hcall_tracepoint_refcount; |
660 | 666 | ||
661 | /* | ||
662 | * Since the tracing code might execute hcalls we need to guard against | ||
663 | * recursion. One example of this are spinlocks calling H_YIELD on | ||
664 | * shared processor partitions. | ||
665 | */ | ||
666 | static DEFINE_PER_CPU(unsigned int, hcall_trace_depth); | ||
667 | |||
668 | void hcall_tracepoint_regfunc(void) | 667 | void hcall_tracepoint_regfunc(void) |
669 | { | 668 | { |
670 | hcall_tracepoint_refcount++; | 669 | hcall_tracepoint_refcount++; |
@@ -674,6 +673,15 @@ void hcall_tracepoint_unregfunc(void) | |||
674 | { | 673 | { |
675 | hcall_tracepoint_refcount--; | 674 | hcall_tracepoint_refcount--; |
676 | } | 675 | } |
676 | #endif | ||
677 | |||
678 | /* | ||
679 | * Since the tracing code might execute hcalls we need to guard against | ||
680 | * recursion. One example of this are spinlocks calling H_YIELD on | ||
681 | * shared processor partitions. | ||
682 | */ | ||
683 | static DEFINE_PER_CPU(unsigned int, hcall_trace_depth); | ||
684 | |||
677 | 685 | ||
678 | void __trace_hcall_entry(unsigned long opcode, unsigned long *args) | 686 | void __trace_hcall_entry(unsigned long opcode, unsigned long *args) |
679 | { | 687 | { |
diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c index bde7ebad3949..e7cb6d4a871a 100644 --- a/arch/powerpc/platforms/pseries/mobility.c +++ b/arch/powerpc/platforms/pseries/mobility.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | 20 | ||
21 | #include <asm/machdep.h> | ||
21 | #include <asm/rtas.h> | 22 | #include <asm/rtas.h> |
22 | #include "pseries.h" | 23 | #include "pseries.h" |
23 | 24 | ||
@@ -319,7 +320,7 @@ static ssize_t migrate_store(struct class *class, struct class_attribute *attr, | |||
319 | u64 streamid; | 320 | u64 streamid; |
320 | int rc; | 321 | int rc; |
321 | 322 | ||
322 | rc = strict_strtoull(buf, 0, &streamid); | 323 | rc = kstrtou64(buf, 0, &streamid); |
323 | if (rc) | 324 | if (rc) |
324 | return rc; | 325 | return rc; |
325 | 326 | ||
@@ -362,4 +363,4 @@ static int __init mobility_sysfs_init(void) | |||
362 | 363 | ||
363 | return rc; | 364 | return rc; |
364 | } | 365 | } |
365 | device_initcall(mobility_sysfs_init); | 366 | machine_device_initcall(pseries, mobility_sysfs_init); |
diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c index 0c882e83c4ce..18ff4626d74e 100644 --- a/arch/powerpc/platforms/pseries/msi.c +++ b/arch/powerpc/platforms/pseries/msi.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <asm/rtas.h> | 16 | #include <asm/rtas.h> |
17 | #include <asm/hw_irq.h> | 17 | #include <asm/hw_irq.h> |
18 | #include <asm/ppc-pci.h> | 18 | #include <asm/ppc-pci.h> |
19 | #include <asm/machdep.h> | ||
19 | 20 | ||
20 | static int query_token, change_token; | 21 | static int query_token, change_token; |
21 | 22 | ||
@@ -532,5 +533,4 @@ static int rtas_msi_init(void) | |||
532 | 533 | ||
533 | return 0; | 534 | return 0; |
534 | } | 535 | } |
535 | arch_initcall(rtas_msi_init); | 536 | machine_arch_initcall(pseries, rtas_msi_init); |
536 | |||
diff --git a/arch/powerpc/platforms/pseries/pci_dlpar.c b/arch/powerpc/platforms/pseries/pci_dlpar.c index 203cbf0dc101..89e23811199c 100644 --- a/arch/powerpc/platforms/pseries/pci_dlpar.c +++ b/arch/powerpc/platforms/pseries/pci_dlpar.c | |||
@@ -118,10 +118,10 @@ int remove_phb_dynamic(struct pci_controller *phb) | |||
118 | } | 118 | } |
119 | } | 119 | } |
120 | 120 | ||
121 | /* Unregister the bridge device from sysfs and remove the PCI bus */ | 121 | /* Remove the PCI bus and unregister the bridge device from sysfs */ |
122 | device_unregister(b->bridge); | ||
123 | phb->bus = NULL; | 122 | phb->bus = NULL; |
124 | pci_remove_bus(b); | 123 | pci_remove_bus(b); |
124 | device_unregister(b->bridge); | ||
125 | 125 | ||
126 | /* Now release the IO resource */ | 126 | /* Now release the IO resource */ |
127 | if (res->flags & IORESOURCE_IO) | 127 | if (res->flags & IORESOURCE_IO) |
diff --git a/arch/powerpc/platforms/pseries/power.c b/arch/powerpc/platforms/pseries/power.c index 6d6266236446..c26eadde434c 100644 --- a/arch/powerpc/platforms/pseries/power.c +++ b/arch/powerpc/platforms/pseries/power.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/string.h> | 25 | #include <linux/string.h> |
26 | #include <linux/errno.h> | 26 | #include <linux/errno.h> |
27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
28 | #include <asm/machdep.h> | ||
28 | 29 | ||
29 | unsigned long rtas_poweron_auto; /* default and normal state is 0 */ | 30 | unsigned long rtas_poweron_auto; /* default and normal state is 0 */ |
30 | 31 | ||
@@ -71,11 +72,11 @@ static int __init pm_init(void) | |||
71 | return -ENOMEM; | 72 | return -ENOMEM; |
72 | return sysfs_create_group(power_kobj, &attr_group); | 73 | return sysfs_create_group(power_kobj, &attr_group); |
73 | } | 74 | } |
74 | core_initcall(pm_init); | 75 | machine_core_initcall(pseries, pm_init); |
75 | #else | 76 | #else |
76 | static int __init apo_pm_init(void) | 77 | static int __init apo_pm_init(void) |
77 | { | 78 | { |
78 | return (sysfs_create_file(power_kobj, &auto_poweron_attr.attr)); | 79 | return (sysfs_create_file(power_kobj, &auto_poweron_attr.attr)); |
79 | } | 80 | } |
80 | __initcall(apo_pm_init); | 81 | machine_device_initcall(pseries, apo_pm_init); |
81 | #endif | 82 | #endif |
diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c index 9c5778e6ed4b..dff05b9eb946 100644 --- a/arch/powerpc/platforms/pseries/ras.c +++ b/arch/powerpc/platforms/pseries/ras.c | |||
@@ -71,7 +71,7 @@ static int __init init_ras_IRQ(void) | |||
71 | 71 | ||
72 | return 0; | 72 | return 0; |
73 | } | 73 | } |
74 | subsys_initcall(init_ras_IRQ); | 74 | machine_subsys_initcall(pseries, init_ras_IRQ); |
75 | 75 | ||
76 | #define EPOW_SHUTDOWN_NORMAL 1 | 76 | #define EPOW_SHUTDOWN_NORMAL 1 |
77 | #define EPOW_SHUTDOWN_ON_UPS 2 | 77 | #define EPOW_SHUTDOWN_ON_UPS 2 |
diff --git a/arch/powerpc/platforms/pseries/reconfig.c b/arch/powerpc/platforms/pseries/reconfig.c index 1c0a60d98867..0f319521e002 100644 --- a/arch/powerpc/platforms/pseries/reconfig.c +++ b/arch/powerpc/platforms/pseries/reconfig.c | |||
@@ -446,13 +446,10 @@ static int proc_ppc64_create_ofdt(void) | |||
446 | { | 446 | { |
447 | struct proc_dir_entry *ent; | 447 | struct proc_dir_entry *ent; |
448 | 448 | ||
449 | if (!machine_is(pseries)) | ||
450 | return 0; | ||
451 | |||
452 | ent = proc_create("powerpc/ofdt", S_IWUSR, NULL, &ofdt_fops); | 449 | ent = proc_create("powerpc/ofdt", S_IWUSR, NULL, &ofdt_fops); |
453 | if (ent) | 450 | if (ent) |
454 | proc_set_size(ent, 0); | 451 | proc_set_size(ent, 0); |
455 | 452 | ||
456 | return 0; | 453 | return 0; |
457 | } | 454 | } |
458 | __initcall(proc_ppc64_create_ofdt); | 455 | machine_device_initcall(pseries, proc_ppc64_create_ofdt); |
diff --git a/arch/powerpc/platforms/pseries/rng.c b/arch/powerpc/platforms/pseries/rng.c index 72a102758d4e..e09608770909 100644 --- a/arch/powerpc/platforms/pseries/rng.c +++ b/arch/powerpc/platforms/pseries/rng.c | |||
@@ -42,4 +42,4 @@ static __init int rng_init(void) | |||
42 | 42 | ||
43 | return 0; | 43 | return 0; |
44 | } | 44 | } |
45 | subsys_initcall(rng_init); | 45 | machine_subsys_initcall(pseries, rng_init); |
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index f2f40e64658f..e724d3186e73 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
@@ -232,8 +232,7 @@ static void __init pseries_discover_pic(void) | |||
232 | struct device_node *np; | 232 | struct device_node *np; |
233 | const char *typep; | 233 | const char *typep; |
234 | 234 | ||
235 | for (np = NULL; (np = of_find_node_by_name(np, | 235 | for_each_node_by_name(np, "interrupt-controller") { |
236 | "interrupt-controller"));) { | ||
237 | typep = of_get_property(np, "compatible", NULL); | 236 | typep = of_get_property(np, "compatible", NULL); |
238 | if (strstr(typep, "open-pic")) { | 237 | if (strstr(typep, "open-pic")) { |
239 | pSeries_mpic_node = of_node_get(np); | 238 | pSeries_mpic_node = of_node_get(np); |
@@ -351,7 +350,7 @@ static int alloc_dispatch_log_kmem_cache(void) | |||
351 | 350 | ||
352 | return alloc_dispatch_logs(); | 351 | return alloc_dispatch_logs(); |
353 | } | 352 | } |
354 | early_initcall(alloc_dispatch_log_kmem_cache); | 353 | machine_early_initcall(pseries, alloc_dispatch_log_kmem_cache); |
355 | 354 | ||
356 | static void pseries_lpar_idle(void) | 355 | static void pseries_lpar_idle(void) |
357 | { | 356 | { |
diff --git a/arch/powerpc/platforms/pseries/suspend.c b/arch/powerpc/platforms/pseries/suspend.c index b87b97849d4c..e76aefae2aa2 100644 --- a/arch/powerpc/platforms/pseries/suspend.c +++ b/arch/powerpc/platforms/pseries/suspend.c | |||
@@ -265,7 +265,7 @@ static int __init pseries_suspend_init(void) | |||
265 | { | 265 | { |
266 | int rc; | 266 | int rc; |
267 | 267 | ||
268 | if (!machine_is(pseries) || !firmware_has_feature(FW_FEATURE_LPAR)) | 268 | if (!firmware_has_feature(FW_FEATURE_LPAR)) |
269 | return 0; | 269 | return 0; |
270 | 270 | ||
271 | suspend_data.token = rtas_token("ibm,suspend-me"); | 271 | suspend_data.token = rtas_token("ibm,suspend-me"); |
@@ -280,5 +280,4 @@ static int __init pseries_suspend_init(void) | |||
280 | suspend_set_ops(&pseries_suspend_ops); | 280 | suspend_set_ops(&pseries_suspend_ops); |
281 | return 0; | 281 | return 0; |
282 | } | 282 | } |
283 | 283 | machine_device_initcall(pseries, pseries_suspend_init); | |
284 | __initcall(pseries_suspend_init); | ||
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index 4bd091a05583..c5077673bd94 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c | |||
@@ -853,8 +853,8 @@ u64 fsl_pci_immrbar_base(struct pci_controller *hose) | |||
853 | in = pcie->cfg_type0 + PEX_RC_INWIN_BASE; | 853 | in = pcie->cfg_type0 + PEX_RC_INWIN_BASE; |
854 | for (i = 0; i < 4; i++) { | 854 | for (i = 0; i < 4; i++) { |
855 | /* not enabled, skip */ | 855 | /* not enabled, skip */ |
856 | if (!in_le32(&in[i].ar) & PEX_RCIWARn_EN) | 856 | if (!(in_le32(&in[i].ar) & PEX_RCIWARn_EN)) |
857 | continue; | 857 | continue; |
858 | 858 | ||
859 | if (get_immrbase() == in_le32(&in[i].tar)) | 859 | if (get_immrbase() == in_le32(&in[i].tar)) |
860 | return (u64)in_le32(&in[i].barh) << 32 | | 860 | return (u64)in_le32(&in[i].barh) << 32 | |
diff --git a/arch/powerpc/sysdev/micropatch.c b/arch/powerpc/sysdev/micropatch.c index c0bb76ef7242..6727dc54d549 100644 --- a/arch/powerpc/sysdev/micropatch.c +++ b/arch/powerpc/sysdev/micropatch.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <linux/mm.h> | 13 | #include <linux/mm.h> |
14 | #include <linux/interrupt.h> | 14 | #include <linux/interrupt.h> |
15 | #include <asm/irq.h> | 15 | #include <asm/irq.h> |
16 | #include <asm/mpc8xx.h> | ||
17 | #include <asm/page.h> | 16 | #include <asm/page.h> |
18 | #include <asm/pgtable.h> | 17 | #include <asm/pgtable.h> |
19 | #include <asm/8xx_immap.h> | 18 | #include <asm/8xx_immap.h> |
diff --git a/arch/powerpc/sysdev/mpic_msgr.c b/arch/powerpc/sysdev/mpic_msgr.c index 2c9b52aa266c..7bdf3cc741e4 100644 --- a/arch/powerpc/sysdev/mpic_msgr.c +++ b/arch/powerpc/sysdev/mpic_msgr.c | |||
@@ -184,7 +184,7 @@ static int mpic_msgr_probe(struct platform_device *dev) | |||
184 | dev_info(&dev->dev, "Found %d message registers\n", | 184 | dev_info(&dev->dev, "Found %d message registers\n", |
185 | mpic_msgr_count); | 185 | mpic_msgr_count); |
186 | 186 | ||
187 | mpic_msgrs = kzalloc(sizeof(struct mpic_msgr) * mpic_msgr_count, | 187 | mpic_msgrs = kcalloc(mpic_msgr_count, sizeof(*mpic_msgrs), |
188 | GFP_KERNEL); | 188 | GFP_KERNEL); |
189 | if (!mpic_msgrs) { | 189 | if (!mpic_msgrs) { |
190 | dev_err(&dev->dev, | 190 | dev_err(&dev->dev, |
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index d199bfa2f1fa..b988b5addf86 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
25 | #include <linux/irq.h> | 25 | #include <linux/irq.h> |
26 | #include <linux/bug.h> | 26 | #include <linux/bug.h> |
27 | #include <linux/nmi.h> | ||
27 | 28 | ||
28 | #include <asm/ptrace.h> | 29 | #include <asm/ptrace.h> |
29 | #include <asm/string.h> | 30 | #include <asm/string.h> |
@@ -374,6 +375,7 @@ static int xmon_core(struct pt_regs *regs, int fromipi) | |||
374 | #endif | 375 | #endif |
375 | 376 | ||
376 | local_irq_save(flags); | 377 | local_irq_save(flags); |
378 | hard_irq_disable(); | ||
377 | 379 | ||
378 | bp = in_breakpoint_table(regs->nip, &offset); | 380 | bp = in_breakpoint_table(regs->nip, &offset); |
379 | if (bp != NULL) { | 381 | if (bp != NULL) { |
@@ -558,6 +560,7 @@ static int xmon_core(struct pt_regs *regs, int fromipi) | |||
558 | #endif | 560 | #endif |
559 | insert_cpu_bpts(); | 561 | insert_cpu_bpts(); |
560 | 562 | ||
563 | touch_nmi_watchdog(); | ||
561 | local_irq_restore(flags); | 564 | local_irq_restore(flags); |
562 | 565 | ||
563 | return cmd != 'X' && cmd != EOF; | 566 | return cmd != 'X' && cmd != EOF; |
@@ -2058,10 +2061,6 @@ static void dump_one_paca(int cpu) | |||
2058 | DUMP(p, kernel_toc, "lx"); | 2061 | DUMP(p, kernel_toc, "lx"); |
2059 | DUMP(p, kernelbase, "lx"); | 2062 | DUMP(p, kernelbase, "lx"); |
2060 | DUMP(p, kernel_msr, "lx"); | 2063 | DUMP(p, kernel_msr, "lx"); |
2061 | #ifdef CONFIG_PPC_STD_MMU_64 | ||
2062 | DUMP(p, stab_real, "lx"); | ||
2063 | DUMP(p, stab_addr, "lx"); | ||
2064 | #endif | ||
2065 | DUMP(p, emergency_sp, "p"); | 2064 | DUMP(p, emergency_sp, "p"); |
2066 | #ifdef CONFIG_PPC_BOOK3S_64 | 2065 | #ifdef CONFIG_PPC_BOOK3S_64 |
2067 | DUMP(p, mc_emergency_sp, "p"); | 2066 | DUMP(p, mc_emergency_sp, "p"); |
@@ -2694,7 +2693,7 @@ static void xmon_print_symbol(unsigned long address, const char *mid, | |||
2694 | } | 2693 | } |
2695 | 2694 | ||
2696 | #ifdef CONFIG_PPC_BOOK3S_64 | 2695 | #ifdef CONFIG_PPC_BOOK3S_64 |
2697 | static void dump_slb(void) | 2696 | void dump_segments(void) |
2698 | { | 2697 | { |
2699 | int i; | 2698 | int i; |
2700 | unsigned long esid,vsid,valid; | 2699 | unsigned long esid,vsid,valid; |
@@ -2726,34 +2725,6 @@ static void dump_slb(void) | |||
2726 | } | 2725 | } |
2727 | } | 2726 | } |
2728 | } | 2727 | } |
2729 | |||
2730 | static void dump_stab(void) | ||
2731 | { | ||
2732 | int i; | ||
2733 | unsigned long *tmp = (unsigned long *)local_paca->stab_addr; | ||
2734 | |||
2735 | printf("Segment table contents of cpu 0x%x\n", smp_processor_id()); | ||
2736 | |||
2737 | for (i = 0; i < PAGE_SIZE/16; i++) { | ||
2738 | unsigned long a, b; | ||
2739 | |||
2740 | a = *tmp++; | ||
2741 | b = *tmp++; | ||
2742 | |||
2743 | if (a || b) { | ||
2744 | printf("%03d %016lx ", i, a); | ||
2745 | printf("%016lx\n", b); | ||
2746 | } | ||
2747 | } | ||
2748 | } | ||
2749 | |||
2750 | void dump_segments(void) | ||
2751 | { | ||
2752 | if (mmu_has_feature(MMU_FTR_SLB)) | ||
2753 | dump_slb(); | ||
2754 | else | ||
2755 | dump_stab(); | ||
2756 | } | ||
2757 | #endif | 2728 | #endif |
2758 | 2729 | ||
2759 | #ifdef CONFIG_PPC_STD_MMU_32 | 2730 | #ifdef CONFIG_PPC_STD_MMU_32 |