diff options
298 files changed, 5696 insertions, 6903 deletions
diff --git a/Documentation/ABI/testing/sysfs-class-cxl b/Documentation/ABI/testing/sysfs-class-cxl index 8e69345c37cc..bbbabffc682a 100644 --- a/Documentation/ABI/testing/sysfs-class-cxl +++ b/Documentation/ABI/testing/sysfs-class-cxl | |||
@@ -69,7 +69,9 @@ Date: September 2014 | |||
69 | Contact: linuxppc-dev@lists.ozlabs.org | 69 | Contact: linuxppc-dev@lists.ozlabs.org |
70 | Description: read/write | 70 | Description: read/write |
71 | Set the mode for prefaulting in segments into the segment table | 71 | Set the mode for prefaulting in segments into the segment table |
72 | when performing the START_WORK ioctl. Possible values: | 72 | when performing the START_WORK ioctl. Only applicable when |
73 | running under hashed page table mmu. | ||
74 | Possible values: | ||
73 | none: No prefaulting (default) | 75 | none: No prefaulting (default) |
74 | work_element_descriptor: Treat the work element | 76 | work_element_descriptor: Treat the work element |
75 | descriptor as an effective address and | 77 | descriptor as an effective address and |
diff --git a/Documentation/accelerators/ocxl.rst b/Documentation/accelerators/ocxl.rst index ddcc58d01cfb..14cefc020e2d 100644 --- a/Documentation/accelerators/ocxl.rst +++ b/Documentation/accelerators/ocxl.rst | |||
@@ -157,6 +157,17 @@ OCXL_IOCTL_GET_METADATA: | |||
157 | Obtains configuration information from the card, such at the size of | 157 | Obtains configuration information from the card, such at the size of |
158 | MMIO areas, the AFU version, and the PASID for the current context. | 158 | MMIO areas, the AFU version, and the PASID for the current context. |
159 | 159 | ||
160 | OCXL_IOCTL_ENABLE_P9_WAIT: | ||
161 | |||
162 | Allows the AFU to wake a userspace thread executing 'wait'. Returns | ||
163 | information to userspace to allow it to configure the AFU. Note that | ||
164 | this is only available on POWER9. | ||
165 | |||
166 | OCXL_IOCTL_GET_FEATURES: | ||
167 | |||
168 | Reports on which CPU features that affect OpenCAPI are usable from | ||
169 | userspace. | ||
170 | |||
160 | 171 | ||
161 | mmap | 172 | mmap |
162 | ---- | 173 | ---- |
diff --git a/Documentation/devicetree/bindings/marvell.txt b/Documentation/devicetree/bindings/marvell.txt deleted file mode 100644 index 7f722316458a..000000000000 --- a/Documentation/devicetree/bindings/marvell.txt +++ /dev/null | |||
@@ -1,516 +0,0 @@ | |||
1 | Marvell Discovery mv64[345]6x System Controller chips | ||
2 | =========================================================== | ||
3 | |||
4 | The Marvell mv64[345]60 series of system controller chips contain | ||
5 | many of the peripherals needed to implement a complete computer | ||
6 | system. In this section, we define device tree nodes to describe | ||
7 | the system controller chip itself and each of the peripherals | ||
8 | which it contains. Compatible string values for each node are | ||
9 | prefixed with the string "marvell,", for Marvell Technology Group Ltd. | ||
10 | |||
11 | 1) The /system-controller node | ||
12 | |||
13 | This node is used to represent the system-controller and must be | ||
14 | present when the system uses a system controller chip. The top-level | ||
15 | system-controller node contains information that is global to all | ||
16 | devices within the system controller chip. The node name begins | ||
17 | with "system-controller" followed by the unit address, which is | ||
18 | the base address of the memory-mapped register set for the system | ||
19 | controller chip. | ||
20 | |||
21 | Required properties: | ||
22 | |||
23 | - ranges : Describes the translation of system controller addresses | ||
24 | for memory mapped registers. | ||
25 | - clock-frequency: Contains the main clock frequency for the system | ||
26 | controller chip. | ||
27 | - reg : This property defines the address and size of the | ||
28 | memory-mapped registers contained within the system controller | ||
29 | chip. The address specified in the "reg" property should match | ||
30 | the unit address of the system-controller node. | ||
31 | - #address-cells : Address representation for system controller | ||
32 | devices. This field represents the number of cells needed to | ||
33 | represent the address of the memory-mapped registers of devices | ||
34 | within the system controller chip. | ||
35 | - #size-cells : Size representation for the memory-mapped | ||
36 | registers within the system controller chip. | ||
37 | - #interrupt-cells : Defines the width of cells used to represent | ||
38 | interrupts. | ||
39 | |||
40 | Optional properties: | ||
41 | |||
42 | - model : The specific model of the system controller chip. Such | ||
43 | as, "mv64360", "mv64460", or "mv64560". | ||
44 | - compatible : A string identifying the compatibility identifiers | ||
45 | of the system controller chip. | ||
46 | |||
47 | The system-controller node contains child nodes for each system | ||
48 | controller device that the platform uses. Nodes should not be created | ||
49 | for devices which exist on the system controller chip but are not used | ||
50 | |||
51 | Example Marvell Discovery mv64360 system-controller node: | ||
52 | |||
53 | system-controller@f1000000 { /* Marvell Discovery mv64360 */ | ||
54 | #address-cells = <1>; | ||
55 | #size-cells = <1>; | ||
56 | model = "mv64360"; /* Default */ | ||
57 | compatible = "marvell,mv64360"; | ||
58 | clock-frequency = <133333333>; | ||
59 | reg = <0xf1000000 0x10000>; | ||
60 | virtual-reg = <0xf1000000>; | ||
61 | ranges = <0x88000000 0x88000000 0x1000000 /* PCI 0 I/O Space */ | ||
62 | 0x80000000 0x80000000 0x8000000 /* PCI 0 MEM Space */ | ||
63 | 0xa0000000 0xa0000000 0x4000000 /* User FLASH */ | ||
64 | 0x00000000 0xf1000000 0x0010000 /* Bridge's regs */ | ||
65 | 0xf2000000 0xf2000000 0x0040000>;/* Integrated SRAM */ | ||
66 | |||
67 | [ child node definitions... ] | ||
68 | } | ||
69 | |||
70 | 2) Child nodes of /system-controller | ||
71 | |||
72 | a) Marvell Discovery MDIO bus | ||
73 | |||
74 | The MDIO is a bus to which the PHY devices are connected. For each | ||
75 | device that exists on this bus, a child node should be created. See | ||
76 | the definition of the PHY node below for an example of how to define | ||
77 | a PHY. | ||
78 | |||
79 | Required properties: | ||
80 | - #address-cells : Should be <1> | ||
81 | - #size-cells : Should be <0> | ||
82 | - compatible : Should be "marvell,mv64360-mdio" | ||
83 | |||
84 | Example: | ||
85 | |||
86 | mdio { | ||
87 | #address-cells = <1>; | ||
88 | #size-cells = <0>; | ||
89 | compatible = "marvell,mv64360-mdio"; | ||
90 | |||
91 | ethernet-phy@0 { | ||
92 | ...... | ||
93 | }; | ||
94 | }; | ||
95 | |||
96 | |||
97 | b) Marvell Discovery ethernet controller | ||
98 | |||
99 | The Discover ethernet controller is described with two levels | ||
100 | of nodes. The first level describes an ethernet silicon block | ||
101 | and the second level describes up to 3 ethernet nodes within | ||
102 | that block. The reason for the multiple levels is that the | ||
103 | registers for the node are interleaved within a single set | ||
104 | of registers. The "ethernet-block" level describes the | ||
105 | shared register set, and the "ethernet" nodes describe ethernet | ||
106 | port-specific properties. | ||
107 | |||
108 | Ethernet block node | ||
109 | |||
110 | Required properties: | ||
111 | - #address-cells : <1> | ||
112 | - #size-cells : <0> | ||
113 | - compatible : "marvell,mv64360-eth-block" | ||
114 | - reg : Offset and length of the register set for this block | ||
115 | |||
116 | Optional properties: | ||
117 | - clocks : Phandle to the clock control device and gate bit | ||
118 | |||
119 | Example Discovery Ethernet block node: | ||
120 | ethernet-block@2000 { | ||
121 | #address-cells = <1>; | ||
122 | #size-cells = <0>; | ||
123 | compatible = "marvell,mv64360-eth-block"; | ||
124 | reg = <0x2000 0x2000>; | ||
125 | ethernet@0 { | ||
126 | ....... | ||
127 | }; | ||
128 | }; | ||
129 | |||
130 | Ethernet port node | ||
131 | |||
132 | Required properties: | ||
133 | - compatible : Should be "marvell,mv64360-eth". | ||
134 | - reg : Should be <0>, <1>, or <2>, according to which registers | ||
135 | within the silicon block the device uses. | ||
136 | - interrupts : <a> where a is the interrupt number for the port. | ||
137 | - interrupt-parent : the phandle for the interrupt controller | ||
138 | that services interrupts for this device. | ||
139 | - phy : the phandle for the PHY connected to this ethernet | ||
140 | controller. | ||
141 | - local-mac-address : 6 bytes, MAC address | ||
142 | |||
143 | Example Discovery Ethernet port node: | ||
144 | ethernet@0 { | ||
145 | compatible = "marvell,mv64360-eth"; | ||
146 | reg = <0>; | ||
147 | interrupts = <32>; | ||
148 | interrupt-parent = <&PIC>; | ||
149 | phy = <&PHY0>; | ||
150 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
151 | }; | ||
152 | |||
153 | |||
154 | |||
155 | c) Marvell Discovery PHY nodes | ||
156 | |||
157 | Required properties: | ||
158 | - interrupts : <a> where a is the interrupt number for this phy. | ||
159 | - interrupt-parent : the phandle for the interrupt controller that | ||
160 | services interrupts for this device. | ||
161 | - reg : The ID number for the phy, usually a small integer | ||
162 | |||
163 | Example Discovery PHY node: | ||
164 | ethernet-phy@1 { | ||
165 | compatible = "broadcom,bcm5421"; | ||
166 | interrupts = <76>; /* GPP 12 */ | ||
167 | interrupt-parent = <&PIC>; | ||
168 | reg = <1>; | ||
169 | }; | ||
170 | |||
171 | |||
172 | d) Marvell Discovery SDMA nodes | ||
173 | |||
174 | Represent DMA hardware associated with the MPSC (multiprotocol | ||
175 | serial controllers). | ||
176 | |||
177 | Required properties: | ||
178 | - compatible : "marvell,mv64360-sdma" | ||
179 | - reg : Offset and length of the register set for this device | ||
180 | - interrupts : <a> where a is the interrupt number for the DMA | ||
181 | device. | ||
182 | - interrupt-parent : the phandle for the interrupt controller | ||
183 | that services interrupts for this device. | ||
184 | |||
185 | Example Discovery SDMA node: | ||
186 | sdma@4000 { | ||
187 | compatible = "marvell,mv64360-sdma"; | ||
188 | reg = <0x4000 0xc18>; | ||
189 | virtual-reg = <0xf1004000>; | ||
190 | interrupts = <36>; | ||
191 | interrupt-parent = <&PIC>; | ||
192 | }; | ||
193 | |||
194 | |||
195 | e) Marvell Discovery BRG nodes | ||
196 | |||
197 | Represent baud rate generator hardware associated with the MPSC | ||
198 | (multiprotocol serial controllers). | ||
199 | |||
200 | Required properties: | ||
201 | - compatible : "marvell,mv64360-brg" | ||
202 | - reg : Offset and length of the register set for this device | ||
203 | - clock-src : A value from 0 to 15 which selects the clock | ||
204 | source for the baud rate generator. This value corresponds | ||
205 | to the CLKS value in the BRGx configuration register. See | ||
206 | the mv64x60 User's Manual. | ||
207 | - clock-frequence : The frequency (in Hz) of the baud rate | ||
208 | generator's input clock. | ||
209 | - current-speed : The current speed setting (presumably by | ||
210 | firmware) of the baud rate generator. | ||
211 | |||
212 | Example Discovery BRG node: | ||
213 | brg@b200 { | ||
214 | compatible = "marvell,mv64360-brg"; | ||
215 | reg = <0xb200 0x8>; | ||
216 | clock-src = <8>; | ||
217 | clock-frequency = <133333333>; | ||
218 | current-speed = <9600>; | ||
219 | }; | ||
220 | |||
221 | |||
222 | f) Marvell Discovery CUNIT nodes | ||
223 | |||
224 | Represent the Serial Communications Unit device hardware. | ||
225 | |||
226 | Required properties: | ||
227 | - reg : Offset and length of the register set for this device | ||
228 | |||
229 | Example Discovery CUNIT node: | ||
230 | cunit@f200 { | ||
231 | reg = <0xf200 0x200>; | ||
232 | }; | ||
233 | |||
234 | |||
235 | g) Marvell Discovery MPSCROUTING nodes | ||
236 | |||
237 | Represent the Discovery's MPSC routing hardware | ||
238 | |||
239 | Required properties: | ||
240 | - reg : Offset and length of the register set for this device | ||
241 | |||
242 | Example Discovery CUNIT node: | ||
243 | mpscrouting@b500 { | ||
244 | reg = <0xb400 0xc>; | ||
245 | }; | ||
246 | |||
247 | |||
248 | h) Marvell Discovery MPSCINTR nodes | ||
249 | |||
250 | Represent the Discovery's MPSC DMA interrupt hardware registers | ||
251 | (SDMA cause and mask registers). | ||
252 | |||
253 | Required properties: | ||
254 | - reg : Offset and length of the register set for this device | ||
255 | |||
256 | Example Discovery MPSCINTR node: | ||
257 | mpsintr@b800 { | ||
258 | reg = <0xb800 0x100>; | ||
259 | }; | ||
260 | |||
261 | |||
262 | i) Marvell Discovery MPSC nodes | ||
263 | |||
264 | Represent the Discovery's MPSC (Multiprotocol Serial Controller) | ||
265 | serial port. | ||
266 | |||
267 | Required properties: | ||
268 | - compatible : "marvell,mv64360-mpsc" | ||
269 | - reg : Offset and length of the register set for this device | ||
270 | - sdma : the phandle for the SDMA node used by this port | ||
271 | - brg : the phandle for the BRG node used by this port | ||
272 | - cunit : the phandle for the CUNIT node used by this port | ||
273 | - mpscrouting : the phandle for the MPSCROUTING node used by this port | ||
274 | - mpscintr : the phandle for the MPSCINTR node used by this port | ||
275 | - cell-index : the hardware index of this cell in the MPSC core | ||
276 | - max_idle : value needed for MPSC CHR3 (Maximum Frame Length) | ||
277 | register | ||
278 | - interrupts : <a> where a is the interrupt number for the MPSC. | ||
279 | - interrupt-parent : the phandle for the interrupt controller | ||
280 | that services interrupts for this device. | ||
281 | |||
282 | Example Discovery MPSCINTR node: | ||
283 | mpsc@8000 { | ||
284 | compatible = "marvell,mv64360-mpsc"; | ||
285 | reg = <0x8000 0x38>; | ||
286 | virtual-reg = <0xf1008000>; | ||
287 | sdma = <&SDMA0>; | ||
288 | brg = <&BRG0>; | ||
289 | cunit = <&CUNIT>; | ||
290 | mpscrouting = <&MPSCROUTING>; | ||
291 | mpscintr = <&MPSCINTR>; | ||
292 | cell-index = <0>; | ||
293 | max_idle = <40>; | ||
294 | interrupts = <40>; | ||
295 | interrupt-parent = <&PIC>; | ||
296 | }; | ||
297 | |||
298 | |||
299 | j) Marvell Discovery Watch Dog Timer nodes | ||
300 | |||
301 | Represent the Discovery's watchdog timer hardware | ||
302 | |||
303 | Required properties: | ||
304 | - compatible : "marvell,mv64360-wdt" | ||
305 | - reg : Offset and length of the register set for this device | ||
306 | |||
307 | Example Discovery Watch Dog Timer node: | ||
308 | wdt@b410 { | ||
309 | compatible = "marvell,mv64360-wdt"; | ||
310 | reg = <0xb410 0x8>; | ||
311 | }; | ||
312 | |||
313 | |||
314 | k) Marvell Discovery I2C nodes | ||
315 | |||
316 | Represent the Discovery's I2C hardware | ||
317 | |||
318 | Required properties: | ||
319 | - device_type : "i2c" | ||
320 | - compatible : "marvell,mv64360-i2c" | ||
321 | - reg : Offset and length of the register set for this device | ||
322 | - interrupts : <a> where a is the interrupt number for the I2C. | ||
323 | - interrupt-parent : the phandle for the interrupt controller | ||
324 | that services interrupts for this device. | ||
325 | |||
326 | Example Discovery I2C node: | ||
327 | compatible = "marvell,mv64360-i2c"; | ||
328 | reg = <0xc000 0x20>; | ||
329 | virtual-reg = <0xf100c000>; | ||
330 | interrupts = <37>; | ||
331 | interrupt-parent = <&PIC>; | ||
332 | }; | ||
333 | |||
334 | |||
335 | l) Marvell Discovery PIC (Programmable Interrupt Controller) nodes | ||
336 | |||
337 | Represent the Discovery's PIC hardware | ||
338 | |||
339 | Required properties: | ||
340 | - #interrupt-cells : <1> | ||
341 | - #address-cells : <0> | ||
342 | - compatible : "marvell,mv64360-pic" | ||
343 | - reg : Offset and length of the register set for this device | ||
344 | - interrupt-controller | ||
345 | |||
346 | Example Discovery PIC node: | ||
347 | pic { | ||
348 | #interrupt-cells = <1>; | ||
349 | #address-cells = <0>; | ||
350 | compatible = "marvell,mv64360-pic"; | ||
351 | reg = <0x0 0x88>; | ||
352 | interrupt-controller; | ||
353 | }; | ||
354 | |||
355 | |||
356 | m) Marvell Discovery MPP (Multipurpose Pins) multiplexing nodes | ||
357 | |||
358 | Represent the Discovery's MPP hardware | ||
359 | |||
360 | Required properties: | ||
361 | - compatible : "marvell,mv64360-mpp" | ||
362 | - reg : Offset and length of the register set for this device | ||
363 | |||
364 | Example Discovery MPP node: | ||
365 | mpp@f000 { | ||
366 | compatible = "marvell,mv64360-mpp"; | ||
367 | reg = <0xf000 0x10>; | ||
368 | }; | ||
369 | |||
370 | |||
371 | n) Marvell Discovery GPP (General Purpose Pins) nodes | ||
372 | |||
373 | Represent the Discovery's GPP hardware | ||
374 | |||
375 | Required properties: | ||
376 | - compatible : "marvell,mv64360-gpp" | ||
377 | - reg : Offset and length of the register set for this device | ||
378 | |||
379 | Example Discovery GPP node: | ||
380 | gpp@f000 { | ||
381 | compatible = "marvell,mv64360-gpp"; | ||
382 | reg = <0xf100 0x20>; | ||
383 | }; | ||
384 | |||
385 | |||
386 | o) Marvell Discovery PCI host bridge node | ||
387 | |||
388 | Represents the Discovery's PCI host bridge device. The properties | ||
389 | for this node conform to Rev 2.1 of the PCI Bus Binding to IEEE | ||
390 | 1275-1994. A typical value for the compatible property is | ||
391 | "marvell,mv64360-pci". | ||
392 | |||
393 | Example Discovery PCI host bridge node | ||
394 | pci@80000000 { | ||
395 | #address-cells = <3>; | ||
396 | #size-cells = <2>; | ||
397 | #interrupt-cells = <1>; | ||
398 | device_type = "pci"; | ||
399 | compatible = "marvell,mv64360-pci"; | ||
400 | reg = <0xcf8 0x8>; | ||
401 | ranges = <0x01000000 0x0 0x0 | ||
402 | 0x88000000 0x0 0x01000000 | ||
403 | 0x02000000 0x0 0x80000000 | ||
404 | 0x80000000 0x0 0x08000000>; | ||
405 | bus-range = <0 255>; | ||
406 | clock-frequency = <66000000>; | ||
407 | interrupt-parent = <&PIC>; | ||
408 | interrupt-map-mask = <0xf800 0x0 0x0 0x7>; | ||
409 | interrupt-map = < | ||
410 | /* IDSEL 0x0a */ | ||
411 | 0x5000 0 0 1 &PIC 80 | ||
412 | 0x5000 0 0 2 &PIC 81 | ||
413 | 0x5000 0 0 3 &PIC 91 | ||
414 | 0x5000 0 0 4 &PIC 93 | ||
415 | |||
416 | /* IDSEL 0x0b */ | ||
417 | 0x5800 0 0 1 &PIC 91 | ||
418 | 0x5800 0 0 2 &PIC 93 | ||
419 | 0x5800 0 0 3 &PIC 80 | ||
420 | 0x5800 0 0 4 &PIC 81 | ||
421 | |||
422 | /* IDSEL 0x0c */ | ||
423 | 0x6000 0 0 1 &PIC 91 | ||
424 | 0x6000 0 0 2 &PIC 93 | ||
425 | 0x6000 0 0 3 &PIC 80 | ||
426 | 0x6000 0 0 4 &PIC 81 | ||
427 | |||
428 | /* IDSEL 0x0d */ | ||
429 | 0x6800 0 0 1 &PIC 93 | ||
430 | 0x6800 0 0 2 &PIC 80 | ||
431 | 0x6800 0 0 3 &PIC 81 | ||
432 | 0x6800 0 0 4 &PIC 91 | ||
433 | >; | ||
434 | }; | ||
435 | |||
436 | |||
437 | p) Marvell Discovery CPU Error nodes | ||
438 | |||
439 | Represent the Discovery's CPU error handler device. | ||
440 | |||
441 | Required properties: | ||
442 | - compatible : "marvell,mv64360-cpu-error" | ||
443 | - reg : Offset and length of the register set for this device | ||
444 | - interrupts : the interrupt number for this device | ||
445 | - interrupt-parent : the phandle for the interrupt controller | ||
446 | that services interrupts for this device. | ||
447 | |||
448 | Example Discovery CPU Error node: | ||
449 | cpu-error@70 { | ||
450 | compatible = "marvell,mv64360-cpu-error"; | ||
451 | reg = <0x70 0x10 0x128 0x28>; | ||
452 | interrupts = <3>; | ||
453 | interrupt-parent = <&PIC>; | ||
454 | }; | ||
455 | |||
456 | |||
457 | q) Marvell Discovery SRAM Controller nodes | ||
458 | |||
459 | Represent the Discovery's SRAM controller device. | ||
460 | |||
461 | Required properties: | ||
462 | - compatible : "marvell,mv64360-sram-ctrl" | ||
463 | - reg : Offset and length of the register set for this device | ||
464 | - interrupts : the interrupt number for this device | ||
465 | - interrupt-parent : the phandle for the interrupt controller | ||
466 | that services interrupts for this device. | ||
467 | |||
468 | Example Discovery SRAM Controller node: | ||
469 | sram-ctrl@380 { | ||
470 | compatible = "marvell,mv64360-sram-ctrl"; | ||
471 | reg = <0x380 0x80>; | ||
472 | interrupts = <13>; | ||
473 | interrupt-parent = <&PIC>; | ||
474 | }; | ||
475 | |||
476 | |||
477 | r) Marvell Discovery PCI Error Handler nodes | ||
478 | |||
479 | Represent the Discovery's PCI error handler device. | ||
480 | |||
481 | Required properties: | ||
482 | - compatible : "marvell,mv64360-pci-error" | ||
483 | - reg : Offset and length of the register set for this device | ||
484 | - interrupts : the interrupt number for this device | ||
485 | - interrupt-parent : the phandle for the interrupt controller | ||
486 | that services interrupts for this device. | ||
487 | |||
488 | Example Discovery PCI Error Handler node: | ||
489 | pci-error@1d40 { | ||
490 | compatible = "marvell,mv64360-pci-error"; | ||
491 | reg = <0x1d40 0x40 0xc28 0x4>; | ||
492 | interrupts = <12>; | ||
493 | interrupt-parent = <&PIC>; | ||
494 | }; | ||
495 | |||
496 | |||
497 | s) Marvell Discovery Memory Controller nodes | ||
498 | |||
499 | Represent the Discovery's memory controller device. | ||
500 | |||
501 | Required properties: | ||
502 | - compatible : "marvell,mv64360-mem-ctrl" | ||
503 | - reg : Offset and length of the register set for this device | ||
504 | - interrupts : the interrupt number for this device | ||
505 | - interrupt-parent : the phandle for the interrupt controller | ||
506 | that services interrupts for this device. | ||
507 | |||
508 | Example Discovery Memory Controller node: | ||
509 | mem-ctrl@1400 { | ||
510 | compatible = "marvell,mv64360-mem-ctrl"; | ||
511 | reg = <0x1400 0x60>; | ||
512 | interrupts = <17>; | ||
513 | interrupt-parent = <&PIC>; | ||
514 | }; | ||
515 | |||
516 | |||
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 9c0ee1859323..076fe3094856 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -156,6 +156,7 @@ config PPC | |||
156 | select BUILDTIME_EXTABLE_SORT | 156 | select BUILDTIME_EXTABLE_SORT |
157 | select CLONE_BACKWARDS | 157 | select CLONE_BACKWARDS |
158 | select DCACHE_WORD_ACCESS if PPC64 && CPU_LITTLE_ENDIAN | 158 | select DCACHE_WORD_ACCESS if PPC64 && CPU_LITTLE_ENDIAN |
159 | select DYNAMIC_FTRACE if FUNCTION_TRACER | ||
159 | select EDAC_ATOMIC_SCRUB | 160 | select EDAC_ATOMIC_SCRUB |
160 | select EDAC_SUPPORT | 161 | select EDAC_SUPPORT |
161 | select GENERIC_ATOMIC64 if PPC32 | 162 | select GENERIC_ATOMIC64 if PPC32 |
@@ -214,6 +215,7 @@ config PPC | |||
214 | select HAVE_PERF_USER_STACK_DUMP | 215 | select HAVE_PERF_USER_STACK_DUMP |
215 | select HAVE_RCU_TABLE_FREE if SMP | 216 | select HAVE_RCU_TABLE_FREE if SMP |
216 | select HAVE_REGS_AND_STACK_ACCESS_API | 217 | select HAVE_REGS_AND_STACK_ACCESS_API |
218 | select HAVE_RELIABLE_STACKTRACE if PPC64 && CPU_LITTLE_ENDIAN | ||
217 | select HAVE_SYSCALL_TRACEPOINTS | 219 | select HAVE_SYSCALL_TRACEPOINTS |
218 | select HAVE_VIRT_CPU_ACCOUNTING | 220 | select HAVE_VIRT_CPU_ACCOUNTING |
219 | select HAVE_IRQ_TIME_ACCOUNTING | 221 | select HAVE_IRQ_TIME_ACCOUNTING |
@@ -228,6 +230,7 @@ config PPC | |||
228 | select OF_RESERVED_MEM | 230 | select OF_RESERVED_MEM |
229 | select OLD_SIGACTION if PPC32 | 231 | select OLD_SIGACTION if PPC32 |
230 | select OLD_SIGSUSPEND | 232 | select OLD_SIGSUSPEND |
233 | select RTC_LIB | ||
231 | select SPARSE_IRQ | 234 | select SPARSE_IRQ |
232 | select SYSCTL_EXCEPTION_TRACE | 235 | select SYSCTL_EXCEPTION_TRACE |
233 | select VIRT_TO_BUS if !PPC64 | 236 | select VIRT_TO_BUS if !PPC64 |
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index 95813df90801..9b52e42e581b 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile | |||
@@ -17,17 +17,18 @@ HAS_BIARCH := $(call cc-option-yn, -m32) | |||
17 | # Set default 32 bits cross compilers for vdso and boot wrapper | 17 | # Set default 32 bits cross compilers for vdso and boot wrapper |
18 | CROSS32_COMPILE ?= | 18 | CROSS32_COMPILE ?= |
19 | 19 | ||
20 | CROSS32CC := $(CROSS32_COMPILE)gcc | ||
21 | CROSS32AR := $(CROSS32_COMPILE)ar | ||
22 | |||
23 | ifeq ($(HAS_BIARCH),y) | 20 | ifeq ($(HAS_BIARCH),y) |
24 | ifeq ($(CROSS32_COMPILE),) | 21 | ifeq ($(CROSS32_COMPILE),) |
25 | CROSS32CC := $(CC) -m32 | 22 | ifdef CONFIG_PPC32 |
26 | KBUILD_ARFLAGS += --target=elf32-powerpc | 23 | # These options will be overridden by any -mcpu option that the CPU |
24 | # or platform code sets later on the command line, but they are needed | ||
25 | # to set a sane 32-bit cpu target for the 64-bit cross compiler which | ||
26 | # may default to the wrong ISA. | ||
27 | KBUILD_CFLAGS += -mcpu=powerpc | ||
28 | KBUILD_AFLAGS += -mcpu=powerpc | ||
29 | endif | ||
27 | endif | 30 | endif |
28 | endif | 31 | endif |
29 | |||
30 | export CROSS32CC CROSS32AR | ||
31 | 32 | ||
32 | ifeq ($(CROSS_COMPILE),) | 33 | ifeq ($(CROSS_COMPILE),) |
33 | KBUILD_DEFCONFIG := $(shell uname -m)_defconfig | 34 | KBUILD_DEFCONFIG := $(shell uname -m)_defconfig |
@@ -74,13 +75,15 @@ endif | |||
74 | endif | 75 | endif |
75 | 76 | ||
76 | ifeq ($(CONFIG_CPU_LITTLE_ENDIAN),y) | 77 | ifeq ($(CONFIG_CPU_LITTLE_ENDIAN),y) |
77 | override LD += -EL | 78 | KBUILD_CFLAGS += -mlittle-endian |
79 | LDFLAGS += -EL | ||
78 | LDEMULATION := lppc | 80 | LDEMULATION := lppc |
79 | GNUTARGET := powerpcle | 81 | GNUTARGET := powerpcle |
80 | MULTIPLEWORD := -mno-multiple | 82 | MULTIPLEWORD := -mno-multiple |
81 | KBUILD_CFLAGS_MODULE += $(call cc-option,-mno-save-toc-indirect) | 83 | KBUILD_CFLAGS_MODULE += $(call cc-option,-mno-save-toc-indirect) |
82 | else | 84 | else |
83 | override LD += -EB | 85 | KBUILD_CFLAGS += $(call cc-option,-mbig-endian) |
86 | LDFLAGS += -EB | ||
84 | LDEMULATION := ppc | 87 | LDEMULATION := ppc |
85 | GNUTARGET := powerpc | 88 | GNUTARGET := powerpc |
86 | MULTIPLEWORD := -mmultiple | 89 | MULTIPLEWORD := -mmultiple |
@@ -93,19 +96,19 @@ aflags-$(CONFIG_CPU_BIG_ENDIAN) += $(call cc-option,-mabi=elfv1) | |||
93 | aflags-$(CONFIG_CPU_LITTLE_ENDIAN) += -mabi=elfv2 | 96 | aflags-$(CONFIG_CPU_LITTLE_ENDIAN) += -mabi=elfv2 |
94 | endif | 97 | endif |
95 | 98 | ||
96 | cflags-$(CONFIG_CPU_LITTLE_ENDIAN) += -mlittle-endian | ||
97 | cflags-$(CONFIG_CPU_BIG_ENDIAN) += $(call cc-option,-mbig-endian) | ||
98 | ifneq ($(cc-name),clang) | 99 | ifneq ($(cc-name),clang) |
99 | cflags-$(CONFIG_CPU_LITTLE_ENDIAN) += -mno-strict-align | 100 | cflags-$(CONFIG_CPU_LITTLE_ENDIAN) += -mno-strict-align |
100 | endif | 101 | endif |
101 | 102 | ||
103 | cflags-$(CONFIG_CPU_BIG_ENDIAN) += $(call cc-option,-mbig-endian) | ||
104 | cflags-$(CONFIG_CPU_LITTLE_ENDIAN) += -mlittle-endian | ||
102 | aflags-$(CONFIG_CPU_BIG_ENDIAN) += $(call cc-option,-mbig-endian) | 105 | aflags-$(CONFIG_CPU_BIG_ENDIAN) += $(call cc-option,-mbig-endian) |
103 | aflags-$(CONFIG_CPU_LITTLE_ENDIAN) += -mlittle-endian | 106 | aflags-$(CONFIG_CPU_LITTLE_ENDIAN) += -mlittle-endian |
104 | 107 | ||
105 | ifeq ($(HAS_BIARCH),y) | 108 | ifeq ($(HAS_BIARCH),y) |
106 | override AS += -a$(BITS) | 109 | KBUILD_CFLAGS += -m$(BITS) |
107 | override LD += -m elf$(BITS)$(LDEMULATION) | 110 | KBUILD_AFLAGS += -m$(BITS) -Wl,-a$(BITS) |
108 | override CC += -m$(BITS) | 111 | LDFLAGS += -m elf$(BITS)$(LDEMULATION) |
109 | KBUILD_ARFLAGS += --target=elf$(BITS)-$(GNUTARGET) | 112 | KBUILD_ARFLAGS += --target=elf$(BITS)-$(GNUTARGET) |
110 | endif | 113 | endif |
111 | 114 | ||
@@ -178,6 +181,7 @@ CFLAGS-$(CONFIG_POWER6_CPU) += $(call cc-option,-mcpu=power6) | |||
178 | CFLAGS-$(CONFIG_POWER7_CPU) += $(call cc-option,-mcpu=power7) | 181 | CFLAGS-$(CONFIG_POWER7_CPU) += $(call cc-option,-mcpu=power7) |
179 | CFLAGS-$(CONFIG_POWER8_CPU) += $(call cc-option,-mcpu=power8) | 182 | CFLAGS-$(CONFIG_POWER8_CPU) += $(call cc-option,-mcpu=power8) |
180 | CFLAGS-$(CONFIG_POWER9_CPU) += $(call cc-option,-mcpu=power9) | 183 | CFLAGS-$(CONFIG_POWER9_CPU) += $(call cc-option,-mcpu=power9) |
184 | CFLAGS-$(CONFIG_PPC_8xx) += $(call cc-option,-mcpu=860) | ||
181 | 185 | ||
182 | # Altivec option not allowed with e500mc64 in GCC. | 186 | # Altivec option not allowed with e500mc64 in GCC. |
183 | ifeq ($(CONFIG_ALTIVEC),y) | 187 | ifeq ($(CONFIG_ALTIVEC),y) |
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 26d5d2a5b8e9..deea20c334df 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile | |||
@@ -23,19 +23,23 @@ all: $(obj)/zImage | |||
23 | compress-$(CONFIG_KERNEL_GZIP) := CONFIG_KERNEL_GZIP | 23 | compress-$(CONFIG_KERNEL_GZIP) := CONFIG_KERNEL_GZIP |
24 | compress-$(CONFIG_KERNEL_XZ) := CONFIG_KERNEL_XZ | 24 | compress-$(CONFIG_KERNEL_XZ) := CONFIG_KERNEL_XZ |
25 | 25 | ||
26 | ifdef CROSS32_COMPILE | ||
27 | BOOTCC := $(CROSS32_COMPILE)gcc | ||
28 | BOOTAR := $(CROSS32_COMPILE)ar | ||
29 | else | ||
30 | BOOTCC := $(CC) | ||
31 | BOOTAR := $(AR) | ||
32 | endif | ||
33 | |||
26 | BOOTCFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ | 34 | BOOTCFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ |
27 | -fno-strict-aliasing -Os -msoft-float -pipe \ | 35 | -fno-strict-aliasing -Os -msoft-float -pipe \ |
28 | -fomit-frame-pointer -fno-builtin -fPIC -nostdinc \ | 36 | -fomit-frame-pointer -fno-builtin -fPIC -nostdinc \ |
29 | -D$(compress-y) | 37 | -D$(compress-y) |
30 | 38 | ||
31 | BOOTCC := $(CC) | ||
32 | ifdef CONFIG_PPC64_BOOT_WRAPPER | 39 | ifdef CONFIG_PPC64_BOOT_WRAPPER |
33 | BOOTCFLAGS += -m64 | 40 | BOOTCFLAGS += -m64 |
34 | else | 41 | else |
35 | BOOTCFLAGS += -m32 | 42 | BOOTCFLAGS += -m32 |
36 | ifdef CROSS32_COMPILE | ||
37 | BOOTCC := $(CROSS32_COMPILE)gcc | ||
38 | endif | ||
39 | endif | 43 | endif |
40 | 44 | ||
41 | BOOTCFLAGS += -isystem $(shell $(BOOTCC) -print-file-name=include) | 45 | BOOTCFLAGS += -isystem $(shell $(BOOTCC) -print-file-name=include) |
@@ -49,6 +53,8 @@ endif | |||
49 | 53 | ||
50 | BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc | 54 | BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc |
51 | 55 | ||
56 | BOOTARFLAGS := -cr$(KBUILD_ARFLAGS) | ||
57 | |||
52 | ifdef CONFIG_DEBUG_INFO | 58 | ifdef CONFIG_DEBUG_INFO |
53 | BOOTCFLAGS += -g | 59 | BOOTCFLAGS += -g |
54 | endif | 60 | endif |
@@ -120,7 +126,7 @@ src-wlib-$(CONFIG_40x) += 4xx.c planetcore.c | |||
120 | src-wlib-$(CONFIG_44x) += 4xx.c ebony.c bamboo.c | 126 | src-wlib-$(CONFIG_44x) += 4xx.c ebony.c bamboo.c |
121 | src-wlib-$(CONFIG_PPC_8xx) += mpc8xx.c planetcore.c fsl-soc.c | 127 | src-wlib-$(CONFIG_PPC_8xx) += mpc8xx.c planetcore.c fsl-soc.c |
122 | src-wlib-$(CONFIG_PPC_82xx) += pq2.c fsl-soc.c planetcore.c | 128 | src-wlib-$(CONFIG_PPC_82xx) += pq2.c fsl-soc.c planetcore.c |
123 | src-wlib-$(CONFIG_EMBEDDED6xx) += mpsc.c mv64x60.c mv64x60_i2c.c ugecon.c fsl-soc.c | 129 | src-wlib-$(CONFIG_EMBEDDED6xx) += ugecon.c fsl-soc.c |
124 | src-wlib-$(CONFIG_XILINX_VIRTEX) += uartlite.c | 130 | src-wlib-$(CONFIG_XILINX_VIRTEX) += uartlite.c |
125 | src-wlib-$(CONFIG_CPM) += cpm-serial.c | 131 | src-wlib-$(CONFIG_CPM) += cpm-serial.c |
126 | 132 | ||
@@ -143,8 +149,8 @@ src-plat-$(CONFIG_PPC_82xx) += cuboot-pq2.c fixed-head.S ep8248e.c cuboot-824x.c | |||
143 | src-plat-$(CONFIG_PPC_83xx) += cuboot-83xx.c fixed-head.S redboot-83xx.c | 149 | src-plat-$(CONFIG_PPC_83xx) += cuboot-83xx.c fixed-head.S redboot-83xx.c |
144 | src-plat-$(CONFIG_FSL_SOC_BOOKE) += cuboot-85xx.c cuboot-85xx-cpm2.c | 150 | src-plat-$(CONFIG_FSL_SOC_BOOKE) += cuboot-85xx.c cuboot-85xx-cpm2.c |
145 | src-plat-$(CONFIG_EMBEDDED6xx) += cuboot-pq2.c cuboot-mpc7448hpc2.c \ | 151 | src-plat-$(CONFIG_EMBEDDED6xx) += cuboot-pq2.c cuboot-mpc7448hpc2.c \ |
146 | cuboot-c2k.c gamecube-head.S \ | 152 | gamecube-head.S gamecube.c \ |
147 | gamecube.c wii-head.S wii.c holly.c \ | 153 | wii-head.S wii.c holly.c \ |
148 | fixed-head.S mvme5100.c | 154 | fixed-head.S mvme5100.c |
149 | src-plat-$(CONFIG_AMIGAONE) += cuboot-amigaone.c | 155 | src-plat-$(CONFIG_AMIGAONE) += cuboot-amigaone.c |
150 | src-plat-$(CONFIG_PPC_PS3) += ps3-head.S ps3-hvcall.S ps3.c | 156 | src-plat-$(CONFIG_PPC_PS3) += ps3-head.S ps3-hvcall.S ps3.c |
@@ -202,7 +208,7 @@ quiet_cmd_bootas = BOOTAS $@ | |||
202 | cmd_bootas = $(BOOTCC) -Wp,-MD,$(depfile) $(BOOTAFLAGS) -c -o $@ $< | 208 | cmd_bootas = $(BOOTCC) -Wp,-MD,$(depfile) $(BOOTAFLAGS) -c -o $@ $< |
203 | 209 | ||
204 | quiet_cmd_bootar = BOOTAR $@ | 210 | quiet_cmd_bootar = BOOTAR $@ |
205 | cmd_bootar = $(CROSS32AR) -cr$(KBUILD_ARFLAGS) $@.$$$$ $(filter-out FORCE,$^); mv $@.$$$$ $@ | 211 | cmd_bootar = $(BOOTAR) $(BOOTARFLAGS) $@.$$$$ $(filter-out FORCE,$^); mv $@.$$$$ $@ |
206 | 212 | ||
207 | $(obj-libfdt): $(obj)/%.o: $(srctree)/scripts/dtc/libfdt/%.c FORCE | 213 | $(obj-libfdt): $(obj)/%.o: $(srctree)/scripts/dtc/libfdt/%.c FORCE |
208 | $(call if_changed_dep,bootcc) | 214 | $(call if_changed_dep,bootcc) |
@@ -339,7 +345,6 @@ image-$(CONFIG_MVME7100) += dtbImage.mvme7100 | |||
339 | # Board ports in arch/powerpc/platform/embedded6xx/Kconfig | 345 | # Board ports in arch/powerpc/platform/embedded6xx/Kconfig |
340 | image-$(CONFIG_STORCENTER) += cuImage.storcenter | 346 | image-$(CONFIG_STORCENTER) += cuImage.storcenter |
341 | image-$(CONFIG_MPC7448HPC2) += cuImage.mpc7448hpc2 | 347 | image-$(CONFIG_MPC7448HPC2) += cuImage.mpc7448hpc2 |
342 | image-$(CONFIG_PPC_C2K) += cuImage.c2k | ||
343 | image-$(CONFIG_GAMECUBE) += dtbImage.gamecube | 348 | image-$(CONFIG_GAMECUBE) += dtbImage.gamecube |
344 | image-$(CONFIG_WII) += dtbImage.wii | 349 | image-$(CONFIG_WII) += dtbImage.wii |
345 | image-$(CONFIG_MVME5100) += dtbImage.mvme5100 | 350 | image-$(CONFIG_MVME5100) += dtbImage.mvme5100 |
diff --git a/arch/powerpc/boot/cuboot-c2k.c b/arch/powerpc/boot/cuboot-c2k.c deleted file mode 100644 index 9309c51f1d65..000000000000 --- a/arch/powerpc/boot/cuboot-c2k.c +++ /dev/null | |||
@@ -1,189 +0,0 @@ | |||
1 | /* | ||
2 | * GEFanuc C2K platform code. | ||
3 | * | ||
4 | * Author: Remi Machet <rmachet@slac.stanford.edu> | ||
5 | * | ||
6 | * Originated from prpmc2800.c | ||
7 | * | ||
8 | * 2008 (c) Stanford University | ||
9 | * 2007 (c) MontaVista, Software, Inc. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License version 2 as published | ||
13 | * by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #include "types.h" | ||
17 | #include "stdio.h" | ||
18 | #include "io.h" | ||
19 | #include "ops.h" | ||
20 | #include "elf.h" | ||
21 | #include "mv64x60.h" | ||
22 | #include "cuboot.h" | ||
23 | #include "ppcboot.h" | ||
24 | |||
25 | static u8 *bridge_base; | ||
26 | |||
27 | static void c2k_bridge_setup(u32 mem_size) | ||
28 | { | ||
29 | u32 i, v[30], enables, acc_bits; | ||
30 | u32 pci_base_hi, pci_base_lo, size, buf[2]; | ||
31 | unsigned long cpu_base; | ||
32 | int rc; | ||
33 | void *devp, *mv64x60_devp; | ||
34 | u8 *bridge_pbase, is_coherent; | ||
35 | struct mv64x60_cpu2pci_win *tbl; | ||
36 | int bus; | ||
37 | |||
38 | bridge_pbase = mv64x60_get_bridge_pbase(); | ||
39 | is_coherent = mv64x60_is_coherent(); | ||
40 | |||
41 | if (is_coherent) | ||
42 | acc_bits = MV64x60_PCI_ACC_CNTL_SNOOP_WB | ||
43 | | MV64x60_PCI_ACC_CNTL_SWAP_NONE | ||
44 | | MV64x60_PCI_ACC_CNTL_MBURST_32_BYTES | ||
45 | | MV64x60_PCI_ACC_CNTL_RDSIZE_32_BYTES; | ||
46 | else | ||
47 | acc_bits = MV64x60_PCI_ACC_CNTL_SNOOP_NONE | ||
48 | | MV64x60_PCI_ACC_CNTL_SWAP_NONE | ||
49 | | MV64x60_PCI_ACC_CNTL_MBURST_128_BYTES | ||
50 | | MV64x60_PCI_ACC_CNTL_RDSIZE_256_BYTES; | ||
51 | |||
52 | mv64x60_config_ctlr_windows(bridge_base, bridge_pbase, is_coherent); | ||
53 | mv64x60_devp = find_node_by_compatible(NULL, "marvell,mv64360"); | ||
54 | if (mv64x60_devp == NULL) | ||
55 | fatal("Error: Missing marvell,mv64360 device tree node\n\r"); | ||
56 | |||
57 | enables = in_le32((u32 *)(bridge_base + MV64x60_CPU_BAR_ENABLE)); | ||
58 | enables |= 0x007ffe00; /* Disable all cpu->pci windows */ | ||
59 | out_le32((u32 *)(bridge_base + MV64x60_CPU_BAR_ENABLE), enables); | ||
60 | |||
61 | /* Get the cpu -> pci i/o & mem mappings from the device tree */ | ||
62 | devp = NULL; | ||
63 | for (bus = 0; ; bus++) { | ||
64 | char name[] = "pci "; | ||
65 | |||
66 | name[strlen(name)-1] = bus+'0'; | ||
67 | |||
68 | devp = find_node_by_alias(name); | ||
69 | if (devp == NULL) | ||
70 | break; | ||
71 | |||
72 | if (bus >= 2) | ||
73 | fatal("Error: Only 2 PCI controllers are supported at" \ | ||
74 | " this time.\n"); | ||
75 | |||
76 | mv64x60_config_pci_windows(bridge_base, bridge_pbase, bus, 0, | ||
77 | mem_size, acc_bits); | ||
78 | |||
79 | rc = getprop(devp, "ranges", v, sizeof(v)); | ||
80 | if (rc == 0) | ||
81 | fatal("Error: Can't find marvell,mv64360-pci ranges" | ||
82 | " property\n\r"); | ||
83 | |||
84 | /* Get the cpu -> pci i/o & mem mappings from the device tree */ | ||
85 | |||
86 | for (i = 0; i < rc; i += 6) { | ||
87 | switch (v[i] & 0xff000000) { | ||
88 | case 0x01000000: /* PCI I/O Space */ | ||
89 | tbl = mv64x60_cpu2pci_io; | ||
90 | break; | ||
91 | case 0x02000000: /* PCI MEM Space */ | ||
92 | tbl = mv64x60_cpu2pci_mem; | ||
93 | break; | ||
94 | default: | ||
95 | continue; | ||
96 | } | ||
97 | |||
98 | pci_base_hi = v[i+1]; | ||
99 | pci_base_lo = v[i+2]; | ||
100 | cpu_base = v[i+3]; | ||
101 | size = v[i+5]; | ||
102 | |||
103 | buf[0] = cpu_base; | ||
104 | buf[1] = size; | ||
105 | |||
106 | if (!dt_xlate_addr(devp, buf, sizeof(buf), &cpu_base)) | ||
107 | fatal("Error: Can't translate PCI address " \ | ||
108 | "0x%x\n\r", (u32)cpu_base); | ||
109 | |||
110 | mv64x60_config_cpu2pci_window(bridge_base, bus, | ||
111 | pci_base_hi, pci_base_lo, cpu_base, size, tbl); | ||
112 | } | ||
113 | |||
114 | enables &= ~(3<<(9+bus*5)); /* Enable cpu->pci<bus> i/o, | ||
115 | cpu->pci<bus> mem0 */ | ||
116 | out_le32((u32 *)(bridge_base + MV64x60_CPU_BAR_ENABLE), | ||
117 | enables); | ||
118 | }; | ||
119 | } | ||
120 | |||
121 | static void c2k_fixups(void) | ||
122 | { | ||
123 | u32 mem_size; | ||
124 | |||
125 | mem_size = mv64x60_get_mem_size(bridge_base); | ||
126 | c2k_bridge_setup(mem_size); /* Do necessary bridge setup */ | ||
127 | } | ||
128 | |||
129 | #define MV64x60_MPP_CNTL_0 0xf000 | ||
130 | #define MV64x60_MPP_CNTL_2 0xf008 | ||
131 | #define MV64x60_GPP_IO_CNTL 0xf100 | ||
132 | #define MV64x60_GPP_LEVEL_CNTL 0xf110 | ||
133 | #define MV64x60_GPP_VALUE_SET 0xf118 | ||
134 | |||
135 | static void c2k_reset(void) | ||
136 | { | ||
137 | u32 temp; | ||
138 | |||
139 | udelay(5000000); | ||
140 | |||
141 | if (bridge_base != 0) { | ||
142 | temp = in_le32((u32 *)(bridge_base + MV64x60_MPP_CNTL_0)); | ||
143 | temp &= 0xFFFF0FFF; | ||
144 | out_le32((u32 *)(bridge_base + MV64x60_MPP_CNTL_0), temp); | ||
145 | |||
146 | temp = in_le32((u32 *)(bridge_base + MV64x60_GPP_LEVEL_CNTL)); | ||
147 | temp |= 0x00000004; | ||
148 | out_le32((u32 *)(bridge_base + MV64x60_GPP_LEVEL_CNTL), temp); | ||
149 | |||
150 | temp = in_le32((u32 *)(bridge_base + MV64x60_GPP_IO_CNTL)); | ||
151 | temp |= 0x00000004; | ||
152 | out_le32((u32 *)(bridge_base + MV64x60_GPP_IO_CNTL), temp); | ||
153 | |||
154 | temp = in_le32((u32 *)(bridge_base + MV64x60_MPP_CNTL_2)); | ||
155 | temp &= 0xFFFF0FFF; | ||
156 | out_le32((u32 *)(bridge_base + MV64x60_MPP_CNTL_2), temp); | ||
157 | |||
158 | temp = in_le32((u32 *)(bridge_base + MV64x60_GPP_LEVEL_CNTL)); | ||
159 | temp |= 0x00080000; | ||
160 | out_le32((u32 *)(bridge_base + MV64x60_GPP_LEVEL_CNTL), temp); | ||
161 | |||
162 | temp = in_le32((u32 *)(bridge_base + MV64x60_GPP_IO_CNTL)); | ||
163 | temp |= 0x00080000; | ||
164 | out_le32((u32 *)(bridge_base + MV64x60_GPP_IO_CNTL), temp); | ||
165 | |||
166 | out_le32((u32 *)(bridge_base + MV64x60_GPP_VALUE_SET), | ||
167 | 0x00080004); | ||
168 | } | ||
169 | |||
170 | for (;;); | ||
171 | } | ||
172 | |||
173 | static bd_t bd; | ||
174 | |||
175 | void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
176 | unsigned long r6, unsigned long r7) | ||
177 | { | ||
178 | CUBOOT_INIT(); | ||
179 | |||
180 | fdt_init(_dtb_start); | ||
181 | |||
182 | bridge_base = mv64x60_get_bridge_base(); | ||
183 | |||
184 | platform_ops.fixups = c2k_fixups; | ||
185 | platform_ops.exit = c2k_reset; | ||
186 | |||
187 | if (serial_console_init() < 0) | ||
188 | exit(); | ||
189 | } | ||
diff --git a/arch/powerpc/boot/dts/c2k.dts b/arch/powerpc/boot/dts/c2k.dts deleted file mode 100644 index c5beb72d18b7..000000000000 --- a/arch/powerpc/boot/dts/c2k.dts +++ /dev/null | |||
@@ -1,366 +0,0 @@ | |||
1 | /* Device Tree Source for GEFanuc C2K | ||
2 | * | ||
3 | * Author: Remi Machet <rmachet@slac.stanford.edu> | ||
4 | * | ||
5 | * Originated from prpmc2800.dts | ||
6 | * | ||
7 | * 2008 (c) Stanford University | ||
8 | * 2007 (c) MontaVista, Software, Inc. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License version 2 as published | ||
12 | * by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | /dts-v1/; | ||
16 | |||
17 | / { | ||
18 | #address-cells = <1>; | ||
19 | #size-cells = <1>; | ||
20 | model = "C2K"; | ||
21 | compatible = "GEFanuc,C2K"; | ||
22 | coherency-off; | ||
23 | |||
24 | aliases { | ||
25 | pci0 = &PCI0; | ||
26 | pci1 = &PCI1; | ||
27 | }; | ||
28 | |||
29 | cpus { | ||
30 | #address-cells = <1>; | ||
31 | #size-cells = <0>; | ||
32 | |||
33 | cpu@0 { | ||
34 | device_type = "cpu"; | ||
35 | compatible = "PowerPC,7447"; | ||
36 | reg = <0>; | ||
37 | clock-frequency = <996000000>; /* 996 MHz */ | ||
38 | bus-frequency = <166666667>; /* 166.6666 MHz */ | ||
39 | timebase-frequency = <41666667>; /* 166.6666/4 MHz */ | ||
40 | i-cache-line-size = <32>; | ||
41 | d-cache-line-size = <32>; | ||
42 | i-cache-size = <32768>; | ||
43 | d-cache-size = <32768>; | ||
44 | }; | ||
45 | }; | ||
46 | |||
47 | memory { | ||
48 | device_type = "memory"; | ||
49 | reg = <0x00000000 0x40000000>; /* 1GB */ | ||
50 | }; | ||
51 | |||
52 | system-controller@d8000000 { /* Marvell Discovery */ | ||
53 | #address-cells = <1>; | ||
54 | #size-cells = <1>; | ||
55 | model = "mv64460"; | ||
56 | compatible = "marvell,mv64360"; | ||
57 | clock-frequency = <166666667>; /* 166.66... MHz */ | ||
58 | reg = <0xd8000000 0x00010000>; | ||
59 | virtual-reg = <0xd8000000>; | ||
60 | ranges = <0xd4000000 0xd4000000 0x01000000 /* PCI 0 I/O Space */ | ||
61 | 0x80000000 0x80000000 0x08000000 /* PCI 0 MEM Space */ | ||
62 | 0xd0000000 0xd0000000 0x01000000 /* PCI 1 I/O Space */ | ||
63 | 0xa0000000 0xa0000000 0x08000000 /* PCI 1 MEM Space */ | ||
64 | 0xd8100000 0xd8100000 0x00010000 /* FPGA */ | ||
65 | 0xd8110000 0xd8110000 0x00010000 /* FPGA USARTs */ | ||
66 | 0xf8000000 0xf8000000 0x08000000 /* User FLASH */ | ||
67 | 0x00000000 0xd8000000 0x00010000 /* Bridge's regs */ | ||
68 | 0xd8140000 0xd8140000 0x00040000>; /* Integrated SRAM */ | ||
69 | |||
70 | mdio@2000 { | ||
71 | #address-cells = <1>; | ||
72 | #size-cells = <0>; | ||
73 | compatible = "marvell,mv64360-mdio"; | ||
74 | reg = <0x2000 4>; | ||
75 | PHY0: ethernet-phy@0 { | ||
76 | interrupts = <76>; /* GPP 12 */ | ||
77 | interrupt-parent = <&PIC>; | ||
78 | reg = <0>; | ||
79 | }; | ||
80 | PHY1: ethernet-phy@1 { | ||
81 | interrupts = <76>; /* GPP 12 */ | ||
82 | interrupt-parent = <&PIC>; | ||
83 | reg = <1>; | ||
84 | }; | ||
85 | PHY2: ethernet-phy@2 { | ||
86 | interrupts = <76>; /* GPP 12 */ | ||
87 | interrupt-parent = <&PIC>; | ||
88 | reg = <2>; | ||
89 | }; | ||
90 | }; | ||
91 | |||
92 | ethernet-group@2000 { | ||
93 | #address-cells = <1>; | ||
94 | #size-cells = <0>; | ||
95 | compatible = "marvell,mv64360-eth-group"; | ||
96 | reg = <0x2000 0x2000>; | ||
97 | ethernet@0 { | ||
98 | device_type = "network"; | ||
99 | compatible = "marvell,mv64360-eth"; | ||
100 | reg = <0>; | ||
101 | interrupts = <32>; | ||
102 | interrupt-parent = <&PIC>; | ||
103 | phy = <&PHY0>; | ||
104 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
105 | }; | ||
106 | ethernet@1 { | ||
107 | device_type = "network"; | ||
108 | compatible = "marvell,mv64360-eth"; | ||
109 | reg = <1>; | ||
110 | interrupts = <33>; | ||
111 | interrupt-parent = <&PIC>; | ||
112 | phy = <&PHY1>; | ||
113 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
114 | }; | ||
115 | ethernet@2 { | ||
116 | device_type = "network"; | ||
117 | compatible = "marvell,mv64360-eth"; | ||
118 | reg = <2>; | ||
119 | interrupts = <34>; | ||
120 | interrupt-parent = <&PIC>; | ||
121 | phy = <&PHY2>; | ||
122 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
123 | }; | ||
124 | }; | ||
125 | |||
126 | SDMA0: sdma@4000 { | ||
127 | compatible = "marvell,mv64360-sdma"; | ||
128 | reg = <0x4000 0xc18>; | ||
129 | virtual-reg = <0xd8004000>; | ||
130 | interrupt-base = <0>; | ||
131 | interrupts = <36>; | ||
132 | interrupt-parent = <&PIC>; | ||
133 | }; | ||
134 | |||
135 | SDMA1: sdma@6000 { | ||
136 | compatible = "marvell,mv64360-sdma"; | ||
137 | reg = <0x6000 0xc18>; | ||
138 | virtual-reg = <0xd8006000>; | ||
139 | interrupt-base = <0>; | ||
140 | interrupts = <38>; | ||
141 | interrupt-parent = <&PIC>; | ||
142 | }; | ||
143 | |||
144 | BRG0: brg@b200 { | ||
145 | compatible = "marvell,mv64360-brg"; | ||
146 | reg = <0xb200 0x8>; | ||
147 | clock-src = <8>; | ||
148 | clock-frequency = <133333333>; | ||
149 | current-speed = <115200>; | ||
150 | }; | ||
151 | |||
152 | BRG1: brg@b208 { | ||
153 | compatible = "marvell,mv64360-brg"; | ||
154 | reg = <0xb208 0x8>; | ||
155 | clock-src = <8>; | ||
156 | clock-frequency = <133333333>; | ||
157 | current-speed = <115200>; | ||
158 | }; | ||
159 | |||
160 | CUNIT: cunit@f200 { | ||
161 | reg = <0xf200 0x200>; | ||
162 | }; | ||
163 | |||
164 | MPSCROUTING: mpscrouting@b400 { | ||
165 | reg = <0xb400 0xc>; | ||
166 | }; | ||
167 | |||
168 | MPSCINTR: mpscintr@b800 { | ||
169 | reg = <0xb800 0x100>; | ||
170 | virtual-reg = <0xd800b800>; | ||
171 | }; | ||
172 | |||
173 | MPSC0: mpsc@8000 { | ||
174 | compatible = "marvell,mv64360-mpsc"; | ||
175 | reg = <0x8000 0x38>; | ||
176 | virtual-reg = <0xd8008000>; | ||
177 | sdma = <&SDMA0>; | ||
178 | brg = <&BRG0>; | ||
179 | cunit = <&CUNIT>; | ||
180 | mpscrouting = <&MPSCROUTING>; | ||
181 | mpscintr = <&MPSCINTR>; | ||
182 | cell-index = <0>; | ||
183 | interrupts = <40>; | ||
184 | interrupt-parent = <&PIC>; | ||
185 | }; | ||
186 | |||
187 | MPSC1: mpsc@9000 { | ||
188 | compatible = "marvell,mv64360-mpsc"; | ||
189 | reg = <0x9000 0x38>; | ||
190 | virtual-reg = <0xd8009000>; | ||
191 | sdma = <&SDMA1>; | ||
192 | brg = <&BRG1>; | ||
193 | cunit = <&CUNIT>; | ||
194 | mpscrouting = <&MPSCROUTING>; | ||
195 | mpscintr = <&MPSCINTR>; | ||
196 | cell-index = <1>; | ||
197 | interrupts = <42>; | ||
198 | interrupt-parent = <&PIC>; | ||
199 | }; | ||
200 | |||
201 | wdt@b410 { /* watchdog timer */ | ||
202 | compatible = "marvell,mv64360-wdt"; | ||
203 | reg = <0xb410 0x8>; | ||
204 | }; | ||
205 | |||
206 | i2c@c000 { | ||
207 | compatible = "marvell,mv64360-i2c"; | ||
208 | reg = <0xc000 0x20>; | ||
209 | virtual-reg = <0xd800c000>; | ||
210 | interrupts = <37>; | ||
211 | interrupt-parent = <&PIC>; | ||
212 | }; | ||
213 | |||
214 | PIC: pic { | ||
215 | #interrupt-cells = <1>; | ||
216 | #address-cells = <0>; | ||
217 | compatible = "marvell,mv64360-pic"; | ||
218 | reg = <0x0000 0x88>; | ||
219 | interrupt-controller; | ||
220 | }; | ||
221 | |||
222 | mpp@f000 { | ||
223 | compatible = "marvell,mv64360-mpp"; | ||
224 | reg = <0xf000 0x10>; | ||
225 | }; | ||
226 | |||
227 | gpp@f100 { | ||
228 | compatible = "marvell,mv64360-gpp"; | ||
229 | reg = <0xf100 0x20>; | ||
230 | }; | ||
231 | |||
232 | PCI0: pci@80000000 { | ||
233 | #address-cells = <3>; | ||
234 | #size-cells = <2>; | ||
235 | #interrupt-cells = <1>; | ||
236 | device_type = "pci"; | ||
237 | compatible = "marvell,mv64360-pci"; | ||
238 | reg = <0x0cf8 0x8>; | ||
239 | ranges = <0x01000000 0x0 0x00000000 0xd4000000 0x0 0x01000000 | ||
240 | 0x02000000 0x0 0x80000000 0x80000000 0x0 0x08000000>; | ||
241 | bus-range = <0 255>; | ||
242 | clock-frequency = <66000000>; | ||
243 | interrupt-pci-iack = <0x0c34>; | ||
244 | interrupt-parent = <&PIC>; | ||
245 | interrupt-map-mask = <0x0000 0x0 0x0 0x7>; | ||
246 | interrupt-map = < | ||
247 | /* Only one interrupt line for PMC0 slot (INTA) */ | ||
248 | 0x0000 0 0 1 &PIC 88 | ||
249 | >; | ||
250 | }; | ||
251 | |||
252 | |||
253 | PCI1: pci@a0000000 { | ||
254 | #address-cells = <3>; | ||
255 | #size-cells = <2>; | ||
256 | #interrupt-cells = <1>; | ||
257 | device_type = "pci"; | ||
258 | compatible = "marvell,mv64360-pci"; | ||
259 | reg = <0x0c78 0x8>; | ||
260 | ranges = <0x01000000 0x0 0x00000000 0xd0000000 0x0 0x01000000 | ||
261 | 0x02000000 0x0 0x80000000 0xa0000000 0x0 0x08000000>; | ||
262 | bus-range = <0 255>; | ||
263 | clock-frequency = <66000000>; | ||
264 | interrupt-pci-iack = <0x0cb4>; | ||
265 | interrupt-parent = <&PIC>; | ||
266 | interrupt-map-mask = <0xf800 0x00 0x00 0x7>; | ||
267 | interrupt-map = < | ||
268 | /* IDSEL 0x01: PMC1 ? */ | ||
269 | 0x0800 0 0 1 &PIC 88 | ||
270 | /* IDSEL 0x02: cPCI bridge */ | ||
271 | 0x1000 0 0 1 &PIC 88 | ||
272 | /* IDSEL 0x03: USB controller */ | ||
273 | 0x1800 0 0 1 &PIC 91 | ||
274 | /* IDSEL 0x04: SATA controller */ | ||
275 | 0x2000 0 0 1 &PIC 95 | ||
276 | >; | ||
277 | }; | ||
278 | |||
279 | cpu-error@70 { | ||
280 | compatible = "marvell,mv64360-cpu-error"; | ||
281 | reg = <0x0070 0x10 0x0128 0x28>; | ||
282 | interrupts = <3>; | ||
283 | interrupt-parent = <&PIC>; | ||
284 | }; | ||
285 | |||
286 | sram-ctrl@380 { | ||
287 | compatible = "marvell,mv64360-sram-ctrl"; | ||
288 | reg = <0x0380 0x80>; | ||
289 | interrupts = <13>; | ||
290 | interrupt-parent = <&PIC>; | ||
291 | }; | ||
292 | |||
293 | pci-error@1d40 { | ||
294 | compatible = "marvell,mv64360-pci-error"; | ||
295 | reg = <0x1d40 0x40 0x0c28 0x4>; | ||
296 | interrupts = <12>; | ||
297 | interrupt-parent = <&PIC>; | ||
298 | }; | ||
299 | |||
300 | pci-error@1dc0 { | ||
301 | compatible = "marvell,mv64360-pci-error"; | ||
302 | reg = <0x1dc0 0x40 0x0ca8 0x4>; | ||
303 | interrupts = <16>; | ||
304 | interrupt-parent = <&PIC>; | ||
305 | }; | ||
306 | |||
307 | mem-ctrl@1400 { | ||
308 | compatible = "marvell,mv64360-mem-ctrl"; | ||
309 | reg = <0x1400 0x60>; | ||
310 | interrupts = <17>; | ||
311 | interrupt-parent = <&PIC>; | ||
312 | }; | ||
313 | /* Devices attached to the device controller */ | ||
314 | devicebus@45c { | ||
315 | #address-cells = <2>; | ||
316 | #size-cells = <1>; | ||
317 | compatible = "marvell,mv64306-devctrl"; | ||
318 | reg = <0x45C 0x88>; | ||
319 | interrupts = <1>; | ||
320 | interrupt-parent = <&PIC>; | ||
321 | ranges = <0 0 0xd8100000 0x10000 | ||
322 | 2 0 0xd8110000 0x10000 | ||
323 | 4 0 0xf8000000 0x8000000>; | ||
324 | fpga@0,0 { | ||
325 | compatible = "sbs,fpga-c2k"; | ||
326 | reg = <0 0 0x10000>; | ||
327 | }; | ||
328 | fpga_usart@2,0 { | ||
329 | compatible = "sbs,fpga_usart-c2k"; | ||
330 | reg = <2 0 0x10000>; | ||
331 | }; | ||
332 | nor_flash@4,0 { | ||
333 | compatible = "cfi-flash"; | ||
334 | reg = <4 0 0x8000000>; /* 128MB */ | ||
335 | bank-width = <4>; | ||
336 | device-width = <1>; | ||
337 | #address-cells = <1>; | ||
338 | #size-cells = <1>; | ||
339 | partition@0 { | ||
340 | label = "boot"; | ||
341 | reg = <0x00000000 0x00080000>; | ||
342 | }; | ||
343 | partition@40000 { | ||
344 | label = "kernel"; | ||
345 | reg = <0x00080000 0x00400000>; | ||
346 | }; | ||
347 | partition@440000 { | ||
348 | label = "initrd"; | ||
349 | reg = <0x00480000 0x00B80000>; | ||
350 | }; | ||
351 | partition@1000000 { | ||
352 | label = "rootfs"; | ||
353 | reg = <0x01000000 0x06800000>; | ||
354 | }; | ||
355 | partition@7800000 { | ||
356 | label = "recovery"; | ||
357 | reg = <0x07800000 0x00800000>; | ||
358 | read-only; | ||
359 | }; | ||
360 | }; | ||
361 | }; | ||
362 | }; | ||
363 | chosen { | ||
364 | stdout-path = &MPSC0; | ||
365 | }; | ||
366 | }; | ||
diff --git a/arch/powerpc/boot/dts/fsl/t104xqds.dtsi b/arch/powerpc/boot/dts/fsl/t104xqds.dtsi index 2fd4cbe7098f..615479732252 100644 --- a/arch/powerpc/boot/dts/fsl/t104xqds.dtsi +++ b/arch/powerpc/boot/dts/fsl/t104xqds.dtsi | |||
@@ -269,7 +269,7 @@ | |||
269 | 269 | ||
270 | i2c@118000 { | 270 | i2c@118000 { |
271 | pca9547@77 { | 271 | pca9547@77 { |
272 | compatible = "philips,pca9547"; | 272 | compatible = "nxp,pca9547"; |
273 | reg = <0x77>; | 273 | reg = <0x77>; |
274 | }; | 274 | }; |
275 | rtc@68 { | 275 | rtc@68 { |
diff --git a/arch/powerpc/boot/dts/sbc8349.dts b/arch/powerpc/boot/dts/sbc8349.dts deleted file mode 100644 index fc89e00b765c..000000000000 --- a/arch/powerpc/boot/dts/sbc8349.dts +++ /dev/null | |||
@@ -1,331 +0,0 @@ | |||
1 | /* | ||
2 | * SBC8349E Device Tree Source | ||
3 | * | ||
4 | * Copyright 2007 Wind River Inc. | ||
5 | * | ||
6 | * Paul Gortmaker (see MAINTAINERS for contact information) | ||
7 | * | ||
8 | * -based largely on the Freescale MPC834x_MDS dts. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | */ | ||
15 | |||
16 | /dts-v1/; | ||
17 | |||
18 | / { | ||
19 | model = "SBC8349E"; | ||
20 | compatible = "SBC834xE"; | ||
21 | #address-cells = <1>; | ||
22 | #size-cells = <1>; | ||
23 | |||
24 | aliases { | ||
25 | ethernet0 = &enet0; | ||
26 | ethernet1 = &enet1; | ||
27 | serial0 = &serial0; | ||
28 | serial1 = &serial1; | ||
29 | pci0 = &pci0; | ||
30 | }; | ||
31 | |||
32 | cpus { | ||
33 | #address-cells = <1>; | ||
34 | #size-cells = <0>; | ||
35 | |||
36 | PowerPC,8349@0 { | ||
37 | device_type = "cpu"; | ||
38 | reg = <0x0>; | ||
39 | d-cache-line-size = <32>; | ||
40 | i-cache-line-size = <32>; | ||
41 | d-cache-size = <32768>; | ||
42 | i-cache-size = <32768>; | ||
43 | timebase-frequency = <0>; // from bootloader | ||
44 | bus-frequency = <0>; // from bootloader | ||
45 | clock-frequency = <0>; // from bootloader | ||
46 | }; | ||
47 | }; | ||
48 | |||
49 | memory { | ||
50 | device_type = "memory"; | ||
51 | reg = <0x00000000 0x10000000>; // 256MB at 0 | ||
52 | }; | ||
53 | |||
54 | soc8349@e0000000 { | ||
55 | #address-cells = <1>; | ||
56 | #size-cells = <1>; | ||
57 | device_type = "soc"; | ||
58 | ranges = <0x0 0xe0000000 0x00100000>; | ||
59 | reg = <0xe0000000 0x00000200>; | ||
60 | bus-frequency = <0>; | ||
61 | |||
62 | wdt@200 { | ||
63 | compatible = "mpc83xx_wdt"; | ||
64 | reg = <0x200 0x100>; | ||
65 | }; | ||
66 | |||
67 | i2c@3000 { | ||
68 | #address-cells = <1>; | ||
69 | #size-cells = <0>; | ||
70 | cell-index = <0>; | ||
71 | compatible = "fsl-i2c"; | ||
72 | reg = <0x3000 0x100>; | ||
73 | interrupts = <14 0x8>; | ||
74 | interrupt-parent = <&ipic>; | ||
75 | dfsrr; | ||
76 | }; | ||
77 | |||
78 | i2c@3100 { | ||
79 | #address-cells = <1>; | ||
80 | #size-cells = <0>; | ||
81 | cell-index = <1>; | ||
82 | compatible = "fsl-i2c"; | ||
83 | reg = <0x3100 0x100>; | ||
84 | interrupts = <15 0x8>; | ||
85 | interrupt-parent = <&ipic>; | ||
86 | dfsrr; | ||
87 | }; | ||
88 | |||
89 | spi@7000 { | ||
90 | cell-index = <0>; | ||
91 | compatible = "fsl,spi"; | ||
92 | reg = <0x7000 0x1000>; | ||
93 | interrupts = <16 0x8>; | ||
94 | interrupt-parent = <&ipic>; | ||
95 | mode = "cpu"; | ||
96 | }; | ||
97 | |||
98 | dma@82a8 { | ||
99 | #address-cells = <1>; | ||
100 | #size-cells = <1>; | ||
101 | compatible = "fsl,mpc8349-dma", "fsl,elo-dma"; | ||
102 | reg = <0x82a8 4>; | ||
103 | ranges = <0 0x8100 0x1a8>; | ||
104 | interrupt-parent = <&ipic>; | ||
105 | interrupts = <71 8>; | ||
106 | cell-index = <0>; | ||
107 | dma-channel@0 { | ||
108 | compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel"; | ||
109 | reg = <0 0x80>; | ||
110 | cell-index = <0>; | ||
111 | interrupt-parent = <&ipic>; | ||
112 | interrupts = <71 8>; | ||
113 | }; | ||
114 | dma-channel@80 { | ||
115 | compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel"; | ||
116 | reg = <0x80 0x80>; | ||
117 | cell-index = <1>; | ||
118 | interrupt-parent = <&ipic>; | ||
119 | interrupts = <71 8>; | ||
120 | }; | ||
121 | dma-channel@100 { | ||
122 | compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel"; | ||
123 | reg = <0x100 0x80>; | ||
124 | cell-index = <2>; | ||
125 | interrupt-parent = <&ipic>; | ||
126 | interrupts = <71 8>; | ||
127 | }; | ||
128 | dma-channel@180 { | ||
129 | compatible = "fsl,mpc8349-dma-channel", "fsl,elo-dma-channel"; | ||
130 | reg = <0x180 0x28>; | ||
131 | cell-index = <3>; | ||
132 | interrupt-parent = <&ipic>; | ||
133 | interrupts = <71 8>; | ||
134 | }; | ||
135 | }; | ||
136 | |||
137 | /* phy type (ULPI or SERIAL) are only types supported for MPH */ | ||
138 | /* port = 0 or 1 */ | ||
139 | usb@22000 { | ||
140 | compatible = "fsl-usb2-mph"; | ||
141 | reg = <0x22000 0x1000>; | ||
142 | #address-cells = <1>; | ||
143 | #size-cells = <0>; | ||
144 | interrupt-parent = <&ipic>; | ||
145 | interrupts = <39 0x8>; | ||
146 | phy_type = "ulpi"; | ||
147 | port0; | ||
148 | }; | ||
149 | |||
150 | enet0: ethernet@24000 { | ||
151 | #address-cells = <1>; | ||
152 | #size-cells = <1>; | ||
153 | cell-index = <0>; | ||
154 | device_type = "network"; | ||
155 | model = "TSEC"; | ||
156 | compatible = "gianfar"; | ||
157 | reg = <0x24000 0x1000>; | ||
158 | ranges = <0x0 0x24000 0x1000>; | ||
159 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
160 | interrupts = <32 0x8 33 0x8 34 0x8>; | ||
161 | interrupt-parent = <&ipic>; | ||
162 | tbi-handle = <&tbi0>; | ||
163 | phy-handle = <&phy0>; | ||
164 | linux,network-index = <0>; | ||
165 | |||
166 | mdio@520 { | ||
167 | #address-cells = <1>; | ||
168 | #size-cells = <0>; | ||
169 | compatible = "fsl,gianfar-mdio"; | ||
170 | reg = <0x520 0x20>; | ||
171 | |||
172 | phy0: ethernet-phy@19 { | ||
173 | interrupt-parent = <&ipic>; | ||
174 | interrupts = <20 0x8>; | ||
175 | reg = <0x19>; | ||
176 | }; | ||
177 | |||
178 | phy1: ethernet-phy@1a { | ||
179 | interrupt-parent = <&ipic>; | ||
180 | interrupts = <21 0x8>; | ||
181 | reg = <0x1a>; | ||
182 | }; | ||
183 | |||
184 | tbi0: tbi-phy@11 { | ||
185 | reg = <0x11>; | ||
186 | device_type = "tbi-phy"; | ||
187 | }; | ||
188 | }; | ||
189 | }; | ||
190 | |||
191 | enet1: ethernet@25000 { | ||
192 | #address-cells = <1>; | ||
193 | #size-cells = <1>; | ||
194 | cell-index = <1>; | ||
195 | device_type = "network"; | ||
196 | model = "TSEC"; | ||
197 | compatible = "gianfar"; | ||
198 | reg = <0x25000 0x1000>; | ||
199 | ranges = <0x0 0x25000 0x1000>; | ||
200 | local-mac-address = [ 00 00 00 00 00 00 ]; | ||
201 | interrupts = <35 0x8 36 0x8 37 0x8>; | ||
202 | interrupt-parent = <&ipic>; | ||
203 | tbi-handle = <&tbi1>; | ||
204 | phy-handle = <&phy1>; | ||
205 | linux,network-index = <1>; | ||
206 | |||
207 | mdio@520 { | ||
208 | #address-cells = <1>; | ||
209 | #size-cells = <0>; | ||
210 | compatible = "fsl,gianfar-tbi"; | ||
211 | reg = <0x520 0x20>; | ||
212 | |||
213 | tbi1: tbi-phy@11 { | ||
214 | reg = <0x11>; | ||
215 | device_type = "tbi-phy"; | ||
216 | }; | ||
217 | }; | ||
218 | }; | ||
219 | |||
220 | serial0: serial@4500 { | ||
221 | cell-index = <0>; | ||
222 | device_type = "serial"; | ||
223 | compatible = "fsl,ns16550", "ns16550"; | ||
224 | reg = <0x4500 0x100>; | ||
225 | clock-frequency = <0>; | ||
226 | interrupts = <9 0x8>; | ||
227 | interrupt-parent = <&ipic>; | ||
228 | }; | ||
229 | |||
230 | serial1: serial@4600 { | ||
231 | cell-index = <1>; | ||
232 | device_type = "serial"; | ||
233 | compatible = "fsl,ns16550", "ns16550"; | ||
234 | reg = <0x4600 0x100>; | ||
235 | clock-frequency = <0>; | ||
236 | interrupts = <10 0x8>; | ||
237 | interrupt-parent = <&ipic>; | ||
238 | }; | ||
239 | |||
240 | crypto@30000 { | ||
241 | compatible = "fsl,sec2.0"; | ||
242 | reg = <0x30000 0x10000>; | ||
243 | interrupts = <11 0x8>; | ||
244 | interrupt-parent = <&ipic>; | ||
245 | fsl,num-channels = <4>; | ||
246 | fsl,channel-fifo-len = <24>; | ||
247 | fsl,exec-units-mask = <0x7e>; | ||
248 | fsl,descriptor-types-mask = <0x01010ebf>; | ||
249 | }; | ||
250 | |||
251 | /* IPIC | ||
252 | * interrupts cell = <intr #, sense> | ||
253 | * sense values match linux IORESOURCE_IRQ_* defines: | ||
254 | * sense == 8: Level, low assertion | ||
255 | * sense == 2: Edge, high-to-low change | ||
256 | */ | ||
257 | ipic: pic@700 { | ||
258 | interrupt-controller; | ||
259 | #address-cells = <0>; | ||
260 | #interrupt-cells = <2>; | ||
261 | reg = <0x700 0x100>; | ||
262 | device_type = "ipic"; | ||
263 | }; | ||
264 | }; | ||
265 | |||
266 | localbus@e0005000 { | ||
267 | #address-cells = <2>; | ||
268 | #size-cells = <1>; | ||
269 | compatible = "fsl,mpc8349-localbus", "simple-bus"; | ||
270 | reg = <0xe0005000 0x1000>; | ||
271 | interrupts = <77 0x8>; | ||
272 | interrupt-parent = <&ipic>; | ||
273 | ranges = <0x0 0x0 0xff800000 0x00800000 /* 8MB Flash */ | ||
274 | 0x1 0x0 0xf8000000 0x00002000 /* 8KB EEPROM */ | ||
275 | 0x2 0x0 0x10000000 0x04000000 /* 64MB SDRAM */ | ||
276 | 0x3 0x0 0x10000000 0x04000000>; /* 64MB SDRAM */ | ||
277 | |||
278 | flash@0,0 { | ||
279 | #address-cells = <1>; | ||
280 | #size-cells = <1>; | ||
281 | compatible = "intel,28F640J3A", "cfi-flash"; | ||
282 | reg = <0x0 0x0 0x800000>; | ||
283 | bank-width = <2>; | ||
284 | device-width = <1>; | ||
285 | |||
286 | partition@0 { | ||
287 | label = "u-boot"; | ||
288 | reg = <0x00000000 0x00040000>; | ||
289 | read-only; | ||
290 | }; | ||
291 | |||
292 | partition@40000 { | ||
293 | label = "user"; | ||
294 | reg = <0x00040000 0x006c0000>; | ||
295 | }; | ||
296 | |||
297 | partition@700000 { | ||
298 | label = "legacy u-boot"; | ||
299 | reg = <0x00700000 0x00100000>; | ||
300 | read-only; | ||
301 | }; | ||
302 | |||
303 | }; | ||
304 | }; | ||
305 | |||
306 | pci0: pci@e0008500 { | ||
307 | interrupt-map-mask = <0xf800 0x0 0x0 0x7>; | ||
308 | interrupt-map = < | ||
309 | |||
310 | /* IDSEL 0x11 */ | ||
311 | 0x8800 0x0 0x0 0x1 &ipic 48 0x8 | ||
312 | 0x8800 0x0 0x0 0x2 &ipic 17 0x8 | ||
313 | 0x8800 0x0 0x0 0x3 &ipic 18 0x8 | ||
314 | 0x8800 0x0 0x0 0x4 &ipic 19 0x8>; | ||
315 | |||
316 | interrupt-parent = <&ipic>; | ||
317 | interrupts = <0x42 0x8>; | ||
318 | bus-range = <0 0>; | ||
319 | ranges = <0x02000000 0x0 0x90000000 0x90000000 0x0 0x10000000 | ||
320 | 0x42000000 0x0 0x80000000 0x80000000 0x0 0x10000000 | ||
321 | 0x01000000 0x0 0x00000000 0xe2000000 0x0 0x00100000>; | ||
322 | clock-frequency = <66666666>; | ||
323 | #interrupt-cells = <1>; | ||
324 | #size-cells = <2>; | ||
325 | #address-cells = <3>; | ||
326 | reg = <0xe0008500 0x100 /* internal registers */ | ||
327 | 0xe0008300 0x8>; /* config space access registers */ | ||
328 | compatible = "fsl,mpc8349-pci"; | ||
329 | device_type = "pci"; | ||
330 | }; | ||
331 | }; | ||
diff --git a/arch/powerpc/boot/mpc8xx.c b/arch/powerpc/boot/mpc8xx.c index add55a7f184f..c9bd9285c548 100644 --- a/arch/powerpc/boot/mpc8xx.c +++ b/arch/powerpc/boot/mpc8xx.c | |||
@@ -24,7 +24,7 @@ u32 mpc885_get_clock(u32 crystal) | |||
24 | { | 24 | { |
25 | u32 *immr; | 25 | u32 *immr; |
26 | u32 plprcr; | 26 | u32 plprcr; |
27 | int mfi, mfn, mfd, pdf, div; | 27 | int mfi, mfn, mfd, pdf; |
28 | u32 ret; | 28 | u32 ret; |
29 | 29 | ||
30 | immr = fsl_get_immr(); | 30 | immr = fsl_get_immr(); |
@@ -43,7 +43,6 @@ u32 mpc885_get_clock(u32 crystal) | |||
43 | } | 43 | } |
44 | 44 | ||
45 | pdf = (plprcr >> 1) & 0xf; | 45 | pdf = (plprcr >> 1) & 0xf; |
46 | div = (plprcr >> 20) & 3; | ||
47 | mfd = (plprcr >> 22) & 0x1f; | 46 | mfd = (plprcr >> 22) & 0x1f; |
48 | mfn = (plprcr >> 27) & 0x1f; | 47 | mfn = (plprcr >> 27) & 0x1f; |
49 | 48 | ||
diff --git a/arch/powerpc/boot/mpsc.c b/arch/powerpc/boot/mpsc.c deleted file mode 100644 index 425ad88cce8d..000000000000 --- a/arch/powerpc/boot/mpsc.c +++ /dev/null | |||
@@ -1,169 +0,0 @@ | |||
1 | /* | ||
2 | * MPSC/UART driver for the Marvell mv64360, mv64460, ... | ||
3 | * | ||
4 | * Author: Mark A. Greer <mgreer@mvista.com> | ||
5 | * | ||
6 | * 2007 (c) MontaVista Software, Inc. This file is licensed under | ||
7 | * the terms of the GNU General Public License version 2. This program | ||
8 | * is licensed "as is" without any warranty of any kind, whether express | ||
9 | * or implied. | ||
10 | */ | ||
11 | |||
12 | #include <stdarg.h> | ||
13 | #include <stddef.h> | ||
14 | #include "types.h" | ||
15 | #include "string.h" | ||
16 | #include "stdio.h" | ||
17 | #include "io.h" | ||
18 | #include "ops.h" | ||
19 | |||
20 | |||
21 | #define MPSC_CHR_1 0x000c | ||
22 | |||
23 | #define MPSC_CHR_2 0x0010 | ||
24 | #define MPSC_CHR_2_TA (1<<7) | ||
25 | #define MPSC_CHR_2_TCS (1<<9) | ||
26 | #define MPSC_CHR_2_RA (1<<23) | ||
27 | #define MPSC_CHR_2_CRD (1<<25) | ||
28 | #define MPSC_CHR_2_EH (1<<31) | ||
29 | |||
30 | #define MPSC_CHR_4 0x0018 | ||
31 | #define MPSC_CHR_4_Z (1<<29) | ||
32 | |||
33 | #define MPSC_CHR_5 0x001c | ||
34 | #define MPSC_CHR_5_CTL1_INTR (1<<12) | ||
35 | #define MPSC_CHR_5_CTL1_VALID (1<<15) | ||
36 | |||
37 | #define MPSC_CHR_10 0x0030 | ||
38 | |||
39 | #define MPSC_INTR_CAUSE 0x0000 | ||
40 | #define MPSC_INTR_CAUSE_RCC (1<<6) | ||
41 | #define MPSC_INTR_MASK 0x0080 | ||
42 | |||
43 | #define SDMA_SDCM 0x0008 | ||
44 | #define SDMA_SDCM_AR (1<<15) | ||
45 | #define SDMA_SDCM_AT (1<<31) | ||
46 | |||
47 | static volatile char *mpsc_base; | ||
48 | static volatile char *mpscintr_base; | ||
49 | static u32 chr1, chr2; | ||
50 | |||
51 | static int mpsc_open(void) | ||
52 | { | ||
53 | chr1 = in_le32((u32 *)(mpsc_base + MPSC_CHR_1)) & 0x00ff0000; | ||
54 | chr2 = in_le32((u32 *)(mpsc_base + MPSC_CHR_2)) & ~(MPSC_CHR_2_TA | ||
55 | | MPSC_CHR_2_TCS | MPSC_CHR_2_RA | MPSC_CHR_2_CRD | ||
56 | | MPSC_CHR_2_EH); | ||
57 | out_le32((u32 *)(mpsc_base + MPSC_CHR_4), MPSC_CHR_4_Z); | ||
58 | out_le32((u32 *)(mpsc_base + MPSC_CHR_5), | ||
59 | MPSC_CHR_5_CTL1_INTR | MPSC_CHR_5_CTL1_VALID); | ||
60 | out_le32((u32 *)(mpsc_base + MPSC_CHR_2), chr2 | MPSC_CHR_2_EH); | ||
61 | return 0; | ||
62 | } | ||
63 | |||
64 | static void mpsc_putc(unsigned char c) | ||
65 | { | ||
66 | while (in_le32((u32 *)(mpsc_base + MPSC_CHR_2)) & MPSC_CHR_2_TCS); | ||
67 | |||
68 | out_le32((u32 *)(mpsc_base + MPSC_CHR_1), chr1 | c); | ||
69 | out_le32((u32 *)(mpsc_base + MPSC_CHR_2), chr2 | MPSC_CHR_2_TCS); | ||
70 | } | ||
71 | |||
72 | static unsigned char mpsc_getc(void) | ||
73 | { | ||
74 | u32 cause = 0; | ||
75 | unsigned char c; | ||
76 | |||
77 | while (!(cause & MPSC_INTR_CAUSE_RCC)) | ||
78 | cause = in_le32((u32 *)(mpscintr_base + MPSC_INTR_CAUSE)); | ||
79 | |||
80 | c = in_8((u8 *)(mpsc_base + MPSC_CHR_10 + 2)); | ||
81 | out_8((u8 *)(mpsc_base + MPSC_CHR_10 + 2), c); | ||
82 | out_le32((u32 *)(mpscintr_base + MPSC_INTR_CAUSE), | ||
83 | cause & ~MPSC_INTR_CAUSE_RCC); | ||
84 | |||
85 | return c; | ||
86 | } | ||
87 | |||
88 | static u8 mpsc_tstc(void) | ||
89 | { | ||
90 | return (u8)((in_le32((u32 *)(mpscintr_base + MPSC_INTR_CAUSE)) | ||
91 | & MPSC_INTR_CAUSE_RCC) != 0); | ||
92 | } | ||
93 | |||
94 | static void mpsc_stop_dma(volatile char *sdma_base) | ||
95 | { | ||
96 | out_le32((u32 *)(mpsc_base + MPSC_CHR_2),MPSC_CHR_2_TA | MPSC_CHR_2_RA); | ||
97 | out_le32((u32 *)(sdma_base + SDMA_SDCM), SDMA_SDCM_AR | SDMA_SDCM_AT); | ||
98 | |||
99 | while ((in_le32((u32 *)(sdma_base + SDMA_SDCM)) | ||
100 | & (SDMA_SDCM_AR | SDMA_SDCM_AT)) != 0) | ||
101 | udelay(100); | ||
102 | } | ||
103 | |||
104 | static volatile char *mpsc_get_virtreg_of_phandle(void *devp, char *prop) | ||
105 | { | ||
106 | void *v; | ||
107 | int n; | ||
108 | |||
109 | n = getprop(devp, prop, &v, sizeof(v)); | ||
110 | if (n != sizeof(v)) | ||
111 | goto err_out; | ||
112 | |||
113 | devp = find_node_by_linuxphandle((u32)v); | ||
114 | if (devp == NULL) | ||
115 | goto err_out; | ||
116 | |||
117 | n = getprop(devp, "virtual-reg", &v, sizeof(v)); | ||
118 | if (n == sizeof(v)) | ||
119 | return v; | ||
120 | |||
121 | err_out: | ||
122 | return NULL; | ||
123 | } | ||
124 | |||
125 | int mpsc_console_init(void *devp, struct serial_console_data *scdp) | ||
126 | { | ||
127 | void *v; | ||
128 | int n, reg_set; | ||
129 | volatile char *sdma_base; | ||
130 | |||
131 | n = getprop(devp, "virtual-reg", &v, sizeof(v)); | ||
132 | if (n != sizeof(v)) | ||
133 | goto err_out; | ||
134 | mpsc_base = v; | ||
135 | |||
136 | sdma_base = mpsc_get_virtreg_of_phandle(devp, "sdma"); | ||
137 | if (sdma_base == NULL) | ||
138 | goto err_out; | ||
139 | |||
140 | mpscintr_base = mpsc_get_virtreg_of_phandle(devp, "mpscintr"); | ||
141 | if (mpscintr_base == NULL) | ||
142 | goto err_out; | ||
143 | |||
144 | n = getprop(devp, "cell-index", &v, sizeof(v)); | ||
145 | if (n != sizeof(v)) | ||
146 | goto err_out; | ||
147 | reg_set = (int)v; | ||
148 | |||
149 | mpscintr_base += (reg_set == 0) ? 0x4 : 0xc; | ||
150 | |||
151 | /* Make sure the mpsc ctlrs are shutdown */ | ||
152 | out_le32((u32 *)(mpscintr_base + MPSC_INTR_CAUSE), 0); | ||
153 | out_le32((u32 *)(mpscintr_base + MPSC_INTR_CAUSE), 0); | ||
154 | out_le32((u32 *)(mpscintr_base + MPSC_INTR_MASK), 0); | ||
155 | out_le32((u32 *)(mpscintr_base + MPSC_INTR_MASK), 0); | ||
156 | |||
157 | mpsc_stop_dma(sdma_base); | ||
158 | |||
159 | scdp->open = mpsc_open; | ||
160 | scdp->putc = mpsc_putc; | ||
161 | scdp->getc = mpsc_getc; | ||
162 | scdp->tstc = mpsc_tstc; | ||
163 | scdp->close = NULL; | ||
164 | |||
165 | return 0; | ||
166 | |||
167 | err_out: | ||
168 | return -1; | ||
169 | } | ||
diff --git a/arch/powerpc/boot/mv64x60.c b/arch/powerpc/boot/mv64x60.c deleted file mode 100644 index d9bb302b91d2..000000000000 --- a/arch/powerpc/boot/mv64x60.c +++ /dev/null | |||
@@ -1,581 +0,0 @@ | |||
1 | /* | ||
2 | * Marvell hostbridge routines | ||
3 | * | ||
4 | * Author: Mark A. Greer <source@mvista.com> | ||
5 | * | ||
6 | * 2004, 2005, 2007 (c) MontaVista Software, Inc. This file is licensed under | ||
7 | * the terms of the GNU General Public License version 2. This program | ||
8 | * is licensed "as is" without any warranty of any kind, whether express | ||
9 | * or implied. | ||
10 | */ | ||
11 | |||
12 | #include <stdarg.h> | ||
13 | #include <stddef.h> | ||
14 | #include "types.h" | ||
15 | #include "elf.h" | ||
16 | #include "page.h" | ||
17 | #include "string.h" | ||
18 | #include "stdio.h" | ||
19 | #include "io.h" | ||
20 | #include "ops.h" | ||
21 | #include "mv64x60.h" | ||
22 | |||
23 | #define PCI_DEVFN(slot,func) ((((slot) & 0x1f) << 3) | ((func) & 0x07)) | ||
24 | |||
25 | #define MV64x60_CPU2MEM_WINDOWS 4 | ||
26 | #define MV64x60_CPU2MEM_0_BASE 0x0008 | ||
27 | #define MV64x60_CPU2MEM_0_SIZE 0x0010 | ||
28 | #define MV64x60_CPU2MEM_1_BASE 0x0208 | ||
29 | #define MV64x60_CPU2MEM_1_SIZE 0x0210 | ||
30 | #define MV64x60_CPU2MEM_2_BASE 0x0018 | ||
31 | #define MV64x60_CPU2MEM_2_SIZE 0x0020 | ||
32 | #define MV64x60_CPU2MEM_3_BASE 0x0218 | ||
33 | #define MV64x60_CPU2MEM_3_SIZE 0x0220 | ||
34 | |||
35 | #define MV64x60_ENET2MEM_BAR_ENABLE 0x2290 | ||
36 | #define MV64x60_ENET2MEM_0_BASE 0x2200 | ||
37 | #define MV64x60_ENET2MEM_0_SIZE 0x2204 | ||
38 | #define MV64x60_ENET2MEM_1_BASE 0x2208 | ||
39 | #define MV64x60_ENET2MEM_1_SIZE 0x220c | ||
40 | #define MV64x60_ENET2MEM_2_BASE 0x2210 | ||
41 | #define MV64x60_ENET2MEM_2_SIZE 0x2214 | ||
42 | #define MV64x60_ENET2MEM_3_BASE 0x2218 | ||
43 | #define MV64x60_ENET2MEM_3_SIZE 0x221c | ||
44 | #define MV64x60_ENET2MEM_4_BASE 0x2220 | ||
45 | #define MV64x60_ENET2MEM_4_SIZE 0x2224 | ||
46 | #define MV64x60_ENET2MEM_5_BASE 0x2228 | ||
47 | #define MV64x60_ENET2MEM_5_SIZE 0x222c | ||
48 | #define MV64x60_ENET2MEM_ACC_PROT_0 0x2294 | ||
49 | #define MV64x60_ENET2MEM_ACC_PROT_1 0x2298 | ||
50 | #define MV64x60_ENET2MEM_ACC_PROT_2 0x229c | ||
51 | |||
52 | #define MV64x60_MPSC2MEM_BAR_ENABLE 0xf250 | ||
53 | #define MV64x60_MPSC2MEM_0_BASE 0xf200 | ||
54 | #define MV64x60_MPSC2MEM_0_SIZE 0xf204 | ||
55 | #define MV64x60_MPSC2MEM_1_BASE 0xf208 | ||
56 | #define MV64x60_MPSC2MEM_1_SIZE 0xf20c | ||
57 | #define MV64x60_MPSC2MEM_2_BASE 0xf210 | ||
58 | #define MV64x60_MPSC2MEM_2_SIZE 0xf214 | ||
59 | #define MV64x60_MPSC2MEM_3_BASE 0xf218 | ||
60 | #define MV64x60_MPSC2MEM_3_SIZE 0xf21c | ||
61 | #define MV64x60_MPSC_0_REMAP 0xf240 | ||
62 | #define MV64x60_MPSC_1_REMAP 0xf244 | ||
63 | #define MV64x60_MPSC2MEM_ACC_PROT_0 0xf254 | ||
64 | #define MV64x60_MPSC2MEM_ACC_PROT_1 0xf258 | ||
65 | #define MV64x60_MPSC2REGS_BASE 0xf25c | ||
66 | |||
67 | #define MV64x60_IDMA2MEM_BAR_ENABLE 0x0a80 | ||
68 | #define MV64x60_IDMA2MEM_0_BASE 0x0a00 | ||
69 | #define MV64x60_IDMA2MEM_0_SIZE 0x0a04 | ||
70 | #define MV64x60_IDMA2MEM_1_BASE 0x0a08 | ||
71 | #define MV64x60_IDMA2MEM_1_SIZE 0x0a0c | ||
72 | #define MV64x60_IDMA2MEM_2_BASE 0x0a10 | ||
73 | #define MV64x60_IDMA2MEM_2_SIZE 0x0a14 | ||
74 | #define MV64x60_IDMA2MEM_3_BASE 0x0a18 | ||
75 | #define MV64x60_IDMA2MEM_3_SIZE 0x0a1c | ||
76 | #define MV64x60_IDMA2MEM_4_BASE 0x0a20 | ||
77 | #define MV64x60_IDMA2MEM_4_SIZE 0x0a24 | ||
78 | #define MV64x60_IDMA2MEM_5_BASE 0x0a28 | ||
79 | #define MV64x60_IDMA2MEM_5_SIZE 0x0a2c | ||
80 | #define MV64x60_IDMA2MEM_6_BASE 0x0a30 | ||
81 | #define MV64x60_IDMA2MEM_6_SIZE 0x0a34 | ||
82 | #define MV64x60_IDMA2MEM_7_BASE 0x0a38 | ||
83 | #define MV64x60_IDMA2MEM_7_SIZE 0x0a3c | ||
84 | #define MV64x60_IDMA2MEM_ACC_PROT_0 0x0a70 | ||
85 | #define MV64x60_IDMA2MEM_ACC_PROT_1 0x0a74 | ||
86 | #define MV64x60_IDMA2MEM_ACC_PROT_2 0x0a78 | ||
87 | #define MV64x60_IDMA2MEM_ACC_PROT_3 0x0a7c | ||
88 | |||
89 | #define MV64x60_PCI_ACC_CNTL_WINDOWS 6 | ||
90 | #define MV64x60_PCI0_PCI_DECODE_CNTL 0x0d3c | ||
91 | #define MV64x60_PCI1_PCI_DECODE_CNTL 0x0dbc | ||
92 | |||
93 | #define MV64x60_PCI0_BAR_ENABLE 0x0c3c | ||
94 | #define MV64x60_PCI02MEM_0_SIZE 0x0c08 | ||
95 | #define MV64x60_PCI0_ACC_CNTL_0_BASE_LO 0x1e00 | ||
96 | #define MV64x60_PCI0_ACC_CNTL_0_BASE_HI 0x1e04 | ||
97 | #define MV64x60_PCI0_ACC_CNTL_0_SIZE 0x1e08 | ||
98 | #define MV64x60_PCI0_ACC_CNTL_1_BASE_LO 0x1e10 | ||
99 | #define MV64x60_PCI0_ACC_CNTL_1_BASE_HI 0x1e14 | ||
100 | #define MV64x60_PCI0_ACC_CNTL_1_SIZE 0x1e18 | ||
101 | #define MV64x60_PCI0_ACC_CNTL_2_BASE_LO 0x1e20 | ||
102 | #define MV64x60_PCI0_ACC_CNTL_2_BASE_HI 0x1e24 | ||
103 | #define MV64x60_PCI0_ACC_CNTL_2_SIZE 0x1e28 | ||
104 | #define MV64x60_PCI0_ACC_CNTL_3_BASE_LO 0x1e30 | ||
105 | #define MV64x60_PCI0_ACC_CNTL_3_BASE_HI 0x1e34 | ||
106 | #define MV64x60_PCI0_ACC_CNTL_3_SIZE 0x1e38 | ||
107 | #define MV64x60_PCI0_ACC_CNTL_4_BASE_LO 0x1e40 | ||
108 | #define MV64x60_PCI0_ACC_CNTL_4_BASE_HI 0x1e44 | ||
109 | #define MV64x60_PCI0_ACC_CNTL_4_SIZE 0x1e48 | ||
110 | #define MV64x60_PCI0_ACC_CNTL_5_BASE_LO 0x1e50 | ||
111 | #define MV64x60_PCI0_ACC_CNTL_5_BASE_HI 0x1e54 | ||
112 | #define MV64x60_PCI0_ACC_CNTL_5_SIZE 0x1e58 | ||
113 | |||
114 | #define MV64x60_PCI1_BAR_ENABLE 0x0cbc | ||
115 | #define MV64x60_PCI12MEM_0_SIZE 0x0c88 | ||
116 | #define MV64x60_PCI1_ACC_CNTL_0_BASE_LO 0x1e80 | ||
117 | #define MV64x60_PCI1_ACC_CNTL_0_BASE_HI 0x1e84 | ||
118 | #define MV64x60_PCI1_ACC_CNTL_0_SIZE 0x1e88 | ||
119 | #define MV64x60_PCI1_ACC_CNTL_1_BASE_LO 0x1e90 | ||
120 | #define MV64x60_PCI1_ACC_CNTL_1_BASE_HI 0x1e94 | ||
121 | #define MV64x60_PCI1_ACC_CNTL_1_SIZE 0x1e98 | ||
122 | #define MV64x60_PCI1_ACC_CNTL_2_BASE_LO 0x1ea0 | ||
123 | #define MV64x60_PCI1_ACC_CNTL_2_BASE_HI 0x1ea4 | ||
124 | #define MV64x60_PCI1_ACC_CNTL_2_SIZE 0x1ea8 | ||
125 | #define MV64x60_PCI1_ACC_CNTL_3_BASE_LO 0x1eb0 | ||
126 | #define MV64x60_PCI1_ACC_CNTL_3_BASE_HI 0x1eb4 | ||
127 | #define MV64x60_PCI1_ACC_CNTL_3_SIZE 0x1eb8 | ||
128 | #define MV64x60_PCI1_ACC_CNTL_4_BASE_LO 0x1ec0 | ||
129 | #define MV64x60_PCI1_ACC_CNTL_4_BASE_HI 0x1ec4 | ||
130 | #define MV64x60_PCI1_ACC_CNTL_4_SIZE 0x1ec8 | ||
131 | #define MV64x60_PCI1_ACC_CNTL_5_BASE_LO 0x1ed0 | ||
132 | #define MV64x60_PCI1_ACC_CNTL_5_BASE_HI 0x1ed4 | ||
133 | #define MV64x60_PCI1_ACC_CNTL_5_SIZE 0x1ed8 | ||
134 | |||
135 | #define MV64x60_CPU2PCI_SWAP_NONE 0x01000000 | ||
136 | |||
137 | #define MV64x60_CPU2PCI0_IO_BASE 0x0048 | ||
138 | #define MV64x60_CPU2PCI0_IO_SIZE 0x0050 | ||
139 | #define MV64x60_CPU2PCI0_IO_REMAP 0x00f0 | ||
140 | #define MV64x60_CPU2PCI0_MEM_0_BASE 0x0058 | ||
141 | #define MV64x60_CPU2PCI0_MEM_0_SIZE 0x0060 | ||
142 | #define MV64x60_CPU2PCI0_MEM_0_REMAP_LO 0x00f8 | ||
143 | #define MV64x60_CPU2PCI0_MEM_0_REMAP_HI 0x0320 | ||
144 | |||
145 | #define MV64x60_CPU2PCI1_IO_BASE 0x0090 | ||
146 | #define MV64x60_CPU2PCI1_IO_SIZE 0x0098 | ||
147 | #define MV64x60_CPU2PCI1_IO_REMAP 0x0108 | ||
148 | #define MV64x60_CPU2PCI1_MEM_0_BASE 0x00a0 | ||
149 | #define MV64x60_CPU2PCI1_MEM_0_SIZE 0x00a8 | ||
150 | #define MV64x60_CPU2PCI1_MEM_0_REMAP_LO 0x0110 | ||
151 | #define MV64x60_CPU2PCI1_MEM_0_REMAP_HI 0x0340 | ||
152 | |||
153 | struct mv64x60_mem_win { | ||
154 | u32 hi; | ||
155 | u32 lo; | ||
156 | u32 size; | ||
157 | }; | ||
158 | |||
159 | struct mv64x60_pci_win { | ||
160 | u32 fcn; | ||
161 | u32 hi; | ||
162 | u32 lo; | ||
163 | u32 size; | ||
164 | }; | ||
165 | |||
166 | /* PCI config access routines */ | ||
167 | struct { | ||
168 | u32 addr; | ||
169 | u32 data; | ||
170 | } static mv64x60_pci_cfgio[2] = { | ||
171 | { /* hose 0 */ | ||
172 | .addr = 0xcf8, | ||
173 | .data = 0xcfc, | ||
174 | }, | ||
175 | { /* hose 1 */ | ||
176 | .addr = 0xc78, | ||
177 | .data = 0xc7c, | ||
178 | } | ||
179 | }; | ||
180 | |||
181 | u32 mv64x60_cfg_read(u8 *bridge_base, u8 hose, u8 bus, u8 devfn, u8 offset) | ||
182 | { | ||
183 | out_le32((u32 *)(bridge_base + mv64x60_pci_cfgio[hose].addr), | ||
184 | (1 << 31) | (bus << 16) | (devfn << 8) | offset); | ||
185 | return in_le32((u32 *)(bridge_base + mv64x60_pci_cfgio[hose].data)); | ||
186 | } | ||
187 | |||
188 | void mv64x60_cfg_write(u8 *bridge_base, u8 hose, u8 bus, u8 devfn, u8 offset, | ||
189 | u32 val) | ||
190 | { | ||
191 | out_le32((u32 *)(bridge_base + mv64x60_pci_cfgio[hose].addr), | ||
192 | (1 << 31) | (bus << 16) | (devfn << 8) | offset); | ||
193 | out_le32((u32 *)(bridge_base + mv64x60_pci_cfgio[hose].data), val); | ||
194 | } | ||
195 | |||
196 | /* I/O ctlr -> system memory setup */ | ||
197 | static struct mv64x60_mem_win mv64x60_cpu2mem[MV64x60_CPU2MEM_WINDOWS] = { | ||
198 | { | ||
199 | .lo = MV64x60_CPU2MEM_0_BASE, | ||
200 | .size = MV64x60_CPU2MEM_0_SIZE, | ||
201 | }, | ||
202 | { | ||
203 | .lo = MV64x60_CPU2MEM_1_BASE, | ||
204 | .size = MV64x60_CPU2MEM_1_SIZE, | ||
205 | }, | ||
206 | { | ||
207 | .lo = MV64x60_CPU2MEM_2_BASE, | ||
208 | .size = MV64x60_CPU2MEM_2_SIZE, | ||
209 | }, | ||
210 | { | ||
211 | .lo = MV64x60_CPU2MEM_3_BASE, | ||
212 | .size = MV64x60_CPU2MEM_3_SIZE, | ||
213 | }, | ||
214 | }; | ||
215 | |||
216 | static struct mv64x60_mem_win mv64x60_enet2mem[MV64x60_CPU2MEM_WINDOWS] = { | ||
217 | { | ||
218 | .lo = MV64x60_ENET2MEM_0_BASE, | ||
219 | .size = MV64x60_ENET2MEM_0_SIZE, | ||
220 | }, | ||
221 | { | ||
222 | .lo = MV64x60_ENET2MEM_1_BASE, | ||
223 | .size = MV64x60_ENET2MEM_1_SIZE, | ||
224 | }, | ||
225 | { | ||
226 | .lo = MV64x60_ENET2MEM_2_BASE, | ||
227 | .size = MV64x60_ENET2MEM_2_SIZE, | ||
228 | }, | ||
229 | { | ||
230 | .lo = MV64x60_ENET2MEM_3_BASE, | ||
231 | .size = MV64x60_ENET2MEM_3_SIZE, | ||
232 | }, | ||
233 | }; | ||
234 | |||
235 | static struct mv64x60_mem_win mv64x60_mpsc2mem[MV64x60_CPU2MEM_WINDOWS] = { | ||
236 | { | ||
237 | .lo = MV64x60_MPSC2MEM_0_BASE, | ||
238 | .size = MV64x60_MPSC2MEM_0_SIZE, | ||
239 | }, | ||
240 | { | ||
241 | .lo = MV64x60_MPSC2MEM_1_BASE, | ||
242 | .size = MV64x60_MPSC2MEM_1_SIZE, | ||
243 | }, | ||
244 | { | ||
245 | .lo = MV64x60_MPSC2MEM_2_BASE, | ||
246 | .size = MV64x60_MPSC2MEM_2_SIZE, | ||
247 | }, | ||
248 | { | ||
249 | .lo = MV64x60_MPSC2MEM_3_BASE, | ||
250 | .size = MV64x60_MPSC2MEM_3_SIZE, | ||
251 | }, | ||
252 | }; | ||
253 | |||
254 | static struct mv64x60_mem_win mv64x60_idma2mem[MV64x60_CPU2MEM_WINDOWS] = { | ||
255 | { | ||
256 | .lo = MV64x60_IDMA2MEM_0_BASE, | ||
257 | .size = MV64x60_IDMA2MEM_0_SIZE, | ||
258 | }, | ||
259 | { | ||
260 | .lo = MV64x60_IDMA2MEM_1_BASE, | ||
261 | .size = MV64x60_IDMA2MEM_1_SIZE, | ||
262 | }, | ||
263 | { | ||
264 | .lo = MV64x60_IDMA2MEM_2_BASE, | ||
265 | .size = MV64x60_IDMA2MEM_2_SIZE, | ||
266 | }, | ||
267 | { | ||
268 | .lo = MV64x60_IDMA2MEM_3_BASE, | ||
269 | .size = MV64x60_IDMA2MEM_3_SIZE, | ||
270 | }, | ||
271 | }; | ||
272 | |||
273 | static u32 mv64x60_dram_selects[MV64x60_CPU2MEM_WINDOWS] = {0xe,0xd,0xb,0x7}; | ||
274 | |||
275 | /* | ||
276 | * ENET, MPSC, and IDMA ctlrs on the MV64x60 have separate windows that | ||
277 | * must be set up so that the respective ctlr can access system memory. | ||
278 | * Configure them to be same as cpu->memory windows. | ||
279 | */ | ||
280 | void mv64x60_config_ctlr_windows(u8 *bridge_base, u8 *bridge_pbase, | ||
281 | u8 is_coherent) | ||
282 | { | ||
283 | u32 i, base, size, enables, prot = 0, snoop_bits = 0; | ||
284 | |||
285 | /* Disable ctlr->mem windows */ | ||
286 | out_le32((u32 *)(bridge_base + MV64x60_ENET2MEM_BAR_ENABLE), 0x3f); | ||
287 | out_le32((u32 *)(bridge_base + MV64x60_MPSC2MEM_BAR_ENABLE), 0xf); | ||
288 | out_le32((u32 *)(bridge_base + MV64x60_ENET2MEM_BAR_ENABLE), 0xff); | ||
289 | |||
290 | if (is_coherent) | ||
291 | snoop_bits = 0x2 << 12; /* Writeback */ | ||
292 | |||
293 | enables = in_le32((u32 *)(bridge_base + MV64x60_CPU_BAR_ENABLE)) & 0xf; | ||
294 | |||
295 | for (i=0; i<MV64x60_CPU2MEM_WINDOWS; i++) { | ||
296 | if (enables & (1 << i)) /* Set means disabled */ | ||
297 | continue; | ||
298 | |||
299 | base = in_le32((u32 *)(bridge_base + mv64x60_cpu2mem[i].lo)) | ||
300 | << 16; | ||
301 | base |= snoop_bits | (mv64x60_dram_selects[i] << 8); | ||
302 | size = in_le32((u32 *)(bridge_base + mv64x60_cpu2mem[i].size)) | ||
303 | << 16; | ||
304 | prot |= (0x3 << (i << 1)); /* RW access */ | ||
305 | |||
306 | out_le32((u32 *)(bridge_base + mv64x60_enet2mem[i].lo), base); | ||
307 | out_le32((u32 *)(bridge_base + mv64x60_enet2mem[i].size), size); | ||
308 | out_le32((u32 *)(bridge_base + mv64x60_mpsc2mem[i].lo), base); | ||
309 | out_le32((u32 *)(bridge_base + mv64x60_mpsc2mem[i].size), size); | ||
310 | out_le32((u32 *)(bridge_base + mv64x60_idma2mem[i].lo), base); | ||
311 | out_le32((u32 *)(bridge_base + mv64x60_idma2mem[i].size), size); | ||
312 | } | ||
313 | |||
314 | out_le32((u32 *)(bridge_base + MV64x60_ENET2MEM_ACC_PROT_0), prot); | ||
315 | out_le32((u32 *)(bridge_base + MV64x60_ENET2MEM_ACC_PROT_1), prot); | ||
316 | out_le32((u32 *)(bridge_base + MV64x60_ENET2MEM_ACC_PROT_2), prot); | ||
317 | out_le32((u32 *)(bridge_base + MV64x60_MPSC2MEM_ACC_PROT_0), prot); | ||
318 | out_le32((u32 *)(bridge_base + MV64x60_MPSC2MEM_ACC_PROT_1), prot); | ||
319 | out_le32((u32 *)(bridge_base + MV64x60_IDMA2MEM_ACC_PROT_0), prot); | ||
320 | out_le32((u32 *)(bridge_base + MV64x60_IDMA2MEM_ACC_PROT_1), prot); | ||
321 | out_le32((u32 *)(bridge_base + MV64x60_IDMA2MEM_ACC_PROT_2), prot); | ||
322 | out_le32((u32 *)(bridge_base + MV64x60_IDMA2MEM_ACC_PROT_3), prot); | ||
323 | |||
324 | /* Set mpsc->bridge's reg window to the bridge's internal registers. */ | ||
325 | out_le32((u32 *)(bridge_base + MV64x60_MPSC2REGS_BASE), | ||
326 | (u32)bridge_pbase); | ||
327 | |||
328 | out_le32((u32 *)(bridge_base + MV64x60_ENET2MEM_BAR_ENABLE), enables); | ||
329 | out_le32((u32 *)(bridge_base + MV64x60_MPSC2MEM_BAR_ENABLE), enables); | ||
330 | out_le32((u32 *)(bridge_base + MV64x60_IDMA2MEM_BAR_ENABLE), enables); | ||
331 | } | ||
332 | |||
333 | /* PCI MEM -> system memory, et. al. setup */ | ||
334 | static struct mv64x60_pci_win mv64x60_pci2mem[2] = { | ||
335 | { /* hose 0 */ | ||
336 | .fcn = 0, | ||
337 | .hi = 0x14, | ||
338 | .lo = 0x10, | ||
339 | .size = MV64x60_PCI02MEM_0_SIZE, | ||
340 | }, | ||
341 | { /* hose 1 */ | ||
342 | .fcn = 0, | ||
343 | .hi = 0x94, | ||
344 | .lo = 0x90, | ||
345 | .size = MV64x60_PCI12MEM_0_SIZE, | ||
346 | }, | ||
347 | }; | ||
348 | |||
349 | static struct | ||
350 | mv64x60_mem_win mv64x60_pci_acc[2][MV64x60_PCI_ACC_CNTL_WINDOWS] = { | ||
351 | { /* hose 0 */ | ||
352 | { | ||
353 | .hi = MV64x60_PCI0_ACC_CNTL_0_BASE_HI, | ||
354 | .lo = MV64x60_PCI0_ACC_CNTL_0_BASE_LO, | ||
355 | .size = MV64x60_PCI0_ACC_CNTL_0_SIZE, | ||
356 | }, | ||
357 | { | ||
358 | .hi = MV64x60_PCI0_ACC_CNTL_1_BASE_HI, | ||
359 | .lo = MV64x60_PCI0_ACC_CNTL_1_BASE_LO, | ||
360 | .size = MV64x60_PCI0_ACC_CNTL_1_SIZE, | ||
361 | }, | ||
362 | { | ||
363 | .hi = MV64x60_PCI0_ACC_CNTL_2_BASE_HI, | ||
364 | .lo = MV64x60_PCI0_ACC_CNTL_2_BASE_LO, | ||
365 | .size = MV64x60_PCI0_ACC_CNTL_2_SIZE, | ||
366 | }, | ||
367 | { | ||
368 | .hi = MV64x60_PCI0_ACC_CNTL_3_BASE_HI, | ||
369 | .lo = MV64x60_PCI0_ACC_CNTL_3_BASE_LO, | ||
370 | .size = MV64x60_PCI0_ACC_CNTL_3_SIZE, | ||
371 | }, | ||
372 | }, | ||
373 | { /* hose 1 */ | ||
374 | { | ||
375 | .hi = MV64x60_PCI1_ACC_CNTL_0_BASE_HI, | ||
376 | .lo = MV64x60_PCI1_ACC_CNTL_0_BASE_LO, | ||
377 | .size = MV64x60_PCI1_ACC_CNTL_0_SIZE, | ||
378 | }, | ||
379 | { | ||
380 | .hi = MV64x60_PCI1_ACC_CNTL_1_BASE_HI, | ||
381 | .lo = MV64x60_PCI1_ACC_CNTL_1_BASE_LO, | ||
382 | .size = MV64x60_PCI1_ACC_CNTL_1_SIZE, | ||
383 | }, | ||
384 | { | ||
385 | .hi = MV64x60_PCI1_ACC_CNTL_2_BASE_HI, | ||
386 | .lo = MV64x60_PCI1_ACC_CNTL_2_BASE_LO, | ||
387 | .size = MV64x60_PCI1_ACC_CNTL_2_SIZE, | ||
388 | }, | ||
389 | { | ||
390 | .hi = MV64x60_PCI1_ACC_CNTL_3_BASE_HI, | ||
391 | .lo = MV64x60_PCI1_ACC_CNTL_3_BASE_LO, | ||
392 | .size = MV64x60_PCI1_ACC_CNTL_3_SIZE, | ||
393 | }, | ||
394 | }, | ||
395 | }; | ||
396 | |||
397 | static struct mv64x60_mem_win mv64x60_pci2reg[2] = { | ||
398 | { | ||
399 | .hi = 0x24, | ||
400 | .lo = 0x20, | ||
401 | .size = 0, | ||
402 | }, | ||
403 | { | ||
404 | .hi = 0xa4, | ||
405 | .lo = 0xa0, | ||
406 | .size = 0, | ||
407 | }, | ||
408 | }; | ||
409 | |||
410 | /* Only need to use 1 window (per hose) to get access to all of system memory */ | ||
411 | void mv64x60_config_pci_windows(u8 *bridge_base, u8 *bridge_pbase, u8 hose, | ||
412 | u8 bus, u32 mem_size, u32 acc_bits) | ||
413 | { | ||
414 | u32 i, offset, bar_enable, enables; | ||
415 | |||
416 | /* Disable all windows but PCI MEM -> Bridge's regs window */ | ||
417 | enables = ~(1 << 9); | ||
418 | bar_enable = hose ? MV64x60_PCI1_BAR_ENABLE : MV64x60_PCI0_BAR_ENABLE; | ||
419 | out_le32((u32 *)(bridge_base + bar_enable), enables); | ||
420 | |||
421 | for (i=0; i<MV64x60_PCI_ACC_CNTL_WINDOWS; i++) | ||
422 | out_le32((u32 *)(bridge_base + mv64x60_pci_acc[hose][i].lo), 0); | ||
423 | |||
424 | /* If mem_size is 0, leave windows disabled */ | ||
425 | if (mem_size == 0) | ||
426 | return; | ||
427 | |||
428 | /* Cause automatic updates of PCI remap regs */ | ||
429 | offset = hose ? | ||
430 | MV64x60_PCI1_PCI_DECODE_CNTL : MV64x60_PCI0_PCI_DECODE_CNTL; | ||
431 | i = in_le32((u32 *)(bridge_base + offset)); | ||
432 | out_le32((u32 *)(bridge_base + offset), i & ~0x1); | ||
433 | |||
434 | mem_size = (mem_size - 1) & 0xfffff000; | ||
435 | |||
436 | /* Map PCI MEM addr 0 -> System Mem addr 0 */ | ||
437 | mv64x60_cfg_write(bridge_base, hose, bus, | ||
438 | PCI_DEVFN(0, mv64x60_pci2mem[hose].fcn), | ||
439 | mv64x60_pci2mem[hose].hi, 0); | ||
440 | mv64x60_cfg_write(bridge_base, hose, bus, | ||
441 | PCI_DEVFN(0, mv64x60_pci2mem[hose].fcn), | ||
442 | mv64x60_pci2mem[hose].lo, 0); | ||
443 | out_le32((u32 *)(bridge_base + mv64x60_pci2mem[hose].size),mem_size); | ||
444 | |||
445 | acc_bits |= MV64x60_PCI_ACC_CNTL_ENABLE; | ||
446 | out_le32((u32 *)(bridge_base + mv64x60_pci_acc[hose][0].hi), 0); | ||
447 | out_le32((u32 *)(bridge_base + mv64x60_pci_acc[hose][0].lo), acc_bits); | ||
448 | out_le32((u32 *)(bridge_base + mv64x60_pci_acc[hose][0].size),mem_size); | ||
449 | |||
450 | /* Set PCI MEM->bridge's reg window to where they are in CPU mem map */ | ||
451 | i = (u32)bridge_base; | ||
452 | i &= 0xffff0000; | ||
453 | i |= (0x2 << 1); | ||
454 | mv64x60_cfg_write(bridge_base, hose, bus, PCI_DEVFN(0,0), | ||
455 | mv64x60_pci2reg[hose].hi, 0); | ||
456 | mv64x60_cfg_write(bridge_base, hose, bus, PCI_DEVFN(0,0), | ||
457 | mv64x60_pci2reg[hose].lo, i); | ||
458 | |||
459 | enables &= ~0x1; /* Enable PCI MEM -> System Mem window 0 */ | ||
460 | out_le32((u32 *)(bridge_base + bar_enable), enables); | ||
461 | } | ||
462 | |||
463 | /* CPU -> PCI I/O & MEM setup */ | ||
464 | struct mv64x60_cpu2pci_win mv64x60_cpu2pci_io[2] = { | ||
465 | { /* hose 0 */ | ||
466 | .lo = MV64x60_CPU2PCI0_IO_BASE, | ||
467 | .size = MV64x60_CPU2PCI0_IO_SIZE, | ||
468 | .remap_hi = 0, | ||
469 | .remap_lo = MV64x60_CPU2PCI0_IO_REMAP, | ||
470 | }, | ||
471 | { /* hose 1 */ | ||
472 | .lo = MV64x60_CPU2PCI1_IO_BASE, | ||
473 | .size = MV64x60_CPU2PCI1_IO_SIZE, | ||
474 | .remap_hi = 0, | ||
475 | .remap_lo = MV64x60_CPU2PCI1_IO_REMAP, | ||
476 | }, | ||
477 | }; | ||
478 | |||
479 | struct mv64x60_cpu2pci_win mv64x60_cpu2pci_mem[2] = { | ||
480 | { /* hose 0 */ | ||
481 | .lo = MV64x60_CPU2PCI0_MEM_0_BASE, | ||
482 | .size = MV64x60_CPU2PCI0_MEM_0_SIZE, | ||
483 | .remap_hi = MV64x60_CPU2PCI0_MEM_0_REMAP_HI, | ||
484 | .remap_lo = MV64x60_CPU2PCI0_MEM_0_REMAP_LO, | ||
485 | }, | ||
486 | { /* hose 1 */ | ||
487 | .lo = MV64x60_CPU2PCI1_MEM_0_BASE, | ||
488 | .size = MV64x60_CPU2PCI1_MEM_0_SIZE, | ||
489 | .remap_hi = MV64x60_CPU2PCI1_MEM_0_REMAP_HI, | ||
490 | .remap_lo = MV64x60_CPU2PCI1_MEM_0_REMAP_LO, | ||
491 | }, | ||
492 | }; | ||
493 | |||
494 | /* Only need to set up 1 window to pci mem space */ | ||
495 | void mv64x60_config_cpu2pci_window(u8 *bridge_base, u8 hose, u32 pci_base_hi, | ||
496 | u32 pci_base_lo, u32 cpu_base, u32 size, | ||
497 | struct mv64x60_cpu2pci_win *offset_tbl) | ||
498 | { | ||
499 | cpu_base >>= 16; | ||
500 | cpu_base |= MV64x60_CPU2PCI_SWAP_NONE; | ||
501 | out_le32((u32 *)(bridge_base + offset_tbl[hose].lo), cpu_base); | ||
502 | |||
503 | if (offset_tbl[hose].remap_hi != 0) | ||
504 | out_le32((u32 *)(bridge_base + offset_tbl[hose].remap_hi), | ||
505 | pci_base_hi); | ||
506 | out_le32((u32 *)(bridge_base + offset_tbl[hose].remap_lo), | ||
507 | pci_base_lo >> 16); | ||
508 | |||
509 | size = (size - 1) >> 16; | ||
510 | out_le32((u32 *)(bridge_base + offset_tbl[hose].size), size); | ||
511 | } | ||
512 | |||
513 | /* Read mem ctlr to get the amount of mem in system */ | ||
514 | u32 mv64x60_get_mem_size(u8 *bridge_base) | ||
515 | { | ||
516 | u32 enables, i, v; | ||
517 | u32 mem = 0; | ||
518 | |||
519 | enables = in_le32((u32 *)(bridge_base + MV64x60_CPU_BAR_ENABLE)) & 0xf; | ||
520 | |||
521 | for (i=0; i<MV64x60_CPU2MEM_WINDOWS; i++) | ||
522 | if (!(enables & (1<<i))) { | ||
523 | v = in_le32((u32*)(bridge_base | ||
524 | + mv64x60_cpu2mem[i].size)); | ||
525 | v = ((v & 0xffff) + 1) << 16; | ||
526 | mem += v; | ||
527 | } | ||
528 | |||
529 | return mem; | ||
530 | } | ||
531 | |||
532 | /* Get physical address of bridge's registers */ | ||
533 | u8 *mv64x60_get_bridge_pbase(void) | ||
534 | { | ||
535 | u32 v[2]; | ||
536 | void *devp; | ||
537 | |||
538 | devp = find_node_by_compatible(NULL, "marvell,mv64360"); | ||
539 | if (devp == NULL) | ||
540 | goto err_out; | ||
541 | if (getprop(devp, "reg", v, sizeof(v)) != sizeof(v)) | ||
542 | goto err_out; | ||
543 | |||
544 | return (u8 *)v[0]; | ||
545 | |||
546 | err_out: | ||
547 | return 0; | ||
548 | } | ||
549 | |||
550 | /* Get virtual address of bridge's registers */ | ||
551 | u8 *mv64x60_get_bridge_base(void) | ||
552 | { | ||
553 | u32 v; | ||
554 | void *devp; | ||
555 | |||
556 | devp = find_node_by_compatible(NULL, "marvell,mv64360"); | ||
557 | if (devp == NULL) | ||
558 | goto err_out; | ||
559 | if (getprop(devp, "virtual-reg", &v, sizeof(v)) != sizeof(v)) | ||
560 | goto err_out; | ||
561 | |||
562 | return (u8 *)v; | ||
563 | |||
564 | err_out: | ||
565 | return 0; | ||
566 | } | ||
567 | |||
568 | u8 mv64x60_is_coherent(void) | ||
569 | { | ||
570 | u32 v; | ||
571 | void *devp; | ||
572 | |||
573 | devp = finddevice("/"); | ||
574 | if (devp == NULL) | ||
575 | return 1; /* Assume coherency on */ | ||
576 | |||
577 | if (getprop(devp, "coherency-off", &v, sizeof(v)) < 0) | ||
578 | return 1; /* Coherency on */ | ||
579 | else | ||
580 | return 0; | ||
581 | } | ||
diff --git a/arch/powerpc/boot/mv64x60.h b/arch/powerpc/boot/mv64x60.h deleted file mode 100644 index b827105e6e54..000000000000 --- a/arch/powerpc/boot/mv64x60.h +++ /dev/null | |||
@@ -1,70 +0,0 @@ | |||
1 | /* | ||
2 | * Author: Mark A. Greer <source@mvista.com> | ||
3 | * | ||
4 | * 2007 (c) MontaVista Software, Inc. This file is licensed under | ||
5 | * the terms of the GNU General Public License version 2. This program | ||
6 | * is licensed "as is" without any warranty of any kind, whether express | ||
7 | * or implied. | ||
8 | */ | ||
9 | |||
10 | #ifndef _PPC_BOOT_MV64x60_H_ | ||
11 | #define _PPC_BOOT_MV64x60_H_ | ||
12 | |||
13 | #define MV64x60_CPU_BAR_ENABLE 0x0278 | ||
14 | |||
15 | #define MV64x60_PCI_ACC_CNTL_ENABLE (1<<0) | ||
16 | #define MV64x60_PCI_ACC_CNTL_REQ64 (1<<1) | ||
17 | #define MV64x60_PCI_ACC_CNTL_SNOOP_NONE 0x00000000 | ||
18 | #define MV64x60_PCI_ACC_CNTL_SNOOP_WT 0x00000004 | ||
19 | #define MV64x60_PCI_ACC_CNTL_SNOOP_WB 0x00000008 | ||
20 | #define MV64x60_PCI_ACC_CNTL_SNOOP_MASK 0x0000000c | ||
21 | #define MV64x60_PCI_ACC_CNTL_ACCPROT (1<<4) | ||
22 | #define MV64x60_PCI_ACC_CNTL_WRPROT (1<<5) | ||
23 | #define MV64x60_PCI_ACC_CNTL_SWAP_BYTE 0x00000000 | ||
24 | #define MV64x60_PCI_ACC_CNTL_SWAP_NONE 0x00000040 | ||
25 | #define MV64x60_PCI_ACC_CNTL_SWAP_BYTE_WORD 0x00000080 | ||
26 | #define MV64x60_PCI_ACC_CNTL_SWAP_WORD 0x000000c0 | ||
27 | #define MV64x60_PCI_ACC_CNTL_SWAP_MASK 0x000000c0 | ||
28 | #define MV64x60_PCI_ACC_CNTL_MBURST_32_BYTES 0x00000000 | ||
29 | #define MV64x60_PCI_ACC_CNTL_MBURST_64_BYTES 0x00000100 | ||
30 | #define MV64x60_PCI_ACC_CNTL_MBURST_128_BYTES 0x00000200 | ||
31 | #define MV64x60_PCI_ACC_CNTL_MBURST_MASK 0x00000300 | ||
32 | #define MV64x60_PCI_ACC_CNTL_RDSIZE_32_BYTES 0x00000000 | ||
33 | #define MV64x60_PCI_ACC_CNTL_RDSIZE_64_BYTES 0x00000400 | ||
34 | #define MV64x60_PCI_ACC_CNTL_RDSIZE_128_BYTES 0x00000800 | ||
35 | #define MV64x60_PCI_ACC_CNTL_RDSIZE_256_BYTES 0x00000c00 | ||
36 | #define MV64x60_PCI_ACC_CNTL_RDSIZE_MASK 0x00000c00 | ||
37 | |||
38 | struct mv64x60_cpu2pci_win { | ||
39 | u32 lo; | ||
40 | u32 size; | ||
41 | u32 remap_hi; | ||
42 | u32 remap_lo; | ||
43 | }; | ||
44 | |||
45 | extern struct mv64x60_cpu2pci_win mv64x60_cpu2pci_io[2]; | ||
46 | extern struct mv64x60_cpu2pci_win mv64x60_cpu2pci_mem[2]; | ||
47 | |||
48 | u32 mv64x60_cfg_read(u8 *bridge_base, u8 hose, u8 bus, u8 devfn, | ||
49 | u8 offset); | ||
50 | void mv64x60_cfg_write(u8 *bridge_base, u8 hose, u8 bus, u8 devfn, | ||
51 | u8 offset, u32 val); | ||
52 | |||
53 | void mv64x60_config_ctlr_windows(u8 *bridge_base, u8 *bridge_pbase, | ||
54 | u8 is_coherent); | ||
55 | void mv64x60_config_pci_windows(u8 *bridge_base, u8 *bridge_pbase, u8 hose, | ||
56 | u8 bus, u32 mem_size, u32 acc_bits); | ||
57 | void mv64x60_config_cpu2pci_window(u8 *bridge_base, u8 hose, u32 pci_base_hi, | ||
58 | u32 pci_base_lo, u32 cpu_base, u32 size, | ||
59 | struct mv64x60_cpu2pci_win *offset_tbl); | ||
60 | u32 mv64x60_get_mem_size(u8 *bridge_base); | ||
61 | u8 *mv64x60_get_bridge_pbase(void); | ||
62 | u8 *mv64x60_get_bridge_base(void); | ||
63 | u8 mv64x60_is_coherent(void); | ||
64 | |||
65 | int mv64x60_i2c_open(void); | ||
66 | int mv64x60_i2c_read(u32 devaddr, u8 *buf, u32 offset, u32 offset_size, | ||
67 | u32 count); | ||
68 | void mv64x60_i2c_close(void); | ||
69 | |||
70 | #endif /* _PPC_BOOT_MV64x60_H_ */ | ||
diff --git a/arch/powerpc/boot/mv64x60_i2c.c b/arch/powerpc/boot/mv64x60_i2c.c deleted file mode 100644 index 52a3212b6638..000000000000 --- a/arch/powerpc/boot/mv64x60_i2c.c +++ /dev/null | |||
@@ -1,204 +0,0 @@ | |||
1 | /* | ||
2 | * Bootloader version of the i2c driver for the MV64x60. | ||
3 | * | ||
4 | * Author: Dale Farnsworth <dfarnsworth@mvista.com> | ||
5 | * Maintained by: Mark A. Greer <mgreer@mvista.com> | ||
6 | * | ||
7 | * 2003, 2007 (c) MontaVista, Software, Inc. This file is licensed under | ||
8 | * the terms of the GNU General Public License version 2. This program is | ||
9 | * licensed "as is" without any warranty of any kind, whether express or | ||
10 | * implied. | ||
11 | */ | ||
12 | |||
13 | #include <stdarg.h> | ||
14 | #include <stddef.h> | ||
15 | #include "types.h" | ||
16 | #include "elf.h" | ||
17 | #include "page.h" | ||
18 | #include "string.h" | ||
19 | #include "stdio.h" | ||
20 | #include "io.h" | ||
21 | #include "ops.h" | ||
22 | #include "mv64x60.h" | ||
23 | |||
24 | /* Register defines */ | ||
25 | #define MV64x60_I2C_REG_SLAVE_ADDR 0x00 | ||
26 | #define MV64x60_I2C_REG_DATA 0x04 | ||
27 | #define MV64x60_I2C_REG_CONTROL 0x08 | ||
28 | #define MV64x60_I2C_REG_STATUS 0x0c | ||
29 | #define MV64x60_I2C_REG_BAUD 0x0c | ||
30 | #define MV64x60_I2C_REG_EXT_SLAVE_ADDR 0x10 | ||
31 | #define MV64x60_I2C_REG_SOFT_RESET 0x1c | ||
32 | |||
33 | #define MV64x60_I2C_CONTROL_ACK 0x04 | ||
34 | #define MV64x60_I2C_CONTROL_IFLG 0x08 | ||
35 | #define MV64x60_I2C_CONTROL_STOP 0x10 | ||
36 | #define MV64x60_I2C_CONTROL_START 0x20 | ||
37 | #define MV64x60_I2C_CONTROL_TWSIEN 0x40 | ||
38 | #define MV64x60_I2C_CONTROL_INTEN 0x80 | ||
39 | |||
40 | #define MV64x60_I2C_STATUS_BUS_ERR 0x00 | ||
41 | #define MV64x60_I2C_STATUS_MAST_START 0x08 | ||
42 | #define MV64x60_I2C_STATUS_MAST_REPEAT_START 0x10 | ||
43 | #define MV64x60_I2C_STATUS_MAST_WR_ADDR_ACK 0x18 | ||
44 | #define MV64x60_I2C_STATUS_MAST_WR_ADDR_NO_ACK 0x20 | ||
45 | #define MV64x60_I2C_STATUS_MAST_WR_ACK 0x28 | ||
46 | #define MV64x60_I2C_STATUS_MAST_WR_NO_ACK 0x30 | ||
47 | #define MV64x60_I2C_STATUS_MAST_LOST_ARB 0x38 | ||
48 | #define MV64x60_I2C_STATUS_MAST_RD_ADDR_ACK 0x40 | ||
49 | #define MV64x60_I2C_STATUS_MAST_RD_ADDR_NO_ACK 0x48 | ||
50 | #define MV64x60_I2C_STATUS_MAST_RD_DATA_ACK 0x50 | ||
51 | #define MV64x60_I2C_STATUS_MAST_RD_DATA_NO_ACK 0x58 | ||
52 | #define MV64x60_I2C_STATUS_MAST_WR_ADDR_2_ACK 0xd0 | ||
53 | #define MV64x60_I2C_STATUS_MAST_WR_ADDR_2_NO_ACK 0xd8 | ||
54 | #define MV64x60_I2C_STATUS_MAST_RD_ADDR_2_ACK 0xe0 | ||
55 | #define MV64x60_I2C_STATUS_MAST_RD_ADDR_2_NO_ACK 0xe8 | ||
56 | #define MV64x60_I2C_STATUS_NO_STATUS 0xf8 | ||
57 | |||
58 | static u8 *ctlr_base; | ||
59 | |||
60 | static int mv64x60_i2c_wait_for_status(int wanted) | ||
61 | { | ||
62 | int i; | ||
63 | int status; | ||
64 | |||
65 | for (i=0; i<1000; i++) { | ||
66 | udelay(10); | ||
67 | status = in_le32((u32 *)(ctlr_base + MV64x60_I2C_REG_STATUS)) | ||
68 | & 0xff; | ||
69 | if (status == wanted) | ||
70 | return status; | ||
71 | } | ||
72 | return -status; | ||
73 | } | ||
74 | |||
75 | static int mv64x60_i2c_control(int control, int status) | ||
76 | { | ||
77 | out_le32((u32 *)(ctlr_base + MV64x60_I2C_REG_CONTROL), control & 0xff); | ||
78 | return mv64x60_i2c_wait_for_status(status); | ||
79 | } | ||
80 | |||
81 | static int mv64x60_i2c_read_byte(int control, int status) | ||
82 | { | ||
83 | out_le32((u32 *)(ctlr_base + MV64x60_I2C_REG_CONTROL), control & 0xff); | ||
84 | if (mv64x60_i2c_wait_for_status(status) < 0) | ||
85 | return -1; | ||
86 | return in_le32((u32 *)(ctlr_base + MV64x60_I2C_REG_DATA)) & 0xff; | ||
87 | } | ||
88 | |||
89 | static int mv64x60_i2c_write_byte(int data, int control, int status) | ||
90 | { | ||
91 | out_le32((u32 *)(ctlr_base + MV64x60_I2C_REG_DATA), data & 0xff); | ||
92 | out_le32((u32 *)(ctlr_base + MV64x60_I2C_REG_CONTROL), control & 0xff); | ||
93 | return mv64x60_i2c_wait_for_status(status); | ||
94 | } | ||
95 | |||
96 | int mv64x60_i2c_read(u32 devaddr, u8 *buf, u32 offset, u32 offset_size, | ||
97 | u32 count) | ||
98 | { | ||
99 | int i; | ||
100 | int data; | ||
101 | int control; | ||
102 | int status; | ||
103 | |||
104 | if (ctlr_base == NULL) | ||
105 | return -1; | ||
106 | |||
107 | /* send reset */ | ||
108 | out_le32((u32 *)(ctlr_base + MV64x60_I2C_REG_SOFT_RESET), 0); | ||
109 | out_le32((u32 *)(ctlr_base + MV64x60_I2C_REG_SLAVE_ADDR), 0); | ||
110 | out_le32((u32 *)(ctlr_base + MV64x60_I2C_REG_EXT_SLAVE_ADDR), 0); | ||
111 | out_le32((u32 *)(ctlr_base + MV64x60_I2C_REG_BAUD), (4 << 3) | 0x4); | ||
112 | |||
113 | if (mv64x60_i2c_control(MV64x60_I2C_CONTROL_TWSIEN, | ||
114 | MV64x60_I2C_STATUS_NO_STATUS) < 0) | ||
115 | return -1; | ||
116 | |||
117 | /* send start */ | ||
118 | control = MV64x60_I2C_CONTROL_START | MV64x60_I2C_CONTROL_TWSIEN; | ||
119 | status = MV64x60_I2C_STATUS_MAST_START; | ||
120 | if (mv64x60_i2c_control(control, status) < 0) | ||
121 | return -1; | ||
122 | |||
123 | /* select device for writing */ | ||
124 | data = devaddr & ~0x1; | ||
125 | control = MV64x60_I2C_CONTROL_TWSIEN; | ||
126 | status = MV64x60_I2C_STATUS_MAST_WR_ADDR_ACK; | ||
127 | if (mv64x60_i2c_write_byte(data, control, status) < 0) | ||
128 | return -1; | ||
129 | |||
130 | /* send offset of data */ | ||
131 | control = MV64x60_I2C_CONTROL_TWSIEN; | ||
132 | status = MV64x60_I2C_STATUS_MAST_WR_ACK; | ||
133 | if (offset_size > 1) { | ||
134 | if (mv64x60_i2c_write_byte(offset >> 8, control, status) < 0) | ||
135 | return -1; | ||
136 | } | ||
137 | if (mv64x60_i2c_write_byte(offset, control, status) < 0) | ||
138 | return -1; | ||
139 | |||
140 | /* resend start */ | ||
141 | control = MV64x60_I2C_CONTROL_START | MV64x60_I2C_CONTROL_TWSIEN; | ||
142 | status = MV64x60_I2C_STATUS_MAST_REPEAT_START; | ||
143 | if (mv64x60_i2c_control(control, status) < 0) | ||
144 | return -1; | ||
145 | |||
146 | /* select device for reading */ | ||
147 | data = devaddr | 0x1; | ||
148 | control = MV64x60_I2C_CONTROL_TWSIEN; | ||
149 | status = MV64x60_I2C_STATUS_MAST_RD_ADDR_ACK; | ||
150 | if (mv64x60_i2c_write_byte(data, control, status) < 0) | ||
151 | return -1; | ||
152 | |||
153 | /* read all but last byte of data */ | ||
154 | control = MV64x60_I2C_CONTROL_ACK | MV64x60_I2C_CONTROL_TWSIEN; | ||
155 | status = MV64x60_I2C_STATUS_MAST_RD_DATA_ACK; | ||
156 | |||
157 | for (i=1; i<count; i++) { | ||
158 | data = mv64x60_i2c_read_byte(control, status); | ||
159 | if (data < 0) { | ||
160 | printf("errors on iteration %d\n", i); | ||
161 | return -1; | ||
162 | } | ||
163 | *buf++ = data; | ||
164 | } | ||
165 | |||
166 | /* read last byte of data */ | ||
167 | control = MV64x60_I2C_CONTROL_TWSIEN; | ||
168 | status = MV64x60_I2C_STATUS_MAST_RD_DATA_NO_ACK; | ||
169 | data = mv64x60_i2c_read_byte(control, status); | ||
170 | if (data < 0) | ||
171 | return -1; | ||
172 | *buf++ = data; | ||
173 | |||
174 | /* send stop */ | ||
175 | control = MV64x60_I2C_CONTROL_STOP | MV64x60_I2C_CONTROL_TWSIEN; | ||
176 | status = MV64x60_I2C_STATUS_NO_STATUS; | ||
177 | if (mv64x60_i2c_control(control, status) < 0) | ||
178 | return -1; | ||
179 | |||
180 | return count; | ||
181 | } | ||
182 | |||
183 | int mv64x60_i2c_open(void) | ||
184 | { | ||
185 | u32 v; | ||
186 | void *devp; | ||
187 | |||
188 | devp = find_node_by_compatible(NULL, "marvell,mv64360-i2c"); | ||
189 | if (devp == NULL) | ||
190 | goto err_out; | ||
191 | if (getprop(devp, "virtual-reg", &v, sizeof(v)) != sizeof(v)) | ||
192 | goto err_out; | ||
193 | |||
194 | ctlr_base = (u8 *)v; | ||
195 | return 0; | ||
196 | |||
197 | err_out: | ||
198 | return -1; | ||
199 | } | ||
200 | |||
201 | void mv64x60_i2c_close(void) | ||
202 | { | ||
203 | ctlr_base = NULL; | ||
204 | } | ||
diff --git a/arch/powerpc/boot/ops.h b/arch/powerpc/boot/ops.h index fad1862f4b2d..cd043726ed88 100644 --- a/arch/powerpc/boot/ops.h +++ b/arch/powerpc/boot/ops.h | |||
@@ -86,7 +86,6 @@ void start(void); | |||
86 | void fdt_init(void *blob); | 86 | void fdt_init(void *blob); |
87 | int serial_console_init(void); | 87 | int serial_console_init(void); |
88 | int ns16550_console_init(void *devp, struct serial_console_data *scdp); | 88 | int ns16550_console_init(void *devp, struct serial_console_data *scdp); |
89 | int mpsc_console_init(void *devp, struct serial_console_data *scdp); | ||
90 | int cpm_console_init(void *devp, struct serial_console_data *scdp); | 89 | int cpm_console_init(void *devp, struct serial_console_data *scdp); |
91 | int mpc5200_psc_console_init(void *devp, struct serial_console_data *scdp); | 90 | int mpc5200_psc_console_init(void *devp, struct serial_console_data *scdp); |
92 | int uartlite_console_init(void *devp, struct serial_console_data *scdp); | 91 | int uartlite_console_init(void *devp, struct serial_console_data *scdp); |
diff --git a/arch/powerpc/boot/serial.c b/arch/powerpc/boot/serial.c index 88955095ec07..48e3743faedf 100644 --- a/arch/powerpc/boot/serial.c +++ b/arch/powerpc/boot/serial.c | |||
@@ -120,10 +120,6 @@ int serial_console_init(void) | |||
120 | if (dt_is_compatible(devp, "ns16550") || | 120 | if (dt_is_compatible(devp, "ns16550") || |
121 | dt_is_compatible(devp, "pnpPNP,501")) | 121 | dt_is_compatible(devp, "pnpPNP,501")) |
122 | rc = ns16550_console_init(devp, &serial_cd); | 122 | rc = ns16550_console_init(devp, &serial_cd); |
123 | #ifdef CONFIG_EMBEDDED6xx | ||
124 | else if (dt_is_compatible(devp, "marvell,mv64360-mpsc")) | ||
125 | rc = mpsc_console_init(devp, &serial_cd); | ||
126 | #endif | ||
127 | #ifdef CONFIG_CPM | 123 | #ifdef CONFIG_CPM |
128 | else if (dt_is_compatible(devp, "fsl,cpm1-scc-uart") || | 124 | else if (dt_is_compatible(devp, "fsl,cpm1-scc-uart") || |
129 | dt_is_compatible(devp, "fsl,cpm1-smc-uart") || | 125 | dt_is_compatible(devp, "fsl,cpm1-smc-uart") || |
diff --git a/arch/powerpc/configs/83xx/sbc834x_defconfig b/arch/powerpc/configs/83xx/sbc834x_defconfig deleted file mode 100644 index 7d74699334da..000000000000 --- a/arch/powerpc/configs/83xx/sbc834x_defconfig +++ /dev/null | |||
@@ -1,74 +0,0 @@ | |||
1 | CONFIG_SYSVIPC=y | ||
2 | CONFIG_LOG_BUF_SHIFT=14 | ||
3 | CONFIG_BLK_DEV_INITRD=y | ||
4 | CONFIG_EXPERT=y | ||
5 | # CONFIG_KALLSYMS is not set | ||
6 | CONFIG_SLAB=y | ||
7 | CONFIG_MODULES=y | ||
8 | CONFIG_MODULE_UNLOAD=y | ||
9 | # CONFIG_BLK_DEV_BSG is not set | ||
10 | # CONFIG_PPC_CHRP is not set | ||
11 | # CONFIG_PPC_PMAC is not set | ||
12 | CONFIG_PPC_83xx=y | ||
13 | CONFIG_SBC834x=y | ||
14 | CONFIG_GEN_RTC=y | ||
15 | CONFIG_PCI=y | ||
16 | CONFIG_NET=y | ||
17 | CONFIG_PACKET=y | ||
18 | CONFIG_UNIX=y | ||
19 | CONFIG_XFRM_USER=m | ||
20 | CONFIG_INET=y | ||
21 | CONFIG_IP_MULTICAST=y | ||
22 | CONFIG_IP_PNP=y | ||
23 | CONFIG_IP_PNP_DHCP=y | ||
24 | CONFIG_IP_PNP_BOOTP=y | ||
25 | CONFIG_SYN_COOKIES=y | ||
26 | # CONFIG_IPV6 is not set | ||
27 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | ||
28 | # CONFIG_FW_LOADER is not set | ||
29 | CONFIG_MTD=y | ||
30 | CONFIG_MTD_CMDLINE_PARTS=y | ||
31 | CONFIG_MTD_BLOCK=y | ||
32 | CONFIG_MTD_CFI=y | ||
33 | CONFIG_MTD_CFI_INTELEXT=y | ||
34 | CONFIG_MTD_PHYSMAP_OF=y | ||
35 | CONFIG_BLK_DEV_LOOP=y | ||
36 | CONFIG_BLK_DEV_RAM=y | ||
37 | CONFIG_BLK_DEV_RAM_SIZE=32768 | ||
38 | CONFIG_SCSI=y | ||
39 | # CONFIG_SCSI_PROC_FS is not set | ||
40 | CONFIG_BLK_DEV_SD=y | ||
41 | # CONFIG_SCSI_LOWLEVEL is not set | ||
42 | CONFIG_NETDEVICES=y | ||
43 | CONFIG_GIANFAR=y | ||
44 | CONFIG_BROADCOM_PHY=y | ||
45 | # CONFIG_INPUT_KEYBOARD is not set | ||
46 | # CONFIG_INPUT_MOUSE is not set | ||
47 | # CONFIG_SERIO is not set | ||
48 | # CONFIG_VT is not set | ||
49 | CONFIG_SERIAL_8250=y | ||
50 | CONFIG_SERIAL_8250_CONSOLE=y | ||
51 | # CONFIG_SERIAL_8250_PCI is not set | ||
52 | CONFIG_SERIAL_8250_NR_UARTS=2 | ||
53 | CONFIG_SERIAL_8250_RUNTIME_UARTS=2 | ||
54 | # CONFIG_HW_RANDOM is not set | ||
55 | CONFIG_I2C=y | ||
56 | CONFIG_I2C_CHARDEV=y | ||
57 | CONFIG_I2C_MPC=y | ||
58 | CONFIG_WATCHDOG=y | ||
59 | # CONFIG_USB_HID is not set | ||
60 | CONFIG_USB=y | ||
61 | CONFIG_USB_MON=y | ||
62 | CONFIG_USB_EHCI_HCD=y | ||
63 | CONFIG_USB_EHCI_FSL=y | ||
64 | CONFIG_USB_STORAGE=y | ||
65 | CONFIG_EXT2_FS=y | ||
66 | CONFIG_EXT4_FS=y | ||
67 | CONFIG_PROC_KCORE=y | ||
68 | CONFIG_TMPFS=y | ||
69 | CONFIG_NFS_FS=y | ||
70 | CONFIG_NFS_V4=y | ||
71 | CONFIG_ROOT_NFS=y | ||
72 | CONFIG_CRYPTO_ECB=m | ||
73 | CONFIG_CRYPTO_PCBC=m | ||
74 | # CONFIG_CRYPTO_HW is not set | ||
diff --git a/arch/powerpc/configs/c2k_defconfig b/arch/powerpc/configs/c2k_defconfig deleted file mode 100644 index 6c1196b0f81e..000000000000 --- a/arch/powerpc/configs/c2k_defconfig +++ /dev/null | |||
@@ -1,389 +0,0 @@ | |||
1 | CONFIG_SYSVIPC=y | ||
2 | CONFIG_POSIX_MQUEUE=y | ||
3 | CONFIG_AUDIT=y | ||
4 | CONFIG_BSD_PROCESS_ACCT=y | ||
5 | CONFIG_BLK_DEV_INITRD=y | ||
6 | CONFIG_PROFILING=y | ||
7 | CONFIG_OPROFILE=m | ||
8 | CONFIG_KPROBES=y | ||
9 | CONFIG_MODULES=y | ||
10 | CONFIG_MODULE_UNLOAD=y | ||
11 | CONFIG_MODVERSIONS=y | ||
12 | CONFIG_PARTITION_ADVANCED=y | ||
13 | CONFIG_OSF_PARTITION=y | ||
14 | CONFIG_MAC_PARTITION=y | ||
15 | CONFIG_BSD_DISKLABEL=y | ||
16 | CONFIG_MINIX_SUBPARTITION=y | ||
17 | CONFIG_SOLARIS_X86_PARTITION=y | ||
18 | CONFIG_UNIXWARE_DISKLABEL=y | ||
19 | CONFIG_SGI_PARTITION=y | ||
20 | CONFIG_SUN_PARTITION=y | ||
21 | # CONFIG_PPC_CHRP is not set | ||
22 | # CONFIG_PPC_PMAC is not set | ||
23 | CONFIG_EMBEDDED6xx=y | ||
24 | CONFIG_PPC_C2K=y | ||
25 | CONFIG_CPU_FREQ=y | ||
26 | CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y | ||
27 | CONFIG_CPU_FREQ_GOV_PERFORMANCE=y | ||
28 | CONFIG_CPU_FREQ_GOV_POWERSAVE=m | ||
29 | CONFIG_CPU_FREQ_GOV_ONDEMAND=m | ||
30 | CONFIG_GEN_RTC=y | ||
31 | CONFIG_HIGHMEM=y | ||
32 | CONFIG_PREEMPT_VOLUNTARY=y | ||
33 | CONFIG_BINFMT_MISC=y | ||
34 | CONFIG_PM=y | ||
35 | CONFIG_PCI_MSI=y | ||
36 | CONFIG_HOTPLUG_PCI=y | ||
37 | CONFIG_HOTPLUG_PCI_SHPC=m | ||
38 | CONFIG_NET=y | ||
39 | CONFIG_PACKET=y | ||
40 | CONFIG_UNIX=y | ||
41 | CONFIG_XFRM_USER=y | ||
42 | CONFIG_NET_KEY=m | ||
43 | CONFIG_INET=y | ||
44 | CONFIG_IP_MULTICAST=y | ||
45 | CONFIG_IP_ADVANCED_ROUTER=y | ||
46 | CONFIG_IP_MULTIPLE_TABLES=y | ||
47 | CONFIG_IP_ROUTE_MULTIPATH=y | ||
48 | CONFIG_IP_ROUTE_VERBOSE=y | ||
49 | CONFIG_IP_PNP=y | ||
50 | CONFIG_IP_PNP_DHCP=y | ||
51 | CONFIG_NET_IPIP=m | ||
52 | CONFIG_IP_MROUTE=y | ||
53 | CONFIG_IP_PIMSM_V1=y | ||
54 | CONFIG_IP_PIMSM_V2=y | ||
55 | CONFIG_SYN_COOKIES=y | ||
56 | CONFIG_INET_AH=m | ||
57 | CONFIG_INET_ESP=m | ||
58 | CONFIG_INET_IPCOMP=m | ||
59 | CONFIG_INET6_AH=m | ||
60 | CONFIG_INET6_ESP=m | ||
61 | CONFIG_INET6_IPCOMP=m | ||
62 | CONFIG_IPV6_TUNNEL=m | ||
63 | CONFIG_NETFILTER=y | ||
64 | # CONFIG_NETFILTER_XT_MATCH_SCTP is not set | ||
65 | CONFIG_IP_NF_IPTABLES=m | ||
66 | CONFIG_IP_NF_MATCH_ECN=m | ||
67 | CONFIG_IP_NF_MATCH_TTL=m | ||
68 | CONFIG_IP_NF_FILTER=m | ||
69 | CONFIG_IP_NF_TARGET_REJECT=m | ||
70 | CONFIG_IP_NF_MANGLE=m | ||
71 | CONFIG_IP_NF_TARGET_ECN=m | ||
72 | CONFIG_IP_NF_RAW=m | ||
73 | CONFIG_IP_NF_ARPTABLES=m | ||
74 | CONFIG_IP_NF_ARPFILTER=m | ||
75 | CONFIG_IP_NF_ARP_MANGLE=m | ||
76 | CONFIG_IP6_NF_IPTABLES=m | ||
77 | CONFIG_IP6_NF_MATCH_EUI64=m | ||
78 | CONFIG_IP6_NF_MATCH_FRAG=m | ||
79 | CONFIG_IP6_NF_MATCH_OPTS=m | ||
80 | CONFIG_IP6_NF_MATCH_HL=m | ||
81 | CONFIG_IP6_NF_MATCH_IPV6HEADER=m | ||
82 | CONFIG_IP6_NF_MATCH_RT=m | ||
83 | CONFIG_IP6_NF_FILTER=m | ||
84 | CONFIG_IP6_NF_MANGLE=m | ||
85 | CONFIG_IP6_NF_RAW=m | ||
86 | CONFIG_BRIDGE_NF_EBTABLES=m | ||
87 | CONFIG_BRIDGE_EBT_BROUTE=m | ||
88 | CONFIG_BRIDGE_EBT_T_FILTER=m | ||
89 | CONFIG_BRIDGE_EBT_T_NAT=m | ||
90 | CONFIG_BRIDGE_EBT_802_3=m | ||
91 | CONFIG_BRIDGE_EBT_AMONG=m | ||
92 | CONFIG_BRIDGE_EBT_ARP=m | ||
93 | CONFIG_BRIDGE_EBT_IP=m | ||
94 | CONFIG_BRIDGE_EBT_LIMIT=m | ||
95 | CONFIG_BRIDGE_EBT_MARK=m | ||
96 | CONFIG_BRIDGE_EBT_PKTTYPE=m | ||
97 | CONFIG_BRIDGE_EBT_STP=m | ||
98 | CONFIG_BRIDGE_EBT_VLAN=m | ||
99 | CONFIG_BRIDGE_EBT_ARPREPLY=m | ||
100 | CONFIG_BRIDGE_EBT_DNAT=m | ||
101 | CONFIG_BRIDGE_EBT_MARK_T=m | ||
102 | CONFIG_BRIDGE_EBT_REDIRECT=m | ||
103 | CONFIG_BRIDGE_EBT_SNAT=m | ||
104 | CONFIG_BRIDGE_EBT_LOG=m | ||
105 | CONFIG_IP_SCTP=m | ||
106 | CONFIG_ATM=m | ||
107 | CONFIG_ATM_CLIP=m | ||
108 | CONFIG_ATM_LANE=m | ||
109 | CONFIG_ATM_BR2684=m | ||
110 | CONFIG_BRIDGE=m | ||
111 | CONFIG_VLAN_8021Q=m | ||
112 | CONFIG_NET_SCHED=y | ||
113 | CONFIG_NET_SCH_CBQ=m | ||
114 | CONFIG_NET_SCH_HTB=m | ||
115 | CONFIG_NET_SCH_HFSC=m | ||
116 | CONFIG_NET_SCH_ATM=m | ||
117 | CONFIG_NET_SCH_PRIO=m | ||
118 | CONFIG_NET_SCH_RED=m | ||
119 | CONFIG_NET_SCH_SFQ=m | ||
120 | CONFIG_NET_SCH_TEQL=m | ||
121 | CONFIG_NET_SCH_TBF=m | ||
122 | CONFIG_NET_SCH_GRED=m | ||
123 | CONFIG_NET_SCH_DSMARK=m | ||
124 | CONFIG_NET_SCH_NETEM=m | ||
125 | CONFIG_NET_CLS_TCINDEX=m | ||
126 | CONFIG_NET_CLS_ROUTE4=m | ||
127 | CONFIG_NET_CLS_FW=m | ||
128 | CONFIG_NET_CLS_U32=m | ||
129 | CONFIG_CLS_U32_PERF=y | ||
130 | CONFIG_NET_CLS_RSVP=m | ||
131 | CONFIG_NET_CLS_RSVP6=m | ||
132 | CONFIG_NET_CLS_IND=y | ||
133 | CONFIG_BT=m | ||
134 | CONFIG_BT_RFCOMM=m | ||
135 | CONFIG_BT_RFCOMM_TTY=y | ||
136 | CONFIG_BT_BNEP=m | ||
137 | CONFIG_BT_BNEP_MC_FILTER=y | ||
138 | CONFIG_BT_BNEP_PROTO_FILTER=y | ||
139 | CONFIG_BT_HIDP=m | ||
140 | CONFIG_BT_HCIUART=m | ||
141 | CONFIG_BT_HCIUART_H4=y | ||
142 | CONFIG_BT_HCIUART_BCSP=y | ||
143 | CONFIG_BT_HCIBCM203X=m | ||
144 | CONFIG_BT_HCIBFUSB=m | ||
145 | CONFIG_BT_HCIVHCI=m | ||
146 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | ||
147 | CONFIG_MTD=y | ||
148 | CONFIG_MTD_BLOCK=y | ||
149 | CONFIG_MTD_CFI=y | ||
150 | CONFIG_MTD_CFI_AMDSTD=y | ||
151 | CONFIG_MTD_COMPLEX_MAPPINGS=y | ||
152 | CONFIG_MTD_PHYSMAP_OF=y | ||
153 | CONFIG_BLK_DEV_LOOP=m | ||
154 | CONFIG_BLK_DEV_CRYPTOLOOP=m | ||
155 | CONFIG_BLK_DEV_NBD=m | ||
156 | CONFIG_BLK_DEV_RAM=y | ||
157 | CONFIG_BLK_DEV_RAM_SIZE=16384 | ||
158 | CONFIG_SCSI=m | ||
159 | CONFIG_BLK_DEV_SD=m | ||
160 | CONFIG_CHR_DEV_ST=m | ||
161 | CONFIG_CHR_DEV_OSST=m | ||
162 | CONFIG_BLK_DEV_SR=m | ||
163 | CONFIG_BLK_DEV_SR_VENDOR=y | ||
164 | CONFIG_CHR_DEV_SG=m | ||
165 | CONFIG_SCSI_CONSTANTS=y | ||
166 | CONFIG_SCSI_LOGGING=y | ||
167 | CONFIG_SCSI_ISCSI_ATTRS=m | ||
168 | CONFIG_BLK_DEV_3W_XXXX_RAID=m | ||
169 | CONFIG_SCSI_3W_9XXX=m | ||
170 | CONFIG_SCSI_ACARD=m | ||
171 | CONFIG_SCSI_AACRAID=m | ||
172 | CONFIG_SCSI_AIC7XXX=m | ||
173 | CONFIG_AIC7XXX_CMDS_PER_DEVICE=4 | ||
174 | CONFIG_AIC7XXX_RESET_DELAY_MS=15000 | ||
175 | # CONFIG_AIC7XXX_DEBUG_ENABLE is not set | ||
176 | # CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set | ||
177 | CONFIG_SCSI_AIC79XX=m | ||
178 | CONFIG_AIC79XX_CMDS_PER_DEVICE=4 | ||
179 | CONFIG_AIC79XX_RESET_DELAY_MS=15000 | ||
180 | # CONFIG_AIC79XX_DEBUG_ENABLE is not set | ||
181 | # CONFIG_AIC79XX_REG_PRETTY_PRINT is not set | ||
182 | CONFIG_SCSI_ARCMSR=m | ||
183 | CONFIG_MEGARAID_NEWGEN=y | ||
184 | CONFIG_MEGARAID_MM=m | ||
185 | CONFIG_MEGARAID_MAILBOX=m | ||
186 | CONFIG_MEGARAID_SAS=m | ||
187 | CONFIG_SCSI_GDTH=m | ||
188 | CONFIG_SCSI_IPS=m | ||
189 | CONFIG_SCSI_INITIO=m | ||
190 | CONFIG_SCSI_SYM53C8XX_2=m | ||
191 | CONFIG_SCSI_QLOGIC_1280=m | ||
192 | CONFIG_NETDEVICES=y | ||
193 | CONFIG_BONDING=m | ||
194 | CONFIG_DUMMY=m | ||
195 | CONFIG_NETCONSOLE=m | ||
196 | CONFIG_TUN=m | ||
197 | # CONFIG_ATM_DRIVERS is not set | ||
198 | CONFIG_MV643XX_ETH=y | ||
199 | CONFIG_VITESSE_PHY=y | ||
200 | CONFIG_INPUT_EVDEV=y | ||
201 | # CONFIG_INPUT_KEYBOARD is not set | ||
202 | # CONFIG_INPUT_MOUSE is not set | ||
203 | CONFIG_INPUT_MISC=y | ||
204 | CONFIG_INPUT_UINPUT=m | ||
205 | # CONFIG_SERIO is not set | ||
206 | # CONFIG_LEGACY_PTYS is not set | ||
207 | CONFIG_SERIAL_NONSTANDARD=y | ||
208 | CONFIG_SERIAL_MPSC=y | ||
209 | CONFIG_SERIAL_MPSC_CONSOLE=y | ||
210 | CONFIG_NVRAM=m | ||
211 | CONFIG_RAW_DRIVER=y | ||
212 | CONFIG_MAX_RAW_DEVS=8192 | ||
213 | CONFIG_I2C=m | ||
214 | CONFIG_I2C_CHARDEV=m | ||
215 | CONFIG_I2C_MV64XXX=m | ||
216 | CONFIG_HWMON=m | ||
217 | CONFIG_SENSORS_ADM1021=m | ||
218 | CONFIG_SENSORS_ADM1025=m | ||
219 | CONFIG_SENSORS_ADM1026=m | ||
220 | CONFIG_SENSORS_ADM1031=m | ||
221 | CONFIG_SENSORS_DS1621=m | ||
222 | CONFIG_SENSORS_GL518SM=m | ||
223 | CONFIG_SENSORS_MAX1619=m | ||
224 | CONFIG_SENSORS_LM75=m | ||
225 | CONFIG_SENSORS_LM77=m | ||
226 | CONFIG_SENSORS_LM78=m | ||
227 | CONFIG_SENSORS_LM80=m | ||
228 | CONFIG_SENSORS_LM83=m | ||
229 | CONFIG_SENSORS_LM85=m | ||
230 | CONFIG_SENSORS_LM87=m | ||
231 | CONFIG_SENSORS_LM90=m | ||
232 | CONFIG_SENSORS_PCF8591=m | ||
233 | CONFIG_SENSORS_VIA686A=m | ||
234 | CONFIG_SENSORS_W83781D=m | ||
235 | CONFIG_SENSORS_W83L785TS=m | ||
236 | CONFIG_WATCHDOG=y | ||
237 | CONFIG_SOFT_WATCHDOG=m | ||
238 | CONFIG_PCIPCWATCHDOG=m | ||
239 | CONFIG_WDTPCI=m | ||
240 | CONFIG_USBPCWATCHDOG=m | ||
241 | # CONFIG_VGA_CONSOLE is not set | ||
242 | CONFIG_USB=m | ||
243 | CONFIG_USB_MON=m | ||
244 | CONFIG_USB_EHCI_HCD=m | ||
245 | CONFIG_USB_EHCI_ROOT_HUB_TT=y | ||
246 | CONFIG_USB_OHCI_HCD=m | ||
247 | CONFIG_USB_OHCI_HCD_PPC_OF_BE=y | ||
248 | CONFIG_USB_UHCI_HCD=m | ||
249 | CONFIG_USB_ACM=m | ||
250 | CONFIG_USB_PRINTER=m | ||
251 | CONFIG_USB_STORAGE=m | ||
252 | CONFIG_USB_STORAGE_DATAFAB=m | ||
253 | CONFIG_USB_STORAGE_FREECOM=m | ||
254 | CONFIG_USB_STORAGE_ISD200=m | ||
255 | CONFIG_USB_STORAGE_SDDR09=m | ||
256 | CONFIG_USB_STORAGE_SDDR55=m | ||
257 | CONFIG_USB_STORAGE_JUMPSHOT=m | ||
258 | CONFIG_USB_MDC800=m | ||
259 | CONFIG_USB_MICROTEK=m | ||
260 | CONFIG_USB_SERIAL=m | ||
261 | CONFIG_USB_SERIAL_GENERIC=y | ||
262 | CONFIG_USB_SERIAL_BELKIN=m | ||
263 | CONFIG_USB_SERIAL_WHITEHEAT=m | ||
264 | CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m | ||
265 | CONFIG_USB_SERIAL_EMPEG=m | ||
266 | CONFIG_USB_SERIAL_FTDI_SIO=m | ||
267 | CONFIG_USB_SERIAL_VISOR=m | ||
268 | CONFIG_USB_SERIAL_IPAQ=m | ||
269 | CONFIG_USB_SERIAL_IR=m | ||
270 | CONFIG_USB_SERIAL_EDGEPORT=m | ||
271 | CONFIG_USB_SERIAL_EDGEPORT_TI=m | ||
272 | CONFIG_USB_SERIAL_KEYSPAN_PDA=m | ||
273 | CONFIG_USB_SERIAL_KEYSPAN=m | ||
274 | CONFIG_USB_SERIAL_KLSI=m | ||
275 | CONFIG_USB_SERIAL_KOBIL_SCT=m | ||
276 | CONFIG_USB_SERIAL_MCT_U232=m | ||
277 | CONFIG_USB_SERIAL_PL2303=m | ||
278 | CONFIG_USB_SERIAL_SAFE=m | ||
279 | CONFIG_USB_SERIAL_SAFE_PADDED=y | ||
280 | CONFIG_USB_SERIAL_CYBERJACK=m | ||
281 | CONFIG_USB_SERIAL_XIRCOM=m | ||
282 | CONFIG_USB_SERIAL_OMNINET=m | ||
283 | CONFIG_USB_EMI62=m | ||
284 | CONFIG_USB_RIO500=m | ||
285 | CONFIG_USB_LEGOTOWER=m | ||
286 | CONFIG_USB_LCD=m | ||
287 | CONFIG_USB_LED=m | ||
288 | CONFIG_USB_TEST=m | ||
289 | CONFIG_USB_ATM=m | ||
290 | CONFIG_USB_SPEEDTOUCH=m | ||
291 | CONFIG_INFINIBAND=m | ||
292 | CONFIG_INFINIBAND_USER_MAD=m | ||
293 | CONFIG_INFINIBAND_USER_ACCESS=m | ||
294 | CONFIG_INFINIBAND_MTHCA=m | ||
295 | CONFIG_INFINIBAND_IPOIB=m | ||
296 | CONFIG_INFINIBAND_IPOIB_CM=y | ||
297 | CONFIG_INFINIBAND_SRP=m | ||
298 | CONFIG_DMADEVICES=y | ||
299 | CONFIG_EXT4_FS=m | ||
300 | CONFIG_EXT4_FS_POSIX_ACL=y | ||
301 | CONFIG_EXT4_FS_SECURITY=y | ||
302 | CONFIG_QUOTA=y | ||
303 | CONFIG_QFMT_V2=y | ||
304 | CONFIG_AUTOFS4_FS=m | ||
305 | CONFIG_UDF_FS=m | ||
306 | CONFIG_MSDOS_FS=m | ||
307 | CONFIG_VFAT_FS=m | ||
308 | CONFIG_FAT_DEFAULT_IOCHARSET="ascii" | ||
309 | CONFIG_PROC_KCORE=y | ||
310 | CONFIG_TMPFS=y | ||
311 | CONFIG_HFS_FS=m | ||
312 | CONFIG_HFSPLUS_FS=m | ||
313 | CONFIG_JFFS2_FS=y | ||
314 | CONFIG_CRAMFS=m | ||
315 | CONFIG_VXFS_FS=m | ||
316 | CONFIG_NFS_FS=y | ||
317 | CONFIG_NFS_V3_ACL=y | ||
318 | CONFIG_NFS_V4=y | ||
319 | CONFIG_ROOT_NFS=y | ||
320 | CONFIG_CIFS=m | ||
321 | CONFIG_CIFS_XATTR=y | ||
322 | CONFIG_CIFS_POSIX=y | ||
323 | CONFIG_NLS=y | ||
324 | CONFIG_NLS_DEFAULT="utf8" | ||
325 | CONFIG_NLS_CODEPAGE_437=y | ||
326 | CONFIG_NLS_CODEPAGE_737=m | ||
327 | CONFIG_NLS_CODEPAGE_775=m | ||
328 | CONFIG_NLS_CODEPAGE_850=m | ||
329 | CONFIG_NLS_CODEPAGE_852=m | ||
330 | CONFIG_NLS_CODEPAGE_855=m | ||
331 | CONFIG_NLS_CODEPAGE_857=m | ||
332 | CONFIG_NLS_CODEPAGE_860=m | ||
333 | CONFIG_NLS_CODEPAGE_861=m | ||
334 | CONFIG_NLS_CODEPAGE_862=m | ||
335 | CONFIG_NLS_CODEPAGE_863=m | ||
336 | CONFIG_NLS_CODEPAGE_864=m | ||
337 | CONFIG_NLS_CODEPAGE_865=m | ||
338 | CONFIG_NLS_CODEPAGE_866=m | ||
339 | CONFIG_NLS_CODEPAGE_869=m | ||
340 | CONFIG_NLS_CODEPAGE_936=m | ||
341 | CONFIG_NLS_CODEPAGE_950=m | ||
342 | CONFIG_NLS_CODEPAGE_932=m | ||
343 | CONFIG_NLS_CODEPAGE_949=m | ||
344 | CONFIG_NLS_CODEPAGE_874=m | ||
345 | CONFIG_NLS_ISO8859_8=m | ||
346 | CONFIG_NLS_CODEPAGE_1250=m | ||
347 | CONFIG_NLS_CODEPAGE_1251=m | ||
348 | CONFIG_NLS_ASCII=y | ||
349 | CONFIG_NLS_ISO8859_1=m | ||
350 | CONFIG_NLS_ISO8859_2=m | ||
351 | CONFIG_NLS_ISO8859_3=m | ||
352 | CONFIG_NLS_ISO8859_4=m | ||
353 | CONFIG_NLS_ISO8859_5=m | ||
354 | CONFIG_NLS_ISO8859_6=m | ||
355 | CONFIG_NLS_ISO8859_7=m | ||
356 | CONFIG_NLS_ISO8859_9=m | ||
357 | CONFIG_NLS_ISO8859_13=m | ||
358 | CONFIG_NLS_ISO8859_14=m | ||
359 | CONFIG_NLS_ISO8859_15=m | ||
360 | CONFIG_NLS_KOI8_R=m | ||
361 | CONFIG_NLS_KOI8_U=m | ||
362 | CONFIG_CRC_CCITT=m | ||
363 | CONFIG_CRC_T10DIF=m | ||
364 | CONFIG_DEBUG_INFO=y | ||
365 | CONFIG_MAGIC_SYSRQ=y | ||
366 | CONFIG_DEBUG_KERNEL=y | ||
367 | CONFIG_DEBUG_STACK_USAGE=y | ||
368 | CONFIG_DEBUG_HIGHMEM=y | ||
369 | CONFIG_DEBUG_STACKOVERFLOW=y | ||
370 | CONFIG_DETECT_HUNG_TASK=y | ||
371 | CONFIG_DEBUG_SPINLOCK=y | ||
372 | CONFIG_BOOTX_TEXT=y | ||
373 | CONFIG_PPC_EARLY_DEBUG=y | ||
374 | CONFIG_SECURITY=y | ||
375 | CONFIG_SECURITY_NETWORK=y | ||
376 | CONFIG_SECURITY_SELINUX=y | ||
377 | CONFIG_SECURITY_SELINUX_BOOTPARAM=y | ||
378 | CONFIG_SECURITY_SELINUX_DISABLE=y | ||
379 | CONFIG_CRYPTO_HMAC=y | ||
380 | CONFIG_CRYPTO_MICHAEL_MIC=m | ||
381 | CONFIG_CRYPTO_SHA1=y | ||
382 | CONFIG_CRYPTO_SHA512=m | ||
383 | CONFIG_CRYPTO_WP512=m | ||
384 | CONFIG_CRYPTO_BLOWFISH=m | ||
385 | CONFIG_CRYPTO_CAST6=m | ||
386 | CONFIG_CRYPTO_KHAZAD=m | ||
387 | CONFIG_CRYPTO_SERPENT=m | ||
388 | CONFIG_CRYPTO_TEA=m | ||
389 | CONFIG_CRYPTO_TWOFISH=m | ||
diff --git a/arch/powerpc/configs/powernv_defconfig b/arch/powerpc/configs/powernv_defconfig index 9e92aa6a52ba..6ab34e60495f 100644 --- a/arch/powerpc/configs/powernv_defconfig +++ b/arch/powerpc/configs/powernv_defconfig | |||
@@ -38,7 +38,9 @@ CONFIG_MODULE_UNLOAD=y | |||
38 | CONFIG_MODVERSIONS=y | 38 | CONFIG_MODVERSIONS=y |
39 | CONFIG_MODULE_SRCVERSION_ALL=y | 39 | CONFIG_MODULE_SRCVERSION_ALL=y |
40 | CONFIG_PARTITION_ADVANCED=y | 40 | CONFIG_PARTITION_ADVANCED=y |
41 | CONFIG_SCOM_DEBUGFS=y | ||
41 | CONFIG_OPAL_PRD=y | 42 | CONFIG_OPAL_PRD=y |
43 | CONFIG_PPC_MEMTRACE=y | ||
42 | # CONFIG_PPC_PSERIES is not set | 44 | # CONFIG_PPC_PSERIES is not set |
43 | # CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set | 45 | # CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set |
44 | CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y | 46 | CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y |
@@ -54,7 +56,10 @@ CONFIG_NUMA=y | |||
54 | CONFIG_MEMORY_HOTPLUG=y | 56 | CONFIG_MEMORY_HOTPLUG=y |
55 | CONFIG_MEMORY_HOTREMOVE=y | 57 | CONFIG_MEMORY_HOTREMOVE=y |
56 | CONFIG_KSM=y | 58 | CONFIG_KSM=y |
59 | CONFIG_MEMORY_FAILURE=y | ||
60 | CONFIG_HWPOISON_INJECT=m | ||
57 | CONFIG_TRANSPARENT_HUGEPAGE=y | 61 | CONFIG_TRANSPARENT_HUGEPAGE=y |
62 | CONFIG_DEFERRED_STRUCT_PAGE_INIT=y | ||
58 | CONFIG_PPC_64K_PAGES=y | 63 | CONFIG_PPC_64K_PAGES=y |
59 | CONFIG_PPC_SUBPAGE_PROT=y | 64 | CONFIG_PPC_SUBPAGE_PROT=y |
60 | CONFIG_SCHED_SMT=y | 65 | CONFIG_SCHED_SMT=y |
@@ -72,7 +77,13 @@ CONFIG_SYN_COOKIES=y | |||
72 | CONFIG_INET_AH=m | 77 | CONFIG_INET_AH=m |
73 | CONFIG_INET_ESP=m | 78 | CONFIG_INET_ESP=m |
74 | CONFIG_INET_IPCOMP=m | 79 | CONFIG_INET_IPCOMP=m |
75 | # CONFIG_IPV6 is not set | 80 | CONFIG_INET6_AH=m |
81 | CONFIG_INET6_ESP=m | ||
82 | CONFIG_INET6_IPCOMP=m | ||
83 | CONFIG_INET6_XFRM_MODE_TRANSPORT=m | ||
84 | CONFIG_INET6_XFRM_MODE_TUNNEL=m | ||
85 | CONFIG_INET6_XFRM_MODE_BEET=m | ||
86 | CONFIG_IPV6_SIT=m | ||
76 | CONFIG_NETFILTER=y | 87 | CONFIG_NETFILTER=y |
77 | # CONFIG_NETFILTER_ADVANCED is not set | 88 | # CONFIG_NETFILTER_ADVANCED is not set |
78 | CONFIG_BRIDGE=m | 89 | CONFIG_BRIDGE=m |
@@ -81,33 +92,28 @@ CONFIG_NET_SCHED=y | |||
81 | CONFIG_NET_CLS_BPF=m | 92 | CONFIG_NET_CLS_BPF=m |
82 | CONFIG_NET_CLS_ACT=y | 93 | CONFIG_NET_CLS_ACT=y |
83 | CONFIG_NET_ACT_BPF=m | 94 | CONFIG_NET_ACT_BPF=m |
95 | CONFIG_DNS_RESOLVER=y | ||
84 | CONFIG_BPF_JIT=y | 96 | CONFIG_BPF_JIT=y |
97 | # CONFIG_WIRELESS is not set | ||
85 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" | 98 | CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" |
86 | CONFIG_DEVTMPFS=y | 99 | CONFIG_DEVTMPFS=y |
87 | CONFIG_DEVTMPFS_MOUNT=y | 100 | CONFIG_DEVTMPFS_MOUNT=y |
88 | CONFIG_MTD=y | 101 | CONFIG_MTD=y |
89 | CONFIG_MTD_BLOCK=y | 102 | CONFIG_MTD_BLOCK=y |
90 | CONFIG_MTD_POWERNV_FLASH=y | 103 | CONFIG_MTD_POWERNV_FLASH=y |
91 | CONFIG_PARPORT=m | ||
92 | CONFIG_PARPORT_PC=m | ||
93 | CONFIG_BLK_DEV_FD=m | ||
94 | CONFIG_BLK_DEV_LOOP=y | 104 | CONFIG_BLK_DEV_LOOP=y |
95 | CONFIG_BLK_DEV_NBD=m | 105 | CONFIG_BLK_DEV_NBD=m |
96 | CONFIG_BLK_DEV_RAM=y | 106 | CONFIG_BLK_DEV_RAM=m |
97 | CONFIG_BLK_DEV_RAM_SIZE=65536 | 107 | CONFIG_BLK_DEV_RAM_SIZE=65536 |
98 | CONFIG_VIRTIO_BLK=m | ||
99 | CONFIG_BLK_DEV_NVME=y | 108 | CONFIG_BLK_DEV_NVME=y |
100 | CONFIG_IDE=y | ||
101 | CONFIG_BLK_DEV_IDECD=y | ||
102 | CONFIG_BLK_DEV_GENERIC=y | ||
103 | CONFIG_BLK_DEV_AMD74XX=y | ||
104 | CONFIG_BLK_DEV_SD=y | 109 | CONFIG_BLK_DEV_SD=y |
105 | CONFIG_CHR_DEV_ST=m | 110 | CONFIG_CHR_DEV_ST=m |
106 | CONFIG_BLK_DEV_SR=y | 111 | CONFIG_BLK_DEV_SR=m |
107 | CONFIG_BLK_DEV_SR_VENDOR=y | 112 | CONFIG_BLK_DEV_SR_VENDOR=y |
108 | CONFIG_CHR_DEV_SG=y | 113 | CONFIG_CHR_DEV_SG=m |
109 | CONFIG_SCSI_CONSTANTS=y | 114 | CONFIG_SCSI_CONSTANTS=y |
110 | CONFIG_SCSI_FC_ATTRS=y | 115 | CONFIG_SCSI_SCAN_ASYNC=y |
116 | CONFIG_SCSI_FC_ATTRS=m | ||
111 | CONFIG_SCSI_SRP_ATTRS=y | 117 | CONFIG_SCSI_SRP_ATTRS=y |
112 | CONFIG_SCSI_CXGB3_ISCSI=m | 118 | CONFIG_SCSI_CXGB3_ISCSI=m |
113 | CONFIG_SCSI_CXGB4_ISCSI=m | 119 | CONFIG_SCSI_CXGB4_ISCSI=m |
@@ -121,7 +127,6 @@ CONFIG_SCSI_IPR=y | |||
121 | CONFIG_SCSI_QLA_FC=m | 127 | CONFIG_SCSI_QLA_FC=m |
122 | CONFIG_SCSI_QLA_ISCSI=m | 128 | CONFIG_SCSI_QLA_ISCSI=m |
123 | CONFIG_SCSI_LPFC=m | 129 | CONFIG_SCSI_LPFC=m |
124 | CONFIG_SCSI_VIRTIO=m | ||
125 | CONFIG_SCSI_DH=y | 130 | CONFIG_SCSI_DH=y |
126 | CONFIG_SCSI_DH_RDAC=m | 131 | CONFIG_SCSI_DH_RDAC=m |
127 | CONFIG_SCSI_DH_ALUA=m | 132 | CONFIG_SCSI_DH_ALUA=m |
@@ -152,16 +157,16 @@ CONFIG_DUMMY=m | |||
152 | CONFIG_MACVLAN=m | 157 | CONFIG_MACVLAN=m |
153 | CONFIG_MACVTAP=m | 158 | CONFIG_MACVTAP=m |
154 | CONFIG_VXLAN=m | 159 | CONFIG_VXLAN=m |
155 | CONFIG_NETCONSOLE=y | 160 | CONFIG_NETCONSOLE=m |
156 | CONFIG_TUN=m | 161 | CONFIG_TUN=m |
157 | CONFIG_VETH=m | 162 | CONFIG_VETH=m |
158 | CONFIG_VIRTIO_NET=m | ||
159 | CONFIG_VORTEX=m | 163 | CONFIG_VORTEX=m |
160 | CONFIG_ACENIC=m | 164 | CONFIG_ACENIC=m |
161 | CONFIG_ACENIC_OMIT_TIGON_I=y | 165 | CONFIG_ACENIC_OMIT_TIGON_I=y |
162 | CONFIG_PCNET32=m | 166 | CONFIG_PCNET32=m |
163 | CONFIG_TIGON3=y | 167 | CONFIG_TIGON3=y |
164 | CONFIG_BNX2X=m | 168 | CONFIG_BNX2X=m |
169 | # CONFIG_CAVIUM_PTP is not set | ||
165 | CONFIG_CHELSIO_T1=m | 170 | CONFIG_CHELSIO_T1=m |
166 | CONFIG_BE2NET=m | 171 | CONFIG_BE2NET=m |
167 | CONFIG_S2IO=m | 172 | CONFIG_S2IO=m |
@@ -172,46 +177,62 @@ CONFIG_IXGB=m | |||
172 | CONFIG_IXGBE=m | 177 | CONFIG_IXGBE=m |
173 | CONFIG_I40E=m | 178 | CONFIG_I40E=m |
174 | CONFIG_MLX4_EN=m | 179 | CONFIG_MLX4_EN=m |
180 | CONFIG_MLX5_CORE=m | ||
181 | CONFIG_MLX5_FPGA=y | ||
182 | CONFIG_MLX5_CORE_EN=y | ||
183 | CONFIG_MLX5_CORE_IPOIB=y | ||
175 | CONFIG_MYRI10GE=m | 184 | CONFIG_MYRI10GE=m |
176 | CONFIG_QLGE=m | 185 | CONFIG_QLGE=m |
177 | CONFIG_NETXEN_NIC=m | 186 | CONFIG_NETXEN_NIC=m |
178 | CONFIG_PPP=m | 187 | CONFIG_USB_NET_DRIVERS=m |
179 | CONFIG_PPP_BSDCOMP=m | 188 | # CONFIG_WLAN is not set |
180 | CONFIG_PPP_DEFLATE=m | ||
181 | CONFIG_PPPOE=m | ||
182 | CONFIG_PPP_ASYNC=m | ||
183 | CONFIG_PPP_SYNC_TTY=m | ||
184 | CONFIG_INPUT_EVDEV=m | 189 | CONFIG_INPUT_EVDEV=m |
185 | CONFIG_INPUT_MISC=y | 190 | # CONFIG_INPUT_KEYBOARD is not set |
186 | # CONFIG_SERIO_SERPORT is not set | 191 | # CONFIG_INPUT_MOUSE is not set |
192 | # CONFIG_SERIO is not set | ||
193 | # CONFIG_LEGACY_PTYS is not set | ||
187 | CONFIG_SERIAL_8250=y | 194 | CONFIG_SERIAL_8250=y |
188 | CONFIG_SERIAL_8250_CONSOLE=y | 195 | CONFIG_SERIAL_8250_CONSOLE=y |
196 | CONFIG_SERIAL_8250_PCI=m | ||
189 | CONFIG_SERIAL_JSM=m | 197 | CONFIG_SERIAL_JSM=m |
190 | CONFIG_VIRTIO_CONSOLE=m | ||
191 | CONFIG_IPMI_HANDLER=y | 198 | CONFIG_IPMI_HANDLER=y |
192 | CONFIG_IPMI_DEVICE_INTERFACE=y | 199 | CONFIG_IPMI_DEVICE_INTERFACE=y |
193 | CONFIG_IPMI_POWERNV=y | 200 | CONFIG_IPMI_POWERNV=y |
194 | CONFIG_RAW_DRIVER=y | 201 | # CONFIG_DEVPORT is not set |
195 | CONFIG_MAX_RAW_DEVS=1024 | ||
196 | CONFIG_I2C_CHARDEV=y | 202 | CONFIG_I2C_CHARDEV=y |
203 | # CONFIG_PTP_1588_CLOCK is not set | ||
197 | CONFIG_DRM=y | 204 | CONFIG_DRM=y |
198 | CONFIG_DRM_AST=y | 205 | CONFIG_DRM_AST=y |
199 | CONFIG_FIRMWARE_EDID=y | 206 | CONFIG_FIRMWARE_EDID=y |
200 | CONFIG_FB_OF=y | 207 | CONFIG_FB_OF=y |
201 | CONFIG_FB_MATROX=y | 208 | CONFIG_FB_MATROX=m |
202 | CONFIG_FB_MATROX_MILLENIUM=y | 209 | CONFIG_FB_MATROX_MILLENIUM=y |
203 | CONFIG_FB_MATROX_MYSTIQUE=y | 210 | CONFIG_FB_MATROX_MYSTIQUE=y |
204 | CONFIG_FB_MATROX_G=y | 211 | CONFIG_FB_MATROX_G=y |
205 | CONFIG_FB_RADEON=y | 212 | CONFIG_FB_RADEON=m |
206 | CONFIG_FB_IBM_GXT4500=y | 213 | CONFIG_FB_IBM_GXT4500=m |
207 | CONFIG_LCD_PLATFORM=m | 214 | CONFIG_LCD_PLATFORM=m |
215 | CONFIG_BACKLIGHT_GENERIC=m | ||
208 | # CONFIG_VGA_CONSOLE is not set | 216 | # CONFIG_VGA_CONSOLE is not set |
209 | CONFIG_LOGO=y | 217 | CONFIG_LOGO=y |
210 | CONFIG_HID_GYRATION=y | 218 | CONFIG_HID_A4TECH=m |
211 | CONFIG_HID_PANTHERLORD=y | 219 | CONFIG_HID_APPLE=m |
212 | CONFIG_HID_PETALYNX=y | 220 | CONFIG_HID_BELKIN=m |
213 | CONFIG_HID_SAMSUNG=y | 221 | CONFIG_HID_CHERRY=m |
214 | CONFIG_HID_SUNPLUS=y | 222 | CONFIG_HID_CHICONY=m |
223 | CONFIG_HID_CYPRESS=m | ||
224 | CONFIG_HID_EZKEY=m | ||
225 | CONFIG_HID_GYRATION=m | ||
226 | CONFIG_HID_ITE=m | ||
227 | CONFIG_HID_KENSINGTON=m | ||
228 | CONFIG_HID_LOGITECH=m | ||
229 | CONFIG_HID_MICROSOFT=m | ||
230 | CONFIG_HID_MONTEREY=m | ||
231 | CONFIG_HID_PANTHERLORD=m | ||
232 | CONFIG_HID_PETALYNX=m | ||
233 | CONFIG_HID_SAMSUNG=m | ||
234 | CONFIG_HID_SUNPLUS=m | ||
235 | CONFIG_USB_HID=m | ||
215 | CONFIG_USB_HIDDEV=y | 236 | CONFIG_USB_HIDDEV=y |
216 | CONFIG_USB=y | 237 | CONFIG_USB=y |
217 | CONFIG_USB_MON=m | 238 | CONFIG_USB_MON=m |
@@ -219,6 +240,7 @@ CONFIG_USB_XHCI_HCD=y | |||
219 | CONFIG_USB_EHCI_HCD=y | 240 | CONFIG_USB_EHCI_HCD=y |
220 | # CONFIG_USB_EHCI_HCD_PPC_OF is not set | 241 | # CONFIG_USB_EHCI_HCD_PPC_OF is not set |
221 | CONFIG_USB_OHCI_HCD=y | 242 | CONFIG_USB_OHCI_HCD=y |
243 | CONFIG_USB_OHCI_HCD_PCI=m | ||
222 | CONFIG_USB_STORAGE=y | 244 | CONFIG_USB_STORAGE=y |
223 | CONFIG_NEW_LEDS=y | 245 | CONFIG_NEW_LEDS=y |
224 | CONFIG_LEDS_CLASS=m | 246 | CONFIG_LEDS_CLASS=m |
@@ -236,8 +258,9 @@ CONFIG_INFINIBAND_SRP=m | |||
236 | CONFIG_INFINIBAND_ISER=m | 258 | CONFIG_INFINIBAND_ISER=m |
237 | CONFIG_RTC_CLASS=y | 259 | CONFIG_RTC_CLASS=y |
238 | CONFIG_RTC_DRV_GENERIC=y | 260 | CONFIG_RTC_DRV_GENERIC=y |
239 | CONFIG_VIRTIO_PCI=m | 261 | # CONFIG_VIRTIO_MENU is not set |
240 | CONFIG_VIRTIO_BALLOON=m | 262 | CONFIG_LIBNVDIMM=y |
263 | # CONFIG_ND_BLK is not set | ||
241 | CONFIG_EXT2_FS=y | 264 | CONFIG_EXT2_FS=y |
242 | CONFIG_EXT2_FS_XATTR=y | 265 | CONFIG_EXT2_FS_XATTR=y |
243 | CONFIG_EXT2_FS_POSIX_ACL=y | 266 | CONFIG_EXT2_FS_POSIX_ACL=y |
@@ -253,12 +276,13 @@ CONFIG_XFS_POSIX_ACL=y | |||
253 | CONFIG_BTRFS_FS=m | 276 | CONFIG_BTRFS_FS=m |
254 | CONFIG_BTRFS_FS_POSIX_ACL=y | 277 | CONFIG_BTRFS_FS_POSIX_ACL=y |
255 | CONFIG_NILFS2_FS=m | 278 | CONFIG_NILFS2_FS=m |
279 | CONFIG_FANOTIFY=y | ||
256 | CONFIG_AUTOFS4_FS=m | 280 | CONFIG_AUTOFS4_FS=m |
257 | CONFIG_FUSE_FS=m | 281 | CONFIG_FUSE_FS=m |
258 | CONFIG_OVERLAY_FS=m | 282 | CONFIG_OVERLAY_FS=m |
259 | CONFIG_ISO9660_FS=y | 283 | CONFIG_ISO9660_FS=y |
260 | CONFIG_UDF_FS=m | 284 | CONFIG_UDF_FS=m |
261 | CONFIG_MSDOS_FS=y | 285 | CONFIG_MSDOS_FS=m |
262 | CONFIG_VFAT_FS=m | 286 | CONFIG_VFAT_FS=m |
263 | CONFIG_PROC_KCORE=y | 287 | CONFIG_PROC_KCORE=y |
264 | CONFIG_TMPFS=y | 288 | CONFIG_TMPFS=y |
@@ -270,9 +294,9 @@ CONFIG_SQUASHFS_XATTR=y | |||
270 | CONFIG_SQUASHFS_LZO=y | 294 | CONFIG_SQUASHFS_LZO=y |
271 | CONFIG_SQUASHFS_XZ=y | 295 | CONFIG_SQUASHFS_XZ=y |
272 | CONFIG_PSTORE=y | 296 | CONFIG_PSTORE=y |
273 | CONFIG_NFS_FS=y | 297 | CONFIG_NFS_FS=m |
274 | CONFIG_NFS_V3_ACL=y | 298 | CONFIG_NFS_V3_ACL=y |
275 | CONFIG_NFS_V4=y | 299 | CONFIG_NFS_V4=m |
276 | CONFIG_NFSD=m | 300 | CONFIG_NFSD=m |
277 | CONFIG_NFSD_V3_ACL=y | 301 | CONFIG_NFSD_V3_ACL=y |
278 | CONFIG_NFSD_V4=y | 302 | CONFIG_NFSD_V4=y |
@@ -291,9 +315,7 @@ CONFIG_DEBUG_STACKOVERFLOW=y | |||
291 | CONFIG_SOFTLOCKUP_DETECTOR=y | 315 | CONFIG_SOFTLOCKUP_DETECTOR=y |
292 | CONFIG_HARDLOCKUP_DETECTOR=y | 316 | CONFIG_HARDLOCKUP_DETECTOR=y |
293 | CONFIG_LATENCYTOP=y | 317 | CONFIG_LATENCYTOP=y |
294 | CONFIG_FTRACE=y | ||
295 | CONFIG_FUNCTION_TRACER=y | 318 | CONFIG_FUNCTION_TRACER=y |
296 | CONFIG_FUNCTION_GRAPH_TRACER=y | ||
297 | CONFIG_SCHED_TRACER=y | 319 | CONFIG_SCHED_TRACER=y |
298 | CONFIG_FTRACE_SYSCALLS=y | 320 | CONFIG_FTRACE_SYSCALLS=y |
299 | CONFIG_BLK_DEV_IO_TRACE=y | 321 | CONFIG_BLK_DEV_IO_TRACE=y |
@@ -303,10 +325,10 @@ CONFIG_FTR_FIXUP_SELFTEST=y | |||
303 | CONFIG_MSI_BITMAP_SELFTEST=y | 325 | CONFIG_MSI_BITMAP_SELFTEST=y |
304 | CONFIG_XMON=y | 326 | CONFIG_XMON=y |
305 | CONFIG_CRYPTO_TEST=m | 327 | CONFIG_CRYPTO_TEST=m |
306 | CONFIG_CRYPTO_CCM=m | ||
307 | CONFIG_CRYPTO_PCBC=m | 328 | CONFIG_CRYPTO_PCBC=m |
308 | CONFIG_CRYPTO_HMAC=y | 329 | CONFIG_CRYPTO_HMAC=y |
309 | CONFIG_CRYPTO_CRC32C_VPMSUM=m | 330 | CONFIG_CRYPTO_CRC32C_VPMSUM=m |
331 | CONFIG_CRYPTO_CRCT10DIF_VPMSUM=m | ||
310 | CONFIG_CRYPTO_MD5_PPC=m | 332 | CONFIG_CRYPTO_MD5_PPC=m |
311 | CONFIG_CRYPTO_MICHAEL_MIC=m | 333 | CONFIG_CRYPTO_MICHAEL_MIC=m |
312 | CONFIG_CRYPTO_SHA1_PPC=m | 334 | CONFIG_CRYPTO_SHA1_PPC=m |
diff --git a/arch/powerpc/configs/wii_defconfig b/arch/powerpc/configs/wii_defconfig index 0b0f78823a1b..10940533da71 100644 --- a/arch/powerpc/configs/wii_defconfig +++ b/arch/powerpc/configs/wii_defconfig | |||
@@ -49,7 +49,9 @@ CONFIG_BLK_DEV_RAM_COUNT=2 | |||
49 | CONFIG_SCSI=y | 49 | CONFIG_SCSI=y |
50 | CONFIG_BLK_DEV_SD=y | 50 | CONFIG_BLK_DEV_SD=y |
51 | CONFIG_NETDEVICES=y | 51 | CONFIG_NETDEVICES=y |
52 | # CONFIG_ETHERNET is not set | ||
52 | CONFIG_B43=y | 53 | CONFIG_B43=y |
54 | CONFIG_B43_BUSES_SSB=y | ||
53 | CONFIG_B43_SDIO=y | 55 | CONFIG_B43_SDIO=y |
54 | # CONFIG_B43_PHY_LP is not set | 56 | # CONFIG_B43_PHY_LP is not set |
55 | CONFIG_B43_DEBUG=y | 57 | CONFIG_B43_DEBUG=y |
@@ -57,6 +59,7 @@ CONFIG_INPUT_FF_MEMLESS=m | |||
57 | CONFIG_INPUT_JOYDEV=y | 59 | CONFIG_INPUT_JOYDEV=y |
58 | CONFIG_INPUT_EVDEV=y | 60 | CONFIG_INPUT_EVDEV=y |
59 | # CONFIG_KEYBOARD_ATKBD is not set | 61 | # CONFIG_KEYBOARD_ATKBD is not set |
62 | CONFIG_KEYBOARD_GPIO=y | ||
60 | # CONFIG_MOUSE_PS2 is not set | 63 | # CONFIG_MOUSE_PS2 is not set |
61 | CONFIG_INPUT_JOYSTICK=y | 64 | CONFIG_INPUT_JOYSTICK=y |
62 | CONFIG_INPUT_MISC=y | 65 | CONFIG_INPUT_MISC=y |
@@ -71,6 +74,9 @@ CONFIG_I2C_CHARDEV=y | |||
71 | CONFIG_I2C_GPIO=y | 74 | CONFIG_I2C_GPIO=y |
72 | CONFIG_GPIOLIB=y | 75 | CONFIG_GPIOLIB=y |
73 | CONFIG_GPIO_SYSFS=y | 76 | CONFIG_GPIO_SYSFS=y |
77 | CONFIG_GPIO_HLWD=y | ||
78 | CONFIG_POWER_RESET=y | ||
79 | CONFIG_POWER_RESET_GPIO=y | ||
74 | # CONFIG_HWMON is not set | 80 | # CONFIG_HWMON is not set |
75 | CONFIG_SSB_DEBUG=y | 81 | CONFIG_SSB_DEBUG=y |
76 | CONFIG_FB=y | 82 | CONFIG_FB=y |
@@ -88,6 +94,14 @@ CONFIG_HID_APPLE=m | |||
88 | CONFIG_HID_WACOM=m | 94 | CONFIG_HID_WACOM=m |
89 | CONFIG_MMC=y | 95 | CONFIG_MMC=y |
90 | CONFIG_MMC_SDHCI=y | 96 | CONFIG_MMC_SDHCI=y |
97 | CONFIG_MMC_SDHCI_PLTFM=y | ||
98 | CONFIG_MMC_SDHCI_OF_HLWD=y | ||
99 | CONFIG_NEW_LEDS=y | ||
100 | CONFIG_LEDS_CLASS=y | ||
101 | CONFIG_LEDS_GPIO=y | ||
102 | CONFIG_LEDS_TRIGGERS=y | ||
103 | CONFIG_LEDS_TRIGGER_HEARTBEAT=y | ||
104 | CONFIG_LEDS_TRIGGER_PANIC=y | ||
91 | CONFIG_RTC_CLASS=y | 105 | CONFIG_RTC_CLASS=y |
92 | CONFIG_RTC_DRV_GENERIC=y | 106 | CONFIG_RTC_DRV_GENERIC=y |
93 | CONFIG_EXT2_FS=y | 107 | CONFIG_EXT2_FS=y |
diff --git a/arch/powerpc/include/asm/asm-prototypes.h b/arch/powerpc/include/asm/asm-prototypes.h index d9713ad62e3c..aa9e785c59c2 100644 --- a/arch/powerpc/include/asm/asm-prototypes.h +++ b/arch/powerpc/include/asm/asm-prototypes.h | |||
@@ -36,8 +36,7 @@ void kexec_copy_flush(struct kimage *image); | |||
36 | /* pseries hcall tracing */ | 36 | /* pseries hcall tracing */ |
37 | extern struct static_key hcall_tracepoint_key; | 37 | extern struct static_key hcall_tracepoint_key; |
38 | void __trace_hcall_entry(unsigned long opcode, unsigned long *args); | 38 | void __trace_hcall_entry(unsigned long opcode, unsigned long *args); |
39 | void __trace_hcall_exit(long opcode, unsigned long retval, | 39 | void __trace_hcall_exit(long opcode, long retval, unsigned long *retbuf); |
40 | unsigned long *retbuf); | ||
41 | /* OPAL tracing */ | 40 | /* OPAL tracing */ |
42 | #ifdef HAVE_JUMP_LABEL | 41 | #ifdef HAVE_JUMP_LABEL |
43 | extern struct static_key opal_tracepoint_key; | 42 | extern struct static_key opal_tracepoint_key; |
@@ -81,18 +80,12 @@ void machine_check_exception(struct pt_regs *regs); | |||
81 | void emulation_assist_interrupt(struct pt_regs *regs); | 80 | void emulation_assist_interrupt(struct pt_regs *regs); |
82 | 81 | ||
83 | /* signals, syscalls and interrupts */ | 82 | /* signals, syscalls and interrupts */ |
84 | #ifdef CONFIG_PPC64 | ||
85 | int sys_swapcontext(struct ucontext __user *old_ctx, | ||
86 | struct ucontext __user *new_ctx, | ||
87 | long ctx_size, long r6, long r7, long r8, struct pt_regs *regs); | ||
88 | #else | ||
89 | long sys_swapcontext(struct ucontext __user *old_ctx, | 83 | long sys_swapcontext(struct ucontext __user *old_ctx, |
90 | struct ucontext __user *new_ctx, | 84 | struct ucontext __user *new_ctx, |
91 | int ctx_size, int r6, int r7, int r8, struct pt_regs *regs); | 85 | long ctx_size); |
92 | int sys_debug_setcontext(struct ucontext __user *ctx, | 86 | #ifdef CONFIG_PPC32 |
93 | int ndbg, struct sig_dbg_op __user *dbg, | 87 | long sys_debug_setcontext(struct ucontext __user *ctx, |
94 | int r6, int r7, int r8, | 88 | int ndbg, struct sig_dbg_op __user *dbg); |
95 | struct pt_regs *regs); | ||
96 | int | 89 | int |
97 | ppc_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, struct timeval __user *tvp); | 90 | ppc_select(int n, fd_set __user *inp, fd_set __user *outp, fd_set __user *exp, struct timeval __user *tvp); |
98 | unsigned long __init early_init(unsigned long dt_ptr); | 91 | unsigned long __init early_init(unsigned long dt_ptr); |
@@ -141,4 +134,7 @@ unsigned long prepare_ftrace_return(unsigned long parent, unsigned long ip); | |||
141 | void pnv_power9_force_smt4_catch(void); | 134 | void pnv_power9_force_smt4_catch(void); |
142 | void pnv_power9_force_smt4_release(void); | 135 | void pnv_power9_force_smt4_release(void); |
143 | 136 | ||
137 | void tm_enable(void); | ||
138 | void tm_disable(void); | ||
139 | void tm_abort(uint8_t cause); | ||
144 | #endif /* _ASM_POWERPC_ASM_PROTOTYPES_H */ | 140 | #endif /* _ASM_POWERPC_ASM_PROTOTYPES_H */ |
diff --git a/arch/powerpc/include/asm/barrier.h b/arch/powerpc/include/asm/barrier.h index c7c63959ba91..f67b3f6e36be 100644 --- a/arch/powerpc/include/asm/barrier.h +++ b/arch/powerpc/include/asm/barrier.h | |||
@@ -76,6 +76,21 @@ do { \ | |||
76 | ___p1; \ | 76 | ___p1; \ |
77 | }) | 77 | }) |
78 | 78 | ||
79 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
80 | /* | ||
81 | * Prevent execution of subsequent instructions until preceding branches have | ||
82 | * been fully resolved and are no longer executing speculatively. | ||
83 | */ | ||
84 | #define barrier_nospec_asm NOSPEC_BARRIER_FIXUP_SECTION; nop | ||
85 | |||
86 | // This also acts as a compiler barrier due to the memory clobber. | ||
87 | #define barrier_nospec() asm (stringify_in_c(barrier_nospec_asm) ::: "memory") | ||
88 | |||
89 | #else /* !CONFIG_PPC_BOOK3S_64 */ | ||
90 | #define barrier_nospec_asm | ||
91 | #define barrier_nospec() | ||
92 | #endif | ||
93 | |||
79 | #include <asm-generic/barrier.h> | 94 | #include <asm-generic/barrier.h> |
80 | 95 | ||
81 | #endif /* _ASM_POWERPC_BARRIER_H */ | 96 | #endif /* _ASM_POWERPC_BARRIER_H */ |
diff --git a/arch/powerpc/include/asm/book3s/32/pgalloc.h b/arch/powerpc/include/asm/book3s/32/pgalloc.h index 5073cc75f1c8..6a6673907e45 100644 --- a/arch/powerpc/include/asm/book3s/32/pgalloc.h +++ b/arch/powerpc/include/asm/book3s/32/pgalloc.h | |||
@@ -99,6 +99,7 @@ static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage) | |||
99 | static inline void pgtable_free(void *table, unsigned index_size) | 99 | static inline void pgtable_free(void *table, unsigned index_size) |
100 | { | 100 | { |
101 | if (!index_size) { | 101 | if (!index_size) { |
102 | pgtable_page_dtor(virt_to_page(table)); | ||
102 | free_page((unsigned long)table); | 103 | free_page((unsigned long)table); |
103 | } else { | 104 | } else { |
104 | BUG_ON(index_size > MAX_PGTABLE_INDEX_SIZE); | 105 | BUG_ON(index_size > MAX_PGTABLE_INDEX_SIZE); |
diff --git a/arch/powerpc/include/asm/book3s/32/pgtable.h b/arch/powerpc/include/asm/book3s/32/pgtable.h index c615abdce119..02f5acd7ccc4 100644 --- a/arch/powerpc/include/asm/book3s/32/pgtable.h +++ b/arch/powerpc/include/asm/book3s/32/pgtable.h | |||
@@ -235,15 +235,18 @@ static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, | |||
235 | } | 235 | } |
236 | 236 | ||
237 | 237 | ||
238 | static inline void __ptep_set_access_flags(struct mm_struct *mm, | 238 | static inline void __ptep_set_access_flags(struct vm_area_struct *vma, |
239 | pte_t *ptep, pte_t entry, | 239 | pte_t *ptep, pte_t entry, |
240 | unsigned long address) | 240 | unsigned long address, |
241 | int psize) | ||
241 | { | 242 | { |
242 | unsigned long set = pte_val(entry) & | 243 | unsigned long set = pte_val(entry) & |
243 | (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC); | 244 | (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC); |
244 | unsigned long clr = ~pte_val(entry) & _PAGE_RO; | 245 | unsigned long clr = ~pte_val(entry) & _PAGE_RO; |
245 | 246 | ||
246 | pte_update(ptep, clr, set); | 247 | pte_update(ptep, clr, set); |
248 | |||
249 | flush_tlb_page(vma, address); | ||
247 | } | 250 | } |
248 | 251 | ||
249 | #define __HAVE_ARCH_PTE_SAME | 252 | #define __HAVE_ARCH_PTE_SAME |
diff --git a/arch/powerpc/include/asm/book3s/64/hash-4k.h b/arch/powerpc/include/asm/book3s/64/hash-4k.h index 4b5423030d4b..9a3798660cef 100644 --- a/arch/powerpc/include/asm/book3s/64/hash-4k.h +++ b/arch/powerpc/include/asm/book3s/64/hash-4k.h | |||
@@ -38,8 +38,12 @@ | |||
38 | #define H_PAGE_4K_PFN 0x0 | 38 | #define H_PAGE_4K_PFN 0x0 |
39 | #define H_PAGE_THP_HUGE 0x0 | 39 | #define H_PAGE_THP_HUGE 0x0 |
40 | #define H_PAGE_COMBO 0x0 | 40 | #define H_PAGE_COMBO 0x0 |
41 | #define H_PTE_FRAG_NR 0 | 41 | |
42 | #define H_PTE_FRAG_SIZE_SHIFT 0 | 42 | /* 8 bytes per each pte entry */ |
43 | #define H_PTE_FRAG_SIZE_SHIFT (H_PTE_INDEX_SIZE + 3) | ||
44 | #define H_PTE_FRAG_NR (PAGE_SIZE >> H_PTE_FRAG_SIZE_SHIFT) | ||
45 | #define H_PMD_FRAG_SIZE_SHIFT (H_PMD_INDEX_SIZE + 3) | ||
46 | #define H_PMD_FRAG_NR (PAGE_SIZE >> H_PMD_FRAG_SIZE_SHIFT) | ||
43 | 47 | ||
44 | /* memory key bits, only 8 keys supported */ | 48 | /* memory key bits, only 8 keys supported */ |
45 | #define H_PTE_PKEY_BIT0 0 | 49 | #define H_PTE_PKEY_BIT0 0 |
diff --git a/arch/powerpc/include/asm/book3s/64/hash-64k.h b/arch/powerpc/include/asm/book3s/64/hash-64k.h index cc82745355b3..c81793d47af9 100644 --- a/arch/powerpc/include/asm/book3s/64/hash-64k.h +++ b/arch/powerpc/include/asm/book3s/64/hash-64k.h | |||
@@ -46,6 +46,13 @@ | |||
46 | #define H_PTE_FRAG_SIZE_SHIFT (H_PTE_INDEX_SIZE + 3 + 1) | 46 | #define H_PTE_FRAG_SIZE_SHIFT (H_PTE_INDEX_SIZE + 3 + 1) |
47 | #define H_PTE_FRAG_NR (PAGE_SIZE >> H_PTE_FRAG_SIZE_SHIFT) | 47 | #define H_PTE_FRAG_NR (PAGE_SIZE >> H_PTE_FRAG_SIZE_SHIFT) |
48 | 48 | ||
49 | #if defined(CONFIG_TRANSPARENT_HUGEPAGE) || defined(CONFIG_HUGETLB_PAGE) | ||
50 | #define H_PMD_FRAG_SIZE_SHIFT (H_PMD_INDEX_SIZE + 3 + 1) | ||
51 | #else | ||
52 | #define H_PMD_FRAG_SIZE_SHIFT (H_PMD_INDEX_SIZE + 3) | ||
53 | #endif | ||
54 | #define H_PMD_FRAG_NR (PAGE_SIZE >> H_PMD_FRAG_SIZE_SHIFT) | ||
55 | |||
49 | #ifndef __ASSEMBLY__ | 56 | #ifndef __ASSEMBLY__ |
50 | #include <asm/errno.h> | 57 | #include <asm/errno.h> |
51 | 58 | ||
diff --git a/arch/powerpc/include/asm/book3s/64/hash.h b/arch/powerpc/include/asm/book3s/64/hash.h index cc8cd656ccfe..0387b155f13d 100644 --- a/arch/powerpc/include/asm/book3s/64/hash.h +++ b/arch/powerpc/include/asm/book3s/64/hash.h | |||
@@ -23,16 +23,6 @@ | |||
23 | H_PUD_INDEX_SIZE + H_PGD_INDEX_SIZE + PAGE_SHIFT) | 23 | H_PUD_INDEX_SIZE + H_PGD_INDEX_SIZE + PAGE_SHIFT) |
24 | #define H_PGTABLE_RANGE (ASM_CONST(1) << H_PGTABLE_EADDR_SIZE) | 24 | #define H_PGTABLE_RANGE (ASM_CONST(1) << H_PGTABLE_EADDR_SIZE) |
25 | 25 | ||
26 | #if (defined(CONFIG_TRANSPARENT_HUGEPAGE) || defined(CONFIG_HUGETLB_PAGE)) && \ | ||
27 | defined(CONFIG_PPC_64K_PAGES) | ||
28 | /* | ||
29 | * only with hash 64k we need to use the second half of pmd page table | ||
30 | * to store pointer to deposited pgtable_t | ||
31 | */ | ||
32 | #define H_PMD_CACHE_INDEX (H_PMD_INDEX_SIZE + 1) | ||
33 | #else | ||
34 | #define H_PMD_CACHE_INDEX H_PMD_INDEX_SIZE | ||
35 | #endif | ||
36 | /* | 26 | /* |
37 | * We store the slot details in the second half of page table. | 27 | * We store the slot details in the second half of page table. |
38 | * Increase the pud level table so that hugetlb ptes can be stored | 28 | * Increase the pud level table so that hugetlb ptes can be stored |
diff --git a/arch/powerpc/include/asm/book3s/64/mmu.h b/arch/powerpc/include/asm/book3s/64/mmu.h index 5094696eecd6..9c8c669a6b6a 100644 --- a/arch/powerpc/include/asm/book3s/64/mmu.h +++ b/arch/powerpc/include/asm/book3s/64/mmu.h | |||
@@ -134,10 +134,11 @@ typedef struct { | |||
134 | #ifdef CONFIG_PPC_SUBPAGE_PROT | 134 | #ifdef CONFIG_PPC_SUBPAGE_PROT |
135 | struct subpage_prot_table spt; | 135 | struct subpage_prot_table spt; |
136 | #endif /* CONFIG_PPC_SUBPAGE_PROT */ | 136 | #endif /* CONFIG_PPC_SUBPAGE_PROT */ |
137 | #ifdef CONFIG_PPC_64K_PAGES | 137 | /* |
138 | /* for 4K PTE fragment support */ | 138 | * pagetable fragment support |
139 | */ | ||
139 | void *pte_frag; | 140 | void *pte_frag; |
140 | #endif | 141 | void *pmd_frag; |
141 | #ifdef CONFIG_SPAPR_TCE_IOMMU | 142 | #ifdef CONFIG_SPAPR_TCE_IOMMU |
142 | struct list_head iommu_group_mem_list; | 143 | struct list_head iommu_group_mem_list; |
143 | #endif | 144 | #endif |
diff --git a/arch/powerpc/include/asm/book3s/64/pgalloc.h b/arch/powerpc/include/asm/book3s/64/pgalloc.h index 558a159600ad..01ee40f11f3a 100644 --- a/arch/powerpc/include/asm/book3s/64/pgalloc.h +++ b/arch/powerpc/include/asm/book3s/64/pgalloc.h | |||
@@ -42,7 +42,9 @@ extern struct kmem_cache *pgtable_cache[]; | |||
42 | }) | 42 | }) |
43 | 43 | ||
44 | extern pte_t *pte_fragment_alloc(struct mm_struct *, unsigned long, int); | 44 | extern pte_t *pte_fragment_alloc(struct mm_struct *, unsigned long, int); |
45 | extern pmd_t *pmd_fragment_alloc(struct mm_struct *, unsigned long); | ||
45 | extern void pte_fragment_free(unsigned long *, int); | 46 | extern void pte_fragment_free(unsigned long *, int); |
47 | extern void pmd_fragment_free(unsigned long *); | ||
46 | extern void pgtable_free_tlb(struct mmu_gather *tlb, void *table, int shift); | 48 | extern void pgtable_free_tlb(struct mmu_gather *tlb, void *table, int shift); |
47 | #ifdef CONFIG_SMP | 49 | #ifdef CONFIG_SMP |
48 | extern void __tlb_remove_table(void *_table); | 50 | extern void __tlb_remove_table(void *_table); |
@@ -88,8 +90,7 @@ static inline pgd_t *pgd_alloc(struct mm_struct *mm) | |||
88 | * need to do this for 4k. | 90 | * need to do this for 4k. |
89 | */ | 91 | */ |
90 | #if defined(CONFIG_HUGETLB_PAGE) && defined(CONFIG_PPC_64K_PAGES) && \ | 92 | #if defined(CONFIG_HUGETLB_PAGE) && defined(CONFIG_PPC_64K_PAGES) && \ |
91 | ((H_PGD_INDEX_SIZE == H_PUD_CACHE_INDEX) || \ | 93 | (H_PGD_INDEX_SIZE == H_PUD_CACHE_INDEX) |
92 | (H_PGD_INDEX_SIZE == H_PMD_CACHE_INDEX)) | ||
93 | memset(pgd, 0, PGD_TABLE_SIZE); | 94 | memset(pgd, 0, PGD_TABLE_SIZE); |
94 | #endif | 95 | #endif |
95 | return pgd; | 96 | return pgd; |
@@ -124,36 +125,35 @@ static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) | |||
124 | } | 125 | } |
125 | 126 | ||
126 | static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud, | 127 | static inline void __pud_free_tlb(struct mmu_gather *tlb, pud_t *pud, |
127 | unsigned long address) | 128 | unsigned long address) |
128 | { | 129 | { |
129 | /* | 130 | /* |
130 | * By now all the pud entries should be none entries. So go | 131 | * By now all the pud entries should be none entries. So go |
131 | * ahead and flush the page walk cache | 132 | * ahead and flush the page walk cache |
132 | */ | 133 | */ |
133 | flush_tlb_pgtable(tlb, address); | 134 | flush_tlb_pgtable(tlb, address); |
134 | pgtable_free_tlb(tlb, pud, PUD_CACHE_INDEX); | 135 | pgtable_free_tlb(tlb, pud, PUD_INDEX); |
135 | } | 136 | } |
136 | 137 | ||
137 | static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) | 138 | static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) |
138 | { | 139 | { |
139 | return kmem_cache_alloc(PGT_CACHE(PMD_CACHE_INDEX), | 140 | return pmd_fragment_alloc(mm, addr); |
140 | pgtable_gfp_flags(mm, GFP_KERNEL)); | ||
141 | } | 141 | } |
142 | 142 | ||
143 | static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd) | 143 | static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd) |
144 | { | 144 | { |
145 | kmem_cache_free(PGT_CACHE(PMD_CACHE_INDEX), pmd); | 145 | pmd_fragment_free((unsigned long *)pmd); |
146 | } | 146 | } |
147 | 147 | ||
148 | static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd, | 148 | static inline void __pmd_free_tlb(struct mmu_gather *tlb, pmd_t *pmd, |
149 | unsigned long address) | 149 | unsigned long address) |
150 | { | 150 | { |
151 | /* | 151 | /* |
152 | * By now all the pud entries should be none entries. So go | 152 | * By now all the pud entries should be none entries. So go |
153 | * ahead and flush the page walk cache | 153 | * ahead and flush the page walk cache |
154 | */ | 154 | */ |
155 | flush_tlb_pgtable(tlb, address); | 155 | flush_tlb_pgtable(tlb, address); |
156 | return pgtable_free_tlb(tlb, pmd, PMD_CACHE_INDEX); | 156 | return pgtable_free_tlb(tlb, pmd, PMD_INDEX); |
157 | } | 157 | } |
158 | 158 | ||
159 | static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, | 159 | static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, |
@@ -173,31 +173,6 @@ static inline pgtable_t pmd_pgtable(pmd_t pmd) | |||
173 | return (pgtable_t)pmd_page_vaddr(pmd); | 173 | return (pgtable_t)pmd_page_vaddr(pmd); |
174 | } | 174 | } |
175 | 175 | ||
176 | #ifdef CONFIG_PPC_4K_PAGES | ||
177 | static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, | ||
178 | unsigned long address) | ||
179 | { | ||
180 | return (pte_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO); | ||
181 | } | ||
182 | |||
183 | static inline pgtable_t pte_alloc_one(struct mm_struct *mm, | ||
184 | unsigned long address) | ||
185 | { | ||
186 | struct page *page; | ||
187 | pte_t *pte; | ||
188 | |||
189 | pte = (pte_t *)__get_free_page(GFP_KERNEL | __GFP_ZERO | __GFP_ACCOUNT); | ||
190 | if (!pte) | ||
191 | return NULL; | ||
192 | page = virt_to_page(pte); | ||
193 | if (!pgtable_page_ctor(page)) { | ||
194 | __free_page(page); | ||
195 | return NULL; | ||
196 | } | ||
197 | return pte; | ||
198 | } | ||
199 | #else /* if CONFIG_PPC_64K_PAGES */ | ||
200 | |||
201 | static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, | 176 | static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, |
202 | unsigned long address) | 177 | unsigned long address) |
203 | { | 178 | { |
@@ -209,7 +184,6 @@ static inline pgtable_t pte_alloc_one(struct mm_struct *mm, | |||
209 | { | 184 | { |
210 | return (pgtable_t)pte_fragment_alloc(mm, address, 0); | 185 | return (pgtable_t)pte_fragment_alloc(mm, address, 0); |
211 | } | 186 | } |
212 | #endif | ||
213 | 187 | ||
214 | static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) | 188 | static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) |
215 | { | 189 | { |
@@ -229,7 +203,7 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table, | |||
229 | * ahead and flush the page walk cache | 203 | * ahead and flush the page walk cache |
230 | */ | 204 | */ |
231 | flush_tlb_pgtable(tlb, address); | 205 | flush_tlb_pgtable(tlb, address); |
232 | pgtable_free_tlb(tlb, table, 0); | 206 | pgtable_free_tlb(tlb, table, PTE_INDEX); |
233 | } | 207 | } |
234 | 208 | ||
235 | #define check_pgt_cache() do { } while (0) | 209 | #define check_pgt_cache() do { } while (0) |
diff --git a/arch/powerpc/include/asm/book3s/64/pgtable.h b/arch/powerpc/include/asm/book3s/64/pgtable.h index 47b5ffc8715d..42fe7c2ff2df 100644 --- a/arch/powerpc/include/asm/book3s/64/pgtable.h +++ b/arch/powerpc/include/asm/book3s/64/pgtable.h | |||
@@ -212,13 +212,13 @@ extern unsigned long __pte_index_size; | |||
212 | extern unsigned long __pmd_index_size; | 212 | extern unsigned long __pmd_index_size; |
213 | extern unsigned long __pud_index_size; | 213 | extern unsigned long __pud_index_size; |
214 | extern unsigned long __pgd_index_size; | 214 | extern unsigned long __pgd_index_size; |
215 | extern unsigned long __pmd_cache_index; | ||
216 | extern unsigned long __pud_cache_index; | 215 | extern unsigned long __pud_cache_index; |
217 | #define PTE_INDEX_SIZE __pte_index_size | 216 | #define PTE_INDEX_SIZE __pte_index_size |
218 | #define PMD_INDEX_SIZE __pmd_index_size | 217 | #define PMD_INDEX_SIZE __pmd_index_size |
219 | #define PUD_INDEX_SIZE __pud_index_size | 218 | #define PUD_INDEX_SIZE __pud_index_size |
220 | #define PGD_INDEX_SIZE __pgd_index_size | 219 | #define PGD_INDEX_SIZE __pgd_index_size |
221 | #define PMD_CACHE_INDEX __pmd_cache_index | 220 | /* pmd table use page table fragments */ |
221 | #define PMD_CACHE_INDEX 0 | ||
222 | #define PUD_CACHE_INDEX __pud_cache_index | 222 | #define PUD_CACHE_INDEX __pud_cache_index |
223 | /* | 223 | /* |
224 | * Because of use of pte fragments and THP, size of page table | 224 | * Because of use of pte fragments and THP, size of page table |
@@ -246,6 +246,12 @@ extern unsigned long __pte_frag_size_shift; | |||
246 | #define PTE_FRAG_SIZE_SHIFT __pte_frag_size_shift | 246 | #define PTE_FRAG_SIZE_SHIFT __pte_frag_size_shift |
247 | #define PTE_FRAG_SIZE (1UL << PTE_FRAG_SIZE_SHIFT) | 247 | #define PTE_FRAG_SIZE (1UL << PTE_FRAG_SIZE_SHIFT) |
248 | 248 | ||
249 | extern unsigned long __pmd_frag_nr; | ||
250 | #define PMD_FRAG_NR __pmd_frag_nr | ||
251 | extern unsigned long __pmd_frag_size_shift; | ||
252 | #define PMD_FRAG_SIZE_SHIFT __pmd_frag_size_shift | ||
253 | #define PMD_FRAG_SIZE (1UL << PMD_FRAG_SIZE_SHIFT) | ||
254 | |||
249 | #define PTRS_PER_PTE (1 << PTE_INDEX_SIZE) | 255 | #define PTRS_PER_PTE (1 << PTE_INDEX_SIZE) |
250 | #define PTRS_PER_PMD (1 << PMD_INDEX_SIZE) | 256 | #define PTRS_PER_PMD (1 << PMD_INDEX_SIZE) |
251 | #define PTRS_PER_PUD (1 << PUD_INDEX_SIZE) | 257 | #define PTRS_PER_PUD (1 << PUD_INDEX_SIZE) |
@@ -273,6 +279,16 @@ extern unsigned long __pte_frag_size_shift; | |||
273 | /* Bits to mask out from a PGD to get to the PUD page */ | 279 | /* Bits to mask out from a PGD to get to the PUD page */ |
274 | #define PGD_MASKED_BITS 0xc0000000000000ffUL | 280 | #define PGD_MASKED_BITS 0xc0000000000000ffUL |
275 | 281 | ||
282 | /* | ||
283 | * Used as an indicator for rcu callback functions | ||
284 | */ | ||
285 | enum pgtable_index { | ||
286 | PTE_INDEX = 0, | ||
287 | PMD_INDEX, | ||
288 | PUD_INDEX, | ||
289 | PGD_INDEX, | ||
290 | }; | ||
291 | |||
276 | extern unsigned long __vmalloc_start; | 292 | extern unsigned long __vmalloc_start; |
277 | extern unsigned long __vmalloc_end; | 293 | extern unsigned long __vmalloc_end; |
278 | #define VMALLOC_START __vmalloc_start | 294 | #define VMALLOC_START __vmalloc_start |
@@ -751,12 +767,14 @@ static inline bool check_pte_access(unsigned long access, unsigned long ptev) | |||
751 | * Generic functions with hash/radix callbacks | 767 | * Generic functions with hash/radix callbacks |
752 | */ | 768 | */ |
753 | 769 | ||
754 | static inline void __ptep_set_access_flags(struct mm_struct *mm, | 770 | static inline void __ptep_set_access_flags(struct vm_area_struct *vma, |
755 | pte_t *ptep, pte_t entry, | 771 | pte_t *ptep, pte_t entry, |
756 | unsigned long address) | 772 | unsigned long address, |
773 | int psize) | ||
757 | { | 774 | { |
758 | if (radix_enabled()) | 775 | if (radix_enabled()) |
759 | return radix__ptep_set_access_flags(mm, ptep, entry, address); | 776 | return radix__ptep_set_access_flags(vma, ptep, entry, |
777 | address, psize); | ||
760 | return hash__ptep_set_access_flags(ptep, entry); | 778 | return hash__ptep_set_access_flags(ptep, entry); |
761 | } | 779 | } |
762 | 780 | ||
diff --git a/arch/powerpc/include/asm/book3s/64/radix-4k.h b/arch/powerpc/include/asm/book3s/64/radix-4k.h index ca366ec86310..863c3e8286fb 100644 --- a/arch/powerpc/include/asm/book3s/64/radix-4k.h +++ b/arch/powerpc/include/asm/book3s/64/radix-4k.h | |||
@@ -15,4 +15,7 @@ | |||
15 | #define RADIX_PTE_FRAG_SIZE_SHIFT (RADIX_PTE_INDEX_SIZE + 3) | 15 | #define RADIX_PTE_FRAG_SIZE_SHIFT (RADIX_PTE_INDEX_SIZE + 3) |
16 | #define RADIX_PTE_FRAG_NR (PAGE_SIZE >> RADIX_PTE_FRAG_SIZE_SHIFT) | 16 | #define RADIX_PTE_FRAG_NR (PAGE_SIZE >> RADIX_PTE_FRAG_SIZE_SHIFT) |
17 | 17 | ||
18 | #define RADIX_PMD_FRAG_SIZE_SHIFT (RADIX_PMD_INDEX_SIZE + 3) | ||
19 | #define RADIX_PMD_FRAG_NR (PAGE_SIZE >> RADIX_PMD_FRAG_SIZE_SHIFT) | ||
20 | |||
18 | #endif /* _ASM_POWERPC_PGTABLE_RADIX_4K_H */ | 21 | #endif /* _ASM_POWERPC_PGTABLE_RADIX_4K_H */ |
diff --git a/arch/powerpc/include/asm/book3s/64/radix-64k.h b/arch/powerpc/include/asm/book3s/64/radix-64k.h index 830082496876..ccb78ca9d0c5 100644 --- a/arch/powerpc/include/asm/book3s/64/radix-64k.h +++ b/arch/powerpc/include/asm/book3s/64/radix-64k.h | |||
@@ -16,4 +16,8 @@ | |||
16 | */ | 16 | */ |
17 | #define RADIX_PTE_FRAG_SIZE_SHIFT (RADIX_PTE_INDEX_SIZE + 3) | 17 | #define RADIX_PTE_FRAG_SIZE_SHIFT (RADIX_PTE_INDEX_SIZE + 3) |
18 | #define RADIX_PTE_FRAG_NR (PAGE_SIZE >> RADIX_PTE_FRAG_SIZE_SHIFT) | 18 | #define RADIX_PTE_FRAG_NR (PAGE_SIZE >> RADIX_PTE_FRAG_SIZE_SHIFT) |
19 | |||
20 | #define RADIX_PMD_FRAG_SIZE_SHIFT (RADIX_PMD_INDEX_SIZE + 3) | ||
21 | #define RADIX_PMD_FRAG_NR (PAGE_SIZE >> RADIX_PMD_FRAG_SIZE_SHIFT) | ||
22 | |||
19 | #endif /* _ASM_POWERPC_PGTABLE_RADIX_64K_H */ | 23 | #endif /* _ASM_POWERPC_PGTABLE_RADIX_64K_H */ |
diff --git a/arch/powerpc/include/asm/book3s/64/radix.h b/arch/powerpc/include/asm/book3s/64/radix.h index 705193e7192f..ef9f96742ce1 100644 --- a/arch/powerpc/include/asm/book3s/64/radix.h +++ b/arch/powerpc/include/asm/book3s/64/radix.h | |||
@@ -124,23 +124,28 @@ extern void radix__mark_rodata_ro(void); | |||
124 | extern void radix__mark_initmem_nx(void); | 124 | extern void radix__mark_initmem_nx(void); |
125 | #endif | 125 | #endif |
126 | 126 | ||
127 | extern void radix__ptep_set_access_flags(struct vm_area_struct *vma, pte_t *ptep, | ||
128 | pte_t entry, unsigned long address, | ||
129 | int psize); | ||
130 | |||
127 | static inline unsigned long __radix_pte_update(pte_t *ptep, unsigned long clr, | 131 | static inline unsigned long __radix_pte_update(pte_t *ptep, unsigned long clr, |
128 | unsigned long set) | 132 | unsigned long set) |
129 | { | 133 | { |
130 | pte_t pte; | 134 | __be64 old_be, tmp_be; |
131 | unsigned long old_pte, new_pte; | 135 | |
132 | 136 | __asm__ __volatile__( | |
133 | do { | 137 | "1: ldarx %0,0,%3 # pte_update\n" |
134 | pte = READ_ONCE(*ptep); | 138 | " andc %1,%0,%5 \n" |
135 | old_pte = pte_val(pte); | 139 | " or %1,%1,%4 \n" |
136 | new_pte = (old_pte | set) & ~clr; | 140 | " stdcx. %1,0,%3 \n" |
137 | 141 | " bne- 1b" | |
138 | } while (!pte_xchg(ptep, __pte(old_pte), __pte(new_pte))); | 142 | : "=&r" (old_be), "=&r" (tmp_be), "=m" (*ptep) |
139 | 143 | : "r" (ptep), "r" (cpu_to_be64(set)), "r" (cpu_to_be64(clr)) | |
140 | return old_pte; | 144 | : "cc" ); |
145 | |||
146 | return be64_to_cpu(old_be); | ||
141 | } | 147 | } |
142 | 148 | ||
143 | |||
144 | static inline unsigned long radix__pte_update(struct mm_struct *mm, | 149 | static inline unsigned long radix__pte_update(struct mm_struct *mm, |
145 | unsigned long addr, | 150 | unsigned long addr, |
146 | pte_t *ptep, unsigned long clr, | 151 | pte_t *ptep, unsigned long clr, |
@@ -176,48 +181,14 @@ static inline pte_t radix__ptep_get_and_clear_full(struct mm_struct *mm, | |||
176 | unsigned long old_pte; | 181 | unsigned long old_pte; |
177 | 182 | ||
178 | if (full) { | 183 | if (full) { |
179 | /* | 184 | old_pte = pte_val(*ptep); |
180 | * If we are trying to clear the pte, we can skip | 185 | *ptep = __pte(0); |
181 | * the DD1 pte update sequence and batch the tlb flush. The | ||
182 | * tlb flush batching is done by mmu gather code. We | ||
183 | * still keep the cmp_xchg update to make sure we get | ||
184 | * correct R/C bit which might be updated via Nest MMU. | ||
185 | */ | ||
186 | old_pte = __radix_pte_update(ptep, ~0ul, 0); | ||
187 | } else | 186 | } else |
188 | old_pte = radix__pte_update(mm, addr, ptep, ~0ul, 0, 0); | 187 | old_pte = radix__pte_update(mm, addr, ptep, ~0ul, 0, 0); |
189 | 188 | ||
190 | return __pte(old_pte); | 189 | return __pte(old_pte); |
191 | } | 190 | } |
192 | 191 | ||
193 | /* | ||
194 | * Set the dirty and/or accessed bits atomically in a linux PTE, this | ||
195 | * function doesn't need to invalidate tlb. | ||
196 | */ | ||
197 | static inline void radix__ptep_set_access_flags(struct mm_struct *mm, | ||
198 | pte_t *ptep, pte_t entry, | ||
199 | unsigned long address) | ||
200 | { | ||
201 | |||
202 | unsigned long set = pte_val(entry) & (_PAGE_DIRTY | _PAGE_ACCESSED | | ||
203 | _PAGE_RW | _PAGE_EXEC); | ||
204 | |||
205 | if (cpu_has_feature(CPU_FTR_POWER9_DD1)) { | ||
206 | |||
207 | unsigned long old_pte, new_pte; | ||
208 | |||
209 | old_pte = __radix_pte_update(ptep, ~0, 0); | ||
210 | /* | ||
211 | * new value of pte | ||
212 | */ | ||
213 | new_pte = old_pte | set; | ||
214 | radix__flush_tlb_pte_p9_dd1(old_pte, mm, address); | ||
215 | __radix_pte_update(ptep, 0, new_pte); | ||
216 | } else | ||
217 | __radix_pte_update(ptep, 0, set); | ||
218 | asm volatile("ptesync" : : : "memory"); | ||
219 | } | ||
220 | |||
221 | static inline int radix__pte_same(pte_t pte_a, pte_t pte_b) | 192 | static inline int radix__pte_same(pte_t pte_a, pte_t pte_b) |
222 | { | 193 | { |
223 | return ((pte_raw(pte_a) ^ pte_raw(pte_b)) == 0); | 194 | return ((pte_raw(pte_a) ^ pte_raw(pte_b)) == 0); |
@@ -232,7 +203,24 @@ static inline void radix__set_pte_at(struct mm_struct *mm, unsigned long addr, | |||
232 | pte_t *ptep, pte_t pte, int percpu) | 203 | pte_t *ptep, pte_t pte, int percpu) |
233 | { | 204 | { |
234 | *ptep = pte; | 205 | *ptep = pte; |
235 | asm volatile("ptesync" : : : "memory"); | 206 | |
207 | /* | ||
208 | * The architecture suggests a ptesync after setting the pte, which | ||
209 | * orders the store that updates the pte with subsequent page table | ||
210 | * walk accesses which may load the pte. Without this it may be | ||
211 | * possible for a subsequent access to result in spurious fault. | ||
212 | * | ||
213 | * This is not necessary for correctness, because a spurious fault | ||
214 | * is tolerated by the page fault handler, and this store will | ||
215 | * eventually be seen. In testing, there was no noticable increase | ||
216 | * in user faults on POWER9. Avoiding ptesync here is a significant | ||
217 | * win for things like fork. If a future microarchitecture benefits | ||
218 | * from ptesync, it should probably go into update_mmu_cache, rather | ||
219 | * than set_pte_at (which is used to set ptes unrelated to faults). | ||
220 | * | ||
221 | * Spurious faults to vmalloc region are not tolerated, so there is | ||
222 | * a ptesync in flush_cache_vmap. | ||
223 | */ | ||
236 | } | 224 | } |
237 | 225 | ||
238 | static inline int radix__pmd_bad(pmd_t pmd) | 226 | static inline int radix__pmd_bad(pmd_t pmd) |
diff --git a/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h b/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h index 19b45ba6caf9..ef5c3f2994c9 100644 --- a/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h +++ b/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h | |||
@@ -51,4 +51,11 @@ extern void radix__flush_tlb_all(void); | |||
51 | extern void radix__flush_tlb_pte_p9_dd1(unsigned long old_pte, struct mm_struct *mm, | 51 | extern void radix__flush_tlb_pte_p9_dd1(unsigned long old_pte, struct mm_struct *mm, |
52 | unsigned long address); | 52 | unsigned long address); |
53 | 53 | ||
54 | extern void radix__flush_tlb_lpid_page(unsigned int lpid, | ||
55 | unsigned long addr, | ||
56 | unsigned long page_size); | ||
57 | extern void radix__flush_pwc_lpid(unsigned int lpid); | ||
58 | extern void radix__local_flush_tlb_lpid(unsigned int lpid); | ||
59 | extern void radix__local_flush_tlb_lpid_guest(unsigned int lpid); | ||
60 | |||
54 | #endif | 61 | #endif |
diff --git a/arch/powerpc/include/asm/book3s/64/tlbflush.h b/arch/powerpc/include/asm/book3s/64/tlbflush.h index 0cac17253513..ebf572ea621e 100644 --- a/arch/powerpc/include/asm/book3s/64/tlbflush.h +++ b/arch/powerpc/include/asm/book3s/64/tlbflush.h | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | #define MMU_NO_CONTEXT ~0UL | 5 | #define MMU_NO_CONTEXT ~0UL |
6 | 6 | ||
7 | 7 | #include <linux/mm_types.h> | |
8 | #include <asm/book3s/64/tlbflush-hash.h> | 8 | #include <asm/book3s/64/tlbflush-hash.h> |
9 | #include <asm/book3s/64/tlbflush-radix.h> | 9 | #include <asm/book3s/64/tlbflush-radix.h> |
10 | 10 | ||
@@ -137,6 +137,16 @@ static inline void flush_all_mm(struct mm_struct *mm) | |||
137 | #define flush_tlb_page(vma, addr) local_flush_tlb_page(vma, addr) | 137 | #define flush_tlb_page(vma, addr) local_flush_tlb_page(vma, addr) |
138 | #define flush_all_mm(mm) local_flush_all_mm(mm) | 138 | #define flush_all_mm(mm) local_flush_all_mm(mm) |
139 | #endif /* CONFIG_SMP */ | 139 | #endif /* CONFIG_SMP */ |
140 | |||
141 | #define flush_tlb_fix_spurious_fault flush_tlb_fix_spurious_fault | ||
142 | static inline void flush_tlb_fix_spurious_fault(struct vm_area_struct *vma, | ||
143 | unsigned long address) | ||
144 | { | ||
145 | /* See ptep_set_access_flags comment */ | ||
146 | if (atomic_read(&vma->vm_mm->context.copros) > 0) | ||
147 | flush_tlb_page(vma, address); | ||
148 | } | ||
149 | |||
140 | /* | 150 | /* |
141 | * flush the page walk cache for the address | 151 | * flush the page walk cache for the address |
142 | */ | 152 | */ |
diff --git a/arch/powerpc/include/asm/cache.h b/arch/powerpc/include/asm/cache.h index c1d257aa4c2d..66298461b640 100644 --- a/arch/powerpc/include/asm/cache.h +++ b/arch/powerpc/include/asm/cache.h | |||
@@ -9,11 +9,14 @@ | |||
9 | #if defined(CONFIG_PPC_8xx) || defined(CONFIG_403GCX) | 9 | #if defined(CONFIG_PPC_8xx) || defined(CONFIG_403GCX) |
10 | #define L1_CACHE_SHIFT 4 | 10 | #define L1_CACHE_SHIFT 4 |
11 | #define MAX_COPY_PREFETCH 1 | 11 | #define MAX_COPY_PREFETCH 1 |
12 | #define IFETCH_ALIGN_SHIFT 2 | ||
12 | #elif defined(CONFIG_PPC_E500MC) | 13 | #elif defined(CONFIG_PPC_E500MC) |
13 | #define L1_CACHE_SHIFT 6 | 14 | #define L1_CACHE_SHIFT 6 |
14 | #define MAX_COPY_PREFETCH 4 | 15 | #define MAX_COPY_PREFETCH 4 |
16 | #define IFETCH_ALIGN_SHIFT 3 | ||
15 | #elif defined(CONFIG_PPC32) | 17 | #elif defined(CONFIG_PPC32) |
16 | #define MAX_COPY_PREFETCH 4 | 18 | #define MAX_COPY_PREFETCH 4 |
19 | #define IFETCH_ALIGN_SHIFT 3 /* 603 fetches 2 insn at a time */ | ||
17 | #if defined(CONFIG_PPC_47x) | 20 | #if defined(CONFIG_PPC_47x) |
18 | #define L1_CACHE_SHIFT 7 | 21 | #define L1_CACHE_SHIFT 7 |
19 | #else | 22 | #else |
diff --git a/arch/powerpc/include/asm/cacheflush.h b/arch/powerpc/include/asm/cacheflush.h index 11843e37d9cf..0d72ec75da63 100644 --- a/arch/powerpc/include/asm/cacheflush.h +++ b/arch/powerpc/include/asm/cacheflush.h | |||
@@ -23,9 +23,21 @@ | |||
23 | #define flush_cache_range(vma, start, end) do { } while (0) | 23 | #define flush_cache_range(vma, start, end) do { } while (0) |
24 | #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) | 24 | #define flush_cache_page(vma, vmaddr, pfn) do { } while (0) |
25 | #define flush_icache_page(vma, page) do { } while (0) | 25 | #define flush_icache_page(vma, page) do { } while (0) |
26 | #define flush_cache_vmap(start, end) do { } while (0) | ||
27 | #define flush_cache_vunmap(start, end) do { } while (0) | 26 | #define flush_cache_vunmap(start, end) do { } while (0) |
28 | 27 | ||
28 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
29 | /* | ||
30 | * Book3s has no ptesync after setting a pte, so without this ptesync it's | ||
31 | * possible for a kernel virtual mapping access to return a spurious fault | ||
32 | * if it's accessed right after the pte is set. The page fault handler does | ||
33 | * not expect this type of fault. flush_cache_vmap is not exactly the right | ||
34 | * place to put this, but it seems to work well enough. | ||
35 | */ | ||
36 | #define flush_cache_vmap(start, end) do { asm volatile("ptesync" ::: "memory"); } while (0) | ||
37 | #else | ||
38 | #define flush_cache_vmap(start, end) do { } while (0) | ||
39 | #endif | ||
40 | |||
29 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 | 41 | #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 |
30 | extern void flush_dcache_page(struct page *page); | 42 | extern void flush_dcache_page(struct page *page); |
31 | #define flush_dcache_mmap_lock(mapping) do { } while (0) | 43 | #define flush_dcache_mmap_lock(mapping) do { } while (0) |
diff --git a/arch/powerpc/include/asm/checksum.h b/arch/powerpc/include/asm/checksum.h index 842124b199b5..a78a57e5058d 100644 --- a/arch/powerpc/include/asm/checksum.h +++ b/arch/powerpc/include/asm/checksum.h | |||
@@ -12,6 +12,8 @@ | |||
12 | #ifdef CONFIG_GENERIC_CSUM | 12 | #ifdef CONFIG_GENERIC_CSUM |
13 | #include <asm-generic/checksum.h> | 13 | #include <asm-generic/checksum.h> |
14 | #else | 14 | #else |
15 | #include <linux/bitops.h> | ||
16 | #include <linux/in6.h> | ||
15 | /* | 17 | /* |
16 | * Computes the checksum of a memory block at src, length len, | 18 | * Computes the checksum of a memory block at src, length len, |
17 | * and adds in "sum" (32-bit), while copying the block to dst. | 19 | * and adds in "sum" (32-bit), while copying the block to dst. |
@@ -55,11 +57,7 @@ static inline __sum16 csum_fold(__wsum sum) | |||
55 | 57 | ||
56 | static inline u32 from64to32(u64 x) | 58 | static inline u32 from64to32(u64 x) |
57 | { | 59 | { |
58 | /* add up 32-bit and 32-bit for 32+c bit */ | 60 | return (x + ror64(x, 32)) >> 32; |
59 | x = (x & 0xffffffff) + (x >> 32); | ||
60 | /* add up carry.. */ | ||
61 | x = (x & 0xffffffff) + (x >> 32); | ||
62 | return (u32)x; | ||
63 | } | 61 | } |
64 | 62 | ||
65 | static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, __u32 len, | 63 | static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, __u32 len, |
@@ -112,7 +110,7 @@ static inline __wsum csum_add(__wsum csum, __wsum addend) | |||
112 | 110 | ||
113 | #ifdef __powerpc64__ | 111 | #ifdef __powerpc64__ |
114 | res += (__force u64)addend; | 112 | res += (__force u64)addend; |
115 | return (__force __wsum) from64to32(res); | 113 | return (__force __wsum)((u32)res + (res >> 32)); |
116 | #else | 114 | #else |
117 | asm("addc %0,%0,%1;" | 115 | asm("addc %0,%0,%1;" |
118 | "addze %0,%0;" | 116 | "addze %0,%0;" |
@@ -214,6 +212,11 @@ static inline __sum16 ip_compute_csum(const void *buff, int len) | |||
214 | return csum_fold(csum_partial(buff, len, 0)); | 212 | return csum_fold(csum_partial(buff, len, 0)); |
215 | } | 213 | } |
216 | 214 | ||
215 | #define _HAVE_ARCH_IPV6_CSUM | ||
216 | __sum16 csum_ipv6_magic(const struct in6_addr *saddr, | ||
217 | const struct in6_addr *daddr, | ||
218 | __u32 len, __u8 proto, __wsum sum); | ||
219 | |||
217 | #endif | 220 | #endif |
218 | #endif /* __KERNEL__ */ | 221 | #endif /* __KERNEL__ */ |
219 | #endif | 222 | #endif |
diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h index 66fcab13c8b4..9c0a3083571b 100644 --- a/arch/powerpc/include/asm/cputable.h +++ b/arch/powerpc/include/asm/cputable.h | |||
@@ -215,6 +215,7 @@ static inline void cpu_feature_keys_init(void) { } | |||
215 | #define CPU_FTR_P9_TM_HV_ASSIST LONG_ASM_CONST(0x0000100000000000) | 215 | #define CPU_FTR_P9_TM_HV_ASSIST LONG_ASM_CONST(0x0000100000000000) |
216 | #define CPU_FTR_P9_TM_XER_SO_BUG LONG_ASM_CONST(0x0000200000000000) | 216 | #define CPU_FTR_P9_TM_XER_SO_BUG LONG_ASM_CONST(0x0000200000000000) |
217 | #define CPU_FTR_P9_TLBIE_BUG LONG_ASM_CONST(0x0000400000000000) | 217 | #define CPU_FTR_P9_TLBIE_BUG LONG_ASM_CONST(0x0000400000000000) |
218 | #define CPU_FTR_P9_TIDR LONG_ASM_CONST(0x0000800000000000) | ||
218 | 219 | ||
219 | #ifndef __ASSEMBLY__ | 220 | #ifndef __ASSEMBLY__ |
220 | 221 | ||
@@ -462,7 +463,7 @@ static inline void cpu_feature_keys_init(void) { } | |||
462 | CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \ | 463 | CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY | \ |
463 | CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_ARCH_207S | \ | 464 | CPU_FTR_DBELL | CPU_FTR_HAS_PPR | CPU_FTR_ARCH_207S | \ |
464 | CPU_FTR_TM_COMP | CPU_FTR_ARCH_300 | CPU_FTR_PKEY | \ | 465 | CPU_FTR_TM_COMP | CPU_FTR_ARCH_300 | CPU_FTR_PKEY | \ |
465 | CPU_FTR_P9_TLBIE_BUG) | 466 | CPU_FTR_P9_TLBIE_BUG | CPU_FTR_P9_TIDR) |
466 | #define CPU_FTRS_POWER9_DD1 ((CPU_FTRS_POWER9 | CPU_FTR_POWER9_DD1) & \ | 467 | #define CPU_FTRS_POWER9_DD1 ((CPU_FTRS_POWER9 | CPU_FTR_POWER9_DD1) & \ |
467 | (~CPU_FTR_SAO)) | 468 | (~CPU_FTR_SAO)) |
468 | #define CPU_FTRS_POWER9_DD2_0 CPU_FTRS_POWER9 | 469 | #define CPU_FTRS_POWER9_DD2_0 CPU_FTRS_POWER9 |
diff --git a/arch/powerpc/include/asm/cputime.h b/arch/powerpc/include/asm/cputime.h index 99b541865d8d..bc4903badb3f 100644 --- a/arch/powerpc/include/asm/cputime.h +++ b/arch/powerpc/include/asm/cputime.h | |||
@@ -47,9 +47,23 @@ static inline unsigned long cputime_to_usecs(const cputime_t ct) | |||
47 | * has to be populated in the new task | 47 | * has to be populated in the new task |
48 | */ | 48 | */ |
49 | #ifdef CONFIG_PPC64 | 49 | #ifdef CONFIG_PPC64 |
50 | #define get_accounting(tsk) (&get_paca()->accounting) | ||
50 | static inline void arch_vtime_task_switch(struct task_struct *tsk) { } | 51 | static inline void arch_vtime_task_switch(struct task_struct *tsk) { } |
51 | #else | 52 | #else |
52 | void arch_vtime_task_switch(struct task_struct *tsk); | 53 | #define get_accounting(tsk) (&task_thread_info(tsk)->accounting) |
54 | /* | ||
55 | * Called from the context switch with interrupts disabled, to charge all | ||
56 | * accumulated times to the current process, and to prepare accounting on | ||
57 | * the next process. | ||
58 | */ | ||
59 | static inline void arch_vtime_task_switch(struct task_struct *prev) | ||
60 | { | ||
61 | struct cpu_accounting_data *acct = get_accounting(current); | ||
62 | struct cpu_accounting_data *acct0 = get_accounting(prev); | ||
63 | |||
64 | acct->starttime = acct0->starttime; | ||
65 | acct->startspurr = acct0->startspurr; | ||
66 | } | ||
53 | #endif | 67 | #endif |
54 | 68 | ||
55 | #endif /* __KERNEL__ */ | 69 | #endif /* __KERNEL__ */ |
diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h index c2266ca61853..677102baf3cd 100644 --- a/arch/powerpc/include/asm/eeh.h +++ b/arch/powerpc/include/asm/eeh.h | |||
@@ -106,6 +106,9 @@ struct eeh_pe { | |||
106 | #define eeh_pe_for_each_dev(pe, edev, tmp) \ | 106 | #define eeh_pe_for_each_dev(pe, edev, tmp) \ |
107 | list_for_each_entry_safe(edev, tmp, &pe->edevs, list) | 107 | list_for_each_entry_safe(edev, tmp, &pe->edevs, list) |
108 | 108 | ||
109 | #define eeh_for_each_pe(root, pe) \ | ||
110 | for (pe = root; pe; pe = eeh_pe_next(pe, root)) | ||
111 | |||
109 | static inline bool eeh_pe_passed(struct eeh_pe *pe) | 112 | static inline bool eeh_pe_passed(struct eeh_pe *pe) |
110 | { | 113 | { |
111 | return pe ? !!atomic_read(&pe->pass_dev_cnt) : false; | 114 | return pe ? !!atomic_read(&pe->pass_dev_cnt) : false; |
@@ -262,19 +265,21 @@ static inline bool eeh_state_active(int state) | |||
262 | == (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE); | 265 | == (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE); |
263 | } | 266 | } |
264 | 267 | ||
265 | typedef void *(*eeh_traverse_func)(void *data, void *flag); | 268 | typedef void *(*eeh_edev_traverse_func)(struct eeh_dev *edev, void *flag); |
269 | typedef void *(*eeh_pe_traverse_func)(struct eeh_pe *pe, void *flag); | ||
266 | void eeh_set_pe_aux_size(int size); | 270 | void eeh_set_pe_aux_size(int size); |
267 | int eeh_phb_pe_create(struct pci_controller *phb); | 271 | int eeh_phb_pe_create(struct pci_controller *phb); |
268 | struct eeh_pe *eeh_phb_pe_get(struct pci_controller *phb); | 272 | struct eeh_pe *eeh_phb_pe_get(struct pci_controller *phb); |
273 | struct eeh_pe *eeh_pe_next(struct eeh_pe *pe, struct eeh_pe *root); | ||
269 | struct eeh_pe *eeh_pe_get(struct pci_controller *phb, | 274 | struct eeh_pe *eeh_pe_get(struct pci_controller *phb, |
270 | int pe_no, int config_addr); | 275 | int pe_no, int config_addr); |
271 | int eeh_add_to_parent_pe(struct eeh_dev *edev); | 276 | int eeh_add_to_parent_pe(struct eeh_dev *edev); |
272 | int eeh_rmv_from_parent_pe(struct eeh_dev *edev); | 277 | int eeh_rmv_from_parent_pe(struct eeh_dev *edev); |
273 | void eeh_pe_update_time_stamp(struct eeh_pe *pe); | 278 | void eeh_pe_update_time_stamp(struct eeh_pe *pe); |
274 | void *eeh_pe_traverse(struct eeh_pe *root, | 279 | void *eeh_pe_traverse(struct eeh_pe *root, |
275 | eeh_traverse_func fn, void *flag); | 280 | eeh_pe_traverse_func fn, void *flag); |
276 | void *eeh_pe_dev_traverse(struct eeh_pe *root, | 281 | void *eeh_pe_dev_traverse(struct eeh_pe *root, |
277 | eeh_traverse_func fn, void *flag); | 282 | eeh_edev_traverse_func fn, void *flag); |
278 | void eeh_pe_restore_bars(struct eeh_pe *pe); | 283 | void eeh_pe_restore_bars(struct eeh_pe *pe); |
279 | const char *eeh_pe_loc_get(struct eeh_pe *pe); | 284 | const char *eeh_pe_loc_get(struct eeh_pe *pe); |
280 | struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe); | 285 | struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe); |
diff --git a/arch/powerpc/include/asm/feature-fixups.h b/arch/powerpc/include/asm/feature-fixups.h index a9b64df34e2a..fcfd05672b1b 100644 --- a/arch/powerpc/include/asm/feature-fixups.h +++ b/arch/powerpc/include/asm/feature-fixups.h | |||
@@ -211,6 +211,14 @@ label##3: \ | |||
211 | FTR_ENTRY_OFFSET 951b-952b; \ | 211 | FTR_ENTRY_OFFSET 951b-952b; \ |
212 | .popsection; | 212 | .popsection; |
213 | 213 | ||
214 | #define NOSPEC_BARRIER_FIXUP_SECTION \ | ||
215 | 953: \ | ||
216 | .pushsection __barrier_nospec_fixup,"a"; \ | ||
217 | .align 2; \ | ||
218 | 954: \ | ||
219 | FTR_ENTRY_OFFSET 953b-954b; \ | ||
220 | .popsection; | ||
221 | |||
214 | 222 | ||
215 | #ifndef __ASSEMBLY__ | 223 | #ifndef __ASSEMBLY__ |
216 | #include <linux/types.h> | 224 | #include <linux/types.h> |
@@ -219,6 +227,7 @@ extern long stf_barrier_fallback; | |||
219 | extern long __start___stf_entry_barrier_fixup, __stop___stf_entry_barrier_fixup; | 227 | extern long __start___stf_entry_barrier_fixup, __stop___stf_entry_barrier_fixup; |
220 | extern long __start___stf_exit_barrier_fixup, __stop___stf_exit_barrier_fixup; | 228 | extern long __start___stf_exit_barrier_fixup, __stop___stf_exit_barrier_fixup; |
221 | extern long __start___rfi_flush_fixup, __stop___rfi_flush_fixup; | 229 | extern long __start___rfi_flush_fixup, __stop___rfi_flush_fixup; |
230 | extern long __start___barrier_nospec_fixup, __stop___barrier_nospec_fixup; | ||
222 | 231 | ||
223 | void apply_feature_fixups(void); | 232 | void apply_feature_fixups(void); |
224 | void setup_feature_keys(void); | 233 | void setup_feature_keys(void); |
diff --git a/arch/powerpc/include/asm/ftrace.h b/arch/powerpc/include/asm/ftrace.h index b2dabd06659d..3dfb80b86561 100644 --- a/arch/powerpc/include/asm/ftrace.h +++ b/arch/powerpc/include/asm/ftrace.h | |||
@@ -48,9 +48,6 @@ | |||
48 | #else /* !__ASSEMBLY__ */ | 48 | #else /* !__ASSEMBLY__ */ |
49 | extern void _mcount(void); | 49 | extern void _mcount(void); |
50 | 50 | ||
51 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
52 | # define FTRACE_ADDR ((unsigned long)ftrace_caller) | ||
53 | # define FTRACE_REGS_ADDR FTRACE_ADDR | ||
54 | static inline unsigned long ftrace_call_adjust(unsigned long addr) | 51 | static inline unsigned long ftrace_call_adjust(unsigned long addr) |
55 | { | 52 | { |
56 | /* reloction of mcount call site is the same as the address */ | 53 | /* reloction of mcount call site is the same as the address */ |
@@ -60,15 +57,15 @@ static inline unsigned long ftrace_call_adjust(unsigned long addr) | |||
60 | struct dyn_arch_ftrace { | 57 | struct dyn_arch_ftrace { |
61 | struct module *mod; | 58 | struct module *mod; |
62 | }; | 59 | }; |
63 | #endif /* CONFIG_DYNAMIC_FTRACE */ | ||
64 | #endif /* __ASSEMBLY__ */ | 60 | #endif /* __ASSEMBLY__ */ |
65 | 61 | ||
66 | #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS | 62 | #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS |
67 | #define ARCH_SUPPORTS_FTRACE_OPS 1 | 63 | #define ARCH_SUPPORTS_FTRACE_OPS 1 |
68 | #endif | 64 | #endif |
69 | #endif | 65 | #endif /* CONFIG_FUNCTION_TRACER */ |
70 | 66 | ||
71 | #if defined(CONFIG_FTRACE_SYSCALLS) && !defined(__ASSEMBLY__) | 67 | #ifndef __ASSEMBLY__ |
68 | #ifdef CONFIG_FTRACE_SYSCALLS | ||
72 | /* | 69 | /* |
73 | * Some syscall entry functions on powerpc start with "ppc_" (fork and clone, | 70 | * Some syscall entry functions on powerpc start with "ppc_" (fork and clone, |
74 | * for instance) or ppc32_/ppc64_. We should also match the sys_ variant with | 71 | * for instance) or ppc32_/ppc64_. We should also match the sys_ variant with |
@@ -94,7 +91,25 @@ static inline bool arch_syscall_match_sym_name(const char *sym, const char *name | |||
94 | (!strncmp(sym, "ppc32_", 6) && !strcmp(sym + 6, name + 4)) || | 91 | (!strncmp(sym, "ppc32_", 6) && !strcmp(sym + 6, name + 4)) || |
95 | (!strncmp(sym, "ppc64_", 6) && !strcmp(sym + 6, name + 4)); | 92 | (!strncmp(sym, "ppc64_", 6) && !strcmp(sym + 6, name + 4)); |
96 | } | 93 | } |
97 | #endif | 94 | #endif /* PPC64_ELF_ABI_v1 */ |
98 | #endif /* CONFIG_FTRACE_SYSCALLS && !__ASSEMBLY__ */ | 95 | #endif /* CONFIG_FTRACE_SYSCALLS */ |
96 | |||
97 | #ifdef CONFIG_PPC64 | ||
98 | #include <asm/paca.h> | ||
99 | |||
100 | static inline void this_cpu_disable_ftrace(void) | ||
101 | { | ||
102 | get_paca()->ftrace_enabled = 0; | ||
103 | } | ||
104 | |||
105 | static inline void this_cpu_enable_ftrace(void) | ||
106 | { | ||
107 | get_paca()->ftrace_enabled = 1; | ||
108 | } | ||
109 | #else /* CONFIG_PPC64 */ | ||
110 | static inline void this_cpu_disable_ftrace(void) { } | ||
111 | static inline void this_cpu_enable_ftrace(void) { } | ||
112 | #endif /* CONFIG_PPC64 */ | ||
113 | #endif /* !__ASSEMBLY__ */ | ||
99 | 114 | ||
100 | #endif /* _ASM_POWERPC_FTRACE */ | 115 | #endif /* _ASM_POWERPC_FTRACE */ |
diff --git a/arch/powerpc/include/asm/hardirq.h b/arch/powerpc/include/asm/hardirq.h index 383f628acbf8..f1e9067bd5ac 100644 --- a/arch/powerpc/include/asm/hardirq.h +++ b/arch/powerpc/include/asm/hardirq.h | |||
@@ -8,6 +8,7 @@ | |||
8 | typedef struct { | 8 | typedef struct { |
9 | unsigned int __softirq_pending; | 9 | unsigned int __softirq_pending; |
10 | unsigned int timer_irqs_event; | 10 | unsigned int timer_irqs_event; |
11 | unsigned int broadcast_irqs_event; | ||
11 | unsigned int timer_irqs_others; | 12 | unsigned int timer_irqs_others; |
12 | unsigned int pmu_irqs; | 13 | unsigned int pmu_irqs; |
13 | unsigned int mce_exceptions; | 14 | unsigned int mce_exceptions; |
diff --git a/arch/powerpc/include/asm/hugetlb.h b/arch/powerpc/include/asm/hugetlb.h index 78540c074d70..3225eb6402cc 100644 --- a/arch/powerpc/include/asm/hugetlb.h +++ b/arch/powerpc/include/asm/hugetlb.h | |||
@@ -166,22 +166,9 @@ static inline pte_t huge_pte_wrprotect(pte_t pte) | |||
166 | return pte_wrprotect(pte); | 166 | return pte_wrprotect(pte); |
167 | } | 167 | } |
168 | 168 | ||
169 | static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma, | 169 | extern int huge_ptep_set_access_flags(struct vm_area_struct *vma, |
170 | unsigned long addr, pte_t *ptep, | 170 | unsigned long addr, pte_t *ptep, |
171 | pte_t pte, int dirty) | 171 | pte_t pte, int dirty); |
172 | { | ||
173 | #ifdef HUGETLB_NEED_PRELOAD | ||
174 | /* | ||
175 | * The "return 1" forces a call of update_mmu_cache, which will write a | ||
176 | * TLB entry. Without this, platforms that don't do a write of the TLB | ||
177 | * entry in the TLB miss handler asm will fault ad infinitum. | ||
178 | */ | ||
179 | ptep_set_access_flags(vma, addr, ptep, pte, dirty); | ||
180 | return 1; | ||
181 | #else | ||
182 | return ptep_set_access_flags(vma, addr, ptep, pte, dirty); | ||
183 | #endif | ||
184 | } | ||
185 | 172 | ||
186 | static inline pte_t huge_ptep_get(pte_t *ptep) | 173 | static inline pte_t huge_ptep_get(pte_t *ptep) |
187 | { | 174 | { |
@@ -202,7 +189,7 @@ static inline void flush_hugetlb_page(struct vm_area_struct *vma, | |||
202 | static inline pte_t *hugepte_offset(hugepd_t hpd, unsigned long addr, | 189 | static inline pte_t *hugepte_offset(hugepd_t hpd, unsigned long addr, |
203 | unsigned pdshift) | 190 | unsigned pdshift) |
204 | { | 191 | { |
205 | return 0; | 192 | return NULL; |
206 | } | 193 | } |
207 | #endif /* CONFIG_HUGETLB_PAGE */ | 194 | #endif /* CONFIG_HUGETLB_PAGE */ |
208 | 195 | ||
diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h index 855e17d158b1..e151774cb577 100644 --- a/arch/powerpc/include/asm/hw_irq.h +++ b/arch/powerpc/include/asm/hw_irq.h | |||
@@ -55,6 +55,7 @@ extern void replay_system_reset(void); | |||
55 | extern void __replay_interrupt(unsigned int vector); | 55 | extern void __replay_interrupt(unsigned int vector); |
56 | 56 | ||
57 | extern void timer_interrupt(struct pt_regs *); | 57 | extern void timer_interrupt(struct pt_regs *); |
58 | extern void timer_broadcast_interrupt(void); | ||
58 | extern void performance_monitor_exception(struct pt_regs *regs); | 59 | extern void performance_monitor_exception(struct pt_regs *regs); |
59 | extern void WatchdogException(struct pt_regs *regs); | 60 | extern void WatchdogException(struct pt_regs *regs); |
60 | extern void unknown_exception(struct pt_regs *regs); | 61 | extern void unknown_exception(struct pt_regs *regs); |
@@ -228,8 +229,8 @@ static inline bool arch_irqs_disabled(void) | |||
228 | #define __hard_irq_enable() asm volatile("wrteei 1" : : : "memory") | 229 | #define __hard_irq_enable() asm volatile("wrteei 1" : : : "memory") |
229 | #define __hard_irq_disable() asm volatile("wrteei 0" : : : "memory") | 230 | #define __hard_irq_disable() asm volatile("wrteei 0" : : : "memory") |
230 | #else | 231 | #else |
231 | #define __hard_irq_enable() __mtmsrd(local_paca->kernel_msr | MSR_EE, 1) | 232 | #define __hard_irq_enable() __mtmsrd(MSR_EE|MSR_RI, 1) |
232 | #define __hard_irq_disable() __mtmsrd(local_paca->kernel_msr, 1) | 233 | #define __hard_irq_disable() __mtmsrd(MSR_RI, 1) |
233 | #endif | 234 | #endif |
234 | 235 | ||
235 | #define hard_irq_disable() do { \ | 236 | #define hard_irq_disable() do { \ |
@@ -237,8 +238,12 @@ static inline bool arch_irqs_disabled(void) | |||
237 | __hard_irq_disable(); \ | 238 | __hard_irq_disable(); \ |
238 | flags = irq_soft_mask_set_return(IRQS_ALL_DISABLED); \ | 239 | flags = irq_soft_mask_set_return(IRQS_ALL_DISABLED); \ |
239 | local_paca->irq_happened |= PACA_IRQ_HARD_DIS; \ | 240 | local_paca->irq_happened |= PACA_IRQ_HARD_DIS; \ |
240 | if (!arch_irqs_disabled_flags(flags)) \ | 241 | if (!arch_irqs_disabled_flags(flags)) { \ |
242 | asm ("stdx %%r1, 0, %1 ;" \ | ||
243 | : "=m" (local_paca->saved_r1) \ | ||
244 | : "b" (&local_paca->saved_r1)); \ | ||
241 | trace_hardirqs_off(); \ | 245 | trace_hardirqs_off(); \ |
246 | } \ | ||
242 | } while(0) | 247 | } while(0) |
243 | 248 | ||
244 | static inline bool lazy_irq_pending(void) | 249 | static inline bool lazy_irq_pending(void) |
diff --git a/arch/powerpc/include/asm/imc-pmu.h b/arch/powerpc/include/asm/imc-pmu.h index d76cb11be3e3..69f516ecb2fd 100644 --- a/arch/powerpc/include/asm/imc-pmu.h +++ b/arch/powerpc/include/asm/imc-pmu.h | |||
@@ -128,4 +128,5 @@ extern int init_imc_pmu(struct device_node *parent, | |||
128 | struct imc_pmu *pmu_ptr, int pmu_id); | 128 | struct imc_pmu *pmu_ptr, int pmu_id); |
129 | extern void thread_imc_disable(void); | 129 | extern void thread_imc_disable(void); |
130 | extern int get_max_nest_dev(void); | 130 | extern int get_max_nest_dev(void); |
131 | extern void unregister_thread_imc(void); | ||
131 | #endif /* __ASM_POWERPC_IMC_PMU_H */ | 132 | #endif /* __ASM_POWERPC_IMC_PMU_H */ |
diff --git a/arch/powerpc/include/asm/io.h b/arch/powerpc/include/asm/io.h index af074923d598..e0331e754568 100644 --- a/arch/powerpc/include/asm/io.h +++ b/arch/powerpc/include/asm/io.h | |||
@@ -367,6 +367,11 @@ static inline void __raw_writeq(unsigned long v, volatile void __iomem *addr) | |||
367 | *(volatile unsigned long __force *)PCI_FIX_ADDR(addr) = v; | 367 | *(volatile unsigned long __force *)PCI_FIX_ADDR(addr) = v; |
368 | } | 368 | } |
369 | 369 | ||
370 | static inline void __raw_writeq_be(unsigned long v, volatile void __iomem *addr) | ||
371 | { | ||
372 | __raw_writeq((__force unsigned long)cpu_to_be64(v), addr); | ||
373 | } | ||
374 | |||
370 | /* | 375 | /* |
371 | * Real mode versions of the above. Those instructions are only supposed | 376 | * Real mode versions of the above. Those instructions are only supposed |
372 | * to be used in hypervisor real mode as per the architecture spec. | 377 | * to be used in hypervisor real mode as per the architecture spec. |
@@ -395,6 +400,11 @@ static inline void __raw_rm_writeq(u64 val, volatile void __iomem *paddr) | |||
395 | : : "r" (val), "r" (paddr) : "memory"); | 400 | : : "r" (val), "r" (paddr) : "memory"); |
396 | } | 401 | } |
397 | 402 | ||
403 | static inline void __raw_rm_writeq_be(u64 val, volatile void __iomem *paddr) | ||
404 | { | ||
405 | __raw_rm_writeq((__force u64)cpu_to_be64(val), paddr); | ||
406 | } | ||
407 | |||
398 | static inline u8 __raw_rm_readb(volatile void __iomem *paddr) | 408 | static inline u8 __raw_rm_readb(volatile void __iomem *paddr) |
399 | { | 409 | { |
400 | u8 ret; | 410 | u8 ret; |
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h index ffe7c71e1132..a47de82fb8e2 100644 --- a/arch/powerpc/include/asm/machdep.h +++ b/arch/powerpc/include/asm/machdep.h | |||
@@ -83,7 +83,7 @@ struct machdep_calls { | |||
83 | 83 | ||
84 | int (*set_rtc_time)(struct rtc_time *); | 84 | int (*set_rtc_time)(struct rtc_time *); |
85 | void (*get_rtc_time)(struct rtc_time *); | 85 | void (*get_rtc_time)(struct rtc_time *); |
86 | unsigned long (*get_boot_time)(void); | 86 | time64_t (*get_boot_time)(void); |
87 | unsigned char (*rtc_read_val)(int addr); | 87 | unsigned char (*rtc_read_val)(int addr); |
88 | void (*rtc_write_val)(int addr, unsigned char val); | 88 | void (*rtc_write_val)(int addr, unsigned char val); |
89 | 89 | ||
diff --git a/arch/powerpc/include/asm/mmu-book3e.h b/arch/powerpc/include/asm/mmu-book3e.h index cda94a0f5146..e20072972e35 100644 --- a/arch/powerpc/include/asm/mmu-book3e.h +++ b/arch/powerpc/include/asm/mmu-book3e.h | |||
@@ -230,10 +230,6 @@ typedef struct { | |||
230 | unsigned int id; | 230 | unsigned int id; |
231 | unsigned int active; | 231 | unsigned int active; |
232 | unsigned long vdso_base; | 232 | unsigned long vdso_base; |
233 | #ifdef CONFIG_PPC_64K_PAGES | ||
234 | /* for 4K PTE fragment support */ | ||
235 | void *pte_frag; | ||
236 | #endif | ||
237 | } mm_context_t; | 233 | } mm_context_t; |
238 | 234 | ||
239 | /* Page size definitions, common between 32 and 64-bit | 235 | /* Page size definitions, common between 32 and 64-bit |
@@ -275,8 +271,6 @@ static inline unsigned int mmu_psize_to_shift(unsigned int mmu_psize) | |||
275 | */ | 271 | */ |
276 | #if defined(CONFIG_PPC_4K_PAGES) | 272 | #if defined(CONFIG_PPC_4K_PAGES) |
277 | #define mmu_virtual_psize MMU_PAGE_4K | 273 | #define mmu_virtual_psize MMU_PAGE_4K |
278 | #elif defined(CONFIG_PPC_64K_PAGES) | ||
279 | #define mmu_virtual_psize MMU_PAGE_64K | ||
280 | #else | 274 | #else |
281 | #error Unsupported page size | 275 | #error Unsupported page size |
282 | #endif | 276 | #endif |
diff --git a/arch/powerpc/include/asm/mmu_context.h b/arch/powerpc/include/asm/mmu_context.h index 1835ca1505d6..896efa559996 100644 --- a/arch/powerpc/include/asm/mmu_context.h +++ b/arch/powerpc/include/asm/mmu_context.h | |||
@@ -250,11 +250,6 @@ static inline bool arch_vma_access_permitted(struct vm_area_struct *vma, | |||
250 | #define thread_pkey_regs_restore(new_thread, old_thread) | 250 | #define thread_pkey_regs_restore(new_thread, old_thread) |
251 | #define thread_pkey_regs_init(thread) | 251 | #define thread_pkey_regs_init(thread) |
252 | 252 | ||
253 | static inline int vma_pkey(struct vm_area_struct *vma) | ||
254 | { | ||
255 | return 0; | ||
256 | } | ||
257 | |||
258 | static inline u64 pte_to_hpte_pkey_bits(u64 pteflags) | 253 | static inline u64 pte_to_hpte_pkey_bits(u64 pteflags) |
259 | { | 254 | { |
260 | return 0x0UL; | 255 | return 0x0UL; |
diff --git a/arch/powerpc/include/asm/module.h b/arch/powerpc/include/asm/module.h index 4f6573934792..d8374f984f39 100644 --- a/arch/powerpc/include/asm/module.h +++ b/arch/powerpc/include/asm/module.h | |||
@@ -50,10 +50,6 @@ struct mod_arch_specific { | |||
50 | unsigned int stubs_section; /* Index of stubs section in module */ | 50 | unsigned int stubs_section; /* Index of stubs section in module */ |
51 | unsigned int toc_section; /* What section is the TOC? */ | 51 | unsigned int toc_section; /* What section is the TOC? */ |
52 | bool toc_fixed; /* Have we fixed up .TOC.? */ | 52 | bool toc_fixed; /* Have we fixed up .TOC.? */ |
53 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
54 | unsigned long toc; | ||
55 | unsigned long tramp; | ||
56 | #endif | ||
57 | 53 | ||
58 | /* For module function descriptor dereference */ | 54 | /* For module function descriptor dereference */ |
59 | unsigned long start_opd; | 55 | unsigned long start_opd; |
@@ -62,10 +58,14 @@ struct mod_arch_specific { | |||
62 | /* Indices of PLT sections within module. */ | 58 | /* Indices of PLT sections within module. */ |
63 | unsigned int core_plt_section; | 59 | unsigned int core_plt_section; |
64 | unsigned int init_plt_section; | 60 | unsigned int init_plt_section; |
61 | #endif /* powerpc64 */ | ||
62 | |||
65 | #ifdef CONFIG_DYNAMIC_FTRACE | 63 | #ifdef CONFIG_DYNAMIC_FTRACE |
66 | unsigned long tramp; | 64 | unsigned long tramp; |
65 | #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS | ||
66 | unsigned long tramp_regs; | ||
67 | #endif | ||
67 | #endif | 68 | #endif |
68 | #endif /* powerpc64 */ | ||
69 | 69 | ||
70 | /* List of BUG addresses, source line numbers and filenames */ | 70 | /* List of BUG addresses, source line numbers and filenames */ |
71 | struct list_head bug_list; | 71 | struct list_head bug_list; |
diff --git a/arch/powerpc/include/asm/mpc52xx.h b/arch/powerpc/include/asm/mpc52xx.h index e94cede14522..ce1e0aabaa64 100644 --- a/arch/powerpc/include/asm/mpc52xx.h +++ b/arch/powerpc/include/asm/mpc52xx.h | |||
@@ -350,14 +350,14 @@ extern struct mpc52xx_suspend mpc52xx_suspend; | |||
350 | extern int __init mpc52xx_pm_init(void); | 350 | extern int __init mpc52xx_pm_init(void); |
351 | extern int mpc52xx_set_wakeup_gpio(u8 pin, u8 level); | 351 | extern int mpc52xx_set_wakeup_gpio(u8 pin, u8 level); |
352 | 352 | ||
353 | #ifdef CONFIG_PPC_LITE5200 | ||
354 | extern int __init lite5200_pm_init(void); | ||
355 | |||
356 | /* lite5200 calls mpc5200 suspend functions, so here they are */ | 353 | /* lite5200 calls mpc5200 suspend functions, so here they are */ |
357 | extern int mpc52xx_pm_prepare(void); | 354 | extern int mpc52xx_pm_prepare(void); |
358 | extern int mpc52xx_pm_enter(suspend_state_t); | 355 | extern int mpc52xx_pm_enter(suspend_state_t); |
359 | extern void mpc52xx_pm_finish(void); | 356 | extern void mpc52xx_pm_finish(void); |
360 | extern char saved_sram[0x4000]; /* reuse buffer from mpc52xx suspend */ | 357 | extern char saved_sram[0x4000]; /* reuse buffer from mpc52xx suspend */ |
358 | |||
359 | #ifdef CONFIG_PPC_LITE5200 | ||
360 | int __init lite5200_pm_init(void); | ||
361 | #endif | 361 | #endif |
362 | #endif /* CONFIG_PM */ | 362 | #endif /* CONFIG_PM */ |
363 | 363 | ||
diff --git a/arch/powerpc/include/asm/nmi.h b/arch/powerpc/include/asm/nmi.h index 9c80939b4d14..0f571e0ebca1 100644 --- a/arch/powerpc/include/asm/nmi.h +++ b/arch/powerpc/include/asm/nmi.h | |||
@@ -8,4 +8,10 @@ extern void arch_touch_nmi_watchdog(void); | |||
8 | static inline void arch_touch_nmi_watchdog(void) {} | 8 | static inline void arch_touch_nmi_watchdog(void) {} |
9 | #endif | 9 | #endif |
10 | 10 | ||
11 | #if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_STACKTRACE) | ||
12 | extern void arch_trigger_cpumask_backtrace(const cpumask_t *mask, | ||
13 | bool exclude_self); | ||
14 | #define arch_trigger_cpumask_backtrace arch_trigger_cpumask_backtrace | ||
15 | #endif | ||
16 | |||
11 | #endif /* _ASM_NMI_H */ | 17 | #endif /* _ASM_NMI_H */ |
diff --git a/arch/powerpc/include/asm/nohash/32/pgalloc.h b/arch/powerpc/include/asm/nohash/32/pgalloc.h index 29d37bd1f3b3..1707781d2f20 100644 --- a/arch/powerpc/include/asm/nohash/32/pgalloc.h +++ b/arch/powerpc/include/asm/nohash/32/pgalloc.h | |||
@@ -100,6 +100,7 @@ static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage) | |||
100 | static inline void pgtable_free(void *table, unsigned index_size) | 100 | static inline void pgtable_free(void *table, unsigned index_size) |
101 | { | 101 | { |
102 | if (!index_size) { | 102 | if (!index_size) { |
103 | pgtable_page_dtor(virt_to_page(table)); | ||
103 | free_page((unsigned long)table); | 104 | free_page((unsigned long)table); |
104 | } else { | 105 | } else { |
105 | BUG_ON(index_size > MAX_PGTABLE_INDEX_SIZE); | 106 | BUG_ON(index_size > MAX_PGTABLE_INDEX_SIZE); |
diff --git a/arch/powerpc/include/asm/nohash/32/pgtable.h b/arch/powerpc/include/asm/nohash/32/pgtable.h index 03bbd1149530..7c46a98cc7f4 100644 --- a/arch/powerpc/include/asm/nohash/32/pgtable.h +++ b/arch/powerpc/include/asm/nohash/32/pgtable.h | |||
@@ -133,7 +133,7 @@ extern int icache_44x_need_flush; | |||
133 | #ifndef __ASSEMBLY__ | 133 | #ifndef __ASSEMBLY__ |
134 | 134 | ||
135 | #define pte_clear(mm, addr, ptep) \ | 135 | #define pte_clear(mm, addr, ptep) \ |
136 | do { pte_update(ptep, ~_PAGE_HASHPTE, 0); } while (0) | 136 | do { pte_update(ptep, ~0, 0); } while (0) |
137 | 137 | ||
138 | #define pmd_none(pmd) (!pmd_val(pmd)) | 138 | #define pmd_none(pmd) (!pmd_val(pmd)) |
139 | #define pmd_bad(pmd) (pmd_val(pmd) & _PMD_BAD) | 139 | #define pmd_bad(pmd) (pmd_val(pmd) & _PMD_BAD) |
@@ -146,21 +146,6 @@ static inline void pmd_clear(pmd_t *pmdp) | |||
146 | 146 | ||
147 | 147 | ||
148 | /* | 148 | /* |
149 | * When flushing the tlb entry for a page, we also need to flush the hash | ||
150 | * table entry. flush_hash_pages is assembler (for speed) in hashtable.S. | ||
151 | */ | ||
152 | extern int flush_hash_pages(unsigned context, unsigned long va, | ||
153 | unsigned long pmdval, int count); | ||
154 | |||
155 | /* Add an HPTE to the hash table */ | ||
156 | extern void add_hash_page(unsigned context, unsigned long va, | ||
157 | unsigned long pmdval); | ||
158 | |||
159 | /* Flush an entry from the TLB/hash table */ | ||
160 | extern void flush_hash_entry(struct mm_struct *mm, pte_t *ptep, | ||
161 | unsigned long address); | ||
162 | |||
163 | /* | ||
164 | * PTE updates. This function is called whenever an existing | 149 | * PTE updates. This function is called whenever an existing |
165 | * valid PTE is updated. This does -not- include set_pte_at() | 150 | * valid PTE is updated. This does -not- include set_pte_at() |
166 | * which nowadays only sets a new PTE. | 151 | * which nowadays only sets a new PTE. |
@@ -246,12 +231,6 @@ static inline int __ptep_test_and_clear_young(unsigned int context, unsigned lon | |||
246 | { | 231 | { |
247 | unsigned long old; | 232 | unsigned long old; |
248 | old = pte_update(ptep, _PAGE_ACCESSED, 0); | 233 | old = pte_update(ptep, _PAGE_ACCESSED, 0); |
249 | #if _PAGE_HASHPTE != 0 | ||
250 | if (old & _PAGE_HASHPTE) { | ||
251 | unsigned long ptephys = __pa(ptep) & PAGE_MASK; | ||
252 | flush_hash_pages(context, addr, ptephys, 1); | ||
253 | } | ||
254 | #endif | ||
255 | return (old & _PAGE_ACCESSED) != 0; | 234 | return (old & _PAGE_ACCESSED) != 0; |
256 | } | 235 | } |
257 | #define ptep_test_and_clear_young(__vma, __addr, __ptep) \ | 236 | #define ptep_test_and_clear_young(__vma, __addr, __ptep) \ |
@@ -261,7 +240,7 @@ static inline int __ptep_test_and_clear_young(unsigned int context, unsigned lon | |||
261 | static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, | 240 | static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, |
262 | pte_t *ptep) | 241 | pte_t *ptep) |
263 | { | 242 | { |
264 | return __pte(pte_update(ptep, ~_PAGE_HASHPTE, 0)); | 243 | return __pte(pte_update(ptep, ~0, 0)); |
265 | } | 244 | } |
266 | 245 | ||
267 | #define __HAVE_ARCH_PTEP_SET_WRPROTECT | 246 | #define __HAVE_ARCH_PTEP_SET_WRPROTECT |
@@ -277,19 +256,27 @@ static inline void huge_ptep_set_wrprotect(struct mm_struct *mm, | |||
277 | } | 256 | } |
278 | 257 | ||
279 | 258 | ||
280 | static inline void __ptep_set_access_flags(struct mm_struct *mm, | 259 | static inline void __ptep_set_access_flags(struct vm_area_struct *vma, |
281 | pte_t *ptep, pte_t entry, | 260 | pte_t *ptep, pte_t entry, |
282 | unsigned long address) | 261 | unsigned long address, |
262 | int psize) | ||
283 | { | 263 | { |
284 | unsigned long set = pte_val(entry) & | 264 | unsigned long set = pte_val(entry) & |
285 | (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC); | 265 | (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC); |
286 | unsigned long clr = ~pte_val(entry) & (_PAGE_RO | _PAGE_NA); | 266 | unsigned long clr = ~pte_val(entry) & (_PAGE_RO | _PAGE_NA); |
287 | 267 | ||
288 | pte_update(ptep, clr, set); | 268 | pte_update(ptep, clr, set); |
269 | |||
270 | flush_tlb_page(vma, address); | ||
271 | } | ||
272 | |||
273 | static inline int pte_young(pte_t pte) | ||
274 | { | ||
275 | return pte_val(pte) & _PAGE_ACCESSED; | ||
289 | } | 276 | } |
290 | 277 | ||
291 | #define __HAVE_ARCH_PTE_SAME | 278 | #define __HAVE_ARCH_PTE_SAME |
292 | #define pte_same(A,B) (((pte_val(A) ^ pte_val(B)) & ~_PAGE_HASHPTE) == 0) | 279 | #define pte_same(A,B) ((pte_val(A) ^ pte_val(B)) == 0) |
293 | 280 | ||
294 | /* | 281 | /* |
295 | * Note that on Book E processors, the pmd contains the kernel virtual | 282 | * Note that on Book E processors, the pmd contains the kernel virtual |
@@ -330,7 +317,7 @@ static inline void __ptep_set_access_flags(struct mm_struct *mm, | |||
330 | /* | 317 | /* |
331 | * Encode and decode a swap entry. | 318 | * Encode and decode a swap entry. |
332 | * Note that the bits we use in a PTE for representing a swap entry | 319 | * Note that the bits we use in a PTE for representing a swap entry |
333 | * must not include the _PAGE_PRESENT bit or the _PAGE_HASHPTE bit (if used). | 320 | * must not include the _PAGE_PRESENT bit. |
334 | * -- paulus | 321 | * -- paulus |
335 | */ | 322 | */ |
336 | #define __swp_type(entry) ((entry).val & 0x1f) | 323 | #define __swp_type(entry) ((entry).val & 0x1f) |
diff --git a/arch/powerpc/include/asm/nohash/32/pte-40x.h b/arch/powerpc/include/asm/nohash/32/pte-40x.h index 124f9ac23a1e..bb4b3a4b92a0 100644 --- a/arch/powerpc/include/asm/nohash/32/pte-40x.h +++ b/arch/powerpc/include/asm/nohash/32/pte-40x.h | |||
@@ -52,12 +52,9 @@ | |||
52 | 52 | ||
53 | #define _PMD_PRESENT 0x400 /* PMD points to page of PTEs */ | 53 | #define _PMD_PRESENT 0x400 /* PMD points to page of PTEs */ |
54 | #define _PMD_BAD 0x802 | 54 | #define _PMD_BAD 0x802 |
55 | #define _PMD_SIZE 0x0e0 /* size field, != 0 for large-page PMD entry */ | ||
56 | #define _PMD_SIZE_4M 0x0c0 | 55 | #define _PMD_SIZE_4M 0x0c0 |
57 | #define _PMD_SIZE_16M 0x0e0 | 56 | #define _PMD_SIZE_16M 0x0e0 |
58 | 57 | ||
59 | #define PMD_PAGE_SIZE(pmdval) (1024 << (((pmdval) & _PMD_SIZE) >> 4)) | ||
60 | |||
61 | /* Until my rework is finished, 40x still needs atomic PTE updates */ | 58 | /* Until my rework is finished, 40x still needs atomic PTE updates */ |
62 | #define PTE_ATOMIC_UPDATES 1 | 59 | #define PTE_ATOMIC_UPDATES 1 |
63 | 60 | ||
diff --git a/arch/powerpc/include/asm/nohash/64/pgalloc.h b/arch/powerpc/include/asm/nohash/64/pgalloc.h index 9721c7867b9c..0e693f322cb2 100644 --- a/arch/powerpc/include/asm/nohash/64/pgalloc.h +++ b/arch/powerpc/include/asm/nohash/64/pgalloc.h | |||
@@ -52,8 +52,6 @@ static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) | |||
52 | kmem_cache_free(PGT_CACHE(PGD_INDEX_SIZE), pgd); | 52 | kmem_cache_free(PGT_CACHE(PGD_INDEX_SIZE), pgd); |
53 | } | 53 | } |
54 | 54 | ||
55 | #ifndef CONFIG_PPC_64K_PAGES | ||
56 | |||
57 | #define pgd_populate(MM, PGD, PUD) pgd_set(PGD, (unsigned long)PUD) | 55 | #define pgd_populate(MM, PGD, PUD) pgd_set(PGD, (unsigned long)PUD) |
58 | 56 | ||
59 | static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr) | 57 | static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long addr) |
@@ -86,6 +84,18 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, | |||
86 | 84 | ||
87 | #define pmd_pgtable(pmd) pmd_page(pmd) | 85 | #define pmd_pgtable(pmd) pmd_page(pmd) |
88 | 86 | ||
87 | static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) | ||
88 | { | ||
89 | return kmem_cache_alloc(PGT_CACHE(PMD_CACHE_INDEX), | ||
90 | pgtable_gfp_flags(mm, GFP_KERNEL)); | ||
91 | } | ||
92 | |||
93 | static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd) | ||
94 | { | ||
95 | kmem_cache_free(PGT_CACHE(PMD_CACHE_INDEX), pmd); | ||
96 | } | ||
97 | |||
98 | |||
89 | static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, | 99 | static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, |
90 | unsigned long address) | 100 | unsigned long address) |
91 | { | 101 | { |
@@ -120,84 +130,47 @@ static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage) | |||
120 | __free_page(ptepage); | 130 | __free_page(ptepage); |
121 | } | 131 | } |
122 | 132 | ||
123 | extern void pgtable_free_tlb(struct mmu_gather *tlb, void *table, int shift); | 133 | static inline void pgtable_free(void *table, int shift) |
124 | #ifdef CONFIG_SMP | ||
125 | extern void __tlb_remove_table(void *_table); | ||
126 | #endif | ||
127 | static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table, | ||
128 | unsigned long address) | ||
129 | { | 134 | { |
130 | tlb_flush_pgtable(tlb, address); | 135 | if (!shift) { |
131 | pgtable_free_tlb(tlb, page_address(table), 0); | 136 | pgtable_page_dtor(virt_to_page(table)); |
137 | free_page((unsigned long)table); | ||
138 | } else { | ||
139 | BUG_ON(shift > MAX_PGTABLE_INDEX_SIZE); | ||
140 | kmem_cache_free(PGT_CACHE(shift), table); | ||
141 | } | ||
132 | } | 142 | } |
133 | 143 | ||
134 | #else /* if CONFIG_PPC_64K_PAGES */ | ||
135 | |||
136 | extern pte_t *pte_fragment_alloc(struct mm_struct *, unsigned long, int); | ||
137 | extern void pte_fragment_free(unsigned long *, int); | ||
138 | extern void pgtable_free_tlb(struct mmu_gather *tlb, void *table, int shift); | ||
139 | #ifdef CONFIG_SMP | 144 | #ifdef CONFIG_SMP |
140 | extern void __tlb_remove_table(void *_table); | 145 | static inline void pgtable_free_tlb(struct mmu_gather *tlb, void *table, int shift) |
141 | #endif | ||
142 | |||
143 | #define pud_populate(mm, pud, pmd) pud_set(pud, (unsigned long)pmd) | ||
144 | |||
145 | static inline void pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmd, | ||
146 | pte_t *pte) | ||
147 | { | 146 | { |
148 | pmd_set(pmd, (unsigned long)pte); | 147 | unsigned long pgf = (unsigned long)table; |
149 | } | ||
150 | 148 | ||
151 | static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd, | 149 | BUG_ON(shift > MAX_PGTABLE_INDEX_SIZE); |
152 | pgtable_t pte_page) | 150 | pgf |= shift; |
153 | { | 151 | tlb_remove_table(tlb, (void *)pgf); |
154 | pmd_set(pmd, (unsigned long)pte_page); | ||
155 | } | 152 | } |
156 | 153 | ||
157 | static inline pgtable_t pmd_pgtable(pmd_t pmd) | 154 | static inline void __tlb_remove_table(void *_table) |
158 | { | 155 | { |
159 | return (pgtable_t)(pmd_val(pmd) & ~PMD_MASKED_BITS); | 156 | void *table = (void *)((unsigned long)_table & ~MAX_PGTABLE_INDEX_SIZE); |
160 | } | 157 | unsigned shift = (unsigned long)_table & MAX_PGTABLE_INDEX_SIZE; |
161 | 158 | ||
162 | static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm, | 159 | pgtable_free(table, shift); |
163 | unsigned long address) | ||
164 | { | ||
165 | return (pte_t *)pte_fragment_alloc(mm, address, 1); | ||
166 | } | 160 | } |
167 | 161 | ||
168 | static inline pgtable_t pte_alloc_one(struct mm_struct *mm, | 162 | #else |
169 | unsigned long address) | 163 | static inline void pgtable_free_tlb(struct mmu_gather *tlb, void *table, int shift) |
170 | { | ||
171 | return (pgtable_t)pte_fragment_alloc(mm, address, 0); | ||
172 | } | ||
173 | |||
174 | static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte) | ||
175 | { | ||
176 | pte_fragment_free((unsigned long *)pte, 1); | ||
177 | } | ||
178 | |||
179 | static inline void pte_free(struct mm_struct *mm, pgtable_t ptepage) | ||
180 | { | 164 | { |
181 | pte_fragment_free((unsigned long *)ptepage, 0); | 165 | pgtable_free(table, shift); |
182 | } | 166 | } |
167 | #endif | ||
183 | 168 | ||
184 | static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table, | 169 | static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t table, |
185 | unsigned long address) | 170 | unsigned long address) |
186 | { | 171 | { |
187 | tlb_flush_pgtable(tlb, address); | 172 | tlb_flush_pgtable(tlb, address); |
188 | pgtable_free_tlb(tlb, table, 0); | 173 | pgtable_free_tlb(tlb, page_address(table), 0); |
189 | } | ||
190 | #endif /* CONFIG_PPC_64K_PAGES */ | ||
191 | |||
192 | static inline pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long addr) | ||
193 | { | ||
194 | return kmem_cache_alloc(PGT_CACHE(PMD_CACHE_INDEX), | ||
195 | pgtable_gfp_flags(mm, GFP_KERNEL)); | ||
196 | } | ||
197 | |||
198 | static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd) | ||
199 | { | ||
200 | kmem_cache_free(PGT_CACHE(PMD_CACHE_INDEX), pmd); | ||
201 | } | 174 | } |
202 | 175 | ||
203 | #define __pmd_free_tlb(tlb, pmd, addr) \ | 176 | #define __pmd_free_tlb(tlb, pmd, addr) \ |
diff --git a/arch/powerpc/include/asm/nohash/64/pgtable-64k.h b/arch/powerpc/include/asm/nohash/64/pgtable-64k.h deleted file mode 100644 index 7210c2818e41..000000000000 --- a/arch/powerpc/include/asm/nohash/64/pgtable-64k.h +++ /dev/null | |||
@@ -1,57 +0,0 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | #ifndef _ASM_POWERPC_NOHASH_64_PGTABLE_64K_H | ||
3 | #define _ASM_POWERPC_NOHASH_64_PGTABLE_64K_H | ||
4 | |||
5 | #define __ARCH_USE_5LEVEL_HACK | ||
6 | #include <asm-generic/pgtable-nopud.h> | ||
7 | |||
8 | |||
9 | #define PTE_INDEX_SIZE 8 | ||
10 | #define PMD_INDEX_SIZE 10 | ||
11 | #define PUD_INDEX_SIZE 0 | ||
12 | #define PGD_INDEX_SIZE 12 | ||
13 | |||
14 | /* | ||
15 | * we support 32 fragments per PTE page of 64K size | ||
16 | */ | ||
17 | #define PTE_FRAG_NR 32 | ||
18 | /* | ||
19 | * We use a 2K PTE page fragment and another 2K for storing | ||
20 | * real_pte_t hash index | ||
21 | */ | ||
22 | #define PTE_FRAG_SIZE_SHIFT 11 | ||
23 | #define PTE_FRAG_SIZE (1UL << PTE_FRAG_SIZE_SHIFT) | ||
24 | |||
25 | #ifndef __ASSEMBLY__ | ||
26 | #define PTE_TABLE_SIZE PTE_FRAG_SIZE | ||
27 | #define PMD_TABLE_SIZE (sizeof(pmd_t) << PMD_INDEX_SIZE) | ||
28 | #define PUD_TABLE_SIZE (0) | ||
29 | #define PGD_TABLE_SIZE (sizeof(pgd_t) << PGD_INDEX_SIZE) | ||
30 | #endif /* __ASSEMBLY__ */ | ||
31 | |||
32 | #define PTRS_PER_PTE (1 << PTE_INDEX_SIZE) | ||
33 | #define PTRS_PER_PMD (1 << PMD_INDEX_SIZE) | ||
34 | #define PTRS_PER_PGD (1 << PGD_INDEX_SIZE) | ||
35 | |||
36 | /* PMD_SHIFT determines what a second-level page table entry can map */ | ||
37 | #define PMD_SHIFT (PAGE_SHIFT + PTE_INDEX_SIZE) | ||
38 | #define PMD_SIZE (1UL << PMD_SHIFT) | ||
39 | #define PMD_MASK (~(PMD_SIZE-1)) | ||
40 | |||
41 | /* PGDIR_SHIFT determines what a third-level page table entry can map */ | ||
42 | #define PGDIR_SHIFT (PMD_SHIFT + PMD_INDEX_SIZE) | ||
43 | #define PGDIR_SIZE (1UL << PGDIR_SHIFT) | ||
44 | #define PGDIR_MASK (~(PGDIR_SIZE-1)) | ||
45 | |||
46 | /* | ||
47 | * Bits to mask out from a PMD to get to the PTE page | ||
48 | * PMDs point to PTE table fragments which are PTE_FRAG_SIZE aligned. | ||
49 | */ | ||
50 | #define PMD_MASKED_BITS (PTE_FRAG_SIZE - 1) | ||
51 | /* Bits to mask out from a PGD/PUD to get to the PMD page */ | ||
52 | #define PUD_MASKED_BITS 0x1ff | ||
53 | |||
54 | #define pgd_pte(pgd) (pud_pte(((pud_t){ pgd }))) | ||
55 | #define pte_pgd(pte) ((pgd_t)pte_pud(pte)) | ||
56 | |||
57 | #endif /* _ASM_POWERPC_NOHASH_64_PGTABLE_64K_H */ | ||
diff --git a/arch/powerpc/include/asm/nohash/64/pgtable.h b/arch/powerpc/include/asm/nohash/64/pgtable.h index 5c5f75d005ad..dd0c7236208f 100644 --- a/arch/powerpc/include/asm/nohash/64/pgtable.h +++ b/arch/powerpc/include/asm/nohash/64/pgtable.h | |||
@@ -6,13 +6,13 @@ | |||
6 | * the ppc64 hashed page table. | 6 | * the ppc64 hashed page table. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #ifdef CONFIG_PPC_64K_PAGES | ||
10 | #include <asm/nohash/64/pgtable-64k.h> | ||
11 | #else | ||
12 | #include <asm/nohash/64/pgtable-4k.h> | 9 | #include <asm/nohash/64/pgtable-4k.h> |
13 | #endif | ||
14 | #include <asm/barrier.h> | 10 | #include <asm/barrier.h> |
15 | 11 | ||
12 | #ifdef CONFIG_PPC_64K_PAGES | ||
13 | #error "Page size not supported" | ||
14 | #endif | ||
15 | |||
16 | #define FIRST_USER_ADDRESS 0UL | 16 | #define FIRST_USER_ADDRESS 0UL |
17 | 17 | ||
18 | /* | 18 | /* |
@@ -173,8 +173,6 @@ static inline void pgd_set(pgd_t *pgdp, unsigned long val) | |||
173 | /* to find an entry in a kernel page-table-directory */ | 173 | /* to find an entry in a kernel page-table-directory */ |
174 | /* This now only contains the vmalloc pages */ | 174 | /* This now only contains the vmalloc pages */ |
175 | #define pgd_offset_k(address) pgd_offset(&init_mm, address) | 175 | #define pgd_offset_k(address) pgd_offset(&init_mm, address) |
176 | extern void hpte_need_flush(struct mm_struct *mm, unsigned long addr, | ||
177 | pte_t *ptep, unsigned long pte, int huge); | ||
178 | 176 | ||
179 | /* Atomic PTE updates */ | 177 | /* Atomic PTE updates */ |
180 | static inline unsigned long pte_update(struct mm_struct *mm, | 178 | static inline unsigned long pte_update(struct mm_struct *mm, |
@@ -188,14 +186,12 @@ static inline unsigned long pte_update(struct mm_struct *mm, | |||
188 | 186 | ||
189 | __asm__ __volatile__( | 187 | __asm__ __volatile__( |
190 | "1: ldarx %0,0,%3 # pte_update\n\ | 188 | "1: ldarx %0,0,%3 # pte_update\n\ |
191 | andi. %1,%0,%6\n\ | ||
192 | bne- 1b \n\ | ||
193 | andc %1,%0,%4 \n\ | 189 | andc %1,%0,%4 \n\ |
194 | or %1,%1,%7\n\ | 190 | or %1,%1,%6\n\ |
195 | stdcx. %1,0,%3 \n\ | 191 | stdcx. %1,0,%3 \n\ |
196 | bne- 1b" | 192 | bne- 1b" |
197 | : "=&r" (old), "=&r" (tmp), "=m" (*ptep) | 193 | : "=&r" (old), "=&r" (tmp), "=m" (*ptep) |
198 | : "r" (ptep), "r" (clr), "m" (*ptep), "i" (_PAGE_BUSY), "r" (set) | 194 | : "r" (ptep), "r" (clr), "m" (*ptep), "r" (set) |
199 | : "cc" ); | 195 | : "cc" ); |
200 | #else | 196 | #else |
201 | unsigned long old = pte_val(*ptep); | 197 | unsigned long old = pte_val(*ptep); |
@@ -205,20 +201,20 @@ static inline unsigned long pte_update(struct mm_struct *mm, | |||
205 | if (!huge) | 201 | if (!huge) |
206 | assert_pte_locked(mm, addr); | 202 | assert_pte_locked(mm, addr); |
207 | 203 | ||
208 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
209 | if (old & _PAGE_HASHPTE) | ||
210 | hpte_need_flush(mm, addr, ptep, old, huge); | ||
211 | #endif | ||
212 | |||
213 | return old; | 204 | return old; |
214 | } | 205 | } |
215 | 206 | ||
207 | static inline int pte_young(pte_t pte) | ||
208 | { | ||
209 | return pte_val(pte) & _PAGE_ACCESSED; | ||
210 | } | ||
211 | |||
216 | static inline int __ptep_test_and_clear_young(struct mm_struct *mm, | 212 | static inline int __ptep_test_and_clear_young(struct mm_struct *mm, |
217 | unsigned long addr, pte_t *ptep) | 213 | unsigned long addr, pte_t *ptep) |
218 | { | 214 | { |
219 | unsigned long old; | 215 | unsigned long old; |
220 | 216 | ||
221 | if ((pte_val(*ptep) & (_PAGE_ACCESSED | _PAGE_HASHPTE)) == 0) | 217 | if (pte_young(*ptep)) |
222 | return 0; | 218 | return 0; |
223 | old = pte_update(mm, addr, ptep, _PAGE_ACCESSED, 0, 0); | 219 | old = pte_update(mm, addr, ptep, _PAGE_ACCESSED, 0, 0); |
224 | return (old & _PAGE_ACCESSED) != 0; | 220 | return (old & _PAGE_ACCESSED) != 0; |
@@ -285,9 +281,10 @@ static inline void pte_clear(struct mm_struct *mm, unsigned long addr, | |||
285 | /* Set the dirty and/or accessed bits atomically in a linux PTE, this | 281 | /* Set the dirty and/or accessed bits atomically in a linux PTE, this |
286 | * function doesn't need to flush the hash entry | 282 | * function doesn't need to flush the hash entry |
287 | */ | 283 | */ |
288 | static inline void __ptep_set_access_flags(struct mm_struct *mm, | 284 | static inline void __ptep_set_access_flags(struct vm_area_struct *vma, |
289 | pte_t *ptep, pte_t entry, | 285 | pte_t *ptep, pte_t entry, |
290 | unsigned long address) | 286 | unsigned long address, |
287 | int psize) | ||
291 | { | 288 | { |
292 | unsigned long bits = pte_val(entry) & | 289 | unsigned long bits = pte_val(entry) & |
293 | (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC); | 290 | (_PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_RW | _PAGE_EXEC); |
@@ -297,22 +294,22 @@ static inline void __ptep_set_access_flags(struct mm_struct *mm, | |||
297 | 294 | ||
298 | __asm__ __volatile__( | 295 | __asm__ __volatile__( |
299 | "1: ldarx %0,0,%4\n\ | 296 | "1: ldarx %0,0,%4\n\ |
300 | andi. %1,%0,%6\n\ | ||
301 | bne- 1b \n\ | ||
302 | or %0,%3,%0\n\ | 297 | or %0,%3,%0\n\ |
303 | stdcx. %0,0,%4\n\ | 298 | stdcx. %0,0,%4\n\ |
304 | bne- 1b" | 299 | bne- 1b" |
305 | :"=&r" (old), "=&r" (tmp), "=m" (*ptep) | 300 | :"=&r" (old), "=&r" (tmp), "=m" (*ptep) |
306 | :"r" (bits), "r" (ptep), "m" (*ptep), "i" (_PAGE_BUSY) | 301 | :"r" (bits), "r" (ptep), "m" (*ptep) |
307 | :"cc"); | 302 | :"cc"); |
308 | #else | 303 | #else |
309 | unsigned long old = pte_val(*ptep); | 304 | unsigned long old = pte_val(*ptep); |
310 | *ptep = __pte(old | bits); | 305 | *ptep = __pte(old | bits); |
311 | #endif | 306 | #endif |
307 | |||
308 | flush_tlb_page(vma, address); | ||
312 | } | 309 | } |
313 | 310 | ||
314 | #define __HAVE_ARCH_PTE_SAME | 311 | #define __HAVE_ARCH_PTE_SAME |
315 | #define pte_same(A,B) (((pte_val(A) ^ pte_val(B)) & ~_PAGE_HPTEFLAGS) == 0) | 312 | #define pte_same(A,B) ((pte_val(A) ^ pte_val(B)) == 0) |
316 | 313 | ||
317 | #define pte_ERROR(e) \ | 314 | #define pte_ERROR(e) \ |
318 | pr_err("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e)) | 315 | pr_err("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, pte_val(e)) |
@@ -324,11 +321,6 @@ static inline void __ptep_set_access_flags(struct mm_struct *mm, | |||
324 | /* Encode and de-code a swap entry */ | 321 | /* Encode and de-code a swap entry */ |
325 | #define MAX_SWAPFILES_CHECK() do { \ | 322 | #define MAX_SWAPFILES_CHECK() do { \ |
326 | BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > SWP_TYPE_BITS); \ | 323 | BUILD_BUG_ON(MAX_SWAPFILES_SHIFT > SWP_TYPE_BITS); \ |
327 | /* \ | ||
328 | * Don't have overlapping bits with _PAGE_HPTEFLAGS \ | ||
329 | * We filter HPTEFLAGS on set_pte. \ | ||
330 | */ \ | ||
331 | BUILD_BUG_ON(_PAGE_HPTEFLAGS & (0x1f << _PAGE_BIT_SWAP_TYPE)); \ | ||
332 | } while (0) | 324 | } while (0) |
333 | /* | 325 | /* |
334 | * on pte we don't need handle RADIX_TREE_EXCEPTIONAL_SHIFT; | 326 | * on pte we don't need handle RADIX_TREE_EXCEPTIONAL_SHIFT; |
diff --git a/arch/powerpc/include/asm/nohash/pgtable.h b/arch/powerpc/include/asm/nohash/pgtable.h index c56de1e8026f..2160be2e4339 100644 --- a/arch/powerpc/include/asm/nohash/pgtable.h +++ b/arch/powerpc/include/asm/nohash/pgtable.h | |||
@@ -17,7 +17,6 @@ static inline int pte_write(pte_t pte) | |||
17 | } | 17 | } |
18 | static inline int pte_read(pte_t pte) { return 1; } | 18 | static inline int pte_read(pte_t pte) { return 1; } |
19 | static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; } | 19 | static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; } |
20 | static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; } | ||
21 | static inline int pte_special(pte_t pte) { return pte_val(pte) & _PAGE_SPECIAL; } | 20 | static inline int pte_special(pte_t pte) { return pte_val(pte) & _PAGE_SPECIAL; } |
22 | static inline int pte_none(pte_t pte) { return (pte_val(pte) & ~_PTE_NONE_MASK) == 0; } | 21 | static inline int pte_none(pte_t pte) { return (pte_val(pte) & ~_PTE_NONE_MASK) == 0; } |
23 | static inline pgprot_t pte_pgprot(pte_t pte) { return __pgprot(pte_val(pte) & PAGE_PROT_BITS); } | 22 | static inline pgprot_t pte_pgprot(pte_t pte) { return __pgprot(pte_val(pte) & PAGE_PROT_BITS); } |
@@ -148,70 +147,33 @@ extern void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, | |||
148 | static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr, | 147 | static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr, |
149 | pte_t *ptep, pte_t pte, int percpu) | 148 | pte_t *ptep, pte_t pte, int percpu) |
150 | { | 149 | { |
151 | #if defined(CONFIG_PPC_STD_MMU_32) && defined(CONFIG_SMP) && !defined(CONFIG_PTE_64BIT) | ||
152 | /* First case is 32-bit Hash MMU in SMP mode with 32-bit PTEs. We use the | ||
153 | * helper pte_update() which does an atomic update. We need to do that | ||
154 | * because a concurrent invalidation can clear _PAGE_HASHPTE. If it's a | ||
155 | * per-CPU PTE such as a kmap_atomic, we do a simple update preserving | ||
156 | * the hash bits instead (ie, same as the non-SMP case) | ||
157 | */ | ||
158 | if (percpu) | ||
159 | *ptep = __pte((pte_val(*ptep) & _PAGE_HASHPTE) | ||
160 | | (pte_val(pte) & ~_PAGE_HASHPTE)); | ||
161 | else | ||
162 | pte_update(ptep, ~_PAGE_HASHPTE, pte_val(pte)); | ||
163 | |||
164 | #elif defined(CONFIG_PPC32) && defined(CONFIG_PTE_64BIT) | ||
165 | /* Second case is 32-bit with 64-bit PTE. In this case, we | 150 | /* Second case is 32-bit with 64-bit PTE. In this case, we |
166 | * can just store as long as we do the two halves in the right order | 151 | * can just store as long as we do the two halves in the right order |
167 | * with a barrier in between. This is possible because we take care, | 152 | * with a barrier in between. |
168 | * in the hash code, to pre-invalidate if the PTE was already hashed, | 153 | * In the percpu case, we also fallback to the simple update |
169 | * which synchronizes us with any concurrent invalidation. | ||
170 | * In the percpu case, we also fallback to the simple update preserving | ||
171 | * the hash bits | ||
172 | */ | 154 | */ |
173 | if (percpu) { | 155 | if (IS_ENABLED(CONFIG_PPC32) && IS_ENABLED(CONFIG_PTE_64BIT) && !percpu) { |
174 | *ptep = __pte((pte_val(*ptep) & _PAGE_HASHPTE) | 156 | __asm__ __volatile__("\ |
175 | | (pte_val(pte) & ~_PAGE_HASHPTE)); | 157 | stw%U0%X0 %2,%0\n\ |
158 | eieio\n\ | ||
159 | stw%U0%X0 %L2,%1" | ||
160 | : "=m" (*ptep), "=m" (*((unsigned char *)ptep+4)) | ||
161 | : "r" (pte) : "memory"); | ||
176 | return; | 162 | return; |
177 | } | 163 | } |
178 | #if _PAGE_HASHPTE != 0 | ||
179 | if (pte_val(*ptep) & _PAGE_HASHPTE) | ||
180 | flush_hash_entry(mm, ptep, addr); | ||
181 | #endif | ||
182 | __asm__ __volatile__("\ | ||
183 | stw%U0%X0 %2,%0\n\ | ||
184 | eieio\n\ | ||
185 | stw%U0%X0 %L2,%1" | ||
186 | : "=m" (*ptep), "=m" (*((unsigned char *)ptep+4)) | ||
187 | : "r" (pte) : "memory"); | ||
188 | |||
189 | #elif defined(CONFIG_PPC_STD_MMU_32) | ||
190 | /* Third case is 32-bit hash table in UP mode, we need to preserve | ||
191 | * the _PAGE_HASHPTE bit since we may not have invalidated the previous | ||
192 | * translation in the hash yet (done in a subsequent flush_tlb_xxx()) | ||
193 | * and see we need to keep track that this PTE needs invalidating | ||
194 | */ | ||
195 | *ptep = __pte((pte_val(*ptep) & _PAGE_HASHPTE) | ||
196 | | (pte_val(pte) & ~_PAGE_HASHPTE)); | ||
197 | |||
198 | #else | ||
199 | /* Anything else just stores the PTE normally. That covers all 64-bit | 164 | /* Anything else just stores the PTE normally. That covers all 64-bit |
200 | * cases, and 32-bit non-hash with 32-bit PTEs. | 165 | * cases, and 32-bit non-hash with 32-bit PTEs. |
201 | */ | 166 | */ |
202 | *ptep = pte; | 167 | *ptep = pte; |
203 | 168 | ||
204 | #ifdef CONFIG_PPC_BOOK3E_64 | ||
205 | /* | 169 | /* |
206 | * With hardware tablewalk, a sync is needed to ensure that | 170 | * With hardware tablewalk, a sync is needed to ensure that |
207 | * subsequent accesses see the PTE we just wrote. Unlike userspace | 171 | * subsequent accesses see the PTE we just wrote. Unlike userspace |
208 | * mappings, we can't tolerate spurious faults, so make sure | 172 | * mappings, we can't tolerate spurious faults, so make sure |
209 | * the new PTE will be seen the first time. | 173 | * the new PTE will be seen the first time. |
210 | */ | 174 | */ |
211 | if (is_kernel_addr(addr)) | 175 | if (IS_ENABLED(CONFIG_PPC_BOOK3E_64) && is_kernel_addr(addr)) |
212 | mb(); | 176 | mb(); |
213 | #endif | ||
214 | #endif | ||
215 | } | 177 | } |
216 | 178 | ||
217 | 179 | ||
diff --git a/arch/powerpc/include/asm/nohash/pte-book3e.h b/arch/powerpc/include/asm/nohash/pte-book3e.h index ccee8eb509bb..12730b81cd98 100644 --- a/arch/powerpc/include/asm/nohash/pte-book3e.h +++ b/arch/powerpc/include/asm/nohash/pte-book3e.h | |||
@@ -57,14 +57,8 @@ | |||
57 | #define _PAGE_USER (_PAGE_BAP_UR | _PAGE_BAP_SR) /* Can be read */ | 57 | #define _PAGE_USER (_PAGE_BAP_UR | _PAGE_BAP_SR) /* Can be read */ |
58 | #define _PAGE_PRIVILEGED (_PAGE_BAP_SR) | 58 | #define _PAGE_PRIVILEGED (_PAGE_BAP_SR) |
59 | 59 | ||
60 | #define _PAGE_HASHPTE 0 | ||
61 | #define _PAGE_BUSY 0 | ||
62 | |||
63 | #define _PAGE_SPECIAL _PAGE_SW0 | 60 | #define _PAGE_SPECIAL _PAGE_SW0 |
64 | 61 | ||
65 | /* Flags to be preserved on PTE modifications */ | ||
66 | #define _PAGE_HPTEFLAGS _PAGE_BUSY | ||
67 | |||
68 | /* Base page size */ | 62 | /* Base page size */ |
69 | #ifdef CONFIG_PPC_64K_PAGES | 63 | #ifdef CONFIG_PPC_64K_PAGES |
70 | #define _PAGE_PSIZE _PAGE_PSIZE_64K | 64 | #define _PAGE_PSIZE _PAGE_PSIZE_64K |
diff --git a/arch/powerpc/include/asm/opal-api.h b/arch/powerpc/include/asm/opal-api.h index d886a5b7ff21..3bab299eda49 100644 --- a/arch/powerpc/include/asm/opal-api.h +++ b/arch/powerpc/include/asm/opal-api.h | |||
@@ -201,13 +201,21 @@ | |||
201 | #define OPAL_SET_POWER_SHIFT_RATIO 155 | 201 | #define OPAL_SET_POWER_SHIFT_RATIO 155 |
202 | #define OPAL_SENSOR_GROUP_CLEAR 156 | 202 | #define OPAL_SENSOR_GROUP_CLEAR 156 |
203 | #define OPAL_PCI_SET_P2P 157 | 203 | #define OPAL_PCI_SET_P2P 157 |
204 | #define OPAL_QUIESCE 158 | ||
204 | #define OPAL_NPU_SPA_SETUP 159 | 205 | #define OPAL_NPU_SPA_SETUP 159 |
205 | #define OPAL_NPU_SPA_CLEAR_CACHE 160 | 206 | #define OPAL_NPU_SPA_CLEAR_CACHE 160 |
206 | #define OPAL_NPU_TL_SET 161 | 207 | #define OPAL_NPU_TL_SET 161 |
208 | #define OPAL_SENSOR_READ_U64 162 | ||
207 | #define OPAL_PCI_GET_PBCQ_TUNNEL_BAR 164 | 209 | #define OPAL_PCI_GET_PBCQ_TUNNEL_BAR 164 |
208 | #define OPAL_PCI_SET_PBCQ_TUNNEL_BAR 165 | 210 | #define OPAL_PCI_SET_PBCQ_TUNNEL_BAR 165 |
209 | #define OPAL_LAST 165 | 211 | #define OPAL_LAST 165 |
210 | 212 | ||
213 | #define QUIESCE_HOLD 1 /* Spin all calls at entry */ | ||
214 | #define QUIESCE_REJECT 2 /* Fail all calls with OPAL_BUSY */ | ||
215 | #define QUIESCE_LOCK_BREAK 3 /* Set to ignore locks. */ | ||
216 | #define QUIESCE_RESUME 4 /* Un-quiesce */ | ||
217 | #define QUIESCE_RESUME_FAST_REBOOT 5 /* Un-quiesce, fast reboot */ | ||
218 | |||
211 | /* Device tree flags */ | 219 | /* Device tree flags */ |
212 | 220 | ||
213 | /* | 221 | /* |
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h index 03e1a920491e..e1b2910c6e81 100644 --- a/arch/powerpc/include/asm/opal.h +++ b/arch/powerpc/include/asm/opal.h | |||
@@ -201,6 +201,7 @@ int64_t opal_get_param(uint64_t token, uint32_t param_id, uint64_t buffer, | |||
201 | int64_t opal_set_param(uint64_t token, uint32_t param_id, uint64_t buffer, | 201 | int64_t opal_set_param(uint64_t token, uint32_t param_id, uint64_t buffer, |
202 | uint64_t length); | 202 | uint64_t length); |
203 | int64_t opal_sensor_read(uint32_t sensor_hndl, int token, __be32 *sensor_data); | 203 | int64_t opal_sensor_read(uint32_t sensor_hndl, int token, __be32 *sensor_data); |
204 | int64_t opal_sensor_read_u64(u32 sensor_hndl, int token, __be64 *sensor_data); | ||
204 | int64_t opal_handle_hmi(void); | 205 | int64_t opal_handle_hmi(void); |
205 | int64_t opal_register_dump_region(uint32_t id, uint64_t start, uint64_t end); | 206 | int64_t opal_register_dump_region(uint32_t id, uint64_t start, uint64_t end); |
206 | int64_t opal_unregister_dump_region(uint32_t id); | 207 | int64_t opal_unregister_dump_region(uint32_t id); |
@@ -293,6 +294,7 @@ int opal_set_power_shift_ratio(u32 handle, int token, u32 psr); | |||
293 | int opal_sensor_group_clear(u32 group_hndl, int token); | 294 | int opal_sensor_group_clear(u32 group_hndl, int token); |
294 | 295 | ||
295 | s64 opal_signal_system_reset(s32 cpu); | 296 | s64 opal_signal_system_reset(s32 cpu); |
297 | s64 opal_quiesce(u64 shutdown_type, s32 cpu); | ||
296 | 298 | ||
297 | /* Internal functions */ | 299 | /* Internal functions */ |
298 | extern int early_init_dt_scan_opal(unsigned long node, const char *uname, | 300 | extern int early_init_dt_scan_opal(unsigned long node, const char *uname, |
@@ -323,9 +325,10 @@ extern int opal_async_wait_response(uint64_t token, struct opal_msg *msg); | |||
323 | extern int opal_async_wait_response_interruptible(uint64_t token, | 325 | extern int opal_async_wait_response_interruptible(uint64_t token, |
324 | struct opal_msg *msg); | 326 | struct opal_msg *msg); |
325 | extern int opal_get_sensor_data(u32 sensor_hndl, u32 *sensor_data); | 327 | extern int opal_get_sensor_data(u32 sensor_hndl, u32 *sensor_data); |
328 | extern int opal_get_sensor_data_u64(u32 sensor_hndl, u64 *sensor_data); | ||
326 | 329 | ||
327 | struct rtc_time; | 330 | struct rtc_time; |
328 | extern unsigned long opal_get_boot_time(void); | 331 | extern time64_t opal_get_boot_time(void); |
329 | extern void opal_nvram_init(void); | 332 | extern void opal_nvram_init(void); |
330 | extern void opal_flash_update_init(void); | 333 | extern void opal_flash_update_init(void); |
331 | extern void opal_flash_update_print_message(void); | 334 | extern void opal_flash_update_print_message(void); |
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h index 3f109a3e3edb..6d34bd71139d 100644 --- a/arch/powerpc/include/asm/paca.h +++ b/arch/powerpc/include/asm/paca.h | |||
@@ -161,7 +161,7 @@ struct paca_struct { | |||
161 | struct task_struct *__current; /* Pointer to current */ | 161 | struct task_struct *__current; /* Pointer to current */ |
162 | u64 kstack; /* Saved Kernel stack addr */ | 162 | u64 kstack; /* Saved Kernel stack addr */ |
163 | u64 stab_rr; /* stab/slb round-robin counter */ | 163 | u64 stab_rr; /* stab/slb round-robin counter */ |
164 | u64 saved_r1; /* r1 save for RTAS calls or PM */ | 164 | u64 saved_r1; /* r1 save for RTAS calls or PM or EE=0 */ |
165 | u64 saved_msr; /* MSR saved here by enter_rtas */ | 165 | u64 saved_msr; /* MSR saved here by enter_rtas */ |
166 | u16 trap_save; /* Used when bad stack is encountered */ | 166 | u16 trap_save; /* Used when bad stack is encountered */ |
167 | u8 irq_soft_mask; /* mask for irq soft masking */ | 167 | u8 irq_soft_mask; /* mask for irq soft masking */ |
@@ -222,6 +222,7 @@ struct paca_struct { | |||
222 | u8 hmi_event_available; /* HMI event is available */ | 222 | u8 hmi_event_available; /* HMI event is available */ |
223 | u8 hmi_p9_special_emu; /* HMI P9 special emulation */ | 223 | u8 hmi_p9_special_emu; /* HMI P9 special emulation */ |
224 | #endif | 224 | #endif |
225 | u8 ftrace_enabled; /* Hard disable ftrace */ | ||
225 | 226 | ||
226 | /* Stuff for accurate time accounting */ | 227 | /* Stuff for accurate time accounting */ |
227 | struct cpu_accounting_data accounting; | 228 | struct cpu_accounting_data accounting; |
diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h index dec9ce5ba8af..db7be0779d55 100644 --- a/arch/powerpc/include/asm/page.h +++ b/arch/powerpc/include/asm/page.h | |||
@@ -39,6 +39,7 @@ | |||
39 | 39 | ||
40 | #ifndef __ASSEMBLY__ | 40 | #ifndef __ASSEMBLY__ |
41 | #ifdef CONFIG_HUGETLB_PAGE | 41 | #ifdef CONFIG_HUGETLB_PAGE |
42 | extern bool hugetlb_disabled; | ||
42 | extern unsigned int HPAGE_SHIFT; | 43 | extern unsigned int HPAGE_SHIFT; |
43 | #else | 44 | #else |
44 | #define HPAGE_SHIFT PAGE_SHIFT | 45 | #define HPAGE_SHIFT PAGE_SHIFT |
diff --git a/arch/powerpc/include/asm/pgtable.h b/arch/powerpc/include/asm/pgtable.h index ab7d2d996be4..14c79a7dc855 100644 --- a/arch/powerpc/include/asm/pgtable.h +++ b/arch/powerpc/include/asm/pgtable.h | |||
@@ -8,6 +8,7 @@ | |||
8 | #include <asm/processor.h> /* For TASK_SIZE */ | 8 | #include <asm/processor.h> /* For TASK_SIZE */ |
9 | #include <asm/mmu.h> | 9 | #include <asm/mmu.h> |
10 | #include <asm/page.h> | 10 | #include <asm/page.h> |
11 | #include <asm/tlbflush.h> | ||
11 | 12 | ||
12 | struct mm_struct; | 13 | struct mm_struct; |
13 | 14 | ||
diff --git a/arch/powerpc/include/asm/pkeys.h b/arch/powerpc/include/asm/pkeys.h index 0409c80c32c0..5ba80cffb505 100644 --- a/arch/powerpc/include/asm/pkeys.h +++ b/arch/powerpc/include/asm/pkeys.h | |||
@@ -15,19 +15,6 @@ DECLARE_STATIC_KEY_TRUE(pkey_disabled); | |||
15 | extern int pkeys_total; /* total pkeys as per device tree */ | 15 | extern int pkeys_total; /* total pkeys as per device tree */ |
16 | extern u32 initial_allocation_mask; /* bits set for reserved keys */ | 16 | extern u32 initial_allocation_mask; /* bits set for reserved keys */ |
17 | 17 | ||
18 | /* | ||
19 | * Define these here temporarily so we're not dependent on patching linux/mm.h. | ||
20 | * Once it's updated we can drop these. | ||
21 | */ | ||
22 | #ifndef VM_PKEY_BIT0 | ||
23 | # define VM_PKEY_SHIFT VM_HIGH_ARCH_BIT_0 | ||
24 | # define VM_PKEY_BIT0 VM_HIGH_ARCH_0 | ||
25 | # define VM_PKEY_BIT1 VM_HIGH_ARCH_1 | ||
26 | # define VM_PKEY_BIT2 VM_HIGH_ARCH_2 | ||
27 | # define VM_PKEY_BIT3 VM_HIGH_ARCH_3 | ||
28 | # define VM_PKEY_BIT4 VM_HIGH_ARCH_4 | ||
29 | #endif | ||
30 | |||
31 | #define ARCH_VM_PKEY_FLAGS (VM_PKEY_BIT0 | VM_PKEY_BIT1 | VM_PKEY_BIT2 | \ | 18 | #define ARCH_VM_PKEY_FLAGS (VM_PKEY_BIT0 | VM_PKEY_BIT1 | VM_PKEY_BIT2 | \ |
32 | VM_PKEY_BIT3 | VM_PKEY_BIT4) | 19 | VM_PKEY_BIT3 | VM_PKEY_BIT4) |
33 | 20 | ||
diff --git a/arch/powerpc/include/asm/plpar_wrappers.h b/arch/powerpc/include/asm/plpar_wrappers.h index 96c1a46acbd0..cff5a411e595 100644 --- a/arch/powerpc/include/asm/plpar_wrappers.h +++ b/arch/powerpc/include/asm/plpar_wrappers.h | |||
@@ -39,10 +39,10 @@ static inline long extended_cede_processor(unsigned long latency_hint) | |||
39 | set_cede_latency_hint(latency_hint); | 39 | set_cede_latency_hint(latency_hint); |
40 | 40 | ||
41 | rc = cede_processor(); | 41 | rc = cede_processor(); |
42 | #ifdef CONFIG_TRACE_IRQFLAGS | 42 | #ifdef CONFIG_PPC_IRQ_SOFT_MASK_DEBUG |
43 | /* Ensure that H_CEDE returns with IRQs on */ | 43 | /* Ensure that H_CEDE returns with IRQs on */ |
44 | if (WARN_ON(!(mfmsr() & MSR_EE))) | 44 | if (WARN_ON(!(mfmsr() & MSR_EE))) |
45 | __hard_irq_enable(); | 45 | __hard_irq_enable(); |
46 | #endif | 46 | #endif |
47 | 47 | ||
48 | set_cede_latency_hint(old_latency_hint); | 48 | set_cede_latency_hint(old_latency_hint); |
diff --git a/arch/powerpc/include/asm/pmac_pfunc.h b/arch/powerpc/include/asm/pmac_pfunc.h index 73bd8f28f2a8..cee4e9f5b8cf 100644 --- a/arch/powerpc/include/asm/pmac_pfunc.h +++ b/arch/powerpc/include/asm/pmac_pfunc.h | |||
@@ -245,6 +245,7 @@ extern void pmf_put_function(struct pmf_function *func); | |||
245 | 245 | ||
246 | extern int pmf_call_one(struct pmf_function *func, struct pmf_args *args); | 246 | extern int pmf_call_one(struct pmf_function *func, struct pmf_args *args); |
247 | 247 | ||
248 | int pmac_pfunc_base_install(void); | ||
248 | 249 | ||
249 | /* Suspend/resume code called by via-pmu directly for now */ | 250 | /* Suspend/resume code called by via-pmu directly for now */ |
250 | extern void pmac_pfunc_base_suspend(void); | 251 | extern void pmac_pfunc_base_suspend(void); |
diff --git a/arch/powerpc/include/asm/pnv-ocxl.h b/arch/powerpc/include/asm/pnv-ocxl.h index f6945d3bc971..208b5503f4ed 100644 --- a/arch/powerpc/include/asm/pnv-ocxl.h +++ b/arch/powerpc/include/asm/pnv-ocxl.h | |||
@@ -28,7 +28,7 @@ extern int pnv_ocxl_map_xsl_regs(struct pci_dev *dev, void __iomem **dsisr, | |||
28 | extern int pnv_ocxl_spa_setup(struct pci_dev *dev, void *spa_mem, int PE_mask, | 28 | extern int pnv_ocxl_spa_setup(struct pci_dev *dev, void *spa_mem, int PE_mask, |
29 | void **platform_data); | 29 | void **platform_data); |
30 | extern void pnv_ocxl_spa_release(void *platform_data); | 30 | extern void pnv_ocxl_spa_release(void *platform_data); |
31 | extern int pnv_ocxl_spa_remove_pe(void *platform_data, int pe_handle); | 31 | extern int pnv_ocxl_spa_remove_pe_from_cache(void *platform_data, int pe_handle); |
32 | 32 | ||
33 | extern int pnv_ocxl_alloc_xive_irq(u32 *irq, u64 *trigger_addr); | 33 | extern int pnv_ocxl_alloc_xive_irq(u32 *irq, u64 *trigger_addr); |
34 | extern void pnv_ocxl_free_xive_irq(u32 irq); | 34 | extern void pnv_ocxl_free_xive_irq(u32 irq); |
diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h index 18883b8a6dac..4436887bc415 100644 --- a/arch/powerpc/include/asm/ppc-opcode.h +++ b/arch/powerpc/include/asm/ppc-opcode.h | |||
@@ -162,6 +162,7 @@ | |||
162 | /* VMX Vector Store Instructions */ | 162 | /* VMX Vector Store Instructions */ |
163 | #define OP_31_XOP_STVX 231 | 163 | #define OP_31_XOP_STVX 231 |
164 | 164 | ||
165 | #define OP_31 31 | ||
165 | #define OP_LWZ 32 | 166 | #define OP_LWZ 32 |
166 | #define OP_STFS 52 | 167 | #define OP_STFS 52 |
167 | #define OP_STFSU 53 | 168 | #define OP_STFSU 53 |
diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h index 13f7f4c0e1ea..75ece56dcd62 100644 --- a/arch/powerpc/include/asm/ppc_asm.h +++ b/arch/powerpc/include/asm/ppc_asm.h | |||
@@ -80,10 +80,8 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR) | |||
80 | #else | 80 | #else |
81 | #define SAVE_GPR(n, base) stw n,GPR0+4*(n)(base) | 81 | #define SAVE_GPR(n, base) stw n,GPR0+4*(n)(base) |
82 | #define REST_GPR(n, base) lwz n,GPR0+4*(n)(base) | 82 | #define REST_GPR(n, base) lwz n,GPR0+4*(n)(base) |
83 | #define SAVE_NVGPRS(base) SAVE_GPR(13, base); SAVE_8GPRS(14, base); \ | 83 | #define SAVE_NVGPRS(base) stmw 13, GPR0+4*13(base) |
84 | SAVE_10GPRS(22, base) | 84 | #define REST_NVGPRS(base) lmw 13, GPR0+4*13(base) |
85 | #define REST_NVGPRS(base) REST_GPR(13, base); REST_8GPRS(14, base); \ | ||
86 | REST_10GPRS(22, base) | ||
87 | #endif | 85 | #endif |
88 | 86 | ||
89 | #define SAVE_2GPRS(n, base) SAVE_GPR(n, base); SAVE_GPR(n+1, base) | 87 | #define SAVE_2GPRS(n, base) SAVE_GPR(n, base); SAVE_GPR(n+1, base) |
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h index c4b36a494a63..5debe337ea9d 100644 --- a/arch/powerpc/include/asm/processor.h +++ b/arch/powerpc/include/asm/processor.h | |||
@@ -249,7 +249,7 @@ struct thread_struct { | |||
249 | unsigned long ksp_vsid; | 249 | unsigned long ksp_vsid; |
250 | #endif | 250 | #endif |
251 | struct pt_regs *regs; /* Pointer to saved register state */ | 251 | struct pt_regs *regs; /* Pointer to saved register state */ |
252 | mm_segment_t fs; /* for get_fs() validation */ | 252 | mm_segment_t addr_limit; /* for get_fs() validation */ |
253 | #ifdef CONFIG_BOOKE | 253 | #ifdef CONFIG_BOOKE |
254 | /* BookE base exception scratch space; align on cacheline */ | 254 | /* BookE base exception scratch space; align on cacheline */ |
255 | unsigned long normsave[8] ____cacheline_aligned; | 255 | unsigned long normsave[8] ____cacheline_aligned; |
@@ -264,10 +264,6 @@ struct thread_struct { | |||
264 | struct thread_fp_state *fp_save_area; | 264 | struct thread_fp_state *fp_save_area; |
265 | int fpexc_mode; /* floating-point exception mode */ | 265 | int fpexc_mode; /* floating-point exception mode */ |
266 | unsigned int align_ctl; /* alignment handling control */ | 266 | unsigned int align_ctl; /* alignment handling control */ |
267 | #ifdef CONFIG_PPC64 | ||
268 | unsigned long start_tb; /* Start purr when proc switched in */ | ||
269 | unsigned long accum_tb; /* Total accumulated purr for process */ | ||
270 | #endif | ||
271 | #ifdef CONFIG_HAVE_HW_BREAKPOINT | 267 | #ifdef CONFIG_HAVE_HW_BREAKPOINT |
272 | struct perf_event *ptrace_bps[HBP_NUM]; | 268 | struct perf_event *ptrace_bps[HBP_NUM]; |
273 | /* | 269 | /* |
@@ -383,7 +379,7 @@ struct thread_struct { | |||
383 | #define INIT_THREAD { \ | 379 | #define INIT_THREAD { \ |
384 | .ksp = INIT_SP, \ | 380 | .ksp = INIT_SP, \ |
385 | .ksp_limit = INIT_SP_LIMIT, \ | 381 | .ksp_limit = INIT_SP_LIMIT, \ |
386 | .fs = KERNEL_DS, \ | 382 | .addr_limit = KERNEL_DS, \ |
387 | .pgdir = swapper_pg_dir, \ | 383 | .pgdir = swapper_pg_dir, \ |
388 | .fpexc_mode = MSR_FE0 | MSR_FE1, \ | 384 | .fpexc_mode = MSR_FE0 | MSR_FE1, \ |
389 | SPEFSCR_INIT \ | 385 | SPEFSCR_INIT \ |
@@ -392,7 +388,7 @@ struct thread_struct { | |||
392 | #define INIT_THREAD { \ | 388 | #define INIT_THREAD { \ |
393 | .ksp = INIT_SP, \ | 389 | .ksp = INIT_SP, \ |
394 | .regs = (struct pt_regs *)INIT_SP - 1, /* XXX bogus, I think */ \ | 390 | .regs = (struct pt_regs *)INIT_SP - 1, /* XXX bogus, I think */ \ |
395 | .fs = KERNEL_DS, \ | 391 | .addr_limit = KERNEL_DS, \ |
396 | .fpexc_mode = 0, \ | 392 | .fpexc_mode = 0, \ |
397 | .ppr = INIT_PPR, \ | 393 | .ppr = INIT_PPR, \ |
398 | .fscr = FSCR_TAR | FSCR_EBB \ | 394 | .fscr = FSCR_TAR | FSCR_EBB \ |
diff --git a/arch/powerpc/include/asm/pte-common.h b/arch/powerpc/include/asm/pte-common.h index c4a72c7a8c83..050b0d775324 100644 --- a/arch/powerpc/include/asm/pte-common.h +++ b/arch/powerpc/include/asm/pte-common.h | |||
@@ -60,10 +60,6 @@ | |||
60 | #ifndef _PMD_PRESENT_MASK | 60 | #ifndef _PMD_PRESENT_MASK |
61 | #define _PMD_PRESENT_MASK _PMD_PRESENT | 61 | #define _PMD_PRESENT_MASK _PMD_PRESENT |
62 | #endif | 62 | #endif |
63 | #ifndef _PMD_SIZE | ||
64 | #define _PMD_SIZE 0 | ||
65 | #define PMD_PAGE_SIZE(pmd) bad_call_to_PMD_PAGE_SIZE() | ||
66 | #endif | ||
67 | #ifndef _PMD_USER | 63 | #ifndef _PMD_USER |
68 | #define _PMD_USER 0 | 64 | #define _PMD_USER 0 |
69 | #endif | 65 | #endif |
@@ -88,11 +84,7 @@ | |||
88 | #define _PTE_NONE_MASK _PAGE_HPTEFLAGS | 84 | #define _PTE_NONE_MASK _PAGE_HPTEFLAGS |
89 | #endif | 85 | #endif |
90 | 86 | ||
91 | /* Make sure we get a link error if PMD_PAGE_SIZE is ever called on a | ||
92 | * kernel without large page PMD support | ||
93 | */ | ||
94 | #ifndef __ASSEMBLY__ | 87 | #ifndef __ASSEMBLY__ |
95 | extern unsigned long bad_call_to_PMD_PAGE_SIZE(void); | ||
96 | 88 | ||
97 | /* | 89 | /* |
98 | * Don't just check for any non zero bits in __PAGE_USER, since for book3e | 90 | * Don't just check for any non zero bits in __PAGE_USER, since for book3e |
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index cb0f272ce123..75c5b2cd9d66 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h | |||
@@ -146,6 +146,12 @@ | |||
146 | #define MSR_64BIT 0 | 146 | #define MSR_64BIT 0 |
147 | #endif | 147 | #endif |
148 | 148 | ||
149 | /* Condition Register related */ | ||
150 | #define CR0_SHIFT 28 | ||
151 | #define CR0_MASK 0xF | ||
152 | #define CR0_TBEGIN_FAILURE (0x2 << 28) /* 0b0010 */ | ||
153 | |||
154 | |||
149 | /* Power Management - Processor Stop Status and Control Register Fields */ | 155 | /* Power Management - Processor Stop Status and Control Register Fields */ |
150 | #define PSSCR_RL_MASK 0x0000000F /* Requested Level */ | 156 | #define PSSCR_RL_MASK 0x0000000F /* Requested Level */ |
151 | #define PSSCR_MTL_MASK 0x000000F0 /* Maximum Transition Level */ | 157 | #define PSSCR_MTL_MASK 0x000000F0 /* Maximum Transition Level */ |
@@ -239,13 +245,27 @@ | |||
239 | #define SPRN_TFIAR 0x81 /* Transaction Failure Inst Addr */ | 245 | #define SPRN_TFIAR 0x81 /* Transaction Failure Inst Addr */ |
240 | #define SPRN_TEXASR 0x82 /* Transaction EXception & Summary */ | 246 | #define SPRN_TEXASR 0x82 /* Transaction EXception & Summary */ |
241 | #define SPRN_TEXASRU 0x83 /* '' '' '' Upper 32 */ | 247 | #define SPRN_TEXASRU 0x83 /* '' '' '' Upper 32 */ |
242 | #define TEXASR_ABORT __MASK(63-31) /* terminated by tabort or treclaim */ | 248 | |
243 | #define TEXASR_SUSP __MASK(63-32) /* tx failed in suspended state */ | 249 | #define TEXASR_FC_LG (63 - 7) /* Failure Code */ |
244 | #define TEXASR_HV __MASK(63-34) /* MSR[HV] when failure occurred */ | 250 | #define TEXASR_AB_LG (63 - 31) /* Abort */ |
245 | #define TEXASR_PR __MASK(63-35) /* MSR[PR] when failure occurred */ | 251 | #define TEXASR_SU_LG (63 - 32) /* Suspend */ |
246 | #define TEXASR_FS __MASK(63-36) /* TEXASR Failure Summary */ | 252 | #define TEXASR_HV_LG (63 - 34) /* Hypervisor state*/ |
247 | #define TEXASR_EXACT __MASK(63-37) /* TFIAR value is exact */ | 253 | #define TEXASR_PR_LG (63 - 35) /* Privilege level */ |
254 | #define TEXASR_FS_LG (63 - 36) /* failure summary */ | ||
255 | #define TEXASR_EX_LG (63 - 37) /* TFIAR exact bit */ | ||
256 | #define TEXASR_ROT_LG (63 - 38) /* ROT bit */ | ||
257 | |||
258 | #define TEXASR_ABORT __MASK(TEXASR_AB_LG) /* terminated by tabort or treclaim */ | ||
259 | #define TEXASR_SUSP __MASK(TEXASR_SU_LG) /* tx failed in suspended state */ | ||
260 | #define TEXASR_HV __MASK(TEXASR_HV_LG) /* MSR[HV] when failure occurred */ | ||
261 | #define TEXASR_PR __MASK(TEXASR_PR_LG) /* MSR[PR] when failure occurred */ | ||
262 | #define TEXASR_FS __MASK(TEXASR_FS_LG) /* TEXASR Failure Summary */ | ||
263 | #define TEXASR_EXACT __MASK(TEXASR_EX_LG) /* TFIAR value is exact */ | ||
264 | #define TEXASR_ROT __MASK(TEXASR_ROT_LG) | ||
265 | #define TEXASR_FC (ASM_CONST(0xFF) << TEXASR_FC_LG) | ||
266 | |||
248 | #define SPRN_TFHAR 0x80 /* Transaction Failure Handler Addr */ | 267 | #define SPRN_TFHAR 0x80 /* Transaction Failure Handler Addr */ |
268 | |||
249 | #define SPRN_TIDR 144 /* Thread ID register */ | 269 | #define SPRN_TIDR 144 /* Thread ID register */ |
250 | #define SPRN_CTRLF 0x088 | 270 | #define SPRN_CTRLF 0x088 |
251 | #define SPRN_CTRLT 0x098 | 271 | #define SPRN_CTRLT 0x098 |
diff --git a/arch/powerpc/include/asm/rheap.h b/arch/powerpc/include/asm/rheap.h index 172381769cfc..8e83703d6736 100644 --- a/arch/powerpc/include/asm/rheap.h +++ b/arch/powerpc/include/asm/rheap.h | |||
@@ -83,6 +83,9 @@ extern int rh_get_stats(rh_info_t * info, int what, int max_stats, | |||
83 | /* Simple dump of remote heap info */ | 83 | /* Simple dump of remote heap info */ |
84 | extern void rh_dump(rh_info_t * info); | 84 | extern void rh_dump(rh_info_t * info); |
85 | 85 | ||
86 | /* Simple dump of remote info block */ | ||
87 | void rh_dump_blk(rh_info_t *info, rh_block_t *blk); | ||
88 | |||
86 | /* Set owner of taken block */ | 89 | /* Set owner of taken block */ |
87 | extern int rh_set_owner(rh_info_t * info, unsigned long start, const char *owner); | 90 | extern int rh_set_owner(rh_info_t * info, unsigned long start, const char *owner); |
88 | 91 | ||
diff --git a/arch/powerpc/include/asm/rtas.h b/arch/powerpc/include/asm/rtas.h index ec9dd79398ee..71e393c46a49 100644 --- a/arch/powerpc/include/asm/rtas.h +++ b/arch/powerpc/include/asm/rtas.h | |||
@@ -361,7 +361,7 @@ extern int rtas_offline_cpus_mask(cpumask_var_t cpus); | |||
361 | extern int rtas_ibm_suspend_me(u64 handle); | 361 | extern int rtas_ibm_suspend_me(u64 handle); |
362 | 362 | ||
363 | struct rtc_time; | 363 | struct rtc_time; |
364 | extern unsigned long rtas_get_boot_time(void); | 364 | extern time64_t rtas_get_boot_time(void); |
365 | extern void rtas_get_rtc_time(struct rtc_time *rtc_time); | 365 | extern void rtas_get_rtc_time(struct rtc_time *rtc_time); |
366 | extern int rtas_set_rtc_time(struct rtc_time *rtc_time); | 366 | extern int rtas_set_rtc_time(struct rtc_time *rtc_time); |
367 | 367 | ||
diff --git a/arch/powerpc/include/asm/setup.h b/arch/powerpc/include/asm/setup.h index 27fa52ed6d00..8721fd004291 100644 --- a/arch/powerpc/include/asm/setup.h +++ b/arch/powerpc/include/asm/setup.h | |||
@@ -52,6 +52,15 @@ enum l1d_flush_type { | |||
52 | 52 | ||
53 | void setup_rfi_flush(enum l1d_flush_type, bool enable); | 53 | void setup_rfi_flush(enum l1d_flush_type, bool enable); |
54 | void do_rfi_flush_fixups(enum l1d_flush_type types); | 54 | void do_rfi_flush_fixups(enum l1d_flush_type types); |
55 | void setup_barrier_nospec(void); | ||
56 | void do_barrier_nospec_fixups(bool enable); | ||
57 | extern bool barrier_nospec_enabled; | ||
58 | |||
59 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
60 | void do_barrier_nospec_fixups_range(bool enable, void *start, void *end); | ||
61 | #else | ||
62 | static inline void do_barrier_nospec_fixups_range(bool enable, void *start, void *end) { }; | ||
63 | #endif | ||
55 | 64 | ||
56 | #endif /* !__ASSEMBLY__ */ | 65 | #endif /* !__ASSEMBLY__ */ |
57 | 66 | ||
diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h index cfecfee1194b..29ffaabdf75b 100644 --- a/arch/powerpc/include/asm/smp.h +++ b/arch/powerpc/include/asm/smp.h | |||
@@ -58,6 +58,7 @@ struct smp_ops_t { | |||
58 | 58 | ||
59 | extern void smp_flush_nmi_ipi(u64 delay_us); | 59 | extern void smp_flush_nmi_ipi(u64 delay_us); |
60 | extern int smp_send_nmi_ipi(int cpu, void (*fn)(struct pt_regs *), u64 delay_us); | 60 | extern int smp_send_nmi_ipi(int cpu, void (*fn)(struct pt_regs *), u64 delay_us); |
61 | extern int smp_send_safe_nmi_ipi(int cpu, void (*fn)(struct pt_regs *), u64 delay_us); | ||
61 | extern void smp_send_debugger_break(void); | 62 | extern void smp_send_debugger_break(void); |
62 | extern void start_secondary_resume(void); | 63 | extern void start_secondary_resume(void); |
63 | extern void smp_generic_give_timebase(void); | 64 | extern void smp_generic_give_timebase(void); |
diff --git a/arch/powerpc/include/asm/sstep.h b/arch/powerpc/include/asm/sstep.h index ab9d849644d0..4547891a684b 100644 --- a/arch/powerpc/include/asm/sstep.h +++ b/arch/powerpc/include/asm/sstep.h | |||
@@ -97,6 +97,8 @@ enum instruction_type { | |||
97 | #define SIZE(n) ((n) << 12) | 97 | #define SIZE(n) ((n) << 12) |
98 | #define GETSIZE(w) ((w) >> 12) | 98 | #define GETSIZE(w) ((w) >> 12) |
99 | 99 | ||
100 | #define GETTYPE(t) ((t) & INSTR_TYPE_MASK) | ||
101 | |||
100 | #define MKOP(t, f, s) ((t) | (f) | SIZE(s)) | 102 | #define MKOP(t, f, s) ((t) | (f) | SIZE(s)) |
101 | 103 | ||
102 | struct instruction_op { | 104 | struct instruction_op { |
diff --git a/arch/powerpc/include/asm/switch_to.h b/arch/powerpc/include/asm/switch_to.h index be8c9fa23983..5b03d8a82409 100644 --- a/arch/powerpc/include/asm/switch_to.h +++ b/arch/powerpc/include/asm/switch_to.h | |||
@@ -94,6 +94,5 @@ static inline void clear_task_ebb(struct task_struct *t) | |||
94 | extern int set_thread_uses_vas(void); | 94 | extern int set_thread_uses_vas(void); |
95 | 95 | ||
96 | extern int set_thread_tidr(struct task_struct *t); | 96 | extern int set_thread_tidr(struct task_struct *t); |
97 | extern void clear_thread_tidr(struct task_struct *t); | ||
98 | 97 | ||
99 | #endif /* _ASM_POWERPC_SWITCH_TO_H */ | 98 | #endif /* _ASM_POWERPC_SWITCH_TO_H */ |
diff --git a/arch/powerpc/include/asm/syscalls.h b/arch/powerpc/include/asm/syscalls.h index 1b90a3516a35..398171fdcd9f 100644 --- a/arch/powerpc/include/asm/syscalls.h +++ b/arch/powerpc/include/asm/syscalls.h | |||
@@ -16,7 +16,7 @@ asmlinkage long sys_mmap2(unsigned long addr, size_t len, | |||
16 | unsigned long prot, unsigned long flags, | 16 | unsigned long prot, unsigned long flags, |
17 | unsigned long fd, unsigned long pgoff); | 17 | unsigned long fd, unsigned long pgoff); |
18 | asmlinkage long ppc64_personality(unsigned long personality); | 18 | asmlinkage long ppc64_personality(unsigned long personality); |
19 | asmlinkage int ppc_rtas(struct rtas_args __user *uargs); | 19 | asmlinkage long sys_rtas(struct rtas_args __user *uargs); |
20 | 20 | ||
21 | #endif /* __KERNEL__ */ | 21 | #endif /* __KERNEL__ */ |
22 | #endif /* __ASM_POWERPC_SYSCALLS_H */ | 22 | #endif /* __ASM_POWERPC_SYSCALLS_H */ |
diff --git a/arch/powerpc/include/asm/systbl.h b/arch/powerpc/include/asm/systbl.h index d61f9c96d916..79a3b47e4839 100644 --- a/arch/powerpc/include/asm/systbl.h +++ b/arch/powerpc/include/asm/systbl.h | |||
@@ -147,7 +147,7 @@ SYSCALL_SPU(setfsuid) | |||
147 | SYSCALL_SPU(setfsgid) | 147 | SYSCALL_SPU(setfsgid) |
148 | SYSCALL_SPU(llseek) | 148 | SYSCALL_SPU(llseek) |
149 | COMPAT_SYS_SPU(getdents) | 149 | COMPAT_SYS_SPU(getdents) |
150 | SYSX_SPU(sys_select,ppc32_select,sys_select) | 150 | COMPAT_SPU_NEW(select) |
151 | SYSCALL_SPU(flock) | 151 | SYSCALL_SPU(flock) |
152 | SYSCALL_SPU(msync) | 152 | SYSCALL_SPU(msync) |
153 | COMPAT_SYS_SPU(readv) | 153 | COMPAT_SYS_SPU(readv) |
@@ -245,7 +245,7 @@ SYSCALL_SPU(epoll_create) | |||
245 | SYSCALL_SPU(epoll_ctl) | 245 | SYSCALL_SPU(epoll_ctl) |
246 | SYSCALL_SPU(epoll_wait) | 246 | SYSCALL_SPU(epoll_wait) |
247 | SYSCALL_SPU(remap_file_pages) | 247 | SYSCALL_SPU(remap_file_pages) |
248 | SYSX_SPU(sys_timer_create,compat_sys_timer_create,sys_timer_create) | 248 | COMPAT_SYS_SPU(timer_create) |
249 | COMPAT_SYS_SPU(timer_settime) | 249 | COMPAT_SYS_SPU(timer_settime) |
250 | COMPAT_SYS_SPU(timer_gettime) | 250 | COMPAT_SYS_SPU(timer_gettime) |
251 | SYSCALL_SPU(timer_getoverrun) | 251 | SYSCALL_SPU(timer_getoverrun) |
@@ -260,7 +260,7 @@ COMPAT_SYS_SPU(utimes) | |||
260 | COMPAT_SYS_SPU(statfs64) | 260 | COMPAT_SYS_SPU(statfs64) |
261 | COMPAT_SYS_SPU(fstatfs64) | 261 | COMPAT_SYS_SPU(fstatfs64) |
262 | SYSX(sys_ni_syscall,ppc_fadvise64_64,ppc_fadvise64_64) | 262 | SYSX(sys_ni_syscall,ppc_fadvise64_64,ppc_fadvise64_64) |
263 | PPC_SYS_SPU(rtas) | 263 | SYSCALL_SPU(rtas) |
264 | OLDSYS(debug_setcontext) | 264 | OLDSYS(debug_setcontext) |
265 | SYSCALL(ni_syscall) | 265 | SYSCALL(ni_syscall) |
266 | COMPAT_SYS(migrate_pages) | 266 | COMPAT_SYS(migrate_pages) |
diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h index 5964145db03d..f308dfeb2746 100644 --- a/arch/powerpc/include/asm/thread_info.h +++ b/arch/powerpc/include/asm/thread_info.h | |||
@@ -79,8 +79,7 @@ extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src | |||
79 | #define TIF_SYSCALL_TRACE 0 /* syscall trace active */ | 79 | #define TIF_SYSCALL_TRACE 0 /* syscall trace active */ |
80 | #define TIF_SIGPENDING 1 /* signal pending */ | 80 | #define TIF_SIGPENDING 1 /* signal pending */ |
81 | #define TIF_NEED_RESCHED 2 /* rescheduling necessary */ | 81 | #define TIF_NEED_RESCHED 2 /* rescheduling necessary */ |
82 | #define TIF_POLLING_NRFLAG 3 /* true if poll_idle() is polling | 82 | #define TIF_FSCHECK 3 /* Check FS is USER_DS on return */ |
83 | TIF_NEED_RESCHED */ | ||
84 | #define TIF_32BIT 4 /* 32 bit binary */ | 83 | #define TIF_32BIT 4 /* 32 bit binary */ |
85 | #define TIF_RESTORE_TM 5 /* need to restore TM FP/VEC/VSX */ | 84 | #define TIF_RESTORE_TM 5 /* need to restore TM FP/VEC/VSX */ |
86 | #define TIF_PATCH_PENDING 6 /* pending live patching update */ | 85 | #define TIF_PATCH_PENDING 6 /* pending live patching update */ |
@@ -99,6 +98,7 @@ extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src | |||
99 | #if defined(CONFIG_PPC64) | 98 | #if defined(CONFIG_PPC64) |
100 | #define TIF_ELF2ABI 18 /* function descriptors must die! */ | 99 | #define TIF_ELF2ABI 18 /* function descriptors must die! */ |
101 | #endif | 100 | #endif |
101 | #define TIF_POLLING_NRFLAG 19 /* true if poll_idle() is polling TIF_NEED_RESCHED */ | ||
102 | 102 | ||
103 | /* as above, but as bit values */ | 103 | /* as above, but as bit values */ |
104 | #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) | 104 | #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) |
@@ -118,13 +118,15 @@ extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src | |||
118 | #define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT) | 118 | #define _TIF_SYSCALL_TRACEPOINT (1<<TIF_SYSCALL_TRACEPOINT) |
119 | #define _TIF_EMULATE_STACK_STORE (1<<TIF_EMULATE_STACK_STORE) | 119 | #define _TIF_EMULATE_STACK_STORE (1<<TIF_EMULATE_STACK_STORE) |
120 | #define _TIF_NOHZ (1<<TIF_NOHZ) | 120 | #define _TIF_NOHZ (1<<TIF_NOHZ) |
121 | #define _TIF_FSCHECK (1<<TIF_FSCHECK) | ||
121 | #define _TIF_SYSCALL_DOTRACE (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \ | 122 | #define _TIF_SYSCALL_DOTRACE (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT | \ |
122 | _TIF_SECCOMP | _TIF_SYSCALL_TRACEPOINT | \ | 123 | _TIF_SECCOMP | _TIF_SYSCALL_TRACEPOINT | \ |
123 | _TIF_NOHZ) | 124 | _TIF_NOHZ) |
124 | 125 | ||
125 | #define _TIF_USER_WORK_MASK (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \ | 126 | #define _TIF_USER_WORK_MASK (_TIF_SIGPENDING | _TIF_NEED_RESCHED | \ |
126 | _TIF_NOTIFY_RESUME | _TIF_UPROBE | \ | 127 | _TIF_NOTIFY_RESUME | _TIF_UPROBE | \ |
127 | _TIF_RESTORE_TM | _TIF_PATCH_PENDING) | 128 | _TIF_RESTORE_TM | _TIF_PATCH_PENDING | \ |
129 | _TIF_FSCHECK) | ||
128 | #define _TIF_PERSYSCALL_MASK (_TIF_RESTOREALL|_TIF_NOERROR) | 130 | #define _TIF_PERSYSCALL_MASK (_TIF_RESTOREALL|_TIF_NOERROR) |
129 | 131 | ||
130 | /* Bits in local_flags */ | 132 | /* Bits in local_flags */ |
diff --git a/arch/powerpc/include/asm/time.h b/arch/powerpc/include/asm/time.h index db546c034905..b80d492ceb29 100644 --- a/arch/powerpc/include/asm/time.h +++ b/arch/powerpc/include/asm/time.h | |||
@@ -26,9 +26,6 @@ extern unsigned long tb_ticks_per_usec; | |||
26 | extern unsigned long tb_ticks_per_sec; | 26 | extern unsigned long tb_ticks_per_sec; |
27 | extern struct clock_event_device decrementer_clockevent; | 27 | extern struct clock_event_device decrementer_clockevent; |
28 | 28 | ||
29 | struct rtc_time; | ||
30 | extern void to_tm(int tim, struct rtc_time * tm); | ||
31 | extern void tick_broadcast_ipi_handler(void); | ||
32 | 29 | ||
33 | extern void generic_calibrate_decr(void); | 30 | extern void generic_calibrate_decr(void); |
34 | extern void hdec_interrupt(struct pt_regs *regs); | 31 | extern void hdec_interrupt(struct pt_regs *regs); |
@@ -196,14 +193,6 @@ extern u64 mulhdu(u64, u64); | |||
196 | extern void div128_by_32(u64 dividend_high, u64 dividend_low, | 193 | extern void div128_by_32(u64 dividend_high, u64 dividend_low, |
197 | unsigned divisor, struct div_result *dr); | 194 | unsigned divisor, struct div_result *dr); |
198 | 195 | ||
199 | /* Used to store Processor Utilization register (purr) values */ | ||
200 | |||
201 | struct cpu_usage { | ||
202 | u64 current_tb; /* Holds the current purr register values */ | ||
203 | }; | ||
204 | |||
205 | DECLARE_PER_CPU(struct cpu_usage, cpu_usage_array); | ||
206 | |||
207 | extern void secondary_cpu_time_init(void); | 196 | extern void secondary_cpu_time_init(void); |
208 | extern void __init time_init(void); | 197 | extern void __init time_init(void); |
209 | 198 | ||
diff --git a/arch/powerpc/include/asm/tlb.h b/arch/powerpc/include/asm/tlb.h index a7eabff27a0f..9138baccebb0 100644 --- a/arch/powerpc/include/asm/tlb.h +++ b/arch/powerpc/include/asm/tlb.h | |||
@@ -76,6 +76,19 @@ static inline int mm_is_thread_local(struct mm_struct *mm) | |||
76 | return false; | 76 | return false; |
77 | return cpumask_test_cpu(smp_processor_id(), mm_cpumask(mm)); | 77 | return cpumask_test_cpu(smp_processor_id(), mm_cpumask(mm)); |
78 | } | 78 | } |
79 | static inline void mm_reset_thread_local(struct mm_struct *mm) | ||
80 | { | ||
81 | WARN_ON(atomic_read(&mm->context.copros) > 0); | ||
82 | /* | ||
83 | * It's possible for mm_access to take a reference on mm_users to | ||
84 | * access the remote mm from another thread, but it's not allowed | ||
85 | * to set mm_cpumask, so mm_users may be > 1 here. | ||
86 | */ | ||
87 | WARN_ON(current->mm != mm); | ||
88 | atomic_set(&mm->context.active_cpus, 1); | ||
89 | cpumask_clear(mm_cpumask(mm)); | ||
90 | cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm)); | ||
91 | } | ||
79 | #else /* CONFIG_PPC_BOOK3S_64 */ | 92 | #else /* CONFIG_PPC_BOOK3S_64 */ |
80 | static inline int mm_is_thread_local(struct mm_struct *mm) | 93 | static inline int mm_is_thread_local(struct mm_struct *mm) |
81 | { | 94 | { |
diff --git a/arch/powerpc/include/asm/tm.h b/arch/powerpc/include/asm/tm.h index b1658c97047c..e94f6db5e367 100644 --- a/arch/powerpc/include/asm/tm.h +++ b/arch/powerpc/include/asm/tm.h | |||
@@ -10,12 +10,10 @@ | |||
10 | 10 | ||
11 | #ifndef __ASSEMBLY__ | 11 | #ifndef __ASSEMBLY__ |
12 | 12 | ||
13 | extern void tm_enable(void); | ||
14 | extern void tm_reclaim(struct thread_struct *thread, | 13 | extern void tm_reclaim(struct thread_struct *thread, |
15 | uint8_t cause); | 14 | uint8_t cause); |
16 | extern void tm_reclaim_current(uint8_t cause); | 15 | extern void tm_reclaim_current(uint8_t cause); |
17 | extern void tm_recheckpoint(struct thread_struct *thread); | 16 | extern void tm_recheckpoint(struct thread_struct *thread); |
18 | extern void tm_abort(uint8_t cause); | ||
19 | extern void tm_save_sprs(struct thread_struct *thread); | 17 | extern void tm_save_sprs(struct thread_struct *thread); |
20 | extern void tm_restore_sprs(struct thread_struct *thread); | 18 | extern void tm_restore_sprs(struct thread_struct *thread); |
21 | 19 | ||
diff --git a/arch/powerpc/include/asm/trace.h b/arch/powerpc/include/asm/trace.h index 33f3b479138b..d018e8602694 100644 --- a/arch/powerpc/include/asm/trace.h +++ b/arch/powerpc/include/asm/trace.h | |||
@@ -81,8 +81,7 @@ TRACE_EVENT_FN_COND(hcall_entry, | |||
81 | 81 | ||
82 | TRACE_EVENT_FN_COND(hcall_exit, | 82 | TRACE_EVENT_FN_COND(hcall_exit, |
83 | 83 | ||
84 | TP_PROTO(unsigned long opcode, unsigned long retval, | 84 | TP_PROTO(unsigned long opcode, long retval, unsigned long *retbuf), |
85 | unsigned long *retbuf), | ||
86 | 85 | ||
87 | TP_ARGS(opcode, retval, retbuf), | 86 | TP_ARGS(opcode, retval, retbuf), |
88 | 87 | ||
@@ -90,7 +89,7 @@ TRACE_EVENT_FN_COND(hcall_exit, | |||
90 | 89 | ||
91 | TP_STRUCT__entry( | 90 | TP_STRUCT__entry( |
92 | __field(unsigned long, opcode) | 91 | __field(unsigned long, opcode) |
93 | __field(unsigned long, retval) | 92 | __field(long, retval) |
94 | ), | 93 | ), |
95 | 94 | ||
96 | TP_fast_assign( | 95 | TP_fast_assign( |
@@ -98,7 +97,7 @@ TRACE_EVENT_FN_COND(hcall_exit, | |||
98 | __entry->retval = retval; | 97 | __entry->retval = retval; |
99 | ), | 98 | ), |
100 | 99 | ||
101 | TP_printk("opcode=%lu retval=%lu", __entry->opcode, __entry->retval), | 100 | TP_printk("opcode=%lu retval=%ld", __entry->opcode, __entry->retval), |
102 | 101 | ||
103 | hcall_tracepoint_regfunc, hcall_tracepoint_unregfunc | 102 | hcall_tracepoint_regfunc, hcall_tracepoint_unregfunc |
104 | ); | 103 | ); |
diff --git a/arch/powerpc/include/asm/uaccess.h b/arch/powerpc/include/asm/uaccess.h index a62ee663b2c8..468653ce844c 100644 --- a/arch/powerpc/include/asm/uaccess.h +++ b/arch/powerpc/include/asm/uaccess.h | |||
@@ -30,8 +30,14 @@ | |||
30 | #endif | 30 | #endif |
31 | 31 | ||
32 | #define get_ds() (KERNEL_DS) | 32 | #define get_ds() (KERNEL_DS) |
33 | #define get_fs() (current->thread.fs) | 33 | #define get_fs() (current->thread.addr_limit) |
34 | #define set_fs(val) (current->thread.fs = (val)) | 34 | |
35 | static inline void set_fs(mm_segment_t fs) | ||
36 | { | ||
37 | current->thread.addr_limit = fs; | ||
38 | /* On user-mode return check addr_limit (fs) is correct */ | ||
39 | set_thread_flag(TIF_FSCHECK); | ||
40 | } | ||
35 | 41 | ||
36 | #define segment_eq(a, b) ((a).seg == (b).seg) | 42 | #define segment_eq(a, b) ((a).seg == (b).seg) |
37 | 43 | ||
@@ -252,6 +258,7 @@ do { \ | |||
252 | __chk_user_ptr(ptr); \ | 258 | __chk_user_ptr(ptr); \ |
253 | if (!is_kernel_addr((unsigned long)__gu_addr)) \ | 259 | if (!is_kernel_addr((unsigned long)__gu_addr)) \ |
254 | might_fault(); \ | 260 | might_fault(); \ |
261 | barrier_nospec(); \ | ||
255 | __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ | 262 | __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ |
256 | (x) = (__typeof__(*(ptr)))__gu_val; \ | 263 | (x) = (__typeof__(*(ptr)))__gu_val; \ |
257 | __gu_err; \ | 264 | __gu_err; \ |
@@ -263,8 +270,10 @@ do { \ | |||
263 | unsigned long __gu_val = 0; \ | 270 | unsigned long __gu_val = 0; \ |
264 | const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ | 271 | const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ |
265 | might_fault(); \ | 272 | might_fault(); \ |
266 | if (access_ok(VERIFY_READ, __gu_addr, (size))) \ | 273 | if (access_ok(VERIFY_READ, __gu_addr, (size))) { \ |
274 | barrier_nospec(); \ | ||
267 | __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ | 275 | __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ |
276 | } \ | ||
268 | (x) = (__force __typeof__(*(ptr)))__gu_val; \ | 277 | (x) = (__force __typeof__(*(ptr)))__gu_val; \ |
269 | __gu_err; \ | 278 | __gu_err; \ |
270 | }) | 279 | }) |
@@ -275,6 +284,7 @@ do { \ | |||
275 | unsigned long __gu_val; \ | 284 | unsigned long __gu_val; \ |
276 | const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ | 285 | const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \ |
277 | __chk_user_ptr(ptr); \ | 286 | __chk_user_ptr(ptr); \ |
287 | barrier_nospec(); \ | ||
278 | __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ | 288 | __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \ |
279 | (x) = (__force __typeof__(*(ptr)))__gu_val; \ | 289 | (x) = (__force __typeof__(*(ptr)))__gu_val; \ |
280 | __gu_err; \ | 290 | __gu_err; \ |
@@ -302,15 +312,19 @@ static inline unsigned long raw_copy_from_user(void *to, | |||
302 | 312 | ||
303 | switch (n) { | 313 | switch (n) { |
304 | case 1: | 314 | case 1: |
315 | barrier_nospec(); | ||
305 | __get_user_size(*(u8 *)to, from, 1, ret); | 316 | __get_user_size(*(u8 *)to, from, 1, ret); |
306 | break; | 317 | break; |
307 | case 2: | 318 | case 2: |
319 | barrier_nospec(); | ||
308 | __get_user_size(*(u16 *)to, from, 2, ret); | 320 | __get_user_size(*(u16 *)to, from, 2, ret); |
309 | break; | 321 | break; |
310 | case 4: | 322 | case 4: |
323 | barrier_nospec(); | ||
311 | __get_user_size(*(u32 *)to, from, 4, ret); | 324 | __get_user_size(*(u32 *)to, from, 4, ret); |
312 | break; | 325 | break; |
313 | case 8: | 326 | case 8: |
327 | barrier_nospec(); | ||
314 | __get_user_size(*(u64 *)to, from, 8, ret); | 328 | __get_user_size(*(u64 *)to, from, 8, ret); |
315 | break; | 329 | break; |
316 | } | 330 | } |
@@ -318,6 +332,7 @@ static inline unsigned long raw_copy_from_user(void *to, | |||
318 | return 0; | 332 | return 0; |
319 | } | 333 | } |
320 | 334 | ||
335 | barrier_nospec(); | ||
321 | return __copy_tofrom_user((__force void __user *)to, from, n); | 336 | return __copy_tofrom_user((__force void __user *)to, from, n); |
322 | } | 337 | } |
323 | 338 | ||
diff --git a/arch/powerpc/include/asm/xive-regs.h b/arch/powerpc/include/asm/xive-regs.h index fa4288822b68..6de989f8defd 100644 --- a/arch/powerpc/include/asm/xive-regs.h +++ b/arch/powerpc/include/asm/xive-regs.h | |||
@@ -123,10 +123,4 @@ | |||
123 | #define TM_QW3_NSR_I PPC_BIT8(2) | 123 | #define TM_QW3_NSR_I PPC_BIT8(2) |
124 | #define TM_QW3_NSR_GRP_LVL PPC_BIT8(3,7) | 124 | #define TM_QW3_NSR_GRP_LVL PPC_BIT8(3,7) |
125 | 125 | ||
126 | /* Utilities to manipulate these (originaly from OPAL) */ | ||
127 | #define MASK_TO_LSH(m) (__builtin_ffsl(m) - 1) | ||
128 | #define GETFIELD(m, v) (((v) & (m)) >> MASK_TO_LSH(m)) | ||
129 | #define SETFIELD(m, v, val) \ | ||
130 | (((v) & ~(m)) | ((((typeof(v))(val)) << MASK_TO_LSH(m)) & (m))) | ||
131 | |||
132 | #endif /* _ASM_POWERPC_XIVE_REGS_H */ | 126 | #endif /* _ASM_POWERPC_XIVE_REGS_H */ |
diff --git a/arch/powerpc/include/asm/xmon.h b/arch/powerpc/include/asm/xmon.h index eb42a0c6e1d9..30ff69bd8f43 100644 --- a/arch/powerpc/include/asm/xmon.h +++ b/arch/powerpc/include/asm/xmon.h | |||
@@ -29,7 +29,7 @@ static inline void xmon_register_spus(struct list_head *list) { }; | |||
29 | extern int cpus_are_in_xmon(void); | 29 | extern int cpus_are_in_xmon(void); |
30 | #endif | 30 | #endif |
31 | 31 | ||
32 | extern void xmon_printf(const char *format, ...); | 32 | extern __printf(1, 2) void xmon_printf(const char *format, ...); |
33 | 33 | ||
34 | #endif /* __KERNEL __ */ | 34 | #endif /* __KERNEL __ */ |
35 | #endif /* __ASM_POWERPC_XMON_H */ | 35 | #endif /* __ASM_POWERPC_XMON_H */ |
diff --git a/arch/powerpc/include/asm/xor.h b/arch/powerpc/include/asm/xor.h index a36c2069d8ed..7d6dc503349d 100644 --- a/arch/powerpc/include/asm/xor.h +++ b/arch/powerpc/include/asm/xor.h | |||
@@ -24,17 +24,7 @@ | |||
24 | 24 | ||
25 | #include <asm/cputable.h> | 25 | #include <asm/cputable.h> |
26 | #include <asm/cpu_has_feature.h> | 26 | #include <asm/cpu_has_feature.h> |
27 | 27 | #include <asm/xor_altivec.h> | |
28 | void xor_altivec_2(unsigned long bytes, unsigned long *v1_in, | ||
29 | unsigned long *v2_in); | ||
30 | void xor_altivec_3(unsigned long bytes, unsigned long *v1_in, | ||
31 | unsigned long *v2_in, unsigned long *v3_in); | ||
32 | void xor_altivec_4(unsigned long bytes, unsigned long *v1_in, | ||
33 | unsigned long *v2_in, unsigned long *v3_in, | ||
34 | unsigned long *v4_in); | ||
35 | void xor_altivec_5(unsigned long bytes, unsigned long *v1_in, | ||
36 | unsigned long *v2_in, unsigned long *v3_in, | ||
37 | unsigned long *v4_in, unsigned long *v5_in); | ||
38 | 28 | ||
39 | static struct xor_block_template xor_block_altivec = { | 29 | static struct xor_block_template xor_block_altivec = { |
40 | .name = "altivec", | 30 | .name = "altivec", |
diff --git a/arch/powerpc/include/asm/xor_altivec.h b/arch/powerpc/include/asm/xor_altivec.h new file mode 100644 index 000000000000..6ca923510b59 --- /dev/null +++ b/arch/powerpc/include/asm/xor_altivec.h | |||
@@ -0,0 +1,19 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | #ifndef _ASM_POWERPC_XOR_ALTIVEC_H | ||
3 | #define _ASM_POWERPC_XOR_ALTIVEC_H | ||
4 | |||
5 | #ifdef CONFIG_ALTIVEC | ||
6 | |||
7 | void xor_altivec_2(unsigned long bytes, unsigned long *v1_in, | ||
8 | unsigned long *v2_in); | ||
9 | void xor_altivec_3(unsigned long bytes, unsigned long *v1_in, | ||
10 | unsigned long *v2_in, unsigned long *v3_in); | ||
11 | void xor_altivec_4(unsigned long bytes, unsigned long *v1_in, | ||
12 | unsigned long *v2_in, unsigned long *v3_in, | ||
13 | unsigned long *v4_in); | ||
14 | void xor_altivec_5(unsigned long bytes, unsigned long *v1_in, | ||
15 | unsigned long *v2_in, unsigned long *v3_in, | ||
16 | unsigned long *v4_in, unsigned long *v5_in); | ||
17 | |||
18 | #endif | ||
19 | #endif /* _ASM_POWERPC_XOR_ALTIVEC_H */ | ||
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c index 3e6c0744c174..11550a3d1ac2 100644 --- a/arch/powerpc/kernel/align.c +++ b/arch/powerpc/kernel/align.c | |||
@@ -339,7 +339,7 @@ int fix_alignment(struct pt_regs *regs) | |||
339 | if (r < 0) | 339 | if (r < 0) |
340 | return -EINVAL; | 340 | return -EINVAL; |
341 | 341 | ||
342 | type = op.type & INSTR_TYPE_MASK; | 342 | type = GETTYPE(op.type); |
343 | if (!OP_IS_LOAD_STORE(type)) { | 343 | if (!OP_IS_LOAD_STORE(type)) { |
344 | if (op.type != CACHEOP + DCBZ) | 344 | if (op.type != CACHEOP + DCBZ) |
345 | return -EINVAL; | 345 | return -EINVAL; |
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 8817c5a6bcc2..9fc9e0977009 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
@@ -180,6 +180,7 @@ int main(void) | |||
180 | OFFSET(PACAKMSR, paca_struct, kernel_msr); | 180 | OFFSET(PACAKMSR, paca_struct, kernel_msr); |
181 | OFFSET(PACAIRQSOFTMASK, paca_struct, irq_soft_mask); | 181 | OFFSET(PACAIRQSOFTMASK, paca_struct, irq_soft_mask); |
182 | OFFSET(PACAIRQHAPPENED, paca_struct, irq_happened); | 182 | OFFSET(PACAIRQHAPPENED, paca_struct, irq_happened); |
183 | OFFSET(PACA_FTRACE_ENABLED, paca_struct, ftrace_enabled); | ||
183 | #ifdef CONFIG_PPC_BOOK3S | 184 | #ifdef CONFIG_PPC_BOOK3S |
184 | OFFSET(PACACONTEXTID, paca_struct, mm_ctx_id); | 185 | OFFSET(PACACONTEXTID, paca_struct, mm_ctx_id); |
185 | #ifdef CONFIG_PPC_MM_SLICES | 186 | #ifdef CONFIG_PPC_MM_SLICES |
diff --git a/arch/powerpc/kernel/btext.c b/arch/powerpc/kernel/btext.c index 6537cba1a758..b2072d5bbf2b 100644 --- a/arch/powerpc/kernel/btext.c +++ b/arch/powerpc/kernel/btext.c | |||
@@ -157,20 +157,20 @@ void btext_map(void) | |||
157 | 157 | ||
158 | /* By default, we are no longer mapped */ | 158 | /* By default, we are no longer mapped */ |
159 | boot_text_mapped = 0; | 159 | boot_text_mapped = 0; |
160 | if (dispDeviceBase == 0) | 160 | if (!dispDeviceBase) |
161 | return; | 161 | return; |
162 | base = ((unsigned long) dispDeviceBase) & 0xFFFFF000UL; | 162 | base = ((unsigned long) dispDeviceBase) & 0xFFFFF000UL; |
163 | offset = ((unsigned long) dispDeviceBase) - base; | 163 | offset = ((unsigned long) dispDeviceBase) - base; |
164 | size = dispDeviceRowBytes * dispDeviceRect[3] + offset | 164 | size = dispDeviceRowBytes * dispDeviceRect[3] + offset |
165 | + dispDeviceRect[0]; | 165 | + dispDeviceRect[0]; |
166 | vbase = __ioremap(base, size, pgprot_val(pgprot_noncached_wc(__pgprot(0)))); | 166 | vbase = __ioremap(base, size, pgprot_val(pgprot_noncached_wc(__pgprot(0)))); |
167 | if (vbase == 0) | 167 | if (!vbase) |
168 | return; | 168 | return; |
169 | logicalDisplayBase = vbase + offset; | 169 | logicalDisplayBase = vbase + offset; |
170 | boot_text_mapped = 1; | 170 | boot_text_mapped = 1; |
171 | } | 171 | } |
172 | 172 | ||
173 | int btext_initialize(struct device_node *np) | 173 | static int btext_initialize(struct device_node *np) |
174 | { | 174 | { |
175 | unsigned int width, height, depth, pitch; | 175 | unsigned int width, height, depth, pitch; |
176 | unsigned long address = 0; | 176 | unsigned long address = 0; |
@@ -270,7 +270,7 @@ static unsigned char * calc_base(int x, int y) | |||
270 | unsigned char *base; | 270 | unsigned char *base; |
271 | 271 | ||
272 | base = logicalDisplayBase; | 272 | base = logicalDisplayBase; |
273 | if (base == 0) | 273 | if (!base) |
274 | base = dispDeviceBase; | 274 | base = dispDeviceBase; |
275 | base += (x + dispDeviceRect[0]) * (dispDeviceDepth >> 3); | 275 | base += (x + dispDeviceRect[0]) * (dispDeviceDepth >> 3); |
276 | base += (y + dispDeviceRect[1]) * dispDeviceRowBytes; | 276 | base += (y + dispDeviceRect[1]) * dispDeviceRowBytes; |
@@ -281,7 +281,7 @@ static unsigned char * calc_base(int x, int y) | |||
281 | void btext_update_display(unsigned long phys, int width, int height, | 281 | void btext_update_display(unsigned long phys, int width, int height, |
282 | int depth, int pitch) | 282 | int depth, int pitch) |
283 | { | 283 | { |
284 | if (dispDeviceBase == 0) | 284 | if (!dispDeviceBase) |
285 | return; | 285 | return; |
286 | 286 | ||
287 | /* check it's the same frame buffer (within 256MB) */ | 287 | /* check it's the same frame buffer (within 256MB) */ |
diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma.c index 138157deeadf..155170d70324 100644 --- a/arch/powerpc/kernel/dma.c +++ b/arch/powerpc/kernel/dma.c | |||
@@ -235,8 +235,6 @@ static inline dma_addr_t dma_nommu_map_page(struct device *dev, | |||
235 | enum dma_data_direction dir, | 235 | enum dma_data_direction dir, |
236 | unsigned long attrs) | 236 | unsigned long attrs) |
237 | { | 237 | { |
238 | BUG_ON(dir == DMA_NONE); | ||
239 | |||
240 | if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC)) | 238 | if (!(attrs & DMA_ATTR_SKIP_CPU_SYNC)) |
241 | __dma_sync_page(page, offset, size, dir); | 239 | __dma_sync_page(page, offset, size, dir); |
242 | 240 | ||
diff --git a/arch/powerpc/kernel/dt_cpu_ftrs.c b/arch/powerpc/kernel/dt_cpu_ftrs.c index c904477abaf3..4be1c0de9406 100644 --- a/arch/powerpc/kernel/dt_cpu_ftrs.c +++ b/arch/powerpc/kernel/dt_cpu_ftrs.c | |||
@@ -717,6 +717,7 @@ static __init void cpufeatures_cpu_quirks(void) | |||
717 | if ((version & 0xffff0000) == 0x004e0000) { | 717 | if ((version & 0xffff0000) == 0x004e0000) { |
718 | cur_cpu_spec->cpu_features &= ~(CPU_FTR_DAWR); | 718 | cur_cpu_spec->cpu_features &= ~(CPU_FTR_DAWR); |
719 | cur_cpu_spec->cpu_features |= CPU_FTR_P9_TLBIE_BUG; | 719 | cur_cpu_spec->cpu_features |= CPU_FTR_P9_TLBIE_BUG; |
720 | cur_cpu_spec->cpu_features |= CPU_FTR_P9_TIDR; | ||
720 | } | 721 | } |
721 | 722 | ||
722 | /* | 723 | /* |
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c index 90bb39b1a23c..5746809cfaad 100644 --- a/arch/powerpc/kernel/eeh.c +++ b/arch/powerpc/kernel/eeh.c | |||
@@ -263,9 +263,8 @@ static size_t eeh_dump_dev_log(struct eeh_dev *edev, char *buf, size_t len) | |||
263 | return n; | 263 | return n; |
264 | } | 264 | } |
265 | 265 | ||
266 | static void *eeh_dump_pe_log(void *data, void *flag) | 266 | static void *eeh_dump_pe_log(struct eeh_pe *pe, void *flag) |
267 | { | 267 | { |
268 | struct eeh_pe *pe = data; | ||
269 | struct eeh_dev *edev, *tmp; | 268 | struct eeh_dev *edev, *tmp; |
270 | size_t *plen = flag; | 269 | size_t *plen = flag; |
271 | 270 | ||
@@ -542,8 +541,12 @@ int eeh_dev_check_failure(struct eeh_dev *edev) | |||
542 | 541 | ||
543 | /* Frozen parent PE ? */ | 542 | /* Frozen parent PE ? */ |
544 | ret = eeh_ops->get_state(parent_pe, NULL); | 543 | ret = eeh_ops->get_state(parent_pe, NULL); |
545 | if (ret > 0 && !eeh_state_active(ret)) | 544 | if (ret > 0 && !eeh_state_active(ret)) { |
546 | pe = parent_pe; | 545 | pe = parent_pe; |
546 | pr_err("EEH: Failure of PHB#%x-PE#%x will be handled at parent PHB#%x-PE#%x.\n", | ||
547 | pe->phb->global_number, pe->addr, | ||
548 | pe->phb->global_number, parent_pe->addr); | ||
549 | } | ||
547 | 550 | ||
548 | /* Next parent level */ | 551 | /* Next parent level */ |
549 | parent_pe = parent_pe->parent; | 552 | parent_pe = parent_pe->parent; |
@@ -686,9 +689,9 @@ int eeh_pci_enable(struct eeh_pe *pe, int function) | |||
686 | return rc; | 689 | return rc; |
687 | } | 690 | } |
688 | 691 | ||
689 | static void *eeh_disable_and_save_dev_state(void *data, void *userdata) | 692 | static void *eeh_disable_and_save_dev_state(struct eeh_dev *edev, |
693 | void *userdata) | ||
690 | { | 694 | { |
691 | struct eeh_dev *edev = data; | ||
692 | struct pci_dev *pdev = eeh_dev_to_pci_dev(edev); | 695 | struct pci_dev *pdev = eeh_dev_to_pci_dev(edev); |
693 | struct pci_dev *dev = userdata; | 696 | struct pci_dev *dev = userdata; |
694 | 697 | ||
@@ -714,9 +717,8 @@ static void *eeh_disable_and_save_dev_state(void *data, void *userdata) | |||
714 | return NULL; | 717 | return NULL; |
715 | } | 718 | } |
716 | 719 | ||
717 | static void *eeh_restore_dev_state(void *data, void *userdata) | 720 | static void *eeh_restore_dev_state(struct eeh_dev *edev, void *userdata) |
718 | { | 721 | { |
719 | struct eeh_dev *edev = data; | ||
720 | struct pci_dn *pdn = eeh_dev_to_pdn(edev); | 722 | struct pci_dn *pdn = eeh_dev_to_pdn(edev); |
721 | struct pci_dev *pdev = eeh_dev_to_pci_dev(edev); | 723 | struct pci_dev *pdev = eeh_dev_to_pci_dev(edev); |
722 | struct pci_dev *dev = userdata; | 724 | struct pci_dev *dev = userdata; |
@@ -856,11 +858,10 @@ int pcibios_set_pcie_reset_state(struct pci_dev *dev, enum pcie_reset_state stat | |||
856 | * the indicated device and its children so that the bunch of the | 858 | * the indicated device and its children so that the bunch of the |
857 | * devices could be reset properly. | 859 | * devices could be reset properly. |
858 | */ | 860 | */ |
859 | static void *eeh_set_dev_freset(void *data, void *flag) | 861 | static void *eeh_set_dev_freset(struct eeh_dev *edev, void *flag) |
860 | { | 862 | { |
861 | struct pci_dev *dev; | 863 | struct pci_dev *dev; |
862 | unsigned int *freset = (unsigned int *)flag; | 864 | unsigned int *freset = (unsigned int *)flag; |
863 | struct eeh_dev *edev = (struct eeh_dev *)data; | ||
864 | 865 | ||
865 | dev = eeh_dev_to_pci_dev(edev); | 866 | dev = eeh_dev_to_pci_dev(edev); |
866 | if (dev) | 867 | if (dev) |
diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c index b8a329f04814..67619b4b3f96 100644 --- a/arch/powerpc/kernel/eeh_driver.c +++ b/arch/powerpc/kernel/eeh_driver.c | |||
@@ -39,18 +39,82 @@ struct eeh_rmv_data { | |||
39 | int removed; | 39 | int removed; |
40 | }; | 40 | }; |
41 | 41 | ||
42 | /** | 42 | static int eeh_result_priority(enum pci_ers_result result) |
43 | * eeh_pcid_name - Retrieve name of PCI device driver | 43 | { |
44 | * @pdev: PCI device | 44 | switch (result) { |
45 | * | 45 | case PCI_ERS_RESULT_NONE: |
46 | * This routine is used to retrieve the name of PCI device driver | 46 | return 1; |
47 | * if that's valid. | 47 | case PCI_ERS_RESULT_NO_AER_DRIVER: |
48 | */ | 48 | return 2; |
49 | static inline const char *eeh_pcid_name(struct pci_dev *pdev) | 49 | case PCI_ERS_RESULT_RECOVERED: |
50 | return 3; | ||
51 | case PCI_ERS_RESULT_CAN_RECOVER: | ||
52 | return 4; | ||
53 | case PCI_ERS_RESULT_DISCONNECT: | ||
54 | return 5; | ||
55 | case PCI_ERS_RESULT_NEED_RESET: | ||
56 | return 6; | ||
57 | default: | ||
58 | WARN_ONCE(1, "Unknown pci_ers_result value: %d\n", (int)result); | ||
59 | return 0; | ||
60 | } | ||
61 | }; | ||
62 | |||
63 | const char *pci_ers_result_name(enum pci_ers_result result) | ||
64 | { | ||
65 | switch (result) { | ||
66 | case PCI_ERS_RESULT_NONE: | ||
67 | return "none"; | ||
68 | case PCI_ERS_RESULT_CAN_RECOVER: | ||
69 | return "can recover"; | ||
70 | case PCI_ERS_RESULT_NEED_RESET: | ||
71 | return "need reset"; | ||
72 | case PCI_ERS_RESULT_DISCONNECT: | ||
73 | return "disconnect"; | ||
74 | case PCI_ERS_RESULT_RECOVERED: | ||
75 | return "recovered"; | ||
76 | case PCI_ERS_RESULT_NO_AER_DRIVER: | ||
77 | return "no AER driver"; | ||
78 | default: | ||
79 | WARN_ONCE(1, "Unknown result type: %d\n", (int)result); | ||
80 | return "unknown"; | ||
81 | } | ||
82 | }; | ||
83 | |||
84 | static __printf(2, 3) void eeh_edev_info(const struct eeh_dev *edev, | ||
85 | const char *fmt, ...) | ||
86 | { | ||
87 | struct va_format vaf; | ||
88 | va_list args; | ||
89 | |||
90 | va_start(args, fmt); | ||
91 | |||
92 | vaf.fmt = fmt; | ||
93 | vaf.va = &args; | ||
94 | |||
95 | printk(KERN_INFO "EEH: PE#%x (PCI %s): %pV\n", edev->pe_config_addr, | ||
96 | edev->pdev ? dev_name(&edev->pdev->dev) : "none", &vaf); | ||
97 | |||
98 | va_end(args); | ||
99 | } | ||
100 | |||
101 | static enum pci_ers_result pci_ers_merge_result(enum pci_ers_result old, | ||
102 | enum pci_ers_result new) | ||
103 | { | ||
104 | if (eeh_result_priority(new) > eeh_result_priority(old)) | ||
105 | return new; | ||
106 | return old; | ||
107 | } | ||
108 | |||
109 | static bool eeh_dev_removed(struct eeh_dev *edev) | ||
50 | { | 110 | { |
51 | if (pdev && pdev->dev.driver) | 111 | return !edev || (edev->mode & EEH_DEV_REMOVED); |
52 | return pdev->dev.driver->name; | 112 | } |
53 | return ""; | 113 | |
114 | static bool eeh_edev_actionable(struct eeh_dev *edev) | ||
115 | { | ||
116 | return (edev->pdev && !eeh_dev_removed(edev) && | ||
117 | !eeh_pe_passed(edev->pe)); | ||
54 | } | 118 | } |
55 | 119 | ||
56 | /** | 120 | /** |
@@ -98,22 +162,20 @@ static inline void eeh_pcid_put(struct pci_dev *pdev) | |||
98 | * do real work because EEH should freeze DMA transfers for those PCI | 162 | * do real work because EEH should freeze DMA transfers for those PCI |
99 | * devices encountering EEH errors, which includes MSI or MSI-X. | 163 | * devices encountering EEH errors, which includes MSI or MSI-X. |
100 | */ | 164 | */ |
101 | static void eeh_disable_irq(struct pci_dev *dev) | 165 | static void eeh_disable_irq(struct eeh_dev *edev) |
102 | { | 166 | { |
103 | struct eeh_dev *edev = pci_dev_to_eeh_dev(dev); | ||
104 | |||
105 | /* Don't disable MSI and MSI-X interrupts. They are | 167 | /* Don't disable MSI and MSI-X interrupts. They are |
106 | * effectively disabled by the DMA Stopped state | 168 | * effectively disabled by the DMA Stopped state |
107 | * when an EEH error occurs. | 169 | * when an EEH error occurs. |
108 | */ | 170 | */ |
109 | if (dev->msi_enabled || dev->msix_enabled) | 171 | if (edev->pdev->msi_enabled || edev->pdev->msix_enabled) |
110 | return; | 172 | return; |
111 | 173 | ||
112 | if (!irq_has_action(dev->irq)) | 174 | if (!irq_has_action(edev->pdev->irq)) |
113 | return; | 175 | return; |
114 | 176 | ||
115 | edev->mode |= EEH_DEV_IRQ_DISABLED; | 177 | edev->mode |= EEH_DEV_IRQ_DISABLED; |
116 | disable_irq_nosync(dev->irq); | 178 | disable_irq_nosync(edev->pdev->irq); |
117 | } | 179 | } |
118 | 180 | ||
119 | /** | 181 | /** |
@@ -123,10 +185,8 @@ static void eeh_disable_irq(struct pci_dev *dev) | |||
123 | * This routine must be called to enable interrupt while failed | 185 | * This routine must be called to enable interrupt while failed |
124 | * device could be resumed. | 186 | * device could be resumed. |
125 | */ | 187 | */ |
126 | static void eeh_enable_irq(struct pci_dev *dev) | 188 | static void eeh_enable_irq(struct eeh_dev *edev) |
127 | { | 189 | { |
128 | struct eeh_dev *edev = pci_dev_to_eeh_dev(dev); | ||
129 | |||
130 | if ((edev->mode) & EEH_DEV_IRQ_DISABLED) { | 190 | if ((edev->mode) & EEH_DEV_IRQ_DISABLED) { |
131 | edev->mode &= ~EEH_DEV_IRQ_DISABLED; | 191 | edev->mode &= ~EEH_DEV_IRQ_DISABLED; |
132 | /* | 192 | /* |
@@ -149,23 +209,13 @@ static void eeh_enable_irq(struct pci_dev *dev) | |||
149 | * | 209 | * |
150 | * tglx | 210 | * tglx |
151 | */ | 211 | */ |
152 | if (irqd_irq_disabled(irq_get_irq_data(dev->irq))) | 212 | if (irqd_irq_disabled(irq_get_irq_data(edev->pdev->irq))) |
153 | enable_irq(dev->irq); | 213 | enable_irq(edev->pdev->irq); |
154 | } | 214 | } |
155 | } | 215 | } |
156 | 216 | ||
157 | static bool eeh_dev_removed(struct eeh_dev *edev) | 217 | static void *eeh_dev_save_state(struct eeh_dev *edev, void *userdata) |
158 | { | ||
159 | /* EEH device removed ? */ | ||
160 | if (!edev || (edev->mode & EEH_DEV_REMOVED)) | ||
161 | return true; | ||
162 | |||
163 | return false; | ||
164 | } | ||
165 | |||
166 | static void *eeh_dev_save_state(void *data, void *userdata) | ||
167 | { | 218 | { |
168 | struct eeh_dev *edev = data; | ||
169 | struct pci_dev *pdev; | 219 | struct pci_dev *pdev; |
170 | 220 | ||
171 | if (!edev) | 221 | if (!edev) |
@@ -189,144 +239,155 @@ static void *eeh_dev_save_state(void *data, void *userdata) | |||
189 | return NULL; | 239 | return NULL; |
190 | } | 240 | } |
191 | 241 | ||
192 | /** | 242 | static void eeh_set_channel_state(struct eeh_pe *root, enum pci_channel_state s) |
193 | * eeh_report_error - Report pci error to each device driver | ||
194 | * @data: eeh device | ||
195 | * @userdata: return value | ||
196 | * | ||
197 | * Report an EEH error to each device driver, collect up and | ||
198 | * merge the device driver responses. Cumulative response | ||
199 | * passed back in "userdata". | ||
200 | */ | ||
201 | static void *eeh_report_error(void *data, void *userdata) | ||
202 | { | 243 | { |
203 | struct eeh_dev *edev = (struct eeh_dev *)data; | 244 | struct eeh_pe *pe; |
204 | struct pci_dev *dev = eeh_dev_to_pci_dev(edev); | 245 | struct eeh_dev *edev, *tmp; |
205 | enum pci_ers_result rc, *res = userdata; | ||
206 | struct pci_driver *driver; | ||
207 | 246 | ||
208 | if (!dev || eeh_dev_removed(edev) || eeh_pe_passed(edev->pe)) | 247 | eeh_for_each_pe(root, pe) |
209 | return NULL; | 248 | eeh_pe_for_each_dev(pe, edev, tmp) |
249 | if (eeh_edev_actionable(edev)) | ||
250 | edev->pdev->error_state = s; | ||
251 | } | ||
210 | 252 | ||
211 | device_lock(&dev->dev); | 253 | static void eeh_set_irq_state(struct eeh_pe *root, bool enable) |
212 | dev->error_state = pci_channel_io_frozen; | 254 | { |
255 | struct eeh_pe *pe; | ||
256 | struct eeh_dev *edev, *tmp; | ||
213 | 257 | ||
214 | driver = eeh_pcid_get(dev); | 258 | eeh_for_each_pe(root, pe) { |
215 | if (!driver) goto out_no_dev; | 259 | eeh_pe_for_each_dev(pe, edev, tmp) { |
260 | if (!eeh_edev_actionable(edev)) | ||
261 | continue; | ||
216 | 262 | ||
217 | eeh_disable_irq(dev); | 263 | if (!eeh_pcid_get(edev->pdev)) |
264 | continue; | ||
218 | 265 | ||
219 | if (!driver->err_handler || | 266 | if (enable) |
220 | !driver->err_handler->error_detected) | 267 | eeh_enable_irq(edev); |
221 | goto out; | 268 | else |
269 | eeh_disable_irq(edev); | ||
222 | 270 | ||
223 | rc = driver->err_handler->error_detected(dev, pci_channel_io_frozen); | 271 | eeh_pcid_put(edev->pdev); |
272 | } | ||
273 | } | ||
274 | } | ||
224 | 275 | ||
225 | /* A driver that needs a reset trumps all others */ | 276 | typedef enum pci_ers_result (*eeh_report_fn)(struct eeh_dev *, |
226 | if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc; | 277 | struct pci_driver *); |
227 | if (*res == PCI_ERS_RESULT_NONE) *res = rc; | 278 | static void eeh_pe_report_edev(struct eeh_dev *edev, eeh_report_fn fn, |
279 | enum pci_ers_result *result) | ||
280 | { | ||
281 | struct pci_driver *driver; | ||
282 | enum pci_ers_result new_result; | ||
283 | |||
284 | device_lock(&edev->pdev->dev); | ||
285 | if (eeh_edev_actionable(edev)) { | ||
286 | driver = eeh_pcid_get(edev->pdev); | ||
287 | |||
288 | if (!driver) | ||
289 | eeh_edev_info(edev, "no driver"); | ||
290 | else if (!driver->err_handler) | ||
291 | eeh_edev_info(edev, "driver not EEH aware"); | ||
292 | else if (edev->mode & EEH_DEV_NO_HANDLER) | ||
293 | eeh_edev_info(edev, "driver bound too late"); | ||
294 | else { | ||
295 | new_result = fn(edev, driver); | ||
296 | eeh_edev_info(edev, "%s driver reports: '%s'", | ||
297 | driver->name, | ||
298 | pci_ers_result_name(new_result)); | ||
299 | if (result) | ||
300 | *result = pci_ers_merge_result(*result, | ||
301 | new_result); | ||
302 | } | ||
303 | if (driver) | ||
304 | eeh_pcid_put(edev->pdev); | ||
305 | } else { | ||
306 | eeh_edev_info(edev, "not actionable (%d,%d,%d)", !!edev->pdev, | ||
307 | !eeh_dev_removed(edev), !eeh_pe_passed(edev->pe)); | ||
308 | } | ||
309 | device_unlock(&edev->pdev->dev); | ||
310 | } | ||
228 | 311 | ||
229 | edev->in_error = true; | 312 | static void eeh_pe_report(const char *name, struct eeh_pe *root, |
230 | pci_uevent_ers(dev, PCI_ERS_RESULT_NONE); | 313 | eeh_report_fn fn, enum pci_ers_result *result) |
314 | { | ||
315 | struct eeh_pe *pe; | ||
316 | struct eeh_dev *edev, *tmp; | ||
231 | 317 | ||
232 | out: | 318 | pr_info("EEH: Beginning: '%s'\n", name); |
233 | eeh_pcid_put(dev); | 319 | eeh_for_each_pe(root, pe) eeh_pe_for_each_dev(pe, edev, tmp) |
234 | out_no_dev: | 320 | eeh_pe_report_edev(edev, fn, result); |
235 | device_unlock(&dev->dev); | 321 | if (result) |
236 | return NULL; | 322 | pr_info("EEH: Finished:'%s' with aggregate recovery state:'%s'\n", |
323 | name, pci_ers_result_name(*result)); | ||
324 | else | ||
325 | pr_info("EEH: Finished:'%s'", name); | ||
237 | } | 326 | } |
238 | 327 | ||
239 | /** | 328 | /** |
240 | * eeh_report_mmio_enabled - Tell drivers that MMIO has been enabled | 329 | * eeh_report_error - Report pci error to each device driver |
241 | * @data: eeh device | 330 | * @edev: eeh device |
242 | * @userdata: return value | 331 | * @driver: device's PCI driver |
243 | * | 332 | * |
244 | * Tells each device driver that IO ports, MMIO and config space I/O | 333 | * Report an EEH error to each device driver. |
245 | * are now enabled. Collects up and merges the device driver responses. | ||
246 | * Cumulative response passed back in "userdata". | ||
247 | */ | 334 | */ |
248 | static void *eeh_report_mmio_enabled(void *data, void *userdata) | 335 | static enum pci_ers_result eeh_report_error(struct eeh_dev *edev, |
336 | struct pci_driver *driver) | ||
249 | { | 337 | { |
250 | struct eeh_dev *edev = (struct eeh_dev *)data; | 338 | enum pci_ers_result rc; |
251 | struct pci_dev *dev = eeh_dev_to_pci_dev(edev); | 339 | struct pci_dev *dev = edev->pdev; |
252 | enum pci_ers_result rc, *res = userdata; | ||
253 | struct pci_driver *driver; | ||
254 | |||
255 | if (!dev || eeh_dev_removed(edev) || eeh_pe_passed(edev->pe)) | ||
256 | return NULL; | ||
257 | |||
258 | device_lock(&dev->dev); | ||
259 | driver = eeh_pcid_get(dev); | ||
260 | if (!driver) goto out_no_dev; | ||
261 | 340 | ||
262 | if (!driver->err_handler || | 341 | if (!driver->err_handler->error_detected) |
263 | !driver->err_handler->mmio_enabled || | 342 | return PCI_ERS_RESULT_NONE; |
264 | (edev->mode & EEH_DEV_NO_HANDLER)) | ||
265 | goto out; | ||
266 | 343 | ||
267 | rc = driver->err_handler->mmio_enabled(dev); | 344 | eeh_edev_info(edev, "Invoking %s->error_detected(IO frozen)", |
345 | driver->name); | ||
346 | rc = driver->err_handler->error_detected(dev, pci_channel_io_frozen); | ||
268 | 347 | ||
269 | /* A driver that needs a reset trumps all others */ | 348 | edev->in_error = true; |
270 | if (rc == PCI_ERS_RESULT_NEED_RESET) *res = rc; | 349 | pci_uevent_ers(dev, PCI_ERS_RESULT_NONE); |
271 | if (*res == PCI_ERS_RESULT_NONE) *res = rc; | 350 | return rc; |
351 | } | ||
272 | 352 | ||
273 | out: | 353 | /** |
274 | eeh_pcid_put(dev); | 354 | * eeh_report_mmio_enabled - Tell drivers that MMIO has been enabled |
275 | out_no_dev: | 355 | * @edev: eeh device |
276 | device_unlock(&dev->dev); | 356 | * @driver: device's PCI driver |
277 | return NULL; | 357 | * |
358 | * Tells each device driver that IO ports, MMIO and config space I/O | ||
359 | * are now enabled. | ||
360 | */ | ||
361 | static enum pci_ers_result eeh_report_mmio_enabled(struct eeh_dev *edev, | ||
362 | struct pci_driver *driver) | ||
363 | { | ||
364 | if (!driver->err_handler->mmio_enabled) | ||
365 | return PCI_ERS_RESULT_NONE; | ||
366 | eeh_edev_info(edev, "Invoking %s->mmio_enabled()", driver->name); | ||
367 | return driver->err_handler->mmio_enabled(edev->pdev); | ||
278 | } | 368 | } |
279 | 369 | ||
280 | /** | 370 | /** |
281 | * eeh_report_reset - Tell device that slot has been reset | 371 | * eeh_report_reset - Tell device that slot has been reset |
282 | * @data: eeh device | 372 | * @edev: eeh device |
283 | * @userdata: return value | 373 | * @driver: device's PCI driver |
284 | * | 374 | * |
285 | * This routine must be called while EEH tries to reset particular | 375 | * This routine must be called while EEH tries to reset particular |
286 | * PCI device so that the associated PCI device driver could take | 376 | * PCI device so that the associated PCI device driver could take |
287 | * some actions, usually to save data the driver needs so that the | 377 | * some actions, usually to save data the driver needs so that the |
288 | * driver can work again while the device is recovered. | 378 | * driver can work again while the device is recovered. |
289 | */ | 379 | */ |
290 | static void *eeh_report_reset(void *data, void *userdata) | 380 | static enum pci_ers_result eeh_report_reset(struct eeh_dev *edev, |
381 | struct pci_driver *driver) | ||
291 | { | 382 | { |
292 | struct eeh_dev *edev = (struct eeh_dev *)data; | 383 | if (!driver->err_handler->slot_reset || !edev->in_error) |
293 | struct pci_dev *dev = eeh_dev_to_pci_dev(edev); | 384 | return PCI_ERS_RESULT_NONE; |
294 | enum pci_ers_result rc, *res = userdata; | 385 | eeh_edev_info(edev, "Invoking %s->slot_reset()", driver->name); |
295 | struct pci_driver *driver; | 386 | return driver->err_handler->slot_reset(edev->pdev); |
296 | |||
297 | if (!dev || eeh_dev_removed(edev) || eeh_pe_passed(edev->pe)) | ||
298 | return NULL; | ||
299 | |||
300 | device_lock(&dev->dev); | ||
301 | dev->error_state = pci_channel_io_normal; | ||
302 | |||
303 | driver = eeh_pcid_get(dev); | ||
304 | if (!driver) goto out_no_dev; | ||
305 | |||
306 | eeh_enable_irq(dev); | ||
307 | |||
308 | if (!driver->err_handler || | ||
309 | !driver->err_handler->slot_reset || | ||
310 | (edev->mode & EEH_DEV_NO_HANDLER) || | ||
311 | (!edev->in_error)) | ||
312 | goto out; | ||
313 | |||
314 | rc = driver->err_handler->slot_reset(dev); | ||
315 | if ((*res == PCI_ERS_RESULT_NONE) || | ||
316 | (*res == PCI_ERS_RESULT_RECOVERED)) *res = rc; | ||
317 | if (*res == PCI_ERS_RESULT_DISCONNECT && | ||
318 | rc == PCI_ERS_RESULT_NEED_RESET) *res = rc; | ||
319 | |||
320 | out: | ||
321 | eeh_pcid_put(dev); | ||
322 | out_no_dev: | ||
323 | device_unlock(&dev->dev); | ||
324 | return NULL; | ||
325 | } | 387 | } |
326 | 388 | ||
327 | static void *eeh_dev_restore_state(void *data, void *userdata) | 389 | static void *eeh_dev_restore_state(struct eeh_dev *edev, void *userdata) |
328 | { | 390 | { |
329 | struct eeh_dev *edev = data; | ||
330 | struct pci_dev *pdev; | 391 | struct pci_dev *pdev; |
331 | 392 | ||
332 | if (!edev) | 393 | if (!edev) |
@@ -355,91 +416,53 @@ static void *eeh_dev_restore_state(void *data, void *userdata) | |||
355 | 416 | ||
356 | /** | 417 | /** |
357 | * eeh_report_resume - Tell device to resume normal operations | 418 | * eeh_report_resume - Tell device to resume normal operations |
358 | * @data: eeh device | 419 | * @edev: eeh device |
359 | * @userdata: return value | 420 | * @driver: device's PCI driver |
360 | * | 421 | * |
361 | * This routine must be called to notify the device driver that it | 422 | * This routine must be called to notify the device driver that it |
362 | * could resume so that the device driver can do some initialization | 423 | * could resume so that the device driver can do some initialization |
363 | * to make the recovered device work again. | 424 | * to make the recovered device work again. |
364 | */ | 425 | */ |
365 | static void *eeh_report_resume(void *data, void *userdata) | 426 | static enum pci_ers_result eeh_report_resume(struct eeh_dev *edev, |
427 | struct pci_driver *driver) | ||
366 | { | 428 | { |
367 | struct eeh_dev *edev = (struct eeh_dev *)data; | 429 | if (!driver->err_handler->resume || !edev->in_error) |
368 | struct pci_dev *dev = eeh_dev_to_pci_dev(edev); | 430 | return PCI_ERS_RESULT_NONE; |
369 | bool was_in_error; | ||
370 | struct pci_driver *driver; | ||
371 | 431 | ||
372 | if (!dev || eeh_dev_removed(edev) || eeh_pe_passed(edev->pe)) | 432 | eeh_edev_info(edev, "Invoking %s->resume()", driver->name); |
373 | return NULL; | 433 | driver->err_handler->resume(edev->pdev); |
374 | |||
375 | device_lock(&dev->dev); | ||
376 | dev->error_state = pci_channel_io_normal; | ||
377 | |||
378 | driver = eeh_pcid_get(dev); | ||
379 | if (!driver) goto out_no_dev; | ||
380 | |||
381 | was_in_error = edev->in_error; | ||
382 | edev->in_error = false; | ||
383 | eeh_enable_irq(dev); | ||
384 | |||
385 | if (!driver->err_handler || | ||
386 | !driver->err_handler->resume || | ||
387 | (edev->mode & EEH_DEV_NO_HANDLER) || !was_in_error) { | ||
388 | edev->mode &= ~EEH_DEV_NO_HANDLER; | ||
389 | goto out; | ||
390 | } | ||
391 | |||
392 | driver->err_handler->resume(dev); | ||
393 | 434 | ||
394 | pci_uevent_ers(dev, PCI_ERS_RESULT_RECOVERED); | 435 | pci_uevent_ers(edev->pdev, PCI_ERS_RESULT_RECOVERED); |
395 | out: | ||
396 | eeh_pcid_put(dev); | ||
397 | #ifdef CONFIG_PCI_IOV | 436 | #ifdef CONFIG_PCI_IOV |
398 | if (eeh_ops->notify_resume && eeh_dev_to_pdn(edev)) | 437 | if (eeh_ops->notify_resume && eeh_dev_to_pdn(edev)) |
399 | eeh_ops->notify_resume(eeh_dev_to_pdn(edev)); | 438 | eeh_ops->notify_resume(eeh_dev_to_pdn(edev)); |
400 | #endif | 439 | #endif |
401 | out_no_dev: | 440 | return PCI_ERS_RESULT_NONE; |
402 | device_unlock(&dev->dev); | ||
403 | return NULL; | ||
404 | } | 441 | } |
405 | 442 | ||
406 | /** | 443 | /** |
407 | * eeh_report_failure - Tell device driver that device is dead. | 444 | * eeh_report_failure - Tell device driver that device is dead. |
408 | * @data: eeh device | 445 | * @edev: eeh device |
409 | * @userdata: return value | 446 | * @driver: device's PCI driver |
410 | * | 447 | * |
411 | * This informs the device driver that the device is permanently | 448 | * This informs the device driver that the device is permanently |
412 | * dead, and that no further recovery attempts will be made on it. | 449 | * dead, and that no further recovery attempts will be made on it. |
413 | */ | 450 | */ |
414 | static void *eeh_report_failure(void *data, void *userdata) | 451 | static enum pci_ers_result eeh_report_failure(struct eeh_dev *edev, |
452 | struct pci_driver *driver) | ||
415 | { | 453 | { |
416 | struct eeh_dev *edev = (struct eeh_dev *)data; | 454 | enum pci_ers_result rc; |
417 | struct pci_dev *dev = eeh_dev_to_pci_dev(edev); | ||
418 | struct pci_driver *driver; | ||
419 | 455 | ||
420 | if (!dev || eeh_dev_removed(edev) || eeh_pe_passed(edev->pe)) | 456 | if (!driver->err_handler->error_detected) |
421 | return NULL; | 457 | return PCI_ERS_RESULT_NONE; |
422 | |||
423 | device_lock(&dev->dev); | ||
424 | dev->error_state = pci_channel_io_perm_failure; | ||
425 | |||
426 | driver = eeh_pcid_get(dev); | ||
427 | if (!driver) goto out_no_dev; | ||
428 | 458 | ||
429 | eeh_disable_irq(dev); | 459 | eeh_edev_info(edev, "Invoking %s->error_detected(permanent failure)", |
460 | driver->name); | ||
461 | rc = driver->err_handler->error_detected(edev->pdev, | ||
462 | pci_channel_io_perm_failure); | ||
430 | 463 | ||
431 | if (!driver->err_handler || | 464 | pci_uevent_ers(edev->pdev, PCI_ERS_RESULT_DISCONNECT); |
432 | !driver->err_handler->error_detected) | 465 | return rc; |
433 | goto out; | ||
434 | |||
435 | driver->err_handler->error_detected(dev, pci_channel_io_perm_failure); | ||
436 | |||
437 | pci_uevent_ers(dev, PCI_ERS_RESULT_DISCONNECT); | ||
438 | out: | ||
439 | eeh_pcid_put(dev); | ||
440 | out_no_dev: | ||
441 | device_unlock(&dev->dev); | ||
442 | return NULL; | ||
443 | } | 466 | } |
444 | 467 | ||
445 | static void *eeh_add_virt_device(void *data, void *userdata) | 468 | static void *eeh_add_virt_device(void *data, void *userdata) |
@@ -458,9 +481,11 @@ static void *eeh_add_virt_device(void *data, void *userdata) | |||
458 | 481 | ||
459 | driver = eeh_pcid_get(dev); | 482 | driver = eeh_pcid_get(dev); |
460 | if (driver) { | 483 | if (driver) { |
461 | eeh_pcid_put(dev); | 484 | if (driver->err_handler) { |
462 | if (driver->err_handler) | 485 | eeh_pcid_put(dev); |
463 | return NULL; | 486 | return NULL; |
487 | } | ||
488 | eeh_pcid_put(dev); | ||
464 | } | 489 | } |
465 | 490 | ||
466 | #ifdef CONFIG_PCI_IOV | 491 | #ifdef CONFIG_PCI_IOV |
@@ -469,10 +494,9 @@ static void *eeh_add_virt_device(void *data, void *userdata) | |||
469 | return NULL; | 494 | return NULL; |
470 | } | 495 | } |
471 | 496 | ||
472 | static void *eeh_rmv_device(void *data, void *userdata) | 497 | static void *eeh_rmv_device(struct eeh_dev *edev, void *userdata) |
473 | { | 498 | { |
474 | struct pci_driver *driver; | 499 | struct pci_driver *driver; |
475 | struct eeh_dev *edev = (struct eeh_dev *)data; | ||
476 | struct pci_dev *dev = eeh_dev_to_pci_dev(edev); | 500 | struct pci_dev *dev = eeh_dev_to_pci_dev(edev); |
477 | struct eeh_rmv_data *rmv_data = (struct eeh_rmv_data *)userdata; | 501 | struct eeh_rmv_data *rmv_data = (struct eeh_rmv_data *)userdata; |
478 | int *removed = rmv_data ? &rmv_data->removed : NULL; | 502 | int *removed = rmv_data ? &rmv_data->removed : NULL; |
@@ -497,17 +521,19 @@ static void *eeh_rmv_device(void *data, void *userdata) | |||
497 | if (eeh_dev_removed(edev)) | 521 | if (eeh_dev_removed(edev)) |
498 | return NULL; | 522 | return NULL; |
499 | 523 | ||
500 | driver = eeh_pcid_get(dev); | 524 | if (removed) { |
501 | if (driver) { | 525 | if (eeh_pe_passed(edev->pe)) |
502 | eeh_pcid_put(dev); | ||
503 | if (removed && | ||
504 | eeh_pe_passed(edev->pe)) | ||
505 | return NULL; | ||
506 | if (removed && | ||
507 | driver->err_handler && | ||
508 | driver->err_handler->error_detected && | ||
509 | driver->err_handler->slot_reset) | ||
510 | return NULL; | 526 | return NULL; |
527 | driver = eeh_pcid_get(dev); | ||
528 | if (driver) { | ||
529 | if (driver->err_handler && | ||
530 | driver->err_handler->error_detected && | ||
531 | driver->err_handler->slot_reset) { | ||
532 | eeh_pcid_put(dev); | ||
533 | return NULL; | ||
534 | } | ||
535 | eeh_pcid_put(dev); | ||
536 | } | ||
511 | } | 537 | } |
512 | 538 | ||
513 | /* Remove it from PCI subsystem */ | 539 | /* Remove it from PCI subsystem */ |
@@ -542,9 +568,8 @@ static void *eeh_rmv_device(void *data, void *userdata) | |||
542 | return NULL; | 568 | return NULL; |
543 | } | 569 | } |
544 | 570 | ||
545 | static void *eeh_pe_detach_dev(void *data, void *userdata) | 571 | static void *eeh_pe_detach_dev(struct eeh_pe *pe, void *userdata) |
546 | { | 572 | { |
547 | struct eeh_pe *pe = (struct eeh_pe *)data; | ||
548 | struct eeh_dev *edev, *tmp; | 573 | struct eeh_dev *edev, *tmp; |
549 | 574 | ||
550 | eeh_pe_for_each_dev(pe, edev, tmp) { | 575 | eeh_pe_for_each_dev(pe, edev, tmp) { |
@@ -565,9 +590,8 @@ static void *eeh_pe_detach_dev(void *data, void *userdata) | |||
565 | * PE reset (for 3 times), we try to clear the frozen state | 590 | * PE reset (for 3 times), we try to clear the frozen state |
566 | * for 3 times as well. | 591 | * for 3 times as well. |
567 | */ | 592 | */ |
568 | static void *__eeh_clear_pe_frozen_state(void *data, void *flag) | 593 | static void *__eeh_clear_pe_frozen_state(struct eeh_pe *pe, void *flag) |
569 | { | 594 | { |
570 | struct eeh_pe *pe = (struct eeh_pe *)data; | ||
571 | bool clear_sw_state = *(bool *)flag; | 595 | bool clear_sw_state = *(bool *)flag; |
572 | int i, rc = 1; | 596 | int i, rc = 1; |
573 | 597 | ||
@@ -762,6 +786,7 @@ void eeh_handle_normal_event(struct eeh_pe *pe) | |||
762 | { | 786 | { |
763 | struct pci_bus *bus; | 787 | struct pci_bus *bus; |
764 | struct eeh_dev *edev, *tmp; | 788 | struct eeh_dev *edev, *tmp; |
789 | struct eeh_pe *tmp_pe; | ||
765 | int rc = 0; | 790 | int rc = 0; |
766 | enum pci_ers_result result = PCI_ERS_RESULT_NONE; | 791 | enum pci_ers_result result = PCI_ERS_RESULT_NONE; |
767 | struct eeh_rmv_data rmv_data = {LIST_HEAD_INIT(rmv_data.edev_list), 0}; | 792 | struct eeh_rmv_data rmv_data = {LIST_HEAD_INIT(rmv_data.edev_list), 0}; |
@@ -778,14 +803,13 @@ void eeh_handle_normal_event(struct eeh_pe *pe) | |||
778 | eeh_pe_update_time_stamp(pe); | 803 | eeh_pe_update_time_stamp(pe); |
779 | pe->freeze_count++; | 804 | pe->freeze_count++; |
780 | if (pe->freeze_count > eeh_max_freezes) { | 805 | if (pe->freeze_count > eeh_max_freezes) { |
781 | pr_err("EEH: PHB#%x-PE#%x has failed %d times in the\n" | 806 | pr_err("EEH: PHB#%x-PE#%x has failed %d times in the last hour and has been permanently disabled.\n", |
782 | "last hour and has been permanently disabled.\n", | ||
783 | pe->phb->global_number, pe->addr, | 807 | pe->phb->global_number, pe->addr, |
784 | pe->freeze_count); | 808 | pe->freeze_count); |
785 | goto hard_fail; | 809 | goto hard_fail; |
786 | } | 810 | } |
787 | pr_warn("EEH: This PCI device has failed %d times in the last hour\n", | 811 | pr_warn("EEH: This PCI device has failed %d times in the last hour and will be permanently disabled after %d failures.\n", |
788 | pe->freeze_count); | 812 | pe->freeze_count, eeh_max_freezes); |
789 | 813 | ||
790 | /* Walk the various device drivers attached to this slot through | 814 | /* Walk the various device drivers attached to this slot through |
791 | * a reset sequence, giving each an opportunity to do what it needs | 815 | * a reset sequence, giving each an opportunity to do what it needs |
@@ -798,7 +822,10 @@ void eeh_handle_normal_event(struct eeh_pe *pe) | |||
798 | * hotplug for this case. | 822 | * hotplug for this case. |
799 | */ | 823 | */ |
800 | pr_info("EEH: Notify device drivers to shutdown\n"); | 824 | pr_info("EEH: Notify device drivers to shutdown\n"); |
801 | eeh_pe_dev_traverse(pe, eeh_report_error, &result); | 825 | eeh_set_channel_state(pe, pci_channel_io_frozen); |
826 | eeh_set_irq_state(pe, false); | ||
827 | eeh_pe_report("error_detected(IO frozen)", pe, eeh_report_error, | ||
828 | &result); | ||
802 | if ((pe->type & EEH_PE_PHB) && | 829 | if ((pe->type & EEH_PE_PHB) && |
803 | result != PCI_ERS_RESULT_NONE && | 830 | result != PCI_ERS_RESULT_NONE && |
804 | result != PCI_ERS_RESULT_NEED_RESET) | 831 | result != PCI_ERS_RESULT_NEED_RESET) |
@@ -845,7 +872,8 @@ void eeh_handle_normal_event(struct eeh_pe *pe) | |||
845 | result = PCI_ERS_RESULT_NEED_RESET; | 872 | result = PCI_ERS_RESULT_NEED_RESET; |
846 | } else { | 873 | } else { |
847 | pr_info("EEH: Notify device drivers to resume I/O\n"); | 874 | pr_info("EEH: Notify device drivers to resume I/O\n"); |
848 | eeh_pe_dev_traverse(pe, eeh_report_mmio_enabled, &result); | 875 | eeh_pe_report("mmio_enabled", pe, |
876 | eeh_report_mmio_enabled, &result); | ||
849 | } | 877 | } |
850 | } | 878 | } |
851 | 879 | ||
@@ -888,7 +916,9 @@ void eeh_handle_normal_event(struct eeh_pe *pe) | |||
888 | pr_info("EEH: Notify device drivers " | 916 | pr_info("EEH: Notify device drivers " |
889 | "the completion of reset\n"); | 917 | "the completion of reset\n"); |
890 | result = PCI_ERS_RESULT_NONE; | 918 | result = PCI_ERS_RESULT_NONE; |
891 | eeh_pe_dev_traverse(pe, eeh_report_reset, &result); | 919 | eeh_set_channel_state(pe, pci_channel_io_normal); |
920 | eeh_set_irq_state(pe, true); | ||
921 | eeh_pe_report("slot_reset", pe, eeh_report_reset, &result); | ||
892 | } | 922 | } |
893 | 923 | ||
894 | /* All devices should claim they have recovered by now. */ | 924 | /* All devices should claim they have recovered by now. */ |
@@ -909,8 +939,17 @@ void eeh_handle_normal_event(struct eeh_pe *pe) | |||
909 | 939 | ||
910 | /* Tell all device drivers that they can resume operations */ | 940 | /* Tell all device drivers that they can resume operations */ |
911 | pr_info("EEH: Notify device driver to resume\n"); | 941 | pr_info("EEH: Notify device driver to resume\n"); |
912 | eeh_pe_dev_traverse(pe, eeh_report_resume, NULL); | 942 | eeh_set_channel_state(pe, pci_channel_io_normal); |
943 | eeh_set_irq_state(pe, true); | ||
944 | eeh_pe_report("resume", pe, eeh_report_resume, NULL); | ||
945 | eeh_for_each_pe(pe, tmp_pe) { | ||
946 | eeh_pe_for_each_dev(tmp_pe, edev, tmp) { | ||
947 | edev->mode &= ~EEH_DEV_NO_HANDLER; | ||
948 | edev->in_error = false; | ||
949 | } | ||
950 | } | ||
913 | 951 | ||
952 | pr_info("EEH: Recovery successful.\n"); | ||
914 | goto final; | 953 | goto final; |
915 | 954 | ||
916 | hard_fail: | 955 | hard_fail: |
@@ -926,7 +965,10 @@ hard_fail: | |||
926 | eeh_slot_error_detail(pe, EEH_LOG_PERM); | 965 | eeh_slot_error_detail(pe, EEH_LOG_PERM); |
927 | 966 | ||
928 | /* Notify all devices that they're about to go down. */ | 967 | /* Notify all devices that they're about to go down. */ |
929 | eeh_pe_dev_traverse(pe, eeh_report_failure, NULL); | 968 | eeh_set_channel_state(pe, pci_channel_io_perm_failure); |
969 | eeh_set_irq_state(pe, false); | ||
970 | eeh_pe_report("error_detected(permanent failure)", pe, | ||
971 | eeh_report_failure, NULL); | ||
930 | 972 | ||
931 | /* Mark the PE to be removed permanently */ | 973 | /* Mark the PE to be removed permanently */ |
932 | eeh_pe_state_mark(pe, EEH_PE_REMOVED); | 974 | eeh_pe_state_mark(pe, EEH_PE_REMOVED); |
@@ -1035,7 +1077,9 @@ void eeh_handle_special_event(void) | |||
1035 | 1077 | ||
1036 | /* Notify all devices to be down */ | 1078 | /* Notify all devices to be down */ |
1037 | eeh_pe_state_clear(pe, EEH_PE_PRI_BUS); | 1079 | eeh_pe_state_clear(pe, EEH_PE_PRI_BUS); |
1038 | eeh_pe_dev_traverse(pe, | 1080 | eeh_set_channel_state(pe, pci_channel_io_perm_failure); |
1081 | eeh_pe_report( | ||
1082 | "error_detected(permanent failure)", pe, | ||
1039 | eeh_report_failure, NULL); | 1083 | eeh_report_failure, NULL); |
1040 | bus = eeh_pe_bus_get(phb_pe); | 1084 | bus = eeh_pe_bus_get(phb_pe); |
1041 | if (!bus) { | 1085 | if (!bus) { |
diff --git a/arch/powerpc/kernel/eeh_pe.c b/arch/powerpc/kernel/eeh_pe.c index ee5a67d57aab..1b238ecc553e 100644 --- a/arch/powerpc/kernel/eeh_pe.c +++ b/arch/powerpc/kernel/eeh_pe.c | |||
@@ -142,8 +142,7 @@ struct eeh_pe *eeh_phb_pe_get(struct pci_controller *phb) | |||
142 | * The function is used to retrieve the next PE in the | 142 | * The function is used to retrieve the next PE in the |
143 | * hierarchy PE tree. | 143 | * hierarchy PE tree. |
144 | */ | 144 | */ |
145 | static struct eeh_pe *eeh_pe_next(struct eeh_pe *pe, | 145 | struct eeh_pe *eeh_pe_next(struct eeh_pe *pe, struct eeh_pe *root) |
146 | struct eeh_pe *root) | ||
147 | { | 146 | { |
148 | struct list_head *next = pe->child_list.next; | 147 | struct list_head *next = pe->child_list.next; |
149 | 148 | ||
@@ -173,12 +172,12 @@ static struct eeh_pe *eeh_pe_next(struct eeh_pe *pe, | |||
173 | * to be traversed. | 172 | * to be traversed. |
174 | */ | 173 | */ |
175 | void *eeh_pe_traverse(struct eeh_pe *root, | 174 | void *eeh_pe_traverse(struct eeh_pe *root, |
176 | eeh_traverse_func fn, void *flag) | 175 | eeh_pe_traverse_func fn, void *flag) |
177 | { | 176 | { |
178 | struct eeh_pe *pe; | 177 | struct eeh_pe *pe; |
179 | void *ret; | 178 | void *ret; |
180 | 179 | ||
181 | for (pe = root; pe; pe = eeh_pe_next(pe, root)) { | 180 | eeh_for_each_pe(root, pe) { |
182 | ret = fn(pe, flag); | 181 | ret = fn(pe, flag); |
183 | if (ret) return ret; | 182 | if (ret) return ret; |
184 | } | 183 | } |
@@ -196,7 +195,7 @@ void *eeh_pe_traverse(struct eeh_pe *root, | |||
196 | * PE and its child PEs. | 195 | * PE and its child PEs. |
197 | */ | 196 | */ |
198 | void *eeh_pe_dev_traverse(struct eeh_pe *root, | 197 | void *eeh_pe_dev_traverse(struct eeh_pe *root, |
199 | eeh_traverse_func fn, void *flag) | 198 | eeh_edev_traverse_func fn, void *flag) |
200 | { | 199 | { |
201 | struct eeh_pe *pe; | 200 | struct eeh_pe *pe; |
202 | struct eeh_dev *edev, *tmp; | 201 | struct eeh_dev *edev, *tmp; |
@@ -209,7 +208,7 @@ void *eeh_pe_dev_traverse(struct eeh_pe *root, | |||
209 | } | 208 | } |
210 | 209 | ||
211 | /* Traverse root PE */ | 210 | /* Traverse root PE */ |
212 | for (pe = root; pe; pe = eeh_pe_next(pe, root)) { | 211 | eeh_for_each_pe(root, pe) { |
213 | eeh_pe_for_each_dev(pe, edev, tmp) { | 212 | eeh_pe_for_each_dev(pe, edev, tmp) { |
214 | ret = fn(edev, flag); | 213 | ret = fn(edev, flag); |
215 | if (ret) | 214 | if (ret) |
@@ -235,9 +234,8 @@ struct eeh_pe_get_flag { | |||
235 | int config_addr; | 234 | int config_addr; |
236 | }; | 235 | }; |
237 | 236 | ||
238 | static void *__eeh_pe_get(void *data, void *flag) | 237 | static void *__eeh_pe_get(struct eeh_pe *pe, void *flag) |
239 | { | 238 | { |
240 | struct eeh_pe *pe = (struct eeh_pe *)data; | ||
241 | struct eeh_pe_get_flag *tmp = (struct eeh_pe_get_flag *) flag; | 239 | struct eeh_pe_get_flag *tmp = (struct eeh_pe_get_flag *) flag; |
242 | 240 | ||
243 | /* Unexpected PHB PE */ | 241 | /* Unexpected PHB PE */ |
@@ -551,9 +549,8 @@ void eeh_pe_update_time_stamp(struct eeh_pe *pe) | |||
551 | * PE. Also, the associated PCI devices will be put into IO frozen | 549 | * PE. Also, the associated PCI devices will be put into IO frozen |
552 | * state as well. | 550 | * state as well. |
553 | */ | 551 | */ |
554 | static void *__eeh_pe_state_mark(void *data, void *flag) | 552 | static void *__eeh_pe_state_mark(struct eeh_pe *pe, void *flag) |
555 | { | 553 | { |
556 | struct eeh_pe *pe = (struct eeh_pe *)data; | ||
557 | int state = *((int *)flag); | 554 | int state = *((int *)flag); |
558 | struct eeh_dev *edev, *tmp; | 555 | struct eeh_dev *edev, *tmp; |
559 | struct pci_dev *pdev; | 556 | struct pci_dev *pdev; |
@@ -595,9 +592,8 @@ void eeh_pe_state_mark(struct eeh_pe *pe, int state) | |||
595 | } | 592 | } |
596 | EXPORT_SYMBOL_GPL(eeh_pe_state_mark); | 593 | EXPORT_SYMBOL_GPL(eeh_pe_state_mark); |
597 | 594 | ||
598 | static void *__eeh_pe_dev_mode_mark(void *data, void *flag) | 595 | static void *__eeh_pe_dev_mode_mark(struct eeh_dev *edev, void *flag) |
599 | { | 596 | { |
600 | struct eeh_dev *edev = data; | ||
601 | int mode = *((int *)flag); | 597 | int mode = *((int *)flag); |
602 | 598 | ||
603 | edev->mode |= mode; | 599 | edev->mode |= mode; |
@@ -625,9 +621,8 @@ void eeh_pe_dev_mode_mark(struct eeh_pe *pe, int mode) | |||
625 | * given PE. Besides, we also clear the check count of the PE | 621 | * given PE. Besides, we also clear the check count of the PE |
626 | * as well. | 622 | * as well. |
627 | */ | 623 | */ |
628 | static void *__eeh_pe_state_clear(void *data, void *flag) | 624 | static void *__eeh_pe_state_clear(struct eeh_pe *pe, void *flag) |
629 | { | 625 | { |
630 | struct eeh_pe *pe = (struct eeh_pe *)data; | ||
631 | int state = *((int *)flag); | 626 | int state = *((int *)flag); |
632 | struct eeh_dev *edev, *tmp; | 627 | struct eeh_dev *edev, *tmp; |
633 | struct pci_dev *pdev; | 628 | struct pci_dev *pdev; |
@@ -858,9 +853,8 @@ static void eeh_restore_device_bars(struct eeh_dev *edev) | |||
858 | * the expansion ROM base address, the latency timer, and etc. | 853 | * the expansion ROM base address, the latency timer, and etc. |
859 | * from the saved values in the device node. | 854 | * from the saved values in the device node. |
860 | */ | 855 | */ |
861 | static void *eeh_restore_one_device_bars(void *data, void *flag) | 856 | static void *eeh_restore_one_device_bars(struct eeh_dev *edev, void *flag) |
862 | { | 857 | { |
863 | struct eeh_dev *edev = (struct eeh_dev *)data; | ||
864 | struct pci_dn *pdn = eeh_dev_to_pdn(edev); | 858 | struct pci_dn *pdn = eeh_dev_to_pdn(edev); |
865 | 859 | ||
866 | /* Do special restore for bridges */ | 860 | /* Do special restore for bridges */ |
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 51695608c68b..b10e01021214 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <asm/context_tracking.h> | 36 | #include <asm/context_tracking.h> |
37 | #include <asm/tm.h> | 37 | #include <asm/tm.h> |
38 | #include <asm/ppc-opcode.h> | 38 | #include <asm/ppc-opcode.h> |
39 | #include <asm/barrier.h> | ||
39 | #include <asm/export.h> | 40 | #include <asm/export.h> |
40 | #ifdef CONFIG_PPC_BOOK3S | 41 | #ifdef CONFIG_PPC_BOOK3S |
41 | #include <asm/exception-64s.h> | 42 | #include <asm/exception-64s.h> |
@@ -178,6 +179,15 @@ system_call: /* label this so stack traces look sane */ | |||
178 | clrldi r8,r8,32 | 179 | clrldi r8,r8,32 |
179 | 15: | 180 | 15: |
180 | slwi r0,r0,4 | 181 | slwi r0,r0,4 |
182 | |||
183 | barrier_nospec_asm | ||
184 | /* | ||
185 | * Prevent the load of the handler below (based on the user-passed | ||
186 | * system call number) being speculatively executed until the test | ||
187 | * against NR_syscalls and branch to .Lsyscall_enosys above has | ||
188 | * committed. | ||
189 | */ | ||
190 | |||
181 | ldx r12,r11,r0 /* Fetch system call handler [ptr] */ | 191 | ldx r12,r11,r0 /* Fetch system call handler [ptr] */ |
182 | mtctr r12 | 192 | mtctr r12 |
183 | bctrl /* Call handler */ | 193 | bctrl /* Call handler */ |
@@ -596,6 +606,7 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT) | |||
596 | * actually hit this code path. | 606 | * actually hit this code path. |
597 | */ | 607 | */ |
598 | 608 | ||
609 | isync | ||
599 | slbie r6 | 610 | slbie r6 |
600 | slbie r6 /* Workaround POWER5 < DD2.1 issue */ | 611 | slbie r6 /* Workaround POWER5 < DD2.1 issue */ |
601 | slbmte r7,r0 | 612 | slbmte r7,r0 |
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index f283958129f2..285c6465324a 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S | |||
@@ -1501,6 +1501,7 @@ masked_##_H##interrupt: \ | |||
1501 | xori r10,r10,MSR_EE; /* clear MSR_EE */ \ | 1501 | xori r10,r10,MSR_EE; /* clear MSR_EE */ \ |
1502 | mtspr SPRN_##_H##SRR1,r10; \ | 1502 | mtspr SPRN_##_H##SRR1,r10; \ |
1503 | 2: mtcrf 0x80,r9; \ | 1503 | 2: mtcrf 0x80,r9; \ |
1504 | std r1,PACAR1(r13); \ | ||
1504 | ld r9,PACA_EXGEN+EX_R9(r13); \ | 1505 | ld r9,PACA_EXGEN+EX_R9(r13); \ |
1505 | ld r10,PACA_EXGEN+EX_R10(r13); \ | 1506 | ld r10,PACA_EXGEN+EX_R10(r13); \ |
1506 | ld r11,PACA_EXGEN+EX_R11(r13); \ | 1507 | ld r11,PACA_EXGEN+EX_R11(r13); \ |
diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c index 3c2c2688918f..07e8396d472b 100644 --- a/arch/powerpc/kernel/fadump.c +++ b/arch/powerpc/kernel/fadump.c | |||
@@ -335,6 +335,26 @@ static unsigned long get_fadump_area_size(void) | |||
335 | return size; | 335 | return size; |
336 | } | 336 | } |
337 | 337 | ||
338 | static void __init fadump_reserve_crash_area(unsigned long base, | ||
339 | unsigned long size) | ||
340 | { | ||
341 | struct memblock_region *reg; | ||
342 | unsigned long mstart, mend, msize; | ||
343 | |||
344 | for_each_memblock(memory, reg) { | ||
345 | mstart = max_t(unsigned long, base, reg->base); | ||
346 | mend = reg->base + reg->size; | ||
347 | mend = min(base + size, mend); | ||
348 | |||
349 | if (mstart < mend) { | ||
350 | msize = mend - mstart; | ||
351 | memblock_reserve(mstart, msize); | ||
352 | pr_info("Reserved %ldMB of memory at %#016lx for saving crash dump\n", | ||
353 | (msize >> 20), mstart); | ||
354 | } | ||
355 | } | ||
356 | } | ||
357 | |||
338 | int __init fadump_reserve_mem(void) | 358 | int __init fadump_reserve_mem(void) |
339 | { | 359 | { |
340 | unsigned long base, size, memory_boundary; | 360 | unsigned long base, size, memory_boundary; |
@@ -380,7 +400,16 @@ int __init fadump_reserve_mem(void) | |||
380 | memory_boundary = memblock_end_of_DRAM(); | 400 | memory_boundary = memblock_end_of_DRAM(); |
381 | 401 | ||
382 | if (fw_dump.dump_active) { | 402 | if (fw_dump.dump_active) { |
383 | printk(KERN_INFO "Firmware-assisted dump is active.\n"); | 403 | pr_info("Firmware-assisted dump is active.\n"); |
404 | |||
405 | #ifdef CONFIG_HUGETLB_PAGE | ||
406 | /* | ||
407 | * FADump capture kernel doesn't care much about hugepages. | ||
408 | * In fact, handling hugepages in capture kernel is asking for | ||
409 | * trouble. So, disable HugeTLB support when fadump is active. | ||
410 | */ | ||
411 | hugetlb_disabled = true; | ||
412 | #endif | ||
384 | /* | 413 | /* |
385 | * If last boot has crashed then reserve all the memory | 414 | * If last boot has crashed then reserve all the memory |
386 | * above boot_memory_size so that we don't touch it until | 415 | * above boot_memory_size so that we don't touch it until |
@@ -389,11 +418,7 @@ int __init fadump_reserve_mem(void) | |||
389 | */ | 418 | */ |
390 | base = fw_dump.boot_memory_size; | 419 | base = fw_dump.boot_memory_size; |
391 | size = memory_boundary - base; | 420 | size = memory_boundary - base; |
392 | memblock_reserve(base, size); | 421 | fadump_reserve_crash_area(base, size); |
393 | printk(KERN_INFO "Reserved %ldMB of memory at %ldMB " | ||
394 | "for saving crash dump\n", | ||
395 | (unsigned long)(size >> 20), | ||
396 | (unsigned long)(base >> 20)); | ||
397 | 422 | ||
398 | fw_dump.fadumphdr_addr = | 423 | fw_dump.fadumphdr_addr = |
399 | be64_to_cpu(fdm_active->rmr_region.destination_address) + | 424 | be64_to_cpu(fdm_active->rmr_region.destination_address) + |
@@ -1155,6 +1180,9 @@ void fadump_cleanup(void) | |||
1155 | init_fadump_mem_struct(&fdm, | 1180 | init_fadump_mem_struct(&fdm, |
1156 | be64_to_cpu(fdm_active->cpu_state_data.destination_address)); | 1181 | be64_to_cpu(fdm_active->cpu_state_data.destination_address)); |
1157 | fadump_invalidate_dump(&fdm); | 1182 | fadump_invalidate_dump(&fdm); |
1183 | } else if (fw_dump.dump_registered) { | ||
1184 | /* Un-register Firmware-assisted dump if it was registered. */ | ||
1185 | fadump_unregister_dump(&fdm); | ||
1158 | } | 1186 | } |
1159 | } | 1187 | } |
1160 | 1188 | ||
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S index d8670a37d70c..6cab07e76732 100644 --- a/arch/powerpc/kernel/head_8xx.S +++ b/arch/powerpc/kernel/head_8xx.S | |||
@@ -913,7 +913,7 @@ start_here: | |||
913 | tovirt(r6,r6) | 913 | tovirt(r6,r6) |
914 | lis r5, abatron_pteptrs@h | 914 | lis r5, abatron_pteptrs@h |
915 | ori r5, r5, abatron_pteptrs@l | 915 | ori r5, r5, abatron_pteptrs@l |
916 | stw r5, 0xf0(r0) /* Must match your Abatron config file */ | 916 | stw r5, 0xf0(0) /* Must match your Abatron config file */ |
917 | tophys(r5,r5) | 917 | tophys(r5,r5) |
918 | stw r6, 0(r5) | 918 | stw r6, 0(r5) |
919 | 919 | ||
diff --git a/arch/powerpc/kernel/hw_breakpoint.c b/arch/powerpc/kernel/hw_breakpoint.c index 4c1012b80d3b..80547dad37da 100644 --- a/arch/powerpc/kernel/hw_breakpoint.c +++ b/arch/powerpc/kernel/hw_breakpoint.c | |||
@@ -178,8 +178,8 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp) | |||
178 | if (cpu_has_feature(CPU_FTR_DAWR)) { | 178 | if (cpu_has_feature(CPU_FTR_DAWR)) { |
179 | length_max = 512 ; /* 64 doublewords */ | 179 | length_max = 512 ; /* 64 doublewords */ |
180 | /* DAWR region can't cross 512 boundary */ | 180 | /* DAWR region can't cross 512 boundary */ |
181 | if ((bp->attr.bp_addr >> 10) != | 181 | if ((bp->attr.bp_addr >> 9) != |
182 | ((bp->attr.bp_addr + bp->attr.bp_len - 1) >> 10)) | 182 | ((bp->attr.bp_addr + bp->attr.bp_len - 1) >> 9)) |
183 | return -EINVAL; | 183 | return -EINVAL; |
184 | } | 184 | } |
185 | if (info->len > | 185 | if (info->len > |
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 061aa0f47bb1..0682fef1f385 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c | |||
@@ -89,7 +89,7 @@ atomic_t ppc_n_lost_interrupts; | |||
89 | 89 | ||
90 | #ifdef CONFIG_TAU_INT | 90 | #ifdef CONFIG_TAU_INT |
91 | extern int tau_initialized; | 91 | extern int tau_initialized; |
92 | extern int tau_interrupts(int); | 92 | u32 tau_interrupts(unsigned long cpu); |
93 | #endif | 93 | #endif |
94 | #endif /* CONFIG_PPC32 */ | 94 | #endif /* CONFIG_PPC32 */ |
95 | 95 | ||
@@ -508,6 +508,11 @@ int arch_show_interrupts(struct seq_file *p, int prec) | |||
508 | seq_printf(p, "%10u ", per_cpu(irq_stat, j).timer_irqs_event); | 508 | seq_printf(p, "%10u ", per_cpu(irq_stat, j).timer_irqs_event); |
509 | seq_printf(p, " Local timer interrupts for timer event device\n"); | 509 | seq_printf(p, " Local timer interrupts for timer event device\n"); |
510 | 510 | ||
511 | seq_printf(p, "%*s: ", prec, "BCT"); | ||
512 | for_each_online_cpu(j) | ||
513 | seq_printf(p, "%10u ", per_cpu(irq_stat, j).broadcast_irqs_event); | ||
514 | seq_printf(p, " Broadcast timer interrupts for timer event device\n"); | ||
515 | |||
511 | seq_printf(p, "%*s: ", prec, "LOC"); | 516 | seq_printf(p, "%*s: ", prec, "LOC"); |
512 | for_each_online_cpu(j) | 517 | for_each_online_cpu(j) |
513 | seq_printf(p, "%10u ", per_cpu(irq_stat, j).timer_irqs_others); | 518 | seq_printf(p, "%10u ", per_cpu(irq_stat, j).timer_irqs_others); |
@@ -567,6 +572,7 @@ u64 arch_irq_stat_cpu(unsigned int cpu) | |||
567 | { | 572 | { |
568 | u64 sum = per_cpu(irq_stat, cpu).timer_irqs_event; | 573 | u64 sum = per_cpu(irq_stat, cpu).timer_irqs_event; |
569 | 574 | ||
575 | sum += per_cpu(irq_stat, cpu).broadcast_irqs_event; | ||
570 | sum += per_cpu(irq_stat, cpu).pmu_irqs; | 576 | sum += per_cpu(irq_stat, cpu).pmu_irqs; |
571 | sum += per_cpu(irq_stat, cpu).mce_exceptions; | 577 | sum += per_cpu(irq_stat, cpu).mce_exceptions; |
572 | sum += per_cpu(irq_stat, cpu).spurious_irqs; | 578 | sum += per_cpu(irq_stat, cpu).spurious_irqs; |
diff --git a/arch/powerpc/kernel/kvm.c b/arch/powerpc/kernel/kvm.c index 9ad37f827a97..683b5b3805bd 100644 --- a/arch/powerpc/kernel/kvm.c +++ b/arch/powerpc/kernel/kvm.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/kvm_para.h> | 25 | #include <linux/kvm_para.h> |
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | #include <linux/of.h> | 27 | #include <linux/of.h> |
28 | #include <linux/pagemap.h> | ||
28 | 29 | ||
29 | #include <asm/reg.h> | 30 | #include <asm/reg.h> |
30 | #include <asm/sections.h> | 31 | #include <asm/sections.h> |
@@ -672,14 +673,13 @@ static void kvm_use_magic_page(void) | |||
672 | { | 673 | { |
673 | u32 *p; | 674 | u32 *p; |
674 | u32 *start, *end; | 675 | u32 *start, *end; |
675 | u32 tmp; | ||
676 | u32 features; | 676 | u32 features; |
677 | 677 | ||
678 | /* Tell the host to map the magic page to -4096 on all CPUs */ | 678 | /* Tell the host to map the magic page to -4096 on all CPUs */ |
679 | on_each_cpu(kvm_map_magic_page, &features, 1); | 679 | on_each_cpu(kvm_map_magic_page, &features, 1); |
680 | 680 | ||
681 | /* Quick self-test to see if the mapping works */ | 681 | /* Quick self-test to see if the mapping works */ |
682 | if (__get_user(tmp, (u32*)KVM_MAGIC_PAGE)) { | 682 | if (!fault_in_pages_readable((const char *)KVM_MAGIC_PAGE, sizeof(u32))) { |
683 | kvm_patching_worked = false; | 683 | kvm_patching_worked = false; |
684 | return; | 684 | return; |
685 | } | 685 | } |
diff --git a/arch/powerpc/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec.c index 2694d078741d..936c7e2d421e 100644 --- a/arch/powerpc/kernel/machine_kexec.c +++ b/arch/powerpc/kernel/machine_kexec.c | |||
@@ -98,12 +98,14 @@ void machine_kexec(struct kimage *image) | |||
98 | int save_ftrace_enabled; | 98 | int save_ftrace_enabled; |
99 | 99 | ||
100 | save_ftrace_enabled = __ftrace_enabled_save(); | 100 | save_ftrace_enabled = __ftrace_enabled_save(); |
101 | this_cpu_disable_ftrace(); | ||
101 | 102 | ||
102 | if (ppc_md.machine_kexec) | 103 | if (ppc_md.machine_kexec) |
103 | ppc_md.machine_kexec(image); | 104 | ppc_md.machine_kexec(image); |
104 | else | 105 | else |
105 | default_machine_kexec(image); | 106 | default_machine_kexec(image); |
106 | 107 | ||
108 | this_cpu_enable_ftrace(); | ||
107 | __ftrace_enabled_restore(save_ftrace_enabled); | 109 | __ftrace_enabled_restore(save_ftrace_enabled); |
108 | 110 | ||
109 | /* Fall back to normal restart if we're still alive. */ | 111 | /* Fall back to normal restart if we're still alive. */ |
diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c index 1044bf15d5ed..a0f6f45005bd 100644 --- a/arch/powerpc/kernel/machine_kexec_64.c +++ b/arch/powerpc/kernel/machine_kexec_64.c | |||
@@ -231,16 +231,16 @@ static void kexec_prepare_cpus(void) | |||
231 | /* we are sure every CPU has IRQs off at this point */ | 231 | /* we are sure every CPU has IRQs off at this point */ |
232 | kexec_all_irq_disabled = 1; | 232 | kexec_all_irq_disabled = 1; |
233 | 233 | ||
234 | /* after we tell the others to go down */ | ||
235 | if (ppc_md.kexec_cpu_down) | ||
236 | ppc_md.kexec_cpu_down(0, 0); | ||
237 | |||
238 | /* | 234 | /* |
239 | * Before removing MMU mappings make sure all CPUs have entered real | 235 | * Before removing MMU mappings make sure all CPUs have entered real |
240 | * mode: | 236 | * mode: |
241 | */ | 237 | */ |
242 | kexec_prepare_cpus_wait(KEXEC_STATE_REAL_MODE); | 238 | kexec_prepare_cpus_wait(KEXEC_STATE_REAL_MODE); |
243 | 239 | ||
240 | /* after we tell the others to go down */ | ||
241 | if (ppc_md.kexec_cpu_down) | ||
242 | ppc_md.kexec_cpu_down(0, 0); | ||
243 | |||
244 | put_cpu(); | 244 | put_cpu(); |
245 | } | 245 | } |
246 | 246 | ||
diff --git a/arch/powerpc/kernel/misc.S b/arch/powerpc/kernel/misc.S index 384357cb8bc0..0b196cdcd15d 100644 --- a/arch/powerpc/kernel/misc.S +++ b/arch/powerpc/kernel/misc.S | |||
@@ -25,23 +25,12 @@ | |||
25 | /* | 25 | /* |
26 | * Returns (address we are running at) - (address we were linked at) | 26 | * Returns (address we are running at) - (address we were linked at) |
27 | * for use before the text and data are mapped to KERNELBASE. | 27 | * for use before the text and data are mapped to KERNELBASE. |
28 | */ | ||
29 | |||
30 | _GLOBAL(reloc_offset) | ||
31 | mflr r0 | ||
32 | bl 1f | ||
33 | 1: mflr r3 | ||
34 | PPC_LL r4,(2f-1b)(r3) | ||
35 | subf r3,r4,r3 | ||
36 | mtlr r0 | ||
37 | blr | ||
38 | 28 | ||
39 | .align 3 | ||
40 | 2: PPC_LONG 1b | ||
41 | |||
42 | /* | ||
43 | * add_reloc_offset(x) returns x + reloc_offset(). | 29 | * add_reloc_offset(x) returns x + reloc_offset(). |
44 | */ | 30 | */ |
31 | |||
32 | _GLOBAL(reloc_offset) | ||
33 | li r3, 0 | ||
45 | _GLOBAL(add_reloc_offset) | 34 | _GLOBAL(add_reloc_offset) |
46 | mflr r0 | 35 | mflr r0 |
47 | bl 1f | 36 | bl 1f |
@@ -60,6 +49,10 @@ _GLOBAL(setjmp) | |||
60 | PPC_STL r0,0(r3) | 49 | PPC_STL r0,0(r3) |
61 | PPC_STL r1,SZL(r3) | 50 | PPC_STL r1,SZL(r3) |
62 | PPC_STL r2,2*SZL(r3) | 51 | PPC_STL r2,2*SZL(r3) |
52 | #ifdef CONFIG_PPC32 | ||
53 | mfcr r12 | ||
54 | stmw r12, 3*SZL(r3) | ||
55 | #else | ||
63 | mfcr r0 | 56 | mfcr r0 |
64 | PPC_STL r0,3*SZL(r3) | 57 | PPC_STL r0,3*SZL(r3) |
65 | PPC_STL r13,4*SZL(r3) | 58 | PPC_STL r13,4*SZL(r3) |
@@ -81,14 +74,16 @@ _GLOBAL(setjmp) | |||
81 | PPC_STL r29,20*SZL(r3) | 74 | PPC_STL r29,20*SZL(r3) |
82 | PPC_STL r30,21*SZL(r3) | 75 | PPC_STL r30,21*SZL(r3) |
83 | PPC_STL r31,22*SZL(r3) | 76 | PPC_STL r31,22*SZL(r3) |
77 | #endif | ||
84 | li r3,0 | 78 | li r3,0 |
85 | blr | 79 | blr |
86 | 80 | ||
87 | _GLOBAL(longjmp) | 81 | _GLOBAL(longjmp) |
88 | PPC_LCMPI r4,0 | 82 | #ifdef CONFIG_PPC32 |
89 | bne 1f | 83 | lmw r12, 3*SZL(r3) |
90 | li r4,1 | 84 | mtcrf 0x38, r12 |
91 | 1: PPC_LL r13,4*SZL(r3) | 85 | #else |
86 | PPC_LL r13,4*SZL(r3) | ||
92 | PPC_LL r14,5*SZL(r3) | 87 | PPC_LL r14,5*SZL(r3) |
93 | PPC_LL r15,6*SZL(r3) | 88 | PPC_LL r15,6*SZL(r3) |
94 | PPC_LL r16,7*SZL(r3) | 89 | PPC_LL r16,7*SZL(r3) |
@@ -109,11 +104,14 @@ _GLOBAL(longjmp) | |||
109 | PPC_LL r31,22*SZL(r3) | 104 | PPC_LL r31,22*SZL(r3) |
110 | PPC_LL r0,3*SZL(r3) | 105 | PPC_LL r0,3*SZL(r3) |
111 | mtcrf 0x38,r0 | 106 | mtcrf 0x38,r0 |
107 | #endif | ||
112 | PPC_LL r0,0(r3) | 108 | PPC_LL r0,0(r3) |
113 | PPC_LL r1,SZL(r3) | 109 | PPC_LL r1,SZL(r3) |
114 | PPC_LL r2,2*SZL(r3) | 110 | PPC_LL r2,2*SZL(r3) |
115 | mtlr r0 | 111 | mtlr r0 |
116 | mr r3,r4 | 112 | mr. r3, r4 |
113 | bnelr | ||
114 | li r3, 1 | ||
117 | blr | 115 | blr |
118 | 116 | ||
119 | _GLOBAL(current_stack_pointer) | 117 | _GLOBAL(current_stack_pointer) |
diff --git a/arch/powerpc/kernel/module.c b/arch/powerpc/kernel/module.c index 3f7ba0f5bf29..1b3c6835e730 100644 --- a/arch/powerpc/kernel/module.c +++ b/arch/powerpc/kernel/module.c | |||
@@ -72,6 +72,12 @@ int module_finalize(const Elf_Ehdr *hdr, | |||
72 | do_feature_fixups(powerpc_firmware_features, | 72 | do_feature_fixups(powerpc_firmware_features, |
73 | (void *)sect->sh_addr, | 73 | (void *)sect->sh_addr, |
74 | (void *)sect->sh_addr + sect->sh_size); | 74 | (void *)sect->sh_addr + sect->sh_size); |
75 | |||
76 | sect = find_section(hdr, sechdrs, "__spec_barrier_fixup"); | ||
77 | if (sect != NULL) | ||
78 | do_barrier_nospec_fixups_range(barrier_nospec_enabled, | ||
79 | (void *)sect->sh_addr, | ||
80 | (void *)sect->sh_addr + sect->sh_size); | ||
75 | #endif | 81 | #endif |
76 | 82 | ||
77 | sect = find_section(hdr, sechdrs, "__lwsync_fixup"); | 83 | sect = find_section(hdr, sechdrs, "__lwsync_fixup"); |
diff --git a/arch/powerpc/kernel/module_32.c b/arch/powerpc/kernel/module_32.c index 5a7a78f12562..88d83771f462 100644 --- a/arch/powerpc/kernel/module_32.c +++ b/arch/powerpc/kernel/module_32.c | |||
@@ -109,12 +109,12 @@ static unsigned long get_plt_size(const Elf32_Ehdr *hdr, | |||
109 | for (i = 1; i < hdr->e_shnum; i++) { | 109 | for (i = 1; i < hdr->e_shnum; i++) { |
110 | /* If it's called *.init*, and we're not init, we're | 110 | /* If it's called *.init*, and we're not init, we're |
111 | not interested */ | 111 | not interested */ |
112 | if ((strstr(secstrings + sechdrs[i].sh_name, ".init") != 0) | 112 | if ((strstr(secstrings + sechdrs[i].sh_name, ".init") != NULL) |
113 | != is_init) | 113 | != is_init) |
114 | continue; | 114 | continue; |
115 | 115 | ||
116 | /* We don't want to look at debug sections. */ | 116 | /* We don't want to look at debug sections. */ |
117 | if (strstr(secstrings + sechdrs[i].sh_name, ".debug") != 0) | 117 | if (strstr(secstrings + sechdrs[i].sh_name, ".debug")) |
118 | continue; | 118 | continue; |
119 | 119 | ||
120 | if (sechdrs[i].sh_type == SHT_RELA) { | 120 | if (sechdrs[i].sh_type == SHT_RELA) { |
diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c index a2636c250b7b..1b7419579820 100644 --- a/arch/powerpc/kernel/module_64.c +++ b/arch/powerpc/kernel/module_64.c | |||
@@ -280,6 +280,10 @@ static unsigned long get_stubs_size(const Elf64_Ehdr *hdr, | |||
280 | #ifdef CONFIG_DYNAMIC_FTRACE | 280 | #ifdef CONFIG_DYNAMIC_FTRACE |
281 | /* make the trampoline to the ftrace_caller */ | 281 | /* make the trampoline to the ftrace_caller */ |
282 | relocs++; | 282 | relocs++; |
283 | #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS | ||
284 | /* an additional one for ftrace_regs_caller */ | ||
285 | relocs++; | ||
286 | #endif | ||
283 | #endif | 287 | #endif |
284 | 288 | ||
285 | pr_debug("Looks like a total of %lu stubs, max\n", relocs); | 289 | pr_debug("Looks like a total of %lu stubs, max\n", relocs); |
@@ -463,8 +467,11 @@ static unsigned long stub_for_addr(const Elf64_Shdr *sechdrs, | |||
463 | } | 467 | } |
464 | 468 | ||
465 | #ifdef CC_USING_MPROFILE_KERNEL | 469 | #ifdef CC_USING_MPROFILE_KERNEL |
466 | static bool is_early_mcount_callsite(u32 *instruction) | 470 | static bool is_mprofile_mcount_callsite(const char *name, u32 *instruction) |
467 | { | 471 | { |
472 | if (strcmp("_mcount", name)) | ||
473 | return false; | ||
474 | |||
468 | /* | 475 | /* |
469 | * Check if this is one of the -mprofile-kernel sequences. | 476 | * Check if this is one of the -mprofile-kernel sequences. |
470 | */ | 477 | */ |
@@ -496,8 +503,7 @@ static void squash_toc_save_inst(const char *name, unsigned long addr) | |||
496 | #else | 503 | #else |
497 | static void squash_toc_save_inst(const char *name, unsigned long addr) { } | 504 | static void squash_toc_save_inst(const char *name, unsigned long addr) { } |
498 | 505 | ||
499 | /* without -mprofile-kernel, mcount calls are never early */ | 506 | static bool is_mprofile_mcount_callsite(const char *name, u32 *instruction) |
500 | static bool is_early_mcount_callsite(u32 *instruction) | ||
501 | { | 507 | { |
502 | return false; | 508 | return false; |
503 | } | 509 | } |
@@ -505,11 +511,11 @@ static bool is_early_mcount_callsite(u32 *instruction) | |||
505 | 511 | ||
506 | /* We expect a noop next: if it is, replace it with instruction to | 512 | /* We expect a noop next: if it is, replace it with instruction to |
507 | restore r2. */ | 513 | restore r2. */ |
508 | static int restore_r2(u32 *instruction, struct module *me) | 514 | static int restore_r2(const char *name, u32 *instruction, struct module *me) |
509 | { | 515 | { |
510 | u32 *prev_insn = instruction - 1; | 516 | u32 *prev_insn = instruction - 1; |
511 | 517 | ||
512 | if (is_early_mcount_callsite(prev_insn)) | 518 | if (is_mprofile_mcount_callsite(name, prev_insn)) |
513 | return 1; | 519 | return 1; |
514 | 520 | ||
515 | /* | 521 | /* |
@@ -650,7 +656,8 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, | |||
650 | value = stub_for_addr(sechdrs, value, me); | 656 | value = stub_for_addr(sechdrs, value, me); |
651 | if (!value) | 657 | if (!value) |
652 | return -ENOENT; | 658 | return -ENOENT; |
653 | if (!restore_r2((u32 *)location + 1, me)) | 659 | if (!restore_r2(strtab + sym->st_name, |
660 | (u32 *)location + 1, me)) | ||
654 | return -ENOEXEC; | 661 | return -ENOEXEC; |
655 | 662 | ||
656 | squash_toc_save_inst(strtab + sym->st_name, value); | 663 | squash_toc_save_inst(strtab + sym->st_name, value); |
@@ -762,7 +769,8 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, | |||
762 | * via the paca (in r13). The target (ftrace_caller()) is responsible for | 769 | * via the paca (in r13). The target (ftrace_caller()) is responsible for |
763 | * saving and restoring the toc before returning. | 770 | * saving and restoring the toc before returning. |
764 | */ | 771 | */ |
765 | static unsigned long create_ftrace_stub(const Elf64_Shdr *sechdrs, struct module *me) | 772 | static unsigned long create_ftrace_stub(const Elf64_Shdr *sechdrs, |
773 | struct module *me, unsigned long addr) | ||
766 | { | 774 | { |
767 | struct ppc64_stub_entry *entry; | 775 | struct ppc64_stub_entry *entry; |
768 | unsigned int i, num_stubs; | 776 | unsigned int i, num_stubs; |
@@ -789,9 +797,10 @@ static unsigned long create_ftrace_stub(const Elf64_Shdr *sechdrs, struct module | |||
789 | memcpy(entry->jump, stub_insns, sizeof(stub_insns)); | 797 | memcpy(entry->jump, stub_insns, sizeof(stub_insns)); |
790 | 798 | ||
791 | /* Stub uses address relative to kernel toc (from the paca) */ | 799 | /* Stub uses address relative to kernel toc (from the paca) */ |
792 | reladdr = (unsigned long)ftrace_caller - kernel_toc_addr(); | 800 | reladdr = addr - kernel_toc_addr(); |
793 | if (reladdr > 0x7FFFFFFF || reladdr < -(0x80000000L)) { | 801 | if (reladdr > 0x7FFFFFFF || reladdr < -(0x80000000L)) { |
794 | pr_err("%s: Address of ftrace_caller out of range of kernel_toc.\n", me->name); | 802 | pr_err("%s: Address of %ps out of range of kernel_toc.\n", |
803 | me->name, (void *)addr); | ||
795 | return 0; | 804 | return 0; |
796 | } | 805 | } |
797 | 806 | ||
@@ -799,22 +808,29 @@ static unsigned long create_ftrace_stub(const Elf64_Shdr *sechdrs, struct module | |||
799 | entry->jump[2] |= PPC_LO(reladdr); | 808 | entry->jump[2] |= PPC_LO(reladdr); |
800 | 809 | ||
801 | /* Eventhough we don't use funcdata in the stub, it's needed elsewhere. */ | 810 | /* Eventhough we don't use funcdata in the stub, it's needed elsewhere. */ |
802 | entry->funcdata = func_desc((unsigned long)ftrace_caller); | 811 | entry->funcdata = func_desc(addr); |
803 | entry->magic = STUB_MAGIC; | 812 | entry->magic = STUB_MAGIC; |
804 | 813 | ||
805 | return (unsigned long)entry; | 814 | return (unsigned long)entry; |
806 | } | 815 | } |
807 | #else | 816 | #else |
808 | static unsigned long create_ftrace_stub(const Elf64_Shdr *sechdrs, struct module *me) | 817 | static unsigned long create_ftrace_stub(const Elf64_Shdr *sechdrs, |
818 | struct module *me, unsigned long addr) | ||
809 | { | 819 | { |
810 | return stub_for_addr(sechdrs, (unsigned long)ftrace_caller, me); | 820 | return stub_for_addr(sechdrs, addr, me); |
811 | } | 821 | } |
812 | #endif | 822 | #endif |
813 | 823 | ||
814 | int module_finalize_ftrace(struct module *mod, const Elf_Shdr *sechdrs) | 824 | int module_finalize_ftrace(struct module *mod, const Elf_Shdr *sechdrs) |
815 | { | 825 | { |
816 | mod->arch.toc = my_r2(sechdrs, mod); | 826 | mod->arch.tramp = create_ftrace_stub(sechdrs, mod, |
817 | mod->arch.tramp = create_ftrace_stub(sechdrs, mod); | 827 | (unsigned long)ftrace_caller); |
828 | #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS | ||
829 | mod->arch.tramp_regs = create_ftrace_stub(sechdrs, mod, | ||
830 | (unsigned long)ftrace_regs_caller); | ||
831 | if (!mod->arch.tramp_regs) | ||
832 | return -ENOENT; | ||
833 | #endif | ||
818 | 834 | ||
819 | if (!mod->arch.tramp) | 835 | if (!mod->arch.tramp) |
820 | return -ENOENT; | 836 | return -ENOENT; |
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c index ba681dac7b46..22e9d281324d 100644 --- a/arch/powerpc/kernel/nvram_64.c +++ b/arch/powerpc/kernel/nvram_64.c | |||
@@ -1030,7 +1030,7 @@ loff_t __init nvram_create_partition(const char *name, int sig, | |||
1030 | return -ENOSPC; | 1030 | return -ENOSPC; |
1031 | 1031 | ||
1032 | /* Create our OS partition */ | 1032 | /* Create our OS partition */ |
1033 | new_part = kmalloc(sizeof(*new_part), GFP_KERNEL); | 1033 | new_part = kzalloc(sizeof(*new_part), GFP_KERNEL); |
1034 | if (!new_part) { | 1034 | if (!new_part) { |
1035 | pr_err("%s: kmalloc failed\n", __func__); | 1035 | pr_err("%s: kmalloc failed\n", __func__); |
1036 | return -ENOMEM; | 1036 | return -ENOMEM; |
@@ -1039,7 +1039,7 @@ loff_t __init nvram_create_partition(const char *name, int sig, | |||
1039 | new_part->index = free_part->index; | 1039 | new_part->index = free_part->index; |
1040 | new_part->header.signature = sig; | 1040 | new_part->header.signature = sig; |
1041 | new_part->header.length = size; | 1041 | new_part->header.length = size; |
1042 | strncpy(new_part->header.name, name, 12); | 1042 | memcpy(new_part->header.name, name, strnlen(name, sizeof(new_part->header.name))); |
1043 | new_part->header.checksum = nvram_checksum(&new_part->header); | 1043 | new_part->header.checksum = nvram_checksum(&new_part->header); |
1044 | 1044 | ||
1045 | rc = nvram_write_header(new_part); | 1045 | rc = nvram_write_header(new_part); |
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index 85ad2f78b889..4f861055a852 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c | |||
@@ -11,11 +11,13 @@ | |||
11 | #include <linux/sched.h> | 11 | #include <linux/sched.h> |
12 | #include <linux/errno.h> | 12 | #include <linux/errno.h> |
13 | #include <linux/bootmem.h> | 13 | #include <linux/bootmem.h> |
14 | #include <linux/syscalls.h> | ||
14 | #include <linux/irq.h> | 15 | #include <linux/irq.h> |
15 | #include <linux/list.h> | 16 | #include <linux/list.h> |
16 | #include <linux/of.h> | 17 | #include <linux/of.h> |
17 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
18 | #include <linux/export.h> | 19 | #include <linux/export.h> |
20 | #include <linux/syscalls.h> | ||
19 | 21 | ||
20 | #include <asm/processor.h> | 22 | #include <asm/processor.h> |
21 | #include <asm/io.h> | 23 | #include <asm/io.h> |
@@ -283,7 +285,11 @@ pci_bus_to_hose(int bus) | |||
283 | * Note that the returned IO or memory base is a physical address | 285 | * Note that the returned IO or memory base is a physical address |
284 | */ | 286 | */ |
285 | 287 | ||
286 | long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn) | 288 | #pragma GCC diagnostic push |
289 | #pragma GCC diagnostic ignored "-Wpragmas" | ||
290 | #pragma GCC diagnostic ignored "-Wattribute-alias" | ||
291 | SYSCALL_DEFINE3(pciconfig_iobase, long, which, | ||
292 | unsigned long, bus, unsigned long, devfn) | ||
287 | { | 293 | { |
288 | struct pci_controller* hose; | 294 | struct pci_controller* hose; |
289 | long result = -EOPNOTSUPP; | 295 | long result = -EOPNOTSUPP; |
@@ -307,5 +313,4 @@ long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn) | |||
307 | 313 | ||
308 | return result; | 314 | return result; |
309 | } | 315 | } |
310 | 316 | #pragma GCC diagnostic pop | |
311 | |||
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 15ce0306b092..812171c09f42 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c | |||
@@ -203,8 +203,11 @@ void pcibios_setup_phb_io_space(struct pci_controller *hose) | |||
203 | #define IOBASE_ISA_IO 3 | 203 | #define IOBASE_ISA_IO 3 |
204 | #define IOBASE_ISA_MEM 4 | 204 | #define IOBASE_ISA_MEM 4 |
205 | 205 | ||
206 | long sys_pciconfig_iobase(long which, unsigned long in_bus, | 206 | #pragma GCC diagnostic push |
207 | unsigned long in_devfn) | 207 | #pragma GCC diagnostic ignored "-Wpragmas" |
208 | #pragma GCC diagnostic ignored "-Wattribute-alias" | ||
209 | SYSCALL_DEFINE3(pciconfig_iobase, long, which, unsigned long, in_bus, | ||
210 | unsigned long, in_devfn) | ||
208 | { | 211 | { |
209 | struct pci_controller* hose; | 212 | struct pci_controller* hose; |
210 | struct pci_bus *tmp_bus, *bus = NULL; | 213 | struct pci_bus *tmp_bus, *bus = NULL; |
@@ -256,6 +259,7 @@ long sys_pciconfig_iobase(long which, unsigned long in_bus, | |||
256 | 259 | ||
257 | return -EOPNOTSUPP; | 260 | return -EOPNOTSUPP; |
258 | } | 261 | } |
262 | #pragma GCC diagnostic pop | ||
259 | 263 | ||
260 | #ifdef CONFIG_NUMA | 264 | #ifdef CONFIG_NUMA |
261 | int pcibus_to_node(struct pci_bus *bus) | 265 | int pcibus_to_node(struct pci_bus *bus) |
diff --git a/arch/powerpc/kernel/ppc_save_regs.S b/arch/powerpc/kernel/ppc_save_regs.S index 1b1787d52896..8afbe213d729 100644 --- a/arch/powerpc/kernel/ppc_save_regs.S +++ b/arch/powerpc/kernel/ppc_save_regs.S | |||
@@ -25,6 +25,9 @@ | |||
25 | */ | 25 | */ |
26 | _GLOBAL(ppc_save_regs) | 26 | _GLOBAL(ppc_save_regs) |
27 | PPC_STL r0,0*SZL(r3) | 27 | PPC_STL r0,0*SZL(r3) |
28 | #ifdef CONFIG_PPC32 | ||
29 | stmw r2, 2*SZL(r3) | ||
30 | #else | ||
28 | PPC_STL r2,2*SZL(r3) | 31 | PPC_STL r2,2*SZL(r3) |
29 | PPC_STL r3,3*SZL(r3) | 32 | PPC_STL r3,3*SZL(r3) |
30 | PPC_STL r4,4*SZL(r3) | 33 | PPC_STL r4,4*SZL(r3) |
@@ -55,6 +58,7 @@ _GLOBAL(ppc_save_regs) | |||
55 | PPC_STL r29,29*SZL(r3) | 58 | PPC_STL r29,29*SZL(r3) |
56 | PPC_STL r30,30*SZL(r3) | 59 | PPC_STL r30,30*SZL(r3) |
57 | PPC_STL r31,31*SZL(r3) | 60 | PPC_STL r31,31*SZL(r3) |
61 | #endif | ||
58 | /* go up one stack frame for SP */ | 62 | /* go up one stack frame for SP */ |
59 | PPC_LL r4,0(r1) | 63 | PPC_LL r4,0(r1) |
60 | PPC_STL r4,1*SZL(r3) | 64 | PPC_STL r4,1*SZL(r3) |
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 26ea9793d290..9ef4aea9fffe 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
@@ -154,6 +154,7 @@ unsigned long msr_check_and_set(unsigned long bits) | |||
154 | 154 | ||
155 | return newmsr; | 155 | return newmsr; |
156 | } | 156 | } |
157 | EXPORT_SYMBOL_GPL(msr_check_and_set); | ||
157 | 158 | ||
158 | void __msr_check_and_clear(unsigned long bits) | 159 | void __msr_check_and_clear(unsigned long bits) |
159 | { | 160 | { |
@@ -846,10 +847,6 @@ bool ppc_breakpoint_available(void) | |||
846 | } | 847 | } |
847 | EXPORT_SYMBOL_GPL(ppc_breakpoint_available); | 848 | EXPORT_SYMBOL_GPL(ppc_breakpoint_available); |
848 | 849 | ||
849 | #ifdef CONFIG_PPC64 | ||
850 | DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array); | ||
851 | #endif | ||
852 | |||
853 | static inline bool hw_brk_match(struct arch_hw_breakpoint *a, | 850 | static inline bool hw_brk_match(struct arch_hw_breakpoint *a, |
854 | struct arch_hw_breakpoint *b) | 851 | struct arch_hw_breakpoint *b) |
855 | { | 852 | { |
@@ -1155,7 +1152,7 @@ static inline void restore_sprs(struct thread_struct *old_thread, | |||
1155 | mtspr(SPRN_TAR, new_thread->tar); | 1152 | mtspr(SPRN_TAR, new_thread->tar); |
1156 | } | 1153 | } |
1157 | 1154 | ||
1158 | if (cpu_has_feature(CPU_FTR_ARCH_300) && | 1155 | if (cpu_has_feature(CPU_FTR_P9_TIDR) && |
1159 | old_thread->tidr != new_thread->tidr) | 1156 | old_thread->tidr != new_thread->tidr) |
1160 | mtspr(SPRN_TIDR, new_thread->tidr); | 1157 | mtspr(SPRN_TIDR, new_thread->tidr); |
1161 | #endif | 1158 | #endif |
@@ -1182,20 +1179,6 @@ struct task_struct *__switch_to(struct task_struct *prev, | |||
1182 | 1179 | ||
1183 | WARN_ON(!irqs_disabled()); | 1180 | WARN_ON(!irqs_disabled()); |
1184 | 1181 | ||
1185 | #ifdef CONFIG_PPC64 | ||
1186 | /* | ||
1187 | * Collect processor utilization data per process | ||
1188 | */ | ||
1189 | if (firmware_has_feature(FW_FEATURE_SPLPAR)) { | ||
1190 | struct cpu_usage *cu = this_cpu_ptr(&cpu_usage_array); | ||
1191 | long unsigned start_tb, current_tb; | ||
1192 | start_tb = old_thread->start_tb; | ||
1193 | cu->current_tb = current_tb = mfspr(SPRN_PURR); | ||
1194 | old_thread->accum_tb += (current_tb - start_tb); | ||
1195 | new_thread->start_tb = current_tb; | ||
1196 | } | ||
1197 | #endif /* CONFIG_PPC64 */ | ||
1198 | |||
1199 | #ifdef CONFIG_PPC_BOOK3S_64 | 1182 | #ifdef CONFIG_PPC_BOOK3S_64 |
1200 | batch = this_cpu_ptr(&ppc64_tlb_batch); | 1183 | batch = this_cpu_ptr(&ppc64_tlb_batch); |
1201 | if (batch->active) { | 1184 | if (batch->active) { |
@@ -1438,7 +1421,7 @@ void show_regs(struct pt_regs * regs) | |||
1438 | pr_cont("DAR: "REG" DSISR: %08lx ", regs->dar, regs->dsisr); | 1421 | pr_cont("DAR: "REG" DSISR: %08lx ", regs->dar, regs->dsisr); |
1439 | #endif | 1422 | #endif |
1440 | #ifdef CONFIG_PPC64 | 1423 | #ifdef CONFIG_PPC64 |
1441 | pr_cont("SOFTE: %ld ", regs->softe); | 1424 | pr_cont("IRQMASK: %lx ", regs->softe); |
1442 | #endif | 1425 | #endif |
1443 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | 1426 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM |
1444 | if (MSR_TM_ACTIVE(regs->msr)) | 1427 | if (MSR_TM_ACTIVE(regs->msr)) |
@@ -1497,104 +1480,42 @@ int set_thread_uses_vas(void) | |||
1497 | } | 1480 | } |
1498 | 1481 | ||
1499 | #ifdef CONFIG_PPC64 | 1482 | #ifdef CONFIG_PPC64 |
1500 | static DEFINE_SPINLOCK(vas_thread_id_lock); | 1483 | /** |
1501 | static DEFINE_IDA(vas_thread_ida); | 1484 | * Assign a TIDR (thread ID) for task @t and set it in the thread |
1502 | 1485 | * structure. For now, we only support setting TIDR for 'current' task. | |
1503 | /* | ||
1504 | * We need to assign a unique thread id to each thread in a process. | ||
1505 | * | 1486 | * |
1506 | * This thread id, referred to as TIDR, and separate from the Linux's tgid, | 1487 | * Since the TID value is a truncated form of it PID, it is possible |
1507 | * is intended to be used to direct an ASB_Notify from the hardware to the | 1488 | * (but unlikely) for 2 threads to have the same TID. In the unlikely event |
1508 | * thread, when a suitable event occurs in the system. | 1489 | * that 2 threads share the same TID and are waiting, one of the following |
1490 | * cases will happen: | ||
1509 | * | 1491 | * |
1510 | * One such event is a "paste" instruction in the context of Fast Thread | 1492 | * 1. The correct thread is running, the wrong thread is not |
1511 | * Wakeup (aka Core-to-core wake up in the Virtual Accelerator Switchboard | 1493 | * In this situation, the correct thread is woken and proceeds to pass it's |
1512 | * (VAS) in POWER9. | 1494 | * condition check. |
1513 | * | 1495 | * |
1514 | * To get a unique TIDR per process we could simply reuse task_pid_nr() but | 1496 | * 2. Neither threads are running |
1515 | * the problem is that task_pid_nr() is not yet available copy_thread() is | 1497 | * In this situation, neither thread will be woken. When scheduled, the waiting |
1516 | * called. Fixing that would require changing more intrusive arch-neutral | 1498 | * threads will execute either a wait, which will return immediately, followed |
1517 | * code in code path in copy_process()?. | 1499 | * by a condition check, which will pass for the correct thread and fail |
1500 | * for the wrong thread, or they will execute the condition check immediately. | ||
1518 | * | 1501 | * |
1519 | * Further, to assign unique TIDRs within each process, we need an atomic | 1502 | * 3. The wrong thread is running, the correct thread is not |
1520 | * field (or an IDR) in task_struct, which again intrudes into the arch- | 1503 | * The wrong thread will be woken, but will fail it's condition check and |
1521 | * neutral code. So try to assign globally unique TIDRs for now. | 1504 | * re-execute wait. The correct thread, when scheduled, will execute either |
1505 | * it's condition check (which will pass), or wait, which returns immediately | ||
1506 | * when called the first time after the thread is scheduled, followed by it's | ||
1507 | * condition check (which will pass). | ||
1522 | * | 1508 | * |
1523 | * NOTE: TIDR 0 indicates that the thread does not need a TIDR value. | 1509 | * 4. Both threads are running |
1524 | * For now, only threads that expect to be notified by the VAS | 1510 | * Both threads will be woken. The wrong thread will fail it's condition check |
1525 | * hardware need a TIDR value and we assign values > 0 for those. | 1511 | * and execute another wait, while the correct thread will pass it's condition |
1526 | */ | 1512 | * check. |
1527 | #define MAX_THREAD_CONTEXT ((1 << 16) - 1) | 1513 | * |
1528 | static int assign_thread_tidr(void) | 1514 | * @t: the task to set the thread ID for |
1529 | { | ||
1530 | int index; | ||
1531 | int err; | ||
1532 | unsigned long flags; | ||
1533 | |||
1534 | again: | ||
1535 | if (!ida_pre_get(&vas_thread_ida, GFP_KERNEL)) | ||
1536 | return -ENOMEM; | ||
1537 | |||
1538 | spin_lock_irqsave(&vas_thread_id_lock, flags); | ||
1539 | err = ida_get_new_above(&vas_thread_ida, 1, &index); | ||
1540 | spin_unlock_irqrestore(&vas_thread_id_lock, flags); | ||
1541 | |||
1542 | if (err == -EAGAIN) | ||
1543 | goto again; | ||
1544 | else if (err) | ||
1545 | return err; | ||
1546 | |||
1547 | if (index > MAX_THREAD_CONTEXT) { | ||
1548 | spin_lock_irqsave(&vas_thread_id_lock, flags); | ||
1549 | ida_remove(&vas_thread_ida, index); | ||
1550 | spin_unlock_irqrestore(&vas_thread_id_lock, flags); | ||
1551 | return -ENOMEM; | ||
1552 | } | ||
1553 | |||
1554 | return index; | ||
1555 | } | ||
1556 | |||
1557 | static void free_thread_tidr(int id) | ||
1558 | { | ||
1559 | unsigned long flags; | ||
1560 | |||
1561 | spin_lock_irqsave(&vas_thread_id_lock, flags); | ||
1562 | ida_remove(&vas_thread_ida, id); | ||
1563 | spin_unlock_irqrestore(&vas_thread_id_lock, flags); | ||
1564 | } | ||
1565 | |||
1566 | /* | ||
1567 | * Clear any TIDR value assigned to this thread. | ||
1568 | */ | ||
1569 | void clear_thread_tidr(struct task_struct *t) | ||
1570 | { | ||
1571 | if (!t->thread.tidr) | ||
1572 | return; | ||
1573 | |||
1574 | if (!cpu_has_feature(CPU_FTR_ARCH_300)) { | ||
1575 | WARN_ON_ONCE(1); | ||
1576 | return; | ||
1577 | } | ||
1578 | |||
1579 | mtspr(SPRN_TIDR, 0); | ||
1580 | free_thread_tidr(t->thread.tidr); | ||
1581 | t->thread.tidr = 0; | ||
1582 | } | ||
1583 | |||
1584 | void arch_release_task_struct(struct task_struct *t) | ||
1585 | { | ||
1586 | clear_thread_tidr(t); | ||
1587 | } | ||
1588 | |||
1589 | /* | ||
1590 | * Assign a unique TIDR (thread id) for task @t and set it in the thread | ||
1591 | * structure. For now, we only support setting TIDR for 'current' task. | ||
1592 | */ | 1515 | */ |
1593 | int set_thread_tidr(struct task_struct *t) | 1516 | int set_thread_tidr(struct task_struct *t) |
1594 | { | 1517 | { |
1595 | int rc; | 1518 | if (!cpu_has_feature(CPU_FTR_P9_TIDR)) |
1596 | |||
1597 | if (!cpu_has_feature(CPU_FTR_ARCH_300)) | ||
1598 | return -EINVAL; | 1519 | return -EINVAL; |
1599 | 1520 | ||
1600 | if (t != current) | 1521 | if (t != current) |
@@ -1603,11 +1524,7 @@ int set_thread_tidr(struct task_struct *t) | |||
1603 | if (t->thread.tidr) | 1524 | if (t->thread.tidr) |
1604 | return 0; | 1525 | return 0; |
1605 | 1526 | ||
1606 | rc = assign_thread_tidr(); | 1527 | t->thread.tidr = (u16)task_pid_nr(t); |
1607 | if (rc < 0) | ||
1608 | return rc; | ||
1609 | |||
1610 | t->thread.tidr = rc; | ||
1611 | mtspr(SPRN_TIDR, t->thread.tidr); | 1528 | mtspr(SPRN_TIDR, t->thread.tidr); |
1612 | 1529 | ||
1613 | return 0; | 1530 | return 0; |
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 9dbed488aba1..05e7fb47a7a4 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
@@ -332,25 +332,10 @@ static int __init early_init_dt_scan_cpus(unsigned long node, | |||
332 | * NOTE: This must match the parsing done in smp_setup_cpu_maps. | 332 | * NOTE: This must match the parsing done in smp_setup_cpu_maps. |
333 | */ | 333 | */ |
334 | for (i = 0; i < nthreads; i++) { | 334 | for (i = 0; i < nthreads; i++) { |
335 | /* | 335 | if (be32_to_cpu(intserv[i]) == |
336 | * version 2 of the kexec param format adds the phys cpuid of | 336 | fdt_boot_cpuid_phys(initial_boot_params)) { |
337 | * booted proc. | 337 | found = boot_cpu_count; |
338 | */ | 338 | found_thread = i; |
339 | if (fdt_version(initial_boot_params) >= 2) { | ||
340 | if (be32_to_cpu(intserv[i]) == | ||
341 | fdt_boot_cpuid_phys(initial_boot_params)) { | ||
342 | found = boot_cpu_count; | ||
343 | found_thread = i; | ||
344 | } | ||
345 | } else { | ||
346 | /* | ||
347 | * Check if it's the boot-cpu, set it's hw index now, | ||
348 | * unfortunately this format did not support booting | ||
349 | * off secondary threads. | ||
350 | */ | ||
351 | if (of_get_flat_dt_prop(node, | ||
352 | "linux,boot-cpu", NULL) != NULL) | ||
353 | found = boot_cpu_count; | ||
354 | } | 339 | } |
355 | #ifdef CONFIG_SMP | 340 | #ifdef CONFIG_SMP |
356 | /* logical cpu id is always 0 on UP kernels */ | 341 | /* logical cpu id is always 0 on UP kernels */ |
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index f9d6befb55a6..5425dd3d6a9f 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c | |||
@@ -103,7 +103,7 @@ int of_workarounds; | |||
103 | #ifdef DEBUG_PROM | 103 | #ifdef DEBUG_PROM |
104 | #define prom_debug(x...) prom_printf(x) | 104 | #define prom_debug(x...) prom_printf(x) |
105 | #else | 105 | #else |
106 | #define prom_debug(x...) | 106 | #define prom_debug(x...) do { } while (0) |
107 | #endif | 107 | #endif |
108 | 108 | ||
109 | 109 | ||
@@ -301,6 +301,10 @@ static void __init prom_print(const char *msg) | |||
301 | } | 301 | } |
302 | 302 | ||
303 | 303 | ||
304 | /* | ||
305 | * Both prom_print_hex & prom_print_dec takes an unsigned long as input so that | ||
306 | * we do not need __udivdi3 or __umoddi3 on 32bits. | ||
307 | */ | ||
304 | static void __init prom_print_hex(unsigned long val) | 308 | static void __init prom_print_hex(unsigned long val) |
305 | { | 309 | { |
306 | int i, nibbles = sizeof(val)*2; | 310 | int i, nibbles = sizeof(val)*2; |
@@ -334,12 +338,14 @@ static void __init prom_print_dec(unsigned long val) | |||
334 | call_prom("write", 3, 1, prom.stdout, buf+i, size); | 338 | call_prom("write", 3, 1, prom.stdout, buf+i, size); |
335 | } | 339 | } |
336 | 340 | ||
341 | __printf(1, 2) | ||
337 | static void __init prom_printf(const char *format, ...) | 342 | static void __init prom_printf(const char *format, ...) |
338 | { | 343 | { |
339 | const char *p, *q, *s; | 344 | const char *p, *q, *s; |
340 | va_list args; | 345 | va_list args; |
341 | unsigned long v; | 346 | unsigned long v; |
342 | long vs; | 347 | long vs; |
348 | int n = 0; | ||
343 | 349 | ||
344 | va_start(args, format); | 350 | va_start(args, format); |
345 | for (p = format; *p != 0; p = q) { | 351 | for (p = format; *p != 0; p = q) { |
@@ -358,6 +364,10 @@ static void __init prom_printf(const char *format, ...) | |||
358 | ++q; | 364 | ++q; |
359 | if (*q == 0) | 365 | if (*q == 0) |
360 | break; | 366 | break; |
367 | while (*q == 'l') { | ||
368 | ++q; | ||
369 | ++n; | ||
370 | } | ||
361 | switch (*q) { | 371 | switch (*q) { |
362 | case 's': | 372 | case 's': |
363 | ++q; | 373 | ++q; |
@@ -366,39 +376,55 @@ static void __init prom_printf(const char *format, ...) | |||
366 | break; | 376 | break; |
367 | case 'x': | 377 | case 'x': |
368 | ++q; | 378 | ++q; |
369 | v = va_arg(args, unsigned long); | 379 | switch (n) { |
380 | case 0: | ||
381 | v = va_arg(args, unsigned int); | ||
382 | break; | ||
383 | case 1: | ||
384 | v = va_arg(args, unsigned long); | ||
385 | break; | ||
386 | case 2: | ||
387 | default: | ||
388 | v = va_arg(args, unsigned long long); | ||
389 | break; | ||
390 | } | ||
370 | prom_print_hex(v); | 391 | prom_print_hex(v); |
371 | break; | 392 | break; |
372 | case 'd': | 393 | case 'u': |
373 | ++q; | 394 | ++q; |
374 | vs = va_arg(args, int); | 395 | switch (n) { |
375 | if (vs < 0) { | 396 | case 0: |
376 | prom_print("-"); | 397 | v = va_arg(args, unsigned int); |
377 | vs = -vs; | 398 | break; |
399 | case 1: | ||
400 | v = va_arg(args, unsigned long); | ||
401 | break; | ||
402 | case 2: | ||
403 | default: | ||
404 | v = va_arg(args, unsigned long long); | ||
405 | break; | ||
378 | } | 406 | } |
379 | prom_print_dec(vs); | 407 | prom_print_dec(v); |
380 | break; | 408 | break; |
381 | case 'l': | 409 | case 'd': |
382 | ++q; | 410 | ++q; |
383 | if (*q == 0) | 411 | switch (n) { |
412 | case 0: | ||
413 | vs = va_arg(args, int); | ||
384 | break; | 414 | break; |
385 | else if (*q == 'x') { | 415 | case 1: |
386 | ++q; | ||
387 | v = va_arg(args, unsigned long); | ||
388 | prom_print_hex(v); | ||
389 | } else if (*q == 'u') { /* '%lu' */ | ||
390 | ++q; | ||
391 | v = va_arg(args, unsigned long); | ||
392 | prom_print_dec(v); | ||
393 | } else if (*q == 'd') { /* %ld */ | ||
394 | ++q; | ||
395 | vs = va_arg(args, long); | 416 | vs = va_arg(args, long); |
396 | if (vs < 0) { | 417 | break; |
397 | prom_print("-"); | 418 | case 2: |
398 | vs = -vs; | 419 | default: |
399 | } | 420 | vs = va_arg(args, long long); |
400 | prom_print_dec(vs); | 421 | break; |
401 | } | 422 | } |
423 | if (vs < 0) { | ||
424 | prom_print("-"); | ||
425 | vs = -vs; | ||
426 | } | ||
427 | prom_print_dec(vs); | ||
402 | break; | 428 | break; |
403 | } | 429 | } |
404 | } | 430 | } |
@@ -1160,7 +1186,7 @@ static void __init prom_send_capabilities(void) | |||
1160 | */ | 1186 | */ |
1161 | 1187 | ||
1162 | cores = DIV_ROUND_UP(NR_CPUS, prom_count_smt_threads()); | 1188 | cores = DIV_ROUND_UP(NR_CPUS, prom_count_smt_threads()); |
1163 | prom_printf("Max number of cores passed to firmware: %lu (NR_CPUS = %lu)\n", | 1189 | prom_printf("Max number of cores passed to firmware: %u (NR_CPUS = %d)\n", |
1164 | cores, NR_CPUS); | 1190 | cores, NR_CPUS); |
1165 | 1191 | ||
1166 | ibm_architecture_vec.vec5.max_cpus = cpu_to_be32(cores); | 1192 | ibm_architecture_vec.vec5.max_cpus = cpu_to_be32(cores); |
@@ -1242,7 +1268,7 @@ static unsigned long __init alloc_up(unsigned long size, unsigned long align) | |||
1242 | 1268 | ||
1243 | if (align) | 1269 | if (align) |
1244 | base = _ALIGN_UP(base, align); | 1270 | base = _ALIGN_UP(base, align); |
1245 | prom_debug("alloc_up(%x, %x)\n", size, align); | 1271 | prom_debug("%s(%lx, %lx)\n", __func__, size, align); |
1246 | if (ram_top == 0) | 1272 | if (ram_top == 0) |
1247 | prom_panic("alloc_up() called with mem not initialized\n"); | 1273 | prom_panic("alloc_up() called with mem not initialized\n"); |
1248 | 1274 | ||
@@ -1253,7 +1279,7 @@ static unsigned long __init alloc_up(unsigned long size, unsigned long align) | |||
1253 | 1279 | ||
1254 | for(; (base + size) <= alloc_top; | 1280 | for(; (base + size) <= alloc_top; |
1255 | base = _ALIGN_UP(base + 0x100000, align)) { | 1281 | base = _ALIGN_UP(base + 0x100000, align)) { |
1256 | prom_debug(" trying: 0x%x\n\r", base); | 1282 | prom_debug(" trying: 0x%lx\n\r", base); |
1257 | addr = (unsigned long)prom_claim(base, size, 0); | 1283 | addr = (unsigned long)prom_claim(base, size, 0); |
1258 | if (addr != PROM_ERROR && addr != 0) | 1284 | if (addr != PROM_ERROR && addr != 0) |
1259 | break; | 1285 | break; |
@@ -1265,12 +1291,12 @@ static unsigned long __init alloc_up(unsigned long size, unsigned long align) | |||
1265 | return 0; | 1291 | return 0; |
1266 | alloc_bottom = addr + size; | 1292 | alloc_bottom = addr + size; |
1267 | 1293 | ||
1268 | prom_debug(" -> %x\n", addr); | 1294 | prom_debug(" -> %lx\n", addr); |
1269 | prom_debug(" alloc_bottom : %x\n", alloc_bottom); | 1295 | prom_debug(" alloc_bottom : %lx\n", alloc_bottom); |
1270 | prom_debug(" alloc_top : %x\n", alloc_top); | 1296 | prom_debug(" alloc_top : %lx\n", alloc_top); |
1271 | prom_debug(" alloc_top_hi : %x\n", alloc_top_high); | 1297 | prom_debug(" alloc_top_hi : %lx\n", alloc_top_high); |
1272 | prom_debug(" rmo_top : %x\n", rmo_top); | 1298 | prom_debug(" rmo_top : %lx\n", rmo_top); |
1273 | prom_debug(" ram_top : %x\n", ram_top); | 1299 | prom_debug(" ram_top : %lx\n", ram_top); |
1274 | 1300 | ||
1275 | return addr; | 1301 | return addr; |
1276 | } | 1302 | } |
@@ -1285,7 +1311,7 @@ static unsigned long __init alloc_down(unsigned long size, unsigned long align, | |||
1285 | { | 1311 | { |
1286 | unsigned long base, addr = 0; | 1312 | unsigned long base, addr = 0; |
1287 | 1313 | ||
1288 | prom_debug("alloc_down(%x, %x, %s)\n", size, align, | 1314 | prom_debug("%s(%lx, %lx, %s)\n", __func__, size, align, |
1289 | highmem ? "(high)" : "(low)"); | 1315 | highmem ? "(high)" : "(low)"); |
1290 | if (ram_top == 0) | 1316 | if (ram_top == 0) |
1291 | prom_panic("alloc_down() called with mem not initialized\n"); | 1317 | prom_panic("alloc_down() called with mem not initialized\n"); |
@@ -1313,7 +1339,7 @@ static unsigned long __init alloc_down(unsigned long size, unsigned long align, | |||
1313 | base = _ALIGN_DOWN(alloc_top - size, align); | 1339 | base = _ALIGN_DOWN(alloc_top - size, align); |
1314 | for (; base > alloc_bottom; | 1340 | for (; base > alloc_bottom; |
1315 | base = _ALIGN_DOWN(base - 0x100000, align)) { | 1341 | base = _ALIGN_DOWN(base - 0x100000, align)) { |
1316 | prom_debug(" trying: 0x%x\n\r", base); | 1342 | prom_debug(" trying: 0x%lx\n\r", base); |
1317 | addr = (unsigned long)prom_claim(base, size, 0); | 1343 | addr = (unsigned long)prom_claim(base, size, 0); |
1318 | if (addr != PROM_ERROR && addr != 0) | 1344 | if (addr != PROM_ERROR && addr != 0) |
1319 | break; | 1345 | break; |
@@ -1324,12 +1350,12 @@ static unsigned long __init alloc_down(unsigned long size, unsigned long align, | |||
1324 | alloc_top = addr; | 1350 | alloc_top = addr; |
1325 | 1351 | ||
1326 | bail: | 1352 | bail: |
1327 | prom_debug(" -> %x\n", addr); | 1353 | prom_debug(" -> %lx\n", addr); |
1328 | prom_debug(" alloc_bottom : %x\n", alloc_bottom); | 1354 | prom_debug(" alloc_bottom : %lx\n", alloc_bottom); |
1329 | prom_debug(" alloc_top : %x\n", alloc_top); | 1355 | prom_debug(" alloc_top : %lx\n", alloc_top); |
1330 | prom_debug(" alloc_top_hi : %x\n", alloc_top_high); | 1356 | prom_debug(" alloc_top_hi : %lx\n", alloc_top_high); |
1331 | prom_debug(" rmo_top : %x\n", rmo_top); | 1357 | prom_debug(" rmo_top : %lx\n", rmo_top); |
1332 | prom_debug(" ram_top : %x\n", ram_top); | 1358 | prom_debug(" ram_top : %lx\n", ram_top); |
1333 | 1359 | ||
1334 | return addr; | 1360 | return addr; |
1335 | } | 1361 | } |
@@ -1455,7 +1481,7 @@ static void __init prom_init_mem(void) | |||
1455 | 1481 | ||
1456 | if (size == 0) | 1482 | if (size == 0) |
1457 | continue; | 1483 | continue; |
1458 | prom_debug(" %x %x\n", base, size); | 1484 | prom_debug(" %lx %lx\n", base, size); |
1459 | if (base == 0 && (of_platform & PLATFORM_LPAR)) | 1485 | if (base == 0 && (of_platform & PLATFORM_LPAR)) |
1460 | rmo_top = size; | 1486 | rmo_top = size; |
1461 | if ((base + size) > ram_top) | 1487 | if ((base + size) > ram_top) |
@@ -1475,12 +1501,12 @@ static void __init prom_init_mem(void) | |||
1475 | 1501 | ||
1476 | if (prom_memory_limit) { | 1502 | if (prom_memory_limit) { |
1477 | if (prom_memory_limit <= alloc_bottom) { | 1503 | if (prom_memory_limit <= alloc_bottom) { |
1478 | prom_printf("Ignoring mem=%x <= alloc_bottom.\n", | 1504 | prom_printf("Ignoring mem=%lx <= alloc_bottom.\n", |
1479 | prom_memory_limit); | 1505 | prom_memory_limit); |
1480 | prom_memory_limit = 0; | 1506 | prom_memory_limit = 0; |
1481 | } else if (prom_memory_limit >= ram_top) { | 1507 | } else if (prom_memory_limit >= ram_top) { |
1482 | prom_printf("Ignoring mem=%x >= ram_top.\n", | 1508 | prom_printf("Ignoring mem=%lx >= ram_top.\n", |
1483 | prom_memory_limit); | 1509 | prom_memory_limit); |
1484 | prom_memory_limit = 0; | 1510 | prom_memory_limit = 0; |
1485 | } else { | 1511 | } else { |
1486 | ram_top = prom_memory_limit; | 1512 | ram_top = prom_memory_limit; |
@@ -1512,12 +1538,13 @@ static void __init prom_init_mem(void) | |||
1512 | alloc_bottom = PAGE_ALIGN(prom_initrd_end); | 1538 | alloc_bottom = PAGE_ALIGN(prom_initrd_end); |
1513 | 1539 | ||
1514 | prom_printf("memory layout at init:\n"); | 1540 | prom_printf("memory layout at init:\n"); |
1515 | prom_printf(" memory_limit : %x (16 MB aligned)\n", prom_memory_limit); | 1541 | prom_printf(" memory_limit : %lx (16 MB aligned)\n", |
1516 | prom_printf(" alloc_bottom : %x\n", alloc_bottom); | 1542 | prom_memory_limit); |
1517 | prom_printf(" alloc_top : %x\n", alloc_top); | 1543 | prom_printf(" alloc_bottom : %lx\n", alloc_bottom); |
1518 | prom_printf(" alloc_top_hi : %x\n", alloc_top_high); | 1544 | prom_printf(" alloc_top : %lx\n", alloc_top); |
1519 | prom_printf(" rmo_top : %x\n", rmo_top); | 1545 | prom_printf(" alloc_top_hi : %lx\n", alloc_top_high); |
1520 | prom_printf(" ram_top : %x\n", ram_top); | 1546 | prom_printf(" rmo_top : %lx\n", rmo_top); |
1547 | prom_printf(" ram_top : %lx\n", ram_top); | ||
1521 | } | 1548 | } |
1522 | 1549 | ||
1523 | static void __init prom_close_stdin(void) | 1550 | static void __init prom_close_stdin(void) |
@@ -1578,7 +1605,7 @@ static void __init prom_instantiate_opal(void) | |||
1578 | return; | 1605 | return; |
1579 | } | 1606 | } |
1580 | 1607 | ||
1581 | prom_printf("instantiating opal at 0x%x...", base); | 1608 | prom_printf("instantiating opal at 0x%llx...", base); |
1582 | 1609 | ||
1583 | if (call_prom_ret("call-method", 4, 3, rets, | 1610 | if (call_prom_ret("call-method", 4, 3, rets, |
1584 | ADDR("load-opal-runtime"), | 1611 | ADDR("load-opal-runtime"), |
@@ -1594,10 +1621,10 @@ static void __init prom_instantiate_opal(void) | |||
1594 | 1621 | ||
1595 | reserve_mem(base, size); | 1622 | reserve_mem(base, size); |
1596 | 1623 | ||
1597 | prom_debug("opal base = 0x%x\n", base); | 1624 | prom_debug("opal base = 0x%llx\n", base); |
1598 | prom_debug("opal align = 0x%x\n", align); | 1625 | prom_debug("opal align = 0x%llx\n", align); |
1599 | prom_debug("opal entry = 0x%x\n", entry); | 1626 | prom_debug("opal entry = 0x%llx\n", entry); |
1600 | prom_debug("opal size = 0x%x\n", (long)size); | 1627 | prom_debug("opal size = 0x%llx\n", size); |
1601 | 1628 | ||
1602 | prom_setprop(opal_node, "/ibm,opal", "opal-base-address", | 1629 | prom_setprop(opal_node, "/ibm,opal", "opal-base-address", |
1603 | &base, sizeof(base)); | 1630 | &base, sizeof(base)); |
@@ -1674,7 +1701,7 @@ static void __init prom_instantiate_rtas(void) | |||
1674 | 1701 | ||
1675 | prom_debug("rtas base = 0x%x\n", base); | 1702 | prom_debug("rtas base = 0x%x\n", base); |
1676 | prom_debug("rtas entry = 0x%x\n", entry); | 1703 | prom_debug("rtas entry = 0x%x\n", entry); |
1677 | prom_debug("rtas size = 0x%x\n", (long)size); | 1704 | prom_debug("rtas size = 0x%x\n", size); |
1678 | 1705 | ||
1679 | prom_debug("prom_instantiate_rtas: end...\n"); | 1706 | prom_debug("prom_instantiate_rtas: end...\n"); |
1680 | } | 1707 | } |
@@ -1732,7 +1759,7 @@ static void __init prom_instantiate_sml(void) | |||
1732 | if (base == 0) | 1759 | if (base == 0) |
1733 | prom_panic("Could not allocate memory for sml\n"); | 1760 | prom_panic("Could not allocate memory for sml\n"); |
1734 | 1761 | ||
1735 | prom_printf("instantiating sml at 0x%x...", base); | 1762 | prom_printf("instantiating sml at 0x%llx...", base); |
1736 | 1763 | ||
1737 | memset((void *)base, 0, size); | 1764 | memset((void *)base, 0, size); |
1738 | 1765 | ||
@@ -1751,8 +1778,8 @@ static void __init prom_instantiate_sml(void) | |||
1751 | prom_setprop(ibmvtpm_node, "/vdevice/vtpm", "linux,sml-size", | 1778 | prom_setprop(ibmvtpm_node, "/vdevice/vtpm", "linux,sml-size", |
1752 | &size, sizeof(size)); | 1779 | &size, sizeof(size)); |
1753 | 1780 | ||
1754 | prom_debug("sml base = 0x%x\n", base); | 1781 | prom_debug("sml base = 0x%llx\n", base); |
1755 | prom_debug("sml size = 0x%x\n", (long)size); | 1782 | prom_debug("sml size = 0x%x\n", size); |
1756 | 1783 | ||
1757 | prom_debug("prom_instantiate_sml: end...\n"); | 1784 | prom_debug("prom_instantiate_sml: end...\n"); |
1758 | } | 1785 | } |
@@ -1845,7 +1872,7 @@ static void __init prom_initialize_tce_table(void) | |||
1845 | 1872 | ||
1846 | prom_debug("TCE table: %s\n", path); | 1873 | prom_debug("TCE table: %s\n", path); |
1847 | prom_debug("\tnode = 0x%x\n", node); | 1874 | prom_debug("\tnode = 0x%x\n", node); |
1848 | prom_debug("\tbase = 0x%x\n", base); | 1875 | prom_debug("\tbase = 0x%llx\n", base); |
1849 | prom_debug("\tsize = 0x%x\n", minsize); | 1876 | prom_debug("\tsize = 0x%x\n", minsize); |
1850 | 1877 | ||
1851 | /* Initialize the table to have a one-to-one mapping | 1878 | /* Initialize the table to have a one-to-one mapping |
@@ -1932,12 +1959,12 @@ static void __init prom_hold_cpus(void) | |||
1932 | } | 1959 | } |
1933 | 1960 | ||
1934 | prom_debug("prom_hold_cpus: start...\n"); | 1961 | prom_debug("prom_hold_cpus: start...\n"); |
1935 | prom_debug(" 1) spinloop = 0x%x\n", (unsigned long)spinloop); | 1962 | prom_debug(" 1) spinloop = 0x%lx\n", (unsigned long)spinloop); |
1936 | prom_debug(" 1) *spinloop = 0x%x\n", *spinloop); | 1963 | prom_debug(" 1) *spinloop = 0x%lx\n", *spinloop); |
1937 | prom_debug(" 1) acknowledge = 0x%x\n", | 1964 | prom_debug(" 1) acknowledge = 0x%lx\n", |
1938 | (unsigned long)acknowledge); | 1965 | (unsigned long)acknowledge); |
1939 | prom_debug(" 1) *acknowledge = 0x%x\n", *acknowledge); | 1966 | prom_debug(" 1) *acknowledge = 0x%lx\n", *acknowledge); |
1940 | prom_debug(" 1) secondary_hold = 0x%x\n", secondary_hold); | 1967 | prom_debug(" 1) secondary_hold = 0x%lx\n", secondary_hold); |
1941 | 1968 | ||
1942 | /* Set the common spinloop variable, so all of the secondary cpus | 1969 | /* Set the common spinloop variable, so all of the secondary cpus |
1943 | * will block when they are awakened from their OF spinloop. | 1970 | * will block when they are awakened from their OF spinloop. |
@@ -1965,7 +1992,7 @@ static void __init prom_hold_cpus(void) | |||
1965 | prom_getprop(node, "reg", ®, sizeof(reg)); | 1992 | prom_getprop(node, "reg", ®, sizeof(reg)); |
1966 | cpu_no = be32_to_cpu(reg); | 1993 | cpu_no = be32_to_cpu(reg); |
1967 | 1994 | ||
1968 | prom_debug("cpu hw idx = %lu\n", cpu_no); | 1995 | prom_debug("cpu hw idx = %u\n", cpu_no); |
1969 | 1996 | ||
1970 | /* Init the acknowledge var which will be reset by | 1997 | /* Init the acknowledge var which will be reset by |
1971 | * the secondary cpu when it awakens from its OF | 1998 | * the secondary cpu when it awakens from its OF |
@@ -1975,7 +2002,7 @@ static void __init prom_hold_cpus(void) | |||
1975 | 2002 | ||
1976 | if (cpu_no != prom.cpu) { | 2003 | if (cpu_no != prom.cpu) { |
1977 | /* Primary Thread of non-boot cpu or any thread */ | 2004 | /* Primary Thread of non-boot cpu or any thread */ |
1978 | prom_printf("starting cpu hw idx %lu... ", cpu_no); | 2005 | prom_printf("starting cpu hw idx %u... ", cpu_no); |
1979 | call_prom("start-cpu", 3, 0, node, | 2006 | call_prom("start-cpu", 3, 0, node, |
1980 | secondary_hold, cpu_no); | 2007 | secondary_hold, cpu_no); |
1981 | 2008 | ||
@@ -1986,11 +2013,11 @@ static void __init prom_hold_cpus(void) | |||
1986 | if (*acknowledge == cpu_no) | 2013 | if (*acknowledge == cpu_no) |
1987 | prom_printf("done\n"); | 2014 | prom_printf("done\n"); |
1988 | else | 2015 | else |
1989 | prom_printf("failed: %x\n", *acknowledge); | 2016 | prom_printf("failed: %lx\n", *acknowledge); |
1990 | } | 2017 | } |
1991 | #ifdef CONFIG_SMP | 2018 | #ifdef CONFIG_SMP |
1992 | else | 2019 | else |
1993 | prom_printf("boot cpu hw idx %lu\n", cpu_no); | 2020 | prom_printf("boot cpu hw idx %u\n", cpu_no); |
1994 | #endif /* CONFIG_SMP */ | 2021 | #endif /* CONFIG_SMP */ |
1995 | } | 2022 | } |
1996 | 2023 | ||
@@ -2268,7 +2295,7 @@ static void __init *make_room(unsigned long *mem_start, unsigned long *mem_end, | |||
2268 | while ((*mem_start + needed) > *mem_end) { | 2295 | while ((*mem_start + needed) > *mem_end) { |
2269 | unsigned long room, chunk; | 2296 | unsigned long room, chunk; |
2270 | 2297 | ||
2271 | prom_debug("Chunk exhausted, claiming more at %x...\n", | 2298 | prom_debug("Chunk exhausted, claiming more at %lx...\n", |
2272 | alloc_bottom); | 2299 | alloc_bottom); |
2273 | room = alloc_top - alloc_bottom; | 2300 | room = alloc_top - alloc_bottom; |
2274 | if (room > DEVTREE_CHUNK_SIZE) | 2301 | if (room > DEVTREE_CHUNK_SIZE) |
@@ -2494,7 +2521,7 @@ static void __init flatten_device_tree(void) | |||
2494 | room = alloc_top - alloc_bottom - 0x4000; | 2521 | room = alloc_top - alloc_bottom - 0x4000; |
2495 | if (room > DEVTREE_CHUNK_SIZE) | 2522 | if (room > DEVTREE_CHUNK_SIZE) |
2496 | room = DEVTREE_CHUNK_SIZE; | 2523 | room = DEVTREE_CHUNK_SIZE; |
2497 | prom_debug("starting device tree allocs at %x\n", alloc_bottom); | 2524 | prom_debug("starting device tree allocs at %lx\n", alloc_bottom); |
2498 | 2525 | ||
2499 | /* Now try to claim that */ | 2526 | /* Now try to claim that */ |
2500 | mem_start = (unsigned long)alloc_up(room, PAGE_SIZE); | 2527 | mem_start = (unsigned long)alloc_up(room, PAGE_SIZE); |
@@ -2557,7 +2584,7 @@ static void __init flatten_device_tree(void) | |||
2557 | int i; | 2584 | int i; |
2558 | prom_printf("reserved memory map:\n"); | 2585 | prom_printf("reserved memory map:\n"); |
2559 | for (i = 0; i < mem_reserve_cnt; i++) | 2586 | for (i = 0; i < mem_reserve_cnt; i++) |
2560 | prom_printf(" %x - %x\n", | 2587 | prom_printf(" %llx - %llx\n", |
2561 | be64_to_cpu(mem_reserve_map[i].base), | 2588 | be64_to_cpu(mem_reserve_map[i].base), |
2562 | be64_to_cpu(mem_reserve_map[i].size)); | 2589 | be64_to_cpu(mem_reserve_map[i].size)); |
2563 | } | 2590 | } |
@@ -2567,9 +2594,9 @@ static void __init flatten_device_tree(void) | |||
2567 | */ | 2594 | */ |
2568 | mem_reserve_cnt = MEM_RESERVE_MAP_SIZE; | 2595 | mem_reserve_cnt = MEM_RESERVE_MAP_SIZE; |
2569 | 2596 | ||
2570 | prom_printf("Device tree strings 0x%x -> 0x%x\n", | 2597 | prom_printf("Device tree strings 0x%lx -> 0x%lx\n", |
2571 | dt_string_start, dt_string_end); | 2598 | dt_string_start, dt_string_end); |
2572 | prom_printf("Device tree struct 0x%x -> 0x%x\n", | 2599 | prom_printf("Device tree struct 0x%lx -> 0x%lx\n", |
2573 | dt_struct_start, dt_struct_end); | 2600 | dt_struct_start, dt_struct_end); |
2574 | } | 2601 | } |
2575 | 2602 | ||
@@ -3001,7 +3028,7 @@ static void __init prom_find_boot_cpu(void) | |||
3001 | prom_getprop(cpu_pkg, "reg", &rval, sizeof(rval)); | 3028 | prom_getprop(cpu_pkg, "reg", &rval, sizeof(rval)); |
3002 | prom.cpu = be32_to_cpu(rval); | 3029 | prom.cpu = be32_to_cpu(rval); |
3003 | 3030 | ||
3004 | prom_debug("Booting CPU hw index = %lu\n", prom.cpu); | 3031 | prom_debug("Booting CPU hw index = %d\n", prom.cpu); |
3005 | } | 3032 | } |
3006 | 3033 | ||
3007 | static void __init prom_check_initrd(unsigned long r3, unsigned long r4) | 3034 | static void __init prom_check_initrd(unsigned long r3, unsigned long r4) |
@@ -3023,8 +3050,8 @@ static void __init prom_check_initrd(unsigned long r3, unsigned long r4) | |||
3023 | reserve_mem(prom_initrd_start, | 3050 | reserve_mem(prom_initrd_start, |
3024 | prom_initrd_end - prom_initrd_start); | 3051 | prom_initrd_end - prom_initrd_start); |
3025 | 3052 | ||
3026 | prom_debug("initrd_start=0x%x\n", prom_initrd_start); | 3053 | prom_debug("initrd_start=0x%lx\n", prom_initrd_start); |
3027 | prom_debug("initrd_end=0x%x\n", prom_initrd_end); | 3054 | prom_debug("initrd_end=0x%lx\n", prom_initrd_end); |
3028 | } | 3055 | } |
3029 | #endif /* CONFIG_BLK_DEV_INITRD */ | 3056 | #endif /* CONFIG_BLK_DEV_INITRD */ |
3030 | } | 3057 | } |
@@ -3277,7 +3304,7 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, | |||
3277 | /* Don't print anything after quiesce under OPAL, it crashes OFW */ | 3304 | /* Don't print anything after quiesce under OPAL, it crashes OFW */ |
3278 | if (of_platform != PLATFORM_OPAL) { | 3305 | if (of_platform != PLATFORM_OPAL) { |
3279 | prom_printf("Booting Linux via __start() @ 0x%lx ...\n", kbase); | 3306 | prom_printf("Booting Linux via __start() @ 0x%lx ...\n", kbase); |
3280 | prom_debug("->dt_header_start=0x%x\n", hdr); | 3307 | prom_debug("->dt_header_start=0x%lx\n", hdr); |
3281 | } | 3308 | } |
3282 | 3309 | ||
3283 | #ifdef CONFIG_PPC32 | 3310 | #ifdef CONFIG_PPC32 |
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index d23cf632edf0..9667666eb18e 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c | |||
@@ -2443,6 +2443,7 @@ static int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, | |||
2443 | /* Create a new breakpoint request if one doesn't exist already */ | 2443 | /* Create a new breakpoint request if one doesn't exist already */ |
2444 | hw_breakpoint_init(&attr); | 2444 | hw_breakpoint_init(&attr); |
2445 | attr.bp_addr = hw_brk.address; | 2445 | attr.bp_addr = hw_brk.address; |
2446 | attr.bp_len = 8; | ||
2446 | arch_bp_generic_fields(hw_brk.type, | 2447 | arch_bp_generic_fields(hw_brk.type, |
2447 | &attr.bp_type); | 2448 | &attr.bp_type); |
2448 | 2449 | ||
@@ -3081,27 +3082,19 @@ long arch_ptrace(struct task_struct *child, long request, | |||
3081 | #endif /* CONFIG_HAVE_HW_BREAKPOINT */ | 3082 | #endif /* CONFIG_HAVE_HW_BREAKPOINT */ |
3082 | #endif /* CONFIG_PPC_ADV_DEBUG_REGS */ | 3083 | #endif /* CONFIG_PPC_ADV_DEBUG_REGS */ |
3083 | 3084 | ||
3084 | if (!access_ok(VERIFY_WRITE, datavp, | 3085 | if (copy_to_user(datavp, &dbginfo, |
3085 | sizeof(struct ppc_debug_info))) | 3086 | sizeof(struct ppc_debug_info))) |
3086 | return -EFAULT; | 3087 | return -EFAULT; |
3087 | ret = __copy_to_user(datavp, &dbginfo, | 3088 | return 0; |
3088 | sizeof(struct ppc_debug_info)) ? | ||
3089 | -EFAULT : 0; | ||
3090 | break; | ||
3091 | } | 3089 | } |
3092 | 3090 | ||
3093 | case PPC_PTRACE_SETHWDEBUG: { | 3091 | case PPC_PTRACE_SETHWDEBUG: { |
3094 | struct ppc_hw_breakpoint bp_info; | 3092 | struct ppc_hw_breakpoint bp_info; |
3095 | 3093 | ||
3096 | if (!access_ok(VERIFY_READ, datavp, | 3094 | if (copy_from_user(&bp_info, datavp, |
3097 | sizeof(struct ppc_hw_breakpoint))) | 3095 | sizeof(struct ppc_hw_breakpoint))) |
3098 | return -EFAULT; | 3096 | return -EFAULT; |
3099 | ret = __copy_from_user(&bp_info, datavp, | 3097 | return ppc_set_hwdebug(child, &bp_info); |
3100 | sizeof(struct ppc_hw_breakpoint)) ? | ||
3101 | -EFAULT : 0; | ||
3102 | if (!ret) | ||
3103 | ret = ppc_set_hwdebug(child, &bp_info); | ||
3104 | break; | ||
3105 | } | 3098 | } |
3106 | 3099 | ||
3107 | case PPC_PTRACE_DELHWDEBUG: { | 3100 | case PPC_PTRACE_DELHWDEBUG: { |
diff --git a/arch/powerpc/kernel/rtas-proc.c b/arch/powerpc/kernel/rtas-proc.c index d49063d0baa4..487dcd8da4de 100644 --- a/arch/powerpc/kernel/rtas-proc.c +++ b/arch/powerpc/kernel/rtas-proc.c | |||
@@ -256,7 +256,7 @@ static int __init proc_rtas_init(void) | |||
256 | 256 | ||
257 | __initcall(proc_rtas_init); | 257 | __initcall(proc_rtas_init); |
258 | 258 | ||
259 | static int parse_number(const char __user *p, size_t count, unsigned long *val) | 259 | static int parse_number(const char __user *p, size_t count, u64 *val) |
260 | { | 260 | { |
261 | char buf[40]; | 261 | char buf[40]; |
262 | char *end; | 262 | char *end; |
@@ -269,7 +269,7 @@ static int parse_number(const char __user *p, size_t count, unsigned long *val) | |||
269 | 269 | ||
270 | buf[count] = 0; | 270 | buf[count] = 0; |
271 | 271 | ||
272 | *val = simple_strtoul(buf, &end, 10); | 272 | *val = simple_strtoull(buf, &end, 10); |
273 | if (*end && *end != '\n') | 273 | if (*end && *end != '\n') |
274 | return -EINVAL; | 274 | return -EINVAL; |
275 | 275 | ||
@@ -283,17 +283,17 @@ static ssize_t ppc_rtas_poweron_write(struct file *file, | |||
283 | const char __user *buf, size_t count, loff_t *ppos) | 283 | const char __user *buf, size_t count, loff_t *ppos) |
284 | { | 284 | { |
285 | struct rtc_time tm; | 285 | struct rtc_time tm; |
286 | unsigned long nowtime; | 286 | time64_t nowtime; |
287 | int error = parse_number(buf, count, &nowtime); | 287 | int error = parse_number(buf, count, &nowtime); |
288 | if (error) | 288 | if (error) |
289 | return error; | 289 | return error; |
290 | 290 | ||
291 | power_on_time = nowtime; /* save the time */ | 291 | power_on_time = nowtime; /* save the time */ |
292 | 292 | ||
293 | to_tm(nowtime, &tm); | 293 | rtc_time64_to_tm(nowtime, &tm); |
294 | 294 | ||
295 | error = rtas_call(rtas_token("set-time-for-power-on"), 7, 1, NULL, | 295 | error = rtas_call(rtas_token("set-time-for-power-on"), 7, 1, NULL, |
296 | tm.tm_year, tm.tm_mon, tm.tm_mday, | 296 | tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, |
297 | tm.tm_hour, tm.tm_min, tm.tm_sec, 0 /* nano */); | 297 | tm.tm_hour, tm.tm_min, tm.tm_sec, 0 /* nano */); |
298 | if (error) | 298 | if (error) |
299 | printk(KERN_WARNING "error: setting poweron time returned: %s\n", | 299 | printk(KERN_WARNING "error: setting poweron time returned: %s\n", |
@@ -349,14 +349,14 @@ static ssize_t ppc_rtas_clock_write(struct file *file, | |||
349 | const char __user *buf, size_t count, loff_t *ppos) | 349 | const char __user *buf, size_t count, loff_t *ppos) |
350 | { | 350 | { |
351 | struct rtc_time tm; | 351 | struct rtc_time tm; |
352 | unsigned long nowtime; | 352 | time64_t nowtime; |
353 | int error = parse_number(buf, count, &nowtime); | 353 | int error = parse_number(buf, count, &nowtime); |
354 | if (error) | 354 | if (error) |
355 | return error; | 355 | return error; |
356 | 356 | ||
357 | to_tm(nowtime, &tm); | 357 | rtc_time64_to_tm(nowtime, &tm); |
358 | error = rtas_call(rtas_token("set-time-of-day"), 7, 1, NULL, | 358 | error = rtas_call(rtas_token("set-time-of-day"), 7, 1, NULL, |
359 | tm.tm_year, tm.tm_mon, tm.tm_mday, | 359 | tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, |
360 | tm.tm_hour, tm.tm_min, tm.tm_sec, 0); | 360 | tm.tm_hour, tm.tm_min, tm.tm_sec, 0); |
361 | if (error) | 361 | if (error) |
362 | printk(KERN_WARNING "error: setting the clock returned: %s\n", | 362 | printk(KERN_WARNING "error: setting the clock returned: %s\n", |
@@ -377,8 +377,8 @@ static int ppc_rtas_clock_show(struct seq_file *m, void *v) | |||
377 | unsigned int year, mon, day, hour, min, sec; | 377 | unsigned int year, mon, day, hour, min, sec; |
378 | year = ret[0]; mon = ret[1]; day = ret[2]; | 378 | year = ret[0]; mon = ret[1]; day = ret[2]; |
379 | hour = ret[3]; min = ret[4]; sec = ret[5]; | 379 | hour = ret[3]; min = ret[4]; sec = ret[5]; |
380 | seq_printf(m, "%lu\n", | 380 | seq_printf(m, "%lld\n", |
381 | mktime(year, mon, day, hour, min, sec)); | 381 | mktime64(year, mon, day, hour, min, sec)); |
382 | } | 382 | } |
383 | return 0; | 383 | return 0; |
384 | } | 384 | } |
@@ -504,7 +504,7 @@ static void ppc_rtas_process_sensor(struct seq_file *m, | |||
504 | "EPOW power off" }; | 504 | "EPOW power off" }; |
505 | const char * battery_cyclestate[] = { "None", "In progress", | 505 | const char * battery_cyclestate[] = { "None", "In progress", |
506 | "Requested" }; | 506 | "Requested" }; |
507 | const char * battery_charging[] = { "Charging", "Discharching", | 507 | const char * battery_charging[] = { "Charging", "Discharging", |
508 | "No current flow" }; | 508 | "No current flow" }; |
509 | const char * ibm_drconnector[] = { "Empty", "Present", "Unusable", | 509 | const char * ibm_drconnector[] = { "Empty", "Present", "Unusable", |
510 | "Exchange" }; | 510 | "Exchange" }; |
@@ -707,7 +707,7 @@ static void get_location_code(struct seq_file *m, struct individual_sensor *s, | |||
707 | static ssize_t ppc_rtas_tone_freq_write(struct file *file, | 707 | static ssize_t ppc_rtas_tone_freq_write(struct file *file, |
708 | const char __user *buf, size_t count, loff_t *ppos) | 708 | const char __user *buf, size_t count, loff_t *ppos) |
709 | { | 709 | { |
710 | unsigned long freq; | 710 | u64 freq; |
711 | int error = parse_number(buf, count, &freq); | 711 | int error = parse_number(buf, count, &freq); |
712 | if (error) | 712 | if (error) |
713 | return error; | 713 | return error; |
@@ -732,7 +732,7 @@ static int ppc_rtas_tone_freq_show(struct seq_file *m, void *v) | |||
732 | static ssize_t ppc_rtas_tone_volume_write(struct file *file, | 732 | static ssize_t ppc_rtas_tone_volume_write(struct file *file, |
733 | const char __user *buf, size_t count, loff_t *ppos) | 733 | const char __user *buf, size_t count, loff_t *ppos) |
734 | { | 734 | { |
735 | unsigned long volume; | 735 | u64 volume; |
736 | int error = parse_number(buf, count, &volume); | 736 | int error = parse_number(buf, count, &volume); |
737 | if (error) | 737 | if (error) |
738 | return error; | 738 | return error; |
diff --git a/arch/powerpc/kernel/rtas-rtc.c b/arch/powerpc/kernel/rtas-rtc.c index 49600985c7ef..a28239b8b0c0 100644 --- a/arch/powerpc/kernel/rtas-rtc.c +++ b/arch/powerpc/kernel/rtas-rtc.c | |||
@@ -13,7 +13,7 @@ | |||
13 | 13 | ||
14 | #define MAX_RTC_WAIT 5000 /* 5 sec */ | 14 | #define MAX_RTC_WAIT 5000 /* 5 sec */ |
15 | #define RTAS_CLOCK_BUSY (-2) | 15 | #define RTAS_CLOCK_BUSY (-2) |
16 | unsigned long __init rtas_get_boot_time(void) | 16 | time64_t __init rtas_get_boot_time(void) |
17 | { | 17 | { |
18 | int ret[8]; | 18 | int ret[8]; |
19 | int error; | 19 | int error; |
@@ -38,7 +38,7 @@ unsigned long __init rtas_get_boot_time(void) | |||
38 | return 0; | 38 | return 0; |
39 | } | 39 | } |
40 | 40 | ||
41 | return mktime(ret[0], ret[1], ret[2], ret[3], ret[4], ret[5]); | 41 | return mktime64(ret[0], ret[1], ret[2], ret[3], ret[4], ret[5]); |
42 | } | 42 | } |
43 | 43 | ||
44 | /* NOTE: get_rtc_time will get an error if executed in interrupt context | 44 | /* NOTE: get_rtc_time will get an error if executed in interrupt context |
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 3f1c4fcbe0aa..7fb9f83dcde8 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/memblock.h> | 26 | #include <linux/memblock.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/reboot.h> | 28 | #include <linux/reboot.h> |
29 | #include <linux/syscalls.h> | ||
29 | 30 | ||
30 | #include <asm/prom.h> | 31 | #include <asm/prom.h> |
31 | #include <asm/rtas.h> | 32 | #include <asm/rtas.h> |
@@ -1050,7 +1051,10 @@ struct pseries_errorlog *get_pseries_errorlog(struct rtas_error_log *log, | |||
1050 | } | 1051 | } |
1051 | 1052 | ||
1052 | /* We assume to be passed big endian arguments */ | 1053 | /* We assume to be passed big endian arguments */ |
1053 | asmlinkage int ppc_rtas(struct rtas_args __user *uargs) | 1054 | #pragma GCC diagnostic push |
1055 | #pragma GCC diagnostic ignored "-Wpragmas" | ||
1056 | #pragma GCC diagnostic ignored "-Wattribute-alias" | ||
1057 | SYSCALL_DEFINE1(rtas, struct rtas_args __user *, uargs) | ||
1054 | { | 1058 | { |
1055 | struct rtas_args args; | 1059 | struct rtas_args args; |
1056 | unsigned long flags; | 1060 | unsigned long flags; |
@@ -1136,6 +1140,7 @@ asmlinkage int ppc_rtas(struct rtas_args __user *uargs) | |||
1136 | 1140 | ||
1137 | return 0; | 1141 | return 0; |
1138 | } | 1142 | } |
1143 | #pragma GCC diagnostic pop | ||
1139 | 1144 | ||
1140 | /* | 1145 | /* |
1141 | * Call early during boot, before mem init, to retrieve the RTAS | 1146 | * Call early during boot, before mem init, to retrieve the RTAS |
diff --git a/arch/powerpc/kernel/security.c b/arch/powerpc/kernel/security.c index b98a722da915..a8b277362931 100644 --- a/arch/powerpc/kernel/security.c +++ b/arch/powerpc/kernel/security.c | |||
@@ -10,10 +10,78 @@ | |||
10 | 10 | ||
11 | #include <asm/debugfs.h> | 11 | #include <asm/debugfs.h> |
12 | #include <asm/security_features.h> | 12 | #include <asm/security_features.h> |
13 | #include <asm/setup.h> | ||
13 | 14 | ||
14 | 15 | ||
15 | unsigned long powerpc_security_features __read_mostly = SEC_FTR_DEFAULT; | 16 | unsigned long powerpc_security_features __read_mostly = SEC_FTR_DEFAULT; |
16 | 17 | ||
18 | bool barrier_nospec_enabled; | ||
19 | |||
20 | static void enable_barrier_nospec(bool enable) | ||
21 | { | ||
22 | barrier_nospec_enabled = enable; | ||
23 | do_barrier_nospec_fixups(enable); | ||
24 | } | ||
25 | |||
26 | void setup_barrier_nospec(void) | ||
27 | { | ||
28 | bool enable; | ||
29 | |||
30 | /* | ||
31 | * It would make sense to check SEC_FTR_SPEC_BAR_ORI31 below as well. | ||
32 | * But there's a good reason not to. The two flags we check below are | ||
33 | * both are enabled by default in the kernel, so if the hcall is not | ||
34 | * functional they will be enabled. | ||
35 | * On a system where the host firmware has been updated (so the ori | ||
36 | * functions as a barrier), but on which the hypervisor (KVM/Qemu) has | ||
37 | * not been updated, we would like to enable the barrier. Dropping the | ||
38 | * check for SEC_FTR_SPEC_BAR_ORI31 achieves that. The only downside is | ||
39 | * we potentially enable the barrier on systems where the host firmware | ||
40 | * is not updated, but that's harmless as it's a no-op. | ||
41 | */ | ||
42 | enable = security_ftr_enabled(SEC_FTR_FAVOUR_SECURITY) && | ||
43 | security_ftr_enabled(SEC_FTR_BNDS_CHK_SPEC_BAR); | ||
44 | |||
45 | enable_barrier_nospec(enable); | ||
46 | } | ||
47 | |||
48 | #ifdef CONFIG_DEBUG_FS | ||
49 | static int barrier_nospec_set(void *data, u64 val) | ||
50 | { | ||
51 | switch (val) { | ||
52 | case 0: | ||
53 | case 1: | ||
54 | break; | ||
55 | default: | ||
56 | return -EINVAL; | ||
57 | } | ||
58 | |||
59 | if (!!val == !!barrier_nospec_enabled) | ||
60 | return 0; | ||
61 | |||
62 | enable_barrier_nospec(!!val); | ||
63 | |||
64 | return 0; | ||
65 | } | ||
66 | |||
67 | static int barrier_nospec_get(void *data, u64 *val) | ||
68 | { | ||
69 | *val = barrier_nospec_enabled ? 1 : 0; | ||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | DEFINE_SIMPLE_ATTRIBUTE(fops_barrier_nospec, | ||
74 | barrier_nospec_get, barrier_nospec_set, "%llu\n"); | ||
75 | |||
76 | static __init int barrier_nospec_debugfs_init(void) | ||
77 | { | ||
78 | debugfs_create_file("barrier_nospec", 0600, powerpc_debugfs_root, NULL, | ||
79 | &fops_barrier_nospec); | ||
80 | return 0; | ||
81 | } | ||
82 | device_initcall(barrier_nospec_debugfs_init); | ||
83 | #endif /* CONFIG_DEBUG_FS */ | ||
84 | |||
17 | ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr, char *buf) | 85 | ssize_t cpu_show_meltdown(struct device *dev, struct device_attribute *attr, char *buf) |
18 | { | 86 | { |
19 | bool thread_priv; | 87 | bool thread_priv; |
@@ -52,6 +120,9 @@ ssize_t cpu_show_spectre_v1(struct device *dev, struct device_attribute *attr, c | |||
52 | if (!security_ftr_enabled(SEC_FTR_BNDS_CHK_SPEC_BAR)) | 120 | if (!security_ftr_enabled(SEC_FTR_BNDS_CHK_SPEC_BAR)) |
53 | return sprintf(buf, "Not affected\n"); | 121 | return sprintf(buf, "Not affected\n"); |
54 | 122 | ||
123 | if (barrier_nospec_enabled) | ||
124 | return sprintf(buf, "Mitigation: __user pointer sanitization\n"); | ||
125 | |||
55 | return sprintf(buf, "Vulnerable\n"); | 126 | return sprintf(buf, "Vulnerable\n"); |
56 | } | 127 | } |
57 | 128 | ||
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 0af5c11b9e78..62b1a40d8957 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c | |||
@@ -192,12 +192,6 @@ void machine_halt(void) | |||
192 | machine_hang(); | 192 | machine_hang(); |
193 | } | 193 | } |
194 | 194 | ||
195 | |||
196 | #ifdef CONFIG_TAU | ||
197 | extern u32 cpu_temp(unsigned long cpu); | ||
198 | extern u32 cpu_temp_both(unsigned long cpu); | ||
199 | #endif /* CONFIG_TAU */ | ||
200 | |||
201 | #ifdef CONFIG_SMP | 195 | #ifdef CONFIG_SMP |
202 | DEFINE_PER_CPU(unsigned int, cpu_pvr); | 196 | DEFINE_PER_CPU(unsigned int, cpu_pvr); |
203 | #endif | 197 | #endif |
diff --git a/arch/powerpc/kernel/setup.h b/arch/powerpc/kernel/setup.h index d144df54ad40..c6a592b67386 100644 --- a/arch/powerpc/kernel/setup.h +++ b/arch/powerpc/kernel/setup.h | |||
@@ -62,4 +62,10 @@ void kvm_cma_reserve(void); | |||
62 | static inline void kvm_cma_reserve(void) { }; | 62 | static inline void kvm_cma_reserve(void) { }; |
63 | #endif | 63 | #endif |
64 | 64 | ||
65 | #ifdef CONFIG_TAU | ||
66 | u32 cpu_temp(unsigned long cpu); | ||
67 | u32 cpu_temp_both(unsigned long cpu); | ||
68 | u32 tau_interrupts(unsigned long cpu); | ||
69 | #endif /* CONFIG_TAU */ | ||
70 | |||
65 | #endif /* __ARCH_POWERPC_KERNEL_SETUP_H */ | 71 | #endif /* __ARCH_POWERPC_KERNEL_SETUP_H */ |
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index b78f142a4148..7a7ce8ad455e 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
@@ -346,6 +346,13 @@ void __init early_setup(unsigned long dt_ptr) | |||
346 | */ | 346 | */ |
347 | cpu_ready_for_interrupts(); | 347 | cpu_ready_for_interrupts(); |
348 | 348 | ||
349 | /* | ||
350 | * We enable ftrace here, but since we only support DYNAMIC_FTRACE, it | ||
351 | * will only actually get enabled on the boot cpu much later once | ||
352 | * ftrace itself has been initialized. | ||
353 | */ | ||
354 | this_cpu_enable_ftrace(); | ||
355 | |||
349 | DBG(" <- early_setup()\n"); | 356 | DBG(" <- early_setup()\n"); |
350 | 357 | ||
351 | #ifdef CONFIG_PPC_EARLY_DEBUG_BOOTX | 358 | #ifdef CONFIG_PPC_EARLY_DEBUG_BOOTX |
diff --git a/arch/powerpc/kernel/signal.c b/arch/powerpc/kernel/signal.c index 61db86ecd318..fb932f1202c7 100644 --- a/arch/powerpc/kernel/signal.c +++ b/arch/powerpc/kernel/signal.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/key.h> | 15 | #include <linux/key.h> |
16 | #include <linux/context_tracking.h> | 16 | #include <linux/context_tracking.h> |
17 | #include <linux/livepatch.h> | 17 | #include <linux/livepatch.h> |
18 | #include <linux/syscalls.h> | ||
18 | #include <asm/hw_breakpoint.h> | 19 | #include <asm/hw_breakpoint.h> |
19 | #include <linux/uaccess.h> | 20 | #include <linux/uaccess.h> |
20 | #include <asm/unistd.h> | 21 | #include <asm/unistd.h> |
@@ -150,6 +151,9 @@ void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) | |||
150 | { | 151 | { |
151 | user_exit(); | 152 | user_exit(); |
152 | 153 | ||
154 | /* Check valid addr_limit, TIF check is done there */ | ||
155 | addr_limit_user_check(); | ||
156 | |||
153 | if (thread_info_flags & _TIF_UPROBE) | 157 | if (thread_info_flags & _TIF_UPROBE) |
154 | uprobe_notify_resume(regs); | 158 | uprobe_notify_resume(regs); |
155 | 159 | ||
diff --git a/arch/powerpc/kernel/signal.h b/arch/powerpc/kernel/signal.h index a6467f843acf..800433685888 100644 --- a/arch/powerpc/kernel/signal.h +++ b/arch/powerpc/kernel/signal.h | |||
@@ -49,10 +49,8 @@ extern int handle_rt_signal64(struct ksignal *ksig, sigset_t *set, | |||
49 | 49 | ||
50 | #else /* CONFIG_PPC64 */ | 50 | #else /* CONFIG_PPC64 */ |
51 | 51 | ||
52 | extern long sys_rt_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8, | 52 | extern long sys_rt_sigreturn(void); |
53 | struct pt_regs *regs); | 53 | extern long sys_sigreturn(void); |
54 | extern long sys_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8, | ||
55 | struct pt_regs *regs); | ||
56 | 54 | ||
57 | static inline int handle_rt_signal64(struct ksignal *ksig, sigset_t *set, | 55 | static inline int handle_rt_signal64(struct ksignal *ksig, sigset_t *set, |
58 | struct task_struct *tsk) | 56 | struct task_struct *tsk) |
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 492f03451877..5eedbb282d42 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c | |||
@@ -25,9 +25,10 @@ | |||
25 | #include <linux/errno.h> | 25 | #include <linux/errno.h> |
26 | #include <linux/elf.h> | 26 | #include <linux/elf.h> |
27 | #include <linux/ptrace.h> | 27 | #include <linux/ptrace.h> |
28 | #include <linux/pagemap.h> | ||
28 | #include <linux/ratelimit.h> | 29 | #include <linux/ratelimit.h> |
29 | #ifdef CONFIG_PPC64 | ||
30 | #include <linux/syscalls.h> | 30 | #include <linux/syscalls.h> |
31 | #ifdef CONFIG_PPC64 | ||
31 | #include <linux/compat.h> | 32 | #include <linux/compat.h> |
32 | #else | 33 | #else |
33 | #include <linux/wait.h> | 34 | #include <linux/wait.h> |
@@ -57,10 +58,6 @@ | |||
57 | 58 | ||
58 | 59 | ||
59 | #ifdef CONFIG_PPC64 | 60 | #ifdef CONFIG_PPC64 |
60 | #define sys_rt_sigreturn compat_sys_rt_sigreturn | ||
61 | #define sys_swapcontext compat_sys_swapcontext | ||
62 | #define sys_sigreturn compat_sys_sigreturn | ||
63 | |||
64 | #define old_sigaction old_sigaction32 | 61 | #define old_sigaction old_sigaction32 |
65 | #define sigcontext sigcontext32 | 62 | #define sigcontext sigcontext32 |
66 | #define mcontext mcontext32 | 63 | #define mcontext mcontext32 |
@@ -1041,11 +1038,18 @@ static int do_setcontext_tm(struct ucontext __user *ucp, | |||
1041 | } | 1038 | } |
1042 | #endif | 1039 | #endif |
1043 | 1040 | ||
1044 | long sys_swapcontext(struct ucontext __user *old_ctx, | 1041 | #pragma GCC diagnostic push |
1045 | struct ucontext __user *new_ctx, | 1042 | #pragma GCC diagnostic ignored "-Wpragmas" |
1046 | int ctx_size, int r6, int r7, int r8, struct pt_regs *regs) | 1043 | #pragma GCC diagnostic ignored "-Wattribute-alias" |
1044 | #ifdef CONFIG_PPC64 | ||
1045 | COMPAT_SYSCALL_DEFINE3(swapcontext, struct ucontext __user *, old_ctx, | ||
1046 | struct ucontext __user *, new_ctx, int, ctx_size) | ||
1047 | #else | ||
1048 | SYSCALL_DEFINE3(swapcontext, struct ucontext __user *, old_ctx, | ||
1049 | struct ucontext __user *, new_ctx, long, ctx_size) | ||
1050 | #endif | ||
1047 | { | 1051 | { |
1048 | unsigned char tmp __maybe_unused; | 1052 | struct pt_regs *regs = current_pt_regs(); |
1049 | int ctx_has_vsx_region = 0; | 1053 | int ctx_has_vsx_region = 0; |
1050 | 1054 | ||
1051 | #ifdef CONFIG_PPC64 | 1055 | #ifdef CONFIG_PPC64 |
@@ -1109,9 +1113,8 @@ long sys_swapcontext(struct ucontext __user *old_ctx, | |||
1109 | } | 1113 | } |
1110 | if (new_ctx == NULL) | 1114 | if (new_ctx == NULL) |
1111 | return 0; | 1115 | return 0; |
1112 | if (!access_ok(VERIFY_READ, new_ctx, ctx_size) | 1116 | if (!access_ok(VERIFY_READ, new_ctx, ctx_size) || |
1113 | || __get_user(tmp, (u8 __user *) new_ctx) | 1117 | fault_in_pages_readable((u8 __user *)new_ctx, ctx_size)) |
1114 | || __get_user(tmp, (u8 __user *) new_ctx + ctx_size - 1)) | ||
1115 | return -EFAULT; | 1118 | return -EFAULT; |
1116 | 1119 | ||
1117 | /* | 1120 | /* |
@@ -1131,11 +1134,16 @@ long sys_swapcontext(struct ucontext __user *old_ctx, | |||
1131 | set_thread_flag(TIF_RESTOREALL); | 1134 | set_thread_flag(TIF_RESTOREALL); |
1132 | return 0; | 1135 | return 0; |
1133 | } | 1136 | } |
1137 | #pragma GCC diagnostic pop | ||
1134 | 1138 | ||
1135 | long sys_rt_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8, | 1139 | #ifdef CONFIG_PPC64 |
1136 | struct pt_regs *regs) | 1140 | COMPAT_SYSCALL_DEFINE0(rt_sigreturn) |
1141 | #else | ||
1142 | SYSCALL_DEFINE0(rt_sigreturn) | ||
1143 | #endif | ||
1137 | { | 1144 | { |
1138 | struct rt_sigframe __user *rt_sf; | 1145 | struct rt_sigframe __user *rt_sf; |
1146 | struct pt_regs *regs = current_pt_regs(); | ||
1139 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | 1147 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM |
1140 | struct ucontext __user *uc_transact; | 1148 | struct ucontext __user *uc_transact; |
1141 | unsigned long msr_hi; | 1149 | unsigned long msr_hi; |
@@ -1223,15 +1231,16 @@ long sys_rt_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8, | |||
1223 | return 0; | 1231 | return 0; |
1224 | } | 1232 | } |
1225 | 1233 | ||
1234 | #pragma GCC diagnostic push | ||
1235 | #pragma GCC diagnostic ignored "-Wpragmas" | ||
1236 | #pragma GCC diagnostic ignored "-Wattribute-alias" | ||
1226 | #ifdef CONFIG_PPC32 | 1237 | #ifdef CONFIG_PPC32 |
1227 | int sys_debug_setcontext(struct ucontext __user *ctx, | 1238 | SYSCALL_DEFINE3(debug_setcontext, struct ucontext __user *, ctx, |
1228 | int ndbg, struct sig_dbg_op __user *dbg, | 1239 | int, ndbg, struct sig_dbg_op __user *, dbg) |
1229 | int r6, int r7, int r8, | ||
1230 | struct pt_regs *regs) | ||
1231 | { | 1240 | { |
1241 | struct pt_regs *regs = current_pt_regs(); | ||
1232 | struct sig_dbg_op op; | 1242 | struct sig_dbg_op op; |
1233 | int i; | 1243 | int i; |
1234 | unsigned char tmp __maybe_unused; | ||
1235 | unsigned long new_msr = regs->msr; | 1244 | unsigned long new_msr = regs->msr; |
1236 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | 1245 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS |
1237 | unsigned long new_dbcr0 = current->thread.debug.dbcr0; | 1246 | unsigned long new_dbcr0 = current->thread.debug.dbcr0; |
@@ -1287,9 +1296,8 @@ int sys_debug_setcontext(struct ucontext __user *ctx, | |||
1287 | current->thread.debug.dbcr0 = new_dbcr0; | 1296 | current->thread.debug.dbcr0 = new_dbcr0; |
1288 | #endif | 1297 | #endif |
1289 | 1298 | ||
1290 | if (!access_ok(VERIFY_READ, ctx, sizeof(*ctx)) | 1299 | if (!access_ok(VERIFY_READ, ctx, sizeof(*ctx)) || |
1291 | || __get_user(tmp, (u8 __user *) ctx) | 1300 | fault_in_pages_readable((u8 __user *)ctx, sizeof(*ctx))) |
1292 | || __get_user(tmp, (u8 __user *) (ctx + 1) - 1)) | ||
1293 | return -EFAULT; | 1301 | return -EFAULT; |
1294 | 1302 | ||
1295 | /* | 1303 | /* |
@@ -1329,6 +1337,7 @@ int sys_debug_setcontext(struct ucontext __user *ctx, | |||
1329 | return 0; | 1337 | return 0; |
1330 | } | 1338 | } |
1331 | #endif | 1339 | #endif |
1340 | #pragma GCC diagnostic pop | ||
1332 | 1341 | ||
1333 | /* | 1342 | /* |
1334 | * OK, we're invoking a handler | 1343 | * OK, we're invoking a handler |
@@ -1419,9 +1428,13 @@ badframe: | |||
1419 | /* | 1428 | /* |
1420 | * Do a signal return; undo the signal stack. | 1429 | * Do a signal return; undo the signal stack. |
1421 | */ | 1430 | */ |
1422 | long sys_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8, | 1431 | #ifdef CONFIG_PPC64 |
1423 | struct pt_regs *regs) | 1432 | COMPAT_SYSCALL_DEFINE0(sigreturn) |
1433 | #else | ||
1434 | SYSCALL_DEFINE0(sigreturn) | ||
1435 | #endif | ||
1424 | { | 1436 | { |
1437 | struct pt_regs *regs = current_pt_regs(); | ||
1425 | struct sigframe __user *sf; | 1438 | struct sigframe __user *sf; |
1426 | struct sigcontext __user *sc; | 1439 | struct sigcontext __user *sc; |
1427 | struct sigcontext sigctx; | 1440 | struct sigcontext sigctx; |
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index 720117690822..d42b60020389 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/elf.h> | 24 | #include <linux/elf.h> |
25 | #include <linux/ptrace.h> | 25 | #include <linux/ptrace.h> |
26 | #include <linux/ratelimit.h> | 26 | #include <linux/ratelimit.h> |
27 | #include <linux/syscalls.h> | ||
27 | 28 | ||
28 | #include <asm/sigcontext.h> | 29 | #include <asm/sigcontext.h> |
29 | #include <asm/ucontext.h> | 30 | #include <asm/ucontext.h> |
@@ -624,17 +625,17 @@ static long setup_trampoline(unsigned int syscall, unsigned int __user *tramp) | |||
624 | /* | 625 | /* |
625 | * Handle {get,set,swap}_context operations | 626 | * Handle {get,set,swap}_context operations |
626 | */ | 627 | */ |
627 | int sys_swapcontext(struct ucontext __user *old_ctx, | 628 | #pragma GCC diagnostic push |
628 | struct ucontext __user *new_ctx, | 629 | #pragma GCC diagnostic ignored "-Wpragmas" |
629 | long ctx_size, long r6, long r7, long r8, struct pt_regs *regs) | 630 | #pragma GCC diagnostic ignored "-Wattribute-alias" |
631 | SYSCALL_DEFINE3(swapcontext, struct ucontext __user *, old_ctx, | ||
632 | struct ucontext __user *, new_ctx, long, ctx_size) | ||
630 | { | 633 | { |
631 | unsigned char tmp; | 634 | unsigned char tmp; |
632 | sigset_t set; | 635 | sigset_t set; |
633 | unsigned long new_msr = 0; | 636 | unsigned long new_msr = 0; |
634 | int ctx_has_vsx_region = 0; | 637 | int ctx_has_vsx_region = 0; |
635 | 638 | ||
636 | BUG_ON(regs != current->thread.regs); | ||
637 | |||
638 | if (new_ctx && | 639 | if (new_ctx && |
639 | get_user(new_msr, &new_ctx->uc_mcontext.gp_regs[PT_MSR])) | 640 | get_user(new_msr, &new_ctx->uc_mcontext.gp_regs[PT_MSR])) |
640 | return -EFAULT; | 641 | return -EFAULT; |
@@ -692,24 +693,22 @@ int sys_swapcontext(struct ucontext __user *old_ctx, | |||
692 | set_thread_flag(TIF_RESTOREALL); | 693 | set_thread_flag(TIF_RESTOREALL); |
693 | return 0; | 694 | return 0; |
694 | } | 695 | } |
696 | #pragma GCC diagnostic pop | ||
695 | 697 | ||
696 | 698 | ||
697 | /* | 699 | /* |
698 | * Do a signal return; undo the signal stack. | 700 | * Do a signal return; undo the signal stack. |
699 | */ | 701 | */ |
700 | 702 | ||
701 | int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, | 703 | SYSCALL_DEFINE0(rt_sigreturn) |
702 | unsigned long r6, unsigned long r7, unsigned long r8, | ||
703 | struct pt_regs *regs) | ||
704 | { | 704 | { |
705 | struct pt_regs *regs = current_pt_regs(); | ||
705 | struct ucontext __user *uc = (struct ucontext __user *)regs->gpr[1]; | 706 | struct ucontext __user *uc = (struct ucontext __user *)regs->gpr[1]; |
706 | sigset_t set; | 707 | sigset_t set; |
707 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | 708 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM |
708 | unsigned long msr; | 709 | unsigned long msr; |
709 | #endif | 710 | #endif |
710 | 711 | ||
711 | BUG_ON(current->thread.regs != regs); | ||
712 | |||
713 | /* Always make any pending restarted system calls return -EINTR */ | 712 | /* Always make any pending restarted system calls return -EINTR */ |
714 | current->restart_block.fn = do_no_restart_syscall; | 713 | current->restart_block.fn = do_no_restart_syscall; |
715 | 714 | ||
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 9ca7148b5881..5eadfffabe35 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c | |||
@@ -59,6 +59,7 @@ | |||
59 | #include <asm/kexec.h> | 59 | #include <asm/kexec.h> |
60 | #include <asm/asm-prototypes.h> | 60 | #include <asm/asm-prototypes.h> |
61 | #include <asm/cpu_has_feature.h> | 61 | #include <asm/cpu_has_feature.h> |
62 | #include <asm/ftrace.h> | ||
62 | 63 | ||
63 | #ifdef DEBUG | 64 | #ifdef DEBUG |
64 | #include <asm/udbg.h> | 65 | #include <asm/udbg.h> |
@@ -155,11 +156,13 @@ static irqreturn_t reschedule_action(int irq, void *data) | |||
155 | return IRQ_HANDLED; | 156 | return IRQ_HANDLED; |
156 | } | 157 | } |
157 | 158 | ||
159 | #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST | ||
158 | static irqreturn_t tick_broadcast_ipi_action(int irq, void *data) | 160 | static irqreturn_t tick_broadcast_ipi_action(int irq, void *data) |
159 | { | 161 | { |
160 | tick_broadcast_ipi_handler(); | 162 | timer_broadcast_interrupt(); |
161 | return IRQ_HANDLED; | 163 | return IRQ_HANDLED; |
162 | } | 164 | } |
165 | #endif | ||
163 | 166 | ||
164 | #ifdef CONFIG_NMI_IPI | 167 | #ifdef CONFIG_NMI_IPI |
165 | static irqreturn_t nmi_ipi_action(int irq, void *data) | 168 | static irqreturn_t nmi_ipi_action(int irq, void *data) |
@@ -172,7 +175,9 @@ static irqreturn_t nmi_ipi_action(int irq, void *data) | |||
172 | static irq_handler_t smp_ipi_action[] = { | 175 | static irq_handler_t smp_ipi_action[] = { |
173 | [PPC_MSG_CALL_FUNCTION] = call_function_action, | 176 | [PPC_MSG_CALL_FUNCTION] = call_function_action, |
174 | [PPC_MSG_RESCHEDULE] = reschedule_action, | 177 | [PPC_MSG_RESCHEDULE] = reschedule_action, |
178 | #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST | ||
175 | [PPC_MSG_TICK_BROADCAST] = tick_broadcast_ipi_action, | 179 | [PPC_MSG_TICK_BROADCAST] = tick_broadcast_ipi_action, |
180 | #endif | ||
176 | #ifdef CONFIG_NMI_IPI | 181 | #ifdef CONFIG_NMI_IPI |
177 | [PPC_MSG_NMI_IPI] = nmi_ipi_action, | 182 | [PPC_MSG_NMI_IPI] = nmi_ipi_action, |
178 | #endif | 183 | #endif |
@@ -186,8 +191,12 @@ static irq_handler_t smp_ipi_action[] = { | |||
186 | const char *smp_ipi_name[] = { | 191 | const char *smp_ipi_name[] = { |
187 | [PPC_MSG_CALL_FUNCTION] = "ipi call function", | 192 | [PPC_MSG_CALL_FUNCTION] = "ipi call function", |
188 | [PPC_MSG_RESCHEDULE] = "ipi reschedule", | 193 | [PPC_MSG_RESCHEDULE] = "ipi reschedule", |
194 | #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST | ||
189 | [PPC_MSG_TICK_BROADCAST] = "ipi tick-broadcast", | 195 | [PPC_MSG_TICK_BROADCAST] = "ipi tick-broadcast", |
196 | #endif | ||
197 | #ifdef CONFIG_NMI_IPI | ||
190 | [PPC_MSG_NMI_IPI] = "nmi ipi", | 198 | [PPC_MSG_NMI_IPI] = "nmi ipi", |
199 | #endif | ||
191 | }; | 200 | }; |
192 | 201 | ||
193 | /* optional function to request ipi, for controllers with >= 4 ipis */ | 202 | /* optional function to request ipi, for controllers with >= 4 ipis */ |
@@ -277,8 +286,10 @@ irqreturn_t smp_ipi_demux_relaxed(void) | |||
277 | generic_smp_call_function_interrupt(); | 286 | generic_smp_call_function_interrupt(); |
278 | if (all & IPI_MESSAGE(PPC_MSG_RESCHEDULE)) | 287 | if (all & IPI_MESSAGE(PPC_MSG_RESCHEDULE)) |
279 | scheduler_ipi(); | 288 | scheduler_ipi(); |
289 | #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST | ||
280 | if (all & IPI_MESSAGE(PPC_MSG_TICK_BROADCAST)) | 290 | if (all & IPI_MESSAGE(PPC_MSG_TICK_BROADCAST)) |
281 | tick_broadcast_ipi_handler(); | 291 | timer_broadcast_interrupt(); |
292 | #endif | ||
282 | #ifdef CONFIG_NMI_IPI | 293 | #ifdef CONFIG_NMI_IPI |
283 | if (all & IPI_MESSAGE(PPC_MSG_NMI_IPI)) | 294 | if (all & IPI_MESSAGE(PPC_MSG_NMI_IPI)) |
284 | nmi_ipi_action(0, NULL); | 295 | nmi_ipi_action(0, NULL); |
@@ -419,9 +430,9 @@ out: | |||
419 | return ret; | 430 | return ret; |
420 | } | 431 | } |
421 | 432 | ||
422 | static void do_smp_send_nmi_ipi(int cpu) | 433 | static void do_smp_send_nmi_ipi(int cpu, bool safe) |
423 | { | 434 | { |
424 | if (smp_ops->cause_nmi_ipi && smp_ops->cause_nmi_ipi(cpu)) | 435 | if (!safe && smp_ops->cause_nmi_ipi && smp_ops->cause_nmi_ipi(cpu)) |
425 | return; | 436 | return; |
426 | 437 | ||
427 | if (cpu >= 0) { | 438 | if (cpu >= 0) { |
@@ -461,7 +472,7 @@ void smp_flush_nmi_ipi(u64 delay_us) | |||
461 | * - delay_us > 0 is the delay before giving up waiting for targets to | 472 | * - delay_us > 0 is the delay before giving up waiting for targets to |
462 | * enter the handler, == 0 specifies indefinite delay. | 473 | * enter the handler, == 0 specifies indefinite delay. |
463 | */ | 474 | */ |
464 | int smp_send_nmi_ipi(int cpu, void (*fn)(struct pt_regs *), u64 delay_us) | 475 | int __smp_send_nmi_ipi(int cpu, void (*fn)(struct pt_regs *), u64 delay_us, bool safe) |
465 | { | 476 | { |
466 | unsigned long flags; | 477 | unsigned long flags; |
467 | int me = raw_smp_processor_id(); | 478 | int me = raw_smp_processor_id(); |
@@ -494,7 +505,7 @@ int smp_send_nmi_ipi(int cpu, void (*fn)(struct pt_regs *), u64 delay_us) | |||
494 | nmi_ipi_busy_count++; | 505 | nmi_ipi_busy_count++; |
495 | nmi_ipi_unlock(); | 506 | nmi_ipi_unlock(); |
496 | 507 | ||
497 | do_smp_send_nmi_ipi(cpu); | 508 | do_smp_send_nmi_ipi(cpu, safe); |
498 | 509 | ||
499 | while (!cpumask_empty(&nmi_ipi_pending_mask)) { | 510 | while (!cpumask_empty(&nmi_ipi_pending_mask)) { |
500 | udelay(1); | 511 | udelay(1); |
@@ -516,6 +527,16 @@ int smp_send_nmi_ipi(int cpu, void (*fn)(struct pt_regs *), u64 delay_us) | |||
516 | 527 | ||
517 | return ret; | 528 | return ret; |
518 | } | 529 | } |
530 | |||
531 | int smp_send_nmi_ipi(int cpu, void (*fn)(struct pt_regs *), u64 delay_us) | ||
532 | { | ||
533 | return __smp_send_nmi_ipi(cpu, fn, delay_us, false); | ||
534 | } | ||
535 | |||
536 | int smp_send_safe_nmi_ipi(int cpu, void (*fn)(struct pt_regs *), u64 delay_us) | ||
537 | { | ||
538 | return __smp_send_nmi_ipi(cpu, fn, delay_us, true); | ||
539 | } | ||
519 | #endif /* CONFIG_NMI_IPI */ | 540 | #endif /* CONFIG_NMI_IPI */ |
520 | 541 | ||
521 | #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST | 542 | #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST |
@@ -559,7 +580,7 @@ void crash_send_ipi(void (*crash_ipi_callback)(struct pt_regs *)) | |||
559 | * entire NMI dance and waiting for | 580 | * entire NMI dance and waiting for |
560 | * cpus to clear pending mask, etc. | 581 | * cpus to clear pending mask, etc. |
561 | */ | 582 | */ |
562 | do_smp_send_nmi_ipi(cpu); | 583 | do_smp_send_nmi_ipi(cpu, false); |
563 | } | 584 | } |
564 | } | 585 | } |
565 | } | 586 | } |
@@ -1066,6 +1087,9 @@ void start_secondary(void *unused) | |||
1066 | 1087 | ||
1067 | local_irq_enable(); | 1088 | local_irq_enable(); |
1068 | 1089 | ||
1090 | /* We can enable ftrace for secondary cpus now */ | ||
1091 | this_cpu_enable_ftrace(); | ||
1092 | |||
1069 | cpu_startup_entry(CPUHP_AP_ONLINE_IDLE); | 1093 | cpu_startup_entry(CPUHP_AP_ONLINE_IDLE); |
1070 | 1094 | ||
1071 | BUG(); | 1095 | BUG(); |
@@ -1162,6 +1186,8 @@ int __cpu_disable(void) | |||
1162 | if (!smp_ops->cpu_disable) | 1186 | if (!smp_ops->cpu_disable) |
1163 | return -ENOSYS; | 1187 | return -ENOSYS; |
1164 | 1188 | ||
1189 | this_cpu_disable_ftrace(); | ||
1190 | |||
1165 | err = smp_ops->cpu_disable(); | 1191 | err = smp_ops->cpu_disable(); |
1166 | if (err) | 1192 | if (err) |
1167 | return err; | 1193 | return err; |
@@ -1180,6 +1206,12 @@ void __cpu_die(unsigned int cpu) | |||
1180 | 1206 | ||
1181 | void cpu_die(void) | 1207 | void cpu_die(void) |
1182 | { | 1208 | { |
1209 | /* | ||
1210 | * Disable on the down path. This will be re-enabled by | ||
1211 | * start_secondary() via start_secondary_resume() below | ||
1212 | */ | ||
1213 | this_cpu_disable_ftrace(); | ||
1214 | |||
1183 | if (ppc_md.cpu_die) | 1215 | if (ppc_md.cpu_die) |
1184 | ppc_md.cpu_die(); | 1216 | ppc_md.cpu_die(); |
1185 | 1217 | ||
diff --git a/arch/powerpc/kernel/stacktrace.c b/arch/powerpc/kernel/stacktrace.c index d534ed901538..07e97f289c52 100644 --- a/arch/powerpc/kernel/stacktrace.c +++ b/arch/powerpc/kernel/stacktrace.c | |||
@@ -1,21 +1,27 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | |||
1 | /* | 3 | /* |
2 | * Stack trace utility | 4 | * Stack trace utility functions etc. |
3 | * | 5 | * |
4 | * Copyright 2008 Christoph Hellwig, IBM Corp. | 6 | * Copyright 2008 Christoph Hellwig, IBM Corp. |
5 | * | 7 | * Copyright 2018 SUSE Linux GmbH |
6 | * | 8 | * Copyright 2018 Nick Piggin, Michael Ellerman, IBM Corp. |
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; either version | ||
10 | * 2 of the License, or (at your option) any later version. | ||
11 | */ | 9 | */ |
12 | 10 | ||
13 | #include <linux/export.h> | 11 | #include <linux/export.h> |
12 | #include <linux/kallsyms.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/nmi.h> | ||
14 | #include <linux/sched.h> | 15 | #include <linux/sched.h> |
15 | #include <linux/sched/debug.h> | 16 | #include <linux/sched/debug.h> |
17 | #include <linux/sched/task_stack.h> | ||
16 | #include <linux/stacktrace.h> | 18 | #include <linux/stacktrace.h> |
17 | #include <asm/ptrace.h> | 19 | #include <asm/ptrace.h> |
18 | #include <asm/processor.h> | 20 | #include <asm/processor.h> |
21 | #include <linux/ftrace.h> | ||
22 | #include <asm/kprobes.h> | ||
23 | |||
24 | #include <asm/paca.h> | ||
19 | 25 | ||
20 | /* | 26 | /* |
21 | * Save stack-backtrace addresses into a stack_trace buffer. | 27 | * Save stack-backtrace addresses into a stack_trace buffer. |
@@ -76,3 +82,164 @@ save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace) | |||
76 | save_context_stack(trace, regs->gpr[1], current, 0); | 82 | save_context_stack(trace, regs->gpr[1], current, 0); |
77 | } | 83 | } |
78 | EXPORT_SYMBOL_GPL(save_stack_trace_regs); | 84 | EXPORT_SYMBOL_GPL(save_stack_trace_regs); |
85 | |||
86 | #ifdef CONFIG_HAVE_RELIABLE_STACKTRACE | ||
87 | int | ||
88 | save_stack_trace_tsk_reliable(struct task_struct *tsk, | ||
89 | struct stack_trace *trace) | ||
90 | { | ||
91 | unsigned long sp; | ||
92 | unsigned long stack_page = (unsigned long)task_stack_page(tsk); | ||
93 | unsigned long stack_end; | ||
94 | int graph_idx = 0; | ||
95 | |||
96 | /* | ||
97 | * The last frame (unwinding first) may not yet have saved | ||
98 | * its LR onto the stack. | ||
99 | */ | ||
100 | int firstframe = 1; | ||
101 | |||
102 | if (tsk == current) | ||
103 | sp = current_stack_pointer(); | ||
104 | else | ||
105 | sp = tsk->thread.ksp; | ||
106 | |||
107 | stack_end = stack_page + THREAD_SIZE; | ||
108 | if (!is_idle_task(tsk)) { | ||
109 | /* | ||
110 | * For user tasks, this is the SP value loaded on | ||
111 | * kernel entry, see "PACAKSAVE(r13)" in _switch() and | ||
112 | * system_call_common()/EXCEPTION_PROLOG_COMMON(). | ||
113 | * | ||
114 | * Likewise for non-swapper kernel threads, | ||
115 | * this also happens to be the top of the stack | ||
116 | * as setup by copy_thread(). | ||
117 | * | ||
118 | * Note that stack backlinks are not properly setup by | ||
119 | * copy_thread() and thus, a forked task() will have | ||
120 | * an unreliable stack trace until it's been | ||
121 | * _switch()'ed to for the first time. | ||
122 | */ | ||
123 | stack_end -= STACK_FRAME_OVERHEAD + sizeof(struct pt_regs); | ||
124 | } else { | ||
125 | /* | ||
126 | * idle tasks have a custom stack layout, | ||
127 | * c.f. cpu_idle_thread_init(). | ||
128 | */ | ||
129 | stack_end -= STACK_FRAME_OVERHEAD; | ||
130 | } | ||
131 | |||
132 | if (sp < stack_page + sizeof(struct thread_struct) || | ||
133 | sp > stack_end - STACK_FRAME_MIN_SIZE) { | ||
134 | return 1; | ||
135 | } | ||
136 | |||
137 | for (;;) { | ||
138 | unsigned long *stack = (unsigned long *) sp; | ||
139 | unsigned long newsp, ip; | ||
140 | |||
141 | /* sanity check: ABI requires SP to be aligned 16 bytes. */ | ||
142 | if (sp & 0xF) | ||
143 | return 1; | ||
144 | |||
145 | /* Mark stacktraces with exception frames as unreliable. */ | ||
146 | if (sp <= stack_end - STACK_INT_FRAME_SIZE && | ||
147 | stack[STACK_FRAME_MARKER] == STACK_FRAME_REGS_MARKER) { | ||
148 | return 1; | ||
149 | } | ||
150 | |||
151 | newsp = stack[0]; | ||
152 | /* Stack grows downwards; unwinder may only go up. */ | ||
153 | if (newsp <= sp) | ||
154 | return 1; | ||
155 | |||
156 | if (newsp != stack_end && | ||
157 | newsp > stack_end - STACK_FRAME_MIN_SIZE) { | ||
158 | return 1; /* invalid backlink, too far up. */ | ||
159 | } | ||
160 | |||
161 | /* Examine the saved LR: it must point into kernel code. */ | ||
162 | ip = stack[STACK_FRAME_LR_SAVE]; | ||
163 | if (!firstframe && !__kernel_text_address(ip)) | ||
164 | return 1; | ||
165 | firstframe = 0; | ||
166 | |||
167 | /* | ||
168 | * FIXME: IMHO these tests do not belong in | ||
169 | * arch-dependent code, they are generic. | ||
170 | */ | ||
171 | ip = ftrace_graph_ret_addr(tsk, &graph_idx, ip, NULL); | ||
172 | #ifdef CONFIG_KPROBES | ||
173 | /* | ||
174 | * Mark stacktraces with kretprobed functions on them | ||
175 | * as unreliable. | ||
176 | */ | ||
177 | if (ip == (unsigned long)kretprobe_trampoline) | ||
178 | return 1; | ||
179 | #endif | ||
180 | |||
181 | if (!trace->skip) | ||
182 | trace->entries[trace->nr_entries++] = ip; | ||
183 | else | ||
184 | trace->skip--; | ||
185 | |||
186 | if (newsp == stack_end) | ||
187 | break; | ||
188 | |||
189 | if (trace->nr_entries >= trace->max_entries) | ||
190 | return -E2BIG; | ||
191 | |||
192 | sp = newsp; | ||
193 | } | ||
194 | return 0; | ||
195 | } | ||
196 | EXPORT_SYMBOL_GPL(save_stack_trace_tsk_reliable); | ||
197 | #endif /* CONFIG_HAVE_RELIABLE_STACKTRACE */ | ||
198 | |||
199 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
200 | static void handle_backtrace_ipi(struct pt_regs *regs) | ||
201 | { | ||
202 | nmi_cpu_backtrace(regs); | ||
203 | } | ||
204 | |||
205 | static void raise_backtrace_ipi(cpumask_t *mask) | ||
206 | { | ||
207 | unsigned int cpu; | ||
208 | |||
209 | for_each_cpu(cpu, mask) { | ||
210 | if (cpu == smp_processor_id()) | ||
211 | handle_backtrace_ipi(NULL); | ||
212 | else | ||
213 | smp_send_safe_nmi_ipi(cpu, handle_backtrace_ipi, 5 * USEC_PER_SEC); | ||
214 | } | ||
215 | |||
216 | for_each_cpu(cpu, mask) { | ||
217 | struct paca_struct *p = paca_ptrs[cpu]; | ||
218 | |||
219 | cpumask_clear_cpu(cpu, mask); | ||
220 | |||
221 | pr_warn("CPU %d didn't respond to backtrace IPI, inspecting paca.\n", cpu); | ||
222 | if (!virt_addr_valid(p)) { | ||
223 | pr_warn("paca pointer appears corrupt? (%px)\n", p); | ||
224 | continue; | ||
225 | } | ||
226 | |||
227 | pr_warn("irq_soft_mask: 0x%02x in_mce: %d in_nmi: %d", | ||
228 | p->irq_soft_mask, p->in_mce, p->in_nmi); | ||
229 | |||
230 | if (virt_addr_valid(p->__current)) | ||
231 | pr_cont(" current: %d (%s)\n", p->__current->pid, | ||
232 | p->__current->comm); | ||
233 | else | ||
234 | pr_cont(" current pointer corrupt? (%px)\n", p->__current); | ||
235 | |||
236 | pr_warn("Back trace of paca->saved_r1 (0x%016llx) (possibly stale):\n", p->saved_r1); | ||
237 | show_stack(p->__current, (unsigned long *)p->saved_r1); | ||
238 | } | ||
239 | } | ||
240 | |||
241 | void arch_trigger_cpumask_backtrace(const cpumask_t *mask, bool exclude_self) | ||
242 | { | ||
243 | nmi_trigger_cpumask_backtrace(mask, exclude_self, raise_backtrace_ipi); | ||
244 | } | ||
245 | #endif /* CONFIG_PPC64 */ | ||
diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c index c11c73373691..bdf58ba1a94b 100644 --- a/arch/powerpc/kernel/sys_ppc32.c +++ b/arch/powerpc/kernel/sys_ppc32.c | |||
@@ -52,15 +52,6 @@ | |||
52 | #include <asm/syscalls.h> | 52 | #include <asm/syscalls.h> |
53 | #include <asm/switch_to.h> | 53 | #include <asm/switch_to.h> |
54 | 54 | ||
55 | |||
56 | asmlinkage long ppc32_select(u32 n, compat_ulong_t __user *inp, | ||
57 | compat_ulong_t __user *outp, compat_ulong_t __user *exp, | ||
58 | compat_uptr_t tvp_x) | ||
59 | { | ||
60 | /* sign extend n */ | ||
61 | return compat_sys_select((int)n, inp, outp, exp, compat_ptr(tvp_x)); | ||
62 | } | ||
63 | |||
64 | unsigned long compat_sys_mmap2(unsigned long addr, size_t len, | 55 | unsigned long compat_sys_mmap2(unsigned long addr, size_t len, |
65 | unsigned long prot, unsigned long flags, | 56 | unsigned long prot, unsigned long flags, |
66 | unsigned long fd, unsigned long pgoff) | 57 | unsigned long fd, unsigned long pgoff) |
diff --git a/arch/powerpc/kernel/syscalls.c b/arch/powerpc/kernel/syscalls.c index 466216506eb2..083fa06962fd 100644 --- a/arch/powerpc/kernel/syscalls.c +++ b/arch/powerpc/kernel/syscalls.c | |||
@@ -62,6 +62,9 @@ out: | |||
62 | return ret; | 62 | return ret; |
63 | } | 63 | } |
64 | 64 | ||
65 | #pragma GCC diagnostic push | ||
66 | #pragma GCC diagnostic ignored "-Wpragmas" | ||
67 | #pragma GCC diagnostic ignored "-Wattribute-alias" | ||
65 | SYSCALL_DEFINE6(mmap2, unsigned long, addr, size_t, len, | 68 | SYSCALL_DEFINE6(mmap2, unsigned long, addr, size_t, len, |
66 | unsigned long, prot, unsigned long, flags, | 69 | unsigned long, prot, unsigned long, flags, |
67 | unsigned long, fd, unsigned long, pgoff) | 70 | unsigned long, fd, unsigned long, pgoff) |
@@ -75,6 +78,7 @@ SYSCALL_DEFINE6(mmap, unsigned long, addr, size_t, len, | |||
75 | { | 78 | { |
76 | return do_mmap2(addr, len, prot, flags, fd, offset, PAGE_SHIFT); | 79 | return do_mmap2(addr, len, prot, flags, fd, offset, PAGE_SHIFT); |
77 | } | 80 | } |
81 | #pragma GCC diagnostic pop | ||
78 | 82 | ||
79 | #ifdef CONFIG_PPC32 | 83 | #ifdef CONFIG_PPC32 |
80 | /* | 84 | /* |
diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S index 7ccb7f81f8db..919a32746ede 100644 --- a/arch/powerpc/kernel/systbl.S +++ b/arch/powerpc/kernel/systbl.S | |||
@@ -35,7 +35,7 @@ | |||
35 | #endif | 35 | #endif |
36 | #define SYSCALL_SPU(func) SYSCALL(func) | 36 | #define SYSCALL_SPU(func) SYSCALL(func) |
37 | #define COMPAT_SYS_SPU(func) COMPAT_SYS(func) | 37 | #define COMPAT_SYS_SPU(func) COMPAT_SYS(func) |
38 | #define PPC_SYS_SPU(func) PPC_SYS(func) | 38 | #define COMPAT_SPU_NEW(func) COMPAT_SYS(func) |
39 | #define SYSX_SPU(f, f3264, f32) SYSX(f, f3264, f32) | 39 | #define SYSX_SPU(f, f3264, f32) SYSX(f, f3264, f32) |
40 | 40 | ||
41 | .section .rodata,"a" | 41 | .section .rodata,"a" |
diff --git a/arch/powerpc/kernel/systbl_chk.c b/arch/powerpc/kernel/systbl_chk.c index 55323a620cfe..4653258722ac 100644 --- a/arch/powerpc/kernel/systbl_chk.c +++ b/arch/powerpc/kernel/systbl_chk.c | |||
@@ -31,7 +31,7 @@ | |||
31 | 31 | ||
32 | #define SYSCALL_SPU(func) SYSCALL(func) | 32 | #define SYSCALL_SPU(func) SYSCALL(func) |
33 | #define COMPAT_SYS_SPU(func) COMPAT_SYS(func) | 33 | #define COMPAT_SYS_SPU(func) COMPAT_SYS(func) |
34 | #define PPC_SYS_SPU(func) PPC_SYS(func) | 34 | #define COMPAT_SPU_NEW(func) COMPAT_SYS(_new##func) |
35 | #define SYSX_SPU(f, f3264, f32) SYSX(f, f3264, f32) | 35 | #define SYSX_SPU(f, f3264, f32) SYSX(f, f3264, f32) |
36 | 36 | ||
37 | /* Just insert a marker for ni_syscalls */ | 37 | /* Just insert a marker for ni_syscalls */ |
diff --git a/arch/powerpc/kernel/systbl_chk.sh b/arch/powerpc/kernel/systbl_chk.sh index 31b6e7c358ca..f2e356c2a345 100644 --- a/arch/powerpc/kernel/systbl_chk.sh +++ b/arch/powerpc/kernel/systbl_chk.sh | |||
@@ -16,7 +16,7 @@ awk 'BEGIN { num = -1; } # Ignore the beginning of the file | |||
16 | /^START_TABLE/ { num = 0; next; } | 16 | /^START_TABLE/ { num = 0; next; } |
17 | /^END_TABLE/ { | 17 | /^END_TABLE/ { |
18 | if (num != $2) { | 18 | if (num != $2) { |
19 | printf "NR_syscalls (%s) is not one more than the last syscall (%s)\n", | 19 | printf "Error: NR_syscalls (%s) is not one more than the last syscall (%s)\n", |
20 | $2, num - 1; | 20 | $2, num - 1; |
21 | exit(1); | 21 | exit(1); |
22 | } | 22 | } |
@@ -25,7 +25,7 @@ awk 'BEGIN { num = -1; } # Ignore the beginning of the file | |||
25 | { | 25 | { |
26 | if (num == -1) next; | 26 | if (num == -1) next; |
27 | if (($1 != -1) && ($1 != num)) { | 27 | if (($1 != -1) && ($1 != num)) { |
28 | printf "Syscall %s out of order (expected %s)\n", | 28 | printf "Error: Syscall %s out of order (expected %s)\n", |
29 | $1, num; | 29 | $1, num; |
30 | exit(1); | 30 | exit(1); |
31 | }; | 31 | }; |
diff --git a/arch/powerpc/kernel/tau_6xx.c b/arch/powerpc/kernel/tau_6xx.c index 8cdd852aedd1..e2ab8a111b69 100644 --- a/arch/powerpc/kernel/tau_6xx.c +++ b/arch/powerpc/kernel/tau_6xx.c | |||
@@ -27,6 +27,9 @@ | |||
27 | #include <asm/cache.h> | 27 | #include <asm/cache.h> |
28 | #include <asm/8xx_immap.h> | 28 | #include <asm/8xx_immap.h> |
29 | #include <asm/machdep.h> | 29 | #include <asm/machdep.h> |
30 | #include <asm/asm-prototypes.h> | ||
31 | |||
32 | #include "setup.h" | ||
30 | 33 | ||
31 | static struct tau_temp | 34 | static struct tau_temp |
32 | { | 35 | { |
@@ -50,7 +53,7 @@ struct timer_list tau_timer; | |||
50 | #define shrink_timer 2*HZ /* period between shrinking the window */ | 53 | #define shrink_timer 2*HZ /* period between shrinking the window */ |
51 | #define min_window 2 /* minimum window size, degrees C */ | 54 | #define min_window 2 /* minimum window size, degrees C */ |
52 | 55 | ||
53 | void set_thresholds(unsigned long cpu) | 56 | static void set_thresholds(unsigned long cpu) |
54 | { | 57 | { |
55 | #ifdef CONFIG_TAU_INT | 58 | #ifdef CONFIG_TAU_INT |
56 | /* | 59 | /* |
@@ -70,7 +73,7 @@ void set_thresholds(unsigned long cpu) | |||
70 | #endif | 73 | #endif |
71 | } | 74 | } |
72 | 75 | ||
73 | void TAUupdate(int cpu) | 76 | static void TAUupdate(int cpu) |
74 | { | 77 | { |
75 | unsigned thrm; | 78 | unsigned thrm; |
76 | 79 | ||
@@ -205,7 +208,7 @@ static void tau_timeout_smp(struct timer_list *unused) | |||
205 | 208 | ||
206 | int tau_initialized = 0; | 209 | int tau_initialized = 0; |
207 | 210 | ||
208 | void __init TAU_init_smp(void * info) | 211 | static void __init TAU_init_smp(void *info) |
209 | { | 212 | { |
210 | unsigned long cpu = smp_processor_id(); | 213 | unsigned long cpu = smp_processor_id(); |
211 | 214 | ||
@@ -217,7 +220,7 @@ void __init TAU_init_smp(void * info) | |||
217 | set_thresholds(cpu); | 220 | set_thresholds(cpu); |
218 | } | 221 | } |
219 | 222 | ||
220 | int __init TAU_init(void) | 223 | static int __init TAU_init(void) |
221 | { | 224 | { |
222 | /* We assume in SMP that if one CPU has TAU support, they | 225 | /* We assume in SMP that if one CPU has TAU support, they |
223 | * all have it --BenH | 226 | * all have it --BenH |
@@ -259,12 +262,12 @@ u32 cpu_temp_both(unsigned long cpu) | |||
259 | return ((tau[cpu].high << 16) | tau[cpu].low); | 262 | return ((tau[cpu].high << 16) | tau[cpu].low); |
260 | } | 263 | } |
261 | 264 | ||
262 | int cpu_temp(unsigned long cpu) | 265 | u32 cpu_temp(unsigned long cpu) |
263 | { | 266 | { |
264 | return ((tau[cpu].high + tau[cpu].low) / 2); | 267 | return ((tau[cpu].high + tau[cpu].low) / 2); |
265 | } | 268 | } |
266 | 269 | ||
267 | int tau_interrupts(unsigned long cpu) | 270 | u32 tau_interrupts(unsigned long cpu) |
268 | { | 271 | { |
269 | return (tau[cpu].interrupts); | 272 | return (tau[cpu].interrupts); |
270 | } | 273 | } |
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 360e71d455cc..70f145e02487 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
@@ -163,12 +163,6 @@ EXPORT_SYMBOL(__cputime_usec_factor); | |||
163 | void (*dtl_consumer)(struct dtl_entry *, u64); | 163 | void (*dtl_consumer)(struct dtl_entry *, u64); |
164 | #endif | 164 | #endif |
165 | 165 | ||
166 | #ifdef CONFIG_PPC64 | ||
167 | #define get_accounting(tsk) (&get_paca()->accounting) | ||
168 | #else | ||
169 | #define get_accounting(tsk) (&task_thread_info(tsk)->accounting) | ||
170 | #endif | ||
171 | |||
172 | static void calc_cputime_factors(void) | 166 | static void calc_cputime_factors(void) |
173 | { | 167 | { |
174 | struct div_result res; | 168 | struct div_result res; |
@@ -421,21 +415,6 @@ void vtime_flush(struct task_struct *tsk) | |||
421 | acct->softirq_time = 0; | 415 | acct->softirq_time = 0; |
422 | } | 416 | } |
423 | 417 | ||
424 | #ifdef CONFIG_PPC32 | ||
425 | /* | ||
426 | * Called from the context switch with interrupts disabled, to charge all | ||
427 | * accumulated times to the current process, and to prepare accounting on | ||
428 | * the next process. | ||
429 | */ | ||
430 | void arch_vtime_task_switch(struct task_struct *prev) | ||
431 | { | ||
432 | struct cpu_accounting_data *acct = get_accounting(current); | ||
433 | |||
434 | acct->starttime = get_accounting(prev)->starttime; | ||
435 | acct->startspurr = get_accounting(prev)->startspurr; | ||
436 | } | ||
437 | #endif /* CONFIG_PPC32 */ | ||
438 | |||
439 | #else /* ! CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ | 418 | #else /* ! CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ |
440 | #define calc_cputime_factors() | 419 | #define calc_cputime_factors() |
441 | #endif | 420 | #endif |
@@ -513,6 +492,35 @@ static inline void clear_irq_work_pending(void) | |||
513 | "i" (offsetof(struct paca_struct, irq_work_pending))); | 492 | "i" (offsetof(struct paca_struct, irq_work_pending))); |
514 | } | 493 | } |
515 | 494 | ||
495 | void arch_irq_work_raise(void) | ||
496 | { | ||
497 | preempt_disable(); | ||
498 | set_irq_work_pending_flag(); | ||
499 | /* | ||
500 | * Non-nmi code running with interrupts disabled will replay | ||
501 | * irq_happened before it re-enables interrupts, so setthe | ||
502 | * decrementer there instead of causing a hardware exception | ||
503 | * which would immediately hit the masked interrupt handler | ||
504 | * and have the net effect of setting the decrementer in | ||
505 | * irq_happened. | ||
506 | * | ||
507 | * NMI interrupts can not check this when they return, so the | ||
508 | * decrementer hardware exception is raised, which will fire | ||
509 | * when interrupts are next enabled. | ||
510 | * | ||
511 | * BookE does not support this yet, it must audit all NMI | ||
512 | * interrupt handlers to ensure they call nmi_enter() so this | ||
513 | * check would be correct. | ||
514 | */ | ||
515 | if (IS_ENABLED(CONFIG_BOOKE) || !irqs_disabled() || in_nmi()) { | ||
516 | set_dec(1); | ||
517 | } else { | ||
518 | hard_irq_disable(); | ||
519 | local_paca->irq_happened |= PACA_IRQ_DEC; | ||
520 | } | ||
521 | preempt_enable(); | ||
522 | } | ||
523 | |||
516 | #else /* 32-bit */ | 524 | #else /* 32-bit */ |
517 | 525 | ||
518 | DEFINE_PER_CPU(u8, irq_work_pending); | 526 | DEFINE_PER_CPU(u8, irq_work_pending); |
@@ -521,8 +529,6 @@ DEFINE_PER_CPU(u8, irq_work_pending); | |||
521 | #define test_irq_work_pending() __this_cpu_read(irq_work_pending) | 529 | #define test_irq_work_pending() __this_cpu_read(irq_work_pending) |
522 | #define clear_irq_work_pending() __this_cpu_write(irq_work_pending, 0) | 530 | #define clear_irq_work_pending() __this_cpu_write(irq_work_pending, 0) |
523 | 531 | ||
524 | #endif /* 32 vs 64 bit */ | ||
525 | |||
526 | void arch_irq_work_raise(void) | 532 | void arch_irq_work_raise(void) |
527 | { | 533 | { |
528 | preempt_disable(); | 534 | preempt_disable(); |
@@ -531,6 +537,8 @@ void arch_irq_work_raise(void) | |||
531 | preempt_enable(); | 537 | preempt_enable(); |
532 | } | 538 | } |
533 | 539 | ||
540 | #endif /* 32 vs 64 bit */ | ||
541 | |||
534 | #else /* CONFIG_IRQ_WORK */ | 542 | #else /* CONFIG_IRQ_WORK */ |
535 | 543 | ||
536 | #define test_irq_work_pending() 0 | 544 | #define test_irq_work_pending() 0 |
@@ -538,60 +546,16 @@ void arch_irq_work_raise(void) | |||
538 | 546 | ||
539 | #endif /* CONFIG_IRQ_WORK */ | 547 | #endif /* CONFIG_IRQ_WORK */ |
540 | 548 | ||
541 | static void __timer_interrupt(void) | ||
542 | { | ||
543 | struct pt_regs *regs = get_irq_regs(); | ||
544 | u64 *next_tb = this_cpu_ptr(&decrementers_next_tb); | ||
545 | struct clock_event_device *evt = this_cpu_ptr(&decrementers); | ||
546 | u64 now; | ||
547 | |||
548 | trace_timer_interrupt_entry(regs); | ||
549 | |||
550 | if (test_irq_work_pending()) { | ||
551 | clear_irq_work_pending(); | ||
552 | irq_work_run(); | ||
553 | } | ||
554 | |||
555 | now = get_tb_or_rtc(); | ||
556 | if (now >= *next_tb) { | ||
557 | *next_tb = ~(u64)0; | ||
558 | if (evt->event_handler) | ||
559 | evt->event_handler(evt); | ||
560 | __this_cpu_inc(irq_stat.timer_irqs_event); | ||
561 | } else { | ||
562 | now = *next_tb - now; | ||
563 | if (now <= decrementer_max) | ||
564 | set_dec(now); | ||
565 | /* We may have raced with new irq work */ | ||
566 | if (test_irq_work_pending()) | ||
567 | set_dec(1); | ||
568 | __this_cpu_inc(irq_stat.timer_irqs_others); | ||
569 | } | ||
570 | |||
571 | #ifdef CONFIG_PPC64 | ||
572 | /* collect purr register values often, for accurate calculations */ | ||
573 | if (firmware_has_feature(FW_FEATURE_SPLPAR)) { | ||
574 | struct cpu_usage *cu = this_cpu_ptr(&cpu_usage_array); | ||
575 | cu->current_tb = mfspr(SPRN_PURR); | ||
576 | } | ||
577 | #endif | ||
578 | |||
579 | trace_timer_interrupt_exit(regs); | ||
580 | } | ||
581 | |||
582 | /* | 549 | /* |
583 | * timer_interrupt - gets called when the decrementer overflows, | 550 | * timer_interrupt - gets called when the decrementer overflows, |
584 | * with interrupts disabled. | 551 | * with interrupts disabled. |
585 | */ | 552 | */ |
586 | void timer_interrupt(struct pt_regs * regs) | 553 | void timer_interrupt(struct pt_regs *regs) |
587 | { | 554 | { |
588 | struct pt_regs *old_regs; | 555 | struct clock_event_device *evt = this_cpu_ptr(&decrementers); |
589 | u64 *next_tb = this_cpu_ptr(&decrementers_next_tb); | 556 | u64 *next_tb = this_cpu_ptr(&decrementers_next_tb); |
590 | 557 | struct pt_regs *old_regs; | |
591 | /* Ensure a positive value is written to the decrementer, or else | 558 | u64 now; |
592 | * some CPUs will continue to take decrementer exceptions. | ||
593 | */ | ||
594 | set_dec(decrementer_max); | ||
595 | 559 | ||
596 | /* Some implementations of hotplug will get timer interrupts while | 560 | /* Some implementations of hotplug will get timer interrupts while |
597 | * offline, just ignore these and we also need to set | 561 | * offline, just ignore these and we also need to set |
@@ -599,11 +563,23 @@ void timer_interrupt(struct pt_regs * regs) | |||
599 | * don't replay timer interrupt when return, otherwise we'll trap | 563 | * don't replay timer interrupt when return, otherwise we'll trap |
600 | * here infinitely :( | 564 | * here infinitely :( |
601 | */ | 565 | */ |
602 | if (!cpu_online(smp_processor_id())) { | 566 | if (unlikely(!cpu_online(smp_processor_id()))) { |
603 | *next_tb = ~(u64)0; | 567 | *next_tb = ~(u64)0; |
568 | set_dec(decrementer_max); | ||
604 | return; | 569 | return; |
605 | } | 570 | } |
606 | 571 | ||
572 | /* Ensure a positive value is written to the decrementer, or else | ||
573 | * some CPUs will continue to take decrementer exceptions. When the | ||
574 | * PPC_WATCHDOG (decrementer based) is configured, keep this at most | ||
575 | * 31 bits, which is about 4 seconds on most systems, which gives | ||
576 | * the watchdog a chance of catching timer interrupt hard lockups. | ||
577 | */ | ||
578 | if (IS_ENABLED(CONFIG_PPC_WATCHDOG)) | ||
579 | set_dec(0x7fffffff); | ||
580 | else | ||
581 | set_dec(decrementer_max); | ||
582 | |||
607 | /* Conditionally hard-enable interrupts now that the DEC has been | 583 | /* Conditionally hard-enable interrupts now that the DEC has been |
608 | * bumped to its maximum value | 584 | * bumped to its maximum value |
609 | */ | 585 | */ |
@@ -617,13 +593,46 @@ void timer_interrupt(struct pt_regs * regs) | |||
617 | 593 | ||
618 | old_regs = set_irq_regs(regs); | 594 | old_regs = set_irq_regs(regs); |
619 | irq_enter(); | 595 | irq_enter(); |
596 | trace_timer_interrupt_entry(regs); | ||
597 | |||
598 | if (test_irq_work_pending()) { | ||
599 | clear_irq_work_pending(); | ||
600 | irq_work_run(); | ||
601 | } | ||
602 | |||
603 | now = get_tb_or_rtc(); | ||
604 | if (now >= *next_tb) { | ||
605 | *next_tb = ~(u64)0; | ||
606 | if (evt->event_handler) | ||
607 | evt->event_handler(evt); | ||
608 | __this_cpu_inc(irq_stat.timer_irqs_event); | ||
609 | } else { | ||
610 | now = *next_tb - now; | ||
611 | if (now <= decrementer_max) | ||
612 | set_dec(now); | ||
613 | /* We may have raced with new irq work */ | ||
614 | if (test_irq_work_pending()) | ||
615 | set_dec(1); | ||
616 | __this_cpu_inc(irq_stat.timer_irqs_others); | ||
617 | } | ||
620 | 618 | ||
621 | __timer_interrupt(); | 619 | trace_timer_interrupt_exit(regs); |
622 | irq_exit(); | 620 | irq_exit(); |
623 | set_irq_regs(old_regs); | 621 | set_irq_regs(old_regs); |
624 | } | 622 | } |
625 | EXPORT_SYMBOL(timer_interrupt); | 623 | EXPORT_SYMBOL(timer_interrupt); |
626 | 624 | ||
625 | #ifdef CONFIG_GENERIC_CLOCKEVENTS_BROADCAST | ||
626 | void timer_broadcast_interrupt(void) | ||
627 | { | ||
628 | u64 *next_tb = this_cpu_ptr(&decrementers_next_tb); | ||
629 | |||
630 | *next_tb = ~(u64)0; | ||
631 | tick_receive_broadcast(); | ||
632 | __this_cpu_inc(irq_stat.broadcast_irqs_event); | ||
633 | } | ||
634 | #endif | ||
635 | |||
627 | /* | 636 | /* |
628 | * Hypervisor decrementer interrupts shouldn't occur but are sometimes | 637 | * Hypervisor decrementer interrupts shouldn't occur but are sometimes |
629 | * left pending on exit from a KVM guest. We don't need to do anything | 638 | * left pending on exit from a KVM guest. We don't need to do anything |
@@ -781,21 +790,19 @@ void __init generic_calibrate_decr(void) | |||
781 | } | 790 | } |
782 | } | 791 | } |
783 | 792 | ||
784 | int update_persistent_clock(struct timespec now) | 793 | int update_persistent_clock64(struct timespec64 now) |
785 | { | 794 | { |
786 | struct rtc_time tm; | 795 | struct rtc_time tm; |
787 | 796 | ||
788 | if (!ppc_md.set_rtc_time) | 797 | if (!ppc_md.set_rtc_time) |
789 | return -ENODEV; | 798 | return -ENODEV; |
790 | 799 | ||
791 | to_tm(now.tv_sec + 1 + timezone_offset, &tm); | 800 | rtc_time64_to_tm(now.tv_sec + 1 + timezone_offset, &tm); |
792 | tm.tm_year -= 1900; | ||
793 | tm.tm_mon -= 1; | ||
794 | 801 | ||
795 | return ppc_md.set_rtc_time(&tm); | 802 | return ppc_md.set_rtc_time(&tm); |
796 | } | 803 | } |
797 | 804 | ||
798 | static void __read_persistent_clock(struct timespec *ts) | 805 | static void __read_persistent_clock(struct timespec64 *ts) |
799 | { | 806 | { |
800 | struct rtc_time tm; | 807 | struct rtc_time tm; |
801 | static int first = 1; | 808 | static int first = 1; |
@@ -819,11 +826,10 @@ static void __read_persistent_clock(struct timespec *ts) | |||
819 | } | 826 | } |
820 | ppc_md.get_rtc_time(&tm); | 827 | ppc_md.get_rtc_time(&tm); |
821 | 828 | ||
822 | ts->tv_sec = mktime(tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, | 829 | ts->tv_sec = rtc_tm_to_time64(&tm); |
823 | tm.tm_hour, tm.tm_min, tm.tm_sec); | ||
824 | } | 830 | } |
825 | 831 | ||
826 | void read_persistent_clock(struct timespec *ts) | 832 | void read_persistent_clock64(struct timespec64 *ts) |
827 | { | 833 | { |
828 | __read_persistent_clock(ts); | 834 | __read_persistent_clock(ts); |
829 | 835 | ||
@@ -971,15 +977,6 @@ static int decrementer_shutdown(struct clock_event_device *dev) | |||
971 | return 0; | 977 | return 0; |
972 | } | 978 | } |
973 | 979 | ||
974 | /* Interrupt handler for the timer broadcast IPI */ | ||
975 | void tick_broadcast_ipi_handler(void) | ||
976 | { | ||
977 | u64 *next_tb = this_cpu_ptr(&decrementers_next_tb); | ||
978 | |||
979 | *next_tb = get_tb_or_rtc(); | ||
980 | __timer_interrupt(); | ||
981 | } | ||
982 | |||
983 | static void register_decrementer_clockevent(int cpu) | 980 | static void register_decrementer_clockevent(int cpu) |
984 | { | 981 | { |
985 | struct clock_event_device *dec = &per_cpu(decrementers, cpu); | 982 | struct clock_event_device *dec = &per_cpu(decrementers, cpu); |
@@ -1141,56 +1138,6 @@ void __init time_init(void) | |||
1141 | #endif | 1138 | #endif |
1142 | } | 1139 | } |
1143 | 1140 | ||
1144 | |||
1145 | #define FEBRUARY 2 | ||
1146 | #define STARTOFTIME 1970 | ||
1147 | #define SECDAY 86400L | ||
1148 | #define SECYR (SECDAY * 365) | ||
1149 | #define leapyear(year) ((year) % 4 == 0 && \ | ||
1150 | ((year) % 100 != 0 || (year) % 400 == 0)) | ||
1151 | #define days_in_year(a) (leapyear(a) ? 366 : 365) | ||
1152 | #define days_in_month(a) (month_days[(a) - 1]) | ||
1153 | |||
1154 | static int month_days[12] = { | ||
1155 | 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 | ||
1156 | }; | ||
1157 | |||
1158 | void to_tm(int tim, struct rtc_time * tm) | ||
1159 | { | ||
1160 | register int i; | ||
1161 | register long hms, day; | ||
1162 | |||
1163 | day = tim / SECDAY; | ||
1164 | hms = tim % SECDAY; | ||
1165 | |||
1166 | /* Hours, minutes, seconds are easy */ | ||
1167 | tm->tm_hour = hms / 3600; | ||
1168 | tm->tm_min = (hms % 3600) / 60; | ||
1169 | tm->tm_sec = (hms % 3600) % 60; | ||
1170 | |||
1171 | /* Number of years in days */ | ||
1172 | for (i = STARTOFTIME; day >= days_in_year(i); i++) | ||
1173 | day -= days_in_year(i); | ||
1174 | tm->tm_year = i; | ||
1175 | |||
1176 | /* Number of months in days left */ | ||
1177 | if (leapyear(tm->tm_year)) | ||
1178 | days_in_month(FEBRUARY) = 29; | ||
1179 | for (i = 1; day >= days_in_month(i); i++) | ||
1180 | day -= days_in_month(i); | ||
1181 | days_in_month(FEBRUARY) = 28; | ||
1182 | tm->tm_mon = i; | ||
1183 | |||
1184 | /* Days are what is left over (+1) from all that. */ | ||
1185 | tm->tm_mday = day + 1; | ||
1186 | |||
1187 | /* | ||
1188 | * No-one uses the day of the week. | ||
1189 | */ | ||
1190 | tm->tm_wday = -1; | ||
1191 | } | ||
1192 | EXPORT_SYMBOL(to_tm); | ||
1193 | |||
1194 | /* | 1141 | /* |
1195 | * Divide a 128-bit dividend by a 32-bit divisor, leaving a 128 bit | 1142 | * Divide a 128-bit dividend by a 32-bit divisor, leaving a 128 bit |
1196 | * result. | 1143 | * result. |
diff --git a/arch/powerpc/kernel/tm.S b/arch/powerpc/kernel/tm.S index b92ac8e711db..ff12f47a96b6 100644 --- a/arch/powerpc/kernel/tm.S +++ b/arch/powerpc/kernel/tm.S | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <asm/ptrace.h> | 12 | #include <asm/ptrace.h> |
13 | #include <asm/reg.h> | 13 | #include <asm/reg.h> |
14 | #include <asm/bug.h> | 14 | #include <asm/bug.h> |
15 | #include <asm/export.h> | ||
15 | 16 | ||
16 | #ifdef CONFIG_VSX | 17 | #ifdef CONFIG_VSX |
17 | /* See fpu.S, this is borrowed from there */ | 18 | /* See fpu.S, this is borrowed from there */ |
@@ -55,6 +56,16 @@ _GLOBAL(tm_enable) | |||
55 | or r4, r4, r3 | 56 | or r4, r4, r3 |
56 | mtmsrd r4 | 57 | mtmsrd r4 |
57 | 1: blr | 58 | 1: blr |
59 | EXPORT_SYMBOL_GPL(tm_enable); | ||
60 | |||
61 | _GLOBAL(tm_disable) | ||
62 | mfmsr r4 | ||
63 | li r3, MSR_TM >> 32 | ||
64 | sldi r3, r3, 32 | ||
65 | andc r4, r4, r3 | ||
66 | mtmsrd r4 | ||
67 | blr | ||
68 | EXPORT_SYMBOL_GPL(tm_disable); | ||
58 | 69 | ||
59 | _GLOBAL(tm_save_sprs) | 70 | _GLOBAL(tm_save_sprs) |
60 | mfspr r0, SPRN_TFHAR | 71 | mfspr r0, SPRN_TFHAR |
@@ -78,6 +89,7 @@ _GLOBAL(tm_restore_sprs) | |||
78 | _GLOBAL(tm_abort) | 89 | _GLOBAL(tm_abort) |
79 | TABORT(R3) | 90 | TABORT(R3) |
80 | blr | 91 | blr |
92 | EXPORT_SYMBOL_GPL(tm_abort); | ||
81 | 93 | ||
82 | /* void tm_reclaim(struct thread_struct *thread, | 94 | /* void tm_reclaim(struct thread_struct *thread, |
83 | * uint8_t cause) | 95 | * uint8_t cause) |
diff --git a/arch/powerpc/kernel/trace/ftrace.c b/arch/powerpc/kernel/trace/ftrace.c index 4741fe112f05..c076a32093fd 100644 --- a/arch/powerpc/kernel/trace/ftrace.c +++ b/arch/powerpc/kernel/trace/ftrace.c | |||
@@ -357,6 +357,8 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) | |||
357 | { | 357 | { |
358 | unsigned int op[2]; | 358 | unsigned int op[2]; |
359 | void *ip = (void *)rec->ip; | 359 | void *ip = (void *)rec->ip; |
360 | unsigned long entry, ptr, tramp; | ||
361 | struct module *mod = rec->arch.mod; | ||
360 | 362 | ||
361 | /* read where this goes */ | 363 | /* read where this goes */ |
362 | if (probe_kernel_read(op, ip, sizeof(op))) | 364 | if (probe_kernel_read(op, ip, sizeof(op))) |
@@ -368,19 +370,44 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) | |||
368 | return -EINVAL; | 370 | return -EINVAL; |
369 | } | 371 | } |
370 | 372 | ||
371 | /* If we never set up a trampoline to ftrace_caller, then bail */ | 373 | /* If we never set up ftrace trampoline(s), then bail */ |
372 | if (!rec->arch.mod->arch.tramp) { | 374 | #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS |
375 | if (!mod->arch.tramp || !mod->arch.tramp_regs) { | ||
376 | #else | ||
377 | if (!mod->arch.tramp) { | ||
378 | #endif | ||
373 | pr_err("No ftrace trampoline\n"); | 379 | pr_err("No ftrace trampoline\n"); |
374 | return -EINVAL; | 380 | return -EINVAL; |
375 | } | 381 | } |
376 | 382 | ||
383 | #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS | ||
384 | if (rec->flags & FTRACE_FL_REGS) | ||
385 | tramp = mod->arch.tramp_regs; | ||
386 | else | ||
387 | #endif | ||
388 | tramp = mod->arch.tramp; | ||
389 | |||
390 | if (module_trampoline_target(mod, tramp, &ptr)) { | ||
391 | pr_err("Failed to get trampoline target\n"); | ||
392 | return -EFAULT; | ||
393 | } | ||
394 | |||
395 | pr_devel("trampoline target %lx", ptr); | ||
396 | |||
397 | entry = ppc_global_function_entry((void *)addr); | ||
398 | /* This should match what was called */ | ||
399 | if (ptr != entry) { | ||
400 | pr_err("addr %lx does not match expected %lx\n", ptr, entry); | ||
401 | return -EINVAL; | ||
402 | } | ||
403 | |||
377 | /* Ensure branch is within 24 bits */ | 404 | /* Ensure branch is within 24 bits */ |
378 | if (!create_branch(ip, rec->arch.mod->arch.tramp, BRANCH_SET_LINK)) { | 405 | if (!create_branch(ip, tramp, BRANCH_SET_LINK)) { |
379 | pr_err("Branch out of range\n"); | 406 | pr_err("Branch out of range\n"); |
380 | return -EINVAL; | 407 | return -EINVAL; |
381 | } | 408 | } |
382 | 409 | ||
383 | if (patch_branch(ip, rec->arch.mod->arch.tramp, BRANCH_SET_LINK)) { | 410 | if (patch_branch(ip, tramp, BRANCH_SET_LINK)) { |
384 | pr_err("REL24 out of range!\n"); | 411 | pr_err("REL24 out of range!\n"); |
385 | return -EINVAL; | 412 | return -EINVAL; |
386 | } | 413 | } |
@@ -388,14 +415,6 @@ __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) | |||
388 | return 0; | 415 | return 0; |
389 | } | 416 | } |
390 | 417 | ||
391 | #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS | ||
392 | int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, | ||
393 | unsigned long addr) | ||
394 | { | ||
395 | return ftrace_make_call(rec, addr); | ||
396 | } | ||
397 | #endif | ||
398 | |||
399 | #else /* !CONFIG_PPC64: */ | 418 | #else /* !CONFIG_PPC64: */ |
400 | static int | 419 | static int |
401 | __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) | 420 | __ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) |
@@ -472,53 +491,158 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr) | |||
472 | #endif /* CONFIG_MODULES */ | 491 | #endif /* CONFIG_MODULES */ |
473 | } | 492 | } |
474 | 493 | ||
475 | int ftrace_update_ftrace_func(ftrace_func_t func) | 494 | #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS |
495 | #ifdef CONFIG_MODULES | ||
496 | static int | ||
497 | __ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, | ||
498 | unsigned long addr) | ||
476 | { | 499 | { |
477 | unsigned long ip = (unsigned long)(&ftrace_call); | 500 | unsigned int op; |
478 | unsigned int old, new; | 501 | unsigned long ip = rec->ip; |
479 | int ret; | 502 | unsigned long entry, ptr, tramp; |
503 | struct module *mod = rec->arch.mod; | ||
480 | 504 | ||
481 | old = *(unsigned int *)&ftrace_call; | 505 | /* If we never set up ftrace trampolines, then bail */ |
482 | new = ftrace_call_replace(ip, (unsigned long)func, 1); | 506 | if (!mod->arch.tramp || !mod->arch.tramp_regs) { |
483 | ret = ftrace_modify_code(ip, old, new); | 507 | pr_err("No ftrace trampoline\n"); |
508 | return -EINVAL; | ||
509 | } | ||
484 | 510 | ||
485 | return ret; | 511 | /* read where this goes */ |
486 | } | 512 | if (probe_kernel_read(&op, (void *)ip, sizeof(int))) { |
513 | pr_err("Fetching opcode failed.\n"); | ||
514 | return -EFAULT; | ||
515 | } | ||
487 | 516 | ||
488 | static int __ftrace_replace_code(struct dyn_ftrace *rec, int enable) | 517 | /* Make sure that that this is still a 24bit jump */ |
489 | { | 518 | if (!is_bl_op(op)) { |
490 | unsigned long ftrace_addr = (unsigned long)FTRACE_ADDR; | 519 | pr_err("Not expected bl: opcode is %x\n", op); |
491 | int ret; | 520 | return -EINVAL; |
521 | } | ||
522 | |||
523 | /* lets find where the pointer goes */ | ||
524 | tramp = find_bl_target(ip, op); | ||
525 | entry = ppc_global_function_entry((void *)old_addr); | ||
526 | |||
527 | pr_devel("ip:%lx jumps to %lx", ip, tramp); | ||
492 | 528 | ||
493 | ret = ftrace_update_record(rec, enable); | 529 | if (tramp != entry) { |
530 | /* old_addr is not within range, so we must have used a trampoline */ | ||
531 | if (module_trampoline_target(mod, tramp, &ptr)) { | ||
532 | pr_err("Failed to get trampoline target\n"); | ||
533 | return -EFAULT; | ||
534 | } | ||
535 | |||
536 | pr_devel("trampoline target %lx", ptr); | ||
537 | |||
538 | /* This should match what was called */ | ||
539 | if (ptr != entry) { | ||
540 | pr_err("addr %lx does not match expected %lx\n", ptr, entry); | ||
541 | return -EINVAL; | ||
542 | } | ||
543 | } | ||
544 | |||
545 | /* The new target may be within range */ | ||
546 | if (test_24bit_addr(ip, addr)) { | ||
547 | /* within range */ | ||
548 | if (patch_branch((unsigned int *)ip, addr, BRANCH_SET_LINK)) { | ||
549 | pr_err("REL24 out of range!\n"); | ||
550 | return -EINVAL; | ||
551 | } | ||
494 | 552 | ||
495 | switch (ret) { | ||
496 | case FTRACE_UPDATE_IGNORE: | ||
497 | return 0; | 553 | return 0; |
498 | case FTRACE_UPDATE_MAKE_CALL: | 554 | } |
499 | return ftrace_make_call(rec, ftrace_addr); | 555 | |
500 | case FTRACE_UPDATE_MAKE_NOP: | 556 | if (rec->flags & FTRACE_FL_REGS) |
501 | return ftrace_make_nop(NULL, rec, ftrace_addr); | 557 | tramp = mod->arch.tramp_regs; |
558 | else | ||
559 | tramp = mod->arch.tramp; | ||
560 | |||
561 | if (module_trampoline_target(mod, tramp, &ptr)) { | ||
562 | pr_err("Failed to get trampoline target\n"); | ||
563 | return -EFAULT; | ||
564 | } | ||
565 | |||
566 | pr_devel("trampoline target %lx", ptr); | ||
567 | |||
568 | entry = ppc_global_function_entry((void *)addr); | ||
569 | /* This should match what was called */ | ||
570 | if (ptr != entry) { | ||
571 | pr_err("addr %lx does not match expected %lx\n", ptr, entry); | ||
572 | return -EINVAL; | ||
573 | } | ||
574 | |||
575 | /* Ensure branch is within 24 bits */ | ||
576 | if (!create_branch((unsigned int *)ip, tramp, BRANCH_SET_LINK)) { | ||
577 | pr_err("Branch out of range\n"); | ||
578 | return -EINVAL; | ||
579 | } | ||
580 | |||
581 | if (patch_branch((unsigned int *)ip, tramp, BRANCH_SET_LINK)) { | ||
582 | pr_err("REL24 out of range!\n"); | ||
583 | return -EINVAL; | ||
502 | } | 584 | } |
503 | 585 | ||
504 | return 0; | 586 | return 0; |
505 | } | 587 | } |
588 | #endif | ||
506 | 589 | ||
507 | void ftrace_replace_code(int enable) | 590 | int ftrace_modify_call(struct dyn_ftrace *rec, unsigned long old_addr, |
591 | unsigned long addr) | ||
508 | { | 592 | { |
509 | struct ftrace_rec_iter *iter; | 593 | unsigned long ip = rec->ip; |
510 | struct dyn_ftrace *rec; | 594 | unsigned int old, new; |
595 | |||
596 | /* | ||
597 | * If the calling address is more that 24 bits away, | ||
598 | * then we had to use a trampoline to make the call. | ||
599 | * Otherwise just update the call site. | ||
600 | */ | ||
601 | if (test_24bit_addr(ip, addr) && test_24bit_addr(ip, old_addr)) { | ||
602 | /* within range */ | ||
603 | old = ftrace_call_replace(ip, old_addr, 1); | ||
604 | new = ftrace_call_replace(ip, addr, 1); | ||
605 | return ftrace_modify_code(ip, old, new); | ||
606 | } | ||
607 | |||
608 | #ifdef CONFIG_MODULES | ||
609 | /* | ||
610 | * Out of range jumps are called from modules. | ||
611 | */ | ||
612 | if (!rec->arch.mod) { | ||
613 | pr_err("No module loaded\n"); | ||
614 | return -EINVAL; | ||
615 | } | ||
616 | |||
617 | return __ftrace_modify_call(rec, old_addr, addr); | ||
618 | #else | ||
619 | /* We should not get here without modules */ | ||
620 | return -EINVAL; | ||
621 | #endif /* CONFIG_MODULES */ | ||
622 | } | ||
623 | #endif | ||
624 | |||
625 | int ftrace_update_ftrace_func(ftrace_func_t func) | ||
626 | { | ||
627 | unsigned long ip = (unsigned long)(&ftrace_call); | ||
628 | unsigned int old, new; | ||
511 | int ret; | 629 | int ret; |
512 | 630 | ||
513 | for (iter = ftrace_rec_iter_start(); iter; | 631 | old = *(unsigned int *)&ftrace_call; |
514 | iter = ftrace_rec_iter_next(iter)) { | 632 | new = ftrace_call_replace(ip, (unsigned long)func, 1); |
515 | rec = ftrace_rec_iter_record(iter); | 633 | ret = ftrace_modify_code(ip, old, new); |
516 | ret = __ftrace_replace_code(rec, enable); | 634 | |
517 | if (ret) { | 635 | #ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS |
518 | ftrace_bug(ret, rec); | 636 | /* Also update the regs callback function */ |
519 | return; | 637 | if (!ret) { |
520 | } | 638 | ip = (unsigned long)(&ftrace_regs_call); |
639 | old = *(unsigned int *)&ftrace_regs_call; | ||
640 | new = ftrace_call_replace(ip, (unsigned long)func, 1); | ||
641 | ret = ftrace_modify_code(ip, old, new); | ||
521 | } | 642 | } |
643 | #endif | ||
644 | |||
645 | return ret; | ||
522 | } | 646 | } |
523 | 647 | ||
524 | /* | 648 | /* |
@@ -538,7 +662,6 @@ int __init ftrace_dyn_arch_init(void) | |||
538 | 662 | ||
539 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 663 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
540 | 664 | ||
541 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
542 | extern void ftrace_graph_call(void); | 665 | extern void ftrace_graph_call(void); |
543 | extern void ftrace_graph_stub(void); | 666 | extern void ftrace_graph_stub(void); |
544 | 667 | ||
@@ -567,7 +690,6 @@ int ftrace_disable_ftrace_graph_caller(void) | |||
567 | 690 | ||
568 | return ftrace_modify_code(ip, old, new); | 691 | return ftrace_modify_code(ip, old, new); |
569 | } | 692 | } |
570 | #endif /* CONFIG_DYNAMIC_FTRACE */ | ||
571 | 693 | ||
572 | /* | 694 | /* |
573 | * Hook the return address and push it in the stack of return addrs | 695 | * Hook the return address and push it in the stack of return addrs |
diff --git a/arch/powerpc/kernel/trace/ftrace_32.S b/arch/powerpc/kernel/trace/ftrace_32.S index afef2c076282..2c29098f630f 100644 --- a/arch/powerpc/kernel/trace/ftrace_32.S +++ b/arch/powerpc/kernel/trace/ftrace_32.S | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <asm/ftrace.h> | 14 | #include <asm/ftrace.h> |
15 | #include <asm/export.h> | 15 | #include <asm/export.h> |
16 | 16 | ||
17 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
18 | _GLOBAL(mcount) | 17 | _GLOBAL(mcount) |
19 | _GLOBAL(_mcount) | 18 | _GLOBAL(_mcount) |
20 | /* | 19 | /* |
@@ -47,26 +46,7 @@ _GLOBAL(ftrace_graph_stub) | |||
47 | MCOUNT_RESTORE_FRAME | 46 | MCOUNT_RESTORE_FRAME |
48 | /* old link register ends up in ctr reg */ | 47 | /* old link register ends up in ctr reg */ |
49 | bctr | 48 | bctr |
50 | #else | ||
51 | _GLOBAL(mcount) | ||
52 | _GLOBAL(_mcount) | ||
53 | |||
54 | MCOUNT_SAVE_FRAME | ||
55 | 49 | ||
56 | subi r3, r3, MCOUNT_INSN_SIZE | ||
57 | LOAD_REG_ADDR(r5, ftrace_trace_function) | ||
58 | lwz r5,0(r5) | ||
59 | |||
60 | mtctr r5 | ||
61 | bctrl | ||
62 | nop | ||
63 | |||
64 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
65 | b ftrace_graph_caller | ||
66 | #endif | ||
67 | MCOUNT_RESTORE_FRAME | ||
68 | bctr | ||
69 | #endif | ||
70 | EXPORT_SYMBOL(_mcount) | 50 | EXPORT_SYMBOL(_mcount) |
71 | 51 | ||
72 | _GLOBAL(ftrace_stub) | 52 | _GLOBAL(ftrace_stub) |
diff --git a/arch/powerpc/kernel/trace/ftrace_64.S b/arch/powerpc/kernel/trace/ftrace_64.S index e5ccea19821e..e25f77c10a72 100644 --- a/arch/powerpc/kernel/trace/ftrace_64.S +++ b/arch/powerpc/kernel/trace/ftrace_64.S | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <asm/ppc-opcode.h> | 14 | #include <asm/ppc-opcode.h> |
15 | #include <asm/export.h> | 15 | #include <asm/export.h> |
16 | 16 | ||
17 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
18 | _GLOBAL(mcount) | 17 | _GLOBAL(mcount) |
19 | _GLOBAL(_mcount) | 18 | _GLOBAL(_mcount) |
20 | EXPORT_SYMBOL(_mcount) | 19 | EXPORT_SYMBOL(_mcount) |
@@ -23,34 +22,6 @@ EXPORT_SYMBOL(_mcount) | |||
23 | mtlr r0 | 22 | mtlr r0 |
24 | bctr | 23 | bctr |
25 | 24 | ||
26 | #else /* CONFIG_DYNAMIC_FTRACE */ | ||
27 | _GLOBAL_TOC(_mcount) | ||
28 | EXPORT_SYMBOL(_mcount) | ||
29 | /* Taken from output of objdump from lib64/glibc */ | ||
30 | mflr r3 | ||
31 | ld r11, 0(r1) | ||
32 | stdu r1, -112(r1) | ||
33 | std r3, 128(r1) | ||
34 | ld r4, 16(r11) | ||
35 | |||
36 | subi r3, r3, MCOUNT_INSN_SIZE | ||
37 | LOAD_REG_ADDR(r5,ftrace_trace_function) | ||
38 | ld r5,0(r5) | ||
39 | ld r5,0(r5) | ||
40 | mtctr r5 | ||
41 | bctrl | ||
42 | nop | ||
43 | |||
44 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
45 | b ftrace_graph_caller | ||
46 | #endif | ||
47 | ld r0, 128(r1) | ||
48 | mtlr r0 | ||
49 | addi r1, r1, 112 | ||
50 | _GLOBAL(ftrace_stub) | ||
51 | blr | ||
52 | #endif /* CONFIG_DYNAMIC_FTRACE */ | ||
53 | |||
54 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 25 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
55 | _GLOBAL(return_to_handler) | 26 | _GLOBAL(return_to_handler) |
56 | /* need to save return values */ | 27 | /* need to save return values */ |
diff --git a/arch/powerpc/kernel/trace/ftrace_64_mprofile.S b/arch/powerpc/kernel/trace/ftrace_64_mprofile.S index 3f3e81852422..9a5b5a513604 100644 --- a/arch/powerpc/kernel/trace/ftrace_64_mprofile.S +++ b/arch/powerpc/kernel/trace/ftrace_64_mprofile.S | |||
@@ -17,11 +17,10 @@ | |||
17 | #include <asm/bug.h> | 17 | #include <asm/bug.h> |
18 | #include <asm/ptrace.h> | 18 | #include <asm/ptrace.h> |
19 | 19 | ||
20 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
21 | /* | 20 | /* |
22 | * | 21 | * |
23 | * ftrace_caller() is the function that replaces _mcount() when ftrace is | 22 | * ftrace_caller()/ftrace_regs_caller() is the function that replaces _mcount() |
24 | * active. | 23 | * when ftrace is active. |
25 | * | 24 | * |
26 | * We arrive here after a function A calls function B, and we are the trace | 25 | * We arrive here after a function A calls function B, and we are the trace |
27 | * function for B. When we enter r1 points to A's stack frame, B has not yet | 26 | * function for B. When we enter r1 points to A's stack frame, B has not yet |
@@ -37,7 +36,7 @@ | |||
37 | * Our job is to save the register state into a struct pt_regs (on the stack) | 36 | * Our job is to save the register state into a struct pt_regs (on the stack) |
38 | * and then arrange for the ftrace function to be called. | 37 | * and then arrange for the ftrace function to be called. |
39 | */ | 38 | */ |
40 | _GLOBAL(ftrace_caller) | 39 | _GLOBAL(ftrace_regs_caller) |
41 | /* Save the original return address in A's stack frame */ | 40 | /* Save the original return address in A's stack frame */ |
42 | std r0,LRSAVE(r1) | 41 | std r0,LRSAVE(r1) |
43 | 42 | ||
@@ -47,6 +46,12 @@ _GLOBAL(ftrace_caller) | |||
47 | /* Save all gprs to pt_regs */ | 46 | /* Save all gprs to pt_regs */ |
48 | SAVE_GPR(0, r1) | 47 | SAVE_GPR(0, r1) |
49 | SAVE_10GPRS(2, r1) | 48 | SAVE_10GPRS(2, r1) |
49 | |||
50 | /* Ok to continue? */ | ||
51 | lbz r3, PACA_FTRACE_ENABLED(r13) | ||
52 | cmpdi r3, 0 | ||
53 | beq ftrace_no_trace | ||
54 | |||
50 | SAVE_10GPRS(12, r1) | 55 | SAVE_10GPRS(12, r1) |
51 | SAVE_10GPRS(22, r1) | 56 | SAVE_10GPRS(22, r1) |
52 | 57 | ||
@@ -94,8 +99,8 @@ _GLOBAL(ftrace_caller) | |||
94 | addi r6, r1 ,STACK_FRAME_OVERHEAD | 99 | addi r6, r1 ,STACK_FRAME_OVERHEAD |
95 | 100 | ||
96 | /* ftrace_call(r3, r4, r5, r6) */ | 101 | /* ftrace_call(r3, r4, r5, r6) */ |
97 | .globl ftrace_call | 102 | .globl ftrace_regs_call |
98 | ftrace_call: | 103 | ftrace_regs_call: |
99 | bl ftrace_stub | 104 | bl ftrace_stub |
100 | nop | 105 | nop |
101 | 106 | ||
@@ -156,6 +161,7 @@ ftrace_call: | |||
156 | bne- livepatch_handler | 161 | bne- livepatch_handler |
157 | #endif | 162 | #endif |
158 | 163 | ||
164 | ftrace_caller_common: | ||
159 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 165 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
160 | .globl ftrace_graph_call | 166 | .globl ftrace_graph_call |
161 | ftrace_graph_call: | 167 | ftrace_graph_call: |
@@ -168,6 +174,74 @@ _GLOBAL(ftrace_graph_stub) | |||
168 | _GLOBAL(ftrace_stub) | 174 | _GLOBAL(ftrace_stub) |
169 | blr | 175 | blr |
170 | 176 | ||
177 | ftrace_no_trace: | ||
178 | mflr r3 | ||
179 | mtctr r3 | ||
180 | REST_GPR(3, r1) | ||
181 | addi r1, r1, SWITCH_FRAME_SIZE | ||
182 | mtlr r0 | ||
183 | bctr | ||
184 | |||
185 | _GLOBAL(ftrace_caller) | ||
186 | /* Save the original return address in A's stack frame */ | ||
187 | std r0, LRSAVE(r1) | ||
188 | |||
189 | /* Create our stack frame + pt_regs */ | ||
190 | stdu r1, -SWITCH_FRAME_SIZE(r1) | ||
191 | |||
192 | /* Save all gprs to pt_regs */ | ||
193 | SAVE_8GPRS(3, r1) | ||
194 | |||
195 | lbz r3, PACA_FTRACE_ENABLED(r13) | ||
196 | cmpdi r3, 0 | ||
197 | beq ftrace_no_trace | ||
198 | |||
199 | /* Get the _mcount() call site out of LR */ | ||
200 | mflr r7 | ||
201 | std r7, _NIP(r1) | ||
202 | |||
203 | /* Save callee's TOC in the ABI compliant location */ | ||
204 | std r2, 24(r1) | ||
205 | ld r2, PACATOC(r13) /* get kernel TOC in r2 */ | ||
206 | |||
207 | addis r3, r2, function_trace_op@toc@ha | ||
208 | addi r3, r3, function_trace_op@toc@l | ||
209 | ld r5, 0(r3) | ||
210 | |||
211 | /* Calculate ip from nip-4 into r3 for call below */ | ||
212 | subi r3, r7, MCOUNT_INSN_SIZE | ||
213 | |||
214 | /* Put the original return address in r4 as parent_ip */ | ||
215 | mr r4, r0 | ||
216 | |||
217 | /* Set pt_regs to NULL */ | ||
218 | li r6, 0 | ||
219 | |||
220 | /* ftrace_call(r3, r4, r5, r6) */ | ||
221 | .globl ftrace_call | ||
222 | ftrace_call: | ||
223 | bl ftrace_stub | ||
224 | nop | ||
225 | |||
226 | ld r3, _NIP(r1) | ||
227 | mtctr r3 | ||
228 | |||
229 | /* Restore gprs */ | ||
230 | REST_8GPRS(3,r1) | ||
231 | |||
232 | /* Restore callee's TOC */ | ||
233 | ld r2, 24(r1) | ||
234 | |||
235 | /* Pop our stack frame */ | ||
236 | addi r1, r1, SWITCH_FRAME_SIZE | ||
237 | |||
238 | /* Reload original LR */ | ||
239 | ld r0, LRSAVE(r1) | ||
240 | mtlr r0 | ||
241 | |||
242 | /* Handle function_graph or go back */ | ||
243 | b ftrace_caller_common | ||
244 | |||
171 | #ifdef CONFIG_LIVEPATCH | 245 | #ifdef CONFIG_LIVEPATCH |
172 | /* | 246 | /* |
173 | * This function runs in the mcount context, between two functions. As | 247 | * This function runs in the mcount context, between two functions. As |
@@ -236,8 +310,6 @@ livepatch_handler: | |||
236 | blr | 310 | blr |
237 | #endif /* CONFIG_LIVEPATCH */ | 311 | #endif /* CONFIG_LIVEPATCH */ |
238 | 312 | ||
239 | #endif /* CONFIG_DYNAMIC_FTRACE */ | ||
240 | |||
241 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 313 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
242 | _GLOBAL(ftrace_graph_caller) | 314 | _GLOBAL(ftrace_graph_caller) |
243 | stdu r1, -112(r1) | 315 | stdu r1, -112(r1) |
diff --git a/arch/powerpc/kernel/trace/ftrace_64_pg.S b/arch/powerpc/kernel/trace/ftrace_64_pg.S index f095358da96e..4c515c4023de 100644 --- a/arch/powerpc/kernel/trace/ftrace_64_pg.S +++ b/arch/powerpc/kernel/trace/ftrace_64_pg.S | |||
@@ -14,8 +14,11 @@ | |||
14 | #include <asm/ppc-opcode.h> | 14 | #include <asm/ppc-opcode.h> |
15 | #include <asm/export.h> | 15 | #include <asm/export.h> |
16 | 16 | ||
17 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
18 | _GLOBAL_TOC(ftrace_caller) | 17 | _GLOBAL_TOC(ftrace_caller) |
18 | lbz r3, PACA_FTRACE_ENABLED(r13) | ||
19 | cmpdi r3, 0 | ||
20 | beqlr | ||
21 | |||
19 | /* Taken from output of objdump from lib64/glibc */ | 22 | /* Taken from output of objdump from lib64/glibc */ |
20 | mflr r3 | 23 | mflr r3 |
21 | ld r11, 0(r1) | 24 | ld r11, 0(r1) |
@@ -39,7 +42,6 @@ _GLOBAL(ftrace_graph_stub) | |||
39 | 42 | ||
40 | _GLOBAL(ftrace_stub) | 43 | _GLOBAL(ftrace_stub) |
41 | blr | 44 | blr |
42 | #endif /* CONFIG_DYNAMIC_FTRACE */ | ||
43 | 45 | ||
44 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 46 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
45 | _GLOBAL(ftrace_graph_caller) | 47 | _GLOBAL(ftrace_graph_caller) |
diff --git a/arch/powerpc/kernel/vdso32/Makefile b/arch/powerpc/kernel/vdso32/Makefile index b8c434d1d459..50112d4473bb 100644 --- a/arch/powerpc/kernel/vdso32/Makefile +++ b/arch/powerpc/kernel/vdso32/Makefile | |||
@@ -8,8 +8,15 @@ obj-vdso32 = sigtramp.o gettimeofday.o datapage.o cacheflush.o note.o \ | |||
8 | 8 | ||
9 | # Build rules | 9 | # Build rules |
10 | 10 | ||
11 | ifeq ($(CONFIG_PPC32),y) | 11 | ifdef CROSS32_COMPILE |
12 | CROSS32CC := $(CC) | 12 | VDSOCC := $(CROSS32_COMPILE)gcc |
13 | else | ||
14 | VDSOCC := $(CC) | ||
15 | endif | ||
16 | |||
17 | CC32FLAGS := | ||
18 | ifdef CONFIG_PPC64 | ||
19 | CC32FLAGS += -m32 | ||
13 | endif | 20 | endif |
14 | 21 | ||
15 | targets := $(obj-vdso32) vdso32.so vdso32.so.dbg | 22 | targets := $(obj-vdso32) vdso32.so vdso32.so.dbg |
@@ -45,9 +52,9 @@ $(obj-vdso32): %.o: %.S FORCE | |||
45 | 52 | ||
46 | # actual build commands | 53 | # actual build commands |
47 | quiet_cmd_vdso32ld = VDSO32L $@ | 54 | quiet_cmd_vdso32ld = VDSO32L $@ |
48 | cmd_vdso32ld = $(CROSS32CC) $(c_flags) -o $@ -Wl,-T$(filter %.lds,$^) $(filter %.o,$^) | 55 | cmd_vdso32ld = $(VDSOCC) $(c_flags) $(CC32FLAGS) -o $@ -Wl,-T$(filter %.lds,$^) $(filter %.o,$^) |
49 | quiet_cmd_vdso32as = VDSO32A $@ | 56 | quiet_cmd_vdso32as = VDSO32A $@ |
50 | cmd_vdso32as = $(CROSS32CC) $(a_flags) -c -o $@ $< | 57 | cmd_vdso32as = $(VDSOCC) $(a_flags) $(CC32FLAGS) -c -o $@ $< |
51 | 58 | ||
52 | # install commands for the unstripped file | 59 | # install commands for the unstripped file |
53 | quiet_cmd_vdso_install = INSTALL $@ | 60 | quiet_cmd_vdso_install = INSTALL $@ |
diff --git a/arch/powerpc/kernel/vecemu.c b/arch/powerpc/kernel/vecemu.c index 8812085883fd..4acd3fb2b38e 100644 --- a/arch/powerpc/kernel/vecemu.c +++ b/arch/powerpc/kernel/vecemu.c | |||
@@ -8,6 +8,7 @@ | |||
8 | #include <linux/sched.h> | 8 | #include <linux/sched.h> |
9 | #include <asm/ptrace.h> | 9 | #include <asm/ptrace.h> |
10 | #include <asm/processor.h> | 10 | #include <asm/processor.h> |
11 | #include <asm/switch_to.h> | ||
11 | #include <linux/uaccess.h> | 12 | #include <linux/uaccess.h> |
12 | 13 | ||
13 | /* Functions in vector.S */ | 14 | /* Functions in vector.S */ |
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index dd10e6f1d1b7..5baac79df97e 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S | |||
@@ -153,6 +153,13 @@ SECTIONS | |||
153 | *(__rfi_flush_fixup) | 153 | *(__rfi_flush_fixup) |
154 | __stop___rfi_flush_fixup = .; | 154 | __stop___rfi_flush_fixup = .; |
155 | } | 155 | } |
156 | |||
157 | . = ALIGN(8); | ||
158 | __spec_barrier_fixup : AT(ADDR(__spec_barrier_fixup) - LOAD_OFFSET) { | ||
159 | __start___barrier_nospec_fixup = .; | ||
160 | *(__barrier_nospec_fixup) | ||
161 | __stop___barrier_nospec_fixup = .; | ||
162 | } | ||
156 | #endif | 163 | #endif |
157 | 164 | ||
158 | EXCEPTION_TABLE(0) | 165 | EXCEPTION_TABLE(0) |
diff --git a/arch/powerpc/kernel/watchdog.c b/arch/powerpc/kernel/watchdog.c index 6256dc3b0087..1d82274f7e9f 100644 --- a/arch/powerpc/kernel/watchdog.c +++ b/arch/powerpc/kernel/watchdog.c | |||
@@ -64,7 +64,7 @@ | |||
64 | * means the CPU(s) with their bit still set in the pending mask have had | 64 | * means the CPU(s) with their bit still set in the pending mask have had |
65 | * their heartbeat stop, and action is taken. | 65 | * their heartbeat stop, and action is taken. |
66 | * | 66 | * |
67 | * Some platforms implement true NMI IPIs, which can by used by the SMP | 67 | * Some platforms implement true NMI IPIs, which can be used by the SMP |
68 | * watchdog to detect an unresponsive CPU and pull it out of its stuck | 68 | * watchdog to detect an unresponsive CPU and pull it out of its stuck |
69 | * state with the NMI IPI, to get crash/debug data from it. This way the | 69 | * state with the NMI IPI, to get crash/debug data from it. This way the |
70 | * SMP watchdog can detect hardware interrupts off lockups. | 70 | * SMP watchdog can detect hardware interrupts off lockups. |
@@ -111,7 +111,13 @@ static inline void wd_smp_unlock(unsigned long *flags) | |||
111 | 111 | ||
112 | static void wd_lockup_ipi(struct pt_regs *regs) | 112 | static void wd_lockup_ipi(struct pt_regs *regs) |
113 | { | 113 | { |
114 | pr_emerg("CPU %d Hard LOCKUP\n", raw_smp_processor_id()); | 114 | int cpu = raw_smp_processor_id(); |
115 | u64 tb = get_tb(); | ||
116 | |||
117 | pr_emerg("CPU %d Hard LOCKUP\n", cpu); | ||
118 | pr_emerg("CPU %d TB:%lld, last heartbeat TB:%lld (%lldms ago)\n", | ||
119 | cpu, tb, per_cpu(wd_timer_tb, cpu), | ||
120 | tb_to_ns(tb - per_cpu(wd_timer_tb, cpu)) / 1000000); | ||
115 | print_modules(); | 121 | print_modules(); |
116 | print_irqtrace_events(current); | 122 | print_irqtrace_events(current); |
117 | if (regs) | 123 | if (regs) |
@@ -154,6 +160,9 @@ static void watchdog_smp_panic(int cpu, u64 tb) | |||
154 | 160 | ||
155 | pr_emerg("CPU %d detected hard LOCKUP on other CPUs %*pbl\n", | 161 | pr_emerg("CPU %d detected hard LOCKUP on other CPUs %*pbl\n", |
156 | cpu, cpumask_pr_args(&wd_smp_cpus_pending)); | 162 | cpu, cpumask_pr_args(&wd_smp_cpus_pending)); |
163 | pr_emerg("CPU %d TB:%lld, last SMP heartbeat TB:%lld (%lldms ago)\n", | ||
164 | cpu, tb, wd_smp_last_reset_tb, | ||
165 | tb_to_ns(tb - wd_smp_last_reset_tb) / 1000000); | ||
157 | 166 | ||
158 | if (!sysctl_hardlockup_all_cpu_backtrace) { | 167 | if (!sysctl_hardlockup_all_cpu_backtrace) { |
159 | /* | 168 | /* |
@@ -194,10 +203,19 @@ static void wd_smp_clear_cpu_pending(int cpu, u64 tb) | |||
194 | { | 203 | { |
195 | if (!cpumask_test_cpu(cpu, &wd_smp_cpus_pending)) { | 204 | if (!cpumask_test_cpu(cpu, &wd_smp_cpus_pending)) { |
196 | if (unlikely(cpumask_test_cpu(cpu, &wd_smp_cpus_stuck))) { | 205 | if (unlikely(cpumask_test_cpu(cpu, &wd_smp_cpus_stuck))) { |
206 | struct pt_regs *regs = get_irq_regs(); | ||
197 | unsigned long flags; | 207 | unsigned long flags; |
198 | 208 | ||
199 | pr_emerg("CPU %d became unstuck\n", cpu); | ||
200 | wd_smp_lock(&flags); | 209 | wd_smp_lock(&flags); |
210 | |||
211 | pr_emerg("CPU %d became unstuck TB:%lld\n", | ||
212 | cpu, tb); | ||
213 | print_irqtrace_events(current); | ||
214 | if (regs) | ||
215 | show_regs(regs); | ||
216 | else | ||
217 | dump_stack(); | ||
218 | |||
201 | cpumask_clear_cpu(cpu, &wd_smp_cpus_stuck); | 219 | cpumask_clear_cpu(cpu, &wd_smp_cpus_stuck); |
202 | wd_smp_unlock(&flags); | 220 | wd_smp_unlock(&flags); |
203 | } | 221 | } |
@@ -245,8 +263,6 @@ void soft_nmi_interrupt(struct pt_regs *regs) | |||
245 | 263 | ||
246 | tb = get_tb(); | 264 | tb = get_tb(); |
247 | if (tb - per_cpu(wd_timer_tb, cpu) >= wd_panic_timeout_tb) { | 265 | if (tb - per_cpu(wd_timer_tb, cpu) >= wd_panic_timeout_tb) { |
248 | per_cpu(wd_timer_tb, cpu) = tb; | ||
249 | |||
250 | wd_smp_lock(&flags); | 266 | wd_smp_lock(&flags); |
251 | if (cpumask_test_cpu(cpu, &wd_smp_cpus_stuck)) { | 267 | if (cpumask_test_cpu(cpu, &wd_smp_cpus_stuck)) { |
252 | wd_smp_unlock(&flags); | 268 | wd_smp_unlock(&flags); |
@@ -254,7 +270,11 @@ void soft_nmi_interrupt(struct pt_regs *regs) | |||
254 | } | 270 | } |
255 | set_cpu_stuck(cpu, tb); | 271 | set_cpu_stuck(cpu, tb); |
256 | 272 | ||
257 | pr_emerg("CPU %d self-detected hard LOCKUP @ %pS\n", cpu, (void *)regs->nip); | 273 | pr_emerg("CPU %d self-detected hard LOCKUP @ %pS\n", |
274 | cpu, (void *)regs->nip); | ||
275 | pr_emerg("CPU %d TB:%lld, last heartbeat TB:%lld (%lldms ago)\n", | ||
276 | cpu, tb, per_cpu(wd_timer_tb, cpu), | ||
277 | tb_to_ns(tb - per_cpu(wd_timer_tb, cpu)) / 1000000); | ||
258 | print_modules(); | 278 | print_modules(); |
259 | print_irqtrace_events(current); | 279 | print_irqtrace_events(current); |
260 | show_regs(regs); | 280 | show_regs(regs); |
diff --git a/arch/powerpc/kvm/book3s_64_mmu_radix.c b/arch/powerpc/kvm/book3s_64_mmu_radix.c index 361f42c8c73e..481da8f93fa4 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_radix.c +++ b/arch/powerpc/kvm/book3s_64_mmu_radix.c | |||
@@ -200,6 +200,7 @@ void kvmppc_radix_set_pte_at(struct kvm *kvm, unsigned long addr, | |||
200 | } | 200 | } |
201 | 201 | ||
202 | static struct kmem_cache *kvm_pte_cache; | 202 | static struct kmem_cache *kvm_pte_cache; |
203 | static struct kmem_cache *kvm_pmd_cache; | ||
203 | 204 | ||
204 | static pte_t *kvmppc_pte_alloc(void) | 205 | static pte_t *kvmppc_pte_alloc(void) |
205 | { | 206 | { |
@@ -217,6 +218,16 @@ static inline int pmd_is_leaf(pmd_t pmd) | |||
217 | return !!(pmd_val(pmd) & _PAGE_PTE); | 218 | return !!(pmd_val(pmd) & _PAGE_PTE); |
218 | } | 219 | } |
219 | 220 | ||
221 | static pmd_t *kvmppc_pmd_alloc(void) | ||
222 | { | ||
223 | return kmem_cache_alloc(kvm_pmd_cache, GFP_KERNEL); | ||
224 | } | ||
225 | |||
226 | static void kvmppc_pmd_free(pmd_t *pmdp) | ||
227 | { | ||
228 | kmem_cache_free(kvm_pmd_cache, pmdp); | ||
229 | } | ||
230 | |||
220 | static int kvmppc_create_pte(struct kvm *kvm, pte_t pte, unsigned long gpa, | 231 | static int kvmppc_create_pte(struct kvm *kvm, pte_t pte, unsigned long gpa, |
221 | unsigned int level, unsigned long mmu_seq) | 232 | unsigned int level, unsigned long mmu_seq) |
222 | { | 233 | { |
@@ -239,7 +250,7 @@ static int kvmppc_create_pte(struct kvm *kvm, pte_t pte, unsigned long gpa, | |||
239 | if (pud && pud_present(*pud) && !pud_huge(*pud)) | 250 | if (pud && pud_present(*pud) && !pud_huge(*pud)) |
240 | pmd = pmd_offset(pud, gpa); | 251 | pmd = pmd_offset(pud, gpa); |
241 | else if (level <= 1) | 252 | else if (level <= 1) |
242 | new_pmd = pmd_alloc_one(kvm->mm, gpa); | 253 | new_pmd = kvmppc_pmd_alloc(); |
243 | 254 | ||
244 | if (level == 0 && !(pmd && pmd_present(*pmd) && !pmd_is_leaf(*pmd))) | 255 | if (level == 0 && !(pmd && pmd_present(*pmd) && !pmd_is_leaf(*pmd))) |
245 | new_ptep = kvmppc_pte_alloc(); | 256 | new_ptep = kvmppc_pte_alloc(); |
@@ -382,7 +393,7 @@ static int kvmppc_create_pte(struct kvm *kvm, pte_t pte, unsigned long gpa, | |||
382 | if (new_pud) | 393 | if (new_pud) |
383 | pud_free(kvm->mm, new_pud); | 394 | pud_free(kvm->mm, new_pud); |
384 | if (new_pmd) | 395 | if (new_pmd) |
385 | pmd_free(kvm->mm, new_pmd); | 396 | kvmppc_pmd_free(new_pmd); |
386 | if (new_ptep) | 397 | if (new_ptep) |
387 | kvmppc_pte_free(new_ptep); | 398 | kvmppc_pte_free(new_ptep); |
388 | return ret; | 399 | return ret; |
@@ -758,7 +769,7 @@ void kvmppc_free_radix(struct kvm *kvm) | |||
758 | kvmppc_pte_free(pte); | 769 | kvmppc_pte_free(pte); |
759 | pmd_clear(pmd); | 770 | pmd_clear(pmd); |
760 | } | 771 | } |
761 | pmd_free(kvm->mm, pmd_offset(pud, 0)); | 772 | kvmppc_pmd_free(pmd_offset(pud, 0)); |
762 | pud_clear(pud); | 773 | pud_clear(pud); |
763 | } | 774 | } |
764 | pud_free(kvm->mm, pud_offset(pgd, 0)); | 775 | pud_free(kvm->mm, pud_offset(pgd, 0)); |
@@ -770,20 +781,35 @@ void kvmppc_free_radix(struct kvm *kvm) | |||
770 | 781 | ||
771 | static void pte_ctor(void *addr) | 782 | static void pte_ctor(void *addr) |
772 | { | 783 | { |
773 | memset(addr, 0, PTE_TABLE_SIZE); | 784 | memset(addr, 0, RADIX_PTE_TABLE_SIZE); |
785 | } | ||
786 | |||
787 | static void pmd_ctor(void *addr) | ||
788 | { | ||
789 | memset(addr, 0, RADIX_PMD_TABLE_SIZE); | ||
774 | } | 790 | } |
775 | 791 | ||
776 | int kvmppc_radix_init(void) | 792 | int kvmppc_radix_init(void) |
777 | { | 793 | { |
778 | unsigned long size = sizeof(void *) << PTE_INDEX_SIZE; | 794 | unsigned long size = sizeof(void *) << RADIX_PTE_INDEX_SIZE; |
779 | 795 | ||
780 | kvm_pte_cache = kmem_cache_create("kvm-pte", size, size, 0, pte_ctor); | 796 | kvm_pte_cache = kmem_cache_create("kvm-pte", size, size, 0, pte_ctor); |
781 | if (!kvm_pte_cache) | 797 | if (!kvm_pte_cache) |
782 | return -ENOMEM; | 798 | return -ENOMEM; |
799 | |||
800 | size = sizeof(void *) << RADIX_PMD_INDEX_SIZE; | ||
801 | |||
802 | kvm_pmd_cache = kmem_cache_create("kvm-pmd", size, size, 0, pmd_ctor); | ||
803 | if (!kvm_pmd_cache) { | ||
804 | kmem_cache_destroy(kvm_pte_cache); | ||
805 | return -ENOMEM; | ||
806 | } | ||
807 | |||
783 | return 0; | 808 | return 0; |
784 | } | 809 | } |
785 | 810 | ||
786 | void kvmppc_radix_exit(void) | 811 | void kvmppc_radix_exit(void) |
787 | { | 812 | { |
788 | kmem_cache_destroy(kvm_pte_cache); | 813 | kmem_cache_destroy(kvm_pte_cache); |
814 | kmem_cache_destroy(kvm_pmd_cache); | ||
789 | } | 815 | } |
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index 9963f65c212b..cb6d2313b19f 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c | |||
@@ -2912,8 +2912,12 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc) | |||
2912 | 2912 | ||
2913 | srcu_idx = srcu_read_lock(&vc->kvm->srcu); | 2913 | srcu_idx = srcu_read_lock(&vc->kvm->srcu); |
2914 | 2914 | ||
2915 | this_cpu_disable_ftrace(); | ||
2916 | |||
2915 | trap = __kvmppc_vcore_entry(); | 2917 | trap = __kvmppc_vcore_entry(); |
2916 | 2918 | ||
2919 | this_cpu_enable_ftrace(); | ||
2920 | |||
2917 | srcu_read_unlock(&vc->kvm->srcu, srcu_idx); | 2921 | srcu_read_unlock(&vc->kvm->srcu, srcu_idx); |
2918 | 2922 | ||
2919 | trace_hardirqs_off(); | 2923 | trace_hardirqs_off(); |
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S index 07ca1b2a7966..b97d261d3b89 100644 --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S | |||
@@ -342,6 +342,9 @@ kvm_start_guest: | |||
342 | 342 | ||
343 | ld r2,PACATOC(r13) | 343 | ld r2,PACATOC(r13) |
344 | 344 | ||
345 | li r0,0 | ||
346 | stb r0,PACA_FTRACE_ENABLED(r13) | ||
347 | |||
345 | li r0,KVM_HWTHREAD_IN_KVM | 348 | li r0,KVM_HWTHREAD_IN_KVM |
346 | stb r0,HSTATE_HWTHREAD_STATE(r13) | 349 | stb r0,HSTATE_HWTHREAD_STATE(r13) |
347 | 350 | ||
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile index 653901042ad7..d0ca13ad8231 100644 --- a/arch/powerpc/lib/Makefile +++ b/arch/powerpc/lib/Makefile | |||
@@ -26,13 +26,14 @@ obj-$(CONFIG_PPC_BOOK3S_64) += copyuser_power7.o copypage_power7.o \ | |||
26 | memcpy_power7.o | 26 | memcpy_power7.o |
27 | 27 | ||
28 | obj64-y += copypage_64.o copyuser_64.o mem_64.o hweight_64.o \ | 28 | obj64-y += copypage_64.o copyuser_64.o mem_64.o hweight_64.o \ |
29 | string_64.o memcpy_64.o memcmp_64.o pmem.o | 29 | memcpy_64.o pmem.o |
30 | 30 | ||
31 | obj64-$(CONFIG_SMP) += locks.o | 31 | obj64-$(CONFIG_SMP) += locks.o |
32 | obj64-$(CONFIG_ALTIVEC) += vmx-helper.o | 32 | obj64-$(CONFIG_ALTIVEC) += vmx-helper.o |
33 | obj64-$(CONFIG_KPROBES_SANITY_TEST) += test_emulate_step.o | 33 | obj64-$(CONFIG_KPROBES_SANITY_TEST) += test_emulate_step.o |
34 | 34 | ||
35 | obj-y += checksum_$(BITS).o checksum_wrappers.o | 35 | obj-y += checksum_$(BITS).o checksum_wrappers.o \ |
36 | string_$(BITS).o memcmp_$(BITS).o | ||
36 | 37 | ||
37 | obj-y += sstep.o ldstfp.o quad.o | 38 | obj-y += sstep.o ldstfp.o quad.o |
38 | obj64-y += quad.o | 39 | obj64-y += quad.o |
diff --git a/arch/powerpc/lib/checksum_32.S b/arch/powerpc/lib/checksum_32.S index 9a671c774b22..aa224069f93a 100644 --- a/arch/powerpc/lib/checksum_32.S +++ b/arch/powerpc/lib/checksum_32.S | |||
@@ -47,16 +47,25 @@ _GLOBAL(__csum_partial) | |||
47 | bdnz 2b | 47 | bdnz 2b |
48 | 21: srwi. r6,r4,4 /* # blocks of 4 words to do */ | 48 | 21: srwi. r6,r4,4 /* # blocks of 4 words to do */ |
49 | beq 3f | 49 | beq 3f |
50 | lwz r0,4(r3) | ||
50 | mtctr r6 | 51 | mtctr r6 |
51 | 22: lwz r0,4(r3) | ||
52 | lwz r6,8(r3) | 52 | lwz r6,8(r3) |
53 | adde r5,r5,r0 | ||
53 | lwz r7,12(r3) | 54 | lwz r7,12(r3) |
55 | adde r5,r5,r6 | ||
54 | lwzu r8,16(r3) | 56 | lwzu r8,16(r3) |
57 | adde r5,r5,r7 | ||
58 | bdz 23f | ||
59 | 22: lwz r0,4(r3) | ||
60 | adde r5,r5,r8 | ||
61 | lwz r6,8(r3) | ||
55 | adde r5,r5,r0 | 62 | adde r5,r5,r0 |
63 | lwz r7,12(r3) | ||
56 | adde r5,r5,r6 | 64 | adde r5,r5,r6 |
65 | lwzu r8,16(r3) | ||
57 | adde r5,r5,r7 | 66 | adde r5,r5,r7 |
58 | adde r5,r5,r8 | ||
59 | bdnz 22b | 67 | bdnz 22b |
68 | 23: adde r5,r5,r8 | ||
60 | 3: andi. r0,r4,2 | 69 | 3: andi. r0,r4,2 |
61 | beq+ 4f | 70 | beq+ 4f |
62 | lhz r0,4(r3) | 71 | lhz r0,4(r3) |
@@ -293,3 +302,36 @@ dst_error: | |||
293 | EX_TABLE(51b, dst_error); | 302 | EX_TABLE(51b, dst_error); |
294 | 303 | ||
295 | EXPORT_SYMBOL(csum_partial_copy_generic) | 304 | EXPORT_SYMBOL(csum_partial_copy_generic) |
305 | |||
306 | /* | ||
307 | * __sum16 csum_ipv6_magic(const struct in6_addr *saddr, | ||
308 | * const struct in6_addr *daddr, | ||
309 | * __u32 len, __u8 proto, __wsum sum) | ||
310 | */ | ||
311 | |||
312 | _GLOBAL(csum_ipv6_magic) | ||
313 | lwz r8, 0(r3) | ||
314 | lwz r9, 4(r3) | ||
315 | addc r0, r7, r8 | ||
316 | lwz r10, 8(r3) | ||
317 | adde r0, r0, r9 | ||
318 | lwz r11, 12(r3) | ||
319 | adde r0, r0, r10 | ||
320 | lwz r8, 0(r4) | ||
321 | adde r0, r0, r11 | ||
322 | lwz r9, 4(r4) | ||
323 | adde r0, r0, r8 | ||
324 | lwz r10, 8(r4) | ||
325 | adde r0, r0, r9 | ||
326 | lwz r11, 12(r4) | ||
327 | adde r0, r0, r10 | ||
328 | add r5, r5, r6 /* assumption: len + proto doesn't carry */ | ||
329 | adde r0, r0, r11 | ||
330 | adde r0, r0, r5 | ||
331 | addze r0, r0 | ||
332 | rotlwi r3, r0, 16 | ||
333 | add r3, r0, r3 | ||
334 | not r3, r3 | ||
335 | rlwinm r3, r3, 16, 16, 31 | ||
336 | blr | ||
337 | EXPORT_SYMBOL(csum_ipv6_magic) | ||
diff --git a/arch/powerpc/lib/checksum_64.S b/arch/powerpc/lib/checksum_64.S index d7f1a966136e..886ed94b9c13 100644 --- a/arch/powerpc/lib/checksum_64.S +++ b/arch/powerpc/lib/checksum_64.S | |||
@@ -429,3 +429,31 @@ dstnr; stb r6,0(r4) | |||
429 | stw r6,0(r8) | 429 | stw r6,0(r8) |
430 | blr | 430 | blr |
431 | EXPORT_SYMBOL(csum_partial_copy_generic) | 431 | EXPORT_SYMBOL(csum_partial_copy_generic) |
432 | |||
433 | /* | ||
434 | * __sum16 csum_ipv6_magic(const struct in6_addr *saddr, | ||
435 | * const struct in6_addr *daddr, | ||
436 | * __u32 len, __u8 proto, __wsum sum) | ||
437 | */ | ||
438 | |||
439 | _GLOBAL(csum_ipv6_magic) | ||
440 | ld r8, 0(r3) | ||
441 | ld r9, 8(r3) | ||
442 | add r5, r5, r6 | ||
443 | addc r0, r8, r9 | ||
444 | ld r10, 0(r4) | ||
445 | ld r11, 8(r4) | ||
446 | adde r0, r0, r10 | ||
447 | add r5, r5, r7 | ||
448 | adde r0, r0, r11 | ||
449 | adde r0, r0, r5 | ||
450 | addze r0, r0 | ||
451 | rotldi r3, r0, 32 /* fold two 32 bit halves together */ | ||
452 | add r3, r0, r3 | ||
453 | srdi r0, r3, 32 | ||
454 | rotlwi r3, r0, 16 /* fold two 16 bit halves together */ | ||
455 | add r3, r0, r3 | ||
456 | not r3, r3 | ||
457 | rlwinm r3, r3, 16, 16, 31 | ||
458 | blr | ||
459 | EXPORT_SYMBOL(csum_ipv6_magic) | ||
diff --git a/arch/powerpc/lib/feature-fixups-test.S b/arch/powerpc/lib/feature-fixups-test.S index f4613118132e..f16cec989506 100644 --- a/arch/powerpc/lib/feature-fixups-test.S +++ b/arch/powerpc/lib/feature-fixups-test.S | |||
@@ -167,16 +167,52 @@ globl(ftr_fixup_test6_expected) | |||
167 | blt 2b | 167 | blt 2b |
168 | b 3f | 168 | b 3f |
169 | b 1b | 169 | b 1b |
170 | 2: or 1,1,1 | 170 | 3: or 1,1,1 |
171 | or 2,2,2 | ||
172 | or 3,3,3 | ||
173 | |||
174 | globl(ftr_fixup_test7) | ||
175 | or 1,1,1 | ||
176 | BEGIN_FTR_SECTION | ||
177 | or 2,2,2 | ||
178 | or 2,2,2 | ||
171 | or 2,2,2 | 179 | or 2,2,2 |
172 | 3: or 3,3,3 | 180 | or 2,2,2 |
181 | or 2,2,2 | ||
182 | or 2,2,2 | ||
183 | or 2,2,2 | ||
184 | FTR_SECTION_ELSE | ||
185 | 2: b 3f | ||
186 | 3: or 5,5,5 | ||
187 | beq 3b | ||
188 | b 1f | ||
189 | or 6,6,6 | ||
190 | b 2b | ||
191 | bdnz 3b | ||
192 | 1: | ||
193 | ALT_FTR_SECTION_END(0, 1) | ||
194 | or 1,1,1 | ||
195 | or 1,1,1 | ||
196 | |||
197 | globl(end_ftr_fixup_test7) | ||
198 | nop | ||
173 | 199 | ||
200 | globl(ftr_fixup_test7_expected) | ||
201 | or 1,1,1 | ||
202 | 2: b 3f | ||
203 | 3: or 5,5,5 | ||
204 | beq 3b | ||
205 | b 1f | ||
206 | or 6,6,6 | ||
207 | b 2b | ||
208 | bdnz 3b | ||
209 | 1: or 1,1,1 | ||
174 | 210 | ||
175 | #if 0 | 211 | #if 0 |
176 | /* Test that if we have a larger else case the assembler spots it and | 212 | /* Test that if we have a larger else case the assembler spots it and |
177 | * reports an error. #if 0'ed so as not to break the build normally. | 213 | * reports an error. #if 0'ed so as not to break the build normally. |
178 | */ | 214 | */ |
179 | ftr_fixup_test7: | 215 | ftr_fixup_test_too_big: |
180 | or 1,1,1 | 216 | or 1,1,1 |
181 | BEGIN_FTR_SECTION | 217 | BEGIN_FTR_SECTION |
182 | or 2,2,2 | 218 | or 2,2,2 |
diff --git a/arch/powerpc/lib/feature-fixups.c b/arch/powerpc/lib/feature-fixups.c index e1bcdc32a851..8b69f868298c 100644 --- a/arch/powerpc/lib/feature-fixups.c +++ b/arch/powerpc/lib/feature-fixups.c | |||
@@ -277,6 +277,43 @@ void do_rfi_flush_fixups(enum l1d_flush_type types) | |||
277 | (types & L1D_FLUSH_MTTRIG) ? "mttrig type" | 277 | (types & L1D_FLUSH_MTTRIG) ? "mttrig type" |
278 | : "unknown"); | 278 | : "unknown"); |
279 | } | 279 | } |
280 | |||
281 | void do_barrier_nospec_fixups_range(bool enable, void *fixup_start, void *fixup_end) | ||
282 | { | ||
283 | unsigned int instr, *dest; | ||
284 | long *start, *end; | ||
285 | int i; | ||
286 | |||
287 | start = fixup_start; | ||
288 | end = fixup_end; | ||
289 | |||
290 | instr = 0x60000000; /* nop */ | ||
291 | |||
292 | if (enable) { | ||
293 | pr_info("barrier-nospec: using ORI speculation barrier\n"); | ||
294 | instr = 0x63ff0000; /* ori 31,31,0 speculation barrier */ | ||
295 | } | ||
296 | |||
297 | for (i = 0; start < end; start++, i++) { | ||
298 | dest = (void *)start + *start; | ||
299 | |||
300 | pr_devel("patching dest %lx\n", (unsigned long)dest); | ||
301 | patch_instruction(dest, instr); | ||
302 | } | ||
303 | |||
304 | printk(KERN_DEBUG "barrier-nospec: patched %d locations\n", i); | ||
305 | } | ||
306 | |||
307 | void do_barrier_nospec_fixups(bool enable) | ||
308 | { | ||
309 | void *start, *end; | ||
310 | |||
311 | start = PTRRELOC(&__start___barrier_nospec_fixup), | ||
312 | end = PTRRELOC(&__stop___barrier_nospec_fixup); | ||
313 | |||
314 | do_barrier_nospec_fixups_range(enable, start, end); | ||
315 | } | ||
316 | |||
280 | #endif /* CONFIG_PPC_BOOK3S_64 */ | 317 | #endif /* CONFIG_PPC_BOOK3S_64 */ |
281 | 318 | ||
282 | void do_lwsync_fixups(unsigned long value, void *fixup_start, void *fixup_end) | 319 | void do_lwsync_fixups(unsigned long value, void *fixup_start, void *fixup_end) |
@@ -400,7 +437,7 @@ static void test_basic_patching(void) | |||
400 | extern unsigned int end_ftr_fixup_test1[]; | 437 | extern unsigned int end_ftr_fixup_test1[]; |
401 | extern unsigned int ftr_fixup_test1_orig[]; | 438 | extern unsigned int ftr_fixup_test1_orig[]; |
402 | extern unsigned int ftr_fixup_test1_expected[]; | 439 | extern unsigned int ftr_fixup_test1_expected[]; |
403 | int size = end_ftr_fixup_test1 - ftr_fixup_test1; | 440 | int size = 4 * (end_ftr_fixup_test1 - ftr_fixup_test1); |
404 | 441 | ||
405 | fixup.value = fixup.mask = 8; | 442 | fixup.value = fixup.mask = 8; |
406 | fixup.start_off = calc_offset(&fixup, ftr_fixup_test1 + 1); | 443 | fixup.start_off = calc_offset(&fixup, ftr_fixup_test1 + 1); |
@@ -432,7 +469,7 @@ static void test_alternative_patching(void) | |||
432 | extern unsigned int ftr_fixup_test2_orig[]; | 469 | extern unsigned int ftr_fixup_test2_orig[]; |
433 | extern unsigned int ftr_fixup_test2_alt[]; | 470 | extern unsigned int ftr_fixup_test2_alt[]; |
434 | extern unsigned int ftr_fixup_test2_expected[]; | 471 | extern unsigned int ftr_fixup_test2_expected[]; |
435 | int size = end_ftr_fixup_test2 - ftr_fixup_test2; | 472 | int size = 4 * (end_ftr_fixup_test2 - ftr_fixup_test2); |
436 | 473 | ||
437 | fixup.value = fixup.mask = 0xF; | 474 | fixup.value = fixup.mask = 0xF; |
438 | fixup.start_off = calc_offset(&fixup, ftr_fixup_test2 + 1); | 475 | fixup.start_off = calc_offset(&fixup, ftr_fixup_test2 + 1); |
@@ -464,7 +501,7 @@ static void test_alternative_case_too_big(void) | |||
464 | extern unsigned int end_ftr_fixup_test3[]; | 501 | extern unsigned int end_ftr_fixup_test3[]; |
465 | extern unsigned int ftr_fixup_test3_orig[]; | 502 | extern unsigned int ftr_fixup_test3_orig[]; |
466 | extern unsigned int ftr_fixup_test3_alt[]; | 503 | extern unsigned int ftr_fixup_test3_alt[]; |
467 | int size = end_ftr_fixup_test3 - ftr_fixup_test3; | 504 | int size = 4 * (end_ftr_fixup_test3 - ftr_fixup_test3); |
468 | 505 | ||
469 | fixup.value = fixup.mask = 0xC; | 506 | fixup.value = fixup.mask = 0xC; |
470 | fixup.start_off = calc_offset(&fixup, ftr_fixup_test3 + 1); | 507 | fixup.start_off = calc_offset(&fixup, ftr_fixup_test3 + 1); |
@@ -491,7 +528,7 @@ static void test_alternative_case_too_small(void) | |||
491 | extern unsigned int ftr_fixup_test4_orig[]; | 528 | extern unsigned int ftr_fixup_test4_orig[]; |
492 | extern unsigned int ftr_fixup_test4_alt[]; | 529 | extern unsigned int ftr_fixup_test4_alt[]; |
493 | extern unsigned int ftr_fixup_test4_expected[]; | 530 | extern unsigned int ftr_fixup_test4_expected[]; |
494 | int size = end_ftr_fixup_test4 - ftr_fixup_test4; | 531 | int size = 4 * (end_ftr_fixup_test4 - ftr_fixup_test4); |
495 | unsigned long flag; | 532 | unsigned long flag; |
496 | 533 | ||
497 | /* Check a high-bit flag */ | 534 | /* Check a high-bit flag */ |
@@ -525,7 +562,7 @@ static void test_alternative_case_with_branch(void) | |||
525 | extern unsigned int ftr_fixup_test5[]; | 562 | extern unsigned int ftr_fixup_test5[]; |
526 | extern unsigned int end_ftr_fixup_test5[]; | 563 | extern unsigned int end_ftr_fixup_test5[]; |
527 | extern unsigned int ftr_fixup_test5_expected[]; | 564 | extern unsigned int ftr_fixup_test5_expected[]; |
528 | int size = end_ftr_fixup_test5 - ftr_fixup_test5; | 565 | int size = 4 * (end_ftr_fixup_test5 - ftr_fixup_test5); |
529 | 566 | ||
530 | check(memcmp(ftr_fixup_test5, ftr_fixup_test5_expected, size) == 0); | 567 | check(memcmp(ftr_fixup_test5, ftr_fixup_test5_expected, size) == 0); |
531 | } | 568 | } |
@@ -535,11 +572,21 @@ static void test_alternative_case_with_external_branch(void) | |||
535 | extern unsigned int ftr_fixup_test6[]; | 572 | extern unsigned int ftr_fixup_test6[]; |
536 | extern unsigned int end_ftr_fixup_test6[]; | 573 | extern unsigned int end_ftr_fixup_test6[]; |
537 | extern unsigned int ftr_fixup_test6_expected[]; | 574 | extern unsigned int ftr_fixup_test6_expected[]; |
538 | int size = end_ftr_fixup_test6 - ftr_fixup_test6; | 575 | int size = 4 * (end_ftr_fixup_test6 - ftr_fixup_test6); |
539 | 576 | ||
540 | check(memcmp(ftr_fixup_test6, ftr_fixup_test6_expected, size) == 0); | 577 | check(memcmp(ftr_fixup_test6, ftr_fixup_test6_expected, size) == 0); |
541 | } | 578 | } |
542 | 579 | ||
580 | static void test_alternative_case_with_branch_to_end(void) | ||
581 | { | ||
582 | extern unsigned int ftr_fixup_test7[]; | ||
583 | extern unsigned int end_ftr_fixup_test7[]; | ||
584 | extern unsigned int ftr_fixup_test7_expected[]; | ||
585 | int size = 4 * (end_ftr_fixup_test7 - ftr_fixup_test7); | ||
586 | |||
587 | check(memcmp(ftr_fixup_test7, ftr_fixup_test7_expected, size) == 0); | ||
588 | } | ||
589 | |||
543 | static void test_cpu_macros(void) | 590 | static void test_cpu_macros(void) |
544 | { | 591 | { |
545 | extern u8 ftr_fixup_test_FTR_macros[]; | 592 | extern u8 ftr_fixup_test_FTR_macros[]; |
@@ -595,6 +642,7 @@ static int __init test_feature_fixups(void) | |||
595 | test_alternative_case_too_small(); | 642 | test_alternative_case_too_small(); |
596 | test_alternative_case_with_branch(); | 643 | test_alternative_case_with_branch(); |
597 | test_alternative_case_with_external_branch(); | 644 | test_alternative_case_with_external_branch(); |
645 | test_alternative_case_with_branch_to_end(); | ||
598 | test_cpu_macros(); | 646 | test_cpu_macros(); |
599 | test_fw_macros(); | 647 | test_fw_macros(); |
600 | test_lwsync_macros(); | 648 | test_lwsync_macros(); |
diff --git a/arch/powerpc/lib/memcmp_32.S b/arch/powerpc/lib/memcmp_32.S new file mode 100644 index 000000000000..5010e376f7b8 --- /dev/null +++ b/arch/powerpc/lib/memcmp_32.S | |||
@@ -0,0 +1,45 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | |||
3 | /* | ||
4 | * memcmp for PowerPC32 | ||
5 | * | ||
6 | * Copyright (C) 1996 Paul Mackerras. | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | #include <asm/ppc_asm.h> | ||
11 | #include <asm/export.h> | ||
12 | |||
13 | .text | ||
14 | |||
15 | _GLOBAL(memcmp) | ||
16 | srawi. r7, r5, 2 /* Divide len by 4 */ | ||
17 | mr r6, r3 | ||
18 | beq- 3f | ||
19 | mtctr r7 | ||
20 | li r7, 0 | ||
21 | 1: lwzx r3, r6, r7 | ||
22 | lwzx r0, r4, r7 | ||
23 | addi r7, r7, 4 | ||
24 | cmplw cr0, r3, r0 | ||
25 | bdnzt eq, 1b | ||
26 | bne 5f | ||
27 | 3: andi. r3, r5, 3 | ||
28 | beqlr | ||
29 | cmplwi cr1, r3, 2 | ||
30 | blt- cr1, 4f | ||
31 | lhzx r3, r6, r7 | ||
32 | lhzx r0, r4, r7 | ||
33 | addi r7, r7, 2 | ||
34 | subf. r3, r0, r3 | ||
35 | beqlr cr1 | ||
36 | bnelr | ||
37 | 4: lbzx r3, r6, r7 | ||
38 | lbzx r0, r4, r7 | ||
39 | subf. r3, r0, r3 | ||
40 | blr | ||
41 | 5: li r3, 1 | ||
42 | bgtlr | ||
43 | li r3, -1 | ||
44 | blr | ||
45 | EXPORT_SYMBOL(memcmp) | ||
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c index 34d68f1b1b40..d81568f783e5 100644 --- a/arch/powerpc/lib/sstep.c +++ b/arch/powerpc/lib/sstep.c | |||
@@ -1065,9 +1065,10 @@ static nokprobe_inline void do_popcnt(const struct pt_regs *regs, | |||
1065 | { | 1065 | { |
1066 | unsigned long long out = v1; | 1066 | unsigned long long out = v1; |
1067 | 1067 | ||
1068 | out -= (out >> 1) & 0x5555555555555555; | 1068 | out -= (out >> 1) & 0x5555555555555555ULL; |
1069 | out = (0x3333333333333333 & out) + (0x3333333333333333 & (out >> 2)); | 1069 | out = (0x3333333333333333ULL & out) + |
1070 | out = (out + (out >> 4)) & 0x0f0f0f0f0f0f0f0f; | 1070 | (0x3333333333333333ULL & (out >> 2)); |
1071 | out = (out + (out >> 4)) & 0x0f0f0f0f0f0f0f0fULL; | ||
1071 | 1072 | ||
1072 | if (size == 8) { /* popcntb */ | 1073 | if (size == 8) { /* popcntb */ |
1073 | op->val = out; | 1074 | op->val = out; |
@@ -1076,7 +1077,7 @@ static nokprobe_inline void do_popcnt(const struct pt_regs *regs, | |||
1076 | out += out >> 8; | 1077 | out += out >> 8; |
1077 | out += out >> 16; | 1078 | out += out >> 16; |
1078 | if (size == 32) { /* popcntw */ | 1079 | if (size == 32) { /* popcntw */ |
1079 | op->val = out & 0x0000003f0000003f; | 1080 | op->val = out & 0x0000003f0000003fULL; |
1080 | return; | 1081 | return; |
1081 | } | 1082 | } |
1082 | 1083 | ||
@@ -1114,7 +1115,7 @@ static nokprobe_inline void do_prty(const struct pt_regs *regs, | |||
1114 | 1115 | ||
1115 | res ^= res >> 16; | 1116 | res ^= res >> 16; |
1116 | if (size == 32) { /* prtyw */ | 1117 | if (size == 32) { /* prtyw */ |
1117 | op->val = res & 0x0000000100000001; | 1118 | op->val = res & 0x0000000100000001ULL; |
1118 | return; | 1119 | return; |
1119 | } | 1120 | } |
1120 | 1121 | ||
@@ -2544,6 +2545,15 @@ int analyse_instr(struct instruction_op *op, const struct pt_regs *regs, | |||
2544 | #endif /* __powerpc64__ */ | 2545 | #endif /* __powerpc64__ */ |
2545 | 2546 | ||
2546 | } | 2547 | } |
2548 | |||
2549 | #ifdef CONFIG_VSX | ||
2550 | if ((GETTYPE(op->type) == LOAD_VSX || | ||
2551 | GETTYPE(op->type) == STORE_VSX) && | ||
2552 | !cpu_has_feature(CPU_FTR_VSX)) { | ||
2553 | return -1; | ||
2554 | } | ||
2555 | #endif /* CONFIG_VSX */ | ||
2556 | |||
2547 | return 0; | 2557 | return 0; |
2548 | 2558 | ||
2549 | logical_done: | 2559 | logical_done: |
@@ -2641,7 +2651,7 @@ void emulate_update_regs(struct pt_regs *regs, struct instruction_op *op) | |||
2641 | unsigned long next_pc; | 2651 | unsigned long next_pc; |
2642 | 2652 | ||
2643 | next_pc = truncate_if_32bit(regs->msr, regs->nip + 4); | 2653 | next_pc = truncate_if_32bit(regs->msr, regs->nip + 4); |
2644 | switch (op->type & INSTR_TYPE_MASK) { | 2654 | switch (GETTYPE(op->type)) { |
2645 | case COMPUTE: | 2655 | case COMPUTE: |
2646 | if (op->type & SETREG) | 2656 | if (op->type & SETREG) |
2647 | regs->gpr[op->reg] = op->val; | 2657 | regs->gpr[op->reg] = op->val; |
@@ -2739,7 +2749,7 @@ int emulate_loadstore(struct pt_regs *regs, struct instruction_op *op) | |||
2739 | 2749 | ||
2740 | err = 0; | 2750 | err = 0; |
2741 | size = GETSIZE(op->type); | 2751 | size = GETSIZE(op->type); |
2742 | type = op->type & INSTR_TYPE_MASK; | 2752 | type = GETTYPE(op->type); |
2743 | cross_endian = (regs->msr & MSR_LE) != (MSR_KERNEL & MSR_LE); | 2753 | cross_endian = (regs->msr & MSR_LE) != (MSR_KERNEL & MSR_LE); |
2744 | ea = truncate_if_32bit(regs->msr, op->ea); | 2754 | ea = truncate_if_32bit(regs->msr, op->ea); |
2745 | 2755 | ||
@@ -3001,7 +3011,7 @@ int emulate_step(struct pt_regs *regs, unsigned int instr) | |||
3001 | } | 3011 | } |
3002 | 3012 | ||
3003 | err = 0; | 3013 | err = 0; |
3004 | type = op.type & INSTR_TYPE_MASK; | 3014 | type = GETTYPE(op.type); |
3005 | 3015 | ||
3006 | if (OP_IS_LOAD_STORE(type)) { | 3016 | if (OP_IS_LOAD_STORE(type)) { |
3007 | err = emulate_loadstore(regs, &op); | 3017 | err = emulate_loadstore(regs, &op); |
diff --git a/arch/powerpc/lib/string.S b/arch/powerpc/lib/string.S index a787776822d8..4b41970e9ed8 100644 --- a/arch/powerpc/lib/string.S +++ b/arch/powerpc/lib/string.S | |||
@@ -8,10 +8,9 @@ | |||
8 | * as published by the Free Software Foundation; either version | 8 | * as published by the Free Software Foundation; either version |
9 | * 2 of the License, or (at your option) any later version. | 9 | * 2 of the License, or (at your option) any later version. |
10 | */ | 10 | */ |
11 | #include <asm/processor.h> | ||
12 | #include <asm/errno.h> | ||
13 | #include <asm/ppc_asm.h> | 11 | #include <asm/ppc_asm.h> |
14 | #include <asm/export.h> | 12 | #include <asm/export.h> |
13 | #include <asm/cache.h> | ||
15 | 14 | ||
16 | .text | 15 | .text |
17 | 16 | ||
@@ -23,7 +22,7 @@ _GLOBAL(strncpy) | |||
23 | mtctr r5 | 22 | mtctr r5 |
24 | addi r6,r3,-1 | 23 | addi r6,r3,-1 |
25 | addi r4,r4,-1 | 24 | addi r4,r4,-1 |
26 | .balign 16 | 25 | .balign IFETCH_ALIGN_BYTES |
27 | 1: lbzu r0,1(r4) | 26 | 1: lbzu r0,1(r4) |
28 | cmpwi 0,r0,0 | 27 | cmpwi 0,r0,0 |
29 | stbu r0,1(r6) | 28 | stbu r0,1(r6) |
@@ -43,7 +42,7 @@ _GLOBAL(strncmp) | |||
43 | mtctr r5 | 42 | mtctr r5 |
44 | addi r5,r3,-1 | 43 | addi r5,r3,-1 |
45 | addi r4,r4,-1 | 44 | addi r4,r4,-1 |
46 | .balign 16 | 45 | .balign IFETCH_ALIGN_BYTES |
47 | 1: lbzu r3,1(r5) | 46 | 1: lbzu r3,1(r5) |
48 | cmpwi 1,r3,0 | 47 | cmpwi 1,r3,0 |
49 | lbzu r0,1(r4) | 48 | lbzu r0,1(r4) |
@@ -55,29 +54,12 @@ _GLOBAL(strncmp) | |||
55 | blr | 54 | blr |
56 | EXPORT_SYMBOL(strncmp) | 55 | EXPORT_SYMBOL(strncmp) |
57 | 56 | ||
58 | #ifdef CONFIG_PPC32 | ||
59 | _GLOBAL(memcmp) | ||
60 | PPC_LCMPI 0,r5,0 | ||
61 | beq- 2f | ||
62 | mtctr r5 | ||
63 | addi r6,r3,-1 | ||
64 | addi r4,r4,-1 | ||
65 | 1: lbzu r3,1(r6) | ||
66 | lbzu r0,1(r4) | ||
67 | subf. r3,r0,r3 | ||
68 | bdnzt 2,1b | ||
69 | blr | ||
70 | 2: li r3,0 | ||
71 | blr | ||
72 | EXPORT_SYMBOL(memcmp) | ||
73 | #endif | ||
74 | |||
75 | _GLOBAL(memchr) | 57 | _GLOBAL(memchr) |
76 | PPC_LCMPI 0,r5,0 | 58 | PPC_LCMPI 0,r5,0 |
77 | beq- 2f | 59 | beq- 2f |
78 | mtctr r5 | 60 | mtctr r5 |
79 | addi r3,r3,-1 | 61 | addi r3,r3,-1 |
80 | .balign 16 | 62 | .balign IFETCH_ALIGN_BYTES |
81 | 1: lbzu r0,1(r3) | 63 | 1: lbzu r0,1(r3) |
82 | cmpw 0,r0,r4 | 64 | cmpw 0,r0,r4 |
83 | bdnzf 2,1b | 65 | bdnzf 2,1b |
@@ -85,47 +67,3 @@ _GLOBAL(memchr) | |||
85 | 2: li r3,0 | 67 | 2: li r3,0 |
86 | blr | 68 | blr |
87 | EXPORT_SYMBOL(memchr) | 69 | EXPORT_SYMBOL(memchr) |
88 | |||
89 | #ifdef CONFIG_PPC32 | ||
90 | _GLOBAL(__clear_user) | ||
91 | addi r6,r3,-4 | ||
92 | li r3,0 | ||
93 | li r5,0 | ||
94 | cmplwi 0,r4,4 | ||
95 | blt 7f | ||
96 | /* clear a single word */ | ||
97 | 11: stwu r5,4(r6) | ||
98 | beqlr | ||
99 | /* clear word sized chunks */ | ||
100 | andi. r0,r6,3 | ||
101 | add r4,r0,r4 | ||
102 | subf r6,r0,r6 | ||
103 | srwi r0,r4,2 | ||
104 | andi. r4,r4,3 | ||
105 | mtctr r0 | ||
106 | bdz 7f | ||
107 | 1: stwu r5,4(r6) | ||
108 | bdnz 1b | ||
109 | /* clear byte sized chunks */ | ||
110 | 7: cmpwi 0,r4,0 | ||
111 | beqlr | ||
112 | mtctr r4 | ||
113 | addi r6,r6,3 | ||
114 | 8: stbu r5,1(r6) | ||
115 | bdnz 8b | ||
116 | blr | ||
117 | 90: mr r3,r4 | ||
118 | blr | ||
119 | 91: mfctr r3 | ||
120 | slwi r3,r3,2 | ||
121 | add r3,r3,r4 | ||
122 | blr | ||
123 | 92: mfctr r3 | ||
124 | blr | ||
125 | |||
126 | EX_TABLE(11b, 90b) | ||
127 | EX_TABLE(1b, 91b) | ||
128 | EX_TABLE(8b, 92b) | ||
129 | |||
130 | EXPORT_SYMBOL(__clear_user) | ||
131 | #endif | ||
diff --git a/arch/powerpc/lib/string_32.S b/arch/powerpc/lib/string_32.S new file mode 100644 index 000000000000..f69a6aab7bfb --- /dev/null +++ b/arch/powerpc/lib/string_32.S | |||
@@ -0,0 +1,90 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | |||
3 | /* | ||
4 | * String handling functions for PowerPC32 | ||
5 | * | ||
6 | * Copyright (C) 1996 Paul Mackerras. | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | #include <asm/ppc_asm.h> | ||
11 | #include <asm/export.h> | ||
12 | #include <asm/cache.h> | ||
13 | |||
14 | .text | ||
15 | |||
16 | CACHELINE_BYTES = L1_CACHE_BYTES | ||
17 | LG_CACHELINE_BYTES = L1_CACHE_SHIFT | ||
18 | CACHELINE_MASK = (L1_CACHE_BYTES-1) | ||
19 | |||
20 | _GLOBAL(__clear_user) | ||
21 | /* | ||
22 | * Use dcbz on the complete cache lines in the destination | ||
23 | * to set them to zero. This requires that the destination | ||
24 | * area is cacheable. | ||
25 | */ | ||
26 | cmplwi cr0, r4, 4 | ||
27 | mr r10, r3 | ||
28 | li r3, 0 | ||
29 | blt 7f | ||
30 | |||
31 | 11: stw r3, 0(r10) | ||
32 | beqlr | ||
33 | andi. r0, r10, 3 | ||
34 | add r11, r0, r4 | ||
35 | subf r6, r0, r10 | ||
36 | |||
37 | clrlwi r7, r6, 32 - LG_CACHELINE_BYTES | ||
38 | add r8, r7, r11 | ||
39 | srwi r9, r8, LG_CACHELINE_BYTES | ||
40 | addic. r9, r9, -1 /* total number of complete cachelines */ | ||
41 | ble 2f | ||
42 | xori r0, r7, CACHELINE_MASK & ~3 | ||
43 | srwi. r0, r0, 2 | ||
44 | beq 3f | ||
45 | mtctr r0 | ||
46 | 4: stwu r3, 4(r6) | ||
47 | bdnz 4b | ||
48 | 3: mtctr r9 | ||
49 | li r7, 4 | ||
50 | 10: dcbz r7, r6 | ||
51 | addi r6, r6, CACHELINE_BYTES | ||
52 | bdnz 10b | ||
53 | clrlwi r11, r8, 32 - LG_CACHELINE_BYTES | ||
54 | addi r11, r11, 4 | ||
55 | |||
56 | 2: srwi r0 ,r11 ,2 | ||
57 | mtctr r0 | ||
58 | bdz 6f | ||
59 | 1: stwu r3, 4(r6) | ||
60 | bdnz 1b | ||
61 | 6: andi. r11, r11, 3 | ||
62 | beqlr | ||
63 | mtctr r11 | ||
64 | addi r6, r6, 3 | ||
65 | 8: stbu r3, 1(r6) | ||
66 | bdnz 8b | ||
67 | blr | ||
68 | |||
69 | 7: cmpwi cr0, r4, 0 | ||
70 | beqlr | ||
71 | mtctr r4 | ||
72 | addi r6, r10, -1 | ||
73 | 9: stbu r3, 1(r6) | ||
74 | bdnz 9b | ||
75 | blr | ||
76 | |||
77 | 90: mr r3, r4 | ||
78 | blr | ||
79 | 91: add r3, r10, r4 | ||
80 | subf r3, r6, r3 | ||
81 | blr | ||
82 | |||
83 | EX_TABLE(11b, 90b) | ||
84 | EX_TABLE(4b, 91b) | ||
85 | EX_TABLE(10b, 91b) | ||
86 | EX_TABLE(1b, 91b) | ||
87 | EX_TABLE(8b, 91b) | ||
88 | EX_TABLE(9b, 91b) | ||
89 | |||
90 | EXPORT_SYMBOL(__clear_user) | ||
diff --git a/arch/powerpc/lib/test_emulate_step.c b/arch/powerpc/lib/test_emulate_step.c index 2534c1447554..6c47daa61614 100644 --- a/arch/powerpc/lib/test_emulate_step.c +++ b/arch/powerpc/lib/test_emulate_step.c | |||
@@ -387,10 +387,14 @@ static void __init test_lxvd2x_stxvd2x(void) | |||
387 | /* lxvd2x vsr39, r3, r4 */ | 387 | /* lxvd2x vsr39, r3, r4 */ |
388 | stepped = emulate_step(®s, TEST_LXVD2X(39, 3, 4)); | 388 | stepped = emulate_step(®s, TEST_LXVD2X(39, 3, 4)); |
389 | 389 | ||
390 | if (stepped == 1) | 390 | if (stepped == 1 && cpu_has_feature(CPU_FTR_VSX)) { |
391 | show_result("lxvd2x", "PASS"); | 391 | show_result("lxvd2x", "PASS"); |
392 | else | 392 | } else { |
393 | show_result("lxvd2x", "FAIL"); | 393 | if (!cpu_has_feature(CPU_FTR_VSX)) |
394 | show_result("lxvd2x", "PASS (!CPU_FTR_VSX)"); | ||
395 | else | ||
396 | show_result("lxvd2x", "FAIL"); | ||
397 | } | ||
394 | 398 | ||
395 | 399 | ||
396 | /*** stxvd2x ***/ | 400 | /*** stxvd2x ***/ |
@@ -404,10 +408,15 @@ static void __init test_lxvd2x_stxvd2x(void) | |||
404 | stepped = emulate_step(®s, TEST_STXVD2X(39, 3, 4)); | 408 | stepped = emulate_step(®s, TEST_STXVD2X(39, 3, 4)); |
405 | 409 | ||
406 | if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] && | 410 | if (stepped == 1 && cached_b[0] == c.b[0] && cached_b[1] == c.b[1] && |
407 | cached_b[2] == c.b[2] && cached_b[3] == c.b[3]) | 411 | cached_b[2] == c.b[2] && cached_b[3] == c.b[3] && |
412 | cpu_has_feature(CPU_FTR_VSX)) { | ||
408 | show_result("stxvd2x", "PASS"); | 413 | show_result("stxvd2x", "PASS"); |
409 | else | 414 | } else { |
410 | show_result("stxvd2x", "FAIL"); | 415 | if (!cpu_has_feature(CPU_FTR_VSX)) |
416 | show_result("stxvd2x", "PASS (!CPU_FTR_VSX)"); | ||
417 | else | ||
418 | show_result("stxvd2x", "FAIL"); | ||
419 | } | ||
411 | } | 420 | } |
412 | #else | 421 | #else |
413 | static void __init test_lxvd2x_stxvd2x(void) | 422 | static void __init test_lxvd2x_stxvd2x(void) |
diff --git a/arch/powerpc/lib/xor_vmx_glue.c b/arch/powerpc/lib/xor_vmx_glue.c index 6521fe5e8cef..dab2b6bfcf36 100644 --- a/arch/powerpc/lib/xor_vmx_glue.c +++ b/arch/powerpc/lib/xor_vmx_glue.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/export.h> | 13 | #include <linux/export.h> |
14 | #include <linux/sched.h> | 14 | #include <linux/sched.h> |
15 | #include <asm/switch_to.h> | 15 | #include <asm/switch_to.h> |
16 | #include <asm/xor_altivec.h> | ||
16 | #include "xor_vmx.h" | 17 | #include "xor_vmx.h" |
17 | 18 | ||
18 | void xor_altivec_2(unsigned long bytes, unsigned long *v1_in, | 19 | void xor_altivec_2(unsigned long bytes, unsigned long *v1_in, |
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index ef268d5d9db7..b1ca7a0974e3 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/errno.h> | 22 | #include <linux/errno.h> |
23 | #include <linux/string.h> | 23 | #include <linux/string.h> |
24 | #include <linux/types.h> | 24 | #include <linux/types.h> |
25 | #include <linux/pagemap.h> | ||
25 | #include <linux/ptrace.h> | 26 | #include <linux/ptrace.h> |
26 | #include <linux/mman.h> | 27 | #include <linux/mman.h> |
27 | #include <linux/mm.h> | 28 | #include <linux/mm.h> |
@@ -66,37 +67,33 @@ static inline bool notify_page_fault(struct pt_regs *regs) | |||
66 | } | 67 | } |
67 | 68 | ||
68 | /* | 69 | /* |
69 | * Check whether the instruction at regs->nip is a store using | 70 | * Check whether the instruction inst is a store using |
70 | * an update addressing form which will update r1. | 71 | * an update addressing form which will update r1. |
71 | */ | 72 | */ |
72 | static bool store_updates_sp(struct pt_regs *regs) | 73 | static bool store_updates_sp(unsigned int inst) |
73 | { | 74 | { |
74 | unsigned int inst; | ||
75 | |||
76 | if (get_user(inst, (unsigned int __user *)regs->nip)) | ||
77 | return false; | ||
78 | /* check for 1 in the rA field */ | 75 | /* check for 1 in the rA field */ |
79 | if (((inst >> 16) & 0x1f) != 1) | 76 | if (((inst >> 16) & 0x1f) != 1) |
80 | return false; | 77 | return false; |
81 | /* check major opcode */ | 78 | /* check major opcode */ |
82 | switch (inst >> 26) { | 79 | switch (inst >> 26) { |
83 | case 37: /* stwu */ | 80 | case OP_STWU: |
84 | case 39: /* stbu */ | 81 | case OP_STBU: |
85 | case 45: /* sthu */ | 82 | case OP_STHU: |
86 | case 53: /* stfsu */ | 83 | case OP_STFSU: |
87 | case 55: /* stfdu */ | 84 | case OP_STFDU: |
88 | return true; | 85 | return true; |
89 | case 62: /* std or stdu */ | 86 | case OP_STD: /* std or stdu */ |
90 | return (inst & 3) == 1; | 87 | return (inst & 3) == 1; |
91 | case 31: | 88 | case OP_31: |
92 | /* check minor opcode */ | 89 | /* check minor opcode */ |
93 | switch ((inst >> 1) & 0x3ff) { | 90 | switch ((inst >> 1) & 0x3ff) { |
94 | case 181: /* stdux */ | 91 | case OP_31_XOP_STDUX: |
95 | case 183: /* stwux */ | 92 | case OP_31_XOP_STWUX: |
96 | case 247: /* stbux */ | 93 | case OP_31_XOP_STBUX: |
97 | case 439: /* sthux */ | 94 | case OP_31_XOP_STHUX: |
98 | case 695: /* stfsux */ | 95 | case OP_31_XOP_STFSUX: |
99 | case 759: /* stfdux */ | 96 | case OP_31_XOP_STFDUX: |
100 | return true; | 97 | return true; |
101 | } | 98 | } |
102 | } | 99 | } |
@@ -235,8 +232,8 @@ static bool bad_kernel_fault(bool is_exec, unsigned long error_code, | |||
235 | } | 232 | } |
236 | 233 | ||
237 | static bool bad_stack_expansion(struct pt_regs *regs, unsigned long address, | 234 | static bool bad_stack_expansion(struct pt_regs *regs, unsigned long address, |
238 | struct vm_area_struct *vma, | 235 | struct vm_area_struct *vma, unsigned int flags, |
239 | bool store_update_sp) | 236 | bool *must_retry) |
240 | { | 237 | { |
241 | /* | 238 | /* |
242 | * N.B. The POWER/Open ABI allows programs to access up to | 239 | * N.B. The POWER/Open ABI allows programs to access up to |
@@ -248,6 +245,7 @@ static bool bad_stack_expansion(struct pt_regs *regs, unsigned long address, | |||
248 | * expand to 1MB without further checks. | 245 | * expand to 1MB without further checks. |
249 | */ | 246 | */ |
250 | if (address + 0x100000 < vma->vm_end) { | 247 | if (address + 0x100000 < vma->vm_end) { |
248 | unsigned int __user *nip = (unsigned int __user *)regs->nip; | ||
251 | /* get user regs even if this fault is in kernel mode */ | 249 | /* get user regs even if this fault is in kernel mode */ |
252 | struct pt_regs *uregs = current->thread.regs; | 250 | struct pt_regs *uregs = current->thread.regs; |
253 | if (uregs == NULL) | 251 | if (uregs == NULL) |
@@ -265,8 +263,22 @@ static bool bad_stack_expansion(struct pt_regs *regs, unsigned long address, | |||
265 | * between the last mapped region and the stack will | 263 | * between the last mapped region and the stack will |
266 | * expand the stack rather than segfaulting. | 264 | * expand the stack rather than segfaulting. |
267 | */ | 265 | */ |
268 | if (address + 2048 < uregs->gpr[1] && !store_update_sp) | 266 | if (address + 2048 >= uregs->gpr[1]) |
269 | return true; | 267 | return false; |
268 | |||
269 | if ((flags & FAULT_FLAG_WRITE) && (flags & FAULT_FLAG_USER) && | ||
270 | access_ok(VERIFY_READ, nip, sizeof(*nip))) { | ||
271 | unsigned int inst; | ||
272 | int res; | ||
273 | |||
274 | pagefault_disable(); | ||
275 | res = __get_user_inatomic(inst, nip); | ||
276 | pagefault_enable(); | ||
277 | if (!res) | ||
278 | return !store_updates_sp(inst); | ||
279 | *must_retry = true; | ||
280 | } | ||
281 | return true; | ||
270 | } | 282 | } |
271 | return false; | 283 | return false; |
272 | } | 284 | } |
@@ -404,7 +416,7 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address, | |||
404 | int is_user = user_mode(regs); | 416 | int is_user = user_mode(regs); |
405 | int is_write = page_fault_is_write(error_code); | 417 | int is_write = page_fault_is_write(error_code); |
406 | int fault, major = 0; | 418 | int fault, major = 0; |
407 | bool store_update_sp = false; | 419 | bool must_retry = false; |
408 | 420 | ||
409 | if (notify_page_fault(regs)) | 421 | if (notify_page_fault(regs)) |
410 | return 0; | 422 | return 0; |
@@ -455,9 +467,6 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address, | |||
455 | * can result in fault, which will cause a deadlock when called with | 467 | * can result in fault, which will cause a deadlock when called with |
456 | * mmap_sem held | 468 | * mmap_sem held |
457 | */ | 469 | */ |
458 | if (is_write && is_user) | ||
459 | store_update_sp = store_updates_sp(regs); | ||
460 | |||
461 | if (is_user) | 470 | if (is_user) |
462 | flags |= FAULT_FLAG_USER; | 471 | flags |= FAULT_FLAG_USER; |
463 | if (is_write) | 472 | if (is_write) |
@@ -504,8 +513,17 @@ retry: | |||
504 | return bad_area(regs, address); | 513 | return bad_area(regs, address); |
505 | 514 | ||
506 | /* The stack is being expanded, check if it's valid */ | 515 | /* The stack is being expanded, check if it's valid */ |
507 | if (unlikely(bad_stack_expansion(regs, address, vma, store_update_sp))) | 516 | if (unlikely(bad_stack_expansion(regs, address, vma, flags, |
508 | return bad_area(regs, address); | 517 | &must_retry))) { |
518 | if (!must_retry) | ||
519 | return bad_area(regs, address); | ||
520 | |||
521 | up_read(&mm->mmap_sem); | ||
522 | if (fault_in_pages_readable((const char __user *)regs->nip, | ||
523 | sizeof(unsigned int))) | ||
524 | return bad_area_nosemaphore(regs, address); | ||
525 | goto retry; | ||
526 | } | ||
509 | 527 | ||
510 | /* Try to expand it */ | 528 | /* Try to expand it */ |
511 | if (unlikely(expand_stack(vma, address))) | 529 | if (unlikely(expand_stack(vma, address))) |
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 0bd3790d35df..8318716e5075 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c | |||
@@ -64,6 +64,7 @@ | |||
64 | #include <asm/trace.h> | 64 | #include <asm/trace.h> |
65 | #include <asm/ps3.h> | 65 | #include <asm/ps3.h> |
66 | #include <asm/pte-walk.h> | 66 | #include <asm/pte-walk.h> |
67 | #include <asm/asm-prototypes.h> | ||
67 | 68 | ||
68 | #ifdef DEBUG | 69 | #ifdef DEBUG |
69 | #define DBG(fmt...) udbg_printf(fmt) | 70 | #define DBG(fmt...) udbg_printf(fmt) |
@@ -572,8 +573,10 @@ static void __init htab_scan_page_sizes(void) | |||
572 | } | 573 | } |
573 | 574 | ||
574 | #ifdef CONFIG_HUGETLB_PAGE | 575 | #ifdef CONFIG_HUGETLB_PAGE |
575 | /* Reserve 16G huge page memory sections for huge pages */ | 576 | if (!hugetlb_disabled) { |
576 | of_scan_flat_dt(htab_dt_scan_hugepage_blocks, NULL); | 577 | /* Reserve 16G huge page memory sections for huge pages */ |
578 | of_scan_flat_dt(htab_dt_scan_hugepage_blocks, NULL); | ||
579 | } | ||
577 | #endif /* CONFIG_HUGETLB_PAGE */ | 580 | #endif /* CONFIG_HUGETLB_PAGE */ |
578 | } | 581 | } |
579 | 582 | ||
@@ -1010,13 +1013,14 @@ void __init hash__early_init_mmu(void) | |||
1010 | */ | 1013 | */ |
1011 | __pte_frag_nr = H_PTE_FRAG_NR; | 1014 | __pte_frag_nr = H_PTE_FRAG_NR; |
1012 | __pte_frag_size_shift = H_PTE_FRAG_SIZE_SHIFT; | 1015 | __pte_frag_size_shift = H_PTE_FRAG_SIZE_SHIFT; |
1016 | __pmd_frag_nr = H_PMD_FRAG_NR; | ||
1017 | __pmd_frag_size_shift = H_PMD_FRAG_SIZE_SHIFT; | ||
1013 | 1018 | ||
1014 | __pte_index_size = H_PTE_INDEX_SIZE; | 1019 | __pte_index_size = H_PTE_INDEX_SIZE; |
1015 | __pmd_index_size = H_PMD_INDEX_SIZE; | 1020 | __pmd_index_size = H_PMD_INDEX_SIZE; |
1016 | __pud_index_size = H_PUD_INDEX_SIZE; | 1021 | __pud_index_size = H_PUD_INDEX_SIZE; |
1017 | __pgd_index_size = H_PGD_INDEX_SIZE; | 1022 | __pgd_index_size = H_PGD_INDEX_SIZE; |
1018 | __pud_cache_index = H_PUD_CACHE_INDEX; | 1023 | __pud_cache_index = H_PUD_CACHE_INDEX; |
1019 | __pmd_cache_index = H_PMD_CACHE_INDEX; | ||
1020 | __pte_table_size = H_PTE_TABLE_SIZE; | 1024 | __pte_table_size = H_PTE_TABLE_SIZE; |
1021 | __pmd_table_size = H_PMD_TABLE_SIZE; | 1025 | __pmd_table_size = H_PMD_TABLE_SIZE; |
1022 | __pud_table_size = H_PUD_TABLE_SIZE; | 1026 | __pud_table_size = H_PUD_TABLE_SIZE; |
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index f1153f8254e3..7c5f479c5c00 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c | |||
@@ -35,6 +35,8 @@ | |||
35 | #define PAGE_SHIFT_16M 24 | 35 | #define PAGE_SHIFT_16M 24 |
36 | #define PAGE_SHIFT_16G 34 | 36 | #define PAGE_SHIFT_16G 34 |
37 | 37 | ||
38 | bool hugetlb_disabled = false; | ||
39 | |||
38 | unsigned int HPAGE_SHIFT; | 40 | unsigned int HPAGE_SHIFT; |
39 | EXPORT_SYMBOL(HPAGE_SHIFT); | 41 | EXPORT_SYMBOL(HPAGE_SHIFT); |
40 | 42 | ||
@@ -50,7 +52,8 @@ pte_t *huge_pte_offset(struct mm_struct *mm, unsigned long addr, unsigned long s | |||
50 | } | 52 | } |
51 | 53 | ||
52 | static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp, | 54 | static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp, |
53 | unsigned long address, unsigned pdshift, unsigned pshift) | 55 | unsigned long address, unsigned int pdshift, |
56 | unsigned int pshift, spinlock_t *ptl) | ||
54 | { | 57 | { |
55 | struct kmem_cache *cachep; | 58 | struct kmem_cache *cachep; |
56 | pte_t *new; | 59 | pte_t *new; |
@@ -80,8 +83,7 @@ static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp, | |||
80 | */ | 83 | */ |
81 | smp_wmb(); | 84 | smp_wmb(); |
82 | 85 | ||
83 | spin_lock(&mm->page_table_lock); | 86 | spin_lock(ptl); |
84 | |||
85 | /* | 87 | /* |
86 | * We have multiple higher-level entries that point to the same | 88 | * We have multiple higher-level entries that point to the same |
87 | * actual pte location. Fill in each as we go and backtrack on error. | 89 | * actual pte location. Fill in each as we go and backtrack on error. |
@@ -111,7 +113,7 @@ static int __hugepte_alloc(struct mm_struct *mm, hugepd_t *hpdp, | |||
111 | *hpdp = __hugepd(0); | 113 | *hpdp = __hugepd(0); |
112 | kmem_cache_free(cachep, new); | 114 | kmem_cache_free(cachep, new); |
113 | } | 115 | } |
114 | spin_unlock(&mm->page_table_lock); | 116 | spin_unlock(ptl); |
115 | return 0; | 117 | return 0; |
116 | } | 118 | } |
117 | 119 | ||
@@ -136,6 +138,7 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr, unsigned long sz | |||
136 | hugepd_t *hpdp = NULL; | 138 | hugepd_t *hpdp = NULL; |
137 | unsigned pshift = __ffs(sz); | 139 | unsigned pshift = __ffs(sz); |
138 | unsigned pdshift = PGDIR_SHIFT; | 140 | unsigned pdshift = PGDIR_SHIFT; |
141 | spinlock_t *ptl; | ||
139 | 142 | ||
140 | addr &= ~(sz-1); | 143 | addr &= ~(sz-1); |
141 | pg = pgd_offset(mm, addr); | 144 | pg = pgd_offset(mm, addr); |
@@ -144,39 +147,46 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr, unsigned long sz | |||
144 | if (pshift == PGDIR_SHIFT) | 147 | if (pshift == PGDIR_SHIFT) |
145 | /* 16GB huge page */ | 148 | /* 16GB huge page */ |
146 | return (pte_t *) pg; | 149 | return (pte_t *) pg; |
147 | else if (pshift > PUD_SHIFT) | 150 | else if (pshift > PUD_SHIFT) { |
148 | /* | 151 | /* |
149 | * We need to use hugepd table | 152 | * We need to use hugepd table |
150 | */ | 153 | */ |
154 | ptl = &mm->page_table_lock; | ||
151 | hpdp = (hugepd_t *)pg; | 155 | hpdp = (hugepd_t *)pg; |
152 | else { | 156 | } else { |
153 | pdshift = PUD_SHIFT; | 157 | pdshift = PUD_SHIFT; |
154 | pu = pud_alloc(mm, pg, addr); | 158 | pu = pud_alloc(mm, pg, addr); |
155 | if (pshift == PUD_SHIFT) | 159 | if (pshift == PUD_SHIFT) |
156 | return (pte_t *)pu; | 160 | return (pte_t *)pu; |
157 | else if (pshift > PMD_SHIFT) | 161 | else if (pshift > PMD_SHIFT) { |
162 | ptl = pud_lockptr(mm, pu); | ||
158 | hpdp = (hugepd_t *)pu; | 163 | hpdp = (hugepd_t *)pu; |
159 | else { | 164 | } else { |
160 | pdshift = PMD_SHIFT; | 165 | pdshift = PMD_SHIFT; |
161 | pm = pmd_alloc(mm, pu, addr); | 166 | pm = pmd_alloc(mm, pu, addr); |
162 | if (pshift == PMD_SHIFT) | 167 | if (pshift == PMD_SHIFT) |
163 | /* 16MB hugepage */ | 168 | /* 16MB hugepage */ |
164 | return (pte_t *)pm; | 169 | return (pte_t *)pm; |
165 | else | 170 | else { |
171 | ptl = pmd_lockptr(mm, pm); | ||
166 | hpdp = (hugepd_t *)pm; | 172 | hpdp = (hugepd_t *)pm; |
173 | } | ||
167 | } | 174 | } |
168 | } | 175 | } |
169 | #else | 176 | #else |
170 | if (pshift >= HUGEPD_PGD_SHIFT) { | 177 | if (pshift >= HUGEPD_PGD_SHIFT) { |
178 | ptl = &mm->page_table_lock; | ||
171 | hpdp = (hugepd_t *)pg; | 179 | hpdp = (hugepd_t *)pg; |
172 | } else { | 180 | } else { |
173 | pdshift = PUD_SHIFT; | 181 | pdshift = PUD_SHIFT; |
174 | pu = pud_alloc(mm, pg, addr); | 182 | pu = pud_alloc(mm, pg, addr); |
175 | if (pshift >= HUGEPD_PUD_SHIFT) { | 183 | if (pshift >= HUGEPD_PUD_SHIFT) { |
184 | ptl = pud_lockptr(mm, pu); | ||
176 | hpdp = (hugepd_t *)pu; | 185 | hpdp = (hugepd_t *)pu; |
177 | } else { | 186 | } else { |
178 | pdshift = PMD_SHIFT; | 187 | pdshift = PMD_SHIFT; |
179 | pm = pmd_alloc(mm, pu, addr); | 188 | pm = pmd_alloc(mm, pu, addr); |
189 | ptl = pmd_lockptr(mm, pm); | ||
180 | hpdp = (hugepd_t *)pm; | 190 | hpdp = (hugepd_t *)pm; |
181 | } | 191 | } |
182 | } | 192 | } |
@@ -186,7 +196,8 @@ pte_t *huge_pte_alloc(struct mm_struct *mm, unsigned long addr, unsigned long sz | |||
186 | 196 | ||
187 | BUG_ON(!hugepd_none(*hpdp) && !hugepd_ok(*hpdp)); | 197 | BUG_ON(!hugepd_none(*hpdp) && !hugepd_ok(*hpdp)); |
188 | 198 | ||
189 | if (hugepd_none(*hpdp) && __hugepte_alloc(mm, hpdp, addr, pdshift, pshift)) | 199 | if (hugepd_none(*hpdp) && __hugepte_alloc(mm, hpdp, addr, |
200 | pdshift, pshift, ptl)) | ||
190 | return NULL; | 201 | return NULL; |
191 | 202 | ||
192 | return hugepte_offset(*hpdp, addr, pdshift); | 203 | return hugepte_offset(*hpdp, addr, pdshift); |
@@ -497,6 +508,10 @@ struct page *follow_huge_pd(struct vm_area_struct *vma, | |||
497 | struct mm_struct *mm = vma->vm_mm; | 508 | struct mm_struct *mm = vma->vm_mm; |
498 | 509 | ||
499 | retry: | 510 | retry: |
511 | /* | ||
512 | * hugepage directory entries are protected by mm->page_table_lock | ||
513 | * Use this instead of huge_pte_lockptr | ||
514 | */ | ||
500 | ptl = &mm->page_table_lock; | 515 | ptl = &mm->page_table_lock; |
501 | spin_lock(ptl); | 516 | spin_lock(ptl); |
502 | 517 | ||
@@ -651,6 +666,11 @@ static int __init hugetlbpage_init(void) | |||
651 | { | 666 | { |
652 | int psize; | 667 | int psize; |
653 | 668 | ||
669 | if (hugetlb_disabled) { | ||
670 | pr_info("HugeTLB support is disabled!\n"); | ||
671 | return 0; | ||
672 | } | ||
673 | |||
654 | #if !defined(CONFIG_PPC_FSL_BOOK3E) && !defined(CONFIG_PPC_8xx) | 674 | #if !defined(CONFIG_PPC_FSL_BOOK3E) && !defined(CONFIG_PPC_8xx) |
655 | if (!radix_enabled() && !mmu_has_feature(MMU_FTR_16M_PAGE)) | 675 | if (!radix_enabled() && !mmu_has_feature(MMU_FTR_16M_PAGE)) |
656 | return -ENODEV; | 676 | return -ENODEV; |
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index c3c39b02b2ba..8cecda4bd66a 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c | |||
@@ -509,8 +509,10 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, | |||
509 | */ | 509 | */ |
510 | unsigned long access, trap; | 510 | unsigned long access, trap; |
511 | 511 | ||
512 | if (radix_enabled()) | 512 | if (radix_enabled()) { |
513 | prefetch((void *)address); | ||
513 | return; | 514 | return; |
515 | } | ||
514 | 516 | ||
515 | /* We only want HPTEs for linux PTEs that have _PAGE_ACCESSED set */ | 517 | /* We only want HPTEs for linux PTEs that have _PAGE_ACCESSED set */ |
516 | if (!pte_young(*ptep) || address >= TASK_SIZE) | 518 | if (!pte_young(*ptep) || address >= TASK_SIZE) |
diff --git a/arch/powerpc/mm/mmu_context.c b/arch/powerpc/mm/mmu_context.c index 0ab297c4cfad..f84e14f23e50 100644 --- a/arch/powerpc/mm/mmu_context.c +++ b/arch/powerpc/mm/mmu_context.c | |||
@@ -57,8 +57,10 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next, | |||
57 | * in switch_slb(), and/or the store of paca->mm_ctx_id in | 57 | * in switch_slb(), and/or the store of paca->mm_ctx_id in |
58 | * copy_mm_to_paca(). | 58 | * copy_mm_to_paca(). |
59 | * | 59 | * |
60 | * On the read side the barrier is in pte_xchg(), which orders | 60 | * On the other side, the barrier is in mm/tlb-radix.c for |
61 | * the store to the PTE vs the load of mm_cpumask. | 61 | * radix which orders earlier stores to clear the PTEs vs |
62 | * the load of mm_cpumask. And pte_xchg which does the same | ||
63 | * thing for hash. | ||
62 | * | 64 | * |
63 | * This full barrier is needed by membarrier when switching | 65 | * This full barrier is needed by membarrier when switching |
64 | * between processes after store to rq->curr, before user-space | 66 | * between processes after store to rq->curr, before user-space |
diff --git a/arch/powerpc/mm/mmu_context_book3s64.c b/arch/powerpc/mm/mmu_context_book3s64.c index b75194dff64c..f3d4b4a0e561 100644 --- a/arch/powerpc/mm/mmu_context_book3s64.c +++ b/arch/powerpc/mm/mmu_context_book3s64.c | |||
@@ -159,9 +159,8 @@ int init_new_context(struct task_struct *tsk, struct mm_struct *mm) | |||
159 | 159 | ||
160 | mm->context.id = index; | 160 | mm->context.id = index; |
161 | 161 | ||
162 | #ifdef CONFIG_PPC_64K_PAGES | ||
163 | mm->context.pte_frag = NULL; | 162 | mm->context.pte_frag = NULL; |
164 | #endif | 163 | mm->context.pmd_frag = NULL; |
165 | #ifdef CONFIG_SPAPR_TCE_IOMMU | 164 | #ifdef CONFIG_SPAPR_TCE_IOMMU |
166 | mm_iommu_init(mm); | 165 | mm_iommu_init(mm); |
167 | #endif | 166 | #endif |
@@ -192,17 +191,11 @@ static void destroy_contexts(mm_context_t *ctx) | |||
192 | spin_unlock(&mmu_context_lock); | 191 | spin_unlock(&mmu_context_lock); |
193 | } | 192 | } |
194 | 193 | ||
195 | #ifdef CONFIG_PPC_64K_PAGES | 194 | static void pte_frag_destroy(void *pte_frag) |
196 | static void destroy_pagetable_page(struct mm_struct *mm) | ||
197 | { | 195 | { |
198 | int count; | 196 | int count; |
199 | void *pte_frag; | ||
200 | struct page *page; | 197 | struct page *page; |
201 | 198 | ||
202 | pte_frag = mm->context.pte_frag; | ||
203 | if (!pte_frag) | ||
204 | return; | ||
205 | |||
206 | page = virt_to_page(pte_frag); | 199 | page = virt_to_page(pte_frag); |
207 | /* drop all the pending references */ | 200 | /* drop all the pending references */ |
208 | count = ((unsigned long)pte_frag & ~PAGE_MASK) >> PTE_FRAG_SIZE_SHIFT; | 201 | count = ((unsigned long)pte_frag & ~PAGE_MASK) >> PTE_FRAG_SIZE_SHIFT; |
@@ -213,12 +206,34 @@ static void destroy_pagetable_page(struct mm_struct *mm) | |||
213 | } | 206 | } |
214 | } | 207 | } |
215 | 208 | ||
216 | #else | 209 | static void pmd_frag_destroy(void *pmd_frag) |
217 | static inline void destroy_pagetable_page(struct mm_struct *mm) | ||
218 | { | 210 | { |
211 | int count; | ||
212 | struct page *page; | ||
213 | |||
214 | page = virt_to_page(pmd_frag); | ||
215 | /* drop all the pending references */ | ||
216 | count = ((unsigned long)pmd_frag & ~PAGE_MASK) >> PMD_FRAG_SIZE_SHIFT; | ||
217 | /* We allow PTE_FRAG_NR fragments from a PTE page */ | ||
218 | if (page_ref_sub_and_test(page, PMD_FRAG_NR - count)) { | ||
219 | pgtable_pmd_page_dtor(page); | ||
220 | free_unref_page(page); | ||
221 | } | ||
222 | } | ||
223 | |||
224 | static void destroy_pagetable_page(struct mm_struct *mm) | ||
225 | { | ||
226 | void *frag; | ||
227 | |||
228 | frag = mm->context.pte_frag; | ||
229 | if (frag) | ||
230 | pte_frag_destroy(frag); | ||
231 | |||
232 | frag = mm->context.pmd_frag; | ||
233 | if (frag) | ||
234 | pmd_frag_destroy(frag); | ||
219 | return; | 235 | return; |
220 | } | 236 | } |
221 | #endif | ||
222 | 237 | ||
223 | void destroy_context(struct mm_struct *mm) | 238 | void destroy_context(struct mm_struct *mm) |
224 | { | 239 | { |
diff --git a/arch/powerpc/mm/mmu_context_nohash.c b/arch/powerpc/mm/mmu_context_nohash.c index be8f5c9d4d08..4d80239ef83c 100644 --- a/arch/powerpc/mm/mmu_context_nohash.c +++ b/arch/powerpc/mm/mmu_context_nohash.c | |||
@@ -54,16 +54,44 @@ | |||
54 | 54 | ||
55 | #include "mmu_decl.h" | 55 | #include "mmu_decl.h" |
56 | 56 | ||
57 | static unsigned int first_context, last_context; | 57 | /* |
58 | * The MPC8xx has only 16 contexts. We rotate through them on each task switch. | ||
59 | * A better way would be to keep track of tasks that own contexts, and implement | ||
60 | * an LRU usage. That way very active tasks don't always have to pay the TLB | ||
61 | * reload overhead. The kernel pages are mapped shared, so the kernel can run on | ||
62 | * behalf of any task that makes a kernel entry. Shared does not mean they are | ||
63 | * not protected, just that the ASID comparison is not performed. -- Dan | ||
64 | * | ||
65 | * The IBM4xx has 256 contexts, so we can just rotate through these as a way of | ||
66 | * "switching" contexts. If the TID of the TLB is zero, the PID/TID comparison | ||
67 | * is disabled, so we can use a TID of zero to represent all kernel pages as | ||
68 | * shared among all contexts. -- Dan | ||
69 | * | ||
70 | * The IBM 47x core supports 16-bit PIDs, thus 65535 contexts. We should | ||
71 | * normally never have to steal though the facility is present if needed. | ||
72 | * -- BenH | ||
73 | */ | ||
74 | #define FIRST_CONTEXT 1 | ||
75 | #ifdef DEBUG_CLAMP_LAST_CONTEXT | ||
76 | #define LAST_CONTEXT DEBUG_CLAMP_LAST_CONTEXT | ||
77 | #elif defined(CONFIG_PPC_8xx) | ||
78 | #define LAST_CONTEXT 16 | ||
79 | #elif defined(CONFIG_PPC_47x) | ||
80 | #define LAST_CONTEXT 65535 | ||
81 | #else | ||
82 | #define LAST_CONTEXT 255 | ||
83 | #endif | ||
84 | |||
58 | static unsigned int next_context, nr_free_contexts; | 85 | static unsigned int next_context, nr_free_contexts; |
59 | static unsigned long *context_map; | 86 | static unsigned long *context_map; |
87 | #ifdef CONFIG_SMP | ||
60 | static unsigned long *stale_map[NR_CPUS]; | 88 | static unsigned long *stale_map[NR_CPUS]; |
89 | #endif | ||
61 | static struct mm_struct **context_mm; | 90 | static struct mm_struct **context_mm; |
62 | static DEFINE_RAW_SPINLOCK(context_lock); | 91 | static DEFINE_RAW_SPINLOCK(context_lock); |
63 | static bool no_selective_tlbil; | ||
64 | 92 | ||
65 | #define CTX_MAP_SIZE \ | 93 | #define CTX_MAP_SIZE \ |
66 | (sizeof(unsigned long) * (last_context / BITS_PER_LONG + 1)) | 94 | (sizeof(unsigned long) * (LAST_CONTEXT / BITS_PER_LONG + 1)) |
67 | 95 | ||
68 | 96 | ||
69 | /* Steal a context from a task that has one at the moment. | 97 | /* Steal a context from a task that has one at the moment. |
@@ -87,7 +115,7 @@ static unsigned int steal_context_smp(unsigned int id) | |||
87 | struct mm_struct *mm; | 115 | struct mm_struct *mm; |
88 | unsigned int cpu, max, i; | 116 | unsigned int cpu, max, i; |
89 | 117 | ||
90 | max = last_context - first_context; | 118 | max = LAST_CONTEXT - FIRST_CONTEXT; |
91 | 119 | ||
92 | /* Attempt to free next_context first and then loop until we manage */ | 120 | /* Attempt to free next_context first and then loop until we manage */ |
93 | while (max--) { | 121 | while (max--) { |
@@ -99,8 +127,8 @@ static unsigned int steal_context_smp(unsigned int id) | |||
99 | */ | 127 | */ |
100 | if (mm->context.active) { | 128 | if (mm->context.active) { |
101 | id++; | 129 | id++; |
102 | if (id > last_context) | 130 | if (id > LAST_CONTEXT) |
103 | id = first_context; | 131 | id = FIRST_CONTEXT; |
104 | continue; | 132 | continue; |
105 | } | 133 | } |
106 | pr_hardcont(" | steal %d from 0x%p", id, mm); | 134 | pr_hardcont(" | steal %d from 0x%p", id, mm); |
@@ -139,10 +167,12 @@ static unsigned int steal_context_smp(unsigned int id) | |||
139 | static unsigned int steal_all_contexts(void) | 167 | static unsigned int steal_all_contexts(void) |
140 | { | 168 | { |
141 | struct mm_struct *mm; | 169 | struct mm_struct *mm; |
170 | #ifdef CONFIG_SMP | ||
142 | int cpu = smp_processor_id(); | 171 | int cpu = smp_processor_id(); |
172 | #endif | ||
143 | unsigned int id; | 173 | unsigned int id; |
144 | 174 | ||
145 | for (id = first_context; id <= last_context; id++) { | 175 | for (id = FIRST_CONTEXT; id <= LAST_CONTEXT; id++) { |
146 | /* Pick up the victim mm */ | 176 | /* Pick up the victim mm */ |
147 | mm = context_mm[id]; | 177 | mm = context_mm[id]; |
148 | 178 | ||
@@ -150,22 +180,24 @@ static unsigned int steal_all_contexts(void) | |||
150 | 180 | ||
151 | /* Mark this mm as having no context anymore */ | 181 | /* Mark this mm as having no context anymore */ |
152 | mm->context.id = MMU_NO_CONTEXT; | 182 | mm->context.id = MMU_NO_CONTEXT; |
153 | if (id != first_context) { | 183 | if (id != FIRST_CONTEXT) { |
154 | context_mm[id] = NULL; | 184 | context_mm[id] = NULL; |
155 | __clear_bit(id, context_map); | 185 | __clear_bit(id, context_map); |
156 | #ifdef DEBUG_MAP_CONSISTENCY | 186 | #ifdef DEBUG_MAP_CONSISTENCY |
157 | mm->context.active = 0; | 187 | mm->context.active = 0; |
158 | #endif | 188 | #endif |
159 | } | 189 | } |
190 | #ifdef CONFIG_SMP | ||
160 | __clear_bit(id, stale_map[cpu]); | 191 | __clear_bit(id, stale_map[cpu]); |
192 | #endif | ||
161 | } | 193 | } |
162 | 194 | ||
163 | /* Flush the TLB for all contexts (not to be used on SMP) */ | 195 | /* Flush the TLB for all contexts (not to be used on SMP) */ |
164 | _tlbil_all(); | 196 | _tlbil_all(); |
165 | 197 | ||
166 | nr_free_contexts = last_context - first_context; | 198 | nr_free_contexts = LAST_CONTEXT - FIRST_CONTEXT; |
167 | 199 | ||
168 | return first_context; | 200 | return FIRST_CONTEXT; |
169 | } | 201 | } |
170 | 202 | ||
171 | /* Note that this will also be called on SMP if all other CPUs are | 203 | /* Note that this will also be called on SMP if all other CPUs are |
@@ -176,7 +208,9 @@ static unsigned int steal_all_contexts(void) | |||
176 | static unsigned int steal_context_up(unsigned int id) | 208 | static unsigned int steal_context_up(unsigned int id) |
177 | { | 209 | { |
178 | struct mm_struct *mm; | 210 | struct mm_struct *mm; |
211 | #ifdef CONFIG_SMP | ||
179 | int cpu = smp_processor_id(); | 212 | int cpu = smp_processor_id(); |
213 | #endif | ||
180 | 214 | ||
181 | /* Pick up the victim mm */ | 215 | /* Pick up the victim mm */ |
182 | mm = context_mm[id]; | 216 | mm = context_mm[id]; |
@@ -190,7 +224,9 @@ static unsigned int steal_context_up(unsigned int id) | |||
190 | mm->context.id = MMU_NO_CONTEXT; | 224 | mm->context.id = MMU_NO_CONTEXT; |
191 | 225 | ||
192 | /* XXX This clear should ultimately be part of local_flush_tlb_mm */ | 226 | /* XXX This clear should ultimately be part of local_flush_tlb_mm */ |
227 | #ifdef CONFIG_SMP | ||
193 | __clear_bit(id, stale_map[cpu]); | 228 | __clear_bit(id, stale_map[cpu]); |
229 | #endif | ||
194 | 230 | ||
195 | return id; | 231 | return id; |
196 | } | 232 | } |
@@ -201,7 +237,7 @@ static void context_check_map(void) | |||
201 | unsigned int id, nrf, nact; | 237 | unsigned int id, nrf, nact; |
202 | 238 | ||
203 | nrf = nact = 0; | 239 | nrf = nact = 0; |
204 | for (id = first_context; id <= last_context; id++) { | 240 | for (id = FIRST_CONTEXT; id <= LAST_CONTEXT; id++) { |
205 | int used = test_bit(id, context_map); | 241 | int used = test_bit(id, context_map); |
206 | if (!used) | 242 | if (!used) |
207 | nrf++; | 243 | nrf++; |
@@ -219,7 +255,7 @@ static void context_check_map(void) | |||
219 | if (nact > num_online_cpus()) | 255 | if (nact > num_online_cpus()) |
220 | pr_err("MMU: More active contexts than CPUs ! (%d vs %d)\n", | 256 | pr_err("MMU: More active contexts than CPUs ! (%d vs %d)\n", |
221 | nact, num_online_cpus()); | 257 | nact, num_online_cpus()); |
222 | if (first_context > 0 && !test_bit(0, context_map)) | 258 | if (FIRST_CONTEXT > 0 && !test_bit(0, context_map)) |
223 | pr_err("MMU: Context 0 has been freed !!!\n"); | 259 | pr_err("MMU: Context 0 has been freed !!!\n"); |
224 | } | 260 | } |
225 | #else | 261 | #else |
@@ -229,7 +265,10 @@ static void context_check_map(void) { } | |||
229 | void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next, | 265 | void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next, |
230 | struct task_struct *tsk) | 266 | struct task_struct *tsk) |
231 | { | 267 | { |
232 | unsigned int i, id, cpu = smp_processor_id(); | 268 | unsigned int id; |
269 | #ifdef CONFIG_SMP | ||
270 | unsigned int i, cpu = smp_processor_id(); | ||
271 | #endif | ||
233 | unsigned long *map; | 272 | unsigned long *map; |
234 | 273 | ||
235 | /* No lockless fast path .. yet */ | 274 | /* No lockless fast path .. yet */ |
@@ -263,8 +302,8 @@ void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next, | |||
263 | 302 | ||
264 | /* We really don't have a context, let's try to acquire one */ | 303 | /* We really don't have a context, let's try to acquire one */ |
265 | id = next_context; | 304 | id = next_context; |
266 | if (id > last_context) | 305 | if (id > LAST_CONTEXT) |
267 | id = first_context; | 306 | id = FIRST_CONTEXT; |
268 | map = context_map; | 307 | map = context_map; |
269 | 308 | ||
270 | /* No more free contexts, let's try to steal one */ | 309 | /* No more free contexts, let's try to steal one */ |
@@ -277,7 +316,7 @@ void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next, | |||
277 | goto stolen; | 316 | goto stolen; |
278 | } | 317 | } |
279 | #endif /* CONFIG_SMP */ | 318 | #endif /* CONFIG_SMP */ |
280 | if (no_selective_tlbil) | 319 | if (IS_ENABLED(CONFIG_PPC_8xx)) |
281 | id = steal_all_contexts(); | 320 | id = steal_all_contexts(); |
282 | else | 321 | else |
283 | id = steal_context_up(id); | 322 | id = steal_context_up(id); |
@@ -287,9 +326,9 @@ void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next, | |||
287 | 326 | ||
288 | /* We know there's at least one free context, try to find it */ | 327 | /* We know there's at least one free context, try to find it */ |
289 | while (__test_and_set_bit(id, map)) { | 328 | while (__test_and_set_bit(id, map)) { |
290 | id = find_next_zero_bit(map, last_context+1, id); | 329 | id = find_next_zero_bit(map, LAST_CONTEXT+1, id); |
291 | if (id > last_context) | 330 | if (id > LAST_CONTEXT) |
292 | id = first_context; | 331 | id = FIRST_CONTEXT; |
293 | } | 332 | } |
294 | stolen: | 333 | stolen: |
295 | next_context = id + 1; | 334 | next_context = id + 1; |
@@ -303,6 +342,7 @@ void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next, | |||
303 | /* If that context got marked stale on this CPU, then flush the | 342 | /* If that context got marked stale on this CPU, then flush the |
304 | * local TLB for it and unmark it before we use it | 343 | * local TLB for it and unmark it before we use it |
305 | */ | 344 | */ |
345 | #ifdef CONFIG_SMP | ||
306 | if (test_bit(id, stale_map[cpu])) { | 346 | if (test_bit(id, stale_map[cpu])) { |
307 | pr_hardcont(" | stale flush %d [%d..%d]", | 347 | pr_hardcont(" | stale flush %d [%d..%d]", |
308 | id, cpu_first_thread_sibling(cpu), | 348 | id, cpu_first_thread_sibling(cpu), |
@@ -317,6 +357,7 @@ void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next, | |||
317 | __clear_bit(id, stale_map[i]); | 357 | __clear_bit(id, stale_map[i]); |
318 | } | 358 | } |
319 | } | 359 | } |
360 | #endif | ||
320 | 361 | ||
321 | /* Flick the MMU and release lock */ | 362 | /* Flick the MMU and release lock */ |
322 | pr_hardcont(" -> %d\n", id); | 363 | pr_hardcont(" -> %d\n", id); |
@@ -418,51 +459,11 @@ void __init mmu_context_init(void) | |||
418 | init_mm.context.active = NR_CPUS; | 459 | init_mm.context.active = NR_CPUS; |
419 | 460 | ||
420 | /* | 461 | /* |
421 | * The MPC8xx has only 16 contexts. We rotate through them on each | ||
422 | * task switch. A better way would be to keep track of tasks that | ||
423 | * own contexts, and implement an LRU usage. That way very active | ||
424 | * tasks don't always have to pay the TLB reload overhead. The | ||
425 | * kernel pages are mapped shared, so the kernel can run on behalf | ||
426 | * of any task that makes a kernel entry. Shared does not mean they | ||
427 | * are not protected, just that the ASID comparison is not performed. | ||
428 | * -- Dan | ||
429 | * | ||
430 | * The IBM4xx has 256 contexts, so we can just rotate through these | ||
431 | * as a way of "switching" contexts. If the TID of the TLB is zero, | ||
432 | * the PID/TID comparison is disabled, so we can use a TID of zero | ||
433 | * to represent all kernel pages as shared among all contexts. | ||
434 | * -- Dan | ||
435 | * | ||
436 | * The IBM 47x core supports 16-bit PIDs, thus 65535 contexts. We | ||
437 | * should normally never have to steal though the facility is | ||
438 | * present if needed. | ||
439 | * -- BenH | ||
440 | */ | ||
441 | if (mmu_has_feature(MMU_FTR_TYPE_8xx)) { | ||
442 | first_context = 1; | ||
443 | last_context = 16; | ||
444 | no_selective_tlbil = true; | ||
445 | } else if (mmu_has_feature(MMU_FTR_TYPE_47x)) { | ||
446 | first_context = 1; | ||
447 | last_context = 65535; | ||
448 | no_selective_tlbil = false; | ||
449 | } else { | ||
450 | first_context = 1; | ||
451 | last_context = 255; | ||
452 | no_selective_tlbil = false; | ||
453 | } | ||
454 | |||
455 | #ifdef DEBUG_CLAMP_LAST_CONTEXT | ||
456 | last_context = DEBUG_CLAMP_LAST_CONTEXT; | ||
457 | #endif | ||
458 | /* | ||
459 | * Allocate the maps used by context management | 462 | * Allocate the maps used by context management |
460 | */ | 463 | */ |
461 | context_map = memblock_virt_alloc(CTX_MAP_SIZE, 0); | 464 | context_map = memblock_virt_alloc(CTX_MAP_SIZE, 0); |
462 | context_mm = memblock_virt_alloc(sizeof(void *) * (last_context + 1), 0); | 465 | context_mm = memblock_virt_alloc(sizeof(void *) * (LAST_CONTEXT + 1), 0); |
463 | #ifndef CONFIG_SMP | 466 | #ifdef CONFIG_SMP |
464 | stale_map[0] = memblock_virt_alloc(CTX_MAP_SIZE, 0); | ||
465 | #else | ||
466 | stale_map[boot_cpuid] = memblock_virt_alloc(CTX_MAP_SIZE, 0); | 467 | stale_map[boot_cpuid] = memblock_virt_alloc(CTX_MAP_SIZE, 0); |
467 | 468 | ||
468 | cpuhp_setup_state_nocalls(CPUHP_POWERPC_MMU_CTX_PREPARE, | 469 | cpuhp_setup_state_nocalls(CPUHP_POWERPC_MMU_CTX_PREPARE, |
@@ -472,17 +473,17 @@ void __init mmu_context_init(void) | |||
472 | 473 | ||
473 | printk(KERN_INFO | 474 | printk(KERN_INFO |
474 | "MMU: Allocated %zu bytes of context maps for %d contexts\n", | 475 | "MMU: Allocated %zu bytes of context maps for %d contexts\n", |
475 | 2 * CTX_MAP_SIZE + (sizeof(void *) * (last_context + 1)), | 476 | 2 * CTX_MAP_SIZE + (sizeof(void *) * (LAST_CONTEXT + 1)), |
476 | last_context - first_context + 1); | 477 | LAST_CONTEXT - FIRST_CONTEXT + 1); |
477 | 478 | ||
478 | /* | 479 | /* |
479 | * Some processors have too few contexts to reserve one for | 480 | * Some processors have too few contexts to reserve one for |
480 | * init_mm, and require using context 0 for a normal task. | 481 | * init_mm, and require using context 0 for a normal task. |
481 | * Other processors reserve the use of context zero for the kernel. | 482 | * Other processors reserve the use of context zero for the kernel. |
482 | * This code assumes first_context < 32. | 483 | * This code assumes FIRST_CONTEXT < 32. |
483 | */ | 484 | */ |
484 | context_map[0] = (1 << first_context) - 1; | 485 | context_map[0] = (1 << FIRST_CONTEXT) - 1; |
485 | next_context = first_context; | 486 | next_context = FIRST_CONTEXT; |
486 | nr_free_contexts = last_context - first_context + 1; | 487 | nr_free_contexts = LAST_CONTEXT - FIRST_CONTEXT + 1; |
487 | } | 488 | } |
488 | 489 | ||
diff --git a/arch/powerpc/mm/pgtable-book3s64.c b/arch/powerpc/mm/pgtable-book3s64.c index 518518fb7c45..c1f4ca45c93a 100644 --- a/arch/powerpc/mm/pgtable-book3s64.c +++ b/arch/powerpc/mm/pgtable-book3s64.c | |||
@@ -9,14 +9,22 @@ | |||
9 | 9 | ||
10 | #include <linux/sched.h> | 10 | #include <linux/sched.h> |
11 | #include <linux/mm_types.h> | 11 | #include <linux/mm_types.h> |
12 | #include <linux/memblock.h> | ||
12 | #include <misc/cxl-base.h> | 13 | #include <misc/cxl-base.h> |
13 | 14 | ||
14 | #include <asm/pgalloc.h> | 15 | #include <asm/pgalloc.h> |
15 | #include <asm/tlb.h> | 16 | #include <asm/tlb.h> |
17 | #include <asm/trace.h> | ||
18 | #include <asm/powernv.h> | ||
16 | 19 | ||
17 | #include "mmu_decl.h" | 20 | #include "mmu_decl.h" |
18 | #include <trace/events/thp.h> | 21 | #include <trace/events/thp.h> |
19 | 22 | ||
23 | unsigned long __pmd_frag_nr; | ||
24 | EXPORT_SYMBOL(__pmd_frag_nr); | ||
25 | unsigned long __pmd_frag_size_shift; | ||
26 | EXPORT_SYMBOL(__pmd_frag_size_shift); | ||
27 | |||
20 | int (*register_process_table)(unsigned long base, unsigned long page_size, | 28 | int (*register_process_table)(unsigned long base, unsigned long page_size, |
21 | unsigned long tbl_size); | 29 | unsigned long tbl_size); |
22 | 30 | ||
@@ -34,13 +42,16 @@ int pmdp_set_access_flags(struct vm_area_struct *vma, unsigned long address, | |||
34 | int changed; | 42 | int changed; |
35 | #ifdef CONFIG_DEBUG_VM | 43 | #ifdef CONFIG_DEBUG_VM |
36 | WARN_ON(!pmd_trans_huge(*pmdp) && !pmd_devmap(*pmdp)); | 44 | WARN_ON(!pmd_trans_huge(*pmdp) && !pmd_devmap(*pmdp)); |
37 | assert_spin_locked(&vma->vm_mm->page_table_lock); | 45 | assert_spin_locked(pmd_lockptr(vma->vm_mm, pmdp)); |
38 | #endif | 46 | #endif |
39 | changed = !pmd_same(*(pmdp), entry); | 47 | changed = !pmd_same(*(pmdp), entry); |
40 | if (changed) { | 48 | if (changed) { |
41 | __ptep_set_access_flags(vma->vm_mm, pmdp_ptep(pmdp), | 49 | /* |
42 | pmd_pte(entry), address); | 50 | * We can use MMU_PAGE_2M here, because only radix |
43 | flush_pmd_tlb_range(vma, address, address + HPAGE_PMD_SIZE); | 51 | * path look at the psize. |
52 | */ | ||
53 | __ptep_set_access_flags(vma, pmdp_ptep(pmdp), | ||
54 | pmd_pte(entry), address, MMU_PAGE_2M); | ||
44 | } | 55 | } |
45 | return changed; | 56 | return changed; |
46 | } | 57 | } |
@@ -59,7 +70,7 @@ void set_pmd_at(struct mm_struct *mm, unsigned long addr, | |||
59 | { | 70 | { |
60 | #ifdef CONFIG_DEBUG_VM | 71 | #ifdef CONFIG_DEBUG_VM |
61 | WARN_ON(pte_present(pmd_pte(*pmdp)) && !pte_protnone(pmd_pte(*pmdp))); | 72 | WARN_ON(pte_present(pmd_pte(*pmdp)) && !pte_protnone(pmd_pte(*pmdp))); |
62 | assert_spin_locked(&mm->page_table_lock); | 73 | assert_spin_locked(pmd_lockptr(mm, pmdp)); |
63 | WARN_ON(!(pmd_trans_huge(pmd) || pmd_devmap(pmd))); | 74 | WARN_ON(!(pmd_trans_huge(pmd) || pmd_devmap(pmd))); |
64 | #endif | 75 | #endif |
65 | trace_hugepage_set_pmd(addr, pmd_val(pmd)); | 76 | trace_hugepage_set_pmd(addr, pmd_val(pmd)); |
@@ -141,7 +152,8 @@ pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) | |||
141 | void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr, | 152 | void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr, |
142 | pmd_t *pmd) | 153 | pmd_t *pmd) |
143 | { | 154 | { |
144 | return; | 155 | if (radix_enabled()) |
156 | prefetch((void *)addr); | ||
145 | } | 157 | } |
146 | #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ | 158 | #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ |
147 | 159 | ||
@@ -171,3 +183,258 @@ int __meminit remove_section_mapping(unsigned long start, unsigned long end) | |||
171 | return hash__remove_section_mapping(start, end); | 183 | return hash__remove_section_mapping(start, end); |
172 | } | 184 | } |
173 | #endif /* CONFIG_MEMORY_HOTPLUG */ | 185 | #endif /* CONFIG_MEMORY_HOTPLUG */ |
186 | |||
187 | void __init mmu_partition_table_init(void) | ||
188 | { | ||
189 | unsigned long patb_size = 1UL << PATB_SIZE_SHIFT; | ||
190 | unsigned long ptcr; | ||
191 | |||
192 | BUILD_BUG_ON_MSG((PATB_SIZE_SHIFT > 36), "Partition table size too large."); | ||
193 | partition_tb = __va(memblock_alloc_base(patb_size, patb_size, | ||
194 | MEMBLOCK_ALLOC_ANYWHERE)); | ||
195 | |||
196 | /* Initialize the Partition Table with no entries */ | ||
197 | memset((void *)partition_tb, 0, patb_size); | ||
198 | |||
199 | /* | ||
200 | * update partition table control register, | ||
201 | * 64 K size. | ||
202 | */ | ||
203 | ptcr = __pa(partition_tb) | (PATB_SIZE_SHIFT - 12); | ||
204 | mtspr(SPRN_PTCR, ptcr); | ||
205 | powernv_set_nmmu_ptcr(ptcr); | ||
206 | } | ||
207 | |||
208 | void mmu_partition_table_set_entry(unsigned int lpid, unsigned long dw0, | ||
209 | unsigned long dw1) | ||
210 | { | ||
211 | unsigned long old = be64_to_cpu(partition_tb[lpid].patb0); | ||
212 | |||
213 | partition_tb[lpid].patb0 = cpu_to_be64(dw0); | ||
214 | partition_tb[lpid].patb1 = cpu_to_be64(dw1); | ||
215 | |||
216 | /* | ||
217 | * Global flush of TLBs and partition table caches for this lpid. | ||
218 | * The type of flush (hash or radix) depends on what the previous | ||
219 | * use of this partition ID was, not the new use. | ||
220 | */ | ||
221 | asm volatile("ptesync" : : : "memory"); | ||
222 | if (old & PATB_HR) { | ||
223 | asm volatile(PPC_TLBIE_5(%0,%1,2,0,1) : : | ||
224 | "r" (TLBIEL_INVAL_SET_LPID), "r" (lpid)); | ||
225 | asm volatile(PPC_TLBIE_5(%0,%1,2,1,1) : : | ||
226 | "r" (TLBIEL_INVAL_SET_LPID), "r" (lpid)); | ||
227 | trace_tlbie(lpid, 0, TLBIEL_INVAL_SET_LPID, lpid, 2, 0, 1); | ||
228 | } else { | ||
229 | asm volatile(PPC_TLBIE_5(%0,%1,2,0,0) : : | ||
230 | "r" (TLBIEL_INVAL_SET_LPID), "r" (lpid)); | ||
231 | trace_tlbie(lpid, 0, TLBIEL_INVAL_SET_LPID, lpid, 2, 0, 0); | ||
232 | } | ||
233 | /* do we need fixup here ?*/ | ||
234 | asm volatile("eieio; tlbsync; ptesync" : : : "memory"); | ||
235 | } | ||
236 | EXPORT_SYMBOL_GPL(mmu_partition_table_set_entry); | ||
237 | |||
238 | static pmd_t *get_pmd_from_cache(struct mm_struct *mm) | ||
239 | { | ||
240 | void *pmd_frag, *ret; | ||
241 | |||
242 | spin_lock(&mm->page_table_lock); | ||
243 | ret = mm->context.pmd_frag; | ||
244 | if (ret) { | ||
245 | pmd_frag = ret + PMD_FRAG_SIZE; | ||
246 | /* | ||
247 | * If we have taken up all the fragments mark PTE page NULL | ||
248 | */ | ||
249 | if (((unsigned long)pmd_frag & ~PAGE_MASK) == 0) | ||
250 | pmd_frag = NULL; | ||
251 | mm->context.pmd_frag = pmd_frag; | ||
252 | } | ||
253 | spin_unlock(&mm->page_table_lock); | ||
254 | return (pmd_t *)ret; | ||
255 | } | ||
256 | |||
257 | static pmd_t *__alloc_for_pmdcache(struct mm_struct *mm) | ||
258 | { | ||
259 | void *ret = NULL; | ||
260 | struct page *page; | ||
261 | gfp_t gfp = GFP_KERNEL_ACCOUNT | __GFP_ZERO; | ||
262 | |||
263 | if (mm == &init_mm) | ||
264 | gfp &= ~__GFP_ACCOUNT; | ||
265 | page = alloc_page(gfp); | ||
266 | if (!page) | ||
267 | return NULL; | ||
268 | if (!pgtable_pmd_page_ctor(page)) { | ||
269 | __free_pages(page, 0); | ||
270 | return NULL; | ||
271 | } | ||
272 | |||
273 | ret = page_address(page); | ||
274 | /* | ||
275 | * if we support only one fragment just return the | ||
276 | * allocated page. | ||
277 | */ | ||
278 | if (PMD_FRAG_NR == 1) | ||
279 | return ret; | ||
280 | |||
281 | spin_lock(&mm->page_table_lock); | ||
282 | /* | ||
283 | * If we find pgtable_page set, we return | ||
284 | * the allocated page with single fragement | ||
285 | * count. | ||
286 | */ | ||
287 | if (likely(!mm->context.pmd_frag)) { | ||
288 | set_page_count(page, PMD_FRAG_NR); | ||
289 | mm->context.pmd_frag = ret + PMD_FRAG_SIZE; | ||
290 | } | ||
291 | spin_unlock(&mm->page_table_lock); | ||
292 | |||
293 | return (pmd_t *)ret; | ||
294 | } | ||
295 | |||
296 | pmd_t *pmd_fragment_alloc(struct mm_struct *mm, unsigned long vmaddr) | ||
297 | { | ||
298 | pmd_t *pmd; | ||
299 | |||
300 | pmd = get_pmd_from_cache(mm); | ||
301 | if (pmd) | ||
302 | return pmd; | ||
303 | |||
304 | return __alloc_for_pmdcache(mm); | ||
305 | } | ||
306 | |||
307 | void pmd_fragment_free(unsigned long *pmd) | ||
308 | { | ||
309 | struct page *page = virt_to_page(pmd); | ||
310 | |||
311 | if (put_page_testzero(page)) { | ||
312 | pgtable_pmd_page_dtor(page); | ||
313 | free_unref_page(page); | ||
314 | } | ||
315 | } | ||
316 | |||
317 | static pte_t *get_pte_from_cache(struct mm_struct *mm) | ||
318 | { | ||
319 | void *pte_frag, *ret; | ||
320 | |||
321 | spin_lock(&mm->page_table_lock); | ||
322 | ret = mm->context.pte_frag; | ||
323 | if (ret) { | ||
324 | pte_frag = ret + PTE_FRAG_SIZE; | ||
325 | /* | ||
326 | * If we have taken up all the fragments mark PTE page NULL | ||
327 | */ | ||
328 | if (((unsigned long)pte_frag & ~PAGE_MASK) == 0) | ||
329 | pte_frag = NULL; | ||
330 | mm->context.pte_frag = pte_frag; | ||
331 | } | ||
332 | spin_unlock(&mm->page_table_lock); | ||
333 | return (pte_t *)ret; | ||
334 | } | ||
335 | |||
336 | static pte_t *__alloc_for_ptecache(struct mm_struct *mm, int kernel) | ||
337 | { | ||
338 | void *ret = NULL; | ||
339 | struct page *page; | ||
340 | |||
341 | if (!kernel) { | ||
342 | page = alloc_page(PGALLOC_GFP | __GFP_ACCOUNT); | ||
343 | if (!page) | ||
344 | return NULL; | ||
345 | if (!pgtable_page_ctor(page)) { | ||
346 | __free_page(page); | ||
347 | return NULL; | ||
348 | } | ||
349 | } else { | ||
350 | page = alloc_page(PGALLOC_GFP); | ||
351 | if (!page) | ||
352 | return NULL; | ||
353 | } | ||
354 | |||
355 | |||
356 | ret = page_address(page); | ||
357 | /* | ||
358 | * if we support only one fragment just return the | ||
359 | * allocated page. | ||
360 | */ | ||
361 | if (PTE_FRAG_NR == 1) | ||
362 | return ret; | ||
363 | spin_lock(&mm->page_table_lock); | ||
364 | /* | ||
365 | * If we find pgtable_page set, we return | ||
366 | * the allocated page with single fragement | ||
367 | * count. | ||
368 | */ | ||
369 | if (likely(!mm->context.pte_frag)) { | ||
370 | set_page_count(page, PTE_FRAG_NR); | ||
371 | mm->context.pte_frag = ret + PTE_FRAG_SIZE; | ||
372 | } | ||
373 | spin_unlock(&mm->page_table_lock); | ||
374 | |||
375 | return (pte_t *)ret; | ||
376 | } | ||
377 | |||
378 | pte_t *pte_fragment_alloc(struct mm_struct *mm, unsigned long vmaddr, int kernel) | ||
379 | { | ||
380 | pte_t *pte; | ||
381 | |||
382 | pte = get_pte_from_cache(mm); | ||
383 | if (pte) | ||
384 | return pte; | ||
385 | |||
386 | return __alloc_for_ptecache(mm, kernel); | ||
387 | } | ||
388 | |||
389 | void pte_fragment_free(unsigned long *table, int kernel) | ||
390 | { | ||
391 | struct page *page = virt_to_page(table); | ||
392 | |||
393 | if (put_page_testzero(page)) { | ||
394 | if (!kernel) | ||
395 | pgtable_page_dtor(page); | ||
396 | free_unref_page(page); | ||
397 | } | ||
398 | } | ||
399 | |||
400 | static inline void pgtable_free(void *table, int index) | ||
401 | { | ||
402 | switch (index) { | ||
403 | case PTE_INDEX: | ||
404 | pte_fragment_free(table, 0); | ||
405 | break; | ||
406 | case PMD_INDEX: | ||
407 | pmd_fragment_free(table); | ||
408 | break; | ||
409 | case PUD_INDEX: | ||
410 | kmem_cache_free(PGT_CACHE(PUD_CACHE_INDEX), table); | ||
411 | break; | ||
412 | /* We don't free pgd table via RCU callback */ | ||
413 | default: | ||
414 | BUG(); | ||
415 | } | ||
416 | } | ||
417 | |||
418 | #ifdef CONFIG_SMP | ||
419 | void pgtable_free_tlb(struct mmu_gather *tlb, void *table, int index) | ||
420 | { | ||
421 | unsigned long pgf = (unsigned long)table; | ||
422 | |||
423 | BUG_ON(index > MAX_PGTABLE_INDEX_SIZE); | ||
424 | pgf |= index; | ||
425 | tlb_remove_table(tlb, (void *)pgf); | ||
426 | } | ||
427 | |||
428 | void __tlb_remove_table(void *_table) | ||
429 | { | ||
430 | void *table = (void *)((unsigned long)_table & ~MAX_PGTABLE_INDEX_SIZE); | ||
431 | unsigned int index = (unsigned long)_table & MAX_PGTABLE_INDEX_SIZE; | ||
432 | |||
433 | return pgtable_free(table, index); | ||
434 | } | ||
435 | #else | ||
436 | void pgtable_free_tlb(struct mmu_gather *tlb, void *table, int index) | ||
437 | { | ||
438 | return pgtable_free(table, index); | ||
439 | } | ||
440 | #endif | ||
diff --git a/arch/powerpc/mm/pgtable-hash64.c b/arch/powerpc/mm/pgtable-hash64.c index 199bfda5f0d9..692bfc9e372c 100644 --- a/arch/powerpc/mm/pgtable-hash64.c +++ b/arch/powerpc/mm/pgtable-hash64.c | |||
@@ -193,7 +193,7 @@ unsigned long hash__pmd_hugepage_update(struct mm_struct *mm, unsigned long addr | |||
193 | 193 | ||
194 | #ifdef CONFIG_DEBUG_VM | 194 | #ifdef CONFIG_DEBUG_VM |
195 | WARN_ON(!hash__pmd_trans_huge(*pmdp) && !pmd_devmap(*pmdp)); | 195 | WARN_ON(!hash__pmd_trans_huge(*pmdp) && !pmd_devmap(*pmdp)); |
196 | assert_spin_locked(&mm->page_table_lock); | 196 | assert_spin_locked(pmd_lockptr(mm, pmdp)); |
197 | #endif | 197 | #endif |
198 | 198 | ||
199 | __asm__ __volatile__( | 199 | __asm__ __volatile__( |
@@ -265,7 +265,8 @@ void hash__pgtable_trans_huge_deposit(struct mm_struct *mm, pmd_t *pmdp, | |||
265 | pgtable_t pgtable) | 265 | pgtable_t pgtable) |
266 | { | 266 | { |
267 | pgtable_t *pgtable_slot; | 267 | pgtable_t *pgtable_slot; |
268 | assert_spin_locked(&mm->page_table_lock); | 268 | |
269 | assert_spin_locked(pmd_lockptr(mm, pmdp)); | ||
269 | /* | 270 | /* |
270 | * we store the pgtable in the second half of PMD | 271 | * we store the pgtable in the second half of PMD |
271 | */ | 272 | */ |
@@ -285,7 +286,8 @@ pgtable_t hash__pgtable_trans_huge_withdraw(struct mm_struct *mm, pmd_t *pmdp) | |||
285 | pgtable_t pgtable; | 286 | pgtable_t pgtable; |
286 | pgtable_t *pgtable_slot; | 287 | pgtable_t *pgtable_slot; |
287 | 288 | ||
288 | assert_spin_locked(&mm->page_table_lock); | 289 | assert_spin_locked(pmd_lockptr(mm, pmdp)); |
290 | |||
289 | pgtable_slot = (pgtable_t *)pmdp + PTRS_PER_PMD; | 291 | pgtable_slot = (pgtable_t *)pmdp + PTRS_PER_PMD; |
290 | pgtable = *pgtable_slot; | 292 | pgtable = *pgtable_slot; |
291 | /* | 293 | /* |
diff --git a/arch/powerpc/mm/pgtable-radix.c b/arch/powerpc/mm/pgtable-radix.c index f1891e215e39..96f68c5aa1f5 100644 --- a/arch/powerpc/mm/pgtable-radix.c +++ b/arch/powerpc/mm/pgtable-radix.c | |||
@@ -617,7 +617,6 @@ void __init radix__early_init_mmu(void) | |||
617 | __pud_index_size = RADIX_PUD_INDEX_SIZE; | 617 | __pud_index_size = RADIX_PUD_INDEX_SIZE; |
618 | __pgd_index_size = RADIX_PGD_INDEX_SIZE; | 618 | __pgd_index_size = RADIX_PGD_INDEX_SIZE; |
619 | __pud_cache_index = RADIX_PUD_INDEX_SIZE; | 619 | __pud_cache_index = RADIX_PUD_INDEX_SIZE; |
620 | __pmd_cache_index = RADIX_PMD_INDEX_SIZE; | ||
621 | __pte_table_size = RADIX_PTE_TABLE_SIZE; | 620 | __pte_table_size = RADIX_PTE_TABLE_SIZE; |
622 | __pmd_table_size = RADIX_PMD_TABLE_SIZE; | 621 | __pmd_table_size = RADIX_PMD_TABLE_SIZE; |
623 | __pud_table_size = RADIX_PUD_TABLE_SIZE; | 622 | __pud_table_size = RADIX_PUD_TABLE_SIZE; |
@@ -640,6 +639,8 @@ void __init radix__early_init_mmu(void) | |||
640 | #endif | 639 | #endif |
641 | __pte_frag_nr = RADIX_PTE_FRAG_NR; | 640 | __pte_frag_nr = RADIX_PTE_FRAG_NR; |
642 | __pte_frag_size_shift = RADIX_PTE_FRAG_SIZE_SHIFT; | 641 | __pte_frag_size_shift = RADIX_PTE_FRAG_SIZE_SHIFT; |
642 | __pmd_frag_nr = RADIX_PMD_FRAG_NR; | ||
643 | __pmd_frag_size_shift = RADIX_PMD_FRAG_SIZE_SHIFT; | ||
643 | 644 | ||
644 | if (!firmware_has_feature(FW_FEATURE_LPAR)) { | 645 | if (!firmware_has_feature(FW_FEATURE_LPAR)) { |
645 | radix_init_native(); | 646 | radix_init_native(); |
@@ -975,7 +976,7 @@ unsigned long radix__pmd_hugepage_update(struct mm_struct *mm, unsigned long add | |||
975 | 976 | ||
976 | #ifdef CONFIG_DEBUG_VM | 977 | #ifdef CONFIG_DEBUG_VM |
977 | WARN_ON(!radix__pmd_trans_huge(*pmdp) && !pmd_devmap(*pmdp)); | 978 | WARN_ON(!radix__pmd_trans_huge(*pmdp) && !pmd_devmap(*pmdp)); |
978 | assert_spin_locked(&mm->page_table_lock); | 979 | assert_spin_locked(pmd_lockptr(mm, pmdp)); |
979 | #endif | 980 | #endif |
980 | 981 | ||
981 | old = radix__pte_update(mm, addr, (pte_t *)pmdp, clr, set, 1); | 982 | old = radix__pte_update(mm, addr, (pte_t *)pmdp, clr, set, 1); |
@@ -1083,3 +1084,36 @@ int radix__has_transparent_hugepage(void) | |||
1083 | return 0; | 1084 | return 0; |
1084 | } | 1085 | } |
1085 | #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ | 1086 | #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ |
1087 | |||
1088 | void radix__ptep_set_access_flags(struct vm_area_struct *vma, pte_t *ptep, | ||
1089 | pte_t entry, unsigned long address, int psize) | ||
1090 | { | ||
1091 | struct mm_struct *mm = vma->vm_mm; | ||
1092 | unsigned long set = pte_val(entry) & (_PAGE_DIRTY | _PAGE_ACCESSED | | ||
1093 | _PAGE_RW | _PAGE_EXEC); | ||
1094 | /* | ||
1095 | * To avoid NMMU hang while relaxing access, we need mark | ||
1096 | * the pte invalid in between. | ||
1097 | */ | ||
1098 | if (cpu_has_feature(CPU_FTR_POWER9_DD1) || | ||
1099 | atomic_read(&mm->context.copros) > 0) { | ||
1100 | unsigned long old_pte, new_pte; | ||
1101 | |||
1102 | old_pte = __radix_pte_update(ptep, ~0, 0); | ||
1103 | /* | ||
1104 | * new value of pte | ||
1105 | */ | ||
1106 | new_pte = old_pte | set; | ||
1107 | radix__flush_tlb_page_psize(mm, address, psize); | ||
1108 | __radix_pte_update(ptep, 0, new_pte); | ||
1109 | } else { | ||
1110 | __radix_pte_update(ptep, 0, set); | ||
1111 | /* | ||
1112 | * Book3S does not require a TLB flush when relaxing access | ||
1113 | * restrictions when the address space is not attached to a | ||
1114 | * NMMU, because the core MMU will reload the pte after taking | ||
1115 | * an access fault, which is defined by the architectue. | ||
1116 | */ | ||
1117 | } | ||
1118 | /* See ptesync comment in radix__set_pte_at */ | ||
1119 | } | ||
diff --git a/arch/powerpc/mm/pgtable.c b/arch/powerpc/mm/pgtable.c index 9f361ae571e9..d71c7777669c 100644 --- a/arch/powerpc/mm/pgtable.c +++ b/arch/powerpc/mm/pgtable.c | |||
@@ -221,14 +221,55 @@ int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long address, | |||
221 | entry = set_access_flags_filter(entry, vma, dirty); | 221 | entry = set_access_flags_filter(entry, vma, dirty); |
222 | changed = !pte_same(*(ptep), entry); | 222 | changed = !pte_same(*(ptep), entry); |
223 | if (changed) { | 223 | if (changed) { |
224 | if (!is_vm_hugetlb_page(vma)) | 224 | assert_pte_locked(vma->vm_mm, address); |
225 | assert_pte_locked(vma->vm_mm, address); | 225 | __ptep_set_access_flags(vma, ptep, entry, |
226 | __ptep_set_access_flags(vma->vm_mm, ptep, entry, address); | 226 | address, mmu_virtual_psize); |
227 | flush_tlb_page(vma, address); | ||
228 | } | 227 | } |
229 | return changed; | 228 | return changed; |
230 | } | 229 | } |
231 | 230 | ||
231 | #ifdef CONFIG_HUGETLB_PAGE | ||
232 | extern int huge_ptep_set_access_flags(struct vm_area_struct *vma, | ||
233 | unsigned long addr, pte_t *ptep, | ||
234 | pte_t pte, int dirty) | ||
235 | { | ||
236 | #ifdef HUGETLB_NEED_PRELOAD | ||
237 | /* | ||
238 | * The "return 1" forces a call of update_mmu_cache, which will write a | ||
239 | * TLB entry. Without this, platforms that don't do a write of the TLB | ||
240 | * entry in the TLB miss handler asm will fault ad infinitum. | ||
241 | */ | ||
242 | ptep_set_access_flags(vma, addr, ptep, pte, dirty); | ||
243 | return 1; | ||
244 | #else | ||
245 | int changed, psize; | ||
246 | |||
247 | pte = set_access_flags_filter(pte, vma, dirty); | ||
248 | changed = !pte_same(*(ptep), pte); | ||
249 | if (changed) { | ||
250 | |||
251 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
252 | struct hstate *h = hstate_vma(vma); | ||
253 | |||
254 | psize = hstate_get_psize(h); | ||
255 | #ifdef CONFIG_DEBUG_VM | ||
256 | assert_spin_locked(huge_pte_lockptr(h, vma->vm_mm, ptep)); | ||
257 | #endif | ||
258 | |||
259 | #else | ||
260 | /* | ||
261 | * Not used on non book3s64 platforms. But 8xx | ||
262 | * can possibly use tsize derived from hstate. | ||
263 | */ | ||
264 | psize = 0; | ||
265 | #endif | ||
266 | __ptep_set_access_flags(vma, ptep, pte, addr, psize); | ||
267 | } | ||
268 | return changed; | ||
269 | #endif | ||
270 | } | ||
271 | #endif /* CONFIG_HUGETLB_PAGE */ | ||
272 | |||
232 | #ifdef CONFIG_DEBUG_VM | 273 | #ifdef CONFIG_DEBUG_VM |
233 | void assert_pte_locked(struct mm_struct *mm, unsigned long addr) | 274 | void assert_pte_locked(struct mm_struct *mm, unsigned long addr) |
234 | { | 275 | { |
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c index 9bf659d5078c..53e9eeecd5d4 100644 --- a/arch/powerpc/mm/pgtable_64.c +++ b/arch/powerpc/mm/pgtable_64.c | |||
@@ -33,7 +33,6 @@ | |||
33 | #include <linux/swap.h> | 33 | #include <linux/swap.h> |
34 | #include <linux/stddef.h> | 34 | #include <linux/stddef.h> |
35 | #include <linux/vmalloc.h> | 35 | #include <linux/vmalloc.h> |
36 | #include <linux/memblock.h> | ||
37 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
38 | #include <linux/hugetlb.h> | 37 | #include <linux/hugetlb.h> |
39 | 38 | ||
@@ -47,13 +46,11 @@ | |||
47 | #include <asm/smp.h> | 46 | #include <asm/smp.h> |
48 | #include <asm/machdep.h> | 47 | #include <asm/machdep.h> |
49 | #include <asm/tlb.h> | 48 | #include <asm/tlb.h> |
50 | #include <asm/trace.h> | ||
51 | #include <asm/processor.h> | 49 | #include <asm/processor.h> |
52 | #include <asm/cputable.h> | 50 | #include <asm/cputable.h> |
53 | #include <asm/sections.h> | 51 | #include <asm/sections.h> |
54 | #include <asm/firmware.h> | 52 | #include <asm/firmware.h> |
55 | #include <asm/dma.h> | 53 | #include <asm/dma.h> |
56 | #include <asm/powernv.h> | ||
57 | 54 | ||
58 | #include "mmu_decl.h" | 55 | #include "mmu_decl.h" |
59 | 56 | ||
@@ -75,8 +72,6 @@ unsigned long __pud_index_size; | |||
75 | EXPORT_SYMBOL(__pud_index_size); | 72 | EXPORT_SYMBOL(__pud_index_size); |
76 | unsigned long __pgd_index_size; | 73 | unsigned long __pgd_index_size; |
77 | EXPORT_SYMBOL(__pgd_index_size); | 74 | EXPORT_SYMBOL(__pgd_index_size); |
78 | unsigned long __pmd_cache_index; | ||
79 | EXPORT_SYMBOL(__pmd_cache_index); | ||
80 | unsigned long __pud_cache_index; | 75 | unsigned long __pud_cache_index; |
81 | EXPORT_SYMBOL(__pud_cache_index); | 76 | EXPORT_SYMBOL(__pud_cache_index); |
82 | unsigned long __pte_table_size; | 77 | unsigned long __pte_table_size; |
@@ -316,172 +311,6 @@ struct page *pmd_page(pmd_t pmd) | |||
316 | return virt_to_page(pmd_page_vaddr(pmd)); | 311 | return virt_to_page(pmd_page_vaddr(pmd)); |
317 | } | 312 | } |
318 | 313 | ||
319 | #ifdef CONFIG_PPC_64K_PAGES | ||
320 | static pte_t *get_from_cache(struct mm_struct *mm) | ||
321 | { | ||
322 | void *pte_frag, *ret; | ||
323 | |||
324 | spin_lock(&mm->page_table_lock); | ||
325 | ret = mm->context.pte_frag; | ||
326 | if (ret) { | ||
327 | pte_frag = ret + PTE_FRAG_SIZE; | ||
328 | /* | ||
329 | * If we have taken up all the fragments mark PTE page NULL | ||
330 | */ | ||
331 | if (((unsigned long)pte_frag & ~PAGE_MASK) == 0) | ||
332 | pte_frag = NULL; | ||
333 | mm->context.pte_frag = pte_frag; | ||
334 | } | ||
335 | spin_unlock(&mm->page_table_lock); | ||
336 | return (pte_t *)ret; | ||
337 | } | ||
338 | |||
339 | static pte_t *__alloc_for_cache(struct mm_struct *mm, int kernel) | ||
340 | { | ||
341 | void *ret = NULL; | ||
342 | struct page *page; | ||
343 | |||
344 | if (!kernel) { | ||
345 | page = alloc_page(PGALLOC_GFP | __GFP_ACCOUNT); | ||
346 | if (!page) | ||
347 | return NULL; | ||
348 | if (!pgtable_page_ctor(page)) { | ||
349 | __free_page(page); | ||
350 | return NULL; | ||
351 | } | ||
352 | } else { | ||
353 | page = alloc_page(PGALLOC_GFP); | ||
354 | if (!page) | ||
355 | return NULL; | ||
356 | } | ||
357 | |||
358 | ret = page_address(page); | ||
359 | spin_lock(&mm->page_table_lock); | ||
360 | /* | ||
361 | * If we find pgtable_page set, we return | ||
362 | * the allocated page with single fragement | ||
363 | * count. | ||
364 | */ | ||
365 | if (likely(!mm->context.pte_frag)) { | ||
366 | set_page_count(page, PTE_FRAG_NR); | ||
367 | mm->context.pte_frag = ret + PTE_FRAG_SIZE; | ||
368 | } | ||
369 | spin_unlock(&mm->page_table_lock); | ||
370 | |||
371 | return (pte_t *)ret; | ||
372 | } | ||
373 | |||
374 | pte_t *pte_fragment_alloc(struct mm_struct *mm, unsigned long vmaddr, int kernel) | ||
375 | { | ||
376 | pte_t *pte; | ||
377 | |||
378 | pte = get_from_cache(mm); | ||
379 | if (pte) | ||
380 | return pte; | ||
381 | |||
382 | return __alloc_for_cache(mm, kernel); | ||
383 | } | ||
384 | #endif /* CONFIG_PPC_64K_PAGES */ | ||
385 | |||
386 | void pte_fragment_free(unsigned long *table, int kernel) | ||
387 | { | ||
388 | struct page *page = virt_to_page(table); | ||
389 | if (put_page_testzero(page)) { | ||
390 | if (!kernel) | ||
391 | pgtable_page_dtor(page); | ||
392 | free_unref_page(page); | ||
393 | } | ||
394 | } | ||
395 | |||
396 | #ifdef CONFIG_SMP | ||
397 | void pgtable_free_tlb(struct mmu_gather *tlb, void *table, int shift) | ||
398 | { | ||
399 | unsigned long pgf = (unsigned long)table; | ||
400 | |||
401 | BUG_ON(shift > MAX_PGTABLE_INDEX_SIZE); | ||
402 | pgf |= shift; | ||
403 | tlb_remove_table(tlb, (void *)pgf); | ||
404 | } | ||
405 | |||
406 | void __tlb_remove_table(void *_table) | ||
407 | { | ||
408 | void *table = (void *)((unsigned long)_table & ~MAX_PGTABLE_INDEX_SIZE); | ||
409 | unsigned shift = (unsigned long)_table & MAX_PGTABLE_INDEX_SIZE; | ||
410 | |||
411 | if (!shift) | ||
412 | /* PTE page needs special handling */ | ||
413 | pte_fragment_free(table, 0); | ||
414 | else { | ||
415 | BUG_ON(shift > MAX_PGTABLE_INDEX_SIZE); | ||
416 | kmem_cache_free(PGT_CACHE(shift), table); | ||
417 | } | ||
418 | } | ||
419 | #else | ||
420 | void pgtable_free_tlb(struct mmu_gather *tlb, void *table, int shift) | ||
421 | { | ||
422 | if (!shift) { | ||
423 | /* PTE page needs special handling */ | ||
424 | pte_fragment_free(table, 0); | ||
425 | } else { | ||
426 | BUG_ON(shift > MAX_PGTABLE_INDEX_SIZE); | ||
427 | kmem_cache_free(PGT_CACHE(shift), table); | ||
428 | } | ||
429 | } | ||
430 | #endif | ||
431 | |||
432 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
433 | void __init mmu_partition_table_init(void) | ||
434 | { | ||
435 | unsigned long patb_size = 1UL << PATB_SIZE_SHIFT; | ||
436 | unsigned long ptcr; | ||
437 | |||
438 | BUILD_BUG_ON_MSG((PATB_SIZE_SHIFT > 36), "Partition table size too large."); | ||
439 | partition_tb = __va(memblock_alloc_base(patb_size, patb_size, | ||
440 | MEMBLOCK_ALLOC_ANYWHERE)); | ||
441 | |||
442 | /* Initialize the Partition Table with no entries */ | ||
443 | memset((void *)partition_tb, 0, patb_size); | ||
444 | |||
445 | /* | ||
446 | * update partition table control register, | ||
447 | * 64 K size. | ||
448 | */ | ||
449 | ptcr = __pa(partition_tb) | (PATB_SIZE_SHIFT - 12); | ||
450 | mtspr(SPRN_PTCR, ptcr); | ||
451 | powernv_set_nmmu_ptcr(ptcr); | ||
452 | } | ||
453 | |||
454 | void mmu_partition_table_set_entry(unsigned int lpid, unsigned long dw0, | ||
455 | unsigned long dw1) | ||
456 | { | ||
457 | unsigned long old = be64_to_cpu(partition_tb[lpid].patb0); | ||
458 | |||
459 | partition_tb[lpid].patb0 = cpu_to_be64(dw0); | ||
460 | partition_tb[lpid].patb1 = cpu_to_be64(dw1); | ||
461 | |||
462 | /* | ||
463 | * Global flush of TLBs and partition table caches for this lpid. | ||
464 | * The type of flush (hash or radix) depends on what the previous | ||
465 | * use of this partition ID was, not the new use. | ||
466 | */ | ||
467 | asm volatile("ptesync" : : : "memory"); | ||
468 | if (old & PATB_HR) { | ||
469 | asm volatile(PPC_TLBIE_5(%0,%1,2,0,1) : : | ||
470 | "r" (TLBIEL_INVAL_SET_LPID), "r" (lpid)); | ||
471 | asm volatile(PPC_TLBIE_5(%0,%1,2,1,1) : : | ||
472 | "r" (TLBIEL_INVAL_SET_LPID), "r" (lpid)); | ||
473 | trace_tlbie(lpid, 0, TLBIEL_INVAL_SET_LPID, lpid, 2, 0, 1); | ||
474 | } else { | ||
475 | asm volatile(PPC_TLBIE_5(%0,%1,2,0,0) : : | ||
476 | "r" (TLBIEL_INVAL_SET_LPID), "r" (lpid)); | ||
477 | trace_tlbie(lpid, 0, TLBIEL_INVAL_SET_LPID, lpid, 2, 0, 0); | ||
478 | } | ||
479 | /* do we need fixup here ?*/ | ||
480 | asm volatile("eieio; tlbsync; ptesync" : : : "memory"); | ||
481 | } | ||
482 | EXPORT_SYMBOL_GPL(mmu_partition_table_set_entry); | ||
483 | #endif /* CONFIG_PPC_BOOK3S_64 */ | ||
484 | |||
485 | #ifdef CONFIG_STRICT_KERNEL_RWX | 314 | #ifdef CONFIG_STRICT_KERNEL_RWX |
486 | void mark_rodata_ro(void) | 315 | void mark_rodata_ro(void) |
487 | { | 316 | { |
diff --git a/arch/powerpc/mm/pkeys.c b/arch/powerpc/mm/pkeys.c index 0eafdf01edc7..e6f500fabf5e 100644 --- a/arch/powerpc/mm/pkeys.c +++ b/arch/powerpc/mm/pkeys.c | |||
@@ -383,9 +383,9 @@ int __arch_override_mprotect_pkey(struct vm_area_struct *vma, int prot, | |||
383 | { | 383 | { |
384 | /* | 384 | /* |
385 | * If the currently associated pkey is execute-only, but the requested | 385 | * If the currently associated pkey is execute-only, but the requested |
386 | * protection requires read or write, move it back to the default pkey. | 386 | * protection is not execute-only, move it back to the default pkey. |
387 | */ | 387 | */ |
388 | if (vma_is_pkey_exec_only(vma) && (prot & (PROT_READ | PROT_WRITE))) | 388 | if (vma_is_pkey_exec_only(vma) && (prot != PROT_EXEC)) |
389 | return 0; | 389 | return 0; |
390 | 390 | ||
391 | /* | 391 | /* |
diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c index 2a049fb8523d..bea6c544e38f 100644 --- a/arch/powerpc/mm/ppc_mmu_32.c +++ b/arch/powerpc/mm/ppc_mmu_32.c | |||
@@ -167,7 +167,7 @@ void hash_preload(struct mm_struct *mm, unsigned long ea, | |||
167 | { | 167 | { |
168 | pmd_t *pmd; | 168 | pmd_t *pmd; |
169 | 169 | ||
170 | if (Hash == 0) | 170 | if (!Hash) |
171 | return; | 171 | return; |
172 | pmd = pmd_offset(pud_offset(pgd_offset(mm, ea), ea), ea); | 172 | pmd = pmd_offset(pud_offset(pgd_offset(mm, ea), ea), ea); |
173 | if (!pmd_none(*pmd)) | 173 | if (!pmd_none(*pmd)) |
diff --git a/arch/powerpc/mm/slb.c b/arch/powerpc/mm/slb.c index 66577cc66dc9..cb796724a6fc 100644 --- a/arch/powerpc/mm/slb.c +++ b/arch/powerpc/mm/slb.c | |||
@@ -63,14 +63,14 @@ static inline void slb_shadow_update(unsigned long ea, int ssize, | |||
63 | * updating it. No write barriers are needed here, provided | 63 | * updating it. No write barriers are needed here, provided |
64 | * we only update the current CPU's SLB shadow buffer. | 64 | * we only update the current CPU's SLB shadow buffer. |
65 | */ | 65 | */ |
66 | p->save_area[index].esid = 0; | 66 | WRITE_ONCE(p->save_area[index].esid, 0); |
67 | p->save_area[index].vsid = cpu_to_be64(mk_vsid_data(ea, ssize, flags)); | 67 | WRITE_ONCE(p->save_area[index].vsid, cpu_to_be64(mk_vsid_data(ea, ssize, flags))); |
68 | p->save_area[index].esid = cpu_to_be64(mk_esid_data(ea, ssize, index)); | 68 | WRITE_ONCE(p->save_area[index].esid, cpu_to_be64(mk_esid_data(ea, ssize, index))); |
69 | } | 69 | } |
70 | 70 | ||
71 | static inline void slb_shadow_clear(enum slb_index index) | 71 | static inline void slb_shadow_clear(enum slb_index index) |
72 | { | 72 | { |
73 | get_slb_shadow()->save_area[index].esid = 0; | 73 | WRITE_ONCE(get_slb_shadow()->save_area[index].esid, 0); |
74 | } | 74 | } |
75 | 75 | ||
76 | static inline void create_shadowed_slbe(unsigned long ea, int ssize, | 76 | static inline void create_shadowed_slbe(unsigned long ea, int ssize, |
@@ -352,6 +352,14 @@ static void insert_slb_entry(unsigned long vsid, unsigned long ea, | |||
352 | /* | 352 | /* |
353 | * We are irq disabled, hence should be safe to access PACA. | 353 | * We are irq disabled, hence should be safe to access PACA. |
354 | */ | 354 | */ |
355 | VM_WARN_ON(!irqs_disabled()); | ||
356 | |||
357 | /* | ||
358 | * We can't take a PMU exception in the following code, so hard | ||
359 | * disable interrupts. | ||
360 | */ | ||
361 | hard_irq_disable(); | ||
362 | |||
355 | index = get_paca()->stab_rr; | 363 | index = get_paca()->stab_rr; |
356 | 364 | ||
357 | /* | 365 | /* |
@@ -369,6 +377,11 @@ static void insert_slb_entry(unsigned long vsid, unsigned long ea, | |||
369 | ((unsigned long) ssize << SLB_VSID_SSIZE_SHIFT); | 377 | ((unsigned long) ssize << SLB_VSID_SSIZE_SHIFT); |
370 | esid_data = mk_esid_data(ea, ssize, index); | 378 | esid_data = mk_esid_data(ea, ssize, index); |
371 | 379 | ||
380 | /* | ||
381 | * No need for an isync before or after this slbmte. The exception | ||
382 | * we enter with and the rfid we exit with are context synchronizing. | ||
383 | * Also we only handle user segments here. | ||
384 | */ | ||
372 | asm volatile("slbmte %0, %1" : : "r" (vsid_data), "r" (esid_data) | 385 | asm volatile("slbmte %0, %1" : : "r" (vsid_data), "r" (esid_data) |
373 | : "memory"); | 386 | : "memory"); |
374 | 387 | ||
diff --git a/arch/powerpc/mm/subpage-prot.c b/arch/powerpc/mm/subpage-prot.c index f14a07c2fb90..75cb646a79c3 100644 --- a/arch/powerpc/mm/subpage-prot.c +++ b/arch/powerpc/mm/subpage-prot.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/types.h> | 13 | #include <linux/types.h> |
14 | #include <linux/mm.h> | 14 | #include <linux/mm.h> |
15 | #include <linux/hugetlb.h> | 15 | #include <linux/hugetlb.h> |
16 | #include <linux/syscalls.h> | ||
16 | 17 | ||
17 | #include <asm/pgtable.h> | 18 | #include <asm/pgtable.h> |
18 | #include <linux/uaccess.h> | 19 | #include <linux/uaccess.h> |
@@ -185,7 +186,11 @@ static void subpage_mark_vma_nohuge(struct mm_struct *mm, unsigned long addr, | |||
185 | * in a 2-bit field won't allow writes to a page that is otherwise | 186 | * in a 2-bit field won't allow writes to a page that is otherwise |
186 | * write-protected. | 187 | * write-protected. |
187 | */ | 188 | */ |
188 | long sys_subpage_prot(unsigned long addr, unsigned long len, u32 __user *map) | 189 | #pragma GCC diagnostic push |
190 | #pragma GCC diagnostic ignored "-Wpragmas" | ||
191 | #pragma GCC diagnostic ignored "-Wattribute-alias" | ||
192 | SYSCALL_DEFINE3(subpage_prot, unsigned long, addr, | ||
193 | unsigned long, len, u32 __user *, map) | ||
189 | { | 194 | { |
190 | struct mm_struct *mm = current->mm; | 195 | struct mm_struct *mm = current->mm; |
191 | struct subpage_prot_table *spt = &mm->context.spt; | 196 | struct subpage_prot_table *spt = &mm->context.spt; |
@@ -267,3 +272,4 @@ long sys_subpage_prot(unsigned long addr, unsigned long len, u32 __user *map) | |||
267 | up_write(&mm->mmap_sem); | 272 | up_write(&mm->mmap_sem); |
268 | return err; | 273 | return err; |
269 | } | 274 | } |
275 | #pragma GCC diagnostic pop | ||
diff --git a/arch/powerpc/mm/tlb-radix.c b/arch/powerpc/mm/tlb-radix.c index a5d7309c2d05..67a6e86d3e7e 100644 --- a/arch/powerpc/mm/tlb-radix.c +++ b/arch/powerpc/mm/tlb-radix.c | |||
@@ -12,6 +12,8 @@ | |||
12 | #include <linux/mm.h> | 12 | #include <linux/mm.h> |
13 | #include <linux/hugetlb.h> | 13 | #include <linux/hugetlb.h> |
14 | #include <linux/memblock.h> | 14 | #include <linux/memblock.h> |
15 | #include <linux/mmu_context.h> | ||
16 | #include <linux/sched/mm.h> | ||
15 | 17 | ||
16 | #include <asm/ppc-opcode.h> | 18 | #include <asm/ppc-opcode.h> |
17 | #include <asm/tlb.h> | 19 | #include <asm/tlb.h> |
@@ -118,6 +120,53 @@ static inline void __tlbie_pid(unsigned long pid, unsigned long ric) | |||
118 | trace_tlbie(0, 0, rb, rs, ric, prs, r); | 120 | trace_tlbie(0, 0, rb, rs, ric, prs, r); |
119 | } | 121 | } |
120 | 122 | ||
123 | static inline void __tlbiel_lpid(unsigned long lpid, int set, | ||
124 | unsigned long ric) | ||
125 | { | ||
126 | unsigned long rb,rs,prs,r; | ||
127 | |||
128 | rb = PPC_BIT(52); /* IS = 2 */ | ||
129 | rb |= set << PPC_BITLSHIFT(51); | ||
130 | rs = 0; /* LPID comes from LPIDR */ | ||
131 | prs = 0; /* partition scoped */ | ||
132 | r = 1; /* radix format */ | ||
133 | |||
134 | asm volatile(PPC_TLBIEL(%0, %4, %3, %2, %1) | ||
135 | : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory"); | ||
136 | trace_tlbie(lpid, 1, rb, rs, ric, prs, r); | ||
137 | } | ||
138 | |||
139 | static inline void __tlbie_lpid(unsigned long lpid, unsigned long ric) | ||
140 | { | ||
141 | unsigned long rb,rs,prs,r; | ||
142 | |||
143 | rb = PPC_BIT(52); /* IS = 2 */ | ||
144 | rs = lpid; | ||
145 | prs = 0; /* partition scoped */ | ||
146 | r = 1; /* radix format */ | ||
147 | |||
148 | asm volatile(PPC_TLBIE_5(%0, %4, %3, %2, %1) | ||
149 | : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory"); | ||
150 | trace_tlbie(lpid, 0, rb, rs, ric, prs, r); | ||
151 | } | ||
152 | |||
153 | static inline void __tlbiel_lpid_guest(unsigned long lpid, int set, | ||
154 | unsigned long ric) | ||
155 | { | ||
156 | unsigned long rb,rs,prs,r; | ||
157 | |||
158 | rb = PPC_BIT(52); /* IS = 2 */ | ||
159 | rb |= set << PPC_BITLSHIFT(51); | ||
160 | rs = 0; /* LPID comes from LPIDR */ | ||
161 | prs = 1; /* process scoped */ | ||
162 | r = 1; /* radix format */ | ||
163 | |||
164 | asm volatile(PPC_TLBIEL(%0, %4, %3, %2, %1) | ||
165 | : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory"); | ||
166 | trace_tlbie(lpid, 1, rb, rs, ric, prs, r); | ||
167 | } | ||
168 | |||
169 | |||
121 | static inline void __tlbiel_va(unsigned long va, unsigned long pid, | 170 | static inline void __tlbiel_va(unsigned long va, unsigned long pid, |
122 | unsigned long ap, unsigned long ric) | 171 | unsigned long ap, unsigned long ric) |
123 | { | 172 | { |
@@ -150,6 +199,22 @@ static inline void __tlbie_va(unsigned long va, unsigned long pid, | |||
150 | trace_tlbie(0, 0, rb, rs, ric, prs, r); | 199 | trace_tlbie(0, 0, rb, rs, ric, prs, r); |
151 | } | 200 | } |
152 | 201 | ||
202 | static inline void __tlbie_lpid_va(unsigned long va, unsigned long lpid, | ||
203 | unsigned long ap, unsigned long ric) | ||
204 | { | ||
205 | unsigned long rb,rs,prs,r; | ||
206 | |||
207 | rb = va & ~(PPC_BITMASK(52, 63)); | ||
208 | rb |= ap << PPC_BITLSHIFT(58); | ||
209 | rs = lpid; | ||
210 | prs = 0; /* partition scoped */ | ||
211 | r = 1; /* radix format */ | ||
212 | |||
213 | asm volatile(PPC_TLBIE_5(%0, %4, %3, %2, %1) | ||
214 | : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory"); | ||
215 | trace_tlbie(lpid, 0, rb, rs, ric, prs, r); | ||
216 | } | ||
217 | |||
153 | static inline void fixup_tlbie(void) | 218 | static inline void fixup_tlbie(void) |
154 | { | 219 | { |
155 | unsigned long pid = 0; | 220 | unsigned long pid = 0; |
@@ -161,6 +226,16 @@ static inline void fixup_tlbie(void) | |||
161 | } | 226 | } |
162 | } | 227 | } |
163 | 228 | ||
229 | static inline void fixup_tlbie_lpid(unsigned long lpid) | ||
230 | { | ||
231 | unsigned long va = ((1UL << 52) - 1); | ||
232 | |||
233 | if (cpu_has_feature(CPU_FTR_P9_TLBIE_BUG)) { | ||
234 | asm volatile("ptesync": : :"memory"); | ||
235 | __tlbie_lpid_va(va, lpid, mmu_get_ap(MMU_PAGE_64K), RIC_FLUSH_TLB); | ||
236 | } | ||
237 | } | ||
238 | |||
164 | /* | 239 | /* |
165 | * We use 128 set in radix mode and 256 set in hpt mode. | 240 | * We use 128 set in radix mode and 256 set in hpt mode. |
166 | */ | 241 | */ |
@@ -214,6 +289,86 @@ static inline void _tlbie_pid(unsigned long pid, unsigned long ric) | |||
214 | asm volatile("eieio; tlbsync; ptesync": : :"memory"); | 289 | asm volatile("eieio; tlbsync; ptesync": : :"memory"); |
215 | } | 290 | } |
216 | 291 | ||
292 | static inline void _tlbiel_lpid(unsigned long lpid, unsigned long ric) | ||
293 | { | ||
294 | int set; | ||
295 | |||
296 | VM_BUG_ON(mfspr(SPRN_LPID) != lpid); | ||
297 | |||
298 | asm volatile("ptesync": : :"memory"); | ||
299 | |||
300 | /* | ||
301 | * Flush the first set of the TLB, and if we're doing a RIC_FLUSH_ALL, | ||
302 | * also flush the entire Page Walk Cache. | ||
303 | */ | ||
304 | __tlbiel_lpid(lpid, 0, ric); | ||
305 | |||
306 | /* For PWC, only one flush is needed */ | ||
307 | if (ric == RIC_FLUSH_PWC) { | ||
308 | asm volatile("ptesync": : :"memory"); | ||
309 | return; | ||
310 | } | ||
311 | |||
312 | /* For the remaining sets, just flush the TLB */ | ||
313 | for (set = 1; set < POWER9_TLB_SETS_RADIX ; set++) | ||
314 | __tlbiel_lpid(lpid, set, RIC_FLUSH_TLB); | ||
315 | |||
316 | asm volatile("ptesync": : :"memory"); | ||
317 | asm volatile(PPC_INVALIDATE_ERAT "; isync" : : :"memory"); | ||
318 | } | ||
319 | |||
320 | static inline void _tlbie_lpid(unsigned long lpid, unsigned long ric) | ||
321 | { | ||
322 | asm volatile("ptesync": : :"memory"); | ||
323 | |||
324 | /* | ||
325 | * Workaround the fact that the "ric" argument to __tlbie_pid | ||
326 | * must be a compile-time contraint to match the "i" constraint | ||
327 | * in the asm statement. | ||
328 | */ | ||
329 | switch (ric) { | ||
330 | case RIC_FLUSH_TLB: | ||
331 | __tlbie_lpid(lpid, RIC_FLUSH_TLB); | ||
332 | break; | ||
333 | case RIC_FLUSH_PWC: | ||
334 | __tlbie_lpid(lpid, RIC_FLUSH_PWC); | ||
335 | break; | ||
336 | case RIC_FLUSH_ALL: | ||
337 | default: | ||
338 | __tlbie_lpid(lpid, RIC_FLUSH_ALL); | ||
339 | } | ||
340 | fixup_tlbie_lpid(lpid); | ||
341 | asm volatile("eieio; tlbsync; ptesync": : :"memory"); | ||
342 | } | ||
343 | |||
344 | static inline void _tlbiel_lpid_guest(unsigned long lpid, unsigned long ric) | ||
345 | { | ||
346 | int set; | ||
347 | |||
348 | VM_BUG_ON(mfspr(SPRN_LPID) != lpid); | ||
349 | |||
350 | asm volatile("ptesync": : :"memory"); | ||
351 | |||
352 | /* | ||
353 | * Flush the first set of the TLB, and if we're doing a RIC_FLUSH_ALL, | ||
354 | * also flush the entire Page Walk Cache. | ||
355 | */ | ||
356 | __tlbiel_lpid_guest(lpid, 0, ric); | ||
357 | |||
358 | /* For PWC, only one flush is needed */ | ||
359 | if (ric == RIC_FLUSH_PWC) { | ||
360 | asm volatile("ptesync": : :"memory"); | ||
361 | return; | ||
362 | } | ||
363 | |||
364 | /* For the remaining sets, just flush the TLB */ | ||
365 | for (set = 1; set < POWER9_TLB_SETS_RADIX ; set++) | ||
366 | __tlbiel_lpid_guest(lpid, set, RIC_FLUSH_TLB); | ||
367 | |||
368 | asm volatile("ptesync": : :"memory"); | ||
369 | } | ||
370 | |||
371 | |||
217 | static inline void __tlbiel_va_range(unsigned long start, unsigned long end, | 372 | static inline void __tlbiel_va_range(unsigned long start, unsigned long end, |
218 | unsigned long pid, unsigned long page_size, | 373 | unsigned long pid, unsigned long page_size, |
219 | unsigned long psize) | 374 | unsigned long psize) |
@@ -268,6 +423,17 @@ static inline void _tlbie_va(unsigned long va, unsigned long pid, | |||
268 | asm volatile("eieio; tlbsync; ptesync": : :"memory"); | 423 | asm volatile("eieio; tlbsync; ptesync": : :"memory"); |
269 | } | 424 | } |
270 | 425 | ||
426 | static inline void _tlbie_lpid_va(unsigned long va, unsigned long lpid, | ||
427 | unsigned long psize, unsigned long ric) | ||
428 | { | ||
429 | unsigned long ap = mmu_get_ap(psize); | ||
430 | |||
431 | asm volatile("ptesync": : :"memory"); | ||
432 | __tlbie_lpid_va(va, lpid, ap, ric); | ||
433 | fixup_tlbie_lpid(lpid); | ||
434 | asm volatile("eieio; tlbsync; ptesync": : :"memory"); | ||
435 | } | ||
436 | |||
271 | static inline void _tlbie_va_range(unsigned long start, unsigned long end, | 437 | static inline void _tlbie_va_range(unsigned long start, unsigned long end, |
272 | unsigned long pid, unsigned long page_size, | 438 | unsigned long pid, unsigned long page_size, |
273 | unsigned long psize, bool also_pwc) | 439 | unsigned long psize, bool also_pwc) |
@@ -340,6 +506,15 @@ void radix__local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmadd | |||
340 | } | 506 | } |
341 | EXPORT_SYMBOL(radix__local_flush_tlb_page); | 507 | EXPORT_SYMBOL(radix__local_flush_tlb_page); |
342 | 508 | ||
509 | static bool mm_is_singlethreaded(struct mm_struct *mm) | ||
510 | { | ||
511 | if (atomic_read(&mm->context.copros) > 0) | ||
512 | return false; | ||
513 | if (atomic_read(&mm->mm_users) <= 1 && current->mm == mm) | ||
514 | return true; | ||
515 | return false; | ||
516 | } | ||
517 | |||
343 | static bool mm_needs_flush_escalation(struct mm_struct *mm) | 518 | static bool mm_needs_flush_escalation(struct mm_struct *mm) |
344 | { | 519 | { |
345 | /* | 520 | /* |
@@ -347,10 +522,47 @@ static bool mm_needs_flush_escalation(struct mm_struct *mm) | |||
347 | * caching PTEs and not flushing them properly when | 522 | * caching PTEs and not flushing them properly when |
348 | * RIC = 0 for a PID/LPID invalidate | 523 | * RIC = 0 for a PID/LPID invalidate |
349 | */ | 524 | */ |
350 | return atomic_read(&mm->context.copros) != 0; | 525 | if (atomic_read(&mm->context.copros) > 0) |
526 | return true; | ||
527 | return false; | ||
351 | } | 528 | } |
352 | 529 | ||
353 | #ifdef CONFIG_SMP | 530 | #ifdef CONFIG_SMP |
531 | static void do_exit_flush_lazy_tlb(void *arg) | ||
532 | { | ||
533 | struct mm_struct *mm = arg; | ||
534 | unsigned long pid = mm->context.id; | ||
535 | |||
536 | if (current->mm == mm) | ||
537 | return; /* Local CPU */ | ||
538 | |||
539 | if (current->active_mm == mm) { | ||
540 | /* | ||
541 | * Must be a kernel thread because sender is single-threaded. | ||
542 | */ | ||
543 | BUG_ON(current->mm); | ||
544 | mmgrab(&init_mm); | ||
545 | switch_mm(mm, &init_mm, current); | ||
546 | current->active_mm = &init_mm; | ||
547 | mmdrop(mm); | ||
548 | } | ||
549 | _tlbiel_pid(pid, RIC_FLUSH_ALL); | ||
550 | } | ||
551 | |||
552 | static void exit_flush_lazy_tlbs(struct mm_struct *mm) | ||
553 | { | ||
554 | /* | ||
555 | * Would be nice if this was async so it could be run in | ||
556 | * parallel with our local flush, but generic code does not | ||
557 | * give a good API for it. Could extend the generic code or | ||
558 | * make a special powerpc IPI for flushing TLBs. | ||
559 | * For now it's not too performance critical. | ||
560 | */ | ||
561 | smp_call_function_many(mm_cpumask(mm), do_exit_flush_lazy_tlb, | ||
562 | (void *)mm, 1); | ||
563 | mm_reset_thread_local(mm); | ||
564 | } | ||
565 | |||
354 | void radix__flush_tlb_mm(struct mm_struct *mm) | 566 | void radix__flush_tlb_mm(struct mm_struct *mm) |
355 | { | 567 | { |
356 | unsigned long pid; | 568 | unsigned long pid; |
@@ -360,18 +572,30 @@ void radix__flush_tlb_mm(struct mm_struct *mm) | |||
360 | return; | 572 | return; |
361 | 573 | ||
362 | preempt_disable(); | 574 | preempt_disable(); |
575 | /* | ||
576 | * Order loads of mm_cpumask vs previous stores to clear ptes before | ||
577 | * the invalidate. See barrier in switch_mm_irqs_off | ||
578 | */ | ||
579 | smp_mb(); | ||
363 | if (!mm_is_thread_local(mm)) { | 580 | if (!mm_is_thread_local(mm)) { |
581 | if (unlikely(mm_is_singlethreaded(mm))) { | ||
582 | exit_flush_lazy_tlbs(mm); | ||
583 | goto local; | ||
584 | } | ||
585 | |||
364 | if (mm_needs_flush_escalation(mm)) | 586 | if (mm_needs_flush_escalation(mm)) |
365 | _tlbie_pid(pid, RIC_FLUSH_ALL); | 587 | _tlbie_pid(pid, RIC_FLUSH_ALL); |
366 | else | 588 | else |
367 | _tlbie_pid(pid, RIC_FLUSH_TLB); | 589 | _tlbie_pid(pid, RIC_FLUSH_TLB); |
368 | } else | 590 | } else { |
591 | local: | ||
369 | _tlbiel_pid(pid, RIC_FLUSH_TLB); | 592 | _tlbiel_pid(pid, RIC_FLUSH_TLB); |
593 | } | ||
370 | preempt_enable(); | 594 | preempt_enable(); |
371 | } | 595 | } |
372 | EXPORT_SYMBOL(radix__flush_tlb_mm); | 596 | EXPORT_SYMBOL(radix__flush_tlb_mm); |
373 | 597 | ||
374 | void radix__flush_all_mm(struct mm_struct *mm) | 598 | static void __flush_all_mm(struct mm_struct *mm, bool fullmm) |
375 | { | 599 | { |
376 | unsigned long pid; | 600 | unsigned long pid; |
377 | 601 | ||
@@ -380,12 +604,25 @@ void radix__flush_all_mm(struct mm_struct *mm) | |||
380 | return; | 604 | return; |
381 | 605 | ||
382 | preempt_disable(); | 606 | preempt_disable(); |
383 | if (!mm_is_thread_local(mm)) | 607 | smp_mb(); /* see radix__flush_tlb_mm */ |
608 | if (!mm_is_thread_local(mm)) { | ||
609 | if (unlikely(mm_is_singlethreaded(mm))) { | ||
610 | if (!fullmm) { | ||
611 | exit_flush_lazy_tlbs(mm); | ||
612 | goto local; | ||
613 | } | ||
614 | } | ||
384 | _tlbie_pid(pid, RIC_FLUSH_ALL); | 615 | _tlbie_pid(pid, RIC_FLUSH_ALL); |
385 | else | 616 | } else { |
617 | local: | ||
386 | _tlbiel_pid(pid, RIC_FLUSH_ALL); | 618 | _tlbiel_pid(pid, RIC_FLUSH_ALL); |
619 | } | ||
387 | preempt_enable(); | 620 | preempt_enable(); |
388 | } | 621 | } |
622 | void radix__flush_all_mm(struct mm_struct *mm) | ||
623 | { | ||
624 | __flush_all_mm(mm, false); | ||
625 | } | ||
389 | EXPORT_SYMBOL(radix__flush_all_mm); | 626 | EXPORT_SYMBOL(radix__flush_all_mm); |
390 | 627 | ||
391 | void radix__flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr) | 628 | void radix__flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr) |
@@ -404,10 +641,17 @@ void radix__flush_tlb_page_psize(struct mm_struct *mm, unsigned long vmaddr, | |||
404 | return; | 641 | return; |
405 | 642 | ||
406 | preempt_disable(); | 643 | preempt_disable(); |
407 | if (!mm_is_thread_local(mm)) | 644 | smp_mb(); /* see radix__flush_tlb_mm */ |
645 | if (!mm_is_thread_local(mm)) { | ||
646 | if (unlikely(mm_is_singlethreaded(mm))) { | ||
647 | exit_flush_lazy_tlbs(mm); | ||
648 | goto local; | ||
649 | } | ||
408 | _tlbie_va(vmaddr, pid, psize, RIC_FLUSH_TLB); | 650 | _tlbie_va(vmaddr, pid, psize, RIC_FLUSH_TLB); |
409 | else | 651 | } else { |
652 | local: | ||
410 | _tlbiel_va(vmaddr, pid, psize, RIC_FLUSH_TLB); | 653 | _tlbiel_va(vmaddr, pid, psize, RIC_FLUSH_TLB); |
654 | } | ||
411 | preempt_enable(); | 655 | preempt_enable(); |
412 | } | 656 | } |
413 | 657 | ||
@@ -466,14 +710,22 @@ void radix__flush_tlb_range(struct vm_area_struct *vma, unsigned long start, | |||
466 | return; | 710 | return; |
467 | 711 | ||
468 | preempt_disable(); | 712 | preempt_disable(); |
469 | if (mm_is_thread_local(mm)) { | 713 | smp_mb(); /* see radix__flush_tlb_mm */ |
470 | local = true; | 714 | if (!mm_is_thread_local(mm)) { |
471 | full = (end == TLB_FLUSH_ALL || | 715 | if (unlikely(mm_is_singlethreaded(mm))) { |
472 | nr_pages > tlb_local_single_page_flush_ceiling); | 716 | if (end != TLB_FLUSH_ALL) { |
473 | } else { | 717 | exit_flush_lazy_tlbs(mm); |
718 | goto is_local; | ||
719 | } | ||
720 | } | ||
474 | local = false; | 721 | local = false; |
475 | full = (end == TLB_FLUSH_ALL || | 722 | full = (end == TLB_FLUSH_ALL || |
476 | nr_pages > tlb_single_page_flush_ceiling); | 723 | nr_pages > tlb_single_page_flush_ceiling); |
724 | } else { | ||
725 | is_local: | ||
726 | local = true; | ||
727 | full = (end == TLB_FLUSH_ALL || | ||
728 | nr_pages > tlb_local_single_page_flush_ceiling); | ||
477 | } | 729 | } |
478 | 730 | ||
479 | if (full) { | 731 | if (full) { |
@@ -534,6 +786,49 @@ static int radix_get_mmu_psize(int page_size) | |||
534 | return psize; | 786 | return psize; |
535 | } | 787 | } |
536 | 788 | ||
789 | /* | ||
790 | * Flush partition scoped LPID address translation for all CPUs. | ||
791 | */ | ||
792 | void radix__flush_tlb_lpid_page(unsigned int lpid, | ||
793 | unsigned long addr, | ||
794 | unsigned long page_size) | ||
795 | { | ||
796 | int psize = radix_get_mmu_psize(page_size); | ||
797 | |||
798 | _tlbie_lpid_va(addr, lpid, psize, RIC_FLUSH_TLB); | ||
799 | } | ||
800 | EXPORT_SYMBOL_GPL(radix__flush_tlb_lpid_page); | ||
801 | |||
802 | /* | ||
803 | * Flush partition scoped PWC from LPID for all CPUs. | ||
804 | */ | ||
805 | void radix__flush_pwc_lpid(unsigned int lpid) | ||
806 | { | ||
807 | _tlbie_lpid(lpid, RIC_FLUSH_PWC); | ||
808 | } | ||
809 | EXPORT_SYMBOL_GPL(radix__flush_pwc_lpid); | ||
810 | |||
811 | /* | ||
812 | * Flush partition scoped translations from LPID (=LPIDR) | ||
813 | */ | ||
814 | void radix__local_flush_tlb_lpid(unsigned int lpid) | ||
815 | { | ||
816 | _tlbiel_lpid(lpid, RIC_FLUSH_ALL); | ||
817 | } | ||
818 | EXPORT_SYMBOL_GPL(radix__local_flush_tlb_lpid); | ||
819 | |||
820 | /* | ||
821 | * Flush process scoped translations from LPID (=LPIDR). | ||
822 | * Important difference, the guest normally manages its own translations, | ||
823 | * but some cases e.g., vCPU CPU migration require KVM to flush. | ||
824 | */ | ||
825 | void radix__local_flush_tlb_lpid_guest(unsigned int lpid) | ||
826 | { | ||
827 | _tlbiel_lpid_guest(lpid, RIC_FLUSH_ALL); | ||
828 | } | ||
829 | EXPORT_SYMBOL_GPL(radix__local_flush_tlb_lpid_guest); | ||
830 | |||
831 | |||
537 | static void radix__flush_tlb_pwc_range_psize(struct mm_struct *mm, unsigned long start, | 832 | static void radix__flush_tlb_pwc_range_psize(struct mm_struct *mm, unsigned long start, |
538 | unsigned long end, int psize); | 833 | unsigned long end, int psize); |
539 | 834 | ||
@@ -551,7 +846,7 @@ void radix__tlb_flush(struct mmu_gather *tlb) | |||
551 | * See the comment for radix in arch_exit_mmap(). | 846 | * See the comment for radix in arch_exit_mmap(). |
552 | */ | 847 | */ |
553 | if (tlb->fullmm) { | 848 | if (tlb->fullmm) { |
554 | radix__flush_all_mm(mm); | 849 | __flush_all_mm(mm, true); |
555 | } else if ( (psize = radix_get_mmu_psize(page_size)) == -1) { | 850 | } else if ( (psize = radix_get_mmu_psize(page_size)) == -1) { |
556 | if (!tlb->need_flush_all) | 851 | if (!tlb->need_flush_all) |
557 | radix__flush_tlb_mm(mm); | 852 | radix__flush_tlb_mm(mm); |
@@ -584,24 +879,33 @@ static inline void __radix__flush_tlb_range_psize(struct mm_struct *mm, | |||
584 | return; | 879 | return; |
585 | 880 | ||
586 | preempt_disable(); | 881 | preempt_disable(); |
587 | if (mm_is_thread_local(mm)) { | 882 | smp_mb(); /* see radix__flush_tlb_mm */ |
588 | local = true; | 883 | if (!mm_is_thread_local(mm)) { |
589 | full = (end == TLB_FLUSH_ALL || | 884 | if (unlikely(mm_is_singlethreaded(mm))) { |
590 | nr_pages > tlb_local_single_page_flush_ceiling); | 885 | if (end != TLB_FLUSH_ALL) { |
591 | } else { | 886 | exit_flush_lazy_tlbs(mm); |
887 | goto is_local; | ||
888 | } | ||
889 | } | ||
592 | local = false; | 890 | local = false; |
593 | full = (end == TLB_FLUSH_ALL || | 891 | full = (end == TLB_FLUSH_ALL || |
594 | nr_pages > tlb_single_page_flush_ceiling); | 892 | nr_pages > tlb_single_page_flush_ceiling); |
893 | } else { | ||
894 | is_local: | ||
895 | local = true; | ||
896 | full = (end == TLB_FLUSH_ALL || | ||
897 | nr_pages > tlb_local_single_page_flush_ceiling); | ||
595 | } | 898 | } |
596 | 899 | ||
597 | if (full) { | 900 | if (full) { |
598 | if (!local && mm_needs_flush_escalation(mm)) | 901 | if (local) { |
599 | also_pwc = true; | ||
600 | |||
601 | if (local) | ||
602 | _tlbiel_pid(pid, also_pwc ? RIC_FLUSH_ALL : RIC_FLUSH_TLB); | 902 | _tlbiel_pid(pid, also_pwc ? RIC_FLUSH_ALL : RIC_FLUSH_TLB); |
603 | else | 903 | } else { |
604 | _tlbie_pid(pid, also_pwc ? RIC_FLUSH_ALL: RIC_FLUSH_TLB); | 904 | if (mm_needs_flush_escalation(mm)) |
905 | also_pwc = true; | ||
906 | |||
907 | _tlbie_pid(pid, also_pwc ? RIC_FLUSH_ALL : RIC_FLUSH_TLB); | ||
908 | } | ||
605 | } else { | 909 | } else { |
606 | if (local) | 910 | if (local) |
607 | _tlbiel_va_range(start, end, pid, page_size, psize, also_pwc); | 911 | _tlbiel_va_range(start, end, pid, page_size, psize, also_pwc); |
@@ -642,11 +946,17 @@ void radix__flush_tlb_collapsed_pmd(struct mm_struct *mm, unsigned long addr) | |||
642 | 946 | ||
643 | /* Otherwise first do the PWC, then iterate the pages. */ | 947 | /* Otherwise first do the PWC, then iterate the pages. */ |
644 | preempt_disable(); | 948 | preempt_disable(); |
645 | 949 | smp_mb(); /* see radix__flush_tlb_mm */ | |
646 | if (mm_is_thread_local(mm)) { | 950 | if (!mm_is_thread_local(mm)) { |
647 | _tlbiel_va_range(addr, end, pid, PAGE_SIZE, mmu_virtual_psize, true); | 951 | if (unlikely(mm_is_singlethreaded(mm))) { |
648 | } else { | 952 | exit_flush_lazy_tlbs(mm); |
953 | goto local; | ||
954 | } | ||
649 | _tlbie_va_range(addr, end, pid, PAGE_SIZE, mmu_virtual_psize, true); | 955 | _tlbie_va_range(addr, end, pid, PAGE_SIZE, mmu_virtual_psize, true); |
956 | goto local; | ||
957 | } else { | ||
958 | local: | ||
959 | _tlbiel_va_range(addr, end, pid, PAGE_SIZE, mmu_virtual_psize, true); | ||
650 | } | 960 | } |
651 | 961 | ||
652 | preempt_enable(); | 962 | preempt_enable(); |
diff --git a/arch/powerpc/mm/tlb_hash32.c b/arch/powerpc/mm/tlb_hash32.c index 702d7689d714..cf8472cf3d59 100644 --- a/arch/powerpc/mm/tlb_hash32.c +++ b/arch/powerpc/mm/tlb_hash32.c | |||
@@ -41,7 +41,7 @@ void flush_hash_entry(struct mm_struct *mm, pte_t *ptep, unsigned long addr) | |||
41 | { | 41 | { |
42 | unsigned long ptephys; | 42 | unsigned long ptephys; |
43 | 43 | ||
44 | if (Hash != 0) { | 44 | if (Hash) { |
45 | ptephys = __pa(ptep) & PAGE_MASK; | 45 | ptephys = __pa(ptep) & PAGE_MASK; |
46 | flush_hash_pages(mm->context.id, addr, ptephys, 1); | 46 | flush_hash_pages(mm->context.id, addr, ptephys, 1); |
47 | } | 47 | } |
@@ -54,7 +54,7 @@ EXPORT_SYMBOL(flush_hash_entry); | |||
54 | */ | 54 | */ |
55 | void tlb_flush(struct mmu_gather *tlb) | 55 | void tlb_flush(struct mmu_gather *tlb) |
56 | { | 56 | { |
57 | if (Hash == 0) { | 57 | if (!Hash) { |
58 | /* | 58 | /* |
59 | * 603 needs to flush the whole TLB here since | 59 | * 603 needs to flush the whole TLB here since |
60 | * it doesn't use a hash table. | 60 | * it doesn't use a hash table. |
@@ -84,7 +84,7 @@ static void flush_range(struct mm_struct *mm, unsigned long start, | |||
84 | int count; | 84 | int count; |
85 | unsigned int ctx = mm->context.id; | 85 | unsigned int ctx = mm->context.id; |
86 | 86 | ||
87 | if (Hash == 0) { | 87 | if (!Hash) { |
88 | _tlbia(); | 88 | _tlbia(); |
89 | return; | 89 | return; |
90 | } | 90 | } |
@@ -124,7 +124,7 @@ void flush_tlb_mm(struct mm_struct *mm) | |||
124 | { | 124 | { |
125 | struct vm_area_struct *mp; | 125 | struct vm_area_struct *mp; |
126 | 126 | ||
127 | if (Hash == 0) { | 127 | if (!Hash) { |
128 | _tlbia(); | 128 | _tlbia(); |
129 | return; | 129 | return; |
130 | } | 130 | } |
@@ -145,7 +145,7 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr) | |||
145 | struct mm_struct *mm; | 145 | struct mm_struct *mm; |
146 | pmd_t *pmd; | 146 | pmd_t *pmd; |
147 | 147 | ||
148 | if (Hash == 0) { | 148 | if (!Hash) { |
149 | _tlbie(vmaddr); | 149 | _tlbie(vmaddr); |
150 | return; | 150 | return; |
151 | } | 151 | } |
diff --git a/arch/powerpc/perf/core-fsl-emb.c b/arch/powerpc/perf/core-fsl-emb.c index 85f1d18e5fd3..ba485844d506 100644 --- a/arch/powerpc/perf/core-fsl-emb.c +++ b/arch/powerpc/perf/core-fsl-emb.c | |||
@@ -42,7 +42,7 @@ static DEFINE_MUTEX(pmc_reserve_mutex); | |||
42 | static inline int perf_intr_is_nmi(struct pt_regs *regs) | 42 | static inline int perf_intr_is_nmi(struct pt_regs *regs) |
43 | { | 43 | { |
44 | #ifdef __powerpc64__ | 44 | #ifdef __powerpc64__ |
45 | return !regs->softe; | 45 | return (regs->softe & IRQS_DISABLED); |
46 | #else | 46 | #else |
47 | return 0; | 47 | return 0; |
48 | #endif | 48 | #endif |
diff --git a/arch/powerpc/perf/imc-pmu.c b/arch/powerpc/perf/imc-pmu.c index d7532e7b9ab5..d1977b61f827 100644 --- a/arch/powerpc/perf/imc-pmu.c +++ b/arch/powerpc/perf/imc-pmu.c | |||
@@ -40,6 +40,7 @@ static struct imc_pmu *core_imc_pmu; | |||
40 | /* Thread IMC data structures and variables */ | 40 | /* Thread IMC data structures and variables */ |
41 | 41 | ||
42 | static DEFINE_PER_CPU(u64 *, thread_imc_mem); | 42 | static DEFINE_PER_CPU(u64 *, thread_imc_mem); |
43 | static struct imc_pmu *thread_imc_pmu; | ||
43 | static int thread_imc_mem_size; | 44 | static int thread_imc_mem_size; |
44 | 45 | ||
45 | struct imc_pmu *imc_event_to_pmu(struct perf_event *event) | 46 | struct imc_pmu *imc_event_to_pmu(struct perf_event *event) |
@@ -1146,14 +1147,14 @@ static int init_nest_pmu_ref(void) | |||
1146 | 1147 | ||
1147 | static void cleanup_all_core_imc_memory(void) | 1148 | static void cleanup_all_core_imc_memory(void) |
1148 | { | 1149 | { |
1149 | int i, nr_cores = DIV_ROUND_UP(num_present_cpus(), threads_per_core); | 1150 | int i, nr_cores = DIV_ROUND_UP(num_possible_cpus(), threads_per_core); |
1150 | struct imc_mem_info *ptr = core_imc_pmu->mem_info; | 1151 | struct imc_mem_info *ptr = core_imc_pmu->mem_info; |
1151 | int size = core_imc_pmu->counter_mem_size; | 1152 | int size = core_imc_pmu->counter_mem_size; |
1152 | 1153 | ||
1153 | /* mem_info will never be NULL */ | 1154 | /* mem_info will never be NULL */ |
1154 | for (i = 0; i < nr_cores; i++) { | 1155 | for (i = 0; i < nr_cores; i++) { |
1155 | if (ptr[i].vbase) | 1156 | if (ptr[i].vbase) |
1156 | free_pages((u64)ptr->vbase, get_order(size)); | 1157 | free_pages((u64)ptr[i].vbase, get_order(size)); |
1157 | } | 1158 | } |
1158 | 1159 | ||
1159 | kfree(ptr); | 1160 | kfree(ptr); |
@@ -1191,7 +1192,6 @@ static void imc_common_mem_free(struct imc_pmu *pmu_ptr) | |||
1191 | if (pmu_ptr->attr_groups[IMC_EVENT_ATTR]) | 1192 | if (pmu_ptr->attr_groups[IMC_EVENT_ATTR]) |
1192 | kfree(pmu_ptr->attr_groups[IMC_EVENT_ATTR]->attrs); | 1193 | kfree(pmu_ptr->attr_groups[IMC_EVENT_ATTR]->attrs); |
1193 | kfree(pmu_ptr->attr_groups[IMC_EVENT_ATTR]); | 1194 | kfree(pmu_ptr->attr_groups[IMC_EVENT_ATTR]); |
1194 | kfree(pmu_ptr); | ||
1195 | } | 1195 | } |
1196 | 1196 | ||
1197 | /* | 1197 | /* |
@@ -1208,6 +1208,7 @@ static void imc_common_cpuhp_mem_free(struct imc_pmu *pmu_ptr) | |||
1208 | cpuhp_remove_state(CPUHP_AP_PERF_POWERPC_NEST_IMC_ONLINE); | 1208 | cpuhp_remove_state(CPUHP_AP_PERF_POWERPC_NEST_IMC_ONLINE); |
1209 | kfree(nest_imc_refc); | 1209 | kfree(nest_imc_refc); |
1210 | kfree(per_nest_pmu_arr); | 1210 | kfree(per_nest_pmu_arr); |
1211 | per_nest_pmu_arr = NULL; | ||
1211 | } | 1212 | } |
1212 | 1213 | ||
1213 | if (nest_pmus > 0) | 1214 | if (nest_pmus > 0) |
@@ -1228,6 +1229,16 @@ static void imc_common_cpuhp_mem_free(struct imc_pmu *pmu_ptr) | |||
1228 | } | 1229 | } |
1229 | } | 1230 | } |
1230 | 1231 | ||
1232 | /* | ||
1233 | * Function to unregister thread-imc if core-imc | ||
1234 | * is not registered. | ||
1235 | */ | ||
1236 | void unregister_thread_imc(void) | ||
1237 | { | ||
1238 | imc_common_cpuhp_mem_free(thread_imc_pmu); | ||
1239 | imc_common_mem_free(thread_imc_pmu); | ||
1240 | perf_pmu_unregister(&thread_imc_pmu->pmu); | ||
1241 | } | ||
1231 | 1242 | ||
1232 | /* | 1243 | /* |
1233 | * imc_mem_init : Function to support memory allocation for core imc. | 1244 | * imc_mem_init : Function to support memory allocation for core imc. |
@@ -1236,7 +1247,7 @@ static int imc_mem_init(struct imc_pmu *pmu_ptr, struct device_node *parent, | |||
1236 | int pmu_index) | 1247 | int pmu_index) |
1237 | { | 1248 | { |
1238 | const char *s; | 1249 | const char *s; |
1239 | int nr_cores, cpu, res; | 1250 | int nr_cores, cpu, res = -ENOMEM; |
1240 | 1251 | ||
1241 | if (of_property_read_string(parent, "name", &s)) | 1252 | if (of_property_read_string(parent, "name", &s)) |
1242 | return -ENODEV; | 1253 | return -ENODEV; |
@@ -1246,7 +1257,7 @@ static int imc_mem_init(struct imc_pmu *pmu_ptr, struct device_node *parent, | |||
1246 | /* Update the pmu name */ | 1257 | /* Update the pmu name */ |
1247 | pmu_ptr->pmu.name = kasprintf(GFP_KERNEL, "%s%s_imc", "nest_", s); | 1258 | pmu_ptr->pmu.name = kasprintf(GFP_KERNEL, "%s%s_imc", "nest_", s); |
1248 | if (!pmu_ptr->pmu.name) | 1259 | if (!pmu_ptr->pmu.name) |
1249 | return -ENOMEM; | 1260 | goto err; |
1250 | 1261 | ||
1251 | /* Needed for hotplug/migration */ | 1262 | /* Needed for hotplug/migration */ |
1252 | if (!per_nest_pmu_arr) { | 1263 | if (!per_nest_pmu_arr) { |
@@ -1254,7 +1265,7 @@ static int imc_mem_init(struct imc_pmu *pmu_ptr, struct device_node *parent, | |||
1254 | sizeof(struct imc_pmu *), | 1265 | sizeof(struct imc_pmu *), |
1255 | GFP_KERNEL); | 1266 | GFP_KERNEL); |
1256 | if (!per_nest_pmu_arr) | 1267 | if (!per_nest_pmu_arr) |
1257 | return -ENOMEM; | 1268 | goto err; |
1258 | } | 1269 | } |
1259 | per_nest_pmu_arr[pmu_index] = pmu_ptr; | 1270 | per_nest_pmu_arr[pmu_index] = pmu_ptr; |
1260 | break; | 1271 | break; |
@@ -1262,21 +1273,21 @@ static int imc_mem_init(struct imc_pmu *pmu_ptr, struct device_node *parent, | |||
1262 | /* Update the pmu name */ | 1273 | /* Update the pmu name */ |
1263 | pmu_ptr->pmu.name = kasprintf(GFP_KERNEL, "%s%s", s, "_imc"); | 1274 | pmu_ptr->pmu.name = kasprintf(GFP_KERNEL, "%s%s", s, "_imc"); |
1264 | if (!pmu_ptr->pmu.name) | 1275 | if (!pmu_ptr->pmu.name) |
1265 | return -ENOMEM; | 1276 | goto err; |
1266 | 1277 | ||
1267 | nr_cores = DIV_ROUND_UP(num_present_cpus(), threads_per_core); | 1278 | nr_cores = DIV_ROUND_UP(num_possible_cpus(), threads_per_core); |
1268 | pmu_ptr->mem_info = kcalloc(nr_cores, sizeof(struct imc_mem_info), | 1279 | pmu_ptr->mem_info = kcalloc(nr_cores, sizeof(struct imc_mem_info), |
1269 | GFP_KERNEL); | 1280 | GFP_KERNEL); |
1270 | 1281 | ||
1271 | if (!pmu_ptr->mem_info) | 1282 | if (!pmu_ptr->mem_info) |
1272 | return -ENOMEM; | 1283 | goto err; |
1273 | 1284 | ||
1274 | core_imc_refc = kcalloc(nr_cores, sizeof(struct imc_pmu_ref), | 1285 | core_imc_refc = kcalloc(nr_cores, sizeof(struct imc_pmu_ref), |
1275 | GFP_KERNEL); | 1286 | GFP_KERNEL); |
1276 | 1287 | ||
1277 | if (!core_imc_refc) { | 1288 | if (!core_imc_refc) { |
1278 | kfree(pmu_ptr->mem_info); | 1289 | kfree(pmu_ptr->mem_info); |
1279 | return -ENOMEM; | 1290 | goto err; |
1280 | } | 1291 | } |
1281 | 1292 | ||
1282 | core_imc_pmu = pmu_ptr; | 1293 | core_imc_pmu = pmu_ptr; |
@@ -1285,23 +1296,26 @@ static int imc_mem_init(struct imc_pmu *pmu_ptr, struct device_node *parent, | |||
1285 | /* Update the pmu name */ | 1296 | /* Update the pmu name */ |
1286 | pmu_ptr->pmu.name = kasprintf(GFP_KERNEL, "%s%s", s, "_imc"); | 1297 | pmu_ptr->pmu.name = kasprintf(GFP_KERNEL, "%s%s", s, "_imc"); |
1287 | if (!pmu_ptr->pmu.name) | 1298 | if (!pmu_ptr->pmu.name) |
1288 | return -ENOMEM; | 1299 | goto err; |
1289 | 1300 | ||
1290 | thread_imc_mem_size = pmu_ptr->counter_mem_size; | 1301 | thread_imc_mem_size = pmu_ptr->counter_mem_size; |
1291 | for_each_online_cpu(cpu) { | 1302 | for_each_online_cpu(cpu) { |
1292 | res = thread_imc_mem_alloc(cpu, pmu_ptr->counter_mem_size); | 1303 | res = thread_imc_mem_alloc(cpu, pmu_ptr->counter_mem_size); |
1293 | if (res) { | 1304 | if (res) { |
1294 | cleanup_all_thread_imc_memory(); | 1305 | cleanup_all_thread_imc_memory(); |
1295 | return res; | 1306 | goto err; |
1296 | } | 1307 | } |
1297 | } | 1308 | } |
1298 | 1309 | ||
1310 | thread_imc_pmu = pmu_ptr; | ||
1299 | break; | 1311 | break; |
1300 | default: | 1312 | default: |
1301 | return -EINVAL; | 1313 | return -EINVAL; |
1302 | } | 1314 | } |
1303 | 1315 | ||
1304 | return 0; | 1316 | return 0; |
1317 | err: | ||
1318 | return res; | ||
1305 | } | 1319 | } |
1306 | 1320 | ||
1307 | /* | 1321 | /* |
@@ -1319,10 +1333,8 @@ int init_imc_pmu(struct device_node *parent, struct imc_pmu *pmu_ptr, int pmu_id | |||
1319 | int ret; | 1333 | int ret; |
1320 | 1334 | ||
1321 | ret = imc_mem_init(pmu_ptr, parent, pmu_idx); | 1335 | ret = imc_mem_init(pmu_ptr, parent, pmu_idx); |
1322 | if (ret) { | 1336 | if (ret) |
1323 | imc_common_mem_free(pmu_ptr); | 1337 | goto err_free_mem; |
1324 | return ret; | ||
1325 | } | ||
1326 | 1338 | ||
1327 | switch (pmu_ptr->domain) { | 1339 | switch (pmu_ptr->domain) { |
1328 | case IMC_DOMAIN_NEST: | 1340 | case IMC_DOMAIN_NEST: |
@@ -1337,7 +1349,9 @@ int init_imc_pmu(struct device_node *parent, struct imc_pmu *pmu_ptr, int pmu_id | |||
1337 | ret = init_nest_pmu_ref(); | 1349 | ret = init_nest_pmu_ref(); |
1338 | if (ret) { | 1350 | if (ret) { |
1339 | mutex_unlock(&nest_init_lock); | 1351 | mutex_unlock(&nest_init_lock); |
1340 | goto err_free; | 1352 | kfree(per_nest_pmu_arr); |
1353 | per_nest_pmu_arr = NULL; | ||
1354 | goto err_free_mem; | ||
1341 | } | 1355 | } |
1342 | /* Register for cpu hotplug notification. */ | 1356 | /* Register for cpu hotplug notification. */ |
1343 | ret = nest_pmu_cpumask_init(); | 1357 | ret = nest_pmu_cpumask_init(); |
@@ -1345,7 +1359,8 @@ int init_imc_pmu(struct device_node *parent, struct imc_pmu *pmu_ptr, int pmu_id | |||
1345 | mutex_unlock(&nest_init_lock); | 1359 | mutex_unlock(&nest_init_lock); |
1346 | kfree(nest_imc_refc); | 1360 | kfree(nest_imc_refc); |
1347 | kfree(per_nest_pmu_arr); | 1361 | kfree(per_nest_pmu_arr); |
1348 | goto err_free; | 1362 | per_nest_pmu_arr = NULL; |
1363 | goto err_free_mem; | ||
1349 | } | 1364 | } |
1350 | } | 1365 | } |
1351 | nest_pmus++; | 1366 | nest_pmus++; |
@@ -1355,7 +1370,7 @@ int init_imc_pmu(struct device_node *parent, struct imc_pmu *pmu_ptr, int pmu_id | |||
1355 | ret = core_imc_pmu_cpumask_init(); | 1370 | ret = core_imc_pmu_cpumask_init(); |
1356 | if (ret) { | 1371 | if (ret) { |
1357 | cleanup_all_core_imc_memory(); | 1372 | cleanup_all_core_imc_memory(); |
1358 | return ret; | 1373 | goto err_free_mem; |
1359 | } | 1374 | } |
1360 | 1375 | ||
1361 | break; | 1376 | break; |
@@ -1363,33 +1378,34 @@ int init_imc_pmu(struct device_node *parent, struct imc_pmu *pmu_ptr, int pmu_id | |||
1363 | ret = thread_imc_cpu_init(); | 1378 | ret = thread_imc_cpu_init(); |
1364 | if (ret) { | 1379 | if (ret) { |
1365 | cleanup_all_thread_imc_memory(); | 1380 | cleanup_all_thread_imc_memory(); |
1366 | return ret; | 1381 | goto err_free_mem; |
1367 | } | 1382 | } |
1368 | 1383 | ||
1369 | break; | 1384 | break; |
1370 | default: | 1385 | default: |
1371 | return -1; /* Unknown domain */ | 1386 | return -EINVAL; /* Unknown domain */ |
1372 | } | 1387 | } |
1373 | 1388 | ||
1374 | ret = update_events_in_group(parent, pmu_ptr); | 1389 | ret = update_events_in_group(parent, pmu_ptr); |
1375 | if (ret) | 1390 | if (ret) |
1376 | goto err_free; | 1391 | goto err_free_cpuhp_mem; |
1377 | 1392 | ||
1378 | ret = update_pmu_ops(pmu_ptr); | 1393 | ret = update_pmu_ops(pmu_ptr); |
1379 | if (ret) | 1394 | if (ret) |
1380 | goto err_free; | 1395 | goto err_free_cpuhp_mem; |
1381 | 1396 | ||
1382 | ret = perf_pmu_register(&pmu_ptr->pmu, pmu_ptr->pmu.name, -1); | 1397 | ret = perf_pmu_register(&pmu_ptr->pmu, pmu_ptr->pmu.name, -1); |
1383 | if (ret) | 1398 | if (ret) |
1384 | goto err_free; | 1399 | goto err_free_cpuhp_mem; |
1385 | 1400 | ||
1386 | pr_info("%s performance monitor hardware support registered\n", | 1401 | pr_info("%s performance monitor hardware support registered\n", |
1387 | pmu_ptr->pmu.name); | 1402 | pmu_ptr->pmu.name); |
1388 | 1403 | ||
1389 | return 0; | 1404 | return 0; |
1390 | 1405 | ||
1391 | err_free: | 1406 | err_free_cpuhp_mem: |
1392 | imc_common_mem_free(pmu_ptr); | ||
1393 | imc_common_cpuhp_mem_free(pmu_ptr); | 1407 | imc_common_cpuhp_mem_free(pmu_ptr); |
1408 | err_free_mem: | ||
1409 | imc_common_mem_free(pmu_ptr); | ||
1394 | return ret; | 1410 | return ret; |
1395 | } | 1411 | } |
diff --git a/arch/powerpc/perf/isa207-common.h b/arch/powerpc/perf/isa207-common.h index 6c737d675792..6a0b586c935a 100644 --- a/arch/powerpc/perf/isa207-common.h +++ b/arch/powerpc/perf/isa207-common.h | |||
@@ -17,70 +17,6 @@ | |||
17 | #include <asm/firmware.h> | 17 | #include <asm/firmware.h> |
18 | #include <asm/cputable.h> | 18 | #include <asm/cputable.h> |
19 | 19 | ||
20 | /* | ||
21 | * Raw event encoding for PowerISA v2.07: | ||
22 | * | ||
23 | * 60 56 52 48 44 40 36 32 | ||
24 | * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | | ||
25 | * | | [ ] [ thresh_cmp ] [ thresh_ctl ] | ||
26 | * | | | | | ||
27 | * | | *- IFM (Linux) thresh start/stop OR FAB match -* | ||
28 | * | *- BHRB (Linux) | ||
29 | * *- EBB (Linux) | ||
30 | * | ||
31 | * 28 24 20 16 12 8 4 0 | ||
32 | * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | | ||
33 | * [ ] [ sample ] [cache] [ pmc ] [unit ] c m [ pmcxsel ] | ||
34 | * | | | | | | ||
35 | * | | | | *- mark | ||
36 | * | | *- L1/L2/L3 cache_sel | | ||
37 | * | | | | ||
38 | * | *- sampling mode for marked events *- combine | ||
39 | * | | ||
40 | * *- thresh_sel | ||
41 | * | ||
42 | * Below uses IBM bit numbering. | ||
43 | * | ||
44 | * MMCR1[x:y] = unit (PMCxUNIT) | ||
45 | * MMCR1[x] = combine (PMCxCOMB) | ||
46 | * | ||
47 | * if pmc == 3 and unit == 0 and pmcxsel[0:6] == 0b0101011 | ||
48 | * # PM_MRK_FAB_RSP_MATCH | ||
49 | * MMCR1[20:27] = thresh_ctl (FAB_CRESP_MATCH / FAB_TYPE_MATCH) | ||
50 | * else if pmc == 4 and unit == 0xf and pmcxsel[0:6] == 0b0101001 | ||
51 | * # PM_MRK_FAB_RSP_MATCH_CYC | ||
52 | * MMCR1[20:27] = thresh_ctl (FAB_CRESP_MATCH / FAB_TYPE_MATCH) | ||
53 | * else | ||
54 | * MMCRA[48:55] = thresh_ctl (THRESH START/END) | ||
55 | * | ||
56 | * if thresh_sel: | ||
57 | * MMCRA[45:47] = thresh_sel | ||
58 | * | ||
59 | * if thresh_cmp: | ||
60 | * MMCRA[22:24] = thresh_cmp[0:2] | ||
61 | * MMCRA[25:31] = thresh_cmp[3:9] | ||
62 | * | ||
63 | * if unit == 6 or unit == 7 | ||
64 | * MMCRC[53:55] = cache_sel[1:3] (L2EVENT_SEL) | ||
65 | * else if unit == 8 or unit == 9: | ||
66 | * if cache_sel[0] == 0: # L3 bank | ||
67 | * MMCRC[47:49] = cache_sel[1:3] (L3EVENT_SEL0) | ||
68 | * else if cache_sel[0] == 1: | ||
69 | * MMCRC[50:51] = cache_sel[2:3] (L3EVENT_SEL1) | ||
70 | * else if cache_sel[1]: # L1 event | ||
71 | * MMCR1[16] = cache_sel[2] | ||
72 | Â * MMCR1[17] = cache_sel[3] | ||
73 | * | ||
74 | * if mark: | ||
75 | * MMCRA[63] = 1 (SAMPLE_ENABLE) | ||
76 | * MMCRA[57:59] = sample[0:2] (RAND_SAMP_ELIG) | ||
77 | Â * MMCRA[61:62] = sample[3:4] (RAND_SAMP_MODE) | ||
78 | * | ||
79 | * if EBB and BHRB: | ||
80 | * MMCRA[32:33] = IFM | ||
81 | * | ||
82 | */ | ||
83 | |||
84 | #define EVENT_EBB_MASK 1ull | 20 | #define EVENT_EBB_MASK 1ull |
85 | #define EVENT_EBB_SHIFT PERF_EVENT_CONFIG_EBB_SHIFT | 21 | #define EVENT_EBB_SHIFT PERF_EVENT_CONFIG_EBB_SHIFT |
86 | #define EVENT_BHRB_MASK 1ull | 22 | #define EVENT_BHRB_MASK 1ull |
diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c index c9356955cab4..d12a2db26353 100644 --- a/arch/powerpc/perf/power8-pmu.c +++ b/arch/powerpc/perf/power8-pmu.c | |||
@@ -30,6 +30,70 @@ enum { | |||
30 | #define POWER8_MMCRA_IFM2 0x0000000080000000UL | 30 | #define POWER8_MMCRA_IFM2 0x0000000080000000UL |
31 | #define POWER8_MMCRA_IFM3 0x00000000C0000000UL | 31 | #define POWER8_MMCRA_IFM3 0x00000000C0000000UL |
32 | 32 | ||
33 | /* | ||
34 | * Raw event encoding for PowerISA v2.07 (Power8): | ||
35 | * | ||
36 | * 60 56 52 48 44 40 36 32 | ||
37 | * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | | ||
38 | * | | [ ] [ thresh_cmp ] [ thresh_ctl ] | ||
39 | * | | | | | ||
40 | * | | *- IFM (Linux) thresh start/stop OR FAB match -* | ||
41 | * | *- BHRB (Linux) | ||
42 | * *- EBB (Linux) | ||
43 | * | ||
44 | * 28 24 20 16 12 8 4 0 | ||
45 | * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | | ||
46 | * [ ] [ sample ] [cache] [ pmc ] [unit ] c m [ pmcxsel ] | ||
47 | * | | | | | | ||
48 | * | | | | *- mark | ||
49 | * | | *- L1/L2/L3 cache_sel | | ||
50 | * | | | | ||
51 | * | *- sampling mode for marked events *- combine | ||
52 | * | | ||
53 | * *- thresh_sel | ||
54 | * | ||
55 | * Below uses IBM bit numbering. | ||
56 | * | ||
57 | * MMCR1[x:y] = unit (PMCxUNIT) | ||
58 | * MMCR1[x] = combine (PMCxCOMB) | ||
59 | * | ||
60 | * if pmc == 3 and unit == 0 and pmcxsel[0:6] == 0b0101011 | ||
61 | * # PM_MRK_FAB_RSP_MATCH | ||
62 | * MMCR1[20:27] = thresh_ctl (FAB_CRESP_MATCH / FAB_TYPE_MATCH) | ||
63 | * else if pmc == 4 and unit == 0xf and pmcxsel[0:6] == 0b0101001 | ||
64 | * # PM_MRK_FAB_RSP_MATCH_CYC | ||
65 | * MMCR1[20:27] = thresh_ctl (FAB_CRESP_MATCH / FAB_TYPE_MATCH) | ||
66 | * else | ||
67 | * MMCRA[48:55] = thresh_ctl (THRESH START/END) | ||
68 | * | ||
69 | * if thresh_sel: | ||
70 | * MMCRA[45:47] = thresh_sel | ||
71 | * | ||
72 | * if thresh_cmp: | ||
73 | * MMCRA[22:24] = thresh_cmp[0:2] | ||
74 | * MMCRA[25:31] = thresh_cmp[3:9] | ||
75 | * | ||
76 | * if unit == 6 or unit == 7 | ||
77 | * MMCRC[53:55] = cache_sel[1:3] (L2EVENT_SEL) | ||
78 | * else if unit == 8 or unit == 9: | ||
79 | * if cache_sel[0] == 0: # L3 bank | ||
80 | * MMCRC[47:49] = cache_sel[1:3] (L3EVENT_SEL0) | ||
81 | * else if cache_sel[0] == 1: | ||
82 | * MMCRC[50:51] = cache_sel[2:3] (L3EVENT_SEL1) | ||
83 | * else if cache_sel[1]: # L1 event | ||
84 | * MMCR1[16] = cache_sel[2] | ||
85 | Â * MMCR1[17] = cache_sel[3] | ||
86 | * | ||
87 | * if mark: | ||
88 | * MMCRA[63] = 1 (SAMPLE_ENABLE) | ||
89 | * MMCRA[57:59] = sample[0:2] (RAND_SAMP_ELIG) | ||
90 | Â * MMCRA[61:62] = sample[3:4] (RAND_SAMP_MODE) | ||
91 | * | ||
92 | * if EBB and BHRB: | ||
93 | * MMCRA[32:33] = IFM | ||
94 | * | ||
95 | */ | ||
96 | |||
33 | /* PowerISA v2.07 format attribute structure*/ | 97 | /* PowerISA v2.07 format attribute structure*/ |
34 | extern struct attribute_group isa207_pmu_format_group; | 98 | extern struct attribute_group isa207_pmu_format_group; |
35 | 99 | ||
diff --git a/arch/powerpc/platforms/83xx/Kconfig b/arch/powerpc/platforms/83xx/Kconfig index 7e38b7b71a5a..071f53b0c0a0 100644 --- a/arch/powerpc/platforms/83xx/Kconfig +++ b/arch/powerpc/platforms/83xx/Kconfig | |||
@@ -90,13 +90,6 @@ config MPC837x_RDB | |||
90 | help | 90 | help |
91 | This option enables support for the MPC837x RDB and WLAN Boards. | 91 | This option enables support for the MPC837x RDB and WLAN Boards. |
92 | 92 | ||
93 | config SBC834x | ||
94 | bool "Wind River SBC834x" | ||
95 | select DEFAULT_UIMAGE | ||
96 | select PPC_MPC834x | ||
97 | help | ||
98 | This option enables support for the Wind River SBC834x board. | ||
99 | |||
100 | config ASP834x | 93 | config ASP834x |
101 | bool "Analogue & Micro ASP 834x" | 94 | bool "Analogue & Micro ASP 834x" |
102 | select PPC_MPC834x | 95 | select PPC_MPC834x |
diff --git a/arch/powerpc/platforms/83xx/Makefile b/arch/powerpc/platforms/83xx/Makefile index bb4720897f6a..41cb5f842eff 100644 --- a/arch/powerpc/platforms/83xx/Makefile +++ b/arch/powerpc/platforms/83xx/Makefile | |||
@@ -14,7 +14,6 @@ obj-$(CONFIG_MPC836x_MDS) += mpc836x_mds.o | |||
14 | obj-$(CONFIG_MPC836x_RDK) += mpc836x_rdk.o | 14 | obj-$(CONFIG_MPC836x_RDK) += mpc836x_rdk.o |
15 | obj-$(CONFIG_MPC832x_MDS) += mpc832x_mds.o | 15 | obj-$(CONFIG_MPC832x_MDS) += mpc832x_mds.o |
16 | obj-$(CONFIG_MPC837x_MDS) += mpc837x_mds.o | 16 | obj-$(CONFIG_MPC837x_MDS) += mpc837x_mds.o |
17 | obj-$(CONFIG_SBC834x) += sbc834x.o | ||
18 | obj-$(CONFIG_MPC837x_RDB) += mpc837x_rdb.o | 17 | obj-$(CONFIG_MPC837x_RDB) += mpc837x_rdb.o |
19 | obj-$(CONFIG_ASP834x) += asp834x.o | 18 | obj-$(CONFIG_ASP834x) += asp834x.o |
20 | obj-$(CONFIG_KMETER1) += km83xx.o | 19 | obj-$(CONFIG_KMETER1) += km83xx.o |
diff --git a/arch/powerpc/platforms/83xx/sbc834x.c b/arch/powerpc/platforms/83xx/sbc834x.c deleted file mode 100644 index cb4bdabfdf1c..000000000000 --- a/arch/powerpc/platforms/83xx/sbc834x.c +++ /dev/null | |||
@@ -1,73 +0,0 @@ | |||
1 | /* | ||
2 | * arch/powerpc/platforms/83xx/sbc834x.c | ||
3 | * | ||
4 | * Wind River SBC834x board specific routines | ||
5 | * | ||
6 | * By Paul Gortmaker (see MAINTAINERS for contact information) | ||
7 | * | ||
8 | * Based largely on the mpc834x_mds.c support by Kumar Gala. | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | */ | ||
15 | |||
16 | #include <linux/stddef.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/errno.h> | ||
20 | #include <linux/reboot.h> | ||
21 | #include <linux/pci.h> | ||
22 | #include <linux/kdev_t.h> | ||
23 | #include <linux/major.h> | ||
24 | #include <linux/console.h> | ||
25 | #include <linux/delay.h> | ||
26 | #include <linux/seq_file.h> | ||
27 | #include <linux/root_dev.h> | ||
28 | #include <linux/of_platform.h> | ||
29 | |||
30 | #include <linux/atomic.h> | ||
31 | #include <asm/time.h> | ||
32 | #include <asm/io.h> | ||
33 | #include <asm/machdep.h> | ||
34 | #include <asm/ipic.h> | ||
35 | #include <asm/irq.h> | ||
36 | #include <asm/prom.h> | ||
37 | #include <asm/udbg.h> | ||
38 | #include <sysdev/fsl_soc.h> | ||
39 | #include <sysdev/fsl_pci.h> | ||
40 | |||
41 | #include "mpc83xx.h" | ||
42 | |||
43 | /* ************************************************************************ | ||
44 | * | ||
45 | * Setup the architecture | ||
46 | * | ||
47 | */ | ||
48 | static void __init sbc834x_setup_arch(void) | ||
49 | { | ||
50 | mpc83xx_setup_arch(); | ||
51 | } | ||
52 | |||
53 | machine_device_initcall(sbc834x, mpc83xx_declare_of_platform_devices); | ||
54 | |||
55 | /* | ||
56 | * Called very early, MMU is off, device-tree isn't unflattened | ||
57 | */ | ||
58 | static int __init sbc834x_probe(void) | ||
59 | { | ||
60 | return of_machine_is_compatible("SBC834xE"); | ||
61 | } | ||
62 | |||
63 | define_machine(sbc834x) { | ||
64 | .name = "SBC834xE", | ||
65 | .probe = sbc834x_probe, | ||
66 | .setup_arch = sbc834x_setup_arch, | ||
67 | .init_IRQ = mpc83xx_ipic_init_IRQ, | ||
68 | .get_irq = ipic_get_irq, | ||
69 | .restart = mpc83xx_restart, | ||
70 | .time_init = mpc83xx_time_init, | ||
71 | .calibrate_decr = generic_calibrate_decr, | ||
72 | .progress = udbg_progress, | ||
73 | }; | ||
diff --git a/arch/powerpc/platforms/8xx/adder875.c b/arch/powerpc/platforms/8xx/adder875.c index 333dece79394..bcef9f66191e 100644 --- a/arch/powerpc/platforms/8xx/adder875.c +++ b/arch/powerpc/platforms/8xx/adder875.c | |||
@@ -111,7 +111,5 @@ define_machine(adder875) { | |||
111 | .get_irq = mpc8xx_get_irq, | 111 | .get_irq = mpc8xx_get_irq, |
112 | .restart = mpc8xx_restart, | 112 | .restart = mpc8xx_restart, |
113 | .calibrate_decr = generic_calibrate_decr, | 113 | .calibrate_decr = generic_calibrate_decr, |
114 | .set_rtc_time = mpc8xx_set_rtc_time, | ||
115 | .get_rtc_time = mpc8xx_get_rtc_time, | ||
116 | .progress = udbg_progress, | 114 | .progress = udbg_progress, |
117 | }; | 115 | }; |
diff --git a/arch/powerpc/platforms/8xx/ep88xc.c b/arch/powerpc/platforms/8xx/ep88xc.c index cd0d90f1fb1c..ebcf34a14789 100644 --- a/arch/powerpc/platforms/8xx/ep88xc.c +++ b/arch/powerpc/platforms/8xx/ep88xc.c | |||
@@ -170,7 +170,5 @@ define_machine(ep88xc) { | |||
170 | .get_irq = mpc8xx_get_irq, | 170 | .get_irq = mpc8xx_get_irq, |
171 | .restart = mpc8xx_restart, | 171 | .restart = mpc8xx_restart, |
172 | .calibrate_decr = mpc8xx_calibrate_decr, | 172 | .calibrate_decr = mpc8xx_calibrate_decr, |
173 | .set_rtc_time = mpc8xx_set_rtc_time, | ||
174 | .get_rtc_time = mpc8xx_get_rtc_time, | ||
175 | .progress = udbg_progress, | 173 | .progress = udbg_progress, |
176 | }; | 174 | }; |
diff --git a/arch/powerpc/platforms/8xx/m8xx_setup.c b/arch/powerpc/platforms/8xx/m8xx_setup.c index 2188d691a40f..027c42d8966c 100644 --- a/arch/powerpc/platforms/8xx/m8xx_setup.c +++ b/arch/powerpc/platforms/8xx/m8xx_setup.c | |||
@@ -169,15 +169,14 @@ int mpc8xx_set_rtc_time(struct rtc_time *tm) | |||
169 | { | 169 | { |
170 | sitk8xx_t __iomem *sys_tmr1; | 170 | sitk8xx_t __iomem *sys_tmr1; |
171 | sit8xx_t __iomem *sys_tmr2; | 171 | sit8xx_t __iomem *sys_tmr2; |
172 | int time; | 172 | time64_t time; |
173 | 173 | ||
174 | sys_tmr1 = immr_map(im_sitk); | 174 | sys_tmr1 = immr_map(im_sitk); |
175 | sys_tmr2 = immr_map(im_sit); | 175 | sys_tmr2 = immr_map(im_sit); |
176 | time = mktime(tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, | 176 | time = rtc_tm_to_time64(tm); |
177 | tm->tm_hour, tm->tm_min, tm->tm_sec); | ||
178 | 177 | ||
179 | out_be32(&sys_tmr1->sitk_rtck, KAPWR_KEY); | 178 | out_be32(&sys_tmr1->sitk_rtck, KAPWR_KEY); |
180 | out_be32(&sys_tmr2->sit_rtc, time); | 179 | out_be32(&sys_tmr2->sit_rtc, (u32)time); |
181 | out_be32(&sys_tmr1->sitk_rtck, ~KAPWR_KEY); | 180 | out_be32(&sys_tmr1->sitk_rtck, ~KAPWR_KEY); |
182 | 181 | ||
183 | immr_unmap(sys_tmr2); | 182 | immr_unmap(sys_tmr2); |
@@ -192,9 +191,7 @@ void mpc8xx_get_rtc_time(struct rtc_time *tm) | |||
192 | 191 | ||
193 | /* Get time from the RTC. */ | 192 | /* Get time from the RTC. */ |
194 | data = in_be32(&sys_tmr->sit_rtc); | 193 | data = in_be32(&sys_tmr->sit_rtc); |
195 | to_tm(data, tm); | 194 | rtc_time64_to_tm(data, tm); |
196 | tm->tm_year -= 1900; | ||
197 | tm->tm_mon -= 1; | ||
198 | immr_unmap(sys_tmr); | 195 | immr_unmap(sys_tmr); |
199 | return; | 196 | return; |
200 | } | 197 | } |
diff --git a/arch/powerpc/platforms/8xx/mpc885ads_setup.c b/arch/powerpc/platforms/8xx/mpc885ads_setup.c index e821a42d5816..a0c83c1905c6 100644 --- a/arch/powerpc/platforms/8xx/mpc885ads_setup.c +++ b/arch/powerpc/platforms/8xx/mpc885ads_setup.c | |||
@@ -220,7 +220,5 @@ define_machine(mpc885_ads) { | |||
220 | .get_irq = mpc8xx_get_irq, | 220 | .get_irq = mpc8xx_get_irq, |
221 | .restart = mpc8xx_restart, | 221 | .restart = mpc8xx_restart, |
222 | .calibrate_decr = mpc8xx_calibrate_decr, | 222 | .calibrate_decr = mpc8xx_calibrate_decr, |
223 | .set_rtc_time = mpc8xx_set_rtc_time, | ||
224 | .get_rtc_time = mpc8xx_get_rtc_time, | ||
225 | .progress = udbg_progress, | 223 | .progress = udbg_progress, |
226 | }; | 224 | }; |
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype index 84b58abc08ee..e6a1de521319 100644 --- a/arch/powerpc/platforms/Kconfig.cputype +++ b/arch/powerpc/platforms/Kconfig.cputype | |||
@@ -293,6 +293,10 @@ config PPC_STD_MMU_32 | |||
293 | def_bool y | 293 | def_bool y |
294 | depends on PPC_STD_MMU && PPC32 | 294 | depends on PPC_STD_MMU && PPC32 |
295 | 295 | ||
296 | config ARCH_ENABLE_SPLIT_PMD_PTLOCK | ||
297 | def_bool y | ||
298 | depends on PPC_BOOK3S_64 | ||
299 | |||
296 | config PPC_RADIX_MMU | 300 | config PPC_RADIX_MMU |
297 | bool "Radix MMU Support" | 301 | bool "Radix MMU Support" |
298 | depends on PPC_BOOK3S_64 | 302 | depends on PPC_BOOK3S_64 |
diff --git a/arch/powerpc/platforms/cell/spu_callbacks.c b/arch/powerpc/platforms/cell/spu_callbacks.c index a494028b2cdf..8ae86200ef6c 100644 --- a/arch/powerpc/platforms/cell/spu_callbacks.c +++ b/arch/powerpc/platforms/cell/spu_callbacks.c | |||
@@ -44,7 +44,7 @@ static void *spu_syscall_table[] = { | |||
44 | 44 | ||
45 | #define SYSCALL_SPU(func) sys_##func, | 45 | #define SYSCALL_SPU(func) sys_##func, |
46 | #define COMPAT_SYS_SPU(func) sys_##func, | 46 | #define COMPAT_SYS_SPU(func) sys_##func, |
47 | #define PPC_SYS_SPU(func) ppc_##func, | 47 | #define COMPAT_SPU_NEW(func) sys_##func, |
48 | #define SYSX_SPU(f, f3264, f32) f, | 48 | #define SYSX_SPU(f, f3264, f32) f, |
49 | 49 | ||
50 | #include <asm/systbl.h> | 50 | #include <asm/systbl.h> |
diff --git a/arch/powerpc/platforms/cell/spu_syscalls.c b/arch/powerpc/platforms/cell/spu_syscalls.c index 5e6e0bad6db6..263413a34823 100644 --- a/arch/powerpc/platforms/cell/spu_syscalls.c +++ b/arch/powerpc/platforms/cell/spu_syscalls.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/syscalls.h> | 26 | #include <linux/syscalls.h> |
27 | #include <linux/rcupdate.h> | 27 | #include <linux/rcupdate.h> |
28 | #include <linux/binfmts.h> | 28 | #include <linux/binfmts.h> |
29 | #include <linux/syscalls.h> | ||
29 | 30 | ||
30 | #include <asm/spu.h> | 31 | #include <asm/spu.h> |
31 | 32 | ||
@@ -90,7 +91,7 @@ SYSCALL_DEFINE4(spu_create, const char __user *, name, unsigned int, flags, | |||
90 | return ret; | 91 | return ret; |
91 | } | 92 | } |
92 | 93 | ||
93 | asmlinkage long sys_spu_run(int fd, __u32 __user *unpc, __u32 __user *ustatus) | 94 | SYSCALL_DEFINE3(spu_run,int, fd, __u32 __user *, unpc, __u32 __user *, ustatus) |
94 | { | 95 | { |
95 | long ret; | 96 | long ret; |
96 | struct fd arg; | 97 | struct fd arg; |
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 469bdd0b748f..43e7b93f27c7 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c | |||
@@ -232,12 +232,13 @@ spufs_mem_write(struct file *file, const char __user *buffer, | |||
232 | return size; | 232 | return size; |
233 | } | 233 | } |
234 | 234 | ||
235 | static int | 235 | static vm_fault_t |
236 | spufs_mem_mmap_fault(struct vm_fault *vmf) | 236 | spufs_mem_mmap_fault(struct vm_fault *vmf) |
237 | { | 237 | { |
238 | struct vm_area_struct *vma = vmf->vma; | 238 | struct vm_area_struct *vma = vmf->vma; |
239 | struct spu_context *ctx = vma->vm_file->private_data; | 239 | struct spu_context *ctx = vma->vm_file->private_data; |
240 | unsigned long pfn, offset; | 240 | unsigned long pfn, offset; |
241 | vm_fault_t ret; | ||
241 | 242 | ||
242 | offset = vmf->pgoff << PAGE_SHIFT; | 243 | offset = vmf->pgoff << PAGE_SHIFT; |
243 | if (offset >= LS_SIZE) | 244 | if (offset >= LS_SIZE) |
@@ -256,11 +257,11 @@ spufs_mem_mmap_fault(struct vm_fault *vmf) | |||
256 | vma->vm_page_prot = pgprot_noncached_wc(vma->vm_page_prot); | 257 | vma->vm_page_prot = pgprot_noncached_wc(vma->vm_page_prot); |
257 | pfn = (ctx->spu->local_store_phys + offset) >> PAGE_SHIFT; | 258 | pfn = (ctx->spu->local_store_phys + offset) >> PAGE_SHIFT; |
258 | } | 259 | } |
259 | vm_insert_pfn(vma, vmf->address, pfn); | 260 | ret = vmf_insert_pfn(vma, vmf->address, pfn); |
260 | 261 | ||
261 | spu_release(ctx); | 262 | spu_release(ctx); |
262 | 263 | ||
263 | return VM_FAULT_NOPAGE; | 264 | return ret; |
264 | } | 265 | } |
265 | 266 | ||
266 | static int spufs_mem_mmap_access(struct vm_area_struct *vma, | 267 | static int spufs_mem_mmap_access(struct vm_area_struct *vma, |
@@ -312,13 +313,14 @@ static const struct file_operations spufs_mem_fops = { | |||
312 | .mmap = spufs_mem_mmap, | 313 | .mmap = spufs_mem_mmap, |
313 | }; | 314 | }; |
314 | 315 | ||
315 | static int spufs_ps_fault(struct vm_fault *vmf, | 316 | static vm_fault_t spufs_ps_fault(struct vm_fault *vmf, |
316 | unsigned long ps_offs, | 317 | unsigned long ps_offs, |
317 | unsigned long ps_size) | 318 | unsigned long ps_size) |
318 | { | 319 | { |
319 | struct spu_context *ctx = vmf->vma->vm_file->private_data; | 320 | struct spu_context *ctx = vmf->vma->vm_file->private_data; |
320 | unsigned long area, offset = vmf->pgoff << PAGE_SHIFT; | 321 | unsigned long area, offset = vmf->pgoff << PAGE_SHIFT; |
321 | int ret = 0; | 322 | int err = 0; |
323 | vm_fault_t ret = VM_FAULT_NOPAGE; | ||
322 | 324 | ||
323 | spu_context_nospu_trace(spufs_ps_fault__enter, ctx); | 325 | spu_context_nospu_trace(spufs_ps_fault__enter, ctx); |
324 | 326 | ||
@@ -349,25 +351,26 @@ static int spufs_ps_fault(struct vm_fault *vmf, | |||
349 | if (ctx->state == SPU_STATE_SAVED) { | 351 | if (ctx->state == SPU_STATE_SAVED) { |
350 | up_read(¤t->mm->mmap_sem); | 352 | up_read(¤t->mm->mmap_sem); |
351 | spu_context_nospu_trace(spufs_ps_fault__sleep, ctx); | 353 | spu_context_nospu_trace(spufs_ps_fault__sleep, ctx); |
352 | ret = spufs_wait(ctx->run_wq, ctx->state == SPU_STATE_RUNNABLE); | 354 | err = spufs_wait(ctx->run_wq, ctx->state == SPU_STATE_RUNNABLE); |
353 | spu_context_trace(spufs_ps_fault__wake, ctx, ctx->spu); | 355 | spu_context_trace(spufs_ps_fault__wake, ctx, ctx->spu); |
354 | down_read(¤t->mm->mmap_sem); | 356 | down_read(¤t->mm->mmap_sem); |
355 | } else { | 357 | } else { |
356 | area = ctx->spu->problem_phys + ps_offs; | 358 | area = ctx->spu->problem_phys + ps_offs; |
357 | vm_insert_pfn(vmf->vma, vmf->address, (area + offset) >> PAGE_SHIFT); | 359 | ret = vmf_insert_pfn(vmf->vma, vmf->address, |
360 | (area + offset) >> PAGE_SHIFT); | ||
358 | spu_context_trace(spufs_ps_fault__insert, ctx, ctx->spu); | 361 | spu_context_trace(spufs_ps_fault__insert, ctx, ctx->spu); |
359 | } | 362 | } |
360 | 363 | ||
361 | if (!ret) | 364 | if (!err) |
362 | spu_release(ctx); | 365 | spu_release(ctx); |
363 | 366 | ||
364 | refault: | 367 | refault: |
365 | put_spu_context(ctx); | 368 | put_spu_context(ctx); |
366 | return VM_FAULT_NOPAGE; | 369 | return ret; |
367 | } | 370 | } |
368 | 371 | ||
369 | #if SPUFS_MMAP_4K | 372 | #if SPUFS_MMAP_4K |
370 | static int spufs_cntl_mmap_fault(struct vm_fault *vmf) | 373 | static vm_fault_t spufs_cntl_mmap_fault(struct vm_fault *vmf) |
371 | { | 374 | { |
372 | return spufs_ps_fault(vmf, 0x4000, SPUFS_CNTL_MAP_SIZE); | 375 | return spufs_ps_fault(vmf, 0x4000, SPUFS_CNTL_MAP_SIZE); |
373 | } | 376 | } |
@@ -1040,7 +1043,7 @@ static ssize_t spufs_signal1_write(struct file *file, const char __user *buf, | |||
1040 | return 4; | 1043 | return 4; |
1041 | } | 1044 | } |
1042 | 1045 | ||
1043 | static int | 1046 | static vm_fault_t |
1044 | spufs_signal1_mmap_fault(struct vm_fault *vmf) | 1047 | spufs_signal1_mmap_fault(struct vm_fault *vmf) |
1045 | { | 1048 | { |
1046 | #if SPUFS_SIGNAL_MAP_SIZE == 0x1000 | 1049 | #if SPUFS_SIGNAL_MAP_SIZE == 0x1000 |
@@ -1178,7 +1181,7 @@ static ssize_t spufs_signal2_write(struct file *file, const char __user *buf, | |||
1178 | } | 1181 | } |
1179 | 1182 | ||
1180 | #if SPUFS_MMAP_4K | 1183 | #if SPUFS_MMAP_4K |
1181 | static int | 1184 | static vm_fault_t |
1182 | spufs_signal2_mmap_fault(struct vm_fault *vmf) | 1185 | spufs_signal2_mmap_fault(struct vm_fault *vmf) |
1183 | { | 1186 | { |
1184 | #if SPUFS_SIGNAL_MAP_SIZE == 0x1000 | 1187 | #if SPUFS_SIGNAL_MAP_SIZE == 0x1000 |
@@ -1307,7 +1310,7 @@ DEFINE_SPUFS_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get, | |||
1307 | spufs_signal2_type_set, "%llu\n", SPU_ATTR_ACQUIRE); | 1310 | spufs_signal2_type_set, "%llu\n", SPU_ATTR_ACQUIRE); |
1308 | 1311 | ||
1309 | #if SPUFS_MMAP_4K | 1312 | #if SPUFS_MMAP_4K |
1310 | static int | 1313 | static vm_fault_t |
1311 | spufs_mss_mmap_fault(struct vm_fault *vmf) | 1314 | spufs_mss_mmap_fault(struct vm_fault *vmf) |
1312 | { | 1315 | { |
1313 | return spufs_ps_fault(vmf, 0x0000, SPUFS_MSS_MAP_SIZE); | 1316 | return spufs_ps_fault(vmf, 0x0000, SPUFS_MSS_MAP_SIZE); |
@@ -1369,7 +1372,7 @@ static const struct file_operations spufs_mss_fops = { | |||
1369 | .llseek = no_llseek, | 1372 | .llseek = no_llseek, |
1370 | }; | 1373 | }; |
1371 | 1374 | ||
1372 | static int | 1375 | static vm_fault_t |
1373 | spufs_psmap_mmap_fault(struct vm_fault *vmf) | 1376 | spufs_psmap_mmap_fault(struct vm_fault *vmf) |
1374 | { | 1377 | { |
1375 | return spufs_ps_fault(vmf, 0x0000, SPUFS_PS_MAP_SIZE); | 1378 | return spufs_ps_fault(vmf, 0x0000, SPUFS_PS_MAP_SIZE); |
@@ -1429,7 +1432,7 @@ static const struct file_operations spufs_psmap_fops = { | |||
1429 | 1432 | ||
1430 | 1433 | ||
1431 | #if SPUFS_MMAP_4K | 1434 | #if SPUFS_MMAP_4K |
1432 | static int | 1435 | static vm_fault_t |
1433 | spufs_mfc_mmap_fault(struct vm_fault *vmf) | 1436 | spufs_mfc_mmap_fault(struct vm_fault *vmf) |
1434 | { | 1437 | { |
1435 | return spufs_ps_fault(vmf, 0x3000, SPUFS_MFC_MAP_SIZE); | 1438 | return spufs_ps_fault(vmf, 0x3000, SPUFS_MFC_MAP_SIZE); |
diff --git a/arch/powerpc/platforms/chrp/pci.c b/arch/powerpc/platforms/chrp/pci.c index 0f512d35f7c5..5ddb57b82921 100644 --- a/arch/powerpc/platforms/chrp/pci.c +++ b/arch/powerpc/platforms/chrp/pci.c | |||
@@ -31,7 +31,7 @@ void __iomem *gg2_pci_config_base; | |||
31 | * limit the bus number to 3 bits | 31 | * limit the bus number to 3 bits |
32 | */ | 32 | */ |
33 | 33 | ||
34 | int gg2_read_config(struct pci_bus *bus, unsigned int devfn, int off, | 34 | static int gg2_read_config(struct pci_bus *bus, unsigned int devfn, int off, |
35 | int len, u32 *val) | 35 | int len, u32 *val) |
36 | { | 36 | { |
37 | volatile void __iomem *cfg_data; | 37 | volatile void __iomem *cfg_data; |
@@ -58,7 +58,7 @@ int gg2_read_config(struct pci_bus *bus, unsigned int devfn, int off, | |||
58 | return PCIBIOS_SUCCESSFUL; | 58 | return PCIBIOS_SUCCESSFUL; |
59 | } | 59 | } |
60 | 60 | ||
61 | int gg2_write_config(struct pci_bus *bus, unsigned int devfn, int off, | 61 | static int gg2_write_config(struct pci_bus *bus, unsigned int devfn, int off, |
62 | int len, u32 val) | 62 | int len, u32 val) |
63 | { | 63 | { |
64 | volatile void __iomem *cfg_data; | 64 | volatile void __iomem *cfg_data; |
@@ -94,8 +94,8 @@ static struct pci_ops gg2_pci_ops = | |||
94 | /* | 94 | /* |
95 | * Access functions for PCI config space using RTAS calls. | 95 | * Access functions for PCI config space using RTAS calls. |
96 | */ | 96 | */ |
97 | int rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset, | 97 | static int rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset, |
98 | int len, u32 *val) | 98 | int len, u32 *val) |
99 | { | 99 | { |
100 | struct pci_controller *hose = pci_bus_to_host(bus); | 100 | struct pci_controller *hose = pci_bus_to_host(bus); |
101 | unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) | 101 | unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) |
@@ -109,8 +109,8 @@ int rtas_read_config(struct pci_bus *bus, unsigned int devfn, int offset, | |||
109 | return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL; | 109 | return rval? PCIBIOS_DEVICE_NOT_FOUND: PCIBIOS_SUCCESSFUL; |
110 | } | 110 | } |
111 | 111 | ||
112 | int rtas_write_config(struct pci_bus *bus, unsigned int devfn, int offset, | 112 | static int rtas_write_config(struct pci_bus *bus, unsigned int devfn, int offset, |
113 | int len, u32 val) | 113 | int len, u32 val) |
114 | { | 114 | { |
115 | struct pci_controller *hose = pci_bus_to_host(bus); | 115 | struct pci_controller *hose = pci_bus_to_host(bus); |
116 | unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) | 116 | unsigned long addr = (offset & 0xff) | ((devfn & 0xff) << 8) |
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c index 481ed133e04b..d6d8ffc0271e 100644 --- a/arch/powerpc/platforms/chrp/setup.c +++ b/arch/powerpc/platforms/chrp/setup.c | |||
@@ -94,7 +94,7 @@ static const char *chrp_names[] = { | |||
94 | "Total Impact Briq" | 94 | "Total Impact Briq" |
95 | }; | 95 | }; |
96 | 96 | ||
97 | void chrp_show_cpuinfo(struct seq_file *m) | 97 | static void chrp_show_cpuinfo(struct seq_file *m) |
98 | { | 98 | { |
99 | int i, sdramen; | 99 | int i, sdramen; |
100 | unsigned int t; | 100 | unsigned int t; |
@@ -299,7 +299,7 @@ out_put: | |||
299 | of_node_put(node); | 299 | of_node_put(node); |
300 | } | 300 | } |
301 | 301 | ||
302 | void __init chrp_setup_arch(void) | 302 | static void __init chrp_setup_arch(void) |
303 | { | 303 | { |
304 | struct device_node *root = of_find_node_by_path("/"); | 304 | struct device_node *root = of_find_node_by_path("/"); |
305 | const char *machine = NULL; | 305 | const char *machine = NULL; |
@@ -382,7 +382,7 @@ static void __init chrp_find_openpic(void) | |||
382 | { | 382 | { |
383 | struct device_node *np, *root; | 383 | struct device_node *np, *root; |
384 | int len, i, j; | 384 | int len, i, j; |
385 | int isu_size, idu_size; | 385 | int isu_size; |
386 | const unsigned int *iranges, *opprop = NULL; | 386 | const unsigned int *iranges, *opprop = NULL; |
387 | int oplen = 0; | 387 | int oplen = 0; |
388 | unsigned long opaddr; | 388 | unsigned long opaddr; |
@@ -427,11 +427,9 @@ static void __init chrp_find_openpic(void) | |||
427 | } | 427 | } |
428 | 428 | ||
429 | isu_size = 0; | 429 | isu_size = 0; |
430 | idu_size = 0; | ||
431 | if (len > 0 && iranges[1] != 0) { | 430 | if (len > 0 && iranges[1] != 0) { |
432 | printk(KERN_INFO "OpenPIC irqs %d..%d in IDU\n", | 431 | printk(KERN_INFO "OpenPIC irqs %d..%d in IDU\n", |
433 | iranges[0], iranges[0] + iranges[1] - 1); | 432 | iranges[0], iranges[0] + iranges[1] - 1); |
434 | idu_size = iranges[1]; | ||
435 | } | 433 | } |
436 | if (len > 1) | 434 | if (len > 1) |
437 | isu_size = iranges[3]; | 435 | isu_size = iranges[3]; |
@@ -523,7 +521,7 @@ static void __init chrp_find_8259(void) | |||
523 | } | 521 | } |
524 | } | 522 | } |
525 | 523 | ||
526 | void __init chrp_init_IRQ(void) | 524 | static void __init chrp_init_IRQ(void) |
527 | { | 525 | { |
528 | #if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_XMON) | 526 | #if defined(CONFIG_VT) && defined(CONFIG_INPUT_ADBHID) && defined(CONFIG_XMON) |
529 | struct device_node *kbd; | 527 | struct device_node *kbd; |
@@ -555,7 +553,7 @@ void __init chrp_init_IRQ(void) | |||
555 | #endif | 553 | #endif |
556 | } | 554 | } |
557 | 555 | ||
558 | void __init | 556 | static void __init |
559 | chrp_init2(void) | 557 | chrp_init2(void) |
560 | { | 558 | { |
561 | #ifdef CONFIG_NVRAM | 559 | #ifdef CONFIG_NVRAM |
diff --git a/arch/powerpc/platforms/chrp/time.c b/arch/powerpc/platforms/chrp/time.c index 03d115aaa191..acde7bbe0716 100644 --- a/arch/powerpc/platforms/chrp/time.c +++ b/arch/powerpc/platforms/chrp/time.c | |||
@@ -28,6 +28,8 @@ | |||
28 | #include <asm/sections.h> | 28 | #include <asm/sections.h> |
29 | #include <asm/time.h> | 29 | #include <asm/time.h> |
30 | 30 | ||
31 | #include <platforms/chrp/chrp.h> | ||
32 | |||
31 | extern spinlock_t rtc_lock; | 33 | extern spinlock_t rtc_lock; |
32 | 34 | ||
33 | #define NVRAM_AS0 0x74 | 35 | #define NVRAM_AS0 0x74 |
@@ -63,7 +65,7 @@ long __init chrp_time_init(void) | |||
63 | return 0; | 65 | return 0; |
64 | } | 66 | } |
65 | 67 | ||
66 | int chrp_cmos_clock_read(int addr) | 68 | static int chrp_cmos_clock_read(int addr) |
67 | { | 69 | { |
68 | if (nvram_as1 != 0) | 70 | if (nvram_as1 != 0) |
69 | outb(addr>>8, nvram_as1); | 71 | outb(addr>>8, nvram_as1); |
@@ -71,7 +73,7 @@ int chrp_cmos_clock_read(int addr) | |||
71 | return (inb(nvram_data)); | 73 | return (inb(nvram_data)); |
72 | } | 74 | } |
73 | 75 | ||
74 | void chrp_cmos_clock_write(unsigned long val, int addr) | 76 | static void chrp_cmos_clock_write(unsigned long val, int addr) |
75 | { | 77 | { |
76 | if (nvram_as1 != 0) | 78 | if (nvram_as1 != 0) |
77 | outb(addr>>8, nvram_as1); | 79 | outb(addr>>8, nvram_as1); |
diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig index 9fb2d5912c5a..8ea16db5ff48 100644 --- a/arch/powerpc/platforms/embedded6xx/Kconfig +++ b/arch/powerpc/platforms/embedded6xx/Kconfig | |||
@@ -48,16 +48,6 @@ config PPC_HOLLY | |||
48 | Select PPC_HOLLY if configuring for an IBM 750GX/CL Eval | 48 | Select PPC_HOLLY if configuring for an IBM 750GX/CL Eval |
49 | Board with TSI108/9 bridge (Hickory/Holly) | 49 | Board with TSI108/9 bridge (Hickory/Holly) |
50 | 50 | ||
51 | config PPC_C2K | ||
52 | bool "SBS/GEFanuc C2K board" | ||
53 | depends on EMBEDDED6xx | ||
54 | select MV64X60 | ||
55 | select NOT_COHERENT_CACHE | ||
56 | select MTD_CFI_I4 | ||
57 | help | ||
58 | This option enables support for the GE Fanuc C2K board (formerly | ||
59 | an SBS board). | ||
60 | |||
61 | config MVME5100 | 51 | config MVME5100 |
62 | bool "Motorola/Emerson MVME5100" | 52 | bool "Motorola/Emerson MVME5100" |
63 | depends on EMBEDDED6xx | 53 | depends on EMBEDDED6xx |
diff --git a/arch/powerpc/platforms/embedded6xx/Makefile b/arch/powerpc/platforms/embedded6xx/Makefile index 12154e3257ad..e656ae9f23c6 100644 --- a/arch/powerpc/platforms/embedded6xx/Makefile +++ b/arch/powerpc/platforms/embedded6xx/Makefile | |||
@@ -6,7 +6,6 @@ obj-$(CONFIG_MPC7448HPC2) += mpc7448_hpc2.o | |||
6 | obj-$(CONFIG_LINKSTATION) += linkstation.o ls_uart.o | 6 | obj-$(CONFIG_LINKSTATION) += linkstation.o ls_uart.o |
7 | obj-$(CONFIG_STORCENTER) += storcenter.o | 7 | obj-$(CONFIG_STORCENTER) += storcenter.o |
8 | obj-$(CONFIG_PPC_HOLLY) += holly.o | 8 | obj-$(CONFIG_PPC_HOLLY) += holly.o |
9 | obj-$(CONFIG_PPC_C2K) += c2k.o | ||
10 | obj-$(CONFIG_USBGECKO_UDBG) += usbgecko_udbg.o | 9 | obj-$(CONFIG_USBGECKO_UDBG) += usbgecko_udbg.o |
11 | obj-$(CONFIG_GAMECUBE_COMMON) += flipper-pic.o | 10 | obj-$(CONFIG_GAMECUBE_COMMON) += flipper-pic.o |
12 | obj-$(CONFIG_GAMECUBE) += gamecube.o | 11 | obj-$(CONFIG_GAMECUBE) += gamecube.o |
diff --git a/arch/powerpc/platforms/embedded6xx/c2k.c b/arch/powerpc/platforms/embedded6xx/c2k.c deleted file mode 100644 index d19e4e759597..000000000000 --- a/arch/powerpc/platforms/embedded6xx/c2k.c +++ /dev/null | |||
@@ -1,148 +0,0 @@ | |||
1 | /* | ||
2 | * Board setup routines for the GEFanuc C2K board | ||
3 | * | ||
4 | * Author: Remi Machet <rmachet@slac.stanford.edu> | ||
5 | * | ||
6 | * Originated from prpmc2800.c | ||
7 | * | ||
8 | * 2008 (c) Stanford University | ||
9 | * 2007 (c) MontaVista, Software, Inc. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License version 2 as published | ||
13 | * by the Free Software Foundation. | ||
14 | */ | ||
15 | |||
16 | #include <linux/stddef.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/seq_file.h> | ||
21 | #include <linux/time.h> | ||
22 | #include <linux/of.h> | ||
23 | |||
24 | #include <asm/machdep.h> | ||
25 | #include <asm/prom.h> | ||
26 | #include <asm/time.h> | ||
27 | |||
28 | #include <mm/mmu_decl.h> | ||
29 | |||
30 | #include <sysdev/mv64x60.h> | ||
31 | |||
32 | #define MV64x60_MPP_CNTL_0 0x0000 | ||
33 | #define MV64x60_MPP_CNTL_2 0x0008 | ||
34 | |||
35 | #define MV64x60_GPP_IO_CNTL 0x0000 | ||
36 | #define MV64x60_GPP_LEVEL_CNTL 0x0010 | ||
37 | #define MV64x60_GPP_VALUE_SET 0x0018 | ||
38 | |||
39 | static void __iomem *mv64x60_mpp_reg_base; | ||
40 | static void __iomem *mv64x60_gpp_reg_base; | ||
41 | |||
42 | static void __init c2k_setup_arch(void) | ||
43 | { | ||
44 | struct device_node *np; | ||
45 | phys_addr_t paddr; | ||
46 | const unsigned int *reg; | ||
47 | |||
48 | /* | ||
49 | * ioremap mpp and gpp registers in case they are later | ||
50 | * needed by c2k_reset_board(). | ||
51 | */ | ||
52 | np = of_find_compatible_node(NULL, NULL, "marvell,mv64360-mpp"); | ||
53 | reg = of_get_property(np, "reg", NULL); | ||
54 | paddr = of_translate_address(np, reg); | ||
55 | of_node_put(np); | ||
56 | mv64x60_mpp_reg_base = ioremap(paddr, reg[1]); | ||
57 | |||
58 | np = of_find_compatible_node(NULL, NULL, "marvell,mv64360-gpp"); | ||
59 | reg = of_get_property(np, "reg", NULL); | ||
60 | paddr = of_translate_address(np, reg); | ||
61 | of_node_put(np); | ||
62 | mv64x60_gpp_reg_base = ioremap(paddr, reg[1]); | ||
63 | |||
64 | #ifdef CONFIG_PCI | ||
65 | mv64x60_pci_init(); | ||
66 | #endif | ||
67 | } | ||
68 | |||
69 | static void c2k_reset_board(void) | ||
70 | { | ||
71 | u32 temp; | ||
72 | |||
73 | local_irq_disable(); | ||
74 | |||
75 | temp = in_le32(mv64x60_mpp_reg_base + MV64x60_MPP_CNTL_0); | ||
76 | temp &= 0xFFFF0FFF; | ||
77 | out_le32(mv64x60_mpp_reg_base + MV64x60_MPP_CNTL_0, temp); | ||
78 | |||
79 | temp = in_le32(mv64x60_gpp_reg_base + MV64x60_GPP_LEVEL_CNTL); | ||
80 | temp |= 0x00000004; | ||
81 | out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_LEVEL_CNTL, temp); | ||
82 | |||
83 | temp = in_le32(mv64x60_gpp_reg_base + MV64x60_GPP_IO_CNTL); | ||
84 | temp |= 0x00000004; | ||
85 | out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_IO_CNTL, temp); | ||
86 | |||
87 | temp = in_le32(mv64x60_mpp_reg_base + MV64x60_MPP_CNTL_2); | ||
88 | temp &= 0xFFFF0FFF; | ||
89 | out_le32(mv64x60_mpp_reg_base + MV64x60_MPP_CNTL_2, temp); | ||
90 | |||
91 | temp = in_le32(mv64x60_gpp_reg_base + MV64x60_GPP_LEVEL_CNTL); | ||
92 | temp |= 0x00080000; | ||
93 | out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_LEVEL_CNTL, temp); | ||
94 | |||
95 | temp = in_le32(mv64x60_gpp_reg_base + MV64x60_GPP_IO_CNTL); | ||
96 | temp |= 0x00080000; | ||
97 | out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_IO_CNTL, temp); | ||
98 | |||
99 | out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_VALUE_SET, 0x00080004); | ||
100 | } | ||
101 | |||
102 | static void __noreturn c2k_restart(char *cmd) | ||
103 | { | ||
104 | c2k_reset_board(); | ||
105 | msleep(100); | ||
106 | panic("restart failed\n"); | ||
107 | } | ||
108 | |||
109 | #ifdef CONFIG_NOT_COHERENT_CACHE | ||
110 | #define COHERENCY_SETTING "off" | ||
111 | #else | ||
112 | #define COHERENCY_SETTING "on" | ||
113 | #endif | ||
114 | |||
115 | void c2k_show_cpuinfo(struct seq_file *m) | ||
116 | { | ||
117 | seq_printf(m, "Vendor\t\t: GEFanuc\n"); | ||
118 | seq_printf(m, "coherency\t: %s\n", COHERENCY_SETTING); | ||
119 | } | ||
120 | |||
121 | /* | ||
122 | * Called very early, device-tree isn't unflattened | ||
123 | */ | ||
124 | static int __init c2k_probe(void) | ||
125 | { | ||
126 | if (!of_machine_is_compatible("GEFanuc,C2K")) | ||
127 | return 0; | ||
128 | |||
129 | printk(KERN_INFO "Detected a GEFanuc C2K board\n"); | ||
130 | |||
131 | _set_L2CR(0); | ||
132 | _set_L2CR(L2CR_L2E | L2CR_L2PE | L2CR_L2I); | ||
133 | |||
134 | mv64x60_init_early(); | ||
135 | |||
136 | return 1; | ||
137 | } | ||
138 | |||
139 | define_machine(c2k) { | ||
140 | .name = "C2K", | ||
141 | .probe = c2k_probe, | ||
142 | .setup_arch = c2k_setup_arch, | ||
143 | .show_cpuinfo = c2k_show_cpuinfo, | ||
144 | .init_IRQ = mv64x60_init_irq, | ||
145 | .get_irq = mv64x60_get_irq, | ||
146 | .restart = c2k_restart, | ||
147 | .calibrate_decr = generic_calibrate_decr, | ||
148 | }; | ||
diff --git a/arch/powerpc/platforms/embedded6xx/flipper-pic.c b/arch/powerpc/platforms/embedded6xx/flipper-pic.c index 7206f3f573d4..db0be007fd06 100644 --- a/arch/powerpc/platforms/embedded6xx/flipper-pic.c +++ b/arch/powerpc/platforms/embedded6xx/flipper-pic.c | |||
@@ -108,16 +108,8 @@ static int flipper_pic_map(struct irq_domain *h, unsigned int virq, | |||
108 | return 0; | 108 | return 0; |
109 | } | 109 | } |
110 | 110 | ||
111 | static int flipper_pic_match(struct irq_domain *h, struct device_node *np, | ||
112 | enum irq_domain_bus_token bus_token) | ||
113 | { | ||
114 | return 1; | ||
115 | } | ||
116 | |||
117 | |||
118 | static const struct irq_domain_ops flipper_irq_domain_ops = { | 111 | static const struct irq_domain_ops flipper_irq_domain_ops = { |
119 | .map = flipper_pic_map, | 112 | .map = flipper_pic_map, |
120 | .match = flipper_pic_match, | ||
121 | }; | 113 | }; |
122 | 114 | ||
123 | /* | 115 | /* |
diff --git a/arch/powerpc/platforms/embedded6xx/hlwd-pic.c b/arch/powerpc/platforms/embedded6xx/hlwd-pic.c index 89c54de88b7a..8112b39879d6 100644 --- a/arch/powerpc/platforms/embedded6xx/hlwd-pic.c +++ b/arch/powerpc/platforms/embedded6xx/hlwd-pic.c | |||
@@ -35,6 +35,8 @@ | |||
35 | */ | 35 | */ |
36 | #define HW_BROADWAY_ICR 0x00 | 36 | #define HW_BROADWAY_ICR 0x00 |
37 | #define HW_BROADWAY_IMR 0x04 | 37 | #define HW_BROADWAY_IMR 0x04 |
38 | #define HW_STARLET_ICR 0x08 | ||
39 | #define HW_STARLET_IMR 0x0c | ||
38 | 40 | ||
39 | 41 | ||
40 | /* | 42 | /* |
@@ -74,6 +76,9 @@ static void hlwd_pic_unmask(struct irq_data *d) | |||
74 | void __iomem *io_base = irq_data_get_irq_chip_data(d); | 76 | void __iomem *io_base = irq_data_get_irq_chip_data(d); |
75 | 77 | ||
76 | setbits32(io_base + HW_BROADWAY_IMR, 1 << irq); | 78 | setbits32(io_base + HW_BROADWAY_IMR, 1 << irq); |
79 | |||
80 | /* Make sure the ARM (aka. Starlet) doesn't handle this interrupt. */ | ||
81 | clrbits32(io_base + HW_STARLET_IMR, 1 << irq); | ||
77 | } | 82 | } |
78 | 83 | ||
79 | 84 | ||
@@ -155,7 +160,7 @@ static void __hlwd_quiesce(void __iomem *io_base) | |||
155 | out_be32(io_base + HW_BROADWAY_ICR, 0xffffffff); | 160 | out_be32(io_base + HW_BROADWAY_ICR, 0xffffffff); |
156 | } | 161 | } |
157 | 162 | ||
158 | struct irq_domain *hlwd_pic_init(struct device_node *np) | 163 | static struct irq_domain *hlwd_pic_init(struct device_node *np) |
159 | { | 164 | { |
160 | struct irq_domain *irq_domain; | 165 | struct irq_domain *irq_domain; |
161 | struct resource res; | 166 | struct resource res; |
diff --git a/arch/powerpc/platforms/maple/maple.h b/arch/powerpc/platforms/maple/maple.h index d10f4af3a42e..4f358b55c341 100644 --- a/arch/powerpc/platforms/maple/maple.h +++ b/arch/powerpc/platforms/maple/maple.h | |||
@@ -6,7 +6,7 @@ | |||
6 | */ | 6 | */ |
7 | extern int maple_set_rtc_time(struct rtc_time *tm); | 7 | extern int maple_set_rtc_time(struct rtc_time *tm); |
8 | extern void maple_get_rtc_time(struct rtc_time *tm); | 8 | extern void maple_get_rtc_time(struct rtc_time *tm); |
9 | extern unsigned long maple_get_boot_time(void); | 9 | extern time64_t maple_get_boot_time(void); |
10 | extern void maple_calibrate_decr(void); | 10 | extern void maple_calibrate_decr(void); |
11 | extern void maple_pci_init(void); | 11 | extern void maple_pci_init(void); |
12 | extern void maple_pci_irq_fixup(struct pci_dev *dev); | 12 | extern void maple_pci_irq_fixup(struct pci_dev *dev); |
diff --git a/arch/powerpc/platforms/maple/time.c b/arch/powerpc/platforms/maple/time.c index cfddc87f81bf..becf2ebf7df5 100644 --- a/arch/powerpc/platforms/maple/time.c +++ b/arch/powerpc/platforms/maple/time.c | |||
@@ -137,7 +137,7 @@ static struct resource rtc_iores = { | |||
137 | .flags = IORESOURCE_IO | IORESOURCE_BUSY, | 137 | .flags = IORESOURCE_IO | IORESOURCE_BUSY, |
138 | }; | 138 | }; |
139 | 139 | ||
140 | unsigned long __init maple_get_boot_time(void) | 140 | time64_t __init maple_get_boot_time(void) |
141 | { | 141 | { |
142 | struct rtc_time tm; | 142 | struct rtc_time tm; |
143 | struct device_node *rtcs; | 143 | struct device_node *rtcs; |
@@ -170,7 +170,6 @@ unsigned long __init maple_get_boot_time(void) | |||
170 | request_resource(&ioport_resource, &rtc_iores); | 170 | request_resource(&ioport_resource, &rtc_iores); |
171 | 171 | ||
172 | maple_get_rtc_time(&tm); | 172 | maple_get_rtc_time(&tm); |
173 | return mktime(tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, | 173 | return rtc_tm_to_time64(&tm); |
174 | tm.tm_hour, tm.tm_min, tm.tm_sec); | ||
175 | } | 174 | } |
176 | 175 | ||
diff --git a/arch/powerpc/platforms/pasemi/pasemi.h b/arch/powerpc/platforms/pasemi/pasemi.h index 329d2a619254..70b56048ed1b 100644 --- a/arch/powerpc/platforms/pasemi/pasemi.h +++ b/arch/powerpc/platforms/pasemi/pasemi.h | |||
@@ -2,7 +2,7 @@ | |||
2 | #ifndef _PASEMI_PASEMI_H | 2 | #ifndef _PASEMI_PASEMI_H |
3 | #define _PASEMI_PASEMI_H | 3 | #define _PASEMI_PASEMI_H |
4 | 4 | ||
5 | extern unsigned long pas_get_boot_time(void); | 5 | extern time64_t pas_get_boot_time(void); |
6 | extern void pas_pci_init(void); | 6 | extern void pas_pci_init(void); |
7 | extern void pas_pci_irq_fixup(struct pci_dev *dev); | 7 | extern void pas_pci_irq_fixup(struct pci_dev *dev); |
8 | extern void pas_pci_dma_dev_setup(struct pci_dev *dev); | 8 | extern void pas_pci_dma_dev_setup(struct pci_dev *dev); |
diff --git a/arch/powerpc/platforms/pasemi/pci.c b/arch/powerpc/platforms/pasemi/pci.c index 5ff6108f19e9..aea9ff2c8e6d 100644 --- a/arch/powerpc/platforms/pasemi/pci.c +++ b/arch/powerpc/platforms/pasemi/pci.c | |||
@@ -224,6 +224,8 @@ void __init pas_pci_init(void) | |||
224 | return; | 224 | return; |
225 | } | 225 | } |
226 | 226 | ||
227 | pci_set_flags(PCI_SCAN_ALL_PCIE_DEVS); | ||
228 | |||
227 | for (np = NULL; (np = of_get_next_child(root, np)) != NULL;) | 229 | for (np = NULL; (np = of_get_next_child(root, np)) != NULL;) |
228 | if (np->name && !strcmp(np->name, "pxp") && !pas_add_bridge(np)) | 230 | if (np->name && !strcmp(np->name, "pxp") && !pas_add_bridge(np)) |
229 | of_node_get(np); | 231 | of_node_get(np); |
diff --git a/arch/powerpc/platforms/pasemi/time.c b/arch/powerpc/platforms/pasemi/time.c index fa54351ac268..ea815254ee7b 100644 --- a/arch/powerpc/platforms/pasemi/time.c +++ b/arch/powerpc/platforms/pasemi/time.c | |||
@@ -21,8 +21,8 @@ | |||
21 | 21 | ||
22 | #include <asm/time.h> | 22 | #include <asm/time.h> |
23 | 23 | ||
24 | unsigned long __init pas_get_boot_time(void) | 24 | time64_t __init pas_get_boot_time(void) |
25 | { | 25 | { |
26 | /* Let's just return a fake date right now */ | 26 | /* Let's just return a fake date right now */ |
27 | return mktime(2006, 1, 1, 12, 0, 0); | 27 | return mktime64(2006, 1, 1, 12, 0, 0); |
28 | } | 28 | } |
diff --git a/arch/powerpc/platforms/powermac/bootx_init.c b/arch/powerpc/platforms/powermac/bootx_init.c index c3c9bbb3573a..3b3b0b9b3577 100644 --- a/arch/powerpc/platforms/powermac/bootx_init.c +++ b/arch/powerpc/platforms/powermac/bootx_init.c | |||
@@ -468,7 +468,7 @@ void __init bootx_init(unsigned long r3, unsigned long r4) | |||
468 | boot_infos_t *bi = (boot_infos_t *) r4; | 468 | boot_infos_t *bi = (boot_infos_t *) r4; |
469 | unsigned long hdr; | 469 | unsigned long hdr; |
470 | unsigned long space; | 470 | unsigned long space; |
471 | unsigned long ptr, x; | 471 | unsigned long ptr; |
472 | char *model; | 472 | char *model; |
473 | unsigned long offset = reloc_offset(); | 473 | unsigned long offset = reloc_offset(); |
474 | 474 | ||
@@ -519,7 +519,7 @@ void __init bootx_init(unsigned long r3, unsigned long r4) | |||
519 | ; | 519 | ; |
520 | } | 520 | } |
521 | if (bi->architecture != BOOT_ARCH_PCI) { | 521 | if (bi->architecture != BOOT_ARCH_PCI) { |
522 | bootx_printf(" !!! WARNING - Usupported machine" | 522 | bootx_printf(" !!! WARNING - Unsupported machine" |
523 | " architecture !\n"); | 523 | " architecture !\n"); |
524 | for (;;) | 524 | for (;;) |
525 | ; | 525 | ; |
@@ -562,6 +562,8 @@ void __init bootx_init(unsigned long r3, unsigned long r4) | |||
562 | * MMU switched OFF, so this should not be useful anymore. | 562 | * MMU switched OFF, so this should not be useful anymore. |
563 | */ | 563 | */ |
564 | if (bi->version < 4) { | 564 | if (bi->version < 4) { |
565 | unsigned long x __maybe_unused; | ||
566 | |||
565 | bootx_printf("Touching pages...\n"); | 567 | bootx_printf("Touching pages...\n"); |
566 | 568 | ||
567 | /* | 569 | /* |
diff --git a/arch/powerpc/platforms/powermac/pci.c b/arch/powerpc/platforms/powermac/pci.c index 0b8174a79993..df762bb3c735 100644 --- a/arch/powerpc/platforms/powermac/pci.c +++ b/arch/powerpc/platforms/powermac/pci.c | |||
@@ -62,7 +62,7 @@ struct device_node *k2_skiplist[2]; | |||
62 | 62 | ||
63 | static int __init fixup_one_level_bus_range(struct device_node *node, int higher) | 63 | static int __init fixup_one_level_bus_range(struct device_node *node, int higher) |
64 | { | 64 | { |
65 | for (; node != 0;node = node->sibling) { | 65 | for (; node; node = node->sibling) { |
66 | const int * bus_range; | 66 | const int * bus_range; |
67 | const unsigned int *class_code; | 67 | const unsigned int *class_code; |
68 | int len; | 68 | int len; |
@@ -1219,7 +1219,7 @@ static void fixup_u4_pcie(struct pci_dev* dev) | |||
1219 | region = r; | 1219 | region = r; |
1220 | } | 1220 | } |
1221 | /* Nothing found, bail */ | 1221 | /* Nothing found, bail */ |
1222 | if (region == 0) | 1222 | if (!region) |
1223 | return; | 1223 | return; |
1224 | 1224 | ||
1225 | /* Print things out */ | 1225 | /* Print things out */ |
diff --git a/arch/powerpc/platforms/powermac/pmac.h b/arch/powerpc/platforms/powermac/pmac.h index 6f15b8804e9b..16a52afdb76e 100644 --- a/arch/powerpc/platforms/powermac/pmac.h +++ b/arch/powerpc/platforms/powermac/pmac.h | |||
@@ -15,7 +15,7 @@ struct rtc_time; | |||
15 | extern int pmac_newworld; | 15 | extern int pmac_newworld; |
16 | 16 | ||
17 | extern long pmac_time_init(void); | 17 | extern long pmac_time_init(void); |
18 | extern unsigned long pmac_get_boot_time(void); | 18 | extern time64_t pmac_get_boot_time(void); |
19 | extern void pmac_get_rtc_time(struct rtc_time *); | 19 | extern void pmac_get_rtc_time(struct rtc_time *); |
20 | extern int pmac_set_rtc_time(struct rtc_time *); | 20 | extern int pmac_set_rtc_time(struct rtc_time *); |
21 | extern void pmac_read_rtc_time(void); | 21 | extern void pmac_read_rtc_time(void); |
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index ab668cb72263..3a529fcdae97 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c | |||
@@ -152,7 +152,7 @@ static void pmac_show_cpuinfo(struct seq_file *m) | |||
152 | of_get_property(np, "d-cache-size", NULL); | 152 | of_get_property(np, "d-cache-size", NULL); |
153 | seq_printf(m, "L2 cache\t:"); | 153 | seq_printf(m, "L2 cache\t:"); |
154 | has_l2cache = 1; | 154 | has_l2cache = 1; |
155 | if (of_get_property(np, "cache-unified", NULL) != 0 && dc) { | 155 | if (of_get_property(np, "cache-unified", NULL) && dc) { |
156 | seq_printf(m, " %dK unified", *dc / 1024); | 156 | seq_printf(m, " %dK unified", *dc / 1024); |
157 | } else { | 157 | } else { |
158 | if (ic) | 158 | if (ic) |
@@ -244,12 +244,12 @@ static void __init l2cr_init(void) | |||
244 | /* Checks "l2cr-value" property in the registry */ | 244 | /* Checks "l2cr-value" property in the registry */ |
245 | if (cpu_has_feature(CPU_FTR_L2CR)) { | 245 | if (cpu_has_feature(CPU_FTR_L2CR)) { |
246 | struct device_node *np = of_find_node_by_name(NULL, "cpus"); | 246 | struct device_node *np = of_find_node_by_name(NULL, "cpus"); |
247 | if (np == 0) | 247 | if (!np) |
248 | np = of_find_node_by_type(NULL, "cpu"); | 248 | np = of_find_node_by_type(NULL, "cpu"); |
249 | if (np != 0) { | 249 | if (np) { |
250 | const unsigned int *l2cr = | 250 | const unsigned int *l2cr = |
251 | of_get_property(np, "l2cr-value", NULL); | 251 | of_get_property(np, "l2cr-value", NULL); |
252 | if (l2cr != 0) { | 252 | if (l2cr) { |
253 | ppc_override_l2cr = 1; | 253 | ppc_override_l2cr = 1; |
254 | ppc_override_l2cr_value = *l2cr; | 254 | ppc_override_l2cr_value = *l2cr; |
255 | _set_L2CR(0); | 255 | _set_L2CR(0); |
@@ -352,6 +352,7 @@ static int pmac_late_init(void) | |||
352 | } | 352 | } |
353 | machine_late_initcall(powermac, pmac_late_init); | 353 | machine_late_initcall(powermac, pmac_late_init); |
354 | 354 | ||
355 | void note_bootable_part(dev_t dev, int part, int goodness); | ||
355 | /* | 356 | /* |
356 | * This is __ref because we check for "initializing" before | 357 | * This is __ref because we check for "initializing" before |
357 | * touching any of the __init sensitive things and "initializing" | 358 | * touching any of the __init sensitive things and "initializing" |
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c index 95275e0e2efa..447da6db450a 100644 --- a/arch/powerpc/platforms/powermac/smp.c +++ b/arch/powerpc/platforms/powermac/smp.c | |||
@@ -65,7 +65,6 @@ | |||
65 | #endif | 65 | #endif |
66 | 66 | ||
67 | extern void __secondary_start_pmac_0(void); | 67 | extern void __secondary_start_pmac_0(void); |
68 | extern int pmac_pfunc_base_install(void); | ||
69 | 68 | ||
70 | static void (*pmac_tb_freeze)(int freeze); | 69 | static void (*pmac_tb_freeze)(int freeze); |
71 | static u64 timebase; | 70 | static u64 timebase; |
diff --git a/arch/powerpc/platforms/powermac/time.c b/arch/powerpc/platforms/powermac/time.c index 274af6fa388e..7c968e46736f 100644 --- a/arch/powerpc/platforms/powermac/time.c +++ b/arch/powerpc/platforms/powermac/time.c | |||
@@ -84,29 +84,11 @@ long __init pmac_time_init(void) | |||
84 | return delta; | 84 | return delta; |
85 | } | 85 | } |
86 | 86 | ||
87 | #if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU) | ||
88 | static void to_rtc_time(unsigned long now, struct rtc_time *tm) | ||
89 | { | ||
90 | to_tm(now, tm); | ||
91 | tm->tm_year -= 1900; | ||
92 | tm->tm_mon -= 1; | ||
93 | } | ||
94 | #endif | ||
95 | |||
96 | #if defined(CONFIG_ADB_CUDA) || defined(CONFIG_ADB_PMU) || \ | ||
97 | defined(CONFIG_PMAC_SMU) | ||
98 | static unsigned long from_rtc_time(struct rtc_time *tm) | ||
99 | { | ||
100 | return mktime(tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, | ||
101 | tm->tm_hour, tm->tm_min, tm->tm_sec); | ||
102 | } | ||
103 | #endif | ||
104 | |||
105 | #ifdef CONFIG_ADB_CUDA | 87 | #ifdef CONFIG_ADB_CUDA |
106 | static unsigned long cuda_get_time(void) | 88 | static time64_t cuda_get_time(void) |
107 | { | 89 | { |
108 | struct adb_request req; | 90 | struct adb_request req; |
109 | unsigned int now; | 91 | time64_t now; |
110 | 92 | ||
111 | if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0) | 93 | if (cuda_request(&req, NULL, 2, CUDA_PACKET, CUDA_GET_TIME) < 0) |
112 | return 0; | 94 | return 0; |
@@ -117,17 +99,17 @@ static unsigned long cuda_get_time(void) | |||
117 | req.reply_len); | 99 | req.reply_len); |
118 | now = (req.reply[3] << 24) + (req.reply[4] << 16) | 100 | now = (req.reply[3] << 24) + (req.reply[4] << 16) |
119 | + (req.reply[5] << 8) + req.reply[6]; | 101 | + (req.reply[5] << 8) + req.reply[6]; |
120 | return ((unsigned long)now) - RTC_OFFSET; | 102 | return now - RTC_OFFSET; |
121 | } | 103 | } |
122 | 104 | ||
123 | #define cuda_get_rtc_time(tm) to_rtc_time(cuda_get_time(), (tm)) | 105 | #define cuda_get_rtc_time(tm) rtc_time64_to_tm(cuda_get_time(), (tm)) |
124 | 106 | ||
125 | static int cuda_set_rtc_time(struct rtc_time *tm) | 107 | static int cuda_set_rtc_time(struct rtc_time *tm) |
126 | { | 108 | { |
127 | unsigned int nowtime; | 109 | time64_t nowtime; |
128 | struct adb_request req; | 110 | struct adb_request req; |
129 | 111 | ||
130 | nowtime = from_rtc_time(tm) + RTC_OFFSET; | 112 | nowtime = rtc_tm_to_time64(tm) + RTC_OFFSET; |
131 | if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME, | 113 | if (cuda_request(&req, NULL, 6, CUDA_PACKET, CUDA_SET_TIME, |
132 | nowtime >> 24, nowtime >> 16, nowtime >> 8, | 114 | nowtime >> 24, nowtime >> 16, nowtime >> 8, |
133 | nowtime) < 0) | 115 | nowtime) < 0) |
@@ -147,10 +129,10 @@ static int cuda_set_rtc_time(struct rtc_time *tm) | |||
147 | #endif | 129 | #endif |
148 | 130 | ||
149 | #ifdef CONFIG_ADB_PMU | 131 | #ifdef CONFIG_ADB_PMU |
150 | static unsigned long pmu_get_time(void) | 132 | static time64_t pmu_get_time(void) |
151 | { | 133 | { |
152 | struct adb_request req; | 134 | struct adb_request req; |
153 | unsigned int now; | 135 | time64_t now; |
154 | 136 | ||
155 | if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0) | 137 | if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0) |
156 | return 0; | 138 | return 0; |
@@ -160,17 +142,17 @@ static unsigned long pmu_get_time(void) | |||
160 | req.reply_len); | 142 | req.reply_len); |
161 | now = (req.reply[0] << 24) + (req.reply[1] << 16) | 143 | now = (req.reply[0] << 24) + (req.reply[1] << 16) |
162 | + (req.reply[2] << 8) + req.reply[3]; | 144 | + (req.reply[2] << 8) + req.reply[3]; |
163 | return ((unsigned long)now) - RTC_OFFSET; | 145 | return now - RTC_OFFSET; |
164 | } | 146 | } |
165 | 147 | ||
166 | #define pmu_get_rtc_time(tm) to_rtc_time(pmu_get_time(), (tm)) | 148 | #define pmu_get_rtc_time(tm) rtc_time64_to_tm(pmu_get_time(), (tm)) |
167 | 149 | ||
168 | static int pmu_set_rtc_time(struct rtc_time *tm) | 150 | static int pmu_set_rtc_time(struct rtc_time *tm) |
169 | { | 151 | { |
170 | unsigned int nowtime; | 152 | time64_t nowtime; |
171 | struct adb_request req; | 153 | struct adb_request req; |
172 | 154 | ||
173 | nowtime = from_rtc_time(tm) + RTC_OFFSET; | 155 | nowtime = rtc_tm_to_time64(tm) + RTC_OFFSET; |
174 | if (pmu_request(&req, NULL, 5, PMU_SET_RTC, nowtime >> 24, | 156 | if (pmu_request(&req, NULL, 5, PMU_SET_RTC, nowtime >> 24, |
175 | nowtime >> 16, nowtime >> 8, nowtime) < 0) | 157 | nowtime >> 16, nowtime >> 8, nowtime) < 0) |
176 | return -ENXIO; | 158 | return -ENXIO; |
@@ -188,13 +170,13 @@ static int pmu_set_rtc_time(struct rtc_time *tm) | |||
188 | #endif | 170 | #endif |
189 | 171 | ||
190 | #ifdef CONFIG_PMAC_SMU | 172 | #ifdef CONFIG_PMAC_SMU |
191 | static unsigned long smu_get_time(void) | 173 | static time64_t smu_get_time(void) |
192 | { | 174 | { |
193 | struct rtc_time tm; | 175 | struct rtc_time tm; |
194 | 176 | ||
195 | if (smu_get_rtc_time(&tm, 1)) | 177 | if (smu_get_rtc_time(&tm, 1)) |
196 | return 0; | 178 | return 0; |
197 | return from_rtc_time(&tm); | 179 | return rtc_tm_to_time64(&tm); |
198 | } | 180 | } |
199 | 181 | ||
200 | #else | 182 | #else |
@@ -204,7 +186,7 @@ static unsigned long smu_get_time(void) | |||
204 | #endif | 186 | #endif |
205 | 187 | ||
206 | /* Can't be __init, it's called when suspending and resuming */ | 188 | /* Can't be __init, it's called when suspending and resuming */ |
207 | unsigned long pmac_get_boot_time(void) | 189 | time64_t pmac_get_boot_time(void) |
208 | { | 190 | { |
209 | /* Get the time from the RTC, used only at boot time */ | 191 | /* Get the time from the RTC, used only at boot time */ |
210 | switch (sys_ctrler) { | 192 | switch (sys_ctrler) { |
diff --git a/arch/powerpc/platforms/powernv/copy-paste.h b/arch/powerpc/platforms/powernv/copy-paste.h index c9a503623431..cb36f9fbcef3 100644 --- a/arch/powerpc/platforms/powernv/copy-paste.h +++ b/arch/powerpc/platforms/powernv/copy-paste.h | |||
@@ -7,9 +7,8 @@ | |||
7 | * 2 of the License, or (at your option) any later version. | 7 | * 2 of the License, or (at your option) any later version. |
8 | */ | 8 | */ |
9 | #include <asm/ppc-opcode.h> | 9 | #include <asm/ppc-opcode.h> |
10 | #include <asm/reg.h> | ||
10 | 11 | ||
11 | #define CR0_SHIFT 28 | ||
12 | #define CR0_MASK 0xF | ||
13 | /* | 12 | /* |
14 | * Copy/paste instructions: | 13 | * Copy/paste instructions: |
15 | * | 14 | * |
@@ -42,5 +41,6 @@ static inline int vas_paste(void *paste_address, int offset) | |||
42 | : "b" (offset), "b" (paste_address) | 41 | : "b" (offset), "b" (paste_address) |
43 | : "memory", "cr0"); | 42 | : "memory", "cr0"); |
44 | 43 | ||
45 | return (cr >> CR0_SHIFT) & CR0_MASK; | 44 | /* We mask with 0xE to ignore SO */ |
45 | return (cr >> CR0_SHIFT) & 0xE; | ||
46 | } | 46 | } |
diff --git a/arch/powerpc/platforms/powernv/idle.c b/arch/powerpc/platforms/powernv/idle.c index 1f12ab1e6030..1c5d0675b43c 100644 --- a/arch/powerpc/platforms/powernv/idle.c +++ b/arch/powerpc/platforms/powernv/idle.c | |||
@@ -79,7 +79,7 @@ static int pnv_save_sprs_for_deep_states(void) | |||
79 | uint64_t msr_val = MSR_IDLE; | 79 | uint64_t msr_val = MSR_IDLE; |
80 | uint64_t psscr_val = pnv_deepest_stop_psscr_val; | 80 | uint64_t psscr_val = pnv_deepest_stop_psscr_val; |
81 | 81 | ||
82 | for_each_possible_cpu(cpu) { | 82 | for_each_present_cpu(cpu) { |
83 | uint64_t pir = get_hard_smp_processor_id(cpu); | 83 | uint64_t pir = get_hard_smp_processor_id(cpu); |
84 | uint64_t hsprg0_val = (uint64_t)paca_ptrs[cpu]; | 84 | uint64_t hsprg0_val = (uint64_t)paca_ptrs[cpu]; |
85 | 85 | ||
@@ -814,7 +814,7 @@ static int __init pnv_init_idle_states(void) | |||
814 | int cpu; | 814 | int cpu; |
815 | 815 | ||
816 | pr_info("powernv: idle: Saving PACA pointers of all CPUs in their thread sibling PACA\n"); | 816 | pr_info("powernv: idle: Saving PACA pointers of all CPUs in their thread sibling PACA\n"); |
817 | for_each_possible_cpu(cpu) { | 817 | for_each_present_cpu(cpu) { |
818 | int base_cpu = cpu_first_thread_sibling(cpu); | 818 | int base_cpu = cpu_first_thread_sibling(cpu); |
819 | int idx = cpu_thread_in_core(cpu); | 819 | int idx = cpu_thread_in_core(cpu); |
820 | int i; | 820 | int i; |
diff --git a/arch/powerpc/platforms/powernv/memtrace.c b/arch/powerpc/platforms/powernv/memtrace.c index fc222a0c2ac4..b99283df8584 100644 --- a/arch/powerpc/platforms/powernv/memtrace.c +++ b/arch/powerpc/platforms/powernv/memtrace.c | |||
@@ -131,7 +131,7 @@ static u64 memtrace_alloc_node(u32 nid, u64 size) | |||
131 | u64 start_pfn, end_pfn, nr_pages; | 131 | u64 start_pfn, end_pfn, nr_pages; |
132 | u64 base_pfn; | 132 | u64 base_pfn; |
133 | 133 | ||
134 | if (!NODE_DATA(nid) || !node_spanned_pages(nid)) | 134 | if (!node_spanned_pages(nid)) |
135 | return 0; | 135 | return 0; |
136 | 136 | ||
137 | start_pfn = node_start_pfn(nid); | 137 | start_pfn = node_start_pfn(nid); |
diff --git a/arch/powerpc/platforms/powernv/npu-dma.c b/arch/powerpc/platforms/powernv/npu-dma.c index 525e966dce34..8cdf91f5d3a4 100644 --- a/arch/powerpc/platforms/powernv/npu-dma.c +++ b/arch/powerpc/platforms/powernv/npu-dma.c | |||
@@ -459,10 +459,9 @@ static void mmio_launch_invalidate(struct mmio_atsd_reg *mmio_atsd_reg, | |||
459 | struct npu *npu = mmio_atsd_reg->npu; | 459 | struct npu *npu = mmio_atsd_reg->npu; |
460 | int reg = mmio_atsd_reg->reg; | 460 | int reg = mmio_atsd_reg->reg; |
461 | 461 | ||
462 | __raw_writeq(cpu_to_be64(va), | 462 | __raw_writeq_be(va, npu->mmio_atsd_regs[reg] + XTS_ATSD_AVA); |
463 | npu->mmio_atsd_regs[reg] + XTS_ATSD_AVA); | ||
464 | eieio(); | 463 | eieio(); |
465 | __raw_writeq(cpu_to_be64(launch), npu->mmio_atsd_regs[reg]); | 464 | __raw_writeq_be(launch, npu->mmio_atsd_regs[reg]); |
466 | } | 465 | } |
467 | 466 | ||
468 | static void mmio_invalidate_pid(struct mmio_atsd_reg mmio_atsd_reg[NV_MAX_NPUS], | 467 | static void mmio_invalidate_pid(struct mmio_atsd_reg mmio_atsd_reg[NV_MAX_NPUS], |
diff --git a/arch/powerpc/platforms/powernv/ocxl.c b/arch/powerpc/platforms/powernv/ocxl.c index fa9b53af3c7b..8c65aacda9c8 100644 --- a/arch/powerpc/platforms/powernv/ocxl.c +++ b/arch/powerpc/platforms/powernv/ocxl.c | |||
@@ -475,7 +475,7 @@ void pnv_ocxl_spa_release(void *platform_data) | |||
475 | } | 475 | } |
476 | EXPORT_SYMBOL_GPL(pnv_ocxl_spa_release); | 476 | EXPORT_SYMBOL_GPL(pnv_ocxl_spa_release); |
477 | 477 | ||
478 | int pnv_ocxl_spa_remove_pe(void *platform_data, int pe_handle) | 478 | int pnv_ocxl_spa_remove_pe_from_cache(void *platform_data, int pe_handle) |
479 | { | 479 | { |
480 | struct spa_data *data = (struct spa_data *) platform_data; | 480 | struct spa_data *data = (struct spa_data *) platform_data; |
481 | int rc; | 481 | int rc; |
@@ -483,7 +483,7 @@ int pnv_ocxl_spa_remove_pe(void *platform_data, int pe_handle) | |||
483 | rc = opal_npu_spa_clear_cache(data->phb_opal_id, data->bdfn, pe_handle); | 483 | rc = opal_npu_spa_clear_cache(data->phb_opal_id, data->bdfn, pe_handle); |
484 | return rc; | 484 | return rc; |
485 | } | 485 | } |
486 | EXPORT_SYMBOL_GPL(pnv_ocxl_spa_remove_pe); | 486 | EXPORT_SYMBOL_GPL(pnv_ocxl_spa_remove_pe_from_cache); |
487 | 487 | ||
488 | int pnv_ocxl_alloc_xive_irq(u32 *irq, u64 *trigger_addr) | 488 | int pnv_ocxl_alloc_xive_irq(u32 *irq, u64 *trigger_addr) |
489 | { | 489 | { |
diff --git a/arch/powerpc/platforms/powernv/opal-hmi.c b/arch/powerpc/platforms/powernv/opal-hmi.c index 4efc95b4c7d4..586ec71a4e17 100644 --- a/arch/powerpc/platforms/powernv/opal-hmi.c +++ b/arch/powerpc/platforms/powernv/opal-hmi.c | |||
@@ -177,7 +177,7 @@ static void print_hmi_event_info(struct OpalHMIEvent *hmi_evt) | |||
177 | "Processor recovery occurred for masked error", | 177 | "Processor recovery occurred for masked error", |
178 | "Timer facility experienced an error", | 178 | "Timer facility experienced an error", |
179 | "TFMR SPR is corrupted", | 179 | "TFMR SPR is corrupted", |
180 | "UPS (Uniterrupted Power System) Overflow indication", | 180 | "UPS (Uninterrupted Power System) Overflow indication", |
181 | "An XSCOM operation failure", | 181 | "An XSCOM operation failure", |
182 | "An XSCOM operation completed", | 182 | "An XSCOM operation completed", |
183 | "SCOM has set a reserved FIR bit to cause recovery", | 183 | "SCOM has set a reserved FIR bit to cause recovery", |
diff --git a/arch/powerpc/platforms/powernv/opal-imc.c b/arch/powerpc/platforms/powernv/opal-imc.c index 2a14fda5ea26..58a07948c76e 100644 --- a/arch/powerpc/platforms/powernv/opal-imc.c +++ b/arch/powerpc/platforms/powernv/opal-imc.c | |||
@@ -115,8 +115,10 @@ static int imc_get_mem_addr_nest(struct device_node *node, | |||
115 | return -ENOMEM; | 115 | return -ENOMEM; |
116 | 116 | ||
117 | chipid_arr = kcalloc(nr_chips, sizeof(*chipid_arr), GFP_KERNEL); | 117 | chipid_arr = kcalloc(nr_chips, sizeof(*chipid_arr), GFP_KERNEL); |
118 | if (!chipid_arr) | 118 | if (!chipid_arr) { |
119 | kfree(base_addr_arr); | ||
119 | return -ENOMEM; | 120 | return -ENOMEM; |
121 | } | ||
120 | 122 | ||
121 | if (of_property_read_u32_array(node, "chip-id", chipid_arr, nr_chips)) | 123 | if (of_property_read_u32_array(node, "chip-id", chipid_arr, nr_chips)) |
122 | goto error; | 124 | goto error; |
@@ -143,7 +145,6 @@ static int imc_get_mem_addr_nest(struct device_node *node, | |||
143 | return 0; | 145 | return 0; |
144 | 146 | ||
145 | error: | 147 | error: |
146 | kfree(pmu_ptr->mem_info); | ||
147 | kfree(base_addr_arr); | 148 | kfree(base_addr_arr); |
148 | kfree(chipid_arr); | 149 | kfree(chipid_arr); |
149 | return -1; | 150 | return -1; |
@@ -183,8 +184,14 @@ static int imc_pmu_create(struct device_node *parent, int pmu_index, int domain) | |||
183 | 184 | ||
184 | /* Function to register IMC pmu */ | 185 | /* Function to register IMC pmu */ |
185 | ret = init_imc_pmu(parent, pmu_ptr, pmu_index); | 186 | ret = init_imc_pmu(parent, pmu_ptr, pmu_index); |
186 | if (ret) | 187 | if (ret) { |
187 | pr_err("IMC PMU %s Register failed\n", pmu_ptr->pmu.name); | 188 | pr_err("IMC PMU %s Register failed\n", pmu_ptr->pmu.name); |
189 | kfree(pmu_ptr->pmu.name); | ||
190 | if (pmu_ptr->domain == IMC_DOMAIN_NEST) | ||
191 | kfree(pmu_ptr->mem_info); | ||
192 | kfree(pmu_ptr); | ||
193 | return ret; | ||
194 | } | ||
188 | 195 | ||
189 | return 0; | 196 | return 0; |
190 | 197 | ||
@@ -248,6 +255,7 @@ static int opal_imc_counters_probe(struct platform_device *pdev) | |||
248 | { | 255 | { |
249 | struct device_node *imc_dev = pdev->dev.of_node; | 256 | struct device_node *imc_dev = pdev->dev.of_node; |
250 | int pmu_count = 0, domain; | 257 | int pmu_count = 0, domain; |
258 | bool core_imc_reg = false, thread_imc_reg = false; | ||
251 | u32 type; | 259 | u32 type; |
252 | 260 | ||
253 | /* | 261 | /* |
@@ -285,6 +293,10 @@ static int opal_imc_counters_probe(struct platform_device *pdev) | |||
285 | if (!imc_pmu_create(imc_dev, pmu_count, domain)) { | 293 | if (!imc_pmu_create(imc_dev, pmu_count, domain)) { |
286 | if (domain == IMC_DOMAIN_NEST) | 294 | if (domain == IMC_DOMAIN_NEST) |
287 | pmu_count++; | 295 | pmu_count++; |
296 | if (domain == IMC_DOMAIN_CORE) | ||
297 | core_imc_reg = true; | ||
298 | if (domain == IMC_DOMAIN_THREAD) | ||
299 | thread_imc_reg = true; | ||
288 | } | 300 | } |
289 | } | 301 | } |
290 | 302 | ||
@@ -292,6 +304,10 @@ static int opal_imc_counters_probe(struct platform_device *pdev) | |||
292 | if (pmu_count == 0) | 304 | if (pmu_count == 0) |
293 | debugfs_remove_recursive(imc_debugfs_parent); | 305 | debugfs_remove_recursive(imc_debugfs_parent); |
294 | 306 | ||
307 | /* If core imc is not registered, unregister thread-imc */ | ||
308 | if (!core_imc_reg && thread_imc_reg) | ||
309 | unregister_thread_imc(); | ||
310 | |||
295 | return 0; | 311 | return 0; |
296 | } | 312 | } |
297 | 313 | ||
diff --git a/arch/powerpc/platforms/powernv/opal-irqchip.c b/arch/powerpc/platforms/powernv/opal-irqchip.c index 9d1b8c0aaf93..605c7e5d52c2 100644 --- a/arch/powerpc/platforms/powernv/opal-irqchip.c +++ b/arch/powerpc/platforms/powernv/opal-irqchip.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <linux/kthread.h> | 22 | #include <linux/kthread.h> |
23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/irq_work.h> | ||
26 | 25 | ||
27 | #include <asm/machdep.h> | 26 | #include <asm/machdep.h> |
28 | #include <asm/opal.h> | 27 | #include <asm/opal.h> |
@@ -38,37 +37,47 @@ struct opal_event_irqchip { | |||
38 | unsigned long mask; | 37 | unsigned long mask; |
39 | }; | 38 | }; |
40 | static struct opal_event_irqchip opal_event_irqchip; | 39 | static struct opal_event_irqchip opal_event_irqchip; |
41 | 40 | static u64 last_outstanding_events; | |
42 | static unsigned int opal_irq_count; | 41 | static unsigned int opal_irq_count; |
43 | static unsigned int *opal_irqs; | 42 | static unsigned int *opal_irqs; |
44 | 43 | ||
45 | static void opal_handle_irq_work(struct irq_work *work); | 44 | void opal_handle_events(void) |
46 | static u64 last_outstanding_events; | ||
47 | static struct irq_work opal_event_irq_work = { | ||
48 | .func = opal_handle_irq_work, | ||
49 | }; | ||
50 | |||
51 | void opal_handle_events(uint64_t events) | ||
52 | { | 45 | { |
53 | int virq, hwirq = 0; | 46 | __be64 events = 0; |
54 | u64 mask = opal_event_irqchip.mask; | 47 | u64 e; |
48 | |||
49 | e = READ_ONCE(last_outstanding_events) & opal_event_irqchip.mask; | ||
50 | again: | ||
51 | while (e) { | ||
52 | int virq, hwirq; | ||
53 | |||
54 | hwirq = fls64(e) - 1; | ||
55 | e &= ~BIT_ULL(hwirq); | ||
56 | |||
57 | local_irq_disable(); | ||
58 | virq = irq_find_mapping(opal_event_irqchip.domain, hwirq); | ||
59 | if (virq) { | ||
60 | irq_enter(); | ||
61 | generic_handle_irq(virq); | ||
62 | irq_exit(); | ||
63 | } | ||
64 | local_irq_enable(); | ||
55 | 65 | ||
56 | if (!in_irq() && (events & mask)) { | 66 | cond_resched(); |
57 | last_outstanding_events = events; | ||
58 | irq_work_queue(&opal_event_irq_work); | ||
59 | return; | ||
60 | } | 67 | } |
68 | last_outstanding_events = 0; | ||
69 | if (opal_poll_events(&events) != OPAL_SUCCESS) | ||
70 | return; | ||
71 | e = be64_to_cpu(events) & opal_event_irqchip.mask; | ||
72 | if (e) | ||
73 | goto again; | ||
74 | } | ||
61 | 75 | ||
62 | while (events & mask) { | 76 | bool opal_have_pending_events(void) |
63 | hwirq = fls64(events) - 1; | 77 | { |
64 | if (BIT_ULL(hwirq) & mask) { | 78 | if (last_outstanding_events & opal_event_irqchip.mask) |
65 | virq = irq_find_mapping(opal_event_irqchip.domain, | 79 | return true; |
66 | hwirq); | 80 | return false; |
67 | if (virq) | ||
68 | generic_handle_irq(virq); | ||
69 | } | ||
70 | events &= ~BIT_ULL(hwirq); | ||
71 | } | ||
72 | } | 81 | } |
73 | 82 | ||
74 | static void opal_event_mask(struct irq_data *d) | 83 | static void opal_event_mask(struct irq_data *d) |
@@ -78,24 +87,9 @@ static void opal_event_mask(struct irq_data *d) | |||
78 | 87 | ||
79 | static void opal_event_unmask(struct irq_data *d) | 88 | static void opal_event_unmask(struct irq_data *d) |
80 | { | 89 | { |
81 | __be64 events; | ||
82 | |||
83 | set_bit(d->hwirq, &opal_event_irqchip.mask); | 90 | set_bit(d->hwirq, &opal_event_irqchip.mask); |
84 | 91 | if (opal_have_pending_events()) | |
85 | opal_poll_events(&events); | 92 | opal_wake_poller(); |
86 | last_outstanding_events = be64_to_cpu(events); | ||
87 | |||
88 | /* | ||
89 | * We can't just handle the events now with opal_handle_events(). | ||
90 | * If we did we would deadlock when opal_event_unmask() is called from | ||
91 | * handle_level_irq() with the irq descriptor lock held, because | ||
92 | * calling opal_handle_events() would call generic_handle_irq() and | ||
93 | * then handle_level_irq() which would try to take the descriptor lock | ||
94 | * again. Instead queue the events for later. | ||
95 | */ | ||
96 | if (last_outstanding_events & opal_event_irqchip.mask) | ||
97 | /* Need to retrigger the interrupt */ | ||
98 | irq_work_queue(&opal_event_irq_work); | ||
99 | } | 93 | } |
100 | 94 | ||
101 | static int opal_event_set_type(struct irq_data *d, unsigned int flow_type) | 95 | static int opal_event_set_type(struct irq_data *d, unsigned int flow_type) |
@@ -136,16 +130,13 @@ static irqreturn_t opal_interrupt(int irq, void *data) | |||
136 | __be64 events; | 130 | __be64 events; |
137 | 131 | ||
138 | opal_handle_interrupt(virq_to_hw(irq), &events); | 132 | opal_handle_interrupt(virq_to_hw(irq), &events); |
139 | opal_handle_events(be64_to_cpu(events)); | 133 | last_outstanding_events = be64_to_cpu(events); |
134 | if (opal_have_pending_events()) | ||
135 | opal_wake_poller(); | ||
140 | 136 | ||
141 | return IRQ_HANDLED; | 137 | return IRQ_HANDLED; |
142 | } | 138 | } |
143 | 139 | ||
144 | static void opal_handle_irq_work(struct irq_work *work) | ||
145 | { | ||
146 | opal_handle_events(last_outstanding_events); | ||
147 | } | ||
148 | |||
149 | static int opal_event_match(struct irq_domain *h, struct device_node *node, | 140 | static int opal_event_match(struct irq_domain *h, struct device_node *node, |
150 | enum irq_domain_bus_token bus_token) | 141 | enum irq_domain_bus_token bus_token) |
151 | { | 142 | { |
@@ -177,7 +168,7 @@ void opal_event_shutdown(void) | |||
177 | if (!opal_irqs[i]) | 168 | if (!opal_irqs[i]) |
178 | continue; | 169 | continue; |
179 | 170 | ||
180 | if (in_interrupt()) | 171 | if (in_interrupt() || irqs_disabled()) |
181 | disable_irq_nosync(opal_irqs[i]); | 172 | disable_irq_nosync(opal_irqs[i]); |
182 | else | 173 | else |
183 | free_irq(opal_irqs[i], NULL); | 174 | free_irq(opal_irqs[i], NULL); |
diff --git a/arch/powerpc/platforms/powernv/opal-rtc.c b/arch/powerpc/platforms/powernv/opal-rtc.c index aa2a5139462e..42ec642a3eba 100644 --- a/arch/powerpc/platforms/powernv/opal-rtc.c +++ b/arch/powerpc/platforms/powernv/opal-rtc.c | |||
@@ -34,7 +34,7 @@ static void opal_to_tm(u32 y_m_d, u64 h_m_s_ms, struct rtc_time *tm) | |||
34 | tm->tm_wday = -1; | 34 | tm->tm_wday = -1; |
35 | } | 35 | } |
36 | 36 | ||
37 | unsigned long __init opal_get_boot_time(void) | 37 | time64_t __init opal_get_boot_time(void) |
38 | { | 38 | { |
39 | struct rtc_time tm; | 39 | struct rtc_time tm; |
40 | u32 y_m_d; | 40 | u32 y_m_d; |
@@ -61,8 +61,7 @@ unsigned long __init opal_get_boot_time(void) | |||
61 | y_m_d = be32_to_cpu(__y_m_d); | 61 | y_m_d = be32_to_cpu(__y_m_d); |
62 | h_m_s_ms = be64_to_cpu(__h_m_s_ms); | 62 | h_m_s_ms = be64_to_cpu(__h_m_s_ms); |
63 | opal_to_tm(y_m_d, h_m_s_ms, &tm); | 63 | opal_to_tm(y_m_d, h_m_s_ms, &tm); |
64 | return mktime(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, | 64 | return rtc_tm_to_time64(&tm); |
65 | tm.tm_hour, tm.tm_min, tm.tm_sec); | ||
66 | } | 65 | } |
67 | 66 | ||
68 | static __init int opal_time_init(void) | 67 | static __init int opal_time_init(void) |
diff --git a/arch/powerpc/platforms/powernv/opal-sensor.c b/arch/powerpc/platforms/powernv/opal-sensor.c index 0a7074bb91dc..35a5f4b9aeb5 100644 --- a/arch/powerpc/platforms/powernv/opal-sensor.c +++ b/arch/powerpc/platforms/powernv/opal-sensor.c | |||
@@ -72,6 +72,59 @@ out: | |||
72 | } | 72 | } |
73 | EXPORT_SYMBOL_GPL(opal_get_sensor_data); | 73 | EXPORT_SYMBOL_GPL(opal_get_sensor_data); |
74 | 74 | ||
75 | int opal_get_sensor_data_u64(u32 sensor_hndl, u64 *sensor_data) | ||
76 | { | ||
77 | int ret, token; | ||
78 | struct opal_msg msg; | ||
79 | __be64 data; | ||
80 | |||
81 | if (!opal_check_token(OPAL_SENSOR_READ_U64)) { | ||
82 | u32 sdata; | ||
83 | |||
84 | ret = opal_get_sensor_data(sensor_hndl, &sdata); | ||
85 | if (!ret) | ||
86 | *sensor_data = sdata; | ||
87 | return ret; | ||
88 | } | ||
89 | |||
90 | token = opal_async_get_token_interruptible(); | ||
91 | if (token < 0) | ||
92 | return token; | ||
93 | |||
94 | ret = opal_sensor_read_u64(sensor_hndl, token, &data); | ||
95 | switch (ret) { | ||
96 | case OPAL_ASYNC_COMPLETION: | ||
97 | ret = opal_async_wait_response(token, &msg); | ||
98 | if (ret) { | ||
99 | pr_err("%s: Failed to wait for the async response, %d\n", | ||
100 | __func__, ret); | ||
101 | goto out_token; | ||
102 | } | ||
103 | |||
104 | ret = opal_error_code(opal_get_async_rc(msg)); | ||
105 | *sensor_data = be64_to_cpu(data); | ||
106 | break; | ||
107 | |||
108 | case OPAL_SUCCESS: | ||
109 | ret = 0; | ||
110 | *sensor_data = be64_to_cpu(data); | ||
111 | break; | ||
112 | |||
113 | case OPAL_WRONG_STATE: | ||
114 | ret = -EIO; | ||
115 | break; | ||
116 | |||
117 | default: | ||
118 | ret = opal_error_code(ret); | ||
119 | break; | ||
120 | } | ||
121 | |||
122 | out_token: | ||
123 | opal_async_release_token(token); | ||
124 | return ret; | ||
125 | } | ||
126 | EXPORT_SYMBOL_GPL(opal_get_sensor_data_u64); | ||
127 | |||
75 | int __init opal_sensor_init(void) | 128 | int __init opal_sensor_init(void) |
76 | { | 129 | { |
77 | struct platform_device *pdev; | 130 | struct platform_device *pdev; |
diff --git a/arch/powerpc/platforms/powernv/opal-wrappers.S b/arch/powerpc/platforms/powernv/opal-wrappers.S index 3da30c2f26b4..a8d9b4089c31 100644 --- a/arch/powerpc/platforms/powernv/opal-wrappers.S +++ b/arch/powerpc/platforms/powernv/opal-wrappers.S | |||
@@ -320,8 +320,10 @@ OPAL_CALL(opal_set_powercap, OPAL_SET_POWERCAP); | |||
320 | OPAL_CALL(opal_get_power_shift_ratio, OPAL_GET_POWER_SHIFT_RATIO); | 320 | OPAL_CALL(opal_get_power_shift_ratio, OPAL_GET_POWER_SHIFT_RATIO); |
321 | OPAL_CALL(opal_set_power_shift_ratio, OPAL_SET_POWER_SHIFT_RATIO); | 321 | OPAL_CALL(opal_set_power_shift_ratio, OPAL_SET_POWER_SHIFT_RATIO); |
322 | OPAL_CALL(opal_sensor_group_clear, OPAL_SENSOR_GROUP_CLEAR); | 322 | OPAL_CALL(opal_sensor_group_clear, OPAL_SENSOR_GROUP_CLEAR); |
323 | OPAL_CALL(opal_quiesce, OPAL_QUIESCE); | ||
323 | OPAL_CALL(opal_npu_spa_setup, OPAL_NPU_SPA_SETUP); | 324 | OPAL_CALL(opal_npu_spa_setup, OPAL_NPU_SPA_SETUP); |
324 | OPAL_CALL(opal_npu_spa_clear_cache, OPAL_NPU_SPA_CLEAR_CACHE); | 325 | OPAL_CALL(opal_npu_spa_clear_cache, OPAL_NPU_SPA_CLEAR_CACHE); |
325 | OPAL_CALL(opal_npu_tl_set, OPAL_NPU_TL_SET); | 326 | OPAL_CALL(opal_npu_tl_set, OPAL_NPU_TL_SET); |
326 | OPAL_CALL(opal_pci_get_pbcq_tunnel_bar, OPAL_PCI_GET_PBCQ_TUNNEL_BAR); | 327 | OPAL_CALL(opal_pci_get_pbcq_tunnel_bar, OPAL_PCI_GET_PBCQ_TUNNEL_BAR); |
327 | OPAL_CALL(opal_pci_set_pbcq_tunnel_bar, OPAL_PCI_SET_PBCQ_TUNNEL_BAR); | 328 | OPAL_CALL(opal_pci_set_pbcq_tunnel_bar, OPAL_PCI_SET_PBCQ_TUNNEL_BAR); |
329 | OPAL_CALL(opal_sensor_read_u64, OPAL_SENSOR_READ_U64); | ||
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c index 48fbb41af5d1..0d539c661748 100644 --- a/arch/powerpc/platforms/powernv/opal.c +++ b/arch/powerpc/platforms/powernv/opal.c | |||
@@ -540,21 +540,15 @@ int opal_hmi_exception_early(struct pt_regs *regs) | |||
540 | /* HMI exception handler called in virtual mode during check_irq_replay. */ | 540 | /* HMI exception handler called in virtual mode during check_irq_replay. */ |
541 | int opal_handle_hmi_exception(struct pt_regs *regs) | 541 | int opal_handle_hmi_exception(struct pt_regs *regs) |
542 | { | 542 | { |
543 | s64 rc; | ||
544 | __be64 evt = 0; | ||
545 | |||
546 | /* | 543 | /* |
547 | * Check if HMI event is available. | 544 | * Check if HMI event is available. |
548 | * if Yes, then call opal_poll_events to pull opal messages and | 545 | * if Yes, then wake kopald to process them. |
549 | * process them. | ||
550 | */ | 546 | */ |
551 | if (!local_paca->hmi_event_available) | 547 | if (!local_paca->hmi_event_available) |
552 | return 0; | 548 | return 0; |
553 | 549 | ||
554 | local_paca->hmi_event_available = 0; | 550 | local_paca->hmi_event_available = 0; |
555 | rc = opal_poll_events(&evt); | 551 | opal_wake_poller(); |
556 | if (rc == OPAL_SUCCESS && evt) | ||
557 | opal_handle_events(be64_to_cpu(evt)); | ||
558 | 552 | ||
559 | return 1; | 553 | return 1; |
560 | } | 554 | } |
@@ -757,14 +751,19 @@ static void __init opal_imc_init_dev(void) | |||
757 | static int kopald(void *unused) | 751 | static int kopald(void *unused) |
758 | { | 752 | { |
759 | unsigned long timeout = msecs_to_jiffies(opal_heartbeat) + 1; | 753 | unsigned long timeout = msecs_to_jiffies(opal_heartbeat) + 1; |
760 | __be64 events; | ||
761 | 754 | ||
762 | set_freezable(); | 755 | set_freezable(); |
763 | do { | 756 | do { |
764 | try_to_freeze(); | 757 | try_to_freeze(); |
765 | opal_poll_events(&events); | 758 | |
766 | opal_handle_events(be64_to_cpu(events)); | 759 | opal_handle_events(); |
767 | schedule_timeout_interruptible(timeout); | 760 | |
761 | set_current_state(TASK_INTERRUPTIBLE); | ||
762 | if (opal_have_pending_events()) | ||
763 | __set_current_state(TASK_RUNNING); | ||
764 | else | ||
765 | schedule_timeout(timeout); | ||
766 | |||
768 | } while (!kthread_should_stop()); | 767 | } while (!kthread_should_stop()); |
769 | 768 | ||
770 | return 0; | 769 | return 0; |
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 3f9c69d7623a..5bd0eb6681bc 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c | |||
@@ -1976,9 +1976,10 @@ static void pnv_pci_p7ioc_tce_invalidate(struct iommu_table *tbl, | |||
1976 | mb(); /* Ensure above stores are visible */ | 1976 | mb(); /* Ensure above stores are visible */ |
1977 | while (start <= end) { | 1977 | while (start <= end) { |
1978 | if (rm) | 1978 | if (rm) |
1979 | __raw_rm_writeq(cpu_to_be64(start), invalidate); | 1979 | __raw_rm_writeq_be(start, invalidate); |
1980 | else | 1980 | else |
1981 | __raw_writeq(cpu_to_be64(start), invalidate); | 1981 | __raw_writeq_be(start, invalidate); |
1982 | |||
1982 | start += inc; | 1983 | start += inc; |
1983 | } | 1984 | } |
1984 | 1985 | ||
@@ -2055,9 +2056,9 @@ static void pnv_pci_phb3_tce_invalidate_entire(struct pnv_phb *phb, bool rm) | |||
2055 | 2056 | ||
2056 | mb(); /* Ensure previous TCE table stores are visible */ | 2057 | mb(); /* Ensure previous TCE table stores are visible */ |
2057 | if (rm) | 2058 | if (rm) |
2058 | __raw_rm_writeq(cpu_to_be64(val), invalidate); | 2059 | __raw_rm_writeq_be(val, invalidate); |
2059 | else | 2060 | else |
2060 | __raw_writeq(cpu_to_be64(val), invalidate); | 2061 | __raw_writeq_be(val, invalidate); |
2061 | } | 2062 | } |
2062 | 2063 | ||
2063 | static inline void pnv_pci_phb3_tce_invalidate_pe(struct pnv_ioda_pe *pe) | 2064 | static inline void pnv_pci_phb3_tce_invalidate_pe(struct pnv_ioda_pe *pe) |
@@ -2067,7 +2068,7 @@ static inline void pnv_pci_phb3_tce_invalidate_pe(struct pnv_ioda_pe *pe) | |||
2067 | unsigned long val = PHB3_TCE_KILL_INVAL_PE | (pe->pe_number & 0xFF); | 2068 | unsigned long val = PHB3_TCE_KILL_INVAL_PE | (pe->pe_number & 0xFF); |
2068 | 2069 | ||
2069 | mb(); /* Ensure above stores are visible */ | 2070 | mb(); /* Ensure above stores are visible */ |
2070 | __raw_writeq(cpu_to_be64(val), invalidate); | 2071 | __raw_writeq_be(val, invalidate); |
2071 | } | 2072 | } |
2072 | 2073 | ||
2073 | static void pnv_pci_phb3_tce_invalidate(struct pnv_ioda_pe *pe, bool rm, | 2074 | static void pnv_pci_phb3_tce_invalidate(struct pnv_ioda_pe *pe, bool rm, |
@@ -2090,9 +2091,9 @@ static void pnv_pci_phb3_tce_invalidate(struct pnv_ioda_pe *pe, bool rm, | |||
2090 | 2091 | ||
2091 | while (start <= end) { | 2092 | while (start <= end) { |
2092 | if (rm) | 2093 | if (rm) |
2093 | __raw_rm_writeq(cpu_to_be64(start), invalidate); | 2094 | __raw_rm_writeq_be(start, invalidate); |
2094 | else | 2095 | else |
2095 | __raw_writeq(cpu_to_be64(start), invalidate); | 2096 | __raw_writeq_be(start, invalidate); |
2096 | start += inc; | 2097 | start += inc; |
2097 | } | 2098 | } |
2098 | } | 2099 | } |
@@ -2910,6 +2911,34 @@ static void pnv_pci_ioda2_table_free_pages(struct iommu_table *tbl) | |||
2910 | tbl->it_indirect_levels); | 2911 | tbl->it_indirect_levels); |
2911 | } | 2912 | } |
2912 | 2913 | ||
2914 | static unsigned long pnv_ioda_parse_tce_sizes(struct pnv_phb *phb) | ||
2915 | { | ||
2916 | struct pci_controller *hose = phb->hose; | ||
2917 | struct device_node *dn = hose->dn; | ||
2918 | unsigned long mask = 0; | ||
2919 | int i, rc, count; | ||
2920 | u32 val; | ||
2921 | |||
2922 | count = of_property_count_u32_elems(dn, "ibm,supported-tce-sizes"); | ||
2923 | if (count <= 0) { | ||
2924 | mask = SZ_4K | SZ_64K; | ||
2925 | /* Add 16M for POWER8 by default */ | ||
2926 | if (cpu_has_feature(CPU_FTR_ARCH_207S) && | ||
2927 | !cpu_has_feature(CPU_FTR_ARCH_300)) | ||
2928 | mask |= SZ_16M; | ||
2929 | return mask; | ||
2930 | } | ||
2931 | |||
2932 | for (i = 0; i < count; i++) { | ||
2933 | rc = of_property_read_u32_index(dn, "ibm,supported-tce-sizes", | ||
2934 | i, &val); | ||
2935 | if (rc == 0) | ||
2936 | mask |= 1ULL << val; | ||
2937 | } | ||
2938 | |||
2939 | return mask; | ||
2940 | } | ||
2941 | |||
2913 | static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb, | 2942 | static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb, |
2914 | struct pnv_ioda_pe *pe) | 2943 | struct pnv_ioda_pe *pe) |
2915 | { | 2944 | { |
@@ -2934,7 +2963,7 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb, | |||
2934 | pe->table_group.max_dynamic_windows_supported = | 2963 | pe->table_group.max_dynamic_windows_supported = |
2935 | IOMMU_TABLE_GROUP_MAX_TABLES; | 2964 | IOMMU_TABLE_GROUP_MAX_TABLES; |
2936 | pe->table_group.max_levels = POWERNV_IOMMU_MAX_LEVELS; | 2965 | pe->table_group.max_levels = POWERNV_IOMMU_MAX_LEVELS; |
2937 | pe->table_group.pgsizes = SZ_4K | SZ_64K | SZ_16M; | 2966 | pe->table_group.pgsizes = pnv_ioda_parse_tce_sizes(phb); |
2938 | #ifdef CONFIG_IOMMU_API | 2967 | #ifdef CONFIG_IOMMU_API |
2939 | pe->table_group.ops = &pnv_pci_ioda2_ops; | 2968 | pe->table_group.ops = &pnv_pci_ioda2_ops; |
2940 | #endif | 2969 | #endif |
@@ -3642,7 +3671,6 @@ static void pnv_pci_ioda2_release_pe_dma(struct pnv_ioda_pe *pe) | |||
3642 | WARN_ON(pe->table_group.group); | 3671 | WARN_ON(pe->table_group.group); |
3643 | } | 3672 | } |
3644 | 3673 | ||
3645 | pnv_pci_ioda2_table_free_pages(tbl); | ||
3646 | iommu_tce_table_put(tbl); | 3674 | iommu_tce_table_put(tbl); |
3647 | } | 3675 | } |
3648 | 3676 | ||
diff --git a/arch/powerpc/platforms/powernv/powernv.h b/arch/powerpc/platforms/powernv/powernv.h index 94f17ab1374b..fd4a1c5a6369 100644 --- a/arch/powerpc/platforms/powernv/powernv.h +++ b/arch/powerpc/platforms/powernv/powernv.h | |||
@@ -24,7 +24,8 @@ extern u32 pnv_get_supported_cpuidle_states(void); | |||
24 | 24 | ||
25 | extern void pnv_lpc_init(void); | 25 | extern void pnv_lpc_init(void); |
26 | 26 | ||
27 | extern void opal_handle_events(uint64_t events); | 27 | extern void opal_handle_events(void); |
28 | extern bool opal_have_pending_events(void); | ||
28 | extern void opal_event_shutdown(void); | 29 | extern void opal_event_shutdown(void); |
29 | 30 | ||
30 | bool cpu_core_split_required(void); | 31 | bool cpu_core_split_required(void); |
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c index a6648ec99ca7..f96df0a25d05 100644 --- a/arch/powerpc/platforms/powernv/setup.c +++ b/arch/powerpc/platforms/powernv/setup.c | |||
@@ -124,6 +124,7 @@ static void pnv_setup_rfi_flush(void) | |||
124 | security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV)); | 124 | security_ftr_enabled(SEC_FTR_L1D_FLUSH_HV)); |
125 | 125 | ||
126 | setup_rfi_flush(type, enable); | 126 | setup_rfi_flush(type, enable); |
127 | setup_barrier_nospec(); | ||
127 | } | 128 | } |
128 | 129 | ||
129 | static void __init pnv_setup_arch(void) | 130 | static void __init pnv_setup_arch(void) |
@@ -357,15 +358,7 @@ static void pnv_kexec_cpu_down(int crash_shutdown, int secondary) | |||
357 | #ifdef CONFIG_MEMORY_HOTPLUG_SPARSE | 358 | #ifdef CONFIG_MEMORY_HOTPLUG_SPARSE |
358 | static unsigned long pnv_memory_block_size(void) | 359 | static unsigned long pnv_memory_block_size(void) |
359 | { | 360 | { |
360 | /* | 361 | return 256UL * 1024 * 1024; |
361 | * We map the kernel linear region with 1GB large pages on radix. For | ||
362 | * memory hot unplug to work our memory block size must be at least | ||
363 | * this size. | ||
364 | */ | ||
365 | if (radix_enabled()) | ||
366 | return 1UL * 1024 * 1024 * 1024; | ||
367 | else | ||
368 | return 256UL * 1024 * 1024; | ||
369 | } | 362 | } |
370 | #endif | 363 | #endif |
371 | 364 | ||
diff --git a/arch/powerpc/platforms/powernv/smp.c b/arch/powerpc/platforms/powernv/smp.c index 19af6de6b6f0..b80909957792 100644 --- a/arch/powerpc/platforms/powernv/smp.c +++ b/arch/powerpc/platforms/powernv/smp.c | |||
@@ -334,7 +334,16 @@ static int pnv_cause_nmi_ipi(int cpu) | |||
334 | int64_t rc; | 334 | int64_t rc; |
335 | 335 | ||
336 | if (cpu >= 0) { | 336 | if (cpu >= 0) { |
337 | rc = opal_signal_system_reset(get_hard_smp_processor_id(cpu)); | 337 | int h = get_hard_smp_processor_id(cpu); |
338 | |||
339 | if (opal_check_token(OPAL_QUIESCE)) | ||
340 | opal_quiesce(QUIESCE_HOLD, h); | ||
341 | |||
342 | rc = opal_signal_system_reset(h); | ||
343 | |||
344 | if (opal_check_token(OPAL_QUIESCE)) | ||
345 | opal_quiesce(QUIESCE_RESUME, h); | ||
346 | |||
338 | if (rc != OPAL_SUCCESS) | 347 | if (rc != OPAL_SUCCESS) |
339 | return 0; | 348 | return 0; |
340 | return 1; | 349 | return 1; |
@@ -343,6 +352,8 @@ static int pnv_cause_nmi_ipi(int cpu) | |||
343 | bool success = true; | 352 | bool success = true; |
344 | int c; | 353 | int c; |
345 | 354 | ||
355 | if (opal_check_token(OPAL_QUIESCE)) | ||
356 | opal_quiesce(QUIESCE_HOLD, -1); | ||
346 | 357 | ||
347 | /* | 358 | /* |
348 | * We do not use broadcasts (yet), because it's not clear | 359 | * We do not use broadcasts (yet), because it's not clear |
@@ -358,6 +369,10 @@ static int pnv_cause_nmi_ipi(int cpu) | |||
358 | if (rc != OPAL_SUCCESS) | 369 | if (rc != OPAL_SUCCESS) |
359 | success = false; | 370 | success = false; |
360 | } | 371 | } |
372 | |||
373 | if (opal_check_token(OPAL_QUIESCE)) | ||
374 | opal_quiesce(QUIESCE_RESUME, -1); | ||
375 | |||
361 | if (success) | 376 | if (success) |
362 | return 1; | 377 | return 1; |
363 | 378 | ||
diff --git a/arch/powerpc/platforms/ps3/platform.h b/arch/powerpc/platforms/ps3/platform.h index 1809cfc562ee..9bc68f913466 100644 --- a/arch/powerpc/platforms/ps3/platform.h +++ b/arch/powerpc/platforms/ps3/platform.h | |||
@@ -57,7 +57,7 @@ static inline void ps3_smp_cleanup_cpu(int cpu) { } | |||
57 | /* time */ | 57 | /* time */ |
58 | 58 | ||
59 | void __init ps3_calibrate_decr(void); | 59 | void __init ps3_calibrate_decr(void); |
60 | unsigned long __init ps3_get_boot_time(void); | 60 | time64_t __init ps3_get_boot_time(void); |
61 | void ps3_get_rtc_time(struct rtc_time *time); | 61 | void ps3_get_rtc_time(struct rtc_time *time); |
62 | int ps3_set_rtc_time(struct rtc_time *time); | 62 | int ps3_set_rtc_time(struct rtc_time *time); |
63 | 63 | ||
diff --git a/arch/powerpc/platforms/ps3/repository.c b/arch/powerpc/platforms/ps3/repository.c index 50dbaf24b1ee..e49c887787c4 100644 --- a/arch/powerpc/platforms/ps3/repository.c +++ b/arch/powerpc/platforms/ps3/repository.c | |||
@@ -101,9 +101,9 @@ static u64 make_first_field(const char *text, u64 index) | |||
101 | 101 | ||
102 | static u64 make_field(const char *text, u64 index) | 102 | static u64 make_field(const char *text, u64 index) |
103 | { | 103 | { |
104 | u64 n; | 104 | u64 n = 0; |
105 | 105 | ||
106 | strncpy((char *)&n, text, 8); | 106 | memcpy((char *)&n, text, strnlen(text, sizeof(n))); |
107 | return n + index; | 107 | return n + index; |
108 | } | 108 | } |
109 | 109 | ||
diff --git a/arch/powerpc/platforms/ps3/time.c b/arch/powerpc/platforms/ps3/time.c index 11b45b58c81b..08ca76e23d09 100644 --- a/arch/powerpc/platforms/ps3/time.c +++ b/arch/powerpc/platforms/ps3/time.c | |||
@@ -28,30 +28,6 @@ | |||
28 | 28 | ||
29 | #include "platform.h" | 29 | #include "platform.h" |
30 | 30 | ||
31 | #define dump_tm(_a) _dump_tm(_a, __func__, __LINE__) | ||
32 | static void _dump_tm(const struct rtc_time *tm, const char* func, int line) | ||
33 | { | ||
34 | pr_debug("%s:%d tm_sec %d\n", func, line, tm->tm_sec); | ||
35 | pr_debug("%s:%d tm_min %d\n", func, line, tm->tm_min); | ||
36 | pr_debug("%s:%d tm_hour %d\n", func, line, tm->tm_hour); | ||
37 | pr_debug("%s:%d tm_mday %d\n", func, line, tm->tm_mday); | ||
38 | pr_debug("%s:%d tm_mon %d\n", func, line, tm->tm_mon); | ||
39 | pr_debug("%s:%d tm_year %d\n", func, line, tm->tm_year); | ||
40 | pr_debug("%s:%d tm_wday %d\n", func, line, tm->tm_wday); | ||
41 | } | ||
42 | |||
43 | #define dump_time(_a) _dump_time(_a, __func__, __LINE__) | ||
44 | static void __maybe_unused _dump_time(int time, const char *func, | ||
45 | int line) | ||
46 | { | ||
47 | struct rtc_time tm; | ||
48 | |||
49 | to_tm(time, &tm); | ||
50 | |||
51 | pr_debug("%s:%d time %d\n", func, line, time); | ||
52 | _dump_tm(&tm, func, line); | ||
53 | } | ||
54 | |||
55 | void __init ps3_calibrate_decr(void) | 31 | void __init ps3_calibrate_decr(void) |
56 | { | 32 | { |
57 | int result; | 33 | int result; |
@@ -76,7 +52,7 @@ static u64 read_rtc(void) | |||
76 | return rtc_val; | 52 | return rtc_val; |
77 | } | 53 | } |
78 | 54 | ||
79 | unsigned long __init ps3_get_boot_time(void) | 55 | time64_t __init ps3_get_boot_time(void) |
80 | { | 56 | { |
81 | return read_rtc() + ps3_os_area_get_rtc_diff(); | 57 | return read_rtc() + ps3_os_area_get_rtc_diff(); |
82 | } | 58 | } |
diff --git a/arch/powerpc/platforms/pseries/hvCall_inst.c b/arch/powerpc/platforms/pseries/hvCall_inst.c index 89b7ce807e70..6da320c786cd 100644 --- a/arch/powerpc/platforms/pseries/hvCall_inst.c +++ b/arch/powerpc/platforms/pseries/hvCall_inst.c | |||
@@ -125,7 +125,7 @@ static void probe_hcall_entry(void *ignored, unsigned long opcode, unsigned long | |||
125 | h->purr_start = mfspr(SPRN_PURR); | 125 | h->purr_start = mfspr(SPRN_PURR); |
126 | } | 126 | } |
127 | 127 | ||
128 | static void probe_hcall_exit(void *ignored, unsigned long opcode, unsigned long retval, | 128 | static void probe_hcall_exit(void *ignored, unsigned long opcode, long retval, |
129 | unsigned long *retbuf) | 129 | unsigned long *retbuf) |
130 | { | 130 | { |
131 | struct hcall_stats *h; | 131 | struct hcall_stats *h; |
diff --git a/arch/powerpc/platforms/pseries/kexec.c b/arch/powerpc/platforms/pseries/kexec.c index 3fe126796975..46fbaef69a59 100644 --- a/arch/powerpc/platforms/pseries/kexec.c +++ b/arch/powerpc/platforms/pseries/kexec.c | |||
@@ -57,8 +57,11 @@ void pseries_kexec_cpu_down(int crash_shutdown, int secondary) | |||
57 | } | 57 | } |
58 | } | 58 | } |
59 | 59 | ||
60 | if (xive_enabled()) | 60 | if (xive_enabled()) { |
61 | xive_kexec_teardown_cpu(secondary); | 61 | xive_kexec_teardown_cpu(secondary); |
62 | else | 62 | |
63 | if (!secondary) | ||
64 | xive_shutdown(); | ||
65 | } else | ||
63 | xics_kexec_teardown_cpu(secondary); | 66 | xics_kexec_teardown_cpu(secondary); |
64 | } | 67 | } |
diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index adb996ed51e1..5a392e40f3d2 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c | |||
@@ -902,8 +902,7 @@ out: | |||
902 | local_irq_restore(flags); | 902 | local_irq_restore(flags); |
903 | } | 903 | } |
904 | 904 | ||
905 | void __trace_hcall_exit(long opcode, unsigned long retval, | 905 | void __trace_hcall_exit(long opcode, long retval, unsigned long *retbuf) |
906 | unsigned long *retbuf) | ||
907 | { | 906 | { |
908 | unsigned long flags; | 907 | unsigned long flags; |
909 | unsigned int *depth; | 908 | unsigned int *depth; |
diff --git a/arch/powerpc/platforms/pseries/lparcfg.c b/arch/powerpc/platforms/pseries/lparcfg.c index c508c938dc71..7c872dc01bdb 100644 --- a/arch/powerpc/platforms/pseries/lparcfg.c +++ b/arch/powerpc/platforms/pseries/lparcfg.c | |||
@@ -52,18 +52,20 @@ | |||
52 | * Track sum of all purrs across all processors. This is used to further | 52 | * Track sum of all purrs across all processors. This is used to further |
53 | * calculate usage values by different applications | 53 | * calculate usage values by different applications |
54 | */ | 54 | */ |
55 | static void cpu_get_purr(void *arg) | ||
56 | { | ||
57 | atomic64_t *sum = arg; | ||
58 | |||
59 | atomic64_add(mfspr(SPRN_PURR), sum); | ||
60 | } | ||
61 | |||
55 | static unsigned long get_purr(void) | 62 | static unsigned long get_purr(void) |
56 | { | 63 | { |
57 | unsigned long sum_purr = 0; | 64 | atomic64_t purr = ATOMIC64_INIT(0); |
58 | int cpu; | ||
59 | 65 | ||
60 | for_each_possible_cpu(cpu) { | 66 | on_each_cpu(cpu_get_purr, &purr, 1); |
61 | struct cpu_usage *cu; | ||
62 | 67 | ||
63 | cu = &per_cpu(cpu_usage_array, cpu); | 68 | return atomic64_read(&purr); |
64 | sum_purr += cu->current_tb; | ||
65 | } | ||
66 | return sum_purr; | ||
67 | } | 69 | } |
68 | 70 | ||
69 | /* | 71 | /* |
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c index fdb32e056ef4..139f0af6c3d9 100644 --- a/arch/powerpc/platforms/pseries/setup.c +++ b/arch/powerpc/platforms/pseries/setup.c | |||
@@ -534,6 +534,7 @@ void pseries_setup_rfi_flush(void) | |||
534 | security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR); | 534 | security_ftr_enabled(SEC_FTR_L1D_FLUSH_PR); |
535 | 535 | ||
536 | setup_rfi_flush(types, enable); | 536 | setup_rfi_flush(types, enable); |
537 | setup_barrier_nospec(); | ||
537 | } | 538 | } |
538 | 539 | ||
539 | #ifdef CONFIG_PCI_IOV | 540 | #ifdef CONFIG_PCI_IOV |
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile index 9861407d644a..ea2f595b5133 100644 --- a/arch/powerpc/sysdev/Makefile +++ b/arch/powerpc/sysdev/Makefile | |||
@@ -28,9 +28,6 @@ obj-$(CONFIG_FSL_85XX_CACHE_SRAM) += fsl_85xx_l2ctlr.o fsl_85xx_cache_sram.o | |||
28 | obj-$(CONFIG_SIMPLE_GPIO) += simple_gpio.o | 28 | obj-$(CONFIG_SIMPLE_GPIO) += simple_gpio.o |
29 | obj-$(CONFIG_FSL_RIO) += fsl_rio.o fsl_rmu.o | 29 | obj-$(CONFIG_FSL_RIO) += fsl_rio.o fsl_rmu.o |
30 | obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o | 30 | obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o |
31 | mv64x60-$(CONFIG_PCI) += mv64x60_pci.o | ||
32 | obj-$(CONFIG_MV64X60) += $(mv64x60-y) mv64x60_pic.o mv64x60_dev.o \ | ||
33 | mv64x60_udbg.o | ||
34 | obj-$(CONFIG_RTC_DRV_CMOS) += rtc_cmos_setup.o | 31 | obj-$(CONFIG_RTC_DRV_CMOS) += rtc_cmos_setup.o |
35 | 32 | ||
36 | obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o | 33 | obj-$(CONFIG_PPC_INDIRECT_PCI) += indirect_pci.o |
diff --git a/arch/powerpc/sysdev/cpm_gpio.c b/arch/powerpc/sysdev/cpm_gpio.c index 0badc90be666..0695d26bd301 100644 --- a/arch/powerpc/sysdev/cpm_gpio.c +++ b/arch/powerpc/sysdev/cpm_gpio.c | |||
@@ -63,7 +63,6 @@ static struct platform_driver cpm_gpio_driver = { | |||
63 | .probe = cpm_gpio_probe, | 63 | .probe = cpm_gpio_probe, |
64 | .driver = { | 64 | .driver = { |
65 | .name = "cpm-gpio", | 65 | .name = "cpm-gpio", |
66 | .owner = THIS_MODULE, | ||
67 | .of_match_table = cpm_gpio_match, | 66 | .of_match_table = cpm_gpio_match, |
68 | }, | 67 | }, |
69 | }; | 68 | }; |
diff --git a/arch/powerpc/sysdev/mv64x60.h b/arch/powerpc/sysdev/mv64x60.h deleted file mode 100644 index 60cfcb90d1fa..000000000000 --- a/arch/powerpc/sysdev/mv64x60.h +++ /dev/null | |||
@@ -1,13 +0,0 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | #ifndef __MV64X60_H__ | ||
3 | #define __MV64X60_H__ | ||
4 | |||
5 | #include <linux/init.h> | ||
6 | |||
7 | extern void __init mv64x60_init_irq(void); | ||
8 | extern unsigned int mv64x60_get_irq(void); | ||
9 | |||
10 | extern void __init mv64x60_pci_init(void); | ||
11 | extern void __init mv64x60_init_early(void); | ||
12 | |||
13 | #endif /* __MV64X60_H__ */ | ||
diff --git a/arch/powerpc/sysdev/mv64x60_dev.c b/arch/powerpc/sysdev/mv64x60_dev.c deleted file mode 100644 index 185a67e742a6..000000000000 --- a/arch/powerpc/sysdev/mv64x60_dev.c +++ /dev/null | |||
@@ -1,535 +0,0 @@ | |||
1 | /* | ||
2 | * Platform device setup for Marvell mv64360/mv64460 host bridges (Discovery) | ||
3 | * | ||
4 | * Author: Dale Farnsworth <dale@farnsworth.org> | ||
5 | * | ||
6 | * 2007 (c) MontaVista, Software, Inc. This file is licensed under | ||
7 | * the terms of the GNU General Public License version 2. This program | ||
8 | * is licensed "as is" without any warranty of any kind, whether express | ||
9 | * or implied. | ||
10 | */ | ||
11 | |||
12 | #include <linux/stddef.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/console.h> | ||
16 | #include <linux/mv643xx.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | #include <linux/of_platform.h> | ||
19 | #include <linux/of_net.h> | ||
20 | #include <linux/dma-mapping.h> | ||
21 | |||
22 | #include <asm/prom.h> | ||
23 | |||
24 | /* These functions provide the necessary setup for the mv64x60 drivers. */ | ||
25 | |||
26 | static const struct of_device_id of_mv64x60_devices[] __initconst = { | ||
27 | { .compatible = "marvell,mv64306-devctrl", }, | ||
28 | {} | ||
29 | }; | ||
30 | |||
31 | /* | ||
32 | * Create MPSC platform devices | ||
33 | */ | ||
34 | static int __init mv64x60_mpsc_register_shared_pdev(struct device_node *np) | ||
35 | { | ||
36 | struct platform_device *pdev; | ||
37 | struct resource r[2]; | ||
38 | struct mpsc_shared_pdata pdata; | ||
39 | const phandle *ph; | ||
40 | struct device_node *mpscrouting, *mpscintr; | ||
41 | int err; | ||
42 | |||
43 | ph = of_get_property(np, "mpscrouting", NULL); | ||
44 | mpscrouting = of_find_node_by_phandle(*ph); | ||
45 | if (!mpscrouting) | ||
46 | return -ENODEV; | ||
47 | |||
48 | err = of_address_to_resource(mpscrouting, 0, &r[0]); | ||
49 | of_node_put(mpscrouting); | ||
50 | if (err) | ||
51 | return err; | ||
52 | |||
53 | ph = of_get_property(np, "mpscintr", NULL); | ||
54 | mpscintr = of_find_node_by_phandle(*ph); | ||
55 | if (!mpscintr) | ||
56 | return -ENODEV; | ||
57 | |||
58 | err = of_address_to_resource(mpscintr, 0, &r[1]); | ||
59 | of_node_put(mpscintr); | ||
60 | if (err) | ||
61 | return err; | ||
62 | |||
63 | memset(&pdata, 0, sizeof(pdata)); | ||
64 | |||
65 | pdev = platform_device_alloc(MPSC_SHARED_NAME, 0); | ||
66 | if (!pdev) | ||
67 | return -ENOMEM; | ||
68 | |||
69 | err = platform_device_add_resources(pdev, r, 2); | ||
70 | if (err) | ||
71 | goto error; | ||
72 | |||
73 | err = platform_device_add_data(pdev, &pdata, sizeof(pdata)); | ||
74 | if (err) | ||
75 | goto error; | ||
76 | |||
77 | err = platform_device_add(pdev); | ||
78 | if (err) | ||
79 | goto error; | ||
80 | |||
81 | return 0; | ||
82 | |||
83 | error: | ||
84 | platform_device_put(pdev); | ||
85 | return err; | ||
86 | } | ||
87 | |||
88 | |||
89 | static int __init mv64x60_mpsc_device_setup(struct device_node *np, int id) | ||
90 | { | ||
91 | struct resource r[5]; | ||
92 | struct mpsc_pdata pdata; | ||
93 | struct platform_device *pdev; | ||
94 | const unsigned int *prop; | ||
95 | const phandle *ph; | ||
96 | struct device_node *sdma, *brg; | ||
97 | int err; | ||
98 | int port_number; | ||
99 | |||
100 | /* only register the shared platform device the first time through */ | ||
101 | if (id == 0 && (err = mv64x60_mpsc_register_shared_pdev(np))) | ||
102 | return err; | ||
103 | |||
104 | memset(r, 0, sizeof(r)); | ||
105 | |||
106 | err = of_address_to_resource(np, 0, &r[0]); | ||
107 | if (err) | ||
108 | return err; | ||
109 | |||
110 | of_irq_to_resource(np, 0, &r[4]); | ||
111 | |||
112 | ph = of_get_property(np, "sdma", NULL); | ||
113 | sdma = of_find_node_by_phandle(*ph); | ||
114 | if (!sdma) | ||
115 | return -ENODEV; | ||
116 | |||
117 | of_irq_to_resource(sdma, 0, &r[3]); | ||
118 | err = of_address_to_resource(sdma, 0, &r[1]); | ||
119 | of_node_put(sdma); | ||
120 | if (err) | ||
121 | return err; | ||
122 | |||
123 | ph = of_get_property(np, "brg", NULL); | ||
124 | brg = of_find_node_by_phandle(*ph); | ||
125 | if (!brg) | ||
126 | return -ENODEV; | ||
127 | |||
128 | err = of_address_to_resource(brg, 0, &r[2]); | ||
129 | of_node_put(brg); | ||
130 | if (err) | ||
131 | return err; | ||
132 | |||
133 | prop = of_get_property(np, "cell-index", NULL); | ||
134 | if (!prop) | ||
135 | return -ENODEV; | ||
136 | port_number = *(int *)prop; | ||
137 | |||
138 | memset(&pdata, 0, sizeof(pdata)); | ||
139 | |||
140 | pdata.cache_mgmt = 1; /* All current revs need this set */ | ||
141 | |||
142 | pdata.max_idle = 40; /* default */ | ||
143 | prop = of_get_property(np, "max_idle", NULL); | ||
144 | if (prop) | ||
145 | pdata.max_idle = *prop; | ||
146 | |||
147 | prop = of_get_property(brg, "current-speed", NULL); | ||
148 | if (prop) | ||
149 | pdata.default_baud = *prop; | ||
150 | |||
151 | /* Default is 8 bits, no parity, no flow control */ | ||
152 | pdata.default_bits = 8; | ||
153 | pdata.default_parity = 'n'; | ||
154 | pdata.default_flow = 'n'; | ||
155 | |||
156 | prop = of_get_property(np, "chr_1", NULL); | ||
157 | if (prop) | ||
158 | pdata.chr_1_val = *prop; | ||
159 | |||
160 | prop = of_get_property(np, "chr_2", NULL); | ||
161 | if (prop) | ||
162 | pdata.chr_2_val = *prop; | ||
163 | |||
164 | prop = of_get_property(np, "chr_10", NULL); | ||
165 | if (prop) | ||
166 | pdata.chr_10_val = *prop; | ||
167 | |||
168 | prop = of_get_property(np, "mpcr", NULL); | ||
169 | if (prop) | ||
170 | pdata.mpcr_val = *prop; | ||
171 | |||
172 | prop = of_get_property(brg, "bcr", NULL); | ||
173 | if (prop) | ||
174 | pdata.bcr_val = *prop; | ||
175 | |||
176 | pdata.brg_can_tune = 1; /* All current revs need this set */ | ||
177 | |||
178 | prop = of_get_property(brg, "clock-src", NULL); | ||
179 | if (prop) | ||
180 | pdata.brg_clk_src = *prop; | ||
181 | |||
182 | prop = of_get_property(brg, "clock-frequency", NULL); | ||
183 | if (prop) | ||
184 | pdata.brg_clk_freq = *prop; | ||
185 | |||
186 | pdev = platform_device_alloc(MPSC_CTLR_NAME, port_number); | ||
187 | if (!pdev) | ||
188 | return -ENOMEM; | ||
189 | pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); | ||
190 | |||
191 | err = platform_device_add_resources(pdev, r, 5); | ||
192 | if (err) | ||
193 | goto error; | ||
194 | |||
195 | err = platform_device_add_data(pdev, &pdata, sizeof(pdata)); | ||
196 | if (err) | ||
197 | goto error; | ||
198 | |||
199 | err = platform_device_add(pdev); | ||
200 | if (err) | ||
201 | goto error; | ||
202 | |||
203 | return 0; | ||
204 | |||
205 | error: | ||
206 | platform_device_put(pdev); | ||
207 | return err; | ||
208 | } | ||
209 | |||
210 | /* | ||
211 | * Create mv64x60_eth platform devices | ||
212 | */ | ||
213 | static struct platform_device * __init mv64x60_eth_register_shared_pdev( | ||
214 | struct device_node *np, int id) | ||
215 | { | ||
216 | struct platform_device *pdev; | ||
217 | struct resource r[2]; | ||
218 | int err; | ||
219 | |||
220 | err = of_address_to_resource(np, 0, &r[0]); | ||
221 | if (err) | ||
222 | return ERR_PTR(err); | ||
223 | |||
224 | /* register an orion mdio bus driver */ | ||
225 | r[1].start = r[0].start + 0x4; | ||
226 | r[1].end = r[0].start + 0x84 - 1; | ||
227 | r[1].flags = IORESOURCE_MEM; | ||
228 | |||
229 | if (id == 0) { | ||
230 | pdev = platform_device_register_simple("orion-mdio", -1, &r[1], 1); | ||
231 | if (IS_ERR(pdev)) | ||
232 | return pdev; | ||
233 | } | ||
234 | |||
235 | pdev = platform_device_register_simple(MV643XX_ETH_SHARED_NAME, id, | ||
236 | &r[0], 1); | ||
237 | |||
238 | return pdev; | ||
239 | } | ||
240 | |||
241 | static int __init mv64x60_eth_device_setup(struct device_node *np, int id, | ||
242 | struct platform_device *shared_pdev) | ||
243 | { | ||
244 | struct resource r[1]; | ||
245 | struct mv643xx_eth_platform_data pdata; | ||
246 | struct platform_device *pdev; | ||
247 | struct device_node *phy; | ||
248 | const u8 *mac_addr; | ||
249 | const int *prop; | ||
250 | const phandle *ph; | ||
251 | int err; | ||
252 | |||
253 | memset(r, 0, sizeof(r)); | ||
254 | of_irq_to_resource(np, 0, &r[0]); | ||
255 | |||
256 | memset(&pdata, 0, sizeof(pdata)); | ||
257 | |||
258 | pdata.shared = shared_pdev; | ||
259 | |||
260 | prop = of_get_property(np, "reg", NULL); | ||
261 | if (!prop) | ||
262 | return -ENODEV; | ||
263 | pdata.port_number = *prop; | ||
264 | |||
265 | mac_addr = of_get_mac_address(np); | ||
266 | if (mac_addr) | ||
267 | memcpy(pdata.mac_addr, mac_addr, 6); | ||
268 | |||
269 | prop = of_get_property(np, "speed", NULL); | ||
270 | if (prop) | ||
271 | pdata.speed = *prop; | ||
272 | |||
273 | prop = of_get_property(np, "tx_queue_size", NULL); | ||
274 | if (prop) | ||
275 | pdata.tx_queue_size = *prop; | ||
276 | |||
277 | prop = of_get_property(np, "rx_queue_size", NULL); | ||
278 | if (prop) | ||
279 | pdata.rx_queue_size = *prop; | ||
280 | |||
281 | prop = of_get_property(np, "tx_sram_addr", NULL); | ||
282 | if (prop) | ||
283 | pdata.tx_sram_addr = *prop; | ||
284 | |||
285 | prop = of_get_property(np, "tx_sram_size", NULL); | ||
286 | if (prop) | ||
287 | pdata.tx_sram_size = *prop; | ||
288 | |||
289 | prop = of_get_property(np, "rx_sram_addr", NULL); | ||
290 | if (prop) | ||
291 | pdata.rx_sram_addr = *prop; | ||
292 | |||
293 | prop = of_get_property(np, "rx_sram_size", NULL); | ||
294 | if (prop) | ||
295 | pdata.rx_sram_size = *prop; | ||
296 | |||
297 | ph = of_get_property(np, "phy", NULL); | ||
298 | if (!ph) | ||
299 | return -ENODEV; | ||
300 | |||
301 | phy = of_find_node_by_phandle(*ph); | ||
302 | if (phy == NULL) | ||
303 | return -ENODEV; | ||
304 | |||
305 | prop = of_get_property(phy, "reg", NULL); | ||
306 | if (prop) | ||
307 | pdata.phy_addr = MV643XX_ETH_PHY_ADDR(*prop); | ||
308 | |||
309 | of_node_put(phy); | ||
310 | |||
311 | pdev = platform_device_alloc(MV643XX_ETH_NAME, id); | ||
312 | if (!pdev) | ||
313 | return -ENOMEM; | ||
314 | |||
315 | pdev->dev.coherent_dma_mask = DMA_BIT_MASK(32); | ||
316 | err = platform_device_add_resources(pdev, r, 1); | ||
317 | if (err) | ||
318 | goto error; | ||
319 | |||
320 | err = platform_device_add_data(pdev, &pdata, sizeof(pdata)); | ||
321 | if (err) | ||
322 | goto error; | ||
323 | |||
324 | err = platform_device_add(pdev); | ||
325 | if (err) | ||
326 | goto error; | ||
327 | |||
328 | return 0; | ||
329 | |||
330 | error: | ||
331 | platform_device_put(pdev); | ||
332 | return err; | ||
333 | } | ||
334 | |||
335 | /* | ||
336 | * Create mv64x60_i2c platform devices | ||
337 | */ | ||
338 | static int __init mv64x60_i2c_device_setup(struct device_node *np, int id) | ||
339 | { | ||
340 | struct resource r[2]; | ||
341 | struct platform_device *pdev; | ||
342 | struct mv64xxx_i2c_pdata pdata; | ||
343 | const unsigned int *prop; | ||
344 | int err; | ||
345 | |||
346 | memset(r, 0, sizeof(r)); | ||
347 | |||
348 | err = of_address_to_resource(np, 0, &r[0]); | ||
349 | if (err) | ||
350 | return err; | ||
351 | |||
352 | of_irq_to_resource(np, 0, &r[1]); | ||
353 | |||
354 | memset(&pdata, 0, sizeof(pdata)); | ||
355 | |||
356 | pdata.freq_m = 8; /* default */ | ||
357 | prop = of_get_property(np, "freq_m", NULL); | ||
358 | if (prop) | ||
359 | pdata.freq_m = *prop; | ||
360 | |||
361 | pdata.freq_n = 3; /* default */ | ||
362 | prop = of_get_property(np, "freq_n", NULL); | ||
363 | if (prop) | ||
364 | pdata.freq_n = *prop; | ||
365 | |||
366 | pdata.timeout = 1000; /* default: 1 second */ | ||
367 | |||
368 | pdev = platform_device_alloc(MV64XXX_I2C_CTLR_NAME, id); | ||
369 | if (!pdev) | ||
370 | return -ENOMEM; | ||
371 | |||
372 | err = platform_device_add_resources(pdev, r, 2); | ||
373 | if (err) | ||
374 | goto error; | ||
375 | |||
376 | err = platform_device_add_data(pdev, &pdata, sizeof(pdata)); | ||
377 | if (err) | ||
378 | goto error; | ||
379 | |||
380 | err = platform_device_add(pdev); | ||
381 | if (err) | ||
382 | goto error; | ||
383 | |||
384 | return 0; | ||
385 | |||
386 | error: | ||
387 | platform_device_put(pdev); | ||
388 | return err; | ||
389 | } | ||
390 | |||
391 | /* | ||
392 | * Create mv64x60_wdt platform devices | ||
393 | */ | ||
394 | static int __init mv64x60_wdt_device_setup(struct device_node *np, int id) | ||
395 | { | ||
396 | struct resource r; | ||
397 | struct platform_device *pdev; | ||
398 | struct mv64x60_wdt_pdata pdata; | ||
399 | const unsigned int *prop; | ||
400 | int err; | ||
401 | |||
402 | err = of_address_to_resource(np, 0, &r); | ||
403 | if (err) | ||
404 | return err; | ||
405 | |||
406 | memset(&pdata, 0, sizeof(pdata)); | ||
407 | |||
408 | pdata.timeout = 10; /* Default: 10 seconds */ | ||
409 | |||
410 | np = of_get_parent(np); | ||
411 | if (!np) | ||
412 | return -ENODEV; | ||
413 | |||
414 | prop = of_get_property(np, "clock-frequency", NULL); | ||
415 | of_node_put(np); | ||
416 | if (!prop) | ||
417 | return -ENODEV; | ||
418 | pdata.bus_clk = *prop / 1000000; /* wdt driver wants freq in MHz */ | ||
419 | |||
420 | pdev = platform_device_alloc(MV64x60_WDT_NAME, id); | ||
421 | if (!pdev) | ||
422 | return -ENOMEM; | ||
423 | |||
424 | err = platform_device_add_resources(pdev, &r, 1); | ||
425 | if (err) | ||
426 | goto error; | ||
427 | |||
428 | err = platform_device_add_data(pdev, &pdata, sizeof(pdata)); | ||
429 | if (err) | ||
430 | goto error; | ||
431 | |||
432 | err = platform_device_add(pdev); | ||
433 | if (err) | ||
434 | goto error; | ||
435 | |||
436 | return 0; | ||
437 | |||
438 | error: | ||
439 | platform_device_put(pdev); | ||
440 | return err; | ||
441 | } | ||
442 | |||
443 | static int __init mv64x60_device_setup(void) | ||
444 | { | ||
445 | struct device_node *np, *np2; | ||
446 | struct platform_device *pdev; | ||
447 | int id, id2; | ||
448 | int err; | ||
449 | |||
450 | id = 0; | ||
451 | for_each_compatible_node(np, NULL, "marvell,mv64360-mpsc") { | ||
452 | err = mv64x60_mpsc_device_setup(np, id++); | ||
453 | if (err) | ||
454 | printk(KERN_ERR "Failed to initialize MV64x60 " | ||
455 | "serial device %pOF: error %d.\n", | ||
456 | np, err); | ||
457 | } | ||
458 | |||
459 | id = 0; | ||
460 | id2 = 0; | ||
461 | for_each_compatible_node(np, NULL, "marvell,mv64360-eth-group") { | ||
462 | pdev = mv64x60_eth_register_shared_pdev(np, id++); | ||
463 | if (IS_ERR(pdev)) { | ||
464 | err = PTR_ERR(pdev); | ||
465 | printk(KERN_ERR "Failed to initialize MV64x60 " | ||
466 | "network block %pOF: error %d.\n", | ||
467 | np, err); | ||
468 | continue; | ||
469 | } | ||
470 | for_each_child_of_node(np, np2) { | ||
471 | if (!of_device_is_compatible(np2, | ||
472 | "marvell,mv64360-eth")) | ||
473 | continue; | ||
474 | err = mv64x60_eth_device_setup(np2, id2++, pdev); | ||
475 | if (err) | ||
476 | printk(KERN_ERR "Failed to initialize " | ||
477 | "MV64x60 network device %pOF: " | ||
478 | "error %d.\n", | ||
479 | np2, err); | ||
480 | } | ||
481 | } | ||
482 | |||
483 | id = 0; | ||
484 | for_each_compatible_node(np, "i2c", "marvell,mv64360-i2c") { | ||
485 | err = mv64x60_i2c_device_setup(np, id++); | ||
486 | if (err) | ||
487 | printk(KERN_ERR "Failed to initialize MV64x60 I2C " | ||
488 | "bus %pOF: error %d.\n", | ||
489 | np, err); | ||
490 | } | ||
491 | |||
492 | /* support up to one watchdog timer */ | ||
493 | np = of_find_compatible_node(np, NULL, "marvell,mv64360-wdt"); | ||
494 | if (np) { | ||
495 | if ((err = mv64x60_wdt_device_setup(np, id))) | ||
496 | printk(KERN_ERR "Failed to initialize MV64x60 " | ||
497 | "Watchdog %pOF: error %d.\n", | ||
498 | np, err); | ||
499 | of_node_put(np); | ||
500 | } | ||
501 | |||
502 | /* Now add every node that is on the device bus */ | ||
503 | for_each_compatible_node(np, NULL, "marvell,mv64360") | ||
504 | of_platform_bus_probe(np, of_mv64x60_devices, NULL); | ||
505 | |||
506 | return 0; | ||
507 | } | ||
508 | arch_initcall(mv64x60_device_setup); | ||
509 | |||
510 | static int __init mv64x60_add_mpsc_console(void) | ||
511 | { | ||
512 | struct device_node *np = NULL; | ||
513 | const char *prop; | ||
514 | |||
515 | prop = of_get_property(of_chosen, "linux,stdout-path", NULL); | ||
516 | if (prop == NULL) | ||
517 | goto not_mpsc; | ||
518 | |||
519 | np = of_find_node_by_path(prop); | ||
520 | if (!np) | ||
521 | goto not_mpsc; | ||
522 | |||
523 | if (!of_device_is_compatible(np, "marvell,mv64360-mpsc")) | ||
524 | goto not_mpsc; | ||
525 | |||
526 | prop = of_get_property(np, "cell-index", NULL); | ||
527 | if (!prop) | ||
528 | goto not_mpsc; | ||
529 | |||
530 | add_preferred_console("ttyMM", *(int *)prop, NULL); | ||
531 | |||
532 | not_mpsc: | ||
533 | return 0; | ||
534 | } | ||
535 | console_initcall(mv64x60_add_mpsc_console); | ||
diff --git a/arch/powerpc/sysdev/mv64x60_pci.c b/arch/powerpc/sysdev/mv64x60_pci.c deleted file mode 100644 index 1afcdb428e51..000000000000 --- a/arch/powerpc/sysdev/mv64x60_pci.c +++ /dev/null | |||
@@ -1,171 +0,0 @@ | |||
1 | /* | ||
2 | * PCI bus setup for Marvell mv64360/mv64460 host bridges (Discovery) | ||
3 | * | ||
4 | * Author: Dale Farnsworth <dale@farnsworth.org> | ||
5 | * | ||
6 | * 2007 (c) MontaVista, Software, Inc. This file is licensed under | ||
7 | * the terms of the GNU General Public License version 2. This program | ||
8 | * is licensed "as is" without any warranty of any kind, whether express | ||
9 | * or implied. | ||
10 | */ | ||
11 | |||
12 | #include <linux/stddef.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/stat.h> | ||
16 | #include <linux/pci.h> | ||
17 | |||
18 | #include <asm/prom.h> | ||
19 | #include <asm/pci-bridge.h> | ||
20 | |||
21 | #define PCI_HEADER_TYPE_INVALID 0x7f /* Invalid PCI header type */ | ||
22 | |||
23 | #ifdef CONFIG_SYSFS | ||
24 | /* 32-bit hex or dec stringified number + '\n' */ | ||
25 | #define MV64X60_VAL_LEN_MAX 11 | ||
26 | #define MV64X60_PCICFG_CPCI_HOTSWAP 0x68 | ||
27 | |||
28 | static ssize_t mv64x60_hs_reg_read(struct file *filp, struct kobject *kobj, | ||
29 | struct bin_attribute *attr, char *buf, | ||
30 | loff_t off, size_t count) | ||
31 | { | ||
32 | struct pci_dev *phb; | ||
33 | u32 v; | ||
34 | |||
35 | if (off > 0) | ||
36 | return 0; | ||
37 | if (count < MV64X60_VAL_LEN_MAX) | ||
38 | return -EINVAL; | ||
39 | |||
40 | phb = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0, 0)); | ||
41 | if (!phb) | ||
42 | return -ENODEV; | ||
43 | pci_read_config_dword(phb, MV64X60_PCICFG_CPCI_HOTSWAP, &v); | ||
44 | pci_dev_put(phb); | ||
45 | |||
46 | return sprintf(buf, "0x%08x\n", v); | ||
47 | } | ||
48 | |||
49 | static ssize_t mv64x60_hs_reg_write(struct file *filp, struct kobject *kobj, | ||
50 | struct bin_attribute *attr, char *buf, | ||
51 | loff_t off, size_t count) | ||
52 | { | ||
53 | struct pci_dev *phb; | ||
54 | u32 v; | ||
55 | |||
56 | if (off > 0) | ||
57 | return 0; | ||
58 | if (count <= 0) | ||
59 | return -EINVAL; | ||
60 | |||
61 | if (sscanf(buf, "%i", &v) != 1) | ||
62 | return -EINVAL; | ||
63 | |||
64 | phb = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0, 0)); | ||
65 | if (!phb) | ||
66 | return -ENODEV; | ||
67 | pci_write_config_dword(phb, MV64X60_PCICFG_CPCI_HOTSWAP, v); | ||
68 | pci_dev_put(phb); | ||
69 | |||
70 | return count; | ||
71 | } | ||
72 | |||
73 | static const struct bin_attribute mv64x60_hs_reg_attr = { /* Hotswap register */ | ||
74 | .attr = { | ||
75 | .name = "hs_reg", | ||
76 | .mode = 0644, | ||
77 | }, | ||
78 | .size = MV64X60_VAL_LEN_MAX, | ||
79 | .read = mv64x60_hs_reg_read, | ||
80 | .write = mv64x60_hs_reg_write, | ||
81 | }; | ||
82 | |||
83 | static int __init mv64x60_sysfs_init(void) | ||
84 | { | ||
85 | struct device_node *np; | ||
86 | struct platform_device *pdev; | ||
87 | const unsigned int *prop; | ||
88 | |||
89 | np = of_find_compatible_node(NULL, NULL, "marvell,mv64360"); | ||
90 | if (!np) | ||
91 | return 0; | ||
92 | |||
93 | prop = of_get_property(np, "hs_reg_valid", NULL); | ||
94 | of_node_put(np); | ||
95 | |||
96 | pdev = platform_device_register_simple("marvell,mv64360", 0, NULL, 0); | ||
97 | if (IS_ERR(pdev)) | ||
98 | return PTR_ERR(pdev); | ||
99 | |||
100 | return sysfs_create_bin_file(&pdev->dev.kobj, &mv64x60_hs_reg_attr); | ||
101 | } | ||
102 | |||
103 | subsys_initcall(mv64x60_sysfs_init); | ||
104 | |||
105 | #endif /* CONFIG_SYSFS */ | ||
106 | |||
107 | static void mv64x60_pci_fixup_early(struct pci_dev *dev) | ||
108 | { | ||
109 | /* | ||
110 | * Set the host bridge hdr_type to an invalid value so that | ||
111 | * pci_setup_device() will ignore the host bridge. | ||
112 | */ | ||
113 | dev->hdr_type = PCI_HEADER_TYPE_INVALID; | ||
114 | } | ||
115 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_MARVELL, PCI_DEVICE_ID_MARVELL_MV64360, | ||
116 | mv64x60_pci_fixup_early); | ||
117 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_MARVELL, PCI_DEVICE_ID_MARVELL_MV64460, | ||
118 | mv64x60_pci_fixup_early); | ||
119 | |||
120 | static int __init mv64x60_add_bridge(struct device_node *dev) | ||
121 | { | ||
122 | int len; | ||
123 | struct pci_controller *hose; | ||
124 | struct resource rsrc; | ||
125 | const int *bus_range; | ||
126 | int primary; | ||
127 | |||
128 | memset(&rsrc, 0, sizeof(rsrc)); | ||
129 | |||
130 | /* Fetch host bridge registers address */ | ||
131 | if (of_address_to_resource(dev, 0, &rsrc)) { | ||
132 | printk(KERN_ERR "No PCI reg property in device tree\n"); | ||
133 | return -ENODEV; | ||
134 | } | ||
135 | |||
136 | /* Get bus range if any */ | ||
137 | bus_range = of_get_property(dev, "bus-range", &len); | ||
138 | if (bus_range == NULL || len < 2 * sizeof(int)) | ||
139 | printk(KERN_WARNING "Can't get bus-range for %pOF, assume" | ||
140 | " bus 0\n", dev); | ||
141 | |||
142 | hose = pcibios_alloc_controller(dev); | ||
143 | if (!hose) | ||
144 | return -ENOMEM; | ||
145 | |||
146 | hose->first_busno = bus_range ? bus_range[0] : 0; | ||
147 | hose->last_busno = bus_range ? bus_range[1] : 0xff; | ||
148 | |||
149 | setup_indirect_pci(hose, rsrc.start, rsrc.start + 4, 0); | ||
150 | hose->self_busno = hose->first_busno; | ||
151 | |||
152 | printk(KERN_INFO "Found MV64x60 PCI host bridge at 0x%016llx. " | ||
153 | "Firmware bus number: %d->%d\n", | ||
154 | (unsigned long long)rsrc.start, hose->first_busno, | ||
155 | hose->last_busno); | ||
156 | |||
157 | /* Interpret the "ranges" property */ | ||
158 | /* This also maps the I/O region and sets isa_io/mem_base */ | ||
159 | primary = (hose->first_busno == 0); | ||
160 | pci_process_bridge_OF_ranges(hose, dev, primary); | ||
161 | |||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | void __init mv64x60_pci_init(void) | ||
166 | { | ||
167 | struct device_node *np; | ||
168 | |||
169 | for_each_compatible_node(np, "pci", "marvell,mv64360-pci") | ||
170 | mv64x60_add_bridge(np); | ||
171 | } | ||
diff --git a/arch/powerpc/sysdev/mv64x60_pic.c b/arch/powerpc/sysdev/mv64x60_pic.c deleted file mode 100644 index a79953deb489..000000000000 --- a/arch/powerpc/sysdev/mv64x60_pic.c +++ /dev/null | |||
@@ -1,297 +0,0 @@ | |||
1 | /* | ||
2 | * Interrupt handling for Marvell mv64360/mv64460 host bridges (Discovery) | ||
3 | * | ||
4 | * Author: Dale Farnsworth <dale@farnsworth.org> | ||
5 | * | ||
6 | * 2007 (c) MontaVista, Software, Inc. This file is licensed under | ||
7 | * the terms of the GNU General Public License version 2. This program | ||
8 | * is licensed "as is" without any warranty of any kind, whether express | ||
9 | * or implied. | ||
10 | */ | ||
11 | |||
12 | #include <linux/stddef.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/irq.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/spinlock.h> | ||
18 | |||
19 | #include <asm/byteorder.h> | ||
20 | #include <asm/io.h> | ||
21 | #include <asm/prom.h> | ||
22 | #include <asm/irq.h> | ||
23 | |||
24 | #include "mv64x60.h" | ||
25 | |||
26 | /* Interrupt Controller Interface Registers */ | ||
27 | #define MV64X60_IC_MAIN_CAUSE_LO 0x0004 | ||
28 | #define MV64X60_IC_MAIN_CAUSE_HI 0x000c | ||
29 | #define MV64X60_IC_CPU0_INTR_MASK_LO 0x0014 | ||
30 | #define MV64X60_IC_CPU0_INTR_MASK_HI 0x001c | ||
31 | #define MV64X60_IC_CPU0_SELECT_CAUSE 0x0024 | ||
32 | |||
33 | #define MV64X60_HIGH_GPP_GROUPS 0x0f000000 | ||
34 | #define MV64X60_SELECT_CAUSE_HIGH 0x40000000 | ||
35 | |||
36 | /* General Purpose Pins Controller Interface Registers */ | ||
37 | #define MV64x60_GPP_INTR_CAUSE 0x0008 | ||
38 | #define MV64x60_GPP_INTR_MASK 0x000c | ||
39 | |||
40 | #define MV64x60_LEVEL1_LOW 0 | ||
41 | #define MV64x60_LEVEL1_HIGH 1 | ||
42 | #define MV64x60_LEVEL1_GPP 2 | ||
43 | |||
44 | #define MV64x60_LEVEL1_MASK 0x00000060 | ||
45 | #define MV64x60_LEVEL1_OFFSET 5 | ||
46 | |||
47 | #define MV64x60_LEVEL2_MASK 0x0000001f | ||
48 | |||
49 | #define MV64x60_NUM_IRQS 96 | ||
50 | |||
51 | static DEFINE_SPINLOCK(mv64x60_lock); | ||
52 | |||
53 | static void __iomem *mv64x60_irq_reg_base; | ||
54 | static void __iomem *mv64x60_gpp_reg_base; | ||
55 | |||
56 | /* | ||
57 | * Interrupt Controller Handling | ||
58 | * | ||
59 | * The interrupt controller handles three groups of interrupts: | ||
60 | * main low: IRQ0-IRQ31 | ||
61 | * main high: IRQ32-IRQ63 | ||
62 | * gpp: IRQ64-IRQ95 | ||
63 | * | ||
64 | * This code handles interrupts in two levels. Level 1 selects the | ||
65 | * interrupt group, and level 2 selects an IRQ within that group. | ||
66 | * Each group has its own irq_chip structure. | ||
67 | */ | ||
68 | |||
69 | static u32 mv64x60_cached_low_mask; | ||
70 | static u32 mv64x60_cached_high_mask = MV64X60_HIGH_GPP_GROUPS; | ||
71 | static u32 mv64x60_cached_gpp_mask; | ||
72 | |||
73 | static struct irq_domain *mv64x60_irq_host; | ||
74 | |||
75 | /* | ||
76 | * mv64x60_chip_low functions | ||
77 | */ | ||
78 | |||
79 | static void mv64x60_mask_low(struct irq_data *d) | ||
80 | { | ||
81 | int level2 = irqd_to_hwirq(d) & MV64x60_LEVEL2_MASK; | ||
82 | unsigned long flags; | ||
83 | |||
84 | spin_lock_irqsave(&mv64x60_lock, flags); | ||
85 | mv64x60_cached_low_mask &= ~(1 << level2); | ||
86 | out_le32(mv64x60_irq_reg_base + MV64X60_IC_CPU0_INTR_MASK_LO, | ||
87 | mv64x60_cached_low_mask); | ||
88 | spin_unlock_irqrestore(&mv64x60_lock, flags); | ||
89 | (void)in_le32(mv64x60_irq_reg_base + MV64X60_IC_CPU0_INTR_MASK_LO); | ||
90 | } | ||
91 | |||
92 | static void mv64x60_unmask_low(struct irq_data *d) | ||
93 | { | ||
94 | int level2 = irqd_to_hwirq(d) & MV64x60_LEVEL2_MASK; | ||
95 | unsigned long flags; | ||
96 | |||
97 | spin_lock_irqsave(&mv64x60_lock, flags); | ||
98 | mv64x60_cached_low_mask |= 1 << level2; | ||
99 | out_le32(mv64x60_irq_reg_base + MV64X60_IC_CPU0_INTR_MASK_LO, | ||
100 | mv64x60_cached_low_mask); | ||
101 | spin_unlock_irqrestore(&mv64x60_lock, flags); | ||
102 | (void)in_le32(mv64x60_irq_reg_base + MV64X60_IC_CPU0_INTR_MASK_LO); | ||
103 | } | ||
104 | |||
105 | static struct irq_chip mv64x60_chip_low = { | ||
106 | .name = "mv64x60_low", | ||
107 | .irq_mask = mv64x60_mask_low, | ||
108 | .irq_mask_ack = mv64x60_mask_low, | ||
109 | .irq_unmask = mv64x60_unmask_low, | ||
110 | }; | ||
111 | |||
112 | /* | ||
113 | * mv64x60_chip_high functions | ||
114 | */ | ||
115 | |||
116 | static void mv64x60_mask_high(struct irq_data *d) | ||
117 | { | ||
118 | int level2 = irqd_to_hwirq(d) & MV64x60_LEVEL2_MASK; | ||
119 | unsigned long flags; | ||
120 | |||
121 | spin_lock_irqsave(&mv64x60_lock, flags); | ||
122 | mv64x60_cached_high_mask &= ~(1 << level2); | ||
123 | out_le32(mv64x60_irq_reg_base + MV64X60_IC_CPU0_INTR_MASK_HI, | ||
124 | mv64x60_cached_high_mask); | ||
125 | spin_unlock_irqrestore(&mv64x60_lock, flags); | ||
126 | (void)in_le32(mv64x60_irq_reg_base + MV64X60_IC_CPU0_INTR_MASK_HI); | ||
127 | } | ||
128 | |||
129 | static void mv64x60_unmask_high(struct irq_data *d) | ||
130 | { | ||
131 | int level2 = irqd_to_hwirq(d) & MV64x60_LEVEL2_MASK; | ||
132 | unsigned long flags; | ||
133 | |||
134 | spin_lock_irqsave(&mv64x60_lock, flags); | ||
135 | mv64x60_cached_high_mask |= 1 << level2; | ||
136 | out_le32(mv64x60_irq_reg_base + MV64X60_IC_CPU0_INTR_MASK_HI, | ||
137 | mv64x60_cached_high_mask); | ||
138 | spin_unlock_irqrestore(&mv64x60_lock, flags); | ||
139 | (void)in_le32(mv64x60_irq_reg_base + MV64X60_IC_CPU0_INTR_MASK_HI); | ||
140 | } | ||
141 | |||
142 | static struct irq_chip mv64x60_chip_high = { | ||
143 | .name = "mv64x60_high", | ||
144 | .irq_mask = mv64x60_mask_high, | ||
145 | .irq_mask_ack = mv64x60_mask_high, | ||
146 | .irq_unmask = mv64x60_unmask_high, | ||
147 | }; | ||
148 | |||
149 | /* | ||
150 | * mv64x60_chip_gpp functions | ||
151 | */ | ||
152 | |||
153 | static void mv64x60_mask_gpp(struct irq_data *d) | ||
154 | { | ||
155 | int level2 = irqd_to_hwirq(d) & MV64x60_LEVEL2_MASK; | ||
156 | unsigned long flags; | ||
157 | |||
158 | spin_lock_irqsave(&mv64x60_lock, flags); | ||
159 | mv64x60_cached_gpp_mask &= ~(1 << level2); | ||
160 | out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_INTR_MASK, | ||
161 | mv64x60_cached_gpp_mask); | ||
162 | spin_unlock_irqrestore(&mv64x60_lock, flags); | ||
163 | (void)in_le32(mv64x60_gpp_reg_base + MV64x60_GPP_INTR_MASK); | ||
164 | } | ||
165 | |||
166 | static void mv64x60_mask_ack_gpp(struct irq_data *d) | ||
167 | { | ||
168 | int level2 = irqd_to_hwirq(d) & MV64x60_LEVEL2_MASK; | ||
169 | unsigned long flags; | ||
170 | |||
171 | spin_lock_irqsave(&mv64x60_lock, flags); | ||
172 | mv64x60_cached_gpp_mask &= ~(1 << level2); | ||
173 | out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_INTR_MASK, | ||
174 | mv64x60_cached_gpp_mask); | ||
175 | out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_INTR_CAUSE, | ||
176 | ~(1 << level2)); | ||
177 | spin_unlock_irqrestore(&mv64x60_lock, flags); | ||
178 | (void)in_le32(mv64x60_gpp_reg_base + MV64x60_GPP_INTR_CAUSE); | ||
179 | } | ||
180 | |||
181 | static void mv64x60_unmask_gpp(struct irq_data *d) | ||
182 | { | ||
183 | int level2 = irqd_to_hwirq(d) & MV64x60_LEVEL2_MASK; | ||
184 | unsigned long flags; | ||
185 | |||
186 | spin_lock_irqsave(&mv64x60_lock, flags); | ||
187 | mv64x60_cached_gpp_mask |= 1 << level2; | ||
188 | out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_INTR_MASK, | ||
189 | mv64x60_cached_gpp_mask); | ||
190 | spin_unlock_irqrestore(&mv64x60_lock, flags); | ||
191 | (void)in_le32(mv64x60_gpp_reg_base + MV64x60_GPP_INTR_MASK); | ||
192 | } | ||
193 | |||
194 | static struct irq_chip mv64x60_chip_gpp = { | ||
195 | .name = "mv64x60_gpp", | ||
196 | .irq_mask = mv64x60_mask_gpp, | ||
197 | .irq_mask_ack = mv64x60_mask_ack_gpp, | ||
198 | .irq_unmask = mv64x60_unmask_gpp, | ||
199 | }; | ||
200 | |||
201 | /* | ||
202 | * mv64x60_host_ops functions | ||
203 | */ | ||
204 | |||
205 | static struct irq_chip *mv64x60_chips[] = { | ||
206 | [MV64x60_LEVEL1_LOW] = &mv64x60_chip_low, | ||
207 | [MV64x60_LEVEL1_HIGH] = &mv64x60_chip_high, | ||
208 | [MV64x60_LEVEL1_GPP] = &mv64x60_chip_gpp, | ||
209 | }; | ||
210 | |||
211 | static int mv64x60_host_map(struct irq_domain *h, unsigned int virq, | ||
212 | irq_hw_number_t hwirq) | ||
213 | { | ||
214 | int level1; | ||
215 | |||
216 | irq_set_status_flags(virq, IRQ_LEVEL); | ||
217 | |||
218 | level1 = (hwirq & MV64x60_LEVEL1_MASK) >> MV64x60_LEVEL1_OFFSET; | ||
219 | BUG_ON(level1 > MV64x60_LEVEL1_GPP); | ||
220 | irq_set_chip_and_handler(virq, mv64x60_chips[level1], | ||
221 | handle_level_irq); | ||
222 | |||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | static const struct irq_domain_ops mv64x60_host_ops = { | ||
227 | .map = mv64x60_host_map, | ||
228 | }; | ||
229 | |||
230 | /* | ||
231 | * Global functions | ||
232 | */ | ||
233 | |||
234 | void __init mv64x60_init_irq(void) | ||
235 | { | ||
236 | struct device_node *np; | ||
237 | phys_addr_t paddr; | ||
238 | unsigned int size; | ||
239 | const unsigned int *reg; | ||
240 | unsigned long flags; | ||
241 | |||
242 | np = of_find_compatible_node(NULL, NULL, "marvell,mv64360-gpp"); | ||
243 | reg = of_get_property(np, "reg", &size); | ||
244 | paddr = of_translate_address(np, reg); | ||
245 | mv64x60_gpp_reg_base = ioremap(paddr, reg[1]); | ||
246 | of_node_put(np); | ||
247 | |||
248 | np = of_find_compatible_node(NULL, NULL, "marvell,mv64360-pic"); | ||
249 | reg = of_get_property(np, "reg", &size); | ||
250 | paddr = of_translate_address(np, reg); | ||
251 | mv64x60_irq_reg_base = ioremap(paddr, reg[1]); | ||
252 | |||
253 | mv64x60_irq_host = irq_domain_add_linear(np, MV64x60_NUM_IRQS, | ||
254 | &mv64x60_host_ops, NULL); | ||
255 | |||
256 | spin_lock_irqsave(&mv64x60_lock, flags); | ||
257 | out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_INTR_MASK, | ||
258 | mv64x60_cached_gpp_mask); | ||
259 | out_le32(mv64x60_irq_reg_base + MV64X60_IC_CPU0_INTR_MASK_LO, | ||
260 | mv64x60_cached_low_mask); | ||
261 | out_le32(mv64x60_irq_reg_base + MV64X60_IC_CPU0_INTR_MASK_HI, | ||
262 | mv64x60_cached_high_mask); | ||
263 | |||
264 | out_le32(mv64x60_gpp_reg_base + MV64x60_GPP_INTR_CAUSE, 0); | ||
265 | out_le32(mv64x60_irq_reg_base + MV64X60_IC_MAIN_CAUSE_LO, 0); | ||
266 | out_le32(mv64x60_irq_reg_base + MV64X60_IC_MAIN_CAUSE_HI, 0); | ||
267 | spin_unlock_irqrestore(&mv64x60_lock, flags); | ||
268 | } | ||
269 | |||
270 | unsigned int mv64x60_get_irq(void) | ||
271 | { | ||
272 | u32 cause; | ||
273 | int level1; | ||
274 | irq_hw_number_t hwirq; | ||
275 | int virq = 0; | ||
276 | |||
277 | cause = in_le32(mv64x60_irq_reg_base + MV64X60_IC_CPU0_SELECT_CAUSE); | ||
278 | if (cause & MV64X60_SELECT_CAUSE_HIGH) { | ||
279 | cause &= mv64x60_cached_high_mask; | ||
280 | level1 = MV64x60_LEVEL1_HIGH; | ||
281 | if (cause & MV64X60_HIGH_GPP_GROUPS) { | ||
282 | cause = in_le32(mv64x60_gpp_reg_base + | ||
283 | MV64x60_GPP_INTR_CAUSE); | ||
284 | cause &= mv64x60_cached_gpp_mask; | ||
285 | level1 = MV64x60_LEVEL1_GPP; | ||
286 | } | ||
287 | } else { | ||
288 | cause &= mv64x60_cached_low_mask; | ||
289 | level1 = MV64x60_LEVEL1_LOW; | ||
290 | } | ||
291 | if (cause) { | ||
292 | hwirq = (level1 << MV64x60_LEVEL1_OFFSET) | __ilog2(cause); | ||
293 | virq = irq_linear_revmap(mv64x60_irq_host, hwirq); | ||
294 | } | ||
295 | |||
296 | return virq; | ||
297 | } | ||
diff --git a/arch/powerpc/sysdev/mv64x60_udbg.c b/arch/powerpc/sysdev/mv64x60_udbg.c deleted file mode 100644 index 3b8734b870e9..000000000000 --- a/arch/powerpc/sysdev/mv64x60_udbg.c +++ /dev/null | |||
@@ -1,152 +0,0 @@ | |||
1 | /* | ||
2 | * udbg serial input/output routines for the Marvell MV64x60 (Discovery). | ||
3 | * | ||
4 | * Author: Dale Farnsworth <dale@farnsworth.org> | ||
5 | * | ||
6 | * 2007 (c) MontaVista Software, Inc. This file is licensed under | ||
7 | * the terms of the GNU General Public License version 2. This program | ||
8 | * is licensed "as is" without any warranty of any kind, whether express | ||
9 | * or implied. | ||
10 | */ | ||
11 | |||
12 | #include <asm/io.h> | ||
13 | #include <asm/prom.h> | ||
14 | #include <asm/udbg.h> | ||
15 | |||
16 | #include <sysdev/mv64x60.h> | ||
17 | |||
18 | #define MPSC_0_CR1_OFFSET 0x000c | ||
19 | |||
20 | #define MPSC_0_CR2_OFFSET 0x0010 | ||
21 | #define MPSC_CHR_2_TCS (1 << 9) | ||
22 | |||
23 | #define MPSC_0_CHR_10_OFFSET 0x0030 | ||
24 | |||
25 | #define MPSC_INTR_CAUSE_OFF_0 0x0004 | ||
26 | #define MPSC_INTR_CAUSE_OFF_1 0x000c | ||
27 | #define MPSC_INTR_CAUSE_RCC (1<<6) | ||
28 | |||
29 | static void __iomem *mpsc_base; | ||
30 | static void __iomem *mpsc_intr_cause; | ||
31 | |||
32 | static void mv64x60_udbg_putc(char c) | ||
33 | { | ||
34 | if (c == '\n') | ||
35 | mv64x60_udbg_putc('\r'); | ||
36 | |||
37 | while(in_le32(mpsc_base + MPSC_0_CR2_OFFSET) & MPSC_CHR_2_TCS) | ||
38 | ; | ||
39 | out_le32(mpsc_base + MPSC_0_CR1_OFFSET, c); | ||
40 | out_le32(mpsc_base + MPSC_0_CR2_OFFSET, MPSC_CHR_2_TCS); | ||
41 | } | ||
42 | |||
43 | static int mv64x60_udbg_testc(void) | ||
44 | { | ||
45 | return (in_le32(mpsc_intr_cause) & MPSC_INTR_CAUSE_RCC) != 0; | ||
46 | } | ||
47 | |||
48 | static int mv64x60_udbg_getc(void) | ||
49 | { | ||
50 | int cause = 0; | ||
51 | int c; | ||
52 | |||
53 | while (!mv64x60_udbg_testc()) | ||
54 | ; | ||
55 | |||
56 | c = in_8(mpsc_base + MPSC_0_CHR_10_OFFSET + 2); | ||
57 | out_8(mpsc_base + MPSC_0_CHR_10_OFFSET + 2, c); | ||
58 | out_le32(mpsc_intr_cause, cause & ~MPSC_INTR_CAUSE_RCC); | ||
59 | return c; | ||
60 | } | ||
61 | |||
62 | static int mv64x60_udbg_getc_poll(void) | ||
63 | { | ||
64 | if (!mv64x60_udbg_testc()) | ||
65 | return -1; | ||
66 | |||
67 | return mv64x60_udbg_getc(); | ||
68 | } | ||
69 | |||
70 | static void mv64x60_udbg_init(void) | ||
71 | { | ||
72 | struct device_node *np, *mpscintr, *stdout = NULL; | ||
73 | const char *path; | ||
74 | const phandle *ph; | ||
75 | struct resource r[2]; | ||
76 | const int *block_index; | ||
77 | int intr_cause_offset; | ||
78 | int err; | ||
79 | |||
80 | path = of_get_property(of_chosen, "linux,stdout-path", NULL); | ||
81 | if (!path) | ||
82 | return; | ||
83 | |||
84 | stdout = of_find_node_by_path(path); | ||
85 | if (!stdout) | ||
86 | return; | ||
87 | |||
88 | for_each_compatible_node(np, NULL, "marvell,mv64360-mpsc") { | ||
89 | if (np == stdout) | ||
90 | break; | ||
91 | } | ||
92 | |||
93 | of_node_put(stdout); | ||
94 | if (!np) | ||
95 | return; | ||
96 | |||
97 | block_index = of_get_property(np, "cell-index", NULL); | ||
98 | if (!block_index) | ||
99 | goto error; | ||
100 | |||
101 | switch (*block_index) { | ||
102 | case 0: | ||
103 | intr_cause_offset = MPSC_INTR_CAUSE_OFF_0; | ||
104 | break; | ||
105 | case 1: | ||
106 | intr_cause_offset = MPSC_INTR_CAUSE_OFF_1; | ||
107 | break; | ||
108 | default: | ||
109 | goto error; | ||
110 | } | ||
111 | |||
112 | err = of_address_to_resource(np, 0, &r[0]); | ||
113 | if (err) | ||
114 | goto error; | ||
115 | |||
116 | ph = of_get_property(np, "mpscintr", NULL); | ||
117 | mpscintr = of_find_node_by_phandle(*ph); | ||
118 | if (!mpscintr) | ||
119 | goto error; | ||
120 | |||
121 | err = of_address_to_resource(mpscintr, 0, &r[1]); | ||
122 | of_node_put(mpscintr); | ||
123 | if (err) | ||
124 | goto error; | ||
125 | |||
126 | of_node_put(np); | ||
127 | |||
128 | mpsc_base = ioremap(r[0].start, resource_size(&r[0])); | ||
129 | if (!mpsc_base) | ||
130 | return; | ||
131 | |||
132 | mpsc_intr_cause = ioremap(r[1].start, resource_size(&r[1])); | ||
133 | if (!mpsc_intr_cause) { | ||
134 | iounmap(mpsc_base); | ||
135 | return; | ||
136 | } | ||
137 | mpsc_intr_cause += intr_cause_offset; | ||
138 | |||
139 | udbg_putc = mv64x60_udbg_putc; | ||
140 | udbg_getc = mv64x60_udbg_getc; | ||
141 | udbg_getc_poll = mv64x60_udbg_getc_poll; | ||
142 | |||
143 | return; | ||
144 | |||
145 | error: | ||
146 | of_node_put(np); | ||
147 | } | ||
148 | |||
149 | void mv64x60_init_early(void) | ||
150 | { | ||
151 | mv64x60_udbg_init(); | ||
152 | } | ||
diff --git a/arch/powerpc/sysdev/xics/xics-common.c b/arch/powerpc/sysdev/xics/xics-common.c index 77e864d5506d..f87470319d71 100644 --- a/arch/powerpc/sysdev/xics/xics-common.c +++ b/arch/powerpc/sysdev/xics/xics-common.c | |||
@@ -446,10 +446,11 @@ static void __init xics_get_server_size(void) | |||
446 | np = of_find_compatible_node(NULL, NULL, "ibm,ppc-xics"); | 446 | np = of_find_compatible_node(NULL, NULL, "ibm,ppc-xics"); |
447 | if (!np) | 447 | if (!np) |
448 | return; | 448 | return; |
449 | |||
449 | isize = of_get_property(np, "ibm,interrupt-server#-size", NULL); | 450 | isize = of_get_property(np, "ibm,interrupt-server#-size", NULL); |
450 | if (!isize) | 451 | if (isize) |
451 | return; | 452 | xics_interrupt_server_size = be32_to_cpu(*isize); |
452 | xics_interrupt_server_size = be32_to_cpu(*isize); | 453 | |
453 | of_node_put(np); | 454 | of_node_put(np); |
454 | } | 455 | } |
455 | 456 | ||
diff --git a/arch/powerpc/sysdev/xive/native.c b/arch/powerpc/sysdev/xive/native.c index b48454be5b98..83bcd72b21cf 100644 --- a/arch/powerpc/sysdev/xive/native.c +++ b/arch/powerpc/sysdev/xive/native.c | |||
@@ -341,7 +341,7 @@ static void xive_native_update_pending(struct xive_cpu *xc) | |||
341 | * of the hypervisor interrupt (if any) | 341 | * of the hypervisor interrupt (if any) |
342 | */ | 342 | */ |
343 | cppr = ack & 0xff; | 343 | cppr = ack & 0xff; |
344 | he = GETFIELD(TM_QW3_NSR_HE, (ack >> 8)); | 344 | he = (ack >> 8) >> 6; |
345 | switch(he) { | 345 | switch(he) { |
346 | case TM_QW3_NSR_HE_NONE: /* Nothing to see here */ | 346 | case TM_QW3_NSR_HE_NONE: /* Nothing to see here */ |
347 | break; | 347 | break; |
diff --git a/arch/powerpc/sysdev/xive/spapr.c b/arch/powerpc/sysdev/xive/spapr.c index 091f1d0d0af1..575db3b06a6b 100644 --- a/arch/powerpc/sysdev/xive/spapr.c +++ b/arch/powerpc/sysdev/xive/spapr.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/spinlock.h> | 19 | #include <linux/spinlock.h> |
20 | #include <linux/cpumask.h> | 20 | #include <linux/cpumask.h> |
21 | #include <linux/mm.h> | 21 | #include <linux/mm.h> |
22 | #include <linux/delay.h> | ||
22 | 23 | ||
23 | #include <asm/prom.h> | 24 | #include <asm/prom.h> |
24 | #include <asm/io.h> | 25 | #include <asm/io.h> |
@@ -108,6 +109,51 @@ static void xive_irq_bitmap_free(int irq) | |||
108 | } | 109 | } |
109 | } | 110 | } |
110 | 111 | ||
112 | |||
113 | /* Based on the similar routines in RTAS */ | ||
114 | static unsigned int plpar_busy_delay_time(long rc) | ||
115 | { | ||
116 | unsigned int ms = 0; | ||
117 | |||
118 | if (H_IS_LONG_BUSY(rc)) { | ||
119 | ms = get_longbusy_msecs(rc); | ||
120 | } else if (rc == H_BUSY) { | ||
121 | ms = 10; /* seems appropriate for XIVE hcalls */ | ||
122 | } | ||
123 | |||
124 | return ms; | ||
125 | } | ||
126 | |||
127 | static unsigned int plpar_busy_delay(int rc) | ||
128 | { | ||
129 | unsigned int ms; | ||
130 | |||
131 | ms = plpar_busy_delay_time(rc); | ||
132 | if (ms) | ||
133 | mdelay(ms); | ||
134 | |||
135 | return ms; | ||
136 | } | ||
137 | |||
138 | /* | ||
139 | * Note: this call has a partition wide scope and can take a while to | ||
140 | * complete. If it returns H_LONG_BUSY_* it should be retried | ||
141 | * periodically. | ||
142 | */ | ||
143 | static long plpar_int_reset(unsigned long flags) | ||
144 | { | ||
145 | long rc; | ||
146 | |||
147 | do { | ||
148 | rc = plpar_hcall_norets(H_INT_RESET, flags); | ||
149 | } while (plpar_busy_delay(rc)); | ||
150 | |||
151 | if (rc) | ||
152 | pr_err("H_INT_RESET failed %ld\n", rc); | ||
153 | |||
154 | return rc; | ||
155 | } | ||
156 | |||
111 | static long plpar_int_get_source_info(unsigned long flags, | 157 | static long plpar_int_get_source_info(unsigned long flags, |
112 | unsigned long lisn, | 158 | unsigned long lisn, |
113 | unsigned long *src_flags, | 159 | unsigned long *src_flags, |
@@ -118,7 +164,10 @@ static long plpar_int_get_source_info(unsigned long flags, | |||
118 | unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; | 164 | unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; |
119 | long rc; | 165 | long rc; |
120 | 166 | ||
121 | rc = plpar_hcall(H_INT_GET_SOURCE_INFO, retbuf, flags, lisn); | 167 | do { |
168 | rc = plpar_hcall(H_INT_GET_SOURCE_INFO, retbuf, flags, lisn); | ||
169 | } while (plpar_busy_delay(rc)); | ||
170 | |||
122 | if (rc) { | 171 | if (rc) { |
123 | pr_err("H_INT_GET_SOURCE_INFO lisn=%ld failed %ld\n", lisn, rc); | 172 | pr_err("H_INT_GET_SOURCE_INFO lisn=%ld failed %ld\n", lisn, rc); |
124 | return rc; | 173 | return rc; |
@@ -151,8 +200,11 @@ static long plpar_int_set_source_config(unsigned long flags, | |||
151 | flags, lisn, target, prio, sw_irq); | 200 | flags, lisn, target, prio, sw_irq); |
152 | 201 | ||
153 | 202 | ||
154 | rc = plpar_hcall_norets(H_INT_SET_SOURCE_CONFIG, flags, lisn, | 203 | do { |
155 | target, prio, sw_irq); | 204 | rc = plpar_hcall_norets(H_INT_SET_SOURCE_CONFIG, flags, lisn, |
205 | target, prio, sw_irq); | ||
206 | } while (plpar_busy_delay(rc)); | ||
207 | |||
156 | if (rc) { | 208 | if (rc) { |
157 | pr_err("H_INT_SET_SOURCE_CONFIG lisn=%ld target=%lx prio=%lx failed %ld\n", | 209 | pr_err("H_INT_SET_SOURCE_CONFIG lisn=%ld target=%lx prio=%lx failed %ld\n", |
158 | lisn, target, prio, rc); | 210 | lisn, target, prio, rc); |
@@ -171,7 +223,11 @@ static long plpar_int_get_queue_info(unsigned long flags, | |||
171 | unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; | 223 | unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; |
172 | long rc; | 224 | long rc; |
173 | 225 | ||
174 | rc = plpar_hcall(H_INT_GET_QUEUE_INFO, retbuf, flags, target, priority); | 226 | do { |
227 | rc = plpar_hcall(H_INT_GET_QUEUE_INFO, retbuf, flags, target, | ||
228 | priority); | ||
229 | } while (plpar_busy_delay(rc)); | ||
230 | |||
175 | if (rc) { | 231 | if (rc) { |
176 | pr_err("H_INT_GET_QUEUE_INFO cpu=%ld prio=%ld failed %ld\n", | 232 | pr_err("H_INT_GET_QUEUE_INFO cpu=%ld prio=%ld failed %ld\n", |
177 | target, priority, rc); | 233 | target, priority, rc); |
@@ -200,8 +256,11 @@ static long plpar_int_set_queue_config(unsigned long flags, | |||
200 | pr_devel("H_INT_SET_QUEUE_CONFIG flags=%lx target=%lx priority=%lx qpage=%lx qsize=%lx\n", | 256 | pr_devel("H_INT_SET_QUEUE_CONFIG flags=%lx target=%lx priority=%lx qpage=%lx qsize=%lx\n", |
201 | flags, target, priority, qpage, qsize); | 257 | flags, target, priority, qpage, qsize); |
202 | 258 | ||
203 | rc = plpar_hcall_norets(H_INT_SET_QUEUE_CONFIG, flags, target, | 259 | do { |
204 | priority, qpage, qsize); | 260 | rc = plpar_hcall_norets(H_INT_SET_QUEUE_CONFIG, flags, target, |
261 | priority, qpage, qsize); | ||
262 | } while (plpar_busy_delay(rc)); | ||
263 | |||
205 | if (rc) { | 264 | if (rc) { |
206 | pr_err("H_INT_SET_QUEUE_CONFIG cpu=%ld prio=%ld qpage=%lx returned %ld\n", | 265 | pr_err("H_INT_SET_QUEUE_CONFIG cpu=%ld prio=%ld qpage=%lx returned %ld\n", |
207 | target, priority, qpage, rc); | 266 | target, priority, qpage, rc); |
@@ -215,7 +274,10 @@ static long plpar_int_sync(unsigned long flags, unsigned long lisn) | |||
215 | { | 274 | { |
216 | long rc; | 275 | long rc; |
217 | 276 | ||
218 | rc = plpar_hcall_norets(H_INT_SYNC, flags, lisn); | 277 | do { |
278 | rc = plpar_hcall_norets(H_INT_SYNC, flags, lisn); | ||
279 | } while (plpar_busy_delay(rc)); | ||
280 | |||
219 | if (rc) { | 281 | if (rc) { |
220 | pr_err("H_INT_SYNC lisn=%ld returned %ld\n", lisn, rc); | 282 | pr_err("H_INT_SYNC lisn=%ld returned %ld\n", lisn, rc); |
221 | return rc; | 283 | return rc; |
@@ -238,7 +300,11 @@ static long plpar_int_esb(unsigned long flags, | |||
238 | pr_devel("H_INT_ESB flags=%lx lisn=%lx offset=%lx in=%lx\n", | 300 | pr_devel("H_INT_ESB flags=%lx lisn=%lx offset=%lx in=%lx\n", |
239 | flags, lisn, offset, in_data); | 301 | flags, lisn, offset, in_data); |
240 | 302 | ||
241 | rc = plpar_hcall(H_INT_ESB, retbuf, flags, lisn, offset, in_data); | 303 | do { |
304 | rc = plpar_hcall(H_INT_ESB, retbuf, flags, lisn, offset, | ||
305 | in_data); | ||
306 | } while (plpar_busy_delay(rc)); | ||
307 | |||
242 | if (rc) { | 308 | if (rc) { |
243 | pr_err("H_INT_ESB lisn=%ld offset=%ld returned %ld\n", | 309 | pr_err("H_INT_ESB lisn=%ld offset=%ld returned %ld\n", |
244 | lisn, offset, rc); | 310 | lisn, offset, rc); |
@@ -445,11 +511,7 @@ static void xive_spapr_put_ipi(unsigned int cpu, struct xive_cpu *xc) | |||
445 | 511 | ||
446 | static void xive_spapr_shutdown(void) | 512 | static void xive_spapr_shutdown(void) |
447 | { | 513 | { |
448 | long rc; | 514 | plpar_int_reset(0); |
449 | |||
450 | rc = plpar_hcall_norets(H_INT_RESET, 0); | ||
451 | if (rc) | ||
452 | pr_err("H_INT_RESET failed %ld\n", rc); | ||
453 | } | 515 | } |
454 | 516 | ||
455 | /* | 517 | /* |
diff --git a/arch/powerpc/tools/gcc-check-mprofile-kernel.sh b/arch/powerpc/tools/gcc-check-mprofile-kernel.sh index 061f8035bdbe..a7dd0e5d9f98 100755 --- a/arch/powerpc/tools/gcc-check-mprofile-kernel.sh +++ b/arch/powerpc/tools/gcc-check-mprofile-kernel.sh | |||
@@ -7,17 +7,21 @@ set -o pipefail | |||
7 | # To debug, uncomment the following line | 7 | # To debug, uncomment the following line |
8 | # set -x | 8 | # set -x |
9 | 9 | ||
10 | # -mprofile-kernel is only supported on 64le, so this should not be invoked | ||
11 | # for other targets. Therefore we can pass in -m64 and -mlittle-endian | ||
12 | # explicitly, to take care of toolchains defaulting to other targets. | ||
13 | |||
10 | # Test whether the compile option -mprofile-kernel exists and generates | 14 | # Test whether the compile option -mprofile-kernel exists and generates |
11 | # profiling code (ie. a call to _mcount()). | 15 | # profiling code (ie. a call to _mcount()). |
12 | echo "int func() { return 0; }" | \ | 16 | echo "int func() { return 0; }" | \ |
13 | $* -S -x c -O2 -p -mprofile-kernel - -o - 2> /dev/null | \ | 17 | $* -m64 -mlittle-endian -S -x c -O2 -p -mprofile-kernel - -o - \ |
14 | grep -q "_mcount" | 18 | 2> /dev/null | grep -q "_mcount" |
15 | 19 | ||
16 | # Test whether the notrace attribute correctly suppresses calls to _mcount(). | 20 | # Test whether the notrace attribute correctly suppresses calls to _mcount(). |
17 | 21 | ||
18 | echo -e "#include <linux/compiler.h>\nnotrace int func() { return 0; }" | \ | 22 | echo -e "#include <linux/compiler.h>\nnotrace int func() { return 0; }" | \ |
19 | $* -S -x c -O2 -p -mprofile-kernel - -o - 2> /dev/null | \ | 23 | $* -m64 -mlittle-endian -S -x c -O2 -p -mprofile-kernel - -o - \ |
20 | grep -q "_mcount" && \ | 24 | 2> /dev/null | grep -q "_mcount" && \ |
21 | exit 1 | 25 | exit 1 |
22 | 26 | ||
23 | echo "OK" | 27 | echo "OK" |
diff --git a/arch/powerpc/xmon/nonstdio.h b/arch/powerpc/xmon/nonstdio.h index 2202ec61972c..e8deac6c84e2 100644 --- a/arch/powerpc/xmon/nonstdio.h +++ b/arch/powerpc/xmon/nonstdio.h | |||
@@ -1,13 +1,13 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | #define EOF (-1) | 2 | #define EOF (-1) |
3 | 3 | ||
4 | #define printf xmon_printf | ||
5 | #define putchar xmon_putchar | ||
6 | |||
7 | extern void xmon_set_pagination_lpp(unsigned long lpp); | 4 | extern void xmon_set_pagination_lpp(unsigned long lpp); |
8 | extern void xmon_start_pagination(void); | 5 | extern void xmon_start_pagination(void); |
9 | extern void xmon_end_pagination(void); | 6 | extern void xmon_end_pagination(void); |
10 | extern int xmon_putchar(int c); | 7 | extern int xmon_putchar(int c); |
11 | extern void xmon_puts(const char *); | 8 | extern void xmon_puts(const char *); |
12 | extern char *xmon_gets(char *, int); | 9 | extern char *xmon_gets(char *, int); |
13 | extern void xmon_printf(const char *, ...); | 10 | extern __printf(1, 2) void xmon_printf(const char *fmt, ...); |
11 | |||
12 | #define printf xmon_printf | ||
13 | #define putchar xmon_putchar | ||
diff --git a/arch/powerpc/xmon/spu-dis.c b/arch/powerpc/xmon/spu-dis.c index e5f89837c82e..4cbc7da88524 100644 --- a/arch/powerpc/xmon/spu-dis.c +++ b/arch/powerpc/xmon/spu-dis.c | |||
@@ -102,7 +102,7 @@ print_insn_spu (unsigned long insn, unsigned long memaddr) | |||
102 | 102 | ||
103 | if (index == 0) | 103 | if (index == 0) |
104 | { | 104 | { |
105 | printf(".long 0x%x", insn); | 105 | printf(".long 0x%lx", insn); |
106 | } | 106 | } |
107 | else | 107 | else |
108 | { | 108 | { |
@@ -134,27 +134,27 @@ print_insn_spu (unsigned long insn, unsigned long memaddr) | |||
134 | switch (arg) | 134 | switch (arg) |
135 | { | 135 | { |
136 | case A_T: | 136 | case A_T: |
137 | printf("$%d", | 137 | printf("$%lu", |
138 | DECODE_INSN_RT (insn)); | 138 | DECODE_INSN_RT (insn)); |
139 | break; | 139 | break; |
140 | case A_A: | 140 | case A_A: |
141 | printf("$%d", | 141 | printf("$%lu", |
142 | DECODE_INSN_RA (insn)); | 142 | DECODE_INSN_RA (insn)); |
143 | break; | 143 | break; |
144 | case A_B: | 144 | case A_B: |
145 | printf("$%d", | 145 | printf("$%lu", |
146 | DECODE_INSN_RB (insn)); | 146 | DECODE_INSN_RB (insn)); |
147 | break; | 147 | break; |
148 | case A_C: | 148 | case A_C: |
149 | printf("$%d", | 149 | printf("$%lu", |
150 | DECODE_INSN_RC (insn)); | 150 | DECODE_INSN_RC (insn)); |
151 | break; | 151 | break; |
152 | case A_S: | 152 | case A_S: |
153 | printf("$sp%d", | 153 | printf("$sp%lu", |
154 | DECODE_INSN_RA (insn)); | 154 | DECODE_INSN_RA (insn)); |
155 | break; | 155 | break; |
156 | case A_H: | 156 | case A_H: |
157 | printf("$ch%d", | 157 | printf("$ch%lu", |
158 | DECODE_INSN_RA (insn)); | 158 | DECODE_INSN_RA (insn)); |
159 | break; | 159 | break; |
160 | case A_P: | 160 | case A_P: |
@@ -162,11 +162,11 @@ print_insn_spu (unsigned long insn, unsigned long memaddr) | |||
162 | printf("("); | 162 | printf("("); |
163 | break; | 163 | break; |
164 | case A_U7A: | 164 | case A_U7A: |
165 | printf("%d", | 165 | printf("%lu", |
166 | 173 - DECODE_INSN_U8 (insn)); | 166 | 173 - DECODE_INSN_U8 (insn)); |
167 | break; | 167 | break; |
168 | case A_U7B: | 168 | case A_U7B: |
169 | printf("%d", | 169 | printf("%lu", |
170 | 155 - DECODE_INSN_U8 (insn)); | 170 | 155 - DECODE_INSN_U8 (insn)); |
171 | break; | 171 | break; |
172 | case A_S3: | 172 | case A_S3: |
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index a0842f1ff72c..47166ad2a669 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c | |||
@@ -515,7 +515,7 @@ static int xmon_core(struct pt_regs *regs, int fromipi) | |||
515 | get_output_lock(); | 515 | get_output_lock(); |
516 | excprint(regs); | 516 | excprint(regs); |
517 | if (bp) { | 517 | if (bp) { |
518 | printf("cpu 0x%x stopped at breakpoint 0x%lx (", | 518 | printf("cpu 0x%x stopped at breakpoint 0x%tx (", |
519 | cpu, BP_NUM(bp)); | 519 | cpu, BP_NUM(bp)); |
520 | xmon_print_symbol(regs->nip, " ", ")\n"); | 520 | xmon_print_symbol(regs->nip, " ", ")\n"); |
521 | } | 521 | } |
@@ -622,7 +622,7 @@ static int xmon_core(struct pt_regs *regs, int fromipi) | |||
622 | excprint(regs); | 622 | excprint(regs); |
623 | bp = at_breakpoint(regs->nip); | 623 | bp = at_breakpoint(regs->nip); |
624 | if (bp) { | 624 | if (bp) { |
625 | printf("Stopped at breakpoint %lx (", BP_NUM(bp)); | 625 | printf("Stopped at breakpoint %tx (", BP_NUM(bp)); |
626 | xmon_print_symbol(regs->nip, " ", ")\n"); | 626 | xmon_print_symbol(regs->nip, " ", ")\n"); |
627 | } | 627 | } |
628 | if (unrecoverable_excp(regs)) | 628 | if (unrecoverable_excp(regs)) |
@@ -778,6 +778,16 @@ static int xmon_fault_handler(struct pt_regs *regs) | |||
778 | return 0; | 778 | return 0; |
779 | } | 779 | } |
780 | 780 | ||
781 | /* Force enable xmon if not already enabled */ | ||
782 | static inline void force_enable_xmon(void) | ||
783 | { | ||
784 | /* Enable xmon hooks if needed */ | ||
785 | if (!xmon_on) { | ||
786 | printf("xmon: Enabling debugger hooks\n"); | ||
787 | xmon_on = 1; | ||
788 | } | ||
789 | } | ||
790 | |||
781 | static struct bpt *at_breakpoint(unsigned long pc) | 791 | static struct bpt *at_breakpoint(unsigned long pc) |
782 | { | 792 | { |
783 | int i; | 793 | int i; |
@@ -1094,6 +1104,7 @@ static int do_step(struct pt_regs *regs) | |||
1094 | unsigned int instr; | 1104 | unsigned int instr; |
1095 | int stepped; | 1105 | int stepped; |
1096 | 1106 | ||
1107 | force_enable_xmon(); | ||
1097 | /* check we are in 64-bit kernel mode, translation enabled */ | 1108 | /* check we are in 64-bit kernel mode, translation enabled */ |
1098 | if ((regs->msr & (MSR_64BIT|MSR_PR|MSR_IR)) == (MSR_64BIT|MSR_IR)) { | 1109 | if ((regs->msr & (MSR_64BIT|MSR_PR|MSR_IR)) == (MSR_64BIT|MSR_IR)) { |
1099 | if (mread(regs->nip, &instr, 4) == 4) { | 1110 | if (mread(regs->nip, &instr, 4) == 4) { |
@@ -1160,7 +1171,11 @@ static int cpu_cmd(void) | |||
1160 | } | 1171 | } |
1161 | /* try to switch to cpu specified */ | 1172 | /* try to switch to cpu specified */ |
1162 | if (!cpumask_test_cpu(cpu, &cpus_in_xmon)) { | 1173 | if (!cpumask_test_cpu(cpu, &cpus_in_xmon)) { |
1163 | printf("cpu 0x%x isn't in xmon\n", cpu); | 1174 | printf("cpu 0x%lx isn't in xmon\n", cpu); |
1175 | #ifdef CONFIG_PPC64 | ||
1176 | printf("backtrace of paca[0x%lx].saved_r1 (possibly stale):\n", cpu); | ||
1177 | xmon_show_stack(paca_ptrs[cpu]->saved_r1, 0, 0); | ||
1178 | #endif | ||
1164 | return 0; | 1179 | return 0; |
1165 | } | 1180 | } |
1166 | xmon_taken = 0; | 1181 | xmon_taken = 0; |
@@ -1174,7 +1189,7 @@ static int cpu_cmd(void) | |||
1174 | /* take control back */ | 1189 | /* take control back */ |
1175 | mb(); | 1190 | mb(); |
1176 | xmon_owner = smp_processor_id(); | 1191 | xmon_owner = smp_processor_id(); |
1177 | printf("cpu 0x%x didn't take control\n", cpu); | 1192 | printf("cpu 0x%lx didn't take control\n", cpu); |
1178 | return 0; | 1193 | return 0; |
1179 | } | 1194 | } |
1180 | barrier(); | 1195 | barrier(); |
@@ -1268,16 +1283,6 @@ static long check_bp_loc(unsigned long addr) | |||
1268 | return 1; | 1283 | return 1; |
1269 | } | 1284 | } |
1270 | 1285 | ||
1271 | /* Force enable xmon if not already enabled */ | ||
1272 | static inline void force_enable_xmon(void) | ||
1273 | { | ||
1274 | /* Enable xmon hooks if needed */ | ||
1275 | if (!xmon_on) { | ||
1276 | printf("xmon: Enabling debugger hooks\n"); | ||
1277 | xmon_on = 1; | ||
1278 | } | ||
1279 | } | ||
1280 | |||
1281 | static char *breakpoint_help_string = | 1286 | static char *breakpoint_help_string = |
1282 | "Breakpoint command usage:\n" | 1287 | "Breakpoint command usage:\n" |
1283 | "b show breakpoints\n" | 1288 | "b show breakpoints\n" |
@@ -1374,7 +1379,7 @@ bpt_cmds(void) | |||
1374 | } | 1379 | } |
1375 | } | 1380 | } |
1376 | 1381 | ||
1377 | printf("Cleared breakpoint %lx (", BP_NUM(bp)); | 1382 | printf("Cleared breakpoint %tx (", BP_NUM(bp)); |
1378 | xmon_print_symbol(bp->address, " ", ")\n"); | 1383 | xmon_print_symbol(bp->address, " ", ")\n"); |
1379 | bp->enabled = 0; | 1384 | bp->enabled = 0; |
1380 | break; | 1385 | break; |
@@ -1401,7 +1406,7 @@ bpt_cmds(void) | |||
1401 | for (bp = bpts; bp < &bpts[NBPTS]; ++bp) { | 1406 | for (bp = bpts; bp < &bpts[NBPTS]; ++bp) { |
1402 | if (!bp->enabled) | 1407 | if (!bp->enabled) |
1403 | continue; | 1408 | continue; |
1404 | printf("%2x %s ", BP_NUM(bp), | 1409 | printf("%tx %s ", BP_NUM(bp), |
1405 | (bp->enabled & BP_CIABR) ? "inst": "trap"); | 1410 | (bp->enabled & BP_CIABR) ? "inst": "trap"); |
1406 | xmon_print_symbol(bp->address, " ", "\n"); | 1411 | xmon_print_symbol(bp->address, " ", "\n"); |
1407 | } | 1412 | } |
@@ -1618,11 +1623,11 @@ static void excprint(struct pt_regs *fp) | |||
1618 | #endif /* CONFIG_SMP */ | 1623 | #endif /* CONFIG_SMP */ |
1619 | 1624 | ||
1620 | trap = TRAP(fp); | 1625 | trap = TRAP(fp); |
1621 | printf("Vector: %lx %s at [%lx]\n", fp->trap, getvecname(trap), fp); | 1626 | printf("Vector: %lx %s at [%px]\n", fp->trap, getvecname(trap), fp); |
1622 | printf(" pc: "); | 1627 | printf(" pc: "); |
1623 | xmon_print_symbol(fp->nip, ": ", "\n"); | 1628 | xmon_print_symbol(fp->nip, ": ", "\n"); |
1624 | 1629 | ||
1625 | printf(" lr: ", fp->link); | 1630 | printf(" lr: "); |
1626 | xmon_print_symbol(fp->link, ": ", "\n"); | 1631 | xmon_print_symbol(fp->link, ": ", "\n"); |
1627 | 1632 | ||
1628 | printf(" sp: %lx\n", fp->gpr[1]); | 1633 | printf(" sp: %lx\n", fp->gpr[1]); |
@@ -1634,13 +1639,13 @@ static void excprint(struct pt_regs *fp) | |||
1634 | printf(" dsisr: %lx\n", fp->dsisr); | 1639 | printf(" dsisr: %lx\n", fp->dsisr); |
1635 | } | 1640 | } |
1636 | 1641 | ||
1637 | printf(" current = 0x%lx\n", current); | 1642 | printf(" current = 0x%px\n", current); |
1638 | #ifdef CONFIG_PPC64 | 1643 | #ifdef CONFIG_PPC64 |
1639 | printf(" paca = 0x%lx\t softe: %d\t irq_happened: 0x%02x\n", | 1644 | printf(" paca = 0x%px\t irqmask: 0x%02x\t irq_happened: 0x%02x\n", |
1640 | local_paca, local_paca->irq_soft_mask, local_paca->irq_happened); | 1645 | local_paca, local_paca->irq_soft_mask, local_paca->irq_happened); |
1641 | #endif | 1646 | #endif |
1642 | if (current) { | 1647 | if (current) { |
1643 | printf(" pid = %ld, comm = %s\n", | 1648 | printf(" pid = %d, comm = %s\n", |
1644 | current->pid, current->comm); | 1649 | current->pid, current->comm); |
1645 | } | 1650 | } |
1646 | 1651 | ||
@@ -1676,16 +1681,16 @@ static void prregs(struct pt_regs *fp) | |||
1676 | #ifdef CONFIG_PPC64 | 1681 | #ifdef CONFIG_PPC64 |
1677 | if (FULL_REGS(fp)) { | 1682 | if (FULL_REGS(fp)) { |
1678 | for (n = 0; n < 16; ++n) | 1683 | for (n = 0; n < 16; ++n) |
1679 | printf("R%.2ld = "REG" R%.2ld = "REG"\n", | 1684 | printf("R%.2d = "REG" R%.2d = "REG"\n", |
1680 | n, fp->gpr[n], n+16, fp->gpr[n+16]); | 1685 | n, fp->gpr[n], n+16, fp->gpr[n+16]); |
1681 | } else { | 1686 | } else { |
1682 | for (n = 0; n < 7; ++n) | 1687 | for (n = 0; n < 7; ++n) |
1683 | printf("R%.2ld = "REG" R%.2ld = "REG"\n", | 1688 | printf("R%.2d = "REG" R%.2d = "REG"\n", |
1684 | n, fp->gpr[n], n+7, fp->gpr[n+7]); | 1689 | n, fp->gpr[n], n+7, fp->gpr[n+7]); |
1685 | } | 1690 | } |
1686 | #else | 1691 | #else |
1687 | for (n = 0; n < 32; ++n) { | 1692 | for (n = 0; n < 32; ++n) { |
1688 | printf("R%.2d = %.8x%s", n, fp->gpr[n], | 1693 | printf("R%.2d = %.8lx%s", n, fp->gpr[n], |
1689 | (n & 3) == 3? "\n": " "); | 1694 | (n & 3) == 3? "\n": " "); |
1690 | if (n == 12 && !FULL_REGS(fp)) { | 1695 | if (n == 12 && !FULL_REGS(fp)) { |
1691 | printf("\n"); | 1696 | printf("\n"); |
@@ -1789,9 +1794,9 @@ static void dump_206_sprs(void) | |||
1789 | 1794 | ||
1790 | /* Actually some of these pre-date 2.06, but whatevs */ | 1795 | /* Actually some of these pre-date 2.06, but whatevs */ |
1791 | 1796 | ||
1792 | printf("srr0 = %.16lx srr1 = %.16lx dsisr = %.8x\n", | 1797 | printf("srr0 = %.16lx srr1 = %.16lx dsisr = %.8lx\n", |
1793 | mfspr(SPRN_SRR0), mfspr(SPRN_SRR1), mfspr(SPRN_DSISR)); | 1798 | mfspr(SPRN_SRR0), mfspr(SPRN_SRR1), mfspr(SPRN_DSISR)); |
1794 | printf("dscr = %.16lx ppr = %.16lx pir = %.8x\n", | 1799 | printf("dscr = %.16lx ppr = %.16lx pir = %.8lx\n", |
1795 | mfspr(SPRN_DSCR), mfspr(SPRN_PPR), mfspr(SPRN_PIR)); | 1800 | mfspr(SPRN_DSCR), mfspr(SPRN_PPR), mfspr(SPRN_PIR)); |
1796 | printf("amr = %.16lx uamor = %.16lx\n", | 1801 | printf("amr = %.16lx uamor = %.16lx\n", |
1797 | mfspr(SPRN_AMR), mfspr(SPRN_UAMOR)); | 1802 | mfspr(SPRN_AMR), mfspr(SPRN_UAMOR)); |
@@ -1799,11 +1804,11 @@ static void dump_206_sprs(void) | |||
1799 | if (!(mfmsr() & MSR_HV)) | 1804 | if (!(mfmsr() & MSR_HV)) |
1800 | return; | 1805 | return; |
1801 | 1806 | ||
1802 | printf("sdr1 = %.16lx hdar = %.16lx hdsisr = %.8x\n", | 1807 | printf("sdr1 = %.16lx hdar = %.16lx hdsisr = %.8lx\n", |
1803 | mfspr(SPRN_SDR1), mfspr(SPRN_HDAR), mfspr(SPRN_HDSISR)); | 1808 | mfspr(SPRN_SDR1), mfspr(SPRN_HDAR), mfspr(SPRN_HDSISR)); |
1804 | printf("hsrr0 = %.16lx hsrr1 = %.16lx hdec = %.16lx\n", | 1809 | printf("hsrr0 = %.16lx hsrr1 = %.16lx hdec = %.16lx\n", |
1805 | mfspr(SPRN_HSRR0), mfspr(SPRN_HSRR1), mfspr(SPRN_HDEC)); | 1810 | mfspr(SPRN_HSRR0), mfspr(SPRN_HSRR1), mfspr(SPRN_HDEC)); |
1806 | printf("lpcr = %.16lx pcr = %.16lx lpidr = %.8x\n", | 1811 | printf("lpcr = %.16lx pcr = %.16lx lpidr = %.8lx\n", |
1807 | mfspr(SPRN_LPCR), mfspr(SPRN_PCR), mfspr(SPRN_LPID)); | 1812 | mfspr(SPRN_LPCR), mfspr(SPRN_PCR), mfspr(SPRN_LPID)); |
1808 | printf("hsprg0 = %.16lx hsprg1 = %.16lx amor = %.16lx\n", | 1813 | printf("hsprg0 = %.16lx hsprg1 = %.16lx amor = %.16lx\n", |
1809 | mfspr(SPRN_HSPRG0), mfspr(SPRN_HSPRG1), mfspr(SPRN_AMOR)); | 1814 | mfspr(SPRN_HSPRG0), mfspr(SPRN_HSPRG1), mfspr(SPRN_AMOR)); |
@@ -1820,10 +1825,10 @@ static void dump_207_sprs(void) | |||
1820 | if (!cpu_has_feature(CPU_FTR_ARCH_207S)) | 1825 | if (!cpu_has_feature(CPU_FTR_ARCH_207S)) |
1821 | return; | 1826 | return; |
1822 | 1827 | ||
1823 | printf("dpdes = %.16lx tir = %.16lx cir = %.8x\n", | 1828 | printf("dpdes = %.16lx tir = %.16lx cir = %.8lx\n", |
1824 | mfspr(SPRN_DPDES), mfspr(SPRN_TIR), mfspr(SPRN_CIR)); | 1829 | mfspr(SPRN_DPDES), mfspr(SPRN_TIR), mfspr(SPRN_CIR)); |
1825 | 1830 | ||
1826 | printf("fscr = %.16lx tar = %.16lx pspb = %.8x\n", | 1831 | printf("fscr = %.16lx tar = %.16lx pspb = %.8lx\n", |
1827 | mfspr(SPRN_FSCR), mfspr(SPRN_TAR), mfspr(SPRN_PSPB)); | 1832 | mfspr(SPRN_FSCR), mfspr(SPRN_TAR), mfspr(SPRN_PSPB)); |
1828 | 1833 | ||
1829 | msr = mfmsr(); | 1834 | msr = mfmsr(); |
@@ -1836,12 +1841,12 @@ static void dump_207_sprs(void) | |||
1836 | 1841 | ||
1837 | printf("mmcr0 = %.16lx mmcr1 = %.16lx mmcr2 = %.16lx\n", | 1842 | printf("mmcr0 = %.16lx mmcr1 = %.16lx mmcr2 = %.16lx\n", |
1838 | mfspr(SPRN_MMCR0), mfspr(SPRN_MMCR1), mfspr(SPRN_MMCR2)); | 1843 | mfspr(SPRN_MMCR0), mfspr(SPRN_MMCR1), mfspr(SPRN_MMCR2)); |
1839 | printf("pmc1 = %.8x pmc2 = %.8x pmc3 = %.8x pmc4 = %.8x\n", | 1844 | printf("pmc1 = %.8lx pmc2 = %.8lx pmc3 = %.8lx pmc4 = %.8lx\n", |
1840 | mfspr(SPRN_PMC1), mfspr(SPRN_PMC2), | 1845 | mfspr(SPRN_PMC1), mfspr(SPRN_PMC2), |
1841 | mfspr(SPRN_PMC3), mfspr(SPRN_PMC4)); | 1846 | mfspr(SPRN_PMC3), mfspr(SPRN_PMC4)); |
1842 | printf("mmcra = %.16lx siar = %.16lx pmc5 = %.8x\n", | 1847 | printf("mmcra = %.16lx siar = %.16lx pmc5 = %.8lx\n", |
1843 | mfspr(SPRN_MMCRA), mfspr(SPRN_SIAR), mfspr(SPRN_PMC5)); | 1848 | mfspr(SPRN_MMCRA), mfspr(SPRN_SIAR), mfspr(SPRN_PMC5)); |
1844 | printf("sdar = %.16lx sier = %.16lx pmc6 = %.8x\n", | 1849 | printf("sdar = %.16lx sier = %.16lx pmc6 = %.8lx\n", |
1845 | mfspr(SPRN_SDAR), mfspr(SPRN_SIER), mfspr(SPRN_PMC6)); | 1850 | mfspr(SPRN_SDAR), mfspr(SPRN_SIER), mfspr(SPRN_PMC6)); |
1846 | printf("ebbhr = %.16lx ebbrr = %.16lx bescr = %.16lx\n", | 1851 | printf("ebbhr = %.16lx ebbrr = %.16lx bescr = %.16lx\n", |
1847 | mfspr(SPRN_EBBHR), mfspr(SPRN_EBBRR), mfspr(SPRN_BESCR)); | 1852 | mfspr(SPRN_EBBHR), mfspr(SPRN_EBBRR), mfspr(SPRN_BESCR)); |
@@ -2345,31 +2350,31 @@ static void dump_one_paca(int cpu) | |||
2345 | 2350 | ||
2346 | printf("paca for cpu 0x%x @ %px:\n", cpu, p); | 2351 | printf("paca for cpu 0x%x @ %px:\n", cpu, p); |
2347 | 2352 | ||
2348 | printf(" %-*s = %s\n", 20, "possible", cpu_possible(cpu) ? "yes" : "no"); | 2353 | printf(" %-*s = %s\n", 25, "possible", cpu_possible(cpu) ? "yes" : "no"); |
2349 | printf(" %-*s = %s\n", 20, "present", cpu_present(cpu) ? "yes" : "no"); | 2354 | printf(" %-*s = %s\n", 25, "present", cpu_present(cpu) ? "yes" : "no"); |
2350 | printf(" %-*s = %s\n", 20, "online", cpu_online(cpu) ? "yes" : "no"); | 2355 | printf(" %-*s = %s\n", 25, "online", cpu_online(cpu) ? "yes" : "no"); |
2351 | 2356 | ||
2352 | #define DUMP(paca, name, format) \ | 2357 | #define DUMP(paca, name, format) \ |
2353 | printf(" %-*s = %#-*"format"\t(0x%lx)\n", 20, #name, 18, paca->name, \ | 2358 | printf(" %-*s = "format"\t(0x%lx)\n", 25, #name, 18, paca->name, \ |
2354 | offsetof(struct paca_struct, name)); | 2359 | offsetof(struct paca_struct, name)); |
2355 | 2360 | ||
2356 | DUMP(p, lock_token, "x"); | 2361 | DUMP(p, lock_token, "%#-*x"); |
2357 | DUMP(p, paca_index, "x"); | 2362 | DUMP(p, paca_index, "%#-*x"); |
2358 | DUMP(p, kernel_toc, "lx"); | 2363 | DUMP(p, kernel_toc, "%#-*llx"); |
2359 | DUMP(p, kernelbase, "lx"); | 2364 | DUMP(p, kernelbase, "%#-*llx"); |
2360 | DUMP(p, kernel_msr, "lx"); | 2365 | DUMP(p, kernel_msr, "%#-*llx"); |
2361 | DUMP(p, emergency_sp, "px"); | 2366 | DUMP(p, emergency_sp, "%-*px"); |
2362 | #ifdef CONFIG_PPC_BOOK3S_64 | 2367 | #ifdef CONFIG_PPC_BOOK3S_64 |
2363 | DUMP(p, nmi_emergency_sp, "px"); | 2368 | DUMP(p, nmi_emergency_sp, "%-*px"); |
2364 | DUMP(p, mc_emergency_sp, "px"); | 2369 | DUMP(p, mc_emergency_sp, "%-*px"); |
2365 | DUMP(p, in_nmi, "x"); | 2370 | DUMP(p, in_nmi, "%#-*x"); |
2366 | DUMP(p, in_mce, "x"); | 2371 | DUMP(p, in_mce, "%#-*x"); |
2367 | DUMP(p, hmi_event_available, "x"); | 2372 | DUMP(p, hmi_event_available, "%#-*x"); |
2368 | #endif | 2373 | #endif |
2369 | DUMP(p, data_offset, "lx"); | 2374 | DUMP(p, data_offset, "%#-*llx"); |
2370 | DUMP(p, hw_cpu_id, "x"); | 2375 | DUMP(p, hw_cpu_id, "%#-*x"); |
2371 | DUMP(p, cpu_start, "x"); | 2376 | DUMP(p, cpu_start, "%#-*x"); |
2372 | DUMP(p, kexec_state, "x"); | 2377 | DUMP(p, kexec_state, "%#-*x"); |
2373 | #ifdef CONFIG_PPC_BOOK3S_64 | 2378 | #ifdef CONFIG_PPC_BOOK3S_64 |
2374 | for (i = 0; i < SLB_NUM_BOLTED; i++) { | 2379 | for (i = 0; i < SLB_NUM_BOLTED; i++) { |
2375 | u64 esid, vsid; | 2380 | u64 esid, vsid; |
@@ -2381,58 +2386,69 @@ static void dump_one_paca(int cpu) | |||
2381 | vsid = be64_to_cpu(p->slb_shadow_ptr->save_area[i].vsid); | 2386 | vsid = be64_to_cpu(p->slb_shadow_ptr->save_area[i].vsid); |
2382 | 2387 | ||
2383 | if (esid || vsid) { | 2388 | if (esid || vsid) { |
2384 | printf(" slb_shadow[%d]: = 0x%016lx 0x%016lx\n", | 2389 | printf(" %-*s[%d] = 0x%016llx 0x%016llx\n", |
2385 | i, esid, vsid); | 2390 | 22, "slb_shadow", i, esid, vsid); |
2386 | } | 2391 | } |
2387 | } | 2392 | } |
2388 | DUMP(p, vmalloc_sllp, "x"); | 2393 | DUMP(p, vmalloc_sllp, "%#-*x"); |
2389 | DUMP(p, slb_cache_ptr, "x"); | 2394 | DUMP(p, slb_cache_ptr, "%#-*x"); |
2390 | for (i = 0; i < SLB_CACHE_ENTRIES; i++) | 2395 | for (i = 0; i < SLB_CACHE_ENTRIES; i++) |
2391 | printf(" slb_cache[%d]: = 0x%016lx\n", i, p->slb_cache[i]); | 2396 | printf(" %-*s[%d] = 0x%016x\n", |
2397 | 22, "slb_cache", i, p->slb_cache[i]); | ||
2392 | 2398 | ||
2393 | DUMP(p, rfi_flush_fallback_area, "px"); | 2399 | DUMP(p, rfi_flush_fallback_area, "%-*px"); |
2394 | #endif | 2400 | #endif |
2395 | DUMP(p, dscr_default, "llx"); | 2401 | DUMP(p, dscr_default, "%#-*llx"); |
2396 | #ifdef CONFIG_PPC_BOOK3E | 2402 | #ifdef CONFIG_PPC_BOOK3E |
2397 | DUMP(p, pgd, "px"); | 2403 | DUMP(p, pgd, "%-*px"); |
2398 | DUMP(p, kernel_pgd, "px"); | 2404 | DUMP(p, kernel_pgd, "%-*px"); |
2399 | DUMP(p, tcd_ptr, "px"); | 2405 | DUMP(p, tcd_ptr, "%-*px"); |
2400 | DUMP(p, mc_kstack, "px"); | 2406 | DUMP(p, mc_kstack, "%-*px"); |
2401 | DUMP(p, crit_kstack, "px"); | 2407 | DUMP(p, crit_kstack, "%-*px"); |
2402 | DUMP(p, dbg_kstack, "px"); | 2408 | DUMP(p, dbg_kstack, "%-*px"); |
2403 | #endif | 2409 | #endif |
2404 | DUMP(p, __current, "px"); | 2410 | DUMP(p, __current, "%-*px"); |
2405 | DUMP(p, kstack, "lx"); | 2411 | DUMP(p, kstack, "%#-*llx"); |
2406 | printf(" kstack_base = 0x%016lx\n", p->kstack & ~(THREAD_SIZE - 1)); | 2412 | printf(" %-*s = 0x%016llx\n", 25, "kstack_base", p->kstack & ~(THREAD_SIZE - 1)); |
2407 | DUMP(p, stab_rr, "lx"); | 2413 | DUMP(p, stab_rr, "%#-*llx"); |
2408 | DUMP(p, saved_r1, "lx"); | 2414 | DUMP(p, saved_r1, "%#-*llx"); |
2409 | DUMP(p, trap_save, "x"); | 2415 | DUMP(p, trap_save, "%#-*x"); |
2410 | DUMP(p, irq_soft_mask, "x"); | 2416 | DUMP(p, irq_soft_mask, "%#-*x"); |
2411 | DUMP(p, irq_happened, "x"); | 2417 | DUMP(p, irq_happened, "%#-*x"); |
2412 | DUMP(p, io_sync, "x"); | 2418 | DUMP(p, io_sync, "%#-*x"); |
2413 | DUMP(p, irq_work_pending, "x"); | 2419 | DUMP(p, irq_work_pending, "%#-*x"); |
2414 | DUMP(p, nap_state_lost, "x"); | 2420 | DUMP(p, nap_state_lost, "%#-*x"); |
2415 | DUMP(p, sprg_vdso, "llx"); | 2421 | DUMP(p, sprg_vdso, "%#-*llx"); |
2416 | 2422 | ||
2417 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | 2423 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM |
2418 | DUMP(p, tm_scratch, "llx"); | 2424 | DUMP(p, tm_scratch, "%#-*llx"); |
2419 | #endif | 2425 | #endif |
2420 | 2426 | ||
2421 | #ifdef CONFIG_PPC_POWERNV | 2427 | #ifdef CONFIG_PPC_POWERNV |
2422 | DUMP(p, core_idle_state_ptr, "px"); | 2428 | DUMP(p, core_idle_state_ptr, "%-*px"); |
2423 | DUMP(p, thread_idle_state, "x"); | 2429 | DUMP(p, thread_idle_state, "%#-*x"); |
2424 | DUMP(p, thread_mask, "x"); | 2430 | DUMP(p, thread_mask, "%#-*x"); |
2425 | DUMP(p, subcore_sibling_mask, "x"); | 2431 | DUMP(p, subcore_sibling_mask, "%#-*x"); |
2432 | DUMP(p, thread_sibling_pacas, "%-*px"); | ||
2433 | DUMP(p, requested_psscr, "%#-*llx"); | ||
2434 | DUMP(p, stop_sprs.pid, "%#-*llx"); | ||
2435 | DUMP(p, stop_sprs.ldbar, "%#-*llx"); | ||
2436 | DUMP(p, stop_sprs.fscr, "%#-*llx"); | ||
2437 | DUMP(p, stop_sprs.hfscr, "%#-*llx"); | ||
2438 | DUMP(p, stop_sprs.mmcr1, "%#-*llx"); | ||
2439 | DUMP(p, stop_sprs.mmcr2, "%#-*llx"); | ||
2440 | DUMP(p, stop_sprs.mmcra, "%#-*llx"); | ||
2441 | DUMP(p, dont_stop.counter, "%#-*x"); | ||
2426 | #endif | 2442 | #endif |
2427 | 2443 | ||
2428 | DUMP(p, accounting.utime, "llx"); | 2444 | DUMP(p, accounting.utime, "%#-*lx"); |
2429 | DUMP(p, accounting.stime, "llx"); | 2445 | DUMP(p, accounting.stime, "%#-*lx"); |
2430 | DUMP(p, accounting.utime_scaled, "llx"); | 2446 | DUMP(p, accounting.utime_scaled, "%#-*lx"); |
2431 | DUMP(p, accounting.starttime, "llx"); | 2447 | DUMP(p, accounting.starttime, "%#-*lx"); |
2432 | DUMP(p, accounting.starttime_user, "llx"); | 2448 | DUMP(p, accounting.starttime_user, "%#-*lx"); |
2433 | DUMP(p, accounting.startspurr, "llx"); | 2449 | DUMP(p, accounting.startspurr, "%#-*lx"); |
2434 | DUMP(p, accounting.utime_sspurr, "llx"); | 2450 | DUMP(p, accounting.utime_sspurr, "%#-*lx"); |
2435 | DUMP(p, accounting.steal_time, "llx"); | 2451 | DUMP(p, accounting.steal_time, "%#-*lx"); |
2436 | #undef DUMP | 2452 | #undef DUMP |
2437 | 2453 | ||
2438 | catch_memory_errors = 0; | 2454 | catch_memory_errors = 0; |
@@ -2578,7 +2594,7 @@ static void dump_by_size(unsigned long addr, long count, int size) | |||
2578 | default: val = 0; | 2594 | default: val = 0; |
2579 | } | 2595 | } |
2580 | 2596 | ||
2581 | printf("%0*lx", size * 2, val); | 2597 | printf("%0*llx", size * 2, val); |
2582 | } | 2598 | } |
2583 | printf("\n"); | 2599 | printf("\n"); |
2584 | } | 2600 | } |
@@ -2742,7 +2758,7 @@ generic_inst_dump(unsigned long adr, long count, int praddr, | |||
2742 | dotted = 0; | 2758 | dotted = 0; |
2743 | last_inst = inst; | 2759 | last_inst = inst; |
2744 | if (praddr) | 2760 | if (praddr) |
2745 | printf(REG" %.8x", adr, inst); | 2761 | printf(REG" %.8lx", adr, inst); |
2746 | printf("\t"); | 2762 | printf("\t"); |
2747 | dump_func(inst, adr); | 2763 | dump_func(inst, adr); |
2748 | printf("\n"); | 2764 | printf("\n"); |
@@ -2874,7 +2890,7 @@ memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr) | |||
2874 | for( n = nb; n > 0; --n ) | 2890 | for( n = nb; n > 0; --n ) |
2875 | if( *p1++ != *p2++ ) | 2891 | if( *p1++ != *p2++ ) |
2876 | if( ++prt <= maxpr ) | 2892 | if( ++prt <= maxpr ) |
2877 | printf("%.16x %.2x # %.16x %.2x\n", p1 - 1, | 2893 | printf("%px %.2x # %px %.2x\n", p1 - 1, |
2878 | p1[-1], p2 - 1, p2[-1]); | 2894 | p1[-1], p2 - 1, p2[-1]); |
2879 | if( prt > maxpr ) | 2895 | if( prt > maxpr ) |
2880 | printf("Total of %d differences\n", prt); | 2896 | printf("Total of %d differences\n", prt); |
@@ -2934,13 +2950,13 @@ memzcan(void) | |||
2934 | if (ok && !ook) { | 2950 | if (ok && !ook) { |
2935 | printf("%.8x .. ", a); | 2951 | printf("%.8x .. ", a); |
2936 | } else if (!ok && ook) | 2952 | } else if (!ok && ook) |
2937 | printf("%.8x\n", a - mskip); | 2953 | printf("%.8lx\n", a - mskip); |
2938 | ook = ok; | 2954 | ook = ok; |
2939 | if (a + mskip < a) | 2955 | if (a + mskip < a) |
2940 | break; | 2956 | break; |
2941 | } | 2957 | } |
2942 | if (ook) | 2958 | if (ook) |
2943 | printf("%.8x\n", a - mskip); | 2959 | printf("%.8lx\n", a - mskip); |
2944 | } | 2960 | } |
2945 | 2961 | ||
2946 | static void show_task(struct task_struct *tsk) | 2962 | static void show_task(struct task_struct *tsk) |
@@ -3024,13 +3040,13 @@ static void show_pte(unsigned long addr) | |||
3024 | return; | 3040 | return; |
3025 | } | 3041 | } |
3026 | 3042 | ||
3027 | printf("pgd @ 0x%016lx\n", pgdir); | 3043 | printf("pgd @ 0x%px\n", pgdir); |
3028 | 3044 | ||
3029 | if (pgd_huge(*pgdp)) { | 3045 | if (pgd_huge(*pgdp)) { |
3030 | format_pte(pgdp, pgd_val(*pgdp)); | 3046 | format_pte(pgdp, pgd_val(*pgdp)); |
3031 | return; | 3047 | return; |
3032 | } | 3048 | } |
3033 | printf("pgdp @ 0x%016lx = 0x%016lx\n", pgdp, pgd_val(*pgdp)); | 3049 | printf("pgdp @ 0x%px = 0x%016lx\n", pgdp, pgd_val(*pgdp)); |
3034 | 3050 | ||
3035 | pudp = pud_offset(pgdp, addr); | 3051 | pudp = pud_offset(pgdp, addr); |
3036 | 3052 | ||
@@ -3044,7 +3060,7 @@ static void show_pte(unsigned long addr) | |||
3044 | return; | 3060 | return; |
3045 | } | 3061 | } |
3046 | 3062 | ||
3047 | printf("pudp @ 0x%016lx = 0x%016lx\n", pudp, pud_val(*pudp)); | 3063 | printf("pudp @ 0x%px = 0x%016lx\n", pudp, pud_val(*pudp)); |
3048 | 3064 | ||
3049 | pmdp = pmd_offset(pudp, addr); | 3065 | pmdp = pmd_offset(pudp, addr); |
3050 | 3066 | ||
@@ -3057,7 +3073,7 @@ static void show_pte(unsigned long addr) | |||
3057 | format_pte(pmdp, pmd_val(*pmdp)); | 3073 | format_pte(pmdp, pmd_val(*pmdp)); |
3058 | return; | 3074 | return; |
3059 | } | 3075 | } |
3060 | printf("pmdp @ 0x%016lx = 0x%016lx\n", pmdp, pmd_val(*pmdp)); | 3076 | printf("pmdp @ 0x%px = 0x%016lx\n", pmdp, pmd_val(*pmdp)); |
3061 | 3077 | ||
3062 | ptep = pte_offset_map(pmdp, addr); | 3078 | ptep = pte_offset_map(pmdp, addr); |
3063 | if (pte_none(*ptep)) { | 3079 | if (pte_none(*ptep)) { |
@@ -3161,7 +3177,7 @@ skipbl(void) | |||
3161 | } | 3177 | } |
3162 | 3178 | ||
3163 | #define N_PTREGS 44 | 3179 | #define N_PTREGS 44 |
3164 | static char *regnames[N_PTREGS] = { | 3180 | static const char *regnames[N_PTREGS] = { |
3165 | "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", | 3181 | "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", |
3166 | "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", | 3182 | "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", |
3167 | "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", | 3183 | "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", |
@@ -3196,18 +3212,17 @@ scanhex(unsigned long *vp) | |||
3196 | regname[i] = c; | 3212 | regname[i] = c; |
3197 | } | 3213 | } |
3198 | regname[i] = 0; | 3214 | regname[i] = 0; |
3199 | for (i = 0; i < N_PTREGS; ++i) { | 3215 | i = match_string(regnames, N_PTREGS, regname); |
3200 | if (strcmp(regnames[i], regname) == 0) { | 3216 | if (i < 0) { |
3201 | if (xmon_regs == NULL) { | 3217 | printf("invalid register name '%%%s'\n", regname); |
3202 | printf("regs not available\n"); | 3218 | return 0; |
3203 | return 0; | ||
3204 | } | ||
3205 | *vp = ((unsigned long *)xmon_regs)[i]; | ||
3206 | return 1; | ||
3207 | } | ||
3208 | } | 3219 | } |
3209 | printf("invalid register name '%%%s'\n", regname); | 3220 | if (xmon_regs == NULL) { |
3210 | return 0; | 3221 | printf("regs not available\n"); |
3222 | return 0; | ||
3223 | } | ||
3224 | *vp = ((unsigned long *)xmon_regs)[i]; | ||
3225 | return 1; | ||
3211 | } | 3226 | } |
3212 | 3227 | ||
3213 | /* skip leading "0x" if any */ | 3228 | /* skip leading "0x" if any */ |
@@ -3456,9 +3471,9 @@ static void dump_tlb_44x(void) | |||
3456 | asm volatile("tlbre %0,%1,0" : "=r" (w0) : "r" (i)); | 3471 | asm volatile("tlbre %0,%1,0" : "=r" (w0) : "r" (i)); |
3457 | asm volatile("tlbre %0,%1,1" : "=r" (w1) : "r" (i)); | 3472 | asm volatile("tlbre %0,%1,1" : "=r" (w1) : "r" (i)); |
3458 | asm volatile("tlbre %0,%1,2" : "=r" (w2) : "r" (i)); | 3473 | asm volatile("tlbre %0,%1,2" : "=r" (w2) : "r" (i)); |
3459 | printf("[%02x] %08x %08x %08x ", i, w0, w1, w2); | 3474 | printf("[%02x] %08lx %08lx %08lx ", i, w0, w1, w2); |
3460 | if (w0 & PPC44x_TLB_VALID) { | 3475 | if (w0 & PPC44x_TLB_VALID) { |
3461 | printf("V %08x -> %01x%08x %c%c%c%c%c", | 3476 | printf("V %08lx -> %01lx%08lx %c%c%c%c%c", |
3462 | w0 & PPC44x_TLB_EPN_MASK, | 3477 | w0 & PPC44x_TLB_EPN_MASK, |
3463 | w1 & PPC44x_TLB_ERPN_MASK, | 3478 | w1 & PPC44x_TLB_ERPN_MASK, |
3464 | w1 & PPC44x_TLB_RPN_MASK, | 3479 | w1 & PPC44x_TLB_RPN_MASK, |
@@ -3882,19 +3897,19 @@ static void dump_spu_fields(struct spu *spu) | |||
3882 | DUMP_FIELD(spu, "0x%lx", ls_size); | 3897 | DUMP_FIELD(spu, "0x%lx", ls_size); |
3883 | DUMP_FIELD(spu, "0x%x", node); | 3898 | DUMP_FIELD(spu, "0x%x", node); |
3884 | DUMP_FIELD(spu, "0x%lx", flags); | 3899 | DUMP_FIELD(spu, "0x%lx", flags); |
3885 | DUMP_FIELD(spu, "%d", class_0_pending); | 3900 | DUMP_FIELD(spu, "%llu", class_0_pending); |
3886 | DUMP_FIELD(spu, "0x%lx", class_0_dar); | 3901 | DUMP_FIELD(spu, "0x%llx", class_0_dar); |
3887 | DUMP_FIELD(spu, "0x%lx", class_1_dar); | 3902 | DUMP_FIELD(spu, "0x%llx", class_1_dar); |
3888 | DUMP_FIELD(spu, "0x%lx", class_1_dsisr); | 3903 | DUMP_FIELD(spu, "0x%llx", class_1_dsisr); |
3889 | DUMP_FIELD(spu, "0x%lx", irqs[0]); | 3904 | DUMP_FIELD(spu, "0x%x", irqs[0]); |
3890 | DUMP_FIELD(spu, "0x%lx", irqs[1]); | 3905 | DUMP_FIELD(spu, "0x%x", irqs[1]); |
3891 | DUMP_FIELD(spu, "0x%lx", irqs[2]); | 3906 | DUMP_FIELD(spu, "0x%x", irqs[2]); |
3892 | DUMP_FIELD(spu, "0x%x", slb_replace); | 3907 | DUMP_FIELD(spu, "0x%x", slb_replace); |
3893 | DUMP_FIELD(spu, "%d", pid); | 3908 | DUMP_FIELD(spu, "%d", pid); |
3894 | DUMP_FIELD(spu, "0x%p", mm); | 3909 | DUMP_FIELD(spu, "0x%p", mm); |
3895 | DUMP_FIELD(spu, "0x%p", ctx); | 3910 | DUMP_FIELD(spu, "0x%p", ctx); |
3896 | DUMP_FIELD(spu, "0x%p", rq); | 3911 | DUMP_FIELD(spu, "0x%p", rq); |
3897 | DUMP_FIELD(spu, "0x%p", timestamp); | 3912 | DUMP_FIELD(spu, "0x%llx", timestamp); |
3898 | DUMP_FIELD(spu, "0x%lx", problem_phys); | 3913 | DUMP_FIELD(spu, "0x%lx", problem_phys); |
3899 | DUMP_FIELD(spu, "0x%p", problem); | 3914 | DUMP_FIELD(spu, "0x%p", problem); |
3900 | DUMP_VALUE("0x%x", problem->spu_runcntl_RW, | 3915 | DUMP_VALUE("0x%x", problem->spu_runcntl_RW, |
@@ -3925,7 +3940,7 @@ static void dump_spu_ls(unsigned long num, int subcmd) | |||
3925 | __delay(200); | 3940 | __delay(200); |
3926 | } else { | 3941 | } else { |
3927 | catch_memory_errors = 0; | 3942 | catch_memory_errors = 0; |
3928 | printf("*** Error: accessing spu info for spu %d\n", num); | 3943 | printf("*** Error: accessing spu info for spu %ld\n", num); |
3929 | return; | 3944 | return; |
3930 | } | 3945 | } |
3931 | catch_memory_errors = 0; | 3946 | catch_memory_errors = 0; |
diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h index cf9911b5a53c..bbc796eb0a3b 100644 --- a/arch/x86/include/asm/mmu_context.h +++ b/arch/x86/include/asm/mmu_context.h | |||
@@ -288,21 +288,6 @@ static inline void arch_unmap(struct mm_struct *mm, struct vm_area_struct *vma, | |||
288 | mpx_notify_unmap(mm, vma, start, end); | 288 | mpx_notify_unmap(mm, vma, start, end); |
289 | } | 289 | } |
290 | 290 | ||
291 | #ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS | ||
292 | static inline int vma_pkey(struct vm_area_struct *vma) | ||
293 | { | ||
294 | unsigned long vma_pkey_mask = VM_PKEY_BIT0 | VM_PKEY_BIT1 | | ||
295 | VM_PKEY_BIT2 | VM_PKEY_BIT3; | ||
296 | |||
297 | return (vma->vm_flags & vma_pkey_mask) >> VM_PKEY_SHIFT; | ||
298 | } | ||
299 | #else | ||
300 | static inline int vma_pkey(struct vm_area_struct *vma) | ||
301 | { | ||
302 | return 0; | ||
303 | } | ||
304 | #endif | ||
305 | |||
306 | /* | 291 | /* |
307 | * We only want to enforce protection keys on the current process | 292 | * We only want to enforce protection keys on the current process |
308 | * because we effectively have no access to PKRU for other | 293 | * because we effectively have no access to PKRU for other |
diff --git a/arch/x86/include/asm/pkeys.h b/arch/x86/include/asm/pkeys.h index 851c04b7a092..19b137f1b3be 100644 --- a/arch/x86/include/asm/pkeys.h +++ b/arch/x86/include/asm/pkeys.h | |||
@@ -9,6 +9,11 @@ | |||
9 | extern int arch_set_user_pkey_access(struct task_struct *tsk, int pkey, | 9 | extern int arch_set_user_pkey_access(struct task_struct *tsk, int pkey, |
10 | unsigned long init_val); | 10 | unsigned long init_val); |
11 | 11 | ||
12 | static inline bool arch_pkeys_enabled(void) | ||
13 | { | ||
14 | return boot_cpu_has(X86_FEATURE_OSPKE); | ||
15 | } | ||
16 | |||
12 | /* | 17 | /* |
13 | * Try to dedicate one of the protection keys to be used as an | 18 | * Try to dedicate one of the protection keys to be used as an |
14 | * execute-only protection key. | 19 | * execute-only protection key. |
@@ -116,4 +121,12 @@ extern int __arch_set_user_pkey_access(struct task_struct *tsk, int pkey, | |||
116 | unsigned long init_val); | 121 | unsigned long init_val); |
117 | extern void copy_init_pkru_to_fpregs(void); | 122 | extern void copy_init_pkru_to_fpregs(void); |
118 | 123 | ||
124 | static inline int vma_pkey(struct vm_area_struct *vma) | ||
125 | { | ||
126 | unsigned long vma_pkey_mask = VM_PKEY_BIT0 | VM_PKEY_BIT1 | | ||
127 | VM_PKEY_BIT2 | VM_PKEY_BIT3; | ||
128 | |||
129 | return (vma->vm_flags & vma_pkey_mask) >> VM_PKEY_SHIFT; | ||
130 | } | ||
131 | |||
119 | #endif /*_ASM_X86_PKEYS_H */ | 132 | #endif /*_ASM_X86_PKEYS_H */ |
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 5c623dfe39d1..2f86d883dd95 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
@@ -1312,11 +1312,3 @@ static int __init register_kernel_offset_dumper(void) | |||
1312 | return 0; | 1312 | return 0; |
1313 | } | 1313 | } |
1314 | __initcall(register_kernel_offset_dumper); | 1314 | __initcall(register_kernel_offset_dumper); |
1315 | |||
1316 | void arch_show_smap(struct seq_file *m, struct vm_area_struct *vma) | ||
1317 | { | ||
1318 | if (!boot_cpu_has(X86_FEATURE_OSPKE)) | ||
1319 | return; | ||
1320 | |||
1321 | seq_printf(m, "ProtectionKey: %8u\n", vma_pkey(vma)); | ||
1322 | } | ||
diff --git a/drivers/cpuidle/cpuidle-powernv.c b/drivers/cpuidle/cpuidle-powernv.c index 1a8234e706bc..d29e4f041efe 100644 --- a/drivers/cpuidle/cpuidle-powernv.c +++ b/drivers/cpuidle/cpuidle-powernv.c | |||
@@ -43,9 +43,31 @@ struct stop_psscr_table { | |||
43 | 43 | ||
44 | static struct stop_psscr_table stop_psscr_table[CPUIDLE_STATE_MAX] __read_mostly; | 44 | static struct stop_psscr_table stop_psscr_table[CPUIDLE_STATE_MAX] __read_mostly; |
45 | 45 | ||
46 | static u64 snooze_timeout __read_mostly; | 46 | static u64 default_snooze_timeout __read_mostly; |
47 | static bool snooze_timeout_en __read_mostly; | 47 | static bool snooze_timeout_en __read_mostly; |
48 | 48 | ||
49 | static u64 get_snooze_timeout(struct cpuidle_device *dev, | ||
50 | struct cpuidle_driver *drv, | ||
51 | int index) | ||
52 | { | ||
53 | int i; | ||
54 | |||
55 | if (unlikely(!snooze_timeout_en)) | ||
56 | return default_snooze_timeout; | ||
57 | |||
58 | for (i = index + 1; i < drv->state_count; i++) { | ||
59 | struct cpuidle_state *s = &drv->states[i]; | ||
60 | struct cpuidle_state_usage *su = &dev->states_usage[i]; | ||
61 | |||
62 | if (s->disabled || su->disable) | ||
63 | continue; | ||
64 | |||
65 | return s->target_residency * tb_ticks_per_usec; | ||
66 | } | ||
67 | |||
68 | return default_snooze_timeout; | ||
69 | } | ||
70 | |||
49 | static int snooze_loop(struct cpuidle_device *dev, | 71 | static int snooze_loop(struct cpuidle_device *dev, |
50 | struct cpuidle_driver *drv, | 72 | struct cpuidle_driver *drv, |
51 | int index) | 73 | int index) |
@@ -56,7 +78,7 @@ static int snooze_loop(struct cpuidle_device *dev, | |||
56 | 78 | ||
57 | local_irq_enable(); | 79 | local_irq_enable(); |
58 | 80 | ||
59 | snooze_exit_time = get_tb() + snooze_timeout; | 81 | snooze_exit_time = get_tb() + get_snooze_timeout(dev, drv, index); |
60 | ppc64_runlatch_off(); | 82 | ppc64_runlatch_off(); |
61 | HMT_very_low(); | 83 | HMT_very_low(); |
62 | while (!need_resched()) { | 84 | while (!need_resched()) { |
@@ -465,11 +487,9 @@ static int powernv_idle_probe(void) | |||
465 | cpuidle_state_table = powernv_states; | 487 | cpuidle_state_table = powernv_states; |
466 | /* Device tree can indicate more idle states */ | 488 | /* Device tree can indicate more idle states */ |
467 | max_idle_state = powernv_add_idle_states(); | 489 | max_idle_state = powernv_add_idle_states(); |
468 | if (max_idle_state > 1) { | 490 | default_snooze_timeout = TICK_USEC * tb_ticks_per_usec; |
491 | if (max_idle_state > 1) | ||
469 | snooze_timeout_en = true; | 492 | snooze_timeout_en = true; |
470 | snooze_timeout = powernv_states[1].target_residency * | ||
471 | tb_ticks_per_usec; | ||
472 | } | ||
473 | } else | 493 | } else |
474 | return -ENODEV; | 494 | return -ENODEV; |
475 | 495 | ||
diff --git a/drivers/hwmon/ibmpowernv.c b/drivers/hwmon/ibmpowernv.c index 5ccdd0b52650..0298745d46e4 100644 --- a/drivers/hwmon/ibmpowernv.c +++ b/drivers/hwmon/ibmpowernv.c | |||
@@ -51,6 +51,7 @@ enum sensors { | |||
51 | POWER_SUPPLY, | 51 | POWER_SUPPLY, |
52 | POWER_INPUT, | 52 | POWER_INPUT, |
53 | CURRENT, | 53 | CURRENT, |
54 | ENERGY, | ||
54 | MAX_SENSOR_TYPE, | 55 | MAX_SENSOR_TYPE, |
55 | }; | 56 | }; |
56 | 57 | ||
@@ -78,6 +79,7 @@ static struct sensor_group { | |||
78 | { "in" }, | 79 | { "in" }, |
79 | { "power" }, | 80 | { "power" }, |
80 | { "curr" }, | 81 | { "curr" }, |
82 | { "energy" }, | ||
81 | }; | 83 | }; |
82 | 84 | ||
83 | struct sensor_data { | 85 | struct sensor_data { |
@@ -101,9 +103,10 @@ static ssize_t show_sensor(struct device *dev, struct device_attribute *devattr, | |||
101 | struct sensor_data *sdata = container_of(devattr, struct sensor_data, | 103 | struct sensor_data *sdata = container_of(devattr, struct sensor_data, |
102 | dev_attr); | 104 | dev_attr); |
103 | ssize_t ret; | 105 | ssize_t ret; |
104 | u32 x; | 106 | u64 x; |
107 | |||
108 | ret = opal_get_sensor_data_u64(sdata->id, &x); | ||
105 | 109 | ||
106 | ret = opal_get_sensor_data(sdata->id, &x); | ||
107 | if (ret) | 110 | if (ret) |
108 | return ret; | 111 | return ret; |
109 | 112 | ||
@@ -114,7 +117,7 @@ static ssize_t show_sensor(struct device *dev, struct device_attribute *devattr, | |||
114 | else if (sdata->type == POWER_INPUT) | 117 | else if (sdata->type == POWER_INPUT) |
115 | x *= 1000000; | 118 | x *= 1000000; |
116 | 119 | ||
117 | return sprintf(buf, "%u\n", x); | 120 | return sprintf(buf, "%llu\n", x); |
118 | } | 121 | } |
119 | 122 | ||
120 | static ssize_t show_label(struct device *dev, struct device_attribute *devattr, | 123 | static ssize_t show_label(struct device *dev, struct device_attribute *devattr, |
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index 6663893f41c4..25c1ce811053 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c | |||
@@ -274,7 +274,7 @@ int __init find_via_pmu(void) | |||
274 | u64 taddr; | 274 | u64 taddr; |
275 | const u32 *reg; | 275 | const u32 *reg; |
276 | 276 | ||
277 | if (via != 0) | 277 | if (via) |
278 | return 1; | 278 | return 1; |
279 | vias = of_find_node_by_name(NULL, "via-pmu"); | 279 | vias = of_find_node_by_name(NULL, "via-pmu"); |
280 | if (vias == NULL) | 280 | if (vias == NULL) |
@@ -1115,7 +1115,7 @@ pmu_queue_request(struct adb_request *req) | |||
1115 | req->complete = 0; | 1115 | req->complete = 0; |
1116 | 1116 | ||
1117 | spin_lock_irqsave(&pmu_lock, flags); | 1117 | spin_lock_irqsave(&pmu_lock, flags); |
1118 | if (current_req != 0) { | 1118 | if (current_req) { |
1119 | last_req->next = req; | 1119 | last_req->next = req; |
1120 | last_req = req; | 1120 | last_req = req; |
1121 | } else { | 1121 | } else { |
@@ -1190,7 +1190,7 @@ pmu_start(void) | |||
1190 | /* assert pmu_state == idle */ | 1190 | /* assert pmu_state == idle */ |
1191 | /* get the packet to send */ | 1191 | /* get the packet to send */ |
1192 | req = current_req; | 1192 | req = current_req; |
1193 | if (req == 0 || pmu_state != idle | 1193 | if (!req || pmu_state != idle |
1194 | || (/*req->reply_expected && */req_awaiting_reply)) | 1194 | || (/*req->reply_expected && */req_awaiting_reply)) |
1195 | return; | 1195 | return; |
1196 | 1196 | ||
@@ -1345,7 +1345,7 @@ next: | |||
1345 | if ((1 << pirq) & PMU_INT_ADB) { | 1345 | if ((1 << pirq) & PMU_INT_ADB) { |
1346 | if ((data[0] & PMU_INT_ADB_AUTO) == 0) { | 1346 | if ((data[0] & PMU_INT_ADB_AUTO) == 0) { |
1347 | struct adb_request *req = req_awaiting_reply; | 1347 | struct adb_request *req = req_awaiting_reply; |
1348 | if (req == 0) { | 1348 | if (!req) { |
1349 | printk(KERN_ERR "PMU: extra ADB reply\n"); | 1349 | printk(KERN_ERR "PMU: extra ADB reply\n"); |
1350 | return; | 1350 | return; |
1351 | } | 1351 | } |
@@ -1712,7 +1712,7 @@ pmu_shutdown(void) | |||
1712 | int | 1712 | int |
1713 | pmu_present(void) | 1713 | pmu_present(void) |
1714 | { | 1714 | { |
1715 | return via != 0; | 1715 | return via != NULL; |
1716 | } | 1716 | } |
1717 | 1717 | ||
1718 | #if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32) | 1718 | #if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32) |
@@ -2044,7 +2044,7 @@ pmu_open(struct inode *inode, struct file *file) | |||
2044 | unsigned long flags; | 2044 | unsigned long flags; |
2045 | 2045 | ||
2046 | pp = kmalloc(sizeof(struct pmu_private), GFP_KERNEL); | 2046 | pp = kmalloc(sizeof(struct pmu_private), GFP_KERNEL); |
2047 | if (pp == 0) | 2047 | if (!pp) |
2048 | return -ENOMEM; | 2048 | return -ENOMEM; |
2049 | pp->rb_get = pp->rb_put = 0; | 2049 | pp->rb_get = pp->rb_put = 0; |
2050 | spin_lock_init(&pp->lock); | 2050 | spin_lock_init(&pp->lock); |
@@ -2070,7 +2070,7 @@ pmu_read(struct file *file, char __user *buf, | |||
2070 | unsigned long flags; | 2070 | unsigned long flags; |
2071 | int ret = 0; | 2071 | int ret = 0; |
2072 | 2072 | ||
2073 | if (count < 1 || pp == 0) | 2073 | if (count < 1 || !pp) |
2074 | return -EINVAL; | 2074 | return -EINVAL; |
2075 | if (!access_ok(VERIFY_WRITE, buf, count)) | 2075 | if (!access_ok(VERIFY_WRITE, buf, count)) |
2076 | return -EFAULT; | 2076 | return -EFAULT; |
@@ -2127,7 +2127,7 @@ pmu_fpoll(struct file *filp, poll_table *wait) | |||
2127 | __poll_t mask = 0; | 2127 | __poll_t mask = 0; |
2128 | unsigned long flags; | 2128 | unsigned long flags; |
2129 | 2129 | ||
2130 | if (pp == 0) | 2130 | if (!pp) |
2131 | return 0; | 2131 | return 0; |
2132 | poll_wait(filp, &pp->wait, wait); | 2132 | poll_wait(filp, &pp->wait, wait); |
2133 | spin_lock_irqsave(&pp->lock, flags); | 2133 | spin_lock_irqsave(&pp->lock, flags); |
@@ -2143,7 +2143,7 @@ pmu_release(struct inode *inode, struct file *file) | |||
2143 | struct pmu_private *pp = file->private_data; | 2143 | struct pmu_private *pp = file->private_data; |
2144 | unsigned long flags; | 2144 | unsigned long flags; |
2145 | 2145 | ||
2146 | if (pp != 0) { | 2146 | if (pp) { |
2147 | file->private_data = NULL; | 2147 | file->private_data = NULL; |
2148 | spin_lock_irqsave(&all_pvt_lock, flags); | 2148 | spin_lock_irqsave(&all_pvt_lock, flags); |
2149 | list_del(&pp->list); | 2149 | list_del(&pp->list); |
diff --git a/drivers/macintosh/windfarm_pm121.c b/drivers/macintosh/windfarm_pm121.c index 4d72d8f58cb6..97634e030991 100644 --- a/drivers/macintosh/windfarm_pm121.c +++ b/drivers/macintosh/windfarm_pm121.c | |||
@@ -710,7 +710,7 @@ static void pm121_create_cpu_fans(void) | |||
710 | wf_cpu_pid_init(&pm121_cpu_state->pid, &pid_param); | 710 | wf_cpu_pid_init(&pm121_cpu_state->pid, &pid_param); |
711 | 711 | ||
712 | pr_debug("pm121: CPU Fan control initialized.\n"); | 712 | pr_debug("pm121: CPU Fan control initialized.\n"); |
713 | pr_debug(" ttarged=%d.%03d, tmax=%d.%03d, min=%d RPM, max=%d RPM,\n", | 713 | pr_debug(" ttarget=%d.%03d, tmax=%d.%03d, min=%d RPM, max=%d RPM,\n", |
714 | FIX32TOPRINT(pid_param.ttarget), FIX32TOPRINT(pid_param.tmax), | 714 | FIX32TOPRINT(pid_param.ttarget), FIX32TOPRINT(pid_param.tmax), |
715 | pid_param.min, pid_param.max); | 715 | pid_param.min, pid_param.max); |
716 | 716 | ||
diff --git a/drivers/macintosh/windfarm_pm81.c b/drivers/macintosh/windfarm_pm81.c index d9ea45581b9e..346c91744442 100644 --- a/drivers/macintosh/windfarm_pm81.c +++ b/drivers/macintosh/windfarm_pm81.c | |||
@@ -455,7 +455,7 @@ static void wf_smu_create_cpu_fans(void) | |||
455 | wf_cpu_pid_init(&wf_smu_cpu_fans->pid, &pid_param); | 455 | wf_cpu_pid_init(&wf_smu_cpu_fans->pid, &pid_param); |
456 | 456 | ||
457 | DBG("wf: CPU Fan control initialized.\n"); | 457 | DBG("wf: CPU Fan control initialized.\n"); |
458 | DBG(" ttarged=%d.%03d, tmax=%d.%03d, min=%d RPM, max=%d RPM\n", | 458 | DBG(" ttarget=%d.%03d, tmax=%d.%03d, min=%d RPM, max=%d RPM\n", |
459 | FIX32TOPRINT(pid_param.ttarget), FIX32TOPRINT(pid_param.tmax), | 459 | FIX32TOPRINT(pid_param.ttarget), FIX32TOPRINT(pid_param.tmax), |
460 | pid_param.min, pid_param.max); | 460 | pid_param.min, pid_param.max); |
461 | 461 | ||
diff --git a/drivers/macintosh/windfarm_pm91.c b/drivers/macintosh/windfarm_pm91.c index 7fd73dcb2b0a..a8a47c62a74b 100644 --- a/drivers/macintosh/windfarm_pm91.c +++ b/drivers/macintosh/windfarm_pm91.c | |||
@@ -200,7 +200,7 @@ static void wf_smu_create_cpu_fans(void) | |||
200 | wf_cpu_pid_init(&wf_smu_cpu_fans->pid, &pid_param); | 200 | wf_cpu_pid_init(&wf_smu_cpu_fans->pid, &pid_param); |
201 | 201 | ||
202 | DBG("wf: CPU Fan control initialized.\n"); | 202 | DBG("wf: CPU Fan control initialized.\n"); |
203 | DBG(" ttarged=%d.%03d, tmax=%d.%03d, min=%d RPM, max=%d RPM\n", | 203 | DBG(" ttarget=%d.%03d, tmax=%d.%03d, min=%d RPM, max=%d RPM\n", |
204 | FIX32TOPRINT(pid_param.ttarget), FIX32TOPRINT(pid_param.tmax), | 204 | FIX32TOPRINT(pid_param.ttarget), FIX32TOPRINT(pid_param.tmax), |
205 | pid_param.min, pid_param.max); | 205 | pid_param.min, pid_param.max); |
206 | 206 | ||
diff --git a/drivers/misc/cxl/pci.c b/drivers/misc/cxl/pci.c index 4d6736f9d463..429d6de1dde7 100644 --- a/drivers/misc/cxl/pci.c +++ b/drivers/misc/cxl/pci.c | |||
@@ -514,9 +514,9 @@ static int init_implementation_adapter_regs_psl9(struct cxl *adapter, | |||
514 | cxl_p1_write(adapter, CXL_PSL9_FIR_CNTL, psl_fircntl); | 514 | cxl_p1_write(adapter, CXL_PSL9_FIR_CNTL, psl_fircntl); |
515 | 515 | ||
516 | /* Setup the PSL to transmit packets on the PCIe before the | 516 | /* Setup the PSL to transmit packets on the PCIe before the |
517 | * CAPP is enabled | 517 | * CAPP is enabled. Make sure that CAPP virtual machines are disabled |
518 | */ | 518 | */ |
519 | cxl_p1_write(adapter, CXL_PSL9_DSNDCTL, 0x0001001000002A10ULL); | 519 | cxl_p1_write(adapter, CXL_PSL9_DSNDCTL, 0x0001001000012A10ULL); |
520 | 520 | ||
521 | /* | 521 | /* |
522 | * A response to an ASB_Notify request is returned by the | 522 | * A response to an ASB_Notify request is returned by the |
diff --git a/drivers/misc/cxl/sysfs.c b/drivers/misc/cxl/sysfs.c index 4b5a4c5d3c01..629e2e156412 100644 --- a/drivers/misc/cxl/sysfs.c +++ b/drivers/misc/cxl/sysfs.c | |||
@@ -353,12 +353,20 @@ static ssize_t prefault_mode_store(struct device *device, | |||
353 | struct cxl_afu *afu = to_cxl_afu(device); | 353 | struct cxl_afu *afu = to_cxl_afu(device); |
354 | enum prefault_modes mode = -1; | 354 | enum prefault_modes mode = -1; |
355 | 355 | ||
356 | if (!strncmp(buf, "work_element_descriptor", 23)) | ||
357 | mode = CXL_PREFAULT_WED; | ||
358 | if (!strncmp(buf, "all", 3)) | ||
359 | mode = CXL_PREFAULT_ALL; | ||
360 | if (!strncmp(buf, "none", 4)) | 356 | if (!strncmp(buf, "none", 4)) |
361 | mode = CXL_PREFAULT_NONE; | 357 | mode = CXL_PREFAULT_NONE; |
358 | else { | ||
359 | if (!radix_enabled()) { | ||
360 | |||
361 | /* only allowed when not in radix mode */ | ||
362 | if (!strncmp(buf, "work_element_descriptor", 23)) | ||
363 | mode = CXL_PREFAULT_WED; | ||
364 | if (!strncmp(buf, "all", 3)) | ||
365 | mode = CXL_PREFAULT_ALL; | ||
366 | } else { | ||
367 | dev_err(device, "Cannot prefault with radix enabled\n"); | ||
368 | } | ||
369 | } | ||
362 | 370 | ||
363 | if (mode == -1) | 371 | if (mode == -1) |
364 | return -EINVAL; | 372 | return -EINVAL; |
diff --git a/drivers/misc/ocxl/context.c b/drivers/misc/ocxl/context.c index 909e8807824a..95f74623113e 100644 --- a/drivers/misc/ocxl/context.c +++ b/drivers/misc/ocxl/context.c | |||
@@ -34,6 +34,8 @@ int ocxl_context_init(struct ocxl_context *ctx, struct ocxl_afu *afu, | |||
34 | mutex_init(&ctx->xsl_error_lock); | 34 | mutex_init(&ctx->xsl_error_lock); |
35 | mutex_init(&ctx->irq_lock); | 35 | mutex_init(&ctx->irq_lock); |
36 | idr_init(&ctx->irq_idr); | 36 | idr_init(&ctx->irq_idr); |
37 | ctx->tidr = 0; | ||
38 | |||
37 | /* | 39 | /* |
38 | * Keep a reference on the AFU to make sure it's valid for the | 40 | * Keep a reference on the AFU to make sure it's valid for the |
39 | * duration of the life of the context | 41 | * duration of the life of the context |
@@ -65,6 +67,7 @@ int ocxl_context_attach(struct ocxl_context *ctx, u64 amr) | |||
65 | { | 67 | { |
66 | int rc; | 68 | int rc; |
67 | 69 | ||
70 | // Locks both status & tidr | ||
68 | mutex_lock(&ctx->status_mutex); | 71 | mutex_lock(&ctx->status_mutex); |
69 | if (ctx->status != OPENED) { | 72 | if (ctx->status != OPENED) { |
70 | rc = -EIO; | 73 | rc = -EIO; |
@@ -72,7 +75,7 @@ int ocxl_context_attach(struct ocxl_context *ctx, u64 amr) | |||
72 | } | 75 | } |
73 | 76 | ||
74 | rc = ocxl_link_add_pe(ctx->afu->fn->link, ctx->pasid, | 77 | rc = ocxl_link_add_pe(ctx->afu->fn->link, ctx->pasid, |
75 | current->mm->context.id, 0, amr, current->mm, | 78 | current->mm->context.id, ctx->tidr, amr, current->mm, |
76 | xsl_fault_error, ctx); | 79 | xsl_fault_error, ctx); |
77 | if (rc) | 80 | if (rc) |
78 | goto out; | 81 | goto out; |
diff --git a/drivers/misc/ocxl/file.c b/drivers/misc/ocxl/file.c index 038509e5d031..e6a607488f8a 100644 --- a/drivers/misc/ocxl/file.c +++ b/drivers/misc/ocxl/file.c | |||
@@ -5,6 +5,8 @@ | |||
5 | #include <linux/sched/signal.h> | 5 | #include <linux/sched/signal.h> |
6 | #include <linux/uaccess.h> | 6 | #include <linux/uaccess.h> |
7 | #include <uapi/misc/ocxl.h> | 7 | #include <uapi/misc/ocxl.h> |
8 | #include <asm/reg.h> | ||
9 | #include <asm/switch_to.h> | ||
8 | #include "ocxl_internal.h" | 10 | #include "ocxl_internal.h" |
9 | 11 | ||
10 | 12 | ||
@@ -123,11 +125,77 @@ static long afu_ioctl_get_metadata(struct ocxl_context *ctx, | |||
123 | return 0; | 125 | return 0; |
124 | } | 126 | } |
125 | 127 | ||
128 | #ifdef CONFIG_PPC64 | ||
129 | static long afu_ioctl_enable_p9_wait(struct ocxl_context *ctx, | ||
130 | struct ocxl_ioctl_p9_wait __user *uarg) | ||
131 | { | ||
132 | struct ocxl_ioctl_p9_wait arg; | ||
133 | |||
134 | memset(&arg, 0, sizeof(arg)); | ||
135 | |||
136 | if (cpu_has_feature(CPU_FTR_P9_TIDR)) { | ||
137 | enum ocxl_context_status status; | ||
138 | |||
139 | // Locks both status & tidr | ||
140 | mutex_lock(&ctx->status_mutex); | ||
141 | if (!ctx->tidr) { | ||
142 | if (set_thread_tidr(current)) { | ||
143 | mutex_unlock(&ctx->status_mutex); | ||
144 | return -ENOENT; | ||
145 | } | ||
146 | |||
147 | ctx->tidr = current->thread.tidr; | ||
148 | } | ||
149 | |||
150 | status = ctx->status; | ||
151 | mutex_unlock(&ctx->status_mutex); | ||
152 | |||
153 | if (status == ATTACHED) { | ||
154 | int rc; | ||
155 | struct link *link = ctx->afu->fn->link; | ||
156 | |||
157 | rc = ocxl_link_update_pe(link, ctx->pasid, ctx->tidr); | ||
158 | if (rc) | ||
159 | return rc; | ||
160 | } | ||
161 | |||
162 | arg.thread_id = ctx->tidr; | ||
163 | } else | ||
164 | return -ENOENT; | ||
165 | |||
166 | if (copy_to_user(uarg, &arg, sizeof(arg))) | ||
167 | return -EFAULT; | ||
168 | |||
169 | return 0; | ||
170 | } | ||
171 | #endif | ||
172 | |||
173 | |||
174 | static long afu_ioctl_get_features(struct ocxl_context *ctx, | ||
175 | struct ocxl_ioctl_features __user *uarg) | ||
176 | { | ||
177 | struct ocxl_ioctl_features arg; | ||
178 | |||
179 | memset(&arg, 0, sizeof(arg)); | ||
180 | |||
181 | #ifdef CONFIG_PPC64 | ||
182 | if (cpu_has_feature(CPU_FTR_P9_TIDR)) | ||
183 | arg.flags[0] |= OCXL_IOCTL_FEATURES_FLAGS0_P9_WAIT; | ||
184 | #endif | ||
185 | |||
186 | if (copy_to_user(uarg, &arg, sizeof(arg))) | ||
187 | return -EFAULT; | ||
188 | |||
189 | return 0; | ||
190 | } | ||
191 | |||
126 | #define CMD_STR(x) (x == OCXL_IOCTL_ATTACH ? "ATTACH" : \ | 192 | #define CMD_STR(x) (x == OCXL_IOCTL_ATTACH ? "ATTACH" : \ |
127 | x == OCXL_IOCTL_IRQ_ALLOC ? "IRQ_ALLOC" : \ | 193 | x == OCXL_IOCTL_IRQ_ALLOC ? "IRQ_ALLOC" : \ |
128 | x == OCXL_IOCTL_IRQ_FREE ? "IRQ_FREE" : \ | 194 | x == OCXL_IOCTL_IRQ_FREE ? "IRQ_FREE" : \ |
129 | x == OCXL_IOCTL_IRQ_SET_FD ? "IRQ_SET_FD" : \ | 195 | x == OCXL_IOCTL_IRQ_SET_FD ? "IRQ_SET_FD" : \ |
130 | x == OCXL_IOCTL_GET_METADATA ? "GET_METADATA" : \ | 196 | x == OCXL_IOCTL_GET_METADATA ? "GET_METADATA" : \ |
197 | x == OCXL_IOCTL_ENABLE_P9_WAIT ? "ENABLE_P9_WAIT" : \ | ||
198 | x == OCXL_IOCTL_GET_FEATURES ? "GET_FEATURES" : \ | ||
131 | "UNKNOWN") | 199 | "UNKNOWN") |
132 | 200 | ||
133 | static long afu_ioctl(struct file *file, unsigned int cmd, | 201 | static long afu_ioctl(struct file *file, unsigned int cmd, |
@@ -186,6 +254,18 @@ static long afu_ioctl(struct file *file, unsigned int cmd, | |||
186 | (struct ocxl_ioctl_metadata __user *) args); | 254 | (struct ocxl_ioctl_metadata __user *) args); |
187 | break; | 255 | break; |
188 | 256 | ||
257 | #ifdef CONFIG_PPC64 | ||
258 | case OCXL_IOCTL_ENABLE_P9_WAIT: | ||
259 | rc = afu_ioctl_enable_p9_wait(ctx, | ||
260 | (struct ocxl_ioctl_p9_wait __user *) args); | ||
261 | break; | ||
262 | #endif | ||
263 | |||
264 | case OCXL_IOCTL_GET_FEATURES: | ||
265 | rc = afu_ioctl_get_features(ctx, | ||
266 | (struct ocxl_ioctl_features __user *) args); | ||
267 | break; | ||
268 | |||
189 | default: | 269 | default: |
190 | rc = -EINVAL; | 270 | rc = -EINVAL; |
191 | } | 271 | } |
diff --git a/drivers/misc/ocxl/link.c b/drivers/misc/ocxl/link.c index f30790582dc0..88876ae8f330 100644 --- a/drivers/misc/ocxl/link.c +++ b/drivers/misc/ocxl/link.c | |||
@@ -544,6 +544,42 @@ unlock: | |||
544 | } | 544 | } |
545 | EXPORT_SYMBOL_GPL(ocxl_link_add_pe); | 545 | EXPORT_SYMBOL_GPL(ocxl_link_add_pe); |
546 | 546 | ||
547 | int ocxl_link_update_pe(void *link_handle, int pasid, __u16 tid) | ||
548 | { | ||
549 | struct link *link = (struct link *) link_handle; | ||
550 | struct spa *spa = link->spa; | ||
551 | struct ocxl_process_element *pe; | ||
552 | int pe_handle, rc; | ||
553 | |||
554 | if (pasid > SPA_PASID_MAX) | ||
555 | return -EINVAL; | ||
556 | |||
557 | pe_handle = pasid & SPA_PE_MASK; | ||
558 | pe = spa->spa_mem + pe_handle; | ||
559 | |||
560 | mutex_lock(&spa->spa_lock); | ||
561 | |||
562 | pe->tid = tid; | ||
563 | |||
564 | /* | ||
565 | * The barrier makes sure the PE is updated | ||
566 | * before we clear the NPU context cache below, so that the | ||
567 | * old PE cannot be reloaded erroneously. | ||
568 | */ | ||
569 | mb(); | ||
570 | |||
571 | /* | ||
572 | * hook to platform code | ||
573 | * On powerpc, the entry needs to be cleared from the context | ||
574 | * cache of the NPU. | ||
575 | */ | ||
576 | rc = pnv_ocxl_spa_remove_pe_from_cache(link->platform_data, pe_handle); | ||
577 | WARN_ON(rc); | ||
578 | |||
579 | mutex_unlock(&spa->spa_lock); | ||
580 | return rc; | ||
581 | } | ||
582 | |||
547 | int ocxl_link_remove_pe(void *link_handle, int pasid) | 583 | int ocxl_link_remove_pe(void *link_handle, int pasid) |
548 | { | 584 | { |
549 | struct link *link = (struct link *) link_handle; | 585 | struct link *link = (struct link *) link_handle; |
@@ -599,7 +635,7 @@ int ocxl_link_remove_pe(void *link_handle, int pasid) | |||
599 | * On powerpc, the entry needs to be cleared from the context | 635 | * On powerpc, the entry needs to be cleared from the context |
600 | * cache of the NPU. | 636 | * cache of the NPU. |
601 | */ | 637 | */ |
602 | rc = pnv_ocxl_spa_remove_pe(link->platform_data, pe_handle); | 638 | rc = pnv_ocxl_spa_remove_pe_from_cache(link->platform_data, pe_handle); |
603 | WARN_ON(rc); | 639 | WARN_ON(rc); |
604 | 640 | ||
605 | pe_data = radix_tree_delete(&spa->pe_tree, pe_handle); | 641 | pe_data = radix_tree_delete(&spa->pe_tree, pe_handle); |
diff --git a/drivers/misc/ocxl/ocxl_internal.h b/drivers/misc/ocxl/ocxl_internal.h index 5d421824afd9..a32f2151029f 100644 --- a/drivers/misc/ocxl/ocxl_internal.h +++ b/drivers/misc/ocxl/ocxl_internal.h | |||
@@ -77,6 +77,7 @@ struct ocxl_context { | |||
77 | struct ocxl_xsl_error xsl_error; | 77 | struct ocxl_xsl_error xsl_error; |
78 | struct mutex irq_lock; | 78 | struct mutex irq_lock; |
79 | struct idr irq_idr; | 79 | struct idr irq_idr; |
80 | u16 tidr; // Thread ID used for P9 wait implementation | ||
80 | }; | 81 | }; |
81 | 82 | ||
82 | struct ocxl_process_element { | 83 | struct ocxl_process_element { |
diff --git a/drivers/tty/hvc/hvc_opal.c b/drivers/tty/hvc/hvc_opal.c index 2ed07ca6389e..9645c0062a90 100644 --- a/drivers/tty/hvc/hvc_opal.c +++ b/drivers/tty/hvc/hvc_opal.c | |||
@@ -318,7 +318,6 @@ static void udbg_init_opal_common(void) | |||
318 | udbg_putc = udbg_opal_putc; | 318 | udbg_putc = udbg_opal_putc; |
319 | udbg_getc = udbg_opal_getc; | 319 | udbg_getc = udbg_opal_getc; |
320 | udbg_getc_poll = udbg_opal_getc_poll; | 320 | udbg_getc_poll = udbg_opal_getc_poll; |
321 | tb_ticks_per_usec = 0x200; /* Make udelay not suck */ | ||
322 | } | 321 | } |
323 | 322 | ||
324 | void __init hvc_opal_init_early(void) | 323 | void __init hvc_opal_init_early(void) |
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index a20c6e495bb2..7e074138d2f2 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/page_idle.h> | 18 | #include <linux/page_idle.h> |
19 | #include <linux/shmem_fs.h> | 19 | #include <linux/shmem_fs.h> |
20 | #include <linux/uaccess.h> | 20 | #include <linux/uaccess.h> |
21 | #include <linux/pkeys.h> | ||
21 | 22 | ||
22 | #include <asm/elf.h> | 23 | #include <asm/elf.h> |
23 | #include <asm/tlb.h> | 24 | #include <asm/tlb.h> |
@@ -673,13 +674,16 @@ static void show_smap_vma_flags(struct seq_file *m, struct vm_area_struct *vma) | |||
673 | [ilog2(VM_MERGEABLE)] = "mg", | 674 | [ilog2(VM_MERGEABLE)] = "mg", |
674 | [ilog2(VM_UFFD_MISSING)]= "um", | 675 | [ilog2(VM_UFFD_MISSING)]= "um", |
675 | [ilog2(VM_UFFD_WP)] = "uw", | 676 | [ilog2(VM_UFFD_WP)] = "uw", |
676 | #ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS | 677 | #ifdef CONFIG_ARCH_HAS_PKEYS |
677 | /* These come out via ProtectionKey: */ | 678 | /* These come out via ProtectionKey: */ |
678 | [ilog2(VM_PKEY_BIT0)] = "", | 679 | [ilog2(VM_PKEY_BIT0)] = "", |
679 | [ilog2(VM_PKEY_BIT1)] = "", | 680 | [ilog2(VM_PKEY_BIT1)] = "", |
680 | [ilog2(VM_PKEY_BIT2)] = "", | 681 | [ilog2(VM_PKEY_BIT2)] = "", |
681 | [ilog2(VM_PKEY_BIT3)] = "", | 682 | [ilog2(VM_PKEY_BIT3)] = "", |
683 | #if VM_PKEY_BIT4 | ||
684 | [ilog2(VM_PKEY_BIT4)] = "", | ||
682 | #endif | 685 | #endif |
686 | #endif /* CONFIG_ARCH_HAS_PKEYS */ | ||
683 | }; | 687 | }; |
684 | size_t i; | 688 | size_t i; |
685 | 689 | ||
@@ -727,10 +731,6 @@ static int smaps_hugetlb_range(pte_t *pte, unsigned long hmask, | |||
727 | } | 731 | } |
728 | #endif /* HUGETLB_PAGE */ | 732 | #endif /* HUGETLB_PAGE */ |
729 | 733 | ||
730 | void __weak arch_show_smap(struct seq_file *m, struct vm_area_struct *vma) | ||
731 | { | ||
732 | } | ||
733 | |||
734 | #define SEQ_PUT_DEC(str, val) \ | 734 | #define SEQ_PUT_DEC(str, val) \ |
735 | seq_put_decimal_ull_width(m, str, (val) >> 10, 8) | 735 | seq_put_decimal_ull_width(m, str, (val) >> 10, 8) |
736 | static int show_smap(struct seq_file *m, void *v, int is_pid) | 736 | static int show_smap(struct seq_file *m, void *v, int is_pid) |
@@ -835,7 +835,8 @@ static int show_smap(struct seq_file *m, void *v, int is_pid) | |||
835 | seq_puts(m, " kB\n"); | 835 | seq_puts(m, " kB\n"); |
836 | } | 836 | } |
837 | if (!rollup_mode) { | 837 | if (!rollup_mode) { |
838 | arch_show_smap(m, vma); | 838 | if (arch_pkeys_enabled()) |
839 | seq_printf(m, "ProtectionKey: %8u\n", vma_pkey(vma)); | ||
839 | show_smap_vma_flags(m, vma); | 840 | show_smap_vma_flags(m, vma); |
840 | } | 841 | } |
841 | m_cache_vma(m, vma); | 842 | m_cache_vma(m, vma); |
diff --git a/include/linux/mm.h b/include/linux/mm.h index 611f19dd471d..0495e6f97fae 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
@@ -229,15 +229,21 @@ extern unsigned int kobjsize(const void *objp); | |||
229 | #define VM_HIGH_ARCH_4 BIT(VM_HIGH_ARCH_BIT_4) | 229 | #define VM_HIGH_ARCH_4 BIT(VM_HIGH_ARCH_BIT_4) |
230 | #endif /* CONFIG_ARCH_USES_HIGH_VMA_FLAGS */ | 230 | #endif /* CONFIG_ARCH_USES_HIGH_VMA_FLAGS */ |
231 | 231 | ||
232 | #if defined(CONFIG_X86) | 232 | #ifdef CONFIG_ARCH_HAS_PKEYS |
233 | # define VM_PAT VM_ARCH_1 /* PAT reserves whole VMA at once (x86) */ | ||
234 | #if defined (CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS) | ||
235 | # define VM_PKEY_SHIFT VM_HIGH_ARCH_BIT_0 | 233 | # define VM_PKEY_SHIFT VM_HIGH_ARCH_BIT_0 |
236 | # define VM_PKEY_BIT0 VM_HIGH_ARCH_0 /* A protection key is a 4-bit value */ | 234 | # define VM_PKEY_BIT0 VM_HIGH_ARCH_0 /* A protection key is a 4-bit value */ |
237 | # define VM_PKEY_BIT1 VM_HIGH_ARCH_1 | 235 | # define VM_PKEY_BIT1 VM_HIGH_ARCH_1 /* on x86 and 5-bit value on ppc64 */ |
238 | # define VM_PKEY_BIT2 VM_HIGH_ARCH_2 | 236 | # define VM_PKEY_BIT2 VM_HIGH_ARCH_2 |
239 | # define VM_PKEY_BIT3 VM_HIGH_ARCH_3 | 237 | # define VM_PKEY_BIT3 VM_HIGH_ARCH_3 |
238 | #ifdef CONFIG_PPC | ||
239 | # define VM_PKEY_BIT4 VM_HIGH_ARCH_4 | ||
240 | #else | ||
241 | # define VM_PKEY_BIT4 0 | ||
240 | #endif | 242 | #endif |
243 | #endif /* CONFIG_ARCH_HAS_PKEYS */ | ||
244 | |||
245 | #if defined(CONFIG_X86) | ||
246 | # define VM_PAT VM_ARCH_1 /* PAT reserves whole VMA at once (x86) */ | ||
241 | #elif defined(CONFIG_PPC) | 247 | #elif defined(CONFIG_PPC) |
242 | # define VM_SAO VM_ARCH_1 /* Strong Access Ordering (powerpc) */ | 248 | # define VM_SAO VM_ARCH_1 /* Strong Access Ordering (powerpc) */ |
243 | #elif defined(CONFIG_PARISC) | 249 | #elif defined(CONFIG_PARISC) |
diff --git a/include/linux/pkeys.h b/include/linux/pkeys.h index 0794ca78c379..2955ba976048 100644 --- a/include/linux/pkeys.h +++ b/include/linux/pkeys.h | |||
@@ -2,8 +2,7 @@ | |||
2 | #ifndef _LINUX_PKEYS_H | 2 | #ifndef _LINUX_PKEYS_H |
3 | #define _LINUX_PKEYS_H | 3 | #define _LINUX_PKEYS_H |
4 | 4 | ||
5 | #include <linux/mm_types.h> | 5 | #include <linux/mm.h> |
6 | #include <asm/mmu_context.h> | ||
7 | 6 | ||
8 | #ifdef CONFIG_ARCH_HAS_PKEYS | 7 | #ifdef CONFIG_ARCH_HAS_PKEYS |
9 | #include <asm/pkeys.h> | 8 | #include <asm/pkeys.h> |
@@ -14,6 +13,11 @@ | |||
14 | #define PKEY_DEDICATED_EXECUTE_ONLY 0 | 13 | #define PKEY_DEDICATED_EXECUTE_ONLY 0 |
15 | #define ARCH_VM_PKEY_FLAGS 0 | 14 | #define ARCH_VM_PKEY_FLAGS 0 |
16 | 15 | ||
16 | static inline int vma_pkey(struct vm_area_struct *vma) | ||
17 | { | ||
18 | return 0; | ||
19 | } | ||
20 | |||
17 | static inline bool mm_pkey_is_allocated(struct mm_struct *mm, int pkey) | 21 | static inline bool mm_pkey_is_allocated(struct mm_struct *mm, int pkey) |
18 | { | 22 | { |
19 | return (pkey == 0); | 23 | return (pkey == 0); |
@@ -35,6 +39,11 @@ static inline int arch_set_user_pkey_access(struct task_struct *tsk, int pkey, | |||
35 | return 0; | 39 | return 0; |
36 | } | 40 | } |
37 | 41 | ||
42 | static inline bool arch_pkeys_enabled(void) | ||
43 | { | ||
44 | return false; | ||
45 | } | ||
46 | |||
38 | static inline void copy_init_pkru_to_fpregs(void) | 47 | static inline void copy_init_pkru_to_fpregs(void) |
39 | { | 48 | { |
40 | } | 49 | } |
diff --git a/include/misc/ocxl.h b/include/misc/ocxl.h index 51ccf76db293..9ff6ddc28e22 100644 --- a/include/misc/ocxl.h +++ b/include/misc/ocxl.h | |||
@@ -188,6 +188,15 @@ extern int ocxl_link_add_pe(void *link_handle, int pasid, u32 pidr, u32 tidr, | |||
188 | void (*xsl_err_cb)(void *data, u64 addr, u64 dsisr), | 188 | void (*xsl_err_cb)(void *data, u64 addr, u64 dsisr), |
189 | void *xsl_err_data); | 189 | void *xsl_err_data); |
190 | 190 | ||
191 | /** | ||
192 | * Update values within a Process Element | ||
193 | * | ||
194 | * link_handle: the link handle associated with the process element | ||
195 | * pasid: the PASID for the AFU context | ||
196 | * tid: the new thread id for the process element | ||
197 | */ | ||
198 | extern int ocxl_link_update_pe(void *link_handle, int pasid, __u16 tid); | ||
199 | |||
191 | /* | 200 | /* |
192 | * Remove a Process Element from the Shared Process Area for a link | 201 | * Remove a Process Element from the Shared Process Area for a link |
193 | */ | 202 | */ |
diff --git a/include/uapi/misc/ocxl.h b/include/uapi/misc/ocxl.h index 0af83d80fb3e..97937cfa3baa 100644 --- a/include/uapi/misc/ocxl.h +++ b/include/uapi/misc/ocxl.h | |||
@@ -48,6 +48,18 @@ struct ocxl_ioctl_metadata { | |||
48 | __u64 reserved[13]; // Total of 16*u64 | 48 | __u64 reserved[13]; // Total of 16*u64 |
49 | }; | 49 | }; |
50 | 50 | ||
51 | struct ocxl_ioctl_p9_wait { | ||
52 | __u16 thread_id; // The thread ID required to wake this thread | ||
53 | __u16 reserved1; | ||
54 | __u32 reserved2; | ||
55 | __u64 reserved3[3]; | ||
56 | }; | ||
57 | |||
58 | #define OCXL_IOCTL_FEATURES_FLAGS0_P9_WAIT 0x01 | ||
59 | struct ocxl_ioctl_features { | ||
60 | __u64 flags[4]; | ||
61 | }; | ||
62 | |||
51 | struct ocxl_ioctl_irq_fd { | 63 | struct ocxl_ioctl_irq_fd { |
52 | __u64 irq_offset; | 64 | __u64 irq_offset; |
53 | __s32 eventfd; | 65 | __s32 eventfd; |
@@ -62,5 +74,7 @@ struct ocxl_ioctl_irq_fd { | |||
62 | #define OCXL_IOCTL_IRQ_FREE _IOW(OCXL_MAGIC, 0x12, __u64) | 74 | #define OCXL_IOCTL_IRQ_FREE _IOW(OCXL_MAGIC, 0x12, __u64) |
63 | #define OCXL_IOCTL_IRQ_SET_FD _IOW(OCXL_MAGIC, 0x13, struct ocxl_ioctl_irq_fd) | 75 | #define OCXL_IOCTL_IRQ_SET_FD _IOW(OCXL_MAGIC, 0x13, struct ocxl_ioctl_irq_fd) |
64 | #define OCXL_IOCTL_GET_METADATA _IOR(OCXL_MAGIC, 0x14, struct ocxl_ioctl_metadata) | 76 | #define OCXL_IOCTL_GET_METADATA _IOR(OCXL_MAGIC, 0x14, struct ocxl_ioctl_metadata) |
77 | #define OCXL_IOCTL_ENABLE_P9_WAIT _IOR(OCXL_MAGIC, 0x15, struct ocxl_ioctl_p9_wait) | ||
78 | #define OCXL_IOCTL_GET_FEATURES _IOR(OCXL_MAGIC, 0x16, struct ocxl_ioctl_features) | ||
65 | 79 | ||
66 | #endif /* _UAPI_MISC_OCXL_H */ | 80 | #endif /* _UAPI_MISC_OCXL_H */ |
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c index 183169c2a75b..06b4ccee0047 100644 --- a/kernel/sys_ni.c +++ b/kernel/sys_ni.c | |||
@@ -367,7 +367,7 @@ COND_SYSCALL(s390_pci_mmio_write); | |||
367 | COND_SYSCALL_COMPAT(s390_ipc); | 367 | COND_SYSCALL_COMPAT(s390_ipc); |
368 | 368 | ||
369 | /* powerpc */ | 369 | /* powerpc */ |
370 | cond_syscall(ppc_rtas); | 370 | COND_SYSCALL(rtas); |
371 | COND_SYSCALL(spu_run); | 371 | COND_SYSCALL(spu_run); |
372 | COND_SYSCALL(spu_create); | 372 | COND_SYSCALL(spu_create); |
373 | COND_SYSCALL(subpage_prot); | 373 | COND_SYSCALL(subpage_prot); |
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index c4f0f2e4126e..dd6c0a2ad969 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig | |||
@@ -110,11 +110,7 @@ config GENERIC_TRACER | |||
110 | # | 110 | # |
111 | config TRACING_SUPPORT | 111 | config TRACING_SUPPORT |
112 | bool | 112 | bool |
113 | # PPC32 has no irqflags tracing support, but it can use most of the | 113 | depends on TRACE_IRQFLAGS_SUPPORT |
114 | # tracers anyway, they were tested to build and work. Note that new | ||
115 | # exceptions to this list aren't welcomed, better implement the | ||
116 | # irqflags tracing for your architecture. | ||
117 | depends on TRACE_IRQFLAGS_SUPPORT || PPC32 | ||
118 | depends on STACKTRACE_SUPPORT | 114 | depends on STACKTRACE_SUPPORT |
119 | default y | 115 | default y |
120 | 116 | ||
diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl index 191eb949d52c..fe06e77c15eb 100755 --- a/scripts/recordmcount.pl +++ b/scripts/recordmcount.pl | |||
@@ -266,13 +266,29 @@ if ($arch eq "x86_64") { | |||
266 | $objcopy .= " -O elf32-sh-linux"; | 266 | $objcopy .= " -O elf32-sh-linux"; |
267 | 267 | ||
268 | } elsif ($arch eq "powerpc") { | 268 | } elsif ($arch eq "powerpc") { |
269 | my $ldemulation; | ||
270 | |||
269 | $local_regex = "^[0-9a-fA-F]+\\s+t\\s+(\\.?\\S+)"; | 271 | $local_regex = "^[0-9a-fA-F]+\\s+t\\s+(\\.?\\S+)"; |
270 | # See comment in the sparc64 section for why we use '\w'. | 272 | # See comment in the sparc64 section for why we use '\w'. |
271 | $function_regex = "^([0-9a-fA-F]+)\\s+<(\\.?\\w*?)>:"; | 273 | $function_regex = "^([0-9a-fA-F]+)\\s+<(\\.?\\w*?)>:"; |
272 | $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s\\.?_mcount\$"; | 274 | $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s\\.?_mcount\$"; |
273 | 275 | ||
276 | if ($endian eq "big") { | ||
277 | $cc .= " -mbig-endian "; | ||
278 | $ld .= " -EB "; | ||
279 | $ldemulation = "ppc" | ||
280 | } else { | ||
281 | $cc .= " -mlittle-endian "; | ||
282 | $ld .= " -EL "; | ||
283 | $ldemulation = "lppc" | ||
284 | } | ||
274 | if ($bits == 64) { | 285 | if ($bits == 64) { |
275 | $type = ".quad"; | 286 | $type = ".quad"; |
287 | $cc .= " -m64 "; | ||
288 | $ld .= " -m elf64".$ldemulation." "; | ||
289 | } else { | ||
290 | $cc .= " -m32 "; | ||
291 | $ld .= " -m elf32".$ldemulation." "; | ||
276 | } | 292 | } |
277 | 293 | ||
278 | } elsif ($arch eq "arm") { | 294 | } elsif ($arch eq "arm") { |
diff --git a/tools/testing/selftests/powerpc/Makefile b/tools/testing/selftests/powerpc/Makefile index f6b1338730db..201b598558b9 100644 --- a/tools/testing/selftests/powerpc/Makefile +++ b/tools/testing/selftests/powerpc/Makefile | |||
@@ -17,7 +17,6 @@ SUB_DIRS = alignment \ | |||
17 | benchmarks \ | 17 | benchmarks \ |
18 | cache_shape \ | 18 | cache_shape \ |
19 | copyloops \ | 19 | copyloops \ |
20 | context_switch \ | ||
21 | dscr \ | 20 | dscr \ |
22 | mm \ | 21 | mm \ |
23 | pmu \ | 22 | pmu \ |
diff --git a/tools/testing/selftests/powerpc/alignment/.gitignore b/tools/testing/selftests/powerpc/alignment/.gitignore index 1d980e3d7039..9d383073b7ad 100644 --- a/tools/testing/selftests/powerpc/alignment/.gitignore +++ b/tools/testing/selftests/powerpc/alignment/.gitignore | |||
@@ -3,3 +3,4 @@ copy_first_unaligned | |||
3 | paste_unaligned | 3 | paste_unaligned |
4 | paste_last_unaligned | 4 | paste_last_unaligned |
5 | copy_paste_unaligned_common | 5 | copy_paste_unaligned_common |
6 | alignment_handler | ||
diff --git a/tools/testing/selftests/powerpc/benchmarks/exec_target.c b/tools/testing/selftests/powerpc/benchmarks/exec_target.c index 3c9c144192be..c14b0fc1edde 100644 --- a/tools/testing/selftests/powerpc/benchmarks/exec_target.c +++ b/tools/testing/selftests/powerpc/benchmarks/exec_target.c | |||
@@ -6,8 +6,11 @@ | |||
6 | * Copyright 2018, Anton Blanchard, IBM Corp. | 6 | * Copyright 2018, Anton Blanchard, IBM Corp. |
7 | */ | 7 | */ |
8 | 8 | ||
9 | void _exit(int); | 9 | #define _GNU_SOURCE |
10 | #include <unistd.h> | ||
11 | #include <sys/syscall.h> | ||
12 | |||
10 | void _start(void) | 13 | void _start(void) |
11 | { | 14 | { |
12 | _exit(0); | 15 | syscall(SYS_exit, 0); |
13 | } | 16 | } |
diff --git a/tools/testing/selftests/powerpc/context_switch/.gitignore b/tools/testing/selftests/powerpc/context_switch/.gitignore deleted file mode 100644 index c1431af7b51c..000000000000 --- a/tools/testing/selftests/powerpc/context_switch/.gitignore +++ /dev/null | |||
@@ -1 +0,0 @@ | |||
1 | cp_abort | ||
diff --git a/tools/testing/selftests/powerpc/context_switch/Makefile b/tools/testing/selftests/powerpc/context_switch/Makefile deleted file mode 100644 index e9351bb4285d..000000000000 --- a/tools/testing/selftests/powerpc/context_switch/Makefile +++ /dev/null | |||
@@ -1,5 +0,0 @@ | |||
1 | TEST_GEN_PROGS := cp_abort | ||
2 | |||
3 | include ../../lib.mk | ||
4 | |||
5 | $(TEST_GEN_PROGS): ../harness.c ../utils.c | ||
diff --git a/tools/testing/selftests/powerpc/context_switch/cp_abort.c b/tools/testing/selftests/powerpc/context_switch/cp_abort.c deleted file mode 100644 index 5a5b55afda0e..000000000000 --- a/tools/testing/selftests/powerpc/context_switch/cp_abort.c +++ /dev/null | |||
@@ -1,110 +0,0 @@ | |||
1 | /* | ||
2 | * Adapted from Anton Blanchard's context switch microbenchmark. | ||
3 | * | ||
4 | * Copyright 2009, Anton Blanchard, IBM Corporation. | ||
5 | * Copyright 2016, Mikey Neuling, Chris Smart, IBM Corporation. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; either version | ||
10 | * 2 of the License, or (at your option) any later version. | ||
11 | * | ||
12 | * This program tests the copy paste abort functionality of a P9 | ||
13 | * (or later) by setting up two processes on the same CPU, one | ||
14 | * which executes the copy instruction and the other which | ||
15 | * executes paste. | ||
16 | * | ||
17 | * The paste instruction should never succeed, as the cp_abort | ||
18 | * instruction is called by the kernel during a context switch. | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #define _GNU_SOURCE | ||
23 | |||
24 | #include <stdio.h> | ||
25 | #include <unistd.h> | ||
26 | #include <stdlib.h> | ||
27 | #include "utils.h" | ||
28 | #include <sched.h> | ||
29 | |||
30 | #define READ_FD 0 | ||
31 | #define WRITE_FD 1 | ||
32 | |||
33 | #define NUM_LOOPS 1000 | ||
34 | |||
35 | /* This defines the "paste" instruction from Power ISA 3.0 Book II, section 4.4. */ | ||
36 | #define PASTE(RA, RB, L, RC) \ | ||
37 | .long (0x7c00070c | (RA) << (31-15) | (RB) << (31-20) | (L) << (31-10) | (RC) << (31-31)) | ||
38 | |||
39 | int paste(void *i) | ||
40 | { | ||
41 | int cr; | ||
42 | |||
43 | asm volatile(str(PASTE(0, %1, 1, 1))";" | ||
44 | "mfcr %0;" | ||
45 | : "=r" (cr) | ||
46 | : "b" (i) | ||
47 | : "memory" | ||
48 | ); | ||
49 | return cr; | ||
50 | } | ||
51 | |||
52 | /* This defines the "copy" instruction from Power ISA 3.0 Book II, section 4.4. */ | ||
53 | #define COPY(RA, RB, L) \ | ||
54 | .long (0x7c00060c | (RA) << (31-15) | (RB) << (31-20) | (L) << (31-10)) | ||
55 | |||
56 | void copy(void *i) | ||
57 | { | ||
58 | asm volatile(str(COPY(0, %0, 1))";" | ||
59 | : | ||
60 | : "b" (i) | ||
61 | : "memory" | ||
62 | ); | ||
63 | } | ||
64 | |||
65 | int test_cp_abort(void) | ||
66 | { | ||
67 | /* 128 bytes for a full cache line */ | ||
68 | char buf[128] __cacheline_aligned; | ||
69 | cpu_set_t cpuset; | ||
70 | int fd1[2], fd2[2], pid; | ||
71 | char c; | ||
72 | |||
73 | /* only run this test on a P9 or later */ | ||
74 | SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_00)); | ||
75 | |||
76 | /* | ||
77 | * Run both processes on the same CPU, so that copy is more likely | ||
78 | * to leak into a paste. | ||
79 | */ | ||
80 | CPU_ZERO(&cpuset); | ||
81 | CPU_SET(pick_online_cpu(), &cpuset); | ||
82 | FAIL_IF(sched_setaffinity(0, sizeof(cpuset), &cpuset)); | ||
83 | |||
84 | FAIL_IF(pipe(fd1) || pipe(fd2)); | ||
85 | |||
86 | pid = fork(); | ||
87 | FAIL_IF(pid < 0); | ||
88 | |||
89 | if (!pid) { | ||
90 | for (int i = 0; i < NUM_LOOPS; i++) { | ||
91 | FAIL_IF((write(fd1[WRITE_FD], &c, 1)) != 1); | ||
92 | FAIL_IF((read(fd2[READ_FD], &c, 1)) != 1); | ||
93 | /* A paste succeeds if CR0 EQ bit is set */ | ||
94 | FAIL_IF(paste(buf) & 0x20000000); | ||
95 | } | ||
96 | } else { | ||
97 | for (int i = 0; i < NUM_LOOPS; i++) { | ||
98 | FAIL_IF((read(fd1[READ_FD], &c, 1)) != 1); | ||
99 | copy(buf); | ||
100 | FAIL_IF((write(fd2[WRITE_FD], &c, 1) != 1)); | ||
101 | } | ||
102 | } | ||
103 | return 0; | ||
104 | |||
105 | } | ||
106 | |||
107 | int main(int argc, char *argv[]) | ||
108 | { | ||
109 | return test_harness(test_cp_abort, "cp_abort"); | ||
110 | } | ||
diff --git a/tools/testing/selftests/powerpc/include/reg.h b/tools/testing/selftests/powerpc/include/reg.h index 4afdebcce4cd..7f348c059bc2 100644 --- a/tools/testing/selftests/powerpc/include/reg.h +++ b/tools/testing/selftests/powerpc/include/reg.h | |||
@@ -54,6 +54,7 @@ | |||
54 | #define SPRN_DSCR_PRIV 0x11 /* Privilege State DSCR */ | 54 | #define SPRN_DSCR_PRIV 0x11 /* Privilege State DSCR */ |
55 | #define SPRN_DSCR 0x03 /* Data Stream Control Register */ | 55 | #define SPRN_DSCR 0x03 /* Data Stream Control Register */ |
56 | #define SPRN_PPR 896 /* Program Priority Register */ | 56 | #define SPRN_PPR 896 /* Program Priority Register */ |
57 | #define SPRN_AMR 13 /* Authority Mask Register - problem state */ | ||
57 | 58 | ||
58 | /* TEXASR register bits */ | 59 | /* TEXASR register bits */ |
59 | #define TEXASR_FC 0xFE00000000000000 | 60 | #define TEXASR_FC 0xFE00000000000000 |
diff --git a/tools/testing/selftests/powerpc/ptrace/.gitignore b/tools/testing/selftests/powerpc/ptrace/.gitignore index 349acfafc95b..07ec449a2767 100644 --- a/tools/testing/selftests/powerpc/ptrace/.gitignore +++ b/tools/testing/selftests/powerpc/ptrace/.gitignore | |||
@@ -8,3 +8,5 @@ ptrace-vsx | |||
8 | ptrace-tm-vsx | 8 | ptrace-tm-vsx |
9 | ptrace-tm-spd-vsx | 9 | ptrace-tm-spd-vsx |
10 | ptrace-tm-spr | 10 | ptrace-tm-spr |
11 | ptrace-hwbreak | ||
12 | perf-hwbreak | ||
diff --git a/tools/testing/selftests/powerpc/ptrace/Makefile b/tools/testing/selftests/powerpc/ptrace/Makefile index 480305266504..28f5b781a553 100644 --- a/tools/testing/selftests/powerpc/ptrace/Makefile +++ b/tools/testing/selftests/powerpc/ptrace/Makefile | |||
@@ -1,7 +1,8 @@ | |||
1 | # SPDX-License-Identifier: GPL-2.0 | 1 | # SPDX-License-Identifier: GPL-2.0 |
2 | TEST_PROGS := ptrace-gpr ptrace-tm-gpr ptrace-tm-spd-gpr \ | 2 | TEST_PROGS := ptrace-gpr ptrace-tm-gpr ptrace-tm-spd-gpr \ |
3 | ptrace-tar ptrace-tm-tar ptrace-tm-spd-tar ptrace-vsx ptrace-tm-vsx \ | 3 | ptrace-tar ptrace-tm-tar ptrace-tm-spd-tar ptrace-vsx ptrace-tm-vsx \ |
4 | ptrace-tm-spd-vsx ptrace-tm-spr | 4 | ptrace-tm-spd-vsx ptrace-tm-spr ptrace-hwbreak ptrace-pkey core-pkey \ |
5 | perf-hwbreak | ||
5 | 6 | ||
6 | include ../../lib.mk | 7 | include ../../lib.mk |
7 | 8 | ||
@@ -9,6 +10,9 @@ all: $(TEST_PROGS) | |||
9 | 10 | ||
10 | CFLAGS += -m64 -I../../../../../usr/include -I../tm -mhtm -fno-pie | 11 | CFLAGS += -m64 -I../../../../../usr/include -I../tm -mhtm -fno-pie |
11 | 12 | ||
13 | ptrace-pkey core-pkey: child.h | ||
14 | ptrace-pkey core-pkey: LDLIBS += -pthread | ||
15 | |||
12 | $(TEST_PROGS): ../harness.c ../utils.c ../lib/reg.S ptrace.h | 16 | $(TEST_PROGS): ../harness.c ../utils.c ../lib/reg.S ptrace.h |
13 | 17 | ||
14 | clean: | 18 | clean: |
diff --git a/tools/testing/selftests/powerpc/ptrace/child.h b/tools/testing/selftests/powerpc/ptrace/child.h new file mode 100644 index 000000000000..d7275b7b33dc --- /dev/null +++ b/tools/testing/selftests/powerpc/ptrace/child.h | |||
@@ -0,0 +1,139 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0+ | ||
2 | /* | ||
3 | * Helper functions to sync execution between parent and child processes. | ||
4 | * | ||
5 | * Copyright 2018, Thiago Jung Bauermann, IBM Corporation. | ||
6 | */ | ||
7 | #include <stdio.h> | ||
8 | #include <stdbool.h> | ||
9 | #include <semaphore.h> | ||
10 | |||
11 | /* | ||
12 | * Information in a shared memory location for synchronization between child and | ||
13 | * parent. | ||
14 | */ | ||
15 | struct child_sync { | ||
16 | /* The parent waits on this semaphore. */ | ||
17 | sem_t sem_parent; | ||
18 | |||
19 | /* If true, the child should give up as well. */ | ||
20 | bool parent_gave_up; | ||
21 | |||
22 | /* The child waits on this semaphore. */ | ||
23 | sem_t sem_child; | ||
24 | |||
25 | /* If true, the parent should give up as well. */ | ||
26 | bool child_gave_up; | ||
27 | }; | ||
28 | |||
29 | #define CHILD_FAIL_IF(x, sync) \ | ||
30 | do { \ | ||
31 | if (x) { \ | ||
32 | fprintf(stderr, \ | ||
33 | "[FAIL] Test FAILED on line %d\n", __LINE__); \ | ||
34 | (sync)->child_gave_up = true; \ | ||
35 | prod_parent(sync); \ | ||
36 | return 1; \ | ||
37 | } \ | ||
38 | } while (0) | ||
39 | |||
40 | #define PARENT_FAIL_IF(x, sync) \ | ||
41 | do { \ | ||
42 | if (x) { \ | ||
43 | fprintf(stderr, \ | ||
44 | "[FAIL] Test FAILED on line %d\n", __LINE__); \ | ||
45 | (sync)->parent_gave_up = true; \ | ||
46 | prod_child(sync); \ | ||
47 | return 1; \ | ||
48 | } \ | ||
49 | } while (0) | ||
50 | |||
51 | #define PARENT_SKIP_IF_UNSUPPORTED(x, sync) \ | ||
52 | do { \ | ||
53 | if ((x) == -1 && (errno == ENODEV || errno == EINVAL)) { \ | ||
54 | (sync)->parent_gave_up = true; \ | ||
55 | prod_child(sync); \ | ||
56 | SKIP_IF(1); \ | ||
57 | } \ | ||
58 | } while (0) | ||
59 | |||
60 | int init_child_sync(struct child_sync *sync) | ||
61 | { | ||
62 | int ret; | ||
63 | |||
64 | ret = sem_init(&sync->sem_parent, 1, 0); | ||
65 | if (ret) { | ||
66 | perror("Semaphore initialization failed"); | ||
67 | return 1; | ||
68 | } | ||
69 | |||
70 | ret = sem_init(&sync->sem_child, 1, 0); | ||
71 | if (ret) { | ||
72 | perror("Semaphore initialization failed"); | ||
73 | return 1; | ||
74 | } | ||
75 | |||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | void destroy_child_sync(struct child_sync *sync) | ||
80 | { | ||
81 | sem_destroy(&sync->sem_parent); | ||
82 | sem_destroy(&sync->sem_child); | ||
83 | } | ||
84 | |||
85 | int wait_child(struct child_sync *sync) | ||
86 | { | ||
87 | int ret; | ||
88 | |||
89 | /* Wait until the child prods us. */ | ||
90 | ret = sem_wait(&sync->sem_parent); | ||
91 | if (ret) { | ||
92 | perror("Error waiting for child"); | ||
93 | return 1; | ||
94 | } | ||
95 | |||
96 | return sync->child_gave_up; | ||
97 | } | ||
98 | |||
99 | int prod_child(struct child_sync *sync) | ||
100 | { | ||
101 | int ret; | ||
102 | |||
103 | /* Unblock the child now. */ | ||
104 | ret = sem_post(&sync->sem_child); | ||
105 | if (ret) { | ||
106 | perror("Error prodding child"); | ||
107 | return 1; | ||
108 | } | ||
109 | |||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | int wait_parent(struct child_sync *sync) | ||
114 | { | ||
115 | int ret; | ||
116 | |||
117 | /* Wait until the parent prods us. */ | ||
118 | ret = sem_wait(&sync->sem_child); | ||
119 | if (ret) { | ||
120 | perror("Error waiting for parent"); | ||
121 | return 1; | ||
122 | } | ||
123 | |||
124 | return sync->parent_gave_up; | ||
125 | } | ||
126 | |||
127 | int prod_parent(struct child_sync *sync) | ||
128 | { | ||
129 | int ret; | ||
130 | |||
131 | /* Unblock the parent now. */ | ||
132 | ret = sem_post(&sync->sem_parent); | ||
133 | if (ret) { | ||
134 | perror("Error prodding parent"); | ||
135 | return 1; | ||
136 | } | ||
137 | |||
138 | return 0; | ||
139 | } | ||
diff --git a/tools/testing/selftests/powerpc/ptrace/core-pkey.c b/tools/testing/selftests/powerpc/ptrace/core-pkey.c new file mode 100644 index 000000000000..36bc312b1f5c --- /dev/null +++ b/tools/testing/selftests/powerpc/ptrace/core-pkey.c | |||
@@ -0,0 +1,461 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0+ | ||
2 | /* | ||
3 | * Ptrace test for Memory Protection Key registers | ||
4 | * | ||
5 | * Copyright (C) 2015 Anshuman Khandual, IBM Corporation. | ||
6 | * Copyright (C) 2018 IBM Corporation. | ||
7 | */ | ||
8 | #include <limits.h> | ||
9 | #include <linux/kernel.h> | ||
10 | #include <sys/mman.h> | ||
11 | #include <sys/types.h> | ||
12 | #include <sys/stat.h> | ||
13 | #include <sys/time.h> | ||
14 | #include <sys/resource.h> | ||
15 | #include <fcntl.h> | ||
16 | #include <unistd.h> | ||
17 | #include "ptrace.h" | ||
18 | #include "child.h" | ||
19 | |||
20 | #ifndef __NR_pkey_alloc | ||
21 | #define __NR_pkey_alloc 384 | ||
22 | #endif | ||
23 | |||
24 | #ifndef __NR_pkey_free | ||
25 | #define __NR_pkey_free 385 | ||
26 | #endif | ||
27 | |||
28 | #ifndef NT_PPC_PKEY | ||
29 | #define NT_PPC_PKEY 0x110 | ||
30 | #endif | ||
31 | |||
32 | #ifndef PKEY_DISABLE_EXECUTE | ||
33 | #define PKEY_DISABLE_EXECUTE 0x4 | ||
34 | #endif | ||
35 | |||
36 | #define AMR_BITS_PER_PKEY 2 | ||
37 | #define PKEY_REG_BITS (sizeof(u64) * 8) | ||
38 | #define pkeyshift(pkey) (PKEY_REG_BITS - ((pkey + 1) * AMR_BITS_PER_PKEY)) | ||
39 | |||
40 | #define CORE_FILE_LIMIT (5 * 1024 * 1024) /* 5 MB should be enough */ | ||
41 | |||
42 | static const char core_pattern_file[] = "/proc/sys/kernel/core_pattern"; | ||
43 | |||
44 | static const char user_write[] = "[User Write (Running)]"; | ||
45 | static const char core_read_running[] = "[Core Read (Running)]"; | ||
46 | |||
47 | /* Information shared between the parent and the child. */ | ||
48 | struct shared_info { | ||
49 | struct child_sync child_sync; | ||
50 | |||
51 | /* AMR value the parent expects to read in the core file. */ | ||
52 | unsigned long amr; | ||
53 | |||
54 | /* IAMR value the parent expects to read in the core file. */ | ||
55 | unsigned long iamr; | ||
56 | |||
57 | /* UAMOR value the parent expects to read in the core file. */ | ||
58 | unsigned long uamor; | ||
59 | |||
60 | /* When the child crashed. */ | ||
61 | time_t core_time; | ||
62 | }; | ||
63 | |||
64 | static int sys_pkey_alloc(unsigned long flags, unsigned long init_access_rights) | ||
65 | { | ||
66 | return syscall(__NR_pkey_alloc, flags, init_access_rights); | ||
67 | } | ||
68 | |||
69 | static int sys_pkey_free(int pkey) | ||
70 | { | ||
71 | return syscall(__NR_pkey_free, pkey); | ||
72 | } | ||
73 | |||
74 | static int increase_core_file_limit(void) | ||
75 | { | ||
76 | struct rlimit rlim; | ||
77 | int ret; | ||
78 | |||
79 | ret = getrlimit(RLIMIT_CORE, &rlim); | ||
80 | FAIL_IF(ret); | ||
81 | |||
82 | if (rlim.rlim_cur != RLIM_INFINITY && rlim.rlim_cur < CORE_FILE_LIMIT) { | ||
83 | rlim.rlim_cur = CORE_FILE_LIMIT; | ||
84 | |||
85 | if (rlim.rlim_max != RLIM_INFINITY && | ||
86 | rlim.rlim_max < CORE_FILE_LIMIT) | ||
87 | rlim.rlim_max = CORE_FILE_LIMIT; | ||
88 | |||
89 | ret = setrlimit(RLIMIT_CORE, &rlim); | ||
90 | FAIL_IF(ret); | ||
91 | } | ||
92 | |||
93 | ret = getrlimit(RLIMIT_FSIZE, &rlim); | ||
94 | FAIL_IF(ret); | ||
95 | |||
96 | if (rlim.rlim_cur != RLIM_INFINITY && rlim.rlim_cur < CORE_FILE_LIMIT) { | ||
97 | rlim.rlim_cur = CORE_FILE_LIMIT; | ||
98 | |||
99 | if (rlim.rlim_max != RLIM_INFINITY && | ||
100 | rlim.rlim_max < CORE_FILE_LIMIT) | ||
101 | rlim.rlim_max = CORE_FILE_LIMIT; | ||
102 | |||
103 | ret = setrlimit(RLIMIT_FSIZE, &rlim); | ||
104 | FAIL_IF(ret); | ||
105 | } | ||
106 | |||
107 | return TEST_PASS; | ||
108 | } | ||
109 | |||
110 | static int child(struct shared_info *info) | ||
111 | { | ||
112 | bool disable_execute = true; | ||
113 | int pkey1, pkey2, pkey3; | ||
114 | int *ptr, ret; | ||
115 | |||
116 | /* Wait until parent fills out the initial register values. */ | ||
117 | ret = wait_parent(&info->child_sync); | ||
118 | if (ret) | ||
119 | return ret; | ||
120 | |||
121 | ret = increase_core_file_limit(); | ||
122 | FAIL_IF(ret); | ||
123 | |||
124 | /* Get some pkeys so that we can change their bits in the AMR. */ | ||
125 | pkey1 = sys_pkey_alloc(0, PKEY_DISABLE_EXECUTE); | ||
126 | if (pkey1 < 0) { | ||
127 | pkey1 = sys_pkey_alloc(0, 0); | ||
128 | FAIL_IF(pkey1 < 0); | ||
129 | |||
130 | disable_execute = false; | ||
131 | } | ||
132 | |||
133 | pkey2 = sys_pkey_alloc(0, 0); | ||
134 | FAIL_IF(pkey2 < 0); | ||
135 | |||
136 | pkey3 = sys_pkey_alloc(0, 0); | ||
137 | FAIL_IF(pkey3 < 0); | ||
138 | |||
139 | info->amr |= 3ul << pkeyshift(pkey1) | 2ul << pkeyshift(pkey2); | ||
140 | |||
141 | if (disable_execute) | ||
142 | info->iamr |= 1ul << pkeyshift(pkey1); | ||
143 | |||
144 | info->uamor |= 3ul << pkeyshift(pkey1) | 3ul << pkeyshift(pkey2); | ||
145 | |||
146 | printf("%-30s AMR: %016lx pkey1: %d pkey2: %d pkey3: %d\n", | ||
147 | user_write, info->amr, pkey1, pkey2, pkey3); | ||
148 | |||
149 | mtspr(SPRN_AMR, info->amr); | ||
150 | |||
151 | /* | ||
152 | * We won't use pkey3. This tests whether the kernel restores the UAMOR | ||
153 | * permissions after a key is freed. | ||
154 | */ | ||
155 | sys_pkey_free(pkey3); | ||
156 | |||
157 | info->core_time = time(NULL); | ||
158 | |||
159 | /* Crash. */ | ||
160 | ptr = 0; | ||
161 | *ptr = 1; | ||
162 | |||
163 | /* Shouldn't get here. */ | ||
164 | FAIL_IF(true); | ||
165 | |||
166 | return TEST_FAIL; | ||
167 | } | ||
168 | |||
169 | /* Return file size if filename exists and pass sanity check, or zero if not. */ | ||
170 | static off_t try_core_file(const char *filename, struct shared_info *info, | ||
171 | pid_t pid) | ||
172 | { | ||
173 | struct stat buf; | ||
174 | int ret; | ||
175 | |||
176 | ret = stat(filename, &buf); | ||
177 | if (ret == -1) | ||
178 | return TEST_FAIL; | ||
179 | |||
180 | /* Make sure we're not using a stale core file. */ | ||
181 | return buf.st_mtime >= info->core_time ? buf.st_size : TEST_FAIL; | ||
182 | } | ||
183 | |||
184 | static Elf64_Nhdr *next_note(Elf64_Nhdr *nhdr) | ||
185 | { | ||
186 | return (void *) nhdr + sizeof(*nhdr) + | ||
187 | __ALIGN_KERNEL(nhdr->n_namesz, 4) + | ||
188 | __ALIGN_KERNEL(nhdr->n_descsz, 4); | ||
189 | } | ||
190 | |||
191 | static int check_core_file(struct shared_info *info, Elf64_Ehdr *ehdr, | ||
192 | off_t core_size) | ||
193 | { | ||
194 | unsigned long *regs; | ||
195 | Elf64_Phdr *phdr; | ||
196 | Elf64_Nhdr *nhdr; | ||
197 | size_t phdr_size; | ||
198 | void *p = ehdr, *note; | ||
199 | int ret; | ||
200 | |||
201 | ret = memcmp(ehdr->e_ident, ELFMAG, SELFMAG); | ||
202 | FAIL_IF(ret); | ||
203 | |||
204 | FAIL_IF(ehdr->e_type != ET_CORE); | ||
205 | FAIL_IF(ehdr->e_machine != EM_PPC64); | ||
206 | FAIL_IF(ehdr->e_phoff == 0 || ehdr->e_phnum == 0); | ||
207 | |||
208 | /* | ||
209 | * e_phnum is at most 65535 so calculating the size of the | ||
210 | * program header cannot overflow. | ||
211 | */ | ||
212 | phdr_size = sizeof(*phdr) * ehdr->e_phnum; | ||
213 | |||
214 | /* Sanity check the program header table location. */ | ||
215 | FAIL_IF(ehdr->e_phoff + phdr_size < ehdr->e_phoff); | ||
216 | FAIL_IF(ehdr->e_phoff + phdr_size > core_size); | ||
217 | |||
218 | /* Find the PT_NOTE segment. */ | ||
219 | for (phdr = p + ehdr->e_phoff; | ||
220 | (void *) phdr < p + ehdr->e_phoff + phdr_size; | ||
221 | phdr += ehdr->e_phentsize) | ||
222 | if (phdr->p_type == PT_NOTE) | ||
223 | break; | ||
224 | |||
225 | FAIL_IF((void *) phdr >= p + ehdr->e_phoff + phdr_size); | ||
226 | |||
227 | /* Find the NT_PPC_PKEY note. */ | ||
228 | for (nhdr = p + phdr->p_offset; | ||
229 | (void *) nhdr < p + phdr->p_offset + phdr->p_filesz; | ||
230 | nhdr = next_note(nhdr)) | ||
231 | if (nhdr->n_type == NT_PPC_PKEY) | ||
232 | break; | ||
233 | |||
234 | FAIL_IF((void *) nhdr >= p + phdr->p_offset + phdr->p_filesz); | ||
235 | FAIL_IF(nhdr->n_descsz == 0); | ||
236 | |||
237 | p = nhdr; | ||
238 | note = p + sizeof(*nhdr) + __ALIGN_KERNEL(nhdr->n_namesz, 4); | ||
239 | |||
240 | regs = (unsigned long *) note; | ||
241 | |||
242 | printf("%-30s AMR: %016lx IAMR: %016lx UAMOR: %016lx\n", | ||
243 | core_read_running, regs[0], regs[1], regs[2]); | ||
244 | |||
245 | FAIL_IF(regs[0] != info->amr); | ||
246 | FAIL_IF(regs[1] != info->iamr); | ||
247 | FAIL_IF(regs[2] != info->uamor); | ||
248 | |||
249 | return TEST_PASS; | ||
250 | } | ||
251 | |||
252 | static int parent(struct shared_info *info, pid_t pid) | ||
253 | { | ||
254 | char *filenames, *filename[3]; | ||
255 | int fd, i, ret, status; | ||
256 | unsigned long regs[3]; | ||
257 | off_t core_size; | ||
258 | void *core; | ||
259 | |||
260 | /* | ||
261 | * Get the initial values for AMR, IAMR and UAMOR and communicate them | ||
262 | * to the child. | ||
263 | */ | ||
264 | ret = ptrace_read_regs(pid, NT_PPC_PKEY, regs, 3); | ||
265 | PARENT_SKIP_IF_UNSUPPORTED(ret, &info->child_sync); | ||
266 | PARENT_FAIL_IF(ret, &info->child_sync); | ||
267 | |||
268 | info->amr = regs[0]; | ||
269 | info->iamr = regs[1]; | ||
270 | info->uamor = regs[2]; | ||
271 | |||
272 | /* Wake up child so that it can set itself up. */ | ||
273 | ret = prod_child(&info->child_sync); | ||
274 | PARENT_FAIL_IF(ret, &info->child_sync); | ||
275 | |||
276 | ret = wait(&status); | ||
277 | if (ret != pid) { | ||
278 | printf("Child's exit status not captured\n"); | ||
279 | return TEST_FAIL; | ||
280 | } else if (!WIFSIGNALED(status) || !WCOREDUMP(status)) { | ||
281 | printf("Child didn't dump core\n"); | ||
282 | return TEST_FAIL; | ||
283 | } | ||
284 | |||
285 | /* Construct array of core file names to try. */ | ||
286 | |||
287 | filename[0] = filenames = malloc(PATH_MAX); | ||
288 | if (!filenames) { | ||
289 | perror("Error allocating memory"); | ||
290 | return TEST_FAIL; | ||
291 | } | ||
292 | |||
293 | ret = snprintf(filename[0], PATH_MAX, "core-pkey.%d", pid); | ||
294 | if (ret < 0 || ret >= PATH_MAX) { | ||
295 | ret = TEST_FAIL; | ||
296 | goto out; | ||
297 | } | ||
298 | |||
299 | filename[1] = filename[0] + ret + 1; | ||
300 | ret = snprintf(filename[1], PATH_MAX - ret - 1, "core.%d", pid); | ||
301 | if (ret < 0 || ret >= PATH_MAX - ret - 1) { | ||
302 | ret = TEST_FAIL; | ||
303 | goto out; | ||
304 | } | ||
305 | filename[2] = "core"; | ||
306 | |||
307 | for (i = 0; i < 3; i++) { | ||
308 | core_size = try_core_file(filename[i], info, pid); | ||
309 | if (core_size != TEST_FAIL) | ||
310 | break; | ||
311 | } | ||
312 | |||
313 | if (i == 3) { | ||
314 | printf("Couldn't find core file\n"); | ||
315 | ret = TEST_FAIL; | ||
316 | goto out; | ||
317 | } | ||
318 | |||
319 | fd = open(filename[i], O_RDONLY); | ||
320 | if (fd == -1) { | ||
321 | perror("Error opening core file"); | ||
322 | ret = TEST_FAIL; | ||
323 | goto out; | ||
324 | } | ||
325 | |||
326 | core = mmap(NULL, core_size, PROT_READ, MAP_PRIVATE, fd, 0); | ||
327 | if (core == (void *) -1) { | ||
328 | perror("Error mmaping core file"); | ||
329 | ret = TEST_FAIL; | ||
330 | goto out; | ||
331 | } | ||
332 | |||
333 | ret = check_core_file(info, core, core_size); | ||
334 | |||
335 | munmap(core, core_size); | ||
336 | close(fd); | ||
337 | unlink(filename[i]); | ||
338 | |||
339 | out: | ||
340 | free(filenames); | ||
341 | |||
342 | return ret; | ||
343 | } | ||
344 | |||
345 | static int write_core_pattern(const char *core_pattern) | ||
346 | { | ||
347 | size_t len = strlen(core_pattern), ret; | ||
348 | FILE *f; | ||
349 | |||
350 | f = fopen(core_pattern_file, "w"); | ||
351 | if (!f) { | ||
352 | perror("Error writing to core_pattern file"); | ||
353 | return TEST_FAIL; | ||
354 | } | ||
355 | |||
356 | ret = fwrite(core_pattern, 1, len, f); | ||
357 | fclose(f); | ||
358 | if (ret != len) { | ||
359 | perror("Error writing to core_pattern file"); | ||
360 | return TEST_FAIL; | ||
361 | } | ||
362 | |||
363 | return TEST_PASS; | ||
364 | } | ||
365 | |||
366 | static int setup_core_pattern(char **core_pattern_, bool *changed_) | ||
367 | { | ||
368 | FILE *f; | ||
369 | char *core_pattern; | ||
370 | int ret; | ||
371 | |||
372 | core_pattern = malloc(PATH_MAX); | ||
373 | if (!core_pattern) { | ||
374 | perror("Error allocating memory"); | ||
375 | return TEST_FAIL; | ||
376 | } | ||
377 | |||
378 | f = fopen(core_pattern_file, "r"); | ||
379 | if (!f) { | ||
380 | perror("Error opening core_pattern file"); | ||
381 | ret = TEST_FAIL; | ||
382 | goto out; | ||
383 | } | ||
384 | |||
385 | ret = fread(core_pattern, 1, PATH_MAX, f); | ||
386 | fclose(f); | ||
387 | if (!ret) { | ||
388 | perror("Error reading core_pattern file"); | ||
389 | ret = TEST_FAIL; | ||
390 | goto out; | ||
391 | } | ||
392 | |||
393 | /* Check whether we can predict the name of the core file. */ | ||
394 | if (!strcmp(core_pattern, "core") || !strcmp(core_pattern, "core.%p")) | ||
395 | *changed_ = false; | ||
396 | else { | ||
397 | ret = write_core_pattern("core-pkey.%p"); | ||
398 | if (ret) | ||
399 | goto out; | ||
400 | |||
401 | *changed_ = true; | ||
402 | } | ||
403 | |||
404 | *core_pattern_ = core_pattern; | ||
405 | ret = TEST_PASS; | ||
406 | |||
407 | out: | ||
408 | if (ret) | ||
409 | free(core_pattern); | ||
410 | |||
411 | return ret; | ||
412 | } | ||
413 | |||
414 | static int core_pkey(void) | ||
415 | { | ||
416 | char *core_pattern; | ||
417 | bool changed_core_pattern; | ||
418 | struct shared_info *info; | ||
419 | int shm_id; | ||
420 | int ret; | ||
421 | pid_t pid; | ||
422 | |||
423 | ret = setup_core_pattern(&core_pattern, &changed_core_pattern); | ||
424 | if (ret) | ||
425 | return ret; | ||
426 | |||
427 | shm_id = shmget(IPC_PRIVATE, sizeof(*info), 0777 | IPC_CREAT); | ||
428 | info = shmat(shm_id, NULL, 0); | ||
429 | |||
430 | ret = init_child_sync(&info->child_sync); | ||
431 | if (ret) | ||
432 | return ret; | ||
433 | |||
434 | pid = fork(); | ||
435 | if (pid < 0) { | ||
436 | perror("fork() failed"); | ||
437 | ret = TEST_FAIL; | ||
438 | } else if (pid == 0) | ||
439 | ret = child(info); | ||
440 | else | ||
441 | ret = parent(info, pid); | ||
442 | |||
443 | shmdt(info); | ||
444 | |||
445 | if (pid) { | ||
446 | destroy_child_sync(&info->child_sync); | ||
447 | shmctl(shm_id, IPC_RMID, NULL); | ||
448 | |||
449 | if (changed_core_pattern) | ||
450 | write_core_pattern(core_pattern); | ||
451 | } | ||
452 | |||
453 | free(core_pattern); | ||
454 | |||
455 | return ret; | ||
456 | } | ||
457 | |||
458 | int main(int argc, char *argv[]) | ||
459 | { | ||
460 | return test_harness(core_pkey, "core_pkey"); | ||
461 | } | ||
diff --git a/tools/testing/selftests/powerpc/ptrace/perf-hwbreak.c b/tools/testing/selftests/powerpc/ptrace/perf-hwbreak.c new file mode 100644 index 000000000000..60df0b5e628a --- /dev/null +++ b/tools/testing/selftests/powerpc/ptrace/perf-hwbreak.c | |||
@@ -0,0 +1,195 @@ | |||
1 | /* | ||
2 | * perf events self profiling example test case for hw breakpoints. | ||
3 | * | ||
4 | * This tests perf PERF_TYPE_BREAKPOINT parameters | ||
5 | * 1) tests all variants of the break on read/write flags | ||
6 | * 2) tests exclude_user == 0 and 1 | ||
7 | * 3) test array matches (if DAWR is supported)) | ||
8 | * 4) test different numbers of breakpoints matches | ||
9 | * | ||
10 | * Configure this breakpoint, then read and write the data a number of | ||
11 | * times. Then check the output count from perf is as expected. | ||
12 | * | ||
13 | * Based on: | ||
14 | * http://ozlabs.org/~anton/junkcode/perf_events_example1.c | ||
15 | * | ||
16 | * Copyright (C) 2018 Michael Neuling, IBM Corporation. | ||
17 | * | ||
18 | * This program is free software; you can redistribute it and/or | ||
19 | * modify it under the terms of the GNU General Public License | ||
20 | * as published by the Free Software Foundation; either version | ||
21 | * 2 of the License, or (at your option) any later version. | ||
22 | */ | ||
23 | |||
24 | #include <unistd.h> | ||
25 | #include <assert.h> | ||
26 | #include <stdio.h> | ||
27 | #include <stdlib.h> | ||
28 | #include <string.h> | ||
29 | #include <sys/ioctl.h> | ||
30 | #include <elf.h> | ||
31 | #include <pthread.h> | ||
32 | #include <sys/syscall.h> | ||
33 | #include <linux/perf_event.h> | ||
34 | #include <linux/hw_breakpoint.h> | ||
35 | #include "utils.h" | ||
36 | |||
37 | #define MAX_LOOPS 10000 | ||
38 | |||
39 | #define DAWR_LENGTH_MAX ((0x3f + 1) * 8) | ||
40 | |||
41 | static inline int sys_perf_event_open(struct perf_event_attr *attr, pid_t pid, | ||
42 | int cpu, int group_fd, | ||
43 | unsigned long flags) | ||
44 | { | ||
45 | attr->size = sizeof(*attr); | ||
46 | return syscall(__NR_perf_event_open, attr, pid, cpu, group_fd, flags); | ||
47 | } | ||
48 | |||
49 | static inline bool breakpoint_test(int len) | ||
50 | { | ||
51 | struct perf_event_attr attr; | ||
52 | int fd; | ||
53 | |||
54 | /* setup counters */ | ||
55 | memset(&attr, 0, sizeof(attr)); | ||
56 | attr.disabled = 1; | ||
57 | attr.type = PERF_TYPE_BREAKPOINT; | ||
58 | attr.bp_type = HW_BREAKPOINT_R; | ||
59 | /* bp_addr can point anywhere but needs to be aligned */ | ||
60 | attr.bp_addr = (__u64)(&attr) & 0xfffffffffffff800; | ||
61 | attr.bp_len = len; | ||
62 | fd = sys_perf_event_open(&attr, 0, -1, -1, 0); | ||
63 | if (fd < 0) | ||
64 | return false; | ||
65 | close(fd); | ||
66 | return true; | ||
67 | } | ||
68 | |||
69 | static inline bool perf_breakpoint_supported(void) | ||
70 | { | ||
71 | return breakpoint_test(4); | ||
72 | } | ||
73 | |||
74 | static inline bool dawr_supported(void) | ||
75 | { | ||
76 | return breakpoint_test(DAWR_LENGTH_MAX); | ||
77 | } | ||
78 | |||
79 | static int runtestsingle(int readwriteflag, int exclude_user, int arraytest) | ||
80 | { | ||
81 | int i,j; | ||
82 | struct perf_event_attr attr; | ||
83 | size_t res; | ||
84 | unsigned long long breaks, needed; | ||
85 | int readint; | ||
86 | int readintarraybig[2*DAWR_LENGTH_MAX/sizeof(int)]; | ||
87 | int *readintalign; | ||
88 | volatile int *ptr; | ||
89 | int break_fd; | ||
90 | int loop_num = MAX_LOOPS - (rand() % 100); /* provide some variability */ | ||
91 | volatile int *k; | ||
92 | |||
93 | /* align to 0x400 boundary as required by DAWR */ | ||
94 | readintalign = (int *)(((unsigned long)readintarraybig + 0x7ff) & | ||
95 | 0xfffffffffffff800); | ||
96 | |||
97 | ptr = &readint; | ||
98 | if (arraytest) | ||
99 | ptr = &readintalign[0]; | ||
100 | |||
101 | /* setup counters */ | ||
102 | memset(&attr, 0, sizeof(attr)); | ||
103 | attr.disabled = 1; | ||
104 | attr.type = PERF_TYPE_BREAKPOINT; | ||
105 | attr.bp_type = readwriteflag; | ||
106 | attr.bp_addr = (__u64)ptr; | ||
107 | attr.bp_len = sizeof(int); | ||
108 | if (arraytest) | ||
109 | attr.bp_len = DAWR_LENGTH_MAX; | ||
110 | attr.exclude_user = exclude_user; | ||
111 | break_fd = sys_perf_event_open(&attr, 0, -1, -1, 0); | ||
112 | if (break_fd < 0) { | ||
113 | perror("sys_perf_event_open"); | ||
114 | exit(1); | ||
115 | } | ||
116 | |||
117 | /* start counters */ | ||
118 | ioctl(break_fd, PERF_EVENT_IOC_ENABLE); | ||
119 | |||
120 | /* Test a bunch of reads and writes */ | ||
121 | k = &readint; | ||
122 | for (i = 0; i < loop_num; i++) { | ||
123 | if (arraytest) | ||
124 | k = &(readintalign[i % (DAWR_LENGTH_MAX/sizeof(int))]); | ||
125 | |||
126 | j = *k; | ||
127 | *k = j; | ||
128 | } | ||
129 | |||
130 | /* stop counters */ | ||
131 | ioctl(break_fd, PERF_EVENT_IOC_DISABLE); | ||
132 | |||
133 | /* read and check counters */ | ||
134 | res = read(break_fd, &breaks, sizeof(unsigned long long)); | ||
135 | assert(res == sizeof(unsigned long long)); | ||
136 | /* we read and write each loop, so subtract the ones we are counting */ | ||
137 | needed = 0; | ||
138 | if (readwriteflag & HW_BREAKPOINT_R) | ||
139 | needed += loop_num; | ||
140 | if (readwriteflag & HW_BREAKPOINT_W) | ||
141 | needed += loop_num; | ||
142 | needed = needed * (1 - exclude_user); | ||
143 | printf("TESTED: addr:0x%lx brks:% 8lld loops:% 8i rw:%i !user:%i array:%i\n", | ||
144 | (unsigned long int)ptr, breaks, loop_num, readwriteflag, exclude_user, arraytest); | ||
145 | if (breaks != needed) { | ||
146 | printf("FAILED: 0x%lx brks:%lld needed:%lli %i %i %i\n\n", | ||
147 | (unsigned long int)ptr, breaks, needed, loop_num, readwriteflag, exclude_user); | ||
148 | return 1; | ||
149 | } | ||
150 | close(break_fd); | ||
151 | |||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | static int runtest(void) | ||
156 | { | ||
157 | int rwflag; | ||
158 | int exclude_user; | ||
159 | int ret; | ||
160 | |||
161 | /* | ||
162 | * perf defines rwflag as two bits read and write and at least | ||
163 | * one must be set. So range 1-3. | ||
164 | */ | ||
165 | for (rwflag = 1 ; rwflag < 4; rwflag++) { | ||
166 | for (exclude_user = 0 ; exclude_user < 2; exclude_user++) { | ||
167 | ret = runtestsingle(rwflag, exclude_user, 0); | ||
168 | if (ret) | ||
169 | return ret; | ||
170 | |||
171 | /* if we have the dawr, we can do an array test */ | ||
172 | if (!dawr_supported()) | ||
173 | continue; | ||
174 | ret = runtestsingle(rwflag, exclude_user, 1); | ||
175 | if (ret) | ||
176 | return ret; | ||
177 | } | ||
178 | } | ||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | |||
183 | static int perf_hwbreak(void) | ||
184 | { | ||
185 | srand ( time(NULL) ); | ||
186 | |||
187 | SKIP_IF(!perf_breakpoint_supported()); | ||
188 | |||
189 | return runtest(); | ||
190 | } | ||
191 | |||
192 | int main(int argc, char *argv[], char **envp) | ||
193 | { | ||
194 | return test_harness(perf_hwbreak, "perf_hwbreak"); | ||
195 | } | ||
diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-hwbreak.c b/tools/testing/selftests/powerpc/ptrace/ptrace-hwbreak.c new file mode 100644 index 000000000000..3066d310f32b --- /dev/null +++ b/tools/testing/selftests/powerpc/ptrace/ptrace-hwbreak.c | |||
@@ -0,0 +1,342 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0+ | ||
2 | |||
3 | /* | ||
4 | * Ptrace test for hw breakpoints | ||
5 | * | ||
6 | * Based on tools/testing/selftests/breakpoints/breakpoint_test.c | ||
7 | * | ||
8 | * This test forks and the parent then traces the child doing various | ||
9 | * types of ptrace enabled breakpoints | ||
10 | * | ||
11 | * Copyright (C) 2018 Michael Neuling, IBM Corporation. | ||
12 | */ | ||
13 | |||
14 | #include <sys/ptrace.h> | ||
15 | #include <unistd.h> | ||
16 | #include <stddef.h> | ||
17 | #include <sys/user.h> | ||
18 | #include <stdio.h> | ||
19 | #include <stdlib.h> | ||
20 | #include <signal.h> | ||
21 | #include <sys/types.h> | ||
22 | #include <sys/wait.h> | ||
23 | #include "ptrace.h" | ||
24 | |||
25 | /* Breakpoint access modes */ | ||
26 | enum { | ||
27 | BP_X = 1, | ||
28 | BP_RW = 2, | ||
29 | BP_W = 4, | ||
30 | }; | ||
31 | |||
32 | static pid_t child_pid; | ||
33 | static struct ppc_debug_info dbginfo; | ||
34 | |||
35 | static void get_dbginfo(void) | ||
36 | { | ||
37 | int ret; | ||
38 | |||
39 | ret = ptrace(PPC_PTRACE_GETHWDBGINFO, child_pid, NULL, &dbginfo); | ||
40 | if (ret) { | ||
41 | perror("Can't get breakpoint info\n"); | ||
42 | exit(-1); | ||
43 | } | ||
44 | } | ||
45 | |||
46 | static bool hwbreak_present(void) | ||
47 | { | ||
48 | return (dbginfo.num_data_bps != 0); | ||
49 | } | ||
50 | |||
51 | static bool dawr_present(void) | ||
52 | { | ||
53 | return !!(dbginfo.features & PPC_DEBUG_FEATURE_DATA_BP_DAWR); | ||
54 | } | ||
55 | |||
56 | static void set_breakpoint_addr(void *addr) | ||
57 | { | ||
58 | int ret; | ||
59 | |||
60 | ret = ptrace(PTRACE_SET_DEBUGREG, child_pid, 0, addr); | ||
61 | if (ret) { | ||
62 | perror("Can't set breakpoint addr\n"); | ||
63 | exit(-1); | ||
64 | } | ||
65 | } | ||
66 | |||
67 | static int set_hwbreakpoint_addr(void *addr, int range) | ||
68 | { | ||
69 | int ret; | ||
70 | |||
71 | struct ppc_hw_breakpoint info; | ||
72 | |||
73 | info.version = 1; | ||
74 | info.trigger_type = PPC_BREAKPOINT_TRIGGER_RW; | ||
75 | info.addr_mode = PPC_BREAKPOINT_MODE_EXACT; | ||
76 | if (range > 0) | ||
77 | info.addr_mode = PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE; | ||
78 | info.condition_mode = PPC_BREAKPOINT_CONDITION_NONE; | ||
79 | info.addr = (__u64)addr; | ||
80 | info.addr2 = (__u64)addr + range; | ||
81 | info.condition_value = 0; | ||
82 | |||
83 | ret = ptrace(PPC_PTRACE_SETHWDEBUG, child_pid, 0, &info); | ||
84 | if (ret < 0) { | ||
85 | perror("Can't set breakpoint\n"); | ||
86 | exit(-1); | ||
87 | } | ||
88 | return ret; | ||
89 | } | ||
90 | |||
91 | static int del_hwbreakpoint_addr(int watchpoint_handle) | ||
92 | { | ||
93 | int ret; | ||
94 | |||
95 | ret = ptrace(PPC_PTRACE_DELHWDEBUG, child_pid, 0, watchpoint_handle); | ||
96 | if (ret < 0) { | ||
97 | perror("Can't delete hw breakpoint\n"); | ||
98 | exit(-1); | ||
99 | } | ||
100 | return ret; | ||
101 | } | ||
102 | |||
103 | #define DAWR_LENGTH_MAX 512 | ||
104 | |||
105 | /* Dummy variables to test read/write accesses */ | ||
106 | static unsigned long long | ||
107 | dummy_array[DAWR_LENGTH_MAX / sizeof(unsigned long long)] | ||
108 | __attribute__((aligned(512))); | ||
109 | static unsigned long long *dummy_var = dummy_array; | ||
110 | |||
111 | static void write_var(int len) | ||
112 | { | ||
113 | long long *plval; | ||
114 | char *pcval; | ||
115 | short *psval; | ||
116 | int *pival; | ||
117 | |||
118 | switch (len) { | ||
119 | case 1: | ||
120 | pcval = (char *)dummy_var; | ||
121 | *pcval = 0xff; | ||
122 | break; | ||
123 | case 2: | ||
124 | psval = (short *)dummy_var; | ||
125 | *psval = 0xffff; | ||
126 | break; | ||
127 | case 4: | ||
128 | pival = (int *)dummy_var; | ||
129 | *pival = 0xffffffff; | ||
130 | break; | ||
131 | case 8: | ||
132 | plval = (long long *)dummy_var; | ||
133 | *plval = 0xffffffffffffffffLL; | ||
134 | break; | ||
135 | } | ||
136 | } | ||
137 | |||
138 | static void read_var(int len) | ||
139 | { | ||
140 | char cval __attribute__((unused)); | ||
141 | short sval __attribute__((unused)); | ||
142 | int ival __attribute__((unused)); | ||
143 | long long lval __attribute__((unused)); | ||
144 | |||
145 | switch (len) { | ||
146 | case 1: | ||
147 | cval = *(char *)dummy_var; | ||
148 | break; | ||
149 | case 2: | ||
150 | sval = *(short *)dummy_var; | ||
151 | break; | ||
152 | case 4: | ||
153 | ival = *(int *)dummy_var; | ||
154 | break; | ||
155 | case 8: | ||
156 | lval = *(long long *)dummy_var; | ||
157 | break; | ||
158 | } | ||
159 | } | ||
160 | |||
161 | /* | ||
162 | * Do the r/w accesses to trigger the breakpoints. And run | ||
163 | * the usual traps. | ||
164 | */ | ||
165 | static void trigger_tests(void) | ||
166 | { | ||
167 | int len, ret; | ||
168 | |||
169 | ret = ptrace(PTRACE_TRACEME, 0, NULL, 0); | ||
170 | if (ret) { | ||
171 | perror("Can't be traced?\n"); | ||
172 | return; | ||
173 | } | ||
174 | |||
175 | /* Wake up father so that it sets up the first test */ | ||
176 | kill(getpid(), SIGUSR1); | ||
177 | |||
178 | /* Test write watchpoints */ | ||
179 | for (len = 1; len <= sizeof(long); len <<= 1) | ||
180 | write_var(len); | ||
181 | |||
182 | /* Test read/write watchpoints (on read accesses) */ | ||
183 | for (len = 1; len <= sizeof(long); len <<= 1) | ||
184 | read_var(len); | ||
185 | |||
186 | /* Test when breakpoint is unset */ | ||
187 | |||
188 | /* Test write watchpoints */ | ||
189 | for (len = 1; len <= sizeof(long); len <<= 1) | ||
190 | write_var(len); | ||
191 | |||
192 | /* Test read/write watchpoints (on read accesses) */ | ||
193 | for (len = 1; len <= sizeof(long); len <<= 1) | ||
194 | read_var(len); | ||
195 | } | ||
196 | |||
197 | static void check_success(const char *msg) | ||
198 | { | ||
199 | const char *msg2; | ||
200 | int status; | ||
201 | |||
202 | /* Wait for the child to SIGTRAP */ | ||
203 | wait(&status); | ||
204 | |||
205 | msg2 = "Failed"; | ||
206 | |||
207 | if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) { | ||
208 | msg2 = "Child process hit the breakpoint"; | ||
209 | } | ||
210 | |||
211 | printf("%s Result: [%s]\n", msg, msg2); | ||
212 | } | ||
213 | |||
214 | static void launch_watchpoints(char *buf, int mode, int len, | ||
215 | struct ppc_debug_info *dbginfo, bool dawr) | ||
216 | { | ||
217 | const char *mode_str; | ||
218 | unsigned long data = (unsigned long)(dummy_var); | ||
219 | int wh, range; | ||
220 | |||
221 | data &= ~0x7UL; | ||
222 | |||
223 | if (mode == BP_W) { | ||
224 | data |= (1UL << 1); | ||
225 | mode_str = "write"; | ||
226 | } else { | ||
227 | data |= (1UL << 0); | ||
228 | data |= (1UL << 1); | ||
229 | mode_str = "read"; | ||
230 | } | ||
231 | |||
232 | /* Set DABR_TRANSLATION bit */ | ||
233 | data |= (1UL << 2); | ||
234 | |||
235 | /* use PTRACE_SET_DEBUGREG breakpoints */ | ||
236 | set_breakpoint_addr((void *)data); | ||
237 | ptrace(PTRACE_CONT, child_pid, NULL, 0); | ||
238 | sprintf(buf, "Test %s watchpoint with len: %d ", mode_str, len); | ||
239 | check_success(buf); | ||
240 | /* Unregister hw brkpoint */ | ||
241 | set_breakpoint_addr(NULL); | ||
242 | |||
243 | data = (data & ~7); /* remove dabr control bits */ | ||
244 | |||
245 | /* use PPC_PTRACE_SETHWDEBUG breakpoint */ | ||
246 | if (!(dbginfo->features & PPC_DEBUG_FEATURE_DATA_BP_RANGE)) | ||
247 | return; /* not supported */ | ||
248 | wh = set_hwbreakpoint_addr((void *)data, 0); | ||
249 | ptrace(PTRACE_CONT, child_pid, NULL, 0); | ||
250 | sprintf(buf, "Test %s watchpoint with len: %d ", mode_str, len); | ||
251 | check_success(buf); | ||
252 | /* Unregister hw brkpoint */ | ||
253 | del_hwbreakpoint_addr(wh); | ||
254 | |||
255 | /* try a wider range */ | ||
256 | range = 8; | ||
257 | if (dawr) | ||
258 | range = 512 - ((int)data & (DAWR_LENGTH_MAX - 1)); | ||
259 | wh = set_hwbreakpoint_addr((void *)data, range); | ||
260 | ptrace(PTRACE_CONT, child_pid, NULL, 0); | ||
261 | sprintf(buf, "Test %s watchpoint with len: %d ", mode_str, len); | ||
262 | check_success(buf); | ||
263 | /* Unregister hw brkpoint */ | ||
264 | del_hwbreakpoint_addr(wh); | ||
265 | } | ||
266 | |||
267 | /* Set the breakpoints and check the child successfully trigger them */ | ||
268 | static int launch_tests(bool dawr) | ||
269 | { | ||
270 | char buf[1024]; | ||
271 | int len, i, status; | ||
272 | |||
273 | struct ppc_debug_info dbginfo; | ||
274 | |||
275 | i = ptrace(PPC_PTRACE_GETHWDBGINFO, child_pid, NULL, &dbginfo); | ||
276 | if (i) { | ||
277 | perror("Can't set breakpoint info\n"); | ||
278 | exit(-1); | ||
279 | } | ||
280 | if (!(dbginfo.features & PPC_DEBUG_FEATURE_DATA_BP_RANGE)) | ||
281 | printf("WARNING: Kernel doesn't support PPC_PTRACE_SETHWDEBUG\n"); | ||
282 | |||
283 | /* Write watchpoint */ | ||
284 | for (len = 1; len <= sizeof(long); len <<= 1) | ||
285 | launch_watchpoints(buf, BP_W, len, &dbginfo, dawr); | ||
286 | |||
287 | /* Read-Write watchpoint */ | ||
288 | for (len = 1; len <= sizeof(long); len <<= 1) | ||
289 | launch_watchpoints(buf, BP_RW, len, &dbginfo, dawr); | ||
290 | |||
291 | ptrace(PTRACE_CONT, child_pid, NULL, 0); | ||
292 | |||
293 | /* | ||
294 | * Now we have unregistered the breakpoint, access by child | ||
295 | * should not cause SIGTRAP. | ||
296 | */ | ||
297 | |||
298 | wait(&status); | ||
299 | |||
300 | if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) { | ||
301 | printf("FAIL: Child process hit the breakpoint, which is not expected\n"); | ||
302 | ptrace(PTRACE_CONT, child_pid, NULL, 0); | ||
303 | return TEST_FAIL; | ||
304 | } | ||
305 | |||
306 | if (WIFEXITED(status)) | ||
307 | printf("Child exited normally\n"); | ||
308 | |||
309 | return TEST_PASS; | ||
310 | } | ||
311 | |||
312 | static int ptrace_hwbreak(void) | ||
313 | { | ||
314 | pid_t pid; | ||
315 | int ret; | ||
316 | bool dawr; | ||
317 | |||
318 | pid = fork(); | ||
319 | if (!pid) { | ||
320 | trigger_tests(); | ||
321 | return 0; | ||
322 | } | ||
323 | |||
324 | wait(NULL); | ||
325 | |||
326 | child_pid = pid; | ||
327 | |||
328 | get_dbginfo(); | ||
329 | SKIP_IF(!hwbreak_present()); | ||
330 | dawr = dawr_present(); | ||
331 | |||
332 | ret = launch_tests(dawr); | ||
333 | |||
334 | wait(NULL); | ||
335 | |||
336 | return ret; | ||
337 | } | ||
338 | |||
339 | int main(int argc, char **argv, char **envp) | ||
340 | { | ||
341 | return test_harness(ptrace_hwbreak, "ptrace-hwbreak"); | ||
342 | } | ||
diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace-pkey.c b/tools/testing/selftests/powerpc/ptrace/ptrace-pkey.c new file mode 100644 index 000000000000..5cf631f792cc --- /dev/null +++ b/tools/testing/selftests/powerpc/ptrace/ptrace-pkey.c | |||
@@ -0,0 +1,327 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0+ | ||
2 | /* | ||
3 | * Ptrace test for Memory Protection Key registers | ||
4 | * | ||
5 | * Copyright (C) 2015 Anshuman Khandual, IBM Corporation. | ||
6 | * Copyright (C) 2018 IBM Corporation. | ||
7 | */ | ||
8 | #include "ptrace.h" | ||
9 | #include "child.h" | ||
10 | |||
11 | #ifndef __NR_pkey_alloc | ||
12 | #define __NR_pkey_alloc 384 | ||
13 | #endif | ||
14 | |||
15 | #ifndef __NR_pkey_free | ||
16 | #define __NR_pkey_free 385 | ||
17 | #endif | ||
18 | |||
19 | #ifndef NT_PPC_PKEY | ||
20 | #define NT_PPC_PKEY 0x110 | ||
21 | #endif | ||
22 | |||
23 | #ifndef PKEY_DISABLE_EXECUTE | ||
24 | #define PKEY_DISABLE_EXECUTE 0x4 | ||
25 | #endif | ||
26 | |||
27 | #define AMR_BITS_PER_PKEY 2 | ||
28 | #define PKEY_REG_BITS (sizeof(u64) * 8) | ||
29 | #define pkeyshift(pkey) (PKEY_REG_BITS - ((pkey + 1) * AMR_BITS_PER_PKEY)) | ||
30 | |||
31 | static const char user_read[] = "[User Read (Running)]"; | ||
32 | static const char user_write[] = "[User Write (Running)]"; | ||
33 | static const char ptrace_read_running[] = "[Ptrace Read (Running)]"; | ||
34 | static const char ptrace_write_running[] = "[Ptrace Write (Running)]"; | ||
35 | |||
36 | /* Information shared between the parent and the child. */ | ||
37 | struct shared_info { | ||
38 | struct child_sync child_sync; | ||
39 | |||
40 | /* AMR value the parent expects to read from the child. */ | ||
41 | unsigned long amr1; | ||
42 | |||
43 | /* AMR value the parent is expected to write to the child. */ | ||
44 | unsigned long amr2; | ||
45 | |||
46 | /* AMR value that ptrace should refuse to write to the child. */ | ||
47 | unsigned long amr3; | ||
48 | |||
49 | /* IAMR value the parent expects to read from the child. */ | ||
50 | unsigned long expected_iamr; | ||
51 | |||
52 | /* UAMOR value the parent expects to read from the child. */ | ||
53 | unsigned long expected_uamor; | ||
54 | |||
55 | /* | ||
56 | * IAMR and UAMOR values that ptrace should refuse to write to the child | ||
57 | * (even though they're valid ones) because userspace doesn't have | ||
58 | * access to those registers. | ||
59 | */ | ||
60 | unsigned long new_iamr; | ||
61 | unsigned long new_uamor; | ||
62 | }; | ||
63 | |||
64 | static int sys_pkey_alloc(unsigned long flags, unsigned long init_access_rights) | ||
65 | { | ||
66 | return syscall(__NR_pkey_alloc, flags, init_access_rights); | ||
67 | } | ||
68 | |||
69 | static int sys_pkey_free(int pkey) | ||
70 | { | ||
71 | return syscall(__NR_pkey_free, pkey); | ||
72 | } | ||
73 | |||
74 | static int child(struct shared_info *info) | ||
75 | { | ||
76 | unsigned long reg; | ||
77 | bool disable_execute = true; | ||
78 | int pkey1, pkey2, pkey3; | ||
79 | int ret; | ||
80 | |||
81 | /* Wait until parent fills out the initial register values. */ | ||
82 | ret = wait_parent(&info->child_sync); | ||
83 | if (ret) | ||
84 | return ret; | ||
85 | |||
86 | /* Get some pkeys so that we can change their bits in the AMR. */ | ||
87 | pkey1 = sys_pkey_alloc(0, PKEY_DISABLE_EXECUTE); | ||
88 | if (pkey1 < 0) { | ||
89 | pkey1 = sys_pkey_alloc(0, 0); | ||
90 | CHILD_FAIL_IF(pkey1 < 0, &info->child_sync); | ||
91 | |||
92 | disable_execute = false; | ||
93 | } | ||
94 | |||
95 | pkey2 = sys_pkey_alloc(0, 0); | ||
96 | CHILD_FAIL_IF(pkey2 < 0, &info->child_sync); | ||
97 | |||
98 | pkey3 = sys_pkey_alloc(0, 0); | ||
99 | CHILD_FAIL_IF(pkey3 < 0, &info->child_sync); | ||
100 | |||
101 | info->amr1 |= 3ul << pkeyshift(pkey1); | ||
102 | info->amr2 |= 3ul << pkeyshift(pkey2); | ||
103 | info->amr3 |= info->amr2 | 3ul << pkeyshift(pkey3); | ||
104 | |||
105 | if (disable_execute) | ||
106 | info->expected_iamr |= 1ul << pkeyshift(pkey1); | ||
107 | |||
108 | info->expected_uamor |= 3ul << pkeyshift(pkey1) | | ||
109 | 3ul << pkeyshift(pkey2); | ||
110 | info->new_iamr |= 1ul << pkeyshift(pkey1) | 1ul << pkeyshift(pkey2); | ||
111 | info->new_uamor |= 3ul << pkeyshift(pkey1); | ||
112 | |||
113 | /* | ||
114 | * We won't use pkey3. We just want a plausible but invalid key to test | ||
115 | * whether ptrace will let us write to AMR bits we are not supposed to. | ||
116 | * | ||
117 | * This also tests whether the kernel restores the UAMOR permissions | ||
118 | * after a key is freed. | ||
119 | */ | ||
120 | sys_pkey_free(pkey3); | ||
121 | |||
122 | printf("%-30s AMR: %016lx pkey1: %d pkey2: %d pkey3: %d\n", | ||
123 | user_write, info->amr1, pkey1, pkey2, pkey3); | ||
124 | |||
125 | mtspr(SPRN_AMR, info->amr1); | ||
126 | |||
127 | /* Wait for parent to read our AMR value and write a new one. */ | ||
128 | ret = prod_parent(&info->child_sync); | ||
129 | CHILD_FAIL_IF(ret, &info->child_sync); | ||
130 | |||
131 | ret = wait_parent(&info->child_sync); | ||
132 | if (ret) | ||
133 | return ret; | ||
134 | |||
135 | reg = mfspr(SPRN_AMR); | ||
136 | |||
137 | printf("%-30s AMR: %016lx\n", user_read, reg); | ||
138 | |||
139 | CHILD_FAIL_IF(reg != info->amr2, &info->child_sync); | ||
140 | |||
141 | /* | ||
142 | * Wait for parent to try to write an invalid AMR value. | ||
143 | */ | ||
144 | ret = prod_parent(&info->child_sync); | ||
145 | CHILD_FAIL_IF(ret, &info->child_sync); | ||
146 | |||
147 | ret = wait_parent(&info->child_sync); | ||
148 | if (ret) | ||
149 | return ret; | ||
150 | |||
151 | reg = mfspr(SPRN_AMR); | ||
152 | |||
153 | printf("%-30s AMR: %016lx\n", user_read, reg); | ||
154 | |||
155 | CHILD_FAIL_IF(reg != info->amr2, &info->child_sync); | ||
156 | |||
157 | /* | ||
158 | * Wait for parent to try to write an IAMR and a UAMOR value. We can't | ||
159 | * verify them, but we can verify that the AMR didn't change. | ||
160 | */ | ||
161 | ret = prod_parent(&info->child_sync); | ||
162 | CHILD_FAIL_IF(ret, &info->child_sync); | ||
163 | |||
164 | ret = wait_parent(&info->child_sync); | ||
165 | if (ret) | ||
166 | return ret; | ||
167 | |||
168 | reg = mfspr(SPRN_AMR); | ||
169 | |||
170 | printf("%-30s AMR: %016lx\n", user_read, reg); | ||
171 | |||
172 | CHILD_FAIL_IF(reg != info->amr2, &info->child_sync); | ||
173 | |||
174 | /* Now let parent now that we are finished. */ | ||
175 | |||
176 | ret = prod_parent(&info->child_sync); | ||
177 | CHILD_FAIL_IF(ret, &info->child_sync); | ||
178 | |||
179 | return TEST_PASS; | ||
180 | } | ||
181 | |||
182 | static int parent(struct shared_info *info, pid_t pid) | ||
183 | { | ||
184 | unsigned long regs[3]; | ||
185 | int ret, status; | ||
186 | |||
187 | /* | ||
188 | * Get the initial values for AMR, IAMR and UAMOR and communicate them | ||
189 | * to the child. | ||
190 | */ | ||
191 | ret = ptrace_read_regs(pid, NT_PPC_PKEY, regs, 3); | ||
192 | PARENT_SKIP_IF_UNSUPPORTED(ret, &info->child_sync); | ||
193 | PARENT_FAIL_IF(ret, &info->child_sync); | ||
194 | |||
195 | info->amr1 = info->amr2 = info->amr3 = regs[0]; | ||
196 | info->expected_iamr = info->new_iamr = regs[1]; | ||
197 | info->expected_uamor = info->new_uamor = regs[2]; | ||
198 | |||
199 | /* Wake up child so that it can set itself up. */ | ||
200 | ret = prod_child(&info->child_sync); | ||
201 | PARENT_FAIL_IF(ret, &info->child_sync); | ||
202 | |||
203 | ret = wait_child(&info->child_sync); | ||
204 | if (ret) | ||
205 | return ret; | ||
206 | |||
207 | /* Verify that we can read the pkey registers from the child. */ | ||
208 | ret = ptrace_read_regs(pid, NT_PPC_PKEY, regs, 3); | ||
209 | PARENT_FAIL_IF(ret, &info->child_sync); | ||
210 | |||
211 | printf("%-30s AMR: %016lx IAMR: %016lx UAMOR: %016lx\n", | ||
212 | ptrace_read_running, regs[0], regs[1], regs[2]); | ||
213 | |||
214 | PARENT_FAIL_IF(regs[0] != info->amr1, &info->child_sync); | ||
215 | PARENT_FAIL_IF(regs[1] != info->expected_iamr, &info->child_sync); | ||
216 | PARENT_FAIL_IF(regs[2] != info->expected_uamor, &info->child_sync); | ||
217 | |||
218 | /* Write valid AMR value in child. */ | ||
219 | ret = ptrace_write_regs(pid, NT_PPC_PKEY, &info->amr2, 1); | ||
220 | PARENT_FAIL_IF(ret, &info->child_sync); | ||
221 | |||
222 | printf("%-30s AMR: %016lx\n", ptrace_write_running, info->amr2); | ||
223 | |||
224 | /* Wake up child so that it can verify it changed. */ | ||
225 | ret = prod_child(&info->child_sync); | ||
226 | PARENT_FAIL_IF(ret, &info->child_sync); | ||
227 | |||
228 | ret = wait_child(&info->child_sync); | ||
229 | if (ret) | ||
230 | return ret; | ||
231 | |||
232 | /* Write invalid AMR value in child. */ | ||
233 | ret = ptrace_write_regs(pid, NT_PPC_PKEY, &info->amr3, 1); | ||
234 | PARENT_FAIL_IF(ret, &info->child_sync); | ||
235 | |||
236 | printf("%-30s AMR: %016lx\n", ptrace_write_running, info->amr3); | ||
237 | |||
238 | /* Wake up child so that it can verify it didn't change. */ | ||
239 | ret = prod_child(&info->child_sync); | ||
240 | PARENT_FAIL_IF(ret, &info->child_sync); | ||
241 | |||
242 | ret = wait_child(&info->child_sync); | ||
243 | if (ret) | ||
244 | return ret; | ||
245 | |||
246 | /* Try to write to IAMR. */ | ||
247 | regs[0] = info->amr1; | ||
248 | regs[1] = info->new_iamr; | ||
249 | ret = ptrace_write_regs(pid, NT_PPC_PKEY, regs, 2); | ||
250 | PARENT_FAIL_IF(!ret, &info->child_sync); | ||
251 | |||
252 | printf("%-30s AMR: %016lx IAMR: %016lx\n", | ||
253 | ptrace_write_running, regs[0], regs[1]); | ||
254 | |||
255 | /* Try to write to IAMR and UAMOR. */ | ||
256 | regs[2] = info->new_uamor; | ||
257 | ret = ptrace_write_regs(pid, NT_PPC_PKEY, regs, 3); | ||
258 | PARENT_FAIL_IF(!ret, &info->child_sync); | ||
259 | |||
260 | printf("%-30s AMR: %016lx IAMR: %016lx UAMOR: %016lx\n", | ||
261 | ptrace_write_running, regs[0], regs[1], regs[2]); | ||
262 | |||
263 | /* Verify that all registers still have their expected values. */ | ||
264 | ret = ptrace_read_regs(pid, NT_PPC_PKEY, regs, 3); | ||
265 | PARENT_FAIL_IF(ret, &info->child_sync); | ||
266 | |||
267 | printf("%-30s AMR: %016lx IAMR: %016lx UAMOR: %016lx\n", | ||
268 | ptrace_read_running, regs[0], regs[1], regs[2]); | ||
269 | |||
270 | PARENT_FAIL_IF(regs[0] != info->amr2, &info->child_sync); | ||
271 | PARENT_FAIL_IF(regs[1] != info->expected_iamr, &info->child_sync); | ||
272 | PARENT_FAIL_IF(regs[2] != info->expected_uamor, &info->child_sync); | ||
273 | |||
274 | /* Wake up child so that it can verify AMR didn't change and wrap up. */ | ||
275 | ret = prod_child(&info->child_sync); | ||
276 | PARENT_FAIL_IF(ret, &info->child_sync); | ||
277 | |||
278 | ret = wait(&status); | ||
279 | if (ret != pid) { | ||
280 | printf("Child's exit status not captured\n"); | ||
281 | ret = TEST_PASS; | ||
282 | } else if (!WIFEXITED(status)) { | ||
283 | printf("Child exited abnormally\n"); | ||
284 | ret = TEST_FAIL; | ||
285 | } else | ||
286 | ret = WEXITSTATUS(status) ? TEST_FAIL : TEST_PASS; | ||
287 | |||
288 | return ret; | ||
289 | } | ||
290 | |||
291 | static int ptrace_pkey(void) | ||
292 | { | ||
293 | struct shared_info *info; | ||
294 | int shm_id; | ||
295 | int ret; | ||
296 | pid_t pid; | ||
297 | |||
298 | shm_id = shmget(IPC_PRIVATE, sizeof(*info), 0777 | IPC_CREAT); | ||
299 | info = shmat(shm_id, NULL, 0); | ||
300 | |||
301 | ret = init_child_sync(&info->child_sync); | ||
302 | if (ret) | ||
303 | return ret; | ||
304 | |||
305 | pid = fork(); | ||
306 | if (pid < 0) { | ||
307 | perror("fork() failed"); | ||
308 | ret = TEST_FAIL; | ||
309 | } else if (pid == 0) | ||
310 | ret = child(info); | ||
311 | else | ||
312 | ret = parent(info, pid); | ||
313 | |||
314 | shmdt(info); | ||
315 | |||
316 | if (pid) { | ||
317 | destroy_child_sync(&info->child_sync); | ||
318 | shmctl(shm_id, IPC_RMID, NULL); | ||
319 | } | ||
320 | |||
321 | return ret; | ||
322 | } | ||
323 | |||
324 | int main(int argc, char *argv[]) | ||
325 | { | ||
326 | return test_harness(ptrace_pkey, "ptrace_pkey"); | ||
327 | } | ||
diff --git a/tools/testing/selftests/powerpc/ptrace/ptrace.h b/tools/testing/selftests/powerpc/ptrace/ptrace.h index 19fb825270a1..34201cfa8335 100644 --- a/tools/testing/selftests/powerpc/ptrace/ptrace.h +++ b/tools/testing/selftests/powerpc/ptrace/ptrace.h | |||
@@ -102,6 +102,44 @@ int cont_trace(pid_t child) | |||
102 | return TEST_PASS; | 102 | return TEST_PASS; |
103 | } | 103 | } |
104 | 104 | ||
105 | int ptrace_read_regs(pid_t child, unsigned long type, unsigned long regs[], | ||
106 | int n) | ||
107 | { | ||
108 | struct iovec iov; | ||
109 | long ret; | ||
110 | |||
111 | FAIL_IF(start_trace(child)); | ||
112 | |||
113 | iov.iov_base = regs; | ||
114 | iov.iov_len = n * sizeof(unsigned long); | ||
115 | |||
116 | ret = ptrace(PTRACE_GETREGSET, child, type, &iov); | ||
117 | if (ret) | ||
118 | return ret; | ||
119 | |||
120 | FAIL_IF(stop_trace(child)); | ||
121 | |||
122 | return TEST_PASS; | ||
123 | } | ||
124 | |||
125 | long ptrace_write_regs(pid_t child, unsigned long type, unsigned long regs[], | ||
126 | int n) | ||
127 | { | ||
128 | struct iovec iov; | ||
129 | long ret; | ||
130 | |||
131 | FAIL_IF(start_trace(child)); | ||
132 | |||
133 | iov.iov_base = regs; | ||
134 | iov.iov_len = n * sizeof(unsigned long); | ||
135 | |||
136 | ret = ptrace(PTRACE_SETREGSET, child, type, &iov); | ||
137 | |||
138 | FAIL_IF(stop_trace(child)); | ||
139 | |||
140 | return ret; | ||
141 | } | ||
142 | |||
105 | /* TAR, PPR, DSCR */ | 143 | /* TAR, PPR, DSCR */ |
106 | int show_tar_registers(pid_t child, unsigned long *out) | 144 | int show_tar_registers(pid_t child, unsigned long *out) |
107 | { | 145 | { |
diff --git a/tools/testing/selftests/powerpc/tm/.gitignore b/tools/testing/selftests/powerpc/tm/.gitignore index bb90d4b79524..c3ee8393dae8 100644 --- a/tools/testing/selftests/powerpc/tm/.gitignore +++ b/tools/testing/selftests/powerpc/tm/.gitignore | |||
@@ -14,3 +14,4 @@ tm-signal-context-chk-vsx | |||
14 | tm-vmx-unavail | 14 | tm-vmx-unavail |
15 | tm-unavailable | 15 | tm-unavailable |
16 | tm-trap | 16 | tm-trap |
17 | tm-sigreturn | ||