diff options
Diffstat (limited to 'arch/powerpc')
281 files changed, 7735 insertions, 4124 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index fcc626cc577b..b44b52c0a8f0 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -98,7 +98,7 @@ config PPC | |||
98 | select VIRT_TO_BUS if !PPC64 | 98 | select VIRT_TO_BUS if !PPC64 |
99 | select HAVE_IDE | 99 | select HAVE_IDE |
100 | select HAVE_IOREMAP_PROT | 100 | select HAVE_IOREMAP_PROT |
101 | select HAVE_EFFICIENT_UNALIGNED_ACCESS | 101 | select HAVE_EFFICIENT_UNALIGNED_ACCESS if !CPU_LITTLE_ENDIAN |
102 | select HAVE_KPROBES | 102 | select HAVE_KPROBES |
103 | select HAVE_ARCH_KGDB | 103 | select HAVE_ARCH_KGDB |
104 | select HAVE_KRETPROBES | 104 | select HAVE_KRETPROBES |
@@ -107,7 +107,6 @@ config PPC | |||
107 | select HAVE_MEMBLOCK_NODE_MAP | 107 | select HAVE_MEMBLOCK_NODE_MAP |
108 | select HAVE_DMA_ATTRS | 108 | select HAVE_DMA_ATTRS |
109 | select HAVE_DMA_API_DEBUG | 109 | select HAVE_DMA_API_DEBUG |
110 | select USE_GENERIC_SMP_HELPERS if SMP | ||
111 | select HAVE_OPROFILE | 110 | select HAVE_OPROFILE |
112 | select HAVE_DEBUG_KMEMLEAK | 111 | select HAVE_DEBUG_KMEMLEAK |
113 | select GENERIC_ATOMIC64 if PPC32 | 112 | select GENERIC_ATOMIC64 if PPC32 |
@@ -139,6 +138,10 @@ config PPC | |||
139 | select OLD_SIGSUSPEND | 138 | select OLD_SIGSUSPEND |
140 | select OLD_SIGACTION if PPC32 | 139 | select OLD_SIGACTION if PPC32 |
141 | select HAVE_DEBUG_STACKOVERFLOW | 140 | select HAVE_DEBUG_STACKOVERFLOW |
141 | select HAVE_IRQ_EXIT_ON_IRQ_STACK | ||
142 | |||
143 | config GENERIC_CSUM | ||
144 | def_bool CPU_LITTLE_ENDIAN | ||
142 | 145 | ||
143 | config EARLY_PRINTK | 146 | config EARLY_PRINTK |
144 | bool | 147 | bool |
@@ -405,7 +408,7 @@ config CRASH_DUMP | |||
405 | 408 | ||
406 | config FA_DUMP | 409 | config FA_DUMP |
407 | bool "Firmware-assisted dump" | 410 | bool "Firmware-assisted dump" |
408 | depends on PPC64 && PPC_RTAS && CRASH_DUMP | 411 | depends on PPC64 && PPC_RTAS && CRASH_DUMP && KEXEC |
409 | help | 412 | help |
410 | A robust mechanism to get reliable kernel crash dump with | 413 | A robust mechanism to get reliable kernel crash dump with |
411 | assistance from firmware. This approach does not use kexec, | 414 | assistance from firmware. This approach does not use kexec, |
@@ -418,7 +421,7 @@ config FA_DUMP | |||
418 | 421 | ||
419 | config IRQ_ALL_CPUS | 422 | config IRQ_ALL_CPUS |
420 | bool "Distribute interrupts on all CPUs by default" | 423 | bool "Distribute interrupts on all CPUs by default" |
421 | depends on SMP && !MV64360 | 424 | depends on SMP |
422 | help | 425 | help |
423 | This option gives the kernel permission to distribute IRQs across | 426 | This option gives the kernel permission to distribute IRQs across |
424 | multiple CPUs. Saying N here will route all IRQs to the first | 427 | multiple CPUs. Saying N here will route all IRQs to the first |
@@ -1010,6 +1013,9 @@ config PHYSICAL_START | |||
1010 | default "0x00000000" | 1013 | default "0x00000000" |
1011 | endif | 1014 | endif |
1012 | 1015 | ||
1016 | config ARCH_RANDOM | ||
1017 | def_bool n | ||
1018 | |||
1013 | source "net/Kconfig" | 1019 | source "net/Kconfig" |
1014 | 1020 | ||
1015 | source "drivers/Kconfig" | 1021 | source "drivers/Kconfig" |
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index 51cfb78d4061..607acf54a425 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile | |||
@@ -36,17 +36,26 @@ KBUILD_DEFCONFIG := ppc64_defconfig | |||
36 | endif | 36 | endif |
37 | 37 | ||
38 | ifeq ($(CONFIG_PPC64),y) | 38 | ifeq ($(CONFIG_PPC64),y) |
39 | OLDARCH := ppc64 | ||
40 | |||
41 | new_nm := $(shell if $(NM) --help 2>&1 | grep -- '--synthetic' > /dev/null; then echo y; else echo n; fi) | 39 | new_nm := $(shell if $(NM) --help 2>&1 | grep -- '--synthetic' > /dev/null; then echo y; else echo n; fi) |
42 | 40 | ||
43 | ifeq ($(new_nm),y) | 41 | ifeq ($(new_nm),y) |
44 | NM := $(NM) --synthetic | 42 | NM := $(NM) --synthetic |
45 | endif | 43 | endif |
44 | endif | ||
46 | 45 | ||
46 | ifeq ($(CONFIG_PPC64),y) | ||
47 | ifeq ($(CONFIG_CPU_LITTLE_ENDIAN),y) | ||
48 | OLDARCH := ppc64le | ||
49 | else | ||
50 | OLDARCH := ppc64 | ||
51 | endif | ||
52 | else | ||
53 | ifeq ($(CONFIG_CPU_LITTLE_ENDIAN),y) | ||
54 | OLDARCH := ppcle | ||
47 | else | 55 | else |
48 | OLDARCH := ppc | 56 | OLDARCH := ppc |
49 | endif | 57 | endif |
58 | endif | ||
50 | 59 | ||
51 | # It seems there are times we use this Makefile without | 60 | # It seems there are times we use this Makefile without |
52 | # including the config file, but this replicates the old behaviour | 61 | # including the config file, but this replicates the old behaviour |
@@ -56,11 +65,29 @@ endif | |||
56 | 65 | ||
57 | UTS_MACHINE := $(OLDARCH) | 66 | UTS_MACHINE := $(OLDARCH) |
58 | 67 | ||
68 | ifeq ($(CONFIG_CPU_LITTLE_ENDIAN),y) | ||
69 | override CC += -mlittle-endian -mno-strict-align | ||
70 | override AS += -mlittle-endian | ||
71 | override LD += -EL | ||
72 | override CROSS32CC += -mlittle-endian | ||
73 | override CROSS32AS += -mlittle-endian | ||
74 | LDEMULATION := lppc | ||
75 | GNUTARGET := powerpcle | ||
76 | MULTIPLEWORD := -mno-multiple | ||
77 | else | ||
78 | override CC += -mbig-endian | ||
79 | override AS += -mbig-endian | ||
80 | override LD += -EB | ||
81 | LDEMULATION := ppc | ||
82 | GNUTARGET := powerpc | ||
83 | MULTIPLEWORD := -mmultiple | ||
84 | endif | ||
85 | |||
59 | ifeq ($(HAS_BIARCH),y) | 86 | ifeq ($(HAS_BIARCH),y) |
60 | override AS += -a$(CONFIG_WORD_SIZE) | 87 | override AS += -a$(CONFIG_WORD_SIZE) |
61 | override LD += -m elf$(CONFIG_WORD_SIZE)ppc | 88 | override LD += -m elf$(CONFIG_WORD_SIZE)$(LDEMULATION) |
62 | override CC += -m$(CONFIG_WORD_SIZE) | 89 | override CC += -m$(CONFIG_WORD_SIZE) |
63 | override AR := GNUTARGET=elf$(CONFIG_WORD_SIZE)-powerpc $(AR) | 90 | override AR := GNUTARGET=elf$(CONFIG_WORD_SIZE)-$(GNUTARGET) $(AR) |
64 | endif | 91 | endif |
65 | 92 | ||
66 | LDFLAGS_vmlinux-y := -Bstatic | 93 | LDFLAGS_vmlinux-y := -Bstatic |
@@ -86,7 +113,7 @@ endif | |||
86 | CFLAGS-$(CONFIG_PPC64) := -mtraceback=no -mcall-aixdesc | 113 | CFLAGS-$(CONFIG_PPC64) := -mtraceback=no -mcall-aixdesc |
87 | CFLAGS-$(CONFIG_PPC64) += $(call cc-option,-mcmodel=medium,-mminimal-toc) | 114 | CFLAGS-$(CONFIG_PPC64) += $(call cc-option,-mcmodel=medium,-mminimal-toc) |
88 | CFLAGS-$(CONFIG_PPC64) += $(call cc-option,-mno-pointers-to-nested-functions) | 115 | CFLAGS-$(CONFIG_PPC64) += $(call cc-option,-mno-pointers-to-nested-functions) |
89 | CFLAGS-$(CONFIG_PPC32) := -ffixed-r2 -mmultiple | 116 | CFLAGS-$(CONFIG_PPC32) := -ffixed-r2 $(MULTIPLEWORD) |
90 | 117 | ||
91 | ifeq ($(CONFIG_PPC_BOOK3S_64),y) | 118 | ifeq ($(CONFIG_PPC_BOOK3S_64),y) |
92 | CFLAGS-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=power7,-mtune=power4) | 119 | CFLAGS-$(CONFIG_GENERIC_CPU) += $(call cc-option,-mtune=power7,-mtune=power4) |
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile index 6a15c968d214..ca7f08cc4afd 100644 --- a/arch/powerpc/boot/Makefile +++ b/arch/powerpc/boot/Makefile | |||
@@ -22,7 +22,8 @@ all: $(obj)/zImage | |||
22 | BOOTCFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ | 22 | BOOTCFLAGS := -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs \ |
23 | -fno-strict-aliasing -Os -msoft-float -pipe \ | 23 | -fno-strict-aliasing -Os -msoft-float -pipe \ |
24 | -fomit-frame-pointer -fno-builtin -fPIC -nostdinc \ | 24 | -fomit-frame-pointer -fno-builtin -fPIC -nostdinc \ |
25 | -isystem $(shell $(CROSS32CC) -print-file-name=include) | 25 | -isystem $(shell $(CROSS32CC) -print-file-name=include) \ |
26 | -mbig-endian | ||
26 | BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc | 27 | BOOTAFLAGS := -D__ASSEMBLY__ $(BOOTCFLAGS) -traditional -nostdinc |
27 | 28 | ||
28 | ifdef CONFIG_DEBUG_INFO | 29 | ifdef CONFIG_DEBUG_INFO |
@@ -74,7 +75,7 @@ src-wlib-$(CONFIG_8xx) += mpc8xx.c planetcore.c | |||
74 | src-wlib-$(CONFIG_PPC_82xx) += pq2.c fsl-soc.c planetcore.c | 75 | src-wlib-$(CONFIG_PPC_82xx) += pq2.c fsl-soc.c planetcore.c |
75 | src-wlib-$(CONFIG_EMBEDDED6xx) += mv64x60.c mv64x60_i2c.c ugecon.c | 76 | src-wlib-$(CONFIG_EMBEDDED6xx) += mv64x60.c mv64x60_i2c.c ugecon.c |
76 | 77 | ||
77 | src-plat-y := of.c | 78 | src-plat-y := of.c epapr.c |
78 | src-plat-$(CONFIG_40x) += fixed-head.S ep405.c cuboot-hotfoot.c \ | 79 | src-plat-$(CONFIG_40x) += fixed-head.S ep405.c cuboot-hotfoot.c \ |
79 | treeboot-walnut.c cuboot-acadia.c \ | 80 | treeboot-walnut.c cuboot-acadia.c \ |
80 | cuboot-kilauea.c simpleboot.c \ | 81 | cuboot-kilauea.c simpleboot.c \ |
@@ -97,7 +98,7 @@ src-plat-$(CONFIG_EMBEDDED6xx) += cuboot-pq2.c cuboot-mpc7448hpc2.c \ | |||
97 | prpmc2800.c | 98 | prpmc2800.c |
98 | src-plat-$(CONFIG_AMIGAONE) += cuboot-amigaone.c | 99 | src-plat-$(CONFIG_AMIGAONE) += cuboot-amigaone.c |
99 | src-plat-$(CONFIG_PPC_PS3) += ps3-head.S ps3-hvcall.S ps3.c | 100 | src-plat-$(CONFIG_PPC_PS3) += ps3-head.S ps3-hvcall.S ps3.c |
100 | src-plat-$(CONFIG_EPAPR_BOOT) += epapr.c | 101 | src-plat-$(CONFIG_EPAPR_BOOT) += epapr.c epapr-wrapper.c |
101 | 102 | ||
102 | src-wlib := $(sort $(src-wlib-y)) | 103 | src-wlib := $(sort $(src-wlib-y)) |
103 | src-plat := $(sort $(src-plat-y)) | 104 | src-plat := $(sort $(src-plat-y)) |
diff --git a/arch/powerpc/boot/dts/b4860emu.dts b/arch/powerpc/boot/dts/b4860emu.dts new file mode 100644 index 000000000000..7290021f2dfc --- /dev/null +++ b/arch/powerpc/boot/dts/b4860emu.dts | |||
@@ -0,0 +1,218 @@ | |||
1 | /* | ||
2 | * B4860 emulator Device Tree Source | ||
3 | * | ||
4 | * Copyright 2013 Freescale Semiconductor Inc. | ||
5 | * | ||
6 | * Redistribution and use in source and binary forms, with or without | ||
7 | * modification, are permitted provided that the following conditions are met: | ||
8 | * * Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions and the following disclaimer. | ||
10 | * * Redistributions in binary form must reproduce the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer in the | ||
12 | * documentation and/or other materials provided with the distribution. | ||
13 | * * Neither the name of Freescale Semiconductor nor the | ||
14 | * names of its contributors may be used to endorse or promote products | ||
15 | * derived from this software without specific prior written permission. | ||
16 | * | ||
17 | * | ||
18 | * ALTERNATIVELY, this software may be distributed under the terms of the | ||
19 | * GNU General Public License ("GPL") as published by the Free Software | ||
20 | * Foundation, either version 2 of that License or (at your option) any | ||
21 | * later version. | ||
22 | * | ||
23 | * This software is provided by Freescale Semiconductor "as is" and any | ||
24 | * express or implied warranties, including, but not limited to, the implied | ||
25 | * warranties of merchantability and fitness for a particular purpose are | ||
26 | * disclaimed. In no event shall Freescale Semiconductor be liable for any | ||
27 | * direct, indirect, incidental, special, exemplary, or consequential damages | ||
28 | * (including, but not limited to, procurement of substitute goods or services; | ||
29 | * loss of use, data, or profits; or business interruption) however caused and | ||
30 | * on any theory of liability, whether in contract, strict liability, or tort | ||
31 | * (including negligence or otherwise) arising in any way out of the use of | ||
32 | * this software, even if advised of the possibility of such damage. | ||
33 | */ | ||
34 | |||
35 | /dts-v1/; | ||
36 | |||
37 | /include/ "fsl/e6500_power_isa.dtsi" | ||
38 | |||
39 | / { | ||
40 | compatible = "fsl,B4860"; | ||
41 | #address-cells = <2>; | ||
42 | #size-cells = <2>; | ||
43 | interrupt-parent = <&mpic>; | ||
44 | |||
45 | aliases { | ||
46 | ccsr = &soc; | ||
47 | |||
48 | serial0 = &serial0; | ||
49 | serial1 = &serial1; | ||
50 | serial2 = &serial2; | ||
51 | serial3 = &serial3; | ||
52 | dma0 = &dma0; | ||
53 | dma1 = &dma1; | ||
54 | }; | ||
55 | |||
56 | cpus { | ||
57 | #address-cells = <1>; | ||
58 | #size-cells = <0>; | ||
59 | |||
60 | cpu0: PowerPC,e6500@0 { | ||
61 | device_type = "cpu"; | ||
62 | reg = <0 1>; | ||
63 | next-level-cache = <&L2>; | ||
64 | }; | ||
65 | cpu1: PowerPC,e6500@2 { | ||
66 | device_type = "cpu"; | ||
67 | reg = <2 3>; | ||
68 | next-level-cache = <&L2>; | ||
69 | }; | ||
70 | cpu2: PowerPC,e6500@4 { | ||
71 | device_type = "cpu"; | ||
72 | reg = <4 5>; | ||
73 | next-level-cache = <&L2>; | ||
74 | }; | ||
75 | cpu3: PowerPC,e6500@6 { | ||
76 | device_type = "cpu"; | ||
77 | reg = <6 7>; | ||
78 | next-level-cache = <&L2>; | ||
79 | }; | ||
80 | }; | ||
81 | }; | ||
82 | |||
83 | / { | ||
84 | model = "fsl,B4860QDS"; | ||
85 | compatible = "fsl,B4860EMU", "fsl,B4860QDS"; | ||
86 | #address-cells = <2>; | ||
87 | #size-cells = <2>; | ||
88 | interrupt-parent = <&mpic>; | ||
89 | |||
90 | ifc: localbus@ffe124000 { | ||
91 | reg = <0xf 0xfe124000 0 0x2000>; | ||
92 | ranges = <0 0 0xf 0xe8000000 0x08000000 | ||
93 | 2 0 0xf 0xff800000 0x00010000 | ||
94 | 3 0 0xf 0xffdf0000 0x00008000>; | ||
95 | |||
96 | nor@0,0 { | ||
97 | #address-cells = <1>; | ||
98 | #size-cells = <1>; | ||
99 | compatible = "cfi-flash"; | ||
100 | reg = <0x0 0x0 0x8000000>; | ||
101 | bank-width = <2>; | ||
102 | device-width = <1>; | ||
103 | }; | ||
104 | }; | ||
105 | |||
106 | memory { | ||
107 | device_type = "memory"; | ||
108 | }; | ||
109 | |||
110 | soc: soc@ffe000000 { | ||
111 | ranges = <0x00000000 0xf 0xfe000000 0x1000000>; | ||
112 | reg = <0xf 0xfe000000 0 0x00001000>; | ||
113 | }; | ||
114 | }; | ||
115 | |||
116 | &ifc { | ||
117 | #address-cells = <2>; | ||
118 | #size-cells = <1>; | ||
119 | compatible = "fsl,ifc", "simple-bus"; | ||
120 | interrupts = <25 2 0 0>; | ||
121 | }; | ||
122 | |||
123 | &soc { | ||
124 | #address-cells = <1>; | ||
125 | #size-cells = <1>; | ||
126 | device_type = "soc"; | ||
127 | compatible = "simple-bus"; | ||
128 | |||
129 | soc-sram-error { | ||
130 | compatible = "fsl,soc-sram-error"; | ||
131 | interrupts = <16 2 1 2>; | ||
132 | }; | ||
133 | |||
134 | corenet-law@0 { | ||
135 | compatible = "fsl,corenet-law"; | ||
136 | reg = <0x0 0x1000>; | ||
137 | fsl,num-laws = <32>; | ||
138 | }; | ||
139 | |||
140 | ddr1: memory-controller@8000 { | ||
141 | compatible = "fsl,qoriq-memory-controller-v4.5", "fsl,qoriq-memory-controller"; | ||
142 | reg = <0x8000 0x1000>; | ||
143 | interrupts = <16 2 1 8>; | ||
144 | }; | ||
145 | |||
146 | ddr2: memory-controller@9000 { | ||
147 | compatible = "fsl,qoriq-memory-controller-v4.5","fsl,qoriq-memory-controller"; | ||
148 | reg = <0x9000 0x1000>; | ||
149 | interrupts = <16 2 1 9>; | ||
150 | }; | ||
151 | |||
152 | cpc: l3-cache-controller@10000 { | ||
153 | compatible = "fsl,b4-l3-cache-controller", "cache"; | ||
154 | reg = <0x10000 0x1000 | ||
155 | 0x11000 0x1000>; | ||
156 | interrupts = <16 2 1 4>; | ||
157 | }; | ||
158 | |||
159 | corenet-cf@18000 { | ||
160 | compatible = "fsl,b4-corenet-cf"; | ||
161 | reg = <0x18000 0x1000>; | ||
162 | interrupts = <16 2 1 0>; | ||
163 | fsl,ccf-num-csdids = <32>; | ||
164 | fsl,ccf-num-snoopids = <32>; | ||
165 | }; | ||
166 | |||
167 | iommu@20000 { | ||
168 | compatible = "fsl,pamu-v1.0", "fsl,pamu"; | ||
169 | reg = <0x20000 0x4000>; | ||
170 | #address-cells = <1>; | ||
171 | #size-cells = <1>; | ||
172 | interrupts = < | ||
173 | 24 2 0 0 | ||
174 | 16 2 1 1>; | ||
175 | pamu0: pamu@0 { | ||
176 | reg = <0 0x1000>; | ||
177 | fsl,primary-cache-geometry = <8 1>; | ||
178 | fsl,secondary-cache-geometry = <32 2>; | ||
179 | }; | ||
180 | }; | ||
181 | |||
182 | /include/ "fsl/qoriq-mpic.dtsi" | ||
183 | |||
184 | guts: global-utilities@e0000 { | ||
185 | compatible = "fsl,b4-device-config"; | ||
186 | reg = <0xe0000 0xe00>; | ||
187 | fsl,has-rstcr; | ||
188 | fsl,liodn-bits = <12>; | ||
189 | }; | ||
190 | |||
191 | clockgen: global-utilities@e1000 { | ||
192 | compatible = "fsl,b4-clockgen", "fsl,qoriq-clockgen-2.0"; | ||
193 | reg = <0xe1000 0x1000>; | ||
194 | }; | ||
195 | |||
196 | /include/ "fsl/qoriq-dma-0.dtsi" | ||
197 | dma@100300 { | ||
198 | fsl,iommu-parent = <&pamu0>; | ||
199 | fsl,liodn-reg = <&guts 0x580>; /* DMA1LIODNR */ | ||
200 | }; | ||
201 | |||
202 | /include/ "fsl/qoriq-dma-1.dtsi" | ||
203 | dma@101300 { | ||
204 | fsl,iommu-parent = <&pamu0>; | ||
205 | fsl,liodn-reg = <&guts 0x584>; /* DMA2LIODNR */ | ||
206 | }; | ||
207 | |||
208 | /include/ "fsl/qoriq-i2c-0.dtsi" | ||
209 | /include/ "fsl/qoriq-i2c-1.dtsi" | ||
210 | /include/ "fsl/qoriq-duart-0.dtsi" | ||
211 | /include/ "fsl/qoriq-duart-1.dtsi" | ||
212 | |||
213 | L2: l2-cache-controller@c20000 { | ||
214 | compatible = "fsl,b4-l2-cache-controller"; | ||
215 | reg = <0xc20000 0x1000>; | ||
216 | next-level-cache = <&cpc>; | ||
217 | }; | ||
218 | }; | ||
diff --git a/arch/powerpc/boot/dts/b4qds.dtsi b/arch/powerpc/boot/dts/b4qds.dtsi index e6d2f8f90544..8b47edcfabf0 100644 --- a/arch/powerpc/boot/dts/b4qds.dtsi +++ b/arch/powerpc/boot/dts/b4qds.dtsi | |||
@@ -120,25 +120,38 @@ | |||
120 | }; | 120 | }; |
121 | 121 | ||
122 | i2c@118000 { | 122 | i2c@118000 { |
123 | eeprom@50 { | 123 | mux@77 { |
124 | compatible = "at24,24c64"; | 124 | compatible = "nxp,pca9547"; |
125 | reg = <0x50>; | 125 | reg = <0x77>; |
126 | }; | 126 | #address-cells = <1>; |
127 | eeprom@51 { | 127 | #size-cells = <0>; |
128 | compatible = "at24,24c256"; | 128 | |
129 | reg = <0x51>; | 129 | i2c@0 { |
130 | }; | 130 | #address-cells = <1>; |
131 | eeprom@53 { | 131 | #size-cells = <0>; |
132 | compatible = "at24,24c256"; | 132 | reg = <0>; |
133 | reg = <0x53>; | 133 | |
134 | }; | 134 | eeprom@50 { |
135 | eeprom@57 { | 135 | compatible = "at24,24c64"; |
136 | compatible = "at24,24c256"; | 136 | reg = <0x50>; |
137 | reg = <0x57>; | 137 | }; |
138 | }; | 138 | eeprom@51 { |
139 | rtc@68 { | 139 | compatible = "at24,24c256"; |
140 | compatible = "dallas,ds3232"; | 140 | reg = <0x51>; |
141 | reg = <0x68>; | 141 | }; |
142 | eeprom@53 { | ||
143 | compatible = "at24,24c256"; | ||
144 | reg = <0x53>; | ||
145 | }; | ||
146 | eeprom@57 { | ||
147 | compatible = "at24,24c256"; | ||
148 | reg = <0x57>; | ||
149 | }; | ||
150 | rtc@68 { | ||
151 | compatible = "dallas,ds3232"; | ||
152 | reg = <0x68>; | ||
153 | }; | ||
154 | }; | ||
142 | }; | 155 | }; |
143 | }; | 156 | }; |
144 | 157 | ||
diff --git a/arch/powerpc/boot/dts/c293pcie.dts b/arch/powerpc/boot/dts/c293pcie.dts index 1238bda8901f..6681cc21030b 100644 --- a/arch/powerpc/boot/dts/c293pcie.dts +++ b/arch/powerpc/boot/dts/c293pcie.dts | |||
@@ -45,6 +45,7 @@ | |||
45 | ifc: ifc@fffe1e000 { | 45 | ifc: ifc@fffe1e000 { |
46 | reg = <0xf 0xffe1e000 0 0x2000>; | 46 | reg = <0xf 0xffe1e000 0 0x2000>; |
47 | ranges = <0x0 0x0 0xf 0xec000000 0x04000000 | 47 | ranges = <0x0 0x0 0xf 0xec000000 0x04000000 |
48 | 0x1 0x0 0xf 0xff800000 0x00010000 | ||
48 | 0x2 0x0 0xf 0xffdf0000 0x00010000>; | 49 | 0x2 0x0 0xf 0xffdf0000 0x00010000>; |
49 | 50 | ||
50 | }; | 51 | }; |
diff --git a/arch/powerpc/boot/dts/fsl/b4420si-pre.dtsi b/arch/powerpc/boot/dts/fsl/b4420si-pre.dtsi index 7b4426e0a5a5..c6e451affb05 100644 --- a/arch/powerpc/boot/dts/fsl/b4420si-pre.dtsi +++ b/arch/powerpc/boot/dts/fsl/b4420si-pre.dtsi | |||
@@ -34,6 +34,8 @@ | |||
34 | 34 | ||
35 | /dts-v1/; | 35 | /dts-v1/; |
36 | 36 | ||
37 | /include/ "e6500_power_isa.dtsi" | ||
38 | |||
37 | / { | 39 | / { |
38 | compatible = "fsl,B4420"; | 40 | compatible = "fsl,B4420"; |
39 | #address-cells = <2>; | 41 | #address-cells = <2>; |
diff --git a/arch/powerpc/boot/dts/fsl/b4860si-post.dtsi b/arch/powerpc/boot/dts/fsl/b4860si-post.dtsi index e5cf6c81dd66..981397518fc6 100644 --- a/arch/powerpc/boot/dts/fsl/b4860si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/b4860si-post.dtsi | |||
@@ -41,7 +41,7 @@ | |||
41 | 41 | ||
42 | &rio { | 42 | &rio { |
43 | compatible = "fsl,srio"; | 43 | compatible = "fsl,srio"; |
44 | interrupts = <16 2 1 11>; | 44 | interrupts = <16 2 1 20>; |
45 | #address-cells = <2>; | 45 | #address-cells = <2>; |
46 | #size-cells = <2>; | 46 | #size-cells = <2>; |
47 | fsl,iommu-parent = <&pamu0>; | 47 | fsl,iommu-parent = <&pamu0>; |
diff --git a/arch/powerpc/boot/dts/fsl/b4860si-pre.dtsi b/arch/powerpc/boot/dts/fsl/b4860si-pre.dtsi index 5263fa46a3fb..9bc26b147900 100644 --- a/arch/powerpc/boot/dts/fsl/b4860si-pre.dtsi +++ b/arch/powerpc/boot/dts/fsl/b4860si-pre.dtsi | |||
@@ -34,6 +34,8 @@ | |||
34 | 34 | ||
35 | /dts-v1/; | 35 | /dts-v1/; |
36 | 36 | ||
37 | /include/ "e6500_power_isa.dtsi" | ||
38 | |||
37 | / { | 39 | / { |
38 | compatible = "fsl,B4860"; | 40 | compatible = "fsl,B4860"; |
39 | #address-cells = <2>; | 41 | #address-cells = <2>; |
diff --git a/arch/powerpc/boot/dts/fsl/bsc9131si-post.dtsi b/arch/powerpc/boot/dts/fsl/bsc9131si-post.dtsi index 5180d9d37989..0c0efa94cfb4 100644 --- a/arch/powerpc/boot/dts/fsl/bsc9131si-post.dtsi +++ b/arch/powerpc/boot/dts/fsl/bsc9131si-post.dtsi | |||
@@ -130,7 +130,7 @@ usb@22000 { | |||
130 | 130 | ||
131 | /include/ "pq3-esdhc-0.dtsi" | 131 | /include/ "pq3-esdhc-0.dtsi" |
132 | sdhc@2e000 { | 132 | sdhc@2e000 { |
133 | fsl,sdhci-auto-cmd12; | 133 | sdhci,auto-cmd12; |
134 | interrupts = <41 0x2 0 0>; | 134 | interrupts = <41 0x2 0 0>; |
135 | }; | 135 | }; |
136 | 136 | ||
diff --git a/arch/powerpc/boot/dts/fsl/bsc9131si-pre.dtsi b/arch/powerpc/boot/dts/fsl/bsc9131si-pre.dtsi index 743e4aeda349..f6ec4a67560c 100644 --- a/arch/powerpc/boot/dts/fsl/bsc9131si-pre.dtsi +++ b/arch/powerpc/boot/dts/fsl/bsc9131si-pre.dtsi | |||
@@ -33,6 +33,9 @@ | |||
33 | */ | 33 | */ |
34 | 34 | ||
35 | /dts-v1/; | 35 | /dts-v1/; |
36 | |||
37 | /include/ "e500v2_power_isa.dtsi" | ||
38 | |||
36 | / { | 39 | / { |
37 | compatible = "fsl,BSC9131"; | 40 | compatible = "fsl,BSC9131"; |
38 | #address-cells = <2>; | 41 | #address-cells = <2>; |
diff --git a/arch/powerpc/boot/dts/t4240emu.dts b/arch/powerpc/boot/dts/t4240emu.dts new file mode 100644 index 000000000000..ee24ab335598 --- /dev/null +++ b/arch/powerpc/boot/dts/t4240emu.dts | |||
@@ -0,0 +1,268 @@ | |||
1 | /* | ||
2 | * T4240 emulator Device Tree Source | ||
3 | * | ||
4 | * Copyright 2013 Freescale Semiconductor Inc. | ||
5 | * | ||
6 | * Redistribution and use in source and binary forms, with or without | ||
7 | * modification, are permitted provided that the following conditions are met: | ||
8 | * * Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions and the following disclaimer. | ||
10 | * * Redistributions in binary form must reproduce the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer in the | ||
12 | * documentation and/or other materials provided with the distribution. | ||
13 | * * Neither the name of Freescale Semiconductor nor the | ||
14 | * names of its contributors may be used to endorse or promote products | ||
15 | * derived from this software without specific prior written permission. | ||
16 | * | ||
17 | * | ||
18 | * ALTERNATIVELY, this software may be distributed under the terms of the | ||
19 | * GNU General Public License ("GPL") as published by the Free Software | ||
20 | * Foundation, either version 2 of that License or (at your option) any | ||
21 | * later version. | ||
22 | * | ||
23 | * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY | ||
24 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
25 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
26 | * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY | ||
27 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
28 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
29 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
30 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
32 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
33 | */ | ||
34 | |||
35 | /dts-v1/; | ||
36 | |||
37 | /include/ "fsl/e6500_power_isa.dtsi" | ||
38 | / { | ||
39 | compatible = "fsl,T4240"; | ||
40 | #address-cells = <2>; | ||
41 | #size-cells = <2>; | ||
42 | interrupt-parent = <&mpic>; | ||
43 | |||
44 | aliases { | ||
45 | ccsr = &soc; | ||
46 | |||
47 | serial0 = &serial0; | ||
48 | serial1 = &serial1; | ||
49 | serial2 = &serial2; | ||
50 | serial3 = &serial3; | ||
51 | dma0 = &dma0; | ||
52 | dma1 = &dma1; | ||
53 | }; | ||
54 | |||
55 | cpus { | ||
56 | #address-cells = <1>; | ||
57 | #size-cells = <0>; | ||
58 | |||
59 | cpu0: PowerPC,e6500@0 { | ||
60 | device_type = "cpu"; | ||
61 | reg = <0 1>; | ||
62 | next-level-cache = <&L2_1>; | ||
63 | }; | ||
64 | cpu1: PowerPC,e6500@2 { | ||
65 | device_type = "cpu"; | ||
66 | reg = <2 3>; | ||
67 | next-level-cache = <&L2_1>; | ||
68 | }; | ||
69 | cpu2: PowerPC,e6500@4 { | ||
70 | device_type = "cpu"; | ||
71 | reg = <4 5>; | ||
72 | next-level-cache = <&L2_1>; | ||
73 | }; | ||
74 | cpu3: PowerPC,e6500@6 { | ||
75 | device_type = "cpu"; | ||
76 | reg = <6 7>; | ||
77 | next-level-cache = <&L2_1>; | ||
78 | }; | ||
79 | |||
80 | cpu4: PowerPC,e6500@8 { | ||
81 | device_type = "cpu"; | ||
82 | reg = <8 9>; | ||
83 | next-level-cache = <&L2_2>; | ||
84 | }; | ||
85 | cpu5: PowerPC,e6500@10 { | ||
86 | device_type = "cpu"; | ||
87 | reg = <10 11>; | ||
88 | next-level-cache = <&L2_2>; | ||
89 | }; | ||
90 | cpu6: PowerPC,e6500@12 { | ||
91 | device_type = "cpu"; | ||
92 | reg = <12 13>; | ||
93 | next-level-cache = <&L2_2>; | ||
94 | }; | ||
95 | cpu7: PowerPC,e6500@14 { | ||
96 | device_type = "cpu"; | ||
97 | reg = <14 15>; | ||
98 | next-level-cache = <&L2_2>; | ||
99 | }; | ||
100 | |||
101 | cpu8: PowerPC,e6500@16 { | ||
102 | device_type = "cpu"; | ||
103 | reg = <16 17>; | ||
104 | next-level-cache = <&L2_3>; | ||
105 | }; | ||
106 | cpu9: PowerPC,e6500@18 { | ||
107 | device_type = "cpu"; | ||
108 | reg = <18 19>; | ||
109 | next-level-cache = <&L2_3>; | ||
110 | }; | ||
111 | cpu10: PowerPC,e6500@20 { | ||
112 | device_type = "cpu"; | ||
113 | reg = <20 21>; | ||
114 | next-level-cache = <&L2_3>; | ||
115 | }; | ||
116 | cpu11: PowerPC,e6500@22 { | ||
117 | device_type = "cpu"; | ||
118 | reg = <22 23>; | ||
119 | next-level-cache = <&L2_3>; | ||
120 | }; | ||
121 | }; | ||
122 | }; | ||
123 | |||
124 | / { | ||
125 | model = "fsl,T4240QDS"; | ||
126 | compatible = "fsl,T4240EMU", "fsl,T4240QDS"; | ||
127 | #address-cells = <2>; | ||
128 | #size-cells = <2>; | ||
129 | interrupt-parent = <&mpic>; | ||
130 | |||
131 | ifc: localbus@ffe124000 { | ||
132 | reg = <0xf 0xfe124000 0 0x2000>; | ||
133 | ranges = <0 0 0xf 0xe8000000 0x08000000 | ||
134 | 2 0 0xf 0xff800000 0x00010000 | ||
135 | 3 0 0xf 0xffdf0000 0x00008000>; | ||
136 | |||
137 | nor@0,0 { | ||
138 | #address-cells = <1>; | ||
139 | #size-cells = <1>; | ||
140 | compatible = "cfi-flash"; | ||
141 | reg = <0x0 0x0 0x8000000>; | ||
142 | |||
143 | bank-width = <2>; | ||
144 | device-width = <1>; | ||
145 | }; | ||
146 | |||
147 | }; | ||
148 | |||
149 | memory { | ||
150 | device_type = "memory"; | ||
151 | }; | ||
152 | |||
153 | soc: soc@ffe000000 { | ||
154 | ranges = <0x00000000 0xf 0xfe000000 0x1000000>; | ||
155 | reg = <0xf 0xfe000000 0 0x00001000>; | ||
156 | |||
157 | }; | ||
158 | }; | ||
159 | |||
160 | &ifc { | ||
161 | #address-cells = <2>; | ||
162 | #size-cells = <1>; | ||
163 | compatible = "fsl,ifc", "simple-bus"; | ||
164 | interrupts = <25 2 0 0>; | ||
165 | }; | ||
166 | |||
167 | &soc { | ||
168 | #address-cells = <1>; | ||
169 | #size-cells = <1>; | ||
170 | device_type = "soc"; | ||
171 | compatible = "simple-bus"; | ||
172 | |||
173 | soc-sram-error { | ||
174 | compatible = "fsl,soc-sram-error"; | ||
175 | interrupts = <16 2 1 29>; | ||
176 | }; | ||
177 | |||
178 | corenet-law@0 { | ||
179 | compatible = "fsl,corenet-law"; | ||
180 | reg = <0x0 0x1000>; | ||
181 | fsl,num-laws = <32>; | ||
182 | }; | ||
183 | |||
184 | ddr1: memory-controller@8000 { | ||
185 | compatible = "fsl,qoriq-memory-controller-v4.7", | ||
186 | "fsl,qoriq-memory-controller"; | ||
187 | reg = <0x8000 0x1000>; | ||
188 | interrupts = <16 2 1 23>; | ||
189 | }; | ||
190 | |||
191 | ddr2: memory-controller@9000 { | ||
192 | compatible = "fsl,qoriq-memory-controller-v4.7", | ||
193 | "fsl,qoriq-memory-controller"; | ||
194 | reg = <0x9000 0x1000>; | ||
195 | interrupts = <16 2 1 22>; | ||
196 | }; | ||
197 | |||
198 | ddr3: memory-controller@a000 { | ||
199 | compatible = "fsl,qoriq-memory-controller-v4.7", | ||
200 | "fsl,qoriq-memory-controller"; | ||
201 | reg = <0xa000 0x1000>; | ||
202 | interrupts = <16 2 1 21>; | ||
203 | }; | ||
204 | |||
205 | cpc: l3-cache-controller@10000 { | ||
206 | compatible = "fsl,t4240-l3-cache-controller", "cache"; | ||
207 | reg = <0x10000 0x1000 | ||
208 | 0x11000 0x1000 | ||
209 | 0x12000 0x1000>; | ||
210 | interrupts = <16 2 1 27 | ||
211 | 16 2 1 26 | ||
212 | 16 2 1 25>; | ||
213 | }; | ||
214 | |||
215 | corenet-cf@18000 { | ||
216 | compatible = "fsl,corenet-cf"; | ||
217 | reg = <0x18000 0x1000>; | ||
218 | interrupts = <16 2 1 31>; | ||
219 | fsl,ccf-num-csdids = <32>; | ||
220 | fsl,ccf-num-snoopids = <32>; | ||
221 | }; | ||
222 | |||
223 | iommu@20000 { | ||
224 | compatible = "fsl,pamu-v1.0", "fsl,pamu"; | ||
225 | reg = <0x20000 0x6000>; | ||
226 | interrupts = < | ||
227 | 24 2 0 0 | ||
228 | 16 2 1 30>; | ||
229 | }; | ||
230 | |||
231 | /include/ "fsl/qoriq-mpic.dtsi" | ||
232 | |||
233 | guts: global-utilities@e0000 { | ||
234 | compatible = "fsl,t4240-device-config", "fsl,qoriq-device-config-2.0"; | ||
235 | reg = <0xe0000 0xe00>; | ||
236 | fsl,has-rstcr; | ||
237 | fsl,liodn-bits = <12>; | ||
238 | }; | ||
239 | |||
240 | clockgen: global-utilities@e1000 { | ||
241 | compatible = "fsl,t4240-clockgen", "fsl,qoriq-clockgen-2.0"; | ||
242 | reg = <0xe1000 0x1000>; | ||
243 | }; | ||
244 | |||
245 | /include/ "fsl/qoriq-dma-0.dtsi" | ||
246 | /include/ "fsl/qoriq-dma-1.dtsi" | ||
247 | |||
248 | /include/ "fsl/qoriq-i2c-0.dtsi" | ||
249 | /include/ "fsl/qoriq-i2c-1.dtsi" | ||
250 | /include/ "fsl/qoriq-duart-0.dtsi" | ||
251 | /include/ "fsl/qoriq-duart-1.dtsi" | ||
252 | |||
253 | L2_1: l2-cache-controller@c20000 { | ||
254 | compatible = "fsl,t4240-l2-cache-controller"; | ||
255 | reg = <0xc20000 0x40000>; | ||
256 | next-level-cache = <&cpc>; | ||
257 | }; | ||
258 | L2_2: l2-cache-controller@c60000 { | ||
259 | compatible = "fsl,t4240-l2-cache-controller"; | ||
260 | reg = <0xc60000 0x40000>; | ||
261 | next-level-cache = <&cpc>; | ||
262 | }; | ||
263 | L2_3: l2-cache-controller@ca0000 { | ||
264 | compatible = "fsl,t4240-l2-cache-controller"; | ||
265 | reg = <0xca0000 0x40000>; | ||
266 | next-level-cache = <&cpc>; | ||
267 | }; | ||
268 | }; | ||
diff --git a/arch/powerpc/boot/dts/t4240qds.dts b/arch/powerpc/boot/dts/t4240qds.dts index 0555976dd0f3..63e81b010804 100644 --- a/arch/powerpc/boot/dts/t4240qds.dts +++ b/arch/powerpc/boot/dts/t4240qds.dts | |||
@@ -118,36 +118,53 @@ | |||
118 | }; | 118 | }; |
119 | 119 | ||
120 | i2c@118000 { | 120 | i2c@118000 { |
121 | eeprom@51 { | 121 | mux@77 { |
122 | compatible = "at24,24c256"; | 122 | compatible = "nxp,pca9547"; |
123 | reg = <0x51>; | 123 | reg = <0x77>; |
124 | }; | 124 | #address-cells = <1>; |
125 | eeprom@52 { | 125 | #size-cells = <0>; |
126 | compatible = "at24,24c256"; | 126 | |
127 | reg = <0x52>; | 127 | i2c@0 { |
128 | }; | 128 | #address-cells = <1>; |
129 | eeprom@53 { | 129 | #size-cells = <0>; |
130 | compatible = "at24,24c256"; | 130 | reg = <0>; |
131 | reg = <0x53>; | 131 | |
132 | }; | 132 | eeprom@51 { |
133 | eeprom@54 { | 133 | compatible = "at24,24c256"; |
134 | compatible = "at24,24c256"; | 134 | reg = <0x51>; |
135 | reg = <0x54>; | 135 | }; |
136 | }; | 136 | eeprom@52 { |
137 | eeprom@55 { | 137 | compatible = "at24,24c256"; |
138 | compatible = "at24,24c256"; | 138 | reg = <0x52>; |
139 | reg = <0x55>; | 139 | }; |
140 | }; | 140 | eeprom@53 { |
141 | eeprom@56 { | 141 | compatible = "at24,24c256"; |
142 | compatible = "at24,24c256"; | 142 | reg = <0x53>; |
143 | reg = <0x56>; | 143 | }; |
144 | }; | 144 | eeprom@54 { |
145 | rtc@68 { | 145 | compatible = "at24,24c256"; |
146 | compatible = "dallas,ds3232"; | 146 | reg = <0x54>; |
147 | reg = <0x68>; | 147 | }; |
148 | interrupts = <0x1 0x1 0 0>; | 148 | eeprom@55 { |
149 | compatible = "at24,24c256"; | ||
150 | reg = <0x55>; | ||
151 | }; | ||
152 | eeprom@56 { | ||
153 | compatible = "at24,24c256"; | ||
154 | reg = <0x56>; | ||
155 | }; | ||
156 | rtc@68 { | ||
157 | compatible = "dallas,ds3232"; | ||
158 | reg = <0x68>; | ||
159 | interrupts = <0x1 0x1 0 0>; | ||
160 | }; | ||
161 | }; | ||
149 | }; | 162 | }; |
150 | }; | 163 | }; |
164 | |||
165 | sdhc@114000 { | ||
166 | voltage-ranges = <1800 1800 3300 3300>; | ||
167 | }; | ||
151 | }; | 168 | }; |
152 | 169 | ||
153 | pci0: pcie@ffe240000 { | 170 | pci0: pcie@ffe240000 { |
diff --git a/arch/powerpc/boot/epapr-wrapper.c b/arch/powerpc/boot/epapr-wrapper.c new file mode 100644 index 000000000000..c10191006673 --- /dev/null +++ b/arch/powerpc/boot/epapr-wrapper.c | |||
@@ -0,0 +1,9 @@ | |||
1 | extern void epapr_platform_init(unsigned long r3, unsigned long r4, | ||
2 | unsigned long r5, unsigned long r6, | ||
3 | unsigned long r7); | ||
4 | |||
5 | void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
6 | unsigned long r6, unsigned long r7) | ||
7 | { | ||
8 | epapr_platform_init(r3, r4, r5, r6, r7); | ||
9 | } | ||
diff --git a/arch/powerpc/boot/epapr.c b/arch/powerpc/boot/epapr.c index 06c1961bd124..02e91aa2194a 100644 --- a/arch/powerpc/boot/epapr.c +++ b/arch/powerpc/boot/epapr.c | |||
@@ -48,8 +48,8 @@ static void platform_fixups(void) | |||
48 | fdt_addr, fdt_totalsize((void *)fdt_addr), ima_size); | 48 | fdt_addr, fdt_totalsize((void *)fdt_addr), ima_size); |
49 | } | 49 | } |
50 | 50 | ||
51 | void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | 51 | void epapr_platform_init(unsigned long r3, unsigned long r4, unsigned long r5, |
52 | unsigned long r6, unsigned long r7) | 52 | unsigned long r6, unsigned long r7) |
53 | { | 53 | { |
54 | epapr_magic = r6; | 54 | epapr_magic = r6; |
55 | ima_size = r7; | 55 | ima_size = r7; |
diff --git a/arch/powerpc/boot/of.c b/arch/powerpc/boot/of.c index 61d9899aa0d0..62e2f43ec1df 100644 --- a/arch/powerpc/boot/of.c +++ b/arch/powerpc/boot/of.c | |||
@@ -26,6 +26,9 @@ | |||
26 | 26 | ||
27 | static unsigned long claim_base; | 27 | static unsigned long claim_base; |
28 | 28 | ||
29 | void epapr_platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
30 | unsigned long r6, unsigned long r7); | ||
31 | |||
29 | static void *of_try_claim(unsigned long size) | 32 | static void *of_try_claim(unsigned long size) |
30 | { | 33 | { |
31 | unsigned long addr = 0; | 34 | unsigned long addr = 0; |
@@ -61,7 +64,7 @@ static void of_image_hdr(const void *hdr) | |||
61 | } | 64 | } |
62 | } | 65 | } |
63 | 66 | ||
64 | void platform_init(unsigned long a1, unsigned long a2, void *promptr) | 67 | static void of_platform_init(unsigned long a1, unsigned long a2, void *promptr) |
65 | { | 68 | { |
66 | platform_ops.image_hdr = of_image_hdr; | 69 | platform_ops.image_hdr = of_image_hdr; |
67 | platform_ops.malloc = of_try_claim; | 70 | platform_ops.malloc = of_try_claim; |
@@ -81,3 +84,14 @@ void platform_init(unsigned long a1, unsigned long a2, void *promptr) | |||
81 | loader_info.initrd_size = a2; | 84 | loader_info.initrd_size = a2; |
82 | } | 85 | } |
83 | } | 86 | } |
87 | |||
88 | void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, | ||
89 | unsigned long r6, unsigned long r7) | ||
90 | { | ||
91 | /* Detect OF vs. ePAPR boot */ | ||
92 | if (r5) | ||
93 | of_platform_init(r3, r4, (void *)r5); | ||
94 | else | ||
95 | epapr_platform_init(r3, r4, r5, r6, r7); | ||
96 | } | ||
97 | |||
diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper index 6761c746048d..2e1af74a64be 100755 --- a/arch/powerpc/boot/wrapper +++ b/arch/powerpc/boot/wrapper | |||
@@ -147,21 +147,29 @@ link_address='0x400000' | |||
147 | make_space=y | 147 | make_space=y |
148 | 148 | ||
149 | case "$platform" in | 149 | case "$platform" in |
150 | of) | ||
151 | platformo="$object/of.o $object/epapr.o" | ||
152 | make_space=n | ||
153 | ;; | ||
150 | pseries) | 154 | pseries) |
151 | platformo=$object/of.o | 155 | platformo="$object/of.o $object/epapr.o" |
152 | link_address='0x4000000' | 156 | link_address='0x4000000' |
157 | make_space=n | ||
153 | ;; | 158 | ;; |
154 | maple) | 159 | maple) |
155 | platformo=$object/of.o | 160 | platformo="$object/of.o $object/epapr.o" |
156 | link_address='0x400000' | 161 | link_address='0x400000' |
162 | make_space=n | ||
157 | ;; | 163 | ;; |
158 | pmac|chrp) | 164 | pmac|chrp) |
159 | platformo=$object/of.o | 165 | platformo="$object/of.o $object/epapr.o" |
166 | make_space=n | ||
160 | ;; | 167 | ;; |
161 | coff) | 168 | coff) |
162 | platformo="$object/crt0.o $object/of.o" | 169 | platformo="$object/crt0.o $object/of.o $object/epapr.o" |
163 | lds=$object/zImage.coff.lds | 170 | lds=$object/zImage.coff.lds |
164 | link_address='0x500000' | 171 | link_address='0x500000' |
172 | make_space=n | ||
165 | pie= | 173 | pie= |
166 | ;; | 174 | ;; |
167 | miboot|uboot*) | 175 | miboot|uboot*) |
@@ -253,6 +261,7 @@ treeboot-iss4xx-mpic) | |||
253 | platformo="$object/treeboot-iss4xx.o" | 261 | platformo="$object/treeboot-iss4xx.o" |
254 | ;; | 262 | ;; |
255 | epapr) | 263 | epapr) |
264 | platformo="$object/epapr.o $object/epapr-wrapper.o" | ||
256 | link_address='0x20000000' | 265 | link_address='0x20000000' |
257 | pie=-pie | 266 | pie=-pie |
258 | ;; | 267 | ;; |
diff --git a/arch/powerpc/configs/corenet32_smp_defconfig b/arch/powerpc/configs/corenet32_smp_defconfig index 3dfab4c40c76..bbd794deb6eb 100644 --- a/arch/powerpc/configs/corenet32_smp_defconfig +++ b/arch/powerpc/configs/corenet32_smp_defconfig | |||
@@ -23,11 +23,7 @@ CONFIG_MODVERSIONS=y | |||
23 | # CONFIG_BLK_DEV_BSG is not set | 23 | # CONFIG_BLK_DEV_BSG is not set |
24 | CONFIG_PARTITION_ADVANCED=y | 24 | CONFIG_PARTITION_ADVANCED=y |
25 | CONFIG_MAC_PARTITION=y | 25 | CONFIG_MAC_PARTITION=y |
26 | CONFIG_P2041_RDB=y | 26 | CONFIG_CORENET_GENERIC=y |
27 | CONFIG_P3041_DS=y | ||
28 | CONFIG_P4080_DS=y | ||
29 | CONFIG_P5020_DS=y | ||
30 | CONFIG_P5040_DS=y | ||
31 | CONFIG_HIGHMEM=y | 27 | CONFIG_HIGHMEM=y |
32 | # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set | 28 | # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set |
33 | CONFIG_BINFMT_MISC=m | 29 | CONFIG_BINFMT_MISC=m |
@@ -104,6 +100,7 @@ CONFIG_FSL_PQ_MDIO=y | |||
104 | CONFIG_E1000=y | 100 | CONFIG_E1000=y |
105 | CONFIG_E1000E=y | 101 | CONFIG_E1000E=y |
106 | CONFIG_VITESSE_PHY=y | 102 | CONFIG_VITESSE_PHY=y |
103 | CONFIG_AT803X_PHY=y | ||
107 | CONFIG_FIXED_PHY=y | 104 | CONFIG_FIXED_PHY=y |
108 | # CONFIG_INPUT_MOUSEDEV is not set | 105 | # CONFIG_INPUT_MOUSEDEV is not set |
109 | # CONFIG_INPUT_KEYBOARD is not set | 106 | # CONFIG_INPUT_KEYBOARD is not set |
diff --git a/arch/powerpc/configs/corenet64_smp_defconfig b/arch/powerpc/configs/corenet64_smp_defconfig index fa94fb3bb44d..63508ddee11c 100644 --- a/arch/powerpc/configs/corenet64_smp_defconfig +++ b/arch/powerpc/configs/corenet64_smp_defconfig | |||
@@ -21,10 +21,7 @@ CONFIG_MODVERSIONS=y | |||
21 | # CONFIG_BLK_DEV_BSG is not set | 21 | # CONFIG_BLK_DEV_BSG is not set |
22 | CONFIG_PARTITION_ADVANCED=y | 22 | CONFIG_PARTITION_ADVANCED=y |
23 | CONFIG_MAC_PARTITION=y | 23 | CONFIG_MAC_PARTITION=y |
24 | CONFIG_B4_QDS=y | 24 | CONFIG_CORENET_GENERIC=y |
25 | CONFIG_P5020_DS=y | ||
26 | CONFIG_P5040_DS=y | ||
27 | CONFIG_T4240_QDS=y | ||
28 | # CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set | 25 | # CONFIG_PPC_OF_BOOT_TRAMPOLINE is not set |
29 | CONFIG_BINFMT_MISC=m | 26 | CONFIG_BINFMT_MISC=m |
30 | CONFIG_MATH_EMULATION=y | 27 | CONFIG_MATH_EMULATION=y |
diff --git a/arch/powerpc/configs/mpc85xx_defconfig b/arch/powerpc/configs/mpc85xx_defconfig index dc098d988211..d2e0fab5ee5b 100644 --- a/arch/powerpc/configs/mpc85xx_defconfig +++ b/arch/powerpc/configs/mpc85xx_defconfig | |||
@@ -138,6 +138,7 @@ CONFIG_MARVELL_PHY=y | |||
138 | CONFIG_DAVICOM_PHY=y | 138 | CONFIG_DAVICOM_PHY=y |
139 | CONFIG_CICADA_PHY=y | 139 | CONFIG_CICADA_PHY=y |
140 | CONFIG_VITESSE_PHY=y | 140 | CONFIG_VITESSE_PHY=y |
141 | CONFIG_AT803X_PHY=y | ||
141 | CONFIG_FIXED_PHY=y | 142 | CONFIG_FIXED_PHY=y |
142 | CONFIG_INPUT_FF_MEMLESS=m | 143 | CONFIG_INPUT_FF_MEMLESS=m |
143 | # CONFIG_INPUT_MOUSEDEV is not set | 144 | # CONFIG_INPUT_MOUSEDEV is not set |
diff --git a/arch/powerpc/configs/mpc85xx_smp_defconfig b/arch/powerpc/configs/mpc85xx_smp_defconfig index 5bca60161bb3..4cb7b59e98bd 100644 --- a/arch/powerpc/configs/mpc85xx_smp_defconfig +++ b/arch/powerpc/configs/mpc85xx_smp_defconfig | |||
@@ -138,6 +138,7 @@ CONFIG_MARVELL_PHY=y | |||
138 | CONFIG_DAVICOM_PHY=y | 138 | CONFIG_DAVICOM_PHY=y |
139 | CONFIG_CICADA_PHY=y | 139 | CONFIG_CICADA_PHY=y |
140 | CONFIG_VITESSE_PHY=y | 140 | CONFIG_VITESSE_PHY=y |
141 | CONFIG_AT803X_PHY=y | ||
141 | CONFIG_FIXED_PHY=y | 142 | CONFIG_FIXED_PHY=y |
142 | CONFIG_INPUT_FF_MEMLESS=m | 143 | CONFIG_INPUT_FF_MEMLESS=m |
143 | # CONFIG_INPUT_MOUSEDEV is not set | 144 | # CONFIG_INPUT_MOUSEDEV is not set |
diff --git a/arch/powerpc/configs/ppc64_defconfig b/arch/powerpc/configs/ppc64_defconfig index 0e8cfd09da2f..581a3bcae728 100644 --- a/arch/powerpc/configs/ppc64_defconfig +++ b/arch/powerpc/configs/ppc64_defconfig | |||
@@ -2,7 +2,6 @@ CONFIG_PPC64=y | |||
2 | CONFIG_ALTIVEC=y | 2 | CONFIG_ALTIVEC=y |
3 | CONFIG_VSX=y | 3 | CONFIG_VSX=y |
4 | CONFIG_SMP=y | 4 | CONFIG_SMP=y |
5 | CONFIG_EXPERIMENTAL=y | ||
6 | CONFIG_SYSVIPC=y | 5 | CONFIG_SYSVIPC=y |
7 | CONFIG_POSIX_MQUEUE=y | 6 | CONFIG_POSIX_MQUEUE=y |
8 | CONFIG_IRQ_DOMAIN_DEBUG=y | 7 | CONFIG_IRQ_DOMAIN_DEBUG=y |
@@ -25,7 +24,6 @@ CONFIG_MODULE_UNLOAD=y | |||
25 | CONFIG_MODVERSIONS=y | 24 | CONFIG_MODVERSIONS=y |
26 | CONFIG_MODULE_SRCVERSION_ALL=y | 25 | CONFIG_MODULE_SRCVERSION_ALL=y |
27 | CONFIG_PARTITION_ADVANCED=y | 26 | CONFIG_PARTITION_ADVANCED=y |
28 | CONFIG_EFI_PARTITION=y | ||
29 | CONFIG_PPC_SPLPAR=y | 27 | CONFIG_PPC_SPLPAR=y |
30 | CONFIG_SCANLOG=m | 28 | CONFIG_SCANLOG=m |
31 | CONFIG_PPC_SMLPAR=y | 29 | CONFIG_PPC_SMLPAR=y |
@@ -50,12 +48,10 @@ CONFIG_CPU_FREQ_PMAC64=y | |||
50 | CONFIG_HZ_100=y | 48 | CONFIG_HZ_100=y |
51 | CONFIG_BINFMT_MISC=m | 49 | CONFIG_BINFMT_MISC=m |
52 | CONFIG_PPC_TRANSACTIONAL_MEM=y | 50 | CONFIG_PPC_TRANSACTIONAL_MEM=y |
53 | CONFIG_HOTPLUG_CPU=y | ||
54 | CONFIG_KEXEC=y | 51 | CONFIG_KEXEC=y |
55 | CONFIG_IRQ_ALL_CPUS=y | 52 | CONFIG_IRQ_ALL_CPUS=y |
56 | CONFIG_MEMORY_HOTREMOVE=y | 53 | CONFIG_MEMORY_HOTREMOVE=y |
57 | CONFIG_SCHED_SMT=y | 54 | CONFIG_SCHED_SMT=y |
58 | CONFIG_PPC_DENORMALISATION=y | ||
59 | CONFIG_PCCARD=y | 55 | CONFIG_PCCARD=y |
60 | CONFIG_ELECTRA_CF=y | 56 | CONFIG_ELECTRA_CF=y |
61 | CONFIG_HOTPLUG_PCI=y | 57 | CONFIG_HOTPLUG_PCI=y |
@@ -89,7 +85,6 @@ CONFIG_NF_CONNTRACK_PPTP=m | |||
89 | CONFIG_NF_CONNTRACK_SIP=m | 85 | CONFIG_NF_CONNTRACK_SIP=m |
90 | CONFIG_NF_CONNTRACK_TFTP=m | 86 | CONFIG_NF_CONNTRACK_TFTP=m |
91 | CONFIG_NF_CT_NETLINK=m | 87 | CONFIG_NF_CT_NETLINK=m |
92 | CONFIG_NETFILTER_TPROXY=m | ||
93 | CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m | 88 | CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m |
94 | CONFIG_NETFILTER_XT_TARGET_CONNMARK=m | 89 | CONFIG_NETFILTER_XT_TARGET_CONNMARK=m |
95 | CONFIG_NETFILTER_XT_TARGET_DSCP=m | 90 | CONFIG_NETFILTER_XT_TARGET_DSCP=m |
@@ -131,7 +126,6 @@ CONFIG_NETFILTER_XT_MATCH_STRING=m | |||
131 | CONFIG_NETFILTER_XT_MATCH_TCPMSS=m | 126 | CONFIG_NETFILTER_XT_MATCH_TCPMSS=m |
132 | CONFIG_NETFILTER_XT_MATCH_U32=m | 127 | CONFIG_NETFILTER_XT_MATCH_U32=m |
133 | CONFIG_NF_CONNTRACK_IPV4=m | 128 | CONFIG_NF_CONNTRACK_IPV4=m |
134 | CONFIG_IP_NF_QUEUE=m | ||
135 | CONFIG_IP_NF_IPTABLES=m | 129 | CONFIG_IP_NF_IPTABLES=m |
136 | CONFIG_IP_NF_MATCH_AH=m | 130 | CONFIG_IP_NF_MATCH_AH=m |
137 | CONFIG_IP_NF_MATCH_ECN=m | 131 | CONFIG_IP_NF_MATCH_ECN=m |
@@ -157,6 +151,7 @@ CONFIG_BLK_DEV_LOOP=y | |||
157 | CONFIG_BLK_DEV_NBD=m | 151 | CONFIG_BLK_DEV_NBD=m |
158 | CONFIG_BLK_DEV_RAM=y | 152 | CONFIG_BLK_DEV_RAM=y |
159 | CONFIG_BLK_DEV_RAM_SIZE=65536 | 153 | CONFIG_BLK_DEV_RAM_SIZE=65536 |
154 | CONFIG_VIRTIO_BLK=m | ||
160 | CONFIG_IDE=y | 155 | CONFIG_IDE=y |
161 | CONFIG_BLK_DEV_IDECD=y | 156 | CONFIG_BLK_DEV_IDECD=y |
162 | CONFIG_BLK_DEV_GENERIC=y | 157 | CONFIG_BLK_DEV_GENERIC=y |
@@ -185,6 +180,10 @@ CONFIG_SCSI_IPR=y | |||
185 | CONFIG_SCSI_QLA_FC=m | 180 | CONFIG_SCSI_QLA_FC=m |
186 | CONFIG_SCSI_QLA_ISCSI=m | 181 | CONFIG_SCSI_QLA_ISCSI=m |
187 | CONFIG_SCSI_LPFC=m | 182 | CONFIG_SCSI_LPFC=m |
183 | CONFIG_SCSI_VIRTIO=m | ||
184 | CONFIG_SCSI_DH=m | ||
185 | CONFIG_SCSI_DH_RDAC=m | ||
186 | CONFIG_SCSI_DH_ALUA=m | ||
188 | CONFIG_ATA=y | 187 | CONFIG_ATA=y |
189 | CONFIG_SATA_SIL24=y | 188 | CONFIG_SATA_SIL24=y |
190 | CONFIG_SATA_SVW=y | 189 | CONFIG_SATA_SVW=y |
@@ -203,6 +202,9 @@ CONFIG_DM_SNAPSHOT=m | |||
203 | CONFIG_DM_MIRROR=m | 202 | CONFIG_DM_MIRROR=m |
204 | CONFIG_DM_ZERO=m | 203 | CONFIG_DM_ZERO=m |
205 | CONFIG_DM_MULTIPATH=m | 204 | CONFIG_DM_MULTIPATH=m |
205 | CONFIG_DM_MULTIPATH_QL=m | ||
206 | CONFIG_DM_MULTIPATH_ST=m | ||
207 | CONFIG_DM_UEVENT=y | ||
206 | CONFIG_ADB_PMU=y | 208 | CONFIG_ADB_PMU=y |
207 | CONFIG_PMAC_SMU=y | 209 | CONFIG_PMAC_SMU=y |
208 | CONFIG_THERM_PM72=y | 210 | CONFIG_THERM_PM72=y |
@@ -216,6 +218,8 @@ CONFIG_DUMMY=m | |||
216 | CONFIG_NETCONSOLE=y | 218 | CONFIG_NETCONSOLE=y |
217 | CONFIG_NETPOLL_TRAP=y | 219 | CONFIG_NETPOLL_TRAP=y |
218 | CONFIG_TUN=m | 220 | CONFIG_TUN=m |
221 | CONFIG_VIRTIO_NET=m | ||
222 | CONFIG_VHOST_NET=m | ||
219 | CONFIG_VORTEX=y | 223 | CONFIG_VORTEX=y |
220 | CONFIG_ACENIC=m | 224 | CONFIG_ACENIC=m |
221 | CONFIG_ACENIC_OMIT_TIGON_I=y | 225 | CONFIG_ACENIC_OMIT_TIGON_I=y |
@@ -262,6 +266,7 @@ CONFIG_HVC_CONSOLE=y | |||
262 | CONFIG_HVC_RTAS=y | 266 | CONFIG_HVC_RTAS=y |
263 | CONFIG_HVC_BEAT=y | 267 | CONFIG_HVC_BEAT=y |
264 | CONFIG_HVCS=m | 268 | CONFIG_HVCS=m |
269 | CONFIG_VIRTIO_CONSOLE=m | ||
265 | CONFIG_IBM_BSR=m | 270 | CONFIG_IBM_BSR=m |
266 | CONFIG_RAW_DRIVER=y | 271 | CONFIG_RAW_DRIVER=y |
267 | CONFIG_I2C_CHARDEV=y | 272 | CONFIG_I2C_CHARDEV=y |
@@ -301,7 +306,6 @@ CONFIG_HID_GYRATION=y | |||
301 | CONFIG_HID_PANTHERLORD=y | 306 | CONFIG_HID_PANTHERLORD=y |
302 | CONFIG_HID_PETALYNX=y | 307 | CONFIG_HID_PETALYNX=y |
303 | CONFIG_HID_SAMSUNG=y | 308 | CONFIG_HID_SAMSUNG=y |
304 | CONFIG_HID_SONY=y | ||
305 | CONFIG_HID_SUNPLUS=y | 309 | CONFIG_HID_SUNPLUS=y |
306 | CONFIG_USB_HIDDEV=y | 310 | CONFIG_USB_HIDDEV=y |
307 | CONFIG_USB=y | 311 | CONFIG_USB=y |
@@ -328,6 +332,8 @@ CONFIG_EDAC_MM_EDAC=y | |||
328 | CONFIG_EDAC_PASEMI=y | 332 | CONFIG_EDAC_PASEMI=y |
329 | CONFIG_RTC_CLASS=y | 333 | CONFIG_RTC_CLASS=y |
330 | CONFIG_RTC_DRV_DS1307=y | 334 | CONFIG_RTC_DRV_DS1307=y |
335 | CONFIG_VIRTIO_PCI=m | ||
336 | CONFIG_VIRTIO_BALLOON=m | ||
331 | CONFIG_EXT2_FS=y | 337 | CONFIG_EXT2_FS=y |
332 | CONFIG_EXT2_FS_XATTR=y | 338 | CONFIG_EXT2_FS_XATTR=y |
333 | CONFIG_EXT2_FS_POSIX_ACL=y | 339 | CONFIG_EXT2_FS_POSIX_ACL=y |
@@ -386,21 +392,19 @@ CONFIG_NLS_UTF8=y | |||
386 | CONFIG_CRC_T10DIF=y | 392 | CONFIG_CRC_T10DIF=y |
387 | CONFIG_MAGIC_SYSRQ=y | 393 | CONFIG_MAGIC_SYSRQ=y |
388 | CONFIG_DEBUG_KERNEL=y | 394 | CONFIG_DEBUG_KERNEL=y |
395 | CONFIG_DEBUG_STACK_USAGE=y | ||
396 | CONFIG_DEBUG_STACKOVERFLOW=y | ||
389 | CONFIG_LOCKUP_DETECTOR=y | 397 | CONFIG_LOCKUP_DETECTOR=y |
390 | CONFIG_DEBUG_MUTEXES=y | 398 | CONFIG_DEBUG_MUTEXES=y |
391 | CONFIG_DEBUG_STACK_USAGE=y | ||
392 | CONFIG_LATENCYTOP=y | 399 | CONFIG_LATENCYTOP=y |
393 | CONFIG_SCHED_TRACER=y | 400 | CONFIG_SCHED_TRACER=y |
394 | CONFIG_BLK_DEV_IO_TRACE=y | 401 | CONFIG_BLK_DEV_IO_TRACE=y |
395 | CONFIG_DEBUG_STACKOVERFLOW=y | ||
396 | CONFIG_CODE_PATCHING_SELFTEST=y | 402 | CONFIG_CODE_PATCHING_SELFTEST=y |
397 | CONFIG_FTR_FIXUP_SELFTEST=y | 403 | CONFIG_FTR_FIXUP_SELFTEST=y |
398 | CONFIG_MSI_BITMAP_SELFTEST=y | 404 | CONFIG_MSI_BITMAP_SELFTEST=y |
399 | CONFIG_XMON=y | 405 | CONFIG_XMON=y |
400 | CONFIG_BOOTX_TEXT=y | 406 | CONFIG_BOOTX_TEXT=y |
401 | CONFIG_PPC_EARLY_DEBUG=y | 407 | CONFIG_PPC_EARLY_DEBUG=y |
402 | CONFIG_PPC_EARLY_DEBUG_BOOTX=y | ||
403 | CONFIG_CRYPTO_NULL=m | ||
404 | CONFIG_CRYPTO_TEST=m | 408 | CONFIG_CRYPTO_TEST=m |
405 | CONFIG_CRYPTO_PCBC=m | 409 | CONFIG_CRYPTO_PCBC=m |
406 | CONFIG_CRYPTO_HMAC=y | 410 | CONFIG_CRYPTO_HMAC=y |
@@ -422,4 +426,3 @@ CONFIG_CRYPTO_DEV_NX_ENCRYPT=m | |||
422 | CONFIG_VIRTUALIZATION=y | 426 | CONFIG_VIRTUALIZATION=y |
423 | CONFIG_KVM_BOOK3S_64=m | 427 | CONFIG_KVM_BOOK3S_64=m |
424 | CONFIG_KVM_BOOK3S_64_HV=y | 428 | CONFIG_KVM_BOOK3S_64_HV=y |
425 | CONFIG_VHOST_NET=m | ||
diff --git a/arch/powerpc/configs/ppc64e_defconfig b/arch/powerpc/configs/ppc64e_defconfig index 0085dc4642c5..f627fda08953 100644 --- a/arch/powerpc/configs/ppc64e_defconfig +++ b/arch/powerpc/configs/ppc64e_defconfig | |||
@@ -1,7 +1,6 @@ | |||
1 | CONFIG_PPC64=y | 1 | CONFIG_PPC64=y |
2 | CONFIG_PPC_BOOK3E_64=y | 2 | CONFIG_PPC_BOOK3E_64=y |
3 | CONFIG_SMP=y | 3 | CONFIG_SMP=y |
4 | CONFIG_EXPERIMENTAL=y | ||
5 | CONFIG_SYSVIPC=y | 4 | CONFIG_SYSVIPC=y |
6 | CONFIG_POSIX_MQUEUE=y | 5 | CONFIG_POSIX_MQUEUE=y |
7 | CONFIG_NO_HZ=y | 6 | CONFIG_NO_HZ=y |
@@ -23,7 +22,7 @@ CONFIG_MODULE_SRCVERSION_ALL=y | |||
23 | CONFIG_PARTITION_ADVANCED=y | 22 | CONFIG_PARTITION_ADVANCED=y |
24 | CONFIG_MAC_PARTITION=y | 23 | CONFIG_MAC_PARTITION=y |
25 | CONFIG_EFI_PARTITION=y | 24 | CONFIG_EFI_PARTITION=y |
26 | CONFIG_P5020_DS=y | 25 | CONFIG_CORENET_GENERIC=y |
27 | CONFIG_CPU_FREQ=y | 26 | CONFIG_CPU_FREQ=y |
28 | CONFIG_CPU_FREQ_GOV_POWERSAVE=y | 27 | CONFIG_CPU_FREQ_GOV_POWERSAVE=y |
29 | CONFIG_CPU_FREQ_GOV_USERSPACE=y | 28 | CONFIG_CPU_FREQ_GOV_USERSPACE=y |
@@ -61,7 +60,6 @@ CONFIG_NF_CONNTRACK_PPTP=m | |||
61 | CONFIG_NF_CONNTRACK_SIP=m | 60 | CONFIG_NF_CONNTRACK_SIP=m |
62 | CONFIG_NF_CONNTRACK_TFTP=m | 61 | CONFIG_NF_CONNTRACK_TFTP=m |
63 | CONFIG_NF_CT_NETLINK=m | 62 | CONFIG_NF_CT_NETLINK=m |
64 | CONFIG_NETFILTER_TPROXY=m | ||
65 | CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m | 63 | CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m |
66 | CONFIG_NETFILTER_XT_TARGET_CONNMARK=m | 64 | CONFIG_NETFILTER_XT_TARGET_CONNMARK=m |
67 | CONFIG_NETFILTER_XT_TARGET_DSCP=m | 65 | CONFIG_NETFILTER_XT_TARGET_DSCP=m |
@@ -103,7 +101,6 @@ CONFIG_NETFILTER_XT_MATCH_STRING=m | |||
103 | CONFIG_NETFILTER_XT_MATCH_TCPMSS=m | 101 | CONFIG_NETFILTER_XT_MATCH_TCPMSS=m |
104 | CONFIG_NETFILTER_XT_MATCH_U32=m | 102 | CONFIG_NETFILTER_XT_MATCH_U32=m |
105 | CONFIG_NF_CONNTRACK_IPV4=m | 103 | CONFIG_NF_CONNTRACK_IPV4=m |
106 | CONFIG_IP_NF_QUEUE=m | ||
107 | CONFIG_IP_NF_IPTABLES=m | 104 | CONFIG_IP_NF_IPTABLES=m |
108 | CONFIG_IP_NF_MATCH_AH=m | 105 | CONFIG_IP_NF_MATCH_AH=m |
109 | CONFIG_IP_NF_MATCH_ECN=m | 106 | CONFIG_IP_NF_MATCH_ECN=m |
@@ -193,7 +190,6 @@ CONFIG_PPP_SYNC_TTY=m | |||
193 | CONFIG_INPUT_EVDEV=m | 190 | CONFIG_INPUT_EVDEV=m |
194 | CONFIG_INPUT_MISC=y | 191 | CONFIG_INPUT_MISC=y |
195 | # CONFIG_SERIO_SERPORT is not set | 192 | # CONFIG_SERIO_SERPORT is not set |
196 | CONFIG_VT_HW_CONSOLE_BINDING=y | ||
197 | CONFIG_SERIAL_8250=y | 193 | CONFIG_SERIAL_8250=y |
198 | CONFIG_SERIAL_8250_CONSOLE=y | 194 | CONFIG_SERIAL_8250_CONSOLE=y |
199 | # CONFIG_HW_RANDOM is not set | 195 | # CONFIG_HW_RANDOM is not set |
@@ -230,7 +226,6 @@ CONFIG_HID_NTRIG=y | |||
230 | CONFIG_HID_PANTHERLORD=y | 226 | CONFIG_HID_PANTHERLORD=y |
231 | CONFIG_HID_PETALYNX=y | 227 | CONFIG_HID_PETALYNX=y |
232 | CONFIG_HID_SAMSUNG=y | 228 | CONFIG_HID_SAMSUNG=y |
233 | CONFIG_HID_SONY=y | ||
234 | CONFIG_HID_SUNPLUS=y | 229 | CONFIG_HID_SUNPLUS=y |
235 | CONFIG_HID_GREENASIA=y | 230 | CONFIG_HID_GREENASIA=y |
236 | CONFIG_HID_SMARTJOYPLUS=y | 231 | CONFIG_HID_SMARTJOYPLUS=y |
@@ -302,19 +297,18 @@ CONFIG_NLS_UTF8=y | |||
302 | CONFIG_CRC_T10DIF=y | 297 | CONFIG_CRC_T10DIF=y |
303 | CONFIG_MAGIC_SYSRQ=y | 298 | CONFIG_MAGIC_SYSRQ=y |
304 | CONFIG_DEBUG_KERNEL=y | 299 | CONFIG_DEBUG_KERNEL=y |
300 | CONFIG_DEBUG_STACK_USAGE=y | ||
301 | CONFIG_DEBUG_STACKOVERFLOW=y | ||
305 | CONFIG_DETECT_HUNG_TASK=y | 302 | CONFIG_DETECT_HUNG_TASK=y |
306 | CONFIG_DEBUG_MUTEXES=y | 303 | CONFIG_DEBUG_MUTEXES=y |
307 | CONFIG_DEBUG_STACK_USAGE=y | ||
308 | CONFIG_LATENCYTOP=y | 304 | CONFIG_LATENCYTOP=y |
309 | CONFIG_IRQSOFF_TRACER=y | 305 | CONFIG_IRQSOFF_TRACER=y |
310 | CONFIG_SCHED_TRACER=y | 306 | CONFIG_SCHED_TRACER=y |
311 | CONFIG_BLK_DEV_IO_TRACE=y | 307 | CONFIG_BLK_DEV_IO_TRACE=y |
312 | CONFIG_DEBUG_STACKOVERFLOW=y | ||
313 | CONFIG_CODE_PATCHING_SELFTEST=y | 308 | CONFIG_CODE_PATCHING_SELFTEST=y |
314 | CONFIG_FTR_FIXUP_SELFTEST=y | 309 | CONFIG_FTR_FIXUP_SELFTEST=y |
315 | CONFIG_MSI_BITMAP_SELFTEST=y | 310 | CONFIG_MSI_BITMAP_SELFTEST=y |
316 | CONFIG_XMON=y | 311 | CONFIG_XMON=y |
317 | CONFIG_CRYPTO_NULL=m | ||
318 | CONFIG_CRYPTO_TEST=m | 312 | CONFIG_CRYPTO_TEST=m |
319 | CONFIG_CRYPTO_CCM=m | 313 | CONFIG_CRYPTO_CCM=m |
320 | CONFIG_CRYPTO_GCM=m | 314 | CONFIG_CRYPTO_GCM=m |
diff --git a/arch/powerpc/configs/ppc6xx_defconfig b/arch/powerpc/configs/ppc6xx_defconfig index 20ebfaf7234b..c2353bf059fd 100644 --- a/arch/powerpc/configs/ppc6xx_defconfig +++ b/arch/powerpc/configs/ppc6xx_defconfig | |||
@@ -71,7 +71,7 @@ CONFIG_QUICC_ENGINE=y | |||
71 | CONFIG_QE_GPIO=y | 71 | CONFIG_QE_GPIO=y |
72 | CONFIG_PPC_BESTCOMM=y | 72 | CONFIG_PPC_BESTCOMM=y |
73 | CONFIG_GPIO_MPC8XXX=y | 73 | CONFIG_GPIO_MPC8XXX=y |
74 | CONFIG_MCU_MPC8349EMITX=m | 74 | CONFIG_MCU_MPC8349EMITX=y |
75 | CONFIG_HIGHMEM=y | 75 | CONFIG_HIGHMEM=y |
76 | CONFIG_NO_HZ=y | 76 | CONFIG_NO_HZ=y |
77 | CONFIG_HIGH_RES_TIMERS=y | 77 | CONFIG_HIGH_RES_TIMERS=y |
diff --git a/arch/powerpc/configs/pseries_defconfig b/arch/powerpc/configs/pseries_defconfig index 1d4b9763895d..e9a8b4e0a0f6 100644 --- a/arch/powerpc/configs/pseries_defconfig +++ b/arch/powerpc/configs/pseries_defconfig | |||
@@ -3,7 +3,6 @@ CONFIG_ALTIVEC=y | |||
3 | CONFIG_VSX=y | 3 | CONFIG_VSX=y |
4 | CONFIG_SMP=y | 4 | CONFIG_SMP=y |
5 | CONFIG_NR_CPUS=2048 | 5 | CONFIG_NR_CPUS=2048 |
6 | CONFIG_EXPERIMENTAL=y | ||
7 | CONFIG_SYSVIPC=y | 6 | CONFIG_SYSVIPC=y |
8 | CONFIG_POSIX_MQUEUE=y | 7 | CONFIG_POSIX_MQUEUE=y |
9 | CONFIG_AUDIT=y | 8 | CONFIG_AUDIT=y |
@@ -33,7 +32,6 @@ CONFIG_MODULE_UNLOAD=y | |||
33 | CONFIG_MODVERSIONS=y | 32 | CONFIG_MODVERSIONS=y |
34 | CONFIG_MODULE_SRCVERSION_ALL=y | 33 | CONFIG_MODULE_SRCVERSION_ALL=y |
35 | CONFIG_PARTITION_ADVANCED=y | 34 | CONFIG_PARTITION_ADVANCED=y |
36 | CONFIG_EFI_PARTITION=y | ||
37 | CONFIG_PPC_SPLPAR=y | 35 | CONFIG_PPC_SPLPAR=y |
38 | CONFIG_SCANLOG=m | 36 | CONFIG_SCANLOG=m |
39 | CONFIG_PPC_SMLPAR=y | 37 | CONFIG_PPC_SMLPAR=y |
@@ -44,7 +42,6 @@ CONFIG_IBMEBUS=y | |||
44 | CONFIG_HZ_100=y | 42 | CONFIG_HZ_100=y |
45 | CONFIG_BINFMT_MISC=m | 43 | CONFIG_BINFMT_MISC=m |
46 | CONFIG_PPC_TRANSACTIONAL_MEM=y | 44 | CONFIG_PPC_TRANSACTIONAL_MEM=y |
47 | CONFIG_HOTPLUG_CPU=y | ||
48 | CONFIG_KEXEC=y | 45 | CONFIG_KEXEC=y |
49 | CONFIG_IRQ_ALL_CPUS=y | 46 | CONFIG_IRQ_ALL_CPUS=y |
50 | CONFIG_MEMORY_HOTPLUG=y | 47 | CONFIG_MEMORY_HOTPLUG=y |
@@ -52,7 +49,6 @@ CONFIG_MEMORY_HOTREMOVE=y | |||
52 | CONFIG_PPC_64K_PAGES=y | 49 | CONFIG_PPC_64K_PAGES=y |
53 | CONFIG_PPC_SUBPAGE_PROT=y | 50 | CONFIG_PPC_SUBPAGE_PROT=y |
54 | CONFIG_SCHED_SMT=y | 51 | CONFIG_SCHED_SMT=y |
55 | CONFIG_PPC_DENORMALISATION=y | ||
56 | CONFIG_HOTPLUG_PCI=y | 52 | CONFIG_HOTPLUG_PCI=y |
57 | CONFIG_HOTPLUG_PCI_RPA=m | 53 | CONFIG_HOTPLUG_PCI_RPA=m |
58 | CONFIG_HOTPLUG_PCI_RPA_DLPAR=m | 54 | CONFIG_HOTPLUG_PCI_RPA_DLPAR=m |
@@ -113,7 +109,6 @@ CONFIG_NETFILTER_XT_MATCH_TCPMSS=m | |||
113 | CONFIG_NETFILTER_XT_MATCH_TIME=m | 109 | CONFIG_NETFILTER_XT_MATCH_TIME=m |
114 | CONFIG_NETFILTER_XT_MATCH_U32=m | 110 | CONFIG_NETFILTER_XT_MATCH_U32=m |
115 | CONFIG_NF_CONNTRACK_IPV4=m | 111 | CONFIG_NF_CONNTRACK_IPV4=m |
116 | CONFIG_IP_NF_QUEUE=m | ||
117 | CONFIG_IP_NF_IPTABLES=m | 112 | CONFIG_IP_NF_IPTABLES=m |
118 | CONFIG_IP_NF_MATCH_AH=m | 113 | CONFIG_IP_NF_MATCH_AH=m |
119 | CONFIG_IP_NF_MATCH_ECN=m | 114 | CONFIG_IP_NF_MATCH_ECN=m |
@@ -132,6 +127,7 @@ CONFIG_BLK_DEV_LOOP=y | |||
132 | CONFIG_BLK_DEV_NBD=m | 127 | CONFIG_BLK_DEV_NBD=m |
133 | CONFIG_BLK_DEV_RAM=y | 128 | CONFIG_BLK_DEV_RAM=y |
134 | CONFIG_BLK_DEV_RAM_SIZE=65536 | 129 | CONFIG_BLK_DEV_RAM_SIZE=65536 |
130 | CONFIG_VIRTIO_BLK=m | ||
135 | CONFIG_IDE=y | 131 | CONFIG_IDE=y |
136 | CONFIG_BLK_DEV_IDECD=y | 132 | CONFIG_BLK_DEV_IDECD=y |
137 | CONFIG_BLK_DEV_GENERIC=y | 133 | CONFIG_BLK_DEV_GENERIC=y |
@@ -157,6 +153,10 @@ CONFIG_SCSI_IPR=y | |||
157 | CONFIG_SCSI_QLA_FC=m | 153 | CONFIG_SCSI_QLA_FC=m |
158 | CONFIG_SCSI_QLA_ISCSI=m | 154 | CONFIG_SCSI_QLA_ISCSI=m |
159 | CONFIG_SCSI_LPFC=m | 155 | CONFIG_SCSI_LPFC=m |
156 | CONFIG_SCSI_VIRTIO=m | ||
157 | CONFIG_SCSI_DH=m | ||
158 | CONFIG_SCSI_DH_RDAC=m | ||
159 | CONFIG_SCSI_DH_ALUA=m | ||
160 | CONFIG_ATA=y | 160 | CONFIG_ATA=y |
161 | # CONFIG_ATA_SFF is not set | 161 | # CONFIG_ATA_SFF is not set |
162 | CONFIG_MD=y | 162 | CONFIG_MD=y |
@@ -174,11 +174,16 @@ CONFIG_DM_SNAPSHOT=m | |||
174 | CONFIG_DM_MIRROR=m | 174 | CONFIG_DM_MIRROR=m |
175 | CONFIG_DM_ZERO=m | 175 | CONFIG_DM_ZERO=m |
176 | CONFIG_DM_MULTIPATH=m | 176 | CONFIG_DM_MULTIPATH=m |
177 | CONFIG_DM_MULTIPATH_QL=m | ||
178 | CONFIG_DM_MULTIPATH_ST=m | ||
179 | CONFIG_DM_UEVENT=y | ||
177 | CONFIG_BONDING=m | 180 | CONFIG_BONDING=m |
178 | CONFIG_DUMMY=m | 181 | CONFIG_DUMMY=m |
179 | CONFIG_NETCONSOLE=y | 182 | CONFIG_NETCONSOLE=y |
180 | CONFIG_NETPOLL_TRAP=y | 183 | CONFIG_NETPOLL_TRAP=y |
181 | CONFIG_TUN=m | 184 | CONFIG_TUN=m |
185 | CONFIG_VIRTIO_NET=m | ||
186 | CONFIG_VHOST_NET=m | ||
182 | CONFIG_VORTEX=y | 187 | CONFIG_VORTEX=y |
183 | CONFIG_ACENIC=m | 188 | CONFIG_ACENIC=m |
184 | CONFIG_ACENIC_OMIT_TIGON_I=y | 189 | CONFIG_ACENIC_OMIT_TIGON_I=y |
@@ -216,6 +221,7 @@ CONFIG_SERIAL_JSM=m | |||
216 | CONFIG_HVC_CONSOLE=y | 221 | CONFIG_HVC_CONSOLE=y |
217 | CONFIG_HVC_RTAS=y | 222 | CONFIG_HVC_RTAS=y |
218 | CONFIG_HVCS=m | 223 | CONFIG_HVCS=m |
224 | CONFIG_VIRTIO_CONSOLE=m | ||
219 | CONFIG_IBM_BSR=m | 225 | CONFIG_IBM_BSR=m |
220 | CONFIG_GEN_RTC=y | 226 | CONFIG_GEN_RTC=y |
221 | CONFIG_RAW_DRIVER=y | 227 | CONFIG_RAW_DRIVER=y |
@@ -237,7 +243,6 @@ CONFIG_HID_GYRATION=y | |||
237 | CONFIG_HID_PANTHERLORD=y | 243 | CONFIG_HID_PANTHERLORD=y |
238 | CONFIG_HID_PETALYNX=y | 244 | CONFIG_HID_PETALYNX=y |
239 | CONFIG_HID_SAMSUNG=y | 245 | CONFIG_HID_SAMSUNG=y |
240 | CONFIG_HID_SONY=y | ||
241 | CONFIG_HID_SUNPLUS=y | 246 | CONFIG_HID_SUNPLUS=y |
242 | CONFIG_USB_HIDDEV=y | 247 | CONFIG_USB_HIDDEV=y |
243 | CONFIG_USB=y | 248 | CONFIG_USB=y |
@@ -258,6 +263,8 @@ CONFIG_INFINIBAND_IPOIB=m | |||
258 | CONFIG_INFINIBAND_IPOIB_CM=y | 263 | CONFIG_INFINIBAND_IPOIB_CM=y |
259 | CONFIG_INFINIBAND_SRP=m | 264 | CONFIG_INFINIBAND_SRP=m |
260 | CONFIG_INFINIBAND_ISER=m | 265 | CONFIG_INFINIBAND_ISER=m |
266 | CONFIG_VIRTIO_PCI=m | ||
267 | CONFIG_VIRTIO_BALLOON=m | ||
261 | CONFIG_EXT2_FS=y | 268 | CONFIG_EXT2_FS=y |
262 | CONFIG_EXT2_FS_XATTR=y | 269 | CONFIG_EXT2_FS_XATTR=y |
263 | CONFIG_EXT2_FS_POSIX_ACL=y | 270 | CONFIG_EXT2_FS_POSIX_ACL=y |
@@ -314,18 +321,17 @@ CONFIG_NLS_UTF8=y | |||
314 | CONFIG_CRC_T10DIF=y | 321 | CONFIG_CRC_T10DIF=y |
315 | CONFIG_MAGIC_SYSRQ=y | 322 | CONFIG_MAGIC_SYSRQ=y |
316 | CONFIG_DEBUG_KERNEL=y | 323 | CONFIG_DEBUG_KERNEL=y |
317 | CONFIG_LOCKUP_DETECTOR=y | ||
318 | CONFIG_DEBUG_STACK_USAGE=y | 324 | CONFIG_DEBUG_STACK_USAGE=y |
325 | CONFIG_DEBUG_STACKOVERFLOW=y | ||
326 | CONFIG_LOCKUP_DETECTOR=y | ||
319 | CONFIG_LATENCYTOP=y | 327 | CONFIG_LATENCYTOP=y |
320 | CONFIG_SCHED_TRACER=y | 328 | CONFIG_SCHED_TRACER=y |
321 | CONFIG_BLK_DEV_IO_TRACE=y | 329 | CONFIG_BLK_DEV_IO_TRACE=y |
322 | CONFIG_DEBUG_STACKOVERFLOW=y | ||
323 | CONFIG_CODE_PATCHING_SELFTEST=y | 330 | CONFIG_CODE_PATCHING_SELFTEST=y |
324 | CONFIG_FTR_FIXUP_SELFTEST=y | 331 | CONFIG_FTR_FIXUP_SELFTEST=y |
325 | CONFIG_MSI_BITMAP_SELFTEST=y | 332 | CONFIG_MSI_BITMAP_SELFTEST=y |
326 | CONFIG_XMON=y | 333 | CONFIG_XMON=y |
327 | CONFIG_XMON_DEFAULT=y | 334 | CONFIG_XMON_DEFAULT=y |
328 | CONFIG_CRYPTO_NULL=m | ||
329 | CONFIG_CRYPTO_TEST=m | 335 | CONFIG_CRYPTO_TEST=m |
330 | CONFIG_CRYPTO_PCBC=m | 336 | CONFIG_CRYPTO_PCBC=m |
331 | CONFIG_CRYPTO_HMAC=y | 337 | CONFIG_CRYPTO_HMAC=y |
@@ -347,4 +353,3 @@ CONFIG_CRYPTO_DEV_NX_ENCRYPT=m | |||
347 | CONFIG_VIRTUALIZATION=y | 353 | CONFIG_VIRTUALIZATION=y |
348 | CONFIG_KVM_BOOK3S_64=m | 354 | CONFIG_KVM_BOOK3S_64=m |
349 | CONFIG_KVM_BOOK3S_64_HV=y | 355 | CONFIG_KVM_BOOK3S_64_HV=y |
350 | CONFIG_VHOST_NET=m | ||
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild index 704e6f10ae80..d8f9d2f18a23 100644 --- a/arch/powerpc/include/asm/Kbuild +++ b/arch/powerpc/include/asm/Kbuild | |||
@@ -2,4 +2,5 @@ | |||
2 | generic-y += clkdev.h | 2 | generic-y += clkdev.h |
3 | generic-y += rwsem.h | 3 | generic-y += rwsem.h |
4 | generic-y += trace_clock.h | 4 | generic-y += trace_clock.h |
5 | generic-y += preempt.h | ||
5 | generic-y += vtime.h \ No newline at end of file | 6 | generic-y += vtime.h \ No newline at end of file |
diff --git a/arch/powerpc/include/asm/archrandom.h b/arch/powerpc/include/asm/archrandom.h new file mode 100644 index 000000000000..d853d163ba47 --- /dev/null +++ b/arch/powerpc/include/asm/archrandom.h | |||
@@ -0,0 +1,32 @@ | |||
1 | #ifndef _ASM_POWERPC_ARCHRANDOM_H | ||
2 | #define _ASM_POWERPC_ARCHRANDOM_H | ||
3 | |||
4 | #ifdef CONFIG_ARCH_RANDOM | ||
5 | |||
6 | #include <asm/machdep.h> | ||
7 | |||
8 | static inline int arch_get_random_long(unsigned long *v) | ||
9 | { | ||
10 | if (ppc_md.get_random_long) | ||
11 | return ppc_md.get_random_long(v); | ||
12 | |||
13 | return 0; | ||
14 | } | ||
15 | |||
16 | static inline int arch_get_random_int(unsigned int *v) | ||
17 | { | ||
18 | unsigned long val; | ||
19 | int rc; | ||
20 | |||
21 | rc = arch_get_random_long(&val); | ||
22 | if (rc) | ||
23 | *v = val; | ||
24 | |||
25 | return rc; | ||
26 | } | ||
27 | |||
28 | int powernv_get_random_long(unsigned long *v); | ||
29 | |||
30 | #endif /* CONFIG_ARCH_RANDOM */ | ||
31 | |||
32 | #endif /* _ASM_POWERPC_ARCHRANDOM_H */ | ||
diff --git a/arch/powerpc/include/asm/checksum.h b/arch/powerpc/include/asm/checksum.h index ce0c28495f9a..8251a3ba870f 100644 --- a/arch/powerpc/include/asm/checksum.h +++ b/arch/powerpc/include/asm/checksum.h | |||
@@ -14,6 +14,9 @@ | |||
14 | * which always checksum on 4 octet boundaries. ihl is the number | 14 | * which always checksum on 4 octet boundaries. ihl is the number |
15 | * of 32-bit words and is always >= 5. | 15 | * of 32-bit words and is always >= 5. |
16 | */ | 16 | */ |
17 | #ifdef CONFIG_GENERIC_CSUM | ||
18 | #include <asm-generic/checksum.h> | ||
19 | #else | ||
17 | extern __sum16 ip_fast_csum(const void *iph, unsigned int ihl); | 20 | extern __sum16 ip_fast_csum(const void *iph, unsigned int ihl); |
18 | 21 | ||
19 | /* | 22 | /* |
@@ -123,5 +126,7 @@ static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr, | |||
123 | return sum; | 126 | return sum; |
124 | #endif | 127 | #endif |
125 | } | 128 | } |
129 | |||
130 | #endif | ||
126 | #endif /* __KERNEL__ */ | 131 | #endif /* __KERNEL__ */ |
127 | #endif | 132 | #endif |
diff --git a/arch/powerpc/include/asm/disassemble.h b/arch/powerpc/include/asm/disassemble.h index 9b198d1b3b2b..856f8deb557a 100644 --- a/arch/powerpc/include/asm/disassemble.h +++ b/arch/powerpc/include/asm/disassemble.h | |||
@@ -77,4 +77,8 @@ static inline unsigned int get_d(u32 inst) | |||
77 | return inst & 0xffff; | 77 | return inst & 0xffff; |
78 | } | 78 | } |
79 | 79 | ||
80 | static inline unsigned int get_oc(u32 inst) | ||
81 | { | ||
82 | return (inst >> 11) & 0x7fff; | ||
83 | } | ||
80 | #endif /* __ASM_PPC_DISASSEMBLE_H__ */ | 84 | #endif /* __ASM_PPC_DISASSEMBLE_H__ */ |
diff --git a/arch/powerpc/include/asm/emulated_ops.h b/arch/powerpc/include/asm/emulated_ops.h index 5a8b82aa7241..4358e3002f35 100644 --- a/arch/powerpc/include/asm/emulated_ops.h +++ b/arch/powerpc/include/asm/emulated_ops.h | |||
@@ -43,6 +43,7 @@ extern struct ppc_emulated { | |||
43 | struct ppc_emulated_entry popcntb; | 43 | struct ppc_emulated_entry popcntb; |
44 | struct ppc_emulated_entry spe; | 44 | struct ppc_emulated_entry spe; |
45 | struct ppc_emulated_entry string; | 45 | struct ppc_emulated_entry string; |
46 | struct ppc_emulated_entry sync; | ||
46 | struct ppc_emulated_entry unaligned; | 47 | struct ppc_emulated_entry unaligned; |
47 | #ifdef CONFIG_MATH_EMULATION | 48 | #ifdef CONFIG_MATH_EMULATION |
48 | struct ppc_emulated_entry math; | 49 | struct ppc_emulated_entry math; |
diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h index cca12f084842..894662a5d4d5 100644 --- a/arch/powerpc/include/asm/exception-64s.h +++ b/arch/powerpc/include/asm/exception-64s.h | |||
@@ -198,12 +198,27 @@ END_FTR_SECTION_NESTED(ftr,ftr,943) | |||
198 | cmpwi r10,0; \ | 198 | cmpwi r10,0; \ |
199 | bne do_kvm_##n | 199 | bne do_kvm_##n |
200 | 200 | ||
201 | #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE | ||
202 | /* | ||
203 | * If hv is possible, interrupts come into to the hv version | ||
204 | * of the kvmppc_interrupt code, which then jumps to the PR handler, | ||
205 | * kvmppc_interrupt_pr, if the guest is a PR guest. | ||
206 | */ | ||
207 | #define kvmppc_interrupt kvmppc_interrupt_hv | ||
208 | #else | ||
209 | #define kvmppc_interrupt kvmppc_interrupt_pr | ||
210 | #endif | ||
211 | |||
201 | #define __KVM_HANDLER(area, h, n) \ | 212 | #define __KVM_HANDLER(area, h, n) \ |
202 | do_kvm_##n: \ | 213 | do_kvm_##n: \ |
203 | BEGIN_FTR_SECTION_NESTED(947) \ | 214 | BEGIN_FTR_SECTION_NESTED(947) \ |
204 | ld r10,area+EX_CFAR(r13); \ | 215 | ld r10,area+EX_CFAR(r13); \ |
205 | std r10,HSTATE_CFAR(r13); \ | 216 | std r10,HSTATE_CFAR(r13); \ |
206 | END_FTR_SECTION_NESTED(CPU_FTR_CFAR,CPU_FTR_CFAR,947); \ | 217 | END_FTR_SECTION_NESTED(CPU_FTR_CFAR,CPU_FTR_CFAR,947); \ |
218 | BEGIN_FTR_SECTION_NESTED(948) \ | ||
219 | ld r10,area+EX_PPR(r13); \ | ||
220 | std r10,HSTATE_PPR(r13); \ | ||
221 | END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,948); \ | ||
207 | ld r10,area+EX_R10(r13); \ | 222 | ld r10,area+EX_R10(r13); \ |
208 | stw r9,HSTATE_SCRATCH1(r13); \ | 223 | stw r9,HSTATE_SCRATCH1(r13); \ |
209 | ld r9,area+EX_R9(r13); \ | 224 | ld r9,area+EX_R9(r13); \ |
@@ -217,6 +232,10 @@ do_kvm_##n: \ | |||
217 | ld r10,area+EX_R10(r13); \ | 232 | ld r10,area+EX_R10(r13); \ |
218 | beq 89f; \ | 233 | beq 89f; \ |
219 | stw r9,HSTATE_SCRATCH1(r13); \ | 234 | stw r9,HSTATE_SCRATCH1(r13); \ |
235 | BEGIN_FTR_SECTION_NESTED(948) \ | ||
236 | ld r9,area+EX_PPR(r13); \ | ||
237 | std r9,HSTATE_PPR(r13); \ | ||
238 | END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,948); \ | ||
220 | ld r9,area+EX_R9(r13); \ | 239 | ld r9,area+EX_R9(r13); \ |
221 | std r12,HSTATE_SCRATCH0(r13); \ | 240 | std r12,HSTATE_SCRATCH0(r13); \ |
222 | li r12,n; \ | 241 | li r12,n; \ |
@@ -236,7 +255,7 @@ do_kvm_##n: \ | |||
236 | #define KVM_HANDLER_SKIP(area, h, n) | 255 | #define KVM_HANDLER_SKIP(area, h, n) |
237 | #endif | 256 | #endif |
238 | 257 | ||
239 | #ifdef CONFIG_KVM_BOOK3S_PR | 258 | #ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE |
240 | #define KVMTEST_PR(n) __KVMTEST(n) | 259 | #define KVMTEST_PR(n) __KVMTEST(n) |
241 | #define KVM_HANDLER_PR(area, h, n) __KVM_HANDLER(area, h, n) | 260 | #define KVM_HANDLER_PR(area, h, n) __KVM_HANDLER(area, h, n) |
242 | #define KVM_HANDLER_PR_SKIP(area, h, n) __KVM_HANDLER_SKIP(area, h, n) | 261 | #define KVM_HANDLER_PR_SKIP(area, h, n) __KVM_HANDLER_SKIP(area, h, n) |
diff --git a/arch/powerpc/include/asm/fsl_ifc.h b/arch/powerpc/include/asm/fsl_ifc.h index b8a4b9bc50b3..f49ddb1b2273 100644 --- a/arch/powerpc/include/asm/fsl_ifc.h +++ b/arch/powerpc/include/asm/fsl_ifc.h | |||
@@ -93,6 +93,7 @@ | |||
93 | #define CSOR_NAND_PGS_512 0x00000000 | 93 | #define CSOR_NAND_PGS_512 0x00000000 |
94 | #define CSOR_NAND_PGS_2K 0x00080000 | 94 | #define CSOR_NAND_PGS_2K 0x00080000 |
95 | #define CSOR_NAND_PGS_4K 0x00100000 | 95 | #define CSOR_NAND_PGS_4K 0x00100000 |
96 | #define CSOR_NAND_PGS_8K 0x00180000 | ||
96 | /* Spare region Size */ | 97 | /* Spare region Size */ |
97 | #define CSOR_NAND_SPRZ_MASK 0x0000E000 | 98 | #define CSOR_NAND_SPRZ_MASK 0x0000E000 |
98 | #define CSOR_NAND_SPRZ_SHIFT 13 | 99 | #define CSOR_NAND_SPRZ_SHIFT 13 |
@@ -102,6 +103,7 @@ | |||
102 | #define CSOR_NAND_SPRZ_210 0x00006000 | 103 | #define CSOR_NAND_SPRZ_210 0x00006000 |
103 | #define CSOR_NAND_SPRZ_218 0x00008000 | 104 | #define CSOR_NAND_SPRZ_218 0x00008000 |
104 | #define CSOR_NAND_SPRZ_224 0x0000A000 | 105 | #define CSOR_NAND_SPRZ_224 0x0000A000 |
106 | #define CSOR_NAND_SPRZ_CSOR_EXT 0x0000C000 | ||
105 | /* Pages Per Block */ | 107 | /* Pages Per Block */ |
106 | #define CSOR_NAND_PB_MASK 0x00000700 | 108 | #define CSOR_NAND_PB_MASK 0x00000700 |
107 | #define CSOR_NAND_PB_SHIFT 8 | 109 | #define CSOR_NAND_PB_SHIFT 8 |
diff --git a/arch/powerpc/include/asm/hvsi.h b/arch/powerpc/include/asm/hvsi.h index d3f64f361814..d4a5315718ca 100644 --- a/arch/powerpc/include/asm/hvsi.h +++ b/arch/powerpc/include/asm/hvsi.h | |||
@@ -25,7 +25,7 @@ | |||
25 | struct hvsi_header { | 25 | struct hvsi_header { |
26 | uint8_t type; | 26 | uint8_t type; |
27 | uint8_t len; | 27 | uint8_t len; |
28 | uint16_t seqno; | 28 | __be16 seqno; |
29 | } __attribute__((packed)); | 29 | } __attribute__((packed)); |
30 | 30 | ||
31 | struct hvsi_data { | 31 | struct hvsi_data { |
@@ -35,24 +35,24 @@ struct hvsi_data { | |||
35 | 35 | ||
36 | struct hvsi_control { | 36 | struct hvsi_control { |
37 | struct hvsi_header hdr; | 37 | struct hvsi_header hdr; |
38 | uint16_t verb; | 38 | __be16 verb; |
39 | /* optional depending on verb: */ | 39 | /* optional depending on verb: */ |
40 | uint32_t word; | 40 | __be32 word; |
41 | uint32_t mask; | 41 | __be32 mask; |
42 | } __attribute__((packed)); | 42 | } __attribute__((packed)); |
43 | 43 | ||
44 | struct hvsi_query { | 44 | struct hvsi_query { |
45 | struct hvsi_header hdr; | 45 | struct hvsi_header hdr; |
46 | uint16_t verb; | 46 | __be16 verb; |
47 | } __attribute__((packed)); | 47 | } __attribute__((packed)); |
48 | 48 | ||
49 | struct hvsi_query_response { | 49 | struct hvsi_query_response { |
50 | struct hvsi_header hdr; | 50 | struct hvsi_header hdr; |
51 | uint16_t verb; | 51 | __be16 verb; |
52 | uint16_t query_seqno; | 52 | __be16 query_seqno; |
53 | union { | 53 | union { |
54 | uint8_t version; | 54 | uint8_t version; |
55 | uint32_t mctrl_word; | 55 | __be32 mctrl_word; |
56 | } u; | 56 | } u; |
57 | } __attribute__((packed)); | 57 | } __attribute__((packed)); |
58 | 58 | ||
diff --git a/arch/powerpc/include/asm/io.h b/arch/powerpc/include/asm/io.h index 5a64757dc0d1..575fbf81fad0 100644 --- a/arch/powerpc/include/asm/io.h +++ b/arch/powerpc/include/asm/io.h | |||
@@ -21,7 +21,7 @@ extern struct pci_dev *isa_bridge_pcidev; | |||
21 | /* | 21 | /* |
22 | * has legacy ISA devices ? | 22 | * has legacy ISA devices ? |
23 | */ | 23 | */ |
24 | #define arch_has_dev_port() (isa_bridge_pcidev != NULL) | 24 | #define arch_has_dev_port() (isa_bridge_pcidev != NULL || isa_io_special) |
25 | #endif | 25 | #endif |
26 | 26 | ||
27 | #include <linux/device.h> | 27 | #include <linux/device.h> |
@@ -113,7 +113,7 @@ extern bool isa_io_special; | |||
113 | 113 | ||
114 | /* gcc 4.0 and older doesn't have 'Z' constraint */ | 114 | /* gcc 4.0 and older doesn't have 'Z' constraint */ |
115 | #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ == 0) | 115 | #if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ == 0) |
116 | #define DEF_MMIO_IN_LE(name, size, insn) \ | 116 | #define DEF_MMIO_IN_X(name, size, insn) \ |
117 | static inline u##size name(const volatile u##size __iomem *addr) \ | 117 | static inline u##size name(const volatile u##size __iomem *addr) \ |
118 | { \ | 118 | { \ |
119 | u##size ret; \ | 119 | u##size ret; \ |
@@ -122,7 +122,7 @@ static inline u##size name(const volatile u##size __iomem *addr) \ | |||
122 | return ret; \ | 122 | return ret; \ |
123 | } | 123 | } |
124 | 124 | ||
125 | #define DEF_MMIO_OUT_LE(name, size, insn) \ | 125 | #define DEF_MMIO_OUT_X(name, size, insn) \ |
126 | static inline void name(volatile u##size __iomem *addr, u##size val) \ | 126 | static inline void name(volatile u##size __iomem *addr, u##size val) \ |
127 | { \ | 127 | { \ |
128 | __asm__ __volatile__("sync;"#insn" %1,0,%2" \ | 128 | __asm__ __volatile__("sync;"#insn" %1,0,%2" \ |
@@ -130,7 +130,7 @@ static inline void name(volatile u##size __iomem *addr, u##size val) \ | |||
130 | IO_SET_SYNC_FLAG(); \ | 130 | IO_SET_SYNC_FLAG(); \ |
131 | } | 131 | } |
132 | #else /* newer gcc */ | 132 | #else /* newer gcc */ |
133 | #define DEF_MMIO_IN_LE(name, size, insn) \ | 133 | #define DEF_MMIO_IN_X(name, size, insn) \ |
134 | static inline u##size name(const volatile u##size __iomem *addr) \ | 134 | static inline u##size name(const volatile u##size __iomem *addr) \ |
135 | { \ | 135 | { \ |
136 | u##size ret; \ | 136 | u##size ret; \ |
@@ -139,7 +139,7 @@ static inline u##size name(const volatile u##size __iomem *addr) \ | |||
139 | return ret; \ | 139 | return ret; \ |
140 | } | 140 | } |
141 | 141 | ||
142 | #define DEF_MMIO_OUT_LE(name, size, insn) \ | 142 | #define DEF_MMIO_OUT_X(name, size, insn) \ |
143 | static inline void name(volatile u##size __iomem *addr, u##size val) \ | 143 | static inline void name(volatile u##size __iomem *addr, u##size val) \ |
144 | { \ | 144 | { \ |
145 | __asm__ __volatile__("sync;"#insn" %1,%y0" \ | 145 | __asm__ __volatile__("sync;"#insn" %1,%y0" \ |
@@ -148,7 +148,7 @@ static inline void name(volatile u##size __iomem *addr, u##size val) \ | |||
148 | } | 148 | } |
149 | #endif | 149 | #endif |
150 | 150 | ||
151 | #define DEF_MMIO_IN_BE(name, size, insn) \ | 151 | #define DEF_MMIO_IN_D(name, size, insn) \ |
152 | static inline u##size name(const volatile u##size __iomem *addr) \ | 152 | static inline u##size name(const volatile u##size __iomem *addr) \ |
153 | { \ | 153 | { \ |
154 | u##size ret; \ | 154 | u##size ret; \ |
@@ -157,7 +157,7 @@ static inline u##size name(const volatile u##size __iomem *addr) \ | |||
157 | return ret; \ | 157 | return ret; \ |
158 | } | 158 | } |
159 | 159 | ||
160 | #define DEF_MMIO_OUT_BE(name, size, insn) \ | 160 | #define DEF_MMIO_OUT_D(name, size, insn) \ |
161 | static inline void name(volatile u##size __iomem *addr, u##size val) \ | 161 | static inline void name(volatile u##size __iomem *addr, u##size val) \ |
162 | { \ | 162 | { \ |
163 | __asm__ __volatile__("sync;"#insn"%U0%X0 %1,%0" \ | 163 | __asm__ __volatile__("sync;"#insn"%U0%X0 %1,%0" \ |
@@ -165,22 +165,37 @@ static inline void name(volatile u##size __iomem *addr, u##size val) \ | |||
165 | IO_SET_SYNC_FLAG(); \ | 165 | IO_SET_SYNC_FLAG(); \ |
166 | } | 166 | } |
167 | 167 | ||
168 | DEF_MMIO_IN_D(in_8, 8, lbz); | ||
169 | DEF_MMIO_OUT_D(out_8, 8, stb); | ||
168 | 170 | ||
169 | DEF_MMIO_IN_BE(in_8, 8, lbz); | 171 | #ifdef __BIG_ENDIAN__ |
170 | DEF_MMIO_IN_BE(in_be16, 16, lhz); | 172 | DEF_MMIO_IN_D(in_be16, 16, lhz); |
171 | DEF_MMIO_IN_BE(in_be32, 32, lwz); | 173 | DEF_MMIO_IN_D(in_be32, 32, lwz); |
172 | DEF_MMIO_IN_LE(in_le16, 16, lhbrx); | 174 | DEF_MMIO_IN_X(in_le16, 16, lhbrx); |
173 | DEF_MMIO_IN_LE(in_le32, 32, lwbrx); | 175 | DEF_MMIO_IN_X(in_le32, 32, lwbrx); |
174 | 176 | ||
175 | DEF_MMIO_OUT_BE(out_8, 8, stb); | 177 | DEF_MMIO_OUT_D(out_be16, 16, sth); |
176 | DEF_MMIO_OUT_BE(out_be16, 16, sth); | 178 | DEF_MMIO_OUT_D(out_be32, 32, stw); |
177 | DEF_MMIO_OUT_BE(out_be32, 32, stw); | 179 | DEF_MMIO_OUT_X(out_le16, 16, sthbrx); |
178 | DEF_MMIO_OUT_LE(out_le16, 16, sthbrx); | 180 | DEF_MMIO_OUT_X(out_le32, 32, stwbrx); |
179 | DEF_MMIO_OUT_LE(out_le32, 32, stwbrx); | 181 | #else |
182 | DEF_MMIO_IN_X(in_be16, 16, lhbrx); | ||
183 | DEF_MMIO_IN_X(in_be32, 32, lwbrx); | ||
184 | DEF_MMIO_IN_D(in_le16, 16, lhz); | ||
185 | DEF_MMIO_IN_D(in_le32, 32, lwz); | ||
186 | |||
187 | DEF_MMIO_OUT_X(out_be16, 16, sthbrx); | ||
188 | DEF_MMIO_OUT_X(out_be32, 32, stwbrx); | ||
189 | DEF_MMIO_OUT_D(out_le16, 16, sth); | ||
190 | DEF_MMIO_OUT_D(out_le32, 32, stw); | ||
191 | |||
192 | #endif /* __BIG_ENDIAN */ | ||
180 | 193 | ||
181 | #ifdef __powerpc64__ | 194 | #ifdef __powerpc64__ |
182 | DEF_MMIO_OUT_BE(out_be64, 64, std); | 195 | |
183 | DEF_MMIO_IN_BE(in_be64, 64, ld); | 196 | #ifdef __BIG_ENDIAN__ |
197 | DEF_MMIO_OUT_D(out_be64, 64, std); | ||
198 | DEF_MMIO_IN_D(in_be64, 64, ld); | ||
184 | 199 | ||
185 | /* There is no asm instructions for 64 bits reverse loads and stores */ | 200 | /* There is no asm instructions for 64 bits reverse loads and stores */ |
186 | static inline u64 in_le64(const volatile u64 __iomem *addr) | 201 | static inline u64 in_le64(const volatile u64 __iomem *addr) |
@@ -192,6 +207,22 @@ static inline void out_le64(volatile u64 __iomem *addr, u64 val) | |||
192 | { | 207 | { |
193 | out_be64(addr, swab64(val)); | 208 | out_be64(addr, swab64(val)); |
194 | } | 209 | } |
210 | #else | ||
211 | DEF_MMIO_OUT_D(out_le64, 64, std); | ||
212 | DEF_MMIO_IN_D(in_le64, 64, ld); | ||
213 | |||
214 | /* There is no asm instructions for 64 bits reverse loads and stores */ | ||
215 | static inline u64 in_be64(const volatile u64 __iomem *addr) | ||
216 | { | ||
217 | return swab64(in_le64(addr)); | ||
218 | } | ||
219 | |||
220 | static inline void out_be64(volatile u64 __iomem *addr, u64 val) | ||
221 | { | ||
222 | out_le64(addr, swab64(val)); | ||
223 | } | ||
224 | |||
225 | #endif | ||
195 | #endif /* __powerpc64__ */ | 226 | #endif /* __powerpc64__ */ |
196 | 227 | ||
197 | /* | 228 | /* |
diff --git a/arch/powerpc/include/asm/irq.h b/arch/powerpc/include/asm/irq.h index 0e40843a1c6e..41f13cec8a8f 100644 --- a/arch/powerpc/include/asm/irq.h +++ b/arch/powerpc/include/asm/irq.h | |||
@@ -69,9 +69,9 @@ extern struct thread_info *softirq_ctx[NR_CPUS]; | |||
69 | 69 | ||
70 | extern void irq_ctx_init(void); | 70 | extern void irq_ctx_init(void); |
71 | extern void call_do_softirq(struct thread_info *tp); | 71 | extern void call_do_softirq(struct thread_info *tp); |
72 | extern int call_handle_irq(int irq, void *p1, | 72 | extern void call_do_irq(struct pt_regs *regs, struct thread_info *tp); |
73 | struct thread_info *tp, void *func); | ||
74 | extern void do_IRQ(struct pt_regs *regs); | 73 | extern void do_IRQ(struct pt_regs *regs); |
74 | extern void __do_irq(struct pt_regs *regs); | ||
75 | 75 | ||
76 | int irq_choose_cpu(const struct cpumask *mask); | 76 | int irq_choose_cpu(const struct cpumask *mask); |
77 | 77 | ||
diff --git a/arch/powerpc/include/asm/jump_label.h b/arch/powerpc/include/asm/jump_label.h index ae098c438f00..f016bb699b5f 100644 --- a/arch/powerpc/include/asm/jump_label.h +++ b/arch/powerpc/include/asm/jump_label.h | |||
@@ -19,7 +19,7 @@ | |||
19 | 19 | ||
20 | static __always_inline bool arch_static_branch(struct static_key *key) | 20 | static __always_inline bool arch_static_branch(struct static_key *key) |
21 | { | 21 | { |
22 | asm goto("1:\n\t" | 22 | asm_volatile_goto("1:\n\t" |
23 | "nop\n\t" | 23 | "nop\n\t" |
24 | ".pushsection __jump_table, \"aw\"\n\t" | 24 | ".pushsection __jump_table, \"aw\"\n\t" |
25 | JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t" | 25 | JUMP_ENTRY_TYPE "1b, %l[l_yes], %c0\n\t" |
diff --git a/arch/powerpc/include/asm/kvm_asm.h b/arch/powerpc/include/asm/kvm_asm.h index 851bac7afa4b..1bd92fd43cfb 100644 --- a/arch/powerpc/include/asm/kvm_asm.h +++ b/arch/powerpc/include/asm/kvm_asm.h | |||
@@ -123,6 +123,8 @@ | |||
123 | #define BOOK3S_HFLAG_SLB 0x2 | 123 | #define BOOK3S_HFLAG_SLB 0x2 |
124 | #define BOOK3S_HFLAG_PAIRED_SINGLE 0x4 | 124 | #define BOOK3S_HFLAG_PAIRED_SINGLE 0x4 |
125 | #define BOOK3S_HFLAG_NATIVE_PS 0x8 | 125 | #define BOOK3S_HFLAG_NATIVE_PS 0x8 |
126 | #define BOOK3S_HFLAG_MULTI_PGSIZE 0x10 | ||
127 | #define BOOK3S_HFLAG_NEW_TLBIE 0x20 | ||
126 | 128 | ||
127 | #define RESUME_FLAG_NV (1<<0) /* Reload guest nonvolatile state? */ | 129 | #define RESUME_FLAG_NV (1<<0) /* Reload guest nonvolatile state? */ |
128 | #define RESUME_FLAG_HOST (1<<1) /* Resume host? */ | 130 | #define RESUME_FLAG_HOST (1<<1) /* Resume host? */ |
@@ -136,6 +138,8 @@ | |||
136 | #define KVM_GUEST_MODE_NONE 0 | 138 | #define KVM_GUEST_MODE_NONE 0 |
137 | #define KVM_GUEST_MODE_GUEST 1 | 139 | #define KVM_GUEST_MODE_GUEST 1 |
138 | #define KVM_GUEST_MODE_SKIP 2 | 140 | #define KVM_GUEST_MODE_SKIP 2 |
141 | #define KVM_GUEST_MODE_GUEST_HV 3 | ||
142 | #define KVM_GUEST_MODE_HOST_HV 4 | ||
139 | 143 | ||
140 | #define KVM_INST_FETCH_FAILED -1 | 144 | #define KVM_INST_FETCH_FAILED -1 |
141 | 145 | ||
diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h index fa19e2f1a874..4a594b76674d 100644 --- a/arch/powerpc/include/asm/kvm_book3s.h +++ b/arch/powerpc/include/asm/kvm_book3s.h | |||
@@ -58,16 +58,18 @@ struct hpte_cache { | |||
58 | struct hlist_node list_pte_long; | 58 | struct hlist_node list_pte_long; |
59 | struct hlist_node list_vpte; | 59 | struct hlist_node list_vpte; |
60 | struct hlist_node list_vpte_long; | 60 | struct hlist_node list_vpte_long; |
61 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
62 | struct hlist_node list_vpte_64k; | ||
63 | #endif | ||
61 | struct rcu_head rcu_head; | 64 | struct rcu_head rcu_head; |
62 | u64 host_vpn; | 65 | u64 host_vpn; |
63 | u64 pfn; | 66 | u64 pfn; |
64 | ulong slot; | 67 | ulong slot; |
65 | struct kvmppc_pte pte; | 68 | struct kvmppc_pte pte; |
69 | int pagesize; | ||
66 | }; | 70 | }; |
67 | 71 | ||
68 | struct kvmppc_vcpu_book3s { | 72 | struct kvmppc_vcpu_book3s { |
69 | struct kvm_vcpu vcpu; | ||
70 | struct kvmppc_book3s_shadow_vcpu *shadow_vcpu; | ||
71 | struct kvmppc_sid_map sid_map[SID_MAP_NUM]; | 73 | struct kvmppc_sid_map sid_map[SID_MAP_NUM]; |
72 | struct { | 74 | struct { |
73 | u64 esid; | 75 | u64 esid; |
@@ -99,6 +101,9 @@ struct kvmppc_vcpu_book3s { | |||
99 | struct hlist_head hpte_hash_pte_long[HPTEG_HASH_NUM_PTE_LONG]; | 101 | struct hlist_head hpte_hash_pte_long[HPTEG_HASH_NUM_PTE_LONG]; |
100 | struct hlist_head hpte_hash_vpte[HPTEG_HASH_NUM_VPTE]; | 102 | struct hlist_head hpte_hash_vpte[HPTEG_HASH_NUM_VPTE]; |
101 | struct hlist_head hpte_hash_vpte_long[HPTEG_HASH_NUM_VPTE_LONG]; | 103 | struct hlist_head hpte_hash_vpte_long[HPTEG_HASH_NUM_VPTE_LONG]; |
104 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
105 | struct hlist_head hpte_hash_vpte_64k[HPTEG_HASH_NUM_VPTE_64K]; | ||
106 | #endif | ||
102 | int hpte_cache_count; | 107 | int hpte_cache_count; |
103 | spinlock_t mmu_lock; | 108 | spinlock_t mmu_lock; |
104 | }; | 109 | }; |
@@ -107,8 +112,9 @@ struct kvmppc_vcpu_book3s { | |||
107 | #define CONTEXT_GUEST 1 | 112 | #define CONTEXT_GUEST 1 |
108 | #define CONTEXT_GUEST_END 2 | 113 | #define CONTEXT_GUEST_END 2 |
109 | 114 | ||
110 | #define VSID_REAL 0x0fffffffffc00000ULL | 115 | #define VSID_REAL 0x07ffffffffc00000ULL |
111 | #define VSID_BAT 0x0fffffffffb00000ULL | 116 | #define VSID_BAT 0x07ffffffffb00000ULL |
117 | #define VSID_64K 0x0800000000000000ULL | ||
112 | #define VSID_1T 0x1000000000000000ULL | 118 | #define VSID_1T 0x1000000000000000ULL |
113 | #define VSID_REAL_DR 0x2000000000000000ULL | 119 | #define VSID_REAL_DR 0x2000000000000000ULL |
114 | #define VSID_REAL_IR 0x4000000000000000ULL | 120 | #define VSID_REAL_IR 0x4000000000000000ULL |
@@ -118,11 +124,12 @@ extern void kvmppc_mmu_pte_flush(struct kvm_vcpu *vcpu, ulong ea, ulong ea_mask) | |||
118 | extern void kvmppc_mmu_pte_vflush(struct kvm_vcpu *vcpu, u64 vp, u64 vp_mask); | 124 | extern void kvmppc_mmu_pte_vflush(struct kvm_vcpu *vcpu, u64 vp, u64 vp_mask); |
119 | extern void kvmppc_mmu_pte_pflush(struct kvm_vcpu *vcpu, ulong pa_start, ulong pa_end); | 125 | extern void kvmppc_mmu_pte_pflush(struct kvm_vcpu *vcpu, ulong pa_start, ulong pa_end); |
120 | extern void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 new_msr); | 126 | extern void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 new_msr); |
121 | extern void kvmppc_set_pvr(struct kvm_vcpu *vcpu, u32 pvr); | ||
122 | extern void kvmppc_mmu_book3s_64_init(struct kvm_vcpu *vcpu); | 127 | extern void kvmppc_mmu_book3s_64_init(struct kvm_vcpu *vcpu); |
123 | extern void kvmppc_mmu_book3s_32_init(struct kvm_vcpu *vcpu); | 128 | extern void kvmppc_mmu_book3s_32_init(struct kvm_vcpu *vcpu); |
124 | extern void kvmppc_mmu_book3s_hv_init(struct kvm_vcpu *vcpu); | 129 | extern void kvmppc_mmu_book3s_hv_init(struct kvm_vcpu *vcpu); |
125 | extern int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte); | 130 | extern int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte, |
131 | bool iswrite); | ||
132 | extern void kvmppc_mmu_unmap_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte); | ||
126 | extern int kvmppc_mmu_map_segment(struct kvm_vcpu *vcpu, ulong eaddr); | 133 | extern int kvmppc_mmu_map_segment(struct kvm_vcpu *vcpu, ulong eaddr); |
127 | extern void kvmppc_mmu_flush_segment(struct kvm_vcpu *vcpu, ulong eaddr, ulong seg_size); | 134 | extern void kvmppc_mmu_flush_segment(struct kvm_vcpu *vcpu, ulong eaddr, ulong seg_size); |
128 | extern void kvmppc_mmu_flush_segments(struct kvm_vcpu *vcpu); | 135 | extern void kvmppc_mmu_flush_segments(struct kvm_vcpu *vcpu); |
@@ -134,6 +141,7 @@ extern long kvmppc_hv_find_lock_hpte(struct kvm *kvm, gva_t eaddr, | |||
134 | 141 | ||
135 | extern void kvmppc_mmu_hpte_cache_map(struct kvm_vcpu *vcpu, struct hpte_cache *pte); | 142 | extern void kvmppc_mmu_hpte_cache_map(struct kvm_vcpu *vcpu, struct hpte_cache *pte); |
136 | extern struct hpte_cache *kvmppc_mmu_hpte_cache_next(struct kvm_vcpu *vcpu); | 143 | extern struct hpte_cache *kvmppc_mmu_hpte_cache_next(struct kvm_vcpu *vcpu); |
144 | extern void kvmppc_mmu_hpte_cache_free(struct hpte_cache *pte); | ||
137 | extern void kvmppc_mmu_hpte_destroy(struct kvm_vcpu *vcpu); | 145 | extern void kvmppc_mmu_hpte_destroy(struct kvm_vcpu *vcpu); |
138 | extern int kvmppc_mmu_hpte_init(struct kvm_vcpu *vcpu); | 146 | extern int kvmppc_mmu_hpte_init(struct kvm_vcpu *vcpu); |
139 | extern void kvmppc_mmu_invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte); | 147 | extern void kvmppc_mmu_invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte); |
@@ -151,7 +159,8 @@ extern void kvmppc_set_bat(struct kvm_vcpu *vcpu, struct kvmppc_bat *bat, | |||
151 | bool upper, u32 val); | 159 | bool upper, u32 val); |
152 | extern void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr); | 160 | extern void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr); |
153 | extern int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu); | 161 | extern int kvmppc_emulate_paired_single(struct kvm_run *run, struct kvm_vcpu *vcpu); |
154 | extern pfn_t kvmppc_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn); | 162 | extern pfn_t kvmppc_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn, bool writing, |
163 | bool *writable); | ||
155 | extern void kvmppc_add_revmap_chain(struct kvm *kvm, struct revmap_entry *rev, | 164 | extern void kvmppc_add_revmap_chain(struct kvm *kvm, struct revmap_entry *rev, |
156 | unsigned long *rmap, long pte_index, int realmode); | 165 | unsigned long *rmap, long pte_index, int realmode); |
157 | extern void kvmppc_invalidate_hpte(struct kvm *kvm, unsigned long *hptep, | 166 | extern void kvmppc_invalidate_hpte(struct kvm *kvm, unsigned long *hptep, |
@@ -172,6 +181,8 @@ extern long kvmppc_do_h_remove(struct kvm *kvm, unsigned long flags, | |||
172 | unsigned long *hpret); | 181 | unsigned long *hpret); |
173 | extern long kvmppc_hv_get_dirty_log(struct kvm *kvm, | 182 | extern long kvmppc_hv_get_dirty_log(struct kvm *kvm, |
174 | struct kvm_memory_slot *memslot, unsigned long *map); | 183 | struct kvm_memory_slot *memslot, unsigned long *map); |
184 | extern void kvmppc_update_lpcr(struct kvm *kvm, unsigned long lpcr, | ||
185 | unsigned long mask); | ||
175 | 186 | ||
176 | extern void kvmppc_entry_trampoline(void); | 187 | extern void kvmppc_entry_trampoline(void); |
177 | extern void kvmppc_hv_entry_trampoline(void); | 188 | extern void kvmppc_hv_entry_trampoline(void); |
@@ -184,11 +195,9 @@ extern int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd); | |||
184 | 195 | ||
185 | static inline struct kvmppc_vcpu_book3s *to_book3s(struct kvm_vcpu *vcpu) | 196 | static inline struct kvmppc_vcpu_book3s *to_book3s(struct kvm_vcpu *vcpu) |
186 | { | 197 | { |
187 | return container_of(vcpu, struct kvmppc_vcpu_book3s, vcpu); | 198 | return vcpu->arch.book3s; |
188 | } | 199 | } |
189 | 200 | ||
190 | extern void kvm_return_point(void); | ||
191 | |||
192 | /* Also add subarch specific defines */ | 201 | /* Also add subarch specific defines */ |
193 | 202 | ||
194 | #ifdef CONFIG_KVM_BOOK3S_32_HANDLER | 203 | #ifdef CONFIG_KVM_BOOK3S_32_HANDLER |
@@ -198,203 +207,6 @@ extern void kvm_return_point(void); | |||
198 | #include <asm/kvm_book3s_64.h> | 207 | #include <asm/kvm_book3s_64.h> |
199 | #endif | 208 | #endif |
200 | 209 | ||
201 | #ifdef CONFIG_KVM_BOOK3S_PR | ||
202 | |||
203 | static inline unsigned long kvmppc_interrupt_offset(struct kvm_vcpu *vcpu) | ||
204 | { | ||
205 | return to_book3s(vcpu)->hior; | ||
206 | } | ||
207 | |||
208 | static inline void kvmppc_update_int_pending(struct kvm_vcpu *vcpu, | ||
209 | unsigned long pending_now, unsigned long old_pending) | ||
210 | { | ||
211 | if (pending_now) | ||
212 | vcpu->arch.shared->int_pending = 1; | ||
213 | else if (old_pending) | ||
214 | vcpu->arch.shared->int_pending = 0; | ||
215 | } | ||
216 | |||
217 | static inline void kvmppc_set_gpr(struct kvm_vcpu *vcpu, int num, ulong val) | ||
218 | { | ||
219 | if ( num < 14 ) { | ||
220 | struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu); | ||
221 | svcpu->gpr[num] = val; | ||
222 | svcpu_put(svcpu); | ||
223 | to_book3s(vcpu)->shadow_vcpu->gpr[num] = val; | ||
224 | } else | ||
225 | vcpu->arch.gpr[num] = val; | ||
226 | } | ||
227 | |||
228 | static inline ulong kvmppc_get_gpr(struct kvm_vcpu *vcpu, int num) | ||
229 | { | ||
230 | if ( num < 14 ) { | ||
231 | struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu); | ||
232 | ulong r = svcpu->gpr[num]; | ||
233 | svcpu_put(svcpu); | ||
234 | return r; | ||
235 | } else | ||
236 | return vcpu->arch.gpr[num]; | ||
237 | } | ||
238 | |||
239 | static inline void kvmppc_set_cr(struct kvm_vcpu *vcpu, u32 val) | ||
240 | { | ||
241 | struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu); | ||
242 | svcpu->cr = val; | ||
243 | svcpu_put(svcpu); | ||
244 | to_book3s(vcpu)->shadow_vcpu->cr = val; | ||
245 | } | ||
246 | |||
247 | static inline u32 kvmppc_get_cr(struct kvm_vcpu *vcpu) | ||
248 | { | ||
249 | struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu); | ||
250 | u32 r; | ||
251 | r = svcpu->cr; | ||
252 | svcpu_put(svcpu); | ||
253 | return r; | ||
254 | } | ||
255 | |||
256 | static inline void kvmppc_set_xer(struct kvm_vcpu *vcpu, u32 val) | ||
257 | { | ||
258 | struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu); | ||
259 | svcpu->xer = val; | ||
260 | to_book3s(vcpu)->shadow_vcpu->xer = val; | ||
261 | svcpu_put(svcpu); | ||
262 | } | ||
263 | |||
264 | static inline u32 kvmppc_get_xer(struct kvm_vcpu *vcpu) | ||
265 | { | ||
266 | struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu); | ||
267 | u32 r; | ||
268 | r = svcpu->xer; | ||
269 | svcpu_put(svcpu); | ||
270 | return r; | ||
271 | } | ||
272 | |||
273 | static inline void kvmppc_set_ctr(struct kvm_vcpu *vcpu, ulong val) | ||
274 | { | ||
275 | struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu); | ||
276 | svcpu->ctr = val; | ||
277 | svcpu_put(svcpu); | ||
278 | } | ||
279 | |||
280 | static inline ulong kvmppc_get_ctr(struct kvm_vcpu *vcpu) | ||
281 | { | ||
282 | struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu); | ||
283 | ulong r; | ||
284 | r = svcpu->ctr; | ||
285 | svcpu_put(svcpu); | ||
286 | return r; | ||
287 | } | ||
288 | |||
289 | static inline void kvmppc_set_lr(struct kvm_vcpu *vcpu, ulong val) | ||
290 | { | ||
291 | struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu); | ||
292 | svcpu->lr = val; | ||
293 | svcpu_put(svcpu); | ||
294 | } | ||
295 | |||
296 | static inline ulong kvmppc_get_lr(struct kvm_vcpu *vcpu) | ||
297 | { | ||
298 | struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu); | ||
299 | ulong r; | ||
300 | r = svcpu->lr; | ||
301 | svcpu_put(svcpu); | ||
302 | return r; | ||
303 | } | ||
304 | |||
305 | static inline void kvmppc_set_pc(struct kvm_vcpu *vcpu, ulong val) | ||
306 | { | ||
307 | struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu); | ||
308 | svcpu->pc = val; | ||
309 | svcpu_put(svcpu); | ||
310 | } | ||
311 | |||
312 | static inline ulong kvmppc_get_pc(struct kvm_vcpu *vcpu) | ||
313 | { | ||
314 | struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu); | ||
315 | ulong r; | ||
316 | r = svcpu->pc; | ||
317 | svcpu_put(svcpu); | ||
318 | return r; | ||
319 | } | ||
320 | |||
321 | static inline u32 kvmppc_get_last_inst(struct kvm_vcpu *vcpu) | ||
322 | { | ||
323 | ulong pc = kvmppc_get_pc(vcpu); | ||
324 | struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu); | ||
325 | u32 r; | ||
326 | |||
327 | /* Load the instruction manually if it failed to do so in the | ||
328 | * exit path */ | ||
329 | if (svcpu->last_inst == KVM_INST_FETCH_FAILED) | ||
330 | kvmppc_ld(vcpu, &pc, sizeof(u32), &svcpu->last_inst, false); | ||
331 | |||
332 | r = svcpu->last_inst; | ||
333 | svcpu_put(svcpu); | ||
334 | return r; | ||
335 | } | ||
336 | |||
337 | /* | ||
338 | * Like kvmppc_get_last_inst(), but for fetching a sc instruction. | ||
339 | * Because the sc instruction sets SRR0 to point to the following | ||
340 | * instruction, we have to fetch from pc - 4. | ||
341 | */ | ||
342 | static inline u32 kvmppc_get_last_sc(struct kvm_vcpu *vcpu) | ||
343 | { | ||
344 | ulong pc = kvmppc_get_pc(vcpu) - 4; | ||
345 | struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu); | ||
346 | u32 r; | ||
347 | |||
348 | /* Load the instruction manually if it failed to do so in the | ||
349 | * exit path */ | ||
350 | if (svcpu->last_inst == KVM_INST_FETCH_FAILED) | ||
351 | kvmppc_ld(vcpu, &pc, sizeof(u32), &svcpu->last_inst, false); | ||
352 | |||
353 | r = svcpu->last_inst; | ||
354 | svcpu_put(svcpu); | ||
355 | return r; | ||
356 | } | ||
357 | |||
358 | static inline ulong kvmppc_get_fault_dar(struct kvm_vcpu *vcpu) | ||
359 | { | ||
360 | struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu); | ||
361 | ulong r; | ||
362 | r = svcpu->fault_dar; | ||
363 | svcpu_put(svcpu); | ||
364 | return r; | ||
365 | } | ||
366 | |||
367 | static inline bool kvmppc_critical_section(struct kvm_vcpu *vcpu) | ||
368 | { | ||
369 | ulong crit_raw = vcpu->arch.shared->critical; | ||
370 | ulong crit_r1 = kvmppc_get_gpr(vcpu, 1); | ||
371 | bool crit; | ||
372 | |||
373 | /* Truncate crit indicators in 32 bit mode */ | ||
374 | if (!(vcpu->arch.shared->msr & MSR_SF)) { | ||
375 | crit_raw &= 0xffffffff; | ||
376 | crit_r1 &= 0xffffffff; | ||
377 | } | ||
378 | |||
379 | /* Critical section when crit == r1 */ | ||
380 | crit = (crit_raw == crit_r1); | ||
381 | /* ... and we're in supervisor mode */ | ||
382 | crit = crit && !(vcpu->arch.shared->msr & MSR_PR); | ||
383 | |||
384 | return crit; | ||
385 | } | ||
386 | #else /* CONFIG_KVM_BOOK3S_PR */ | ||
387 | |||
388 | static inline unsigned long kvmppc_interrupt_offset(struct kvm_vcpu *vcpu) | ||
389 | { | ||
390 | return 0; | ||
391 | } | ||
392 | |||
393 | static inline void kvmppc_update_int_pending(struct kvm_vcpu *vcpu, | ||
394 | unsigned long pending_now, unsigned long old_pending) | ||
395 | { | ||
396 | } | ||
397 | |||
398 | static inline void kvmppc_set_gpr(struct kvm_vcpu *vcpu, int num, ulong val) | 210 | static inline void kvmppc_set_gpr(struct kvm_vcpu *vcpu, int num, ulong val) |
399 | { | 211 | { |
400 | vcpu->arch.gpr[num] = val; | 212 | vcpu->arch.gpr[num] = val; |
@@ -489,12 +301,6 @@ static inline ulong kvmppc_get_fault_dar(struct kvm_vcpu *vcpu) | |||
489 | return vcpu->arch.fault_dar; | 301 | return vcpu->arch.fault_dar; |
490 | } | 302 | } |
491 | 303 | ||
492 | static inline bool kvmppc_critical_section(struct kvm_vcpu *vcpu) | ||
493 | { | ||
494 | return false; | ||
495 | } | ||
496 | #endif | ||
497 | |||
498 | /* Magic register values loaded into r3 and r4 before the 'sc' assembly | 304 | /* Magic register values loaded into r3 and r4 before the 'sc' assembly |
499 | * instruction for the OSI hypercalls */ | 305 | * instruction for the OSI hypercalls */ |
500 | #define OSI_SC_MAGIC_R3 0x113724FA | 306 | #define OSI_SC_MAGIC_R3 0x113724FA |
diff --git a/arch/powerpc/include/asm/kvm_book3s_32.h b/arch/powerpc/include/asm/kvm_book3s_32.h index ce0ef6ce8f86..c720e0b3238d 100644 --- a/arch/powerpc/include/asm/kvm_book3s_32.h +++ b/arch/powerpc/include/asm/kvm_book3s_32.h | |||
@@ -22,7 +22,7 @@ | |||
22 | 22 | ||
23 | static inline struct kvmppc_book3s_shadow_vcpu *svcpu_get(struct kvm_vcpu *vcpu) | 23 | static inline struct kvmppc_book3s_shadow_vcpu *svcpu_get(struct kvm_vcpu *vcpu) |
24 | { | 24 | { |
25 | return to_book3s(vcpu)->shadow_vcpu; | 25 | return vcpu->arch.shadow_vcpu; |
26 | } | 26 | } |
27 | 27 | ||
28 | static inline void svcpu_put(struct kvmppc_book3s_shadow_vcpu *svcpu) | 28 | static inline void svcpu_put(struct kvmppc_book3s_shadow_vcpu *svcpu) |
diff --git a/arch/powerpc/include/asm/kvm_book3s_64.h b/arch/powerpc/include/asm/kvm_book3s_64.h index 86d638a3b359..bf0fa8b0a883 100644 --- a/arch/powerpc/include/asm/kvm_book3s_64.h +++ b/arch/powerpc/include/asm/kvm_book3s_64.h | |||
@@ -20,7 +20,7 @@ | |||
20 | #ifndef __ASM_KVM_BOOK3S_64_H__ | 20 | #ifndef __ASM_KVM_BOOK3S_64_H__ |
21 | #define __ASM_KVM_BOOK3S_64_H__ | 21 | #define __ASM_KVM_BOOK3S_64_H__ |
22 | 22 | ||
23 | #ifdef CONFIG_KVM_BOOK3S_PR | 23 | #ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE |
24 | static inline struct kvmppc_book3s_shadow_vcpu *svcpu_get(struct kvm_vcpu *vcpu) | 24 | static inline struct kvmppc_book3s_shadow_vcpu *svcpu_get(struct kvm_vcpu *vcpu) |
25 | { | 25 | { |
26 | preempt_disable(); | 26 | preempt_disable(); |
@@ -35,7 +35,7 @@ static inline void svcpu_put(struct kvmppc_book3s_shadow_vcpu *svcpu) | |||
35 | 35 | ||
36 | #define SPAPR_TCE_SHIFT 12 | 36 | #define SPAPR_TCE_SHIFT 12 |
37 | 37 | ||
38 | #ifdef CONFIG_KVM_BOOK3S_64_HV | 38 | #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE |
39 | #define KVM_DEFAULT_HPT_ORDER 24 /* 16MB HPT by default */ | 39 | #define KVM_DEFAULT_HPT_ORDER 24 /* 16MB HPT by default */ |
40 | extern unsigned long kvm_rma_pages; | 40 | extern unsigned long kvm_rma_pages; |
41 | #endif | 41 | #endif |
@@ -278,7 +278,7 @@ static inline int is_vrma_hpte(unsigned long hpte_v) | |||
278 | (HPTE_V_1TB_SEG | (VRMA_VSID << (40 - 16))); | 278 | (HPTE_V_1TB_SEG | (VRMA_VSID << (40 - 16))); |
279 | } | 279 | } |
280 | 280 | ||
281 | #ifdef CONFIG_KVM_BOOK3S_64_HV | 281 | #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE |
282 | /* | 282 | /* |
283 | * Note modification of an HPTE; set the HPTE modified bit | 283 | * Note modification of an HPTE; set the HPTE modified bit |
284 | * if anyone is interested. | 284 | * if anyone is interested. |
@@ -289,6 +289,6 @@ static inline void note_hpte_modification(struct kvm *kvm, | |||
289 | if (atomic_read(&kvm->arch.hpte_mod_interest)) | 289 | if (atomic_read(&kvm->arch.hpte_mod_interest)) |
290 | rev->guest_rpte |= HPTE_GR_MODIFIED; | 290 | rev->guest_rpte |= HPTE_GR_MODIFIED; |
291 | } | 291 | } |
292 | #endif /* CONFIG_KVM_BOOK3S_64_HV */ | 292 | #endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */ |
293 | 293 | ||
294 | #endif /* __ASM_KVM_BOOK3S_64_H__ */ | 294 | #endif /* __ASM_KVM_BOOK3S_64_H__ */ |
diff --git a/arch/powerpc/include/asm/kvm_book3s_asm.h b/arch/powerpc/include/asm/kvm_book3s_asm.h index 9039d3c97eec..0bd9348a4db9 100644 --- a/arch/powerpc/include/asm/kvm_book3s_asm.h +++ b/arch/powerpc/include/asm/kvm_book3s_asm.h | |||
@@ -83,7 +83,7 @@ struct kvmppc_host_state { | |||
83 | u8 restore_hid5; | 83 | u8 restore_hid5; |
84 | u8 napping; | 84 | u8 napping; |
85 | 85 | ||
86 | #ifdef CONFIG_KVM_BOOK3S_64_HV | 86 | #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE |
87 | u8 hwthread_req; | 87 | u8 hwthread_req; |
88 | u8 hwthread_state; | 88 | u8 hwthread_state; |
89 | u8 host_ipi; | 89 | u8 host_ipi; |
@@ -101,6 +101,7 @@ struct kvmppc_host_state { | |||
101 | #endif | 101 | #endif |
102 | #ifdef CONFIG_PPC_BOOK3S_64 | 102 | #ifdef CONFIG_PPC_BOOK3S_64 |
103 | u64 cfar; | 103 | u64 cfar; |
104 | u64 ppr; | ||
104 | #endif | 105 | #endif |
105 | }; | 106 | }; |
106 | 107 | ||
@@ -108,14 +109,14 @@ struct kvmppc_book3s_shadow_vcpu { | |||
108 | ulong gpr[14]; | 109 | ulong gpr[14]; |
109 | u32 cr; | 110 | u32 cr; |
110 | u32 xer; | 111 | u32 xer; |
111 | |||
112 | u32 fault_dsisr; | ||
113 | u32 last_inst; | ||
114 | ulong ctr; | 112 | ulong ctr; |
115 | ulong lr; | 113 | ulong lr; |
116 | ulong pc; | 114 | ulong pc; |
115 | |||
117 | ulong shadow_srr1; | 116 | ulong shadow_srr1; |
118 | ulong fault_dar; | 117 | ulong fault_dar; |
118 | u32 fault_dsisr; | ||
119 | u32 last_inst; | ||
119 | 120 | ||
120 | #ifdef CONFIG_PPC_BOOK3S_32 | 121 | #ifdef CONFIG_PPC_BOOK3S_32 |
121 | u32 sr[16]; /* Guest SRs */ | 122 | u32 sr[16]; /* Guest SRs */ |
diff --git a/arch/powerpc/include/asm/kvm_booke.h b/arch/powerpc/include/asm/kvm_booke.h index d3c1eb34c986..dd8f61510dfd 100644 --- a/arch/powerpc/include/asm/kvm_booke.h +++ b/arch/powerpc/include/asm/kvm_booke.h | |||
@@ -26,7 +26,12 @@ | |||
26 | /* LPIDs we support with this build -- runtime limit may be lower */ | 26 | /* LPIDs we support with this build -- runtime limit may be lower */ |
27 | #define KVMPPC_NR_LPIDS 64 | 27 | #define KVMPPC_NR_LPIDS 64 |
28 | 28 | ||
29 | #define KVMPPC_INST_EHPRIV 0x7c00021c | 29 | #define KVMPPC_INST_EHPRIV 0x7c00021c |
30 | #define EHPRIV_OC_SHIFT 11 | ||
31 | /* "ehpriv 1" : ehpriv with OC = 1 is used for debug emulation */ | ||
32 | #define EHPRIV_OC_DEBUG 1 | ||
33 | #define KVMPPC_INST_EHPRIV_DEBUG (KVMPPC_INST_EHPRIV | \ | ||
34 | (EHPRIV_OC_DEBUG << EHPRIV_OC_SHIFT)) | ||
30 | 35 | ||
31 | static inline void kvmppc_set_gpr(struct kvm_vcpu *vcpu, int num, ulong val) | 36 | static inline void kvmppc_set_gpr(struct kvm_vcpu *vcpu, int num, ulong val) |
32 | { | 37 | { |
diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h index 33283532e9d8..237d1d25b448 100644 --- a/arch/powerpc/include/asm/kvm_host.h +++ b/arch/powerpc/include/asm/kvm_host.h | |||
@@ -63,20 +63,17 @@ extern void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte); | |||
63 | 63 | ||
64 | #endif | 64 | #endif |
65 | 65 | ||
66 | /* We don't currently support large pages. */ | ||
67 | #define KVM_HPAGE_GFN_SHIFT(x) 0 | ||
68 | #define KVM_NR_PAGE_SIZES 1 | ||
69 | #define KVM_PAGES_PER_HPAGE(x) (1UL<<31) | ||
70 | |||
71 | #define HPTEG_CACHE_NUM (1 << 15) | 66 | #define HPTEG_CACHE_NUM (1 << 15) |
72 | #define HPTEG_HASH_BITS_PTE 13 | 67 | #define HPTEG_HASH_BITS_PTE 13 |
73 | #define HPTEG_HASH_BITS_PTE_LONG 12 | 68 | #define HPTEG_HASH_BITS_PTE_LONG 12 |
74 | #define HPTEG_HASH_BITS_VPTE 13 | 69 | #define HPTEG_HASH_BITS_VPTE 13 |
75 | #define HPTEG_HASH_BITS_VPTE_LONG 5 | 70 | #define HPTEG_HASH_BITS_VPTE_LONG 5 |
71 | #define HPTEG_HASH_BITS_VPTE_64K 11 | ||
76 | #define HPTEG_HASH_NUM_PTE (1 << HPTEG_HASH_BITS_PTE) | 72 | #define HPTEG_HASH_NUM_PTE (1 << HPTEG_HASH_BITS_PTE) |
77 | #define HPTEG_HASH_NUM_PTE_LONG (1 << HPTEG_HASH_BITS_PTE_LONG) | 73 | #define HPTEG_HASH_NUM_PTE_LONG (1 << HPTEG_HASH_BITS_PTE_LONG) |
78 | #define HPTEG_HASH_NUM_VPTE (1 << HPTEG_HASH_BITS_VPTE) | 74 | #define HPTEG_HASH_NUM_VPTE (1 << HPTEG_HASH_BITS_VPTE) |
79 | #define HPTEG_HASH_NUM_VPTE_LONG (1 << HPTEG_HASH_BITS_VPTE_LONG) | 75 | #define HPTEG_HASH_NUM_VPTE_LONG (1 << HPTEG_HASH_BITS_VPTE_LONG) |
76 | #define HPTEG_HASH_NUM_VPTE_64K (1 << HPTEG_HASH_BITS_VPTE_64K) | ||
80 | 77 | ||
81 | /* Physical Address Mask - allowed range of real mode RAM access */ | 78 | /* Physical Address Mask - allowed range of real mode RAM access */ |
82 | #define KVM_PAM 0x0fffffffffffffffULL | 79 | #define KVM_PAM 0x0fffffffffffffffULL |
@@ -89,6 +86,9 @@ struct lppaca; | |||
89 | struct slb_shadow; | 86 | struct slb_shadow; |
90 | struct dtl_entry; | 87 | struct dtl_entry; |
91 | 88 | ||
89 | struct kvmppc_vcpu_book3s; | ||
90 | struct kvmppc_book3s_shadow_vcpu; | ||
91 | |||
92 | struct kvm_vm_stat { | 92 | struct kvm_vm_stat { |
93 | u32 remote_tlb_flush; | 93 | u32 remote_tlb_flush; |
94 | }; | 94 | }; |
@@ -224,15 +224,15 @@ struct revmap_entry { | |||
224 | #define KVMPPC_GOT_PAGE 0x80 | 224 | #define KVMPPC_GOT_PAGE 0x80 |
225 | 225 | ||
226 | struct kvm_arch_memory_slot { | 226 | struct kvm_arch_memory_slot { |
227 | #ifdef CONFIG_KVM_BOOK3S_64_HV | 227 | #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE |
228 | unsigned long *rmap; | 228 | unsigned long *rmap; |
229 | unsigned long *slot_phys; | 229 | unsigned long *slot_phys; |
230 | #endif /* CONFIG_KVM_BOOK3S_64_HV */ | 230 | #endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */ |
231 | }; | 231 | }; |
232 | 232 | ||
233 | struct kvm_arch { | 233 | struct kvm_arch { |
234 | unsigned int lpid; | 234 | unsigned int lpid; |
235 | #ifdef CONFIG_KVM_BOOK3S_64_HV | 235 | #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE |
236 | unsigned long hpt_virt; | 236 | unsigned long hpt_virt; |
237 | struct revmap_entry *revmap; | 237 | struct revmap_entry *revmap; |
238 | unsigned int host_lpid; | 238 | unsigned int host_lpid; |
@@ -256,7 +256,10 @@ struct kvm_arch { | |||
256 | cpumask_t need_tlb_flush; | 256 | cpumask_t need_tlb_flush; |
257 | struct kvmppc_vcore *vcores[KVM_MAX_VCORES]; | 257 | struct kvmppc_vcore *vcores[KVM_MAX_VCORES]; |
258 | int hpt_cma_alloc; | 258 | int hpt_cma_alloc; |
259 | #endif /* CONFIG_KVM_BOOK3S_64_HV */ | 259 | #endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */ |
260 | #ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE | ||
261 | struct mutex hpt_mutex; | ||
262 | #endif | ||
260 | #ifdef CONFIG_PPC_BOOK3S_64 | 263 | #ifdef CONFIG_PPC_BOOK3S_64 |
261 | struct list_head spapr_tce_tables; | 264 | struct list_head spapr_tce_tables; |
262 | struct list_head rtas_tokens; | 265 | struct list_head rtas_tokens; |
@@ -267,6 +270,7 @@ struct kvm_arch { | |||
267 | #ifdef CONFIG_KVM_XICS | 270 | #ifdef CONFIG_KVM_XICS |
268 | struct kvmppc_xics *xics; | 271 | struct kvmppc_xics *xics; |
269 | #endif | 272 | #endif |
273 | struct kvmppc_ops *kvm_ops; | ||
270 | }; | 274 | }; |
271 | 275 | ||
272 | /* | 276 | /* |
@@ -294,6 +298,10 @@ struct kvmppc_vcore { | |||
294 | u64 stolen_tb; | 298 | u64 stolen_tb; |
295 | u64 preempt_tb; | 299 | u64 preempt_tb; |
296 | struct kvm_vcpu *runner; | 300 | struct kvm_vcpu *runner; |
301 | u64 tb_offset; /* guest timebase - host timebase */ | ||
302 | ulong lpcr; | ||
303 | u32 arch_compat; | ||
304 | ulong pcr; | ||
297 | }; | 305 | }; |
298 | 306 | ||
299 | #define VCORE_ENTRY_COUNT(vc) ((vc)->entry_exit_count & 0xff) | 307 | #define VCORE_ENTRY_COUNT(vc) ((vc)->entry_exit_count & 0xff) |
@@ -328,6 +336,7 @@ struct kvmppc_pte { | |||
328 | bool may_read : 1; | 336 | bool may_read : 1; |
329 | bool may_write : 1; | 337 | bool may_write : 1; |
330 | bool may_execute : 1; | 338 | bool may_execute : 1; |
339 | u8 page_size; /* MMU_PAGE_xxx */ | ||
331 | }; | 340 | }; |
332 | 341 | ||
333 | struct kvmppc_mmu { | 342 | struct kvmppc_mmu { |
@@ -340,7 +349,8 @@ struct kvmppc_mmu { | |||
340 | /* book3s */ | 349 | /* book3s */ |
341 | void (*mtsrin)(struct kvm_vcpu *vcpu, u32 srnum, ulong value); | 350 | void (*mtsrin)(struct kvm_vcpu *vcpu, u32 srnum, ulong value); |
342 | u32 (*mfsrin)(struct kvm_vcpu *vcpu, u32 srnum); | 351 | u32 (*mfsrin)(struct kvm_vcpu *vcpu, u32 srnum); |
343 | int (*xlate)(struct kvm_vcpu *vcpu, gva_t eaddr, struct kvmppc_pte *pte, bool data); | 352 | int (*xlate)(struct kvm_vcpu *vcpu, gva_t eaddr, |
353 | struct kvmppc_pte *pte, bool data, bool iswrite); | ||
344 | void (*reset_msr)(struct kvm_vcpu *vcpu); | 354 | void (*reset_msr)(struct kvm_vcpu *vcpu); |
345 | void (*tlbie)(struct kvm_vcpu *vcpu, ulong addr, bool large); | 355 | void (*tlbie)(struct kvm_vcpu *vcpu, ulong addr, bool large); |
346 | int (*esid_to_vsid)(struct kvm_vcpu *vcpu, ulong esid, u64 *vsid); | 356 | int (*esid_to_vsid)(struct kvm_vcpu *vcpu, ulong esid, u64 *vsid); |
@@ -360,6 +370,7 @@ struct kvmppc_slb { | |||
360 | bool large : 1; /* PTEs are 16MB */ | 370 | bool large : 1; /* PTEs are 16MB */ |
361 | bool tb : 1; /* 1TB segment */ | 371 | bool tb : 1; /* 1TB segment */ |
362 | bool class : 1; | 372 | bool class : 1; |
373 | u8 base_page_size; /* MMU_PAGE_xxx */ | ||
363 | }; | 374 | }; |
364 | 375 | ||
365 | # ifdef CONFIG_PPC_FSL_BOOK3E | 376 | # ifdef CONFIG_PPC_FSL_BOOK3E |
@@ -377,17 +388,6 @@ struct kvmppc_slb { | |||
377 | #define KVMPPC_EPR_USER 1 /* exit to userspace to fill EPR */ | 388 | #define KVMPPC_EPR_USER 1 /* exit to userspace to fill EPR */ |
378 | #define KVMPPC_EPR_KERNEL 2 /* in-kernel irqchip */ | 389 | #define KVMPPC_EPR_KERNEL 2 /* in-kernel irqchip */ |
379 | 390 | ||
380 | struct kvmppc_booke_debug_reg { | ||
381 | u32 dbcr0; | ||
382 | u32 dbcr1; | ||
383 | u32 dbcr2; | ||
384 | #ifdef CONFIG_KVM_E500MC | ||
385 | u32 dbcr4; | ||
386 | #endif | ||
387 | u64 iac[KVMPPC_BOOKE_MAX_IAC]; | ||
388 | u64 dac[KVMPPC_BOOKE_MAX_DAC]; | ||
389 | }; | ||
390 | |||
391 | #define KVMPPC_IRQ_DEFAULT 0 | 391 | #define KVMPPC_IRQ_DEFAULT 0 |
392 | #define KVMPPC_IRQ_MPIC 1 | 392 | #define KVMPPC_IRQ_MPIC 1 |
393 | #define KVMPPC_IRQ_XICS 2 | 393 | #define KVMPPC_IRQ_XICS 2 |
@@ -402,6 +402,10 @@ struct kvm_vcpu_arch { | |||
402 | int slb_max; /* 1 + index of last valid entry in slb[] */ | 402 | int slb_max; /* 1 + index of last valid entry in slb[] */ |
403 | int slb_nr; /* total number of entries in SLB */ | 403 | int slb_nr; /* total number of entries in SLB */ |
404 | struct kvmppc_mmu mmu; | 404 | struct kvmppc_mmu mmu; |
405 | struct kvmppc_vcpu_book3s *book3s; | ||
406 | #endif | ||
407 | #ifdef CONFIG_PPC_BOOK3S_32 | ||
408 | struct kvmppc_book3s_shadow_vcpu *shadow_vcpu; | ||
405 | #endif | 409 | #endif |
406 | 410 | ||
407 | ulong gpr[32]; | 411 | ulong gpr[32]; |
@@ -463,6 +467,8 @@ struct kvm_vcpu_arch { | |||
463 | u32 ctrl; | 467 | u32 ctrl; |
464 | ulong dabr; | 468 | ulong dabr; |
465 | ulong cfar; | 469 | ulong cfar; |
470 | ulong ppr; | ||
471 | ulong shadow_srr1; | ||
466 | #endif | 472 | #endif |
467 | u32 vrsave; /* also USPRG0 */ | 473 | u32 vrsave; /* also USPRG0 */ |
468 | u32 mmucr; | 474 | u32 mmucr; |
@@ -498,6 +504,8 @@ struct kvm_vcpu_arch { | |||
498 | 504 | ||
499 | u64 mmcr[3]; | 505 | u64 mmcr[3]; |
500 | u32 pmc[8]; | 506 | u32 pmc[8]; |
507 | u64 siar; | ||
508 | u64 sdar; | ||
501 | 509 | ||
502 | #ifdef CONFIG_KVM_EXIT_TIMING | 510 | #ifdef CONFIG_KVM_EXIT_TIMING |
503 | struct mutex exit_timing_lock; | 511 | struct mutex exit_timing_lock; |
@@ -531,7 +539,10 @@ struct kvm_vcpu_arch { | |||
531 | u32 eptcfg; | 539 | u32 eptcfg; |
532 | u32 epr; | 540 | u32 epr; |
533 | u32 crit_save; | 541 | u32 crit_save; |
534 | struct kvmppc_booke_debug_reg dbg_reg; | 542 | /* guest debug registers*/ |
543 | struct debug_reg dbg_reg; | ||
544 | /* hardware visible debug registers when in guest state */ | ||
545 | struct debug_reg shadow_dbg_reg; | ||
535 | #endif | 546 | #endif |
536 | gpa_t paddr_accessed; | 547 | gpa_t paddr_accessed; |
537 | gva_t vaddr_accessed; | 548 | gva_t vaddr_accessed; |
@@ -582,7 +593,7 @@ struct kvm_vcpu_arch { | |||
582 | struct kvmppc_icp *icp; /* XICS presentation controller */ | 593 | struct kvmppc_icp *icp; /* XICS presentation controller */ |
583 | #endif | 594 | #endif |
584 | 595 | ||
585 | #ifdef CONFIG_KVM_BOOK3S_64_HV | 596 | #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE |
586 | struct kvm_vcpu_arch_shared shregs; | 597 | struct kvm_vcpu_arch_shared shregs; |
587 | 598 | ||
588 | unsigned long pgfault_addr; | 599 | unsigned long pgfault_addr; |
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h index b15554a26c20..c8317fbf92c4 100644 --- a/arch/powerpc/include/asm/kvm_ppc.h +++ b/arch/powerpc/include/asm/kvm_ppc.h | |||
@@ -106,13 +106,6 @@ extern void kvmppc_core_queue_external(struct kvm_vcpu *vcpu, | |||
106 | struct kvm_interrupt *irq); | 106 | struct kvm_interrupt *irq); |
107 | extern void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu); | 107 | extern void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu); |
108 | extern void kvmppc_core_flush_tlb(struct kvm_vcpu *vcpu); | 108 | extern void kvmppc_core_flush_tlb(struct kvm_vcpu *vcpu); |
109 | |||
110 | extern int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, | ||
111 | unsigned int op, int *advance); | ||
112 | extern int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, | ||
113 | ulong val); | ||
114 | extern int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, | ||
115 | ulong *val); | ||
116 | extern int kvmppc_core_check_requests(struct kvm_vcpu *vcpu); | 109 | extern int kvmppc_core_check_requests(struct kvm_vcpu *vcpu); |
117 | 110 | ||
118 | extern int kvmppc_booke_init(void); | 111 | extern int kvmppc_booke_init(void); |
@@ -135,17 +128,17 @@ extern long kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm, | |||
135 | struct kvm_create_spapr_tce *args); | 128 | struct kvm_create_spapr_tce *args); |
136 | extern long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn, | 129 | extern long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn, |
137 | unsigned long ioba, unsigned long tce); | 130 | unsigned long ioba, unsigned long tce); |
138 | extern long kvm_vm_ioctl_allocate_rma(struct kvm *kvm, | ||
139 | struct kvm_allocate_rma *rma); | ||
140 | extern struct kvm_rma_info *kvm_alloc_rma(void); | 131 | extern struct kvm_rma_info *kvm_alloc_rma(void); |
141 | extern void kvm_release_rma(struct kvm_rma_info *ri); | 132 | extern void kvm_release_rma(struct kvm_rma_info *ri); |
142 | extern struct page *kvm_alloc_hpt(unsigned long nr_pages); | 133 | extern struct page *kvm_alloc_hpt(unsigned long nr_pages); |
143 | extern void kvm_release_hpt(struct page *page, unsigned long nr_pages); | 134 | extern void kvm_release_hpt(struct page *page, unsigned long nr_pages); |
144 | extern int kvmppc_core_init_vm(struct kvm *kvm); | 135 | extern int kvmppc_core_init_vm(struct kvm *kvm); |
145 | extern void kvmppc_core_destroy_vm(struct kvm *kvm); | 136 | extern void kvmppc_core_destroy_vm(struct kvm *kvm); |
146 | extern void kvmppc_core_free_memslot(struct kvm_memory_slot *free, | 137 | extern void kvmppc_core_free_memslot(struct kvm *kvm, |
138 | struct kvm_memory_slot *free, | ||
147 | struct kvm_memory_slot *dont); | 139 | struct kvm_memory_slot *dont); |
148 | extern int kvmppc_core_create_memslot(struct kvm_memory_slot *slot, | 140 | extern int kvmppc_core_create_memslot(struct kvm *kvm, |
141 | struct kvm_memory_slot *slot, | ||
149 | unsigned long npages); | 142 | unsigned long npages); |
150 | extern int kvmppc_core_prepare_memory_region(struct kvm *kvm, | 143 | extern int kvmppc_core_prepare_memory_region(struct kvm *kvm, |
151 | struct kvm_memory_slot *memslot, | 144 | struct kvm_memory_slot *memslot, |
@@ -177,6 +170,72 @@ extern int kvmppc_xics_get_xive(struct kvm *kvm, u32 irq, u32 *server, | |||
177 | extern int kvmppc_xics_int_on(struct kvm *kvm, u32 irq); | 170 | extern int kvmppc_xics_int_on(struct kvm *kvm, u32 irq); |
178 | extern int kvmppc_xics_int_off(struct kvm *kvm, u32 irq); | 171 | extern int kvmppc_xics_int_off(struct kvm *kvm, u32 irq); |
179 | 172 | ||
173 | union kvmppc_one_reg { | ||
174 | u32 wval; | ||
175 | u64 dval; | ||
176 | vector128 vval; | ||
177 | u64 vsxval[2]; | ||
178 | struct { | ||
179 | u64 addr; | ||
180 | u64 length; | ||
181 | } vpaval; | ||
182 | }; | ||
183 | |||
184 | struct kvmppc_ops { | ||
185 | struct module *owner; | ||
186 | int (*get_sregs)(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs); | ||
187 | int (*set_sregs)(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs); | ||
188 | int (*get_one_reg)(struct kvm_vcpu *vcpu, u64 id, | ||
189 | union kvmppc_one_reg *val); | ||
190 | int (*set_one_reg)(struct kvm_vcpu *vcpu, u64 id, | ||
191 | union kvmppc_one_reg *val); | ||
192 | void (*vcpu_load)(struct kvm_vcpu *vcpu, int cpu); | ||
193 | void (*vcpu_put)(struct kvm_vcpu *vcpu); | ||
194 | void (*set_msr)(struct kvm_vcpu *vcpu, u64 msr); | ||
195 | int (*vcpu_run)(struct kvm_run *run, struct kvm_vcpu *vcpu); | ||
196 | struct kvm_vcpu *(*vcpu_create)(struct kvm *kvm, unsigned int id); | ||
197 | void (*vcpu_free)(struct kvm_vcpu *vcpu); | ||
198 | int (*check_requests)(struct kvm_vcpu *vcpu); | ||
199 | int (*get_dirty_log)(struct kvm *kvm, struct kvm_dirty_log *log); | ||
200 | void (*flush_memslot)(struct kvm *kvm, struct kvm_memory_slot *memslot); | ||
201 | int (*prepare_memory_region)(struct kvm *kvm, | ||
202 | struct kvm_memory_slot *memslot, | ||
203 | struct kvm_userspace_memory_region *mem); | ||
204 | void (*commit_memory_region)(struct kvm *kvm, | ||
205 | struct kvm_userspace_memory_region *mem, | ||
206 | const struct kvm_memory_slot *old); | ||
207 | int (*unmap_hva)(struct kvm *kvm, unsigned long hva); | ||
208 | int (*unmap_hva_range)(struct kvm *kvm, unsigned long start, | ||
209 | unsigned long end); | ||
210 | int (*age_hva)(struct kvm *kvm, unsigned long hva); | ||
211 | int (*test_age_hva)(struct kvm *kvm, unsigned long hva); | ||
212 | void (*set_spte_hva)(struct kvm *kvm, unsigned long hva, pte_t pte); | ||
213 | void (*mmu_destroy)(struct kvm_vcpu *vcpu); | ||
214 | void (*free_memslot)(struct kvm_memory_slot *free, | ||
215 | struct kvm_memory_slot *dont); | ||
216 | int (*create_memslot)(struct kvm_memory_slot *slot, | ||
217 | unsigned long npages); | ||
218 | int (*init_vm)(struct kvm *kvm); | ||
219 | void (*destroy_vm)(struct kvm *kvm); | ||
220 | int (*get_smmu_info)(struct kvm *kvm, struct kvm_ppc_smmu_info *info); | ||
221 | int (*emulate_op)(struct kvm_run *run, struct kvm_vcpu *vcpu, | ||
222 | unsigned int inst, int *advance); | ||
223 | int (*emulate_mtspr)(struct kvm_vcpu *vcpu, int sprn, ulong spr_val); | ||
224 | int (*emulate_mfspr)(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val); | ||
225 | void (*fast_vcpu_kick)(struct kvm_vcpu *vcpu); | ||
226 | long (*arch_vm_ioctl)(struct file *filp, unsigned int ioctl, | ||
227 | unsigned long arg); | ||
228 | |||
229 | }; | ||
230 | |||
231 | extern struct kvmppc_ops *kvmppc_hv_ops; | ||
232 | extern struct kvmppc_ops *kvmppc_pr_ops; | ||
233 | |||
234 | static inline bool is_kvmppc_hv_enabled(struct kvm *kvm) | ||
235 | { | ||
236 | return kvm->arch.kvm_ops == kvmppc_hv_ops; | ||
237 | } | ||
238 | |||
180 | /* | 239 | /* |
181 | * Cuts out inst bits with ordering according to spec. | 240 | * Cuts out inst bits with ordering according to spec. |
182 | * That means the leftmost bit is zero. All given bits are included. | 241 | * That means the leftmost bit is zero. All given bits are included. |
@@ -210,17 +269,6 @@ static inline u32 kvmppc_set_field(u64 inst, int msb, int lsb, int value) | |||
210 | return r; | 269 | return r; |
211 | } | 270 | } |
212 | 271 | ||
213 | union kvmppc_one_reg { | ||
214 | u32 wval; | ||
215 | u64 dval; | ||
216 | vector128 vval; | ||
217 | u64 vsxval[2]; | ||
218 | struct { | ||
219 | u64 addr; | ||
220 | u64 length; | ||
221 | } vpaval; | ||
222 | }; | ||
223 | |||
224 | #define one_reg_size(id) \ | 272 | #define one_reg_size(id) \ |
225 | (1ul << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT)) | 273 | (1ul << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT)) |
226 | 274 | ||
@@ -245,10 +293,10 @@ union kvmppc_one_reg { | |||
245 | __v; \ | 293 | __v; \ |
246 | }) | 294 | }) |
247 | 295 | ||
248 | void kvmppc_core_get_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs); | 296 | int kvmppc_core_get_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs); |
249 | int kvmppc_core_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs); | 297 | int kvmppc_core_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs); |
250 | 298 | ||
251 | void kvmppc_get_sregs_ivor(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs); | 299 | int kvmppc_get_sregs_ivor(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs); |
252 | int kvmppc_set_sregs_ivor(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs); | 300 | int kvmppc_set_sregs_ivor(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs); |
253 | 301 | ||
254 | int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg); | 302 | int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg); |
@@ -260,7 +308,7 @@ void kvmppc_set_pid(struct kvm_vcpu *vcpu, u32 pid); | |||
260 | 308 | ||
261 | struct openpic; | 309 | struct openpic; |
262 | 310 | ||
263 | #ifdef CONFIG_KVM_BOOK3S_64_HV | 311 | #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE |
264 | extern void kvm_cma_reserve(void) __init; | 312 | extern void kvm_cma_reserve(void) __init; |
265 | static inline void kvmppc_set_xics_phys(int cpu, unsigned long addr) | 313 | static inline void kvmppc_set_xics_phys(int cpu, unsigned long addr) |
266 | { | 314 | { |
@@ -269,10 +317,10 @@ static inline void kvmppc_set_xics_phys(int cpu, unsigned long addr) | |||
269 | 317 | ||
270 | static inline u32 kvmppc_get_xics_latch(void) | 318 | static inline u32 kvmppc_get_xics_latch(void) |
271 | { | 319 | { |
272 | u32 xirr = get_paca()->kvm_hstate.saved_xirr; | 320 | u32 xirr; |
273 | 321 | ||
322 | xirr = get_paca()->kvm_hstate.saved_xirr; | ||
274 | get_paca()->kvm_hstate.saved_xirr = 0; | 323 | get_paca()->kvm_hstate.saved_xirr = 0; |
275 | |||
276 | return xirr; | 324 | return xirr; |
277 | } | 325 | } |
278 | 326 | ||
@@ -281,7 +329,10 @@ static inline void kvmppc_set_host_ipi(int cpu, u8 host_ipi) | |||
281 | paca[cpu].kvm_hstate.host_ipi = host_ipi; | 329 | paca[cpu].kvm_hstate.host_ipi = host_ipi; |
282 | } | 330 | } |
283 | 331 | ||
284 | extern void kvmppc_fast_vcpu_kick(struct kvm_vcpu *vcpu); | 332 | static inline void kvmppc_fast_vcpu_kick(struct kvm_vcpu *vcpu) |
333 | { | ||
334 | vcpu->kvm->arch.kvm_ops->fast_vcpu_kick(vcpu); | ||
335 | } | ||
285 | 336 | ||
286 | #else | 337 | #else |
287 | static inline void __init kvm_cma_reserve(void) | 338 | static inline void __init kvm_cma_reserve(void) |
diff --git a/arch/powerpc/include/asm/lppaca.h b/arch/powerpc/include/asm/lppaca.h index 4470d1e34d23..844c28de7ec0 100644 --- a/arch/powerpc/include/asm/lppaca.h +++ b/arch/powerpc/include/asm/lppaca.h | |||
@@ -84,8 +84,8 @@ struct lppaca { | |||
84 | * the processor is yielded (either because of an OS yield or a | 84 | * the processor is yielded (either because of an OS yield or a |
85 | * hypervisor preempt). An even value implies that the processor is | 85 | * hypervisor preempt). An even value implies that the processor is |
86 | * currently executing. | 86 | * currently executing. |
87 | * NOTE: This value will ALWAYS be zero for dedicated processors and | 87 | * NOTE: Even dedicated processor partitions can yield so this |
88 | * will NEVER be zero for shared processors (ie, initialized to a 1). | 88 | * field cannot be used to determine if we are shared or dedicated. |
89 | */ | 89 | */ |
90 | volatile __be32 yield_count; | 90 | volatile __be32 yield_count; |
91 | volatile __be32 dispersion_count; /* dispatch changed physical cpu */ | 91 | volatile __be32 dispersion_count; /* dispatch changed physical cpu */ |
@@ -106,15 +106,15 @@ extern struct lppaca lppaca[]; | |||
106 | #define lppaca_of(cpu) (*paca[cpu].lppaca_ptr) | 106 | #define lppaca_of(cpu) (*paca[cpu].lppaca_ptr) |
107 | 107 | ||
108 | /* | 108 | /* |
109 | * Old kernels used a reserved bit in the VPA to determine if it was running | 109 | * We are using a non architected field to determine if a partition is |
110 | * in shared processor mode. New kernels look for a non zero yield count | 110 | * shared or dedicated. This currently works on both KVM and PHYP, but |
111 | * but KVM still needs to set the bit to keep the old stuff happy. | 111 | * we will have to transition to something better. |
112 | */ | 112 | */ |
113 | #define LPPACA_OLD_SHARED_PROC 2 | 113 | #define LPPACA_OLD_SHARED_PROC 2 |
114 | 114 | ||
115 | static inline bool lppaca_shared_proc(struct lppaca *l) | 115 | static inline bool lppaca_shared_proc(struct lppaca *l) |
116 | { | 116 | { |
117 | return l->yield_count != 0; | 117 | return !!(l->__old_status & LPPACA_OLD_SHARED_PROC); |
118 | } | 118 | } |
119 | 119 | ||
120 | /* | 120 | /* |
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h index 8b480901165a..ad3025d0880b 100644 --- a/arch/powerpc/include/asm/machdep.h +++ b/arch/powerpc/include/asm/machdep.h | |||
@@ -78,6 +78,18 @@ struct machdep_calls { | |||
78 | long index); | 78 | long index); |
79 | void (*tce_flush)(struct iommu_table *tbl); | 79 | void (*tce_flush)(struct iommu_table *tbl); |
80 | 80 | ||
81 | /* _rm versions are for real mode use only */ | ||
82 | int (*tce_build_rm)(struct iommu_table *tbl, | ||
83 | long index, | ||
84 | long npages, | ||
85 | unsigned long uaddr, | ||
86 | enum dma_data_direction direction, | ||
87 | struct dma_attrs *attrs); | ||
88 | void (*tce_free_rm)(struct iommu_table *tbl, | ||
89 | long index, | ||
90 | long npages); | ||
91 | void (*tce_flush_rm)(struct iommu_table *tbl); | ||
92 | |||
81 | void __iomem * (*ioremap)(phys_addr_t addr, unsigned long size, | 93 | void __iomem * (*ioremap)(phys_addr_t addr, unsigned long size, |
82 | unsigned long flags, void *caller); | 94 | unsigned long flags, void *caller); |
83 | void (*iounmap)(volatile void __iomem *token); | 95 | void (*iounmap)(volatile void __iomem *token); |
@@ -263,6 +275,10 @@ struct machdep_calls { | |||
263 | ssize_t (*cpu_probe)(const char *, size_t); | 275 | ssize_t (*cpu_probe)(const char *, size_t); |
264 | ssize_t (*cpu_release)(const char *, size_t); | 276 | ssize_t (*cpu_release)(const char *, size_t); |
265 | #endif | 277 | #endif |
278 | |||
279 | #ifdef CONFIG_ARCH_RANDOM | ||
280 | int (*get_random_long)(unsigned long *v); | ||
281 | #endif | ||
266 | }; | 282 | }; |
267 | 283 | ||
268 | extern void e500_idle(void); | 284 | extern void e500_idle(void); |
diff --git a/arch/powerpc/include/asm/mmu-hash64.h b/arch/powerpc/include/asm/mmu-hash64.h index c4cf01197273..807014dde821 100644 --- a/arch/powerpc/include/asm/mmu-hash64.h +++ b/arch/powerpc/include/asm/mmu-hash64.h | |||
@@ -135,8 +135,8 @@ extern char initial_stab[]; | |||
135 | #ifndef __ASSEMBLY__ | 135 | #ifndef __ASSEMBLY__ |
136 | 136 | ||
137 | struct hash_pte { | 137 | struct hash_pte { |
138 | unsigned long v; | 138 | __be64 v; |
139 | unsigned long r; | 139 | __be64 r; |
140 | }; | 140 | }; |
141 | 141 | ||
142 | extern struct hash_pte *htab_address; | 142 | extern struct hash_pte *htab_address; |
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h index c5cd72833d6e..033c06be1d84 100644 --- a/arch/powerpc/include/asm/opal.h +++ b/arch/powerpc/include/asm/opal.h | |||
@@ -129,6 +129,9 @@ extern int opal_enter_rtas(struct rtas_args *args, | |||
129 | #define OPAL_LPC_READ 67 | 129 | #define OPAL_LPC_READ 67 |
130 | #define OPAL_LPC_WRITE 68 | 130 | #define OPAL_LPC_WRITE 68 |
131 | #define OPAL_RETURN_CPU 69 | 131 | #define OPAL_RETURN_CPU 69 |
132 | #define OPAL_FLASH_VALIDATE 76 | ||
133 | #define OPAL_FLASH_MANAGE 77 | ||
134 | #define OPAL_FLASH_UPDATE 78 | ||
132 | 135 | ||
133 | #ifndef __ASSEMBLY__ | 136 | #ifndef __ASSEMBLY__ |
134 | 137 | ||
@@ -460,10 +463,12 @@ enum { | |||
460 | 463 | ||
461 | enum { | 464 | enum { |
462 | OPAL_PHB_ERROR_DATA_TYPE_P7IOC = 1, | 465 | OPAL_PHB_ERROR_DATA_TYPE_P7IOC = 1, |
466 | OPAL_PHB_ERROR_DATA_TYPE_PHB3 = 2 | ||
463 | }; | 467 | }; |
464 | 468 | ||
465 | enum { | 469 | enum { |
466 | OPAL_P7IOC_NUM_PEST_REGS = 128, | 470 | OPAL_P7IOC_NUM_PEST_REGS = 128, |
471 | OPAL_PHB3_NUM_PEST_REGS = 256 | ||
467 | }; | 472 | }; |
468 | 473 | ||
469 | struct OpalIoPhbErrorCommon { | 474 | struct OpalIoPhbErrorCommon { |
@@ -531,28 +536,94 @@ struct OpalIoP7IOCPhbErrorData { | |||
531 | uint64_t pestB[OPAL_P7IOC_NUM_PEST_REGS]; | 536 | uint64_t pestB[OPAL_P7IOC_NUM_PEST_REGS]; |
532 | }; | 537 | }; |
533 | 538 | ||
539 | struct OpalIoPhb3ErrorData { | ||
540 | struct OpalIoPhbErrorCommon common; | ||
541 | |||
542 | uint32_t brdgCtl; | ||
543 | |||
544 | /* PHB3 UTL regs */ | ||
545 | uint32_t portStatusReg; | ||
546 | uint32_t rootCmplxStatus; | ||
547 | uint32_t busAgentStatus; | ||
548 | |||
549 | /* PHB3 cfg regs */ | ||
550 | uint32_t deviceStatus; | ||
551 | uint32_t slotStatus; | ||
552 | uint32_t linkStatus; | ||
553 | uint32_t devCmdStatus; | ||
554 | uint32_t devSecStatus; | ||
555 | |||
556 | /* cfg AER regs */ | ||
557 | uint32_t rootErrorStatus; | ||
558 | uint32_t uncorrErrorStatus; | ||
559 | uint32_t corrErrorStatus; | ||
560 | uint32_t tlpHdr1; | ||
561 | uint32_t tlpHdr2; | ||
562 | uint32_t tlpHdr3; | ||
563 | uint32_t tlpHdr4; | ||
564 | uint32_t sourceId; | ||
565 | |||
566 | uint32_t rsv3; | ||
567 | |||
568 | /* Record data about the call to allocate a buffer */ | ||
569 | uint64_t errorClass; | ||
570 | uint64_t correlator; | ||
571 | |||
572 | uint64_t nFir; /* 000 */ | ||
573 | uint64_t nFirMask; /* 003 */ | ||
574 | uint64_t nFirWOF; /* 008 */ | ||
575 | |||
576 | /* PHB3 MMIO Error Regs */ | ||
577 | uint64_t phbPlssr; /* 120 */ | ||
578 | uint64_t phbCsr; /* 110 */ | ||
579 | uint64_t lemFir; /* C00 */ | ||
580 | uint64_t lemErrorMask; /* C18 */ | ||
581 | uint64_t lemWOF; /* C40 */ | ||
582 | uint64_t phbErrorStatus; /* C80 */ | ||
583 | uint64_t phbFirstErrorStatus; /* C88 */ | ||
584 | uint64_t phbErrorLog0; /* CC0 */ | ||
585 | uint64_t phbErrorLog1; /* CC8 */ | ||
586 | uint64_t mmioErrorStatus; /* D00 */ | ||
587 | uint64_t mmioFirstErrorStatus; /* D08 */ | ||
588 | uint64_t mmioErrorLog0; /* D40 */ | ||
589 | uint64_t mmioErrorLog1; /* D48 */ | ||
590 | uint64_t dma0ErrorStatus; /* D80 */ | ||
591 | uint64_t dma0FirstErrorStatus; /* D88 */ | ||
592 | uint64_t dma0ErrorLog0; /* DC0 */ | ||
593 | uint64_t dma0ErrorLog1; /* DC8 */ | ||
594 | uint64_t dma1ErrorStatus; /* E00 */ | ||
595 | uint64_t dma1FirstErrorStatus; /* E08 */ | ||
596 | uint64_t dma1ErrorLog0; /* E40 */ | ||
597 | uint64_t dma1ErrorLog1; /* E48 */ | ||
598 | uint64_t pestA[OPAL_PHB3_NUM_PEST_REGS]; | ||
599 | uint64_t pestB[OPAL_PHB3_NUM_PEST_REGS]; | ||
600 | }; | ||
601 | |||
534 | typedef struct oppanel_line { | 602 | typedef struct oppanel_line { |
535 | const char * line; | 603 | const char * line; |
536 | uint64_t line_len; | 604 | uint64_t line_len; |
537 | } oppanel_line_t; | 605 | } oppanel_line_t; |
538 | 606 | ||
607 | /* /sys/firmware/opal */ | ||
608 | extern struct kobject *opal_kobj; | ||
609 | |||
539 | /* API functions */ | 610 | /* API functions */ |
540 | int64_t opal_console_write(int64_t term_number, int64_t *length, | 611 | int64_t opal_console_write(int64_t term_number, __be64 *length, |
541 | const uint8_t *buffer); | 612 | const uint8_t *buffer); |
542 | int64_t opal_console_read(int64_t term_number, int64_t *length, | 613 | int64_t opal_console_read(int64_t term_number, __be64 *length, |
543 | uint8_t *buffer); | 614 | uint8_t *buffer); |
544 | int64_t opal_console_write_buffer_space(int64_t term_number, | 615 | int64_t opal_console_write_buffer_space(int64_t term_number, |
545 | int64_t *length); | 616 | __be64 *length); |
546 | int64_t opal_rtc_read(uint32_t *year_month_day, | 617 | int64_t opal_rtc_read(__be32 *year_month_day, |
547 | uint64_t *hour_minute_second_millisecond); | 618 | __be64 *hour_minute_second_millisecond); |
548 | int64_t opal_rtc_write(uint32_t year_month_day, | 619 | int64_t opal_rtc_write(uint32_t year_month_day, |
549 | uint64_t hour_minute_second_millisecond); | 620 | uint64_t hour_minute_second_millisecond); |
550 | int64_t opal_cec_power_down(uint64_t request); | 621 | int64_t opal_cec_power_down(uint64_t request); |
551 | int64_t opal_cec_reboot(void); | 622 | int64_t opal_cec_reboot(void); |
552 | int64_t opal_read_nvram(uint64_t buffer, uint64_t size, uint64_t offset); | 623 | int64_t opal_read_nvram(uint64_t buffer, uint64_t size, uint64_t offset); |
553 | int64_t opal_write_nvram(uint64_t buffer, uint64_t size, uint64_t offset); | 624 | int64_t opal_write_nvram(uint64_t buffer, uint64_t size, uint64_t offset); |
554 | int64_t opal_handle_interrupt(uint64_t isn, uint64_t *outstanding_event_mask); | 625 | int64_t opal_handle_interrupt(uint64_t isn, __be64 *outstanding_event_mask); |
555 | int64_t opal_poll_events(uint64_t *outstanding_event_mask); | 626 | int64_t opal_poll_events(__be64 *outstanding_event_mask); |
556 | int64_t opal_pci_set_hub_tce_memory(uint64_t hub_id, uint64_t tce_mem_addr, | 627 | int64_t opal_pci_set_hub_tce_memory(uint64_t hub_id, uint64_t tce_mem_addr, |
557 | uint64_t tce_mem_size); | 628 | uint64_t tce_mem_size); |
558 | int64_t opal_pci_set_phb_tce_memory(uint64_t phb_id, uint64_t tce_mem_addr, | 629 | int64_t opal_pci_set_phb_tce_memory(uint64_t phb_id, uint64_t tce_mem_addr, |
@@ -560,9 +631,9 @@ int64_t opal_pci_set_phb_tce_memory(uint64_t phb_id, uint64_t tce_mem_addr, | |||
560 | int64_t opal_pci_config_read_byte(uint64_t phb_id, uint64_t bus_dev_func, | 631 | int64_t opal_pci_config_read_byte(uint64_t phb_id, uint64_t bus_dev_func, |
561 | uint64_t offset, uint8_t *data); | 632 | uint64_t offset, uint8_t *data); |
562 | int64_t opal_pci_config_read_half_word(uint64_t phb_id, uint64_t bus_dev_func, | 633 | int64_t opal_pci_config_read_half_word(uint64_t phb_id, uint64_t bus_dev_func, |
563 | uint64_t offset, uint16_t *data); | 634 | uint64_t offset, __be16 *data); |
564 | int64_t opal_pci_config_read_word(uint64_t phb_id, uint64_t bus_dev_func, | 635 | int64_t opal_pci_config_read_word(uint64_t phb_id, uint64_t bus_dev_func, |
565 | uint64_t offset, uint32_t *data); | 636 | uint64_t offset, __be32 *data); |
566 | int64_t opal_pci_config_write_byte(uint64_t phb_id, uint64_t bus_dev_func, | 637 | int64_t opal_pci_config_write_byte(uint64_t phb_id, uint64_t bus_dev_func, |
567 | uint64_t offset, uint8_t data); | 638 | uint64_t offset, uint8_t data); |
568 | int64_t opal_pci_config_write_half_word(uint64_t phb_id, uint64_t bus_dev_func, | 639 | int64_t opal_pci_config_write_half_word(uint64_t phb_id, uint64_t bus_dev_func, |
@@ -570,14 +641,14 @@ int64_t opal_pci_config_write_half_word(uint64_t phb_id, uint64_t bus_dev_func, | |||
570 | int64_t opal_pci_config_write_word(uint64_t phb_id, uint64_t bus_dev_func, | 641 | int64_t opal_pci_config_write_word(uint64_t phb_id, uint64_t bus_dev_func, |
571 | uint64_t offset, uint32_t data); | 642 | uint64_t offset, uint32_t data); |
572 | int64_t opal_set_xive(uint32_t isn, uint16_t server, uint8_t priority); | 643 | int64_t opal_set_xive(uint32_t isn, uint16_t server, uint8_t priority); |
573 | int64_t opal_get_xive(uint32_t isn, uint16_t *server, uint8_t *priority); | 644 | int64_t opal_get_xive(uint32_t isn, __be16 *server, uint8_t *priority); |
574 | int64_t opal_register_exception_handler(uint64_t opal_exception, | 645 | int64_t opal_register_exception_handler(uint64_t opal_exception, |
575 | uint64_t handler_address, | 646 | uint64_t handler_address, |
576 | uint64_t glue_cache_line); | 647 | uint64_t glue_cache_line); |
577 | int64_t opal_pci_eeh_freeze_status(uint64_t phb_id, uint64_t pe_number, | 648 | int64_t opal_pci_eeh_freeze_status(uint64_t phb_id, uint64_t pe_number, |
578 | uint8_t *freeze_state, | 649 | uint8_t *freeze_state, |
579 | uint16_t *pci_error_type, | 650 | __be16 *pci_error_type, |
580 | uint64_t *phb_status); | 651 | __be64 *phb_status); |
581 | int64_t opal_pci_eeh_freeze_clear(uint64_t phb_id, uint64_t pe_number, | 652 | int64_t opal_pci_eeh_freeze_clear(uint64_t phb_id, uint64_t pe_number, |
582 | uint64_t eeh_action_token); | 653 | uint64_t eeh_action_token); |
583 | int64_t opal_pci_shpc(uint64_t phb_id, uint64_t shpc_action, uint8_t *state); | 654 | int64_t opal_pci_shpc(uint64_t phb_id, uint64_t shpc_action, uint8_t *state); |
@@ -614,13 +685,13 @@ int64_t opal_pci_msi_eoi(uint64_t phb_id, uint32_t hw_irq); | |||
614 | int64_t opal_pci_set_xive_pe(uint64_t phb_id, uint32_t pe_number, | 685 | int64_t opal_pci_set_xive_pe(uint64_t phb_id, uint32_t pe_number, |
615 | uint32_t xive_num); | 686 | uint32_t xive_num); |
616 | int64_t opal_get_xive_source(uint64_t phb_id, uint32_t xive_num, | 687 | int64_t opal_get_xive_source(uint64_t phb_id, uint32_t xive_num, |
617 | int32_t *interrupt_source_number); | 688 | __be32 *interrupt_source_number); |
618 | int64_t opal_get_msi_32(uint64_t phb_id, uint32_t mve_number, uint32_t xive_num, | 689 | int64_t opal_get_msi_32(uint64_t phb_id, uint32_t mve_number, uint32_t xive_num, |
619 | uint8_t msi_range, uint32_t *msi_address, | 690 | uint8_t msi_range, __be32 *msi_address, |
620 | uint32_t *message_data); | 691 | __be32 *message_data); |
621 | int64_t opal_get_msi_64(uint64_t phb_id, uint32_t mve_number, | 692 | int64_t opal_get_msi_64(uint64_t phb_id, uint32_t mve_number, |
622 | uint32_t xive_num, uint8_t msi_range, | 693 | uint32_t xive_num, uint8_t msi_range, |
623 | uint64_t *msi_address, uint32_t *message_data); | 694 | __be64 *msi_address, __be32 *message_data); |
624 | int64_t opal_start_cpu(uint64_t thread_number, uint64_t start_address); | 695 | int64_t opal_start_cpu(uint64_t thread_number, uint64_t start_address); |
625 | int64_t opal_query_cpu_status(uint64_t thread_number, uint8_t *thread_status); | 696 | int64_t opal_query_cpu_status(uint64_t thread_number, uint8_t *thread_status); |
626 | int64_t opal_write_oppanel(oppanel_line_t *lines, uint64_t num_lines); | 697 | int64_t opal_write_oppanel(oppanel_line_t *lines, uint64_t num_lines); |
@@ -642,7 +713,7 @@ int64_t opal_pci_fence_phb(uint64_t phb_id); | |||
642 | int64_t opal_pci_reinit(uint64_t phb_id, uint8_t reinit_scope); | 713 | int64_t opal_pci_reinit(uint64_t phb_id, uint8_t reinit_scope); |
643 | int64_t opal_pci_mask_pe_error(uint64_t phb_id, uint16_t pe_number, uint8_t error_type, uint8_t mask_action); | 714 | int64_t opal_pci_mask_pe_error(uint64_t phb_id, uint16_t pe_number, uint8_t error_type, uint8_t mask_action); |
644 | int64_t opal_set_slot_led_status(uint64_t phb_id, uint64_t slot_id, uint8_t led_type, uint8_t led_action); | 715 | int64_t opal_set_slot_led_status(uint64_t phb_id, uint64_t slot_id, uint8_t led_type, uint8_t led_action); |
645 | int64_t opal_get_epow_status(uint64_t *status); | 716 | int64_t opal_get_epow_status(__be64 *status); |
646 | int64_t opal_set_system_attention_led(uint8_t led_action); | 717 | int64_t opal_set_system_attention_led(uint8_t led_action); |
647 | int64_t opal_pci_next_error(uint64_t phb_id, uint64_t *first_frozen_pe, | 718 | int64_t opal_pci_next_error(uint64_t phb_id, uint64_t *first_frozen_pe, |
648 | uint16_t *pci_error_type, uint16_t *severity); | 719 | uint16_t *pci_error_type, uint16_t *severity); |
@@ -656,6 +727,9 @@ int64_t opal_lpc_write(uint32_t chip_id, enum OpalLPCAddressType addr_type, | |||
656 | uint32_t addr, uint32_t data, uint32_t sz); | 727 | uint32_t addr, uint32_t data, uint32_t sz); |
657 | int64_t opal_lpc_read(uint32_t chip_id, enum OpalLPCAddressType addr_type, | 728 | int64_t opal_lpc_read(uint32_t chip_id, enum OpalLPCAddressType addr_type, |
658 | uint32_t addr, uint32_t *data, uint32_t sz); | 729 | uint32_t addr, uint32_t *data, uint32_t sz); |
730 | int64_t opal_validate_flash(uint64_t buffer, uint32_t *size, uint32_t *result); | ||
731 | int64_t opal_manage_flash(uint8_t op); | ||
732 | int64_t opal_update_flash(uint64_t blk_list); | ||
659 | 733 | ||
660 | /* Internal functions */ | 734 | /* Internal functions */ |
661 | extern int early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data); | 735 | extern int early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data); |
@@ -684,6 +758,7 @@ extern int opal_set_rtc_time(struct rtc_time *tm); | |||
684 | extern void opal_get_rtc_time(struct rtc_time *tm); | 758 | extern void opal_get_rtc_time(struct rtc_time *tm); |
685 | extern unsigned long opal_get_boot_time(void); | 759 | extern unsigned long opal_get_boot_time(void); |
686 | extern void opal_nvram_init(void); | 760 | extern void opal_nvram_init(void); |
761 | extern void opal_flash_init(void); | ||
687 | 762 | ||
688 | extern int opal_machine_check(struct pt_regs *regs); | 763 | extern int opal_machine_check(struct pt_regs *regs); |
689 | 764 | ||
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h index a5954cebbc55..b6ea9e068c13 100644 --- a/arch/powerpc/include/asm/paca.h +++ b/arch/powerpc/include/asm/paca.h | |||
@@ -166,7 +166,7 @@ struct paca_struct { | |||
166 | struct dtl_entry *dtl_curr; /* pointer corresponding to dtl_ridx */ | 166 | struct dtl_entry *dtl_curr; /* pointer corresponding to dtl_ridx */ |
167 | 167 | ||
168 | #ifdef CONFIG_KVM_BOOK3S_HANDLER | 168 | #ifdef CONFIG_KVM_BOOK3S_HANDLER |
169 | #ifdef CONFIG_KVM_BOOK3S_PR | 169 | #ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE |
170 | /* We use this to store guest state in */ | 170 | /* We use this to store guest state in */ |
171 | struct kvmppc_book3s_shadow_vcpu shadow_vcpu; | 171 | struct kvmppc_book3s_shadow_vcpu shadow_vcpu; |
172 | #endif | 172 | #endif |
diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h index b9f426212d3a..32e4e212b9c1 100644 --- a/arch/powerpc/include/asm/page.h +++ b/arch/powerpc/include/asm/page.h | |||
@@ -78,7 +78,7 @@ extern unsigned int HPAGE_SHIFT; | |||
78 | * | 78 | * |
79 | * Also, KERNELBASE >= PAGE_OFFSET and PHYSICAL_START >= MEMORY_START | 79 | * Also, KERNELBASE >= PAGE_OFFSET and PHYSICAL_START >= MEMORY_START |
80 | * | 80 | * |
81 | * There are two was to determine a physical address from a virtual one: | 81 | * There are two ways to determine a physical address from a virtual one: |
82 | * va = pa + PAGE_OFFSET - MEMORY_START | 82 | * va = pa + PAGE_OFFSET - MEMORY_START |
83 | * va = pa + KERNELBASE - PHYSICAL_START | 83 | * va = pa + KERNELBASE - PHYSICAL_START |
84 | * | 84 | * |
@@ -403,7 +403,7 @@ void arch_free_page(struct page *page, int order); | |||
403 | 403 | ||
404 | struct vm_area_struct; | 404 | struct vm_area_struct; |
405 | 405 | ||
406 | #ifdef CONFIG_PPC_64K_PAGES | 406 | #if defined(CONFIG_PPC_64K_PAGES) && defined(CONFIG_PPC64) |
407 | typedef pte_t *pgtable_t; | 407 | typedef pte_t *pgtable_t; |
408 | #else | 408 | #else |
409 | typedef struct page *pgtable_t; | 409 | typedef struct page *pgtable_t; |
diff --git a/arch/powerpc/include/asm/pgalloc-64.h b/arch/powerpc/include/asm/pgalloc-64.h index f65e27b09bd3..16cb92d215d2 100644 --- a/arch/powerpc/include/asm/pgalloc-64.h +++ b/arch/powerpc/include/asm/pgalloc-64.h | |||
@@ -91,7 +91,10 @@ static inline pgtable_t pte_alloc_one(struct mm_struct *mm, | |||
91 | if (!pte) | 91 | if (!pte) |
92 | return NULL; | 92 | return NULL; |
93 | page = virt_to_page(pte); | 93 | page = virt_to_page(pte); |
94 | pgtable_page_ctor(page); | 94 | if (!pgtable_page_ctor(page)) { |
95 | __free_page(page); | ||
96 | return NULL; | ||
97 | } | ||
95 | return page; | 98 | return page; |
96 | } | 99 | } |
97 | 100 | ||
diff --git a/arch/powerpc/include/asm/pgtable-ppc64.h b/arch/powerpc/include/asm/pgtable-ppc64.h index 46db09414a10..4a191c472867 100644 --- a/arch/powerpc/include/asm/pgtable-ppc64.h +++ b/arch/powerpc/include/asm/pgtable-ppc64.h | |||
@@ -394,6 +394,8 @@ static inline void mark_hpte_slot_valid(unsigned char *hpte_slot_array, | |||
394 | hpte_slot_array[index] = hidx << 4 | 0x1 << 3; | 394 | hpte_slot_array[index] = hidx << 4 | 0x1 << 3; |
395 | } | 395 | } |
396 | 396 | ||
397 | struct page *realmode_pfn_to_page(unsigned long pfn); | ||
398 | |||
397 | static inline char *get_hpte_slot_array(pmd_t *pmdp) | 399 | static inline char *get_hpte_slot_array(pmd_t *pmdp) |
398 | { | 400 | { |
399 | /* | 401 | /* |
diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h index d7fe9f5b46d4..3132bb9365f3 100644 --- a/arch/powerpc/include/asm/ppc-opcode.h +++ b/arch/powerpc/include/asm/ppc-opcode.h | |||
@@ -143,6 +143,8 @@ | |||
143 | #define PPC_INST_LSWX 0x7c00042a | 143 | #define PPC_INST_LSWX 0x7c00042a |
144 | #define PPC_INST_LWARX 0x7c000028 | 144 | #define PPC_INST_LWARX 0x7c000028 |
145 | #define PPC_INST_LWSYNC 0x7c2004ac | 145 | #define PPC_INST_LWSYNC 0x7c2004ac |
146 | #define PPC_INST_SYNC 0x7c0004ac | ||
147 | #define PPC_INST_SYNC_MASK 0xfc0007fe | ||
146 | #define PPC_INST_LXVD2X 0x7c000698 | 148 | #define PPC_INST_LXVD2X 0x7c000698 |
147 | #define PPC_INST_MCRXR 0x7c000400 | 149 | #define PPC_INST_MCRXR 0x7c000400 |
148 | #define PPC_INST_MCRXR_MASK 0xfc0007fe | 150 | #define PPC_INST_MCRXR_MASK 0xfc0007fe |
@@ -181,6 +183,7 @@ | |||
181 | #define PPC_INST_TLBIVAX 0x7c000624 | 183 | #define PPC_INST_TLBIVAX 0x7c000624 |
182 | #define PPC_INST_TLBSRX_DOT 0x7c0006a5 | 184 | #define PPC_INST_TLBSRX_DOT 0x7c0006a5 |
183 | #define PPC_INST_XXLOR 0xf0000510 | 185 | #define PPC_INST_XXLOR 0xf0000510 |
186 | #define PPC_INST_XXSWAPD 0xf0000250 | ||
184 | #define PPC_INST_XVCPSGNDP 0xf0000780 | 187 | #define PPC_INST_XVCPSGNDP 0xf0000780 |
185 | #define PPC_INST_TRECHKPT 0x7c0007dd | 188 | #define PPC_INST_TRECHKPT 0x7c0007dd |
186 | #define PPC_INST_TRECLAIM 0x7c00075d | 189 | #define PPC_INST_TRECLAIM 0x7c00075d |
@@ -200,6 +203,7 @@ | |||
200 | /* Misc instructions for BPF compiler */ | 203 | /* Misc instructions for BPF compiler */ |
201 | #define PPC_INST_LD 0xe8000000 | 204 | #define PPC_INST_LD 0xe8000000 |
202 | #define PPC_INST_LHZ 0xa0000000 | 205 | #define PPC_INST_LHZ 0xa0000000 |
206 | #define PPC_INST_LHBRX 0x7c00062c | ||
203 | #define PPC_INST_LWZ 0x80000000 | 207 | #define PPC_INST_LWZ 0x80000000 |
204 | #define PPC_INST_STD 0xf8000000 | 208 | #define PPC_INST_STD 0xf8000000 |
205 | #define PPC_INST_STDU 0xf8000001 | 209 | #define PPC_INST_STDU 0xf8000001 |
@@ -218,7 +222,7 @@ | |||
218 | #define PPC_INST_MULLW 0x7c0001d6 | 222 | #define PPC_INST_MULLW 0x7c0001d6 |
219 | #define PPC_INST_MULHWU 0x7c000016 | 223 | #define PPC_INST_MULHWU 0x7c000016 |
220 | #define PPC_INST_MULLI 0x1c000000 | 224 | #define PPC_INST_MULLI 0x1c000000 |
221 | #define PPC_INST_DIVWU 0x7c0003d6 | 225 | #define PPC_INST_DIVWU 0x7c000396 |
222 | #define PPC_INST_RLWINM 0x54000000 | 226 | #define PPC_INST_RLWINM 0x54000000 |
223 | #define PPC_INST_RLDICR 0x78000004 | 227 | #define PPC_INST_RLDICR 0x78000004 |
224 | #define PPC_INST_SLW 0x7c000030 | 228 | #define PPC_INST_SLW 0x7c000030 |
@@ -344,6 +348,8 @@ | |||
344 | VSX_XX1((s), a, b)) | 348 | VSX_XX1((s), a, b)) |
345 | #define XXLOR(t, a, b) stringify_in_c(.long PPC_INST_XXLOR | \ | 349 | #define XXLOR(t, a, b) stringify_in_c(.long PPC_INST_XXLOR | \ |
346 | VSX_XX3((t), a, b)) | 350 | VSX_XX3((t), a, b)) |
351 | #define XXSWAPD(t, a) stringify_in_c(.long PPC_INST_XXSWAPD | \ | ||
352 | VSX_XX3((t), a, a)) | ||
347 | #define XVCPSGNDP(t, a, b) stringify_in_c(.long (PPC_INST_XVCPSGNDP | \ | 353 | #define XVCPSGNDP(t, a, b) stringify_in_c(.long (PPC_INST_XVCPSGNDP | \ |
348 | VSX_XX3((t), (a), (b)))) | 354 | VSX_XX3((t), (a), (b)))) |
349 | 355 | ||
diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h index 599545738af3..3c1acc31a092 100644 --- a/arch/powerpc/include/asm/ppc_asm.h +++ b/arch/powerpc/include/asm/ppc_asm.h | |||
@@ -98,123 +98,51 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR) | |||
98 | #define REST_8GPRS(n, base) REST_4GPRS(n, base); REST_4GPRS(n+4, base) | 98 | #define REST_8GPRS(n, base) REST_4GPRS(n, base); REST_4GPRS(n+4, base) |
99 | #define REST_10GPRS(n, base) REST_8GPRS(n, base); REST_2GPRS(n+8, base) | 99 | #define REST_10GPRS(n, base) REST_8GPRS(n, base); REST_2GPRS(n+8, base) |
100 | 100 | ||
101 | #define SAVE_FPR(n, base) stfd n,THREAD_FPR0+8*TS_FPRWIDTH*(n)(base) | 101 | #define SAVE_FPR(n, base) stfd n,8*TS_FPRWIDTH*(n)(base) |
102 | #define SAVE_2FPRS(n, base) SAVE_FPR(n, base); SAVE_FPR(n+1, base) | 102 | #define SAVE_2FPRS(n, base) SAVE_FPR(n, base); SAVE_FPR(n+1, base) |
103 | #define SAVE_4FPRS(n, base) SAVE_2FPRS(n, base); SAVE_2FPRS(n+2, base) | 103 | #define SAVE_4FPRS(n, base) SAVE_2FPRS(n, base); SAVE_2FPRS(n+2, base) |
104 | #define SAVE_8FPRS(n, base) SAVE_4FPRS(n, base); SAVE_4FPRS(n+4, base) | 104 | #define SAVE_8FPRS(n, base) SAVE_4FPRS(n, base); SAVE_4FPRS(n+4, base) |
105 | #define SAVE_16FPRS(n, base) SAVE_8FPRS(n, base); SAVE_8FPRS(n+8, base) | 105 | #define SAVE_16FPRS(n, base) SAVE_8FPRS(n, base); SAVE_8FPRS(n+8, base) |
106 | #define SAVE_32FPRS(n, base) SAVE_16FPRS(n, base); SAVE_16FPRS(n+16, base) | 106 | #define SAVE_32FPRS(n, base) SAVE_16FPRS(n, base); SAVE_16FPRS(n+16, base) |
107 | #define REST_FPR(n, base) lfd n,THREAD_FPR0+8*TS_FPRWIDTH*(n)(base) | 107 | #define REST_FPR(n, base) lfd n,8*TS_FPRWIDTH*(n)(base) |
108 | #define REST_2FPRS(n, base) REST_FPR(n, base); REST_FPR(n+1, base) | 108 | #define REST_2FPRS(n, base) REST_FPR(n, base); REST_FPR(n+1, base) |
109 | #define REST_4FPRS(n, base) REST_2FPRS(n, base); REST_2FPRS(n+2, base) | 109 | #define REST_4FPRS(n, base) REST_2FPRS(n, base); REST_2FPRS(n+2, base) |
110 | #define REST_8FPRS(n, base) REST_4FPRS(n, base); REST_4FPRS(n+4, base) | 110 | #define REST_8FPRS(n, base) REST_4FPRS(n, base); REST_4FPRS(n+4, base) |
111 | #define REST_16FPRS(n, base) REST_8FPRS(n, base); REST_8FPRS(n+8, base) | 111 | #define REST_16FPRS(n, base) REST_8FPRS(n, base); REST_8FPRS(n+8, base) |
112 | #define REST_32FPRS(n, base) REST_16FPRS(n, base); REST_16FPRS(n+16, base) | 112 | #define REST_32FPRS(n, base) REST_16FPRS(n, base); REST_16FPRS(n+16, base) |
113 | 113 | ||
114 | #define SAVE_VR(n,b,base) li b,THREAD_VR0+(16*(n)); stvx n,base,b | 114 | #define SAVE_VR(n,b,base) li b,16*(n); stvx n,base,b |
115 | #define SAVE_2VRS(n,b,base) SAVE_VR(n,b,base); SAVE_VR(n+1,b,base) | 115 | #define SAVE_2VRS(n,b,base) SAVE_VR(n,b,base); SAVE_VR(n+1,b,base) |
116 | #define SAVE_4VRS(n,b,base) SAVE_2VRS(n,b,base); SAVE_2VRS(n+2,b,base) | 116 | #define SAVE_4VRS(n,b,base) SAVE_2VRS(n,b,base); SAVE_2VRS(n+2,b,base) |
117 | #define SAVE_8VRS(n,b,base) SAVE_4VRS(n,b,base); SAVE_4VRS(n+4,b,base) | 117 | #define SAVE_8VRS(n,b,base) SAVE_4VRS(n,b,base); SAVE_4VRS(n+4,b,base) |
118 | #define SAVE_16VRS(n,b,base) SAVE_8VRS(n,b,base); SAVE_8VRS(n+8,b,base) | 118 | #define SAVE_16VRS(n,b,base) SAVE_8VRS(n,b,base); SAVE_8VRS(n+8,b,base) |
119 | #define SAVE_32VRS(n,b,base) SAVE_16VRS(n,b,base); SAVE_16VRS(n+16,b,base) | 119 | #define SAVE_32VRS(n,b,base) SAVE_16VRS(n,b,base); SAVE_16VRS(n+16,b,base) |
120 | #define REST_VR(n,b,base) li b,THREAD_VR0+(16*(n)); lvx n,base,b | 120 | #define REST_VR(n,b,base) li b,16*(n); lvx n,base,b |
121 | #define REST_2VRS(n,b,base) REST_VR(n,b,base); REST_VR(n+1,b,base) | 121 | #define REST_2VRS(n,b,base) REST_VR(n,b,base); REST_VR(n+1,b,base) |
122 | #define REST_4VRS(n,b,base) REST_2VRS(n,b,base); REST_2VRS(n+2,b,base) | 122 | #define REST_4VRS(n,b,base) REST_2VRS(n,b,base); REST_2VRS(n+2,b,base) |
123 | #define REST_8VRS(n,b,base) REST_4VRS(n,b,base); REST_4VRS(n+4,b,base) | 123 | #define REST_8VRS(n,b,base) REST_4VRS(n,b,base); REST_4VRS(n+4,b,base) |
124 | #define REST_16VRS(n,b,base) REST_8VRS(n,b,base); REST_8VRS(n+8,b,base) | 124 | #define REST_16VRS(n,b,base) REST_8VRS(n,b,base); REST_8VRS(n+8,b,base) |
125 | #define REST_32VRS(n,b,base) REST_16VRS(n,b,base); REST_16VRS(n+16,b,base) | 125 | #define REST_32VRS(n,b,base) REST_16VRS(n,b,base); REST_16VRS(n+16,b,base) |
126 | 126 | ||
127 | /* Save/restore FPRs, VRs and VSRs from their checkpointed backups in | 127 | #ifdef __BIG_ENDIAN__ |
128 | * thread_struct: | 128 | #define STXVD2X_ROT(n,b,base) STXVD2X(n,b,base) |
129 | */ | 129 | #define LXVD2X_ROT(n,b,base) LXVD2X(n,b,base) |
130 | #define SAVE_FPR_TRANSACT(n, base) stfd n,THREAD_TRANSACT_FPR0+ \ | 130 | #else |
131 | 8*TS_FPRWIDTH*(n)(base) | 131 | #define STXVD2X_ROT(n,b,base) XXSWAPD(n,n); \ |
132 | #define SAVE_2FPRS_TRANSACT(n, base) SAVE_FPR_TRANSACT(n, base); \ | 132 | STXVD2X(n,b,base); \ |
133 | SAVE_FPR_TRANSACT(n+1, base) | 133 | XXSWAPD(n,n) |
134 | #define SAVE_4FPRS_TRANSACT(n, base) SAVE_2FPRS_TRANSACT(n, base); \ | ||
135 | SAVE_2FPRS_TRANSACT(n+2, base) | ||
136 | #define SAVE_8FPRS_TRANSACT(n, base) SAVE_4FPRS_TRANSACT(n, base); \ | ||
137 | SAVE_4FPRS_TRANSACT(n+4, base) | ||
138 | #define SAVE_16FPRS_TRANSACT(n, base) SAVE_8FPRS_TRANSACT(n, base); \ | ||
139 | SAVE_8FPRS_TRANSACT(n+8, base) | ||
140 | #define SAVE_32FPRS_TRANSACT(n, base) SAVE_16FPRS_TRANSACT(n, base); \ | ||
141 | SAVE_16FPRS_TRANSACT(n+16, base) | ||
142 | |||
143 | #define REST_FPR_TRANSACT(n, base) lfd n,THREAD_TRANSACT_FPR0+ \ | ||
144 | 8*TS_FPRWIDTH*(n)(base) | ||
145 | #define REST_2FPRS_TRANSACT(n, base) REST_FPR_TRANSACT(n, base); \ | ||
146 | REST_FPR_TRANSACT(n+1, base) | ||
147 | #define REST_4FPRS_TRANSACT(n, base) REST_2FPRS_TRANSACT(n, base); \ | ||
148 | REST_2FPRS_TRANSACT(n+2, base) | ||
149 | #define REST_8FPRS_TRANSACT(n, base) REST_4FPRS_TRANSACT(n, base); \ | ||
150 | REST_4FPRS_TRANSACT(n+4, base) | ||
151 | #define REST_16FPRS_TRANSACT(n, base) REST_8FPRS_TRANSACT(n, base); \ | ||
152 | REST_8FPRS_TRANSACT(n+8, base) | ||
153 | #define REST_32FPRS_TRANSACT(n, base) REST_16FPRS_TRANSACT(n, base); \ | ||
154 | REST_16FPRS_TRANSACT(n+16, base) | ||
155 | |||
156 | |||
157 | #define SAVE_VR_TRANSACT(n,b,base) li b,THREAD_TRANSACT_VR0+(16*(n)); \ | ||
158 | stvx n,b,base | ||
159 | #define SAVE_2VRS_TRANSACT(n,b,base) SAVE_VR_TRANSACT(n,b,base); \ | ||
160 | SAVE_VR_TRANSACT(n+1,b,base) | ||
161 | #define SAVE_4VRS_TRANSACT(n,b,base) SAVE_2VRS_TRANSACT(n,b,base); \ | ||
162 | SAVE_2VRS_TRANSACT(n+2,b,base) | ||
163 | #define SAVE_8VRS_TRANSACT(n,b,base) SAVE_4VRS_TRANSACT(n,b,base); \ | ||
164 | SAVE_4VRS_TRANSACT(n+4,b,base) | ||
165 | #define SAVE_16VRS_TRANSACT(n,b,base) SAVE_8VRS_TRANSACT(n,b,base); \ | ||
166 | SAVE_8VRS_TRANSACT(n+8,b,base) | ||
167 | #define SAVE_32VRS_TRANSACT(n,b,base) SAVE_16VRS_TRANSACT(n,b,base); \ | ||
168 | SAVE_16VRS_TRANSACT(n+16,b,base) | ||
169 | |||
170 | #define REST_VR_TRANSACT(n,b,base) li b,THREAD_TRANSACT_VR0+(16*(n)); \ | ||
171 | lvx n,b,base | ||
172 | #define REST_2VRS_TRANSACT(n,b,base) REST_VR_TRANSACT(n,b,base); \ | ||
173 | REST_VR_TRANSACT(n+1,b,base) | ||
174 | #define REST_4VRS_TRANSACT(n,b,base) REST_2VRS_TRANSACT(n,b,base); \ | ||
175 | REST_2VRS_TRANSACT(n+2,b,base) | ||
176 | #define REST_8VRS_TRANSACT(n,b,base) REST_4VRS_TRANSACT(n,b,base); \ | ||
177 | REST_4VRS_TRANSACT(n+4,b,base) | ||
178 | #define REST_16VRS_TRANSACT(n,b,base) REST_8VRS_TRANSACT(n,b,base); \ | ||
179 | REST_8VRS_TRANSACT(n+8,b,base) | ||
180 | #define REST_32VRS_TRANSACT(n,b,base) REST_16VRS_TRANSACT(n,b,base); \ | ||
181 | REST_16VRS_TRANSACT(n+16,b,base) | ||
182 | |||
183 | |||
184 | #define SAVE_VSR_TRANSACT(n,b,base) li b,THREAD_TRANSACT_VSR0+(16*(n)); \ | ||
185 | STXVD2X(n,R##base,R##b) | ||
186 | #define SAVE_2VSRS_TRANSACT(n,b,base) SAVE_VSR_TRANSACT(n,b,base); \ | ||
187 | SAVE_VSR_TRANSACT(n+1,b,base) | ||
188 | #define SAVE_4VSRS_TRANSACT(n,b,base) SAVE_2VSRS_TRANSACT(n,b,base); \ | ||
189 | SAVE_2VSRS_TRANSACT(n+2,b,base) | ||
190 | #define SAVE_8VSRS_TRANSACT(n,b,base) SAVE_4VSRS_TRANSACT(n,b,base); \ | ||
191 | SAVE_4VSRS_TRANSACT(n+4,b,base) | ||
192 | #define SAVE_16VSRS_TRANSACT(n,b,base) SAVE_8VSRS_TRANSACT(n,b,base); \ | ||
193 | SAVE_8VSRS_TRANSACT(n+8,b,base) | ||
194 | #define SAVE_32VSRS_TRANSACT(n,b,base) SAVE_16VSRS_TRANSACT(n,b,base); \ | ||
195 | SAVE_16VSRS_TRANSACT(n+16,b,base) | ||
196 | |||
197 | #define REST_VSR_TRANSACT(n,b,base) li b,THREAD_TRANSACT_VSR0+(16*(n)); \ | ||
198 | LXVD2X(n,R##base,R##b) | ||
199 | #define REST_2VSRS_TRANSACT(n,b,base) REST_VSR_TRANSACT(n,b,base); \ | ||
200 | REST_VSR_TRANSACT(n+1,b,base) | ||
201 | #define REST_4VSRS_TRANSACT(n,b,base) REST_2VSRS_TRANSACT(n,b,base); \ | ||
202 | REST_2VSRS_TRANSACT(n+2,b,base) | ||
203 | #define REST_8VSRS_TRANSACT(n,b,base) REST_4VSRS_TRANSACT(n,b,base); \ | ||
204 | REST_4VSRS_TRANSACT(n+4,b,base) | ||
205 | #define REST_16VSRS_TRANSACT(n,b,base) REST_8VSRS_TRANSACT(n,b,base); \ | ||
206 | REST_8VSRS_TRANSACT(n+8,b,base) | ||
207 | #define REST_32VSRS_TRANSACT(n,b,base) REST_16VSRS_TRANSACT(n,b,base); \ | ||
208 | REST_16VSRS_TRANSACT(n+16,b,base) | ||
209 | 134 | ||
135 | #define LXVD2X_ROT(n,b,base) LXVD2X(n,b,base); \ | ||
136 | XXSWAPD(n,n) | ||
137 | #endif | ||
210 | /* Save the lower 32 VSRs in the thread VSR region */ | 138 | /* Save the lower 32 VSRs in the thread VSR region */ |
211 | #define SAVE_VSR(n,b,base) li b,THREAD_VSR0+(16*(n)); STXVD2X(n,R##base,R##b) | 139 | #define SAVE_VSR(n,b,base) li b,16*(n); STXVD2X_ROT(n,R##base,R##b) |
212 | #define SAVE_2VSRS(n,b,base) SAVE_VSR(n,b,base); SAVE_VSR(n+1,b,base) | 140 | #define SAVE_2VSRS(n,b,base) SAVE_VSR(n,b,base); SAVE_VSR(n+1,b,base) |
213 | #define SAVE_4VSRS(n,b,base) SAVE_2VSRS(n,b,base); SAVE_2VSRS(n+2,b,base) | 141 | #define SAVE_4VSRS(n,b,base) SAVE_2VSRS(n,b,base); SAVE_2VSRS(n+2,b,base) |
214 | #define SAVE_8VSRS(n,b,base) SAVE_4VSRS(n,b,base); SAVE_4VSRS(n+4,b,base) | 142 | #define SAVE_8VSRS(n,b,base) SAVE_4VSRS(n,b,base); SAVE_4VSRS(n+4,b,base) |
215 | #define SAVE_16VSRS(n,b,base) SAVE_8VSRS(n,b,base); SAVE_8VSRS(n+8,b,base) | 143 | #define SAVE_16VSRS(n,b,base) SAVE_8VSRS(n,b,base); SAVE_8VSRS(n+8,b,base) |
216 | #define SAVE_32VSRS(n,b,base) SAVE_16VSRS(n,b,base); SAVE_16VSRS(n+16,b,base) | 144 | #define SAVE_32VSRS(n,b,base) SAVE_16VSRS(n,b,base); SAVE_16VSRS(n+16,b,base) |
217 | #define REST_VSR(n,b,base) li b,THREAD_VSR0+(16*(n)); LXVD2X(n,R##base,R##b) | 145 | #define REST_VSR(n,b,base) li b,16*(n); LXVD2X_ROT(n,R##base,R##b) |
218 | #define REST_2VSRS(n,b,base) REST_VSR(n,b,base); REST_VSR(n+1,b,base) | 146 | #define REST_2VSRS(n,b,base) REST_VSR(n,b,base); REST_VSR(n+1,b,base) |
219 | #define REST_4VSRS(n,b,base) REST_2VSRS(n,b,base); REST_2VSRS(n+2,b,base) | 147 | #define REST_4VSRS(n,b,base) REST_2VSRS(n,b,base); REST_2VSRS(n+2,b,base) |
220 | #define REST_8VSRS(n,b,base) REST_4VSRS(n,b,base); REST_4VSRS(n+4,b,base) | 148 | #define REST_8VSRS(n,b,base) REST_4VSRS(n,b,base); REST_4VSRS(n+4,b,base) |
@@ -478,13 +406,6 @@ BEGIN_FTR_SECTION_NESTED(945) \ | |||
478 | std ra,TASKTHREADPPR(rb); \ | 406 | std ra,TASKTHREADPPR(rb); \ |
479 | END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,945) | 407 | END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,945) |
480 | 408 | ||
481 | #define RESTORE_PPR(ra, rb) \ | ||
482 | BEGIN_FTR_SECTION_NESTED(946) \ | ||
483 | ld ra,PACACURRENT(r13); \ | ||
484 | ld rb,TASKTHREADPPR(ra); \ | ||
485 | mtspr SPRN_PPR,rb; /* Restore PPR */ \ | ||
486 | END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,946) | ||
487 | |||
488 | #endif | 409 | #endif |
489 | 410 | ||
490 | /* | 411 | /* |
@@ -832,6 +753,35 @@ END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,946) | |||
832 | #define N_SLINE 68 | 753 | #define N_SLINE 68 |
833 | #define N_SO 100 | 754 | #define N_SO 100 |
834 | 755 | ||
835 | #endif /* __ASSEMBLY__ */ | 756 | /* |
757 | * Create an endian fixup trampoline | ||
758 | * | ||
759 | * This starts with a "tdi 0,0,0x48" instruction which is | ||
760 | * essentially a "trap never", and thus akin to a nop. | ||
761 | * | ||
762 | * The opcode for this instruction read with the wrong endian | ||
763 | * however results in a b . + 8 | ||
764 | * | ||
765 | * So essentially we use that trick to execute the following | ||
766 | * trampoline in "reverse endian" if we are running with the | ||
767 | * MSR_LE bit set the "wrong" way for whatever endianness the | ||
768 | * kernel is built for. | ||
769 | */ | ||
836 | 770 | ||
771 | #ifdef CONFIG_PPC_BOOK3E | ||
772 | #define FIXUP_ENDIAN | ||
773 | #else | ||
774 | #define FIXUP_ENDIAN \ | ||
775 | tdi 0,0,0x48; /* Reverse endian of b . + 8 */ \ | ||
776 | b $+36; /* Skip trampoline if endian is good */ \ | ||
777 | .long 0x05009f42; /* bcl 20,31,$+4 */ \ | ||
778 | .long 0xa602487d; /* mflr r10 */ \ | ||
779 | .long 0x1c004a39; /* addi r10,r10,28 */ \ | ||
780 | .long 0xa600607d; /* mfmsr r11 */ \ | ||
781 | .long 0x01006b69; /* xori r11,r11,1 */ \ | ||
782 | .long 0xa6035a7d; /* mtsrr0 r10 */ \ | ||
783 | .long 0xa6037b7d; /* mtsrr1 r11 */ \ | ||
784 | .long 0x2400004c /* rfid */ | ||
785 | #endif /* !CONFIG_PPC_BOOK3E */ | ||
786 | #endif /* __ASSEMBLY__ */ | ||
837 | #endif /* _ASM_POWERPC_PPC_ASM_H */ | 787 | #endif /* _ASM_POWERPC_PPC_ASM_H */ |
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h index e378cccfca55..fc14a38c7ccf 100644 --- a/arch/powerpc/include/asm/processor.h +++ b/arch/powerpc/include/asm/processor.h | |||
@@ -14,8 +14,18 @@ | |||
14 | 14 | ||
15 | #ifdef CONFIG_VSX | 15 | #ifdef CONFIG_VSX |
16 | #define TS_FPRWIDTH 2 | 16 | #define TS_FPRWIDTH 2 |
17 | |||
18 | #ifdef __BIG_ENDIAN__ | ||
19 | #define TS_FPROFFSET 0 | ||
20 | #define TS_VSRLOWOFFSET 1 | ||
21 | #else | ||
22 | #define TS_FPROFFSET 1 | ||
23 | #define TS_VSRLOWOFFSET 0 | ||
24 | #endif | ||
25 | |||
17 | #else | 26 | #else |
18 | #define TS_FPRWIDTH 1 | 27 | #define TS_FPRWIDTH 1 |
28 | #define TS_FPROFFSET 0 | ||
19 | #endif | 29 | #endif |
20 | 30 | ||
21 | #ifdef CONFIG_PPC64 | 31 | #ifdef CONFIG_PPC64 |
@@ -142,27 +152,22 @@ typedef struct { | |||
142 | unsigned long seg; | 152 | unsigned long seg; |
143 | } mm_segment_t; | 153 | } mm_segment_t; |
144 | 154 | ||
145 | #define TS_FPROFFSET 0 | 155 | #define TS_FPR(i) fp_state.fpr[i][TS_FPROFFSET] |
146 | #define TS_VSRLOWOFFSET 1 | 156 | #define TS_TRANS_FPR(i) transact_fp.fpr[i][TS_FPROFFSET] |
147 | #define TS_FPR(i) fpr[i][TS_FPROFFSET] | ||
148 | #define TS_TRANS_FPR(i) transact_fpr[i][TS_FPROFFSET] | ||
149 | 157 | ||
150 | struct thread_struct { | 158 | /* FP and VSX 0-31 register set */ |
151 | unsigned long ksp; /* Kernel stack pointer */ | 159 | struct thread_fp_state { |
152 | unsigned long ksp_limit; /* if ksp <= ksp_limit stack overflow */ | 160 | u64 fpr[32][TS_FPRWIDTH] __attribute__((aligned(16))); |
161 | u64 fpscr; /* Floating point status */ | ||
162 | }; | ||
153 | 163 | ||
154 | #ifdef CONFIG_PPC64 | 164 | /* Complete AltiVec register set including VSCR */ |
155 | unsigned long ksp_vsid; | 165 | struct thread_vr_state { |
156 | #endif | 166 | vector128 vr[32] __attribute__((aligned(16))); |
157 | struct pt_regs *regs; /* Pointer to saved register state */ | 167 | vector128 vscr __attribute__((aligned(16))); |
158 | mm_segment_t fs; /* for get_fs() validation */ | 168 | }; |
159 | #ifdef CONFIG_BOOKE | 169 | |
160 | /* BookE base exception scratch space; align on cacheline */ | 170 | struct debug_reg { |
161 | unsigned long normsave[8] ____cacheline_aligned; | ||
162 | #endif | ||
163 | #ifdef CONFIG_PPC32 | ||
164 | void *pgdir; /* root of page-table tree */ | ||
165 | #endif | ||
166 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | 171 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS |
167 | /* | 172 | /* |
168 | * The following help to manage the use of Debug Control Registers | 173 | * The following help to manage the use of Debug Control Registers |
@@ -199,13 +204,28 @@ struct thread_struct { | |||
199 | unsigned long dvc2; | 204 | unsigned long dvc2; |
200 | #endif | 205 | #endif |
201 | #endif | 206 | #endif |
202 | /* FP and VSX 0-31 register set */ | 207 | }; |
203 | double fpr[32][TS_FPRWIDTH] __attribute__((aligned(16))); | ||
204 | struct { | ||
205 | 208 | ||
206 | unsigned int pad; | 209 | struct thread_struct { |
207 | unsigned int val; /* Floating point status */ | 210 | unsigned long ksp; /* Kernel stack pointer */ |
208 | } fpscr; | 211 | |
212 | #ifdef CONFIG_PPC64 | ||
213 | unsigned long ksp_vsid; | ||
214 | #endif | ||
215 | struct pt_regs *regs; /* Pointer to saved register state */ | ||
216 | mm_segment_t fs; /* for get_fs() validation */ | ||
217 | #ifdef CONFIG_BOOKE | ||
218 | /* BookE base exception scratch space; align on cacheline */ | ||
219 | unsigned long normsave[8] ____cacheline_aligned; | ||
220 | #endif | ||
221 | #ifdef CONFIG_PPC32 | ||
222 | void *pgdir; /* root of page-table tree */ | ||
223 | unsigned long ksp_limit; /* if ksp <= ksp_limit stack overflow */ | ||
224 | #endif | ||
225 | /* Debug Registers */ | ||
226 | struct debug_reg debug; | ||
227 | struct thread_fp_state fp_state; | ||
228 | struct thread_fp_state *fp_save_area; | ||
209 | int fpexc_mode; /* floating-point exception mode */ | 229 | int fpexc_mode; /* floating-point exception mode */ |
210 | unsigned int align_ctl; /* alignment handling control */ | 230 | unsigned int align_ctl; /* alignment handling control */ |
211 | #ifdef CONFIG_PPC64 | 231 | #ifdef CONFIG_PPC64 |
@@ -223,10 +243,8 @@ struct thread_struct { | |||
223 | struct arch_hw_breakpoint hw_brk; /* info on the hardware breakpoint */ | 243 | struct arch_hw_breakpoint hw_brk; /* info on the hardware breakpoint */ |
224 | unsigned long trap_nr; /* last trap # on this thread */ | 244 | unsigned long trap_nr; /* last trap # on this thread */ |
225 | #ifdef CONFIG_ALTIVEC | 245 | #ifdef CONFIG_ALTIVEC |
226 | /* Complete AltiVec register set */ | 246 | struct thread_vr_state vr_state; |
227 | vector128 vr[32] __attribute__((aligned(16))); | 247 | struct thread_vr_state *vr_save_area; |
228 | /* AltiVec status */ | ||
229 | vector128 vscr __attribute__((aligned(16))); | ||
230 | unsigned long vrsave; | 248 | unsigned long vrsave; |
231 | int used_vr; /* set if process has used altivec */ | 249 | int used_vr; /* set if process has used altivec */ |
232 | #endif /* CONFIG_ALTIVEC */ | 250 | #endif /* CONFIG_ALTIVEC */ |
@@ -263,13 +281,8 @@ struct thread_struct { | |||
263 | * transact_fpr[] is the new set of transactional values. | 281 | * transact_fpr[] is the new set of transactional values. |
264 | * VRs work the same way. | 282 | * VRs work the same way. |
265 | */ | 283 | */ |
266 | double transact_fpr[32][TS_FPRWIDTH]; | 284 | struct thread_fp_state transact_fp; |
267 | struct { | 285 | struct thread_vr_state transact_vr; |
268 | unsigned int pad; | ||
269 | unsigned int val; /* Floating point status */ | ||
270 | } transact_fpscr; | ||
271 | vector128 transact_vr[32] __attribute__((aligned(16))); | ||
272 | vector128 transact_vscr __attribute__((aligned(16))); | ||
273 | unsigned long transact_vrsave; | 286 | unsigned long transact_vrsave; |
274 | #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ | 287 | #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ |
275 | #ifdef CONFIG_KVM_BOOK3S_32_HANDLER | 288 | #ifdef CONFIG_KVM_BOOK3S_32_HANDLER |
@@ -321,11 +334,8 @@ struct thread_struct { | |||
321 | #else | 334 | #else |
322 | #define INIT_THREAD { \ | 335 | #define INIT_THREAD { \ |
323 | .ksp = INIT_SP, \ | 336 | .ksp = INIT_SP, \ |
324 | .ksp_limit = INIT_SP_LIMIT, \ | ||
325 | .regs = (struct pt_regs *)INIT_SP - 1, /* XXX bogus, I think */ \ | 337 | .regs = (struct pt_regs *)INIT_SP - 1, /* XXX bogus, I think */ \ |
326 | .fs = KERNEL_DS, \ | 338 | .fs = KERNEL_DS, \ |
327 | .fpr = {{0}}, \ | ||
328 | .fpscr = { .val = 0, }, \ | ||
329 | .fpexc_mode = 0, \ | 339 | .fpexc_mode = 0, \ |
330 | .ppr = INIT_PPR, \ | 340 | .ppr = INIT_PPR, \ |
331 | } | 341 | } |
@@ -363,6 +373,11 @@ extern int set_endian(struct task_struct *tsk, unsigned int val); | |||
363 | extern int get_unalign_ctl(struct task_struct *tsk, unsigned long adr); | 373 | extern int get_unalign_ctl(struct task_struct *tsk, unsigned long adr); |
364 | extern int set_unalign_ctl(struct task_struct *tsk, unsigned int val); | 374 | extern int set_unalign_ctl(struct task_struct *tsk, unsigned int val); |
365 | 375 | ||
376 | extern void load_fp_state(struct thread_fp_state *fp); | ||
377 | extern void store_fp_state(struct thread_fp_state *fp); | ||
378 | extern void load_vr_state(struct thread_vr_state *vr); | ||
379 | extern void store_vr_state(struct thread_vr_state *vr); | ||
380 | |||
366 | static inline unsigned int __unpack_fe01(unsigned long msr_bits) | 381 | static inline unsigned int __unpack_fe01(unsigned long msr_bits) |
367 | { | 382 | { |
368 | return ((msr_bits & MSR_FE0) >> 10) | ((msr_bits & MSR_FE1) >> 8); | 383 | return ((msr_bits & MSR_FE0) >> 10) | ((msr_bits & MSR_FE1) >> 8); |
diff --git a/arch/powerpc/include/asm/prom.h b/arch/powerpc/include/asm/prom.h index 7d0c7f3a7171..d977b9b78696 100644 --- a/arch/powerpc/include/asm/prom.h +++ b/arch/powerpc/include/asm/prom.h | |||
@@ -1,4 +1,3 @@ | |||
1 | #include <linux/of.h> /* linux/of.h gets to determine #include ordering */ | ||
2 | #ifndef _POWERPC_PROM_H | 1 | #ifndef _POWERPC_PROM_H |
3 | #define _POWERPC_PROM_H | 2 | #define _POWERPC_PROM_H |
4 | #ifdef __KERNEL__ | 3 | #ifdef __KERNEL__ |
@@ -20,21 +19,17 @@ | |||
20 | #include <asm/irq.h> | 19 | #include <asm/irq.h> |
21 | #include <linux/atomic.h> | 20 | #include <linux/atomic.h> |
22 | 21 | ||
23 | #define HAVE_ARCH_DEVTREE_FIXUPS | 22 | /* These includes should be removed once implicit includes are cleaned up. */ |
23 | #include <linux/of.h> | ||
24 | #include <linux/of_fdt.h> | ||
25 | #include <linux/of_address.h> | ||
26 | #include <linux/of_irq.h> | ||
27 | #include <linux/platform_device.h> | ||
24 | 28 | ||
25 | /* | 29 | /* |
26 | * OF address retreival & translation | 30 | * OF address retreival & translation |
27 | */ | 31 | */ |
28 | 32 | ||
29 | /* Translate a DMA address from device space to CPU space */ | ||
30 | extern u64 of_translate_dma_address(struct device_node *dev, | ||
31 | const __be32 *in_addr); | ||
32 | |||
33 | #ifdef CONFIG_PCI | ||
34 | extern unsigned long pci_address_to_pio(phys_addr_t address); | ||
35 | #define pci_address_to_pio pci_address_to_pio | ||
36 | #endif /* CONFIG_PCI */ | ||
37 | |||
38 | /* Parse the ibm,dma-window property of an OF node into the busno, phys and | 33 | /* Parse the ibm,dma-window property of an OF node into the busno, phys and |
39 | * size parameters. | 34 | * size parameters. |
40 | */ | 35 | */ |
@@ -44,16 +39,6 @@ void of_parse_dma_window(struct device_node *dn, const __be32 *dma_window, | |||
44 | 39 | ||
45 | extern void kdump_move_device_tree(void); | 40 | extern void kdump_move_device_tree(void); |
46 | 41 | ||
47 | /* cache lookup */ | ||
48 | struct device_node *of_find_next_cache_node(struct device_node *np); | ||
49 | |||
50 | #ifdef CONFIG_NUMA | ||
51 | extern int of_node_to_nid(struct device_node *device); | ||
52 | #else | ||
53 | static inline int of_node_to_nid(struct device_node *device) { return 0; } | ||
54 | #endif | ||
55 | #define of_node_to_nid of_node_to_nid | ||
56 | |||
57 | extern void of_instantiate_rtc(void); | 42 | extern void of_instantiate_rtc(void); |
58 | 43 | ||
59 | extern int of_get_ibm_chip_id(struct device_node *np); | 44 | extern int of_get_ibm_chip_id(struct device_node *np); |
@@ -143,14 +128,5 @@ struct of_drconf_cell { | |||
143 | */ | 128 | */ |
144 | extern unsigned char ibm_architecture_vec[]; | 129 | extern unsigned char ibm_architecture_vec[]; |
145 | 130 | ||
146 | /* These includes are put at the bottom because they may contain things | ||
147 | * that are overridden by this file. Ideally they shouldn't be included | ||
148 | * by this file, but there are a bunch of .c files that currently depend | ||
149 | * on it. Eventually they will be cleaned up. */ | ||
150 | #include <linux/of_fdt.h> | ||
151 | #include <linux/of_address.h> | ||
152 | #include <linux/of_irq.h> | ||
153 | #include <linux/platform_device.h> | ||
154 | |||
155 | #endif /* __KERNEL__ */ | 131 | #endif /* __KERNEL__ */ |
156 | #endif /* _POWERPC_PROM_H */ | 132 | #endif /* _POWERPC_PROM_H */ |
diff --git a/arch/powerpc/include/asm/pte-book3e.h b/arch/powerpc/include/asm/pte-book3e.h index 0156702ba24e..576ad88104cb 100644 --- a/arch/powerpc/include/asm/pte-book3e.h +++ b/arch/powerpc/include/asm/pte-book3e.h | |||
@@ -40,7 +40,7 @@ | |||
40 | #define _PAGE_U1 0x010000 | 40 | #define _PAGE_U1 0x010000 |
41 | #define _PAGE_U0 0x020000 | 41 | #define _PAGE_U0 0x020000 |
42 | #define _PAGE_ACCESSED 0x040000 | 42 | #define _PAGE_ACCESSED 0x040000 |
43 | #define _PAGE_LENDIAN 0x080000 | 43 | #define _PAGE_ENDIAN 0x080000 |
44 | #define _PAGE_GUARDED 0x100000 | 44 | #define _PAGE_GUARDED 0x100000 |
45 | #define _PAGE_COHERENT 0x200000 /* M: enforce memory coherence */ | 45 | #define _PAGE_COHERENT 0x200000 /* M: enforce memory coherence */ |
46 | #define _PAGE_NO_CACHE 0x400000 /* I: cache inhibit */ | 46 | #define _PAGE_NO_CACHE 0x400000 /* I: cache inhibit */ |
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index 10d1ef016bf1..5c45787d551e 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h | |||
@@ -115,7 +115,12 @@ | |||
115 | #define MSR_64BIT MSR_SF | 115 | #define MSR_64BIT MSR_SF |
116 | 116 | ||
117 | /* Server variant */ | 117 | /* Server variant */ |
118 | #define MSR_ (MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_ISF |MSR_HV) | 118 | #define __MSR (MSR_ME | MSR_RI | MSR_IR | MSR_DR | MSR_ISF |MSR_HV) |
119 | #ifdef __BIG_ENDIAN__ | ||
120 | #define MSR_ __MSR | ||
121 | #else | ||
122 | #define MSR_ (__MSR | MSR_LE) | ||
123 | #endif | ||
119 | #define MSR_KERNEL (MSR_ | MSR_64BIT) | 124 | #define MSR_KERNEL (MSR_ | MSR_64BIT) |
120 | #define MSR_USER32 (MSR_ | MSR_PR | MSR_EE) | 125 | #define MSR_USER32 (MSR_ | MSR_PR | MSR_EE) |
121 | #define MSR_USER64 (MSR_USER32 | MSR_64BIT) | 126 | #define MSR_USER64 (MSR_USER32 | MSR_64BIT) |
@@ -243,6 +248,7 @@ | |||
243 | #define SPRN_TBRU 0x10D /* Time Base Read Upper Register (user, R/O) */ | 248 | #define SPRN_TBRU 0x10D /* Time Base Read Upper Register (user, R/O) */ |
244 | #define SPRN_TBWL 0x11C /* Time Base Lower Register (super, R/W) */ | 249 | #define SPRN_TBWL 0x11C /* Time Base Lower Register (super, R/W) */ |
245 | #define SPRN_TBWU 0x11D /* Time Base Upper Register (super, R/W) */ | 250 | #define SPRN_TBWU 0x11D /* Time Base Upper Register (super, R/W) */ |
251 | #define SPRN_TBU40 0x11E /* Timebase upper 40 bits (hyper, R/W) */ | ||
246 | #define SPRN_SPURR 0x134 /* Scaled PURR */ | 252 | #define SPRN_SPURR 0x134 /* Scaled PURR */ |
247 | #define SPRN_HSPRG0 0x130 /* Hypervisor Scratch 0 */ | 253 | #define SPRN_HSPRG0 0x130 /* Hypervisor Scratch 0 */ |
248 | #define SPRN_HSPRG1 0x131 /* Hypervisor Scratch 1 */ | 254 | #define SPRN_HSPRG1 0x131 /* Hypervisor Scratch 1 */ |
@@ -283,6 +289,7 @@ | |||
283 | #define LPCR_ISL (1ul << (63-2)) | 289 | #define LPCR_ISL (1ul << (63-2)) |
284 | #define LPCR_VC_SH (63-2) | 290 | #define LPCR_VC_SH (63-2) |
285 | #define LPCR_DPFD_SH (63-11) | 291 | #define LPCR_DPFD_SH (63-11) |
292 | #define LPCR_DPFD (7ul << LPCR_DPFD_SH) | ||
286 | #define LPCR_VRMASD (0x1ful << (63-16)) | 293 | #define LPCR_VRMASD (0x1ful << (63-16)) |
287 | #define LPCR_VRMA_L (1ul << (63-12)) | 294 | #define LPCR_VRMA_L (1ul << (63-12)) |
288 | #define LPCR_VRMA_LP0 (1ul << (63-15)) | 295 | #define LPCR_VRMA_LP0 (1ul << (63-15)) |
@@ -299,6 +306,7 @@ | |||
299 | #define LPCR_PECE2 0x00001000 /* machine check etc can cause exit */ | 306 | #define LPCR_PECE2 0x00001000 /* machine check etc can cause exit */ |
300 | #define LPCR_MER 0x00000800 /* Mediated External Exception */ | 307 | #define LPCR_MER 0x00000800 /* Mediated External Exception */ |
301 | #define LPCR_MER_SH 11 | 308 | #define LPCR_MER_SH 11 |
309 | #define LPCR_TC 0x00000200 /* Translation control */ | ||
302 | #define LPCR_LPES 0x0000000c | 310 | #define LPCR_LPES 0x0000000c |
303 | #define LPCR_LPES0 0x00000008 /* LPAR Env selector 0 */ | 311 | #define LPCR_LPES0 0x00000008 /* LPAR Env selector 0 */ |
304 | #define LPCR_LPES1 0x00000004 /* LPAR Env selector 1 */ | 312 | #define LPCR_LPES1 0x00000004 /* LPAR Env selector 1 */ |
@@ -311,6 +319,10 @@ | |||
311 | #define LPID_RSVD 0x3ff /* Reserved LPID for partn switching */ | 319 | #define LPID_RSVD 0x3ff /* Reserved LPID for partn switching */ |
312 | #define SPRN_HMER 0x150 /* Hardware m? error recovery */ | 320 | #define SPRN_HMER 0x150 /* Hardware m? error recovery */ |
313 | #define SPRN_HMEER 0x151 /* Hardware m? enable error recovery */ | 321 | #define SPRN_HMEER 0x151 /* Hardware m? enable error recovery */ |
322 | #define SPRN_PCR 0x152 /* Processor compatibility register */ | ||
323 | #define PCR_VEC_DIS (1ul << (63-0)) /* Vec. disable (bit NA since POWER8) */ | ||
324 | #define PCR_VSX_DIS (1ul << (63-1)) /* VSX disable (bit NA since POWER8) */ | ||
325 | #define PCR_ARCH_205 0x2 /* Architecture 2.05 */ | ||
314 | #define SPRN_HEIR 0x153 /* Hypervisor Emulated Instruction Register */ | 326 | #define SPRN_HEIR 0x153 /* Hypervisor Emulated Instruction Register */ |
315 | #define SPRN_TLBINDEXR 0x154 /* P7 TLB control register */ | 327 | #define SPRN_TLBINDEXR 0x154 /* P7 TLB control register */ |
316 | #define SPRN_TLBVPNR 0x155 /* P7 TLB control register */ | 328 | #define SPRN_TLBVPNR 0x155 /* P7 TLB control register */ |
@@ -420,6 +432,7 @@ | |||
420 | #define HID4_RMLS2_SH (63 - 2) /* Real mode limit bottom 2 bits */ | 432 | #define HID4_RMLS2_SH (63 - 2) /* Real mode limit bottom 2 bits */ |
421 | #define HID4_LPID5_SH (63 - 6) /* partition ID bottom 4 bits */ | 433 | #define HID4_LPID5_SH (63 - 6) /* partition ID bottom 4 bits */ |
422 | #define HID4_RMOR_SH (63 - 22) /* real mode offset (16 bits) */ | 434 | #define HID4_RMOR_SH (63 - 22) /* real mode offset (16 bits) */ |
435 | #define HID4_RMOR (0xFFFFul << HID4_RMOR_SH) | ||
423 | #define HID4_LPES1 (1 << (63-57)) /* LPAR env. sel. bit 1 */ | 436 | #define HID4_LPES1 (1 << (63-57)) /* LPAR env. sel. bit 1 */ |
424 | #define HID4_RMLS0_SH (63 - 58) /* Real mode limit top bit */ | 437 | #define HID4_RMLS0_SH (63 - 58) /* Real mode limit top bit */ |
425 | #define HID4_LPID1_SH 0 /* partition ID top 2 bits */ | 438 | #define HID4_LPID1_SH 0 /* partition ID top 2 bits */ |
@@ -1102,6 +1115,13 @@ | |||
1102 | #define PVR_BE 0x0070 | 1115 | #define PVR_BE 0x0070 |
1103 | #define PVR_PA6T 0x0090 | 1116 | #define PVR_PA6T 0x0090 |
1104 | 1117 | ||
1118 | /* "Logical" PVR values defined in PAPR, representing architecture levels */ | ||
1119 | #define PVR_ARCH_204 0x0f000001 | ||
1120 | #define PVR_ARCH_205 0x0f000002 | ||
1121 | #define PVR_ARCH_206 0x0f000003 | ||
1122 | #define PVR_ARCH_206p 0x0f100003 | ||
1123 | #define PVR_ARCH_207 0x0f000004 | ||
1124 | |||
1105 | /* Macros for setting and retrieving special purpose registers */ | 1125 | /* Macros for setting and retrieving special purpose registers */ |
1106 | #ifndef __ASSEMBLY__ | 1126 | #ifndef __ASSEMBLY__ |
1107 | #define mfmsr() ({unsigned long rval; \ | 1127 | #define mfmsr() ({unsigned long rval; \ |
diff --git a/arch/powerpc/include/asm/reg_booke.h b/arch/powerpc/include/asm/reg_booke.h index ed8f836da094..2e31aacd8acc 100644 --- a/arch/powerpc/include/asm/reg_booke.h +++ b/arch/powerpc/include/asm/reg_booke.h | |||
@@ -381,7 +381,7 @@ | |||
381 | #define DBCR0_IA34T 0x00004000 /* Instr Addr 3-4 range Toggle */ | 381 | #define DBCR0_IA34T 0x00004000 /* Instr Addr 3-4 range Toggle */ |
382 | #define DBCR0_FT 0x00000001 /* Freeze Timers on debug event */ | 382 | #define DBCR0_FT 0x00000001 /* Freeze Timers on debug event */ |
383 | 383 | ||
384 | #define dbcr_iac_range(task) ((task)->thread.dbcr0) | 384 | #define dbcr_iac_range(task) ((task)->thread.debug.dbcr0) |
385 | #define DBCR_IAC12I DBCR0_IA12 /* Range Inclusive */ | 385 | #define DBCR_IAC12I DBCR0_IA12 /* Range Inclusive */ |
386 | #define DBCR_IAC12X (DBCR0_IA12 | DBCR0_IA12X) /* Range Exclusive */ | 386 | #define DBCR_IAC12X (DBCR0_IA12 | DBCR0_IA12X) /* Range Exclusive */ |
387 | #define DBCR_IAC12MODE (DBCR0_IA12 | DBCR0_IA12X) /* IAC 1-2 Mode Bits */ | 387 | #define DBCR_IAC12MODE (DBCR0_IA12 | DBCR0_IA12X) /* IAC 1-2 Mode Bits */ |
@@ -395,7 +395,7 @@ | |||
395 | #define DBCR1_DAC1W 0x20000000 /* DAC1 Write Debug Event */ | 395 | #define DBCR1_DAC1W 0x20000000 /* DAC1 Write Debug Event */ |
396 | #define DBCR1_DAC2W 0x10000000 /* DAC2 Write Debug Event */ | 396 | #define DBCR1_DAC2W 0x10000000 /* DAC2 Write Debug Event */ |
397 | 397 | ||
398 | #define dbcr_dac(task) ((task)->thread.dbcr1) | 398 | #define dbcr_dac(task) ((task)->thread.debug.dbcr1) |
399 | #define DBCR_DAC1R DBCR1_DAC1R | 399 | #define DBCR_DAC1R DBCR1_DAC1R |
400 | #define DBCR_DAC1W DBCR1_DAC1W | 400 | #define DBCR_DAC1W DBCR1_DAC1W |
401 | #define DBCR_DAC2R DBCR1_DAC2R | 401 | #define DBCR_DAC2R DBCR1_DAC2R |
@@ -441,7 +441,7 @@ | |||
441 | #define DBCR0_CRET 0x00000020 /* Critical Return Debug Event */ | 441 | #define DBCR0_CRET 0x00000020 /* Critical Return Debug Event */ |
442 | #define DBCR0_FT 0x00000001 /* Freeze Timers on debug event */ | 442 | #define DBCR0_FT 0x00000001 /* Freeze Timers on debug event */ |
443 | 443 | ||
444 | #define dbcr_dac(task) ((task)->thread.dbcr0) | 444 | #define dbcr_dac(task) ((task)->thread.debug.dbcr0) |
445 | #define DBCR_DAC1R DBCR0_DAC1R | 445 | #define DBCR_DAC1R DBCR0_DAC1R |
446 | #define DBCR_DAC1W DBCR0_DAC1W | 446 | #define DBCR_DAC1W DBCR0_DAC1W |
447 | #define DBCR_DAC2R DBCR0_DAC2R | 447 | #define DBCR_DAC2R DBCR0_DAC2R |
@@ -475,7 +475,7 @@ | |||
475 | #define DBCR1_IAC34MX 0x000000C0 /* Instr Addr 3-4 range eXclusive */ | 475 | #define DBCR1_IAC34MX 0x000000C0 /* Instr Addr 3-4 range eXclusive */ |
476 | #define DBCR1_IAC34AT 0x00000001 /* Instr Addr 3-4 range Toggle */ | 476 | #define DBCR1_IAC34AT 0x00000001 /* Instr Addr 3-4 range Toggle */ |
477 | 477 | ||
478 | #define dbcr_iac_range(task) ((task)->thread.dbcr1) | 478 | #define dbcr_iac_range(task) ((task)->thread.debug.dbcr1) |
479 | #define DBCR_IAC12I DBCR1_IAC12M /* Range Inclusive */ | 479 | #define DBCR_IAC12I DBCR1_IAC12M /* Range Inclusive */ |
480 | #define DBCR_IAC12X DBCR1_IAC12MX /* Range Exclusive */ | 480 | #define DBCR_IAC12X DBCR1_IAC12MX /* Range Exclusive */ |
481 | #define DBCR_IAC12MODE DBCR1_IAC12MX /* IAC 1-2 Mode Bits */ | 481 | #define DBCR_IAC12MODE DBCR1_IAC12MX /* IAC 1-2 Mode Bits */ |
diff --git a/arch/powerpc/include/asm/scom.h b/arch/powerpc/include/asm/scom.h index 0cabfd7bc2d1..f5cde45b1161 100644 --- a/arch/powerpc/include/asm/scom.h +++ b/arch/powerpc/include/asm/scom.h | |||
@@ -54,8 +54,8 @@ struct scom_controller { | |||
54 | scom_map_t (*map)(struct device_node *ctrl_dev, u64 reg, u64 count); | 54 | scom_map_t (*map)(struct device_node *ctrl_dev, u64 reg, u64 count); |
55 | void (*unmap)(scom_map_t map); | 55 | void (*unmap)(scom_map_t map); |
56 | 56 | ||
57 | u64 (*read)(scom_map_t map, u32 reg); | 57 | int (*read)(scom_map_t map, u64 reg, u64 *value); |
58 | void (*write)(scom_map_t map, u32 reg, u64 value); | 58 | int (*write)(scom_map_t map, u64 reg, u64 value); |
59 | }; | 59 | }; |
60 | 60 | ||
61 | extern const struct scom_controller *scom_controller; | 61 | extern const struct scom_controller *scom_controller; |
@@ -133,10 +133,18 @@ static inline void scom_unmap(scom_map_t map) | |||
133 | * scom_read - Read a SCOM register | 133 | * scom_read - Read a SCOM register |
134 | * @map: Result of scom_map | 134 | * @map: Result of scom_map |
135 | * @reg: Register index within that map | 135 | * @reg: Register index within that map |
136 | * @value: Updated with the value read | ||
137 | * | ||
138 | * Returns 0 (success) or a negative error code | ||
136 | */ | 139 | */ |
137 | static inline u64 scom_read(scom_map_t map, u32 reg) | 140 | static inline int scom_read(scom_map_t map, u64 reg, u64 *value) |
138 | { | 141 | { |
139 | return scom_controller->read(map, reg); | 142 | int rc; |
143 | |||
144 | rc = scom_controller->read(map, reg, value); | ||
145 | if (rc) | ||
146 | *value = 0xfffffffffffffffful; | ||
147 | return rc; | ||
140 | } | 148 | } |
141 | 149 | ||
142 | /** | 150 | /** |
@@ -144,12 +152,15 @@ static inline u64 scom_read(scom_map_t map, u32 reg) | |||
144 | * @map: Result of scom_map | 152 | * @map: Result of scom_map |
145 | * @reg: Register index within that map | 153 | * @reg: Register index within that map |
146 | * @value: Value to write | 154 | * @value: Value to write |
155 | * | ||
156 | * Returns 0 (success) or a negative error code | ||
147 | */ | 157 | */ |
148 | static inline void scom_write(scom_map_t map, u32 reg, u64 value) | 158 | static inline int scom_write(scom_map_t map, u64 reg, u64 value) |
149 | { | 159 | { |
150 | scom_controller->write(map, reg, value); | 160 | return scom_controller->write(map, reg, value); |
151 | } | 161 | } |
152 | 162 | ||
163 | |||
153 | #endif /* CONFIG_PPC_SCOM */ | 164 | #endif /* CONFIG_PPC_SCOM */ |
154 | #endif /* __ASSEMBLY__ */ | 165 | #endif /* __ASSEMBLY__ */ |
155 | #endif /* __KERNEL__ */ | 166 | #endif /* __KERNEL__ */ |
diff --git a/arch/powerpc/include/asm/setup.h b/arch/powerpc/include/asm/setup.h index d3ca85529b8b..703a8412dac2 100644 --- a/arch/powerpc/include/asm/setup.h +++ b/arch/powerpc/include/asm/setup.h | |||
@@ -23,6 +23,10 @@ extern void reloc_got2(unsigned long); | |||
23 | 23 | ||
24 | #define PTRRELOC(x) ((typeof(x)) add_reloc_offset((unsigned long)(x))) | 24 | #define PTRRELOC(x) ((typeof(x)) add_reloc_offset((unsigned long)(x))) |
25 | 25 | ||
26 | void check_for_initrd(void); | ||
27 | void do_init_bootmem(void); | ||
28 | void setup_panic(void); | ||
29 | |||
26 | #endif /* !__ASSEMBLY__ */ | 30 | #endif /* !__ASSEMBLY__ */ |
27 | 31 | ||
28 | #endif /* _ASM_POWERPC_SETUP_H */ | 32 | #endif /* _ASM_POWERPC_SETUP_H */ |
diff --git a/arch/powerpc/include/asm/sfp-machine.h b/arch/powerpc/include/asm/sfp-machine.h index 3a7a67a0d006..d89beaba26ff 100644 --- a/arch/powerpc/include/asm/sfp-machine.h +++ b/arch/powerpc/include/asm/sfp-machine.h | |||
@@ -125,7 +125,7 @@ | |||
125 | #define FP_EX_DIVZERO (1 << (31 - 5)) | 125 | #define FP_EX_DIVZERO (1 << (31 - 5)) |
126 | #define FP_EX_INEXACT (1 << (31 - 6)) | 126 | #define FP_EX_INEXACT (1 << (31 - 6)) |
127 | 127 | ||
128 | #define __FPU_FPSCR (current->thread.fpscr.val) | 128 | #define __FPU_FPSCR (current->thread.fp_state.fpscr) |
129 | 129 | ||
130 | /* We only actually write to the destination register | 130 | /* We only actually write to the destination register |
131 | * if exceptions signalled (if any) will not trap. | 131 | * if exceptions signalled (if any) will not trap. |
diff --git a/arch/powerpc/include/asm/spu.h b/arch/powerpc/include/asm/spu.h index 93f280e23279..37b7ca39ec9f 100644 --- a/arch/powerpc/include/asm/spu.h +++ b/arch/powerpc/include/asm/spu.h | |||
@@ -235,6 +235,7 @@ extern long spu_sys_callback(struct spu_syscall_block *s); | |||
235 | 235 | ||
236 | /* syscalls implemented in spufs */ | 236 | /* syscalls implemented in spufs */ |
237 | struct file; | 237 | struct file; |
238 | struct coredump_params; | ||
238 | struct spufs_calls { | 239 | struct spufs_calls { |
239 | long (*create_thread)(const char __user *name, | 240 | long (*create_thread)(const char __user *name, |
240 | unsigned int flags, umode_t mode, | 241 | unsigned int flags, umode_t mode, |
@@ -242,7 +243,7 @@ struct spufs_calls { | |||
242 | long (*spu_run)(struct file *filp, __u32 __user *unpc, | 243 | long (*spu_run)(struct file *filp, __u32 __user *unpc, |
243 | __u32 __user *ustatus); | 244 | __u32 __user *ustatus); |
244 | int (*coredump_extra_notes_size)(void); | 245 | int (*coredump_extra_notes_size)(void); |
245 | int (*coredump_extra_notes_write)(struct file *file, loff_t *foffset); | 246 | int (*coredump_extra_notes_write)(struct coredump_params *cprm); |
246 | void (*notify_spus_active)(void); | 247 | void (*notify_spus_active)(void); |
247 | struct module *owner; | 248 | struct module *owner; |
248 | }; | 249 | }; |
diff --git a/arch/powerpc/include/asm/string.h b/arch/powerpc/include/asm/string.h index e40010abcaf1..0dffad6bcc84 100644 --- a/arch/powerpc/include/asm/string.h +++ b/arch/powerpc/include/asm/string.h | |||
@@ -10,7 +10,9 @@ | |||
10 | #define __HAVE_ARCH_STRNCMP | 10 | #define __HAVE_ARCH_STRNCMP |
11 | #define __HAVE_ARCH_STRCAT | 11 | #define __HAVE_ARCH_STRCAT |
12 | #define __HAVE_ARCH_MEMSET | 12 | #define __HAVE_ARCH_MEMSET |
13 | #ifdef __BIG_ENDIAN__ | ||
13 | #define __HAVE_ARCH_MEMCPY | 14 | #define __HAVE_ARCH_MEMCPY |
15 | #endif | ||
14 | #define __HAVE_ARCH_MEMMOVE | 16 | #define __HAVE_ARCH_MEMMOVE |
15 | #define __HAVE_ARCH_MEMCMP | 17 | #define __HAVE_ARCH_MEMCMP |
16 | #define __HAVE_ARCH_MEMCHR | 18 | #define __HAVE_ARCH_MEMCHR |
@@ -22,7 +24,9 @@ extern int strcmp(const char *,const char *); | |||
22 | extern int strncmp(const char *, const char *, __kernel_size_t); | 24 | extern int strncmp(const char *, const char *, __kernel_size_t); |
23 | extern char * strcat(char *, const char *); | 25 | extern char * strcat(char *, const char *); |
24 | extern void * memset(void *,int,__kernel_size_t); | 26 | extern void * memset(void *,int,__kernel_size_t); |
27 | #ifdef __BIG_ENDIAN__ | ||
25 | extern void * memcpy(void *,const void *,__kernel_size_t); | 28 | extern void * memcpy(void *,const void *,__kernel_size_t); |
29 | #endif | ||
26 | extern void * memmove(void *,const void *,__kernel_size_t); | 30 | extern void * memmove(void *,const void *,__kernel_size_t); |
27 | extern int memcmp(const void *,const void *,__kernel_size_t); | 31 | extern int memcmp(const void *,const void *,__kernel_size_t); |
28 | extern void * memchr(const void *,int,__kernel_size_t); | 32 | extern void * memchr(const void *,int,__kernel_size_t); |
diff --git a/arch/powerpc/include/asm/switch_to.h b/arch/powerpc/include/asm/switch_to.h index 2be5618cdec6..9ee12610af02 100644 --- a/arch/powerpc/include/asm/switch_to.h +++ b/arch/powerpc/include/asm/switch_to.h | |||
@@ -35,6 +35,7 @@ extern void giveup_vsx(struct task_struct *); | |||
35 | extern void enable_kernel_spe(void); | 35 | extern void enable_kernel_spe(void); |
36 | extern void giveup_spe(struct task_struct *); | 36 | extern void giveup_spe(struct task_struct *); |
37 | extern void load_up_spe(struct task_struct *); | 37 | extern void load_up_spe(struct task_struct *); |
38 | extern void switch_booke_debug_regs(struct thread_struct *new_thread); | ||
38 | 39 | ||
39 | #ifndef CONFIG_SMP | 40 | #ifndef CONFIG_SMP |
40 | extern void discard_lazy_cpu_state(void); | 41 | extern void discard_lazy_cpu_state(void); |
diff --git a/arch/powerpc/include/asm/uprobes.h b/arch/powerpc/include/asm/uprobes.h index 23016020915e..75c6ecdb8f37 100644 --- a/arch/powerpc/include/asm/uprobes.h +++ b/arch/powerpc/include/asm/uprobes.h | |||
@@ -37,6 +37,7 @@ typedef ppc_opcode_t uprobe_opcode_t; | |||
37 | struct arch_uprobe { | 37 | struct arch_uprobe { |
38 | union { | 38 | union { |
39 | u8 insn[MAX_UINSN_BYTES]; | 39 | u8 insn[MAX_UINSN_BYTES]; |
40 | u8 ixol[MAX_UINSN_BYTES]; | ||
40 | u32 ainsn; | 41 | u32 ainsn; |
41 | }; | 42 | }; |
42 | }; | 43 | }; |
@@ -45,11 +46,4 @@ struct arch_uprobe_task { | |||
45 | unsigned long saved_trap_nr; | 46 | unsigned long saved_trap_nr; |
46 | }; | 47 | }; |
47 | 48 | ||
48 | extern int arch_uprobe_analyze_insn(struct arch_uprobe *aup, struct mm_struct *mm, unsigned long addr); | ||
49 | extern int arch_uprobe_pre_xol(struct arch_uprobe *aup, struct pt_regs *regs); | ||
50 | extern int arch_uprobe_post_xol(struct arch_uprobe *aup, struct pt_regs *regs); | ||
51 | extern bool arch_uprobe_xol_was_trapped(struct task_struct *tsk); | ||
52 | extern int arch_uprobe_exception_notify(struct notifier_block *self, unsigned long val, void *data); | ||
53 | extern void arch_uprobe_abort_xol(struct arch_uprobe *aup, struct pt_regs *regs); | ||
54 | extern unsigned long arch_uretprobe_hijack_return_addr(unsigned long trampoline_vaddr, struct pt_regs *regs); | ||
55 | #endif /* _ASM_UPROBES_H */ | 49 | #endif /* _ASM_UPROBES_H */ |
diff --git a/arch/powerpc/include/asm/word-at-a-time.h b/arch/powerpc/include/asm/word-at-a-time.h index d0b6d4ac6dda..9a5c928bb3c6 100644 --- a/arch/powerpc/include/asm/word-at-a-time.h +++ b/arch/powerpc/include/asm/word-at-a-time.h | |||
@@ -8,6 +8,8 @@ | |||
8 | #include <linux/kernel.h> | 8 | #include <linux/kernel.h> |
9 | #include <asm/asm-compat.h> | 9 | #include <asm/asm-compat.h> |
10 | 10 | ||
11 | #ifdef __BIG_ENDIAN__ | ||
12 | |||
11 | struct word_at_a_time { | 13 | struct word_at_a_time { |
12 | const unsigned long high_bits, low_bits; | 14 | const unsigned long high_bits, low_bits; |
13 | }; | 15 | }; |
@@ -38,4 +40,80 @@ static inline bool has_zero(unsigned long val, unsigned long *data, const struct | |||
38 | return (val + c->high_bits) & ~rhs; | 40 | return (val + c->high_bits) & ~rhs; |
39 | } | 41 | } |
40 | 42 | ||
43 | #else | ||
44 | |||
45 | struct word_at_a_time { | ||
46 | const unsigned long one_bits, high_bits; | ||
47 | }; | ||
48 | |||
49 | #define WORD_AT_A_TIME_CONSTANTS { REPEAT_BYTE(0x01), REPEAT_BYTE(0x80) } | ||
50 | |||
51 | #ifdef CONFIG_64BIT | ||
52 | |||
53 | /* Alan Modra's little-endian strlen tail for 64-bit */ | ||
54 | #define create_zero_mask(mask) (mask) | ||
55 | |||
56 | static inline unsigned long find_zero(unsigned long mask) | ||
57 | { | ||
58 | unsigned long leading_zero_bits; | ||
59 | long trailing_zero_bit_mask; | ||
60 | |||
61 | asm ("addi %1,%2,-1\n\t" | ||
62 | "andc %1,%1,%2\n\t" | ||
63 | "popcntd %0,%1" | ||
64 | : "=r" (leading_zero_bits), "=&r" (trailing_zero_bit_mask) | ||
65 | : "r" (mask)); | ||
66 | return leading_zero_bits >> 3; | ||
67 | } | ||
68 | |||
69 | #else /* 32-bit case */ | ||
70 | |||
71 | /* | ||
72 | * This is largely generic for little-endian machines, but the | ||
73 | * optimal byte mask counting is probably going to be something | ||
74 | * that is architecture-specific. If you have a reliably fast | ||
75 | * bit count instruction, that might be better than the multiply | ||
76 | * and shift, for example. | ||
77 | */ | ||
78 | |||
79 | /* Carl Chatfield / Jan Achrenius G+ version for 32-bit */ | ||
80 | static inline long count_masked_bytes(long mask) | ||
81 | { | ||
82 | /* (000000 0000ff 00ffff ffffff) -> ( 1 1 2 3 ) */ | ||
83 | long a = (0x0ff0001+mask) >> 23; | ||
84 | /* Fix the 1 for 00 case */ | ||
85 | return a & mask; | ||
86 | } | ||
87 | |||
88 | static inline unsigned long create_zero_mask(unsigned long bits) | ||
89 | { | ||
90 | bits = (bits - 1) & ~bits; | ||
91 | return bits >> 7; | ||
92 | } | ||
93 | |||
94 | static inline unsigned long find_zero(unsigned long mask) | ||
95 | { | ||
96 | return count_masked_bytes(mask); | ||
97 | } | ||
98 | |||
99 | #endif | ||
100 | |||
101 | /* Return nonzero if it has a zero */ | ||
102 | static inline unsigned long has_zero(unsigned long a, unsigned long *bits, const struct word_at_a_time *c) | ||
103 | { | ||
104 | unsigned long mask = ((a - c->one_bits) & ~a) & c->high_bits; | ||
105 | *bits = mask; | ||
106 | return mask; | ||
107 | } | ||
108 | |||
109 | static inline unsigned long prep_zero_mask(unsigned long a, unsigned long bits, const struct word_at_a_time *c) | ||
110 | { | ||
111 | return bits; | ||
112 | } | ||
113 | |||
114 | /* The mask we created is directly usable as a bytemask */ | ||
115 | #define zero_bytemask(mask) (mask) | ||
116 | |||
117 | #endif | ||
118 | |||
41 | #endif /* _ASM_WORD_AT_A_TIME_H */ | 119 | #endif /* _ASM_WORD_AT_A_TIME_H */ |
diff --git a/arch/powerpc/include/asm/xor.h b/arch/powerpc/include/asm/xor.h index c82eb12a5b18..0abb97f3be10 100644 --- a/arch/powerpc/include/asm/xor.h +++ b/arch/powerpc/include/asm/xor.h | |||
@@ -1 +1,68 @@ | |||
1 | /* | ||
2 | * This program is free software; you can redistribute it and/or modify | ||
3 | * it under the terms of the GNU General Public License as published by | ||
4 | * the Free Software Foundation; either version 2 of the License, or | ||
5 | * (at your option) any later version. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
15 | * | ||
16 | * Copyright (C) IBM Corporation, 2012 | ||
17 | * | ||
18 | * Author: Anton Blanchard <anton@au.ibm.com> | ||
19 | */ | ||
20 | #ifndef _ASM_POWERPC_XOR_H | ||
21 | #define _ASM_POWERPC_XOR_H | ||
22 | |||
23 | #ifdef CONFIG_ALTIVEC | ||
24 | |||
25 | #include <asm/cputable.h> | ||
26 | |||
27 | void xor_altivec_2(unsigned long bytes, unsigned long *v1_in, | ||
28 | unsigned long *v2_in); | ||
29 | void xor_altivec_3(unsigned long bytes, unsigned long *v1_in, | ||
30 | unsigned long *v2_in, unsigned long *v3_in); | ||
31 | void xor_altivec_4(unsigned long bytes, unsigned long *v1_in, | ||
32 | unsigned long *v2_in, unsigned long *v3_in, | ||
33 | unsigned long *v4_in); | ||
34 | void xor_altivec_5(unsigned long bytes, unsigned long *v1_in, | ||
35 | unsigned long *v2_in, unsigned long *v3_in, | ||
36 | unsigned long *v4_in, unsigned long *v5_in); | ||
37 | |||
38 | static struct xor_block_template xor_block_altivec = { | ||
39 | .name = "altivec", | ||
40 | .do_2 = xor_altivec_2, | ||
41 | .do_3 = xor_altivec_3, | ||
42 | .do_4 = xor_altivec_4, | ||
43 | .do_5 = xor_altivec_5, | ||
44 | }; | ||
45 | |||
46 | #define XOR_SPEED_ALTIVEC() \ | ||
47 | do { \ | ||
48 | if (cpu_has_feature(CPU_FTR_ALTIVEC)) \ | ||
49 | xor_speed(&xor_block_altivec); \ | ||
50 | } while (0) | ||
51 | #else | ||
52 | #define XOR_SPEED_ALTIVEC() | ||
53 | #endif | ||
54 | |||
55 | /* Also try the generic routines. */ | ||
1 | #include <asm-generic/xor.h> | 56 | #include <asm-generic/xor.h> |
57 | |||
58 | #undef XOR_TRY_TEMPLATES | ||
59 | #define XOR_TRY_TEMPLATES \ | ||
60 | do { \ | ||
61 | xor_speed(&xor_block_8regs); \ | ||
62 | xor_speed(&xor_block_8regs_p); \ | ||
63 | xor_speed(&xor_block_32regs); \ | ||
64 | xor_speed(&xor_block_32regs_p); \ | ||
65 | XOR_SPEED_ALTIVEC(); \ | ||
66 | } while (0) | ||
67 | |||
68 | #endif /* _ASM_POWERPC_XOR_H */ | ||
diff --git a/arch/powerpc/include/uapi/asm/byteorder.h b/arch/powerpc/include/uapi/asm/byteorder.h index aa6cc4fac965..ca931d074000 100644 --- a/arch/powerpc/include/uapi/asm/byteorder.h +++ b/arch/powerpc/include/uapi/asm/byteorder.h | |||
@@ -7,6 +7,10 @@ | |||
7 | * as published by the Free Software Foundation; either version | 7 | * as published by the Free Software Foundation; either version |
8 | * 2 of the License, or (at your option) any later version. | 8 | * 2 of the License, or (at your option) any later version. |
9 | */ | 9 | */ |
10 | #ifdef __LITTLE_ENDIAN__ | ||
11 | #include <linux/byteorder/little_endian.h> | ||
12 | #else | ||
10 | #include <linux/byteorder/big_endian.h> | 13 | #include <linux/byteorder/big_endian.h> |
14 | #endif | ||
11 | 15 | ||
12 | #endif /* _ASM_POWERPC_BYTEORDER_H */ | 16 | #endif /* _ASM_POWERPC_BYTEORDER_H */ |
diff --git a/arch/powerpc/include/uapi/asm/kvm.h b/arch/powerpc/include/uapi/asm/kvm.h index 0fb1a6e9ff90..6836ec79a830 100644 --- a/arch/powerpc/include/uapi/asm/kvm.h +++ b/arch/powerpc/include/uapi/asm/kvm.h | |||
@@ -27,6 +27,7 @@ | |||
27 | #define __KVM_HAVE_PPC_SMT | 27 | #define __KVM_HAVE_PPC_SMT |
28 | #define __KVM_HAVE_IRQCHIP | 28 | #define __KVM_HAVE_IRQCHIP |
29 | #define __KVM_HAVE_IRQ_LINE | 29 | #define __KVM_HAVE_IRQ_LINE |
30 | #define __KVM_HAVE_GUEST_DEBUG | ||
30 | 31 | ||
31 | struct kvm_regs { | 32 | struct kvm_regs { |
32 | __u64 pc; | 33 | __u64 pc; |
@@ -269,7 +270,24 @@ struct kvm_fpu { | |||
269 | __u64 fpr[32]; | 270 | __u64 fpr[32]; |
270 | }; | 271 | }; |
271 | 272 | ||
273 | /* | ||
274 | * Defines for h/w breakpoint, watchpoint (read, write or both) and | ||
275 | * software breakpoint. | ||
276 | * These are used as "type" in KVM_SET_GUEST_DEBUG ioctl and "status" | ||
277 | * for KVM_DEBUG_EXIT. | ||
278 | */ | ||
279 | #define KVMPPC_DEBUG_NONE 0x0 | ||
280 | #define KVMPPC_DEBUG_BREAKPOINT (1UL << 1) | ||
281 | #define KVMPPC_DEBUG_WATCH_WRITE (1UL << 2) | ||
282 | #define KVMPPC_DEBUG_WATCH_READ (1UL << 3) | ||
272 | struct kvm_debug_exit_arch { | 283 | struct kvm_debug_exit_arch { |
284 | __u64 address; | ||
285 | /* | ||
286 | * exiting to userspace because of h/w breakpoint, watchpoint | ||
287 | * (read, write or both) and software breakpoint. | ||
288 | */ | ||
289 | __u32 status; | ||
290 | __u32 reserved; | ||
273 | }; | 291 | }; |
274 | 292 | ||
275 | /* for KVM_SET_GUEST_DEBUG */ | 293 | /* for KVM_SET_GUEST_DEBUG */ |
@@ -281,10 +299,6 @@ struct kvm_guest_debug_arch { | |||
281 | * Type denotes h/w breakpoint, read watchpoint, write | 299 | * Type denotes h/w breakpoint, read watchpoint, write |
282 | * watchpoint or watchpoint (both read and write). | 300 | * watchpoint or watchpoint (both read and write). |
283 | */ | 301 | */ |
284 | #define KVMPPC_DEBUG_NONE 0x0 | ||
285 | #define KVMPPC_DEBUG_BREAKPOINT (1UL << 1) | ||
286 | #define KVMPPC_DEBUG_WATCH_WRITE (1UL << 2) | ||
287 | #define KVMPPC_DEBUG_WATCH_READ (1UL << 3) | ||
288 | __u32 type; | 302 | __u32 type; |
289 | __u32 reserved; | 303 | __u32 reserved; |
290 | } bp[16]; | 304 | } bp[16]; |
@@ -429,6 +443,11 @@ struct kvm_get_htab_header { | |||
429 | #define KVM_REG_PPC_MMCR0 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x10) | 443 | #define KVM_REG_PPC_MMCR0 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x10) |
430 | #define KVM_REG_PPC_MMCR1 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x11) | 444 | #define KVM_REG_PPC_MMCR1 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x11) |
431 | #define KVM_REG_PPC_MMCRA (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x12) | 445 | #define KVM_REG_PPC_MMCRA (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x12) |
446 | #define KVM_REG_PPC_MMCR2 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x13) | ||
447 | #define KVM_REG_PPC_MMCRS (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x14) | ||
448 | #define KVM_REG_PPC_SIAR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x15) | ||
449 | #define KVM_REG_PPC_SDAR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x16) | ||
450 | #define KVM_REG_PPC_SIER (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x17) | ||
432 | 451 | ||
433 | #define KVM_REG_PPC_PMC1 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x18) | 452 | #define KVM_REG_PPC_PMC1 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x18) |
434 | #define KVM_REG_PPC_PMC2 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x19) | 453 | #define KVM_REG_PPC_PMC2 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x19) |
@@ -499,6 +518,65 @@ struct kvm_get_htab_header { | |||
499 | #define KVM_REG_PPC_TLB3PS (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x9a) | 518 | #define KVM_REG_PPC_TLB3PS (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x9a) |
500 | #define KVM_REG_PPC_EPTCFG (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x9b) | 519 | #define KVM_REG_PPC_EPTCFG (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x9b) |
501 | 520 | ||
521 | /* Timebase offset */ | ||
522 | #define KVM_REG_PPC_TB_OFFSET (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x9c) | ||
523 | |||
524 | /* POWER8 registers */ | ||
525 | #define KVM_REG_PPC_SPMC1 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x9d) | ||
526 | #define KVM_REG_PPC_SPMC2 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x9e) | ||
527 | #define KVM_REG_PPC_IAMR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x9f) | ||
528 | #define KVM_REG_PPC_TFHAR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa0) | ||
529 | #define KVM_REG_PPC_TFIAR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa1) | ||
530 | #define KVM_REG_PPC_TEXASR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa2) | ||
531 | #define KVM_REG_PPC_FSCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa3) | ||
532 | #define KVM_REG_PPC_PSPB (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xa4) | ||
533 | #define KVM_REG_PPC_EBBHR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa5) | ||
534 | #define KVM_REG_PPC_EBBRR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa6) | ||
535 | #define KVM_REG_PPC_BESCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa7) | ||
536 | #define KVM_REG_PPC_TAR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa8) | ||
537 | #define KVM_REG_PPC_DPDES (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa9) | ||
538 | #define KVM_REG_PPC_DAWR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xaa) | ||
539 | #define KVM_REG_PPC_DAWRX (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xab) | ||
540 | #define KVM_REG_PPC_CIABR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xac) | ||
541 | #define KVM_REG_PPC_IC (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xad) | ||
542 | #define KVM_REG_PPC_VTB (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xae) | ||
543 | #define KVM_REG_PPC_CSIGR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xaf) | ||
544 | #define KVM_REG_PPC_TACR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb0) | ||
545 | #define KVM_REG_PPC_TCSCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb1) | ||
546 | #define KVM_REG_PPC_PID (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb2) | ||
547 | #define KVM_REG_PPC_ACOP (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb3) | ||
548 | |||
549 | #define KVM_REG_PPC_VRSAVE (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb4) | ||
550 | #define KVM_REG_PPC_LPCR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb5) | ||
551 | #define KVM_REG_PPC_PPR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb6) | ||
552 | |||
553 | /* Architecture compatibility level */ | ||
554 | #define KVM_REG_PPC_ARCH_COMPAT (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb7) | ||
555 | |||
556 | /* Transactional Memory checkpointed state: | ||
557 | * This is all GPRs, all VSX regs and a subset of SPRs | ||
558 | */ | ||
559 | #define KVM_REG_PPC_TM (KVM_REG_PPC | 0x80000000) | ||
560 | /* TM GPRs */ | ||
561 | #define KVM_REG_PPC_TM_GPR0 (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0) | ||
562 | #define KVM_REG_PPC_TM_GPR(n) (KVM_REG_PPC_TM_GPR0 + (n)) | ||
563 | #define KVM_REG_PPC_TM_GPR31 (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x1f) | ||
564 | /* TM VSX */ | ||
565 | #define KVM_REG_PPC_TM_VSR0 (KVM_REG_PPC_TM | KVM_REG_SIZE_U128 | 0x20) | ||
566 | #define KVM_REG_PPC_TM_VSR(n) (KVM_REG_PPC_TM_VSR0 + (n)) | ||
567 | #define KVM_REG_PPC_TM_VSR63 (KVM_REG_PPC_TM | KVM_REG_SIZE_U128 | 0x5f) | ||
568 | /* TM SPRS */ | ||
569 | #define KVM_REG_PPC_TM_CR (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x60) | ||
570 | #define KVM_REG_PPC_TM_LR (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x61) | ||
571 | #define KVM_REG_PPC_TM_CTR (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x62) | ||
572 | #define KVM_REG_PPC_TM_FPSCR (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x63) | ||
573 | #define KVM_REG_PPC_TM_AMR (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x64) | ||
574 | #define KVM_REG_PPC_TM_PPR (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x65) | ||
575 | #define KVM_REG_PPC_TM_VRSAVE (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x66) | ||
576 | #define KVM_REG_PPC_TM_VSCR (KVM_REG_PPC_TM | KVM_REG_SIZE_U32 | 0x67) | ||
577 | #define KVM_REG_PPC_TM_DSCR (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x68) | ||
578 | #define KVM_REG_PPC_TM_TAR (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x69) | ||
579 | |||
502 | /* PPC64 eXternal Interrupt Controller Specification */ | 580 | /* PPC64 eXternal Interrupt Controller Specification */ |
503 | #define KVM_DEV_XICS_GRP_SOURCES 1 /* 64-bit source attributes */ | 581 | #define KVM_DEV_XICS_GRP_SOURCES 1 /* 64-bit source attributes */ |
504 | 582 | ||
diff --git a/arch/powerpc/include/uapi/asm/socket.h b/arch/powerpc/include/uapi/asm/socket.h index a6d74467c9ed..fa698324a1fd 100644 --- a/arch/powerpc/include/uapi/asm/socket.h +++ b/arch/powerpc/include/uapi/asm/socket.h | |||
@@ -83,4 +83,6 @@ | |||
83 | 83 | ||
84 | #define SO_BUSY_POLL 46 | 84 | #define SO_BUSY_POLL 46 |
85 | 85 | ||
86 | #define SO_MAX_PACING_RATE 47 | ||
87 | |||
86 | #endif /* _ASM_POWERPC_SOCKET_H */ | 88 | #endif /* _ASM_POWERPC_SOCKET_H */ |
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c index a27ccd5dc6b9..de91f3ae631e 100644 --- a/arch/powerpc/kernel/align.c +++ b/arch/powerpc/kernel/align.c | |||
@@ -54,8 +54,6 @@ struct aligninfo { | |||
54 | /* DSISR bits reported for a DCBZ instruction: */ | 54 | /* DSISR bits reported for a DCBZ instruction: */ |
55 | #define DCBZ 0x5f /* 8xx/82xx dcbz faults when cache not enabled */ | 55 | #define DCBZ 0x5f /* 8xx/82xx dcbz faults when cache not enabled */ |
56 | 56 | ||
57 | #define SWAP(a, b) (t = (a), (a) = (b), (b) = t) | ||
58 | |||
59 | /* | 57 | /* |
60 | * The PowerPC stores certain bits of the instruction that caused the | 58 | * The PowerPC stores certain bits of the instruction that caused the |
61 | * alignment exception in the DSISR register. This array maps those | 59 | * alignment exception in the DSISR register. This array maps those |
@@ -256,11 +254,17 @@ static int emulate_dcbz(struct pt_regs *regs, unsigned char __user *addr) | |||
256 | * bottom 4 bytes of each register, and the loads clear the | 254 | * bottom 4 bytes of each register, and the loads clear the |
257 | * top 4 bytes of the affected register. | 255 | * top 4 bytes of the affected register. |
258 | */ | 256 | */ |
257 | #ifdef __BIG_ENDIAN__ | ||
259 | #ifdef CONFIG_PPC64 | 258 | #ifdef CONFIG_PPC64 |
260 | #define REG_BYTE(rp, i) *((u8 *)((rp) + ((i) >> 2)) + ((i) & 3) + 4) | 259 | #define REG_BYTE(rp, i) *((u8 *)((rp) + ((i) >> 2)) + ((i) & 3) + 4) |
261 | #else | 260 | #else |
262 | #define REG_BYTE(rp, i) *((u8 *)(rp) + (i)) | 261 | #define REG_BYTE(rp, i) *((u8 *)(rp) + (i)) |
263 | #endif | 262 | #endif |
263 | #endif | ||
264 | |||
265 | #ifdef __LITTLE_ENDIAN__ | ||
266 | #define REG_BYTE(rp, i) (*(((u8 *)((rp) + ((i)>>2)) + ((i)&3)))) | ||
267 | #endif | ||
264 | 268 | ||
265 | #define SWIZ_PTR(p) ((unsigned char __user *)((p) ^ swiz)) | 269 | #define SWIZ_PTR(p) ((unsigned char __user *)((p) ^ swiz)) |
266 | 270 | ||
@@ -305,6 +309,15 @@ static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr, | |||
305 | nb0 = nb + reg * 4 - 128; | 309 | nb0 = nb + reg * 4 - 128; |
306 | nb = 128 - reg * 4; | 310 | nb = 128 - reg * 4; |
307 | } | 311 | } |
312 | #ifdef __LITTLE_ENDIAN__ | ||
313 | /* | ||
314 | * String instructions are endian neutral but the code | ||
315 | * below is not. Force byte swapping on so that the | ||
316 | * effects of swizzling are undone in the load/store | ||
317 | * loops below. | ||
318 | */ | ||
319 | flags ^= SW; | ||
320 | #endif | ||
308 | } else { | 321 | } else { |
309 | /* lwm, stmw */ | 322 | /* lwm, stmw */ |
310 | nb = (32 - reg) * 4; | 323 | nb = (32 - reg) * 4; |
@@ -458,7 +471,7 @@ static struct aligninfo spe_aligninfo[32] = { | |||
458 | static int emulate_spe(struct pt_regs *regs, unsigned int reg, | 471 | static int emulate_spe(struct pt_regs *regs, unsigned int reg, |
459 | unsigned int instr) | 472 | unsigned int instr) |
460 | { | 473 | { |
461 | int t, ret; | 474 | int ret; |
462 | union { | 475 | union { |
463 | u64 ll; | 476 | u64 ll; |
464 | u32 w[2]; | 477 | u32 w[2]; |
@@ -581,24 +594,18 @@ static int emulate_spe(struct pt_regs *regs, unsigned int reg, | |||
581 | if (flags & SW) { | 594 | if (flags & SW) { |
582 | switch (flags & 0xf0) { | 595 | switch (flags & 0xf0) { |
583 | case E8: | 596 | case E8: |
584 | SWAP(data.v[0], data.v[7]); | 597 | data.ll = swab64(data.ll); |
585 | SWAP(data.v[1], data.v[6]); | ||
586 | SWAP(data.v[2], data.v[5]); | ||
587 | SWAP(data.v[3], data.v[4]); | ||
588 | break; | 598 | break; |
589 | case E4: | 599 | case E4: |
590 | 600 | data.w[0] = swab32(data.w[0]); | |
591 | SWAP(data.v[0], data.v[3]); | 601 | data.w[1] = swab32(data.w[1]); |
592 | SWAP(data.v[1], data.v[2]); | ||
593 | SWAP(data.v[4], data.v[7]); | ||
594 | SWAP(data.v[5], data.v[6]); | ||
595 | break; | 602 | break; |
596 | /* Its half word endian */ | 603 | /* Its half word endian */ |
597 | default: | 604 | default: |
598 | SWAP(data.v[0], data.v[1]); | 605 | data.h[0] = swab16(data.h[0]); |
599 | SWAP(data.v[2], data.v[3]); | 606 | data.h[1] = swab16(data.h[1]); |
600 | SWAP(data.v[4], data.v[5]); | 607 | data.h[2] = swab16(data.h[2]); |
601 | SWAP(data.v[6], data.v[7]); | 608 | data.h[3] = swab16(data.h[3]); |
602 | break; | 609 | break; |
603 | } | 610 | } |
604 | } | 611 | } |
@@ -658,14 +665,31 @@ static int emulate_vsx(unsigned char __user *addr, unsigned int reg, | |||
658 | flush_vsx_to_thread(current); | 665 | flush_vsx_to_thread(current); |
659 | 666 | ||
660 | if (reg < 32) | 667 | if (reg < 32) |
661 | ptr = (char *) ¤t->thread.TS_FPR(reg); | 668 | ptr = (char *) ¤t->thread.fp_state.fpr[reg][0]; |
662 | else | 669 | else |
663 | ptr = (char *) ¤t->thread.vr[reg - 32]; | 670 | ptr = (char *) ¤t->thread.vr_state.vr[reg - 32]; |
664 | 671 | ||
665 | lptr = (unsigned long *) ptr; | 672 | lptr = (unsigned long *) ptr; |
666 | 673 | ||
674 | #ifdef __LITTLE_ENDIAN__ | ||
675 | if (flags & SW) { | ||
676 | elsize = length; | ||
677 | sw = length-1; | ||
678 | } else { | ||
679 | /* | ||
680 | * The elements are BE ordered, even in LE mode, so process | ||
681 | * them in reverse order. | ||
682 | */ | ||
683 | addr += length - elsize; | ||
684 | |||
685 | /* 8 byte memory accesses go in the top 8 bytes of the VR */ | ||
686 | if (length == 8) | ||
687 | ptr += 8; | ||
688 | } | ||
689 | #else | ||
667 | if (flags & SW) | 690 | if (flags & SW) |
668 | sw = elsize-1; | 691 | sw = elsize-1; |
692 | #endif | ||
669 | 693 | ||
670 | for (j = 0; j < length; j += elsize) { | 694 | for (j = 0; j < length; j += elsize) { |
671 | for (i = 0; i < elsize; ++i) { | 695 | for (i = 0; i < elsize; ++i) { |
@@ -675,19 +699,31 @@ static int emulate_vsx(unsigned char __user *addr, unsigned int reg, | |||
675 | ret |= __get_user(ptr[i^sw], addr + i); | 699 | ret |= __get_user(ptr[i^sw], addr + i); |
676 | } | 700 | } |
677 | ptr += elsize; | 701 | ptr += elsize; |
702 | #ifdef __LITTLE_ENDIAN__ | ||
703 | addr -= elsize; | ||
704 | #else | ||
678 | addr += elsize; | 705 | addr += elsize; |
706 | #endif | ||
679 | } | 707 | } |
680 | 708 | ||
709 | #ifdef __BIG_ENDIAN__ | ||
710 | #define VSX_HI 0 | ||
711 | #define VSX_LO 1 | ||
712 | #else | ||
713 | #define VSX_HI 1 | ||
714 | #define VSX_LO 0 | ||
715 | #endif | ||
716 | |||
681 | if (!ret) { | 717 | if (!ret) { |
682 | if (flags & U) | 718 | if (flags & U) |
683 | regs->gpr[areg] = regs->dar; | 719 | regs->gpr[areg] = regs->dar; |
684 | 720 | ||
685 | /* Splat load copies the same data to top and bottom 8 bytes */ | 721 | /* Splat load copies the same data to top and bottom 8 bytes */ |
686 | if (flags & SPLT) | 722 | if (flags & SPLT) |
687 | lptr[1] = lptr[0]; | 723 | lptr[VSX_LO] = lptr[VSX_HI]; |
688 | /* For 8 byte loads, zero the top 8 bytes */ | 724 | /* For 8 byte loads, zero the low 8 bytes */ |
689 | else if (!(flags & ST) && (8 == length)) | 725 | else if (!(flags & ST) && (8 == length)) |
690 | lptr[1] = 0; | 726 | lptr[VSX_LO] = 0; |
691 | } else | 727 | } else |
692 | return -EFAULT; | 728 | return -EFAULT; |
693 | 729 | ||
@@ -710,18 +746,28 @@ int fix_alignment(struct pt_regs *regs) | |||
710 | unsigned int dsisr; | 746 | unsigned int dsisr; |
711 | unsigned char __user *addr; | 747 | unsigned char __user *addr; |
712 | unsigned long p, swiz; | 748 | unsigned long p, swiz; |
713 | int ret, t; | 749 | int ret, i; |
714 | union { | 750 | union data { |
715 | u64 ll; | 751 | u64 ll; |
716 | double dd; | 752 | double dd; |
717 | unsigned char v[8]; | 753 | unsigned char v[8]; |
718 | struct { | 754 | struct { |
755 | #ifdef __LITTLE_ENDIAN__ | ||
756 | int low32; | ||
757 | unsigned hi32; | ||
758 | #else | ||
719 | unsigned hi32; | 759 | unsigned hi32; |
720 | int low32; | 760 | int low32; |
761 | #endif | ||
721 | } x32; | 762 | } x32; |
722 | struct { | 763 | struct { |
764 | #ifdef __LITTLE_ENDIAN__ | ||
765 | short low16; | ||
766 | unsigned char hi48[6]; | ||
767 | #else | ||
723 | unsigned char hi48[6]; | 768 | unsigned char hi48[6]; |
724 | short low16; | 769 | short low16; |
770 | #endif | ||
725 | } x16; | 771 | } x16; |
726 | } data; | 772 | } data; |
727 | 773 | ||
@@ -780,8 +826,9 @@ int fix_alignment(struct pt_regs *regs) | |||
780 | 826 | ||
781 | /* Byteswap little endian loads and stores */ | 827 | /* Byteswap little endian loads and stores */ |
782 | swiz = 0; | 828 | swiz = 0; |
783 | if (regs->msr & MSR_LE) { | 829 | if ((regs->msr & MSR_LE) != (MSR_KERNEL & MSR_LE)) { |
784 | flags ^= SW; | 830 | flags ^= SW; |
831 | #ifdef __BIG_ENDIAN__ | ||
785 | /* | 832 | /* |
786 | * So-called "PowerPC little endian" mode works by | 833 | * So-called "PowerPC little endian" mode works by |
787 | * swizzling addresses rather than by actually doing | 834 | * swizzling addresses rather than by actually doing |
@@ -794,6 +841,7 @@ int fix_alignment(struct pt_regs *regs) | |||
794 | */ | 841 | */ |
795 | if (cpu_has_feature(CPU_FTR_PPC_LE)) | 842 | if (cpu_has_feature(CPU_FTR_PPC_LE)) |
796 | swiz = 7; | 843 | swiz = 7; |
844 | #endif | ||
797 | } | 845 | } |
798 | 846 | ||
799 | /* DAR has the operand effective address */ | 847 | /* DAR has the operand effective address */ |
@@ -818,7 +866,7 @@ int fix_alignment(struct pt_regs *regs) | |||
818 | elsize = 8; | 866 | elsize = 8; |
819 | 867 | ||
820 | flags = 0; | 868 | flags = 0; |
821 | if (regs->msr & MSR_LE) | 869 | if ((regs->msr & MSR_LE) != (MSR_KERNEL & MSR_LE)) |
822 | flags |= SW; | 870 | flags |= SW; |
823 | if (instruction & 0x100) | 871 | if (instruction & 0x100) |
824 | flags |= ST; | 872 | flags |= ST; |
@@ -878,32 +926,36 @@ int fix_alignment(struct pt_regs *regs) | |||
878 | * get it from register values | 926 | * get it from register values |
879 | */ | 927 | */ |
880 | if (!(flags & ST)) { | 928 | if (!(flags & ST)) { |
881 | data.ll = 0; | 929 | unsigned int start = 0; |
882 | ret = 0; | 930 | |
883 | p = (unsigned long) addr; | ||
884 | switch (nb) { | 931 | switch (nb) { |
885 | case 8: | ||
886 | ret |= __get_user_inatomic(data.v[0], SWIZ_PTR(p++)); | ||
887 | ret |= __get_user_inatomic(data.v[1], SWIZ_PTR(p++)); | ||
888 | ret |= __get_user_inatomic(data.v[2], SWIZ_PTR(p++)); | ||
889 | ret |= __get_user_inatomic(data.v[3], SWIZ_PTR(p++)); | ||
890 | case 4: | 932 | case 4: |
891 | ret |= __get_user_inatomic(data.v[4], SWIZ_PTR(p++)); | 933 | start = offsetof(union data, x32.low32); |
892 | ret |= __get_user_inatomic(data.v[5], SWIZ_PTR(p++)); | 934 | break; |
893 | case 2: | 935 | case 2: |
894 | ret |= __get_user_inatomic(data.v[6], SWIZ_PTR(p++)); | 936 | start = offsetof(union data, x16.low16); |
895 | ret |= __get_user_inatomic(data.v[7], SWIZ_PTR(p++)); | 937 | break; |
896 | if (unlikely(ret)) | ||
897 | return -EFAULT; | ||
898 | } | 938 | } |
939 | |||
940 | data.ll = 0; | ||
941 | ret = 0; | ||
942 | p = (unsigned long)addr; | ||
943 | |||
944 | for (i = 0; i < nb; i++) | ||
945 | ret |= __get_user_inatomic(data.v[start + i], | ||
946 | SWIZ_PTR(p++)); | ||
947 | |||
948 | if (unlikely(ret)) | ||
949 | return -EFAULT; | ||
950 | |||
899 | } else if (flags & F) { | 951 | } else if (flags & F) { |
900 | data.dd = current->thread.TS_FPR(reg); | 952 | data.ll = current->thread.TS_FPR(reg); |
901 | if (flags & S) { | 953 | if (flags & S) { |
902 | /* Single-precision FP store requires conversion... */ | 954 | /* Single-precision FP store requires conversion... */ |
903 | #ifdef CONFIG_PPC_FPU | 955 | #ifdef CONFIG_PPC_FPU |
904 | preempt_disable(); | 956 | preempt_disable(); |
905 | enable_kernel_fp(); | 957 | enable_kernel_fp(); |
906 | cvt_df(&data.dd, (float *)&data.v[4]); | 958 | cvt_df(&data.dd, (float *)&data.x32.low32); |
907 | preempt_enable(); | 959 | preempt_enable(); |
908 | #else | 960 | #else |
909 | return 0; | 961 | return 0; |
@@ -915,17 +967,13 @@ int fix_alignment(struct pt_regs *regs) | |||
915 | if (flags & SW) { | 967 | if (flags & SW) { |
916 | switch (nb) { | 968 | switch (nb) { |
917 | case 8: | 969 | case 8: |
918 | SWAP(data.v[0], data.v[7]); | 970 | data.ll = swab64(data.ll); |
919 | SWAP(data.v[1], data.v[6]); | ||
920 | SWAP(data.v[2], data.v[5]); | ||
921 | SWAP(data.v[3], data.v[4]); | ||
922 | break; | 971 | break; |
923 | case 4: | 972 | case 4: |
924 | SWAP(data.v[4], data.v[7]); | 973 | data.x32.low32 = swab32(data.x32.low32); |
925 | SWAP(data.v[5], data.v[6]); | ||
926 | break; | 974 | break; |
927 | case 2: | 975 | case 2: |
928 | SWAP(data.v[6], data.v[7]); | 976 | data.x16.low16 = swab16(data.x16.low16); |
929 | break; | 977 | break; |
930 | } | 978 | } |
931 | } | 979 | } |
@@ -947,7 +995,7 @@ int fix_alignment(struct pt_regs *regs) | |||
947 | #ifdef CONFIG_PPC_FPU | 995 | #ifdef CONFIG_PPC_FPU |
948 | preempt_disable(); | 996 | preempt_disable(); |
949 | enable_kernel_fp(); | 997 | enable_kernel_fp(); |
950 | cvt_fd((float *)&data.v[4], &data.dd); | 998 | cvt_fd((float *)&data.x32.low32, &data.dd); |
951 | preempt_enable(); | 999 | preempt_enable(); |
952 | #else | 1000 | #else |
953 | return 0; | 1001 | return 0; |
@@ -957,25 +1005,28 @@ int fix_alignment(struct pt_regs *regs) | |||
957 | 1005 | ||
958 | /* Store result to memory or update registers */ | 1006 | /* Store result to memory or update registers */ |
959 | if (flags & ST) { | 1007 | if (flags & ST) { |
960 | ret = 0; | 1008 | unsigned int start = 0; |
961 | p = (unsigned long) addr; | 1009 | |
962 | switch (nb) { | 1010 | switch (nb) { |
963 | case 8: | ||
964 | ret |= __put_user_inatomic(data.v[0], SWIZ_PTR(p++)); | ||
965 | ret |= __put_user_inatomic(data.v[1], SWIZ_PTR(p++)); | ||
966 | ret |= __put_user_inatomic(data.v[2], SWIZ_PTR(p++)); | ||
967 | ret |= __put_user_inatomic(data.v[3], SWIZ_PTR(p++)); | ||
968 | case 4: | 1011 | case 4: |
969 | ret |= __put_user_inatomic(data.v[4], SWIZ_PTR(p++)); | 1012 | start = offsetof(union data, x32.low32); |
970 | ret |= __put_user_inatomic(data.v[5], SWIZ_PTR(p++)); | 1013 | break; |
971 | case 2: | 1014 | case 2: |
972 | ret |= __put_user_inatomic(data.v[6], SWIZ_PTR(p++)); | 1015 | start = offsetof(union data, x16.low16); |
973 | ret |= __put_user_inatomic(data.v[7], SWIZ_PTR(p++)); | 1016 | break; |
974 | } | 1017 | } |
1018 | |||
1019 | ret = 0; | ||
1020 | p = (unsigned long)addr; | ||
1021 | |||
1022 | for (i = 0; i < nb; i++) | ||
1023 | ret |= __put_user_inatomic(data.v[start + i], | ||
1024 | SWIZ_PTR(p++)); | ||
1025 | |||
975 | if (unlikely(ret)) | 1026 | if (unlikely(ret)) |
976 | return -EFAULT; | 1027 | return -EFAULT; |
977 | } else if (flags & F) | 1028 | } else if (flags & F) |
978 | current->thread.TS_FPR(reg) = data.dd; | 1029 | current->thread.TS_FPR(reg) = data.ll; |
979 | else | 1030 | else |
980 | regs->gpr[reg] = data.ll; | 1031 | regs->gpr[reg] = data.ll; |
981 | 1032 | ||
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index d8958be5f31a..2ea5cc033ec8 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
@@ -80,25 +80,27 @@ int main(void) | |||
80 | DEFINE(TASKTHREADPPR, offsetof(struct task_struct, thread.ppr)); | 80 | DEFINE(TASKTHREADPPR, offsetof(struct task_struct, thread.ppr)); |
81 | #else | 81 | #else |
82 | DEFINE(THREAD_INFO, offsetof(struct task_struct, stack)); | 82 | DEFINE(THREAD_INFO, offsetof(struct task_struct, stack)); |
83 | DEFINE(THREAD_INFO_GAP, _ALIGN_UP(sizeof(struct thread_info), 16)); | ||
84 | DEFINE(KSP_LIMIT, offsetof(struct thread_struct, ksp_limit)); | ||
83 | #endif /* CONFIG_PPC64 */ | 85 | #endif /* CONFIG_PPC64 */ |
84 | 86 | ||
85 | DEFINE(KSP, offsetof(struct thread_struct, ksp)); | 87 | DEFINE(KSP, offsetof(struct thread_struct, ksp)); |
86 | DEFINE(KSP_LIMIT, offsetof(struct thread_struct, ksp_limit)); | ||
87 | DEFINE(PT_REGS, offsetof(struct thread_struct, regs)); | 88 | DEFINE(PT_REGS, offsetof(struct thread_struct, regs)); |
88 | #ifdef CONFIG_BOOKE | 89 | #ifdef CONFIG_BOOKE |
89 | DEFINE(THREAD_NORMSAVES, offsetof(struct thread_struct, normsave[0])); | 90 | DEFINE(THREAD_NORMSAVES, offsetof(struct thread_struct, normsave[0])); |
90 | #endif | 91 | #endif |
91 | DEFINE(THREAD_FPEXC_MODE, offsetof(struct thread_struct, fpexc_mode)); | 92 | DEFINE(THREAD_FPEXC_MODE, offsetof(struct thread_struct, fpexc_mode)); |
92 | DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0])); | 93 | DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fp_state)); |
93 | DEFINE(THREAD_FPSCR, offsetof(struct thread_struct, fpscr)); | 94 | DEFINE(THREAD_FPSAVEAREA, offsetof(struct thread_struct, fp_save_area)); |
95 | DEFINE(FPSTATE_FPSCR, offsetof(struct thread_fp_state, fpscr)); | ||
94 | #ifdef CONFIG_ALTIVEC | 96 | #ifdef CONFIG_ALTIVEC |
95 | DEFINE(THREAD_VR0, offsetof(struct thread_struct, vr[0])); | 97 | DEFINE(THREAD_VRSTATE, offsetof(struct thread_struct, vr_state)); |
98 | DEFINE(THREAD_VRSAVEAREA, offsetof(struct thread_struct, vr_save_area)); | ||
96 | DEFINE(THREAD_VRSAVE, offsetof(struct thread_struct, vrsave)); | 99 | DEFINE(THREAD_VRSAVE, offsetof(struct thread_struct, vrsave)); |
97 | DEFINE(THREAD_VSCR, offsetof(struct thread_struct, vscr)); | ||
98 | DEFINE(THREAD_USED_VR, offsetof(struct thread_struct, used_vr)); | 100 | DEFINE(THREAD_USED_VR, offsetof(struct thread_struct, used_vr)); |
101 | DEFINE(VRSTATE_VSCR, offsetof(struct thread_vr_state, vscr)); | ||
99 | #endif /* CONFIG_ALTIVEC */ | 102 | #endif /* CONFIG_ALTIVEC */ |
100 | #ifdef CONFIG_VSX | 103 | #ifdef CONFIG_VSX |
101 | DEFINE(THREAD_VSR0, offsetof(struct thread_struct, fpr)); | ||
102 | DEFINE(THREAD_USED_VSR, offsetof(struct thread_struct, used_vsr)); | 104 | DEFINE(THREAD_USED_VSR, offsetof(struct thread_struct, used_vsr)); |
103 | #endif /* CONFIG_VSX */ | 105 | #endif /* CONFIG_VSX */ |
104 | #ifdef CONFIG_PPC64 | 106 | #ifdef CONFIG_PPC64 |
@@ -113,7 +115,7 @@ int main(void) | |||
113 | #endif /* CONFIG_SPE */ | 115 | #endif /* CONFIG_SPE */ |
114 | #endif /* CONFIG_PPC64 */ | 116 | #endif /* CONFIG_PPC64 */ |
115 | #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) | 117 | #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) |
116 | DEFINE(THREAD_DBCR0, offsetof(struct thread_struct, dbcr0)); | 118 | DEFINE(THREAD_DBCR0, offsetof(struct thread_struct, debug.dbcr0)); |
117 | #endif | 119 | #endif |
118 | #ifdef CONFIG_KVM_BOOK3S_32_HANDLER | 120 | #ifdef CONFIG_KVM_BOOK3S_32_HANDLER |
119 | DEFINE(THREAD_KVM_SVCPU, offsetof(struct thread_struct, kvm_shadow_vcpu)); | 121 | DEFINE(THREAD_KVM_SVCPU, offsetof(struct thread_struct, kvm_shadow_vcpu)); |
@@ -142,20 +144,12 @@ int main(void) | |||
142 | DEFINE(THREAD_TM_PPR, offsetof(struct thread_struct, tm_ppr)); | 144 | DEFINE(THREAD_TM_PPR, offsetof(struct thread_struct, tm_ppr)); |
143 | DEFINE(THREAD_TM_DSCR, offsetof(struct thread_struct, tm_dscr)); | 145 | DEFINE(THREAD_TM_DSCR, offsetof(struct thread_struct, tm_dscr)); |
144 | DEFINE(PT_CKPT_REGS, offsetof(struct thread_struct, ckpt_regs)); | 146 | DEFINE(PT_CKPT_REGS, offsetof(struct thread_struct, ckpt_regs)); |
145 | DEFINE(THREAD_TRANSACT_VR0, offsetof(struct thread_struct, | 147 | DEFINE(THREAD_TRANSACT_VRSTATE, offsetof(struct thread_struct, |
146 | transact_vr[0])); | 148 | transact_vr)); |
147 | DEFINE(THREAD_TRANSACT_VSCR, offsetof(struct thread_struct, | ||
148 | transact_vscr)); | ||
149 | DEFINE(THREAD_TRANSACT_VRSAVE, offsetof(struct thread_struct, | 149 | DEFINE(THREAD_TRANSACT_VRSAVE, offsetof(struct thread_struct, |
150 | transact_vrsave)); | 150 | transact_vrsave)); |
151 | DEFINE(THREAD_TRANSACT_FPR0, offsetof(struct thread_struct, | 151 | DEFINE(THREAD_TRANSACT_FPSTATE, offsetof(struct thread_struct, |
152 | transact_fpr[0])); | 152 | transact_fp)); |
153 | DEFINE(THREAD_TRANSACT_FPSCR, offsetof(struct thread_struct, | ||
154 | transact_fpscr)); | ||
155 | #ifdef CONFIG_VSX | ||
156 | DEFINE(THREAD_TRANSACT_VSR0, offsetof(struct thread_struct, | ||
157 | transact_fpr[0])); | ||
158 | #endif | ||
159 | /* Local pt_regs on stack for Transactional Memory funcs. */ | 153 | /* Local pt_regs on stack for Transactional Memory funcs. */ |
160 | DEFINE(TM_FRAME_SIZE, STACK_FRAME_OVERHEAD + | 154 | DEFINE(TM_FRAME_SIZE, STACK_FRAME_OVERHEAD + |
161 | sizeof(struct pt_regs) + 16); | 155 | sizeof(struct pt_regs) + 16); |
@@ -445,7 +439,7 @@ int main(void) | |||
445 | DEFINE(VCPU_LR, offsetof(struct kvm_vcpu, arch.lr)); | 439 | DEFINE(VCPU_LR, offsetof(struct kvm_vcpu, arch.lr)); |
446 | DEFINE(VCPU_CR, offsetof(struct kvm_vcpu, arch.cr)); | 440 | DEFINE(VCPU_CR, offsetof(struct kvm_vcpu, arch.cr)); |
447 | DEFINE(VCPU_PC, offsetof(struct kvm_vcpu, arch.pc)); | 441 | DEFINE(VCPU_PC, offsetof(struct kvm_vcpu, arch.pc)); |
448 | #ifdef CONFIG_KVM_BOOK3S_64_HV | 442 | #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE |
449 | DEFINE(VCPU_MSR, offsetof(struct kvm_vcpu, arch.shregs.msr)); | 443 | DEFINE(VCPU_MSR, offsetof(struct kvm_vcpu, arch.shregs.msr)); |
450 | DEFINE(VCPU_SRR0, offsetof(struct kvm_vcpu, arch.shregs.srr0)); | 444 | DEFINE(VCPU_SRR0, offsetof(struct kvm_vcpu, arch.shregs.srr0)); |
451 | DEFINE(VCPU_SRR1, offsetof(struct kvm_vcpu, arch.shregs.srr1)); | 445 | DEFINE(VCPU_SRR1, offsetof(struct kvm_vcpu, arch.shregs.srr1)); |
@@ -476,7 +470,7 @@ int main(void) | |||
476 | DEFINE(KVM_LPID, offsetof(struct kvm, arch.lpid)); | 470 | DEFINE(KVM_LPID, offsetof(struct kvm, arch.lpid)); |
477 | 471 | ||
478 | /* book3s */ | 472 | /* book3s */ |
479 | #ifdef CONFIG_KVM_BOOK3S_64_HV | 473 | #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE |
480 | DEFINE(KVM_SDR1, offsetof(struct kvm, arch.sdr1)); | 474 | DEFINE(KVM_SDR1, offsetof(struct kvm, arch.sdr1)); |
481 | DEFINE(KVM_HOST_LPID, offsetof(struct kvm, arch.host_lpid)); | 475 | DEFINE(KVM_HOST_LPID, offsetof(struct kvm, arch.host_lpid)); |
482 | DEFINE(KVM_HOST_LPCR, offsetof(struct kvm, arch.host_lpcr)); | 476 | DEFINE(KVM_HOST_LPCR, offsetof(struct kvm, arch.host_lpcr)); |
@@ -508,6 +502,8 @@ int main(void) | |||
508 | DEFINE(VCPU_PRODDED, offsetof(struct kvm_vcpu, arch.prodded)); | 502 | DEFINE(VCPU_PRODDED, offsetof(struct kvm_vcpu, arch.prodded)); |
509 | DEFINE(VCPU_MMCR, offsetof(struct kvm_vcpu, arch.mmcr)); | 503 | DEFINE(VCPU_MMCR, offsetof(struct kvm_vcpu, arch.mmcr)); |
510 | DEFINE(VCPU_PMC, offsetof(struct kvm_vcpu, arch.pmc)); | 504 | DEFINE(VCPU_PMC, offsetof(struct kvm_vcpu, arch.pmc)); |
505 | DEFINE(VCPU_SIAR, offsetof(struct kvm_vcpu, arch.siar)); | ||
506 | DEFINE(VCPU_SDAR, offsetof(struct kvm_vcpu, arch.sdar)); | ||
511 | DEFINE(VCPU_SLB, offsetof(struct kvm_vcpu, arch.slb)); | 507 | DEFINE(VCPU_SLB, offsetof(struct kvm_vcpu, arch.slb)); |
512 | DEFINE(VCPU_SLB_MAX, offsetof(struct kvm_vcpu, arch.slb_max)); | 508 | DEFINE(VCPU_SLB_MAX, offsetof(struct kvm_vcpu, arch.slb_max)); |
513 | DEFINE(VCPU_SLB_NR, offsetof(struct kvm_vcpu, arch.slb_nr)); | 509 | DEFINE(VCPU_SLB_NR, offsetof(struct kvm_vcpu, arch.slb_nr)); |
@@ -517,18 +513,22 @@ int main(void) | |||
517 | DEFINE(VCPU_TRAP, offsetof(struct kvm_vcpu, arch.trap)); | 513 | DEFINE(VCPU_TRAP, offsetof(struct kvm_vcpu, arch.trap)); |
518 | DEFINE(VCPU_PTID, offsetof(struct kvm_vcpu, arch.ptid)); | 514 | DEFINE(VCPU_PTID, offsetof(struct kvm_vcpu, arch.ptid)); |
519 | DEFINE(VCPU_CFAR, offsetof(struct kvm_vcpu, arch.cfar)); | 515 | DEFINE(VCPU_CFAR, offsetof(struct kvm_vcpu, arch.cfar)); |
516 | DEFINE(VCPU_PPR, offsetof(struct kvm_vcpu, arch.ppr)); | ||
517 | DEFINE(VCPU_SHADOW_SRR1, offsetof(struct kvm_vcpu, arch.shadow_srr1)); | ||
520 | DEFINE(VCORE_ENTRY_EXIT, offsetof(struct kvmppc_vcore, entry_exit_count)); | 518 | DEFINE(VCORE_ENTRY_EXIT, offsetof(struct kvmppc_vcore, entry_exit_count)); |
521 | DEFINE(VCORE_NAP_COUNT, offsetof(struct kvmppc_vcore, nap_count)); | 519 | DEFINE(VCORE_NAP_COUNT, offsetof(struct kvmppc_vcore, nap_count)); |
522 | DEFINE(VCORE_IN_GUEST, offsetof(struct kvmppc_vcore, in_guest)); | 520 | DEFINE(VCORE_IN_GUEST, offsetof(struct kvmppc_vcore, in_guest)); |
523 | DEFINE(VCORE_NAPPING_THREADS, offsetof(struct kvmppc_vcore, napping_threads)); | 521 | DEFINE(VCORE_NAPPING_THREADS, offsetof(struct kvmppc_vcore, napping_threads)); |
524 | DEFINE(VCPU_SVCPU, offsetof(struct kvmppc_vcpu_book3s, shadow_vcpu) - | 522 | DEFINE(VCORE_TB_OFFSET, offsetof(struct kvmppc_vcore, tb_offset)); |
525 | offsetof(struct kvmppc_vcpu_book3s, vcpu)); | 523 | DEFINE(VCORE_LPCR, offsetof(struct kvmppc_vcore, lpcr)); |
524 | DEFINE(VCORE_PCR, offsetof(struct kvmppc_vcore, pcr)); | ||
526 | DEFINE(VCPU_SLB_E, offsetof(struct kvmppc_slb, orige)); | 525 | DEFINE(VCPU_SLB_E, offsetof(struct kvmppc_slb, orige)); |
527 | DEFINE(VCPU_SLB_V, offsetof(struct kvmppc_slb, origv)); | 526 | DEFINE(VCPU_SLB_V, offsetof(struct kvmppc_slb, origv)); |
528 | DEFINE(VCPU_SLB_SIZE, sizeof(struct kvmppc_slb)); | 527 | DEFINE(VCPU_SLB_SIZE, sizeof(struct kvmppc_slb)); |
529 | 528 | ||
530 | #ifdef CONFIG_PPC_BOOK3S_64 | 529 | #ifdef CONFIG_PPC_BOOK3S_64 |
531 | #ifdef CONFIG_KVM_BOOK3S_PR | 530 | #ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE |
531 | DEFINE(PACA_SVCPU, offsetof(struct paca_struct, shadow_vcpu)); | ||
532 | # define SVCPU_FIELD(x, f) DEFINE(x, offsetof(struct paca_struct, shadow_vcpu.f)) | 532 | # define SVCPU_FIELD(x, f) DEFINE(x, offsetof(struct paca_struct, shadow_vcpu.f)) |
533 | #else | 533 | #else |
534 | # define SVCPU_FIELD(x, f) | 534 | # define SVCPU_FIELD(x, f) |
@@ -580,7 +580,7 @@ int main(void) | |||
580 | HSTATE_FIELD(HSTATE_RESTORE_HID5, restore_hid5); | 580 | HSTATE_FIELD(HSTATE_RESTORE_HID5, restore_hid5); |
581 | HSTATE_FIELD(HSTATE_NAPPING, napping); | 581 | HSTATE_FIELD(HSTATE_NAPPING, napping); |
582 | 582 | ||
583 | #ifdef CONFIG_KVM_BOOK3S_64_HV | 583 | #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE |
584 | HSTATE_FIELD(HSTATE_HWTHREAD_REQ, hwthread_req); | 584 | HSTATE_FIELD(HSTATE_HWTHREAD_REQ, hwthread_req); |
585 | HSTATE_FIELD(HSTATE_HWTHREAD_STATE, hwthread_state); | 585 | HSTATE_FIELD(HSTATE_HWTHREAD_STATE, hwthread_state); |
586 | HSTATE_FIELD(HSTATE_KVM_VCPU, kvm_vcpu); | 586 | HSTATE_FIELD(HSTATE_KVM_VCPU, kvm_vcpu); |
@@ -596,10 +596,11 @@ int main(void) | |||
596 | HSTATE_FIELD(HSTATE_DABR, dabr); | 596 | HSTATE_FIELD(HSTATE_DABR, dabr); |
597 | HSTATE_FIELD(HSTATE_DECEXP, dec_expires); | 597 | HSTATE_FIELD(HSTATE_DECEXP, dec_expires); |
598 | DEFINE(IPI_PRIORITY, IPI_PRIORITY); | 598 | DEFINE(IPI_PRIORITY, IPI_PRIORITY); |
599 | #endif /* CONFIG_KVM_BOOK3S_64_HV */ | 599 | #endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */ |
600 | 600 | ||
601 | #ifdef CONFIG_PPC_BOOK3S_64 | 601 | #ifdef CONFIG_PPC_BOOK3S_64 |
602 | HSTATE_FIELD(HSTATE_CFAR, cfar); | 602 | HSTATE_FIELD(HSTATE_CFAR, cfar); |
603 | HSTATE_FIELD(HSTATE_PPR, ppr); | ||
603 | #endif /* CONFIG_PPC_BOOK3S_64 */ | 604 | #endif /* CONFIG_PPC_BOOK3S_64 */ |
604 | 605 | ||
605 | #else /* CONFIG_PPC_BOOK3S */ | 606 | #else /* CONFIG_PPC_BOOK3S */ |
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c index 55593ee2d5aa..671302065347 100644 --- a/arch/powerpc/kernel/eeh.c +++ b/arch/powerpc/kernel/eeh.c | |||
@@ -189,14 +189,13 @@ static size_t eeh_gather_pci_data(struct eeh_dev *edev, char * buf, size_t len) | |||
189 | } | 189 | } |
190 | 190 | ||
191 | /* If PCI-E capable, dump PCI-E cap 10, and the AER */ | 191 | /* If PCI-E capable, dump PCI-E cap 10, and the AER */ |
192 | cap = pci_find_capability(dev, PCI_CAP_ID_EXP); | 192 | if (pci_is_pcie(dev)) { |
193 | if (cap) { | ||
194 | n += scnprintf(buf+n, len-n, "pci-e cap10:\n"); | 193 | n += scnprintf(buf+n, len-n, "pci-e cap10:\n"); |
195 | printk(KERN_WARNING | 194 | printk(KERN_WARNING |
196 | "EEH: PCI-E capabilities and status follow:\n"); | 195 | "EEH: PCI-E capabilities and status follow:\n"); |
197 | 196 | ||
198 | for (i=0; i<=8; i++) { | 197 | for (i=0; i<=8; i++) { |
199 | eeh_ops->read_config(dn, cap+4*i, 4, &cfg); | 198 | eeh_ops->read_config(dn, dev->pcie_cap+4*i, 4, &cfg); |
200 | n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg); | 199 | n += scnprintf(buf+n, len-n, "%02x:%x\n", 4*i, cfg); |
201 | printk(KERN_WARNING "EEH: PCI-E %02x: %08x\n", i, cfg); | 200 | printk(KERN_WARNING "EEH: PCI-E %02x: %08x\n", i, cfg); |
202 | } | 201 | } |
@@ -327,11 +326,11 @@ static int eeh_phb_check_failure(struct eeh_pe *pe) | |||
327 | /* Isolate the PHB and send event */ | 326 | /* Isolate the PHB and send event */ |
328 | eeh_pe_state_mark(phb_pe, EEH_PE_ISOLATED); | 327 | eeh_pe_state_mark(phb_pe, EEH_PE_ISOLATED); |
329 | eeh_serialize_unlock(flags); | 328 | eeh_serialize_unlock(flags); |
330 | eeh_send_failure_event(phb_pe); | ||
331 | 329 | ||
332 | pr_err("EEH: PHB#%x failure detected\n", | 330 | pr_err("EEH: PHB#%x failure detected\n", |
333 | phb_pe->phb->global_number); | 331 | phb_pe->phb->global_number); |
334 | dump_stack(); | 332 | dump_stack(); |
333 | eeh_send_failure_event(phb_pe); | ||
335 | 334 | ||
336 | return 1; | 335 | return 1; |
337 | out: | 336 | out: |
@@ -454,8 +453,6 @@ int eeh_dev_check_failure(struct eeh_dev *edev) | |||
454 | eeh_pe_state_mark(pe, EEH_PE_ISOLATED); | 453 | eeh_pe_state_mark(pe, EEH_PE_ISOLATED); |
455 | eeh_serialize_unlock(flags); | 454 | eeh_serialize_unlock(flags); |
456 | 455 | ||
457 | eeh_send_failure_event(pe); | ||
458 | |||
459 | /* Most EEH events are due to device driver bugs. Having | 456 | /* Most EEH events are due to device driver bugs. Having |
460 | * a stack trace will help the device-driver authors figure | 457 | * a stack trace will help the device-driver authors figure |
461 | * out what happened. So print that out. | 458 | * out what happened. So print that out. |
@@ -464,6 +461,8 @@ int eeh_dev_check_failure(struct eeh_dev *edev) | |||
464 | pe->addr, pe->phb->global_number); | 461 | pe->addr, pe->phb->global_number); |
465 | dump_stack(); | 462 | dump_stack(); |
466 | 463 | ||
464 | eeh_send_failure_event(pe); | ||
465 | |||
467 | return 1; | 466 | return 1; |
468 | 467 | ||
469 | dn_unlock: | 468 | dn_unlock: |
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index c04cdf70d487..bbfb0294b354 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S | |||
@@ -673,9 +673,7 @@ _GLOBAL(ret_from_except_lite) | |||
673 | 673 | ||
674 | resume_kernel: | 674 | resume_kernel: |
675 | /* check current_thread_info, _TIF_EMULATE_STACK_STORE */ | 675 | /* check current_thread_info, _TIF_EMULATE_STACK_STORE */ |
676 | CURRENT_THREAD_INFO(r9, r1) | 676 | andis. r8,r4,_TIF_EMULATE_STACK_STORE@h |
677 | ld r8,TI_FLAGS(r9) | ||
678 | andis. r8,r8,_TIF_EMULATE_STACK_STORE@h | ||
679 | beq+ 1f | 677 | beq+ 1f |
680 | 678 | ||
681 | addi r8,r1,INT_FRAME_SIZE /* Get the kprobed function entry */ | 679 | addi r8,r1,INT_FRAME_SIZE /* Get the kprobed function entry */ |
@@ -820,6 +818,12 @@ fast_exception_return: | |||
820 | andi. r0,r3,MSR_RI | 818 | andi. r0,r3,MSR_RI |
821 | beq- unrecov_restore | 819 | beq- unrecov_restore |
822 | 820 | ||
821 | /* Load PPR from thread struct before we clear MSR:RI */ | ||
822 | BEGIN_FTR_SECTION | ||
823 | ld r2,PACACURRENT(r13) | ||
824 | ld r2,TASKTHREADPPR(r2) | ||
825 | END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) | ||
826 | |||
823 | /* | 827 | /* |
824 | * Clear RI before restoring r13. If we are returning to | 828 | * Clear RI before restoring r13. If we are returning to |
825 | * userspace and we take an exception after restoring r13, | 829 | * userspace and we take an exception after restoring r13, |
@@ -840,8 +844,10 @@ fast_exception_return: | |||
840 | */ | 844 | */ |
841 | andi. r0,r3,MSR_PR | 845 | andi. r0,r3,MSR_PR |
842 | beq 1f | 846 | beq 1f |
847 | BEGIN_FTR_SECTION | ||
848 | mtspr SPRN_PPR,r2 /* Restore PPR */ | ||
849 | END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) | ||
843 | ACCOUNT_CPU_USER_EXIT(r2, r4) | 850 | ACCOUNT_CPU_USER_EXIT(r2, r4) |
844 | RESTORE_PPR(r2, r4) | ||
845 | REST_GPR(13, r1) | 851 | REST_GPR(13, r1) |
846 | 1: | 852 | 1: |
847 | mtspr SPRN_SRR1,r3 | 853 | mtspr SPRN_SRR1,r3 |
@@ -1017,7 +1023,7 @@ _GLOBAL(enter_rtas) | |||
1017 | 1023 | ||
1018 | li r9,1 | 1024 | li r9,1 |
1019 | rldicr r9,r9,MSR_SF_LG,(63-MSR_SF_LG) | 1025 | rldicr r9,r9,MSR_SF_LG,(63-MSR_SF_LG) |
1020 | ori r9,r9,MSR_IR|MSR_DR|MSR_FE0|MSR_FE1|MSR_FP|MSR_RI | 1026 | ori r9,r9,MSR_IR|MSR_DR|MSR_FE0|MSR_FE1|MSR_FP|MSR_RI|MSR_LE |
1021 | andc r6,r0,r9 | 1027 | andc r6,r0,r9 |
1022 | sync /* disable interrupts so SRR0/1 */ | 1028 | sync /* disable interrupts so SRR0/1 */ |
1023 | mtmsrd r0 /* don't get trashed */ | 1029 | mtmsrd r0 /* don't get trashed */ |
@@ -1032,6 +1038,8 @@ _GLOBAL(enter_rtas) | |||
1032 | b . /* prevent speculative execution */ | 1038 | b . /* prevent speculative execution */ |
1033 | 1039 | ||
1034 | _STATIC(rtas_return_loc) | 1040 | _STATIC(rtas_return_loc) |
1041 | FIXUP_ENDIAN | ||
1042 | |||
1035 | /* relocation is off at this point */ | 1043 | /* relocation is off at this point */ |
1036 | GET_PACA(r4) | 1044 | GET_PACA(r4) |
1037 | clrldi r4,r4,2 /* convert to realmode address */ | 1045 | clrldi r4,r4,2 /* convert to realmode address */ |
@@ -1103,28 +1111,30 @@ _GLOBAL(enter_prom) | |||
1103 | std r10,_CCR(r1) | 1111 | std r10,_CCR(r1) |
1104 | std r11,_MSR(r1) | 1112 | std r11,_MSR(r1) |
1105 | 1113 | ||
1106 | /* Get the PROM entrypoint */ | 1114 | /* Put PROM address in SRR0 */ |
1107 | mtlr r4 | 1115 | mtsrr0 r4 |
1108 | 1116 | ||
1109 | /* Switch MSR to 32 bits mode | 1117 | /* Setup our trampoline return addr in LR */ |
1118 | bcl 20,31,$+4 | ||
1119 | 0: mflr r4 | ||
1120 | addi r4,r4,(1f - 0b) | ||
1121 | mtlr r4 | ||
1122 | |||
1123 | /* Prepare a 32-bit mode big endian MSR | ||
1110 | */ | 1124 | */ |
1111 | #ifdef CONFIG_PPC_BOOK3E | 1125 | #ifdef CONFIG_PPC_BOOK3E |
1112 | rlwinm r11,r11,0,1,31 | 1126 | rlwinm r11,r11,0,1,31 |
1113 | mtmsr r11 | 1127 | mtsrr1 r11 |
1128 | rfi | ||
1114 | #else /* CONFIG_PPC_BOOK3E */ | 1129 | #else /* CONFIG_PPC_BOOK3E */ |
1115 | mfmsr r11 | 1130 | LOAD_REG_IMMEDIATE(r12, MSR_SF | MSR_ISF | MSR_LE) |
1116 | li r12,1 | 1131 | andc r11,r11,r12 |
1117 | rldicr r12,r12,MSR_SF_LG,(63-MSR_SF_LG) | 1132 | mtsrr1 r11 |
1118 | andc r11,r11,r12 | 1133 | rfid |
1119 | li r12,1 | ||
1120 | rldicr r12,r12,MSR_ISF_LG,(63-MSR_ISF_LG) | ||
1121 | andc r11,r11,r12 | ||
1122 | mtmsrd r11 | ||
1123 | #endif /* CONFIG_PPC_BOOK3E */ | 1134 | #endif /* CONFIG_PPC_BOOK3E */ |
1124 | isync | ||
1125 | 1135 | ||
1126 | /* Enter PROM here... */ | 1136 | 1: /* Return from OF */ |
1127 | blrl | 1137 | FIXUP_ENDIAN |
1128 | 1138 | ||
1129 | /* Just make sure that r1 top 32 bits didn't get | 1139 | /* Just make sure that r1 top 32 bits didn't get |
1130 | * corrupt by OF | 1140 | * corrupt by OF |
diff --git a/arch/powerpc/kernel/epapr_paravirt.c b/arch/powerpc/kernel/epapr_paravirt.c index 6300c13bbde4..7898be90f2dc 100644 --- a/arch/powerpc/kernel/epapr_paravirt.c +++ b/arch/powerpc/kernel/epapr_paravirt.c | |||
@@ -18,6 +18,7 @@ | |||
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/of.h> | 20 | #include <linux/of.h> |
21 | #include <linux/of_fdt.h> | ||
21 | #include <asm/epapr_hcalls.h> | 22 | #include <asm/epapr_hcalls.h> |
22 | #include <asm/cacheflush.h> | 23 | #include <asm/cacheflush.h> |
23 | #include <asm/code-patching.h> | 24 | #include <asm/code-patching.h> |
diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S index 2d067049db27..e7751561fd1d 100644 --- a/arch/powerpc/kernel/exceptions-64e.S +++ b/arch/powerpc/kernel/exceptions-64e.S | |||
@@ -399,7 +399,7 @@ interrupt_end_book3e: | |||
399 | 399 | ||
400 | /* Altivec Unavailable Interrupt */ | 400 | /* Altivec Unavailable Interrupt */ |
401 | START_EXCEPTION(altivec_unavailable); | 401 | START_EXCEPTION(altivec_unavailable); |
402 | NORMAL_EXCEPTION_PROLOG(0x200, BOOKE_INTERRUPT_ALTIVEC_UNAVAIL, | 402 | NORMAL_EXCEPTION_PROLOG(0x200, BOOKE_INTERRUPT_SPE_ALTIVEC_UNAVAIL, |
403 | PROLOG_ADDITION_NONE) | 403 | PROLOG_ADDITION_NONE) |
404 | /* we can probably do a shorter exception entry for that one... */ | 404 | /* we can probably do a shorter exception entry for that one... */ |
405 | EXCEPTION_COMMON(0x200, PACA_EXGEN, INTS_KEEP) | 405 | EXCEPTION_COMMON(0x200, PACA_EXGEN, INTS_KEEP) |
@@ -421,7 +421,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | |||
421 | 421 | ||
422 | /* AltiVec Assist */ | 422 | /* AltiVec Assist */ |
423 | START_EXCEPTION(altivec_assist); | 423 | START_EXCEPTION(altivec_assist); |
424 | NORMAL_EXCEPTION_PROLOG(0x220, BOOKE_INTERRUPT_ALTIVEC_ASSIST, | 424 | NORMAL_EXCEPTION_PROLOG(0x220, |
425 | BOOKE_INTERRUPT_SPE_FP_DATA_ALTIVEC_ASSIST, | ||
425 | PROLOG_ADDITION_NONE) | 426 | PROLOG_ADDITION_NONE) |
426 | EXCEPTION_COMMON(0x220, PACA_EXGEN, INTS_DISABLE) | 427 | EXCEPTION_COMMON(0x220, PACA_EXGEN, INTS_DISABLE) |
427 | bl .save_nvgprs | 428 | bl .save_nvgprs |
@@ -607,6 +608,7 @@ kernel_dbg_exc: | |||
607 | NORMAL_EXCEPTION_PROLOG(0x260, BOOKE_INTERRUPT_PERFORMANCE_MONITOR, | 608 | NORMAL_EXCEPTION_PROLOG(0x260, BOOKE_INTERRUPT_PERFORMANCE_MONITOR, |
608 | PROLOG_ADDITION_NONE) | 609 | PROLOG_ADDITION_NONE) |
609 | EXCEPTION_COMMON(0x260, PACA_EXGEN, INTS_DISABLE) | 610 | EXCEPTION_COMMON(0x260, PACA_EXGEN, INTS_DISABLE) |
611 | CHECK_NAPPING() | ||
610 | addi r3,r1,STACK_FRAME_OVERHEAD | 612 | addi r3,r1,STACK_FRAME_OVERHEAD |
611 | bl .performance_monitor_exception | 613 | bl .performance_monitor_exception |
612 | b .ret_from_except_lite | 614 | b .ret_from_except_lite |
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index 3a9ed6ac224b..9f905e40922e 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S | |||
@@ -126,7 +126,7 @@ BEGIN_FTR_SECTION | |||
126 | bgt cr1,. | 126 | bgt cr1,. |
127 | GET_PACA(r13) | 127 | GET_PACA(r13) |
128 | 128 | ||
129 | #ifdef CONFIG_KVM_BOOK3S_64_HV | 129 | #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE |
130 | li r0,KVM_HWTHREAD_IN_KERNEL | 130 | li r0,KVM_HWTHREAD_IN_KERNEL |
131 | stb r0,HSTATE_HWTHREAD_STATE(r13) | 131 | stb r0,HSTATE_HWTHREAD_STATE(r13) |
132 | /* Order setting hwthread_state vs. testing hwthread_req */ | 132 | /* Order setting hwthread_state vs. testing hwthread_req */ |
@@ -425,7 +425,7 @@ data_access_check_stab: | |||
425 | mfspr r9,SPRN_DSISR | 425 | mfspr r9,SPRN_DSISR |
426 | srdi r10,r10,60 | 426 | srdi r10,r10,60 |
427 | rlwimi r10,r9,16,0x20 | 427 | rlwimi r10,r9,16,0x20 |
428 | #ifdef CONFIG_KVM_BOOK3S_PR | 428 | #ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE |
429 | lbz r9,HSTATE_IN_GUEST(r13) | 429 | lbz r9,HSTATE_IN_GUEST(r13) |
430 | rlwimi r10,r9,8,0x300 | 430 | rlwimi r10,r9,8,0x300 |
431 | #endif | 431 | #endif |
@@ -650,6 +650,32 @@ slb_miss_user_pseries: | |||
650 | b . /* prevent spec. execution */ | 650 | b . /* prevent spec. execution */ |
651 | #endif /* __DISABLED__ */ | 651 | #endif /* __DISABLED__ */ |
652 | 652 | ||
653 | #ifdef CONFIG_KVM_BOOK3S_64_HANDLER | ||
654 | kvmppc_skip_interrupt: | ||
655 | /* | ||
656 | * Here all GPRs are unchanged from when the interrupt happened | ||
657 | * except for r13, which is saved in SPRG_SCRATCH0. | ||
658 | */ | ||
659 | mfspr r13, SPRN_SRR0 | ||
660 | addi r13, r13, 4 | ||
661 | mtspr SPRN_SRR0, r13 | ||
662 | GET_SCRATCH0(r13) | ||
663 | rfid | ||
664 | b . | ||
665 | |||
666 | kvmppc_skip_Hinterrupt: | ||
667 | /* | ||
668 | * Here all GPRs are unchanged from when the interrupt happened | ||
669 | * except for r13, which is saved in SPRG_SCRATCH0. | ||
670 | */ | ||
671 | mfspr r13, SPRN_HSRR0 | ||
672 | addi r13, r13, 4 | ||
673 | mtspr SPRN_HSRR0, r13 | ||
674 | GET_SCRATCH0(r13) | ||
675 | hrfid | ||
676 | b . | ||
677 | #endif | ||
678 | |||
653 | /* | 679 | /* |
654 | * Code from here down to __end_handlers is invoked from the | 680 | * Code from here down to __end_handlers is invoked from the |
655 | * exception prologs above. Because the prologs assemble the | 681 | * exception prologs above. Because the prologs assemble the |
diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S index caeaabf11a2f..f7f5b8bed68f 100644 --- a/arch/powerpc/kernel/fpu.S +++ b/arch/powerpc/kernel/fpu.S | |||
@@ -35,15 +35,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX); \ | |||
35 | 2: REST_32VSRS(n,c,base); \ | 35 | 2: REST_32VSRS(n,c,base); \ |
36 | 3: | 36 | 3: |
37 | 37 | ||
38 | #define __REST_32FPVSRS_TRANSACT(n,c,base) \ | ||
39 | BEGIN_FTR_SECTION \ | ||
40 | b 2f; \ | ||
41 | END_FTR_SECTION_IFSET(CPU_FTR_VSX); \ | ||
42 | REST_32FPRS_TRANSACT(n,base); \ | ||
43 | b 3f; \ | ||
44 | 2: REST_32VSRS_TRANSACT(n,c,base); \ | ||
45 | 3: | ||
46 | |||
47 | #define __SAVE_32FPVSRS(n,c,base) \ | 38 | #define __SAVE_32FPVSRS(n,c,base) \ |
48 | BEGIN_FTR_SECTION \ | 39 | BEGIN_FTR_SECTION \ |
49 | b 2f; \ | 40 | b 2f; \ |
@@ -54,40 +45,12 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX); \ | |||
54 | 3: | 45 | 3: |
55 | #else | 46 | #else |
56 | #define __REST_32FPVSRS(n,b,base) REST_32FPRS(n, base) | 47 | #define __REST_32FPVSRS(n,b,base) REST_32FPRS(n, base) |
57 | #define __REST_32FPVSRS_TRANSACT(n,b,base) REST_32FPRS(n, base) | ||
58 | #define __SAVE_32FPVSRS(n,b,base) SAVE_32FPRS(n, base) | 48 | #define __SAVE_32FPVSRS(n,b,base) SAVE_32FPRS(n, base) |
59 | #endif | 49 | #endif |
60 | #define REST_32FPVSRS(n,c,base) __REST_32FPVSRS(n,__REG_##c,__REG_##base) | 50 | #define REST_32FPVSRS(n,c,base) __REST_32FPVSRS(n,__REG_##c,__REG_##base) |
61 | #define REST_32FPVSRS_TRANSACT(n,c,base) \ | ||
62 | __REST_32FPVSRS_TRANSACT(n,__REG_##c,__REG_##base) | ||
63 | #define SAVE_32FPVSRS(n,c,base) __SAVE_32FPVSRS(n,__REG_##c,__REG_##base) | 51 | #define SAVE_32FPVSRS(n,c,base) __SAVE_32FPVSRS(n,__REG_##c,__REG_##base) |
64 | 52 | ||
65 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | 53 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM |
66 | /* | ||
67 | * Wrapper to call load_up_fpu from C. | ||
68 | * void do_load_up_fpu(struct pt_regs *regs); | ||
69 | */ | ||
70 | _GLOBAL(do_load_up_fpu) | ||
71 | mflr r0 | ||
72 | std r0, 16(r1) | ||
73 | stdu r1, -112(r1) | ||
74 | |||
75 | subi r6, r3, STACK_FRAME_OVERHEAD | ||
76 | /* load_up_fpu expects r12=MSR, r13=PACA, and returns | ||
77 | * with r12 = new MSR. | ||
78 | */ | ||
79 | ld r12,_MSR(r6) | ||
80 | GET_PACA(r13) | ||
81 | |||
82 | bl load_up_fpu | ||
83 | std r12,_MSR(r6) | ||
84 | |||
85 | ld r0, 112+16(r1) | ||
86 | addi r1, r1, 112 | ||
87 | mtlr r0 | ||
88 | blr | ||
89 | |||
90 | |||
91 | /* void do_load_up_transact_fpu(struct thread_struct *thread) | 54 | /* void do_load_up_transact_fpu(struct thread_struct *thread) |
92 | * | 55 | * |
93 | * This is similar to load_up_fpu but for the transactional version of the FP | 56 | * This is similar to load_up_fpu but for the transactional version of the FP |
@@ -105,9 +68,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX) | |||
105 | SYNC | 68 | SYNC |
106 | MTMSRD(r5) | 69 | MTMSRD(r5) |
107 | 70 | ||
108 | lfd fr0,THREAD_TRANSACT_FPSCR(r3) | 71 | addi r7,r3,THREAD_TRANSACT_FPSTATE |
72 | lfd fr0,FPSTATE_FPSCR(r7) | ||
109 | MTFSF_L(fr0) | 73 | MTFSF_L(fr0) |
110 | REST_32FPVSRS_TRANSACT(0, R4, R3) | 74 | REST_32FPVSRS(0, R4, R7) |
111 | 75 | ||
112 | /* FP/VSX off again */ | 76 | /* FP/VSX off again */ |
113 | MTMSRD(r6) | 77 | MTMSRD(r6) |
@@ -117,11 +81,33 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX) | |||
117 | #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ | 81 | #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ |
118 | 82 | ||
119 | /* | 83 | /* |
84 | * Load state from memory into FP registers including FPSCR. | ||
85 | * Assumes the caller has enabled FP in the MSR. | ||
86 | */ | ||
87 | _GLOBAL(load_fp_state) | ||
88 | lfd fr0,FPSTATE_FPSCR(r3) | ||
89 | MTFSF_L(fr0) | ||
90 | REST_32FPVSRS(0, R4, R3) | ||
91 | blr | ||
92 | |||
93 | /* | ||
94 | * Store FP state into memory, including FPSCR | ||
95 | * Assumes the caller has enabled FP in the MSR. | ||
96 | */ | ||
97 | _GLOBAL(store_fp_state) | ||
98 | SAVE_32FPVSRS(0, R4, R3) | ||
99 | mffs fr0 | ||
100 | stfd fr0,FPSTATE_FPSCR(r3) | ||
101 | blr | ||
102 | |||
103 | /* | ||
120 | * This task wants to use the FPU now. | 104 | * This task wants to use the FPU now. |
121 | * On UP, disable FP for the task which had the FPU previously, | 105 | * On UP, disable FP for the task which had the FPU previously, |
122 | * and save its floating-point registers in its thread_struct. | 106 | * and save its floating-point registers in its thread_struct. |
123 | * Load up this task's FP registers from its thread_struct, | 107 | * Load up this task's FP registers from its thread_struct, |
124 | * enable the FPU for the current task and return to the task. | 108 | * enable the FPU for the current task and return to the task. |
109 | * Note that on 32-bit this can only use registers that will be | ||
110 | * restored by fast_exception_return, i.e. r3 - r6, r10 and r11. | ||
125 | */ | 111 | */ |
126 | _GLOBAL(load_up_fpu) | 112 | _GLOBAL(load_up_fpu) |
127 | mfmsr r5 | 113 | mfmsr r5 |
@@ -147,9 +133,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX) | |||
147 | beq 1f | 133 | beq 1f |
148 | toreal(r4) | 134 | toreal(r4) |
149 | addi r4,r4,THREAD /* want last_task_used_math->thread */ | 135 | addi r4,r4,THREAD /* want last_task_used_math->thread */ |
150 | SAVE_32FPVSRS(0, R5, R4) | 136 | addi r10,r4,THREAD_FPSTATE |
137 | SAVE_32FPVSRS(0, R5, R10) | ||
151 | mffs fr0 | 138 | mffs fr0 |
152 | stfd fr0,THREAD_FPSCR(r4) | 139 | stfd fr0,FPSTATE_FPSCR(r10) |
153 | PPC_LL r5,PT_REGS(r4) | 140 | PPC_LL r5,PT_REGS(r4) |
154 | toreal(r5) | 141 | toreal(r5) |
155 | PPC_LL r4,_MSR-STACK_FRAME_OVERHEAD(r5) | 142 | PPC_LL r4,_MSR-STACK_FRAME_OVERHEAD(r5) |
@@ -160,7 +147,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX) | |||
160 | #endif /* CONFIG_SMP */ | 147 | #endif /* CONFIG_SMP */ |
161 | /* enable use of FP after return */ | 148 | /* enable use of FP after return */ |
162 | #ifdef CONFIG_PPC32 | 149 | #ifdef CONFIG_PPC32 |
163 | mfspr r5,SPRN_SPRG_THREAD /* current task's THREAD (phys) */ | 150 | mfspr r5,SPRN_SPRG_THREAD /* current task's THREAD (phys) */ |
164 | lwz r4,THREAD_FPEXC_MODE(r5) | 151 | lwz r4,THREAD_FPEXC_MODE(r5) |
165 | ori r9,r9,MSR_FP /* enable FP for current */ | 152 | ori r9,r9,MSR_FP /* enable FP for current */ |
166 | or r9,r9,r4 | 153 | or r9,r9,r4 |
@@ -172,9 +159,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX) | |||
172 | or r12,r12,r4 | 159 | or r12,r12,r4 |
173 | std r12,_MSR(r1) | 160 | std r12,_MSR(r1) |
174 | #endif | 161 | #endif |
175 | lfd fr0,THREAD_FPSCR(r5) | 162 | addi r10,r5,THREAD_FPSTATE |
163 | lfd fr0,FPSTATE_FPSCR(r10) | ||
176 | MTFSF_L(fr0) | 164 | MTFSF_L(fr0) |
177 | REST_32FPVSRS(0, R4, R5) | 165 | REST_32FPVSRS(0, R4, R10) |
178 | #ifndef CONFIG_SMP | 166 | #ifndef CONFIG_SMP |
179 | subi r4,r5,THREAD | 167 | subi r4,r5,THREAD |
180 | fromreal(r4) | 168 | fromreal(r4) |
@@ -206,11 +194,15 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX) | |||
206 | PPC_LCMPI 0,r3,0 | 194 | PPC_LCMPI 0,r3,0 |
207 | beqlr- /* if no previous owner, done */ | 195 | beqlr- /* if no previous owner, done */ |
208 | addi r3,r3,THREAD /* want THREAD of task */ | 196 | addi r3,r3,THREAD /* want THREAD of task */ |
197 | PPC_LL r6,THREAD_FPSAVEAREA(r3) | ||
209 | PPC_LL r5,PT_REGS(r3) | 198 | PPC_LL r5,PT_REGS(r3) |
210 | PPC_LCMPI 0,r5,0 | 199 | PPC_LCMPI 0,r6,0 |
211 | SAVE_32FPVSRS(0, R4 ,R3) | 200 | bne 2f |
201 | addi r6,r3,THREAD_FPSTATE | ||
202 | 2: PPC_LCMPI 0,r5,0 | ||
203 | SAVE_32FPVSRS(0, R4, R6) | ||
212 | mffs fr0 | 204 | mffs fr0 |
213 | stfd fr0,THREAD_FPSCR(r3) | 205 | stfd fr0,FPSTATE_FPSCR(r6) |
214 | beq 1f | 206 | beq 1f |
215 | PPC_LL r4,_MSR-STACK_FRAME_OVERHEAD(r5) | 207 | PPC_LL r4,_MSR-STACK_FRAME_OVERHEAD(r5) |
216 | li r3,MSR_FP|MSR_FE0|MSR_FE1 | 208 | li r3,MSR_FP|MSR_FE0|MSR_FE1 |
diff --git a/arch/powerpc/kernel/ftrace.c b/arch/powerpc/kernel/ftrace.c index 1fb78561096a..9b27b293a922 100644 --- a/arch/powerpc/kernel/ftrace.c +++ b/arch/powerpc/kernel/ftrace.c | |||
@@ -174,7 +174,11 @@ __ftrace_make_nop(struct module *mod, | |||
174 | 174 | ||
175 | pr_devel(" %08x %08x\n", jmp[0], jmp[1]); | 175 | pr_devel(" %08x %08x\n", jmp[0], jmp[1]); |
176 | 176 | ||
177 | #ifdef __LITTLE_ENDIAN__ | ||
178 | ptr = ((unsigned long)jmp[1] << 32) + jmp[0]; | ||
179 | #else | ||
177 | ptr = ((unsigned long)jmp[0] << 32) + jmp[1]; | 180 | ptr = ((unsigned long)jmp[0] << 32) + jmp[1]; |
181 | #endif | ||
178 | 182 | ||
179 | /* This should match what was called */ | 183 | /* This should match what was called */ |
180 | if (ptr != ppc_function_entry((void *)addr)) { | 184 | if (ptr != ppc_function_entry((void *)addr)) { |
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 3d11d8038dee..2ae41aba4053 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S | |||
@@ -68,6 +68,7 @@ _stext: | |||
68 | _GLOBAL(__start) | 68 | _GLOBAL(__start) |
69 | /* NOP this out unconditionally */ | 69 | /* NOP this out unconditionally */ |
70 | BEGIN_FTR_SECTION | 70 | BEGIN_FTR_SECTION |
71 | FIXUP_ENDIAN | ||
71 | b .__start_initialization_multiplatform | 72 | b .__start_initialization_multiplatform |
72 | END_FTR_SECTION(0, 1) | 73 | END_FTR_SECTION(0, 1) |
73 | 74 | ||
@@ -115,6 +116,7 @@ __run_at_load: | |||
115 | */ | 116 | */ |
116 | .globl __secondary_hold | 117 | .globl __secondary_hold |
117 | __secondary_hold: | 118 | __secondary_hold: |
119 | FIXUP_ENDIAN | ||
118 | #ifndef CONFIG_PPC_BOOK3E | 120 | #ifndef CONFIG_PPC_BOOK3E |
119 | mfmsr r24 | 121 | mfmsr r24 |
120 | ori r24,r24,MSR_RI | 122 | ori r24,r24,MSR_RI |
@@ -205,6 +207,7 @@ _GLOBAL(generic_secondary_thread_init) | |||
205 | * as SCOM before entry). | 207 | * as SCOM before entry). |
206 | */ | 208 | */ |
207 | _GLOBAL(generic_secondary_smp_init) | 209 | _GLOBAL(generic_secondary_smp_init) |
210 | FIXUP_ENDIAN | ||
208 | mr r24,r3 | 211 | mr r24,r3 |
209 | mr r25,r4 | 212 | mr r25,r4 |
210 | 213 | ||
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S index 1b92a97b1b04..7ee876d2adb5 100644 --- a/arch/powerpc/kernel/head_8xx.S +++ b/arch/powerpc/kernel/head_8xx.S | |||
@@ -858,6 +858,9 @@ initial_mmu: | |||
858 | addis r11, r11, 0x0080 /* Add 8M */ | 858 | addis r11, r11, 0x0080 /* Add 8M */ |
859 | mtspr SPRN_MD_RPN, r11 | 859 | mtspr SPRN_MD_RPN, r11 |
860 | 860 | ||
861 | addi r10, r10, 0x0100 | ||
862 | mtspr SPRN_MD_CTR, r10 | ||
863 | |||
861 | addis r8, r8, 0x0080 /* Add 8M */ | 864 | addis r8, r8, 0x0080 /* Add 8M */ |
862 | mtspr SPRN_MD_EPN, r8 | 865 | mtspr SPRN_MD_EPN, r8 |
863 | mtspr SPRN_MD_TWC, r9 | 866 | mtspr SPRN_MD_TWC, r9 |
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S index 289afaffbbb5..f45726a1d963 100644 --- a/arch/powerpc/kernel/head_fsl_booke.S +++ b/arch/powerpc/kernel/head_fsl_booke.S | |||
@@ -555,27 +555,27 @@ END_FTR_SECTION_IFSET(CPU_FTR_EMB_HV) | |||
555 | #ifdef CONFIG_SPE | 555 | #ifdef CONFIG_SPE |
556 | /* SPE Unavailable */ | 556 | /* SPE Unavailable */ |
557 | START_EXCEPTION(SPEUnavailable) | 557 | START_EXCEPTION(SPEUnavailable) |
558 | NORMAL_EXCEPTION_PROLOG(SPE_UNAVAIL) | 558 | NORMAL_EXCEPTION_PROLOG(SPE_ALTIVEC_UNAVAIL) |
559 | beq 1f | 559 | beq 1f |
560 | bl load_up_spe | 560 | bl load_up_spe |
561 | b fast_exception_return | 561 | b fast_exception_return |
562 | 1: addi r3,r1,STACK_FRAME_OVERHEAD | 562 | 1: addi r3,r1,STACK_FRAME_OVERHEAD |
563 | EXC_XFER_EE_LITE(0x2010, KernelSPE) | 563 | EXC_XFER_EE_LITE(0x2010, KernelSPE) |
564 | #else | 564 | #else |
565 | EXCEPTION(0x2020, SPE_UNAVAIL, SPEUnavailable, \ | 565 | EXCEPTION(0x2020, SPE_ALTIVEC_UNAVAIL, SPEUnavailable, \ |
566 | unknown_exception, EXC_XFER_EE) | 566 | unknown_exception, EXC_XFER_EE) |
567 | #endif /* CONFIG_SPE */ | 567 | #endif /* CONFIG_SPE */ |
568 | 568 | ||
569 | /* SPE Floating Point Data */ | 569 | /* SPE Floating Point Data */ |
570 | #ifdef CONFIG_SPE | 570 | #ifdef CONFIG_SPE |
571 | EXCEPTION(0x2030, SPE_FP_DATA, SPEFloatingPointData, \ | 571 | EXCEPTION(0x2030, SPE_FP_DATA_ALTIVEC_ASSIST, SPEFloatingPointData, |
572 | SPEFloatingPointException, EXC_XFER_EE); | 572 | SPEFloatingPointException, EXC_XFER_EE) |
573 | 573 | ||
574 | /* SPE Floating Point Round */ | 574 | /* SPE Floating Point Round */ |
575 | EXCEPTION(0x2050, SPE_FP_ROUND, SPEFloatingPointRound, \ | 575 | EXCEPTION(0x2050, SPE_FP_ROUND, SPEFloatingPointRound, \ |
576 | SPEFloatingPointRoundException, EXC_XFER_EE) | 576 | SPEFloatingPointRoundException, EXC_XFER_EE) |
577 | #else | 577 | #else |
578 | EXCEPTION(0x2040, SPE_FP_DATA, SPEFloatingPointData, \ | 578 | EXCEPTION(0x2040, SPE_FP_DATA_ALTIVEC_ASSIST, SPEFloatingPointData, |
579 | unknown_exception, EXC_XFER_EE) | 579 | unknown_exception, EXC_XFER_EE) |
580 | EXCEPTION(0x2050, SPE_FP_ROUND, SPEFloatingPointRound, \ | 580 | EXCEPTION(0x2050, SPE_FP_ROUND, SPEFloatingPointRound, \ |
581 | unknown_exception, EXC_XFER_EE) | 581 | unknown_exception, EXC_XFER_EE) |
diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c index 16a7c2326d48..1114d13ac19f 100644 --- a/arch/powerpc/kernel/ibmebus.c +++ b/arch/powerpc/kernel/ibmebus.c | |||
@@ -292,6 +292,7 @@ out: | |||
292 | return rc; | 292 | return rc; |
293 | return count; | 293 | return count; |
294 | } | 294 | } |
295 | static BUS_ATTR(probe, S_IWUSR, NULL, ibmebus_store_probe); | ||
295 | 296 | ||
296 | static ssize_t ibmebus_store_remove(struct bus_type *bus, | 297 | static ssize_t ibmebus_store_remove(struct bus_type *bus, |
297 | const char *buf, size_t count) | 298 | const char *buf, size_t count) |
@@ -317,13 +318,14 @@ static ssize_t ibmebus_store_remove(struct bus_type *bus, | |||
317 | return -ENODEV; | 318 | return -ENODEV; |
318 | } | 319 | } |
319 | } | 320 | } |
321 | static BUS_ATTR(remove, S_IWUSR, NULL, ibmebus_store_remove); | ||
320 | 322 | ||
321 | 323 | static struct attribute *ibmbus_bus_attrs[] = { | |
322 | static struct bus_attribute ibmebus_bus_attrs[] = { | 324 | &bus_attr_probe.attr, |
323 | __ATTR(probe, S_IWUSR, NULL, ibmebus_store_probe), | 325 | &bus_attr_remove.attr, |
324 | __ATTR(remove, S_IWUSR, NULL, ibmebus_store_remove), | 326 | NULL, |
325 | __ATTR_NULL | ||
326 | }; | 327 | }; |
328 | ATTRIBUTE_GROUPS(ibmbus_bus); | ||
327 | 329 | ||
328 | static int ibmebus_bus_bus_match(struct device *dev, struct device_driver *drv) | 330 | static int ibmebus_bus_bus_match(struct device *dev, struct device_driver *drv) |
329 | { | 331 | { |
@@ -713,7 +715,7 @@ static struct dev_pm_ops ibmebus_bus_dev_pm_ops = { | |||
713 | struct bus_type ibmebus_bus_type = { | 715 | struct bus_type ibmebus_bus_type = { |
714 | .name = "ibmebus", | 716 | .name = "ibmebus", |
715 | .uevent = of_device_uevent_modalias, | 717 | .uevent = of_device_uevent_modalias, |
716 | .bus_attrs = ibmebus_bus_attrs, | 718 | .bus_groups = ibmbus_bus_groups, |
717 | .match = ibmebus_bus_bus_match, | 719 | .match = ibmebus_bus_bus_match, |
718 | .probe = ibmebus_bus_device_probe, | 720 | .probe = ibmebus_bus_device_probe, |
719 | .remove = ibmebus_bus_device_remove, | 721 | .remove = ibmebus_bus_device_remove, |
diff --git a/arch/powerpc/kernel/idle_power7.S b/arch/powerpc/kernel/idle_power7.S index e11863f4e595..847e40e62fce 100644 --- a/arch/powerpc/kernel/idle_power7.S +++ b/arch/powerpc/kernel/idle_power7.S | |||
@@ -84,7 +84,7 @@ _GLOBAL(power7_nap) | |||
84 | std r9,_MSR(r1) | 84 | std r9,_MSR(r1) |
85 | std r1,PACAR1(r13) | 85 | std r1,PACAR1(r13) |
86 | 86 | ||
87 | #ifdef CONFIG_KVM_BOOK3S_64_HV | 87 | #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE |
88 | /* Tell KVM we're napping */ | 88 | /* Tell KVM we're napping */ |
89 | li r4,KVM_HWTHREAD_IN_NAP | 89 | li r4,KVM_HWTHREAD_IN_NAP |
90 | stb r4,HSTATE_HWTHREAD_STATE(r13) | 90 | stb r4,HSTATE_HWTHREAD_STATE(r13) |
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index 0adab06ce5c0..572bb5b95f35 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c | |||
@@ -661,7 +661,7 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid) | |||
661 | /* number of bytes needed for the bitmap */ | 661 | /* number of bytes needed for the bitmap */ |
662 | sz = BITS_TO_LONGS(tbl->it_size) * sizeof(unsigned long); | 662 | sz = BITS_TO_LONGS(tbl->it_size) * sizeof(unsigned long); |
663 | 663 | ||
664 | page = alloc_pages_node(nid, GFP_ATOMIC, get_order(sz)); | 664 | page = alloc_pages_node(nid, GFP_KERNEL, get_order(sz)); |
665 | if (!page) | 665 | if (!page) |
666 | panic("iommu_init_table: Can't allocate %ld bytes\n", sz); | 666 | panic("iommu_init_table: Can't allocate %ld bytes\n", sz); |
667 | tbl->it_map = page_address(page); | 667 | tbl->it_map = page_address(page); |
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index c69440cef7af..ba0165615215 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c | |||
@@ -441,50 +441,6 @@ void migrate_irqs(void) | |||
441 | } | 441 | } |
442 | #endif | 442 | #endif |
443 | 443 | ||
444 | static inline void handle_one_irq(unsigned int irq) | ||
445 | { | ||
446 | struct thread_info *curtp, *irqtp; | ||
447 | unsigned long saved_sp_limit; | ||
448 | struct irq_desc *desc; | ||
449 | |||
450 | desc = irq_to_desc(irq); | ||
451 | if (!desc) | ||
452 | return; | ||
453 | |||
454 | /* Switch to the irq stack to handle this */ | ||
455 | curtp = current_thread_info(); | ||
456 | irqtp = hardirq_ctx[smp_processor_id()]; | ||
457 | |||
458 | if (curtp == irqtp) { | ||
459 | /* We're already on the irq stack, just handle it */ | ||
460 | desc->handle_irq(irq, desc); | ||
461 | return; | ||
462 | } | ||
463 | |||
464 | saved_sp_limit = current->thread.ksp_limit; | ||
465 | |||
466 | irqtp->task = curtp->task; | ||
467 | irqtp->flags = 0; | ||
468 | |||
469 | /* Copy the softirq bits in preempt_count so that the | ||
470 | * softirq checks work in the hardirq context. */ | ||
471 | irqtp->preempt_count = (irqtp->preempt_count & ~SOFTIRQ_MASK) | | ||
472 | (curtp->preempt_count & SOFTIRQ_MASK); | ||
473 | |||
474 | current->thread.ksp_limit = (unsigned long)irqtp + | ||
475 | _ALIGN_UP(sizeof(struct thread_info), 16); | ||
476 | |||
477 | call_handle_irq(irq, desc, irqtp, desc->handle_irq); | ||
478 | current->thread.ksp_limit = saved_sp_limit; | ||
479 | irqtp->task = NULL; | ||
480 | |||
481 | /* Set any flag that may have been set on the | ||
482 | * alternate stack | ||
483 | */ | ||
484 | if (irqtp->flags) | ||
485 | set_bits(irqtp->flags, &curtp->flags); | ||
486 | } | ||
487 | |||
488 | static inline void check_stack_overflow(void) | 444 | static inline void check_stack_overflow(void) |
489 | { | 445 | { |
490 | #ifdef CONFIG_DEBUG_STACKOVERFLOW | 446 | #ifdef CONFIG_DEBUG_STACKOVERFLOW |
@@ -501,9 +457,9 @@ static inline void check_stack_overflow(void) | |||
501 | #endif | 457 | #endif |
502 | } | 458 | } |
503 | 459 | ||
504 | void do_IRQ(struct pt_regs *regs) | 460 | void __do_irq(struct pt_regs *regs) |
505 | { | 461 | { |
506 | struct pt_regs *old_regs = set_irq_regs(regs); | 462 | struct irq_desc *desc; |
507 | unsigned int irq; | 463 | unsigned int irq; |
508 | 464 | ||
509 | irq_enter(); | 465 | irq_enter(); |
@@ -519,18 +475,57 @@ void do_IRQ(struct pt_regs *regs) | |||
519 | */ | 475 | */ |
520 | irq = ppc_md.get_irq(); | 476 | irq = ppc_md.get_irq(); |
521 | 477 | ||
522 | /* We can hard enable interrupts now */ | 478 | /* We can hard enable interrupts now to allow perf interrupts */ |
523 | may_hard_irq_enable(); | 479 | may_hard_irq_enable(); |
524 | 480 | ||
525 | /* And finally process it */ | 481 | /* And finally process it */ |
526 | if (irq != NO_IRQ) | 482 | if (unlikely(irq == NO_IRQ)) |
527 | handle_one_irq(irq); | ||
528 | else | ||
529 | __get_cpu_var(irq_stat).spurious_irqs++; | 483 | __get_cpu_var(irq_stat).spurious_irqs++; |
484 | else { | ||
485 | desc = irq_to_desc(irq); | ||
486 | if (likely(desc)) | ||
487 | desc->handle_irq(irq, desc); | ||
488 | } | ||
530 | 489 | ||
531 | trace_irq_exit(regs); | 490 | trace_irq_exit(regs); |
532 | 491 | ||
533 | irq_exit(); | 492 | irq_exit(); |
493 | } | ||
494 | |||
495 | void do_IRQ(struct pt_regs *regs) | ||
496 | { | ||
497 | struct pt_regs *old_regs = set_irq_regs(regs); | ||
498 | struct thread_info *curtp, *irqtp, *sirqtp; | ||
499 | |||
500 | /* Switch to the irq stack to handle this */ | ||
501 | curtp = current_thread_info(); | ||
502 | irqtp = hardirq_ctx[raw_smp_processor_id()]; | ||
503 | sirqtp = softirq_ctx[raw_smp_processor_id()]; | ||
504 | |||
505 | /* Already there ? */ | ||
506 | if (unlikely(curtp == irqtp || curtp == sirqtp)) { | ||
507 | __do_irq(regs); | ||
508 | set_irq_regs(old_regs); | ||
509 | return; | ||
510 | } | ||
511 | |||
512 | /* Prepare the thread_info in the irq stack */ | ||
513 | irqtp->task = curtp->task; | ||
514 | irqtp->flags = 0; | ||
515 | |||
516 | /* Copy the preempt_count so that the [soft]irq checks work. */ | ||
517 | irqtp->preempt_count = curtp->preempt_count; | ||
518 | |||
519 | /* Switch stack and call */ | ||
520 | call_do_irq(regs, irqtp); | ||
521 | |||
522 | /* Restore stack limit */ | ||
523 | irqtp->task = NULL; | ||
524 | |||
525 | /* Copy back updates to the thread_info */ | ||
526 | if (irqtp->flags) | ||
527 | set_bits(irqtp->flags, &curtp->flags); | ||
528 | |||
534 | set_irq_regs(old_regs); | 529 | set_irq_regs(old_regs); |
535 | } | 530 | } |
536 | 531 | ||
@@ -592,28 +587,22 @@ void irq_ctx_init(void) | |||
592 | memset((void *)softirq_ctx[i], 0, THREAD_SIZE); | 587 | memset((void *)softirq_ctx[i], 0, THREAD_SIZE); |
593 | tp = softirq_ctx[i]; | 588 | tp = softirq_ctx[i]; |
594 | tp->cpu = i; | 589 | tp->cpu = i; |
595 | tp->preempt_count = 0; | ||
596 | 590 | ||
597 | memset((void *)hardirq_ctx[i], 0, THREAD_SIZE); | 591 | memset((void *)hardirq_ctx[i], 0, THREAD_SIZE); |
598 | tp = hardirq_ctx[i]; | 592 | tp = hardirq_ctx[i]; |
599 | tp->cpu = i; | 593 | tp->cpu = i; |
600 | tp->preempt_count = HARDIRQ_OFFSET; | ||
601 | } | 594 | } |
602 | } | 595 | } |
603 | 596 | ||
604 | static inline void do_softirq_onstack(void) | 597 | void do_softirq_own_stack(void) |
605 | { | 598 | { |
606 | struct thread_info *curtp, *irqtp; | 599 | struct thread_info *curtp, *irqtp; |
607 | unsigned long saved_sp_limit = current->thread.ksp_limit; | ||
608 | 600 | ||
609 | curtp = current_thread_info(); | 601 | curtp = current_thread_info(); |
610 | irqtp = softirq_ctx[smp_processor_id()]; | 602 | irqtp = softirq_ctx[smp_processor_id()]; |
611 | irqtp->task = curtp->task; | 603 | irqtp->task = curtp->task; |
612 | irqtp->flags = 0; | 604 | irqtp->flags = 0; |
613 | current->thread.ksp_limit = (unsigned long)irqtp + | ||
614 | _ALIGN_UP(sizeof(struct thread_info), 16); | ||
615 | call_do_softirq(irqtp); | 605 | call_do_softirq(irqtp); |
616 | current->thread.ksp_limit = saved_sp_limit; | ||
617 | irqtp->task = NULL; | 606 | irqtp->task = NULL; |
618 | 607 | ||
619 | /* Set any flag that may have been set on the | 608 | /* Set any flag that may have been set on the |
@@ -623,21 +612,6 @@ static inline void do_softirq_onstack(void) | |||
623 | set_bits(irqtp->flags, &curtp->flags); | 612 | set_bits(irqtp->flags, &curtp->flags); |
624 | } | 613 | } |
625 | 614 | ||
626 | void do_softirq(void) | ||
627 | { | ||
628 | unsigned long flags; | ||
629 | |||
630 | if (in_interrupt()) | ||
631 | return; | ||
632 | |||
633 | local_irq_save(flags); | ||
634 | |||
635 | if (local_softirq_pending()) | ||
636 | do_softirq_onstack(); | ||
637 | |||
638 | local_irq_restore(flags); | ||
639 | } | ||
640 | |||
641 | irq_hw_number_t virq_to_hw(unsigned int virq) | 615 | irq_hw_number_t virq_to_hw(unsigned int virq) |
642 | { | 616 | { |
643 | struct irq_data *irq_data = irq_get_irq_data(virq); | 617 | struct irq_data *irq_data = irq_get_irq_data(virq); |
diff --git a/arch/powerpc/kernel/kgdb.c b/arch/powerpc/kernel/kgdb.c index c1eef241017a..83e89d310734 100644 --- a/arch/powerpc/kernel/kgdb.c +++ b/arch/powerpc/kernel/kgdb.c | |||
@@ -151,15 +151,16 @@ static int kgdb_handle_breakpoint(struct pt_regs *regs) | |||
151 | return 1; | 151 | return 1; |
152 | } | 152 | } |
153 | 153 | ||
154 | static DEFINE_PER_CPU(struct thread_info, kgdb_thread_info); | ||
154 | static int kgdb_singlestep(struct pt_regs *regs) | 155 | static int kgdb_singlestep(struct pt_regs *regs) |
155 | { | 156 | { |
156 | struct thread_info *thread_info, *exception_thread_info; | 157 | struct thread_info *thread_info, *exception_thread_info; |
157 | struct thread_info *backup_current_thread_info; | 158 | struct thread_info *backup_current_thread_info = |
159 | &__get_cpu_var(kgdb_thread_info); | ||
158 | 160 | ||
159 | if (user_mode(regs)) | 161 | if (user_mode(regs)) |
160 | return 0; | 162 | return 0; |
161 | 163 | ||
162 | backup_current_thread_info = kmalloc(sizeof(struct thread_info), GFP_KERNEL); | ||
163 | /* | 164 | /* |
164 | * On Book E and perhaps other processors, singlestep is handled on | 165 | * On Book E and perhaps other processors, singlestep is handled on |
165 | * the critical exception stack. This causes current_thread_info() | 166 | * the critical exception stack. This causes current_thread_info() |
@@ -185,7 +186,6 @@ static int kgdb_singlestep(struct pt_regs *regs) | |||
185 | /* Restore current_thread_info lastly. */ | 186 | /* Restore current_thread_info lastly. */ |
186 | memcpy(exception_thread_info, backup_current_thread_info, sizeof *thread_info); | 187 | memcpy(exception_thread_info, backup_current_thread_info, sizeof *thread_info); |
187 | 188 | ||
188 | kfree(backup_current_thread_info); | ||
189 | return 1; | 189 | return 1; |
190 | } | 190 | } |
191 | 191 | ||
diff --git a/arch/powerpc/kernel/legacy_serial.c b/arch/powerpc/kernel/legacy_serial.c index 22e88dd2f34a..40bd7bd4e19a 100644 --- a/arch/powerpc/kernel/legacy_serial.c +++ b/arch/powerpc/kernel/legacy_serial.c | |||
@@ -35,7 +35,7 @@ static struct legacy_serial_info { | |||
35 | phys_addr_t taddr; | 35 | phys_addr_t taddr; |
36 | } legacy_serial_infos[MAX_LEGACY_SERIAL_PORTS]; | 36 | } legacy_serial_infos[MAX_LEGACY_SERIAL_PORTS]; |
37 | 37 | ||
38 | static struct __initdata of_device_id legacy_serial_parents[] = { | 38 | static struct of_device_id legacy_serial_parents[] __initdata = { |
39 | {.type = "soc",}, | 39 | {.type = "soc",}, |
40 | {.type = "tsi-bridge",}, | 40 | {.type = "tsi-bridge",}, |
41 | {.type = "opb", }, | 41 | {.type = "opb", }, |
diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c index 611acdf30096..be4e6d648f60 100644 --- a/arch/powerpc/kernel/machine_kexec_64.c +++ b/arch/powerpc/kernel/machine_kexec_64.c | |||
@@ -312,7 +312,7 @@ static union thread_union kexec_stack __init_task_data = | |||
312 | */ | 312 | */ |
313 | struct paca_struct kexec_paca; | 313 | struct paca_struct kexec_paca; |
314 | 314 | ||
315 | /* Our assembly helper, in kexec_stub.S */ | 315 | /* Our assembly helper, in misc_64.S */ |
316 | extern void kexec_sequence(void *newstack, unsigned long start, | 316 | extern void kexec_sequence(void *newstack, unsigned long start, |
317 | void *image, void *control, | 317 | void *image, void *control, |
318 | void (*clear_all)(void)) __noreturn; | 318 | void (*clear_all)(void)) __noreturn; |
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index 777d999f563b..e47d268727a4 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S | |||
@@ -36,26 +36,41 @@ | |||
36 | 36 | ||
37 | .text | 37 | .text |
38 | 38 | ||
39 | /* | ||
40 | * We store the saved ksp_limit in the unused part | ||
41 | * of the STACK_FRAME_OVERHEAD | ||
42 | */ | ||
39 | _GLOBAL(call_do_softirq) | 43 | _GLOBAL(call_do_softirq) |
40 | mflr r0 | 44 | mflr r0 |
41 | stw r0,4(r1) | 45 | stw r0,4(r1) |
46 | lwz r10,THREAD+KSP_LIMIT(r2) | ||
47 | addi r11,r3,THREAD_INFO_GAP | ||
42 | stwu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r3) | 48 | stwu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r3) |
43 | mr r1,r3 | 49 | mr r1,r3 |
50 | stw r10,8(r1) | ||
51 | stw r11,THREAD+KSP_LIMIT(r2) | ||
44 | bl __do_softirq | 52 | bl __do_softirq |
53 | lwz r10,8(r1) | ||
45 | lwz r1,0(r1) | 54 | lwz r1,0(r1) |
46 | lwz r0,4(r1) | 55 | lwz r0,4(r1) |
56 | stw r10,THREAD+KSP_LIMIT(r2) | ||
47 | mtlr r0 | 57 | mtlr r0 |
48 | blr | 58 | blr |
49 | 59 | ||
50 | _GLOBAL(call_handle_irq) | 60 | _GLOBAL(call_do_irq) |
51 | mflr r0 | 61 | mflr r0 |
52 | stw r0,4(r1) | 62 | stw r0,4(r1) |
53 | mtctr r6 | 63 | lwz r10,THREAD+KSP_LIMIT(r2) |
54 | stwu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r5) | 64 | addi r11,r3,THREAD_INFO_GAP |
55 | mr r1,r5 | 65 | stwu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r4) |
56 | bctrl | 66 | mr r1,r4 |
67 | stw r10,8(r1) | ||
68 | stw r11,THREAD+KSP_LIMIT(r2) | ||
69 | bl __do_irq | ||
70 | lwz r10,8(r1) | ||
57 | lwz r1,0(r1) | 71 | lwz r1,0(r1) |
58 | lwz r0,4(r1) | 72 | lwz r0,4(r1) |
73 | stw r10,THREAD+KSP_LIMIT(r2) | ||
59 | mtlr r0 | 74 | mtlr r0 |
60 | blr | 75 | blr |
61 | 76 | ||
@@ -644,6 +659,20 @@ _GLOBAL(__lshrdi3) | |||
644 | blr | 659 | blr |
645 | 660 | ||
646 | /* | 661 | /* |
662 | * 64-bit comparison: __cmpdi2(s64 a, s64 b) | ||
663 | * Returns 0 if a < b, 1 if a == b, 2 if a > b. | ||
664 | */ | ||
665 | _GLOBAL(__cmpdi2) | ||
666 | cmpw r3,r5 | ||
667 | li r3,1 | ||
668 | bne 1f | ||
669 | cmplw r4,r6 | ||
670 | beqlr | ||
671 | 1: li r3,0 | ||
672 | bltlr | ||
673 | li r3,2 | ||
674 | blr | ||
675 | /* | ||
647 | * 64-bit comparison: __ucmpdi2(u64 a, u64 b) | 676 | * 64-bit comparison: __ucmpdi2(u64 a, u64 b) |
648 | * Returns 0 if a < b, 1 if a == b, 2 if a > b. | 677 | * Returns 0 if a < b, 1 if a == b, 2 if a > b. |
649 | */ | 678 | */ |
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S index 971d7e78aff2..e59caf874d05 100644 --- a/arch/powerpc/kernel/misc_64.S +++ b/arch/powerpc/kernel/misc_64.S | |||
@@ -40,14 +40,12 @@ _GLOBAL(call_do_softirq) | |||
40 | mtlr r0 | 40 | mtlr r0 |
41 | blr | 41 | blr |
42 | 42 | ||
43 | _GLOBAL(call_handle_irq) | 43 | _GLOBAL(call_do_irq) |
44 | ld r8,0(r6) | ||
45 | mflr r0 | 44 | mflr r0 |
46 | std r0,16(r1) | 45 | std r0,16(r1) |
47 | mtctr r8 | 46 | stdu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r4) |
48 | stdu r1,THREAD_SIZE-STACK_FRAME_OVERHEAD(r5) | 47 | mr r1,r4 |
49 | mr r1,r5 | 48 | bl .__do_irq |
50 | bctrl | ||
51 | ld r1,0(r1) | 49 | ld r1,0(r1) |
52 | ld r0,16(r1) | 50 | ld r0,16(r1) |
53 | mtlr r0 | 51 | mtlr r0 |
diff --git a/arch/powerpc/kernel/module.c b/arch/powerpc/kernel/module.c index 2d275707f419..9547381b631a 100644 --- a/arch/powerpc/kernel/module.c +++ b/arch/powerpc/kernel/module.c | |||
@@ -25,8 +25,7 @@ | |||
25 | #include <asm/uaccess.h> | 25 | #include <asm/uaccess.h> |
26 | #include <asm/firmware.h> | 26 | #include <asm/firmware.h> |
27 | #include <linux/sort.h> | 27 | #include <linux/sort.h> |
28 | 28 | #include <asm/setup.h> | |
29 | #include "setup.h" | ||
30 | 29 | ||
31 | LIST_HEAD(module_bug_list); | 30 | LIST_HEAD(module_bug_list); |
32 | 31 | ||
diff --git a/arch/powerpc/kernel/module_32.c b/arch/powerpc/kernel/module_32.c index 2e3200ca485f..6cff040bf456 100644 --- a/arch/powerpc/kernel/module_32.c +++ b/arch/powerpc/kernel/module_32.c | |||
@@ -26,8 +26,7 @@ | |||
26 | #include <linux/cache.h> | 26 | #include <linux/cache.h> |
27 | #include <linux/bug.h> | 27 | #include <linux/bug.h> |
28 | #include <linux/sort.h> | 28 | #include <linux/sort.h> |
29 | 29 | #include <asm/setup.h> | |
30 | #include "setup.h" | ||
31 | 30 | ||
32 | #if 0 | 31 | #if 0 |
33 | #define DEBUGP printk | 32 | #define DEBUGP printk |
diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c index 6ee59a0eb268..12664c130d73 100644 --- a/arch/powerpc/kernel/module_64.c +++ b/arch/powerpc/kernel/module_64.c | |||
@@ -26,8 +26,7 @@ | |||
26 | #include <asm/firmware.h> | 26 | #include <asm/firmware.h> |
27 | #include <asm/code-patching.h> | 27 | #include <asm/code-patching.h> |
28 | #include <linux/sort.h> | 28 | #include <linux/sort.h> |
29 | 29 | #include <asm/setup.h> | |
30 | #include "setup.h" | ||
31 | 30 | ||
32 | /* FIXME: We don't do .init separately. To do this, we'd need to have | 31 | /* FIXME: We don't do .init separately. To do this, we'd need to have |
33 | a separate r2 value in the init and core section, and stub between | 32 | a separate r2 value in the init and core section, and stub between |
@@ -62,6 +61,16 @@ struct ppc64_stub_entry | |||
62 | r2) into the stub. */ | 61 | r2) into the stub. */ |
63 | static struct ppc64_stub_entry ppc64_stub = | 62 | static struct ppc64_stub_entry ppc64_stub = |
64 | { .jump = { | 63 | { .jump = { |
64 | #ifdef __LITTLE_ENDIAN__ | ||
65 | 0x00, 0x00, 0x82, 0x3d, /* addis r12,r2, <high> */ | ||
66 | 0x00, 0x00, 0x8c, 0x39, /* addi r12,r12, <low> */ | ||
67 | /* Save current r2 value in magic place on the stack. */ | ||
68 | 0x28, 0x00, 0x41, 0xf8, /* std r2,40(r1) */ | ||
69 | 0x20, 0x00, 0x6c, 0xe9, /* ld r11,32(r12) */ | ||
70 | 0x28, 0x00, 0x4c, 0xe8, /* ld r2,40(r12) */ | ||
71 | 0xa6, 0x03, 0x69, 0x7d, /* mtctr r11 */ | ||
72 | 0x20, 0x04, 0x80, 0x4e /* bctr */ | ||
73 | #else | ||
65 | 0x3d, 0x82, 0x00, 0x00, /* addis r12,r2, <high> */ | 74 | 0x3d, 0x82, 0x00, 0x00, /* addis r12,r2, <high> */ |
66 | 0x39, 0x8c, 0x00, 0x00, /* addi r12,r12, <low> */ | 75 | 0x39, 0x8c, 0x00, 0x00, /* addi r12,r12, <low> */ |
67 | /* Save current r2 value in magic place on the stack. */ | 76 | /* Save current r2 value in magic place on the stack. */ |
@@ -70,6 +79,7 @@ static struct ppc64_stub_entry ppc64_stub = | |||
70 | 0xe8, 0x4c, 0x00, 0x28, /* ld r2,40(r12) */ | 79 | 0xe8, 0x4c, 0x00, 0x28, /* ld r2,40(r12) */ |
71 | 0x7d, 0x69, 0x03, 0xa6, /* mtctr r11 */ | 80 | 0x7d, 0x69, 0x03, 0xa6, /* mtctr r11 */ |
72 | 0x4e, 0x80, 0x04, 0x20 /* bctr */ | 81 | 0x4e, 0x80, 0x04, 0x20 /* bctr */ |
82 | #endif | ||
73 | } }; | 83 | } }; |
74 | 84 | ||
75 | /* Count how many different 24-bit relocations (different symbol, | 85 | /* Count how many different 24-bit relocations (different symbol, |
@@ -269,8 +279,13 @@ static inline int create_stub(Elf64_Shdr *sechdrs, | |||
269 | 279 | ||
270 | *entry = ppc64_stub; | 280 | *entry = ppc64_stub; |
271 | 281 | ||
282 | #ifdef __LITTLE_ENDIAN__ | ||
283 | loc1 = (Elf64_Half *)&entry->jump[0]; | ||
284 | loc2 = (Elf64_Half *)&entry->jump[4]; | ||
285 | #else | ||
272 | loc1 = (Elf64_Half *)&entry->jump[2]; | 286 | loc1 = (Elf64_Half *)&entry->jump[2]; |
273 | loc2 = (Elf64_Half *)&entry->jump[6]; | 287 | loc2 = (Elf64_Half *)&entry->jump[6]; |
288 | #endif | ||
274 | 289 | ||
275 | /* Stub uses address relative to r2. */ | 290 | /* Stub uses address relative to r2. */ |
276 | reladdr = (unsigned long)entry - my_r2(sechdrs, me); | 291 | reladdr = (unsigned long)entry - my_r2(sechdrs, me); |
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c index 8213ee1eb05a..fd82c289ab1c 100644 --- a/arch/powerpc/kernel/nvram_64.c +++ b/arch/powerpc/kernel/nvram_64.c | |||
@@ -223,9 +223,13 @@ static int __init nvram_write_header(struct nvram_partition * part) | |||
223 | { | 223 | { |
224 | loff_t tmp_index; | 224 | loff_t tmp_index; |
225 | int rc; | 225 | int rc; |
226 | 226 | struct nvram_header phead; | |
227 | |||
228 | memcpy(&phead, &part->header, NVRAM_HEADER_LEN); | ||
229 | phead.length = cpu_to_be16(phead.length); | ||
230 | |||
227 | tmp_index = part->index; | 231 | tmp_index = part->index; |
228 | rc = ppc_md.nvram_write((char *)&part->header, NVRAM_HEADER_LEN, &tmp_index); | 232 | rc = ppc_md.nvram_write((char *)&phead, NVRAM_HEADER_LEN, &tmp_index); |
229 | 233 | ||
230 | return rc; | 234 | return rc; |
231 | } | 235 | } |
@@ -505,6 +509,8 @@ int __init nvram_scan_partitions(void) | |||
505 | 509 | ||
506 | memcpy(&phead, header, NVRAM_HEADER_LEN); | 510 | memcpy(&phead, header, NVRAM_HEADER_LEN); |
507 | 511 | ||
512 | phead.length = be16_to_cpu(phead.length); | ||
513 | |||
508 | err = 0; | 514 | err = 0; |
509 | c_sum = nvram_checksum(&phead); | 515 | c_sum = nvram_checksum(&phead); |
510 | if (c_sum != phead.checksum) { | 516 | if (c_sum != phead.checksum) { |
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c index 3fc16e3beb9f..0620eaaaad45 100644 --- a/arch/powerpc/kernel/paca.c +++ b/arch/powerpc/kernel/paca.c | |||
@@ -46,7 +46,7 @@ struct lppaca lppaca[] = { | |||
46 | static struct lppaca *extra_lppacas; | 46 | static struct lppaca *extra_lppacas; |
47 | static long __initdata lppaca_size; | 47 | static long __initdata lppaca_size; |
48 | 48 | ||
49 | static void allocate_lppacas(int nr_cpus, unsigned long limit) | 49 | static void __init allocate_lppacas(int nr_cpus, unsigned long limit) |
50 | { | 50 | { |
51 | if (nr_cpus <= NR_LPPACAS) | 51 | if (nr_cpus <= NR_LPPACAS) |
52 | return; | 52 | return; |
@@ -57,7 +57,7 @@ static void allocate_lppacas(int nr_cpus, unsigned long limit) | |||
57 | PAGE_SIZE, limit)); | 57 | PAGE_SIZE, limit)); |
58 | } | 58 | } |
59 | 59 | ||
60 | static struct lppaca *new_lppaca(int cpu) | 60 | static struct lppaca * __init new_lppaca(int cpu) |
61 | { | 61 | { |
62 | struct lppaca *lp; | 62 | struct lppaca *lp; |
63 | 63 | ||
@@ -70,7 +70,7 @@ static struct lppaca *new_lppaca(int cpu) | |||
70 | return lp; | 70 | return lp; |
71 | } | 71 | } |
72 | 72 | ||
73 | static void free_lppacas(void) | 73 | static void __init free_lppacas(void) |
74 | { | 74 | { |
75 | long new_size = 0, nr; | 75 | long new_size = 0, nr; |
76 | 76 | ||
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 905a24bb7acc..a1e3e40ca3fd 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c | |||
@@ -228,7 +228,7 @@ int pcibios_add_platform_entries(struct pci_dev *pdev) | |||
228 | */ | 228 | */ |
229 | static int pci_read_irq_line(struct pci_dev *pci_dev) | 229 | static int pci_read_irq_line(struct pci_dev *pci_dev) |
230 | { | 230 | { |
231 | struct of_irq oirq; | 231 | struct of_phandle_args oirq; |
232 | unsigned int virq; | 232 | unsigned int virq; |
233 | 233 | ||
234 | pr_debug("PCI: Try to map irq for %s...\n", pci_name(pci_dev)); | 234 | pr_debug("PCI: Try to map irq for %s...\n", pci_name(pci_dev)); |
@@ -237,7 +237,7 @@ static int pci_read_irq_line(struct pci_dev *pci_dev) | |||
237 | memset(&oirq, 0xff, sizeof(oirq)); | 237 | memset(&oirq, 0xff, sizeof(oirq)); |
238 | #endif | 238 | #endif |
239 | /* Try to get a mapping from the device-tree */ | 239 | /* Try to get a mapping from the device-tree */ |
240 | if (of_irq_map_pci(pci_dev, &oirq)) { | 240 | if (of_irq_parse_pci(pci_dev, &oirq)) { |
241 | u8 line, pin; | 241 | u8 line, pin; |
242 | 242 | ||
243 | /* If that fails, lets fallback to what is in the config | 243 | /* If that fails, lets fallback to what is in the config |
@@ -263,11 +263,10 @@ static int pci_read_irq_line(struct pci_dev *pci_dev) | |||
263 | irq_set_irq_type(virq, IRQ_TYPE_LEVEL_LOW); | 263 | irq_set_irq_type(virq, IRQ_TYPE_LEVEL_LOW); |
264 | } else { | 264 | } else { |
265 | pr_debug(" Got one, spec %d cells (0x%08x 0x%08x...) on %s\n", | 265 | pr_debug(" Got one, spec %d cells (0x%08x 0x%08x...) on %s\n", |
266 | oirq.size, oirq.specifier[0], oirq.specifier[1], | 266 | oirq.args_count, oirq.args[0], oirq.args[1], |
267 | of_node_full_name(oirq.controller)); | 267 | of_node_full_name(oirq.np)); |
268 | 268 | ||
269 | virq = irq_create_of_mapping(oirq.controller, oirq.specifier, | 269 | virq = irq_create_of_mapping(&oirq); |
270 | oirq.size); | ||
271 | } | 270 | } |
272 | if(virq == NO_IRQ) { | 271 | if(virq == NO_IRQ) { |
273 | pr_debug(" Failed to map !\n"); | 272 | pr_debug(" Failed to map !\n"); |
diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c index 4368ec6fdc8c..ac0b034f9ae0 100644 --- a/arch/powerpc/kernel/pci_of_scan.c +++ b/arch/powerpc/kernel/pci_of_scan.c | |||
@@ -302,7 +302,7 @@ static struct pci_dev *of_scan_pci_dev(struct pci_bus *bus, | |||
302 | struct device_node *dn) | 302 | struct device_node *dn) |
303 | { | 303 | { |
304 | struct pci_dev *dev = NULL; | 304 | struct pci_dev *dev = NULL; |
305 | const u32 *reg; | 305 | const __be32 *reg; |
306 | int reglen, devfn; | 306 | int reglen, devfn; |
307 | 307 | ||
308 | pr_debug(" * %s\n", dn->full_name); | 308 | pr_debug(" * %s\n", dn->full_name); |
@@ -312,7 +312,7 @@ static struct pci_dev *of_scan_pci_dev(struct pci_bus *bus, | |||
312 | reg = of_get_property(dn, "reg", ®len); | 312 | reg = of_get_property(dn, "reg", ®len); |
313 | if (reg == NULL || reglen < 20) | 313 | if (reg == NULL || reglen < 20) |
314 | return NULL; | 314 | return NULL; |
315 | devfn = (reg[0] >> 8) & 0xff; | 315 | devfn = (of_read_number(reg, 1) >> 8) & 0xff; |
316 | 316 | ||
317 | /* Check if the PCI device is already there */ | 317 | /* Check if the PCI device is already there */ |
318 | dev = pci_get_slot(bus, devfn); | 318 | dev = pci_get_slot(bus, devfn); |
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index 21646dbe1bb3..3bd77edd7610 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c | |||
@@ -79,10 +79,12 @@ EXPORT_SYMBOL(strlen); | |||
79 | EXPORT_SYMBOL(strcmp); | 79 | EXPORT_SYMBOL(strcmp); |
80 | EXPORT_SYMBOL(strncmp); | 80 | EXPORT_SYMBOL(strncmp); |
81 | 81 | ||
82 | #ifndef CONFIG_GENERIC_CSUM | ||
82 | EXPORT_SYMBOL(csum_partial); | 83 | EXPORT_SYMBOL(csum_partial); |
83 | EXPORT_SYMBOL(csum_partial_copy_generic); | 84 | EXPORT_SYMBOL(csum_partial_copy_generic); |
84 | EXPORT_SYMBOL(ip_fast_csum); | 85 | EXPORT_SYMBOL(ip_fast_csum); |
85 | EXPORT_SYMBOL(csum_tcpudp_magic); | 86 | EXPORT_SYMBOL(csum_tcpudp_magic); |
87 | #endif | ||
86 | 88 | ||
87 | EXPORT_SYMBOL(__copy_tofrom_user); | 89 | EXPORT_SYMBOL(__copy_tofrom_user); |
88 | EXPORT_SYMBOL(__clear_user); | 90 | EXPORT_SYMBOL(__clear_user); |
@@ -98,9 +100,13 @@ EXPORT_SYMBOL(start_thread); | |||
98 | 100 | ||
99 | #ifdef CONFIG_PPC_FPU | 101 | #ifdef CONFIG_PPC_FPU |
100 | EXPORT_SYMBOL(giveup_fpu); | 102 | EXPORT_SYMBOL(giveup_fpu); |
103 | EXPORT_SYMBOL(load_fp_state); | ||
104 | EXPORT_SYMBOL(store_fp_state); | ||
101 | #endif | 105 | #endif |
102 | #ifdef CONFIG_ALTIVEC | 106 | #ifdef CONFIG_ALTIVEC |
103 | EXPORT_SYMBOL(giveup_altivec); | 107 | EXPORT_SYMBOL(giveup_altivec); |
108 | EXPORT_SYMBOL(load_vr_state); | ||
109 | EXPORT_SYMBOL(store_vr_state); | ||
104 | #endif /* CONFIG_ALTIVEC */ | 110 | #endif /* CONFIG_ALTIVEC */ |
105 | #ifdef CONFIG_VSX | 111 | #ifdef CONFIG_VSX |
106 | EXPORT_SYMBOL(giveup_vsx); | 112 | EXPORT_SYMBOL(giveup_vsx); |
@@ -143,10 +149,14 @@ EXPORT_SYMBOL(__ashldi3); | |||
143 | EXPORT_SYMBOL(__lshrdi3); | 149 | EXPORT_SYMBOL(__lshrdi3); |
144 | int __ucmpdi2(unsigned long long, unsigned long long); | 150 | int __ucmpdi2(unsigned long long, unsigned long long); |
145 | EXPORT_SYMBOL(__ucmpdi2); | 151 | EXPORT_SYMBOL(__ucmpdi2); |
152 | int __cmpdi2(long long, long long); | ||
153 | EXPORT_SYMBOL(__cmpdi2); | ||
146 | #endif | 154 | #endif |
147 | long long __bswapdi2(long long); | 155 | long long __bswapdi2(long long); |
148 | EXPORT_SYMBOL(__bswapdi2); | 156 | EXPORT_SYMBOL(__bswapdi2); |
157 | #ifdef __BIG_ENDIAN__ | ||
149 | EXPORT_SYMBOL(memcpy); | 158 | EXPORT_SYMBOL(memcpy); |
159 | #endif | ||
150 | EXPORT_SYMBOL(memset); | 160 | EXPORT_SYMBOL(memset); |
151 | EXPORT_SYMBOL(memmove); | 161 | EXPORT_SYMBOL(memmove); |
152 | EXPORT_SYMBOL(memcmp); | 162 | EXPORT_SYMBOL(memcmp); |
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 6f428da53e20..75c2d1009985 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
@@ -314,28 +314,28 @@ static DEFINE_PER_CPU(struct arch_hw_breakpoint, current_brk); | |||
314 | */ | 314 | */ |
315 | static void set_debug_reg_defaults(struct thread_struct *thread) | 315 | static void set_debug_reg_defaults(struct thread_struct *thread) |
316 | { | 316 | { |
317 | thread->iac1 = thread->iac2 = 0; | 317 | thread->debug.iac1 = thread->debug.iac2 = 0; |
318 | #if CONFIG_PPC_ADV_DEBUG_IACS > 2 | 318 | #if CONFIG_PPC_ADV_DEBUG_IACS > 2 |
319 | thread->iac3 = thread->iac4 = 0; | 319 | thread->debug.iac3 = thread->debug.iac4 = 0; |
320 | #endif | 320 | #endif |
321 | thread->dac1 = thread->dac2 = 0; | 321 | thread->debug.dac1 = thread->debug.dac2 = 0; |
322 | #if CONFIG_PPC_ADV_DEBUG_DVCS > 0 | 322 | #if CONFIG_PPC_ADV_DEBUG_DVCS > 0 |
323 | thread->dvc1 = thread->dvc2 = 0; | 323 | thread->debug.dvc1 = thread->debug.dvc2 = 0; |
324 | #endif | 324 | #endif |
325 | thread->dbcr0 = 0; | 325 | thread->debug.dbcr0 = 0; |
326 | #ifdef CONFIG_BOOKE | 326 | #ifdef CONFIG_BOOKE |
327 | /* | 327 | /* |
328 | * Force User/Supervisor bits to b11 (user-only MSR[PR]=1) | 328 | * Force User/Supervisor bits to b11 (user-only MSR[PR]=1) |
329 | */ | 329 | */ |
330 | thread->dbcr1 = DBCR1_IAC1US | DBCR1_IAC2US | \ | 330 | thread->debug.dbcr1 = DBCR1_IAC1US | DBCR1_IAC2US | |
331 | DBCR1_IAC3US | DBCR1_IAC4US; | 331 | DBCR1_IAC3US | DBCR1_IAC4US; |
332 | /* | 332 | /* |
333 | * Force Data Address Compare User/Supervisor bits to be User-only | 333 | * Force Data Address Compare User/Supervisor bits to be User-only |
334 | * (0b11 MSR[PR]=1) and set all other bits in DBCR2 register to be 0. | 334 | * (0b11 MSR[PR]=1) and set all other bits in DBCR2 register to be 0. |
335 | */ | 335 | */ |
336 | thread->dbcr2 = DBCR2_DAC1US | DBCR2_DAC2US; | 336 | thread->debug.dbcr2 = DBCR2_DAC1US | DBCR2_DAC2US; |
337 | #else | 337 | #else |
338 | thread->dbcr1 = 0; | 338 | thread->debug.dbcr1 = 0; |
339 | #endif | 339 | #endif |
340 | } | 340 | } |
341 | 341 | ||
@@ -348,22 +348,22 @@ static void prime_debug_regs(struct thread_struct *thread) | |||
348 | */ | 348 | */ |
349 | mtmsr(mfmsr() & ~MSR_DE); | 349 | mtmsr(mfmsr() & ~MSR_DE); |
350 | 350 | ||
351 | mtspr(SPRN_IAC1, thread->iac1); | 351 | mtspr(SPRN_IAC1, thread->debug.iac1); |
352 | mtspr(SPRN_IAC2, thread->iac2); | 352 | mtspr(SPRN_IAC2, thread->debug.iac2); |
353 | #if CONFIG_PPC_ADV_DEBUG_IACS > 2 | 353 | #if CONFIG_PPC_ADV_DEBUG_IACS > 2 |
354 | mtspr(SPRN_IAC3, thread->iac3); | 354 | mtspr(SPRN_IAC3, thread->debug.iac3); |
355 | mtspr(SPRN_IAC4, thread->iac4); | 355 | mtspr(SPRN_IAC4, thread->debug.iac4); |
356 | #endif | 356 | #endif |
357 | mtspr(SPRN_DAC1, thread->dac1); | 357 | mtspr(SPRN_DAC1, thread->debug.dac1); |
358 | mtspr(SPRN_DAC2, thread->dac2); | 358 | mtspr(SPRN_DAC2, thread->debug.dac2); |
359 | #if CONFIG_PPC_ADV_DEBUG_DVCS > 0 | 359 | #if CONFIG_PPC_ADV_DEBUG_DVCS > 0 |
360 | mtspr(SPRN_DVC1, thread->dvc1); | 360 | mtspr(SPRN_DVC1, thread->debug.dvc1); |
361 | mtspr(SPRN_DVC2, thread->dvc2); | 361 | mtspr(SPRN_DVC2, thread->debug.dvc2); |
362 | #endif | 362 | #endif |
363 | mtspr(SPRN_DBCR0, thread->dbcr0); | 363 | mtspr(SPRN_DBCR0, thread->debug.dbcr0); |
364 | mtspr(SPRN_DBCR1, thread->dbcr1); | 364 | mtspr(SPRN_DBCR1, thread->debug.dbcr1); |
365 | #ifdef CONFIG_BOOKE | 365 | #ifdef CONFIG_BOOKE |
366 | mtspr(SPRN_DBCR2, thread->dbcr2); | 366 | mtspr(SPRN_DBCR2, thread->debug.dbcr2); |
367 | #endif | 367 | #endif |
368 | } | 368 | } |
369 | /* | 369 | /* |
@@ -371,12 +371,13 @@ static void prime_debug_regs(struct thread_struct *thread) | |||
371 | * debug registers, set the debug registers from the values | 371 | * debug registers, set the debug registers from the values |
372 | * stored in the new thread. | 372 | * stored in the new thread. |
373 | */ | 373 | */ |
374 | static void switch_booke_debug_regs(struct thread_struct *new_thread) | 374 | void switch_booke_debug_regs(struct thread_struct *new_thread) |
375 | { | 375 | { |
376 | if ((current->thread.dbcr0 & DBCR0_IDM) | 376 | if ((current->thread.debug.dbcr0 & DBCR0_IDM) |
377 | || (new_thread->dbcr0 & DBCR0_IDM)) | 377 | || (new_thread->debug.dbcr0 & DBCR0_IDM)) |
378 | prime_debug_regs(new_thread); | 378 | prime_debug_regs(new_thread); |
379 | } | 379 | } |
380 | EXPORT_SYMBOL_GPL(switch_booke_debug_regs); | ||
380 | #else /* !CONFIG_PPC_ADV_DEBUG_REGS */ | 381 | #else /* !CONFIG_PPC_ADV_DEBUG_REGS */ |
381 | #ifndef CONFIG_HAVE_HW_BREAKPOINT | 382 | #ifndef CONFIG_HAVE_HW_BREAKPOINT |
382 | static void set_debug_reg_defaults(struct thread_struct *thread) | 383 | static void set_debug_reg_defaults(struct thread_struct *thread) |
@@ -596,12 +597,13 @@ struct task_struct *__switch_to(struct task_struct *prev, | |||
596 | struct task_struct *new) | 597 | struct task_struct *new) |
597 | { | 598 | { |
598 | struct thread_struct *new_thread, *old_thread; | 599 | struct thread_struct *new_thread, *old_thread; |
599 | unsigned long flags; | ||
600 | struct task_struct *last; | 600 | struct task_struct *last; |
601 | #ifdef CONFIG_PPC_BOOK3S_64 | 601 | #ifdef CONFIG_PPC_BOOK3S_64 |
602 | struct ppc64_tlb_batch *batch; | 602 | struct ppc64_tlb_batch *batch; |
603 | #endif | 603 | #endif |
604 | 604 | ||
605 | WARN_ON(!irqs_disabled()); | ||
606 | |||
605 | /* Back up the TAR across context switches. | 607 | /* Back up the TAR across context switches. |
606 | * Note that the TAR is not available for use in the kernel. (To | 608 | * Note that the TAR is not available for use in the kernel. (To |
607 | * provide this, the TAR should be backed up/restored on exception | 609 | * provide this, the TAR should be backed up/restored on exception |
@@ -721,8 +723,6 @@ struct task_struct *__switch_to(struct task_struct *prev, | |||
721 | } | 723 | } |
722 | #endif /* CONFIG_PPC_BOOK3S_64 */ | 724 | #endif /* CONFIG_PPC_BOOK3S_64 */ |
723 | 725 | ||
724 | local_irq_save(flags); | ||
725 | |||
726 | /* | 726 | /* |
727 | * We can't take a PMU exception inside _switch() since there is a | 727 | * We can't take a PMU exception inside _switch() since there is a |
728 | * window where the kernel stack SLB and the kernel stack are out | 728 | * window where the kernel stack SLB and the kernel stack are out |
@@ -742,8 +742,6 @@ struct task_struct *__switch_to(struct task_struct *prev, | |||
742 | } | 742 | } |
743 | #endif /* CONFIG_PPC_BOOK3S_64 */ | 743 | #endif /* CONFIG_PPC_BOOK3S_64 */ |
744 | 744 | ||
745 | local_irq_restore(flags); | ||
746 | |||
747 | return last; | 745 | return last; |
748 | } | 746 | } |
749 | 747 | ||
@@ -1000,13 +998,19 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
1000 | kregs = (struct pt_regs *) sp; | 998 | kregs = (struct pt_regs *) sp; |
1001 | sp -= STACK_FRAME_OVERHEAD; | 999 | sp -= STACK_FRAME_OVERHEAD; |
1002 | p->thread.ksp = sp; | 1000 | p->thread.ksp = sp; |
1001 | #ifdef CONFIG_PPC32 | ||
1003 | p->thread.ksp_limit = (unsigned long)task_stack_page(p) + | 1002 | p->thread.ksp_limit = (unsigned long)task_stack_page(p) + |
1004 | _ALIGN_UP(sizeof(struct thread_info), 16); | 1003 | _ALIGN_UP(sizeof(struct thread_info), 16); |
1005 | 1004 | #endif | |
1006 | #ifdef CONFIG_HAVE_HW_BREAKPOINT | 1005 | #ifdef CONFIG_HAVE_HW_BREAKPOINT |
1007 | p->thread.ptrace_bps[0] = NULL; | 1006 | p->thread.ptrace_bps[0] = NULL; |
1008 | #endif | 1007 | #endif |
1009 | 1008 | ||
1009 | p->thread.fp_save_area = NULL; | ||
1010 | #ifdef CONFIG_ALTIVEC | ||
1011 | p->thread.vr_save_area = NULL; | ||
1012 | #endif | ||
1013 | |||
1010 | #ifdef CONFIG_PPC_STD_MMU_64 | 1014 | #ifdef CONFIG_PPC_STD_MMU_64 |
1011 | if (mmu_has_feature(MMU_FTR_SLB)) { | 1015 | if (mmu_has_feature(MMU_FTR_SLB)) { |
1012 | unsigned long sp_vsid; | 1016 | unsigned long sp_vsid; |
@@ -1112,12 +1116,12 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp) | |||
1112 | #ifdef CONFIG_VSX | 1116 | #ifdef CONFIG_VSX |
1113 | current->thread.used_vsr = 0; | 1117 | current->thread.used_vsr = 0; |
1114 | #endif | 1118 | #endif |
1115 | memset(current->thread.fpr, 0, sizeof(current->thread.fpr)); | 1119 | memset(¤t->thread.fp_state, 0, sizeof(current->thread.fp_state)); |
1116 | current->thread.fpscr.val = 0; | 1120 | current->thread.fp_save_area = NULL; |
1117 | #ifdef CONFIG_ALTIVEC | 1121 | #ifdef CONFIG_ALTIVEC |
1118 | memset(current->thread.vr, 0, sizeof(current->thread.vr)); | 1122 | memset(¤t->thread.vr_state, 0, sizeof(current->thread.vr_state)); |
1119 | memset(¤t->thread.vscr, 0, sizeof(current->thread.vscr)); | 1123 | current->thread.vr_state.vscr.u[3] = 0x00010000; /* Java mode disabled */ |
1120 | current->thread.vscr.u[3] = 0x00010000; /* Java mode disabled */ | 1124 | current->thread.vr_save_area = NULL; |
1121 | current->thread.vrsave = 0; | 1125 | current->thread.vrsave = 0; |
1122 | current->thread.used_vr = 0; | 1126 | current->thread.used_vr = 0; |
1123 | #endif /* CONFIG_ALTIVEC */ | 1127 | #endif /* CONFIG_ALTIVEC */ |
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index b7634ce41dbc..f3a47098fb8e 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
@@ -546,15 +546,6 @@ void __init early_init_dt_add_memory_arch(u64 base, u64 size) | |||
546 | memblock_add(base, size); | 546 | memblock_add(base, size); |
547 | } | 547 | } |
548 | 548 | ||
549 | #ifdef CONFIG_BLK_DEV_INITRD | ||
550 | void __init early_init_dt_setup_initrd_arch(u64 start, u64 end) | ||
551 | { | ||
552 | initrd_start = (unsigned long)__va(start); | ||
553 | initrd_end = (unsigned long)__va(end); | ||
554 | initrd_below_start_ok = 1; | ||
555 | } | ||
556 | #endif | ||
557 | |||
558 | static void __init early_reserve_mem_dt(void) | 549 | static void __init early_reserve_mem_dt(void) |
559 | { | 550 | { |
560 | unsigned long i, len, dt_root; | 551 | unsigned long i, len, dt_root; |
@@ -761,37 +752,6 @@ void __init early_init_devtree(void *params) | |||
761 | *******/ | 752 | *******/ |
762 | 753 | ||
763 | /** | 754 | /** |
764 | * of_find_next_cache_node - Find a node's subsidiary cache | ||
765 | * @np: node of type "cpu" or "cache" | ||
766 | * | ||
767 | * Returns a node pointer with refcount incremented, use | ||
768 | * of_node_put() on it when done. Caller should hold a reference | ||
769 | * to np. | ||
770 | */ | ||
771 | struct device_node *of_find_next_cache_node(struct device_node *np) | ||
772 | { | ||
773 | struct device_node *child; | ||
774 | const phandle *handle; | ||
775 | |||
776 | handle = of_get_property(np, "l2-cache", NULL); | ||
777 | if (!handle) | ||
778 | handle = of_get_property(np, "next-level-cache", NULL); | ||
779 | |||
780 | if (handle) | ||
781 | return of_find_node_by_phandle(*handle); | ||
782 | |||
783 | /* OF on pmac has nodes instead of properties named "l2-cache" | ||
784 | * beneath CPU nodes. | ||
785 | */ | ||
786 | if (!strcmp(np->type, "cpu")) | ||
787 | for_each_child_of_node(np, child) | ||
788 | if (!strcmp(child->type, "cache")) | ||
789 | return child; | ||
790 | |||
791 | return NULL; | ||
792 | } | ||
793 | |||
794 | /** | ||
795 | * of_get_ibm_chip_id - Returns the IBM "chip-id" of a device | 755 | * of_get_ibm_chip_id - Returns the IBM "chip-id" of a device |
796 | * @np: device node of the device | 756 | * @np: device node of the device |
797 | * | 757 | * |
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 12e656ffe60e..cb64a6e1dc51 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c | |||
@@ -196,6 +196,8 @@ static int __initdata mem_reserve_cnt; | |||
196 | 196 | ||
197 | static cell_t __initdata regbuf[1024]; | 197 | static cell_t __initdata regbuf[1024]; |
198 | 198 | ||
199 | static bool rtas_has_query_cpu_stopped; | ||
200 | |||
199 | 201 | ||
200 | /* | 202 | /* |
201 | * Error results ... some OF calls will return "-1" on error, some | 203 | * Error results ... some OF calls will return "-1" on error, some |
@@ -856,7 +858,8 @@ static void __init prom_send_capabilities(void) | |||
856 | { | 858 | { |
857 | ihandle root; | 859 | ihandle root; |
858 | prom_arg_t ret; | 860 | prom_arg_t ret; |
859 | __be32 *cores; | 861 | u32 cores; |
862 | unsigned char *ptcores; | ||
860 | 863 | ||
861 | root = call_prom("open", 1, 1, ADDR("/")); | 864 | root = call_prom("open", 1, 1, ADDR("/")); |
862 | if (root != 0) { | 865 | if (root != 0) { |
@@ -866,15 +869,30 @@ static void __init prom_send_capabilities(void) | |||
866 | * (we assume this is the same for all cores) and use it to | 869 | * (we assume this is the same for all cores) and use it to |
867 | * divide NR_CPUS. | 870 | * divide NR_CPUS. |
868 | */ | 871 | */ |
869 | cores = (__be32 *)&ibm_architecture_vec[IBM_ARCH_VEC_NRCORES_OFFSET]; | 872 | |
870 | if (be32_to_cpup(cores) != NR_CPUS) { | 873 | /* The core value may start at an odd address. If such a word |
874 | * access is made at a cache line boundary, this leads to an | ||
875 | * exception which may not be handled at this time. | ||
876 | * Forcing a per byte access to avoid exception. | ||
877 | */ | ||
878 | ptcores = &ibm_architecture_vec[IBM_ARCH_VEC_NRCORES_OFFSET]; | ||
879 | cores = 0; | ||
880 | cores |= ptcores[0] << 24; | ||
881 | cores |= ptcores[1] << 16; | ||
882 | cores |= ptcores[2] << 8; | ||
883 | cores |= ptcores[3]; | ||
884 | if (cores != NR_CPUS) { | ||
871 | prom_printf("WARNING ! " | 885 | prom_printf("WARNING ! " |
872 | "ibm_architecture_vec structure inconsistent: %lu!\n", | 886 | "ibm_architecture_vec structure inconsistent: %lu!\n", |
873 | be32_to_cpup(cores)); | 887 | cores); |
874 | } else { | 888 | } else { |
875 | *cores = cpu_to_be32(DIV_ROUND_UP(NR_CPUS, prom_count_smt_threads())); | 889 | cores = DIV_ROUND_UP(NR_CPUS, prom_count_smt_threads()); |
876 | prom_printf("Max number of cores passed to firmware: %lu (NR_CPUS = %lu)\n", | 890 | prom_printf("Max number of cores passed to firmware: %lu (NR_CPUS = %lu)\n", |
877 | be32_to_cpup(cores), NR_CPUS); | 891 | cores, NR_CPUS); |
892 | ptcores[0] = (cores >> 24) & 0xff; | ||
893 | ptcores[1] = (cores >> 16) & 0xff; | ||
894 | ptcores[2] = (cores >> 8) & 0xff; | ||
895 | ptcores[3] = cores & 0xff; | ||
878 | } | 896 | } |
879 | 897 | ||
880 | /* try calling the ibm,client-architecture-support method */ | 898 | /* try calling the ibm,client-architecture-support method */ |
@@ -1574,6 +1592,11 @@ static void __init prom_instantiate_rtas(void) | |||
1574 | prom_setprop(rtas_node, "/rtas", "linux,rtas-entry", | 1592 | prom_setprop(rtas_node, "/rtas", "linux,rtas-entry", |
1575 | &val, sizeof(val)); | 1593 | &val, sizeof(val)); |
1576 | 1594 | ||
1595 | /* Check if it supports "query-cpu-stopped-state" */ | ||
1596 | if (prom_getprop(rtas_node, "query-cpu-stopped-state", | ||
1597 | &val, sizeof(val)) != PROM_ERROR) | ||
1598 | rtas_has_query_cpu_stopped = true; | ||
1599 | |||
1577 | #if defined(CONFIG_PPC_POWERNV) && defined(__BIG_ENDIAN__) | 1600 | #if defined(CONFIG_PPC_POWERNV) && defined(__BIG_ENDIAN__) |
1578 | /* PowerVN takeover hack */ | 1601 | /* PowerVN takeover hack */ |
1579 | prom_rtas_data = base; | 1602 | prom_rtas_data = base; |
@@ -1815,6 +1838,18 @@ static void __init prom_hold_cpus(void) | |||
1815 | = (void *) LOW_ADDR(__secondary_hold_acknowledge); | 1838 | = (void *) LOW_ADDR(__secondary_hold_acknowledge); |
1816 | unsigned long secondary_hold = LOW_ADDR(__secondary_hold); | 1839 | unsigned long secondary_hold = LOW_ADDR(__secondary_hold); |
1817 | 1840 | ||
1841 | /* | ||
1842 | * On pseries, if RTAS supports "query-cpu-stopped-state", | ||
1843 | * we skip this stage, the CPUs will be started by the | ||
1844 | * kernel using RTAS. | ||
1845 | */ | ||
1846 | if ((of_platform == PLATFORM_PSERIES || | ||
1847 | of_platform == PLATFORM_PSERIES_LPAR) && | ||
1848 | rtas_has_query_cpu_stopped) { | ||
1849 | prom_printf("prom_hold_cpus: skipped\n"); | ||
1850 | return; | ||
1851 | } | ||
1852 | |||
1818 | prom_debug("prom_hold_cpus: start...\n"); | 1853 | prom_debug("prom_hold_cpus: start...\n"); |
1819 | prom_debug(" 1) spinloop = 0x%x\n", (unsigned long)spinloop); | 1854 | prom_debug(" 1) spinloop = 0x%x\n", (unsigned long)spinloop); |
1820 | prom_debug(" 1) *spinloop = 0x%x\n", *spinloop); | 1855 | prom_debug(" 1) *spinloop = 0x%x\n", *spinloop); |
@@ -3011,6 +3046,8 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, | |||
3011 | * On non-powermacs, put all CPUs in spin-loops. | 3046 | * On non-powermacs, put all CPUs in spin-loops. |
3012 | * | 3047 | * |
3013 | * PowerMacs use a different mechanism to spin CPUs | 3048 | * PowerMacs use a different mechanism to spin CPUs |
3049 | * | ||
3050 | * (This must be done after instanciating RTAS) | ||
3014 | */ | 3051 | */ |
3015 | if (of_platform != PLATFORM_POWERMAC && | 3052 | if (of_platform != PLATFORM_POWERMAC && |
3016 | of_platform != PLATFORM_OPAL) | 3053 | of_platform != PLATFORM_OPAL) |
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 9a0d24c390a3..75fb40498b41 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c | |||
@@ -362,7 +362,7 @@ static int fpr_get(struct task_struct *target, const struct user_regset *regset, | |||
362 | void *kbuf, void __user *ubuf) | 362 | void *kbuf, void __user *ubuf) |
363 | { | 363 | { |
364 | #ifdef CONFIG_VSX | 364 | #ifdef CONFIG_VSX |
365 | double buf[33]; | 365 | u64 buf[33]; |
366 | int i; | 366 | int i; |
367 | #endif | 367 | #endif |
368 | flush_fp_to_thread(target); | 368 | flush_fp_to_thread(target); |
@@ -371,15 +371,15 @@ static int fpr_get(struct task_struct *target, const struct user_regset *regset, | |||
371 | /* copy to local buffer then write that out */ | 371 | /* copy to local buffer then write that out */ |
372 | for (i = 0; i < 32 ; i++) | 372 | for (i = 0; i < 32 ; i++) |
373 | buf[i] = target->thread.TS_FPR(i); | 373 | buf[i] = target->thread.TS_FPR(i); |
374 | memcpy(&buf[32], &target->thread.fpscr, sizeof(double)); | 374 | buf[32] = target->thread.fp_state.fpscr; |
375 | return user_regset_copyout(&pos, &count, &kbuf, &ubuf, buf, 0, -1); | 375 | return user_regset_copyout(&pos, &count, &kbuf, &ubuf, buf, 0, -1); |
376 | 376 | ||
377 | #else | 377 | #else |
378 | BUILD_BUG_ON(offsetof(struct thread_struct, fpscr) != | 378 | BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) != |
379 | offsetof(struct thread_struct, TS_FPR(32))); | 379 | offsetof(struct thread_fp_state, fpr[32][0])); |
380 | 380 | ||
381 | return user_regset_copyout(&pos, &count, &kbuf, &ubuf, | 381 | return user_regset_copyout(&pos, &count, &kbuf, &ubuf, |
382 | &target->thread.fpr, 0, -1); | 382 | &target->thread.fp_state, 0, -1); |
383 | #endif | 383 | #endif |
384 | } | 384 | } |
385 | 385 | ||
@@ -388,7 +388,7 @@ static int fpr_set(struct task_struct *target, const struct user_regset *regset, | |||
388 | const void *kbuf, const void __user *ubuf) | 388 | const void *kbuf, const void __user *ubuf) |
389 | { | 389 | { |
390 | #ifdef CONFIG_VSX | 390 | #ifdef CONFIG_VSX |
391 | double buf[33]; | 391 | u64 buf[33]; |
392 | int i; | 392 | int i; |
393 | #endif | 393 | #endif |
394 | flush_fp_to_thread(target); | 394 | flush_fp_to_thread(target); |
@@ -400,14 +400,14 @@ static int fpr_set(struct task_struct *target, const struct user_regset *regset, | |||
400 | return i; | 400 | return i; |
401 | for (i = 0; i < 32 ; i++) | 401 | for (i = 0; i < 32 ; i++) |
402 | target->thread.TS_FPR(i) = buf[i]; | 402 | target->thread.TS_FPR(i) = buf[i]; |
403 | memcpy(&target->thread.fpscr, &buf[32], sizeof(double)); | 403 | target->thread.fp_state.fpscr = buf[32]; |
404 | return 0; | 404 | return 0; |
405 | #else | 405 | #else |
406 | BUILD_BUG_ON(offsetof(struct thread_struct, fpscr) != | 406 | BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) != |
407 | offsetof(struct thread_struct, TS_FPR(32))); | 407 | offsetof(struct thread_fp_state, fpr[32][0])); |
408 | 408 | ||
409 | return user_regset_copyin(&pos, &count, &kbuf, &ubuf, | 409 | return user_regset_copyin(&pos, &count, &kbuf, &ubuf, |
410 | &target->thread.fpr, 0, -1); | 410 | &target->thread.fp_state, 0, -1); |
411 | #endif | 411 | #endif |
412 | } | 412 | } |
413 | 413 | ||
@@ -440,11 +440,11 @@ static int vr_get(struct task_struct *target, const struct user_regset *regset, | |||
440 | 440 | ||
441 | flush_altivec_to_thread(target); | 441 | flush_altivec_to_thread(target); |
442 | 442 | ||
443 | BUILD_BUG_ON(offsetof(struct thread_struct, vscr) != | 443 | BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) != |
444 | offsetof(struct thread_struct, vr[32])); | 444 | offsetof(struct thread_vr_state, vr[32])); |
445 | 445 | ||
446 | ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, | 446 | ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, |
447 | &target->thread.vr, 0, | 447 | &target->thread.vr_state, 0, |
448 | 33 * sizeof(vector128)); | 448 | 33 * sizeof(vector128)); |
449 | if (!ret) { | 449 | if (!ret) { |
450 | /* | 450 | /* |
@@ -471,11 +471,12 @@ static int vr_set(struct task_struct *target, const struct user_regset *regset, | |||
471 | 471 | ||
472 | flush_altivec_to_thread(target); | 472 | flush_altivec_to_thread(target); |
473 | 473 | ||
474 | BUILD_BUG_ON(offsetof(struct thread_struct, vscr) != | 474 | BUILD_BUG_ON(offsetof(struct thread_vr_state, vscr) != |
475 | offsetof(struct thread_struct, vr[32])); | 475 | offsetof(struct thread_vr_state, vr[32])); |
476 | 476 | ||
477 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, | 477 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, |
478 | &target->thread.vr, 0, 33 * sizeof(vector128)); | 478 | &target->thread.vr_state, 0, |
479 | 33 * sizeof(vector128)); | ||
479 | if (!ret && count > 0) { | 480 | if (!ret && count > 0) { |
480 | /* | 481 | /* |
481 | * We use only the first word of vrsave. | 482 | * We use only the first word of vrsave. |
@@ -514,13 +515,13 @@ static int vsr_get(struct task_struct *target, const struct user_regset *regset, | |||
514 | unsigned int pos, unsigned int count, | 515 | unsigned int pos, unsigned int count, |
515 | void *kbuf, void __user *ubuf) | 516 | void *kbuf, void __user *ubuf) |
516 | { | 517 | { |
517 | double buf[32]; | 518 | u64 buf[32]; |
518 | int ret, i; | 519 | int ret, i; |
519 | 520 | ||
520 | flush_vsx_to_thread(target); | 521 | flush_vsx_to_thread(target); |
521 | 522 | ||
522 | for (i = 0; i < 32 ; i++) | 523 | for (i = 0; i < 32 ; i++) |
523 | buf[i] = target->thread.fpr[i][TS_VSRLOWOFFSET]; | 524 | buf[i] = target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET]; |
524 | ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, | 525 | ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, |
525 | buf, 0, 32 * sizeof(double)); | 526 | buf, 0, 32 * sizeof(double)); |
526 | 527 | ||
@@ -531,7 +532,7 @@ static int vsr_set(struct task_struct *target, const struct user_regset *regset, | |||
531 | unsigned int pos, unsigned int count, | 532 | unsigned int pos, unsigned int count, |
532 | const void *kbuf, const void __user *ubuf) | 533 | const void *kbuf, const void __user *ubuf) |
533 | { | 534 | { |
534 | double buf[32]; | 535 | u64 buf[32]; |
535 | int ret,i; | 536 | int ret,i; |
536 | 537 | ||
537 | flush_vsx_to_thread(target); | 538 | flush_vsx_to_thread(target); |
@@ -539,7 +540,7 @@ static int vsr_set(struct task_struct *target, const struct user_regset *regset, | |||
539 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, | 540 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, |
540 | buf, 0, 32 * sizeof(double)); | 541 | buf, 0, 32 * sizeof(double)); |
541 | for (i = 0; i < 32 ; i++) | 542 | for (i = 0; i < 32 ; i++) |
542 | target->thread.fpr[i][TS_VSRLOWOFFSET] = buf[i]; | 543 | target->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = buf[i]; |
543 | 544 | ||
544 | 545 | ||
545 | return ret; | 546 | return ret; |
@@ -657,7 +658,7 @@ static const struct user_regset native_regsets[] = { | |||
657 | #endif | 658 | #endif |
658 | #ifdef CONFIG_SPE | 659 | #ifdef CONFIG_SPE |
659 | [REGSET_SPE] = { | 660 | [REGSET_SPE] = { |
660 | .n = 35, | 661 | .core_note_type = NT_PPC_SPE, .n = 35, |
661 | .size = sizeof(u32), .align = sizeof(u32), | 662 | .size = sizeof(u32), .align = sizeof(u32), |
662 | .active = evr_active, .get = evr_get, .set = evr_set | 663 | .active = evr_active, .get = evr_get, .set = evr_set |
663 | }, | 664 | }, |
@@ -854,8 +855,8 @@ void user_enable_single_step(struct task_struct *task) | |||
854 | 855 | ||
855 | if (regs != NULL) { | 856 | if (regs != NULL) { |
856 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | 857 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS |
857 | task->thread.dbcr0 &= ~DBCR0_BT; | 858 | task->thread.debug.dbcr0 &= ~DBCR0_BT; |
858 | task->thread.dbcr0 |= DBCR0_IDM | DBCR0_IC; | 859 | task->thread.debug.dbcr0 |= DBCR0_IDM | DBCR0_IC; |
859 | regs->msr |= MSR_DE; | 860 | regs->msr |= MSR_DE; |
860 | #else | 861 | #else |
861 | regs->msr &= ~MSR_BE; | 862 | regs->msr &= ~MSR_BE; |
@@ -871,8 +872,8 @@ void user_enable_block_step(struct task_struct *task) | |||
871 | 872 | ||
872 | if (regs != NULL) { | 873 | if (regs != NULL) { |
873 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | 874 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS |
874 | task->thread.dbcr0 &= ~DBCR0_IC; | 875 | task->thread.debug.dbcr0 &= ~DBCR0_IC; |
875 | task->thread.dbcr0 = DBCR0_IDM | DBCR0_BT; | 876 | task->thread.debug.dbcr0 = DBCR0_IDM | DBCR0_BT; |
876 | regs->msr |= MSR_DE; | 877 | regs->msr |= MSR_DE; |
877 | #else | 878 | #else |
878 | regs->msr &= ~MSR_SE; | 879 | regs->msr &= ~MSR_SE; |
@@ -894,16 +895,16 @@ void user_disable_single_step(struct task_struct *task) | |||
894 | * And, after doing so, if all debug flags are off, turn | 895 | * And, after doing so, if all debug flags are off, turn |
895 | * off DBCR0(IDM) and MSR(DE) .... Torez | 896 | * off DBCR0(IDM) and MSR(DE) .... Torez |
896 | */ | 897 | */ |
897 | task->thread.dbcr0 &= ~DBCR0_IC; | 898 | task->thread.debug.dbcr0 &= ~(DBCR0_IC|DBCR0_BT); |
898 | /* | 899 | /* |
899 | * Test to see if any of the DBCR_ACTIVE_EVENTS bits are set. | 900 | * Test to see if any of the DBCR_ACTIVE_EVENTS bits are set. |
900 | */ | 901 | */ |
901 | if (!DBCR_ACTIVE_EVENTS(task->thread.dbcr0, | 902 | if (!DBCR_ACTIVE_EVENTS(task->thread.debug.dbcr0, |
902 | task->thread.dbcr1)) { | 903 | task->thread.debug.dbcr1)) { |
903 | /* | 904 | /* |
904 | * All debug events were off..... | 905 | * All debug events were off..... |
905 | */ | 906 | */ |
906 | task->thread.dbcr0 &= ~DBCR0_IDM; | 907 | task->thread.debug.dbcr0 &= ~DBCR0_IDM; |
907 | regs->msr &= ~MSR_DE; | 908 | regs->msr &= ~MSR_DE; |
908 | } | 909 | } |
909 | #else | 910 | #else |
@@ -1022,14 +1023,14 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, | |||
1022 | */ | 1023 | */ |
1023 | 1024 | ||
1024 | /* DAC's hold the whole address without any mode flags */ | 1025 | /* DAC's hold the whole address without any mode flags */ |
1025 | task->thread.dac1 = data & ~0x3UL; | 1026 | task->thread.debug.dac1 = data & ~0x3UL; |
1026 | 1027 | ||
1027 | if (task->thread.dac1 == 0) { | 1028 | if (task->thread.debug.dac1 == 0) { |
1028 | dbcr_dac(task) &= ~(DBCR_DAC1R | DBCR_DAC1W); | 1029 | dbcr_dac(task) &= ~(DBCR_DAC1R | DBCR_DAC1W); |
1029 | if (!DBCR_ACTIVE_EVENTS(task->thread.dbcr0, | 1030 | if (!DBCR_ACTIVE_EVENTS(task->thread.debug.dbcr0, |
1030 | task->thread.dbcr1)) { | 1031 | task->thread.debug.dbcr1)) { |
1031 | task->thread.regs->msr &= ~MSR_DE; | 1032 | task->thread.regs->msr &= ~MSR_DE; |
1032 | task->thread.dbcr0 &= ~DBCR0_IDM; | 1033 | task->thread.debug.dbcr0 &= ~DBCR0_IDM; |
1033 | } | 1034 | } |
1034 | return 0; | 1035 | return 0; |
1035 | } | 1036 | } |
@@ -1041,7 +1042,7 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr, | |||
1041 | 1042 | ||
1042 | /* Set the Internal Debugging flag (IDM bit 1) for the DBCR0 | 1043 | /* Set the Internal Debugging flag (IDM bit 1) for the DBCR0 |
1043 | register */ | 1044 | register */ |
1044 | task->thread.dbcr0 |= DBCR0_IDM; | 1045 | task->thread.debug.dbcr0 |= DBCR0_IDM; |
1045 | 1046 | ||
1046 | /* Check for write and read flags and set DBCR0 | 1047 | /* Check for write and read flags and set DBCR0 |
1047 | accordingly */ | 1048 | accordingly */ |
@@ -1071,10 +1072,10 @@ static long set_instruction_bp(struct task_struct *child, | |||
1071 | struct ppc_hw_breakpoint *bp_info) | 1072 | struct ppc_hw_breakpoint *bp_info) |
1072 | { | 1073 | { |
1073 | int slot; | 1074 | int slot; |
1074 | int slot1_in_use = ((child->thread.dbcr0 & DBCR0_IAC1) != 0); | 1075 | int slot1_in_use = ((child->thread.debug.dbcr0 & DBCR0_IAC1) != 0); |
1075 | int slot2_in_use = ((child->thread.dbcr0 & DBCR0_IAC2) != 0); | 1076 | int slot2_in_use = ((child->thread.debug.dbcr0 & DBCR0_IAC2) != 0); |
1076 | int slot3_in_use = ((child->thread.dbcr0 & DBCR0_IAC3) != 0); | 1077 | int slot3_in_use = ((child->thread.debug.dbcr0 & DBCR0_IAC3) != 0); |
1077 | int slot4_in_use = ((child->thread.dbcr0 & DBCR0_IAC4) != 0); | 1078 | int slot4_in_use = ((child->thread.debug.dbcr0 & DBCR0_IAC4) != 0); |
1078 | 1079 | ||
1079 | if (dbcr_iac_range(child) & DBCR_IAC12MODE) | 1080 | if (dbcr_iac_range(child) & DBCR_IAC12MODE) |
1080 | slot2_in_use = 1; | 1081 | slot2_in_use = 1; |
@@ -1093,9 +1094,9 @@ static long set_instruction_bp(struct task_struct *child, | |||
1093 | /* We need a pair of IAC regsisters */ | 1094 | /* We need a pair of IAC regsisters */ |
1094 | if ((!slot1_in_use) && (!slot2_in_use)) { | 1095 | if ((!slot1_in_use) && (!slot2_in_use)) { |
1095 | slot = 1; | 1096 | slot = 1; |
1096 | child->thread.iac1 = bp_info->addr; | 1097 | child->thread.debug.iac1 = bp_info->addr; |
1097 | child->thread.iac2 = bp_info->addr2; | 1098 | child->thread.debug.iac2 = bp_info->addr2; |
1098 | child->thread.dbcr0 |= DBCR0_IAC1; | 1099 | child->thread.debug.dbcr0 |= DBCR0_IAC1; |
1099 | if (bp_info->addr_mode == | 1100 | if (bp_info->addr_mode == |
1100 | PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE) | 1101 | PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE) |
1101 | dbcr_iac_range(child) |= DBCR_IAC12X; | 1102 | dbcr_iac_range(child) |= DBCR_IAC12X; |
@@ -1104,9 +1105,9 @@ static long set_instruction_bp(struct task_struct *child, | |||
1104 | #if CONFIG_PPC_ADV_DEBUG_IACS > 2 | 1105 | #if CONFIG_PPC_ADV_DEBUG_IACS > 2 |
1105 | } else if ((!slot3_in_use) && (!slot4_in_use)) { | 1106 | } else if ((!slot3_in_use) && (!slot4_in_use)) { |
1106 | slot = 3; | 1107 | slot = 3; |
1107 | child->thread.iac3 = bp_info->addr; | 1108 | child->thread.debug.iac3 = bp_info->addr; |
1108 | child->thread.iac4 = bp_info->addr2; | 1109 | child->thread.debug.iac4 = bp_info->addr2; |
1109 | child->thread.dbcr0 |= DBCR0_IAC3; | 1110 | child->thread.debug.dbcr0 |= DBCR0_IAC3; |
1110 | if (bp_info->addr_mode == | 1111 | if (bp_info->addr_mode == |
1111 | PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE) | 1112 | PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE) |
1112 | dbcr_iac_range(child) |= DBCR_IAC34X; | 1113 | dbcr_iac_range(child) |= DBCR_IAC34X; |
@@ -1126,30 +1127,30 @@ static long set_instruction_bp(struct task_struct *child, | |||
1126 | */ | 1127 | */ |
1127 | if (slot2_in_use || (slot3_in_use == slot4_in_use)) { | 1128 | if (slot2_in_use || (slot3_in_use == slot4_in_use)) { |
1128 | slot = 1; | 1129 | slot = 1; |
1129 | child->thread.iac1 = bp_info->addr; | 1130 | child->thread.debug.iac1 = bp_info->addr; |
1130 | child->thread.dbcr0 |= DBCR0_IAC1; | 1131 | child->thread.debug.dbcr0 |= DBCR0_IAC1; |
1131 | goto out; | 1132 | goto out; |
1132 | } | 1133 | } |
1133 | } | 1134 | } |
1134 | if (!slot2_in_use) { | 1135 | if (!slot2_in_use) { |
1135 | slot = 2; | 1136 | slot = 2; |
1136 | child->thread.iac2 = bp_info->addr; | 1137 | child->thread.debug.iac2 = bp_info->addr; |
1137 | child->thread.dbcr0 |= DBCR0_IAC2; | 1138 | child->thread.debug.dbcr0 |= DBCR0_IAC2; |
1138 | #if CONFIG_PPC_ADV_DEBUG_IACS > 2 | 1139 | #if CONFIG_PPC_ADV_DEBUG_IACS > 2 |
1139 | } else if (!slot3_in_use) { | 1140 | } else if (!slot3_in_use) { |
1140 | slot = 3; | 1141 | slot = 3; |
1141 | child->thread.iac3 = bp_info->addr; | 1142 | child->thread.debug.iac3 = bp_info->addr; |
1142 | child->thread.dbcr0 |= DBCR0_IAC3; | 1143 | child->thread.debug.dbcr0 |= DBCR0_IAC3; |
1143 | } else if (!slot4_in_use) { | 1144 | } else if (!slot4_in_use) { |
1144 | slot = 4; | 1145 | slot = 4; |
1145 | child->thread.iac4 = bp_info->addr; | 1146 | child->thread.debug.iac4 = bp_info->addr; |
1146 | child->thread.dbcr0 |= DBCR0_IAC4; | 1147 | child->thread.debug.dbcr0 |= DBCR0_IAC4; |
1147 | #endif | 1148 | #endif |
1148 | } else | 1149 | } else |
1149 | return -ENOSPC; | 1150 | return -ENOSPC; |
1150 | } | 1151 | } |
1151 | out: | 1152 | out: |
1152 | child->thread.dbcr0 |= DBCR0_IDM; | 1153 | child->thread.debug.dbcr0 |= DBCR0_IDM; |
1153 | child->thread.regs->msr |= MSR_DE; | 1154 | child->thread.regs->msr |= MSR_DE; |
1154 | 1155 | ||
1155 | return slot; | 1156 | return slot; |
@@ -1159,49 +1160,49 @@ static int del_instruction_bp(struct task_struct *child, int slot) | |||
1159 | { | 1160 | { |
1160 | switch (slot) { | 1161 | switch (slot) { |
1161 | case 1: | 1162 | case 1: |
1162 | if ((child->thread.dbcr0 & DBCR0_IAC1) == 0) | 1163 | if ((child->thread.debug.dbcr0 & DBCR0_IAC1) == 0) |
1163 | return -ENOENT; | 1164 | return -ENOENT; |
1164 | 1165 | ||
1165 | if (dbcr_iac_range(child) & DBCR_IAC12MODE) { | 1166 | if (dbcr_iac_range(child) & DBCR_IAC12MODE) { |
1166 | /* address range - clear slots 1 & 2 */ | 1167 | /* address range - clear slots 1 & 2 */ |
1167 | child->thread.iac2 = 0; | 1168 | child->thread.debug.iac2 = 0; |
1168 | dbcr_iac_range(child) &= ~DBCR_IAC12MODE; | 1169 | dbcr_iac_range(child) &= ~DBCR_IAC12MODE; |
1169 | } | 1170 | } |
1170 | child->thread.iac1 = 0; | 1171 | child->thread.debug.iac1 = 0; |
1171 | child->thread.dbcr0 &= ~DBCR0_IAC1; | 1172 | child->thread.debug.dbcr0 &= ~DBCR0_IAC1; |
1172 | break; | 1173 | break; |
1173 | case 2: | 1174 | case 2: |
1174 | if ((child->thread.dbcr0 & DBCR0_IAC2) == 0) | 1175 | if ((child->thread.debug.dbcr0 & DBCR0_IAC2) == 0) |
1175 | return -ENOENT; | 1176 | return -ENOENT; |
1176 | 1177 | ||
1177 | if (dbcr_iac_range(child) & DBCR_IAC12MODE) | 1178 | if (dbcr_iac_range(child) & DBCR_IAC12MODE) |
1178 | /* used in a range */ | 1179 | /* used in a range */ |
1179 | return -EINVAL; | 1180 | return -EINVAL; |
1180 | child->thread.iac2 = 0; | 1181 | child->thread.debug.iac2 = 0; |
1181 | child->thread.dbcr0 &= ~DBCR0_IAC2; | 1182 | child->thread.debug.dbcr0 &= ~DBCR0_IAC2; |
1182 | break; | 1183 | break; |
1183 | #if CONFIG_PPC_ADV_DEBUG_IACS > 2 | 1184 | #if CONFIG_PPC_ADV_DEBUG_IACS > 2 |
1184 | case 3: | 1185 | case 3: |
1185 | if ((child->thread.dbcr0 & DBCR0_IAC3) == 0) | 1186 | if ((child->thread.debug.dbcr0 & DBCR0_IAC3) == 0) |
1186 | return -ENOENT; | 1187 | return -ENOENT; |
1187 | 1188 | ||
1188 | if (dbcr_iac_range(child) & DBCR_IAC34MODE) { | 1189 | if (dbcr_iac_range(child) & DBCR_IAC34MODE) { |
1189 | /* address range - clear slots 3 & 4 */ | 1190 | /* address range - clear slots 3 & 4 */ |
1190 | child->thread.iac4 = 0; | 1191 | child->thread.debug.iac4 = 0; |
1191 | dbcr_iac_range(child) &= ~DBCR_IAC34MODE; | 1192 | dbcr_iac_range(child) &= ~DBCR_IAC34MODE; |
1192 | } | 1193 | } |
1193 | child->thread.iac3 = 0; | 1194 | child->thread.debug.iac3 = 0; |
1194 | child->thread.dbcr0 &= ~DBCR0_IAC3; | 1195 | child->thread.debug.dbcr0 &= ~DBCR0_IAC3; |
1195 | break; | 1196 | break; |
1196 | case 4: | 1197 | case 4: |
1197 | if ((child->thread.dbcr0 & DBCR0_IAC4) == 0) | 1198 | if ((child->thread.debug.dbcr0 & DBCR0_IAC4) == 0) |
1198 | return -ENOENT; | 1199 | return -ENOENT; |
1199 | 1200 | ||
1200 | if (dbcr_iac_range(child) & DBCR_IAC34MODE) | 1201 | if (dbcr_iac_range(child) & DBCR_IAC34MODE) |
1201 | /* Used in a range */ | 1202 | /* Used in a range */ |
1202 | return -EINVAL; | 1203 | return -EINVAL; |
1203 | child->thread.iac4 = 0; | 1204 | child->thread.debug.iac4 = 0; |
1204 | child->thread.dbcr0 &= ~DBCR0_IAC4; | 1205 | child->thread.debug.dbcr0 &= ~DBCR0_IAC4; |
1205 | break; | 1206 | break; |
1206 | #endif | 1207 | #endif |
1207 | default: | 1208 | default: |
@@ -1231,18 +1232,18 @@ static int set_dac(struct task_struct *child, struct ppc_hw_breakpoint *bp_info) | |||
1231 | dbcr_dac(child) |= DBCR_DAC1R; | 1232 | dbcr_dac(child) |= DBCR_DAC1R; |
1232 | if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE) | 1233 | if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE) |
1233 | dbcr_dac(child) |= DBCR_DAC1W; | 1234 | dbcr_dac(child) |= DBCR_DAC1W; |
1234 | child->thread.dac1 = (unsigned long)bp_info->addr; | 1235 | child->thread.debug.dac1 = (unsigned long)bp_info->addr; |
1235 | #if CONFIG_PPC_ADV_DEBUG_DVCS > 0 | 1236 | #if CONFIG_PPC_ADV_DEBUG_DVCS > 0 |
1236 | if (byte_enable) { | 1237 | if (byte_enable) { |
1237 | child->thread.dvc1 = | 1238 | child->thread.debug.dvc1 = |
1238 | (unsigned long)bp_info->condition_value; | 1239 | (unsigned long)bp_info->condition_value; |
1239 | child->thread.dbcr2 |= | 1240 | child->thread.debug.dbcr2 |= |
1240 | ((byte_enable << DBCR2_DVC1BE_SHIFT) | | 1241 | ((byte_enable << DBCR2_DVC1BE_SHIFT) | |
1241 | (condition_mode << DBCR2_DVC1M_SHIFT)); | 1242 | (condition_mode << DBCR2_DVC1M_SHIFT)); |
1242 | } | 1243 | } |
1243 | #endif | 1244 | #endif |
1244 | #ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE | 1245 | #ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE |
1245 | } else if (child->thread.dbcr2 & DBCR2_DAC12MODE) { | 1246 | } else if (child->thread.debug.dbcr2 & DBCR2_DAC12MODE) { |
1246 | /* Both dac1 and dac2 are part of a range */ | 1247 | /* Both dac1 and dac2 are part of a range */ |
1247 | return -ENOSPC; | 1248 | return -ENOSPC; |
1248 | #endif | 1249 | #endif |
@@ -1252,19 +1253,19 @@ static int set_dac(struct task_struct *child, struct ppc_hw_breakpoint *bp_info) | |||
1252 | dbcr_dac(child) |= DBCR_DAC2R; | 1253 | dbcr_dac(child) |= DBCR_DAC2R; |
1253 | if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE) | 1254 | if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE) |
1254 | dbcr_dac(child) |= DBCR_DAC2W; | 1255 | dbcr_dac(child) |= DBCR_DAC2W; |
1255 | child->thread.dac2 = (unsigned long)bp_info->addr; | 1256 | child->thread.debug.dac2 = (unsigned long)bp_info->addr; |
1256 | #if CONFIG_PPC_ADV_DEBUG_DVCS > 0 | 1257 | #if CONFIG_PPC_ADV_DEBUG_DVCS > 0 |
1257 | if (byte_enable) { | 1258 | if (byte_enable) { |
1258 | child->thread.dvc2 = | 1259 | child->thread.debug.dvc2 = |
1259 | (unsigned long)bp_info->condition_value; | 1260 | (unsigned long)bp_info->condition_value; |
1260 | child->thread.dbcr2 |= | 1261 | child->thread.debug.dbcr2 |= |
1261 | ((byte_enable << DBCR2_DVC2BE_SHIFT) | | 1262 | ((byte_enable << DBCR2_DVC2BE_SHIFT) | |
1262 | (condition_mode << DBCR2_DVC2M_SHIFT)); | 1263 | (condition_mode << DBCR2_DVC2M_SHIFT)); |
1263 | } | 1264 | } |
1264 | #endif | 1265 | #endif |
1265 | } else | 1266 | } else |
1266 | return -ENOSPC; | 1267 | return -ENOSPC; |
1267 | child->thread.dbcr0 |= DBCR0_IDM; | 1268 | child->thread.debug.dbcr0 |= DBCR0_IDM; |
1268 | child->thread.regs->msr |= MSR_DE; | 1269 | child->thread.regs->msr |= MSR_DE; |
1269 | 1270 | ||
1270 | return slot + 4; | 1271 | return slot + 4; |
@@ -1276,32 +1277,32 @@ static int del_dac(struct task_struct *child, int slot) | |||
1276 | if ((dbcr_dac(child) & (DBCR_DAC1R | DBCR_DAC1W)) == 0) | 1277 | if ((dbcr_dac(child) & (DBCR_DAC1R | DBCR_DAC1W)) == 0) |
1277 | return -ENOENT; | 1278 | return -ENOENT; |
1278 | 1279 | ||
1279 | child->thread.dac1 = 0; | 1280 | child->thread.debug.dac1 = 0; |
1280 | dbcr_dac(child) &= ~(DBCR_DAC1R | DBCR_DAC1W); | 1281 | dbcr_dac(child) &= ~(DBCR_DAC1R | DBCR_DAC1W); |
1281 | #ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE | 1282 | #ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE |
1282 | if (child->thread.dbcr2 & DBCR2_DAC12MODE) { | 1283 | if (child->thread.debug.dbcr2 & DBCR2_DAC12MODE) { |
1283 | child->thread.dac2 = 0; | 1284 | child->thread.debug.dac2 = 0; |
1284 | child->thread.dbcr2 &= ~DBCR2_DAC12MODE; | 1285 | child->thread.debug.dbcr2 &= ~DBCR2_DAC12MODE; |
1285 | } | 1286 | } |
1286 | child->thread.dbcr2 &= ~(DBCR2_DVC1M | DBCR2_DVC1BE); | 1287 | child->thread.debug.dbcr2 &= ~(DBCR2_DVC1M | DBCR2_DVC1BE); |
1287 | #endif | 1288 | #endif |
1288 | #if CONFIG_PPC_ADV_DEBUG_DVCS > 0 | 1289 | #if CONFIG_PPC_ADV_DEBUG_DVCS > 0 |
1289 | child->thread.dvc1 = 0; | 1290 | child->thread.debug.dvc1 = 0; |
1290 | #endif | 1291 | #endif |
1291 | } else if (slot == 2) { | 1292 | } else if (slot == 2) { |
1292 | if ((dbcr_dac(child) & (DBCR_DAC2R | DBCR_DAC2W)) == 0) | 1293 | if ((dbcr_dac(child) & (DBCR_DAC2R | DBCR_DAC2W)) == 0) |
1293 | return -ENOENT; | 1294 | return -ENOENT; |
1294 | 1295 | ||
1295 | #ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE | 1296 | #ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE |
1296 | if (child->thread.dbcr2 & DBCR2_DAC12MODE) | 1297 | if (child->thread.debug.dbcr2 & DBCR2_DAC12MODE) |
1297 | /* Part of a range */ | 1298 | /* Part of a range */ |
1298 | return -EINVAL; | 1299 | return -EINVAL; |
1299 | child->thread.dbcr2 &= ~(DBCR2_DVC2M | DBCR2_DVC2BE); | 1300 | child->thread.debug.dbcr2 &= ~(DBCR2_DVC2M | DBCR2_DVC2BE); |
1300 | #endif | 1301 | #endif |
1301 | #if CONFIG_PPC_ADV_DEBUG_DVCS > 0 | 1302 | #if CONFIG_PPC_ADV_DEBUG_DVCS > 0 |
1302 | child->thread.dvc2 = 0; | 1303 | child->thread.debug.dvc2 = 0; |
1303 | #endif | 1304 | #endif |
1304 | child->thread.dac2 = 0; | 1305 | child->thread.debug.dac2 = 0; |
1305 | dbcr_dac(child) &= ~(DBCR_DAC2R | DBCR_DAC2W); | 1306 | dbcr_dac(child) &= ~(DBCR_DAC2R | DBCR_DAC2W); |
1306 | } else | 1307 | } else |
1307 | return -EINVAL; | 1308 | return -EINVAL; |
@@ -1343,22 +1344,22 @@ static int set_dac_range(struct task_struct *child, | |||
1343 | return -EIO; | 1344 | return -EIO; |
1344 | } | 1345 | } |
1345 | 1346 | ||
1346 | if (child->thread.dbcr0 & | 1347 | if (child->thread.debug.dbcr0 & |
1347 | (DBCR0_DAC1R | DBCR0_DAC1W | DBCR0_DAC2R | DBCR0_DAC2W)) | 1348 | (DBCR0_DAC1R | DBCR0_DAC1W | DBCR0_DAC2R | DBCR0_DAC2W)) |
1348 | return -ENOSPC; | 1349 | return -ENOSPC; |
1349 | 1350 | ||
1350 | if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_READ) | 1351 | if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_READ) |
1351 | child->thread.dbcr0 |= (DBCR0_DAC1R | DBCR0_IDM); | 1352 | child->thread.debug.dbcr0 |= (DBCR0_DAC1R | DBCR0_IDM); |
1352 | if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE) | 1353 | if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE) |
1353 | child->thread.dbcr0 |= (DBCR0_DAC1W | DBCR0_IDM); | 1354 | child->thread.debug.dbcr0 |= (DBCR0_DAC1W | DBCR0_IDM); |
1354 | child->thread.dac1 = bp_info->addr; | 1355 | child->thread.debug.dac1 = bp_info->addr; |
1355 | child->thread.dac2 = bp_info->addr2; | 1356 | child->thread.debug.dac2 = bp_info->addr2; |
1356 | if (mode == PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE) | 1357 | if (mode == PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE) |
1357 | child->thread.dbcr2 |= DBCR2_DAC12M; | 1358 | child->thread.debug.dbcr2 |= DBCR2_DAC12M; |
1358 | else if (mode == PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE) | 1359 | else if (mode == PPC_BREAKPOINT_MODE_RANGE_EXCLUSIVE) |
1359 | child->thread.dbcr2 |= DBCR2_DAC12MX; | 1360 | child->thread.debug.dbcr2 |= DBCR2_DAC12MX; |
1360 | else /* PPC_BREAKPOINT_MODE_MASK */ | 1361 | else /* PPC_BREAKPOINT_MODE_MASK */ |
1361 | child->thread.dbcr2 |= DBCR2_DAC12MM; | 1362 | child->thread.debug.dbcr2 |= DBCR2_DAC12MM; |
1362 | child->thread.regs->msr |= MSR_DE; | 1363 | child->thread.regs->msr |= MSR_DE; |
1363 | 1364 | ||
1364 | return 5; | 1365 | return 5; |
@@ -1489,9 +1490,9 @@ static long ppc_del_hwdebug(struct task_struct *child, long data) | |||
1489 | rc = del_dac(child, (int)data - 4); | 1490 | rc = del_dac(child, (int)data - 4); |
1490 | 1491 | ||
1491 | if (!rc) { | 1492 | if (!rc) { |
1492 | if (!DBCR_ACTIVE_EVENTS(child->thread.dbcr0, | 1493 | if (!DBCR_ACTIVE_EVENTS(child->thread.debug.dbcr0, |
1493 | child->thread.dbcr1)) { | 1494 | child->thread.debug.dbcr1)) { |
1494 | child->thread.dbcr0 &= ~DBCR0_IDM; | 1495 | child->thread.debug.dbcr0 &= ~DBCR0_IDM; |
1495 | child->thread.regs->msr &= ~MSR_DE; | 1496 | child->thread.regs->msr &= ~MSR_DE; |
1496 | } | 1497 | } |
1497 | } | 1498 | } |
@@ -1554,10 +1555,10 @@ long arch_ptrace(struct task_struct *child, long request, | |||
1554 | 1555 | ||
1555 | flush_fp_to_thread(child); | 1556 | flush_fp_to_thread(child); |
1556 | if (fpidx < (PT_FPSCR - PT_FPR0)) | 1557 | if (fpidx < (PT_FPSCR - PT_FPR0)) |
1557 | tmp = ((unsigned long *)child->thread.fpr) | 1558 | memcpy(&tmp, &child->thread.fp_state.fpr, |
1558 | [fpidx * TS_FPRWIDTH]; | 1559 | sizeof(long)); |
1559 | else | 1560 | else |
1560 | tmp = child->thread.fpscr.val; | 1561 | tmp = child->thread.fp_state.fpscr; |
1561 | } | 1562 | } |
1562 | ret = put_user(tmp, datalp); | 1563 | ret = put_user(tmp, datalp); |
1563 | break; | 1564 | break; |
@@ -1587,10 +1588,10 @@ long arch_ptrace(struct task_struct *child, long request, | |||
1587 | 1588 | ||
1588 | flush_fp_to_thread(child); | 1589 | flush_fp_to_thread(child); |
1589 | if (fpidx < (PT_FPSCR - PT_FPR0)) | 1590 | if (fpidx < (PT_FPSCR - PT_FPR0)) |
1590 | ((unsigned long *)child->thread.fpr) | 1591 | memcpy(&child->thread.fp_state.fpr, &data, |
1591 | [fpidx * TS_FPRWIDTH] = data; | 1592 | sizeof(long)); |
1592 | else | 1593 | else |
1593 | child->thread.fpscr.val = data; | 1594 | child->thread.fp_state.fpscr = data; |
1594 | ret = 0; | 1595 | ret = 0; |
1595 | } | 1596 | } |
1596 | break; | 1597 | break; |
@@ -1669,7 +1670,7 @@ long arch_ptrace(struct task_struct *child, long request, | |||
1669 | if (addr > 0) | 1670 | if (addr > 0) |
1670 | break; | 1671 | break; |
1671 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | 1672 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS |
1672 | ret = put_user(child->thread.dac1, datalp); | 1673 | ret = put_user(child->thread.debug.dac1, datalp); |
1673 | #else | 1674 | #else |
1674 | dabr_fake = ((child->thread.hw_brk.address & (~HW_BRK_TYPE_DABR)) | | 1675 | dabr_fake = ((child->thread.hw_brk.address & (~HW_BRK_TYPE_DABR)) | |
1675 | (child->thread.hw_brk.type & HW_BRK_TYPE_DABR)); | 1676 | (child->thread.hw_brk.type & HW_BRK_TYPE_DABR)); |
diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c index f51599e941c7..f52b7db327c8 100644 --- a/arch/powerpc/kernel/ptrace32.c +++ b/arch/powerpc/kernel/ptrace32.c | |||
@@ -43,7 +43,6 @@ | |||
43 | #define FPRNUMBER(i) (((i) - PT_FPR0) >> 1) | 43 | #define FPRNUMBER(i) (((i) - PT_FPR0) >> 1) |
44 | #define FPRHALF(i) (((i) - PT_FPR0) & 1) | 44 | #define FPRHALF(i) (((i) - PT_FPR0) & 1) |
45 | #define FPRINDEX(i) TS_FPRWIDTH * FPRNUMBER(i) * 2 + FPRHALF(i) | 45 | #define FPRINDEX(i) TS_FPRWIDTH * FPRNUMBER(i) * 2 + FPRHALF(i) |
46 | #define FPRINDEX_3264(i) (TS_FPRWIDTH * ((i) - PT_FPR0)) | ||
47 | 46 | ||
48 | long compat_arch_ptrace(struct task_struct *child, compat_long_t request, | 47 | long compat_arch_ptrace(struct task_struct *child, compat_long_t request, |
49 | compat_ulong_t caddr, compat_ulong_t cdata) | 48 | compat_ulong_t caddr, compat_ulong_t cdata) |
@@ -105,7 +104,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, | |||
105 | * to be an array of unsigned int (32 bits) - the | 104 | * to be an array of unsigned int (32 bits) - the |
106 | * index passed in is based on this assumption. | 105 | * index passed in is based on this assumption. |
107 | */ | 106 | */ |
108 | tmp = ((unsigned int *)child->thread.fpr) | 107 | tmp = ((unsigned int *)child->thread.fp_state.fpr) |
109 | [FPRINDEX(index)]; | 108 | [FPRINDEX(index)]; |
110 | } | 109 | } |
111 | ret = put_user((unsigned int)tmp, (u32 __user *)data); | 110 | ret = put_user((unsigned int)tmp, (u32 __user *)data); |
@@ -147,8 +146,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, | |||
147 | if (numReg >= PT_FPR0) { | 146 | if (numReg >= PT_FPR0) { |
148 | flush_fp_to_thread(child); | 147 | flush_fp_to_thread(child); |
149 | /* get 64 bit FPR */ | 148 | /* get 64 bit FPR */ |
150 | tmp = ((u64 *)child->thread.fpr) | 149 | tmp = child->thread.fp_state.fpr[numReg - PT_FPR0][0]; |
151 | [FPRINDEX_3264(numReg)]; | ||
152 | } else { /* register within PT_REGS struct */ | 150 | } else { /* register within PT_REGS struct */ |
153 | unsigned long tmp2; | 151 | unsigned long tmp2; |
154 | ret = ptrace_get_reg(child, numReg, &tmp2); | 152 | ret = ptrace_get_reg(child, numReg, &tmp2); |
@@ -207,7 +205,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, | |||
207 | * to be an array of unsigned int (32 bits) - the | 205 | * to be an array of unsigned int (32 bits) - the |
208 | * index passed in is based on this assumption. | 206 | * index passed in is based on this assumption. |
209 | */ | 207 | */ |
210 | ((unsigned int *)child->thread.fpr) | 208 | ((unsigned int *)child->thread.fp_state.fpr) |
211 | [FPRINDEX(index)] = data; | 209 | [FPRINDEX(index)] = data; |
212 | ret = 0; | 210 | ret = 0; |
213 | } | 211 | } |
@@ -251,8 +249,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, | |||
251 | u64 *tmp; | 249 | u64 *tmp; |
252 | flush_fp_to_thread(child); | 250 | flush_fp_to_thread(child); |
253 | /* get 64 bit FPR ... */ | 251 | /* get 64 bit FPR ... */ |
254 | tmp = &(((u64 *)child->thread.fpr) | 252 | tmp = &child->thread.fp_state.fpr[numReg - PT_FPR0][0]; |
255 | [FPRINDEX_3264(numReg)]); | ||
256 | /* ... write the 32 bit part we want */ | 253 | /* ... write the 32 bit part we want */ |
257 | ((u32 *)tmp)[index % 2] = data; | 254 | ((u32 *)tmp)[index % 2] = data; |
258 | ret = 0; | 255 | ret = 0; |
@@ -269,7 +266,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, | |||
269 | if (addr > 0) | 266 | if (addr > 0) |
270 | break; | 267 | break; |
271 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | 268 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS |
272 | ret = put_user(child->thread.dac1, (u32 __user *)data); | 269 | ret = put_user(child->thread.debug.dac1, (u32 __user *)data); |
273 | #else | 270 | #else |
274 | dabr_fake = ( | 271 | dabr_fake = ( |
275 | (child->thread.hw_brk.address & (~HW_BRK_TYPE_DABR)) | | 272 | (child->thread.hw_brk.address & (~HW_BRK_TYPE_DABR)) | |
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c index 6e7b7cdeec65..7d4c7172f38e 100644 --- a/arch/powerpc/kernel/rtas_pci.c +++ b/arch/powerpc/kernel/rtas_pci.c | |||
@@ -223,7 +223,7 @@ unsigned long get_phb_buid(struct device_node *phb) | |||
223 | static int phb_set_bus_ranges(struct device_node *dev, | 223 | static int phb_set_bus_ranges(struct device_node *dev, |
224 | struct pci_controller *phb) | 224 | struct pci_controller *phb) |
225 | { | 225 | { |
226 | const int *bus_range; | 226 | const __be32 *bus_range; |
227 | unsigned int len; | 227 | unsigned int len; |
228 | 228 | ||
229 | bus_range = of_get_property(dev, "bus-range", &len); | 229 | bus_range = of_get_property(dev, "bus-range", &len); |
@@ -231,8 +231,8 @@ static int phb_set_bus_ranges(struct device_node *dev, | |||
231 | return 1; | 231 | return 1; |
232 | } | 232 | } |
233 | 233 | ||
234 | phb->first_busno = bus_range[0]; | 234 | phb->first_busno = be32_to_cpu(bus_range[0]); |
235 | phb->last_busno = bus_range[1]; | 235 | phb->last_busno = be32_to_cpu(bus_range[1]); |
236 | 236 | ||
237 | return 0; | 237 | return 0; |
238 | } | 238 | } |
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 3d261c071fc8..febc80445d25 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c | |||
@@ -62,8 +62,6 @@ | |||
62 | #include <mm/mmu_decl.h> | 62 | #include <mm/mmu_decl.h> |
63 | #include <asm/fadump.h> | 63 | #include <asm/fadump.h> |
64 | 64 | ||
65 | #include "setup.h" | ||
66 | |||
67 | #ifdef DEBUG | 65 | #ifdef DEBUG |
68 | #include <asm/udbg.h> | 66 | #include <asm/udbg.h> |
69 | #define DBG(fmt...) udbg_printf(fmt) | 67 | #define DBG(fmt...) udbg_printf(fmt) |
diff --git a/arch/powerpc/kernel/setup.h b/arch/powerpc/kernel/setup.h deleted file mode 100644 index 4c67ad7fae08..000000000000 --- a/arch/powerpc/kernel/setup.h +++ /dev/null | |||
@@ -1,9 +0,0 @@ | |||
1 | #ifndef _POWERPC_KERNEL_SETUP_H | ||
2 | #define _POWERPC_KERNEL_SETUP_H | ||
3 | |||
4 | void check_for_initrd(void); | ||
5 | void do_init_bootmem(void); | ||
6 | void setup_panic(void); | ||
7 | extern int do_early_xmon; | ||
8 | |||
9 | #endif /* _POWERPC_KERNEL_SETUP_H */ | ||
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index a4bbcae72578..b903dc5cf944 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c | |||
@@ -40,8 +40,6 @@ | |||
40 | #include <asm/mmu_context.h> | 40 | #include <asm/mmu_context.h> |
41 | #include <asm/epapr_hcalls.h> | 41 | #include <asm/epapr_hcalls.h> |
42 | 42 | ||
43 | #include "setup.h" | ||
44 | |||
45 | #define DBG(fmt...) | 43 | #define DBG(fmt...) |
46 | 44 | ||
47 | extern void bootx_init(unsigned long r4, unsigned long phys); | 45 | extern void bootx_init(unsigned long r4, unsigned long phys); |
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 278ca93e1f28..4085aaa9478f 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
@@ -68,8 +68,6 @@ | |||
68 | #include <asm/hugetlb.h> | 68 | #include <asm/hugetlb.h> |
69 | #include <asm/epapr_hcalls.h> | 69 | #include <asm/epapr_hcalls.h> |
70 | 70 | ||
71 | #include "setup.h" | ||
72 | |||
73 | #ifdef DEBUG | 71 | #ifdef DEBUG |
74 | #define DBG(fmt...) udbg_printf(fmt) | 72 | #define DBG(fmt...) udbg_printf(fmt) |
75 | #else | 73 | #else |
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index bebdf1a1a540..749778e0a69d 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c | |||
@@ -265,27 +265,27 @@ struct rt_sigframe { | |||
265 | unsigned long copy_fpr_to_user(void __user *to, | 265 | unsigned long copy_fpr_to_user(void __user *to, |
266 | struct task_struct *task) | 266 | struct task_struct *task) |
267 | { | 267 | { |
268 | double buf[ELF_NFPREG]; | 268 | u64 buf[ELF_NFPREG]; |
269 | int i; | 269 | int i; |
270 | 270 | ||
271 | /* save FPR copy to local buffer then write to the thread_struct */ | 271 | /* save FPR copy to local buffer then write to the thread_struct */ |
272 | for (i = 0; i < (ELF_NFPREG - 1) ; i++) | 272 | for (i = 0; i < (ELF_NFPREG - 1) ; i++) |
273 | buf[i] = task->thread.TS_FPR(i); | 273 | buf[i] = task->thread.TS_FPR(i); |
274 | memcpy(&buf[i], &task->thread.fpscr, sizeof(double)); | 274 | buf[i] = task->thread.fp_state.fpscr; |
275 | return __copy_to_user(to, buf, ELF_NFPREG * sizeof(double)); | 275 | return __copy_to_user(to, buf, ELF_NFPREG * sizeof(double)); |
276 | } | 276 | } |
277 | 277 | ||
278 | unsigned long copy_fpr_from_user(struct task_struct *task, | 278 | unsigned long copy_fpr_from_user(struct task_struct *task, |
279 | void __user *from) | 279 | void __user *from) |
280 | { | 280 | { |
281 | double buf[ELF_NFPREG]; | 281 | u64 buf[ELF_NFPREG]; |
282 | int i; | 282 | int i; |
283 | 283 | ||
284 | if (__copy_from_user(buf, from, ELF_NFPREG * sizeof(double))) | 284 | if (__copy_from_user(buf, from, ELF_NFPREG * sizeof(double))) |
285 | return 1; | 285 | return 1; |
286 | for (i = 0; i < (ELF_NFPREG - 1) ; i++) | 286 | for (i = 0; i < (ELF_NFPREG - 1) ; i++) |
287 | task->thread.TS_FPR(i) = buf[i]; | 287 | task->thread.TS_FPR(i) = buf[i]; |
288 | memcpy(&task->thread.fpscr, &buf[i], sizeof(double)); | 288 | task->thread.fp_state.fpscr = buf[i]; |
289 | 289 | ||
290 | return 0; | 290 | return 0; |
291 | } | 291 | } |
@@ -293,25 +293,25 @@ unsigned long copy_fpr_from_user(struct task_struct *task, | |||
293 | unsigned long copy_vsx_to_user(void __user *to, | 293 | unsigned long copy_vsx_to_user(void __user *to, |
294 | struct task_struct *task) | 294 | struct task_struct *task) |
295 | { | 295 | { |
296 | double buf[ELF_NVSRHALFREG]; | 296 | u64 buf[ELF_NVSRHALFREG]; |
297 | int i; | 297 | int i; |
298 | 298 | ||
299 | /* save FPR copy to local buffer then write to the thread_struct */ | 299 | /* save FPR copy to local buffer then write to the thread_struct */ |
300 | for (i = 0; i < ELF_NVSRHALFREG; i++) | 300 | for (i = 0; i < ELF_NVSRHALFREG; i++) |
301 | buf[i] = task->thread.fpr[i][TS_VSRLOWOFFSET]; | 301 | buf[i] = task->thread.fp_state.fpr[i][TS_VSRLOWOFFSET]; |
302 | return __copy_to_user(to, buf, ELF_NVSRHALFREG * sizeof(double)); | 302 | return __copy_to_user(to, buf, ELF_NVSRHALFREG * sizeof(double)); |
303 | } | 303 | } |
304 | 304 | ||
305 | unsigned long copy_vsx_from_user(struct task_struct *task, | 305 | unsigned long copy_vsx_from_user(struct task_struct *task, |
306 | void __user *from) | 306 | void __user *from) |
307 | { | 307 | { |
308 | double buf[ELF_NVSRHALFREG]; | 308 | u64 buf[ELF_NVSRHALFREG]; |
309 | int i; | 309 | int i; |
310 | 310 | ||
311 | if (__copy_from_user(buf, from, ELF_NVSRHALFREG * sizeof(double))) | 311 | if (__copy_from_user(buf, from, ELF_NVSRHALFREG * sizeof(double))) |
312 | return 1; | 312 | return 1; |
313 | for (i = 0; i < ELF_NVSRHALFREG ; i++) | 313 | for (i = 0; i < ELF_NVSRHALFREG ; i++) |
314 | task->thread.fpr[i][TS_VSRLOWOFFSET] = buf[i]; | 314 | task->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = buf[i]; |
315 | return 0; | 315 | return 0; |
316 | } | 316 | } |
317 | 317 | ||
@@ -319,27 +319,27 @@ unsigned long copy_vsx_from_user(struct task_struct *task, | |||
319 | unsigned long copy_transact_fpr_to_user(void __user *to, | 319 | unsigned long copy_transact_fpr_to_user(void __user *to, |
320 | struct task_struct *task) | 320 | struct task_struct *task) |
321 | { | 321 | { |
322 | double buf[ELF_NFPREG]; | 322 | u64 buf[ELF_NFPREG]; |
323 | int i; | 323 | int i; |
324 | 324 | ||
325 | /* save FPR copy to local buffer then write to the thread_struct */ | 325 | /* save FPR copy to local buffer then write to the thread_struct */ |
326 | for (i = 0; i < (ELF_NFPREG - 1) ; i++) | 326 | for (i = 0; i < (ELF_NFPREG - 1) ; i++) |
327 | buf[i] = task->thread.TS_TRANS_FPR(i); | 327 | buf[i] = task->thread.TS_TRANS_FPR(i); |
328 | memcpy(&buf[i], &task->thread.transact_fpscr, sizeof(double)); | 328 | buf[i] = task->thread.transact_fp.fpscr; |
329 | return __copy_to_user(to, buf, ELF_NFPREG * sizeof(double)); | 329 | return __copy_to_user(to, buf, ELF_NFPREG * sizeof(double)); |
330 | } | 330 | } |
331 | 331 | ||
332 | unsigned long copy_transact_fpr_from_user(struct task_struct *task, | 332 | unsigned long copy_transact_fpr_from_user(struct task_struct *task, |
333 | void __user *from) | 333 | void __user *from) |
334 | { | 334 | { |
335 | double buf[ELF_NFPREG]; | 335 | u64 buf[ELF_NFPREG]; |
336 | int i; | 336 | int i; |
337 | 337 | ||
338 | if (__copy_from_user(buf, from, ELF_NFPREG * sizeof(double))) | 338 | if (__copy_from_user(buf, from, ELF_NFPREG * sizeof(double))) |
339 | return 1; | 339 | return 1; |
340 | for (i = 0; i < (ELF_NFPREG - 1) ; i++) | 340 | for (i = 0; i < (ELF_NFPREG - 1) ; i++) |
341 | task->thread.TS_TRANS_FPR(i) = buf[i]; | 341 | task->thread.TS_TRANS_FPR(i) = buf[i]; |
342 | memcpy(&task->thread.transact_fpscr, &buf[i], sizeof(double)); | 342 | task->thread.transact_fp.fpscr = buf[i]; |
343 | 343 | ||
344 | return 0; | 344 | return 0; |
345 | } | 345 | } |
@@ -347,25 +347,25 @@ unsigned long copy_transact_fpr_from_user(struct task_struct *task, | |||
347 | unsigned long copy_transact_vsx_to_user(void __user *to, | 347 | unsigned long copy_transact_vsx_to_user(void __user *to, |
348 | struct task_struct *task) | 348 | struct task_struct *task) |
349 | { | 349 | { |
350 | double buf[ELF_NVSRHALFREG]; | 350 | u64 buf[ELF_NVSRHALFREG]; |
351 | int i; | 351 | int i; |
352 | 352 | ||
353 | /* save FPR copy to local buffer then write to the thread_struct */ | 353 | /* save FPR copy to local buffer then write to the thread_struct */ |
354 | for (i = 0; i < ELF_NVSRHALFREG; i++) | 354 | for (i = 0; i < ELF_NVSRHALFREG; i++) |
355 | buf[i] = task->thread.transact_fpr[i][TS_VSRLOWOFFSET]; | 355 | buf[i] = task->thread.transact_fp.fpr[i][TS_VSRLOWOFFSET]; |
356 | return __copy_to_user(to, buf, ELF_NVSRHALFREG * sizeof(double)); | 356 | return __copy_to_user(to, buf, ELF_NVSRHALFREG * sizeof(double)); |
357 | } | 357 | } |
358 | 358 | ||
359 | unsigned long copy_transact_vsx_from_user(struct task_struct *task, | 359 | unsigned long copy_transact_vsx_from_user(struct task_struct *task, |
360 | void __user *from) | 360 | void __user *from) |
361 | { | 361 | { |
362 | double buf[ELF_NVSRHALFREG]; | 362 | u64 buf[ELF_NVSRHALFREG]; |
363 | int i; | 363 | int i; |
364 | 364 | ||
365 | if (__copy_from_user(buf, from, ELF_NVSRHALFREG * sizeof(double))) | 365 | if (__copy_from_user(buf, from, ELF_NVSRHALFREG * sizeof(double))) |
366 | return 1; | 366 | return 1; |
367 | for (i = 0; i < ELF_NVSRHALFREG ; i++) | 367 | for (i = 0; i < ELF_NVSRHALFREG ; i++) |
368 | task->thread.transact_fpr[i][TS_VSRLOWOFFSET] = buf[i]; | 368 | task->thread.transact_fp.fpr[i][TS_VSRLOWOFFSET] = buf[i]; |
369 | return 0; | 369 | return 0; |
370 | } | 370 | } |
371 | #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ | 371 | #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ |
@@ -373,14 +373,14 @@ unsigned long copy_transact_vsx_from_user(struct task_struct *task, | |||
373 | inline unsigned long copy_fpr_to_user(void __user *to, | 373 | inline unsigned long copy_fpr_to_user(void __user *to, |
374 | struct task_struct *task) | 374 | struct task_struct *task) |
375 | { | 375 | { |
376 | return __copy_to_user(to, task->thread.fpr, | 376 | return __copy_to_user(to, task->thread.fp_state.fpr, |
377 | ELF_NFPREG * sizeof(double)); | 377 | ELF_NFPREG * sizeof(double)); |
378 | } | 378 | } |
379 | 379 | ||
380 | inline unsigned long copy_fpr_from_user(struct task_struct *task, | 380 | inline unsigned long copy_fpr_from_user(struct task_struct *task, |
381 | void __user *from) | 381 | void __user *from) |
382 | { | 382 | { |
383 | return __copy_from_user(task->thread.fpr, from, | 383 | return __copy_from_user(task->thread.fp_state.fpr, from, |
384 | ELF_NFPREG * sizeof(double)); | 384 | ELF_NFPREG * sizeof(double)); |
385 | } | 385 | } |
386 | 386 | ||
@@ -388,14 +388,14 @@ inline unsigned long copy_fpr_from_user(struct task_struct *task, | |||
388 | inline unsigned long copy_transact_fpr_to_user(void __user *to, | 388 | inline unsigned long copy_transact_fpr_to_user(void __user *to, |
389 | struct task_struct *task) | 389 | struct task_struct *task) |
390 | { | 390 | { |
391 | return __copy_to_user(to, task->thread.transact_fpr, | 391 | return __copy_to_user(to, task->thread.transact_fp.fpr, |
392 | ELF_NFPREG * sizeof(double)); | 392 | ELF_NFPREG * sizeof(double)); |
393 | } | 393 | } |
394 | 394 | ||
395 | inline unsigned long copy_transact_fpr_from_user(struct task_struct *task, | 395 | inline unsigned long copy_transact_fpr_from_user(struct task_struct *task, |
396 | void __user *from) | 396 | void __user *from) |
397 | { | 397 | { |
398 | return __copy_from_user(task->thread.transact_fpr, from, | 398 | return __copy_from_user(task->thread.transact_fp.fpr, from, |
399 | ELF_NFPREG * sizeof(double)); | 399 | ELF_NFPREG * sizeof(double)); |
400 | } | 400 | } |
401 | #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ | 401 | #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ |
@@ -423,7 +423,7 @@ static int save_user_regs(struct pt_regs *regs, struct mcontext __user *frame, | |||
423 | /* save altivec registers */ | 423 | /* save altivec registers */ |
424 | if (current->thread.used_vr) { | 424 | if (current->thread.used_vr) { |
425 | flush_altivec_to_thread(current); | 425 | flush_altivec_to_thread(current); |
426 | if (__copy_to_user(&frame->mc_vregs, current->thread.vr, | 426 | if (__copy_to_user(&frame->mc_vregs, ¤t->thread.vr_state, |
427 | ELF_NVRREG * sizeof(vector128))) | 427 | ELF_NVRREG * sizeof(vector128))) |
428 | return 1; | 428 | return 1; |
429 | /* set MSR_VEC in the saved MSR value to indicate that | 429 | /* set MSR_VEC in the saved MSR value to indicate that |
@@ -534,17 +534,17 @@ static int save_tm_user_regs(struct pt_regs *regs, | |||
534 | /* save altivec registers */ | 534 | /* save altivec registers */ |
535 | if (current->thread.used_vr) { | 535 | if (current->thread.used_vr) { |
536 | flush_altivec_to_thread(current); | 536 | flush_altivec_to_thread(current); |
537 | if (__copy_to_user(&frame->mc_vregs, current->thread.vr, | 537 | if (__copy_to_user(&frame->mc_vregs, ¤t->thread.vr_state, |
538 | ELF_NVRREG * sizeof(vector128))) | 538 | ELF_NVRREG * sizeof(vector128))) |
539 | return 1; | 539 | return 1; |
540 | if (msr & MSR_VEC) { | 540 | if (msr & MSR_VEC) { |
541 | if (__copy_to_user(&tm_frame->mc_vregs, | 541 | if (__copy_to_user(&tm_frame->mc_vregs, |
542 | current->thread.transact_vr, | 542 | ¤t->thread.transact_vr, |
543 | ELF_NVRREG * sizeof(vector128))) | 543 | ELF_NVRREG * sizeof(vector128))) |
544 | return 1; | 544 | return 1; |
545 | } else { | 545 | } else { |
546 | if (__copy_to_user(&tm_frame->mc_vregs, | 546 | if (__copy_to_user(&tm_frame->mc_vregs, |
547 | current->thread.vr, | 547 | ¤t->thread.vr_state, |
548 | ELF_NVRREG * sizeof(vector128))) | 548 | ELF_NVRREG * sizeof(vector128))) |
549 | return 1; | 549 | return 1; |
550 | } | 550 | } |
@@ -692,11 +692,12 @@ static long restore_user_regs(struct pt_regs *regs, | |||
692 | regs->msr &= ~MSR_VEC; | 692 | regs->msr &= ~MSR_VEC; |
693 | if (msr & MSR_VEC) { | 693 | if (msr & MSR_VEC) { |
694 | /* restore altivec registers from the stack */ | 694 | /* restore altivec registers from the stack */ |
695 | if (__copy_from_user(current->thread.vr, &sr->mc_vregs, | 695 | if (__copy_from_user(¤t->thread.vr_state, &sr->mc_vregs, |
696 | sizeof(sr->mc_vregs))) | 696 | sizeof(sr->mc_vregs))) |
697 | return 1; | 697 | return 1; |
698 | } else if (current->thread.used_vr) | 698 | } else if (current->thread.used_vr) |
699 | memset(current->thread.vr, 0, ELF_NVRREG * sizeof(vector128)); | 699 | memset(¤t->thread.vr_state, 0, |
700 | ELF_NVRREG * sizeof(vector128)); | ||
700 | 701 | ||
701 | /* Always get VRSAVE back */ | 702 | /* Always get VRSAVE back */ |
702 | if (__get_user(current->thread.vrsave, (u32 __user *)&sr->mc_vregs[32])) | 703 | if (__get_user(current->thread.vrsave, (u32 __user *)&sr->mc_vregs[32])) |
@@ -722,7 +723,7 @@ static long restore_user_regs(struct pt_regs *regs, | |||
722 | return 1; | 723 | return 1; |
723 | } else if (current->thread.used_vsr) | 724 | } else if (current->thread.used_vsr) |
724 | for (i = 0; i < 32 ; i++) | 725 | for (i = 0; i < 32 ; i++) |
725 | current->thread.fpr[i][TS_VSRLOWOFFSET] = 0; | 726 | current->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = 0; |
726 | #endif /* CONFIG_VSX */ | 727 | #endif /* CONFIG_VSX */ |
727 | /* | 728 | /* |
728 | * force the process to reload the FP registers from | 729 | * force the process to reload the FP registers from |
@@ -798,15 +799,16 @@ static long restore_tm_user_regs(struct pt_regs *regs, | |||
798 | regs->msr &= ~MSR_VEC; | 799 | regs->msr &= ~MSR_VEC; |
799 | if (msr & MSR_VEC) { | 800 | if (msr & MSR_VEC) { |
800 | /* restore altivec registers from the stack */ | 801 | /* restore altivec registers from the stack */ |
801 | if (__copy_from_user(current->thread.vr, &sr->mc_vregs, | 802 | if (__copy_from_user(¤t->thread.vr_state, &sr->mc_vregs, |
802 | sizeof(sr->mc_vregs)) || | 803 | sizeof(sr->mc_vregs)) || |
803 | __copy_from_user(current->thread.transact_vr, | 804 | __copy_from_user(¤t->thread.transact_vr, |
804 | &tm_sr->mc_vregs, | 805 | &tm_sr->mc_vregs, |
805 | sizeof(sr->mc_vregs))) | 806 | sizeof(sr->mc_vregs))) |
806 | return 1; | 807 | return 1; |
807 | } else if (current->thread.used_vr) { | 808 | } else if (current->thread.used_vr) { |
808 | memset(current->thread.vr, 0, ELF_NVRREG * sizeof(vector128)); | 809 | memset(¤t->thread.vr_state, 0, |
809 | memset(current->thread.transact_vr, 0, | 810 | ELF_NVRREG * sizeof(vector128)); |
811 | memset(¤t->thread.transact_vr, 0, | ||
810 | ELF_NVRREG * sizeof(vector128)); | 812 | ELF_NVRREG * sizeof(vector128)); |
811 | } | 813 | } |
812 | 814 | ||
@@ -838,8 +840,8 @@ static long restore_tm_user_regs(struct pt_regs *regs, | |||
838 | return 1; | 840 | return 1; |
839 | } else if (current->thread.used_vsr) | 841 | } else if (current->thread.used_vsr) |
840 | for (i = 0; i < 32 ; i++) { | 842 | for (i = 0; i < 32 ; i++) { |
841 | current->thread.fpr[i][TS_VSRLOWOFFSET] = 0; | 843 | current->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = 0; |
842 | current->thread.transact_fpr[i][TS_VSRLOWOFFSET] = 0; | 844 | current->thread.transact_fp.fpr[i][TS_VSRLOWOFFSET] = 0; |
843 | } | 845 | } |
844 | #endif /* CONFIG_VSX */ | 846 | #endif /* CONFIG_VSX */ |
845 | 847 | ||
@@ -891,7 +893,7 @@ static long restore_tm_user_regs(struct pt_regs *regs, | |||
891 | #endif | 893 | #endif |
892 | 894 | ||
893 | #ifdef CONFIG_PPC64 | 895 | #ifdef CONFIG_PPC64 |
894 | int copy_siginfo_to_user32(struct compat_siginfo __user *d, siginfo_t *s) | 896 | int copy_siginfo_to_user32(struct compat_siginfo __user *d, const siginfo_t *s) |
895 | { | 897 | { |
896 | int err; | 898 | int err; |
897 | 899 | ||
@@ -1030,7 +1032,7 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, | |||
1030 | if (__put_user(0, &rt_sf->uc.uc_link)) | 1032 | if (__put_user(0, &rt_sf->uc.uc_link)) |
1031 | goto badframe; | 1033 | goto badframe; |
1032 | 1034 | ||
1033 | current->thread.fpscr.val = 0; /* turn off all fp exceptions */ | 1035 | current->thread.fp_state.fpscr = 0; /* turn off all fp exceptions */ |
1034 | 1036 | ||
1035 | /* create a stack frame for the caller of the handler */ | 1037 | /* create a stack frame for the caller of the handler */ |
1036 | newsp = ((unsigned long)rt_sf) - (__SIGNAL_FRAMESIZE + 16); | 1038 | newsp = ((unsigned long)rt_sf) - (__SIGNAL_FRAMESIZE + 16); |
@@ -1045,8 +1047,9 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, | |||
1045 | regs->gpr[5] = (unsigned long) &rt_sf->uc; | 1047 | regs->gpr[5] = (unsigned long) &rt_sf->uc; |
1046 | regs->gpr[6] = (unsigned long) rt_sf; | 1048 | regs->gpr[6] = (unsigned long) rt_sf; |
1047 | regs->nip = (unsigned long) ka->sa.sa_handler; | 1049 | regs->nip = (unsigned long) ka->sa.sa_handler; |
1048 | /* enter the signal handler in big-endian mode */ | 1050 | /* enter the signal handler in native-endian mode */ |
1049 | regs->msr &= ~MSR_LE; | 1051 | regs->msr &= ~MSR_LE; |
1052 | regs->msr |= (MSR_KERNEL & MSR_LE); | ||
1050 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | 1053 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM |
1051 | /* Remove TM bits from thread's MSR. The MSR in the sigcontext | 1054 | /* Remove TM bits from thread's MSR. The MSR in the sigcontext |
1052 | * just indicates to userland that we were doing a transaction, but we | 1055 | * just indicates to userland that we were doing a transaction, but we |
@@ -1309,7 +1312,7 @@ int sys_debug_setcontext(struct ucontext __user *ctx, | |||
1309 | unsigned char tmp; | 1312 | unsigned char tmp; |
1310 | unsigned long new_msr = regs->msr; | 1313 | unsigned long new_msr = regs->msr; |
1311 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | 1314 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS |
1312 | unsigned long new_dbcr0 = current->thread.dbcr0; | 1315 | unsigned long new_dbcr0 = current->thread.debug.dbcr0; |
1313 | #endif | 1316 | #endif |
1314 | 1317 | ||
1315 | for (i=0; i<ndbg; i++) { | 1318 | for (i=0; i<ndbg; i++) { |
@@ -1324,7 +1327,7 @@ int sys_debug_setcontext(struct ucontext __user *ctx, | |||
1324 | } else { | 1327 | } else { |
1325 | new_dbcr0 &= ~DBCR0_IC; | 1328 | new_dbcr0 &= ~DBCR0_IC; |
1326 | if (!DBCR_ACTIVE_EVENTS(new_dbcr0, | 1329 | if (!DBCR_ACTIVE_EVENTS(new_dbcr0, |
1327 | current->thread.dbcr1)) { | 1330 | current->thread.debug.dbcr1)) { |
1328 | new_msr &= ~MSR_DE; | 1331 | new_msr &= ~MSR_DE; |
1329 | new_dbcr0 &= ~DBCR0_IDM; | 1332 | new_dbcr0 &= ~DBCR0_IDM; |
1330 | } | 1333 | } |
@@ -1359,7 +1362,7 @@ int sys_debug_setcontext(struct ucontext __user *ctx, | |||
1359 | the user is really doing something wrong. */ | 1362 | the user is really doing something wrong. */ |
1360 | regs->msr = new_msr; | 1363 | regs->msr = new_msr; |
1361 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS | 1364 | #ifdef CONFIG_PPC_ADV_DEBUG_REGS |
1362 | current->thread.dbcr0 = new_dbcr0; | 1365 | current->thread.debug.dbcr0 = new_dbcr0; |
1363 | #endif | 1366 | #endif |
1364 | 1367 | ||
1365 | if (!access_ok(VERIFY_READ, ctx, sizeof(*ctx)) | 1368 | if (!access_ok(VERIFY_READ, ctx, sizeof(*ctx)) |
@@ -1462,7 +1465,7 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka, | |||
1462 | 1465 | ||
1463 | regs->link = tramp; | 1466 | regs->link = tramp; |
1464 | 1467 | ||
1465 | current->thread.fpscr.val = 0; /* turn off all fp exceptions */ | 1468 | current->thread.fp_state.fpscr = 0; /* turn off all fp exceptions */ |
1466 | 1469 | ||
1467 | /* create a stack frame for the caller of the handler */ | 1470 | /* create a stack frame for the caller of the handler */ |
1468 | newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE; | 1471 | newsp = ((unsigned long)frame) - __SIGNAL_FRAMESIZE; |
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index f93ec2835a13..b3c615764c9b 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c | |||
@@ -103,7 +103,8 @@ static long setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, | |||
103 | if (current->thread.used_vr) { | 103 | if (current->thread.used_vr) { |
104 | flush_altivec_to_thread(current); | 104 | flush_altivec_to_thread(current); |
105 | /* Copy 33 vec registers (vr0..31 and vscr) to the stack */ | 105 | /* Copy 33 vec registers (vr0..31 and vscr) to the stack */ |
106 | err |= __copy_to_user(v_regs, current->thread.vr, 33 * sizeof(vector128)); | 106 | err |= __copy_to_user(v_regs, ¤t->thread.vr_state, |
107 | 33 * sizeof(vector128)); | ||
107 | /* set MSR_VEC in the MSR value in the frame to indicate that sc->v_reg) | 108 | /* set MSR_VEC in the MSR value in the frame to indicate that sc->v_reg) |
108 | * contains valid data. | 109 | * contains valid data. |
109 | */ | 110 | */ |
@@ -195,18 +196,18 @@ static long setup_tm_sigcontexts(struct sigcontext __user *sc, | |||
195 | if (current->thread.used_vr) { | 196 | if (current->thread.used_vr) { |
196 | flush_altivec_to_thread(current); | 197 | flush_altivec_to_thread(current); |
197 | /* Copy 33 vec registers (vr0..31 and vscr) to the stack */ | 198 | /* Copy 33 vec registers (vr0..31 and vscr) to the stack */ |
198 | err |= __copy_to_user(v_regs, current->thread.vr, | 199 | err |= __copy_to_user(v_regs, ¤t->thread.vr_state, |
199 | 33 * sizeof(vector128)); | 200 | 33 * sizeof(vector128)); |
200 | /* If VEC was enabled there are transactional VRs valid too, | 201 | /* If VEC was enabled there are transactional VRs valid too, |
201 | * else they're a copy of the checkpointed VRs. | 202 | * else they're a copy of the checkpointed VRs. |
202 | */ | 203 | */ |
203 | if (msr & MSR_VEC) | 204 | if (msr & MSR_VEC) |
204 | err |= __copy_to_user(tm_v_regs, | 205 | err |= __copy_to_user(tm_v_regs, |
205 | current->thread.transact_vr, | 206 | ¤t->thread.transact_vr, |
206 | 33 * sizeof(vector128)); | 207 | 33 * sizeof(vector128)); |
207 | else | 208 | else |
208 | err |= __copy_to_user(tm_v_regs, | 209 | err |= __copy_to_user(tm_v_regs, |
209 | current->thread.vr, | 210 | ¤t->thread.vr_state, |
210 | 33 * sizeof(vector128)); | 211 | 33 * sizeof(vector128)); |
211 | 212 | ||
212 | /* set MSR_VEC in the MSR value in the frame to indicate | 213 | /* set MSR_VEC in the MSR value in the frame to indicate |
@@ -349,10 +350,10 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig, | |||
349 | return -EFAULT; | 350 | return -EFAULT; |
350 | /* Copy 33 vec registers (vr0..31 and vscr) from the stack */ | 351 | /* Copy 33 vec registers (vr0..31 and vscr) from the stack */ |
351 | if (v_regs != NULL && (msr & MSR_VEC) != 0) | 352 | if (v_regs != NULL && (msr & MSR_VEC) != 0) |
352 | err |= __copy_from_user(current->thread.vr, v_regs, | 353 | err |= __copy_from_user(¤t->thread.vr_state, v_regs, |
353 | 33 * sizeof(vector128)); | 354 | 33 * sizeof(vector128)); |
354 | else if (current->thread.used_vr) | 355 | else if (current->thread.used_vr) |
355 | memset(current->thread.vr, 0, 33 * sizeof(vector128)); | 356 | memset(¤t->thread.vr_state, 0, 33 * sizeof(vector128)); |
356 | /* Always get VRSAVE back */ | 357 | /* Always get VRSAVE back */ |
357 | if (v_regs != NULL) | 358 | if (v_regs != NULL) |
358 | err |= __get_user(current->thread.vrsave, (u32 __user *)&v_regs[33]); | 359 | err |= __get_user(current->thread.vrsave, (u32 __user *)&v_regs[33]); |
@@ -374,7 +375,7 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig, | |||
374 | err |= copy_vsx_from_user(current, v_regs); | 375 | err |= copy_vsx_from_user(current, v_regs); |
375 | else | 376 | else |
376 | for (i = 0; i < 32 ; i++) | 377 | for (i = 0; i < 32 ; i++) |
377 | current->thread.fpr[i][TS_VSRLOWOFFSET] = 0; | 378 | current->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = 0; |
378 | #endif | 379 | #endif |
379 | return err; | 380 | return err; |
380 | } | 381 | } |
@@ -468,14 +469,14 @@ static long restore_tm_sigcontexts(struct pt_regs *regs, | |||
468 | return -EFAULT; | 469 | return -EFAULT; |
469 | /* Copy 33 vec registers (vr0..31 and vscr) from the stack */ | 470 | /* Copy 33 vec registers (vr0..31 and vscr) from the stack */ |
470 | if (v_regs != NULL && tm_v_regs != NULL && (msr & MSR_VEC) != 0) { | 471 | if (v_regs != NULL && tm_v_regs != NULL && (msr & MSR_VEC) != 0) { |
471 | err |= __copy_from_user(current->thread.vr, v_regs, | 472 | err |= __copy_from_user(¤t->thread.vr_state, v_regs, |
472 | 33 * sizeof(vector128)); | 473 | 33 * sizeof(vector128)); |
473 | err |= __copy_from_user(current->thread.transact_vr, tm_v_regs, | 474 | err |= __copy_from_user(¤t->thread.transact_vr, tm_v_regs, |
474 | 33 * sizeof(vector128)); | 475 | 33 * sizeof(vector128)); |
475 | } | 476 | } |
476 | else if (current->thread.used_vr) { | 477 | else if (current->thread.used_vr) { |
477 | memset(current->thread.vr, 0, 33 * sizeof(vector128)); | 478 | memset(¤t->thread.vr_state, 0, 33 * sizeof(vector128)); |
478 | memset(current->thread.transact_vr, 0, 33 * sizeof(vector128)); | 479 | memset(¤t->thread.transact_vr, 0, 33 * sizeof(vector128)); |
479 | } | 480 | } |
480 | /* Always get VRSAVE back */ | 481 | /* Always get VRSAVE back */ |
481 | if (v_regs != NULL && tm_v_regs != NULL) { | 482 | if (v_regs != NULL && tm_v_regs != NULL) { |
@@ -507,8 +508,8 @@ static long restore_tm_sigcontexts(struct pt_regs *regs, | |||
507 | err |= copy_transact_vsx_from_user(current, tm_v_regs); | 508 | err |= copy_transact_vsx_from_user(current, tm_v_regs); |
508 | } else { | 509 | } else { |
509 | for (i = 0; i < 32 ; i++) { | 510 | for (i = 0; i < 32 ; i++) { |
510 | current->thread.fpr[i][TS_VSRLOWOFFSET] = 0; | 511 | current->thread.fp_state.fpr[i][TS_VSRLOWOFFSET] = 0; |
511 | current->thread.transact_fpr[i][TS_VSRLOWOFFSET] = 0; | 512 | current->thread.transact_fp.fpr[i][TS_VSRLOWOFFSET] = 0; |
512 | } | 513 | } |
513 | } | 514 | } |
514 | #endif | 515 | #endif |
@@ -747,7 +748,7 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info, | |||
747 | goto badframe; | 748 | goto badframe; |
748 | 749 | ||
749 | /* Make sure signal handler doesn't get spurious FP exceptions */ | 750 | /* Make sure signal handler doesn't get spurious FP exceptions */ |
750 | current->thread.fpscr.val = 0; | 751 | current->thread.fp_state.fpscr = 0; |
751 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | 752 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM |
752 | /* Remove TM bits from thread's MSR. The MSR in the sigcontext | 753 | /* Remove TM bits from thread's MSR. The MSR in the sigcontext |
753 | * just indicates to userland that we were doing a transaction, but we | 754 | * just indicates to userland that we were doing a transaction, but we |
@@ -773,8 +774,9 @@ int handle_rt_signal64(int signr, struct k_sigaction *ka, siginfo_t *info, | |||
773 | 774 | ||
774 | /* Set up "regs" so we "return" to the signal handler. */ | 775 | /* Set up "regs" so we "return" to the signal handler. */ |
775 | err |= get_user(regs->nip, &funct_desc_ptr->entry); | 776 | err |= get_user(regs->nip, &funct_desc_ptr->entry); |
776 | /* enter the signal handler in big-endian mode */ | 777 | /* enter the signal handler in native-endian mode */ |
777 | regs->msr &= ~MSR_LE; | 778 | regs->msr &= ~MSR_LE; |
779 | regs->msr |= (MSR_KERNEL & MSR_LE); | ||
778 | regs->gpr[1] = newsp; | 780 | regs->gpr[1] = newsp; |
779 | err |= get_user(regs->gpr[2], &funct_desc_ptr->toc); | 781 | err |= get_user(regs->gpr[2], &funct_desc_ptr->toc); |
780 | regs->gpr[3] = signr; | 782 | regs->gpr[3] = signr; |
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 8e59abc237d7..930cd8af3503 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c | |||
@@ -844,18 +844,6 @@ void __cpu_die(unsigned int cpu) | |||
844 | smp_ops->cpu_die(cpu); | 844 | smp_ops->cpu_die(cpu); |
845 | } | 845 | } |
846 | 846 | ||
847 | static DEFINE_MUTEX(powerpc_cpu_hotplug_driver_mutex); | ||
848 | |||
849 | void cpu_hotplug_driver_lock() | ||
850 | { | ||
851 | mutex_lock(&powerpc_cpu_hotplug_driver_mutex); | ||
852 | } | ||
853 | |||
854 | void cpu_hotplug_driver_unlock() | ||
855 | { | ||
856 | mutex_unlock(&powerpc_cpu_hotplug_driver_mutex); | ||
857 | } | ||
858 | |||
859 | void cpu_die(void) | 847 | void cpu_die(void) |
860 | { | 848 | { |
861 | if (ppc_md.cpu_die) | 849 | if (ppc_md.cpu_die) |
diff --git a/arch/powerpc/kernel/swsusp_asm64.S b/arch/powerpc/kernel/swsusp_asm64.S index 22045984835f..988f38dced0f 100644 --- a/arch/powerpc/kernel/swsusp_asm64.S +++ b/arch/powerpc/kernel/swsusp_asm64.S | |||
@@ -114,7 +114,9 @@ _GLOBAL(swsusp_arch_suspend) | |||
114 | SAVE_SPECIAL(MSR) | 114 | SAVE_SPECIAL(MSR) |
115 | SAVE_SPECIAL(XER) | 115 | SAVE_SPECIAL(XER) |
116 | #ifdef CONFIG_PPC_BOOK3S_64 | 116 | #ifdef CONFIG_PPC_BOOK3S_64 |
117 | BEGIN_FW_FTR_SECTION | ||
117 | SAVE_SPECIAL(SDR1) | 118 | SAVE_SPECIAL(SDR1) |
119 | END_FW_FTR_SECTION_IFCLR(FW_FEATURE_LPAR) | ||
118 | #else | 120 | #else |
119 | SAVE_SPR(TCR) | 121 | SAVE_SPR(TCR) |
120 | 122 | ||
@@ -231,7 +233,9 @@ nothing_to_copy: | |||
231 | /* can't use RESTORE_SPECIAL(MSR) */ | 233 | /* can't use RESTORE_SPECIAL(MSR) */ |
232 | ld r0, SL_MSR(r11) | 234 | ld r0, SL_MSR(r11) |
233 | mtmsrd r0, 0 | 235 | mtmsrd r0, 0 |
236 | BEGIN_FW_FTR_SECTION | ||
234 | RESTORE_SPECIAL(SDR1) | 237 | RESTORE_SPECIAL(SDR1) |
238 | END_FW_FTR_SECTION_IFCLR(FW_FEATURE_LPAR) | ||
235 | #else | 239 | #else |
236 | /* Restore SPRG1, be used to save paca */ | 240 | /* Restore SPRG1, be used to save paca */ |
237 | ld r0, SL_SPRG1(r11) | 241 | ld r0, SL_SPRG1(r11) |
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index 27a90b99ef67..b4e667663d9b 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <asm/machdep.h> | 17 | #include <asm/machdep.h> |
18 | #include <asm/smp.h> | 18 | #include <asm/smp.h> |
19 | #include <asm/pmc.h> | 19 | #include <asm/pmc.h> |
20 | #include <asm/firmware.h> | ||
20 | 21 | ||
21 | #include "cacheinfo.h" | 22 | #include "cacheinfo.h" |
22 | 23 | ||
@@ -179,15 +180,25 @@ SYSFS_PMCSETUP(spurr, SPRN_SPURR); | |||
179 | SYSFS_PMCSETUP(dscr, SPRN_DSCR); | 180 | SYSFS_PMCSETUP(dscr, SPRN_DSCR); |
180 | SYSFS_PMCSETUP(pir, SPRN_PIR); | 181 | SYSFS_PMCSETUP(pir, SPRN_PIR); |
181 | 182 | ||
183 | /* | ||
184 | Lets only enable read for phyp resources and | ||
185 | enable write when needed with a separate function. | ||
186 | Lets be conservative and default to pseries. | ||
187 | */ | ||
182 | static DEVICE_ATTR(mmcra, 0600, show_mmcra, store_mmcra); | 188 | static DEVICE_ATTR(mmcra, 0600, show_mmcra, store_mmcra); |
183 | static DEVICE_ATTR(spurr, 0400, show_spurr, NULL); | 189 | static DEVICE_ATTR(spurr, 0400, show_spurr, NULL); |
184 | static DEVICE_ATTR(dscr, 0600, show_dscr, store_dscr); | 190 | static DEVICE_ATTR(dscr, 0600, show_dscr, store_dscr); |
185 | static DEVICE_ATTR(purr, 0600, show_purr, store_purr); | 191 | static DEVICE_ATTR(purr, 0400, show_purr, store_purr); |
186 | static DEVICE_ATTR(pir, 0400, show_pir, NULL); | 192 | static DEVICE_ATTR(pir, 0400, show_pir, NULL); |
187 | 193 | ||
188 | unsigned long dscr_default = 0; | 194 | unsigned long dscr_default = 0; |
189 | EXPORT_SYMBOL(dscr_default); | 195 | EXPORT_SYMBOL(dscr_default); |
190 | 196 | ||
197 | static void add_write_permission_dev_attr(struct device_attribute *attr) | ||
198 | { | ||
199 | attr->attr.mode |= 0200; | ||
200 | } | ||
201 | |||
191 | static ssize_t show_dscr_default(struct device *dev, | 202 | static ssize_t show_dscr_default(struct device *dev, |
192 | struct device_attribute *attr, char *buf) | 203 | struct device_attribute *attr, char *buf) |
193 | { | 204 | { |
@@ -394,8 +405,11 @@ static void register_cpu_online(unsigned int cpu) | |||
394 | if (cpu_has_feature(CPU_FTR_MMCRA)) | 405 | if (cpu_has_feature(CPU_FTR_MMCRA)) |
395 | device_create_file(s, &dev_attr_mmcra); | 406 | device_create_file(s, &dev_attr_mmcra); |
396 | 407 | ||
397 | if (cpu_has_feature(CPU_FTR_PURR)) | 408 | if (cpu_has_feature(CPU_FTR_PURR)) { |
409 | if (!firmware_has_feature(FW_FEATURE_LPAR)) | ||
410 | add_write_permission_dev_attr(&dev_attr_purr); | ||
398 | device_create_file(s, &dev_attr_purr); | 411 | device_create_file(s, &dev_attr_purr); |
412 | } | ||
399 | 413 | ||
400 | if (cpu_has_feature(CPU_FTR_SPURR)) | 414 | if (cpu_has_feature(CPU_FTR_SPURR)) |
401 | device_create_file(s, &dev_attr_spurr); | 415 | device_create_file(s, &dev_attr_spurr); |
diff --git a/arch/powerpc/kernel/tm.S b/arch/powerpc/kernel/tm.S index 7b60b9851469..ef47bcbd4352 100644 --- a/arch/powerpc/kernel/tm.S +++ b/arch/powerpc/kernel/tm.S | |||
@@ -12,16 +12,15 @@ | |||
12 | #include <asm/reg.h> | 12 | #include <asm/reg.h> |
13 | 13 | ||
14 | #ifdef CONFIG_VSX | 14 | #ifdef CONFIG_VSX |
15 | /* See fpu.S, this is very similar but to save/restore checkpointed FPRs/VSRs */ | 15 | /* See fpu.S, this is borrowed from there */ |
16 | #define __SAVE_32FPRS_VSRS_TRANSACT(n,c,base) \ | 16 | #define __SAVE_32FPRS_VSRS(n,c,base) \ |
17 | BEGIN_FTR_SECTION \ | 17 | BEGIN_FTR_SECTION \ |
18 | b 2f; \ | 18 | b 2f; \ |
19 | END_FTR_SECTION_IFSET(CPU_FTR_VSX); \ | 19 | END_FTR_SECTION_IFSET(CPU_FTR_VSX); \ |
20 | SAVE_32FPRS_TRANSACT(n,base); \ | 20 | SAVE_32FPRS(n,base); \ |
21 | b 3f; \ | 21 | b 3f; \ |
22 | 2: SAVE_32VSRS_TRANSACT(n,c,base); \ | 22 | 2: SAVE_32VSRS(n,c,base); \ |
23 | 3: | 23 | 3: |
24 | /* ...and this is just plain borrowed from there. */ | ||
25 | #define __REST_32FPRS_VSRS(n,c,base) \ | 24 | #define __REST_32FPRS_VSRS(n,c,base) \ |
26 | BEGIN_FTR_SECTION \ | 25 | BEGIN_FTR_SECTION \ |
27 | b 2f; \ | 26 | b 2f; \ |
@@ -31,11 +30,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX); \ | |||
31 | 2: REST_32VSRS(n,c,base); \ | 30 | 2: REST_32VSRS(n,c,base); \ |
32 | 3: | 31 | 3: |
33 | #else | 32 | #else |
34 | #define __SAVE_32FPRS_VSRS_TRANSACT(n,c,base) SAVE_32FPRS_TRANSACT(n, base) | 33 | #define __SAVE_32FPRS_VSRS(n,c,base) SAVE_32FPRS(n, base) |
35 | #define __REST_32FPRS_VSRS(n,c,base) REST_32FPRS(n, base) | 34 | #define __REST_32FPRS_VSRS(n,c,base) REST_32FPRS(n, base) |
36 | #endif | 35 | #endif |
37 | #define SAVE_32FPRS_VSRS_TRANSACT(n,c,base) \ | 36 | #define SAVE_32FPRS_VSRS(n,c,base) \ |
38 | __SAVE_32FPRS_VSRS_TRANSACT(n,__REG_##c,__REG_##base) | 37 | __SAVE_32FPRS_VSRS(n,__REG_##c,__REG_##base) |
39 | #define REST_32FPRS_VSRS(n,c,base) \ | 38 | #define REST_32FPRS_VSRS(n,c,base) \ |
40 | __REST_32FPRS_VSRS(n,__REG_##c,__REG_##base) | 39 | __REST_32FPRS_VSRS(n,__REG_##c,__REG_##base) |
41 | 40 | ||
@@ -79,6 +78,11 @@ _GLOBAL(tm_abort) | |||
79 | TABORT(R3) | 78 | TABORT(R3) |
80 | blr | 79 | blr |
81 | 80 | ||
81 | .section ".toc","aw" | ||
82 | DSCR_DEFAULT: | ||
83 | .tc dscr_default[TC],dscr_default | ||
84 | |||
85 | .section ".text" | ||
82 | 86 | ||
83 | /* void tm_reclaim(struct thread_struct *thread, | 87 | /* void tm_reclaim(struct thread_struct *thread, |
84 | * unsigned long orig_msr, | 88 | * unsigned long orig_msr, |
@@ -102,7 +106,7 @@ _GLOBAL(tm_abort) | |||
102 | _GLOBAL(tm_reclaim) | 106 | _GLOBAL(tm_reclaim) |
103 | mfcr r6 | 107 | mfcr r6 |
104 | mflr r0 | 108 | mflr r0 |
105 | std r6, 8(r1) | 109 | stw r6, 8(r1) |
106 | std r0, 16(r1) | 110 | std r0, 16(r1) |
107 | std r2, 40(r1) | 111 | std r2, 40(r1) |
108 | stdu r1, -TM_FRAME_SIZE(r1) | 112 | stdu r1, -TM_FRAME_SIZE(r1) |
@@ -123,6 +127,7 @@ _GLOBAL(tm_reclaim) | |||
123 | mr r15, r14 | 127 | mr r15, r14 |
124 | ori r15, r15, MSR_FP | 128 | ori r15, r15, MSR_FP |
125 | li r16, MSR_RI | 129 | li r16, MSR_RI |
130 | ori r16, r16, MSR_EE /* IRQs hard off */ | ||
126 | andc r15, r15, r16 | 131 | andc r15, r15, r16 |
127 | oris r15, r15, MSR_VEC@h | 132 | oris r15, r15, MSR_VEC@h |
128 | #ifdef CONFIG_VSX | 133 | #ifdef CONFIG_VSX |
@@ -151,10 +156,11 @@ _GLOBAL(tm_reclaim) | |||
151 | andis. r0, r4, MSR_VEC@h | 156 | andis. r0, r4, MSR_VEC@h |
152 | beq dont_backup_vec | 157 | beq dont_backup_vec |
153 | 158 | ||
154 | SAVE_32VRS_TRANSACT(0, r6, r3) /* r6 scratch, r3 thread */ | 159 | addi r7, r3, THREAD_TRANSACT_VRSTATE |
160 | SAVE_32VRS(0, r6, r7) /* r6 scratch, r7 transact vr state */ | ||
155 | mfvscr vr0 | 161 | mfvscr vr0 |
156 | li r6, THREAD_TRANSACT_VSCR | 162 | li r6, VRSTATE_VSCR |
157 | stvx vr0, r3, r6 | 163 | stvx vr0, r7, r6 |
158 | dont_backup_vec: | 164 | dont_backup_vec: |
159 | mfspr r0, SPRN_VRSAVE | 165 | mfspr r0, SPRN_VRSAVE |
160 | std r0, THREAD_TRANSACT_VRSAVE(r3) | 166 | std r0, THREAD_TRANSACT_VRSAVE(r3) |
@@ -162,10 +168,11 @@ dont_backup_vec: | |||
162 | andi. r0, r4, MSR_FP | 168 | andi. r0, r4, MSR_FP |
163 | beq dont_backup_fp | 169 | beq dont_backup_fp |
164 | 170 | ||
165 | SAVE_32FPRS_VSRS_TRANSACT(0, R6, R3) /* r6 scratch, r3 thread */ | 171 | addi r7, r3, THREAD_TRANSACT_FPSTATE |
172 | SAVE_32FPRS_VSRS(0, R6, R7) /* r6 scratch, r7 transact fp state */ | ||
166 | 173 | ||
167 | mffs fr0 | 174 | mffs fr0 |
168 | stfd fr0,THREAD_TRANSACT_FPSCR(r3) | 175 | stfd fr0,FPSTATE_FPSCR(r7) |
169 | 176 | ||
170 | dont_backup_fp: | 177 | dont_backup_fp: |
171 | /* The moment we treclaim, ALL of our GPRs will switch | 178 | /* The moment we treclaim, ALL of our GPRs will switch |
@@ -187,11 +194,18 @@ dont_backup_fp: | |||
187 | std r1, PACATMSCRATCH(r13) | 194 | std r1, PACATMSCRATCH(r13) |
188 | ld r1, PACAR1(r13) | 195 | ld r1, PACAR1(r13) |
189 | 196 | ||
197 | /* Store the PPR in r11 and reset to decent value */ | ||
198 | std r11, GPR11(r1) /* Temporary stash */ | ||
199 | mfspr r11, SPRN_PPR | ||
200 | HMT_MEDIUM | ||
201 | |||
190 | /* Now get some more GPRS free */ | 202 | /* Now get some more GPRS free */ |
191 | std r7, GPR7(r1) /* Temporary stash */ | 203 | std r7, GPR7(r1) /* Temporary stash */ |
192 | std r12, GPR12(r1) /* '' '' '' */ | 204 | std r12, GPR12(r1) /* '' '' '' */ |
193 | ld r12, STACK_PARAM(0)(r1) /* Param 0, thread_struct * */ | 205 | ld r12, STACK_PARAM(0)(r1) /* Param 0, thread_struct * */ |
194 | 206 | ||
207 | std r11, THREAD_TM_PPR(r12) /* Store PPR and free r11 */ | ||
208 | |||
195 | addi r7, r12, PT_CKPT_REGS /* Thread's ckpt_regs */ | 209 | addi r7, r12, PT_CKPT_REGS /* Thread's ckpt_regs */ |
196 | 210 | ||
197 | /* Make r7 look like an exception frame so that we | 211 | /* Make r7 look like an exception frame so that we |
@@ -203,15 +217,19 @@ dont_backup_fp: | |||
203 | SAVE_GPR(0, r7) /* user r0 */ | 217 | SAVE_GPR(0, r7) /* user r0 */ |
204 | SAVE_GPR(2, r7) /* user r2 */ | 218 | SAVE_GPR(2, r7) /* user r2 */ |
205 | SAVE_4GPRS(3, r7) /* user r3-r6 */ | 219 | SAVE_4GPRS(3, r7) /* user r3-r6 */ |
206 | SAVE_4GPRS(8, r7) /* user r8-r11 */ | 220 | SAVE_GPR(8, r7) /* user r8 */ |
221 | SAVE_GPR(9, r7) /* user r9 */ | ||
222 | SAVE_GPR(10, r7) /* user r10 */ | ||
207 | ld r3, PACATMSCRATCH(r13) /* user r1 */ | 223 | ld r3, PACATMSCRATCH(r13) /* user r1 */ |
208 | ld r4, GPR7(r1) /* user r7 */ | 224 | ld r4, GPR7(r1) /* user r7 */ |
209 | ld r5, GPR12(r1) /* user r12 */ | 225 | ld r5, GPR11(r1) /* user r11 */ |
210 | GET_SCRATCH0(6) /* user r13 */ | 226 | ld r6, GPR12(r1) /* user r12 */ |
227 | GET_SCRATCH0(8) /* user r13 */ | ||
211 | std r3, GPR1(r7) | 228 | std r3, GPR1(r7) |
212 | std r4, GPR7(r7) | 229 | std r4, GPR7(r7) |
213 | std r5, GPR12(r7) | 230 | std r5, GPR11(r7) |
214 | std r6, GPR13(r7) | 231 | std r6, GPR12(r7) |
232 | std r8, GPR13(r7) | ||
215 | 233 | ||
216 | SAVE_NVGPRS(r7) /* user r14-r31 */ | 234 | SAVE_NVGPRS(r7) /* user r14-r31 */ |
217 | 235 | ||
@@ -234,14 +252,12 @@ dont_backup_fp: | |||
234 | std r6, _XER(r7) | 252 | std r6, _XER(r7) |
235 | 253 | ||
236 | 254 | ||
237 | /* ******************** TAR, PPR, DSCR ********** */ | 255 | /* ******************** TAR, DSCR ********** */ |
238 | mfspr r3, SPRN_TAR | 256 | mfspr r3, SPRN_TAR |
239 | mfspr r4, SPRN_PPR | 257 | mfspr r4, SPRN_DSCR |
240 | mfspr r5, SPRN_DSCR | ||
241 | 258 | ||
242 | std r3, THREAD_TM_TAR(r12) | 259 | std r3, THREAD_TM_TAR(r12) |
243 | std r4, THREAD_TM_PPR(r12) | 260 | std r4, THREAD_TM_DSCR(r12) |
244 | std r5, THREAD_TM_DSCR(r12) | ||
245 | 261 | ||
246 | /* MSR and flags: We don't change CRs, and we don't need to alter | 262 | /* MSR and flags: We don't change CRs, and we don't need to alter |
247 | * MSR. | 263 | * MSR. |
@@ -258,7 +274,7 @@ dont_backup_fp: | |||
258 | std r3, THREAD_TM_TFHAR(r12) | 274 | std r3, THREAD_TM_TFHAR(r12) |
259 | std r4, THREAD_TM_TFIAR(r12) | 275 | std r4, THREAD_TM_TFIAR(r12) |
260 | 276 | ||
261 | /* AMR and PPR are checkpointed too, but are unsupported by Linux. */ | 277 | /* AMR is checkpointed too, but is unsupported by Linux. */ |
262 | 278 | ||
263 | /* Restore original MSR/IRQ state & clear TM mode */ | 279 | /* Restore original MSR/IRQ state & clear TM mode */ |
264 | ld r14, TM_FRAME_L0(r1) /* Orig MSR */ | 280 | ld r14, TM_FRAME_L0(r1) /* Orig MSR */ |
@@ -269,11 +285,17 @@ dont_backup_fp: | |||
269 | REST_NVGPRS(r1) | 285 | REST_NVGPRS(r1) |
270 | 286 | ||
271 | addi r1, r1, TM_FRAME_SIZE | 287 | addi r1, r1, TM_FRAME_SIZE |
272 | ld r4, 8(r1) | 288 | lwz r4, 8(r1) |
273 | ld r0, 16(r1) | 289 | ld r0, 16(r1) |
274 | mtcr r4 | 290 | mtcr r4 |
275 | mtlr r0 | 291 | mtlr r0 |
276 | ld r2, 40(r1) | 292 | ld r2, 40(r1) |
293 | |||
294 | /* Load system default DSCR */ | ||
295 | ld r4, DSCR_DEFAULT@toc(r2) | ||
296 | ld r0, 0(r4) | ||
297 | mtspr SPRN_DSCR, r0 | ||
298 | |||
277 | blr | 299 | blr |
278 | 300 | ||
279 | 301 | ||
@@ -288,7 +310,7 @@ dont_backup_fp: | |||
288 | _GLOBAL(tm_recheckpoint) | 310 | _GLOBAL(tm_recheckpoint) |
289 | mfcr r5 | 311 | mfcr r5 |
290 | mflr r0 | 312 | mflr r0 |
291 | std r5, 8(r1) | 313 | stw r5, 8(r1) |
292 | std r0, 16(r1) | 314 | std r0, 16(r1) |
293 | std r2, 40(r1) | 315 | std r2, 40(r1) |
294 | stdu r1, -TM_FRAME_SIZE(r1) | 316 | stdu r1, -TM_FRAME_SIZE(r1) |
@@ -337,10 +359,11 @@ _GLOBAL(tm_recheckpoint) | |||
337 | andis. r0, r4, MSR_VEC@h | 359 | andis. r0, r4, MSR_VEC@h |
338 | beq dont_restore_vec | 360 | beq dont_restore_vec |
339 | 361 | ||
340 | li r5, THREAD_VSCR | 362 | addi r8, r3, THREAD_VRSTATE |
341 | lvx vr0, r3, r5 | 363 | li r5, VRSTATE_VSCR |
364 | lvx vr0, r8, r5 | ||
342 | mtvscr vr0 | 365 | mtvscr vr0 |
343 | REST_32VRS(0, r5, r3) /* r5 scratch, r3 THREAD ptr */ | 366 | REST_32VRS(0, r5, r8) /* r5 scratch, r8 ptr */ |
344 | dont_restore_vec: | 367 | dont_restore_vec: |
345 | ld r5, THREAD_VRSAVE(r3) | 368 | ld r5, THREAD_VRSAVE(r3) |
346 | mtspr SPRN_VRSAVE, r5 | 369 | mtspr SPRN_VRSAVE, r5 |
@@ -349,34 +372,34 @@ dont_restore_vec: | |||
349 | andi. r0, r4, MSR_FP | 372 | andi. r0, r4, MSR_FP |
350 | beq dont_restore_fp | 373 | beq dont_restore_fp |
351 | 374 | ||
352 | lfd fr0, THREAD_FPSCR(r3) | 375 | addi r8, r3, THREAD_FPSTATE |
376 | lfd fr0, FPSTATE_FPSCR(r8) | ||
353 | MTFSF_L(fr0) | 377 | MTFSF_L(fr0) |
354 | REST_32FPRS_VSRS(0, R4, R3) | 378 | REST_32FPRS_VSRS(0, R4, R8) |
355 | 379 | ||
356 | dont_restore_fp: | 380 | dont_restore_fp: |
357 | mtmsr r6 /* FP/Vec off again! */ | 381 | mtmsr r6 /* FP/Vec off again! */ |
358 | 382 | ||
359 | restore_gprs: | 383 | restore_gprs: |
360 | 384 | ||
361 | /* ******************** TAR, PPR, DSCR ********** */ | 385 | /* ******************** CR,LR,CCR,MSR ********** */ |
362 | ld r4, THREAD_TM_TAR(r3) | 386 | ld r4, _CTR(r7) |
363 | ld r5, THREAD_TM_PPR(r3) | 387 | ld r5, _LINK(r7) |
364 | ld r6, THREAD_TM_DSCR(r3) | 388 | ld r6, _CCR(r7) |
389 | ld r8, _XER(r7) | ||
365 | 390 | ||
366 | mtspr SPRN_TAR, r4 | 391 | mtctr r4 |
367 | mtspr SPRN_PPR, r5 | 392 | mtlr r5 |
368 | mtspr SPRN_DSCR, r6 | 393 | mtcr r6 |
394 | mtxer r8 | ||
369 | 395 | ||
370 | /* ******************** CR,LR,CCR,MSR ********** */ | 396 | /* ******************** TAR ******************** */ |
371 | ld r3, _CTR(r7) | 397 | ld r4, THREAD_TM_TAR(r3) |
372 | ld r4, _LINK(r7) | 398 | mtspr SPRN_TAR, r4 |
373 | ld r5, _CCR(r7) | ||
374 | ld r6, _XER(r7) | ||
375 | 399 | ||
376 | mtctr r3 | 400 | /* Load up the PPR and DSCR in GPRs only at this stage */ |
377 | mtlr r4 | 401 | ld r5, THREAD_TM_DSCR(r3) |
378 | mtcr r5 | 402 | ld r6, THREAD_TM_PPR(r3) |
379 | mtxer r6 | ||
380 | 403 | ||
381 | /* Clear the MSR RI since we are about to change R1. EE is already off | 404 | /* Clear the MSR RI since we are about to change R1. EE is already off |
382 | */ | 405 | */ |
@@ -384,19 +407,26 @@ restore_gprs: | |||
384 | mtmsrd r4, 1 | 407 | mtmsrd r4, 1 |
385 | 408 | ||
386 | REST_4GPRS(0, r7) /* GPR0-3 */ | 409 | REST_4GPRS(0, r7) /* GPR0-3 */ |
387 | REST_GPR(4, r7) /* GPR4-6 */ | 410 | REST_GPR(4, r7) /* GPR4 */ |
388 | REST_GPR(5, r7) | ||
389 | REST_GPR(6, r7) | ||
390 | REST_4GPRS(8, r7) /* GPR8-11 */ | 411 | REST_4GPRS(8, r7) /* GPR8-11 */ |
391 | REST_2GPRS(12, r7) /* GPR12-13 */ | 412 | REST_2GPRS(12, r7) /* GPR12-13 */ |
392 | 413 | ||
393 | REST_NVGPRS(r7) /* GPR14-31 */ | 414 | REST_NVGPRS(r7) /* GPR14-31 */ |
394 | 415 | ||
395 | ld r7, GPR7(r7) /* GPR7 */ | 416 | /* Load up PPR and DSCR here so we don't run with user values for long |
417 | */ | ||
418 | mtspr SPRN_DSCR, r5 | ||
419 | mtspr SPRN_PPR, r6 | ||
420 | |||
421 | REST_GPR(5, r7) /* GPR5-7 */ | ||
422 | REST_GPR(6, r7) | ||
423 | ld r7, GPR7(r7) | ||
396 | 424 | ||
397 | /* Commit register state as checkpointed state: */ | 425 | /* Commit register state as checkpointed state: */ |
398 | TRECHKPT | 426 | TRECHKPT |
399 | 427 | ||
428 | HMT_MEDIUM | ||
429 | |||
400 | /* Our transactional state has now changed. | 430 | /* Our transactional state has now changed. |
401 | * | 431 | * |
402 | * Now just get out of here. Transactional (current) state will be | 432 | * Now just get out of here. Transactional (current) state will be |
@@ -414,11 +444,17 @@ restore_gprs: | |||
414 | REST_NVGPRS(r1) | 444 | REST_NVGPRS(r1) |
415 | 445 | ||
416 | addi r1, r1, TM_FRAME_SIZE | 446 | addi r1, r1, TM_FRAME_SIZE |
417 | ld r4, 8(r1) | 447 | lwz r4, 8(r1) |
418 | ld r0, 16(r1) | 448 | ld r0, 16(r1) |
419 | mtcr r4 | 449 | mtcr r4 |
420 | mtlr r0 | 450 | mtlr r0 |
421 | ld r2, 40(r1) | 451 | ld r2, 40(r1) |
452 | |||
453 | /* Load system default DSCR */ | ||
454 | ld r4, DSCR_DEFAULT@toc(r2) | ||
455 | ld r0, 0(r4) | ||
456 | mtspr SPRN_DSCR, r0 | ||
457 | |||
422 | blr | 458 | blr |
423 | 459 | ||
424 | /* ****************************************************************** */ | 460 | /* ****************************************************************** */ |
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index f783c932faeb..907a472f9a9e 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
@@ -351,8 +351,8 @@ static inline int check_io_access(struct pt_regs *regs) | |||
351 | #define REASON_TRAP ESR_PTR | 351 | #define REASON_TRAP ESR_PTR |
352 | 352 | ||
353 | /* single-step stuff */ | 353 | /* single-step stuff */ |
354 | #define single_stepping(regs) (current->thread.dbcr0 & DBCR0_IC) | 354 | #define single_stepping(regs) (current->thread.debug.dbcr0 & DBCR0_IC) |
355 | #define clear_single_step(regs) (current->thread.dbcr0 &= ~DBCR0_IC) | 355 | #define clear_single_step(regs) (current->thread.debug.dbcr0 &= ~DBCR0_IC) |
356 | 356 | ||
357 | #else | 357 | #else |
358 | /* On non-4xx, the reason for the machine check or program | 358 | /* On non-4xx, the reason for the machine check or program |
@@ -816,7 +816,7 @@ static void parse_fpe(struct pt_regs *regs) | |||
816 | 816 | ||
817 | flush_fp_to_thread(current); | 817 | flush_fp_to_thread(current); |
818 | 818 | ||
819 | code = __parse_fpscr(current->thread.fpscr.val); | 819 | code = __parse_fpscr(current->thread.fp_state.fpscr); |
820 | 820 | ||
821 | _exception(SIGFPE, regs, code, regs->nip); | 821 | _exception(SIGFPE, regs, code, regs->nip); |
822 | } | 822 | } |
@@ -1018,6 +1018,13 @@ static int emulate_instruction(struct pt_regs *regs) | |||
1018 | return emulate_isel(regs, instword); | 1018 | return emulate_isel(regs, instword); |
1019 | } | 1019 | } |
1020 | 1020 | ||
1021 | /* Emulate sync instruction variants */ | ||
1022 | if ((instword & PPC_INST_SYNC_MASK) == PPC_INST_SYNC) { | ||
1023 | PPC_WARN_EMULATED(sync, regs); | ||
1024 | asm volatile("sync"); | ||
1025 | return 0; | ||
1026 | } | ||
1027 | |||
1021 | #ifdef CONFIG_PPC64 | 1028 | #ifdef CONFIG_PPC64 |
1022 | /* Emulate the mfspr rD, DSCR. */ | 1029 | /* Emulate the mfspr rD, DSCR. */ |
1023 | if ((((instword & PPC_INST_MFSPR_DSCR_USER_MASK) == | 1030 | if ((((instword & PPC_INST_MFSPR_DSCR_USER_MASK) == |
@@ -1069,7 +1076,7 @@ static int emulate_math(struct pt_regs *regs) | |||
1069 | return 0; | 1076 | return 0; |
1070 | case 1: { | 1077 | case 1: { |
1071 | int code = 0; | 1078 | int code = 0; |
1072 | code = __parse_fpscr(current->thread.fpscr.val); | 1079 | code = __parse_fpscr(current->thread.fp_state.fpscr); |
1073 | _exception(SIGFPE, regs, code, regs->nip); | 1080 | _exception(SIGFPE, regs, code, regs->nip); |
1074 | return 0; | 1081 | return 0; |
1075 | } | 1082 | } |
@@ -1371,8 +1378,6 @@ void facility_unavailable_exception(struct pt_regs *regs) | |||
1371 | 1378 | ||
1372 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | 1379 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM |
1373 | 1380 | ||
1374 | extern void do_load_up_fpu(struct pt_regs *regs); | ||
1375 | |||
1376 | void fp_unavailable_tm(struct pt_regs *regs) | 1381 | void fp_unavailable_tm(struct pt_regs *regs) |
1377 | { | 1382 | { |
1378 | /* Note: This does not handle any kind of FP laziness. */ | 1383 | /* Note: This does not handle any kind of FP laziness. */ |
@@ -1403,8 +1408,6 @@ void fp_unavailable_tm(struct pt_regs *regs) | |||
1403 | } | 1408 | } |
1404 | 1409 | ||
1405 | #ifdef CONFIG_ALTIVEC | 1410 | #ifdef CONFIG_ALTIVEC |
1406 | extern void do_load_up_altivec(struct pt_regs *regs); | ||
1407 | |||
1408 | void altivec_unavailable_tm(struct pt_regs *regs) | 1411 | void altivec_unavailable_tm(struct pt_regs *regs) |
1409 | { | 1412 | { |
1410 | /* See the comments in fp_unavailable_tm(). This function operates | 1413 | /* See the comments in fp_unavailable_tm(). This function operates |
@@ -1465,7 +1468,8 @@ void SoftwareEmulation(struct pt_regs *regs) | |||
1465 | 1468 | ||
1466 | if (!user_mode(regs)) { | 1469 | if (!user_mode(regs)) { |
1467 | debugger(regs); | 1470 | debugger(regs); |
1468 | die("Kernel Mode Software FPU Emulation", regs, SIGFPE); | 1471 | die("Kernel Mode Unimplemented Instruction or SW FPU Emulation", |
1472 | regs, SIGFPE); | ||
1469 | } | 1473 | } |
1470 | 1474 | ||
1471 | if (!emulate_math(regs)) | 1475 | if (!emulate_math(regs)) |
@@ -1486,7 +1490,7 @@ static void handle_debug(struct pt_regs *regs, unsigned long debug_status) | |||
1486 | if (debug_status & (DBSR_DAC1R | DBSR_DAC1W)) { | 1490 | if (debug_status & (DBSR_DAC1R | DBSR_DAC1W)) { |
1487 | dbcr_dac(current) &= ~(DBCR_DAC1R | DBCR_DAC1W); | 1491 | dbcr_dac(current) &= ~(DBCR_DAC1R | DBCR_DAC1W); |
1488 | #ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE | 1492 | #ifdef CONFIG_PPC_ADV_DEBUG_DAC_RANGE |
1489 | current->thread.dbcr2 &= ~DBCR2_DAC12MODE; | 1493 | current->thread.debug.dbcr2 &= ~DBCR2_DAC12MODE; |
1490 | #endif | 1494 | #endif |
1491 | do_send_trap(regs, mfspr(SPRN_DAC1), debug_status, TRAP_HWBKPT, | 1495 | do_send_trap(regs, mfspr(SPRN_DAC1), debug_status, TRAP_HWBKPT, |
1492 | 5); | 1496 | 5); |
@@ -1497,24 +1501,24 @@ static void handle_debug(struct pt_regs *regs, unsigned long debug_status) | |||
1497 | 6); | 1501 | 6); |
1498 | changed |= 0x01; | 1502 | changed |= 0x01; |
1499 | } else if (debug_status & DBSR_IAC1) { | 1503 | } else if (debug_status & DBSR_IAC1) { |
1500 | current->thread.dbcr0 &= ~DBCR0_IAC1; | 1504 | current->thread.debug.dbcr0 &= ~DBCR0_IAC1; |
1501 | dbcr_iac_range(current) &= ~DBCR_IAC12MODE; | 1505 | dbcr_iac_range(current) &= ~DBCR_IAC12MODE; |
1502 | do_send_trap(regs, mfspr(SPRN_IAC1), debug_status, TRAP_HWBKPT, | 1506 | do_send_trap(regs, mfspr(SPRN_IAC1), debug_status, TRAP_HWBKPT, |
1503 | 1); | 1507 | 1); |
1504 | changed |= 0x01; | 1508 | changed |= 0x01; |
1505 | } else if (debug_status & DBSR_IAC2) { | 1509 | } else if (debug_status & DBSR_IAC2) { |
1506 | current->thread.dbcr0 &= ~DBCR0_IAC2; | 1510 | current->thread.debug.dbcr0 &= ~DBCR0_IAC2; |
1507 | do_send_trap(regs, mfspr(SPRN_IAC2), debug_status, TRAP_HWBKPT, | 1511 | do_send_trap(regs, mfspr(SPRN_IAC2), debug_status, TRAP_HWBKPT, |
1508 | 2); | 1512 | 2); |
1509 | changed |= 0x01; | 1513 | changed |= 0x01; |
1510 | } else if (debug_status & DBSR_IAC3) { | 1514 | } else if (debug_status & DBSR_IAC3) { |
1511 | current->thread.dbcr0 &= ~DBCR0_IAC3; | 1515 | current->thread.debug.dbcr0 &= ~DBCR0_IAC3; |
1512 | dbcr_iac_range(current) &= ~DBCR_IAC34MODE; | 1516 | dbcr_iac_range(current) &= ~DBCR_IAC34MODE; |
1513 | do_send_trap(regs, mfspr(SPRN_IAC3), debug_status, TRAP_HWBKPT, | 1517 | do_send_trap(regs, mfspr(SPRN_IAC3), debug_status, TRAP_HWBKPT, |
1514 | 3); | 1518 | 3); |
1515 | changed |= 0x01; | 1519 | changed |= 0x01; |
1516 | } else if (debug_status & DBSR_IAC4) { | 1520 | } else if (debug_status & DBSR_IAC4) { |
1517 | current->thread.dbcr0 &= ~DBCR0_IAC4; | 1521 | current->thread.debug.dbcr0 &= ~DBCR0_IAC4; |
1518 | do_send_trap(regs, mfspr(SPRN_IAC4), debug_status, TRAP_HWBKPT, | 1522 | do_send_trap(regs, mfspr(SPRN_IAC4), debug_status, TRAP_HWBKPT, |
1519 | 4); | 1523 | 4); |
1520 | changed |= 0x01; | 1524 | changed |= 0x01; |
@@ -1524,19 +1528,20 @@ static void handle_debug(struct pt_regs *regs, unsigned long debug_status) | |||
1524 | * Check all other debug flags and see if that bit needs to be turned | 1528 | * Check all other debug flags and see if that bit needs to be turned |
1525 | * back on or not. | 1529 | * back on or not. |
1526 | */ | 1530 | */ |
1527 | if (DBCR_ACTIVE_EVENTS(current->thread.dbcr0, current->thread.dbcr1)) | 1531 | if (DBCR_ACTIVE_EVENTS(current->thread.debug.dbcr0, |
1532 | current->thread.debug.dbcr1)) | ||
1528 | regs->msr |= MSR_DE; | 1533 | regs->msr |= MSR_DE; |
1529 | else | 1534 | else |
1530 | /* Make sure the IDM flag is off */ | 1535 | /* Make sure the IDM flag is off */ |
1531 | current->thread.dbcr0 &= ~DBCR0_IDM; | 1536 | current->thread.debug.dbcr0 &= ~DBCR0_IDM; |
1532 | 1537 | ||
1533 | if (changed & 0x01) | 1538 | if (changed & 0x01) |
1534 | mtspr(SPRN_DBCR0, current->thread.dbcr0); | 1539 | mtspr(SPRN_DBCR0, current->thread.debug.dbcr0); |
1535 | } | 1540 | } |
1536 | 1541 | ||
1537 | void __kprobes DebugException(struct pt_regs *regs, unsigned long debug_status) | 1542 | void __kprobes DebugException(struct pt_regs *regs, unsigned long debug_status) |
1538 | { | 1543 | { |
1539 | current->thread.dbsr = debug_status; | 1544 | current->thread.debug.dbsr = debug_status; |
1540 | 1545 | ||
1541 | /* Hack alert: On BookE, Branch Taken stops on the branch itself, while | 1546 | /* Hack alert: On BookE, Branch Taken stops on the branch itself, while |
1542 | * on server, it stops on the target of the branch. In order to simulate | 1547 | * on server, it stops on the target of the branch. In order to simulate |
@@ -1553,8 +1558,8 @@ void __kprobes DebugException(struct pt_regs *regs, unsigned long debug_status) | |||
1553 | 1558 | ||
1554 | /* Do the single step trick only when coming from userspace */ | 1559 | /* Do the single step trick only when coming from userspace */ |
1555 | if (user_mode(regs)) { | 1560 | if (user_mode(regs)) { |
1556 | current->thread.dbcr0 &= ~DBCR0_BT; | 1561 | current->thread.debug.dbcr0 &= ~DBCR0_BT; |
1557 | current->thread.dbcr0 |= DBCR0_IDM | DBCR0_IC; | 1562 | current->thread.debug.dbcr0 |= DBCR0_IDM | DBCR0_IC; |
1558 | regs->msr |= MSR_DE; | 1563 | regs->msr |= MSR_DE; |
1559 | return; | 1564 | return; |
1560 | } | 1565 | } |
@@ -1582,13 +1587,13 @@ void __kprobes DebugException(struct pt_regs *regs, unsigned long debug_status) | |||
1582 | return; | 1587 | return; |
1583 | 1588 | ||
1584 | if (user_mode(regs)) { | 1589 | if (user_mode(regs)) { |
1585 | current->thread.dbcr0 &= ~DBCR0_IC; | 1590 | current->thread.debug.dbcr0 &= ~DBCR0_IC; |
1586 | if (DBCR_ACTIVE_EVENTS(current->thread.dbcr0, | 1591 | if (DBCR_ACTIVE_EVENTS(current->thread.debug.dbcr0, |
1587 | current->thread.dbcr1)) | 1592 | current->thread.debug.dbcr1)) |
1588 | regs->msr |= MSR_DE; | 1593 | regs->msr |= MSR_DE; |
1589 | else | 1594 | else |
1590 | /* Make sure the IDM bit is off */ | 1595 | /* Make sure the IDM bit is off */ |
1591 | current->thread.dbcr0 &= ~DBCR0_IDM; | 1596 | current->thread.debug.dbcr0 &= ~DBCR0_IDM; |
1592 | } | 1597 | } |
1593 | 1598 | ||
1594 | _exception(SIGTRAP, regs, TRAP_TRACE, regs->nip); | 1599 | _exception(SIGTRAP, regs, TRAP_TRACE, regs->nip); |
@@ -1634,7 +1639,7 @@ void altivec_assist_exception(struct pt_regs *regs) | |||
1634 | /* XXX quick hack for now: set the non-Java bit in the VSCR */ | 1639 | /* XXX quick hack for now: set the non-Java bit in the VSCR */ |
1635 | printk_ratelimited(KERN_ERR "Unrecognized altivec instruction " | 1640 | printk_ratelimited(KERN_ERR "Unrecognized altivec instruction " |
1636 | "in %s at %lx\n", current->comm, regs->nip); | 1641 | "in %s at %lx\n", current->comm, regs->nip); |
1637 | current->thread.vscr.u[3] |= 0x10000; | 1642 | current->thread.vr_state.vscr.u[3] |= 0x10000; |
1638 | } | 1643 | } |
1639 | } | 1644 | } |
1640 | #endif /* CONFIG_ALTIVEC */ | 1645 | #endif /* CONFIG_ALTIVEC */ |
@@ -1815,6 +1820,7 @@ struct ppc_emulated ppc_emulated = { | |||
1815 | WARN_EMULATED_SETUP(popcntb), | 1820 | WARN_EMULATED_SETUP(popcntb), |
1816 | WARN_EMULATED_SETUP(spe), | 1821 | WARN_EMULATED_SETUP(spe), |
1817 | WARN_EMULATED_SETUP(string), | 1822 | WARN_EMULATED_SETUP(string), |
1823 | WARN_EMULATED_SETUP(sync), | ||
1818 | WARN_EMULATED_SETUP(unaligned), | 1824 | WARN_EMULATED_SETUP(unaligned), |
1819 | #ifdef CONFIG_MATH_EMULATION | 1825 | #ifdef CONFIG_MATH_EMULATION |
1820 | WARN_EMULATED_SETUP(math), | 1826 | WARN_EMULATED_SETUP(math), |
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index 1d9c92621b36..094e45c16a17 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c | |||
@@ -34,8 +34,7 @@ | |||
34 | #include <asm/firmware.h> | 34 | #include <asm/firmware.h> |
35 | #include <asm/vdso.h> | 35 | #include <asm/vdso.h> |
36 | #include <asm/vdso_datapage.h> | 36 | #include <asm/vdso_datapage.h> |
37 | 37 | #include <asm/setup.h> | |
38 | #include "setup.h" | ||
39 | 38 | ||
40 | #undef DEBUG | 39 | #undef DEBUG |
41 | 40 | ||
diff --git a/arch/powerpc/kernel/vdso32/vdso32.lds.S b/arch/powerpc/kernel/vdso32/vdso32.lds.S index f223409629b9..e58ee10fa5c0 100644 --- a/arch/powerpc/kernel/vdso32/vdso32.lds.S +++ b/arch/powerpc/kernel/vdso32/vdso32.lds.S | |||
@@ -4,7 +4,11 @@ | |||
4 | */ | 4 | */ |
5 | #include <asm/vdso.h> | 5 | #include <asm/vdso.h> |
6 | 6 | ||
7 | #ifdef __LITTLE_ENDIAN__ | ||
8 | OUTPUT_FORMAT("elf32-powerpcle", "elf32-powerpcle", "elf32-powerpcle") | ||
9 | #else | ||
7 | OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc") | 10 | OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", "elf32-powerpc") |
11 | #endif | ||
8 | OUTPUT_ARCH(powerpc:common) | 12 | OUTPUT_ARCH(powerpc:common) |
9 | ENTRY(_start) | 13 | ENTRY(_start) |
10 | 14 | ||
diff --git a/arch/powerpc/kernel/vdso64/vdso64.lds.S b/arch/powerpc/kernel/vdso64/vdso64.lds.S index e4863819663b..64fb183a47c2 100644 --- a/arch/powerpc/kernel/vdso64/vdso64.lds.S +++ b/arch/powerpc/kernel/vdso64/vdso64.lds.S | |||
@@ -4,7 +4,11 @@ | |||
4 | */ | 4 | */ |
5 | #include <asm/vdso.h> | 5 | #include <asm/vdso.h> |
6 | 6 | ||
7 | #ifdef __LITTLE_ENDIAN__ | ||
8 | OUTPUT_FORMAT("elf64-powerpcle", "elf64-powerpcle", "elf64-powerpcle") | ||
9 | #else | ||
7 | OUTPUT_FORMAT("elf64-powerpc", "elf64-powerpc", "elf64-powerpc") | 10 | OUTPUT_FORMAT("elf64-powerpc", "elf64-powerpc", "elf64-powerpc") |
11 | #endif | ||
8 | OUTPUT_ARCH(powerpc:common64) | 12 | OUTPUT_ARCH(powerpc:common64) |
9 | ENTRY(_start) | 13 | ENTRY(_start) |
10 | 14 | ||
diff --git a/arch/powerpc/kernel/vecemu.c b/arch/powerpc/kernel/vecemu.c index 604d0947cb20..c4bfadb2606b 100644 --- a/arch/powerpc/kernel/vecemu.c +++ b/arch/powerpc/kernel/vecemu.c | |||
@@ -271,7 +271,7 @@ int emulate_altivec(struct pt_regs *regs) | |||
271 | vb = (instr >> 11) & 0x1f; | 271 | vb = (instr >> 11) & 0x1f; |
272 | vc = (instr >> 6) & 0x1f; | 272 | vc = (instr >> 6) & 0x1f; |
273 | 273 | ||
274 | vrs = current->thread.vr; | 274 | vrs = current->thread.vr_state.vr; |
275 | switch (instr & 0x3f) { | 275 | switch (instr & 0x3f) { |
276 | case 10: | 276 | case 10: |
277 | switch (vc) { | 277 | switch (vc) { |
@@ -320,12 +320,12 @@ int emulate_altivec(struct pt_regs *regs) | |||
320 | case 14: /* vctuxs */ | 320 | case 14: /* vctuxs */ |
321 | for (i = 0; i < 4; ++i) | 321 | for (i = 0; i < 4; ++i) |
322 | vrs[vd].u[i] = ctuxs(vrs[vb].u[i], va, | 322 | vrs[vd].u[i] = ctuxs(vrs[vb].u[i], va, |
323 | ¤t->thread.vscr.u[3]); | 323 | ¤t->thread.vr_state.vscr.u[3]); |
324 | break; | 324 | break; |
325 | case 15: /* vctsxs */ | 325 | case 15: /* vctsxs */ |
326 | for (i = 0; i < 4; ++i) | 326 | for (i = 0; i < 4; ++i) |
327 | vrs[vd].u[i] = ctsxs(vrs[vb].u[i], va, | 327 | vrs[vd].u[i] = ctsxs(vrs[vb].u[i], va, |
328 | ¤t->thread.vscr.u[3]); | 328 | ¤t->thread.vr_state.vscr.u[3]); |
329 | break; | 329 | break; |
330 | default: | 330 | default: |
331 | return -EINVAL; | 331 | return -EINVAL; |
diff --git a/arch/powerpc/kernel/vector.S b/arch/powerpc/kernel/vector.S index 9e20999aaef2..0458a9aaba9d 100644 --- a/arch/powerpc/kernel/vector.S +++ b/arch/powerpc/kernel/vector.S | |||
@@ -8,29 +8,6 @@ | |||
8 | #include <asm/ptrace.h> | 8 | #include <asm/ptrace.h> |
9 | 9 | ||
10 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | 10 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM |
11 | /* | ||
12 | * Wrapper to call load_up_altivec from C. | ||
13 | * void do_load_up_altivec(struct pt_regs *regs); | ||
14 | */ | ||
15 | _GLOBAL(do_load_up_altivec) | ||
16 | mflr r0 | ||
17 | std r0, 16(r1) | ||
18 | stdu r1, -112(r1) | ||
19 | |||
20 | subi r6, r3, STACK_FRAME_OVERHEAD | ||
21 | /* load_up_altivec expects r12=MSR, r13=PACA, and returns | ||
22 | * with r12 = new MSR. | ||
23 | */ | ||
24 | ld r12,_MSR(r6) | ||
25 | GET_PACA(r13) | ||
26 | bl load_up_altivec | ||
27 | std r12,_MSR(r6) | ||
28 | |||
29 | ld r0, 112+16(r1) | ||
30 | addi r1, r1, 112 | ||
31 | mtlr r0 | ||
32 | blr | ||
33 | |||
34 | /* void do_load_up_transact_altivec(struct thread_struct *thread) | 11 | /* void do_load_up_transact_altivec(struct thread_struct *thread) |
35 | * | 12 | * |
36 | * This is similar to load_up_altivec but for the transactional version of the | 13 | * This is similar to load_up_altivec but for the transactional version of the |
@@ -46,10 +23,11 @@ _GLOBAL(do_load_up_transact_altivec) | |||
46 | li r4,1 | 23 | li r4,1 |
47 | stw r4,THREAD_USED_VR(r3) | 24 | stw r4,THREAD_USED_VR(r3) |
48 | 25 | ||
49 | li r10,THREAD_TRANSACT_VSCR | 26 | li r10,THREAD_TRANSACT_VRSTATE+VRSTATE_VSCR |
50 | lvx vr0,r10,r3 | 27 | lvx vr0,r10,r3 |
51 | mtvscr vr0 | 28 | mtvscr vr0 |
52 | REST_32VRS_TRANSACT(0,r4,r3) | 29 | addi r10,r3,THREAD_TRANSACT_VRSTATE |
30 | REST_32VRS(0,r4,r10) | ||
53 | 31 | ||
54 | /* Disable VEC again. */ | 32 | /* Disable VEC again. */ |
55 | MTMSRD(r6) | 33 | MTMSRD(r6) |
@@ -59,12 +37,36 @@ _GLOBAL(do_load_up_transact_altivec) | |||
59 | #endif | 37 | #endif |
60 | 38 | ||
61 | /* | 39 | /* |
62 | * load_up_altivec(unused, unused, tsk) | 40 | * Load state from memory into VMX registers including VSCR. |
41 | * Assumes the caller has enabled VMX in the MSR. | ||
42 | */ | ||
43 | _GLOBAL(load_vr_state) | ||
44 | li r4,VRSTATE_VSCR | ||
45 | lvx vr0,r4,r3 | ||
46 | mtvscr vr0 | ||
47 | REST_32VRS(0,r4,r3) | ||
48 | blr | ||
49 | |||
50 | /* | ||
51 | * Store VMX state into memory, including VSCR. | ||
52 | * Assumes the caller has enabled VMX in the MSR. | ||
53 | */ | ||
54 | _GLOBAL(store_vr_state) | ||
55 | SAVE_32VRS(0, r4, r3) | ||
56 | mfvscr vr0 | ||
57 | li r4, VRSTATE_VSCR | ||
58 | stvx vr0, r4, r3 | ||
59 | blr | ||
60 | |||
61 | /* | ||
63 | * Disable VMX for the task which had it previously, | 62 | * Disable VMX for the task which had it previously, |
64 | * and save its vector registers in its thread_struct. | 63 | * and save its vector registers in its thread_struct. |
65 | * Enables the VMX for use in the kernel on return. | 64 | * Enables the VMX for use in the kernel on return. |
66 | * On SMP we know the VMX is free, since we give it up every | 65 | * On SMP we know the VMX is free, since we give it up every |
67 | * switch (ie, no lazy save of the vector registers). | 66 | * switch (ie, no lazy save of the vector registers). |
67 | * | ||
68 | * Note that on 32-bit this can only use registers that will be | ||
69 | * restored by fast_exception_return, i.e. r3 - r6, r10 and r11. | ||
68 | */ | 70 | */ |
69 | _GLOBAL(load_up_altivec) | 71 | _GLOBAL(load_up_altivec) |
70 | mfmsr r5 /* grab the current MSR */ | 72 | mfmsr r5 /* grab the current MSR */ |
@@ -90,10 +92,11 @@ _GLOBAL(load_up_altivec) | |||
90 | /* Save VMX state to last_task_used_altivec's THREAD struct */ | 92 | /* Save VMX state to last_task_used_altivec's THREAD struct */ |
91 | toreal(r4) | 93 | toreal(r4) |
92 | addi r4,r4,THREAD | 94 | addi r4,r4,THREAD |
93 | SAVE_32VRS(0,r5,r4) | 95 | addi r6,r4,THREAD_VRSTATE |
96 | SAVE_32VRS(0,r5,r6) | ||
94 | mfvscr vr0 | 97 | mfvscr vr0 |
95 | li r10,THREAD_VSCR | 98 | li r10,VRSTATE_VSCR |
96 | stvx vr0,r10,r4 | 99 | stvx vr0,r10,r6 |
97 | /* Disable VMX for last_task_used_altivec */ | 100 | /* Disable VMX for last_task_used_altivec */ |
98 | PPC_LL r5,PT_REGS(r4) | 101 | PPC_LL r5,PT_REGS(r4) |
99 | toreal(r5) | 102 | toreal(r5) |
@@ -125,12 +128,13 @@ _GLOBAL(load_up_altivec) | |||
125 | oris r12,r12,MSR_VEC@h | 128 | oris r12,r12,MSR_VEC@h |
126 | std r12,_MSR(r1) | 129 | std r12,_MSR(r1) |
127 | #endif | 130 | #endif |
131 | addi r6,r5,THREAD_VRSTATE | ||
128 | li r4,1 | 132 | li r4,1 |
129 | li r10,THREAD_VSCR | 133 | li r10,VRSTATE_VSCR |
130 | stw r4,THREAD_USED_VR(r5) | 134 | stw r4,THREAD_USED_VR(r5) |
131 | lvx vr0,r10,r5 | 135 | lvx vr0,r10,r6 |
132 | mtvscr vr0 | 136 | mtvscr vr0 |
133 | REST_32VRS(0,r4,r5) | 137 | REST_32VRS(0,r4,r6) |
134 | #ifndef CONFIG_SMP | 138 | #ifndef CONFIG_SMP |
135 | /* Update last_task_used_altivec to 'current' */ | 139 | /* Update last_task_used_altivec to 'current' */ |
136 | subi r4,r5,THREAD /* Back to 'current' */ | 140 | subi r4,r5,THREAD /* Back to 'current' */ |
@@ -165,12 +169,16 @@ _GLOBAL(giveup_altivec) | |||
165 | PPC_LCMPI 0,r3,0 | 169 | PPC_LCMPI 0,r3,0 |
166 | beqlr /* if no previous owner, done */ | 170 | beqlr /* if no previous owner, done */ |
167 | addi r3,r3,THREAD /* want THREAD of task */ | 171 | addi r3,r3,THREAD /* want THREAD of task */ |
172 | PPC_LL r7,THREAD_VRSAVEAREA(r3) | ||
168 | PPC_LL r5,PT_REGS(r3) | 173 | PPC_LL r5,PT_REGS(r3) |
169 | PPC_LCMPI 0,r5,0 | 174 | PPC_LCMPI 0,r7,0 |
170 | SAVE_32VRS(0,r4,r3) | 175 | bne 2f |
176 | addi r7,r3,THREAD_VRSTATE | ||
177 | 2: PPC_LCMPI 0,r5,0 | ||
178 | SAVE_32VRS(0,r4,r7) | ||
171 | mfvscr vr0 | 179 | mfvscr vr0 |
172 | li r4,THREAD_VSCR | 180 | li r4,VRSTATE_VSCR |
173 | stvx vr0,r4,r3 | 181 | stvx vr0,r4,r7 |
174 | beq 1f | 182 | beq 1f |
175 | PPC_LL r4,_MSR-STACK_FRAME_OVERHEAD(r5) | 183 | PPC_LL r4,_MSR-STACK_FRAME_OVERHEAD(r5) |
176 | #ifdef CONFIG_VSX | 184 | #ifdef CONFIG_VSX |
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index 78a350670de3..e7d0c88f621a 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c | |||
@@ -997,21 +997,36 @@ static struct device_attribute vio_cmo_dev_attrs[] = { | |||
997 | /* sysfs bus functions and data structures for CMO */ | 997 | /* sysfs bus functions and data structures for CMO */ |
998 | 998 | ||
999 | #define viobus_cmo_rd_attr(name) \ | 999 | #define viobus_cmo_rd_attr(name) \ |
1000 | static ssize_t \ | 1000 | static ssize_t cmo_##name##_show(struct bus_type *bt, char *buf) \ |
1001 | viobus_cmo_##name##_show(struct bus_type *bt, char *buf) \ | ||
1002 | { \ | 1001 | { \ |
1003 | return sprintf(buf, "%lu\n", vio_cmo.name); \ | 1002 | return sprintf(buf, "%lu\n", vio_cmo.name); \ |
1004 | } | 1003 | } \ |
1004 | static BUS_ATTR_RO(cmo_##name) | ||
1005 | 1005 | ||
1006 | #define viobus_cmo_pool_rd_attr(name, var) \ | 1006 | #define viobus_cmo_pool_rd_attr(name, var) \ |
1007 | static ssize_t \ | 1007 | static ssize_t \ |
1008 | viobus_cmo_##name##_pool_show_##var(struct bus_type *bt, char *buf) \ | 1008 | cmo_##name##_##var##_show(struct bus_type *bt, char *buf) \ |
1009 | { \ | 1009 | { \ |
1010 | return sprintf(buf, "%lu\n", vio_cmo.name.var); \ | 1010 | return sprintf(buf, "%lu\n", vio_cmo.name.var); \ |
1011 | } \ | ||
1012 | static BUS_ATTR_RO(cmo_##name##_##var) | ||
1013 | |||
1014 | viobus_cmo_rd_attr(entitled); | ||
1015 | viobus_cmo_rd_attr(spare); | ||
1016 | viobus_cmo_rd_attr(min); | ||
1017 | viobus_cmo_rd_attr(desired); | ||
1018 | viobus_cmo_rd_attr(curr); | ||
1019 | viobus_cmo_pool_rd_attr(reserve, size); | ||
1020 | viobus_cmo_pool_rd_attr(excess, size); | ||
1021 | viobus_cmo_pool_rd_attr(excess, free); | ||
1022 | |||
1023 | static ssize_t cmo_high_show(struct bus_type *bt, char *buf) | ||
1024 | { | ||
1025 | return sprintf(buf, "%lu\n", vio_cmo.high); | ||
1011 | } | 1026 | } |
1012 | 1027 | ||
1013 | static ssize_t viobus_cmo_high_reset(struct bus_type *bt, const char *buf, | 1028 | static ssize_t cmo_high_store(struct bus_type *bt, const char *buf, |
1014 | size_t count) | 1029 | size_t count) |
1015 | { | 1030 | { |
1016 | unsigned long flags; | 1031 | unsigned long flags; |
1017 | 1032 | ||
@@ -1021,35 +1036,26 @@ static ssize_t viobus_cmo_high_reset(struct bus_type *bt, const char *buf, | |||
1021 | 1036 | ||
1022 | return count; | 1037 | return count; |
1023 | } | 1038 | } |
1024 | 1039 | static BUS_ATTR_RW(cmo_high); | |
1025 | viobus_cmo_rd_attr(entitled); | 1040 | |
1026 | viobus_cmo_pool_rd_attr(reserve, size); | 1041 | static struct attribute *vio_bus_attrs[] = { |
1027 | viobus_cmo_pool_rd_attr(excess, size); | 1042 | &bus_attr_cmo_entitled.attr, |
1028 | viobus_cmo_pool_rd_attr(excess, free); | 1043 | &bus_attr_cmo_spare.attr, |
1029 | viobus_cmo_rd_attr(spare); | 1044 | &bus_attr_cmo_min.attr, |
1030 | viobus_cmo_rd_attr(min); | 1045 | &bus_attr_cmo_desired.attr, |
1031 | viobus_cmo_rd_attr(desired); | 1046 | &bus_attr_cmo_curr.attr, |
1032 | viobus_cmo_rd_attr(curr); | 1047 | &bus_attr_cmo_high.attr, |
1033 | viobus_cmo_rd_attr(high); | 1048 | &bus_attr_cmo_reserve_size.attr, |
1034 | 1049 | &bus_attr_cmo_excess_size.attr, | |
1035 | static struct bus_attribute vio_cmo_bus_attrs[] = { | 1050 | &bus_attr_cmo_excess_free.attr, |
1036 | __ATTR(cmo_entitled, S_IRUGO, viobus_cmo_entitled_show, NULL), | 1051 | NULL, |
1037 | __ATTR(cmo_reserve_size, S_IRUGO, viobus_cmo_reserve_pool_show_size, NULL), | ||
1038 | __ATTR(cmo_excess_size, S_IRUGO, viobus_cmo_excess_pool_show_size, NULL), | ||
1039 | __ATTR(cmo_excess_free, S_IRUGO, viobus_cmo_excess_pool_show_free, NULL), | ||
1040 | __ATTR(cmo_spare, S_IRUGO, viobus_cmo_spare_show, NULL), | ||
1041 | __ATTR(cmo_min, S_IRUGO, viobus_cmo_min_show, NULL), | ||
1042 | __ATTR(cmo_desired, S_IRUGO, viobus_cmo_desired_show, NULL), | ||
1043 | __ATTR(cmo_curr, S_IRUGO, viobus_cmo_curr_show, NULL), | ||
1044 | __ATTR(cmo_high, S_IWUSR|S_IRUSR|S_IWGRP|S_IRGRP|S_IROTH, | ||
1045 | viobus_cmo_high_show, viobus_cmo_high_reset), | ||
1046 | __ATTR_NULL | ||
1047 | }; | 1052 | }; |
1053 | ATTRIBUTE_GROUPS(vio_bus); | ||
1048 | 1054 | ||
1049 | static void vio_cmo_sysfs_init(void) | 1055 | static void vio_cmo_sysfs_init(void) |
1050 | { | 1056 | { |
1051 | vio_bus_type.dev_attrs = vio_cmo_dev_attrs; | 1057 | vio_bus_type.dev_attrs = vio_cmo_dev_attrs; |
1052 | vio_bus_type.bus_attrs = vio_cmo_bus_attrs; | 1058 | vio_bus_type.bus_groups = vio_bus_groups; |
1053 | } | 1059 | } |
1054 | #else /* CONFIG_PPC_SMLPAR */ | 1060 | #else /* CONFIG_PPC_SMLPAR */ |
1055 | int vio_cmo_entitlement_update(size_t new_entitlement) { return 0; } | 1061 | int vio_cmo_entitlement_update(size_t new_entitlement) { return 0; } |
@@ -1413,8 +1419,7 @@ struct vio_dev *vio_register_device_node(struct device_node *of_node) | |||
1413 | 1419 | ||
1414 | /* needed to ensure proper operation of coherent allocations | 1420 | /* needed to ensure proper operation of coherent allocations |
1415 | * later, in case driver doesn't set it explicitly */ | 1421 | * later, in case driver doesn't set it explicitly */ |
1416 | dma_set_mask(&viodev->dev, DMA_BIT_MASK(64)); | 1422 | dma_set_mask_and_coherent(&viodev->dev, DMA_BIT_MASK(64)); |
1417 | dma_set_coherent_mask(&viodev->dev, DMA_BIT_MASK(64)); | ||
1418 | } | 1423 | } |
1419 | 1424 | ||
1420 | /* register with generic device framework */ | 1425 | /* register with generic device framework */ |
@@ -1530,11 +1535,15 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, | |||
1530 | const char *cp; | 1535 | const char *cp; |
1531 | 1536 | ||
1532 | dn = dev->of_node; | 1537 | dn = dev->of_node; |
1533 | if (!dn) | 1538 | if (!dn) { |
1534 | return -ENODEV; | 1539 | strcpy(buf, "\n"); |
1540 | return strlen(buf); | ||
1541 | } | ||
1535 | cp = of_get_property(dn, "compatible", NULL); | 1542 | cp = of_get_property(dn, "compatible", NULL); |
1536 | if (!cp) | 1543 | if (!cp) { |
1537 | return -ENODEV; | 1544 | strcpy(buf, "\n"); |
1545 | return strlen(buf); | ||
1546 | } | ||
1538 | 1547 | ||
1539 | return sprintf(buf, "vio:T%sS%s\n", vio_dev->type, cp); | 1548 | return sprintf(buf, "vio:T%sS%s\n", vio_dev->type, cp); |
1540 | } | 1549 | } |
diff --git a/arch/powerpc/kvm/44x.c b/arch/powerpc/kvm/44x.c index 2f5c6b6d6877..93221e87b911 100644 --- a/arch/powerpc/kvm/44x.c +++ b/arch/powerpc/kvm/44x.c | |||
@@ -31,13 +31,13 @@ | |||
31 | #include "44x_tlb.h" | 31 | #include "44x_tlb.h" |
32 | #include "booke.h" | 32 | #include "booke.h" |
33 | 33 | ||
34 | void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu) | 34 | static void kvmppc_core_vcpu_load_44x(struct kvm_vcpu *vcpu, int cpu) |
35 | { | 35 | { |
36 | kvmppc_booke_vcpu_load(vcpu, cpu); | 36 | kvmppc_booke_vcpu_load(vcpu, cpu); |
37 | kvmppc_44x_tlb_load(vcpu); | 37 | kvmppc_44x_tlb_load(vcpu); |
38 | } | 38 | } |
39 | 39 | ||
40 | void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu) | 40 | static void kvmppc_core_vcpu_put_44x(struct kvm_vcpu *vcpu) |
41 | { | 41 | { |
42 | kvmppc_44x_tlb_put(vcpu); | 42 | kvmppc_44x_tlb_put(vcpu); |
43 | kvmppc_booke_vcpu_put(vcpu); | 43 | kvmppc_booke_vcpu_put(vcpu); |
@@ -114,29 +114,32 @@ int kvmppc_core_vcpu_translate(struct kvm_vcpu *vcpu, | |||
114 | return 0; | 114 | return 0; |
115 | } | 115 | } |
116 | 116 | ||
117 | void kvmppc_core_get_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) | 117 | static int kvmppc_core_get_sregs_44x(struct kvm_vcpu *vcpu, |
118 | struct kvm_sregs *sregs) | ||
118 | { | 119 | { |
119 | kvmppc_get_sregs_ivor(vcpu, sregs); | 120 | return kvmppc_get_sregs_ivor(vcpu, sregs); |
120 | } | 121 | } |
121 | 122 | ||
122 | int kvmppc_core_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) | 123 | static int kvmppc_core_set_sregs_44x(struct kvm_vcpu *vcpu, |
124 | struct kvm_sregs *sregs) | ||
123 | { | 125 | { |
124 | return kvmppc_set_sregs_ivor(vcpu, sregs); | 126 | return kvmppc_set_sregs_ivor(vcpu, sregs); |
125 | } | 127 | } |
126 | 128 | ||
127 | int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id, | 129 | static int kvmppc_get_one_reg_44x(struct kvm_vcpu *vcpu, u64 id, |
128 | union kvmppc_one_reg *val) | 130 | union kvmppc_one_reg *val) |
129 | { | 131 | { |
130 | return -EINVAL; | 132 | return -EINVAL; |
131 | } | 133 | } |
132 | 134 | ||
133 | int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id, | 135 | static int kvmppc_set_one_reg_44x(struct kvm_vcpu *vcpu, u64 id, |
134 | union kvmppc_one_reg *val) | 136 | union kvmppc_one_reg *val) |
135 | { | 137 | { |
136 | return -EINVAL; | 138 | return -EINVAL; |
137 | } | 139 | } |
138 | 140 | ||
139 | struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id) | 141 | static struct kvm_vcpu *kvmppc_core_vcpu_create_44x(struct kvm *kvm, |
142 | unsigned int id) | ||
140 | { | 143 | { |
141 | struct kvmppc_vcpu_44x *vcpu_44x; | 144 | struct kvmppc_vcpu_44x *vcpu_44x; |
142 | struct kvm_vcpu *vcpu; | 145 | struct kvm_vcpu *vcpu; |
@@ -167,7 +170,7 @@ out: | |||
167 | return ERR_PTR(err); | 170 | return ERR_PTR(err); |
168 | } | 171 | } |
169 | 172 | ||
170 | void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu) | 173 | static void kvmppc_core_vcpu_free_44x(struct kvm_vcpu *vcpu) |
171 | { | 174 | { |
172 | struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); | 175 | struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); |
173 | 176 | ||
@@ -176,28 +179,53 @@ void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu) | |||
176 | kmem_cache_free(kvm_vcpu_cache, vcpu_44x); | 179 | kmem_cache_free(kvm_vcpu_cache, vcpu_44x); |
177 | } | 180 | } |
178 | 181 | ||
179 | int kvmppc_core_init_vm(struct kvm *kvm) | 182 | static int kvmppc_core_init_vm_44x(struct kvm *kvm) |
180 | { | 183 | { |
181 | return 0; | 184 | return 0; |
182 | } | 185 | } |
183 | 186 | ||
184 | void kvmppc_core_destroy_vm(struct kvm *kvm) | 187 | static void kvmppc_core_destroy_vm_44x(struct kvm *kvm) |
185 | { | 188 | { |
186 | } | 189 | } |
187 | 190 | ||
191 | static struct kvmppc_ops kvm_ops_44x = { | ||
192 | .get_sregs = kvmppc_core_get_sregs_44x, | ||
193 | .set_sregs = kvmppc_core_set_sregs_44x, | ||
194 | .get_one_reg = kvmppc_get_one_reg_44x, | ||
195 | .set_one_reg = kvmppc_set_one_reg_44x, | ||
196 | .vcpu_load = kvmppc_core_vcpu_load_44x, | ||
197 | .vcpu_put = kvmppc_core_vcpu_put_44x, | ||
198 | .vcpu_create = kvmppc_core_vcpu_create_44x, | ||
199 | .vcpu_free = kvmppc_core_vcpu_free_44x, | ||
200 | .mmu_destroy = kvmppc_mmu_destroy_44x, | ||
201 | .init_vm = kvmppc_core_init_vm_44x, | ||
202 | .destroy_vm = kvmppc_core_destroy_vm_44x, | ||
203 | .emulate_op = kvmppc_core_emulate_op_44x, | ||
204 | .emulate_mtspr = kvmppc_core_emulate_mtspr_44x, | ||
205 | .emulate_mfspr = kvmppc_core_emulate_mfspr_44x, | ||
206 | }; | ||
207 | |||
188 | static int __init kvmppc_44x_init(void) | 208 | static int __init kvmppc_44x_init(void) |
189 | { | 209 | { |
190 | int r; | 210 | int r; |
191 | 211 | ||
192 | r = kvmppc_booke_init(); | 212 | r = kvmppc_booke_init(); |
193 | if (r) | 213 | if (r) |
194 | return r; | 214 | goto err_out; |
215 | |||
216 | r = kvm_init(NULL, sizeof(struct kvmppc_vcpu_44x), 0, THIS_MODULE); | ||
217 | if (r) | ||
218 | goto err_out; | ||
219 | kvm_ops_44x.owner = THIS_MODULE; | ||
220 | kvmppc_pr_ops = &kvm_ops_44x; | ||
195 | 221 | ||
196 | return kvm_init(NULL, sizeof(struct kvmppc_vcpu_44x), 0, THIS_MODULE); | 222 | err_out: |
223 | return r; | ||
197 | } | 224 | } |
198 | 225 | ||
199 | static void __exit kvmppc_44x_exit(void) | 226 | static void __exit kvmppc_44x_exit(void) |
200 | { | 227 | { |
228 | kvmppc_pr_ops = NULL; | ||
201 | kvmppc_booke_exit(); | 229 | kvmppc_booke_exit(); |
202 | } | 230 | } |
203 | 231 | ||
diff --git a/arch/powerpc/kvm/44x_emulate.c b/arch/powerpc/kvm/44x_emulate.c index 35ec0a8547da..92c9ab4bcfec 100644 --- a/arch/powerpc/kvm/44x_emulate.c +++ b/arch/powerpc/kvm/44x_emulate.c | |||
@@ -91,8 +91,8 @@ static int emulate_mfdcr(struct kvm_vcpu *vcpu, int rt, int dcrn) | |||
91 | return EMULATE_DONE; | 91 | return EMULATE_DONE; |
92 | } | 92 | } |
93 | 93 | ||
94 | int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, | 94 | int kvmppc_core_emulate_op_44x(struct kvm_run *run, struct kvm_vcpu *vcpu, |
95 | unsigned int inst, int *advance) | 95 | unsigned int inst, int *advance) |
96 | { | 96 | { |
97 | int emulated = EMULATE_DONE; | 97 | int emulated = EMULATE_DONE; |
98 | int dcrn = get_dcrn(inst); | 98 | int dcrn = get_dcrn(inst); |
@@ -152,7 +152,7 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
152 | return emulated; | 152 | return emulated; |
153 | } | 153 | } |
154 | 154 | ||
155 | int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val) | 155 | int kvmppc_core_emulate_mtspr_44x(struct kvm_vcpu *vcpu, int sprn, ulong spr_val) |
156 | { | 156 | { |
157 | int emulated = EMULATE_DONE; | 157 | int emulated = EMULATE_DONE; |
158 | 158 | ||
@@ -172,7 +172,7 @@ int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val) | |||
172 | return emulated; | 172 | return emulated; |
173 | } | 173 | } |
174 | 174 | ||
175 | int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val) | 175 | int kvmppc_core_emulate_mfspr_44x(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val) |
176 | { | 176 | { |
177 | int emulated = EMULATE_DONE; | 177 | int emulated = EMULATE_DONE; |
178 | 178 | ||
diff --git a/arch/powerpc/kvm/44x_tlb.c b/arch/powerpc/kvm/44x_tlb.c index ed0385448148..0deef1082e02 100644 --- a/arch/powerpc/kvm/44x_tlb.c +++ b/arch/powerpc/kvm/44x_tlb.c | |||
@@ -268,7 +268,7 @@ static void kvmppc_44x_shadow_release(struct kvmppc_vcpu_44x *vcpu_44x, | |||
268 | trace_kvm_stlb_inval(stlb_index); | 268 | trace_kvm_stlb_inval(stlb_index); |
269 | } | 269 | } |
270 | 270 | ||
271 | void kvmppc_mmu_destroy(struct kvm_vcpu *vcpu) | 271 | void kvmppc_mmu_destroy_44x(struct kvm_vcpu *vcpu) |
272 | { | 272 | { |
273 | struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); | 273 | struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu); |
274 | int i; | 274 | int i; |
diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig index ffaef2cb101a..141b2027189a 100644 --- a/arch/powerpc/kvm/Kconfig +++ b/arch/powerpc/kvm/Kconfig | |||
@@ -6,6 +6,7 @@ source "virt/kvm/Kconfig" | |||
6 | 6 | ||
7 | menuconfig VIRTUALIZATION | 7 | menuconfig VIRTUALIZATION |
8 | bool "Virtualization" | 8 | bool "Virtualization" |
9 | depends on !CPU_LITTLE_ENDIAN | ||
9 | ---help--- | 10 | ---help--- |
10 | Say Y here to get to see options for using your Linux host to run | 11 | Say Y here to get to see options for using your Linux host to run |
11 | other operating systems inside virtual machines (guests). | 12 | other operating systems inside virtual machines (guests). |
@@ -34,17 +35,20 @@ config KVM_BOOK3S_64_HANDLER | |||
34 | bool | 35 | bool |
35 | select KVM_BOOK3S_HANDLER | 36 | select KVM_BOOK3S_HANDLER |
36 | 37 | ||
37 | config KVM_BOOK3S_PR | 38 | config KVM_BOOK3S_PR_POSSIBLE |
38 | bool | 39 | bool |
39 | select KVM_MMIO | 40 | select KVM_MMIO |
40 | select MMU_NOTIFIER | 41 | select MMU_NOTIFIER |
41 | 42 | ||
43 | config KVM_BOOK3S_HV_POSSIBLE | ||
44 | bool | ||
45 | |||
42 | config KVM_BOOK3S_32 | 46 | config KVM_BOOK3S_32 |
43 | tristate "KVM support for PowerPC book3s_32 processors" | 47 | tristate "KVM support for PowerPC book3s_32 processors" |
44 | depends on PPC_BOOK3S_32 && !SMP && !PTE_64BIT | 48 | depends on PPC_BOOK3S_32 && !SMP && !PTE_64BIT |
45 | select KVM | 49 | select KVM |
46 | select KVM_BOOK3S_32_HANDLER | 50 | select KVM_BOOK3S_32_HANDLER |
47 | select KVM_BOOK3S_PR | 51 | select KVM_BOOK3S_PR_POSSIBLE |
48 | ---help--- | 52 | ---help--- |
49 | Support running unmodified book3s_32 guest kernels | 53 | Support running unmodified book3s_32 guest kernels |
50 | in virtual machines on book3s_32 host processors. | 54 | in virtual machines on book3s_32 host processors. |
@@ -59,6 +63,7 @@ config KVM_BOOK3S_64 | |||
59 | depends on PPC_BOOK3S_64 | 63 | depends on PPC_BOOK3S_64 |
60 | select KVM_BOOK3S_64_HANDLER | 64 | select KVM_BOOK3S_64_HANDLER |
61 | select KVM | 65 | select KVM |
66 | select KVM_BOOK3S_PR_POSSIBLE if !KVM_BOOK3S_HV_POSSIBLE | ||
62 | ---help--- | 67 | ---help--- |
63 | Support running unmodified book3s_64 and book3s_32 guest kernels | 68 | Support running unmodified book3s_64 and book3s_32 guest kernels |
64 | in virtual machines on book3s_64 host processors. | 69 | in virtual machines on book3s_64 host processors. |
@@ -69,8 +74,9 @@ config KVM_BOOK3S_64 | |||
69 | If unsure, say N. | 74 | If unsure, say N. |
70 | 75 | ||
71 | config KVM_BOOK3S_64_HV | 76 | config KVM_BOOK3S_64_HV |
72 | bool "KVM support for POWER7 and PPC970 using hypervisor mode in host" | 77 | tristate "KVM support for POWER7 and PPC970 using hypervisor mode in host" |
73 | depends on KVM_BOOK3S_64 | 78 | depends on KVM_BOOK3S_64 |
79 | select KVM_BOOK3S_HV_POSSIBLE | ||
74 | select MMU_NOTIFIER | 80 | select MMU_NOTIFIER |
75 | select CMA | 81 | select CMA |
76 | ---help--- | 82 | ---help--- |
@@ -89,9 +95,20 @@ config KVM_BOOK3S_64_HV | |||
89 | If unsure, say N. | 95 | If unsure, say N. |
90 | 96 | ||
91 | config KVM_BOOK3S_64_PR | 97 | config KVM_BOOK3S_64_PR |
92 | def_bool y | 98 | tristate "KVM support without using hypervisor mode in host" |
93 | depends on KVM_BOOK3S_64 && !KVM_BOOK3S_64_HV | 99 | depends on KVM_BOOK3S_64 |
94 | select KVM_BOOK3S_PR | 100 | select KVM_BOOK3S_PR_POSSIBLE |
101 | ---help--- | ||
102 | Support running guest kernels in virtual machines on processors | ||
103 | without using hypervisor mode in the host, by running the | ||
104 | guest in user mode (problem state) and emulating all | ||
105 | privileged instructions and registers. | ||
106 | |||
107 | This is not as fast as using hypervisor mode, but works on | ||
108 | machines where hypervisor mode is not available or not usable, | ||
109 | and can emulate processors that are different from the host | ||
110 | processor, including emulating 32-bit processors on a 64-bit | ||
111 | host. | ||
95 | 112 | ||
96 | config KVM_BOOKE_HV | 113 | config KVM_BOOKE_HV |
97 | bool | 114 | bool |
diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile index 6646c952c5e3..ce569b6bf4d8 100644 --- a/arch/powerpc/kvm/Makefile +++ b/arch/powerpc/kvm/Makefile | |||
@@ -53,41 +53,51 @@ kvm-e500mc-objs := \ | |||
53 | e500_emulate.o | 53 | e500_emulate.o |
54 | kvm-objs-$(CONFIG_KVM_E500MC) := $(kvm-e500mc-objs) | 54 | kvm-objs-$(CONFIG_KVM_E500MC) := $(kvm-e500mc-objs) |
55 | 55 | ||
56 | kvm-book3s_64-objs-$(CONFIG_KVM_BOOK3S_64_PR) := \ | 56 | kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HANDLER) := \ |
57 | $(KVM)/coalesced_mmio.o \ | 57 | book3s_64_vio_hv.o |
58 | |||
59 | kvm-pr-y := \ | ||
58 | fpu.o \ | 60 | fpu.o \ |
59 | book3s_paired_singles.o \ | 61 | book3s_paired_singles.o \ |
60 | book3s_pr.o \ | 62 | book3s_pr.o \ |
61 | book3s_pr_papr.o \ | 63 | book3s_pr_papr.o \ |
62 | book3s_64_vio_hv.o \ | ||
63 | book3s_emulate.o \ | 64 | book3s_emulate.o \ |
64 | book3s_interrupts.o \ | 65 | book3s_interrupts.o \ |
65 | book3s_mmu_hpte.o \ | 66 | book3s_mmu_hpte.o \ |
66 | book3s_64_mmu_host.o \ | 67 | book3s_64_mmu_host.o \ |
67 | book3s_64_mmu.o \ | 68 | book3s_64_mmu.o \ |
68 | book3s_32_mmu.o | 69 | book3s_32_mmu.o |
69 | kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_PR) := \ | 70 | |
71 | ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE | ||
72 | kvm-book3s_64-module-objs := \ | ||
73 | $(KVM)/coalesced_mmio.o | ||
74 | |||
75 | kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HANDLER) += \ | ||
70 | book3s_rmhandlers.o | 76 | book3s_rmhandlers.o |
77 | endif | ||
71 | 78 | ||
72 | kvm-book3s_64-objs-$(CONFIG_KVM_BOOK3S_64_HV) := \ | 79 | kvm-hv-y += \ |
73 | book3s_hv.o \ | 80 | book3s_hv.o \ |
74 | book3s_hv_interrupts.o \ | 81 | book3s_hv_interrupts.o \ |
75 | book3s_64_mmu_hv.o | 82 | book3s_64_mmu_hv.o |
83 | |||
76 | kvm-book3s_64-builtin-xics-objs-$(CONFIG_KVM_XICS) := \ | 84 | kvm-book3s_64-builtin-xics-objs-$(CONFIG_KVM_XICS) := \ |
77 | book3s_hv_rm_xics.o | 85 | book3s_hv_rm_xics.o |
78 | kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HV) := \ | 86 | |
87 | ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE | ||
88 | kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HANDLER) += \ | ||
79 | book3s_hv_rmhandlers.o \ | 89 | book3s_hv_rmhandlers.o \ |
80 | book3s_hv_rm_mmu.o \ | 90 | book3s_hv_rm_mmu.o \ |
81 | book3s_64_vio_hv.o \ | ||
82 | book3s_hv_ras.o \ | 91 | book3s_hv_ras.o \ |
83 | book3s_hv_builtin.o \ | 92 | book3s_hv_builtin.o \ |
84 | book3s_hv_cma.o \ | 93 | book3s_hv_cma.o \ |
85 | $(kvm-book3s_64-builtin-xics-objs-y) | 94 | $(kvm-book3s_64-builtin-xics-objs-y) |
95 | endif | ||
86 | 96 | ||
87 | kvm-book3s_64-objs-$(CONFIG_KVM_XICS) += \ | 97 | kvm-book3s_64-objs-$(CONFIG_KVM_XICS) += \ |
88 | book3s_xics.o | 98 | book3s_xics.o |
89 | 99 | ||
90 | kvm-book3s_64-module-objs := \ | 100 | kvm-book3s_64-module-objs += \ |
91 | $(KVM)/kvm_main.o \ | 101 | $(KVM)/kvm_main.o \ |
92 | $(KVM)/eventfd.o \ | 102 | $(KVM)/eventfd.o \ |
93 | powerpc.o \ | 103 | powerpc.o \ |
@@ -123,4 +133,7 @@ obj-$(CONFIG_KVM_E500MC) += kvm.o | |||
123 | obj-$(CONFIG_KVM_BOOK3S_64) += kvm.o | 133 | obj-$(CONFIG_KVM_BOOK3S_64) += kvm.o |
124 | obj-$(CONFIG_KVM_BOOK3S_32) += kvm.o | 134 | obj-$(CONFIG_KVM_BOOK3S_32) += kvm.o |
125 | 135 | ||
136 | obj-$(CONFIG_KVM_BOOK3S_64_PR) += kvm-pr.o | ||
137 | obj-$(CONFIG_KVM_BOOK3S_64_HV) += kvm-hv.o | ||
138 | |||
126 | obj-y += $(kvm-book3s_64-builtin-objs-y) | 139 | obj-y += $(kvm-book3s_64-builtin-objs-y) |
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c index 700df6f1d32c..8912608b7e1b 100644 --- a/arch/powerpc/kvm/book3s.c +++ b/arch/powerpc/kvm/book3s.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/vmalloc.h> | 34 | #include <linux/vmalloc.h> |
35 | #include <linux/highmem.h> | 35 | #include <linux/highmem.h> |
36 | 36 | ||
37 | #include "book3s.h" | ||
37 | #include "trace.h" | 38 | #include "trace.h" |
38 | 39 | ||
39 | #define VCPU_STAT(x) offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU | 40 | #define VCPU_STAT(x) offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU |
@@ -69,6 +70,50 @@ void kvmppc_core_load_guest_debugstate(struct kvm_vcpu *vcpu) | |||
69 | { | 70 | { |
70 | } | 71 | } |
71 | 72 | ||
73 | static inline unsigned long kvmppc_interrupt_offset(struct kvm_vcpu *vcpu) | ||
74 | { | ||
75 | if (!is_kvmppc_hv_enabled(vcpu->kvm)) | ||
76 | return to_book3s(vcpu)->hior; | ||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | static inline void kvmppc_update_int_pending(struct kvm_vcpu *vcpu, | ||
81 | unsigned long pending_now, unsigned long old_pending) | ||
82 | { | ||
83 | if (is_kvmppc_hv_enabled(vcpu->kvm)) | ||
84 | return; | ||
85 | if (pending_now) | ||
86 | vcpu->arch.shared->int_pending = 1; | ||
87 | else if (old_pending) | ||
88 | vcpu->arch.shared->int_pending = 0; | ||
89 | } | ||
90 | |||
91 | static inline bool kvmppc_critical_section(struct kvm_vcpu *vcpu) | ||
92 | { | ||
93 | ulong crit_raw; | ||
94 | ulong crit_r1; | ||
95 | bool crit; | ||
96 | |||
97 | if (is_kvmppc_hv_enabled(vcpu->kvm)) | ||
98 | return false; | ||
99 | |||
100 | crit_raw = vcpu->arch.shared->critical; | ||
101 | crit_r1 = kvmppc_get_gpr(vcpu, 1); | ||
102 | |||
103 | /* Truncate crit indicators in 32 bit mode */ | ||
104 | if (!(vcpu->arch.shared->msr & MSR_SF)) { | ||
105 | crit_raw &= 0xffffffff; | ||
106 | crit_r1 &= 0xffffffff; | ||
107 | } | ||
108 | |||
109 | /* Critical section when crit == r1 */ | ||
110 | crit = (crit_raw == crit_r1); | ||
111 | /* ... and we're in supervisor mode */ | ||
112 | crit = crit && !(vcpu->arch.shared->msr & MSR_PR); | ||
113 | |||
114 | return crit; | ||
115 | } | ||
116 | |||
72 | void kvmppc_inject_interrupt(struct kvm_vcpu *vcpu, int vec, u64 flags) | 117 | void kvmppc_inject_interrupt(struct kvm_vcpu *vcpu, int vec, u64 flags) |
73 | { | 118 | { |
74 | vcpu->arch.shared->srr0 = kvmppc_get_pc(vcpu); | 119 | vcpu->arch.shared->srr0 = kvmppc_get_pc(vcpu); |
@@ -126,28 +171,32 @@ void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec) | |||
126 | printk(KERN_INFO "Queueing interrupt %x\n", vec); | 171 | printk(KERN_INFO "Queueing interrupt %x\n", vec); |
127 | #endif | 172 | #endif |
128 | } | 173 | } |
129 | 174 | EXPORT_SYMBOL_GPL(kvmppc_book3s_queue_irqprio); | |
130 | 175 | ||
131 | void kvmppc_core_queue_program(struct kvm_vcpu *vcpu, ulong flags) | 176 | void kvmppc_core_queue_program(struct kvm_vcpu *vcpu, ulong flags) |
132 | { | 177 | { |
133 | /* might as well deliver this straight away */ | 178 | /* might as well deliver this straight away */ |
134 | kvmppc_inject_interrupt(vcpu, BOOK3S_INTERRUPT_PROGRAM, flags); | 179 | kvmppc_inject_interrupt(vcpu, BOOK3S_INTERRUPT_PROGRAM, flags); |
135 | } | 180 | } |
181 | EXPORT_SYMBOL_GPL(kvmppc_core_queue_program); | ||
136 | 182 | ||
137 | void kvmppc_core_queue_dec(struct kvm_vcpu *vcpu) | 183 | void kvmppc_core_queue_dec(struct kvm_vcpu *vcpu) |
138 | { | 184 | { |
139 | kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_DECREMENTER); | 185 | kvmppc_book3s_queue_irqprio(vcpu, BOOK3S_INTERRUPT_DECREMENTER); |
140 | } | 186 | } |
187 | EXPORT_SYMBOL_GPL(kvmppc_core_queue_dec); | ||
141 | 188 | ||
142 | int kvmppc_core_pending_dec(struct kvm_vcpu *vcpu) | 189 | int kvmppc_core_pending_dec(struct kvm_vcpu *vcpu) |
143 | { | 190 | { |
144 | return test_bit(BOOK3S_IRQPRIO_DECREMENTER, &vcpu->arch.pending_exceptions); | 191 | return test_bit(BOOK3S_IRQPRIO_DECREMENTER, &vcpu->arch.pending_exceptions); |
145 | } | 192 | } |
193 | EXPORT_SYMBOL_GPL(kvmppc_core_pending_dec); | ||
146 | 194 | ||
147 | void kvmppc_core_dequeue_dec(struct kvm_vcpu *vcpu) | 195 | void kvmppc_core_dequeue_dec(struct kvm_vcpu *vcpu) |
148 | { | 196 | { |
149 | kvmppc_book3s_dequeue_irqprio(vcpu, BOOK3S_INTERRUPT_DECREMENTER); | 197 | kvmppc_book3s_dequeue_irqprio(vcpu, BOOK3S_INTERRUPT_DECREMENTER); |
150 | } | 198 | } |
199 | EXPORT_SYMBOL_GPL(kvmppc_core_dequeue_dec); | ||
151 | 200 | ||
152 | void kvmppc_core_queue_external(struct kvm_vcpu *vcpu, | 201 | void kvmppc_core_queue_external(struct kvm_vcpu *vcpu, |
153 | struct kvm_interrupt *irq) | 202 | struct kvm_interrupt *irq) |
@@ -285,8 +334,10 @@ int kvmppc_core_prepare_to_enter(struct kvm_vcpu *vcpu) | |||
285 | 334 | ||
286 | return 0; | 335 | return 0; |
287 | } | 336 | } |
337 | EXPORT_SYMBOL_GPL(kvmppc_core_prepare_to_enter); | ||
288 | 338 | ||
289 | pfn_t kvmppc_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn) | 339 | pfn_t kvmppc_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn, bool writing, |
340 | bool *writable) | ||
290 | { | 341 | { |
291 | ulong mp_pa = vcpu->arch.magic_page_pa; | 342 | ulong mp_pa = vcpu->arch.magic_page_pa; |
292 | 343 | ||
@@ -302,20 +353,23 @@ pfn_t kvmppc_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn) | |||
302 | 353 | ||
303 | pfn = (pfn_t)virt_to_phys((void*)shared_page) >> PAGE_SHIFT; | 354 | pfn = (pfn_t)virt_to_phys((void*)shared_page) >> PAGE_SHIFT; |
304 | get_page(pfn_to_page(pfn)); | 355 | get_page(pfn_to_page(pfn)); |
356 | if (writable) | ||
357 | *writable = true; | ||
305 | return pfn; | 358 | return pfn; |
306 | } | 359 | } |
307 | 360 | ||
308 | return gfn_to_pfn(vcpu->kvm, gfn); | 361 | return gfn_to_pfn_prot(vcpu->kvm, gfn, writing, writable); |
309 | } | 362 | } |
363 | EXPORT_SYMBOL_GPL(kvmppc_gfn_to_pfn); | ||
310 | 364 | ||
311 | static int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, bool data, | 365 | static int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, bool data, |
312 | struct kvmppc_pte *pte) | 366 | bool iswrite, struct kvmppc_pte *pte) |
313 | { | 367 | { |
314 | int relocated = (vcpu->arch.shared->msr & (data ? MSR_DR : MSR_IR)); | 368 | int relocated = (vcpu->arch.shared->msr & (data ? MSR_DR : MSR_IR)); |
315 | int r; | 369 | int r; |
316 | 370 | ||
317 | if (relocated) { | 371 | if (relocated) { |
318 | r = vcpu->arch.mmu.xlate(vcpu, eaddr, pte, data); | 372 | r = vcpu->arch.mmu.xlate(vcpu, eaddr, pte, data, iswrite); |
319 | } else { | 373 | } else { |
320 | pte->eaddr = eaddr; | 374 | pte->eaddr = eaddr; |
321 | pte->raddr = eaddr & KVM_PAM; | 375 | pte->raddr = eaddr & KVM_PAM; |
@@ -361,7 +415,7 @@ int kvmppc_st(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr, | |||
361 | 415 | ||
362 | vcpu->stat.st++; | 416 | vcpu->stat.st++; |
363 | 417 | ||
364 | if (kvmppc_xlate(vcpu, *eaddr, data, &pte)) | 418 | if (kvmppc_xlate(vcpu, *eaddr, data, true, &pte)) |
365 | return -ENOENT; | 419 | return -ENOENT; |
366 | 420 | ||
367 | *eaddr = pte.raddr; | 421 | *eaddr = pte.raddr; |
@@ -374,6 +428,7 @@ int kvmppc_st(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr, | |||
374 | 428 | ||
375 | return EMULATE_DONE; | 429 | return EMULATE_DONE; |
376 | } | 430 | } |
431 | EXPORT_SYMBOL_GPL(kvmppc_st); | ||
377 | 432 | ||
378 | int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr, | 433 | int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr, |
379 | bool data) | 434 | bool data) |
@@ -383,7 +438,7 @@ int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr, | |||
383 | 438 | ||
384 | vcpu->stat.ld++; | 439 | vcpu->stat.ld++; |
385 | 440 | ||
386 | if (kvmppc_xlate(vcpu, *eaddr, data, &pte)) | 441 | if (kvmppc_xlate(vcpu, *eaddr, data, false, &pte)) |
387 | goto nopte; | 442 | goto nopte; |
388 | 443 | ||
389 | *eaddr = pte.raddr; | 444 | *eaddr = pte.raddr; |
@@ -404,6 +459,7 @@ nopte: | |||
404 | mmio: | 459 | mmio: |
405 | return EMULATE_DO_MMIO; | 460 | return EMULATE_DO_MMIO; |
406 | } | 461 | } |
462 | EXPORT_SYMBOL_GPL(kvmppc_ld); | ||
407 | 463 | ||
408 | int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) | 464 | int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) |
409 | { | 465 | { |
@@ -419,6 +475,18 @@ void kvmppc_subarch_vcpu_uninit(struct kvm_vcpu *vcpu) | |||
419 | { | 475 | { |
420 | } | 476 | } |
421 | 477 | ||
478 | int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu, | ||
479 | struct kvm_sregs *sregs) | ||
480 | { | ||
481 | return vcpu->kvm->arch.kvm_ops->get_sregs(vcpu, sregs); | ||
482 | } | ||
483 | |||
484 | int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, | ||
485 | struct kvm_sregs *sregs) | ||
486 | { | ||
487 | return vcpu->kvm->arch.kvm_ops->set_sregs(vcpu, sregs); | ||
488 | } | ||
489 | |||
422 | int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) | 490 | int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) |
423 | { | 491 | { |
424 | int i; | 492 | int i; |
@@ -495,8 +563,7 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) | |||
495 | if (size > sizeof(val)) | 563 | if (size > sizeof(val)) |
496 | return -EINVAL; | 564 | return -EINVAL; |
497 | 565 | ||
498 | r = kvmppc_get_one_reg(vcpu, reg->id, &val); | 566 | r = vcpu->kvm->arch.kvm_ops->get_one_reg(vcpu, reg->id, &val); |
499 | |||
500 | if (r == -EINVAL) { | 567 | if (r == -EINVAL) { |
501 | r = 0; | 568 | r = 0; |
502 | switch (reg->id) { | 569 | switch (reg->id) { |
@@ -528,6 +595,9 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) | |||
528 | } | 595 | } |
529 | val = get_reg_val(reg->id, vcpu->arch.vscr.u[3]); | 596 | val = get_reg_val(reg->id, vcpu->arch.vscr.u[3]); |
530 | break; | 597 | break; |
598 | case KVM_REG_PPC_VRSAVE: | ||
599 | val = get_reg_val(reg->id, vcpu->arch.vrsave); | ||
600 | break; | ||
531 | #endif /* CONFIG_ALTIVEC */ | 601 | #endif /* CONFIG_ALTIVEC */ |
532 | case KVM_REG_PPC_DEBUG_INST: { | 602 | case KVM_REG_PPC_DEBUG_INST: { |
533 | u32 opcode = INS_TW; | 603 | u32 opcode = INS_TW; |
@@ -572,8 +642,7 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) | |||
572 | if (copy_from_user(&val, (char __user *)(unsigned long)reg->addr, size)) | 642 | if (copy_from_user(&val, (char __user *)(unsigned long)reg->addr, size)) |
573 | return -EFAULT; | 643 | return -EFAULT; |
574 | 644 | ||
575 | r = kvmppc_set_one_reg(vcpu, reg->id, &val); | 645 | r = vcpu->kvm->arch.kvm_ops->set_one_reg(vcpu, reg->id, &val); |
576 | |||
577 | if (r == -EINVAL) { | 646 | if (r == -EINVAL) { |
578 | r = 0; | 647 | r = 0; |
579 | switch (reg->id) { | 648 | switch (reg->id) { |
@@ -605,6 +674,13 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) | |||
605 | } | 674 | } |
606 | vcpu->arch.vscr.u[3] = set_reg_val(reg->id, val); | 675 | vcpu->arch.vscr.u[3] = set_reg_val(reg->id, val); |
607 | break; | 676 | break; |
677 | case KVM_REG_PPC_VRSAVE: | ||
678 | if (!cpu_has_feature(CPU_FTR_ALTIVEC)) { | ||
679 | r = -ENXIO; | ||
680 | break; | ||
681 | } | ||
682 | vcpu->arch.vrsave = set_reg_val(reg->id, val); | ||
683 | break; | ||
608 | #endif /* CONFIG_ALTIVEC */ | 684 | #endif /* CONFIG_ALTIVEC */ |
609 | #ifdef CONFIG_KVM_XICS | 685 | #ifdef CONFIG_KVM_XICS |
610 | case KVM_REG_PPC_ICP_STATE: | 686 | case KVM_REG_PPC_ICP_STATE: |
@@ -625,6 +701,27 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) | |||
625 | return r; | 701 | return r; |
626 | } | 702 | } |
627 | 703 | ||
704 | void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu) | ||
705 | { | ||
706 | vcpu->kvm->arch.kvm_ops->vcpu_load(vcpu, cpu); | ||
707 | } | ||
708 | |||
709 | void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu) | ||
710 | { | ||
711 | vcpu->kvm->arch.kvm_ops->vcpu_put(vcpu); | ||
712 | } | ||
713 | |||
714 | void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 msr) | ||
715 | { | ||
716 | vcpu->kvm->arch.kvm_ops->set_msr(vcpu, msr); | ||
717 | } | ||
718 | EXPORT_SYMBOL_GPL(kvmppc_set_msr); | ||
719 | |||
720 | int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) | ||
721 | { | ||
722 | return vcpu->kvm->arch.kvm_ops->vcpu_run(kvm_run, vcpu); | ||
723 | } | ||
724 | |||
628 | int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu, | 725 | int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu, |
629 | struct kvm_translation *tr) | 726 | struct kvm_translation *tr) |
630 | { | 727 | { |
@@ -644,3 +741,141 @@ void kvmppc_decrementer_func(unsigned long data) | |||
644 | kvmppc_core_queue_dec(vcpu); | 741 | kvmppc_core_queue_dec(vcpu); |
645 | kvm_vcpu_kick(vcpu); | 742 | kvm_vcpu_kick(vcpu); |
646 | } | 743 | } |
744 | |||
745 | struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id) | ||
746 | { | ||
747 | return kvm->arch.kvm_ops->vcpu_create(kvm, id); | ||
748 | } | ||
749 | |||
750 | void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu) | ||
751 | { | ||
752 | vcpu->kvm->arch.kvm_ops->vcpu_free(vcpu); | ||
753 | } | ||
754 | |||
755 | int kvmppc_core_check_requests(struct kvm_vcpu *vcpu) | ||
756 | { | ||
757 | return vcpu->kvm->arch.kvm_ops->check_requests(vcpu); | ||
758 | } | ||
759 | |||
760 | int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log) | ||
761 | { | ||
762 | return kvm->arch.kvm_ops->get_dirty_log(kvm, log); | ||
763 | } | ||
764 | |||
765 | void kvmppc_core_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free, | ||
766 | struct kvm_memory_slot *dont) | ||
767 | { | ||
768 | kvm->arch.kvm_ops->free_memslot(free, dont); | ||
769 | } | ||
770 | |||
771 | int kvmppc_core_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot, | ||
772 | unsigned long npages) | ||
773 | { | ||
774 | return kvm->arch.kvm_ops->create_memslot(slot, npages); | ||
775 | } | ||
776 | |||
777 | void kvmppc_core_flush_memslot(struct kvm *kvm, struct kvm_memory_slot *memslot) | ||
778 | { | ||
779 | kvm->arch.kvm_ops->flush_memslot(kvm, memslot); | ||
780 | } | ||
781 | |||
782 | int kvmppc_core_prepare_memory_region(struct kvm *kvm, | ||
783 | struct kvm_memory_slot *memslot, | ||
784 | struct kvm_userspace_memory_region *mem) | ||
785 | { | ||
786 | return kvm->arch.kvm_ops->prepare_memory_region(kvm, memslot, mem); | ||
787 | } | ||
788 | |||
789 | void kvmppc_core_commit_memory_region(struct kvm *kvm, | ||
790 | struct kvm_userspace_memory_region *mem, | ||
791 | const struct kvm_memory_slot *old) | ||
792 | { | ||
793 | kvm->arch.kvm_ops->commit_memory_region(kvm, mem, old); | ||
794 | } | ||
795 | |||
796 | int kvm_unmap_hva(struct kvm *kvm, unsigned long hva) | ||
797 | { | ||
798 | return kvm->arch.kvm_ops->unmap_hva(kvm, hva); | ||
799 | } | ||
800 | EXPORT_SYMBOL_GPL(kvm_unmap_hva); | ||
801 | |||
802 | int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end) | ||
803 | { | ||
804 | return kvm->arch.kvm_ops->unmap_hva_range(kvm, start, end); | ||
805 | } | ||
806 | |||
807 | int kvm_age_hva(struct kvm *kvm, unsigned long hva) | ||
808 | { | ||
809 | return kvm->arch.kvm_ops->age_hva(kvm, hva); | ||
810 | } | ||
811 | |||
812 | int kvm_test_age_hva(struct kvm *kvm, unsigned long hva) | ||
813 | { | ||
814 | return kvm->arch.kvm_ops->test_age_hva(kvm, hva); | ||
815 | } | ||
816 | |||
817 | void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte) | ||
818 | { | ||
819 | kvm->arch.kvm_ops->set_spte_hva(kvm, hva, pte); | ||
820 | } | ||
821 | |||
822 | void kvmppc_mmu_destroy(struct kvm_vcpu *vcpu) | ||
823 | { | ||
824 | vcpu->kvm->arch.kvm_ops->mmu_destroy(vcpu); | ||
825 | } | ||
826 | |||
827 | int kvmppc_core_init_vm(struct kvm *kvm) | ||
828 | { | ||
829 | |||
830 | #ifdef CONFIG_PPC64 | ||
831 | INIT_LIST_HEAD(&kvm->arch.spapr_tce_tables); | ||
832 | INIT_LIST_HEAD(&kvm->arch.rtas_tokens); | ||
833 | #endif | ||
834 | |||
835 | return kvm->arch.kvm_ops->init_vm(kvm); | ||
836 | } | ||
837 | |||
838 | void kvmppc_core_destroy_vm(struct kvm *kvm) | ||
839 | { | ||
840 | kvm->arch.kvm_ops->destroy_vm(kvm); | ||
841 | |||
842 | #ifdef CONFIG_PPC64 | ||
843 | kvmppc_rtas_tokens_free(kvm); | ||
844 | WARN_ON(!list_empty(&kvm->arch.spapr_tce_tables)); | ||
845 | #endif | ||
846 | } | ||
847 | |||
848 | int kvmppc_core_check_processor_compat(void) | ||
849 | { | ||
850 | /* | ||
851 | * We always return 0 for book3s. We check | ||
852 | * for compatability while loading the HV | ||
853 | * or PR module | ||
854 | */ | ||
855 | return 0; | ||
856 | } | ||
857 | |||
858 | static int kvmppc_book3s_init(void) | ||
859 | { | ||
860 | int r; | ||
861 | |||
862 | r = kvm_init(NULL, sizeof(struct kvm_vcpu), 0, THIS_MODULE); | ||
863 | if (r) | ||
864 | return r; | ||
865 | #ifdef CONFIG_KVM_BOOK3S_32 | ||
866 | r = kvmppc_book3s_init_pr(); | ||
867 | #endif | ||
868 | return r; | ||
869 | |||
870 | } | ||
871 | |||
872 | static void kvmppc_book3s_exit(void) | ||
873 | { | ||
874 | #ifdef CONFIG_KVM_BOOK3S_32 | ||
875 | kvmppc_book3s_exit_pr(); | ||
876 | #endif | ||
877 | kvm_exit(); | ||
878 | } | ||
879 | |||
880 | module_init(kvmppc_book3s_init); | ||
881 | module_exit(kvmppc_book3s_exit); | ||
diff --git a/arch/powerpc/kvm/book3s.h b/arch/powerpc/kvm/book3s.h new file mode 100644 index 000000000000..4bf956cf94d6 --- /dev/null +++ b/arch/powerpc/kvm/book3s.h | |||
@@ -0,0 +1,34 @@ | |||
1 | /* | ||
2 | * Copyright IBM Corporation, 2013 | ||
3 | * Author Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation; either version 2 of the | ||
8 | * License or (at your optional) any later version of the license. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #ifndef __POWERPC_KVM_BOOK3S_H__ | ||
13 | #define __POWERPC_KVM_BOOK3S_H__ | ||
14 | |||
15 | extern void kvmppc_core_flush_memslot_hv(struct kvm *kvm, | ||
16 | struct kvm_memory_slot *memslot); | ||
17 | extern int kvm_unmap_hva_hv(struct kvm *kvm, unsigned long hva); | ||
18 | extern int kvm_unmap_hva_range_hv(struct kvm *kvm, unsigned long start, | ||
19 | unsigned long end); | ||
20 | extern int kvm_age_hva_hv(struct kvm *kvm, unsigned long hva); | ||
21 | extern int kvm_test_age_hva_hv(struct kvm *kvm, unsigned long hva); | ||
22 | extern void kvm_set_spte_hva_hv(struct kvm *kvm, unsigned long hva, pte_t pte); | ||
23 | |||
24 | extern void kvmppc_mmu_destroy_pr(struct kvm_vcpu *vcpu); | ||
25 | extern int kvmppc_core_emulate_op_pr(struct kvm_run *run, struct kvm_vcpu *vcpu, | ||
26 | unsigned int inst, int *advance); | ||
27 | extern int kvmppc_core_emulate_mtspr_pr(struct kvm_vcpu *vcpu, | ||
28 | int sprn, ulong spr_val); | ||
29 | extern int kvmppc_core_emulate_mfspr_pr(struct kvm_vcpu *vcpu, | ||
30 | int sprn, ulong *spr_val); | ||
31 | extern int kvmppc_book3s_init_pr(void); | ||
32 | extern void kvmppc_book3s_exit_pr(void); | ||
33 | |||
34 | #endif | ||
diff --git a/arch/powerpc/kvm/book3s_32_mmu.c b/arch/powerpc/kvm/book3s_32_mmu.c index c8cefdd15fd8..76a64ce6a5b6 100644 --- a/arch/powerpc/kvm/book3s_32_mmu.c +++ b/arch/powerpc/kvm/book3s_32_mmu.c | |||
@@ -84,7 +84,8 @@ static inline bool sr_nx(u32 sr_raw) | |||
84 | } | 84 | } |
85 | 85 | ||
86 | static int kvmppc_mmu_book3s_32_xlate_bat(struct kvm_vcpu *vcpu, gva_t eaddr, | 86 | static int kvmppc_mmu_book3s_32_xlate_bat(struct kvm_vcpu *vcpu, gva_t eaddr, |
87 | struct kvmppc_pte *pte, bool data); | 87 | struct kvmppc_pte *pte, bool data, |
88 | bool iswrite); | ||
88 | static int kvmppc_mmu_book3s_32_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid, | 89 | static int kvmppc_mmu_book3s_32_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid, |
89 | u64 *vsid); | 90 | u64 *vsid); |
90 | 91 | ||
@@ -99,7 +100,7 @@ static u64 kvmppc_mmu_book3s_32_ea_to_vp(struct kvm_vcpu *vcpu, gva_t eaddr, | |||
99 | u64 vsid; | 100 | u64 vsid; |
100 | struct kvmppc_pte pte; | 101 | struct kvmppc_pte pte; |
101 | 102 | ||
102 | if (!kvmppc_mmu_book3s_32_xlate_bat(vcpu, eaddr, &pte, data)) | 103 | if (!kvmppc_mmu_book3s_32_xlate_bat(vcpu, eaddr, &pte, data, false)) |
103 | return pte.vpage; | 104 | return pte.vpage; |
104 | 105 | ||
105 | kvmppc_mmu_book3s_32_esid_to_vsid(vcpu, eaddr >> SID_SHIFT, &vsid); | 106 | kvmppc_mmu_book3s_32_esid_to_vsid(vcpu, eaddr >> SID_SHIFT, &vsid); |
@@ -111,10 +112,11 @@ static void kvmppc_mmu_book3s_32_reset_msr(struct kvm_vcpu *vcpu) | |||
111 | kvmppc_set_msr(vcpu, 0); | 112 | kvmppc_set_msr(vcpu, 0); |
112 | } | 113 | } |
113 | 114 | ||
114 | static hva_t kvmppc_mmu_book3s_32_get_pteg(struct kvmppc_vcpu_book3s *vcpu_book3s, | 115 | static hva_t kvmppc_mmu_book3s_32_get_pteg(struct kvm_vcpu *vcpu, |
115 | u32 sre, gva_t eaddr, | 116 | u32 sre, gva_t eaddr, |
116 | bool primary) | 117 | bool primary) |
117 | { | 118 | { |
119 | struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); | ||
118 | u32 page, hash, pteg, htabmask; | 120 | u32 page, hash, pteg, htabmask; |
119 | hva_t r; | 121 | hva_t r; |
120 | 122 | ||
@@ -132,7 +134,7 @@ static hva_t kvmppc_mmu_book3s_32_get_pteg(struct kvmppc_vcpu_book3s *vcpu_book3 | |||
132 | kvmppc_get_pc(&vcpu_book3s->vcpu), eaddr, vcpu_book3s->sdr1, pteg, | 134 | kvmppc_get_pc(&vcpu_book3s->vcpu), eaddr, vcpu_book3s->sdr1, pteg, |
133 | sr_vsid(sre)); | 135 | sr_vsid(sre)); |
134 | 136 | ||
135 | r = gfn_to_hva(vcpu_book3s->vcpu.kvm, pteg >> PAGE_SHIFT); | 137 | r = gfn_to_hva(vcpu->kvm, pteg >> PAGE_SHIFT); |
136 | if (kvm_is_error_hva(r)) | 138 | if (kvm_is_error_hva(r)) |
137 | return r; | 139 | return r; |
138 | return r | (pteg & ~PAGE_MASK); | 140 | return r | (pteg & ~PAGE_MASK); |
@@ -145,7 +147,8 @@ static u32 kvmppc_mmu_book3s_32_get_ptem(u32 sre, gva_t eaddr, bool primary) | |||
145 | } | 147 | } |
146 | 148 | ||
147 | static int kvmppc_mmu_book3s_32_xlate_bat(struct kvm_vcpu *vcpu, gva_t eaddr, | 149 | static int kvmppc_mmu_book3s_32_xlate_bat(struct kvm_vcpu *vcpu, gva_t eaddr, |
148 | struct kvmppc_pte *pte, bool data) | 150 | struct kvmppc_pte *pte, bool data, |
151 | bool iswrite) | ||
149 | { | 152 | { |
150 | struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); | 153 | struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); |
151 | struct kvmppc_bat *bat; | 154 | struct kvmppc_bat *bat; |
@@ -186,8 +189,7 @@ static int kvmppc_mmu_book3s_32_xlate_bat(struct kvm_vcpu *vcpu, gva_t eaddr, | |||
186 | printk(KERN_INFO "BAT is not readable!\n"); | 189 | printk(KERN_INFO "BAT is not readable!\n"); |
187 | continue; | 190 | continue; |
188 | } | 191 | } |
189 | if (!pte->may_write) { | 192 | if (iswrite && !pte->may_write) { |
190 | /* let's treat r/o BATs as not-readable for now */ | ||
191 | dprintk_pte("BAT is read-only!\n"); | 193 | dprintk_pte("BAT is read-only!\n"); |
192 | continue; | 194 | continue; |
193 | } | 195 | } |
@@ -201,9 +203,8 @@ static int kvmppc_mmu_book3s_32_xlate_bat(struct kvm_vcpu *vcpu, gva_t eaddr, | |||
201 | 203 | ||
202 | static int kvmppc_mmu_book3s_32_xlate_pte(struct kvm_vcpu *vcpu, gva_t eaddr, | 204 | static int kvmppc_mmu_book3s_32_xlate_pte(struct kvm_vcpu *vcpu, gva_t eaddr, |
203 | struct kvmppc_pte *pte, bool data, | 205 | struct kvmppc_pte *pte, bool data, |
204 | bool primary) | 206 | bool iswrite, bool primary) |
205 | { | 207 | { |
206 | struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); | ||
207 | u32 sre; | 208 | u32 sre; |
208 | hva_t ptegp; | 209 | hva_t ptegp; |
209 | u32 pteg[16]; | 210 | u32 pteg[16]; |
@@ -218,7 +219,7 @@ static int kvmppc_mmu_book3s_32_xlate_pte(struct kvm_vcpu *vcpu, gva_t eaddr, | |||
218 | 219 | ||
219 | pte->vpage = kvmppc_mmu_book3s_32_ea_to_vp(vcpu, eaddr, data); | 220 | pte->vpage = kvmppc_mmu_book3s_32_ea_to_vp(vcpu, eaddr, data); |
220 | 221 | ||
221 | ptegp = kvmppc_mmu_book3s_32_get_pteg(vcpu_book3s, sre, eaddr, primary); | 222 | ptegp = kvmppc_mmu_book3s_32_get_pteg(vcpu, sre, eaddr, primary); |
222 | if (kvm_is_error_hva(ptegp)) { | 223 | if (kvm_is_error_hva(ptegp)) { |
223 | printk(KERN_INFO "KVM: Invalid PTEG!\n"); | 224 | printk(KERN_INFO "KVM: Invalid PTEG!\n"); |
224 | goto no_page_found; | 225 | goto no_page_found; |
@@ -258,9 +259,6 @@ static int kvmppc_mmu_book3s_32_xlate_pte(struct kvm_vcpu *vcpu, gva_t eaddr, | |||
258 | break; | 259 | break; |
259 | } | 260 | } |
260 | 261 | ||
261 | if ( !pte->may_read ) | ||
262 | continue; | ||
263 | |||
264 | dprintk_pte("MMU: Found PTE -> %x %x - %x\n", | 262 | dprintk_pte("MMU: Found PTE -> %x %x - %x\n", |
265 | pteg[i], pteg[i+1], pp); | 263 | pteg[i], pteg[i+1], pp); |
266 | found = 1; | 264 | found = 1; |
@@ -271,19 +269,23 @@ static int kvmppc_mmu_book3s_32_xlate_pte(struct kvm_vcpu *vcpu, gva_t eaddr, | |||
271 | /* Update PTE C and A bits, so the guest's swapper knows we used the | 269 | /* Update PTE C and A bits, so the guest's swapper knows we used the |
272 | page */ | 270 | page */ |
273 | if (found) { | 271 | if (found) { |
274 | u32 oldpte = pteg[i+1]; | 272 | u32 pte_r = pteg[i+1]; |
275 | 273 | char __user *addr = (char __user *) &pteg[i+1]; | |
276 | if (pte->may_read) | 274 | |
277 | pteg[i+1] |= PTEG_FLAG_ACCESSED; | 275 | /* |
278 | if (pte->may_write) | 276 | * Use single-byte writes to update the HPTE, to |
279 | pteg[i+1] |= PTEG_FLAG_DIRTY; | 277 | * conform to what real hardware does. |
280 | else | 278 | */ |
281 | dprintk_pte("KVM: Mapping read-only page!\n"); | 279 | if (pte->may_read && !(pte_r & PTEG_FLAG_ACCESSED)) { |
282 | 280 | pte_r |= PTEG_FLAG_ACCESSED; | |
283 | /* Write back into the PTEG */ | 281 | put_user(pte_r >> 8, addr + 2); |
284 | if (pteg[i+1] != oldpte) | 282 | } |
285 | copy_to_user((void __user *)ptegp, pteg, sizeof(pteg)); | 283 | if (iswrite && pte->may_write && !(pte_r & PTEG_FLAG_DIRTY)) { |
286 | 284 | pte_r |= PTEG_FLAG_DIRTY; | |
285 | put_user(pte_r, addr + 3); | ||
286 | } | ||
287 | if (!pte->may_read || (iswrite && !pte->may_write)) | ||
288 | return -EPERM; | ||
287 | return 0; | 289 | return 0; |
288 | } | 290 | } |
289 | 291 | ||
@@ -302,12 +304,14 @@ no_page_found: | |||
302 | } | 304 | } |
303 | 305 | ||
304 | static int kvmppc_mmu_book3s_32_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, | 306 | static int kvmppc_mmu_book3s_32_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, |
305 | struct kvmppc_pte *pte, bool data) | 307 | struct kvmppc_pte *pte, bool data, |
308 | bool iswrite) | ||
306 | { | 309 | { |
307 | int r; | 310 | int r; |
308 | ulong mp_ea = vcpu->arch.magic_page_ea; | 311 | ulong mp_ea = vcpu->arch.magic_page_ea; |
309 | 312 | ||
310 | pte->eaddr = eaddr; | 313 | pte->eaddr = eaddr; |
314 | pte->page_size = MMU_PAGE_4K; | ||
311 | 315 | ||
312 | /* Magic page override */ | 316 | /* Magic page override */ |
313 | if (unlikely(mp_ea) && | 317 | if (unlikely(mp_ea) && |
@@ -323,11 +327,13 @@ static int kvmppc_mmu_book3s_32_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, | |||
323 | return 0; | 327 | return 0; |
324 | } | 328 | } |
325 | 329 | ||
326 | r = kvmppc_mmu_book3s_32_xlate_bat(vcpu, eaddr, pte, data); | 330 | r = kvmppc_mmu_book3s_32_xlate_bat(vcpu, eaddr, pte, data, iswrite); |
327 | if (r < 0) | 331 | if (r < 0) |
328 | r = kvmppc_mmu_book3s_32_xlate_pte(vcpu, eaddr, pte, data, true); | 332 | r = kvmppc_mmu_book3s_32_xlate_pte(vcpu, eaddr, pte, |
333 | data, iswrite, true); | ||
329 | if (r < 0) | 334 | if (r < 0) |
330 | r = kvmppc_mmu_book3s_32_xlate_pte(vcpu, eaddr, pte, data, false); | 335 | r = kvmppc_mmu_book3s_32_xlate_pte(vcpu, eaddr, pte, |
336 | data, iswrite, false); | ||
331 | 337 | ||
332 | return r; | 338 | return r; |
333 | } | 339 | } |
@@ -347,7 +353,12 @@ static void kvmppc_mmu_book3s_32_mtsrin(struct kvm_vcpu *vcpu, u32 srnum, | |||
347 | 353 | ||
348 | static void kvmppc_mmu_book3s_32_tlbie(struct kvm_vcpu *vcpu, ulong ea, bool large) | 354 | static void kvmppc_mmu_book3s_32_tlbie(struct kvm_vcpu *vcpu, ulong ea, bool large) |
349 | { | 355 | { |
350 | kvmppc_mmu_pte_flush(vcpu, ea, 0x0FFFF000); | 356 | int i; |
357 | struct kvm_vcpu *v; | ||
358 | |||
359 | /* flush this VA on all cpus */ | ||
360 | kvm_for_each_vcpu(i, v, vcpu->kvm) | ||
361 | kvmppc_mmu_pte_flush(v, ea, 0x0FFFF000); | ||
351 | } | 362 | } |
352 | 363 | ||
353 | static int kvmppc_mmu_book3s_32_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid, | 364 | static int kvmppc_mmu_book3s_32_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid, |
diff --git a/arch/powerpc/kvm/book3s_32_mmu_host.c b/arch/powerpc/kvm/book3s_32_mmu_host.c index 00e619bf608e..3a0abd2e5a15 100644 --- a/arch/powerpc/kvm/book3s_32_mmu_host.c +++ b/arch/powerpc/kvm/book3s_32_mmu_host.c | |||
@@ -138,7 +138,8 @@ static u32 *kvmppc_mmu_get_pteg(struct kvm_vcpu *vcpu, u32 vsid, u32 eaddr, | |||
138 | 138 | ||
139 | extern char etext[]; | 139 | extern char etext[]; |
140 | 140 | ||
141 | int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte) | 141 | int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte, |
142 | bool iswrite) | ||
142 | { | 143 | { |
143 | pfn_t hpaddr; | 144 | pfn_t hpaddr; |
144 | u64 vpn; | 145 | u64 vpn; |
@@ -152,9 +153,11 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte) | |||
152 | bool evict = false; | 153 | bool evict = false; |
153 | struct hpte_cache *pte; | 154 | struct hpte_cache *pte; |
154 | int r = 0; | 155 | int r = 0; |
156 | bool writable; | ||
155 | 157 | ||
156 | /* Get host physical address for gpa */ | 158 | /* Get host physical address for gpa */ |
157 | hpaddr = kvmppc_gfn_to_pfn(vcpu, orig_pte->raddr >> PAGE_SHIFT); | 159 | hpaddr = kvmppc_gfn_to_pfn(vcpu, orig_pte->raddr >> PAGE_SHIFT, |
160 | iswrite, &writable); | ||
158 | if (is_error_noslot_pfn(hpaddr)) { | 161 | if (is_error_noslot_pfn(hpaddr)) { |
159 | printk(KERN_INFO "Couldn't get guest page for gfn %lx!\n", | 162 | printk(KERN_INFO "Couldn't get guest page for gfn %lx!\n", |
160 | orig_pte->eaddr); | 163 | orig_pte->eaddr); |
@@ -204,7 +207,7 @@ next_pteg: | |||
204 | (primary ? 0 : PTE_SEC); | 207 | (primary ? 0 : PTE_SEC); |
205 | pteg1 = hpaddr | PTE_M | PTE_R | PTE_C; | 208 | pteg1 = hpaddr | PTE_M | PTE_R | PTE_C; |
206 | 209 | ||
207 | if (orig_pte->may_write) { | 210 | if (orig_pte->may_write && writable) { |
208 | pteg1 |= PP_RWRW; | 211 | pteg1 |= PP_RWRW; |
209 | mark_page_dirty(vcpu->kvm, orig_pte->raddr >> PAGE_SHIFT); | 212 | mark_page_dirty(vcpu->kvm, orig_pte->raddr >> PAGE_SHIFT); |
210 | } else { | 213 | } else { |
@@ -259,6 +262,11 @@ out: | |||
259 | return r; | 262 | return r; |
260 | } | 263 | } |
261 | 264 | ||
265 | void kvmppc_mmu_unmap_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte) | ||
266 | { | ||
267 | kvmppc_mmu_pte_vflush(vcpu, pte->vpage, 0xfffffffffULL); | ||
268 | } | ||
269 | |||
262 | static struct kvmppc_sid_map *create_sid_map(struct kvm_vcpu *vcpu, u64 gvsid) | 270 | static struct kvmppc_sid_map *create_sid_map(struct kvm_vcpu *vcpu, u64 gvsid) |
263 | { | 271 | { |
264 | struct kvmppc_sid_map *map; | 272 | struct kvmppc_sid_map *map; |
@@ -341,7 +349,7 @@ void kvmppc_mmu_flush_segments(struct kvm_vcpu *vcpu) | |||
341 | svcpu_put(svcpu); | 349 | svcpu_put(svcpu); |
342 | } | 350 | } |
343 | 351 | ||
344 | void kvmppc_mmu_destroy(struct kvm_vcpu *vcpu) | 352 | void kvmppc_mmu_destroy_pr(struct kvm_vcpu *vcpu) |
345 | { | 353 | { |
346 | int i; | 354 | int i; |
347 | 355 | ||
diff --git a/arch/powerpc/kvm/book3s_64_mmu.c b/arch/powerpc/kvm/book3s_64_mmu.c index 7e345e00661a..83da1f868fd5 100644 --- a/arch/powerpc/kvm/book3s_64_mmu.c +++ b/arch/powerpc/kvm/book3s_64_mmu.c | |||
@@ -107,9 +107,20 @@ static u64 kvmppc_mmu_book3s_64_ea_to_vp(struct kvm_vcpu *vcpu, gva_t eaddr, | |||
107 | return kvmppc_slb_calc_vpn(slb, eaddr); | 107 | return kvmppc_slb_calc_vpn(slb, eaddr); |
108 | } | 108 | } |
109 | 109 | ||
110 | static int mmu_pagesize(int mmu_pg) | ||
111 | { | ||
112 | switch (mmu_pg) { | ||
113 | case MMU_PAGE_64K: | ||
114 | return 16; | ||
115 | case MMU_PAGE_16M: | ||
116 | return 24; | ||
117 | } | ||
118 | return 12; | ||
119 | } | ||
120 | |||
110 | static int kvmppc_mmu_book3s_64_get_pagesize(struct kvmppc_slb *slbe) | 121 | static int kvmppc_mmu_book3s_64_get_pagesize(struct kvmppc_slb *slbe) |
111 | { | 122 | { |
112 | return slbe->large ? 24 : 12; | 123 | return mmu_pagesize(slbe->base_page_size); |
113 | } | 124 | } |
114 | 125 | ||
115 | static u32 kvmppc_mmu_book3s_64_get_page(struct kvmppc_slb *slbe, gva_t eaddr) | 126 | static u32 kvmppc_mmu_book3s_64_get_page(struct kvmppc_slb *slbe, gva_t eaddr) |
@@ -119,11 +130,11 @@ static u32 kvmppc_mmu_book3s_64_get_page(struct kvmppc_slb *slbe, gva_t eaddr) | |||
119 | return ((eaddr & kvmppc_slb_offset_mask(slbe)) >> p); | 130 | return ((eaddr & kvmppc_slb_offset_mask(slbe)) >> p); |
120 | } | 131 | } |
121 | 132 | ||
122 | static hva_t kvmppc_mmu_book3s_64_get_pteg( | 133 | static hva_t kvmppc_mmu_book3s_64_get_pteg(struct kvm_vcpu *vcpu, |
123 | struct kvmppc_vcpu_book3s *vcpu_book3s, | ||
124 | struct kvmppc_slb *slbe, gva_t eaddr, | 134 | struct kvmppc_slb *slbe, gva_t eaddr, |
125 | bool second) | 135 | bool second) |
126 | { | 136 | { |
137 | struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); | ||
127 | u64 hash, pteg, htabsize; | 138 | u64 hash, pteg, htabsize; |
128 | u32 ssize; | 139 | u32 ssize; |
129 | hva_t r; | 140 | hva_t r; |
@@ -148,10 +159,10 @@ static hva_t kvmppc_mmu_book3s_64_get_pteg( | |||
148 | 159 | ||
149 | /* When running a PAPR guest, SDR1 contains a HVA address instead | 160 | /* When running a PAPR guest, SDR1 contains a HVA address instead |
150 | of a GPA */ | 161 | of a GPA */ |
151 | if (vcpu_book3s->vcpu.arch.papr_enabled) | 162 | if (vcpu->arch.papr_enabled) |
152 | r = pteg; | 163 | r = pteg; |
153 | else | 164 | else |
154 | r = gfn_to_hva(vcpu_book3s->vcpu.kvm, pteg >> PAGE_SHIFT); | 165 | r = gfn_to_hva(vcpu->kvm, pteg >> PAGE_SHIFT); |
155 | 166 | ||
156 | if (kvm_is_error_hva(r)) | 167 | if (kvm_is_error_hva(r)) |
157 | return r; | 168 | return r; |
@@ -166,18 +177,38 @@ static u64 kvmppc_mmu_book3s_64_get_avpn(struct kvmppc_slb *slbe, gva_t eaddr) | |||
166 | avpn = kvmppc_mmu_book3s_64_get_page(slbe, eaddr); | 177 | avpn = kvmppc_mmu_book3s_64_get_page(slbe, eaddr); |
167 | avpn |= slbe->vsid << (kvmppc_slb_sid_shift(slbe) - p); | 178 | avpn |= slbe->vsid << (kvmppc_slb_sid_shift(slbe) - p); |
168 | 179 | ||
169 | if (p < 24) | 180 | if (p < 16) |
170 | avpn >>= ((80 - p) - 56) - 8; | 181 | avpn >>= ((80 - p) - 56) - 8; /* 16 - p */ |
171 | else | 182 | else |
172 | avpn <<= 8; | 183 | avpn <<= p - 16; |
173 | 184 | ||
174 | return avpn; | 185 | return avpn; |
175 | } | 186 | } |
176 | 187 | ||
188 | /* | ||
189 | * Return page size encoded in the second word of a HPTE, or | ||
190 | * -1 for an invalid encoding for the base page size indicated by | ||
191 | * the SLB entry. This doesn't handle mixed pagesize segments yet. | ||
192 | */ | ||
193 | static int decode_pagesize(struct kvmppc_slb *slbe, u64 r) | ||
194 | { | ||
195 | switch (slbe->base_page_size) { | ||
196 | case MMU_PAGE_64K: | ||
197 | if ((r & 0xf000) == 0x1000) | ||
198 | return MMU_PAGE_64K; | ||
199 | break; | ||
200 | case MMU_PAGE_16M: | ||
201 | if ((r & 0xff000) == 0) | ||
202 | return MMU_PAGE_16M; | ||
203 | break; | ||
204 | } | ||
205 | return -1; | ||
206 | } | ||
207 | |||
177 | static int kvmppc_mmu_book3s_64_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, | 208 | static int kvmppc_mmu_book3s_64_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, |
178 | struct kvmppc_pte *gpte, bool data) | 209 | struct kvmppc_pte *gpte, bool data, |
210 | bool iswrite) | ||
179 | { | 211 | { |
180 | struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); | ||
181 | struct kvmppc_slb *slbe; | 212 | struct kvmppc_slb *slbe; |
182 | hva_t ptegp; | 213 | hva_t ptegp; |
183 | u64 pteg[16]; | 214 | u64 pteg[16]; |
@@ -189,6 +220,7 @@ static int kvmppc_mmu_book3s_64_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, | |||
189 | u8 pp, key = 0; | 220 | u8 pp, key = 0; |
190 | bool found = false; | 221 | bool found = false; |
191 | bool second = false; | 222 | bool second = false; |
223 | int pgsize; | ||
192 | ulong mp_ea = vcpu->arch.magic_page_ea; | 224 | ulong mp_ea = vcpu->arch.magic_page_ea; |
193 | 225 | ||
194 | /* Magic page override */ | 226 | /* Magic page override */ |
@@ -202,6 +234,7 @@ static int kvmppc_mmu_book3s_64_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, | |||
202 | gpte->may_execute = true; | 234 | gpte->may_execute = true; |
203 | gpte->may_read = true; | 235 | gpte->may_read = true; |
204 | gpte->may_write = true; | 236 | gpte->may_write = true; |
237 | gpte->page_size = MMU_PAGE_4K; | ||
205 | 238 | ||
206 | return 0; | 239 | return 0; |
207 | } | 240 | } |
@@ -222,8 +255,12 @@ static int kvmppc_mmu_book3s_64_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, | |||
222 | v_mask = SLB_VSID_B | HPTE_V_AVPN | HPTE_V_LARGE | HPTE_V_VALID | | 255 | v_mask = SLB_VSID_B | HPTE_V_AVPN | HPTE_V_LARGE | HPTE_V_VALID | |
223 | HPTE_V_SECONDARY; | 256 | HPTE_V_SECONDARY; |
224 | 257 | ||
258 | pgsize = slbe->large ? MMU_PAGE_16M : MMU_PAGE_4K; | ||
259 | |||
260 | mutex_lock(&vcpu->kvm->arch.hpt_mutex); | ||
261 | |||
225 | do_second: | 262 | do_second: |
226 | ptegp = kvmppc_mmu_book3s_64_get_pteg(vcpu_book3s, slbe, eaddr, second); | 263 | ptegp = kvmppc_mmu_book3s_64_get_pteg(vcpu, slbe, eaddr, second); |
227 | if (kvm_is_error_hva(ptegp)) | 264 | if (kvm_is_error_hva(ptegp)) |
228 | goto no_page_found; | 265 | goto no_page_found; |
229 | 266 | ||
@@ -240,6 +277,13 @@ do_second: | |||
240 | for (i=0; i<16; i+=2) { | 277 | for (i=0; i<16; i+=2) { |
241 | /* Check all relevant fields of 1st dword */ | 278 | /* Check all relevant fields of 1st dword */ |
242 | if ((pteg[i] & v_mask) == v_val) { | 279 | if ((pteg[i] & v_mask) == v_val) { |
280 | /* If large page bit is set, check pgsize encoding */ | ||
281 | if (slbe->large && | ||
282 | (vcpu->arch.hflags & BOOK3S_HFLAG_MULTI_PGSIZE)) { | ||
283 | pgsize = decode_pagesize(slbe, pteg[i+1]); | ||
284 | if (pgsize < 0) | ||
285 | continue; | ||
286 | } | ||
243 | found = true; | 287 | found = true; |
244 | break; | 288 | break; |
245 | } | 289 | } |
@@ -256,13 +300,15 @@ do_second: | |||
256 | v = pteg[i]; | 300 | v = pteg[i]; |
257 | r = pteg[i+1]; | 301 | r = pteg[i+1]; |
258 | pp = (r & HPTE_R_PP) | key; | 302 | pp = (r & HPTE_R_PP) | key; |
259 | eaddr_mask = 0xFFF; | 303 | if (r & HPTE_R_PP0) |
304 | pp |= 8; | ||
260 | 305 | ||
261 | gpte->eaddr = eaddr; | 306 | gpte->eaddr = eaddr; |
262 | gpte->vpage = kvmppc_mmu_book3s_64_ea_to_vp(vcpu, eaddr, data); | 307 | gpte->vpage = kvmppc_mmu_book3s_64_ea_to_vp(vcpu, eaddr, data); |
263 | if (slbe->large) | 308 | |
264 | eaddr_mask = 0xFFFFFF; | 309 | eaddr_mask = (1ull << mmu_pagesize(pgsize)) - 1; |
265 | gpte->raddr = (r & HPTE_R_RPN & ~eaddr_mask) | (eaddr & eaddr_mask); | 310 | gpte->raddr = (r & HPTE_R_RPN & ~eaddr_mask) | (eaddr & eaddr_mask); |
311 | gpte->page_size = pgsize; | ||
266 | gpte->may_execute = ((r & HPTE_R_N) ? false : true); | 312 | gpte->may_execute = ((r & HPTE_R_N) ? false : true); |
267 | gpte->may_read = false; | 313 | gpte->may_read = false; |
268 | gpte->may_write = false; | 314 | gpte->may_write = false; |
@@ -277,6 +323,7 @@ do_second: | |||
277 | case 3: | 323 | case 3: |
278 | case 5: | 324 | case 5: |
279 | case 7: | 325 | case 7: |
326 | case 10: | ||
280 | gpte->may_read = true; | 327 | gpte->may_read = true; |
281 | break; | 328 | break; |
282 | } | 329 | } |
@@ -287,30 +334,37 @@ do_second: | |||
287 | 334 | ||
288 | /* Update PTE R and C bits, so the guest's swapper knows we used the | 335 | /* Update PTE R and C bits, so the guest's swapper knows we used the |
289 | * page */ | 336 | * page */ |
290 | if (gpte->may_read) { | 337 | if (gpte->may_read && !(r & HPTE_R_R)) { |
291 | /* Set the accessed flag */ | 338 | /* |
339 | * Set the accessed flag. | ||
340 | * We have to write this back with a single byte write | ||
341 | * because another vcpu may be accessing this on | ||
342 | * non-PAPR platforms such as mac99, and this is | ||
343 | * what real hardware does. | ||
344 | */ | ||
345 | char __user *addr = (char __user *) &pteg[i+1]; | ||
292 | r |= HPTE_R_R; | 346 | r |= HPTE_R_R; |
347 | put_user(r >> 8, addr + 6); | ||
293 | } | 348 | } |
294 | if (data && gpte->may_write) { | 349 | if (iswrite && gpte->may_write && !(r & HPTE_R_C)) { |
295 | /* Set the dirty flag -- XXX even if not writing */ | 350 | /* Set the dirty flag */ |
351 | /* Use a single byte write */ | ||
352 | char __user *addr = (char __user *) &pteg[i+1]; | ||
296 | r |= HPTE_R_C; | 353 | r |= HPTE_R_C; |
354 | put_user(r, addr + 7); | ||
297 | } | 355 | } |
298 | 356 | ||
299 | /* Write back into the PTEG */ | 357 | mutex_unlock(&vcpu->kvm->arch.hpt_mutex); |
300 | if (pteg[i+1] != r) { | ||
301 | pteg[i+1] = r; | ||
302 | copy_to_user((void __user *)ptegp, pteg, sizeof(pteg)); | ||
303 | } | ||
304 | 358 | ||
305 | if (!gpte->may_read) | 359 | if (!gpte->may_read || (iswrite && !gpte->may_write)) |
306 | return -EPERM; | 360 | return -EPERM; |
307 | return 0; | 361 | return 0; |
308 | 362 | ||
309 | no_page_found: | 363 | no_page_found: |
364 | mutex_unlock(&vcpu->kvm->arch.hpt_mutex); | ||
310 | return -ENOENT; | 365 | return -ENOENT; |
311 | 366 | ||
312 | no_seg_found: | 367 | no_seg_found: |
313 | |||
314 | dprintk("KVM MMU: Trigger segment fault\n"); | 368 | dprintk("KVM MMU: Trigger segment fault\n"); |
315 | return -EINVAL; | 369 | return -EINVAL; |
316 | } | 370 | } |
@@ -345,6 +399,21 @@ static void kvmppc_mmu_book3s_64_slbmte(struct kvm_vcpu *vcpu, u64 rs, u64 rb) | |||
345 | slbe->nx = (rs & SLB_VSID_N) ? 1 : 0; | 399 | slbe->nx = (rs & SLB_VSID_N) ? 1 : 0; |
346 | slbe->class = (rs & SLB_VSID_C) ? 1 : 0; | 400 | slbe->class = (rs & SLB_VSID_C) ? 1 : 0; |
347 | 401 | ||
402 | slbe->base_page_size = MMU_PAGE_4K; | ||
403 | if (slbe->large) { | ||
404 | if (vcpu->arch.hflags & BOOK3S_HFLAG_MULTI_PGSIZE) { | ||
405 | switch (rs & SLB_VSID_LP) { | ||
406 | case SLB_VSID_LP_00: | ||
407 | slbe->base_page_size = MMU_PAGE_16M; | ||
408 | break; | ||
409 | case SLB_VSID_LP_01: | ||
410 | slbe->base_page_size = MMU_PAGE_64K; | ||
411 | break; | ||
412 | } | ||
413 | } else | ||
414 | slbe->base_page_size = MMU_PAGE_16M; | ||
415 | } | ||
416 | |||
348 | slbe->orige = rb & (ESID_MASK | SLB_ESID_V); | 417 | slbe->orige = rb & (ESID_MASK | SLB_ESID_V); |
349 | slbe->origv = rs; | 418 | slbe->origv = rs; |
350 | 419 | ||
@@ -460,14 +529,45 @@ static void kvmppc_mmu_book3s_64_tlbie(struct kvm_vcpu *vcpu, ulong va, | |||
460 | bool large) | 529 | bool large) |
461 | { | 530 | { |
462 | u64 mask = 0xFFFFFFFFFULL; | 531 | u64 mask = 0xFFFFFFFFFULL; |
532 | long i; | ||
533 | struct kvm_vcpu *v; | ||
463 | 534 | ||
464 | dprintk("KVM MMU: tlbie(0x%lx)\n", va); | 535 | dprintk("KVM MMU: tlbie(0x%lx)\n", va); |
465 | 536 | ||
466 | if (large) | 537 | /* |
467 | mask = 0xFFFFFF000ULL; | 538 | * The tlbie instruction changed behaviour starting with |
468 | kvmppc_mmu_pte_vflush(vcpu, va >> 12, mask); | 539 | * POWER6. POWER6 and later don't have the large page flag |
540 | * in the instruction but in the RB value, along with bits | ||
541 | * indicating page and segment sizes. | ||
542 | */ | ||
543 | if (vcpu->arch.hflags & BOOK3S_HFLAG_NEW_TLBIE) { | ||
544 | /* POWER6 or later */ | ||
545 | if (va & 1) { /* L bit */ | ||
546 | if ((va & 0xf000) == 0x1000) | ||
547 | mask = 0xFFFFFFFF0ULL; /* 64k page */ | ||
548 | else | ||
549 | mask = 0xFFFFFF000ULL; /* 16M page */ | ||
550 | } | ||
551 | } else { | ||
552 | /* older processors, e.g. PPC970 */ | ||
553 | if (large) | ||
554 | mask = 0xFFFFFF000ULL; | ||
555 | } | ||
556 | /* flush this VA on all vcpus */ | ||
557 | kvm_for_each_vcpu(i, v, vcpu->kvm) | ||
558 | kvmppc_mmu_pte_vflush(v, va >> 12, mask); | ||
469 | } | 559 | } |
470 | 560 | ||
561 | #ifdef CONFIG_PPC_64K_PAGES | ||
562 | static int segment_contains_magic_page(struct kvm_vcpu *vcpu, ulong esid) | ||
563 | { | ||
564 | ulong mp_ea = vcpu->arch.magic_page_ea; | ||
565 | |||
566 | return mp_ea && !(vcpu->arch.shared->msr & MSR_PR) && | ||
567 | (mp_ea >> SID_SHIFT) == esid; | ||
568 | } | ||
569 | #endif | ||
570 | |||
471 | static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid, | 571 | static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid, |
472 | u64 *vsid) | 572 | u64 *vsid) |
473 | { | 573 | { |
@@ -475,11 +575,13 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid, | |||
475 | struct kvmppc_slb *slb; | 575 | struct kvmppc_slb *slb; |
476 | u64 gvsid = esid; | 576 | u64 gvsid = esid; |
477 | ulong mp_ea = vcpu->arch.magic_page_ea; | 577 | ulong mp_ea = vcpu->arch.magic_page_ea; |
578 | int pagesize = MMU_PAGE_64K; | ||
478 | 579 | ||
479 | if (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) { | 580 | if (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) { |
480 | slb = kvmppc_mmu_book3s_64_find_slbe(vcpu, ea); | 581 | slb = kvmppc_mmu_book3s_64_find_slbe(vcpu, ea); |
481 | if (slb) { | 582 | if (slb) { |
482 | gvsid = slb->vsid; | 583 | gvsid = slb->vsid; |
584 | pagesize = slb->base_page_size; | ||
483 | if (slb->tb) { | 585 | if (slb->tb) { |
484 | gvsid <<= SID_SHIFT_1T - SID_SHIFT; | 586 | gvsid <<= SID_SHIFT_1T - SID_SHIFT; |
485 | gvsid |= esid & ((1ul << (SID_SHIFT_1T - SID_SHIFT)) - 1); | 587 | gvsid |= esid & ((1ul << (SID_SHIFT_1T - SID_SHIFT)) - 1); |
@@ -490,28 +592,41 @@ static int kvmppc_mmu_book3s_64_esid_to_vsid(struct kvm_vcpu *vcpu, ulong esid, | |||
490 | 592 | ||
491 | switch (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) { | 593 | switch (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) { |
492 | case 0: | 594 | case 0: |
493 | *vsid = VSID_REAL | esid; | 595 | gvsid = VSID_REAL | esid; |
494 | break; | 596 | break; |
495 | case MSR_IR: | 597 | case MSR_IR: |
496 | *vsid = VSID_REAL_IR | gvsid; | 598 | gvsid |= VSID_REAL_IR; |
497 | break; | 599 | break; |
498 | case MSR_DR: | 600 | case MSR_DR: |
499 | *vsid = VSID_REAL_DR | gvsid; | 601 | gvsid |= VSID_REAL_DR; |
500 | break; | 602 | break; |
501 | case MSR_DR|MSR_IR: | 603 | case MSR_DR|MSR_IR: |
502 | if (!slb) | 604 | if (!slb) |
503 | goto no_slb; | 605 | goto no_slb; |
504 | 606 | ||
505 | *vsid = gvsid; | ||
506 | break; | 607 | break; |
507 | default: | 608 | default: |
508 | BUG(); | 609 | BUG(); |
509 | break; | 610 | break; |
510 | } | 611 | } |
511 | 612 | ||
613 | #ifdef CONFIG_PPC_64K_PAGES | ||
614 | /* | ||
615 | * Mark this as a 64k segment if the host is using | ||
616 | * 64k pages, the host MMU supports 64k pages and | ||
617 | * the guest segment page size is >= 64k, | ||
618 | * but not if this segment contains the magic page. | ||
619 | */ | ||
620 | if (pagesize >= MMU_PAGE_64K && | ||
621 | mmu_psize_defs[MMU_PAGE_64K].shift && | ||
622 | !segment_contains_magic_page(vcpu, esid)) | ||
623 | gvsid |= VSID_64K; | ||
624 | #endif | ||
625 | |||
512 | if (vcpu->arch.shared->msr & MSR_PR) | 626 | if (vcpu->arch.shared->msr & MSR_PR) |
513 | *vsid |= VSID_PR; | 627 | gvsid |= VSID_PR; |
514 | 628 | ||
629 | *vsid = gvsid; | ||
515 | return 0; | 630 | return 0; |
516 | 631 | ||
517 | no_slb: | 632 | no_slb: |
diff --git a/arch/powerpc/kvm/book3s_64_mmu_host.c b/arch/powerpc/kvm/book3s_64_mmu_host.c index e5240524bf6c..0d513af62bba 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_host.c +++ b/arch/powerpc/kvm/book3s_64_mmu_host.c | |||
@@ -27,14 +27,14 @@ | |||
27 | #include <asm/machdep.h> | 27 | #include <asm/machdep.h> |
28 | #include <asm/mmu_context.h> | 28 | #include <asm/mmu_context.h> |
29 | #include <asm/hw_irq.h> | 29 | #include <asm/hw_irq.h> |
30 | #include "trace.h" | 30 | #include "trace_pr.h" |
31 | 31 | ||
32 | #define PTE_SIZE 12 | 32 | #define PTE_SIZE 12 |
33 | 33 | ||
34 | void kvmppc_mmu_invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte) | 34 | void kvmppc_mmu_invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte) |
35 | { | 35 | { |
36 | ppc_md.hpte_invalidate(pte->slot, pte->host_vpn, | 36 | ppc_md.hpte_invalidate(pte->slot, pte->host_vpn, |
37 | MMU_PAGE_4K, MMU_PAGE_4K, MMU_SEGSIZE_256M, | 37 | pte->pagesize, pte->pagesize, MMU_SEGSIZE_256M, |
38 | false); | 38 | false); |
39 | } | 39 | } |
40 | 40 | ||
@@ -78,7 +78,8 @@ static struct kvmppc_sid_map *find_sid_vsid(struct kvm_vcpu *vcpu, u64 gvsid) | |||
78 | return NULL; | 78 | return NULL; |
79 | } | 79 | } |
80 | 80 | ||
81 | int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte) | 81 | int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte, |
82 | bool iswrite) | ||
82 | { | 83 | { |
83 | unsigned long vpn; | 84 | unsigned long vpn; |
84 | pfn_t hpaddr; | 85 | pfn_t hpaddr; |
@@ -90,16 +91,26 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte) | |||
90 | int attempt = 0; | 91 | int attempt = 0; |
91 | struct kvmppc_sid_map *map; | 92 | struct kvmppc_sid_map *map; |
92 | int r = 0; | 93 | int r = 0; |
94 | int hpsize = MMU_PAGE_4K; | ||
95 | bool writable; | ||
96 | unsigned long mmu_seq; | ||
97 | struct kvm *kvm = vcpu->kvm; | ||
98 | struct hpte_cache *cpte; | ||
99 | unsigned long gfn = orig_pte->raddr >> PAGE_SHIFT; | ||
100 | unsigned long pfn; | ||
101 | |||
102 | /* used to check for invalidations in progress */ | ||
103 | mmu_seq = kvm->mmu_notifier_seq; | ||
104 | smp_rmb(); | ||
93 | 105 | ||
94 | /* Get host physical address for gpa */ | 106 | /* Get host physical address for gpa */ |
95 | hpaddr = kvmppc_gfn_to_pfn(vcpu, orig_pte->raddr >> PAGE_SHIFT); | 107 | pfn = kvmppc_gfn_to_pfn(vcpu, gfn, iswrite, &writable); |
96 | if (is_error_noslot_pfn(hpaddr)) { | 108 | if (is_error_noslot_pfn(pfn)) { |
97 | printk(KERN_INFO "Couldn't get guest page for gfn %lx!\n", orig_pte->eaddr); | 109 | printk(KERN_INFO "Couldn't get guest page for gfn %lx!\n", gfn); |
98 | r = -EINVAL; | 110 | r = -EINVAL; |
99 | goto out; | 111 | goto out; |
100 | } | 112 | } |
101 | hpaddr <<= PAGE_SHIFT; | 113 | hpaddr = pfn << PAGE_SHIFT; |
102 | hpaddr |= orig_pte->raddr & (~0xfffULL & ~PAGE_MASK); | ||
103 | 114 | ||
104 | /* and write the mapping ea -> hpa into the pt */ | 115 | /* and write the mapping ea -> hpa into the pt */ |
105 | vcpu->arch.mmu.esid_to_vsid(vcpu, orig_pte->eaddr >> SID_SHIFT, &vsid); | 116 | vcpu->arch.mmu.esid_to_vsid(vcpu, orig_pte->eaddr >> SID_SHIFT, &vsid); |
@@ -117,20 +128,39 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte) | |||
117 | goto out; | 128 | goto out; |
118 | } | 129 | } |
119 | 130 | ||
120 | vsid = map->host_vsid; | 131 | vpn = hpt_vpn(orig_pte->eaddr, map->host_vsid, MMU_SEGSIZE_256M); |
121 | vpn = hpt_vpn(orig_pte->eaddr, vsid, MMU_SEGSIZE_256M); | ||
122 | 132 | ||
123 | if (!orig_pte->may_write) | 133 | kvm_set_pfn_accessed(pfn); |
124 | rflags |= HPTE_R_PP; | 134 | if (!orig_pte->may_write || !writable) |
125 | else | 135 | rflags |= PP_RXRX; |
126 | mark_page_dirty(vcpu->kvm, orig_pte->raddr >> PAGE_SHIFT); | 136 | else { |
137 | mark_page_dirty(vcpu->kvm, gfn); | ||
138 | kvm_set_pfn_dirty(pfn); | ||
139 | } | ||
127 | 140 | ||
128 | if (!orig_pte->may_execute) | 141 | if (!orig_pte->may_execute) |
129 | rflags |= HPTE_R_N; | 142 | rflags |= HPTE_R_N; |
130 | else | 143 | else |
131 | kvmppc_mmu_flush_icache(hpaddr >> PAGE_SHIFT); | 144 | kvmppc_mmu_flush_icache(pfn); |
145 | |||
146 | /* | ||
147 | * Use 64K pages if possible; otherwise, on 64K page kernels, | ||
148 | * we need to transfer 4 more bits from guest real to host real addr. | ||
149 | */ | ||
150 | if (vsid & VSID_64K) | ||
151 | hpsize = MMU_PAGE_64K; | ||
152 | else | ||
153 | hpaddr |= orig_pte->raddr & (~0xfffULL & ~PAGE_MASK); | ||
154 | |||
155 | hash = hpt_hash(vpn, mmu_psize_defs[hpsize].shift, MMU_SEGSIZE_256M); | ||
132 | 156 | ||
133 | hash = hpt_hash(vpn, PTE_SIZE, MMU_SEGSIZE_256M); | 157 | cpte = kvmppc_mmu_hpte_cache_next(vcpu); |
158 | |||
159 | spin_lock(&kvm->mmu_lock); | ||
160 | if (!cpte || mmu_notifier_retry(kvm, mmu_seq)) { | ||
161 | r = -EAGAIN; | ||
162 | goto out_unlock; | ||
163 | } | ||
134 | 164 | ||
135 | map_again: | 165 | map_again: |
136 | hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP); | 166 | hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP); |
@@ -139,11 +169,11 @@ map_again: | |||
139 | if (attempt > 1) | 169 | if (attempt > 1) |
140 | if (ppc_md.hpte_remove(hpteg) < 0) { | 170 | if (ppc_md.hpte_remove(hpteg) < 0) { |
141 | r = -1; | 171 | r = -1; |
142 | goto out; | 172 | goto out_unlock; |
143 | } | 173 | } |
144 | 174 | ||
145 | ret = ppc_md.hpte_insert(hpteg, vpn, hpaddr, rflags, vflags, | 175 | ret = ppc_md.hpte_insert(hpteg, vpn, hpaddr, rflags, vflags, |
146 | MMU_PAGE_4K, MMU_PAGE_4K, MMU_SEGSIZE_256M); | 176 | hpsize, hpsize, MMU_SEGSIZE_256M); |
147 | 177 | ||
148 | if (ret < 0) { | 178 | if (ret < 0) { |
149 | /* If we couldn't map a primary PTE, try a secondary */ | 179 | /* If we couldn't map a primary PTE, try a secondary */ |
@@ -152,8 +182,6 @@ map_again: | |||
152 | attempt++; | 182 | attempt++; |
153 | goto map_again; | 183 | goto map_again; |
154 | } else { | 184 | } else { |
155 | struct hpte_cache *pte = kvmppc_mmu_hpte_cache_next(vcpu); | ||
156 | |||
157 | trace_kvm_book3s_64_mmu_map(rflags, hpteg, | 185 | trace_kvm_book3s_64_mmu_map(rflags, hpteg, |
158 | vpn, hpaddr, orig_pte); | 186 | vpn, hpaddr, orig_pte); |
159 | 187 | ||
@@ -164,19 +192,37 @@ map_again: | |||
164 | hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP); | 192 | hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP); |
165 | } | 193 | } |
166 | 194 | ||
167 | pte->slot = hpteg + (ret & 7); | 195 | cpte->slot = hpteg + (ret & 7); |
168 | pte->host_vpn = vpn; | 196 | cpte->host_vpn = vpn; |
169 | pte->pte = *orig_pte; | 197 | cpte->pte = *orig_pte; |
170 | pte->pfn = hpaddr >> PAGE_SHIFT; | 198 | cpte->pfn = pfn; |
199 | cpte->pagesize = hpsize; | ||
171 | 200 | ||
172 | kvmppc_mmu_hpte_cache_map(vcpu, pte); | 201 | kvmppc_mmu_hpte_cache_map(vcpu, cpte); |
202 | cpte = NULL; | ||
173 | } | 203 | } |
174 | kvm_release_pfn_clean(hpaddr >> PAGE_SHIFT); | 204 | |
205 | out_unlock: | ||
206 | spin_unlock(&kvm->mmu_lock); | ||
207 | kvm_release_pfn_clean(pfn); | ||
208 | if (cpte) | ||
209 | kvmppc_mmu_hpte_cache_free(cpte); | ||
175 | 210 | ||
176 | out: | 211 | out: |
177 | return r; | 212 | return r; |
178 | } | 213 | } |
179 | 214 | ||
215 | void kvmppc_mmu_unmap_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte) | ||
216 | { | ||
217 | u64 mask = 0xfffffffffULL; | ||
218 | u64 vsid; | ||
219 | |||
220 | vcpu->arch.mmu.esid_to_vsid(vcpu, pte->eaddr >> SID_SHIFT, &vsid); | ||
221 | if (vsid & VSID_64K) | ||
222 | mask = 0xffffffff0ULL; | ||
223 | kvmppc_mmu_pte_vflush(vcpu, pte->vpage, mask); | ||
224 | } | ||
225 | |||
180 | static struct kvmppc_sid_map *create_sid_map(struct kvm_vcpu *vcpu, u64 gvsid) | 226 | static struct kvmppc_sid_map *create_sid_map(struct kvm_vcpu *vcpu, u64 gvsid) |
181 | { | 227 | { |
182 | struct kvmppc_sid_map *map; | 228 | struct kvmppc_sid_map *map; |
@@ -291,6 +337,12 @@ int kvmppc_mmu_map_segment(struct kvm_vcpu *vcpu, ulong eaddr) | |||
291 | slb_vsid &= ~SLB_VSID_KP; | 337 | slb_vsid &= ~SLB_VSID_KP; |
292 | slb_esid |= slb_index; | 338 | slb_esid |= slb_index; |
293 | 339 | ||
340 | #ifdef CONFIG_PPC_64K_PAGES | ||
341 | /* Set host segment base page size to 64K if possible */ | ||
342 | if (gvsid & VSID_64K) | ||
343 | slb_vsid |= mmu_psize_defs[MMU_PAGE_64K].sllp; | ||
344 | #endif | ||
345 | |||
294 | svcpu->slb[slb_index].esid = slb_esid; | 346 | svcpu->slb[slb_index].esid = slb_esid; |
295 | svcpu->slb[slb_index].vsid = slb_vsid; | 347 | svcpu->slb[slb_index].vsid = slb_vsid; |
296 | 348 | ||
@@ -326,7 +378,7 @@ void kvmppc_mmu_flush_segments(struct kvm_vcpu *vcpu) | |||
326 | svcpu_put(svcpu); | 378 | svcpu_put(svcpu); |
327 | } | 379 | } |
328 | 380 | ||
329 | void kvmppc_mmu_destroy(struct kvm_vcpu *vcpu) | 381 | void kvmppc_mmu_destroy_pr(struct kvm_vcpu *vcpu) |
330 | { | 382 | { |
331 | kvmppc_mmu_hpte_destroy(vcpu); | 383 | kvmppc_mmu_hpte_destroy(vcpu); |
332 | __destroy_context(to_book3s(vcpu)->context_id[0]); | 384 | __destroy_context(to_book3s(vcpu)->context_id[0]); |
diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c index 043eec8461e7..f3ff587a8b7d 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_hv.c +++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c | |||
@@ -260,10 +260,6 @@ int kvmppc_mmu_hv_init(void) | |||
260 | return 0; | 260 | return 0; |
261 | } | 261 | } |
262 | 262 | ||
263 | void kvmppc_mmu_destroy(struct kvm_vcpu *vcpu) | ||
264 | { | ||
265 | } | ||
266 | |||
267 | static void kvmppc_mmu_book3s_64_hv_reset_msr(struct kvm_vcpu *vcpu) | 263 | static void kvmppc_mmu_book3s_64_hv_reset_msr(struct kvm_vcpu *vcpu) |
268 | { | 264 | { |
269 | kvmppc_set_msr(vcpu, MSR_SF | MSR_ME); | 265 | kvmppc_set_msr(vcpu, MSR_SF | MSR_ME); |
@@ -451,7 +447,7 @@ static unsigned long kvmppc_mmu_get_real_addr(unsigned long v, unsigned long r, | |||
451 | } | 447 | } |
452 | 448 | ||
453 | static int kvmppc_mmu_book3s_64_hv_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, | 449 | static int kvmppc_mmu_book3s_64_hv_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, |
454 | struct kvmppc_pte *gpte, bool data) | 450 | struct kvmppc_pte *gpte, bool data, bool iswrite) |
455 | { | 451 | { |
456 | struct kvm *kvm = vcpu->kvm; | 452 | struct kvm *kvm = vcpu->kvm; |
457 | struct kvmppc_slb *slbe; | 453 | struct kvmppc_slb *slbe; |
@@ -906,21 +902,22 @@ static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp, | |||
906 | return 0; | 902 | return 0; |
907 | } | 903 | } |
908 | 904 | ||
909 | int kvm_unmap_hva(struct kvm *kvm, unsigned long hva) | 905 | int kvm_unmap_hva_hv(struct kvm *kvm, unsigned long hva) |
910 | { | 906 | { |
911 | if (kvm->arch.using_mmu_notifiers) | 907 | if (kvm->arch.using_mmu_notifiers) |
912 | kvm_handle_hva(kvm, hva, kvm_unmap_rmapp); | 908 | kvm_handle_hva(kvm, hva, kvm_unmap_rmapp); |
913 | return 0; | 909 | return 0; |
914 | } | 910 | } |
915 | 911 | ||
916 | int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end) | 912 | int kvm_unmap_hva_range_hv(struct kvm *kvm, unsigned long start, unsigned long end) |
917 | { | 913 | { |
918 | if (kvm->arch.using_mmu_notifiers) | 914 | if (kvm->arch.using_mmu_notifiers) |
919 | kvm_handle_hva_range(kvm, start, end, kvm_unmap_rmapp); | 915 | kvm_handle_hva_range(kvm, start, end, kvm_unmap_rmapp); |
920 | return 0; | 916 | return 0; |
921 | } | 917 | } |
922 | 918 | ||
923 | void kvmppc_core_flush_memslot(struct kvm *kvm, struct kvm_memory_slot *memslot) | 919 | void kvmppc_core_flush_memslot_hv(struct kvm *kvm, |
920 | struct kvm_memory_slot *memslot) | ||
924 | { | 921 | { |
925 | unsigned long *rmapp; | 922 | unsigned long *rmapp; |
926 | unsigned long gfn; | 923 | unsigned long gfn; |
@@ -994,7 +991,7 @@ static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp, | |||
994 | return ret; | 991 | return ret; |
995 | } | 992 | } |
996 | 993 | ||
997 | int kvm_age_hva(struct kvm *kvm, unsigned long hva) | 994 | int kvm_age_hva_hv(struct kvm *kvm, unsigned long hva) |
998 | { | 995 | { |
999 | if (!kvm->arch.using_mmu_notifiers) | 996 | if (!kvm->arch.using_mmu_notifiers) |
1000 | return 0; | 997 | return 0; |
@@ -1032,14 +1029,14 @@ static int kvm_test_age_rmapp(struct kvm *kvm, unsigned long *rmapp, | |||
1032 | return ret; | 1029 | return ret; |
1033 | } | 1030 | } |
1034 | 1031 | ||
1035 | int kvm_test_age_hva(struct kvm *kvm, unsigned long hva) | 1032 | int kvm_test_age_hva_hv(struct kvm *kvm, unsigned long hva) |
1036 | { | 1033 | { |
1037 | if (!kvm->arch.using_mmu_notifiers) | 1034 | if (!kvm->arch.using_mmu_notifiers) |
1038 | return 0; | 1035 | return 0; |
1039 | return kvm_handle_hva(kvm, hva, kvm_test_age_rmapp); | 1036 | return kvm_handle_hva(kvm, hva, kvm_test_age_rmapp); |
1040 | } | 1037 | } |
1041 | 1038 | ||
1042 | void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte) | 1039 | void kvm_set_spte_hva_hv(struct kvm *kvm, unsigned long hva, pte_t pte) |
1043 | { | 1040 | { |
1044 | if (!kvm->arch.using_mmu_notifiers) | 1041 | if (!kvm->arch.using_mmu_notifiers) |
1045 | return; | 1042 | return; |
@@ -1512,9 +1509,8 @@ static ssize_t kvm_htab_write(struct file *file, const char __user *buf, | |||
1512 | 1509 | ||
1513 | kvm->arch.vrma_slb_v = senc | SLB_VSID_B_1T | | 1510 | kvm->arch.vrma_slb_v = senc | SLB_VSID_B_1T | |
1514 | (VRMA_VSID << SLB_VSID_SHIFT_1T); | 1511 | (VRMA_VSID << SLB_VSID_SHIFT_1T); |
1515 | lpcr = kvm->arch.lpcr & ~LPCR_VRMASD; | 1512 | lpcr = senc << (LPCR_VRMASD_SH - 4); |
1516 | lpcr |= senc << (LPCR_VRMASD_SH - 4); | 1513 | kvmppc_update_lpcr(kvm, lpcr, LPCR_VRMASD); |
1517 | kvm->arch.lpcr = lpcr; | ||
1518 | rma_setup = 1; | 1514 | rma_setup = 1; |
1519 | } | 1515 | } |
1520 | ++i; | 1516 | ++i; |
diff --git a/arch/powerpc/kvm/book3s_64_vio_hv.c b/arch/powerpc/kvm/book3s_64_vio_hv.c index 30c2f3b134c6..2c25f5412bdb 100644 --- a/arch/powerpc/kvm/book3s_64_vio_hv.c +++ b/arch/powerpc/kvm/book3s_64_vio_hv.c | |||
@@ -74,3 +74,4 @@ long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn, | |||
74 | /* Didn't find the liobn, punt it to userspace */ | 74 | /* Didn't find the liobn, punt it to userspace */ |
75 | return H_TOO_HARD; | 75 | return H_TOO_HARD; |
76 | } | 76 | } |
77 | EXPORT_SYMBOL_GPL(kvmppc_h_put_tce); | ||
diff --git a/arch/powerpc/kvm/book3s_emulate.c b/arch/powerpc/kvm/book3s_emulate.c index 360ce68c9809..99d40f8977e8 100644 --- a/arch/powerpc/kvm/book3s_emulate.c +++ b/arch/powerpc/kvm/book3s_emulate.c | |||
@@ -86,8 +86,8 @@ static bool spr_allowed(struct kvm_vcpu *vcpu, enum priv_level level) | |||
86 | return true; | 86 | return true; |
87 | } | 87 | } |
88 | 88 | ||
89 | int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, | 89 | int kvmppc_core_emulate_op_pr(struct kvm_run *run, struct kvm_vcpu *vcpu, |
90 | unsigned int inst, int *advance) | 90 | unsigned int inst, int *advance) |
91 | { | 91 | { |
92 | int emulated = EMULATE_DONE; | 92 | int emulated = EMULATE_DONE; |
93 | int rt = get_rt(inst); | 93 | int rt = get_rt(inst); |
@@ -172,7 +172,7 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
172 | vcpu->arch.mmu.tlbie(vcpu, addr, large); | 172 | vcpu->arch.mmu.tlbie(vcpu, addr, large); |
173 | break; | 173 | break; |
174 | } | 174 | } |
175 | #ifdef CONFIG_KVM_BOOK3S_64_PR | 175 | #ifdef CONFIG_PPC_BOOK3S_64 |
176 | case OP_31_XOP_FAKE_SC1: | 176 | case OP_31_XOP_FAKE_SC1: |
177 | { | 177 | { |
178 | /* SC 1 papr hypercalls */ | 178 | /* SC 1 papr hypercalls */ |
@@ -267,12 +267,9 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
267 | 267 | ||
268 | r = kvmppc_st(vcpu, &addr, 32, zeros, true); | 268 | r = kvmppc_st(vcpu, &addr, 32, zeros, true); |
269 | if ((r == -ENOENT) || (r == -EPERM)) { | 269 | if ((r == -ENOENT) || (r == -EPERM)) { |
270 | struct kvmppc_book3s_shadow_vcpu *svcpu; | ||
271 | |||
272 | svcpu = svcpu_get(vcpu); | ||
273 | *advance = 0; | 270 | *advance = 0; |
274 | vcpu->arch.shared->dar = vaddr; | 271 | vcpu->arch.shared->dar = vaddr; |
275 | svcpu->fault_dar = vaddr; | 272 | vcpu->arch.fault_dar = vaddr; |
276 | 273 | ||
277 | dsisr = DSISR_ISSTORE; | 274 | dsisr = DSISR_ISSTORE; |
278 | if (r == -ENOENT) | 275 | if (r == -ENOENT) |
@@ -281,8 +278,7 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
281 | dsisr |= DSISR_PROTFAULT; | 278 | dsisr |= DSISR_PROTFAULT; |
282 | 279 | ||
283 | vcpu->arch.shared->dsisr = dsisr; | 280 | vcpu->arch.shared->dsisr = dsisr; |
284 | svcpu->fault_dsisr = dsisr; | 281 | vcpu->arch.fault_dsisr = dsisr; |
285 | svcpu_put(svcpu); | ||
286 | 282 | ||
287 | kvmppc_book3s_queue_irqprio(vcpu, | 283 | kvmppc_book3s_queue_irqprio(vcpu, |
288 | BOOK3S_INTERRUPT_DATA_STORAGE); | 284 | BOOK3S_INTERRUPT_DATA_STORAGE); |
@@ -349,7 +345,7 @@ static struct kvmppc_bat *kvmppc_find_bat(struct kvm_vcpu *vcpu, int sprn) | |||
349 | return bat; | 345 | return bat; |
350 | } | 346 | } |
351 | 347 | ||
352 | int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val) | 348 | int kvmppc_core_emulate_mtspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val) |
353 | { | 349 | { |
354 | int emulated = EMULATE_DONE; | 350 | int emulated = EMULATE_DONE; |
355 | 351 | ||
@@ -472,7 +468,7 @@ unprivileged: | |||
472 | return emulated; | 468 | return emulated; |
473 | } | 469 | } |
474 | 470 | ||
475 | int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val) | 471 | int kvmppc_core_emulate_mfspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val) |
476 | { | 472 | { |
477 | int emulated = EMULATE_DONE; | 473 | int emulated = EMULATE_DONE; |
478 | 474 | ||
diff --git a/arch/powerpc/kvm/book3s_exports.c b/arch/powerpc/kvm/book3s_exports.c index 7057a02f0906..852989a9bad3 100644 --- a/arch/powerpc/kvm/book3s_exports.c +++ b/arch/powerpc/kvm/book3s_exports.c | |||
@@ -20,9 +20,10 @@ | |||
20 | #include <linux/export.h> | 20 | #include <linux/export.h> |
21 | #include <asm/kvm_book3s.h> | 21 | #include <asm/kvm_book3s.h> |
22 | 22 | ||
23 | #ifdef CONFIG_KVM_BOOK3S_64_HV | 23 | #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE |
24 | EXPORT_SYMBOL_GPL(kvmppc_hv_entry_trampoline); | 24 | EXPORT_SYMBOL_GPL(kvmppc_hv_entry_trampoline); |
25 | #else | 25 | #endif |
26 | #ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE | ||
26 | EXPORT_SYMBOL_GPL(kvmppc_entry_trampoline); | 27 | EXPORT_SYMBOL_GPL(kvmppc_entry_trampoline); |
27 | EXPORT_SYMBOL_GPL(kvmppc_load_up_fpu); | 28 | EXPORT_SYMBOL_GPL(kvmppc_load_up_fpu); |
28 | #ifdef CONFIG_ALTIVEC | 29 | #ifdef CONFIG_ALTIVEC |
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c index 62a2b5ab08ed..072287f1c3bc 100644 --- a/arch/powerpc/kvm/book3s_hv.c +++ b/arch/powerpc/kvm/book3s_hv.c | |||
@@ -52,6 +52,9 @@ | |||
52 | #include <linux/vmalloc.h> | 52 | #include <linux/vmalloc.h> |
53 | #include <linux/highmem.h> | 53 | #include <linux/highmem.h> |
54 | #include <linux/hugetlb.h> | 54 | #include <linux/hugetlb.h> |
55 | #include <linux/module.h> | ||
56 | |||
57 | #include "book3s.h" | ||
55 | 58 | ||
56 | /* #define EXIT_DEBUG */ | 59 | /* #define EXIT_DEBUG */ |
57 | /* #define EXIT_DEBUG_SIMPLE */ | 60 | /* #define EXIT_DEBUG_SIMPLE */ |
@@ -66,7 +69,7 @@ | |||
66 | static void kvmppc_end_cede(struct kvm_vcpu *vcpu); | 69 | static void kvmppc_end_cede(struct kvm_vcpu *vcpu); |
67 | static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu); | 70 | static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu); |
68 | 71 | ||
69 | void kvmppc_fast_vcpu_kick(struct kvm_vcpu *vcpu) | 72 | static void kvmppc_fast_vcpu_kick_hv(struct kvm_vcpu *vcpu) |
70 | { | 73 | { |
71 | int me; | 74 | int me; |
72 | int cpu = vcpu->cpu; | 75 | int cpu = vcpu->cpu; |
@@ -125,7 +128,7 @@ void kvmppc_fast_vcpu_kick(struct kvm_vcpu *vcpu) | |||
125 | * purely defensive; they should never fail.) | 128 | * purely defensive; they should never fail.) |
126 | */ | 129 | */ |
127 | 130 | ||
128 | void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu) | 131 | static void kvmppc_core_vcpu_load_hv(struct kvm_vcpu *vcpu, int cpu) |
129 | { | 132 | { |
130 | struct kvmppc_vcore *vc = vcpu->arch.vcore; | 133 | struct kvmppc_vcore *vc = vcpu->arch.vcore; |
131 | 134 | ||
@@ -143,7 +146,7 @@ void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu) | |||
143 | spin_unlock(&vcpu->arch.tbacct_lock); | 146 | spin_unlock(&vcpu->arch.tbacct_lock); |
144 | } | 147 | } |
145 | 148 | ||
146 | void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu) | 149 | static void kvmppc_core_vcpu_put_hv(struct kvm_vcpu *vcpu) |
147 | { | 150 | { |
148 | struct kvmppc_vcore *vc = vcpu->arch.vcore; | 151 | struct kvmppc_vcore *vc = vcpu->arch.vcore; |
149 | 152 | ||
@@ -155,17 +158,46 @@ void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu) | |||
155 | spin_unlock(&vcpu->arch.tbacct_lock); | 158 | spin_unlock(&vcpu->arch.tbacct_lock); |
156 | } | 159 | } |
157 | 160 | ||
158 | void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 msr) | 161 | static void kvmppc_set_msr_hv(struct kvm_vcpu *vcpu, u64 msr) |
159 | { | 162 | { |
160 | vcpu->arch.shregs.msr = msr; | 163 | vcpu->arch.shregs.msr = msr; |
161 | kvmppc_end_cede(vcpu); | 164 | kvmppc_end_cede(vcpu); |
162 | } | 165 | } |
163 | 166 | ||
164 | void kvmppc_set_pvr(struct kvm_vcpu *vcpu, u32 pvr) | 167 | void kvmppc_set_pvr_hv(struct kvm_vcpu *vcpu, u32 pvr) |
165 | { | 168 | { |
166 | vcpu->arch.pvr = pvr; | 169 | vcpu->arch.pvr = pvr; |
167 | } | 170 | } |
168 | 171 | ||
172 | int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat) | ||
173 | { | ||
174 | unsigned long pcr = 0; | ||
175 | struct kvmppc_vcore *vc = vcpu->arch.vcore; | ||
176 | |||
177 | if (arch_compat) { | ||
178 | if (!cpu_has_feature(CPU_FTR_ARCH_206)) | ||
179 | return -EINVAL; /* 970 has no compat mode support */ | ||
180 | |||
181 | switch (arch_compat) { | ||
182 | case PVR_ARCH_205: | ||
183 | pcr = PCR_ARCH_205; | ||
184 | break; | ||
185 | case PVR_ARCH_206: | ||
186 | case PVR_ARCH_206p: | ||
187 | break; | ||
188 | default: | ||
189 | return -EINVAL; | ||
190 | } | ||
191 | } | ||
192 | |||
193 | spin_lock(&vc->lock); | ||
194 | vc->arch_compat = arch_compat; | ||
195 | vc->pcr = pcr; | ||
196 | spin_unlock(&vc->lock); | ||
197 | |||
198 | return 0; | ||
199 | } | ||
200 | |||
169 | void kvmppc_dump_regs(struct kvm_vcpu *vcpu) | 201 | void kvmppc_dump_regs(struct kvm_vcpu *vcpu) |
170 | { | 202 | { |
171 | int r; | 203 | int r; |
@@ -195,7 +227,7 @@ void kvmppc_dump_regs(struct kvm_vcpu *vcpu) | |||
195 | pr_err(" ESID = %.16llx VSID = %.16llx\n", | 227 | pr_err(" ESID = %.16llx VSID = %.16llx\n", |
196 | vcpu->arch.slb[r].orige, vcpu->arch.slb[r].origv); | 228 | vcpu->arch.slb[r].orige, vcpu->arch.slb[r].origv); |
197 | pr_err("lpcr = %.16lx sdr1 = %.16lx last_inst = %.8x\n", | 229 | pr_err("lpcr = %.16lx sdr1 = %.16lx last_inst = %.8x\n", |
198 | vcpu->kvm->arch.lpcr, vcpu->kvm->arch.sdr1, | 230 | vcpu->arch.vcore->lpcr, vcpu->kvm->arch.sdr1, |
199 | vcpu->arch.last_inst); | 231 | vcpu->arch.last_inst); |
200 | } | 232 | } |
201 | 233 | ||
@@ -489,7 +521,7 @@ static void kvmppc_create_dtl_entry(struct kvm_vcpu *vcpu, | |||
489 | memset(dt, 0, sizeof(struct dtl_entry)); | 521 | memset(dt, 0, sizeof(struct dtl_entry)); |
490 | dt->dispatch_reason = 7; | 522 | dt->dispatch_reason = 7; |
491 | dt->processor_id = vc->pcpu + vcpu->arch.ptid; | 523 | dt->processor_id = vc->pcpu + vcpu->arch.ptid; |
492 | dt->timebase = now; | 524 | dt->timebase = now + vc->tb_offset; |
493 | dt->enqueue_to_dispatch_time = stolen; | 525 | dt->enqueue_to_dispatch_time = stolen; |
494 | dt->srr0 = kvmppc_get_pc(vcpu); | 526 | dt->srr0 = kvmppc_get_pc(vcpu); |
495 | dt->srr1 = vcpu->arch.shregs.msr; | 527 | dt->srr1 = vcpu->arch.shregs.msr; |
@@ -538,6 +570,15 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu) | |||
538 | } | 570 | } |
539 | break; | 571 | break; |
540 | case H_CONFER: | 572 | case H_CONFER: |
573 | target = kvmppc_get_gpr(vcpu, 4); | ||
574 | if (target == -1) | ||
575 | break; | ||
576 | tvcpu = kvmppc_find_vcpu(vcpu->kvm, target); | ||
577 | if (!tvcpu) { | ||
578 | ret = H_PARAMETER; | ||
579 | break; | ||
580 | } | ||
581 | kvm_vcpu_yield_to(tvcpu); | ||
541 | break; | 582 | break; |
542 | case H_REGISTER_VPA: | 583 | case H_REGISTER_VPA: |
543 | ret = do_h_register_vpa(vcpu, kvmppc_get_gpr(vcpu, 4), | 584 | ret = do_h_register_vpa(vcpu, kvmppc_get_gpr(vcpu, 4), |
@@ -576,8 +617,8 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu) | |||
576 | return RESUME_GUEST; | 617 | return RESUME_GUEST; |
577 | } | 618 | } |
578 | 619 | ||
579 | static int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | 620 | static int kvmppc_handle_exit_hv(struct kvm_run *run, struct kvm_vcpu *vcpu, |
580 | struct task_struct *tsk) | 621 | struct task_struct *tsk) |
581 | { | 622 | { |
582 | int r = RESUME_HOST; | 623 | int r = RESUME_HOST; |
583 | 624 | ||
@@ -671,16 +712,16 @@ static int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
671 | printk(KERN_EMERG "trap=0x%x | pc=0x%lx | msr=0x%llx\n", | 712 | printk(KERN_EMERG "trap=0x%x | pc=0x%lx | msr=0x%llx\n", |
672 | vcpu->arch.trap, kvmppc_get_pc(vcpu), | 713 | vcpu->arch.trap, kvmppc_get_pc(vcpu), |
673 | vcpu->arch.shregs.msr); | 714 | vcpu->arch.shregs.msr); |
715 | run->hw.hardware_exit_reason = vcpu->arch.trap; | ||
674 | r = RESUME_HOST; | 716 | r = RESUME_HOST; |
675 | BUG(); | ||
676 | break; | 717 | break; |
677 | } | 718 | } |
678 | 719 | ||
679 | return r; | 720 | return r; |
680 | } | 721 | } |
681 | 722 | ||
682 | int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu, | 723 | static int kvm_arch_vcpu_ioctl_get_sregs_hv(struct kvm_vcpu *vcpu, |
683 | struct kvm_sregs *sregs) | 724 | struct kvm_sregs *sregs) |
684 | { | 725 | { |
685 | int i; | 726 | int i; |
686 | 727 | ||
@@ -694,12 +735,12 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu, | |||
694 | return 0; | 735 | return 0; |
695 | } | 736 | } |
696 | 737 | ||
697 | int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, | 738 | static int kvm_arch_vcpu_ioctl_set_sregs_hv(struct kvm_vcpu *vcpu, |
698 | struct kvm_sregs *sregs) | 739 | struct kvm_sregs *sregs) |
699 | { | 740 | { |
700 | int i, j; | 741 | int i, j; |
701 | 742 | ||
702 | kvmppc_set_pvr(vcpu, sregs->pvr); | 743 | kvmppc_set_pvr_hv(vcpu, sregs->pvr); |
703 | 744 | ||
704 | j = 0; | 745 | j = 0; |
705 | for (i = 0; i < vcpu->arch.slb_nr; i++) { | 746 | for (i = 0; i < vcpu->arch.slb_nr; i++) { |
@@ -714,7 +755,23 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, | |||
714 | return 0; | 755 | return 0; |
715 | } | 756 | } |
716 | 757 | ||
717 | int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val) | 758 | static void kvmppc_set_lpcr(struct kvm_vcpu *vcpu, u64 new_lpcr) |
759 | { | ||
760 | struct kvmppc_vcore *vc = vcpu->arch.vcore; | ||
761 | u64 mask; | ||
762 | |||
763 | spin_lock(&vc->lock); | ||
764 | /* | ||
765 | * Userspace can only modify DPFD (default prefetch depth), | ||
766 | * ILE (interrupt little-endian) and TC (translation control). | ||
767 | */ | ||
768 | mask = LPCR_DPFD | LPCR_ILE | LPCR_TC; | ||
769 | vc->lpcr = (vc->lpcr & ~mask) | (new_lpcr & mask); | ||
770 | spin_unlock(&vc->lock); | ||
771 | } | ||
772 | |||
773 | static int kvmppc_get_one_reg_hv(struct kvm_vcpu *vcpu, u64 id, | ||
774 | union kvmppc_one_reg *val) | ||
718 | { | 775 | { |
719 | int r = 0; | 776 | int r = 0; |
720 | long int i; | 777 | long int i; |
@@ -749,6 +806,12 @@ int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val) | |||
749 | i = id - KVM_REG_PPC_PMC1; | 806 | i = id - KVM_REG_PPC_PMC1; |
750 | *val = get_reg_val(id, vcpu->arch.pmc[i]); | 807 | *val = get_reg_val(id, vcpu->arch.pmc[i]); |
751 | break; | 808 | break; |
809 | case KVM_REG_PPC_SIAR: | ||
810 | *val = get_reg_val(id, vcpu->arch.siar); | ||
811 | break; | ||
812 | case KVM_REG_PPC_SDAR: | ||
813 | *val = get_reg_val(id, vcpu->arch.sdar); | ||
814 | break; | ||
752 | #ifdef CONFIG_VSX | 815 | #ifdef CONFIG_VSX |
753 | case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31: | 816 | case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31: |
754 | if (cpu_has_feature(CPU_FTR_VSX)) { | 817 | if (cpu_has_feature(CPU_FTR_VSX)) { |
@@ -787,6 +850,18 @@ int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val) | |||
787 | val->vpaval.length = vcpu->arch.dtl.len; | 850 | val->vpaval.length = vcpu->arch.dtl.len; |
788 | spin_unlock(&vcpu->arch.vpa_update_lock); | 851 | spin_unlock(&vcpu->arch.vpa_update_lock); |
789 | break; | 852 | break; |
853 | case KVM_REG_PPC_TB_OFFSET: | ||
854 | *val = get_reg_val(id, vcpu->arch.vcore->tb_offset); | ||
855 | break; | ||
856 | case KVM_REG_PPC_LPCR: | ||
857 | *val = get_reg_val(id, vcpu->arch.vcore->lpcr); | ||
858 | break; | ||
859 | case KVM_REG_PPC_PPR: | ||
860 | *val = get_reg_val(id, vcpu->arch.ppr); | ||
861 | break; | ||
862 | case KVM_REG_PPC_ARCH_COMPAT: | ||
863 | *val = get_reg_val(id, vcpu->arch.vcore->arch_compat); | ||
864 | break; | ||
790 | default: | 865 | default: |
791 | r = -EINVAL; | 866 | r = -EINVAL; |
792 | break; | 867 | break; |
@@ -795,7 +870,8 @@ int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val) | |||
795 | return r; | 870 | return r; |
796 | } | 871 | } |
797 | 872 | ||
798 | int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val) | 873 | static int kvmppc_set_one_reg_hv(struct kvm_vcpu *vcpu, u64 id, |
874 | union kvmppc_one_reg *val) | ||
799 | { | 875 | { |
800 | int r = 0; | 876 | int r = 0; |
801 | long int i; | 877 | long int i; |
@@ -833,6 +909,12 @@ int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val) | |||
833 | i = id - KVM_REG_PPC_PMC1; | 909 | i = id - KVM_REG_PPC_PMC1; |
834 | vcpu->arch.pmc[i] = set_reg_val(id, *val); | 910 | vcpu->arch.pmc[i] = set_reg_val(id, *val); |
835 | break; | 911 | break; |
912 | case KVM_REG_PPC_SIAR: | ||
913 | vcpu->arch.siar = set_reg_val(id, *val); | ||
914 | break; | ||
915 | case KVM_REG_PPC_SDAR: | ||
916 | vcpu->arch.sdar = set_reg_val(id, *val); | ||
917 | break; | ||
836 | #ifdef CONFIG_VSX | 918 | #ifdef CONFIG_VSX |
837 | case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31: | 919 | case KVM_REG_PPC_FPR0 ... KVM_REG_PPC_FPR31: |
838 | if (cpu_has_feature(CPU_FTR_VSX)) { | 920 | if (cpu_has_feature(CPU_FTR_VSX)) { |
@@ -880,6 +962,20 @@ int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val) | |||
880 | len -= len % sizeof(struct dtl_entry); | 962 | len -= len % sizeof(struct dtl_entry); |
881 | r = set_vpa(vcpu, &vcpu->arch.dtl, addr, len); | 963 | r = set_vpa(vcpu, &vcpu->arch.dtl, addr, len); |
882 | break; | 964 | break; |
965 | case KVM_REG_PPC_TB_OFFSET: | ||
966 | /* round up to multiple of 2^24 */ | ||
967 | vcpu->arch.vcore->tb_offset = | ||
968 | ALIGN(set_reg_val(id, *val), 1UL << 24); | ||
969 | break; | ||
970 | case KVM_REG_PPC_LPCR: | ||
971 | kvmppc_set_lpcr(vcpu, set_reg_val(id, *val)); | ||
972 | break; | ||
973 | case KVM_REG_PPC_PPR: | ||
974 | vcpu->arch.ppr = set_reg_val(id, *val); | ||
975 | break; | ||
976 | case KVM_REG_PPC_ARCH_COMPAT: | ||
977 | r = kvmppc_set_arch_compat(vcpu, set_reg_val(id, *val)); | ||
978 | break; | ||
883 | default: | 979 | default: |
884 | r = -EINVAL; | 980 | r = -EINVAL; |
885 | break; | 981 | break; |
@@ -888,14 +984,8 @@ int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val) | |||
888 | return r; | 984 | return r; |
889 | } | 985 | } |
890 | 986 | ||
891 | int kvmppc_core_check_processor_compat(void) | 987 | static struct kvm_vcpu *kvmppc_core_vcpu_create_hv(struct kvm *kvm, |
892 | { | 988 | unsigned int id) |
893 | if (cpu_has_feature(CPU_FTR_HVMODE)) | ||
894 | return 0; | ||
895 | return -EIO; | ||
896 | } | ||
897 | |||
898 | struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id) | ||
899 | { | 989 | { |
900 | struct kvm_vcpu *vcpu; | 990 | struct kvm_vcpu *vcpu; |
901 | int err = -EINVAL; | 991 | int err = -EINVAL; |
@@ -919,8 +1009,7 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id) | |||
919 | vcpu->arch.mmcr[0] = MMCR0_FC; | 1009 | vcpu->arch.mmcr[0] = MMCR0_FC; |
920 | vcpu->arch.ctrl = CTRL_RUNLATCH; | 1010 | vcpu->arch.ctrl = CTRL_RUNLATCH; |
921 | /* default to host PVR, since we can't spoof it */ | 1011 | /* default to host PVR, since we can't spoof it */ |
922 | vcpu->arch.pvr = mfspr(SPRN_PVR); | 1012 | kvmppc_set_pvr_hv(vcpu, mfspr(SPRN_PVR)); |
923 | kvmppc_set_pvr(vcpu, vcpu->arch.pvr); | ||
924 | spin_lock_init(&vcpu->arch.vpa_update_lock); | 1013 | spin_lock_init(&vcpu->arch.vpa_update_lock); |
925 | spin_lock_init(&vcpu->arch.tbacct_lock); | 1014 | spin_lock_init(&vcpu->arch.tbacct_lock); |
926 | vcpu->arch.busy_preempt = TB_NIL; | 1015 | vcpu->arch.busy_preempt = TB_NIL; |
@@ -940,6 +1029,7 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id) | |||
940 | spin_lock_init(&vcore->lock); | 1029 | spin_lock_init(&vcore->lock); |
941 | init_waitqueue_head(&vcore->wq); | 1030 | init_waitqueue_head(&vcore->wq); |
942 | vcore->preempt_tb = TB_NIL; | 1031 | vcore->preempt_tb = TB_NIL; |
1032 | vcore->lpcr = kvm->arch.lpcr; | ||
943 | } | 1033 | } |
944 | kvm->arch.vcores[core] = vcore; | 1034 | kvm->arch.vcores[core] = vcore; |
945 | kvm->arch.online_vcores++; | 1035 | kvm->arch.online_vcores++; |
@@ -972,7 +1062,7 @@ static void unpin_vpa(struct kvm *kvm, struct kvmppc_vpa *vpa) | |||
972 | vpa->dirty); | 1062 | vpa->dirty); |
973 | } | 1063 | } |
974 | 1064 | ||
975 | void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu) | 1065 | static void kvmppc_core_vcpu_free_hv(struct kvm_vcpu *vcpu) |
976 | { | 1066 | { |
977 | spin_lock(&vcpu->arch.vpa_update_lock); | 1067 | spin_lock(&vcpu->arch.vpa_update_lock); |
978 | unpin_vpa(vcpu->kvm, &vcpu->arch.dtl); | 1068 | unpin_vpa(vcpu->kvm, &vcpu->arch.dtl); |
@@ -983,6 +1073,12 @@ void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu) | |||
983 | kmem_cache_free(kvm_vcpu_cache, vcpu); | 1073 | kmem_cache_free(kvm_vcpu_cache, vcpu); |
984 | } | 1074 | } |
985 | 1075 | ||
1076 | static int kvmppc_core_check_requests_hv(struct kvm_vcpu *vcpu) | ||
1077 | { | ||
1078 | /* Indicate we want to get back into the guest */ | ||
1079 | return 1; | ||
1080 | } | ||
1081 | |||
986 | static void kvmppc_set_timer(struct kvm_vcpu *vcpu) | 1082 | static void kvmppc_set_timer(struct kvm_vcpu *vcpu) |
987 | { | 1083 | { |
988 | unsigned long dec_nsec, now; | 1084 | unsigned long dec_nsec, now; |
@@ -1264,8 +1360,8 @@ static void kvmppc_run_core(struct kvmppc_vcore *vc) | |||
1264 | 1360 | ||
1265 | ret = RESUME_GUEST; | 1361 | ret = RESUME_GUEST; |
1266 | if (vcpu->arch.trap) | 1362 | if (vcpu->arch.trap) |
1267 | ret = kvmppc_handle_exit(vcpu->arch.kvm_run, vcpu, | 1363 | ret = kvmppc_handle_exit_hv(vcpu->arch.kvm_run, vcpu, |
1268 | vcpu->arch.run_task); | 1364 | vcpu->arch.run_task); |
1269 | 1365 | ||
1270 | vcpu->arch.ret = ret; | 1366 | vcpu->arch.ret = ret; |
1271 | vcpu->arch.trap = 0; | 1367 | vcpu->arch.trap = 0; |
@@ -1424,7 +1520,7 @@ static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) | |||
1424 | return vcpu->arch.ret; | 1520 | return vcpu->arch.ret; |
1425 | } | 1521 | } |
1426 | 1522 | ||
1427 | int kvmppc_vcpu_run(struct kvm_run *run, struct kvm_vcpu *vcpu) | 1523 | static int kvmppc_vcpu_run_hv(struct kvm_run *run, struct kvm_vcpu *vcpu) |
1428 | { | 1524 | { |
1429 | int r; | 1525 | int r; |
1430 | int srcu_idx; | 1526 | int srcu_idx; |
@@ -1546,7 +1642,8 @@ static const struct file_operations kvm_rma_fops = { | |||
1546 | .release = kvm_rma_release, | 1642 | .release = kvm_rma_release, |
1547 | }; | 1643 | }; |
1548 | 1644 | ||
1549 | long kvm_vm_ioctl_allocate_rma(struct kvm *kvm, struct kvm_allocate_rma *ret) | 1645 | static long kvm_vm_ioctl_allocate_rma(struct kvm *kvm, |
1646 | struct kvm_allocate_rma *ret) | ||
1550 | { | 1647 | { |
1551 | long fd; | 1648 | long fd; |
1552 | struct kvm_rma_info *ri; | 1649 | struct kvm_rma_info *ri; |
@@ -1592,7 +1689,8 @@ static void kvmppc_add_seg_page_size(struct kvm_ppc_one_seg_page_size **sps, | |||
1592 | (*sps)++; | 1689 | (*sps)++; |
1593 | } | 1690 | } |
1594 | 1691 | ||
1595 | int kvm_vm_ioctl_get_smmu_info(struct kvm *kvm, struct kvm_ppc_smmu_info *info) | 1692 | static int kvm_vm_ioctl_get_smmu_info_hv(struct kvm *kvm, |
1693 | struct kvm_ppc_smmu_info *info) | ||
1596 | { | 1694 | { |
1597 | struct kvm_ppc_one_seg_page_size *sps; | 1695 | struct kvm_ppc_one_seg_page_size *sps; |
1598 | 1696 | ||
@@ -1613,7 +1711,8 @@ int kvm_vm_ioctl_get_smmu_info(struct kvm *kvm, struct kvm_ppc_smmu_info *info) | |||
1613 | /* | 1711 | /* |
1614 | * Get (and clear) the dirty memory log for a memory slot. | 1712 | * Get (and clear) the dirty memory log for a memory slot. |
1615 | */ | 1713 | */ |
1616 | int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log) | 1714 | static int kvm_vm_ioctl_get_dirty_log_hv(struct kvm *kvm, |
1715 | struct kvm_dirty_log *log) | ||
1617 | { | 1716 | { |
1618 | struct kvm_memory_slot *memslot; | 1717 | struct kvm_memory_slot *memslot; |
1619 | int r; | 1718 | int r; |
@@ -1667,8 +1766,8 @@ static void unpin_slot(struct kvm_memory_slot *memslot) | |||
1667 | } | 1766 | } |
1668 | } | 1767 | } |
1669 | 1768 | ||
1670 | void kvmppc_core_free_memslot(struct kvm_memory_slot *free, | 1769 | static void kvmppc_core_free_memslot_hv(struct kvm_memory_slot *free, |
1671 | struct kvm_memory_slot *dont) | 1770 | struct kvm_memory_slot *dont) |
1672 | { | 1771 | { |
1673 | if (!dont || free->arch.rmap != dont->arch.rmap) { | 1772 | if (!dont || free->arch.rmap != dont->arch.rmap) { |
1674 | vfree(free->arch.rmap); | 1773 | vfree(free->arch.rmap); |
@@ -1681,8 +1780,8 @@ void kvmppc_core_free_memslot(struct kvm_memory_slot *free, | |||
1681 | } | 1780 | } |
1682 | } | 1781 | } |
1683 | 1782 | ||
1684 | int kvmppc_core_create_memslot(struct kvm_memory_slot *slot, | 1783 | static int kvmppc_core_create_memslot_hv(struct kvm_memory_slot *slot, |
1685 | unsigned long npages) | 1784 | unsigned long npages) |
1686 | { | 1785 | { |
1687 | slot->arch.rmap = vzalloc(npages * sizeof(*slot->arch.rmap)); | 1786 | slot->arch.rmap = vzalloc(npages * sizeof(*slot->arch.rmap)); |
1688 | if (!slot->arch.rmap) | 1787 | if (!slot->arch.rmap) |
@@ -1692,9 +1791,9 @@ int kvmppc_core_create_memslot(struct kvm_memory_slot *slot, | |||
1692 | return 0; | 1791 | return 0; |
1693 | } | 1792 | } |
1694 | 1793 | ||
1695 | int kvmppc_core_prepare_memory_region(struct kvm *kvm, | 1794 | static int kvmppc_core_prepare_memory_region_hv(struct kvm *kvm, |
1696 | struct kvm_memory_slot *memslot, | 1795 | struct kvm_memory_slot *memslot, |
1697 | struct kvm_userspace_memory_region *mem) | 1796 | struct kvm_userspace_memory_region *mem) |
1698 | { | 1797 | { |
1699 | unsigned long *phys; | 1798 | unsigned long *phys; |
1700 | 1799 | ||
@@ -1710,9 +1809,9 @@ int kvmppc_core_prepare_memory_region(struct kvm *kvm, | |||
1710 | return 0; | 1809 | return 0; |
1711 | } | 1810 | } |
1712 | 1811 | ||
1713 | void kvmppc_core_commit_memory_region(struct kvm *kvm, | 1812 | static void kvmppc_core_commit_memory_region_hv(struct kvm *kvm, |
1714 | struct kvm_userspace_memory_region *mem, | 1813 | struct kvm_userspace_memory_region *mem, |
1715 | const struct kvm_memory_slot *old) | 1814 | const struct kvm_memory_slot *old) |
1716 | { | 1815 | { |
1717 | unsigned long npages = mem->memory_size >> PAGE_SHIFT; | 1816 | unsigned long npages = mem->memory_size >> PAGE_SHIFT; |
1718 | struct kvm_memory_slot *memslot; | 1817 | struct kvm_memory_slot *memslot; |
@@ -1729,6 +1828,37 @@ void kvmppc_core_commit_memory_region(struct kvm *kvm, | |||
1729 | } | 1828 | } |
1730 | } | 1829 | } |
1731 | 1830 | ||
1831 | /* | ||
1832 | * Update LPCR values in kvm->arch and in vcores. | ||
1833 | * Caller must hold kvm->lock. | ||
1834 | */ | ||
1835 | void kvmppc_update_lpcr(struct kvm *kvm, unsigned long lpcr, unsigned long mask) | ||
1836 | { | ||
1837 | long int i; | ||
1838 | u32 cores_done = 0; | ||
1839 | |||
1840 | if ((kvm->arch.lpcr & mask) == lpcr) | ||
1841 | return; | ||
1842 | |||
1843 | kvm->arch.lpcr = (kvm->arch.lpcr & ~mask) | lpcr; | ||
1844 | |||
1845 | for (i = 0; i < KVM_MAX_VCORES; ++i) { | ||
1846 | struct kvmppc_vcore *vc = kvm->arch.vcores[i]; | ||
1847 | if (!vc) | ||
1848 | continue; | ||
1849 | spin_lock(&vc->lock); | ||
1850 | vc->lpcr = (vc->lpcr & ~mask) | lpcr; | ||
1851 | spin_unlock(&vc->lock); | ||
1852 | if (++cores_done >= kvm->arch.online_vcores) | ||
1853 | break; | ||
1854 | } | ||
1855 | } | ||
1856 | |||
1857 | static void kvmppc_mmu_destroy_hv(struct kvm_vcpu *vcpu) | ||
1858 | { | ||
1859 | return; | ||
1860 | } | ||
1861 | |||
1732 | static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu) | 1862 | static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu) |
1733 | { | 1863 | { |
1734 | int err = 0; | 1864 | int err = 0; |
@@ -1737,7 +1867,8 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu) | |||
1737 | unsigned long hva; | 1867 | unsigned long hva; |
1738 | struct kvm_memory_slot *memslot; | 1868 | struct kvm_memory_slot *memslot; |
1739 | struct vm_area_struct *vma; | 1869 | struct vm_area_struct *vma; |
1740 | unsigned long lpcr, senc; | 1870 | unsigned long lpcr = 0, senc; |
1871 | unsigned long lpcr_mask = 0; | ||
1741 | unsigned long psize, porder; | 1872 | unsigned long psize, porder; |
1742 | unsigned long rma_size; | 1873 | unsigned long rma_size; |
1743 | unsigned long rmls; | 1874 | unsigned long rmls; |
@@ -1802,9 +1933,9 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu) | |||
1802 | senc = slb_pgsize_encoding(psize); | 1933 | senc = slb_pgsize_encoding(psize); |
1803 | kvm->arch.vrma_slb_v = senc | SLB_VSID_B_1T | | 1934 | kvm->arch.vrma_slb_v = senc | SLB_VSID_B_1T | |
1804 | (VRMA_VSID << SLB_VSID_SHIFT_1T); | 1935 | (VRMA_VSID << SLB_VSID_SHIFT_1T); |
1805 | lpcr = kvm->arch.lpcr & ~LPCR_VRMASD; | 1936 | lpcr_mask = LPCR_VRMASD; |
1806 | lpcr |= senc << (LPCR_VRMASD_SH - 4); | 1937 | /* the -4 is to account for senc values starting at 0x10 */ |
1807 | kvm->arch.lpcr = lpcr; | 1938 | lpcr = senc << (LPCR_VRMASD_SH - 4); |
1808 | 1939 | ||
1809 | /* Create HPTEs in the hash page table for the VRMA */ | 1940 | /* Create HPTEs in the hash page table for the VRMA */ |
1810 | kvmppc_map_vrma(vcpu, memslot, porder); | 1941 | kvmppc_map_vrma(vcpu, memslot, porder); |
@@ -1825,23 +1956,21 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu) | |||
1825 | kvm->arch.rma = ri; | 1956 | kvm->arch.rma = ri; |
1826 | 1957 | ||
1827 | /* Update LPCR and RMOR */ | 1958 | /* Update LPCR and RMOR */ |
1828 | lpcr = kvm->arch.lpcr; | ||
1829 | if (cpu_has_feature(CPU_FTR_ARCH_201)) { | 1959 | if (cpu_has_feature(CPU_FTR_ARCH_201)) { |
1830 | /* PPC970; insert RMLS value (split field) in HID4 */ | 1960 | /* PPC970; insert RMLS value (split field) in HID4 */ |
1831 | lpcr &= ~((1ul << HID4_RMLS0_SH) | | 1961 | lpcr_mask = (1ul << HID4_RMLS0_SH) | |
1832 | (3ul << HID4_RMLS2_SH)); | 1962 | (3ul << HID4_RMLS2_SH) | HID4_RMOR; |
1833 | lpcr |= ((rmls >> 2) << HID4_RMLS0_SH) | | 1963 | lpcr = ((rmls >> 2) << HID4_RMLS0_SH) | |
1834 | ((rmls & 3) << HID4_RMLS2_SH); | 1964 | ((rmls & 3) << HID4_RMLS2_SH); |
1835 | /* RMOR is also in HID4 */ | 1965 | /* RMOR is also in HID4 */ |
1836 | lpcr |= ((ri->base_pfn >> (26 - PAGE_SHIFT)) & 0xffff) | 1966 | lpcr |= ((ri->base_pfn >> (26 - PAGE_SHIFT)) & 0xffff) |
1837 | << HID4_RMOR_SH; | 1967 | << HID4_RMOR_SH; |
1838 | } else { | 1968 | } else { |
1839 | /* POWER7 */ | 1969 | /* POWER7 */ |
1840 | lpcr &= ~(LPCR_VPM0 | LPCR_VRMA_L); | 1970 | lpcr_mask = LPCR_VPM0 | LPCR_VRMA_L | LPCR_RMLS; |
1841 | lpcr |= rmls << LPCR_RMLS_SH; | 1971 | lpcr = rmls << LPCR_RMLS_SH; |
1842 | kvm->arch.rmor = ri->base_pfn << PAGE_SHIFT; | 1972 | kvm->arch.rmor = ri->base_pfn << PAGE_SHIFT; |
1843 | } | 1973 | } |
1844 | kvm->arch.lpcr = lpcr; | ||
1845 | pr_info("KVM: Using RMO at %lx size %lx (LPCR = %lx)\n", | 1974 | pr_info("KVM: Using RMO at %lx size %lx (LPCR = %lx)\n", |
1846 | ri->base_pfn << PAGE_SHIFT, rma_size, lpcr); | 1975 | ri->base_pfn << PAGE_SHIFT, rma_size, lpcr); |
1847 | 1976 | ||
@@ -1860,6 +1989,8 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu) | |||
1860 | } | 1989 | } |
1861 | } | 1990 | } |
1862 | 1991 | ||
1992 | kvmppc_update_lpcr(kvm, lpcr, lpcr_mask); | ||
1993 | |||
1863 | /* Order updates to kvm->arch.lpcr etc. vs. rma_setup_done */ | 1994 | /* Order updates to kvm->arch.lpcr etc. vs. rma_setup_done */ |
1864 | smp_wmb(); | 1995 | smp_wmb(); |
1865 | kvm->arch.rma_setup_done = 1; | 1996 | kvm->arch.rma_setup_done = 1; |
@@ -1875,7 +2006,7 @@ static int kvmppc_hv_setup_htab_rma(struct kvm_vcpu *vcpu) | |||
1875 | goto out_srcu; | 2006 | goto out_srcu; |
1876 | } | 2007 | } |
1877 | 2008 | ||
1878 | int kvmppc_core_init_vm(struct kvm *kvm) | 2009 | static int kvmppc_core_init_vm_hv(struct kvm *kvm) |
1879 | { | 2010 | { |
1880 | unsigned long lpcr, lpid; | 2011 | unsigned long lpcr, lpid; |
1881 | 2012 | ||
@@ -1893,9 +2024,6 @@ int kvmppc_core_init_vm(struct kvm *kvm) | |||
1893 | */ | 2024 | */ |
1894 | cpumask_setall(&kvm->arch.need_tlb_flush); | 2025 | cpumask_setall(&kvm->arch.need_tlb_flush); |
1895 | 2026 | ||
1896 | INIT_LIST_HEAD(&kvm->arch.spapr_tce_tables); | ||
1897 | INIT_LIST_HEAD(&kvm->arch.rtas_tokens); | ||
1898 | |||
1899 | kvm->arch.rma = NULL; | 2027 | kvm->arch.rma = NULL; |
1900 | 2028 | ||
1901 | kvm->arch.host_sdr1 = mfspr(SPRN_SDR1); | 2029 | kvm->arch.host_sdr1 = mfspr(SPRN_SDR1); |
@@ -1931,61 +2059,162 @@ int kvmppc_core_init_vm(struct kvm *kvm) | |||
1931 | return 0; | 2059 | return 0; |
1932 | } | 2060 | } |
1933 | 2061 | ||
1934 | void kvmppc_core_destroy_vm(struct kvm *kvm) | 2062 | static void kvmppc_free_vcores(struct kvm *kvm) |
2063 | { | ||
2064 | long int i; | ||
2065 | |||
2066 | for (i = 0; i < KVM_MAX_VCORES; ++i) | ||
2067 | kfree(kvm->arch.vcores[i]); | ||
2068 | kvm->arch.online_vcores = 0; | ||
2069 | } | ||
2070 | |||
2071 | static void kvmppc_core_destroy_vm_hv(struct kvm *kvm) | ||
1935 | { | 2072 | { |
1936 | uninhibit_secondary_onlining(); | 2073 | uninhibit_secondary_onlining(); |
1937 | 2074 | ||
2075 | kvmppc_free_vcores(kvm); | ||
1938 | if (kvm->arch.rma) { | 2076 | if (kvm->arch.rma) { |
1939 | kvm_release_rma(kvm->arch.rma); | 2077 | kvm_release_rma(kvm->arch.rma); |
1940 | kvm->arch.rma = NULL; | 2078 | kvm->arch.rma = NULL; |
1941 | } | 2079 | } |
1942 | 2080 | ||
1943 | kvmppc_rtas_tokens_free(kvm); | ||
1944 | |||
1945 | kvmppc_free_hpt(kvm); | 2081 | kvmppc_free_hpt(kvm); |
1946 | WARN_ON(!list_empty(&kvm->arch.spapr_tce_tables)); | ||
1947 | } | 2082 | } |
1948 | 2083 | ||
1949 | /* These are stubs for now */ | 2084 | /* We don't need to emulate any privileged instructions or dcbz */ |
1950 | void kvmppc_mmu_pte_pflush(struct kvm_vcpu *vcpu, ulong pa_start, ulong pa_end) | 2085 | static int kvmppc_core_emulate_op_hv(struct kvm_run *run, struct kvm_vcpu *vcpu, |
2086 | unsigned int inst, int *advance) | ||
1951 | { | 2087 | { |
2088 | return EMULATE_FAIL; | ||
1952 | } | 2089 | } |
1953 | 2090 | ||
1954 | /* We don't need to emulate any privileged instructions or dcbz */ | 2091 | static int kvmppc_core_emulate_mtspr_hv(struct kvm_vcpu *vcpu, int sprn, |
1955 | int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, | 2092 | ulong spr_val) |
1956 | unsigned int inst, int *advance) | ||
1957 | { | 2093 | { |
1958 | return EMULATE_FAIL; | 2094 | return EMULATE_FAIL; |
1959 | } | 2095 | } |
1960 | 2096 | ||
1961 | int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val) | 2097 | static int kvmppc_core_emulate_mfspr_hv(struct kvm_vcpu *vcpu, int sprn, |
2098 | ulong *spr_val) | ||
1962 | { | 2099 | { |
1963 | return EMULATE_FAIL; | 2100 | return EMULATE_FAIL; |
1964 | } | 2101 | } |
1965 | 2102 | ||
1966 | int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val) | 2103 | static int kvmppc_core_check_processor_compat_hv(void) |
1967 | { | 2104 | { |
1968 | return EMULATE_FAIL; | 2105 | if (!cpu_has_feature(CPU_FTR_HVMODE)) |
2106 | return -EIO; | ||
2107 | return 0; | ||
1969 | } | 2108 | } |
1970 | 2109 | ||
1971 | static int kvmppc_book3s_hv_init(void) | 2110 | static long kvm_arch_vm_ioctl_hv(struct file *filp, |
2111 | unsigned int ioctl, unsigned long arg) | ||
1972 | { | 2112 | { |
1973 | int r; | 2113 | struct kvm *kvm __maybe_unused = filp->private_data; |
2114 | void __user *argp = (void __user *)arg; | ||
2115 | long r; | ||
1974 | 2116 | ||
1975 | r = kvm_init(NULL, sizeof(struct kvm_vcpu), 0, THIS_MODULE); | 2117 | switch (ioctl) { |
1976 | 2118 | ||
1977 | if (r) | 2119 | case KVM_ALLOCATE_RMA: { |
2120 | struct kvm_allocate_rma rma; | ||
2121 | struct kvm *kvm = filp->private_data; | ||
2122 | |||
2123 | r = kvm_vm_ioctl_allocate_rma(kvm, &rma); | ||
2124 | if (r >= 0 && copy_to_user(argp, &rma, sizeof(rma))) | ||
2125 | r = -EFAULT; | ||
2126 | break; | ||
2127 | } | ||
2128 | |||
2129 | case KVM_PPC_ALLOCATE_HTAB: { | ||
2130 | u32 htab_order; | ||
2131 | |||
2132 | r = -EFAULT; | ||
2133 | if (get_user(htab_order, (u32 __user *)argp)) | ||
2134 | break; | ||
2135 | r = kvmppc_alloc_reset_hpt(kvm, &htab_order); | ||
2136 | if (r) | ||
2137 | break; | ||
2138 | r = -EFAULT; | ||
2139 | if (put_user(htab_order, (u32 __user *)argp)) | ||
2140 | break; | ||
2141 | r = 0; | ||
2142 | break; | ||
2143 | } | ||
2144 | |||
2145 | case KVM_PPC_GET_HTAB_FD: { | ||
2146 | struct kvm_get_htab_fd ghf; | ||
2147 | |||
2148 | r = -EFAULT; | ||
2149 | if (copy_from_user(&ghf, argp, sizeof(ghf))) | ||
2150 | break; | ||
2151 | r = kvm_vm_ioctl_get_htab_fd(kvm, &ghf); | ||
2152 | break; | ||
2153 | } | ||
2154 | |||
2155 | default: | ||
2156 | r = -ENOTTY; | ||
2157 | } | ||
2158 | |||
2159 | return r; | ||
2160 | } | ||
2161 | |||
2162 | static struct kvmppc_ops kvm_ops_hv = { | ||
2163 | .get_sregs = kvm_arch_vcpu_ioctl_get_sregs_hv, | ||
2164 | .set_sregs = kvm_arch_vcpu_ioctl_set_sregs_hv, | ||
2165 | .get_one_reg = kvmppc_get_one_reg_hv, | ||
2166 | .set_one_reg = kvmppc_set_one_reg_hv, | ||
2167 | .vcpu_load = kvmppc_core_vcpu_load_hv, | ||
2168 | .vcpu_put = kvmppc_core_vcpu_put_hv, | ||
2169 | .set_msr = kvmppc_set_msr_hv, | ||
2170 | .vcpu_run = kvmppc_vcpu_run_hv, | ||
2171 | .vcpu_create = kvmppc_core_vcpu_create_hv, | ||
2172 | .vcpu_free = kvmppc_core_vcpu_free_hv, | ||
2173 | .check_requests = kvmppc_core_check_requests_hv, | ||
2174 | .get_dirty_log = kvm_vm_ioctl_get_dirty_log_hv, | ||
2175 | .flush_memslot = kvmppc_core_flush_memslot_hv, | ||
2176 | .prepare_memory_region = kvmppc_core_prepare_memory_region_hv, | ||
2177 | .commit_memory_region = kvmppc_core_commit_memory_region_hv, | ||
2178 | .unmap_hva = kvm_unmap_hva_hv, | ||
2179 | .unmap_hva_range = kvm_unmap_hva_range_hv, | ||
2180 | .age_hva = kvm_age_hva_hv, | ||
2181 | .test_age_hva = kvm_test_age_hva_hv, | ||
2182 | .set_spte_hva = kvm_set_spte_hva_hv, | ||
2183 | .mmu_destroy = kvmppc_mmu_destroy_hv, | ||
2184 | .free_memslot = kvmppc_core_free_memslot_hv, | ||
2185 | .create_memslot = kvmppc_core_create_memslot_hv, | ||
2186 | .init_vm = kvmppc_core_init_vm_hv, | ||
2187 | .destroy_vm = kvmppc_core_destroy_vm_hv, | ||
2188 | .get_smmu_info = kvm_vm_ioctl_get_smmu_info_hv, | ||
2189 | .emulate_op = kvmppc_core_emulate_op_hv, | ||
2190 | .emulate_mtspr = kvmppc_core_emulate_mtspr_hv, | ||
2191 | .emulate_mfspr = kvmppc_core_emulate_mfspr_hv, | ||
2192 | .fast_vcpu_kick = kvmppc_fast_vcpu_kick_hv, | ||
2193 | .arch_vm_ioctl = kvm_arch_vm_ioctl_hv, | ||
2194 | }; | ||
2195 | |||
2196 | static int kvmppc_book3s_init_hv(void) | ||
2197 | { | ||
2198 | int r; | ||
2199 | /* | ||
2200 | * FIXME!! Do we need to check on all cpus ? | ||
2201 | */ | ||
2202 | r = kvmppc_core_check_processor_compat_hv(); | ||
2203 | if (r < 0) | ||
1978 | return r; | 2204 | return r; |
1979 | 2205 | ||
1980 | r = kvmppc_mmu_hv_init(); | 2206 | kvm_ops_hv.owner = THIS_MODULE; |
2207 | kvmppc_hv_ops = &kvm_ops_hv; | ||
1981 | 2208 | ||
2209 | r = kvmppc_mmu_hv_init(); | ||
1982 | return r; | 2210 | return r; |
1983 | } | 2211 | } |
1984 | 2212 | ||
1985 | static void kvmppc_book3s_hv_exit(void) | 2213 | static void kvmppc_book3s_exit_hv(void) |
1986 | { | 2214 | { |
1987 | kvm_exit(); | 2215 | kvmppc_hv_ops = NULL; |
1988 | } | 2216 | } |
1989 | 2217 | ||
1990 | module_init(kvmppc_book3s_hv_init); | 2218 | module_init(kvmppc_book3s_init_hv); |
1991 | module_exit(kvmppc_book3s_hv_exit); | 2219 | module_exit(kvmppc_book3s_exit_hv); |
2220 | MODULE_LICENSE("GPL"); | ||
diff --git a/arch/powerpc/kvm/book3s_hv_interrupts.S b/arch/powerpc/kvm/book3s_hv_interrupts.S index 37f1cc417ca0..928142c64cb0 100644 --- a/arch/powerpc/kvm/book3s_hv_interrupts.S +++ b/arch/powerpc/kvm/book3s_hv_interrupts.S | |||
@@ -158,9 +158,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201) | |||
158 | * Interrupts are enabled again at this point. | 158 | * Interrupts are enabled again at this point. |
159 | */ | 159 | */ |
160 | 160 | ||
161 | .global kvmppc_handler_highmem | ||
162 | kvmppc_handler_highmem: | ||
163 | |||
164 | /* | 161 | /* |
165 | * Register usage at this point: | 162 | * Register usage at this point: |
166 | * | 163 | * |
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S index 294b7af28cdd..bc8de75b1925 100644 --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S | |||
@@ -33,30 +33,6 @@ | |||
33 | #error Need to fix lppaca and SLB shadow accesses in little endian mode | 33 | #error Need to fix lppaca and SLB shadow accesses in little endian mode |
34 | #endif | 34 | #endif |
35 | 35 | ||
36 | /***************************************************************************** | ||
37 | * * | ||
38 | * Real Mode handlers that need to be in the linear mapping * | ||
39 | * * | ||
40 | ****************************************************************************/ | ||
41 | |||
42 | .globl kvmppc_skip_interrupt | ||
43 | kvmppc_skip_interrupt: | ||
44 | mfspr r13,SPRN_SRR0 | ||
45 | addi r13,r13,4 | ||
46 | mtspr SPRN_SRR0,r13 | ||
47 | GET_SCRATCH0(r13) | ||
48 | rfid | ||
49 | b . | ||
50 | |||
51 | .globl kvmppc_skip_Hinterrupt | ||
52 | kvmppc_skip_Hinterrupt: | ||
53 | mfspr r13,SPRN_HSRR0 | ||
54 | addi r13,r13,4 | ||
55 | mtspr SPRN_HSRR0,r13 | ||
56 | GET_SCRATCH0(r13) | ||
57 | hrfid | ||
58 | b . | ||
59 | |||
60 | /* | 36 | /* |
61 | * Call kvmppc_hv_entry in real mode. | 37 | * Call kvmppc_hv_entry in real mode. |
62 | * Must be called with interrupts hard-disabled. | 38 | * Must be called with interrupts hard-disabled. |
@@ -66,8 +42,11 @@ kvmppc_skip_Hinterrupt: | |||
66 | * LR = return address to continue at after eventually re-enabling MMU | 42 | * LR = return address to continue at after eventually re-enabling MMU |
67 | */ | 43 | */ |
68 | _GLOBAL(kvmppc_hv_entry_trampoline) | 44 | _GLOBAL(kvmppc_hv_entry_trampoline) |
45 | mflr r0 | ||
46 | std r0, PPC_LR_STKOFF(r1) | ||
47 | stdu r1, -112(r1) | ||
69 | mfmsr r10 | 48 | mfmsr r10 |
70 | LOAD_REG_ADDR(r5, kvmppc_hv_entry) | 49 | LOAD_REG_ADDR(r5, kvmppc_call_hv_entry) |
71 | li r0,MSR_RI | 50 | li r0,MSR_RI |
72 | andc r0,r10,r0 | 51 | andc r0,r10,r0 |
73 | li r6,MSR_IR | MSR_DR | 52 | li r6,MSR_IR | MSR_DR |
@@ -77,11 +56,103 @@ _GLOBAL(kvmppc_hv_entry_trampoline) | |||
77 | mtsrr1 r6 | 56 | mtsrr1 r6 |
78 | RFI | 57 | RFI |
79 | 58 | ||
80 | /****************************************************************************** | 59 | kvmppc_call_hv_entry: |
81 | * * | 60 | bl kvmppc_hv_entry |
82 | * Entry code * | 61 | |
83 | * * | 62 | /* Back from guest - restore host state and return to caller */ |
84 | *****************************************************************************/ | 63 | |
64 | /* Restore host DABR and DABRX */ | ||
65 | ld r5,HSTATE_DABR(r13) | ||
66 | li r6,7 | ||
67 | mtspr SPRN_DABR,r5 | ||
68 | mtspr SPRN_DABRX,r6 | ||
69 | |||
70 | /* Restore SPRG3 */ | ||
71 | ld r3,PACA_SPRG3(r13) | ||
72 | mtspr SPRN_SPRG3,r3 | ||
73 | |||
74 | /* | ||
75 | * Reload DEC. HDEC interrupts were disabled when | ||
76 | * we reloaded the host's LPCR value. | ||
77 | */ | ||
78 | ld r3, HSTATE_DECEXP(r13) | ||
79 | mftb r4 | ||
80 | subf r4, r4, r3 | ||
81 | mtspr SPRN_DEC, r4 | ||
82 | |||
83 | /* Reload the host's PMU registers */ | ||
84 | ld r3, PACALPPACAPTR(r13) /* is the host using the PMU? */ | ||
85 | lbz r4, LPPACA_PMCINUSE(r3) | ||
86 | cmpwi r4, 0 | ||
87 | beq 23f /* skip if not */ | ||
88 | lwz r3, HSTATE_PMC(r13) | ||
89 | lwz r4, HSTATE_PMC + 4(r13) | ||
90 | lwz r5, HSTATE_PMC + 8(r13) | ||
91 | lwz r6, HSTATE_PMC + 12(r13) | ||
92 | lwz r8, HSTATE_PMC + 16(r13) | ||
93 | lwz r9, HSTATE_PMC + 20(r13) | ||
94 | BEGIN_FTR_SECTION | ||
95 | lwz r10, HSTATE_PMC + 24(r13) | ||
96 | lwz r11, HSTATE_PMC + 28(r13) | ||
97 | END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201) | ||
98 | mtspr SPRN_PMC1, r3 | ||
99 | mtspr SPRN_PMC2, r4 | ||
100 | mtspr SPRN_PMC3, r5 | ||
101 | mtspr SPRN_PMC4, r6 | ||
102 | mtspr SPRN_PMC5, r8 | ||
103 | mtspr SPRN_PMC6, r9 | ||
104 | BEGIN_FTR_SECTION | ||
105 | mtspr SPRN_PMC7, r10 | ||
106 | mtspr SPRN_PMC8, r11 | ||
107 | END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201) | ||
108 | ld r3, HSTATE_MMCR(r13) | ||
109 | ld r4, HSTATE_MMCR + 8(r13) | ||
110 | ld r5, HSTATE_MMCR + 16(r13) | ||
111 | mtspr SPRN_MMCR1, r4 | ||
112 | mtspr SPRN_MMCRA, r5 | ||
113 | mtspr SPRN_MMCR0, r3 | ||
114 | isync | ||
115 | 23: | ||
116 | |||
117 | /* | ||
118 | * For external and machine check interrupts, we need | ||
119 | * to call the Linux handler to process the interrupt. | ||
120 | * We do that by jumping to absolute address 0x500 for | ||
121 | * external interrupts, or the machine_check_fwnmi label | ||
122 | * for machine checks (since firmware might have patched | ||
123 | * the vector area at 0x200). The [h]rfid at the end of the | ||
124 | * handler will return to the book3s_hv_interrupts.S code. | ||
125 | * For other interrupts we do the rfid to get back | ||
126 | * to the book3s_hv_interrupts.S code here. | ||
127 | */ | ||
128 | ld r8, 112+PPC_LR_STKOFF(r1) | ||
129 | addi r1, r1, 112 | ||
130 | ld r7, HSTATE_HOST_MSR(r13) | ||
131 | |||
132 | cmpwi cr1, r12, BOOK3S_INTERRUPT_MACHINE_CHECK | ||
133 | cmpwi r12, BOOK3S_INTERRUPT_EXTERNAL | ||
134 | BEGIN_FTR_SECTION | ||
135 | beq 11f | ||
136 | END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206) | ||
137 | |||
138 | /* RFI into the highmem handler, or branch to interrupt handler */ | ||
139 | mfmsr r6 | ||
140 | li r0, MSR_RI | ||
141 | andc r6, r6, r0 | ||
142 | mtmsrd r6, 1 /* Clear RI in MSR */ | ||
143 | mtsrr0 r8 | ||
144 | mtsrr1 r7 | ||
145 | beqa 0x500 /* external interrupt (PPC970) */ | ||
146 | beq cr1, 13f /* machine check */ | ||
147 | RFI | ||
148 | |||
149 | /* On POWER7, we have external interrupts set to use HSRR0/1 */ | ||
150 | 11: mtspr SPRN_HSRR0, r8 | ||
151 | mtspr SPRN_HSRR1, r7 | ||
152 | ba 0x500 | ||
153 | |||
154 | 13: b machine_check_fwnmi | ||
155 | |||
85 | 156 | ||
86 | /* | 157 | /* |
87 | * We come in here when wakened from nap mode on a secondary hw thread. | 158 | * We come in here when wakened from nap mode on a secondary hw thread. |
@@ -137,7 +208,7 @@ kvm_start_guest: | |||
137 | cmpdi r4,0 | 208 | cmpdi r4,0 |
138 | /* if we have no vcpu to run, go back to sleep */ | 209 | /* if we have no vcpu to run, go back to sleep */ |
139 | beq kvm_no_guest | 210 | beq kvm_no_guest |
140 | b kvmppc_hv_entry | 211 | b 30f |
141 | 212 | ||
142 | 27: /* XXX should handle hypervisor maintenance interrupts etc. here */ | 213 | 27: /* XXX should handle hypervisor maintenance interrupts etc. here */ |
143 | b kvm_no_guest | 214 | b kvm_no_guest |
@@ -147,6 +218,57 @@ kvm_start_guest: | |||
147 | stw r8,HSTATE_SAVED_XIRR(r13) | 218 | stw r8,HSTATE_SAVED_XIRR(r13) |
148 | b kvm_no_guest | 219 | b kvm_no_guest |
149 | 220 | ||
221 | 30: bl kvmppc_hv_entry | ||
222 | |||
223 | /* Back from the guest, go back to nap */ | ||
224 | /* Clear our vcpu pointer so we don't come back in early */ | ||
225 | li r0, 0 | ||
226 | std r0, HSTATE_KVM_VCPU(r13) | ||
227 | lwsync | ||
228 | /* Clear any pending IPI - we're an offline thread */ | ||
229 | ld r5, HSTATE_XICS_PHYS(r13) | ||
230 | li r7, XICS_XIRR | ||
231 | lwzcix r3, r5, r7 /* ack any pending interrupt */ | ||
232 | rlwinm. r0, r3, 0, 0xffffff /* any pending? */ | ||
233 | beq 37f | ||
234 | sync | ||
235 | li r0, 0xff | ||
236 | li r6, XICS_MFRR | ||
237 | stbcix r0, r5, r6 /* clear the IPI */ | ||
238 | stwcix r3, r5, r7 /* EOI it */ | ||
239 | 37: sync | ||
240 | |||
241 | /* increment the nap count and then go to nap mode */ | ||
242 | ld r4, HSTATE_KVM_VCORE(r13) | ||
243 | addi r4, r4, VCORE_NAP_COUNT | ||
244 | lwsync /* make previous updates visible */ | ||
245 | 51: lwarx r3, 0, r4 | ||
246 | addi r3, r3, 1 | ||
247 | stwcx. r3, 0, r4 | ||
248 | bne 51b | ||
249 | |||
250 | kvm_no_guest: | ||
251 | li r0, KVM_HWTHREAD_IN_NAP | ||
252 | stb r0, HSTATE_HWTHREAD_STATE(r13) | ||
253 | li r3, LPCR_PECE0 | ||
254 | mfspr r4, SPRN_LPCR | ||
255 | rlwimi r4, r3, 0, LPCR_PECE0 | LPCR_PECE1 | ||
256 | mtspr SPRN_LPCR, r4 | ||
257 | isync | ||
258 | std r0, HSTATE_SCRATCH0(r13) | ||
259 | ptesync | ||
260 | ld r0, HSTATE_SCRATCH0(r13) | ||
261 | 1: cmpd r0, r0 | ||
262 | bne 1b | ||
263 | nap | ||
264 | b . | ||
265 | |||
266 | /****************************************************************************** | ||
267 | * * | ||
268 | * Entry code * | ||
269 | * * | ||
270 | *****************************************************************************/ | ||
271 | |||
150 | .global kvmppc_hv_entry | 272 | .global kvmppc_hv_entry |
151 | kvmppc_hv_entry: | 273 | kvmppc_hv_entry: |
152 | 274 | ||
@@ -159,7 +281,8 @@ kvmppc_hv_entry: | |||
159 | * all other volatile GPRS = free | 281 | * all other volatile GPRS = free |
160 | */ | 282 | */ |
161 | mflr r0 | 283 | mflr r0 |
162 | std r0, HSTATE_VMHANDLER(r13) | 284 | std r0, PPC_LR_STKOFF(r1) |
285 | stdu r1, -112(r1) | ||
163 | 286 | ||
164 | /* Set partition DABR */ | 287 | /* Set partition DABR */ |
165 | /* Do this before re-enabling PMU to avoid P7 DABR corruption bug */ | 288 | /* Do this before re-enabling PMU to avoid P7 DABR corruption bug */ |
@@ -200,8 +323,12 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201) | |||
200 | ld r3, VCPU_MMCR(r4) | 323 | ld r3, VCPU_MMCR(r4) |
201 | ld r5, VCPU_MMCR + 8(r4) | 324 | ld r5, VCPU_MMCR + 8(r4) |
202 | ld r6, VCPU_MMCR + 16(r4) | 325 | ld r6, VCPU_MMCR + 16(r4) |
326 | ld r7, VCPU_SIAR(r4) | ||
327 | ld r8, VCPU_SDAR(r4) | ||
203 | mtspr SPRN_MMCR1, r5 | 328 | mtspr SPRN_MMCR1, r5 |
204 | mtspr SPRN_MMCRA, r6 | 329 | mtspr SPRN_MMCRA, r6 |
330 | mtspr SPRN_SIAR, r7 | ||
331 | mtspr SPRN_SDAR, r8 | ||
205 | mtspr SPRN_MMCR0, r3 | 332 | mtspr SPRN_MMCR0, r3 |
206 | isync | 333 | isync |
207 | 334 | ||
@@ -254,22 +381,15 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206) | |||
254 | /* Save R1 in the PACA */ | 381 | /* Save R1 in the PACA */ |
255 | std r1, HSTATE_HOST_R1(r13) | 382 | std r1, HSTATE_HOST_R1(r13) |
256 | 383 | ||
257 | /* Increment yield count if they have a VPA */ | ||
258 | ld r3, VCPU_VPA(r4) | ||
259 | cmpdi r3, 0 | ||
260 | beq 25f | ||
261 | lwz r5, LPPACA_YIELDCOUNT(r3) | ||
262 | addi r5, r5, 1 | ||
263 | stw r5, LPPACA_YIELDCOUNT(r3) | ||
264 | li r6, 1 | ||
265 | stb r6, VCPU_VPA_DIRTY(r4) | ||
266 | 25: | ||
267 | /* Load up DAR and DSISR */ | 384 | /* Load up DAR and DSISR */ |
268 | ld r5, VCPU_DAR(r4) | 385 | ld r5, VCPU_DAR(r4) |
269 | lwz r6, VCPU_DSISR(r4) | 386 | lwz r6, VCPU_DSISR(r4) |
270 | mtspr SPRN_DAR, r5 | 387 | mtspr SPRN_DAR, r5 |
271 | mtspr SPRN_DSISR, r6 | 388 | mtspr SPRN_DSISR, r6 |
272 | 389 | ||
390 | li r6, KVM_GUEST_MODE_HOST_HV | ||
391 | stb r6, HSTATE_IN_GUEST(r13) | ||
392 | |||
273 | BEGIN_FTR_SECTION | 393 | BEGIN_FTR_SECTION |
274 | /* Restore AMR and UAMOR, set AMOR to all 1s */ | 394 | /* Restore AMR and UAMOR, set AMOR to all 1s */ |
275 | ld r5,VCPU_AMR(r4) | 395 | ld r5,VCPU_AMR(r4) |
@@ -343,7 +463,28 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201) | |||
343 | bdnz 28b | 463 | bdnz 28b |
344 | ptesync | 464 | ptesync |
345 | 465 | ||
346 | 22: li r0,1 | 466 | /* Add timebase offset onto timebase */ |
467 | 22: ld r8,VCORE_TB_OFFSET(r5) | ||
468 | cmpdi r8,0 | ||
469 | beq 37f | ||
470 | mftb r6 /* current host timebase */ | ||
471 | add r8,r8,r6 | ||
472 | mtspr SPRN_TBU40,r8 /* update upper 40 bits */ | ||
473 | mftb r7 /* check if lower 24 bits overflowed */ | ||
474 | clrldi r6,r6,40 | ||
475 | clrldi r7,r7,40 | ||
476 | cmpld r7,r6 | ||
477 | bge 37f | ||
478 | addis r8,r8,0x100 /* if so, increment upper 40 bits */ | ||
479 | mtspr SPRN_TBU40,r8 | ||
480 | |||
481 | /* Load guest PCR value to select appropriate compat mode */ | ||
482 | 37: ld r7, VCORE_PCR(r5) | ||
483 | cmpdi r7, 0 | ||
484 | beq 38f | ||
485 | mtspr SPRN_PCR, r7 | ||
486 | 38: | ||
487 | li r0,1 | ||
347 | stb r0,VCORE_IN_GUEST(r5) /* signal secondaries to continue */ | 488 | stb r0,VCORE_IN_GUEST(r5) /* signal secondaries to continue */ |
348 | b 10f | 489 | b 10f |
349 | 490 | ||
@@ -353,12 +494,22 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201) | |||
353 | beq 20b | 494 | beq 20b |
354 | 495 | ||
355 | /* Set LPCR and RMOR. */ | 496 | /* Set LPCR and RMOR. */ |
356 | 10: ld r8,KVM_LPCR(r9) | 497 | 10: ld r8,VCORE_LPCR(r5) |
357 | mtspr SPRN_LPCR,r8 | 498 | mtspr SPRN_LPCR,r8 |
358 | ld r8,KVM_RMOR(r9) | 499 | ld r8,KVM_RMOR(r9) |
359 | mtspr SPRN_RMOR,r8 | 500 | mtspr SPRN_RMOR,r8 |
360 | isync | 501 | isync |
361 | 502 | ||
503 | /* Increment yield count if they have a VPA */ | ||
504 | ld r3, VCPU_VPA(r4) | ||
505 | cmpdi r3, 0 | ||
506 | beq 25f | ||
507 | lwz r5, LPPACA_YIELDCOUNT(r3) | ||
508 | addi r5, r5, 1 | ||
509 | stw r5, LPPACA_YIELDCOUNT(r3) | ||
510 | li r6, 1 | ||
511 | stb r6, VCPU_VPA_DIRTY(r4) | ||
512 | 25: | ||
362 | /* Check if HDEC expires soon */ | 513 | /* Check if HDEC expires soon */ |
363 | mfspr r3,SPRN_HDEC | 514 | mfspr r3,SPRN_HDEC |
364 | cmpwi r3,10 | 515 | cmpwi r3,10 |
@@ -405,7 +556,8 @@ toc_tlbie_lock: | |||
405 | bne 24b | 556 | bne 24b |
406 | isync | 557 | isync |
407 | 558 | ||
408 | ld r7,KVM_LPCR(r9) /* use kvm->arch.lpcr to store HID4 */ | 559 | ld r5,HSTATE_KVM_VCORE(r13) |
560 | ld r7,VCORE_LPCR(r5) /* use vcore->lpcr to store HID4 */ | ||
409 | li r0,0x18f | 561 | li r0,0x18f |
410 | rotldi r0,r0,HID4_LPID5_SH /* all lpid bits in HID4 = 1 */ | 562 | rotldi r0,r0,HID4_LPID5_SH /* all lpid bits in HID4 = 1 */ |
411 | or r0,r7,r0 | 563 | or r0,r7,r0 |
@@ -541,7 +693,7 @@ fast_guest_return: | |||
541 | mtspr SPRN_HSRR1,r11 | 693 | mtspr SPRN_HSRR1,r11 |
542 | 694 | ||
543 | /* Activate guest mode, so faults get handled by KVM */ | 695 | /* Activate guest mode, so faults get handled by KVM */ |
544 | li r9, KVM_GUEST_MODE_GUEST | 696 | li r9, KVM_GUEST_MODE_GUEST_HV |
545 | stb r9, HSTATE_IN_GUEST(r13) | 697 | stb r9, HSTATE_IN_GUEST(r13) |
546 | 698 | ||
547 | /* Enter guest */ | 699 | /* Enter guest */ |
@@ -550,13 +702,15 @@ BEGIN_FTR_SECTION | |||
550 | ld r5, VCPU_CFAR(r4) | 702 | ld r5, VCPU_CFAR(r4) |
551 | mtspr SPRN_CFAR, r5 | 703 | mtspr SPRN_CFAR, r5 |
552 | END_FTR_SECTION_IFSET(CPU_FTR_CFAR) | 704 | END_FTR_SECTION_IFSET(CPU_FTR_CFAR) |
705 | BEGIN_FTR_SECTION | ||
706 | ld r0, VCPU_PPR(r4) | ||
707 | END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) | ||
553 | 708 | ||
554 | ld r5, VCPU_LR(r4) | 709 | ld r5, VCPU_LR(r4) |
555 | lwz r6, VCPU_CR(r4) | 710 | lwz r6, VCPU_CR(r4) |
556 | mtlr r5 | 711 | mtlr r5 |
557 | mtcr r6 | 712 | mtcr r6 |
558 | 713 | ||
559 | ld r0, VCPU_GPR(R0)(r4) | ||
560 | ld r1, VCPU_GPR(R1)(r4) | 714 | ld r1, VCPU_GPR(R1)(r4) |
561 | ld r2, VCPU_GPR(R2)(r4) | 715 | ld r2, VCPU_GPR(R2)(r4) |
562 | ld r3, VCPU_GPR(R3)(r4) | 716 | ld r3, VCPU_GPR(R3)(r4) |
@@ -570,6 +724,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_CFAR) | |||
570 | ld r12, VCPU_GPR(R12)(r4) | 724 | ld r12, VCPU_GPR(R12)(r4) |
571 | ld r13, VCPU_GPR(R13)(r4) | 725 | ld r13, VCPU_GPR(R13)(r4) |
572 | 726 | ||
727 | BEGIN_FTR_SECTION | ||
728 | mtspr SPRN_PPR, r0 | ||
729 | END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) | ||
730 | ld r0, VCPU_GPR(R0)(r4) | ||
573 | ld r4, VCPU_GPR(R4)(r4) | 731 | ld r4, VCPU_GPR(R4)(r4) |
574 | 732 | ||
575 | hrfid | 733 | hrfid |
@@ -584,8 +742,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_CFAR) | |||
584 | /* | 742 | /* |
585 | * We come here from the first-level interrupt handlers. | 743 | * We come here from the first-level interrupt handlers. |
586 | */ | 744 | */ |
587 | .globl kvmppc_interrupt | 745 | .globl kvmppc_interrupt_hv |
588 | kvmppc_interrupt: | 746 | kvmppc_interrupt_hv: |
589 | /* | 747 | /* |
590 | * Register contents: | 748 | * Register contents: |
591 | * R12 = interrupt vector | 749 | * R12 = interrupt vector |
@@ -595,6 +753,19 @@ kvmppc_interrupt: | |||
595 | */ | 753 | */ |
596 | /* abuse host_r2 as third scratch area; we get r2 from PACATOC(r13) */ | 754 | /* abuse host_r2 as third scratch area; we get r2 from PACATOC(r13) */ |
597 | std r9, HSTATE_HOST_R2(r13) | 755 | std r9, HSTATE_HOST_R2(r13) |
756 | |||
757 | lbz r9, HSTATE_IN_GUEST(r13) | ||
758 | cmpwi r9, KVM_GUEST_MODE_HOST_HV | ||
759 | beq kvmppc_bad_host_intr | ||
760 | #ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE | ||
761 | cmpwi r9, KVM_GUEST_MODE_GUEST | ||
762 | ld r9, HSTATE_HOST_R2(r13) | ||
763 | beq kvmppc_interrupt_pr | ||
764 | #endif | ||
765 | /* We're now back in the host but in guest MMU context */ | ||
766 | li r9, KVM_GUEST_MODE_HOST_HV | ||
767 | stb r9, HSTATE_IN_GUEST(r13) | ||
768 | |||
598 | ld r9, HSTATE_KVM_VCPU(r13) | 769 | ld r9, HSTATE_KVM_VCPU(r13) |
599 | 770 | ||
600 | /* Save registers */ | 771 | /* Save registers */ |
@@ -620,6 +791,10 @@ BEGIN_FTR_SECTION | |||
620 | ld r3, HSTATE_CFAR(r13) | 791 | ld r3, HSTATE_CFAR(r13) |
621 | std r3, VCPU_CFAR(r9) | 792 | std r3, VCPU_CFAR(r9) |
622 | END_FTR_SECTION_IFSET(CPU_FTR_CFAR) | 793 | END_FTR_SECTION_IFSET(CPU_FTR_CFAR) |
794 | BEGIN_FTR_SECTION | ||
795 | ld r4, HSTATE_PPR(r13) | ||
796 | std r4, VCPU_PPR(r9) | ||
797 | END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) | ||
623 | 798 | ||
624 | /* Restore R1/R2 so we can handle faults */ | 799 | /* Restore R1/R2 so we can handle faults */ |
625 | ld r1, HSTATE_HOST_R1(r13) | 800 | ld r1, HSTATE_HOST_R1(r13) |
@@ -642,10 +817,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_CFAR) | |||
642 | std r3, VCPU_GPR(R13)(r9) | 817 | std r3, VCPU_GPR(R13)(r9) |
643 | std r4, VCPU_LR(r9) | 818 | std r4, VCPU_LR(r9) |
644 | 819 | ||
645 | /* Unset guest mode */ | ||
646 | li r0, KVM_GUEST_MODE_NONE | ||
647 | stb r0, HSTATE_IN_GUEST(r13) | ||
648 | |||
649 | stw r12,VCPU_TRAP(r9) | 820 | stw r12,VCPU_TRAP(r9) |
650 | 821 | ||
651 | /* Save HEIR (HV emulation assist reg) in last_inst | 822 | /* Save HEIR (HV emulation assist reg) in last_inst |
@@ -696,46 +867,11 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_206) | |||
696 | * set, we know the host wants us out so let's do it now | 867 | * set, we know the host wants us out so let's do it now |
697 | */ | 868 | */ |
698 | do_ext_interrupt: | 869 | do_ext_interrupt: |
699 | lbz r0, HSTATE_HOST_IPI(r13) | 870 | bl kvmppc_read_intr |
700 | cmpwi r0, 0 | 871 | cmpdi r3, 0 |
701 | bne ext_interrupt_to_host | 872 | bgt ext_interrupt_to_host |
702 | |||
703 | /* Now read the interrupt from the ICP */ | ||
704 | ld r5, HSTATE_XICS_PHYS(r13) | ||
705 | li r7, XICS_XIRR | ||
706 | cmpdi r5, 0 | ||
707 | beq- ext_interrupt_to_host | ||
708 | lwzcix r3, r5, r7 | ||
709 | rlwinm. r0, r3, 0, 0xffffff | ||
710 | sync | ||
711 | beq 3f /* if nothing pending in the ICP */ | ||
712 | |||
713 | /* We found something in the ICP... | ||
714 | * | ||
715 | * If it's not an IPI, stash it in the PACA and return to | ||
716 | * the host, we don't (yet) handle directing real external | ||
717 | * interrupts directly to the guest | ||
718 | */ | ||
719 | cmpwi r0, XICS_IPI | ||
720 | bne ext_stash_for_host | ||
721 | |||
722 | /* It's an IPI, clear the MFRR and EOI it */ | ||
723 | li r0, 0xff | ||
724 | li r6, XICS_MFRR | ||
725 | stbcix r0, r5, r6 /* clear the IPI */ | ||
726 | stwcix r3, r5, r7 /* EOI it */ | ||
727 | sync | ||
728 | |||
729 | /* We need to re-check host IPI now in case it got set in the | ||
730 | * meantime. If it's clear, we bounce the interrupt to the | ||
731 | * guest | ||
732 | */ | ||
733 | lbz r0, HSTATE_HOST_IPI(r13) | ||
734 | cmpwi r0, 0 | ||
735 | bne- 1f | ||
736 | 873 | ||
737 | /* Allright, looks like an IPI for the guest, we need to set MER */ | 874 | /* Allright, looks like an IPI for the guest, we need to set MER */ |
738 | 3: | ||
739 | /* Check if any CPU is heading out to the host, if so head out too */ | 875 | /* Check if any CPU is heading out to the host, if so head out too */ |
740 | ld r5, HSTATE_KVM_VCORE(r13) | 876 | ld r5, HSTATE_KVM_VCORE(r13) |
741 | lwz r0, VCORE_ENTRY_EXIT(r5) | 877 | lwz r0, VCORE_ENTRY_EXIT(r5) |
@@ -764,27 +900,9 @@ do_ext_interrupt: | |||
764 | mtspr SPRN_LPCR, r8 | 900 | mtspr SPRN_LPCR, r8 |
765 | b fast_guest_return | 901 | b fast_guest_return |
766 | 902 | ||
767 | /* We raced with the host, we need to resend that IPI, bummer */ | ||
768 | 1: li r0, IPI_PRIORITY | ||
769 | stbcix r0, r5, r6 /* set the IPI */ | ||
770 | sync | ||
771 | b ext_interrupt_to_host | ||
772 | |||
773 | ext_stash_for_host: | ||
774 | /* It's not an IPI and it's for the host, stash it in the PACA | ||
775 | * before exit, it will be picked up by the host ICP driver | ||
776 | */ | ||
777 | stw r3, HSTATE_SAVED_XIRR(r13) | ||
778 | ext_interrupt_to_host: | 903 | ext_interrupt_to_host: |
779 | 904 | ||
780 | guest_exit_cont: /* r9 = vcpu, r12 = trap, r13 = paca */ | 905 | guest_exit_cont: /* r9 = vcpu, r12 = trap, r13 = paca */ |
781 | /* Save DEC */ | ||
782 | mfspr r5,SPRN_DEC | ||
783 | mftb r6 | ||
784 | extsw r5,r5 | ||
785 | add r5,r5,r6 | ||
786 | std r5,VCPU_DEC_EXPIRES(r9) | ||
787 | |||
788 | /* Save more register state */ | 906 | /* Save more register state */ |
789 | mfdar r6 | 907 | mfdar r6 |
790 | mfdsisr r7 | 908 | mfdsisr r7 |
@@ -954,7 +1072,30 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201) | |||
954 | mtspr SPRN_SDR1,r6 /* switch to partition page table */ | 1072 | mtspr SPRN_SDR1,r6 /* switch to partition page table */ |
955 | mtspr SPRN_LPID,r7 | 1073 | mtspr SPRN_LPID,r7 |
956 | isync | 1074 | isync |
957 | li r0,0 | 1075 | |
1076 | /* Subtract timebase offset from timebase */ | ||
1077 | ld r8,VCORE_TB_OFFSET(r5) | ||
1078 | cmpdi r8,0 | ||
1079 | beq 17f | ||
1080 | mftb r6 /* current host timebase */ | ||
1081 | subf r8,r8,r6 | ||
1082 | mtspr SPRN_TBU40,r8 /* update upper 40 bits */ | ||
1083 | mftb r7 /* check if lower 24 bits overflowed */ | ||
1084 | clrldi r6,r6,40 | ||
1085 | clrldi r7,r7,40 | ||
1086 | cmpld r7,r6 | ||
1087 | bge 17f | ||
1088 | addis r8,r8,0x100 /* if so, increment upper 40 bits */ | ||
1089 | mtspr SPRN_TBU40,r8 | ||
1090 | |||
1091 | /* Reset PCR */ | ||
1092 | 17: ld r0, VCORE_PCR(r5) | ||
1093 | cmpdi r0, 0 | ||
1094 | beq 18f | ||
1095 | li r0, 0 | ||
1096 | mtspr SPRN_PCR, r0 | ||
1097 | 18: | ||
1098 | /* Signal secondary CPUs to continue */ | ||
958 | stb r0,VCORE_IN_GUEST(r5) | 1099 | stb r0,VCORE_IN_GUEST(r5) |
959 | lis r8,0x7fff /* MAX_INT@h */ | 1100 | lis r8,0x7fff /* MAX_INT@h */ |
960 | mtspr SPRN_HDEC,r8 | 1101 | mtspr SPRN_HDEC,r8 |
@@ -1052,6 +1193,13 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201) | |||
1052 | 1: addi r8,r8,16 | 1193 | 1: addi r8,r8,16 |
1053 | .endr | 1194 | .endr |
1054 | 1195 | ||
1196 | /* Save DEC */ | ||
1197 | mfspr r5,SPRN_DEC | ||
1198 | mftb r6 | ||
1199 | extsw r5,r5 | ||
1200 | add r5,r5,r6 | ||
1201 | std r5,VCPU_DEC_EXPIRES(r9) | ||
1202 | |||
1055 | /* Save and reset AMR and UAMOR before turning on the MMU */ | 1203 | /* Save and reset AMR and UAMOR before turning on the MMU */ |
1056 | BEGIN_FTR_SECTION | 1204 | BEGIN_FTR_SECTION |
1057 | mfspr r5,SPRN_AMR | 1205 | mfspr r5,SPRN_AMR |
@@ -1062,11 +1210,15 @@ BEGIN_FTR_SECTION | |||
1062 | mtspr SPRN_AMR,r6 | 1210 | mtspr SPRN_AMR,r6 |
1063 | END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206) | 1211 | END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206) |
1064 | 1212 | ||
1213 | /* Unset guest mode */ | ||
1214 | li r0, KVM_GUEST_MODE_NONE | ||
1215 | stb r0, HSTATE_IN_GUEST(r13) | ||
1216 | |||
1065 | /* Switch DSCR back to host value */ | 1217 | /* Switch DSCR back to host value */ |
1066 | BEGIN_FTR_SECTION | 1218 | BEGIN_FTR_SECTION |
1067 | mfspr r8, SPRN_DSCR | 1219 | mfspr r8, SPRN_DSCR |
1068 | ld r7, HSTATE_DSCR(r13) | 1220 | ld r7, HSTATE_DSCR(r13) |
1069 | std r8, VCPU_DSCR(r7) | 1221 | std r8, VCPU_DSCR(r9) |
1070 | mtspr SPRN_DSCR, r7 | 1222 | mtspr SPRN_DSCR, r7 |
1071 | END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206) | 1223 | END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206) |
1072 | 1224 | ||
@@ -1134,9 +1286,13 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206) | |||
1134 | std r3, VCPU_MMCR(r9) /* if not, set saved MMCR0 to FC */ | 1286 | std r3, VCPU_MMCR(r9) /* if not, set saved MMCR0 to FC */ |
1135 | b 22f | 1287 | b 22f |
1136 | 21: mfspr r5, SPRN_MMCR1 | 1288 | 21: mfspr r5, SPRN_MMCR1 |
1289 | mfspr r7, SPRN_SIAR | ||
1290 | mfspr r8, SPRN_SDAR | ||
1137 | std r4, VCPU_MMCR(r9) | 1291 | std r4, VCPU_MMCR(r9) |
1138 | std r5, VCPU_MMCR + 8(r9) | 1292 | std r5, VCPU_MMCR + 8(r9) |
1139 | std r6, VCPU_MMCR + 16(r9) | 1293 | std r6, VCPU_MMCR + 16(r9) |
1294 | std r7, VCPU_SIAR(r9) | ||
1295 | std r8, VCPU_SDAR(r9) | ||
1140 | mfspr r3, SPRN_PMC1 | 1296 | mfspr r3, SPRN_PMC1 |
1141 | mfspr r4, SPRN_PMC2 | 1297 | mfspr r4, SPRN_PMC2 |
1142 | mfspr r5, SPRN_PMC3 | 1298 | mfspr r5, SPRN_PMC3 |
@@ -1158,103 +1314,30 @@ BEGIN_FTR_SECTION | |||
1158 | stw r11, VCPU_PMC + 28(r9) | 1314 | stw r11, VCPU_PMC + 28(r9) |
1159 | END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201) | 1315 | END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201) |
1160 | 22: | 1316 | 22: |
1317 | ld r0, 112+PPC_LR_STKOFF(r1) | ||
1318 | addi r1, r1, 112 | ||
1319 | mtlr r0 | ||
1320 | blr | ||
1321 | secondary_too_late: | ||
1322 | ld r5,HSTATE_KVM_VCORE(r13) | ||
1323 | HMT_LOW | ||
1324 | 13: lbz r3,VCORE_IN_GUEST(r5) | ||
1325 | cmpwi r3,0 | ||
1326 | bne 13b | ||
1327 | HMT_MEDIUM | ||
1328 | li r0, KVM_GUEST_MODE_NONE | ||
1329 | stb r0, HSTATE_IN_GUEST(r13) | ||
1330 | ld r11,PACA_SLBSHADOWPTR(r13) | ||
1161 | 1331 | ||
1162 | /* Secondary threads go off to take a nap on POWER7 */ | 1332 | .rept SLB_NUM_BOLTED |
1163 | BEGIN_FTR_SECTION | 1333 | ld r5,SLBSHADOW_SAVEAREA(r11) |
1164 | lwz r0,VCPU_PTID(r9) | 1334 | ld r6,SLBSHADOW_SAVEAREA+8(r11) |
1165 | cmpwi r0,0 | 1335 | andis. r7,r5,SLB_ESID_V@h |
1166 | bne secondary_nap | 1336 | beq 1f |
1167 | END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206) | 1337 | slbmte r6,r5 |
1168 | 1338 | 1: addi r11,r11,16 | |
1169 | /* Restore host DABR and DABRX */ | 1339 | .endr |
1170 | ld r5,HSTATE_DABR(r13) | 1340 | b 22b |
1171 | li r6,7 | ||
1172 | mtspr SPRN_DABR,r5 | ||
1173 | mtspr SPRN_DABRX,r6 | ||
1174 | |||
1175 | /* Restore SPRG3 */ | ||
1176 | ld r3,PACA_SPRG3(r13) | ||
1177 | mtspr SPRN_SPRG3,r3 | ||
1178 | |||
1179 | /* | ||
1180 | * Reload DEC. HDEC interrupts were disabled when | ||
1181 | * we reloaded the host's LPCR value. | ||
1182 | */ | ||
1183 | ld r3, HSTATE_DECEXP(r13) | ||
1184 | mftb r4 | ||
1185 | subf r4, r4, r3 | ||
1186 | mtspr SPRN_DEC, r4 | ||
1187 | |||
1188 | /* Reload the host's PMU registers */ | ||
1189 | ld r3, PACALPPACAPTR(r13) /* is the host using the PMU? */ | ||
1190 | lbz r4, LPPACA_PMCINUSE(r3) | ||
1191 | cmpwi r4, 0 | ||
1192 | beq 23f /* skip if not */ | ||
1193 | lwz r3, HSTATE_PMC(r13) | ||
1194 | lwz r4, HSTATE_PMC + 4(r13) | ||
1195 | lwz r5, HSTATE_PMC + 8(r13) | ||
1196 | lwz r6, HSTATE_PMC + 12(r13) | ||
1197 | lwz r8, HSTATE_PMC + 16(r13) | ||
1198 | lwz r9, HSTATE_PMC + 20(r13) | ||
1199 | BEGIN_FTR_SECTION | ||
1200 | lwz r10, HSTATE_PMC + 24(r13) | ||
1201 | lwz r11, HSTATE_PMC + 28(r13) | ||
1202 | END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201) | ||
1203 | mtspr SPRN_PMC1, r3 | ||
1204 | mtspr SPRN_PMC2, r4 | ||
1205 | mtspr SPRN_PMC3, r5 | ||
1206 | mtspr SPRN_PMC4, r6 | ||
1207 | mtspr SPRN_PMC5, r8 | ||
1208 | mtspr SPRN_PMC6, r9 | ||
1209 | BEGIN_FTR_SECTION | ||
1210 | mtspr SPRN_PMC7, r10 | ||
1211 | mtspr SPRN_PMC8, r11 | ||
1212 | END_FTR_SECTION_IFSET(CPU_FTR_ARCH_201) | ||
1213 | ld r3, HSTATE_MMCR(r13) | ||
1214 | ld r4, HSTATE_MMCR + 8(r13) | ||
1215 | ld r5, HSTATE_MMCR + 16(r13) | ||
1216 | mtspr SPRN_MMCR1, r4 | ||
1217 | mtspr SPRN_MMCRA, r5 | ||
1218 | mtspr SPRN_MMCR0, r3 | ||
1219 | isync | ||
1220 | 23: | ||
1221 | /* | ||
1222 | * For external and machine check interrupts, we need | ||
1223 | * to call the Linux handler to process the interrupt. | ||
1224 | * We do that by jumping to absolute address 0x500 for | ||
1225 | * external interrupts, or the machine_check_fwnmi label | ||
1226 | * for machine checks (since firmware might have patched | ||
1227 | * the vector area at 0x200). The [h]rfid at the end of the | ||
1228 | * handler will return to the book3s_hv_interrupts.S code. | ||
1229 | * For other interrupts we do the rfid to get back | ||
1230 | * to the book3s_hv_interrupts.S code here. | ||
1231 | */ | ||
1232 | ld r8, HSTATE_VMHANDLER(r13) | ||
1233 | ld r7, HSTATE_HOST_MSR(r13) | ||
1234 | |||
1235 | cmpwi cr1, r12, BOOK3S_INTERRUPT_MACHINE_CHECK | ||
1236 | cmpwi r12, BOOK3S_INTERRUPT_EXTERNAL | ||
1237 | BEGIN_FTR_SECTION | ||
1238 | beq 11f | ||
1239 | END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206) | ||
1240 | |||
1241 | /* RFI into the highmem handler, or branch to interrupt handler */ | ||
1242 | mfmsr r6 | ||
1243 | li r0, MSR_RI | ||
1244 | andc r6, r6, r0 | ||
1245 | mtmsrd r6, 1 /* Clear RI in MSR */ | ||
1246 | mtsrr0 r8 | ||
1247 | mtsrr1 r7 | ||
1248 | beqa 0x500 /* external interrupt (PPC970) */ | ||
1249 | beq cr1, 13f /* machine check */ | ||
1250 | RFI | ||
1251 | |||
1252 | /* On POWER7, we have external interrupts set to use HSRR0/1 */ | ||
1253 | 11: mtspr SPRN_HSRR0, r8 | ||
1254 | mtspr SPRN_HSRR1, r7 | ||
1255 | ba 0x500 | ||
1256 | |||
1257 | 13: b machine_check_fwnmi | ||
1258 | 1341 | ||
1259 | /* | 1342 | /* |
1260 | * Check whether an HDSI is an HPTE not found fault or something else. | 1343 | * Check whether an HDSI is an HPTE not found fault or something else. |
@@ -1333,7 +1416,7 @@ fast_interrupt_c_return: | |||
1333 | stw r8, VCPU_LAST_INST(r9) | 1416 | stw r8, VCPU_LAST_INST(r9) |
1334 | 1417 | ||
1335 | /* Unset guest mode. */ | 1418 | /* Unset guest mode. */ |
1336 | li r0, KVM_GUEST_MODE_NONE | 1419 | li r0, KVM_GUEST_MODE_HOST_HV |
1337 | stb r0, HSTATE_IN_GUEST(r13) | 1420 | stb r0, HSTATE_IN_GUEST(r13) |
1338 | b guest_exit_cont | 1421 | b guest_exit_cont |
1339 | 1422 | ||
@@ -1701,67 +1784,70 @@ machine_check_realmode: | |||
1701 | rotldi r11, r11, 63 | 1784 | rotldi r11, r11, 63 |
1702 | b fast_interrupt_c_return | 1785 | b fast_interrupt_c_return |
1703 | 1786 | ||
1704 | secondary_too_late: | 1787 | /* |
1705 | ld r5,HSTATE_KVM_VCORE(r13) | 1788 | * Determine what sort of external interrupt is pending (if any). |
1706 | HMT_LOW | 1789 | * Returns: |
1707 | 13: lbz r3,VCORE_IN_GUEST(r5) | 1790 | * 0 if no interrupt is pending |
1708 | cmpwi r3,0 | 1791 | * 1 if an interrupt is pending that needs to be handled by the host |
1709 | bne 13b | 1792 | * -1 if there was a guest wakeup IPI (which has now been cleared) |
1710 | HMT_MEDIUM | 1793 | */ |
1711 | ld r11,PACA_SLBSHADOWPTR(r13) | 1794 | kvmppc_read_intr: |
1712 | 1795 | /* see if a host IPI is pending */ | |
1713 | .rept SLB_NUM_BOLTED | 1796 | li r3, 1 |
1714 | ld r5,SLBSHADOW_SAVEAREA(r11) | 1797 | lbz r0, HSTATE_HOST_IPI(r13) |
1715 | ld r6,SLBSHADOW_SAVEAREA+8(r11) | 1798 | cmpwi r0, 0 |
1716 | andis. r7,r5,SLB_ESID_V@h | 1799 | bne 1f |
1717 | beq 1f | ||
1718 | slbmte r6,r5 | ||
1719 | 1: addi r11,r11,16 | ||
1720 | .endr | ||
1721 | 1800 | ||
1722 | secondary_nap: | 1801 | /* Now read the interrupt from the ICP */ |
1723 | /* Clear our vcpu pointer so we don't come back in early */ | 1802 | ld r6, HSTATE_XICS_PHYS(r13) |
1724 | li r0, 0 | ||
1725 | std r0, HSTATE_KVM_VCPU(r13) | ||
1726 | lwsync | ||
1727 | /* Clear any pending IPI - assume we're a secondary thread */ | ||
1728 | ld r5, HSTATE_XICS_PHYS(r13) | ||
1729 | li r7, XICS_XIRR | 1803 | li r7, XICS_XIRR |
1730 | lwzcix r3, r5, r7 /* ack any pending interrupt */ | 1804 | cmpdi r6, 0 |
1731 | rlwinm. r0, r3, 0, 0xffffff /* any pending? */ | 1805 | beq- 1f |
1732 | beq 37f | 1806 | lwzcix r0, r6, r7 |
1807 | rlwinm. r3, r0, 0, 0xffffff | ||
1733 | sync | 1808 | sync |
1734 | li r0, 0xff | 1809 | beq 1f /* if nothing pending in the ICP */ |
1735 | li r6, XICS_MFRR | ||
1736 | stbcix r0, r5, r6 /* clear the IPI */ | ||
1737 | stwcix r3, r5, r7 /* EOI it */ | ||
1738 | 37: sync | ||
1739 | 1810 | ||
1740 | /* increment the nap count and then go to nap mode */ | 1811 | /* We found something in the ICP... |
1741 | ld r4, HSTATE_KVM_VCORE(r13) | 1812 | * |
1742 | addi r4, r4, VCORE_NAP_COUNT | 1813 | * If it's not an IPI, stash it in the PACA and return to |
1743 | lwsync /* make previous updates visible */ | 1814 | * the host, we don't (yet) handle directing real external |
1744 | 51: lwarx r3, 0, r4 | 1815 | * interrupts directly to the guest |
1745 | addi r3, r3, 1 | 1816 | */ |
1746 | stwcx. r3, 0, r4 | 1817 | cmpwi r3, XICS_IPI /* if there is, is it an IPI? */ |
1747 | bne 51b | 1818 | li r3, 1 |
1819 | bne 42f | ||
1748 | 1820 | ||
1749 | kvm_no_guest: | 1821 | /* It's an IPI, clear the MFRR and EOI it */ |
1750 | li r0, KVM_HWTHREAD_IN_NAP | 1822 | li r3, 0xff |
1751 | stb r0, HSTATE_HWTHREAD_STATE(r13) | 1823 | li r8, XICS_MFRR |
1824 | stbcix r3, r6, r8 /* clear the IPI */ | ||
1825 | stwcix r0, r6, r7 /* EOI it */ | ||
1826 | sync | ||
1752 | 1827 | ||
1753 | li r3, LPCR_PECE0 | 1828 | /* We need to re-check host IPI now in case it got set in the |
1754 | mfspr r4, SPRN_LPCR | 1829 | * meantime. If it's clear, we bounce the interrupt to the |
1755 | rlwimi r4, r3, 0, LPCR_PECE0 | LPCR_PECE1 | 1830 | * guest |
1756 | mtspr SPRN_LPCR, r4 | 1831 | */ |
1757 | isync | 1832 | lbz r0, HSTATE_HOST_IPI(r13) |
1758 | std r0, HSTATE_SCRATCH0(r13) | 1833 | cmpwi r0, 0 |
1759 | ptesync | 1834 | bne- 43f |
1760 | ld r0, HSTATE_SCRATCH0(r13) | 1835 | |
1761 | 1: cmpd r0, r0 | 1836 | /* OK, it's an IPI for us */ |
1762 | bne 1b | 1837 | li r3, -1 |
1763 | nap | 1838 | 1: blr |
1764 | b . | 1839 | |
1840 | 42: /* It's not an IPI and it's for the host, stash it in the PACA | ||
1841 | * before exit, it will be picked up by the host ICP driver | ||
1842 | */ | ||
1843 | stw r0, HSTATE_SAVED_XIRR(r13) | ||
1844 | b 1b | ||
1845 | |||
1846 | 43: /* We raced with the host, we need to resend that IPI, bummer */ | ||
1847 | li r0, IPI_PRIORITY | ||
1848 | stbcix r0, r6, r8 /* set the IPI */ | ||
1849 | sync | ||
1850 | b 1b | ||
1765 | 1851 | ||
1766 | /* | 1852 | /* |
1767 | * Save away FP, VMX and VSX registers. | 1853 | * Save away FP, VMX and VSX registers. |
@@ -1879,3 +1965,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | |||
1879 | lwz r7,VCPU_VRSAVE(r4) | 1965 | lwz r7,VCPU_VRSAVE(r4) |
1880 | mtspr SPRN_VRSAVE,r7 | 1966 | mtspr SPRN_VRSAVE,r7 |
1881 | blr | 1967 | blr |
1968 | |||
1969 | /* | ||
1970 | * We come here if we get any exception or interrupt while we are | ||
1971 | * executing host real mode code while in guest MMU context. | ||
1972 | * For now just spin, but we should do something better. | ||
1973 | */ | ||
1974 | kvmppc_bad_host_intr: | ||
1975 | b . | ||
diff --git a/arch/powerpc/kvm/book3s_interrupts.S b/arch/powerpc/kvm/book3s_interrupts.S index 17cfae5497a3..f4dd041c14ea 100644 --- a/arch/powerpc/kvm/book3s_interrupts.S +++ b/arch/powerpc/kvm/book3s_interrupts.S | |||
@@ -26,8 +26,12 @@ | |||
26 | 26 | ||
27 | #if defined(CONFIG_PPC_BOOK3S_64) | 27 | #if defined(CONFIG_PPC_BOOK3S_64) |
28 | #define FUNC(name) GLUE(.,name) | 28 | #define FUNC(name) GLUE(.,name) |
29 | #define GET_SHADOW_VCPU(reg) addi reg, r13, PACA_SVCPU | ||
30 | |||
29 | #elif defined(CONFIG_PPC_BOOK3S_32) | 31 | #elif defined(CONFIG_PPC_BOOK3S_32) |
30 | #define FUNC(name) name | 32 | #define FUNC(name) name |
33 | #define GET_SHADOW_VCPU(reg) lwz reg, (THREAD + THREAD_KVM_SVCPU)(r2) | ||
34 | |||
31 | #endif /* CONFIG_PPC_BOOK3S_XX */ | 35 | #endif /* CONFIG_PPC_BOOK3S_XX */ |
32 | 36 | ||
33 | #define VCPU_LOAD_NVGPRS(vcpu) \ | 37 | #define VCPU_LOAD_NVGPRS(vcpu) \ |
@@ -87,8 +91,14 @@ kvm_start_entry: | |||
87 | VCPU_LOAD_NVGPRS(r4) | 91 | VCPU_LOAD_NVGPRS(r4) |
88 | 92 | ||
89 | kvm_start_lightweight: | 93 | kvm_start_lightweight: |
94 | /* Copy registers into shadow vcpu so we can access them in real mode */ | ||
95 | GET_SHADOW_VCPU(r3) | ||
96 | bl FUNC(kvmppc_copy_to_svcpu) | ||
97 | nop | ||
98 | REST_GPR(4, r1) | ||
90 | 99 | ||
91 | #ifdef CONFIG_PPC_BOOK3S_64 | 100 | #ifdef CONFIG_PPC_BOOK3S_64 |
101 | /* Get the dcbz32 flag */ | ||
92 | PPC_LL r3, VCPU_HFLAGS(r4) | 102 | PPC_LL r3, VCPU_HFLAGS(r4) |
93 | rldicl r3, r3, 0, 63 /* r3 &= 1 */ | 103 | rldicl r3, r3, 0, 63 /* r3 &= 1 */ |
94 | stb r3, HSTATE_RESTORE_HID5(r13) | 104 | stb r3, HSTATE_RESTORE_HID5(r13) |
@@ -111,9 +121,6 @@ kvm_start_lightweight: | |||
111 | * | 121 | * |
112 | */ | 122 | */ |
113 | 123 | ||
114 | .global kvmppc_handler_highmem | ||
115 | kvmppc_handler_highmem: | ||
116 | |||
117 | /* | 124 | /* |
118 | * Register usage at this point: | 125 | * Register usage at this point: |
119 | * | 126 | * |
@@ -125,18 +132,31 @@ kvmppc_handler_highmem: | |||
125 | * | 132 | * |
126 | */ | 133 | */ |
127 | 134 | ||
128 | /* R7 = vcpu */ | 135 | /* Transfer reg values from shadow vcpu back to vcpu struct */ |
129 | PPC_LL r7, GPR4(r1) | 136 | /* On 64-bit, interrupts are still off at this point */ |
137 | PPC_LL r3, GPR4(r1) /* vcpu pointer */ | ||
138 | GET_SHADOW_VCPU(r4) | ||
139 | bl FUNC(kvmppc_copy_from_svcpu) | ||
140 | nop | ||
130 | 141 | ||
131 | #ifdef CONFIG_PPC_BOOK3S_64 | 142 | #ifdef CONFIG_PPC_BOOK3S_64 |
143 | /* Re-enable interrupts */ | ||
144 | ld r3, HSTATE_HOST_MSR(r13) | ||
145 | ori r3, r3, MSR_EE | ||
146 | MTMSR_EERI(r3) | ||
147 | |||
132 | /* | 148 | /* |
133 | * Reload kernel SPRG3 value. | 149 | * Reload kernel SPRG3 value. |
134 | * No need to save guest value as usermode can't modify SPRG3. | 150 | * No need to save guest value as usermode can't modify SPRG3. |
135 | */ | 151 | */ |
136 | ld r3, PACA_SPRG3(r13) | 152 | ld r3, PACA_SPRG3(r13) |
137 | mtspr SPRN_SPRG3, r3 | 153 | mtspr SPRN_SPRG3, r3 |
154 | |||
138 | #endif /* CONFIG_PPC_BOOK3S_64 */ | 155 | #endif /* CONFIG_PPC_BOOK3S_64 */ |
139 | 156 | ||
157 | /* R7 = vcpu */ | ||
158 | PPC_LL r7, GPR4(r1) | ||
159 | |||
140 | PPC_STL r14, VCPU_GPR(R14)(r7) | 160 | PPC_STL r14, VCPU_GPR(R14)(r7) |
141 | PPC_STL r15, VCPU_GPR(R15)(r7) | 161 | PPC_STL r15, VCPU_GPR(R15)(r7) |
142 | PPC_STL r16, VCPU_GPR(R16)(r7) | 162 | PPC_STL r16, VCPU_GPR(R16)(r7) |
@@ -161,7 +181,7 @@ kvmppc_handler_highmem: | |||
161 | 181 | ||
162 | /* Restore r3 (kvm_run) and r4 (vcpu) */ | 182 | /* Restore r3 (kvm_run) and r4 (vcpu) */ |
163 | REST_2GPRS(3, r1) | 183 | REST_2GPRS(3, r1) |
164 | bl FUNC(kvmppc_handle_exit) | 184 | bl FUNC(kvmppc_handle_exit_pr) |
165 | 185 | ||
166 | /* If RESUME_GUEST, get back in the loop */ | 186 | /* If RESUME_GUEST, get back in the loop */ |
167 | cmpwi r3, RESUME_GUEST | 187 | cmpwi r3, RESUME_GUEST |
diff --git a/arch/powerpc/kvm/book3s_mmu_hpte.c b/arch/powerpc/kvm/book3s_mmu_hpte.c index da8b13c4b776..5a1ab1250a05 100644 --- a/arch/powerpc/kvm/book3s_mmu_hpte.c +++ b/arch/powerpc/kvm/book3s_mmu_hpte.c | |||
@@ -28,7 +28,7 @@ | |||
28 | #include <asm/mmu_context.h> | 28 | #include <asm/mmu_context.h> |
29 | #include <asm/hw_irq.h> | 29 | #include <asm/hw_irq.h> |
30 | 30 | ||
31 | #include "trace.h" | 31 | #include "trace_pr.h" |
32 | 32 | ||
33 | #define PTE_SIZE 12 | 33 | #define PTE_SIZE 12 |
34 | 34 | ||
@@ -56,6 +56,14 @@ static inline u64 kvmppc_mmu_hash_vpte_long(u64 vpage) | |||
56 | HPTEG_HASH_BITS_VPTE_LONG); | 56 | HPTEG_HASH_BITS_VPTE_LONG); |
57 | } | 57 | } |
58 | 58 | ||
59 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
60 | static inline u64 kvmppc_mmu_hash_vpte_64k(u64 vpage) | ||
61 | { | ||
62 | return hash_64((vpage & 0xffffffff0ULL) >> 4, | ||
63 | HPTEG_HASH_BITS_VPTE_64K); | ||
64 | } | ||
65 | #endif | ||
66 | |||
59 | void kvmppc_mmu_hpte_cache_map(struct kvm_vcpu *vcpu, struct hpte_cache *pte) | 67 | void kvmppc_mmu_hpte_cache_map(struct kvm_vcpu *vcpu, struct hpte_cache *pte) |
60 | { | 68 | { |
61 | u64 index; | 69 | u64 index; |
@@ -83,6 +91,15 @@ void kvmppc_mmu_hpte_cache_map(struct kvm_vcpu *vcpu, struct hpte_cache *pte) | |||
83 | hlist_add_head_rcu(&pte->list_vpte_long, | 91 | hlist_add_head_rcu(&pte->list_vpte_long, |
84 | &vcpu3s->hpte_hash_vpte_long[index]); | 92 | &vcpu3s->hpte_hash_vpte_long[index]); |
85 | 93 | ||
94 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
95 | /* Add to vPTE_64k list */ | ||
96 | index = kvmppc_mmu_hash_vpte_64k(pte->pte.vpage); | ||
97 | hlist_add_head_rcu(&pte->list_vpte_64k, | ||
98 | &vcpu3s->hpte_hash_vpte_64k[index]); | ||
99 | #endif | ||
100 | |||
101 | vcpu3s->hpte_cache_count++; | ||
102 | |||
86 | spin_unlock(&vcpu3s->mmu_lock); | 103 | spin_unlock(&vcpu3s->mmu_lock); |
87 | } | 104 | } |
88 | 105 | ||
@@ -113,10 +130,13 @@ static void invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte) | |||
113 | hlist_del_init_rcu(&pte->list_pte_long); | 130 | hlist_del_init_rcu(&pte->list_pte_long); |
114 | hlist_del_init_rcu(&pte->list_vpte); | 131 | hlist_del_init_rcu(&pte->list_vpte); |
115 | hlist_del_init_rcu(&pte->list_vpte_long); | 132 | hlist_del_init_rcu(&pte->list_vpte_long); |
133 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
134 | hlist_del_init_rcu(&pte->list_vpte_64k); | ||
135 | #endif | ||
136 | vcpu3s->hpte_cache_count--; | ||
116 | 137 | ||
117 | spin_unlock(&vcpu3s->mmu_lock); | 138 | spin_unlock(&vcpu3s->mmu_lock); |
118 | 139 | ||
119 | vcpu3s->hpte_cache_count--; | ||
120 | call_rcu(&pte->rcu_head, free_pte_rcu); | 140 | call_rcu(&pte->rcu_head, free_pte_rcu); |
121 | } | 141 | } |
122 | 142 | ||
@@ -219,6 +239,29 @@ static void kvmppc_mmu_pte_vflush_short(struct kvm_vcpu *vcpu, u64 guest_vp) | |||
219 | rcu_read_unlock(); | 239 | rcu_read_unlock(); |
220 | } | 240 | } |
221 | 241 | ||
242 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
243 | /* Flush with mask 0xffffffff0 */ | ||
244 | static void kvmppc_mmu_pte_vflush_64k(struct kvm_vcpu *vcpu, u64 guest_vp) | ||
245 | { | ||
246 | struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu); | ||
247 | struct hlist_head *list; | ||
248 | struct hpte_cache *pte; | ||
249 | u64 vp_mask = 0xffffffff0ULL; | ||
250 | |||
251 | list = &vcpu3s->hpte_hash_vpte_64k[ | ||
252 | kvmppc_mmu_hash_vpte_64k(guest_vp)]; | ||
253 | |||
254 | rcu_read_lock(); | ||
255 | |||
256 | /* Check the list for matching entries and invalidate */ | ||
257 | hlist_for_each_entry_rcu(pte, list, list_vpte_64k) | ||
258 | if ((pte->pte.vpage & vp_mask) == guest_vp) | ||
259 | invalidate_pte(vcpu, pte); | ||
260 | |||
261 | rcu_read_unlock(); | ||
262 | } | ||
263 | #endif | ||
264 | |||
222 | /* Flush with mask 0xffffff000 */ | 265 | /* Flush with mask 0xffffff000 */ |
223 | static void kvmppc_mmu_pte_vflush_long(struct kvm_vcpu *vcpu, u64 guest_vp) | 266 | static void kvmppc_mmu_pte_vflush_long(struct kvm_vcpu *vcpu, u64 guest_vp) |
224 | { | 267 | { |
@@ -249,6 +292,11 @@ void kvmppc_mmu_pte_vflush(struct kvm_vcpu *vcpu, u64 guest_vp, u64 vp_mask) | |||
249 | case 0xfffffffffULL: | 292 | case 0xfffffffffULL: |
250 | kvmppc_mmu_pte_vflush_short(vcpu, guest_vp); | 293 | kvmppc_mmu_pte_vflush_short(vcpu, guest_vp); |
251 | break; | 294 | break; |
295 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
296 | case 0xffffffff0ULL: | ||
297 | kvmppc_mmu_pte_vflush_64k(vcpu, guest_vp); | ||
298 | break; | ||
299 | #endif | ||
252 | case 0xffffff000ULL: | 300 | case 0xffffff000ULL: |
253 | kvmppc_mmu_pte_vflush_long(vcpu, guest_vp); | 301 | kvmppc_mmu_pte_vflush_long(vcpu, guest_vp); |
254 | break; | 302 | break; |
@@ -285,15 +333,19 @@ struct hpte_cache *kvmppc_mmu_hpte_cache_next(struct kvm_vcpu *vcpu) | |||
285 | struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu); | 333 | struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu); |
286 | struct hpte_cache *pte; | 334 | struct hpte_cache *pte; |
287 | 335 | ||
288 | pte = kmem_cache_zalloc(hpte_cache, GFP_KERNEL); | ||
289 | vcpu3s->hpte_cache_count++; | ||
290 | |||
291 | if (vcpu3s->hpte_cache_count == HPTEG_CACHE_NUM) | 336 | if (vcpu3s->hpte_cache_count == HPTEG_CACHE_NUM) |
292 | kvmppc_mmu_pte_flush_all(vcpu); | 337 | kvmppc_mmu_pte_flush_all(vcpu); |
293 | 338 | ||
339 | pte = kmem_cache_zalloc(hpte_cache, GFP_KERNEL); | ||
340 | |||
294 | return pte; | 341 | return pte; |
295 | } | 342 | } |
296 | 343 | ||
344 | void kvmppc_mmu_hpte_cache_free(struct hpte_cache *pte) | ||
345 | { | ||
346 | kmem_cache_free(hpte_cache, pte); | ||
347 | } | ||
348 | |||
297 | void kvmppc_mmu_hpte_destroy(struct kvm_vcpu *vcpu) | 349 | void kvmppc_mmu_hpte_destroy(struct kvm_vcpu *vcpu) |
298 | { | 350 | { |
299 | kvmppc_mmu_pte_flush(vcpu, 0, 0); | 351 | kvmppc_mmu_pte_flush(vcpu, 0, 0); |
@@ -320,6 +372,10 @@ int kvmppc_mmu_hpte_init(struct kvm_vcpu *vcpu) | |||
320 | ARRAY_SIZE(vcpu3s->hpte_hash_vpte)); | 372 | ARRAY_SIZE(vcpu3s->hpte_hash_vpte)); |
321 | kvmppc_mmu_hpte_init_hash(vcpu3s->hpte_hash_vpte_long, | 373 | kvmppc_mmu_hpte_init_hash(vcpu3s->hpte_hash_vpte_long, |
322 | ARRAY_SIZE(vcpu3s->hpte_hash_vpte_long)); | 374 | ARRAY_SIZE(vcpu3s->hpte_hash_vpte_long)); |
375 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
376 | kvmppc_mmu_hpte_init_hash(vcpu3s->hpte_hash_vpte_64k, | ||
377 | ARRAY_SIZE(vcpu3s->hpte_hash_vpte_64k)); | ||
378 | #endif | ||
323 | 379 | ||
324 | spin_lock_init(&vcpu3s->mmu_lock); | 380 | spin_lock_init(&vcpu3s->mmu_lock); |
325 | 381 | ||
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c index 27db1e665959..fe14ca3dd171 100644 --- a/arch/powerpc/kvm/book3s_pr.c +++ b/arch/powerpc/kvm/book3s_pr.c | |||
@@ -40,8 +40,12 @@ | |||
40 | #include <linux/sched.h> | 40 | #include <linux/sched.h> |
41 | #include <linux/vmalloc.h> | 41 | #include <linux/vmalloc.h> |
42 | #include <linux/highmem.h> | 42 | #include <linux/highmem.h> |
43 | #include <linux/module.h> | ||
43 | 44 | ||
44 | #include "trace.h" | 45 | #include "book3s.h" |
46 | |||
47 | #define CREATE_TRACE_POINTS | ||
48 | #include "trace_pr.h" | ||
45 | 49 | ||
46 | /* #define EXIT_DEBUG */ | 50 | /* #define EXIT_DEBUG */ |
47 | /* #define DEBUG_EXT */ | 51 | /* #define DEBUG_EXT */ |
@@ -56,29 +60,25 @@ static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr, | |||
56 | #define HW_PAGE_SIZE PAGE_SIZE | 60 | #define HW_PAGE_SIZE PAGE_SIZE |
57 | #endif | 61 | #endif |
58 | 62 | ||
59 | void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu) | 63 | static void kvmppc_core_vcpu_load_pr(struct kvm_vcpu *vcpu, int cpu) |
60 | { | 64 | { |
61 | #ifdef CONFIG_PPC_BOOK3S_64 | 65 | #ifdef CONFIG_PPC_BOOK3S_64 |
62 | struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu); | 66 | struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu); |
63 | memcpy(svcpu->slb, to_book3s(vcpu)->slb_shadow, sizeof(svcpu->slb)); | 67 | memcpy(svcpu->slb, to_book3s(vcpu)->slb_shadow, sizeof(svcpu->slb)); |
64 | memcpy(&get_paca()->shadow_vcpu, to_book3s(vcpu)->shadow_vcpu, | ||
65 | sizeof(get_paca()->shadow_vcpu)); | ||
66 | svcpu->slb_max = to_book3s(vcpu)->slb_shadow_max; | 68 | svcpu->slb_max = to_book3s(vcpu)->slb_shadow_max; |
67 | svcpu_put(svcpu); | 69 | svcpu_put(svcpu); |
68 | #endif | 70 | #endif |
69 | vcpu->cpu = smp_processor_id(); | 71 | vcpu->cpu = smp_processor_id(); |
70 | #ifdef CONFIG_PPC_BOOK3S_32 | 72 | #ifdef CONFIG_PPC_BOOK3S_32 |
71 | current->thread.kvm_shadow_vcpu = to_book3s(vcpu)->shadow_vcpu; | 73 | current->thread.kvm_shadow_vcpu = vcpu->arch.shadow_vcpu; |
72 | #endif | 74 | #endif |
73 | } | 75 | } |
74 | 76 | ||
75 | void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu) | 77 | static void kvmppc_core_vcpu_put_pr(struct kvm_vcpu *vcpu) |
76 | { | 78 | { |
77 | #ifdef CONFIG_PPC_BOOK3S_64 | 79 | #ifdef CONFIG_PPC_BOOK3S_64 |
78 | struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu); | 80 | struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu); |
79 | memcpy(to_book3s(vcpu)->slb_shadow, svcpu->slb, sizeof(svcpu->slb)); | 81 | memcpy(to_book3s(vcpu)->slb_shadow, svcpu->slb, sizeof(svcpu->slb)); |
80 | memcpy(to_book3s(vcpu)->shadow_vcpu, &get_paca()->shadow_vcpu, | ||
81 | sizeof(get_paca()->shadow_vcpu)); | ||
82 | to_book3s(vcpu)->slb_shadow_max = svcpu->slb_max; | 82 | to_book3s(vcpu)->slb_shadow_max = svcpu->slb_max; |
83 | svcpu_put(svcpu); | 83 | svcpu_put(svcpu); |
84 | #endif | 84 | #endif |
@@ -87,7 +87,61 @@ void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu) | |||
87 | vcpu->cpu = -1; | 87 | vcpu->cpu = -1; |
88 | } | 88 | } |
89 | 89 | ||
90 | int kvmppc_core_check_requests(struct kvm_vcpu *vcpu) | 90 | /* Copy data needed by real-mode code from vcpu to shadow vcpu */ |
91 | void kvmppc_copy_to_svcpu(struct kvmppc_book3s_shadow_vcpu *svcpu, | ||
92 | struct kvm_vcpu *vcpu) | ||
93 | { | ||
94 | svcpu->gpr[0] = vcpu->arch.gpr[0]; | ||
95 | svcpu->gpr[1] = vcpu->arch.gpr[1]; | ||
96 | svcpu->gpr[2] = vcpu->arch.gpr[2]; | ||
97 | svcpu->gpr[3] = vcpu->arch.gpr[3]; | ||
98 | svcpu->gpr[4] = vcpu->arch.gpr[4]; | ||
99 | svcpu->gpr[5] = vcpu->arch.gpr[5]; | ||
100 | svcpu->gpr[6] = vcpu->arch.gpr[6]; | ||
101 | svcpu->gpr[7] = vcpu->arch.gpr[7]; | ||
102 | svcpu->gpr[8] = vcpu->arch.gpr[8]; | ||
103 | svcpu->gpr[9] = vcpu->arch.gpr[9]; | ||
104 | svcpu->gpr[10] = vcpu->arch.gpr[10]; | ||
105 | svcpu->gpr[11] = vcpu->arch.gpr[11]; | ||
106 | svcpu->gpr[12] = vcpu->arch.gpr[12]; | ||
107 | svcpu->gpr[13] = vcpu->arch.gpr[13]; | ||
108 | svcpu->cr = vcpu->arch.cr; | ||
109 | svcpu->xer = vcpu->arch.xer; | ||
110 | svcpu->ctr = vcpu->arch.ctr; | ||
111 | svcpu->lr = vcpu->arch.lr; | ||
112 | svcpu->pc = vcpu->arch.pc; | ||
113 | } | ||
114 | |||
115 | /* Copy data touched by real-mode code from shadow vcpu back to vcpu */ | ||
116 | void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu, | ||
117 | struct kvmppc_book3s_shadow_vcpu *svcpu) | ||
118 | { | ||
119 | vcpu->arch.gpr[0] = svcpu->gpr[0]; | ||
120 | vcpu->arch.gpr[1] = svcpu->gpr[1]; | ||
121 | vcpu->arch.gpr[2] = svcpu->gpr[2]; | ||
122 | vcpu->arch.gpr[3] = svcpu->gpr[3]; | ||
123 | vcpu->arch.gpr[4] = svcpu->gpr[4]; | ||
124 | vcpu->arch.gpr[5] = svcpu->gpr[5]; | ||
125 | vcpu->arch.gpr[6] = svcpu->gpr[6]; | ||
126 | vcpu->arch.gpr[7] = svcpu->gpr[7]; | ||
127 | vcpu->arch.gpr[8] = svcpu->gpr[8]; | ||
128 | vcpu->arch.gpr[9] = svcpu->gpr[9]; | ||
129 | vcpu->arch.gpr[10] = svcpu->gpr[10]; | ||
130 | vcpu->arch.gpr[11] = svcpu->gpr[11]; | ||
131 | vcpu->arch.gpr[12] = svcpu->gpr[12]; | ||
132 | vcpu->arch.gpr[13] = svcpu->gpr[13]; | ||
133 | vcpu->arch.cr = svcpu->cr; | ||
134 | vcpu->arch.xer = svcpu->xer; | ||
135 | vcpu->arch.ctr = svcpu->ctr; | ||
136 | vcpu->arch.lr = svcpu->lr; | ||
137 | vcpu->arch.pc = svcpu->pc; | ||
138 | vcpu->arch.shadow_srr1 = svcpu->shadow_srr1; | ||
139 | vcpu->arch.fault_dar = svcpu->fault_dar; | ||
140 | vcpu->arch.fault_dsisr = svcpu->fault_dsisr; | ||
141 | vcpu->arch.last_inst = svcpu->last_inst; | ||
142 | } | ||
143 | |||
144 | static int kvmppc_core_check_requests_pr(struct kvm_vcpu *vcpu) | ||
91 | { | 145 | { |
92 | int r = 1; /* Indicate we want to get back into the guest */ | 146 | int r = 1; /* Indicate we want to get back into the guest */ |
93 | 147 | ||
@@ -100,44 +154,69 @@ int kvmppc_core_check_requests(struct kvm_vcpu *vcpu) | |||
100 | } | 154 | } |
101 | 155 | ||
102 | /************* MMU Notifiers *************/ | 156 | /************* MMU Notifiers *************/ |
157 | static void do_kvm_unmap_hva(struct kvm *kvm, unsigned long start, | ||
158 | unsigned long end) | ||
159 | { | ||
160 | long i; | ||
161 | struct kvm_vcpu *vcpu; | ||
162 | struct kvm_memslots *slots; | ||
163 | struct kvm_memory_slot *memslot; | ||
164 | |||
165 | slots = kvm_memslots(kvm); | ||
166 | kvm_for_each_memslot(memslot, slots) { | ||
167 | unsigned long hva_start, hva_end; | ||
168 | gfn_t gfn, gfn_end; | ||
169 | |||
170 | hva_start = max(start, memslot->userspace_addr); | ||
171 | hva_end = min(end, memslot->userspace_addr + | ||
172 | (memslot->npages << PAGE_SHIFT)); | ||
173 | if (hva_start >= hva_end) | ||
174 | continue; | ||
175 | /* | ||
176 | * {gfn(page) | page intersects with [hva_start, hva_end)} = | ||
177 | * {gfn, gfn+1, ..., gfn_end-1}. | ||
178 | */ | ||
179 | gfn = hva_to_gfn_memslot(hva_start, memslot); | ||
180 | gfn_end = hva_to_gfn_memslot(hva_end + PAGE_SIZE - 1, memslot); | ||
181 | kvm_for_each_vcpu(i, vcpu, kvm) | ||
182 | kvmppc_mmu_pte_pflush(vcpu, gfn << PAGE_SHIFT, | ||
183 | gfn_end << PAGE_SHIFT); | ||
184 | } | ||
185 | } | ||
103 | 186 | ||
104 | int kvm_unmap_hva(struct kvm *kvm, unsigned long hva) | 187 | static int kvm_unmap_hva_pr(struct kvm *kvm, unsigned long hva) |
105 | { | 188 | { |
106 | trace_kvm_unmap_hva(hva); | 189 | trace_kvm_unmap_hva(hva); |
107 | 190 | ||
108 | /* | 191 | do_kvm_unmap_hva(kvm, hva, hva + PAGE_SIZE); |
109 | * Flush all shadow tlb entries everywhere. This is slow, but | ||
110 | * we are 100% sure that we catch the to be unmapped page | ||
111 | */ | ||
112 | kvm_flush_remote_tlbs(kvm); | ||
113 | 192 | ||
114 | return 0; | 193 | return 0; |
115 | } | 194 | } |
116 | 195 | ||
117 | int kvm_unmap_hva_range(struct kvm *kvm, unsigned long start, unsigned long end) | 196 | static int kvm_unmap_hva_range_pr(struct kvm *kvm, unsigned long start, |
197 | unsigned long end) | ||
118 | { | 198 | { |
119 | /* kvm_unmap_hva flushes everything anyways */ | 199 | do_kvm_unmap_hva(kvm, start, end); |
120 | kvm_unmap_hva(kvm, start); | ||
121 | 200 | ||
122 | return 0; | 201 | return 0; |
123 | } | 202 | } |
124 | 203 | ||
125 | int kvm_age_hva(struct kvm *kvm, unsigned long hva) | 204 | static int kvm_age_hva_pr(struct kvm *kvm, unsigned long hva) |
126 | { | 205 | { |
127 | /* XXX could be more clever ;) */ | 206 | /* XXX could be more clever ;) */ |
128 | return 0; | 207 | return 0; |
129 | } | 208 | } |
130 | 209 | ||
131 | int kvm_test_age_hva(struct kvm *kvm, unsigned long hva) | 210 | static int kvm_test_age_hva_pr(struct kvm *kvm, unsigned long hva) |
132 | { | 211 | { |
133 | /* XXX could be more clever ;) */ | 212 | /* XXX could be more clever ;) */ |
134 | return 0; | 213 | return 0; |
135 | } | 214 | } |
136 | 215 | ||
137 | void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte) | 216 | static void kvm_set_spte_hva_pr(struct kvm *kvm, unsigned long hva, pte_t pte) |
138 | { | 217 | { |
139 | /* The page will get remapped properly on its next fault */ | 218 | /* The page will get remapped properly on its next fault */ |
140 | kvm_unmap_hva(kvm, hva); | 219 | do_kvm_unmap_hva(kvm, hva, hva + PAGE_SIZE); |
141 | } | 220 | } |
142 | 221 | ||
143 | /*****************************************/ | 222 | /*****************************************/ |
@@ -159,7 +238,7 @@ static void kvmppc_recalc_shadow_msr(struct kvm_vcpu *vcpu) | |||
159 | vcpu->arch.shadow_msr = smsr; | 238 | vcpu->arch.shadow_msr = smsr; |
160 | } | 239 | } |
161 | 240 | ||
162 | void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 msr) | 241 | static void kvmppc_set_msr_pr(struct kvm_vcpu *vcpu, u64 msr) |
163 | { | 242 | { |
164 | ulong old_msr = vcpu->arch.shared->msr; | 243 | ulong old_msr = vcpu->arch.shared->msr; |
165 | 244 | ||
@@ -219,7 +298,7 @@ void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 msr) | |||
219 | kvmppc_handle_ext(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, MSR_FP); | 298 | kvmppc_handle_ext(vcpu, BOOK3S_INTERRUPT_FP_UNAVAIL, MSR_FP); |
220 | } | 299 | } |
221 | 300 | ||
222 | void kvmppc_set_pvr(struct kvm_vcpu *vcpu, u32 pvr) | 301 | void kvmppc_set_pvr_pr(struct kvm_vcpu *vcpu, u32 pvr) |
223 | { | 302 | { |
224 | u32 host_pvr; | 303 | u32 host_pvr; |
225 | 304 | ||
@@ -256,6 +335,23 @@ void kvmppc_set_pvr(struct kvm_vcpu *vcpu, u32 pvr) | |||
256 | if (!strcmp(cur_cpu_spec->platform, "ppc-cell-be")) | 335 | if (!strcmp(cur_cpu_spec->platform, "ppc-cell-be")) |
257 | to_book3s(vcpu)->msr_mask &= ~(MSR_FE0 | MSR_FE1); | 336 | to_book3s(vcpu)->msr_mask &= ~(MSR_FE0 | MSR_FE1); |
258 | 337 | ||
338 | /* | ||
339 | * If they're asking for POWER6 or later, set the flag | ||
340 | * indicating that we can do multiple large page sizes | ||
341 | * and 1TB segments. | ||
342 | * Also set the flag that indicates that tlbie has the large | ||
343 | * page bit in the RB operand instead of the instruction. | ||
344 | */ | ||
345 | switch (PVR_VER(pvr)) { | ||
346 | case PVR_POWER6: | ||
347 | case PVR_POWER7: | ||
348 | case PVR_POWER7p: | ||
349 | case PVR_POWER8: | ||
350 | vcpu->arch.hflags |= BOOK3S_HFLAG_MULTI_PGSIZE | | ||
351 | BOOK3S_HFLAG_NEW_TLBIE; | ||
352 | break; | ||
353 | } | ||
354 | |||
259 | #ifdef CONFIG_PPC_BOOK3S_32 | 355 | #ifdef CONFIG_PPC_BOOK3S_32 |
260 | /* 32 bit Book3S always has 32 byte dcbz */ | 356 | /* 32 bit Book3S always has 32 byte dcbz */ |
261 | vcpu->arch.hflags |= BOOK3S_HFLAG_DCBZ32; | 357 | vcpu->arch.hflags |= BOOK3S_HFLAG_DCBZ32; |
@@ -334,6 +430,7 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
334 | ulong eaddr, int vec) | 430 | ulong eaddr, int vec) |
335 | { | 431 | { |
336 | bool data = (vec == BOOK3S_INTERRUPT_DATA_STORAGE); | 432 | bool data = (vec == BOOK3S_INTERRUPT_DATA_STORAGE); |
433 | bool iswrite = false; | ||
337 | int r = RESUME_GUEST; | 434 | int r = RESUME_GUEST; |
338 | int relocated; | 435 | int relocated; |
339 | int page_found = 0; | 436 | int page_found = 0; |
@@ -344,10 +441,12 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
344 | u64 vsid; | 441 | u64 vsid; |
345 | 442 | ||
346 | relocated = data ? dr : ir; | 443 | relocated = data ? dr : ir; |
444 | if (data && (vcpu->arch.fault_dsisr & DSISR_ISSTORE)) | ||
445 | iswrite = true; | ||
347 | 446 | ||
348 | /* Resolve real address if translation turned on */ | 447 | /* Resolve real address if translation turned on */ |
349 | if (relocated) { | 448 | if (relocated) { |
350 | page_found = vcpu->arch.mmu.xlate(vcpu, eaddr, &pte, data); | 449 | page_found = vcpu->arch.mmu.xlate(vcpu, eaddr, &pte, data, iswrite); |
351 | } else { | 450 | } else { |
352 | pte.may_execute = true; | 451 | pte.may_execute = true; |
353 | pte.may_read = true; | 452 | pte.may_read = true; |
@@ -355,6 +454,7 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
355 | pte.raddr = eaddr & KVM_PAM; | 454 | pte.raddr = eaddr & KVM_PAM; |
356 | pte.eaddr = eaddr; | 455 | pte.eaddr = eaddr; |
357 | pte.vpage = eaddr >> 12; | 456 | pte.vpage = eaddr >> 12; |
457 | pte.page_size = MMU_PAGE_64K; | ||
358 | } | 458 | } |
359 | 459 | ||
360 | switch (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) { | 460 | switch (vcpu->arch.shared->msr & (MSR_DR|MSR_IR)) { |
@@ -388,22 +488,18 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
388 | 488 | ||
389 | if (page_found == -ENOENT) { | 489 | if (page_found == -ENOENT) { |
390 | /* Page not found in guest PTE entries */ | 490 | /* Page not found in guest PTE entries */ |
391 | struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu); | ||
392 | vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu); | 491 | vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu); |
393 | vcpu->arch.shared->dsisr = svcpu->fault_dsisr; | 492 | vcpu->arch.shared->dsisr = vcpu->arch.fault_dsisr; |
394 | vcpu->arch.shared->msr |= | 493 | vcpu->arch.shared->msr |= |
395 | (svcpu->shadow_srr1 & 0x00000000f8000000ULL); | 494 | vcpu->arch.shadow_srr1 & 0x00000000f8000000ULL; |
396 | svcpu_put(svcpu); | ||
397 | kvmppc_book3s_queue_irqprio(vcpu, vec); | 495 | kvmppc_book3s_queue_irqprio(vcpu, vec); |
398 | } else if (page_found == -EPERM) { | 496 | } else if (page_found == -EPERM) { |
399 | /* Storage protection */ | 497 | /* Storage protection */ |
400 | struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu); | ||
401 | vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu); | 498 | vcpu->arch.shared->dar = kvmppc_get_fault_dar(vcpu); |
402 | vcpu->arch.shared->dsisr = svcpu->fault_dsisr & ~DSISR_NOHPTE; | 499 | vcpu->arch.shared->dsisr = vcpu->arch.fault_dsisr & ~DSISR_NOHPTE; |
403 | vcpu->arch.shared->dsisr |= DSISR_PROTFAULT; | 500 | vcpu->arch.shared->dsisr |= DSISR_PROTFAULT; |
404 | vcpu->arch.shared->msr |= | 501 | vcpu->arch.shared->msr |= |
405 | svcpu->shadow_srr1 & 0x00000000f8000000ULL; | 502 | vcpu->arch.shadow_srr1 & 0x00000000f8000000ULL; |
406 | svcpu_put(svcpu); | ||
407 | kvmppc_book3s_queue_irqprio(vcpu, vec); | 503 | kvmppc_book3s_queue_irqprio(vcpu, vec); |
408 | } else if (page_found == -EINVAL) { | 504 | } else if (page_found == -EINVAL) { |
409 | /* Page not found in guest SLB */ | 505 | /* Page not found in guest SLB */ |
@@ -411,12 +507,20 @@ int kvmppc_handle_pagefault(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
411 | kvmppc_book3s_queue_irqprio(vcpu, vec + 0x80); | 507 | kvmppc_book3s_queue_irqprio(vcpu, vec + 0x80); |
412 | } else if (!is_mmio && | 508 | } else if (!is_mmio && |
413 | kvmppc_visible_gfn(vcpu, pte.raddr >> PAGE_SHIFT)) { | 509 | kvmppc_visible_gfn(vcpu, pte.raddr >> PAGE_SHIFT)) { |
510 | if (data && !(vcpu->arch.fault_dsisr & DSISR_NOHPTE)) { | ||
511 | /* | ||
512 | * There is already a host HPTE there, presumably | ||
513 | * a read-only one for a page the guest thinks | ||
514 | * is writable, so get rid of it first. | ||
515 | */ | ||
516 | kvmppc_mmu_unmap_page(vcpu, &pte); | ||
517 | } | ||
414 | /* The guest's PTE is not mapped yet. Map on the host */ | 518 | /* The guest's PTE is not mapped yet. Map on the host */ |
415 | kvmppc_mmu_map_page(vcpu, &pte); | 519 | kvmppc_mmu_map_page(vcpu, &pte, iswrite); |
416 | if (data) | 520 | if (data) |
417 | vcpu->stat.sp_storage++; | 521 | vcpu->stat.sp_storage++; |
418 | else if (vcpu->arch.mmu.is_dcbz32(vcpu) && | 522 | else if (vcpu->arch.mmu.is_dcbz32(vcpu) && |
419 | (!(vcpu->arch.hflags & BOOK3S_HFLAG_DCBZ32))) | 523 | (!(vcpu->arch.hflags & BOOK3S_HFLAG_DCBZ32))) |
420 | kvmppc_patch_dcbz(vcpu, &pte); | 524 | kvmppc_patch_dcbz(vcpu, &pte); |
421 | } else { | 525 | } else { |
422 | /* MMIO */ | 526 | /* MMIO */ |
@@ -444,7 +548,7 @@ void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr) | |||
444 | #ifdef CONFIG_VSX | 548 | #ifdef CONFIG_VSX |
445 | u64 *vcpu_vsx = vcpu->arch.vsr; | 549 | u64 *vcpu_vsx = vcpu->arch.vsr; |
446 | #endif | 550 | #endif |
447 | u64 *thread_fpr = (u64*)t->fpr; | 551 | u64 *thread_fpr = &t->fp_state.fpr[0][0]; |
448 | int i; | 552 | int i; |
449 | 553 | ||
450 | /* | 554 | /* |
@@ -466,14 +570,14 @@ void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr) | |||
466 | /* | 570 | /* |
467 | * Note that on CPUs with VSX, giveup_fpu stores | 571 | * Note that on CPUs with VSX, giveup_fpu stores |
468 | * both the traditional FP registers and the added VSX | 572 | * both the traditional FP registers and the added VSX |
469 | * registers into thread.fpr[]. | 573 | * registers into thread.fp_state.fpr[]. |
470 | */ | 574 | */ |
471 | if (current->thread.regs->msr & MSR_FP) | 575 | if (current->thread.regs->msr & MSR_FP) |
472 | giveup_fpu(current); | 576 | giveup_fpu(current); |
473 | for (i = 0; i < ARRAY_SIZE(vcpu->arch.fpr); i++) | 577 | for (i = 0; i < ARRAY_SIZE(vcpu->arch.fpr); i++) |
474 | vcpu_fpr[i] = thread_fpr[get_fpr_index(i)]; | 578 | vcpu_fpr[i] = thread_fpr[get_fpr_index(i)]; |
475 | 579 | ||
476 | vcpu->arch.fpscr = t->fpscr.val; | 580 | vcpu->arch.fpscr = t->fp_state.fpscr; |
477 | 581 | ||
478 | #ifdef CONFIG_VSX | 582 | #ifdef CONFIG_VSX |
479 | if (cpu_has_feature(CPU_FTR_VSX)) | 583 | if (cpu_has_feature(CPU_FTR_VSX)) |
@@ -486,8 +590,8 @@ void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr) | |||
486 | if (msr & MSR_VEC) { | 590 | if (msr & MSR_VEC) { |
487 | if (current->thread.regs->msr & MSR_VEC) | 591 | if (current->thread.regs->msr & MSR_VEC) |
488 | giveup_altivec(current); | 592 | giveup_altivec(current); |
489 | memcpy(vcpu->arch.vr, t->vr, sizeof(vcpu->arch.vr)); | 593 | memcpy(vcpu->arch.vr, t->vr_state.vr, sizeof(vcpu->arch.vr)); |
490 | vcpu->arch.vscr = t->vscr; | 594 | vcpu->arch.vscr = t->vr_state.vscr; |
491 | } | 595 | } |
492 | #endif | 596 | #endif |
493 | 597 | ||
@@ -539,7 +643,7 @@ static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr, | |||
539 | #ifdef CONFIG_VSX | 643 | #ifdef CONFIG_VSX |
540 | u64 *vcpu_vsx = vcpu->arch.vsr; | 644 | u64 *vcpu_vsx = vcpu->arch.vsr; |
541 | #endif | 645 | #endif |
542 | u64 *thread_fpr = (u64*)t->fpr; | 646 | u64 *thread_fpr = &t->fp_state.fpr[0][0]; |
543 | int i; | 647 | int i; |
544 | 648 | ||
545 | /* When we have paired singles, we emulate in software */ | 649 | /* When we have paired singles, we emulate in software */ |
@@ -584,15 +688,15 @@ static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr, | |||
584 | for (i = 0; i < ARRAY_SIZE(vcpu->arch.vsr) / 2; i++) | 688 | for (i = 0; i < ARRAY_SIZE(vcpu->arch.vsr) / 2; i++) |
585 | thread_fpr[get_fpr_index(i) + 1] = vcpu_vsx[i]; | 689 | thread_fpr[get_fpr_index(i) + 1] = vcpu_vsx[i]; |
586 | #endif | 690 | #endif |
587 | t->fpscr.val = vcpu->arch.fpscr; | 691 | t->fp_state.fpscr = vcpu->arch.fpscr; |
588 | t->fpexc_mode = 0; | 692 | t->fpexc_mode = 0; |
589 | kvmppc_load_up_fpu(); | 693 | kvmppc_load_up_fpu(); |
590 | } | 694 | } |
591 | 695 | ||
592 | if (msr & MSR_VEC) { | 696 | if (msr & MSR_VEC) { |
593 | #ifdef CONFIG_ALTIVEC | 697 | #ifdef CONFIG_ALTIVEC |
594 | memcpy(t->vr, vcpu->arch.vr, sizeof(vcpu->arch.vr)); | 698 | memcpy(t->vr_state.vr, vcpu->arch.vr, sizeof(vcpu->arch.vr)); |
595 | t->vscr = vcpu->arch.vscr; | 699 | t->vr_state.vscr = vcpu->arch.vscr; |
596 | t->vrsave = -1; | 700 | t->vrsave = -1; |
597 | kvmppc_load_up_altivec(); | 701 | kvmppc_load_up_altivec(); |
598 | #endif | 702 | #endif |
@@ -619,13 +723,15 @@ static void kvmppc_handle_lost_ext(struct kvm_vcpu *vcpu) | |||
619 | 723 | ||
620 | if (lost_ext & MSR_FP) | 724 | if (lost_ext & MSR_FP) |
621 | kvmppc_load_up_fpu(); | 725 | kvmppc_load_up_fpu(); |
726 | #ifdef CONFIG_ALTIVEC | ||
622 | if (lost_ext & MSR_VEC) | 727 | if (lost_ext & MSR_VEC) |
623 | kvmppc_load_up_altivec(); | 728 | kvmppc_load_up_altivec(); |
729 | #endif | ||
624 | current->thread.regs->msr |= lost_ext; | 730 | current->thread.regs->msr |= lost_ext; |
625 | } | 731 | } |
626 | 732 | ||
627 | int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | 733 | int kvmppc_handle_exit_pr(struct kvm_run *run, struct kvm_vcpu *vcpu, |
628 | unsigned int exit_nr) | 734 | unsigned int exit_nr) |
629 | { | 735 | { |
630 | int r = RESUME_HOST; | 736 | int r = RESUME_HOST; |
631 | int s; | 737 | int s; |
@@ -643,25 +749,32 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
643 | switch (exit_nr) { | 749 | switch (exit_nr) { |
644 | case BOOK3S_INTERRUPT_INST_STORAGE: | 750 | case BOOK3S_INTERRUPT_INST_STORAGE: |
645 | { | 751 | { |
646 | struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu); | 752 | ulong shadow_srr1 = vcpu->arch.shadow_srr1; |
647 | ulong shadow_srr1 = svcpu->shadow_srr1; | ||
648 | vcpu->stat.pf_instruc++; | 753 | vcpu->stat.pf_instruc++; |
649 | 754 | ||
650 | #ifdef CONFIG_PPC_BOOK3S_32 | 755 | #ifdef CONFIG_PPC_BOOK3S_32 |
651 | /* We set segments as unused segments when invalidating them. So | 756 | /* We set segments as unused segments when invalidating them. So |
652 | * treat the respective fault as segment fault. */ | 757 | * treat the respective fault as segment fault. */ |
653 | if (svcpu->sr[kvmppc_get_pc(vcpu) >> SID_SHIFT] == SR_INVALID) { | 758 | { |
654 | kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu)); | 759 | struct kvmppc_book3s_shadow_vcpu *svcpu; |
655 | r = RESUME_GUEST; | 760 | u32 sr; |
761 | |||
762 | svcpu = svcpu_get(vcpu); | ||
763 | sr = svcpu->sr[kvmppc_get_pc(vcpu) >> SID_SHIFT]; | ||
656 | svcpu_put(svcpu); | 764 | svcpu_put(svcpu); |
657 | break; | 765 | if (sr == SR_INVALID) { |
766 | kvmppc_mmu_map_segment(vcpu, kvmppc_get_pc(vcpu)); | ||
767 | r = RESUME_GUEST; | ||
768 | break; | ||
769 | } | ||
658 | } | 770 | } |
659 | #endif | 771 | #endif |
660 | svcpu_put(svcpu); | ||
661 | 772 | ||
662 | /* only care about PTEG not found errors, but leave NX alone */ | 773 | /* only care about PTEG not found errors, but leave NX alone */ |
663 | if (shadow_srr1 & 0x40000000) { | 774 | if (shadow_srr1 & 0x40000000) { |
775 | int idx = srcu_read_lock(&vcpu->kvm->srcu); | ||
664 | r = kvmppc_handle_pagefault(run, vcpu, kvmppc_get_pc(vcpu), exit_nr); | 776 | r = kvmppc_handle_pagefault(run, vcpu, kvmppc_get_pc(vcpu), exit_nr); |
777 | srcu_read_unlock(&vcpu->kvm->srcu, idx); | ||
665 | vcpu->stat.sp_instruc++; | 778 | vcpu->stat.sp_instruc++; |
666 | } else if (vcpu->arch.mmu.is_dcbz32(vcpu) && | 779 | } else if (vcpu->arch.mmu.is_dcbz32(vcpu) && |
667 | (!(vcpu->arch.hflags & BOOK3S_HFLAG_DCBZ32))) { | 780 | (!(vcpu->arch.hflags & BOOK3S_HFLAG_DCBZ32))) { |
@@ -682,25 +795,36 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
682 | case BOOK3S_INTERRUPT_DATA_STORAGE: | 795 | case BOOK3S_INTERRUPT_DATA_STORAGE: |
683 | { | 796 | { |
684 | ulong dar = kvmppc_get_fault_dar(vcpu); | 797 | ulong dar = kvmppc_get_fault_dar(vcpu); |
685 | struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu); | 798 | u32 fault_dsisr = vcpu->arch.fault_dsisr; |
686 | u32 fault_dsisr = svcpu->fault_dsisr; | ||
687 | vcpu->stat.pf_storage++; | 799 | vcpu->stat.pf_storage++; |
688 | 800 | ||
689 | #ifdef CONFIG_PPC_BOOK3S_32 | 801 | #ifdef CONFIG_PPC_BOOK3S_32 |
690 | /* We set segments as unused segments when invalidating them. So | 802 | /* We set segments as unused segments when invalidating them. So |
691 | * treat the respective fault as segment fault. */ | 803 | * treat the respective fault as segment fault. */ |
692 | if ((svcpu->sr[dar >> SID_SHIFT]) == SR_INVALID) { | 804 | { |
693 | kvmppc_mmu_map_segment(vcpu, dar); | 805 | struct kvmppc_book3s_shadow_vcpu *svcpu; |
694 | r = RESUME_GUEST; | 806 | u32 sr; |
807 | |||
808 | svcpu = svcpu_get(vcpu); | ||
809 | sr = svcpu->sr[dar >> SID_SHIFT]; | ||
695 | svcpu_put(svcpu); | 810 | svcpu_put(svcpu); |
696 | break; | 811 | if (sr == SR_INVALID) { |
812 | kvmppc_mmu_map_segment(vcpu, dar); | ||
813 | r = RESUME_GUEST; | ||
814 | break; | ||
815 | } | ||
697 | } | 816 | } |
698 | #endif | 817 | #endif |
699 | svcpu_put(svcpu); | ||
700 | 818 | ||
701 | /* The only case we need to handle is missing shadow PTEs */ | 819 | /* |
702 | if (fault_dsisr & DSISR_NOHPTE) { | 820 | * We need to handle missing shadow PTEs, and |
821 | * protection faults due to us mapping a page read-only | ||
822 | * when the guest thinks it is writable. | ||
823 | */ | ||
824 | if (fault_dsisr & (DSISR_NOHPTE | DSISR_PROTFAULT)) { | ||
825 | int idx = srcu_read_lock(&vcpu->kvm->srcu); | ||
703 | r = kvmppc_handle_pagefault(run, vcpu, dar, exit_nr); | 826 | r = kvmppc_handle_pagefault(run, vcpu, dar, exit_nr); |
827 | srcu_read_unlock(&vcpu->kvm->srcu, idx); | ||
704 | } else { | 828 | } else { |
705 | vcpu->arch.shared->dar = dar; | 829 | vcpu->arch.shared->dar = dar; |
706 | vcpu->arch.shared->dsisr = fault_dsisr; | 830 | vcpu->arch.shared->dsisr = fault_dsisr; |
@@ -743,13 +867,10 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
743 | case BOOK3S_INTERRUPT_H_EMUL_ASSIST: | 867 | case BOOK3S_INTERRUPT_H_EMUL_ASSIST: |
744 | { | 868 | { |
745 | enum emulation_result er; | 869 | enum emulation_result er; |
746 | struct kvmppc_book3s_shadow_vcpu *svcpu; | ||
747 | ulong flags; | 870 | ulong flags; |
748 | 871 | ||
749 | program_interrupt: | 872 | program_interrupt: |
750 | svcpu = svcpu_get(vcpu); | 873 | flags = vcpu->arch.shadow_srr1 & 0x1f0000ull; |
751 | flags = svcpu->shadow_srr1 & 0x1f0000ull; | ||
752 | svcpu_put(svcpu); | ||
753 | 874 | ||
754 | if (vcpu->arch.shared->msr & MSR_PR) { | 875 | if (vcpu->arch.shared->msr & MSR_PR) { |
755 | #ifdef EXIT_DEBUG | 876 | #ifdef EXIT_DEBUG |
@@ -798,7 +919,7 @@ program_interrupt: | |||
798 | ulong cmd = kvmppc_get_gpr(vcpu, 3); | 919 | ulong cmd = kvmppc_get_gpr(vcpu, 3); |
799 | int i; | 920 | int i; |
800 | 921 | ||
801 | #ifdef CONFIG_KVM_BOOK3S_64_PR | 922 | #ifdef CONFIG_PPC_BOOK3S_64 |
802 | if (kvmppc_h_pr(vcpu, cmd) == EMULATE_DONE) { | 923 | if (kvmppc_h_pr(vcpu, cmd) == EMULATE_DONE) { |
803 | r = RESUME_GUEST; | 924 | r = RESUME_GUEST; |
804 | break; | 925 | break; |
@@ -881,9 +1002,7 @@ program_interrupt: | |||
881 | break; | 1002 | break; |
882 | default: | 1003 | default: |
883 | { | 1004 | { |
884 | struct kvmppc_book3s_shadow_vcpu *svcpu = svcpu_get(vcpu); | 1005 | ulong shadow_srr1 = vcpu->arch.shadow_srr1; |
885 | ulong shadow_srr1 = svcpu->shadow_srr1; | ||
886 | svcpu_put(svcpu); | ||
887 | /* Ugh - bork here! What did we get? */ | 1006 | /* Ugh - bork here! What did we get? */ |
888 | printk(KERN_EMERG "exit_nr=0x%x | pc=0x%lx | msr=0x%lx\n", | 1007 | printk(KERN_EMERG "exit_nr=0x%x | pc=0x%lx | msr=0x%lx\n", |
889 | exit_nr, kvmppc_get_pc(vcpu), shadow_srr1); | 1008 | exit_nr, kvmppc_get_pc(vcpu), shadow_srr1); |
@@ -920,8 +1039,8 @@ program_interrupt: | |||
920 | return r; | 1039 | return r; |
921 | } | 1040 | } |
922 | 1041 | ||
923 | int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu, | 1042 | static int kvm_arch_vcpu_ioctl_get_sregs_pr(struct kvm_vcpu *vcpu, |
924 | struct kvm_sregs *sregs) | 1043 | struct kvm_sregs *sregs) |
925 | { | 1044 | { |
926 | struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu); | 1045 | struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu); |
927 | int i; | 1046 | int i; |
@@ -947,13 +1066,13 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu, | |||
947 | return 0; | 1066 | return 0; |
948 | } | 1067 | } |
949 | 1068 | ||
950 | int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, | 1069 | static int kvm_arch_vcpu_ioctl_set_sregs_pr(struct kvm_vcpu *vcpu, |
951 | struct kvm_sregs *sregs) | 1070 | struct kvm_sregs *sregs) |
952 | { | 1071 | { |
953 | struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu); | 1072 | struct kvmppc_vcpu_book3s *vcpu3s = to_book3s(vcpu); |
954 | int i; | 1073 | int i; |
955 | 1074 | ||
956 | kvmppc_set_pvr(vcpu, sregs->pvr); | 1075 | kvmppc_set_pvr_pr(vcpu, sregs->pvr); |
957 | 1076 | ||
958 | vcpu3s->sdr1 = sregs->u.s.sdr1; | 1077 | vcpu3s->sdr1 = sregs->u.s.sdr1; |
959 | if (vcpu->arch.hflags & BOOK3S_HFLAG_SLB) { | 1078 | if (vcpu->arch.hflags & BOOK3S_HFLAG_SLB) { |
@@ -983,7 +1102,8 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, | |||
983 | return 0; | 1102 | return 0; |
984 | } | 1103 | } |
985 | 1104 | ||
986 | int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val) | 1105 | static int kvmppc_get_one_reg_pr(struct kvm_vcpu *vcpu, u64 id, |
1106 | union kvmppc_one_reg *val) | ||
987 | { | 1107 | { |
988 | int r = 0; | 1108 | int r = 0; |
989 | 1109 | ||
@@ -1012,7 +1132,8 @@ int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val) | |||
1012 | return r; | 1132 | return r; |
1013 | } | 1133 | } |
1014 | 1134 | ||
1015 | int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val) | 1135 | static int kvmppc_set_one_reg_pr(struct kvm_vcpu *vcpu, u64 id, |
1136 | union kvmppc_one_reg *val) | ||
1016 | { | 1137 | { |
1017 | int r = 0; | 1138 | int r = 0; |
1018 | 1139 | ||
@@ -1042,28 +1163,30 @@ int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *val) | |||
1042 | return r; | 1163 | return r; |
1043 | } | 1164 | } |
1044 | 1165 | ||
1045 | int kvmppc_core_check_processor_compat(void) | 1166 | static struct kvm_vcpu *kvmppc_core_vcpu_create_pr(struct kvm *kvm, |
1046 | { | 1167 | unsigned int id) |
1047 | return 0; | ||
1048 | } | ||
1049 | |||
1050 | struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id) | ||
1051 | { | 1168 | { |
1052 | struct kvmppc_vcpu_book3s *vcpu_book3s; | 1169 | struct kvmppc_vcpu_book3s *vcpu_book3s; |
1053 | struct kvm_vcpu *vcpu; | 1170 | struct kvm_vcpu *vcpu; |
1054 | int err = -ENOMEM; | 1171 | int err = -ENOMEM; |
1055 | unsigned long p; | 1172 | unsigned long p; |
1056 | 1173 | ||
1057 | vcpu_book3s = vzalloc(sizeof(struct kvmppc_vcpu_book3s)); | 1174 | vcpu = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL); |
1058 | if (!vcpu_book3s) | 1175 | if (!vcpu) |
1059 | goto out; | 1176 | goto out; |
1060 | 1177 | ||
1061 | vcpu_book3s->shadow_vcpu = | 1178 | vcpu_book3s = vzalloc(sizeof(struct kvmppc_vcpu_book3s)); |
1062 | kzalloc(sizeof(*vcpu_book3s->shadow_vcpu), GFP_KERNEL); | 1179 | if (!vcpu_book3s) |
1063 | if (!vcpu_book3s->shadow_vcpu) | ||
1064 | goto free_vcpu; | 1180 | goto free_vcpu; |
1181 | vcpu->arch.book3s = vcpu_book3s; | ||
1182 | |||
1183 | #ifdef CONFIG_KVM_BOOK3S_32 | ||
1184 | vcpu->arch.shadow_vcpu = | ||
1185 | kzalloc(sizeof(*vcpu->arch.shadow_vcpu), GFP_KERNEL); | ||
1186 | if (!vcpu->arch.shadow_vcpu) | ||
1187 | goto free_vcpu3s; | ||
1188 | #endif | ||
1065 | 1189 | ||
1066 | vcpu = &vcpu_book3s->vcpu; | ||
1067 | err = kvm_vcpu_init(vcpu, kvm, id); | 1190 | err = kvm_vcpu_init(vcpu, kvm, id); |
1068 | if (err) | 1191 | if (err) |
1069 | goto free_shadow_vcpu; | 1192 | goto free_shadow_vcpu; |
@@ -1076,13 +1199,19 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id) | |||
1076 | vcpu->arch.shared = (void *)(p + PAGE_SIZE - 4096); | 1199 | vcpu->arch.shared = (void *)(p + PAGE_SIZE - 4096); |
1077 | 1200 | ||
1078 | #ifdef CONFIG_PPC_BOOK3S_64 | 1201 | #ifdef CONFIG_PPC_BOOK3S_64 |
1079 | /* default to book3s_64 (970fx) */ | 1202 | /* |
1203 | * Default to the same as the host if we're on sufficiently | ||
1204 | * recent machine that we have 1TB segments; | ||
1205 | * otherwise default to PPC970FX. | ||
1206 | */ | ||
1080 | vcpu->arch.pvr = 0x3C0301; | 1207 | vcpu->arch.pvr = 0x3C0301; |
1208 | if (mmu_has_feature(MMU_FTR_1T_SEGMENT)) | ||
1209 | vcpu->arch.pvr = mfspr(SPRN_PVR); | ||
1081 | #else | 1210 | #else |
1082 | /* default to book3s_32 (750) */ | 1211 | /* default to book3s_32 (750) */ |
1083 | vcpu->arch.pvr = 0x84202; | 1212 | vcpu->arch.pvr = 0x84202; |
1084 | #endif | 1213 | #endif |
1085 | kvmppc_set_pvr(vcpu, vcpu->arch.pvr); | 1214 | kvmppc_set_pvr_pr(vcpu, vcpu->arch.pvr); |
1086 | vcpu->arch.slb_nr = 64; | 1215 | vcpu->arch.slb_nr = 64; |
1087 | 1216 | ||
1088 | vcpu->arch.shadow_msr = MSR_USER64; | 1217 | vcpu->arch.shadow_msr = MSR_USER64; |
@@ -1096,32 +1225,37 @@ struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id) | |||
1096 | uninit_vcpu: | 1225 | uninit_vcpu: |
1097 | kvm_vcpu_uninit(vcpu); | 1226 | kvm_vcpu_uninit(vcpu); |
1098 | free_shadow_vcpu: | 1227 | free_shadow_vcpu: |
1099 | kfree(vcpu_book3s->shadow_vcpu); | 1228 | #ifdef CONFIG_KVM_BOOK3S_32 |
1100 | free_vcpu: | 1229 | kfree(vcpu->arch.shadow_vcpu); |
1230 | free_vcpu3s: | ||
1231 | #endif | ||
1101 | vfree(vcpu_book3s); | 1232 | vfree(vcpu_book3s); |
1233 | free_vcpu: | ||
1234 | kmem_cache_free(kvm_vcpu_cache, vcpu); | ||
1102 | out: | 1235 | out: |
1103 | return ERR_PTR(err); | 1236 | return ERR_PTR(err); |
1104 | } | 1237 | } |
1105 | 1238 | ||
1106 | void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu) | 1239 | static void kvmppc_core_vcpu_free_pr(struct kvm_vcpu *vcpu) |
1107 | { | 1240 | { |
1108 | struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); | 1241 | struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); |
1109 | 1242 | ||
1110 | free_page((unsigned long)vcpu->arch.shared & PAGE_MASK); | 1243 | free_page((unsigned long)vcpu->arch.shared & PAGE_MASK); |
1111 | kvm_vcpu_uninit(vcpu); | 1244 | kvm_vcpu_uninit(vcpu); |
1112 | kfree(vcpu_book3s->shadow_vcpu); | 1245 | #ifdef CONFIG_KVM_BOOK3S_32 |
1246 | kfree(vcpu->arch.shadow_vcpu); | ||
1247 | #endif | ||
1113 | vfree(vcpu_book3s); | 1248 | vfree(vcpu_book3s); |
1249 | kmem_cache_free(kvm_vcpu_cache, vcpu); | ||
1114 | } | 1250 | } |
1115 | 1251 | ||
1116 | int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) | 1252 | static int kvmppc_vcpu_run_pr(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) |
1117 | { | 1253 | { |
1118 | int ret; | 1254 | int ret; |
1119 | double fpr[32][TS_FPRWIDTH]; | 1255 | struct thread_fp_state fp; |
1120 | unsigned int fpscr; | ||
1121 | int fpexc_mode; | 1256 | int fpexc_mode; |
1122 | #ifdef CONFIG_ALTIVEC | 1257 | #ifdef CONFIG_ALTIVEC |
1123 | vector128 vr[32]; | 1258 | struct thread_vr_state vr; |
1124 | vector128 vscr; | ||
1125 | unsigned long uninitialized_var(vrsave); | 1259 | unsigned long uninitialized_var(vrsave); |
1126 | int used_vr; | 1260 | int used_vr; |
1127 | #endif | 1261 | #endif |
@@ -1153,8 +1287,7 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) | |||
1153 | /* Save FPU state in stack */ | 1287 | /* Save FPU state in stack */ |
1154 | if (current->thread.regs->msr & MSR_FP) | 1288 | if (current->thread.regs->msr & MSR_FP) |
1155 | giveup_fpu(current); | 1289 | giveup_fpu(current); |
1156 | memcpy(fpr, current->thread.fpr, sizeof(current->thread.fpr)); | 1290 | fp = current->thread.fp_state; |
1157 | fpscr = current->thread.fpscr.val; | ||
1158 | fpexc_mode = current->thread.fpexc_mode; | 1291 | fpexc_mode = current->thread.fpexc_mode; |
1159 | 1292 | ||
1160 | #ifdef CONFIG_ALTIVEC | 1293 | #ifdef CONFIG_ALTIVEC |
@@ -1163,8 +1296,7 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) | |||
1163 | if (used_vr) { | 1296 | if (used_vr) { |
1164 | if (current->thread.regs->msr & MSR_VEC) | 1297 | if (current->thread.regs->msr & MSR_VEC) |
1165 | giveup_altivec(current); | 1298 | giveup_altivec(current); |
1166 | memcpy(vr, current->thread.vr, sizeof(current->thread.vr)); | 1299 | vr = current->thread.vr_state; |
1167 | vscr = current->thread.vscr; | ||
1168 | vrsave = current->thread.vrsave; | 1300 | vrsave = current->thread.vrsave; |
1169 | } | 1301 | } |
1170 | #endif | 1302 | #endif |
@@ -1196,15 +1328,13 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) | |||
1196 | current->thread.regs->msr = ext_msr; | 1328 | current->thread.regs->msr = ext_msr; |
1197 | 1329 | ||
1198 | /* Restore FPU/VSX state from stack */ | 1330 | /* Restore FPU/VSX state from stack */ |
1199 | memcpy(current->thread.fpr, fpr, sizeof(current->thread.fpr)); | 1331 | current->thread.fp_state = fp; |
1200 | current->thread.fpscr.val = fpscr; | ||
1201 | current->thread.fpexc_mode = fpexc_mode; | 1332 | current->thread.fpexc_mode = fpexc_mode; |
1202 | 1333 | ||
1203 | #ifdef CONFIG_ALTIVEC | 1334 | #ifdef CONFIG_ALTIVEC |
1204 | /* Restore Altivec state from stack */ | 1335 | /* Restore Altivec state from stack */ |
1205 | if (used_vr && current->thread.used_vr) { | 1336 | if (used_vr && current->thread.used_vr) { |
1206 | memcpy(current->thread.vr, vr, sizeof(current->thread.vr)); | 1337 | current->thread.vr_state = vr; |
1207 | current->thread.vscr = vscr; | ||
1208 | current->thread.vrsave = vrsave; | 1338 | current->thread.vrsave = vrsave; |
1209 | } | 1339 | } |
1210 | current->thread.used_vr = used_vr; | 1340 | current->thread.used_vr = used_vr; |
@@ -1222,8 +1352,8 @@ out: | |||
1222 | /* | 1352 | /* |
1223 | * Get (and clear) the dirty memory log for a memory slot. | 1353 | * Get (and clear) the dirty memory log for a memory slot. |
1224 | */ | 1354 | */ |
1225 | int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, | 1355 | static int kvm_vm_ioctl_get_dirty_log_pr(struct kvm *kvm, |
1226 | struct kvm_dirty_log *log) | 1356 | struct kvm_dirty_log *log) |
1227 | { | 1357 | { |
1228 | struct kvm_memory_slot *memslot; | 1358 | struct kvm_memory_slot *memslot; |
1229 | struct kvm_vcpu *vcpu; | 1359 | struct kvm_vcpu *vcpu; |
@@ -1258,67 +1388,100 @@ out: | |||
1258 | return r; | 1388 | return r; |
1259 | } | 1389 | } |
1260 | 1390 | ||
1261 | #ifdef CONFIG_PPC64 | 1391 | static void kvmppc_core_flush_memslot_pr(struct kvm *kvm, |
1262 | int kvm_vm_ioctl_get_smmu_info(struct kvm *kvm, struct kvm_ppc_smmu_info *info) | 1392 | struct kvm_memory_slot *memslot) |
1263 | { | 1393 | { |
1264 | info->flags = KVM_PPC_1T_SEGMENTS; | 1394 | return; |
1265 | 1395 | } | |
1266 | /* SLB is always 64 entries */ | ||
1267 | info->slb_size = 64; | ||
1268 | |||
1269 | /* Standard 4k base page size segment */ | ||
1270 | info->sps[0].page_shift = 12; | ||
1271 | info->sps[0].slb_enc = 0; | ||
1272 | info->sps[0].enc[0].page_shift = 12; | ||
1273 | info->sps[0].enc[0].pte_enc = 0; | ||
1274 | |||
1275 | /* Standard 16M large page size segment */ | ||
1276 | info->sps[1].page_shift = 24; | ||
1277 | info->sps[1].slb_enc = SLB_VSID_L; | ||
1278 | info->sps[1].enc[0].page_shift = 24; | ||
1279 | info->sps[1].enc[0].pte_enc = 0; | ||
1280 | 1396 | ||
1397 | static int kvmppc_core_prepare_memory_region_pr(struct kvm *kvm, | ||
1398 | struct kvm_memory_slot *memslot, | ||
1399 | struct kvm_userspace_memory_region *mem) | ||
1400 | { | ||
1281 | return 0; | 1401 | return 0; |
1282 | } | 1402 | } |
1283 | #endif /* CONFIG_PPC64 */ | ||
1284 | 1403 | ||
1285 | void kvmppc_core_free_memslot(struct kvm_memory_slot *free, | 1404 | static void kvmppc_core_commit_memory_region_pr(struct kvm *kvm, |
1286 | struct kvm_memory_slot *dont) | 1405 | struct kvm_userspace_memory_region *mem, |
1406 | const struct kvm_memory_slot *old) | ||
1287 | { | 1407 | { |
1408 | return; | ||
1288 | } | 1409 | } |
1289 | 1410 | ||
1290 | int kvmppc_core_create_memslot(struct kvm_memory_slot *slot, | 1411 | static void kvmppc_core_free_memslot_pr(struct kvm_memory_slot *free, |
1291 | unsigned long npages) | 1412 | struct kvm_memory_slot *dont) |
1292 | { | 1413 | { |
1293 | return 0; | 1414 | return; |
1294 | } | 1415 | } |
1295 | 1416 | ||
1296 | int kvmppc_core_prepare_memory_region(struct kvm *kvm, | 1417 | static int kvmppc_core_create_memslot_pr(struct kvm_memory_slot *slot, |
1297 | struct kvm_memory_slot *memslot, | 1418 | unsigned long npages) |
1298 | struct kvm_userspace_memory_region *mem) | ||
1299 | { | 1419 | { |
1300 | return 0; | 1420 | return 0; |
1301 | } | 1421 | } |
1302 | 1422 | ||
1303 | void kvmppc_core_commit_memory_region(struct kvm *kvm, | 1423 | |
1304 | struct kvm_userspace_memory_region *mem, | 1424 | #ifdef CONFIG_PPC64 |
1305 | const struct kvm_memory_slot *old) | 1425 | static int kvm_vm_ioctl_get_smmu_info_pr(struct kvm *kvm, |
1426 | struct kvm_ppc_smmu_info *info) | ||
1306 | { | 1427 | { |
1307 | } | 1428 | long int i; |
1429 | struct kvm_vcpu *vcpu; | ||
1430 | |||
1431 | info->flags = 0; | ||
1432 | |||
1433 | /* SLB is always 64 entries */ | ||
1434 | info->slb_size = 64; | ||
1435 | |||
1436 | /* Standard 4k base page size segment */ | ||
1437 | info->sps[0].page_shift = 12; | ||
1438 | info->sps[0].slb_enc = 0; | ||
1439 | info->sps[0].enc[0].page_shift = 12; | ||
1440 | info->sps[0].enc[0].pte_enc = 0; | ||
1441 | |||
1442 | /* | ||
1443 | * 64k large page size. | ||
1444 | * We only want to put this in if the CPUs we're emulating | ||
1445 | * support it, but unfortunately we don't have a vcpu easily | ||
1446 | * to hand here to test. Just pick the first vcpu, and if | ||
1447 | * that doesn't exist yet, report the minimum capability, | ||
1448 | * i.e., no 64k pages. | ||
1449 | * 1T segment support goes along with 64k pages. | ||
1450 | */ | ||
1451 | i = 1; | ||
1452 | vcpu = kvm_get_vcpu(kvm, 0); | ||
1453 | if (vcpu && (vcpu->arch.hflags & BOOK3S_HFLAG_MULTI_PGSIZE)) { | ||
1454 | info->flags = KVM_PPC_1T_SEGMENTS; | ||
1455 | info->sps[i].page_shift = 16; | ||
1456 | info->sps[i].slb_enc = SLB_VSID_L | SLB_VSID_LP_01; | ||
1457 | info->sps[i].enc[0].page_shift = 16; | ||
1458 | info->sps[i].enc[0].pte_enc = 1; | ||
1459 | ++i; | ||
1460 | } | ||
1461 | |||
1462 | /* Standard 16M large page size segment */ | ||
1463 | info->sps[i].page_shift = 24; | ||
1464 | info->sps[i].slb_enc = SLB_VSID_L; | ||
1465 | info->sps[i].enc[0].page_shift = 24; | ||
1466 | info->sps[i].enc[0].pte_enc = 0; | ||
1308 | 1467 | ||
1309 | void kvmppc_core_flush_memslot(struct kvm *kvm, struct kvm_memory_slot *memslot) | 1468 | return 0; |
1469 | } | ||
1470 | #else | ||
1471 | static int kvm_vm_ioctl_get_smmu_info_pr(struct kvm *kvm, | ||
1472 | struct kvm_ppc_smmu_info *info) | ||
1310 | { | 1473 | { |
1474 | /* We should not get called */ | ||
1475 | BUG(); | ||
1311 | } | 1476 | } |
1477 | #endif /* CONFIG_PPC64 */ | ||
1312 | 1478 | ||
1313 | static unsigned int kvm_global_user_count = 0; | 1479 | static unsigned int kvm_global_user_count = 0; |
1314 | static DEFINE_SPINLOCK(kvm_global_user_count_lock); | 1480 | static DEFINE_SPINLOCK(kvm_global_user_count_lock); |
1315 | 1481 | ||
1316 | int kvmppc_core_init_vm(struct kvm *kvm) | 1482 | static int kvmppc_core_init_vm_pr(struct kvm *kvm) |
1317 | { | 1483 | { |
1318 | #ifdef CONFIG_PPC64 | 1484 | mutex_init(&kvm->arch.hpt_mutex); |
1319 | INIT_LIST_HEAD(&kvm->arch.spapr_tce_tables); | ||
1320 | INIT_LIST_HEAD(&kvm->arch.rtas_tokens); | ||
1321 | #endif | ||
1322 | 1485 | ||
1323 | if (firmware_has_feature(FW_FEATURE_SET_MODE)) { | 1486 | if (firmware_has_feature(FW_FEATURE_SET_MODE)) { |
1324 | spin_lock(&kvm_global_user_count_lock); | 1487 | spin_lock(&kvm_global_user_count_lock); |
@@ -1329,7 +1492,7 @@ int kvmppc_core_init_vm(struct kvm *kvm) | |||
1329 | return 0; | 1492 | return 0; |
1330 | } | 1493 | } |
1331 | 1494 | ||
1332 | void kvmppc_core_destroy_vm(struct kvm *kvm) | 1495 | static void kvmppc_core_destroy_vm_pr(struct kvm *kvm) |
1333 | { | 1496 | { |
1334 | #ifdef CONFIG_PPC64 | 1497 | #ifdef CONFIG_PPC64 |
1335 | WARN_ON(!list_empty(&kvm->arch.spapr_tce_tables)); | 1498 | WARN_ON(!list_empty(&kvm->arch.spapr_tce_tables)); |
@@ -1344,26 +1507,81 @@ void kvmppc_core_destroy_vm(struct kvm *kvm) | |||
1344 | } | 1507 | } |
1345 | } | 1508 | } |
1346 | 1509 | ||
1347 | static int kvmppc_book3s_init(void) | 1510 | static int kvmppc_core_check_processor_compat_pr(void) |
1348 | { | 1511 | { |
1349 | int r; | 1512 | /* we are always compatible */ |
1513 | return 0; | ||
1514 | } | ||
1350 | 1515 | ||
1351 | r = kvm_init(NULL, sizeof(struct kvmppc_vcpu_book3s), 0, | 1516 | static long kvm_arch_vm_ioctl_pr(struct file *filp, |
1352 | THIS_MODULE); | 1517 | unsigned int ioctl, unsigned long arg) |
1518 | { | ||
1519 | return -ENOTTY; | ||
1520 | } | ||
1353 | 1521 | ||
1354 | if (r) | 1522 | static struct kvmppc_ops kvm_ops_pr = { |
1523 | .get_sregs = kvm_arch_vcpu_ioctl_get_sregs_pr, | ||
1524 | .set_sregs = kvm_arch_vcpu_ioctl_set_sregs_pr, | ||
1525 | .get_one_reg = kvmppc_get_one_reg_pr, | ||
1526 | .set_one_reg = kvmppc_set_one_reg_pr, | ||
1527 | .vcpu_load = kvmppc_core_vcpu_load_pr, | ||
1528 | .vcpu_put = kvmppc_core_vcpu_put_pr, | ||
1529 | .set_msr = kvmppc_set_msr_pr, | ||
1530 | .vcpu_run = kvmppc_vcpu_run_pr, | ||
1531 | .vcpu_create = kvmppc_core_vcpu_create_pr, | ||
1532 | .vcpu_free = kvmppc_core_vcpu_free_pr, | ||
1533 | .check_requests = kvmppc_core_check_requests_pr, | ||
1534 | .get_dirty_log = kvm_vm_ioctl_get_dirty_log_pr, | ||
1535 | .flush_memslot = kvmppc_core_flush_memslot_pr, | ||
1536 | .prepare_memory_region = kvmppc_core_prepare_memory_region_pr, | ||
1537 | .commit_memory_region = kvmppc_core_commit_memory_region_pr, | ||
1538 | .unmap_hva = kvm_unmap_hva_pr, | ||
1539 | .unmap_hva_range = kvm_unmap_hva_range_pr, | ||
1540 | .age_hva = kvm_age_hva_pr, | ||
1541 | .test_age_hva = kvm_test_age_hva_pr, | ||
1542 | .set_spte_hva = kvm_set_spte_hva_pr, | ||
1543 | .mmu_destroy = kvmppc_mmu_destroy_pr, | ||
1544 | .free_memslot = kvmppc_core_free_memslot_pr, | ||
1545 | .create_memslot = kvmppc_core_create_memslot_pr, | ||
1546 | .init_vm = kvmppc_core_init_vm_pr, | ||
1547 | .destroy_vm = kvmppc_core_destroy_vm_pr, | ||
1548 | .get_smmu_info = kvm_vm_ioctl_get_smmu_info_pr, | ||
1549 | .emulate_op = kvmppc_core_emulate_op_pr, | ||
1550 | .emulate_mtspr = kvmppc_core_emulate_mtspr_pr, | ||
1551 | .emulate_mfspr = kvmppc_core_emulate_mfspr_pr, | ||
1552 | .fast_vcpu_kick = kvm_vcpu_kick, | ||
1553 | .arch_vm_ioctl = kvm_arch_vm_ioctl_pr, | ||
1554 | }; | ||
1555 | |||
1556 | |||
1557 | int kvmppc_book3s_init_pr(void) | ||
1558 | { | ||
1559 | int r; | ||
1560 | |||
1561 | r = kvmppc_core_check_processor_compat_pr(); | ||
1562 | if (r < 0) | ||
1355 | return r; | 1563 | return r; |
1356 | 1564 | ||
1357 | r = kvmppc_mmu_hpte_sysinit(); | 1565 | kvm_ops_pr.owner = THIS_MODULE; |
1566 | kvmppc_pr_ops = &kvm_ops_pr; | ||
1358 | 1567 | ||
1568 | r = kvmppc_mmu_hpte_sysinit(); | ||
1359 | return r; | 1569 | return r; |
1360 | } | 1570 | } |
1361 | 1571 | ||
1362 | static void kvmppc_book3s_exit(void) | 1572 | void kvmppc_book3s_exit_pr(void) |
1363 | { | 1573 | { |
1574 | kvmppc_pr_ops = NULL; | ||
1364 | kvmppc_mmu_hpte_sysexit(); | 1575 | kvmppc_mmu_hpte_sysexit(); |
1365 | kvm_exit(); | ||
1366 | } | 1576 | } |
1367 | 1577 | ||
1368 | module_init(kvmppc_book3s_init); | 1578 | /* |
1369 | module_exit(kvmppc_book3s_exit); | 1579 | * We only support separate modules for book3s 64 |
1580 | */ | ||
1581 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
1582 | |||
1583 | module_init(kvmppc_book3s_init_pr); | ||
1584 | module_exit(kvmppc_book3s_exit_pr); | ||
1585 | |||
1586 | MODULE_LICENSE("GPL"); | ||
1587 | #endif | ||
diff --git a/arch/powerpc/kvm/book3s_pr_papr.c b/arch/powerpc/kvm/book3s_pr_papr.c index da0e0bc268bd..5efa97b993d8 100644 --- a/arch/powerpc/kvm/book3s_pr_papr.c +++ b/arch/powerpc/kvm/book3s_pr_papr.c | |||
@@ -21,6 +21,8 @@ | |||
21 | #include <asm/kvm_ppc.h> | 21 | #include <asm/kvm_ppc.h> |
22 | #include <asm/kvm_book3s.h> | 22 | #include <asm/kvm_book3s.h> |
23 | 23 | ||
24 | #define HPTE_SIZE 16 /* bytes per HPT entry */ | ||
25 | |||
24 | static unsigned long get_pteg_addr(struct kvm_vcpu *vcpu, long pte_index) | 26 | static unsigned long get_pteg_addr(struct kvm_vcpu *vcpu, long pte_index) |
25 | { | 27 | { |
26 | struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); | 28 | struct kvmppc_vcpu_book3s *vcpu_book3s = to_book3s(vcpu); |
@@ -40,32 +42,41 @@ static int kvmppc_h_pr_enter(struct kvm_vcpu *vcpu) | |||
40 | long pte_index = kvmppc_get_gpr(vcpu, 5); | 42 | long pte_index = kvmppc_get_gpr(vcpu, 5); |
41 | unsigned long pteg[2 * 8]; | 43 | unsigned long pteg[2 * 8]; |
42 | unsigned long pteg_addr, i, *hpte; | 44 | unsigned long pteg_addr, i, *hpte; |
45 | long int ret; | ||
43 | 46 | ||
47 | i = pte_index & 7; | ||
44 | pte_index &= ~7UL; | 48 | pte_index &= ~7UL; |
45 | pteg_addr = get_pteg_addr(vcpu, pte_index); | 49 | pteg_addr = get_pteg_addr(vcpu, pte_index); |
46 | 50 | ||
51 | mutex_lock(&vcpu->kvm->arch.hpt_mutex); | ||
47 | copy_from_user(pteg, (void __user *)pteg_addr, sizeof(pteg)); | 52 | copy_from_user(pteg, (void __user *)pteg_addr, sizeof(pteg)); |
48 | hpte = pteg; | 53 | hpte = pteg; |
49 | 54 | ||
55 | ret = H_PTEG_FULL; | ||
50 | if (likely((flags & H_EXACT) == 0)) { | 56 | if (likely((flags & H_EXACT) == 0)) { |
51 | pte_index &= ~7UL; | ||
52 | for (i = 0; ; ++i) { | 57 | for (i = 0; ; ++i) { |
53 | if (i == 8) | 58 | if (i == 8) |
54 | return H_PTEG_FULL; | 59 | goto done; |
55 | if ((*hpte & HPTE_V_VALID) == 0) | 60 | if ((*hpte & HPTE_V_VALID) == 0) |
56 | break; | 61 | break; |
57 | hpte += 2; | 62 | hpte += 2; |
58 | } | 63 | } |
59 | } else { | 64 | } else { |
60 | i = kvmppc_get_gpr(vcpu, 5) & 7UL; | ||
61 | hpte += i * 2; | 65 | hpte += i * 2; |
66 | if (*hpte & HPTE_V_VALID) | ||
67 | goto done; | ||
62 | } | 68 | } |
63 | 69 | ||
64 | hpte[0] = kvmppc_get_gpr(vcpu, 6); | 70 | hpte[0] = kvmppc_get_gpr(vcpu, 6); |
65 | hpte[1] = kvmppc_get_gpr(vcpu, 7); | 71 | hpte[1] = kvmppc_get_gpr(vcpu, 7); |
66 | copy_to_user((void __user *)pteg_addr, pteg, sizeof(pteg)); | 72 | pteg_addr += i * HPTE_SIZE; |
67 | kvmppc_set_gpr(vcpu, 3, H_SUCCESS); | 73 | copy_to_user((void __user *)pteg_addr, hpte, HPTE_SIZE); |
68 | kvmppc_set_gpr(vcpu, 4, pte_index | i); | 74 | kvmppc_set_gpr(vcpu, 4, pte_index | i); |
75 | ret = H_SUCCESS; | ||
76 | |||
77 | done: | ||
78 | mutex_unlock(&vcpu->kvm->arch.hpt_mutex); | ||
79 | kvmppc_set_gpr(vcpu, 3, ret); | ||
69 | 80 | ||
70 | return EMULATE_DONE; | 81 | return EMULATE_DONE; |
71 | } | 82 | } |
@@ -77,26 +88,31 @@ static int kvmppc_h_pr_remove(struct kvm_vcpu *vcpu) | |||
77 | unsigned long avpn = kvmppc_get_gpr(vcpu, 6); | 88 | unsigned long avpn = kvmppc_get_gpr(vcpu, 6); |
78 | unsigned long v = 0, pteg, rb; | 89 | unsigned long v = 0, pteg, rb; |
79 | unsigned long pte[2]; | 90 | unsigned long pte[2]; |
91 | long int ret; | ||
80 | 92 | ||
81 | pteg = get_pteg_addr(vcpu, pte_index); | 93 | pteg = get_pteg_addr(vcpu, pte_index); |
94 | mutex_lock(&vcpu->kvm->arch.hpt_mutex); | ||
82 | copy_from_user(pte, (void __user *)pteg, sizeof(pte)); | 95 | copy_from_user(pte, (void __user *)pteg, sizeof(pte)); |
83 | 96 | ||
97 | ret = H_NOT_FOUND; | ||
84 | if ((pte[0] & HPTE_V_VALID) == 0 || | 98 | if ((pte[0] & HPTE_V_VALID) == 0 || |
85 | ((flags & H_AVPN) && (pte[0] & ~0x7fUL) != avpn) || | 99 | ((flags & H_AVPN) && (pte[0] & ~0x7fUL) != avpn) || |
86 | ((flags & H_ANDCOND) && (pte[0] & avpn) != 0)) { | 100 | ((flags & H_ANDCOND) && (pte[0] & avpn) != 0)) |
87 | kvmppc_set_gpr(vcpu, 3, H_NOT_FOUND); | 101 | goto done; |
88 | return EMULATE_DONE; | ||
89 | } | ||
90 | 102 | ||
91 | copy_to_user((void __user *)pteg, &v, sizeof(v)); | 103 | copy_to_user((void __user *)pteg, &v, sizeof(v)); |
92 | 104 | ||
93 | rb = compute_tlbie_rb(pte[0], pte[1], pte_index); | 105 | rb = compute_tlbie_rb(pte[0], pte[1], pte_index); |
94 | vcpu->arch.mmu.tlbie(vcpu, rb, rb & 1 ? true : false); | 106 | vcpu->arch.mmu.tlbie(vcpu, rb, rb & 1 ? true : false); |
95 | 107 | ||
96 | kvmppc_set_gpr(vcpu, 3, H_SUCCESS); | 108 | ret = H_SUCCESS; |
97 | kvmppc_set_gpr(vcpu, 4, pte[0]); | 109 | kvmppc_set_gpr(vcpu, 4, pte[0]); |
98 | kvmppc_set_gpr(vcpu, 5, pte[1]); | 110 | kvmppc_set_gpr(vcpu, 5, pte[1]); |
99 | 111 | ||
112 | done: | ||
113 | mutex_unlock(&vcpu->kvm->arch.hpt_mutex); | ||
114 | kvmppc_set_gpr(vcpu, 3, ret); | ||
115 | |||
100 | return EMULATE_DONE; | 116 | return EMULATE_DONE; |
101 | } | 117 | } |
102 | 118 | ||
@@ -124,6 +140,7 @@ static int kvmppc_h_pr_bulk_remove(struct kvm_vcpu *vcpu) | |||
124 | int paramnr = 4; | 140 | int paramnr = 4; |
125 | int ret = H_SUCCESS; | 141 | int ret = H_SUCCESS; |
126 | 142 | ||
143 | mutex_lock(&vcpu->kvm->arch.hpt_mutex); | ||
127 | for (i = 0; i < H_BULK_REMOVE_MAX_BATCH; i++) { | 144 | for (i = 0; i < H_BULK_REMOVE_MAX_BATCH; i++) { |
128 | unsigned long tsh = kvmppc_get_gpr(vcpu, paramnr+(2*i)); | 145 | unsigned long tsh = kvmppc_get_gpr(vcpu, paramnr+(2*i)); |
129 | unsigned long tsl = kvmppc_get_gpr(vcpu, paramnr+(2*i)+1); | 146 | unsigned long tsl = kvmppc_get_gpr(vcpu, paramnr+(2*i)+1); |
@@ -172,6 +189,7 @@ static int kvmppc_h_pr_bulk_remove(struct kvm_vcpu *vcpu) | |||
172 | } | 189 | } |
173 | kvmppc_set_gpr(vcpu, paramnr+(2*i), tsh); | 190 | kvmppc_set_gpr(vcpu, paramnr+(2*i), tsh); |
174 | } | 191 | } |
192 | mutex_unlock(&vcpu->kvm->arch.hpt_mutex); | ||
175 | kvmppc_set_gpr(vcpu, 3, ret); | 193 | kvmppc_set_gpr(vcpu, 3, ret); |
176 | 194 | ||
177 | return EMULATE_DONE; | 195 | return EMULATE_DONE; |
@@ -184,15 +202,16 @@ static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu) | |||
184 | unsigned long avpn = kvmppc_get_gpr(vcpu, 6); | 202 | unsigned long avpn = kvmppc_get_gpr(vcpu, 6); |
185 | unsigned long rb, pteg, r, v; | 203 | unsigned long rb, pteg, r, v; |
186 | unsigned long pte[2]; | 204 | unsigned long pte[2]; |
205 | long int ret; | ||
187 | 206 | ||
188 | pteg = get_pteg_addr(vcpu, pte_index); | 207 | pteg = get_pteg_addr(vcpu, pte_index); |
208 | mutex_lock(&vcpu->kvm->arch.hpt_mutex); | ||
189 | copy_from_user(pte, (void __user *)pteg, sizeof(pte)); | 209 | copy_from_user(pte, (void __user *)pteg, sizeof(pte)); |
190 | 210 | ||
211 | ret = H_NOT_FOUND; | ||
191 | if ((pte[0] & HPTE_V_VALID) == 0 || | 212 | if ((pte[0] & HPTE_V_VALID) == 0 || |
192 | ((flags & H_AVPN) && (pte[0] & ~0x7fUL) != avpn)) { | 213 | ((flags & H_AVPN) && (pte[0] & ~0x7fUL) != avpn)) |
193 | kvmppc_set_gpr(vcpu, 3, H_NOT_FOUND); | 214 | goto done; |
194 | return EMULATE_DONE; | ||
195 | } | ||
196 | 215 | ||
197 | v = pte[0]; | 216 | v = pte[0]; |
198 | r = pte[1]; | 217 | r = pte[1]; |
@@ -207,8 +226,11 @@ static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu) | |||
207 | rb = compute_tlbie_rb(v, r, pte_index); | 226 | rb = compute_tlbie_rb(v, r, pte_index); |
208 | vcpu->arch.mmu.tlbie(vcpu, rb, rb & 1 ? true : false); | 227 | vcpu->arch.mmu.tlbie(vcpu, rb, rb & 1 ? true : false); |
209 | copy_to_user((void __user *)pteg, pte, sizeof(pte)); | 228 | copy_to_user((void __user *)pteg, pte, sizeof(pte)); |
229 | ret = H_SUCCESS; | ||
210 | 230 | ||
211 | kvmppc_set_gpr(vcpu, 3, H_SUCCESS); | 231 | done: |
232 | mutex_unlock(&vcpu->kvm->arch.hpt_mutex); | ||
233 | kvmppc_set_gpr(vcpu, 3, ret); | ||
212 | 234 | ||
213 | return EMULATE_DONE; | 235 | return EMULATE_DONE; |
214 | } | 236 | } |
diff --git a/arch/powerpc/kvm/book3s_rmhandlers.S b/arch/powerpc/kvm/book3s_rmhandlers.S index 8f7633e3afb8..a38c4c9edab8 100644 --- a/arch/powerpc/kvm/book3s_rmhandlers.S +++ b/arch/powerpc/kvm/book3s_rmhandlers.S | |||
@@ -38,32 +38,6 @@ | |||
38 | 38 | ||
39 | #define FUNC(name) GLUE(.,name) | 39 | #define FUNC(name) GLUE(.,name) |
40 | 40 | ||
41 | .globl kvmppc_skip_interrupt | ||
42 | kvmppc_skip_interrupt: | ||
43 | /* | ||
44 | * Here all GPRs are unchanged from when the interrupt happened | ||
45 | * except for r13, which is saved in SPRG_SCRATCH0. | ||
46 | */ | ||
47 | mfspr r13, SPRN_SRR0 | ||
48 | addi r13, r13, 4 | ||
49 | mtspr SPRN_SRR0, r13 | ||
50 | GET_SCRATCH0(r13) | ||
51 | rfid | ||
52 | b . | ||
53 | |||
54 | .globl kvmppc_skip_Hinterrupt | ||
55 | kvmppc_skip_Hinterrupt: | ||
56 | /* | ||
57 | * Here all GPRs are unchanged from when the interrupt happened | ||
58 | * except for r13, which is saved in SPRG_SCRATCH0. | ||
59 | */ | ||
60 | mfspr r13, SPRN_HSRR0 | ||
61 | addi r13, r13, 4 | ||
62 | mtspr SPRN_HSRR0, r13 | ||
63 | GET_SCRATCH0(r13) | ||
64 | hrfid | ||
65 | b . | ||
66 | |||
67 | #elif defined(CONFIG_PPC_BOOK3S_32) | 41 | #elif defined(CONFIG_PPC_BOOK3S_32) |
68 | 42 | ||
69 | #define FUNC(name) name | 43 | #define FUNC(name) name |
@@ -179,11 +153,15 @@ _GLOBAL(kvmppc_entry_trampoline) | |||
179 | 153 | ||
180 | li r6, MSR_IR | MSR_DR | 154 | li r6, MSR_IR | MSR_DR |
181 | andc r6, r5, r6 /* Clear DR and IR in MSR value */ | 155 | andc r6, r5, r6 /* Clear DR and IR in MSR value */ |
156 | #ifdef CONFIG_PPC_BOOK3S_32 | ||
182 | /* | 157 | /* |
183 | * Set EE in HOST_MSR so that it's enabled when we get into our | 158 | * Set EE in HOST_MSR so that it's enabled when we get into our |
184 | * C exit handler function | 159 | * C exit handler function. On 64-bit we delay enabling |
160 | * interrupts until we have finished transferring stuff | ||
161 | * to or from the PACA. | ||
185 | */ | 162 | */ |
186 | ori r5, r5, MSR_EE | 163 | ori r5, r5, MSR_EE |
164 | #endif | ||
187 | mtsrr0 r7 | 165 | mtsrr0 r7 |
188 | mtsrr1 r6 | 166 | mtsrr1 r6 |
189 | RFI | 167 | RFI |
diff --git a/arch/powerpc/kvm/book3s_rtas.c b/arch/powerpc/kvm/book3s_rtas.c index 3219ba895246..cf95cdef73c9 100644 --- a/arch/powerpc/kvm/book3s_rtas.c +++ b/arch/powerpc/kvm/book3s_rtas.c | |||
@@ -260,6 +260,7 @@ fail: | |||
260 | */ | 260 | */ |
261 | return rc; | 261 | return rc; |
262 | } | 262 | } |
263 | EXPORT_SYMBOL_GPL(kvmppc_rtas_hcall); | ||
263 | 264 | ||
264 | void kvmppc_rtas_tokens_free(struct kvm *kvm) | 265 | void kvmppc_rtas_tokens_free(struct kvm *kvm) |
265 | { | 266 | { |
diff --git a/arch/powerpc/kvm/book3s_segment.S b/arch/powerpc/kvm/book3s_segment.S index 1abe4788191a..bc50c97751d3 100644 --- a/arch/powerpc/kvm/book3s_segment.S +++ b/arch/powerpc/kvm/book3s_segment.S | |||
@@ -161,8 +161,8 @@ kvmppc_handler_trampoline_enter_end: | |||
161 | .global kvmppc_handler_trampoline_exit | 161 | .global kvmppc_handler_trampoline_exit |
162 | kvmppc_handler_trampoline_exit: | 162 | kvmppc_handler_trampoline_exit: |
163 | 163 | ||
164 | .global kvmppc_interrupt | 164 | .global kvmppc_interrupt_pr |
165 | kvmppc_interrupt: | 165 | kvmppc_interrupt_pr: |
166 | 166 | ||
167 | /* Register usage at this point: | 167 | /* Register usage at this point: |
168 | * | 168 | * |
diff --git a/arch/powerpc/kvm/book3s_xics.c b/arch/powerpc/kvm/book3s_xics.c index a3a5cb8ee7ea..02a17dcf1610 100644 --- a/arch/powerpc/kvm/book3s_xics.c +++ b/arch/powerpc/kvm/book3s_xics.c | |||
@@ -818,7 +818,7 @@ int kvmppc_xics_hcall(struct kvm_vcpu *vcpu, u32 req) | |||
818 | } | 818 | } |
819 | 819 | ||
820 | /* Check for real mode returning too hard */ | 820 | /* Check for real mode returning too hard */ |
821 | if (xics->real_mode) | 821 | if (xics->real_mode && is_kvmppc_hv_enabled(vcpu->kvm)) |
822 | return kvmppc_xics_rm_complete(vcpu, req); | 822 | return kvmppc_xics_rm_complete(vcpu, req); |
823 | 823 | ||
824 | switch (req) { | 824 | switch (req) { |
@@ -840,6 +840,7 @@ int kvmppc_xics_hcall(struct kvm_vcpu *vcpu, u32 req) | |||
840 | 840 | ||
841 | return rc; | 841 | return rc; |
842 | } | 842 | } |
843 | EXPORT_SYMBOL_GPL(kvmppc_xics_hcall); | ||
843 | 844 | ||
844 | 845 | ||
845 | /* -- Initialisation code etc. -- */ | 846 | /* -- Initialisation code etc. -- */ |
@@ -1250,13 +1251,13 @@ static int kvmppc_xics_create(struct kvm_device *dev, u32 type) | |||
1250 | 1251 | ||
1251 | xics_debugfs_init(xics); | 1252 | xics_debugfs_init(xics); |
1252 | 1253 | ||
1253 | #ifdef CONFIG_KVM_BOOK3S_64_HV | 1254 | #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE |
1254 | if (cpu_has_feature(CPU_FTR_ARCH_206)) { | 1255 | if (cpu_has_feature(CPU_FTR_ARCH_206)) { |
1255 | /* Enable real mode support */ | 1256 | /* Enable real mode support */ |
1256 | xics->real_mode = ENABLE_REALMODE; | 1257 | xics->real_mode = ENABLE_REALMODE; |
1257 | xics->real_mode_dbg = DEBUG_REALMODE; | 1258 | xics->real_mode_dbg = DEBUG_REALMODE; |
1258 | } | 1259 | } |
1259 | #endif /* CONFIG_KVM_BOOK3S_64_HV */ | 1260 | #endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */ |
1260 | 1261 | ||
1261 | return 0; | 1262 | return 0; |
1262 | } | 1263 | } |
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index 17722d82f1d1..53e65a210b9a 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c | |||
@@ -40,7 +40,9 @@ | |||
40 | 40 | ||
41 | #include "timing.h" | 41 | #include "timing.h" |
42 | #include "booke.h" | 42 | #include "booke.h" |
43 | #include "trace.h" | 43 | |
44 | #define CREATE_TRACE_POINTS | ||
45 | #include "trace_booke.h" | ||
44 | 46 | ||
45 | unsigned long kvmppc_booke_handlers; | 47 | unsigned long kvmppc_booke_handlers; |
46 | 48 | ||
@@ -133,6 +135,29 @@ static void kvmppc_vcpu_sync_fpu(struct kvm_vcpu *vcpu) | |||
133 | #endif | 135 | #endif |
134 | } | 136 | } |
135 | 137 | ||
138 | static void kvmppc_vcpu_sync_debug(struct kvm_vcpu *vcpu) | ||
139 | { | ||
140 | /* Synchronize guest's desire to get debug interrupts into shadow MSR */ | ||
141 | #ifndef CONFIG_KVM_BOOKE_HV | ||
142 | vcpu->arch.shadow_msr &= ~MSR_DE; | ||
143 | vcpu->arch.shadow_msr |= vcpu->arch.shared->msr & MSR_DE; | ||
144 | #endif | ||
145 | |||
146 | /* Force enable debug interrupts when user space wants to debug */ | ||
147 | if (vcpu->guest_debug) { | ||
148 | #ifdef CONFIG_KVM_BOOKE_HV | ||
149 | /* | ||
150 | * Since there is no shadow MSR, sync MSR_DE into the guest | ||
151 | * visible MSR. | ||
152 | */ | ||
153 | vcpu->arch.shared->msr |= MSR_DE; | ||
154 | #else | ||
155 | vcpu->arch.shadow_msr |= MSR_DE; | ||
156 | vcpu->arch.shared->msr &= ~MSR_DE; | ||
157 | #endif | ||
158 | } | ||
159 | } | ||
160 | |||
136 | /* | 161 | /* |
137 | * Helper function for "full" MSR writes. No need to call this if only | 162 | * Helper function for "full" MSR writes. No need to call this if only |
138 | * EE/CE/ME/DE/RI are changing. | 163 | * EE/CE/ME/DE/RI are changing. |
@@ -150,6 +175,7 @@ void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr) | |||
150 | kvmppc_mmu_msr_notify(vcpu, old_msr); | 175 | kvmppc_mmu_msr_notify(vcpu, old_msr); |
151 | kvmppc_vcpu_sync_spe(vcpu); | 176 | kvmppc_vcpu_sync_spe(vcpu); |
152 | kvmppc_vcpu_sync_fpu(vcpu); | 177 | kvmppc_vcpu_sync_fpu(vcpu); |
178 | kvmppc_vcpu_sync_debug(vcpu); | ||
153 | } | 179 | } |
154 | 180 | ||
155 | static void kvmppc_booke_queue_irqprio(struct kvm_vcpu *vcpu, | 181 | static void kvmppc_booke_queue_irqprio(struct kvm_vcpu *vcpu, |
@@ -655,10 +681,10 @@ int kvmppc_core_check_requests(struct kvm_vcpu *vcpu) | |||
655 | int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) | 681 | int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) |
656 | { | 682 | { |
657 | int ret, s; | 683 | int ret, s; |
684 | struct thread_struct thread; | ||
658 | #ifdef CONFIG_PPC_FPU | 685 | #ifdef CONFIG_PPC_FPU |
659 | unsigned int fpscr; | 686 | struct thread_fp_state fp; |
660 | int fpexc_mode; | 687 | int fpexc_mode; |
661 | u64 fpr[32]; | ||
662 | #endif | 688 | #endif |
663 | 689 | ||
664 | if (!vcpu->arch.sane) { | 690 | if (!vcpu->arch.sane) { |
@@ -677,13 +703,13 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) | |||
677 | #ifdef CONFIG_PPC_FPU | 703 | #ifdef CONFIG_PPC_FPU |
678 | /* Save userspace FPU state in stack */ | 704 | /* Save userspace FPU state in stack */ |
679 | enable_kernel_fp(); | 705 | enable_kernel_fp(); |
680 | memcpy(fpr, current->thread.fpr, sizeof(current->thread.fpr)); | 706 | fp = current->thread.fp_state; |
681 | fpscr = current->thread.fpscr.val; | ||
682 | fpexc_mode = current->thread.fpexc_mode; | 707 | fpexc_mode = current->thread.fpexc_mode; |
683 | 708 | ||
684 | /* Restore guest FPU state to thread */ | 709 | /* Restore guest FPU state to thread */ |
685 | memcpy(current->thread.fpr, vcpu->arch.fpr, sizeof(vcpu->arch.fpr)); | 710 | memcpy(current->thread.fp_state.fpr, vcpu->arch.fpr, |
686 | current->thread.fpscr.val = vcpu->arch.fpscr; | 711 | sizeof(vcpu->arch.fpr)); |
712 | current->thread.fp_state.fpscr = vcpu->arch.fpscr; | ||
687 | 713 | ||
688 | /* | 714 | /* |
689 | * Since we can't trap on MSR_FP in GS-mode, we consider the guest | 715 | * Since we can't trap on MSR_FP in GS-mode, we consider the guest |
@@ -696,6 +722,12 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) | |||
696 | kvmppc_load_guest_fp(vcpu); | 722 | kvmppc_load_guest_fp(vcpu); |
697 | #endif | 723 | #endif |
698 | 724 | ||
725 | /* Switch to guest debug context */ | ||
726 | thread.debug = vcpu->arch.shadow_dbg_reg; | ||
727 | switch_booke_debug_regs(&thread); | ||
728 | thread.debug = current->thread.debug; | ||
729 | current->thread.debug = vcpu->arch.shadow_dbg_reg; | ||
730 | |||
699 | kvmppc_fix_ee_before_entry(); | 731 | kvmppc_fix_ee_before_entry(); |
700 | 732 | ||
701 | ret = __kvmppc_vcpu_run(kvm_run, vcpu); | 733 | ret = __kvmppc_vcpu_run(kvm_run, vcpu); |
@@ -703,18 +735,22 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) | |||
703 | /* No need for kvm_guest_exit. It's done in handle_exit. | 735 | /* No need for kvm_guest_exit. It's done in handle_exit. |
704 | We also get here with interrupts enabled. */ | 736 | We also get here with interrupts enabled. */ |
705 | 737 | ||
738 | /* Switch back to user space debug context */ | ||
739 | switch_booke_debug_regs(&thread); | ||
740 | current->thread.debug = thread.debug; | ||
741 | |||
706 | #ifdef CONFIG_PPC_FPU | 742 | #ifdef CONFIG_PPC_FPU |
707 | kvmppc_save_guest_fp(vcpu); | 743 | kvmppc_save_guest_fp(vcpu); |
708 | 744 | ||
709 | vcpu->fpu_active = 0; | 745 | vcpu->fpu_active = 0; |
710 | 746 | ||
711 | /* Save guest FPU state from thread */ | 747 | /* Save guest FPU state from thread */ |
712 | memcpy(vcpu->arch.fpr, current->thread.fpr, sizeof(vcpu->arch.fpr)); | 748 | memcpy(vcpu->arch.fpr, current->thread.fp_state.fpr, |
713 | vcpu->arch.fpscr = current->thread.fpscr.val; | 749 | sizeof(vcpu->arch.fpr)); |
750 | vcpu->arch.fpscr = current->thread.fp_state.fpscr; | ||
714 | 751 | ||
715 | /* Restore userspace FPU state from stack */ | 752 | /* Restore userspace FPU state from stack */ |
716 | memcpy(current->thread.fpr, fpr, sizeof(current->thread.fpr)); | 753 | current->thread.fp_state = fp; |
717 | current->thread.fpscr.val = fpscr; | ||
718 | current->thread.fpexc_mode = fpexc_mode; | 754 | current->thread.fpexc_mode = fpexc_mode; |
719 | #endif | 755 | #endif |
720 | 756 | ||
@@ -758,6 +794,30 @@ static int emulation_exit(struct kvm_run *run, struct kvm_vcpu *vcpu) | |||
758 | } | 794 | } |
759 | } | 795 | } |
760 | 796 | ||
797 | static int kvmppc_handle_debug(struct kvm_run *run, struct kvm_vcpu *vcpu) | ||
798 | { | ||
799 | struct debug_reg *dbg_reg = &(vcpu->arch.shadow_dbg_reg); | ||
800 | u32 dbsr = vcpu->arch.dbsr; | ||
801 | |||
802 | run->debug.arch.status = 0; | ||
803 | run->debug.arch.address = vcpu->arch.pc; | ||
804 | |||
805 | if (dbsr & (DBSR_IAC1 | DBSR_IAC2 | DBSR_IAC3 | DBSR_IAC4)) { | ||
806 | run->debug.arch.status |= KVMPPC_DEBUG_BREAKPOINT; | ||
807 | } else { | ||
808 | if (dbsr & (DBSR_DAC1W | DBSR_DAC2W)) | ||
809 | run->debug.arch.status |= KVMPPC_DEBUG_WATCH_WRITE; | ||
810 | else if (dbsr & (DBSR_DAC1R | DBSR_DAC2R)) | ||
811 | run->debug.arch.status |= KVMPPC_DEBUG_WATCH_READ; | ||
812 | if (dbsr & (DBSR_DAC1R | DBSR_DAC1W)) | ||
813 | run->debug.arch.address = dbg_reg->dac1; | ||
814 | else if (dbsr & (DBSR_DAC2R | DBSR_DAC2W)) | ||
815 | run->debug.arch.address = dbg_reg->dac2; | ||
816 | } | ||
817 | |||
818 | return RESUME_HOST; | ||
819 | } | ||
820 | |||
761 | static void kvmppc_fill_pt_regs(struct pt_regs *regs) | 821 | static void kvmppc_fill_pt_regs(struct pt_regs *regs) |
762 | { | 822 | { |
763 | ulong r1, ip, msr, lr; | 823 | ulong r1, ip, msr, lr; |
@@ -818,6 +878,11 @@ static void kvmppc_restart_interrupt(struct kvm_vcpu *vcpu, | |||
818 | case BOOKE_INTERRUPT_CRITICAL: | 878 | case BOOKE_INTERRUPT_CRITICAL: |
819 | unknown_exception(®s); | 879 | unknown_exception(®s); |
820 | break; | 880 | break; |
881 | case BOOKE_INTERRUPT_DEBUG: | ||
882 | /* Save DBSR before preemption is enabled */ | ||
883 | vcpu->arch.dbsr = mfspr(SPRN_DBSR); | ||
884 | kvmppc_clear_dbsr(); | ||
885 | break; | ||
821 | } | 886 | } |
822 | } | 887 | } |
823 | 888 | ||
@@ -1135,18 +1200,10 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
1135 | } | 1200 | } |
1136 | 1201 | ||
1137 | case BOOKE_INTERRUPT_DEBUG: { | 1202 | case BOOKE_INTERRUPT_DEBUG: { |
1138 | u32 dbsr; | 1203 | r = kvmppc_handle_debug(run, vcpu); |
1139 | 1204 | if (r == RESUME_HOST) | |
1140 | vcpu->arch.pc = mfspr(SPRN_CSRR0); | 1205 | run->exit_reason = KVM_EXIT_DEBUG; |
1141 | |||
1142 | /* clear IAC events in DBSR register */ | ||
1143 | dbsr = mfspr(SPRN_DBSR); | ||
1144 | dbsr &= DBSR_IAC1 | DBSR_IAC2 | DBSR_IAC3 | DBSR_IAC4; | ||
1145 | mtspr(SPRN_DBSR, dbsr); | ||
1146 | |||
1147 | run->exit_reason = KVM_EXIT_DEBUG; | ||
1148 | kvmppc_account_exit(vcpu, DEBUG_EXITS); | 1206 | kvmppc_account_exit(vcpu, DEBUG_EXITS); |
1149 | r = RESUME_HOST; | ||
1150 | break; | 1207 | break; |
1151 | } | 1208 | } |
1152 | 1209 | ||
@@ -1197,7 +1254,7 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) | |||
1197 | kvmppc_set_msr(vcpu, 0); | 1254 | kvmppc_set_msr(vcpu, 0); |
1198 | 1255 | ||
1199 | #ifndef CONFIG_KVM_BOOKE_HV | 1256 | #ifndef CONFIG_KVM_BOOKE_HV |
1200 | vcpu->arch.shadow_msr = MSR_USER | MSR_DE | MSR_IS | MSR_DS; | 1257 | vcpu->arch.shadow_msr = MSR_USER | MSR_IS | MSR_DS; |
1201 | vcpu->arch.shadow_pid = 1; | 1258 | vcpu->arch.shadow_pid = 1; |
1202 | vcpu->arch.shared->msr = 0; | 1259 | vcpu->arch.shared->msr = 0; |
1203 | #endif | 1260 | #endif |
@@ -1359,7 +1416,7 @@ static int set_sregs_arch206(struct kvm_vcpu *vcpu, | |||
1359 | return 0; | 1416 | return 0; |
1360 | } | 1417 | } |
1361 | 1418 | ||
1362 | void kvmppc_get_sregs_ivor(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) | 1419 | int kvmppc_get_sregs_ivor(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) |
1363 | { | 1420 | { |
1364 | sregs->u.e.features |= KVM_SREGS_E_IVOR; | 1421 | sregs->u.e.features |= KVM_SREGS_E_IVOR; |
1365 | 1422 | ||
@@ -1379,6 +1436,7 @@ void kvmppc_get_sregs_ivor(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) | |||
1379 | sregs->u.e.ivor_low[13] = vcpu->arch.ivor[BOOKE_IRQPRIO_DTLB_MISS]; | 1436 | sregs->u.e.ivor_low[13] = vcpu->arch.ivor[BOOKE_IRQPRIO_DTLB_MISS]; |
1380 | sregs->u.e.ivor_low[14] = vcpu->arch.ivor[BOOKE_IRQPRIO_ITLB_MISS]; | 1437 | sregs->u.e.ivor_low[14] = vcpu->arch.ivor[BOOKE_IRQPRIO_ITLB_MISS]; |
1381 | sregs->u.e.ivor_low[15] = vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG]; | 1438 | sregs->u.e.ivor_low[15] = vcpu->arch.ivor[BOOKE_IRQPRIO_DEBUG]; |
1439 | return 0; | ||
1382 | } | 1440 | } |
1383 | 1441 | ||
1384 | int kvmppc_set_sregs_ivor(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) | 1442 | int kvmppc_set_sregs_ivor(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) |
@@ -1413,8 +1471,7 @@ int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu, | |||
1413 | 1471 | ||
1414 | get_sregs_base(vcpu, sregs); | 1472 | get_sregs_base(vcpu, sregs); |
1415 | get_sregs_arch206(vcpu, sregs); | 1473 | get_sregs_arch206(vcpu, sregs); |
1416 | kvmppc_core_get_sregs(vcpu, sregs); | 1474 | return vcpu->kvm->arch.kvm_ops->get_sregs(vcpu, sregs); |
1417 | return 0; | ||
1418 | } | 1475 | } |
1419 | 1476 | ||
1420 | int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, | 1477 | int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, |
@@ -1433,7 +1490,7 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, | |||
1433 | if (ret < 0) | 1490 | if (ret < 0) |
1434 | return ret; | 1491 | return ret; |
1435 | 1492 | ||
1436 | return kvmppc_core_set_sregs(vcpu, sregs); | 1493 | return vcpu->kvm->arch.kvm_ops->set_sregs(vcpu, sregs); |
1437 | } | 1494 | } |
1438 | 1495 | ||
1439 | int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) | 1496 | int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) |
@@ -1441,7 +1498,6 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) | |||
1441 | int r = 0; | 1498 | int r = 0; |
1442 | union kvmppc_one_reg val; | 1499 | union kvmppc_one_reg val; |
1443 | int size; | 1500 | int size; |
1444 | long int i; | ||
1445 | 1501 | ||
1446 | size = one_reg_size(reg->id); | 1502 | size = one_reg_size(reg->id); |
1447 | if (size > sizeof(val)) | 1503 | if (size > sizeof(val)) |
@@ -1449,16 +1505,24 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) | |||
1449 | 1505 | ||
1450 | switch (reg->id) { | 1506 | switch (reg->id) { |
1451 | case KVM_REG_PPC_IAC1: | 1507 | case KVM_REG_PPC_IAC1: |
1508 | val = get_reg_val(reg->id, vcpu->arch.dbg_reg.iac1); | ||
1509 | break; | ||
1452 | case KVM_REG_PPC_IAC2: | 1510 | case KVM_REG_PPC_IAC2: |
1511 | val = get_reg_val(reg->id, vcpu->arch.dbg_reg.iac2); | ||
1512 | break; | ||
1513 | #if CONFIG_PPC_ADV_DEBUG_IACS > 2 | ||
1453 | case KVM_REG_PPC_IAC3: | 1514 | case KVM_REG_PPC_IAC3: |
1515 | val = get_reg_val(reg->id, vcpu->arch.dbg_reg.iac3); | ||
1516 | break; | ||
1454 | case KVM_REG_PPC_IAC4: | 1517 | case KVM_REG_PPC_IAC4: |
1455 | i = reg->id - KVM_REG_PPC_IAC1; | 1518 | val = get_reg_val(reg->id, vcpu->arch.dbg_reg.iac4); |
1456 | val = get_reg_val(reg->id, vcpu->arch.dbg_reg.iac[i]); | ||
1457 | break; | 1519 | break; |
1520 | #endif | ||
1458 | case KVM_REG_PPC_DAC1: | 1521 | case KVM_REG_PPC_DAC1: |
1522 | val = get_reg_val(reg->id, vcpu->arch.dbg_reg.dac1); | ||
1523 | break; | ||
1459 | case KVM_REG_PPC_DAC2: | 1524 | case KVM_REG_PPC_DAC2: |
1460 | i = reg->id - KVM_REG_PPC_DAC1; | 1525 | val = get_reg_val(reg->id, vcpu->arch.dbg_reg.dac2); |
1461 | val = get_reg_val(reg->id, vcpu->arch.dbg_reg.dac[i]); | ||
1462 | break; | 1526 | break; |
1463 | case KVM_REG_PPC_EPR: { | 1527 | case KVM_REG_PPC_EPR: { |
1464 | u32 epr = get_guest_epr(vcpu); | 1528 | u32 epr = get_guest_epr(vcpu); |
@@ -1477,10 +1541,13 @@ int kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) | |||
1477 | val = get_reg_val(reg->id, vcpu->arch.tsr); | 1541 | val = get_reg_val(reg->id, vcpu->arch.tsr); |
1478 | break; | 1542 | break; |
1479 | case KVM_REG_PPC_DEBUG_INST: | 1543 | case KVM_REG_PPC_DEBUG_INST: |
1480 | val = get_reg_val(reg->id, KVMPPC_INST_EHPRIV); | 1544 | val = get_reg_val(reg->id, KVMPPC_INST_EHPRIV_DEBUG); |
1545 | break; | ||
1546 | case KVM_REG_PPC_VRSAVE: | ||
1547 | val = get_reg_val(reg->id, vcpu->arch.vrsave); | ||
1481 | break; | 1548 | break; |
1482 | default: | 1549 | default: |
1483 | r = kvmppc_get_one_reg(vcpu, reg->id, &val); | 1550 | r = vcpu->kvm->arch.kvm_ops->get_one_reg(vcpu, reg->id, &val); |
1484 | break; | 1551 | break; |
1485 | } | 1552 | } |
1486 | 1553 | ||
@@ -1498,7 +1565,6 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) | |||
1498 | int r = 0; | 1565 | int r = 0; |
1499 | union kvmppc_one_reg val; | 1566 | union kvmppc_one_reg val; |
1500 | int size; | 1567 | int size; |
1501 | long int i; | ||
1502 | 1568 | ||
1503 | size = one_reg_size(reg->id); | 1569 | size = one_reg_size(reg->id); |
1504 | if (size > sizeof(val)) | 1570 | if (size > sizeof(val)) |
@@ -1509,16 +1575,24 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) | |||
1509 | 1575 | ||
1510 | switch (reg->id) { | 1576 | switch (reg->id) { |
1511 | case KVM_REG_PPC_IAC1: | 1577 | case KVM_REG_PPC_IAC1: |
1578 | vcpu->arch.dbg_reg.iac1 = set_reg_val(reg->id, val); | ||
1579 | break; | ||
1512 | case KVM_REG_PPC_IAC2: | 1580 | case KVM_REG_PPC_IAC2: |
1581 | vcpu->arch.dbg_reg.iac2 = set_reg_val(reg->id, val); | ||
1582 | break; | ||
1583 | #if CONFIG_PPC_ADV_DEBUG_IACS > 2 | ||
1513 | case KVM_REG_PPC_IAC3: | 1584 | case KVM_REG_PPC_IAC3: |
1585 | vcpu->arch.dbg_reg.iac3 = set_reg_val(reg->id, val); | ||
1586 | break; | ||
1514 | case KVM_REG_PPC_IAC4: | 1587 | case KVM_REG_PPC_IAC4: |
1515 | i = reg->id - KVM_REG_PPC_IAC1; | 1588 | vcpu->arch.dbg_reg.iac4 = set_reg_val(reg->id, val); |
1516 | vcpu->arch.dbg_reg.iac[i] = set_reg_val(reg->id, val); | ||
1517 | break; | 1589 | break; |
1590 | #endif | ||
1518 | case KVM_REG_PPC_DAC1: | 1591 | case KVM_REG_PPC_DAC1: |
1592 | vcpu->arch.dbg_reg.dac1 = set_reg_val(reg->id, val); | ||
1593 | break; | ||
1519 | case KVM_REG_PPC_DAC2: | 1594 | case KVM_REG_PPC_DAC2: |
1520 | i = reg->id - KVM_REG_PPC_DAC1; | 1595 | vcpu->arch.dbg_reg.dac2 = set_reg_val(reg->id, val); |
1521 | vcpu->arch.dbg_reg.dac[i] = set_reg_val(reg->id, val); | ||
1522 | break; | 1596 | break; |
1523 | case KVM_REG_PPC_EPR: { | 1597 | case KVM_REG_PPC_EPR: { |
1524 | u32 new_epr = set_reg_val(reg->id, val); | 1598 | u32 new_epr = set_reg_val(reg->id, val); |
@@ -1552,20 +1626,17 @@ int kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg) | |||
1552 | kvmppc_set_tcr(vcpu, tcr); | 1626 | kvmppc_set_tcr(vcpu, tcr); |
1553 | break; | 1627 | break; |
1554 | } | 1628 | } |
1629 | case KVM_REG_PPC_VRSAVE: | ||
1630 | vcpu->arch.vrsave = set_reg_val(reg->id, val); | ||
1631 | break; | ||
1555 | default: | 1632 | default: |
1556 | r = kvmppc_set_one_reg(vcpu, reg->id, &val); | 1633 | r = vcpu->kvm->arch.kvm_ops->set_one_reg(vcpu, reg->id, &val); |
1557 | break; | 1634 | break; |
1558 | } | 1635 | } |
1559 | 1636 | ||
1560 | return r; | 1637 | return r; |
1561 | } | 1638 | } |
1562 | 1639 | ||
1563 | int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, | ||
1564 | struct kvm_guest_debug *dbg) | ||
1565 | { | ||
1566 | return -EINVAL; | ||
1567 | } | ||
1568 | |||
1569 | int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) | 1640 | int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) |
1570 | { | 1641 | { |
1571 | return -ENOTSUPP; | 1642 | return -ENOTSUPP; |
@@ -1590,12 +1661,12 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log) | |||
1590 | return -ENOTSUPP; | 1661 | return -ENOTSUPP; |
1591 | } | 1662 | } |
1592 | 1663 | ||
1593 | void kvmppc_core_free_memslot(struct kvm_memory_slot *free, | 1664 | void kvmppc_core_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free, |
1594 | struct kvm_memory_slot *dont) | 1665 | struct kvm_memory_slot *dont) |
1595 | { | 1666 | { |
1596 | } | 1667 | } |
1597 | 1668 | ||
1598 | int kvmppc_core_create_memslot(struct kvm_memory_slot *slot, | 1669 | int kvmppc_core_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot, |
1599 | unsigned long npages) | 1670 | unsigned long npages) |
1600 | { | 1671 | { |
1601 | return 0; | 1672 | return 0; |
@@ -1671,6 +1742,157 @@ void kvmppc_decrementer_func(unsigned long data) | |||
1671 | kvmppc_set_tsr_bits(vcpu, TSR_DIS); | 1742 | kvmppc_set_tsr_bits(vcpu, TSR_DIS); |
1672 | } | 1743 | } |
1673 | 1744 | ||
1745 | static int kvmppc_booke_add_breakpoint(struct debug_reg *dbg_reg, | ||
1746 | uint64_t addr, int index) | ||
1747 | { | ||
1748 | switch (index) { | ||
1749 | case 0: | ||
1750 | dbg_reg->dbcr0 |= DBCR0_IAC1; | ||
1751 | dbg_reg->iac1 = addr; | ||
1752 | break; | ||
1753 | case 1: | ||
1754 | dbg_reg->dbcr0 |= DBCR0_IAC2; | ||
1755 | dbg_reg->iac2 = addr; | ||
1756 | break; | ||
1757 | #if CONFIG_PPC_ADV_DEBUG_IACS > 2 | ||
1758 | case 2: | ||
1759 | dbg_reg->dbcr0 |= DBCR0_IAC3; | ||
1760 | dbg_reg->iac3 = addr; | ||
1761 | break; | ||
1762 | case 3: | ||
1763 | dbg_reg->dbcr0 |= DBCR0_IAC4; | ||
1764 | dbg_reg->iac4 = addr; | ||
1765 | break; | ||
1766 | #endif | ||
1767 | default: | ||
1768 | return -EINVAL; | ||
1769 | } | ||
1770 | |||
1771 | dbg_reg->dbcr0 |= DBCR0_IDM; | ||
1772 | return 0; | ||
1773 | } | ||
1774 | |||
1775 | static int kvmppc_booke_add_watchpoint(struct debug_reg *dbg_reg, uint64_t addr, | ||
1776 | int type, int index) | ||
1777 | { | ||
1778 | switch (index) { | ||
1779 | case 0: | ||
1780 | if (type & KVMPPC_DEBUG_WATCH_READ) | ||
1781 | dbg_reg->dbcr0 |= DBCR0_DAC1R; | ||
1782 | if (type & KVMPPC_DEBUG_WATCH_WRITE) | ||
1783 | dbg_reg->dbcr0 |= DBCR0_DAC1W; | ||
1784 | dbg_reg->dac1 = addr; | ||
1785 | break; | ||
1786 | case 1: | ||
1787 | if (type & KVMPPC_DEBUG_WATCH_READ) | ||
1788 | dbg_reg->dbcr0 |= DBCR0_DAC2R; | ||
1789 | if (type & KVMPPC_DEBUG_WATCH_WRITE) | ||
1790 | dbg_reg->dbcr0 |= DBCR0_DAC2W; | ||
1791 | dbg_reg->dac2 = addr; | ||
1792 | break; | ||
1793 | default: | ||
1794 | return -EINVAL; | ||
1795 | } | ||
1796 | |||
1797 | dbg_reg->dbcr0 |= DBCR0_IDM; | ||
1798 | return 0; | ||
1799 | } | ||
1800 | void kvm_guest_protect_msr(struct kvm_vcpu *vcpu, ulong prot_bitmap, bool set) | ||
1801 | { | ||
1802 | /* XXX: Add similar MSR protection for BookE-PR */ | ||
1803 | #ifdef CONFIG_KVM_BOOKE_HV | ||
1804 | BUG_ON(prot_bitmap & ~(MSRP_UCLEP | MSRP_DEP | MSRP_PMMP)); | ||
1805 | if (set) { | ||
1806 | if (prot_bitmap & MSR_UCLE) | ||
1807 | vcpu->arch.shadow_msrp |= MSRP_UCLEP; | ||
1808 | if (prot_bitmap & MSR_DE) | ||
1809 | vcpu->arch.shadow_msrp |= MSRP_DEP; | ||
1810 | if (prot_bitmap & MSR_PMM) | ||
1811 | vcpu->arch.shadow_msrp |= MSRP_PMMP; | ||
1812 | } else { | ||
1813 | if (prot_bitmap & MSR_UCLE) | ||
1814 | vcpu->arch.shadow_msrp &= ~MSRP_UCLEP; | ||
1815 | if (prot_bitmap & MSR_DE) | ||
1816 | vcpu->arch.shadow_msrp &= ~MSRP_DEP; | ||
1817 | if (prot_bitmap & MSR_PMM) | ||
1818 | vcpu->arch.shadow_msrp &= ~MSRP_PMMP; | ||
1819 | } | ||
1820 | #endif | ||
1821 | } | ||
1822 | |||
1823 | int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, | ||
1824 | struct kvm_guest_debug *dbg) | ||
1825 | { | ||
1826 | struct debug_reg *dbg_reg; | ||
1827 | int n, b = 0, w = 0; | ||
1828 | |||
1829 | if (!(dbg->control & KVM_GUESTDBG_ENABLE)) { | ||
1830 | vcpu->arch.shadow_dbg_reg.dbcr0 = 0; | ||
1831 | vcpu->guest_debug = 0; | ||
1832 | kvm_guest_protect_msr(vcpu, MSR_DE, false); | ||
1833 | return 0; | ||
1834 | } | ||
1835 | |||
1836 | kvm_guest_protect_msr(vcpu, MSR_DE, true); | ||
1837 | vcpu->guest_debug = dbg->control; | ||
1838 | vcpu->arch.shadow_dbg_reg.dbcr0 = 0; | ||
1839 | /* Set DBCR0_EDM in guest visible DBCR0 register. */ | ||
1840 | vcpu->arch.dbg_reg.dbcr0 = DBCR0_EDM; | ||
1841 | |||
1842 | if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) | ||
1843 | vcpu->arch.shadow_dbg_reg.dbcr0 |= DBCR0_IDM | DBCR0_IC; | ||
1844 | |||
1845 | /* Code below handles only HW breakpoints */ | ||
1846 | dbg_reg = &(vcpu->arch.shadow_dbg_reg); | ||
1847 | |||
1848 | #ifdef CONFIG_KVM_BOOKE_HV | ||
1849 | /* | ||
1850 | * On BookE-HV (e500mc) the guest is always executed with MSR.GS=1 | ||
1851 | * DBCR1 and DBCR2 are set to trigger debug events when MSR.PR is 0 | ||
1852 | */ | ||
1853 | dbg_reg->dbcr1 = 0; | ||
1854 | dbg_reg->dbcr2 = 0; | ||
1855 | #else | ||
1856 | /* | ||
1857 | * On BookE-PR (e500v2) the guest is always executed with MSR.PR=1 | ||
1858 | * We set DBCR1 and DBCR2 to only trigger debug events when MSR.PR | ||
1859 | * is set. | ||
1860 | */ | ||
1861 | dbg_reg->dbcr1 = DBCR1_IAC1US | DBCR1_IAC2US | DBCR1_IAC3US | | ||
1862 | DBCR1_IAC4US; | ||
1863 | dbg_reg->dbcr2 = DBCR2_DAC1US | DBCR2_DAC2US; | ||
1864 | #endif | ||
1865 | |||
1866 | if (!(vcpu->guest_debug & KVM_GUESTDBG_USE_HW_BP)) | ||
1867 | return 0; | ||
1868 | |||
1869 | for (n = 0; n < (KVMPPC_BOOKE_IAC_NUM + KVMPPC_BOOKE_DAC_NUM); n++) { | ||
1870 | uint64_t addr = dbg->arch.bp[n].addr; | ||
1871 | uint32_t type = dbg->arch.bp[n].type; | ||
1872 | |||
1873 | if (type == KVMPPC_DEBUG_NONE) | ||
1874 | continue; | ||
1875 | |||
1876 | if (type & !(KVMPPC_DEBUG_WATCH_READ | | ||
1877 | KVMPPC_DEBUG_WATCH_WRITE | | ||
1878 | KVMPPC_DEBUG_BREAKPOINT)) | ||
1879 | return -EINVAL; | ||
1880 | |||
1881 | if (type & KVMPPC_DEBUG_BREAKPOINT) { | ||
1882 | /* Setting H/W breakpoint */ | ||
1883 | if (kvmppc_booke_add_breakpoint(dbg_reg, addr, b++)) | ||
1884 | return -EINVAL; | ||
1885 | } else { | ||
1886 | /* Setting H/W watchpoint */ | ||
1887 | if (kvmppc_booke_add_watchpoint(dbg_reg, addr, | ||
1888 | type, w++)) | ||
1889 | return -EINVAL; | ||
1890 | } | ||
1891 | } | ||
1892 | |||
1893 | return 0; | ||
1894 | } | ||
1895 | |||
1674 | void kvmppc_booke_vcpu_load(struct kvm_vcpu *vcpu, int cpu) | 1896 | void kvmppc_booke_vcpu_load(struct kvm_vcpu *vcpu, int cpu) |
1675 | { | 1897 | { |
1676 | vcpu->cpu = smp_processor_id(); | 1898 | vcpu->cpu = smp_processor_id(); |
@@ -1681,6 +1903,44 @@ void kvmppc_booke_vcpu_put(struct kvm_vcpu *vcpu) | |||
1681 | { | 1903 | { |
1682 | current->thread.kvm_vcpu = NULL; | 1904 | current->thread.kvm_vcpu = NULL; |
1683 | vcpu->cpu = -1; | 1905 | vcpu->cpu = -1; |
1906 | |||
1907 | /* Clear pending debug event in DBSR */ | ||
1908 | kvmppc_clear_dbsr(); | ||
1909 | } | ||
1910 | |||
1911 | void kvmppc_mmu_destroy(struct kvm_vcpu *vcpu) | ||
1912 | { | ||
1913 | vcpu->kvm->arch.kvm_ops->mmu_destroy(vcpu); | ||
1914 | } | ||
1915 | |||
1916 | int kvmppc_core_init_vm(struct kvm *kvm) | ||
1917 | { | ||
1918 | return kvm->arch.kvm_ops->init_vm(kvm); | ||
1919 | } | ||
1920 | |||
1921 | struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id) | ||
1922 | { | ||
1923 | return kvm->arch.kvm_ops->vcpu_create(kvm, id); | ||
1924 | } | ||
1925 | |||
1926 | void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu) | ||
1927 | { | ||
1928 | vcpu->kvm->arch.kvm_ops->vcpu_free(vcpu); | ||
1929 | } | ||
1930 | |||
1931 | void kvmppc_core_destroy_vm(struct kvm *kvm) | ||
1932 | { | ||
1933 | kvm->arch.kvm_ops->destroy_vm(kvm); | ||
1934 | } | ||
1935 | |||
1936 | void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu) | ||
1937 | { | ||
1938 | vcpu->kvm->arch.kvm_ops->vcpu_load(vcpu, cpu); | ||
1939 | } | ||
1940 | |||
1941 | void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu) | ||
1942 | { | ||
1943 | vcpu->kvm->arch.kvm_ops->vcpu_put(vcpu); | ||
1684 | } | 1944 | } |
1685 | 1945 | ||
1686 | int __init kvmppc_booke_init(void) | 1946 | int __init kvmppc_booke_init(void) |
diff --git a/arch/powerpc/kvm/booke.h b/arch/powerpc/kvm/booke.h index 5fd1ba693579..09bfd9bc7cf8 100644 --- a/arch/powerpc/kvm/booke.h +++ b/arch/powerpc/kvm/booke.h | |||
@@ -99,6 +99,30 @@ enum int_class { | |||
99 | 99 | ||
100 | void kvmppc_set_pending_interrupt(struct kvm_vcpu *vcpu, enum int_class type); | 100 | void kvmppc_set_pending_interrupt(struct kvm_vcpu *vcpu, enum int_class type); |
101 | 101 | ||
102 | extern void kvmppc_mmu_destroy_44x(struct kvm_vcpu *vcpu); | ||
103 | extern int kvmppc_core_emulate_op_44x(struct kvm_run *run, struct kvm_vcpu *vcpu, | ||
104 | unsigned int inst, int *advance); | ||
105 | extern int kvmppc_core_emulate_mtspr_44x(struct kvm_vcpu *vcpu, int sprn, | ||
106 | ulong spr_val); | ||
107 | extern int kvmppc_core_emulate_mfspr_44x(struct kvm_vcpu *vcpu, int sprn, | ||
108 | ulong *spr_val); | ||
109 | extern void kvmppc_mmu_destroy_e500(struct kvm_vcpu *vcpu); | ||
110 | extern int kvmppc_core_emulate_op_e500(struct kvm_run *run, | ||
111 | struct kvm_vcpu *vcpu, | ||
112 | unsigned int inst, int *advance); | ||
113 | extern int kvmppc_core_emulate_mtspr_e500(struct kvm_vcpu *vcpu, int sprn, | ||
114 | ulong spr_val); | ||
115 | extern int kvmppc_core_emulate_mfspr_e500(struct kvm_vcpu *vcpu, int sprn, | ||
116 | ulong *spr_val); | ||
117 | extern void kvmppc_mmu_destroy_e500(struct kvm_vcpu *vcpu); | ||
118 | extern int kvmppc_core_emulate_op_e500(struct kvm_run *run, | ||
119 | struct kvm_vcpu *vcpu, | ||
120 | unsigned int inst, int *advance); | ||
121 | extern int kvmppc_core_emulate_mtspr_e500(struct kvm_vcpu *vcpu, int sprn, | ||
122 | ulong spr_val); | ||
123 | extern int kvmppc_core_emulate_mfspr_e500(struct kvm_vcpu *vcpu, int sprn, | ||
124 | ulong *spr_val); | ||
125 | |||
102 | /* | 126 | /* |
103 | * Load up guest vcpu FP state if it's needed. | 127 | * Load up guest vcpu FP state if it's needed. |
104 | * It also set the MSR_FP in thread so that host know | 128 | * It also set the MSR_FP in thread so that host know |
@@ -129,4 +153,9 @@ static inline void kvmppc_save_guest_fp(struct kvm_vcpu *vcpu) | |||
129 | giveup_fpu(current); | 153 | giveup_fpu(current); |
130 | #endif | 154 | #endif |
131 | } | 155 | } |
156 | |||
157 | static inline void kvmppc_clear_dbsr(void) | ||
158 | { | ||
159 | mtspr(SPRN_DBSR, mfspr(SPRN_DBSR)); | ||
160 | } | ||
132 | #endif /* __KVM_BOOKE_H__ */ | 161 | #endif /* __KVM_BOOKE_H__ */ |
diff --git a/arch/powerpc/kvm/e500.c b/arch/powerpc/kvm/e500.c index ce6b73c29612..497b142f651c 100644 --- a/arch/powerpc/kvm/e500.c +++ b/arch/powerpc/kvm/e500.c | |||
@@ -305,7 +305,7 @@ void kvmppc_core_load_guest_debugstate(struct kvm_vcpu *vcpu) | |||
305 | { | 305 | { |
306 | } | 306 | } |
307 | 307 | ||
308 | void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu) | 308 | static void kvmppc_core_vcpu_load_e500(struct kvm_vcpu *vcpu, int cpu) |
309 | { | 309 | { |
310 | kvmppc_booke_vcpu_load(vcpu, cpu); | 310 | kvmppc_booke_vcpu_load(vcpu, cpu); |
311 | 311 | ||
@@ -313,7 +313,7 @@ void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu) | |||
313 | kvmppc_e500_recalc_shadow_pid(to_e500(vcpu)); | 313 | kvmppc_e500_recalc_shadow_pid(to_e500(vcpu)); |
314 | } | 314 | } |
315 | 315 | ||
316 | void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu) | 316 | static void kvmppc_core_vcpu_put_e500(struct kvm_vcpu *vcpu) |
317 | { | 317 | { |
318 | #ifdef CONFIG_SPE | 318 | #ifdef CONFIG_SPE |
319 | if (vcpu->arch.shadow_msr & MSR_SPE) | 319 | if (vcpu->arch.shadow_msr & MSR_SPE) |
@@ -367,7 +367,8 @@ int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu) | |||
367 | return 0; | 367 | return 0; |
368 | } | 368 | } |
369 | 369 | ||
370 | void kvmppc_core_get_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) | 370 | static int kvmppc_core_get_sregs_e500(struct kvm_vcpu *vcpu, |
371 | struct kvm_sregs *sregs) | ||
371 | { | 372 | { |
372 | struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); | 373 | struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); |
373 | 374 | ||
@@ -388,9 +389,11 @@ void kvmppc_core_get_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) | |||
388 | 389 | ||
389 | kvmppc_get_sregs_ivor(vcpu, sregs); | 390 | kvmppc_get_sregs_ivor(vcpu, sregs); |
390 | kvmppc_get_sregs_e500_tlb(vcpu, sregs); | 391 | kvmppc_get_sregs_e500_tlb(vcpu, sregs); |
392 | return 0; | ||
391 | } | 393 | } |
392 | 394 | ||
393 | int kvmppc_core_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) | 395 | static int kvmppc_core_set_sregs_e500(struct kvm_vcpu *vcpu, |
396 | struct kvm_sregs *sregs) | ||
394 | { | 397 | { |
395 | struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); | 398 | struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); |
396 | int ret; | 399 | int ret; |
@@ -425,21 +428,22 @@ int kvmppc_core_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) | |||
425 | return kvmppc_set_sregs_ivor(vcpu, sregs); | 428 | return kvmppc_set_sregs_ivor(vcpu, sregs); |
426 | } | 429 | } |
427 | 430 | ||
428 | int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id, | 431 | static int kvmppc_get_one_reg_e500(struct kvm_vcpu *vcpu, u64 id, |
429 | union kvmppc_one_reg *val) | 432 | union kvmppc_one_reg *val) |
430 | { | 433 | { |
431 | int r = kvmppc_get_one_reg_e500_tlb(vcpu, id, val); | 434 | int r = kvmppc_get_one_reg_e500_tlb(vcpu, id, val); |
432 | return r; | 435 | return r; |
433 | } | 436 | } |
434 | 437 | ||
435 | int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id, | 438 | static int kvmppc_set_one_reg_e500(struct kvm_vcpu *vcpu, u64 id, |
436 | union kvmppc_one_reg *val) | 439 | union kvmppc_one_reg *val) |
437 | { | 440 | { |
438 | int r = kvmppc_get_one_reg_e500_tlb(vcpu, id, val); | 441 | int r = kvmppc_get_one_reg_e500_tlb(vcpu, id, val); |
439 | return r; | 442 | return r; |
440 | } | 443 | } |
441 | 444 | ||
442 | struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id) | 445 | static struct kvm_vcpu *kvmppc_core_vcpu_create_e500(struct kvm *kvm, |
446 | unsigned int id) | ||
443 | { | 447 | { |
444 | struct kvmppc_vcpu_e500 *vcpu_e500; | 448 | struct kvmppc_vcpu_e500 *vcpu_e500; |
445 | struct kvm_vcpu *vcpu; | 449 | struct kvm_vcpu *vcpu; |
@@ -481,7 +485,7 @@ out: | |||
481 | return ERR_PTR(err); | 485 | return ERR_PTR(err); |
482 | } | 486 | } |
483 | 487 | ||
484 | void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu) | 488 | static void kvmppc_core_vcpu_free_e500(struct kvm_vcpu *vcpu) |
485 | { | 489 | { |
486 | struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); | 490 | struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); |
487 | 491 | ||
@@ -492,15 +496,32 @@ void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu) | |||
492 | kmem_cache_free(kvm_vcpu_cache, vcpu_e500); | 496 | kmem_cache_free(kvm_vcpu_cache, vcpu_e500); |
493 | } | 497 | } |
494 | 498 | ||
495 | int kvmppc_core_init_vm(struct kvm *kvm) | 499 | static int kvmppc_core_init_vm_e500(struct kvm *kvm) |
496 | { | 500 | { |
497 | return 0; | 501 | return 0; |
498 | } | 502 | } |
499 | 503 | ||
500 | void kvmppc_core_destroy_vm(struct kvm *kvm) | 504 | static void kvmppc_core_destroy_vm_e500(struct kvm *kvm) |
501 | { | 505 | { |
502 | } | 506 | } |
503 | 507 | ||
508 | static struct kvmppc_ops kvm_ops_e500 = { | ||
509 | .get_sregs = kvmppc_core_get_sregs_e500, | ||
510 | .set_sregs = kvmppc_core_set_sregs_e500, | ||
511 | .get_one_reg = kvmppc_get_one_reg_e500, | ||
512 | .set_one_reg = kvmppc_set_one_reg_e500, | ||
513 | .vcpu_load = kvmppc_core_vcpu_load_e500, | ||
514 | .vcpu_put = kvmppc_core_vcpu_put_e500, | ||
515 | .vcpu_create = kvmppc_core_vcpu_create_e500, | ||
516 | .vcpu_free = kvmppc_core_vcpu_free_e500, | ||
517 | .mmu_destroy = kvmppc_mmu_destroy_e500, | ||
518 | .init_vm = kvmppc_core_init_vm_e500, | ||
519 | .destroy_vm = kvmppc_core_destroy_vm_e500, | ||
520 | .emulate_op = kvmppc_core_emulate_op_e500, | ||
521 | .emulate_mtspr = kvmppc_core_emulate_mtspr_e500, | ||
522 | .emulate_mfspr = kvmppc_core_emulate_mfspr_e500, | ||
523 | }; | ||
524 | |||
504 | static int __init kvmppc_e500_init(void) | 525 | static int __init kvmppc_e500_init(void) |
505 | { | 526 | { |
506 | int r, i; | 527 | int r, i; |
@@ -512,11 +533,11 @@ static int __init kvmppc_e500_init(void) | |||
512 | 533 | ||
513 | r = kvmppc_core_check_processor_compat(); | 534 | r = kvmppc_core_check_processor_compat(); |
514 | if (r) | 535 | if (r) |
515 | return r; | 536 | goto err_out; |
516 | 537 | ||
517 | r = kvmppc_booke_init(); | 538 | r = kvmppc_booke_init(); |
518 | if (r) | 539 | if (r) |
519 | return r; | 540 | goto err_out; |
520 | 541 | ||
521 | /* copy extra E500 exception handlers */ | 542 | /* copy extra E500 exception handlers */ |
522 | ivor[0] = mfspr(SPRN_IVOR32); | 543 | ivor[0] = mfspr(SPRN_IVOR32); |
@@ -534,11 +555,19 @@ static int __init kvmppc_e500_init(void) | |||
534 | flush_icache_range(kvmppc_booke_handlers, kvmppc_booke_handlers + | 555 | flush_icache_range(kvmppc_booke_handlers, kvmppc_booke_handlers + |
535 | ivor[max_ivor] + handler_len); | 556 | ivor[max_ivor] + handler_len); |
536 | 557 | ||
537 | return kvm_init(NULL, sizeof(struct kvmppc_vcpu_e500), 0, THIS_MODULE); | 558 | r = kvm_init(NULL, sizeof(struct kvmppc_vcpu_e500), 0, THIS_MODULE); |
559 | if (r) | ||
560 | goto err_out; | ||
561 | kvm_ops_e500.owner = THIS_MODULE; | ||
562 | kvmppc_pr_ops = &kvm_ops_e500; | ||
563 | |||
564 | err_out: | ||
565 | return r; | ||
538 | } | 566 | } |
539 | 567 | ||
540 | static void __exit kvmppc_e500_exit(void) | 568 | static void __exit kvmppc_e500_exit(void) |
541 | { | 569 | { |
570 | kvmppc_pr_ops = NULL; | ||
542 | kvmppc_booke_exit(); | 571 | kvmppc_booke_exit(); |
543 | } | 572 | } |
544 | 573 | ||
diff --git a/arch/powerpc/kvm/e500.h b/arch/powerpc/kvm/e500.h index c2e5e98453a6..4fd9650eb018 100644 --- a/arch/powerpc/kvm/e500.h +++ b/arch/powerpc/kvm/e500.h | |||
@@ -117,7 +117,7 @@ static inline struct kvmppc_vcpu_e500 *to_e500(struct kvm_vcpu *vcpu) | |||
117 | #define E500_TLB_USER_PERM_MASK (MAS3_UX|MAS3_UR|MAS3_UW) | 117 | #define E500_TLB_USER_PERM_MASK (MAS3_UX|MAS3_UR|MAS3_UW) |
118 | #define E500_TLB_SUPER_PERM_MASK (MAS3_SX|MAS3_SR|MAS3_SW) | 118 | #define E500_TLB_SUPER_PERM_MASK (MAS3_SX|MAS3_SR|MAS3_SW) |
119 | #define MAS2_ATTRIB_MASK \ | 119 | #define MAS2_ATTRIB_MASK \ |
120 | (MAS2_X0 | MAS2_X1) | 120 | (MAS2_X0 | MAS2_X1 | MAS2_E | MAS2_G) |
121 | #define MAS3_ATTRIB_MASK \ | 121 | #define MAS3_ATTRIB_MASK \ |
122 | (MAS3_U0 | MAS3_U1 | MAS3_U2 | MAS3_U3 \ | 122 | (MAS3_U0 | MAS3_U1 | MAS3_U2 | MAS3_U3 \ |
123 | | E500_TLB_USER_PERM_MASK | E500_TLB_SUPER_PERM_MASK) | 123 | | E500_TLB_USER_PERM_MASK | E500_TLB_SUPER_PERM_MASK) |
diff --git a/arch/powerpc/kvm/e500_emulate.c b/arch/powerpc/kvm/e500_emulate.c index b10a01243abd..89b7f821f6c4 100644 --- a/arch/powerpc/kvm/e500_emulate.c +++ b/arch/powerpc/kvm/e500_emulate.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #define XOP_TLBRE 946 | 26 | #define XOP_TLBRE 946 |
27 | #define XOP_TLBWE 978 | 27 | #define XOP_TLBWE 978 |
28 | #define XOP_TLBILX 18 | 28 | #define XOP_TLBILX 18 |
29 | #define XOP_EHPRIV 270 | ||
29 | 30 | ||
30 | #ifdef CONFIG_KVM_E500MC | 31 | #ifdef CONFIG_KVM_E500MC |
31 | static int dbell2prio(ulong param) | 32 | static int dbell2prio(ulong param) |
@@ -82,8 +83,28 @@ static int kvmppc_e500_emul_msgsnd(struct kvm_vcpu *vcpu, int rb) | |||
82 | } | 83 | } |
83 | #endif | 84 | #endif |
84 | 85 | ||
85 | int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, | 86 | static int kvmppc_e500_emul_ehpriv(struct kvm_run *run, struct kvm_vcpu *vcpu, |
86 | unsigned int inst, int *advance) | 87 | unsigned int inst, int *advance) |
88 | { | ||
89 | int emulated = EMULATE_DONE; | ||
90 | |||
91 | switch (get_oc(inst)) { | ||
92 | case EHPRIV_OC_DEBUG: | ||
93 | run->exit_reason = KVM_EXIT_DEBUG; | ||
94 | run->debug.arch.address = vcpu->arch.pc; | ||
95 | run->debug.arch.status = 0; | ||
96 | kvmppc_account_exit(vcpu, DEBUG_EXITS); | ||
97 | emulated = EMULATE_EXIT_USER; | ||
98 | *advance = 0; | ||
99 | break; | ||
100 | default: | ||
101 | emulated = EMULATE_FAIL; | ||
102 | } | ||
103 | return emulated; | ||
104 | } | ||
105 | |||
106 | int kvmppc_core_emulate_op_e500(struct kvm_run *run, struct kvm_vcpu *vcpu, | ||
107 | unsigned int inst, int *advance) | ||
87 | { | 108 | { |
88 | int emulated = EMULATE_DONE; | 109 | int emulated = EMULATE_DONE; |
89 | int ra = get_ra(inst); | 110 | int ra = get_ra(inst); |
@@ -130,6 +151,11 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
130 | emulated = kvmppc_e500_emul_tlbivax(vcpu, ea); | 151 | emulated = kvmppc_e500_emul_tlbivax(vcpu, ea); |
131 | break; | 152 | break; |
132 | 153 | ||
154 | case XOP_EHPRIV: | ||
155 | emulated = kvmppc_e500_emul_ehpriv(run, vcpu, inst, | ||
156 | advance); | ||
157 | break; | ||
158 | |||
133 | default: | 159 | default: |
134 | emulated = EMULATE_FAIL; | 160 | emulated = EMULATE_FAIL; |
135 | } | 161 | } |
@@ -146,7 +172,7 @@ int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
146 | return emulated; | 172 | return emulated; |
147 | } | 173 | } |
148 | 174 | ||
149 | int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val) | 175 | int kvmppc_core_emulate_mtspr_e500(struct kvm_vcpu *vcpu, int sprn, ulong spr_val) |
150 | { | 176 | { |
151 | struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); | 177 | struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); |
152 | int emulated = EMULATE_DONE; | 178 | int emulated = EMULATE_DONE; |
@@ -237,7 +263,7 @@ int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val) | |||
237 | return emulated; | 263 | return emulated; |
238 | } | 264 | } |
239 | 265 | ||
240 | int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val) | 266 | int kvmppc_core_emulate_mfspr_e500(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val) |
241 | { | 267 | { |
242 | struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); | 268 | struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); |
243 | int emulated = EMULATE_DONE; | 269 | int emulated = EMULATE_DONE; |
diff --git a/arch/powerpc/kvm/e500_mmu.c b/arch/powerpc/kvm/e500_mmu.c index 6d6f153b6c1d..ebca6b88ea5e 100644 --- a/arch/powerpc/kvm/e500_mmu.c +++ b/arch/powerpc/kvm/e500_mmu.c | |||
@@ -32,7 +32,7 @@ | |||
32 | #include <asm/kvm_ppc.h> | 32 | #include <asm/kvm_ppc.h> |
33 | 33 | ||
34 | #include "e500.h" | 34 | #include "e500.h" |
35 | #include "trace.h" | 35 | #include "trace_booke.h" |
36 | #include "timing.h" | 36 | #include "timing.h" |
37 | #include "e500_mmu_host.h" | 37 | #include "e500_mmu_host.h" |
38 | 38 | ||
@@ -536,7 +536,7 @@ gpa_t kvmppc_mmu_xlate(struct kvm_vcpu *vcpu, unsigned int index, | |||
536 | return get_tlb_raddr(gtlbe) | (eaddr & pgmask); | 536 | return get_tlb_raddr(gtlbe) | (eaddr & pgmask); |
537 | } | 537 | } |
538 | 538 | ||
539 | void kvmppc_mmu_destroy(struct kvm_vcpu *vcpu) | 539 | void kvmppc_mmu_destroy_e500(struct kvm_vcpu *vcpu) |
540 | { | 540 | { |
541 | } | 541 | } |
542 | 542 | ||
diff --git a/arch/powerpc/kvm/e500_mmu_host.c b/arch/powerpc/kvm/e500_mmu_host.c index 1c6a9d729df4..ecf2247b13be 100644 --- a/arch/powerpc/kvm/e500_mmu_host.c +++ b/arch/powerpc/kvm/e500_mmu_host.c | |||
@@ -32,10 +32,11 @@ | |||
32 | #include <asm/kvm_ppc.h> | 32 | #include <asm/kvm_ppc.h> |
33 | 33 | ||
34 | #include "e500.h" | 34 | #include "e500.h" |
35 | #include "trace.h" | ||
36 | #include "timing.h" | 35 | #include "timing.h" |
37 | #include "e500_mmu_host.h" | 36 | #include "e500_mmu_host.h" |
38 | 37 | ||
38 | #include "trace_booke.h" | ||
39 | |||
39 | #define to_htlb1_esel(esel) (host_tlb_params[1].entries - (esel) - 1) | 40 | #define to_htlb1_esel(esel) (host_tlb_params[1].entries - (esel) - 1) |
40 | 41 | ||
41 | static struct kvmppc_e500_tlb_params host_tlb_params[E500_TLB_NUM]; | 42 | static struct kvmppc_e500_tlb_params host_tlb_params[E500_TLB_NUM]; |
@@ -253,6 +254,9 @@ static inline void kvmppc_e500_ref_setup(struct tlbe_ref *ref, | |||
253 | ref->pfn = pfn; | 254 | ref->pfn = pfn; |
254 | ref->flags |= E500_TLB_VALID; | 255 | ref->flags |= E500_TLB_VALID; |
255 | 256 | ||
257 | /* Mark the page accessed */ | ||
258 | kvm_set_pfn_accessed(pfn); | ||
259 | |||
256 | if (tlbe_is_writable(gtlbe)) | 260 | if (tlbe_is_writable(gtlbe)) |
257 | kvm_set_pfn_dirty(pfn); | 261 | kvm_set_pfn_dirty(pfn); |
258 | } | 262 | } |
@@ -332,6 +336,13 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, | |||
332 | unsigned long hva; | 336 | unsigned long hva; |
333 | int pfnmap = 0; | 337 | int pfnmap = 0; |
334 | int tsize = BOOK3E_PAGESZ_4K; | 338 | int tsize = BOOK3E_PAGESZ_4K; |
339 | int ret = 0; | ||
340 | unsigned long mmu_seq; | ||
341 | struct kvm *kvm = vcpu_e500->vcpu.kvm; | ||
342 | |||
343 | /* used to check for invalidations in progress */ | ||
344 | mmu_seq = kvm->mmu_notifier_seq; | ||
345 | smp_rmb(); | ||
335 | 346 | ||
336 | /* | 347 | /* |
337 | * Translate guest physical to true physical, acquiring | 348 | * Translate guest physical to true physical, acquiring |
@@ -449,6 +460,12 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, | |||
449 | gvaddr &= ~((tsize_pages << PAGE_SHIFT) - 1); | 460 | gvaddr &= ~((tsize_pages << PAGE_SHIFT) - 1); |
450 | } | 461 | } |
451 | 462 | ||
463 | spin_lock(&kvm->mmu_lock); | ||
464 | if (mmu_notifier_retry(kvm, mmu_seq)) { | ||
465 | ret = -EAGAIN; | ||
466 | goto out; | ||
467 | } | ||
468 | |||
452 | kvmppc_e500_ref_setup(ref, gtlbe, pfn); | 469 | kvmppc_e500_ref_setup(ref, gtlbe, pfn); |
453 | 470 | ||
454 | kvmppc_e500_setup_stlbe(&vcpu_e500->vcpu, gtlbe, tsize, | 471 | kvmppc_e500_setup_stlbe(&vcpu_e500->vcpu, gtlbe, tsize, |
@@ -457,10 +474,13 @@ static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, | |||
457 | /* Clear i-cache for new pages */ | 474 | /* Clear i-cache for new pages */ |
458 | kvmppc_mmu_flush_icache(pfn); | 475 | kvmppc_mmu_flush_icache(pfn); |
459 | 476 | ||
477 | out: | ||
478 | spin_unlock(&kvm->mmu_lock); | ||
479 | |||
460 | /* Drop refcount on page, so that mmu notifiers can clear it */ | 480 | /* Drop refcount on page, so that mmu notifiers can clear it */ |
461 | kvm_release_pfn_clean(pfn); | 481 | kvm_release_pfn_clean(pfn); |
462 | 482 | ||
463 | return 0; | 483 | return ret; |
464 | } | 484 | } |
465 | 485 | ||
466 | /* XXX only map the one-one case, for now use TLB0 */ | 486 | /* XXX only map the one-one case, for now use TLB0 */ |
diff --git a/arch/powerpc/kvm/e500mc.c b/arch/powerpc/kvm/e500mc.c index 19c8379575f7..4132cd2fc171 100644 --- a/arch/powerpc/kvm/e500mc.c +++ b/arch/powerpc/kvm/e500mc.c | |||
@@ -110,7 +110,7 @@ void kvmppc_mmu_msr_notify(struct kvm_vcpu *vcpu, u32 old_msr) | |||
110 | 110 | ||
111 | static DEFINE_PER_CPU(struct kvm_vcpu *, last_vcpu_on_cpu); | 111 | static DEFINE_PER_CPU(struct kvm_vcpu *, last_vcpu_on_cpu); |
112 | 112 | ||
113 | void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu) | 113 | static void kvmppc_core_vcpu_load_e500mc(struct kvm_vcpu *vcpu, int cpu) |
114 | { | 114 | { |
115 | struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); | 115 | struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); |
116 | 116 | ||
@@ -147,7 +147,7 @@ void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu) | |||
147 | kvmppc_load_guest_fp(vcpu); | 147 | kvmppc_load_guest_fp(vcpu); |
148 | } | 148 | } |
149 | 149 | ||
150 | void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu) | 150 | static void kvmppc_core_vcpu_put_e500mc(struct kvm_vcpu *vcpu) |
151 | { | 151 | { |
152 | vcpu->arch.eplc = mfspr(SPRN_EPLC); | 152 | vcpu->arch.eplc = mfspr(SPRN_EPLC); |
153 | vcpu->arch.epsc = mfspr(SPRN_EPSC); | 153 | vcpu->arch.epsc = mfspr(SPRN_EPSC); |
@@ -204,7 +204,8 @@ int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu) | |||
204 | return 0; | 204 | return 0; |
205 | } | 205 | } |
206 | 206 | ||
207 | void kvmppc_core_get_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) | 207 | static int kvmppc_core_get_sregs_e500mc(struct kvm_vcpu *vcpu, |
208 | struct kvm_sregs *sregs) | ||
208 | { | 209 | { |
209 | struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); | 210 | struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); |
210 | 211 | ||
@@ -224,10 +225,11 @@ void kvmppc_core_get_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) | |||
224 | sregs->u.e.ivor_high[4] = vcpu->arch.ivor[BOOKE_IRQPRIO_DBELL]; | 225 | sregs->u.e.ivor_high[4] = vcpu->arch.ivor[BOOKE_IRQPRIO_DBELL]; |
225 | sregs->u.e.ivor_high[5] = vcpu->arch.ivor[BOOKE_IRQPRIO_DBELL_CRIT]; | 226 | sregs->u.e.ivor_high[5] = vcpu->arch.ivor[BOOKE_IRQPRIO_DBELL_CRIT]; |
226 | 227 | ||
227 | kvmppc_get_sregs_ivor(vcpu, sregs); | 228 | return kvmppc_get_sregs_ivor(vcpu, sregs); |
228 | } | 229 | } |
229 | 230 | ||
230 | int kvmppc_core_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) | 231 | static int kvmppc_core_set_sregs_e500mc(struct kvm_vcpu *vcpu, |
232 | struct kvm_sregs *sregs) | ||
231 | { | 233 | { |
232 | struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); | 234 | struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); |
233 | int ret; | 235 | int ret; |
@@ -260,21 +262,22 @@ int kvmppc_core_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs) | |||
260 | return kvmppc_set_sregs_ivor(vcpu, sregs); | 262 | return kvmppc_set_sregs_ivor(vcpu, sregs); |
261 | } | 263 | } |
262 | 264 | ||
263 | int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id, | 265 | static int kvmppc_get_one_reg_e500mc(struct kvm_vcpu *vcpu, u64 id, |
264 | union kvmppc_one_reg *val) | 266 | union kvmppc_one_reg *val) |
265 | { | 267 | { |
266 | int r = kvmppc_get_one_reg_e500_tlb(vcpu, id, val); | 268 | int r = kvmppc_get_one_reg_e500_tlb(vcpu, id, val); |
267 | return r; | 269 | return r; |
268 | } | 270 | } |
269 | 271 | ||
270 | int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id, | 272 | static int kvmppc_set_one_reg_e500mc(struct kvm_vcpu *vcpu, u64 id, |
271 | union kvmppc_one_reg *val) | 273 | union kvmppc_one_reg *val) |
272 | { | 274 | { |
273 | int r = kvmppc_set_one_reg_e500_tlb(vcpu, id, val); | 275 | int r = kvmppc_set_one_reg_e500_tlb(vcpu, id, val); |
274 | return r; | 276 | return r; |
275 | } | 277 | } |
276 | 278 | ||
277 | struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm, unsigned int id) | 279 | static struct kvm_vcpu *kvmppc_core_vcpu_create_e500mc(struct kvm *kvm, |
280 | unsigned int id) | ||
278 | { | 281 | { |
279 | struct kvmppc_vcpu_e500 *vcpu_e500; | 282 | struct kvmppc_vcpu_e500 *vcpu_e500; |
280 | struct kvm_vcpu *vcpu; | 283 | struct kvm_vcpu *vcpu; |
@@ -315,7 +318,7 @@ out: | |||
315 | return ERR_PTR(err); | 318 | return ERR_PTR(err); |
316 | } | 319 | } |
317 | 320 | ||
318 | void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu) | 321 | static void kvmppc_core_vcpu_free_e500mc(struct kvm_vcpu *vcpu) |
319 | { | 322 | { |
320 | struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); | 323 | struct kvmppc_vcpu_e500 *vcpu_e500 = to_e500(vcpu); |
321 | 324 | ||
@@ -325,7 +328,7 @@ void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu) | |||
325 | kmem_cache_free(kvm_vcpu_cache, vcpu_e500); | 328 | kmem_cache_free(kvm_vcpu_cache, vcpu_e500); |
326 | } | 329 | } |
327 | 330 | ||
328 | int kvmppc_core_init_vm(struct kvm *kvm) | 331 | static int kvmppc_core_init_vm_e500mc(struct kvm *kvm) |
329 | { | 332 | { |
330 | int lpid; | 333 | int lpid; |
331 | 334 | ||
@@ -337,27 +340,52 @@ int kvmppc_core_init_vm(struct kvm *kvm) | |||
337 | return 0; | 340 | return 0; |
338 | } | 341 | } |
339 | 342 | ||
340 | void kvmppc_core_destroy_vm(struct kvm *kvm) | 343 | static void kvmppc_core_destroy_vm_e500mc(struct kvm *kvm) |
341 | { | 344 | { |
342 | kvmppc_free_lpid(kvm->arch.lpid); | 345 | kvmppc_free_lpid(kvm->arch.lpid); |
343 | } | 346 | } |
344 | 347 | ||
348 | static struct kvmppc_ops kvm_ops_e500mc = { | ||
349 | .get_sregs = kvmppc_core_get_sregs_e500mc, | ||
350 | .set_sregs = kvmppc_core_set_sregs_e500mc, | ||
351 | .get_one_reg = kvmppc_get_one_reg_e500mc, | ||
352 | .set_one_reg = kvmppc_set_one_reg_e500mc, | ||
353 | .vcpu_load = kvmppc_core_vcpu_load_e500mc, | ||
354 | .vcpu_put = kvmppc_core_vcpu_put_e500mc, | ||
355 | .vcpu_create = kvmppc_core_vcpu_create_e500mc, | ||
356 | .vcpu_free = kvmppc_core_vcpu_free_e500mc, | ||
357 | .mmu_destroy = kvmppc_mmu_destroy_e500, | ||
358 | .init_vm = kvmppc_core_init_vm_e500mc, | ||
359 | .destroy_vm = kvmppc_core_destroy_vm_e500mc, | ||
360 | .emulate_op = kvmppc_core_emulate_op_e500, | ||
361 | .emulate_mtspr = kvmppc_core_emulate_mtspr_e500, | ||
362 | .emulate_mfspr = kvmppc_core_emulate_mfspr_e500, | ||
363 | }; | ||
364 | |||
345 | static int __init kvmppc_e500mc_init(void) | 365 | static int __init kvmppc_e500mc_init(void) |
346 | { | 366 | { |
347 | int r; | 367 | int r; |
348 | 368 | ||
349 | r = kvmppc_booke_init(); | 369 | r = kvmppc_booke_init(); |
350 | if (r) | 370 | if (r) |
351 | return r; | 371 | goto err_out; |
352 | 372 | ||
353 | kvmppc_init_lpid(64); | 373 | kvmppc_init_lpid(64); |
354 | kvmppc_claim_lpid(0); /* host */ | 374 | kvmppc_claim_lpid(0); /* host */ |
355 | 375 | ||
356 | return kvm_init(NULL, sizeof(struct kvmppc_vcpu_e500), 0, THIS_MODULE); | 376 | r = kvm_init(NULL, sizeof(struct kvmppc_vcpu_e500), 0, THIS_MODULE); |
377 | if (r) | ||
378 | goto err_out; | ||
379 | kvm_ops_e500mc.owner = THIS_MODULE; | ||
380 | kvmppc_pr_ops = &kvm_ops_e500mc; | ||
381 | |||
382 | err_out: | ||
383 | return r; | ||
357 | } | 384 | } |
358 | 385 | ||
359 | static void __exit kvmppc_e500mc_exit(void) | 386 | static void __exit kvmppc_e500mc_exit(void) |
360 | { | 387 | { |
388 | kvmppc_pr_ops = NULL; | ||
361 | kvmppc_booke_exit(); | 389 | kvmppc_booke_exit(); |
362 | } | 390 | } |
363 | 391 | ||
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c index 751cd45f65a0..2f9a0873b44f 100644 --- a/arch/powerpc/kvm/emulate.c +++ b/arch/powerpc/kvm/emulate.c | |||
@@ -130,8 +130,8 @@ static int kvmppc_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs) | |||
130 | case SPRN_PIR: break; | 130 | case SPRN_PIR: break; |
131 | 131 | ||
132 | default: | 132 | default: |
133 | emulated = kvmppc_core_emulate_mtspr(vcpu, sprn, | 133 | emulated = vcpu->kvm->arch.kvm_ops->emulate_mtspr(vcpu, sprn, |
134 | spr_val); | 134 | spr_val); |
135 | if (emulated == EMULATE_FAIL) | 135 | if (emulated == EMULATE_FAIL) |
136 | printk(KERN_INFO "mtspr: unknown spr " | 136 | printk(KERN_INFO "mtspr: unknown spr " |
137 | "0x%x\n", sprn); | 137 | "0x%x\n", sprn); |
@@ -191,8 +191,8 @@ static int kvmppc_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt) | |||
191 | spr_val = kvmppc_get_dec(vcpu, get_tb()); | 191 | spr_val = kvmppc_get_dec(vcpu, get_tb()); |
192 | break; | 192 | break; |
193 | default: | 193 | default: |
194 | emulated = kvmppc_core_emulate_mfspr(vcpu, sprn, | 194 | emulated = vcpu->kvm->arch.kvm_ops->emulate_mfspr(vcpu, sprn, |
195 | &spr_val); | 195 | &spr_val); |
196 | if (unlikely(emulated == EMULATE_FAIL)) { | 196 | if (unlikely(emulated == EMULATE_FAIL)) { |
197 | printk(KERN_INFO "mfspr: unknown spr " | 197 | printk(KERN_INFO "mfspr: unknown spr " |
198 | "0x%x\n", sprn); | 198 | "0x%x\n", sprn); |
@@ -464,7 +464,8 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) | |||
464 | } | 464 | } |
465 | 465 | ||
466 | if (emulated == EMULATE_FAIL) { | 466 | if (emulated == EMULATE_FAIL) { |
467 | emulated = kvmppc_core_emulate_op(run, vcpu, inst, &advance); | 467 | emulated = vcpu->kvm->arch.kvm_ops->emulate_op(run, vcpu, inst, |
468 | &advance); | ||
468 | if (emulated == EMULATE_AGAIN) { | 469 | if (emulated == EMULATE_AGAIN) { |
469 | advance = 0; | 470 | advance = 0; |
470 | } else if (emulated == EMULATE_FAIL) { | 471 | } else if (emulated == EMULATE_FAIL) { |
@@ -483,3 +484,4 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) | |||
483 | 484 | ||
484 | return emulated; | 485 | return emulated; |
485 | } | 486 | } |
487 | EXPORT_SYMBOL_GPL(kvmppc_emulate_instruction); | ||
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c index 07c0106fab76..9ae97686e9f4 100644 --- a/arch/powerpc/kvm/powerpc.c +++ b/arch/powerpc/kvm/powerpc.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/fs.h> | 26 | #include <linux/fs.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/file.h> | 28 | #include <linux/file.h> |
29 | #include <linux/module.h> | ||
29 | #include <asm/cputable.h> | 30 | #include <asm/cputable.h> |
30 | #include <asm/uaccess.h> | 31 | #include <asm/uaccess.h> |
31 | #include <asm/kvm_ppc.h> | 32 | #include <asm/kvm_ppc.h> |
@@ -39,6 +40,12 @@ | |||
39 | #define CREATE_TRACE_POINTS | 40 | #define CREATE_TRACE_POINTS |
40 | #include "trace.h" | 41 | #include "trace.h" |
41 | 42 | ||
43 | struct kvmppc_ops *kvmppc_hv_ops; | ||
44 | EXPORT_SYMBOL_GPL(kvmppc_hv_ops); | ||
45 | struct kvmppc_ops *kvmppc_pr_ops; | ||
46 | EXPORT_SYMBOL_GPL(kvmppc_pr_ops); | ||
47 | |||
48 | |||
42 | int kvm_arch_vcpu_runnable(struct kvm_vcpu *v) | 49 | int kvm_arch_vcpu_runnable(struct kvm_vcpu *v) |
43 | { | 50 | { |
44 | return !!(v->arch.pending_exceptions) || | 51 | return !!(v->arch.pending_exceptions) || |
@@ -50,7 +57,6 @@ int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu) | |||
50 | return 1; | 57 | return 1; |
51 | } | 58 | } |
52 | 59 | ||
53 | #ifndef CONFIG_KVM_BOOK3S_64_HV | ||
54 | /* | 60 | /* |
55 | * Common checks before entering the guest world. Call with interrupts | 61 | * Common checks before entering the guest world. Call with interrupts |
56 | * disabled. | 62 | * disabled. |
@@ -125,7 +131,7 @@ int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu) | |||
125 | 131 | ||
126 | return r; | 132 | return r; |
127 | } | 133 | } |
128 | #endif /* CONFIG_KVM_BOOK3S_64_HV */ | 134 | EXPORT_SYMBOL_GPL(kvmppc_prepare_to_enter); |
129 | 135 | ||
130 | int kvmppc_kvm_pv(struct kvm_vcpu *vcpu) | 136 | int kvmppc_kvm_pv(struct kvm_vcpu *vcpu) |
131 | { | 137 | { |
@@ -179,6 +185,7 @@ int kvmppc_kvm_pv(struct kvm_vcpu *vcpu) | |||
179 | 185 | ||
180 | return r; | 186 | return r; |
181 | } | 187 | } |
188 | EXPORT_SYMBOL_GPL(kvmppc_kvm_pv); | ||
182 | 189 | ||
183 | int kvmppc_sanity_check(struct kvm_vcpu *vcpu) | 190 | int kvmppc_sanity_check(struct kvm_vcpu *vcpu) |
184 | { | 191 | { |
@@ -192,11 +199,9 @@ int kvmppc_sanity_check(struct kvm_vcpu *vcpu) | |||
192 | if ((vcpu->arch.cpu_type != KVM_CPU_3S_64) && vcpu->arch.papr_enabled) | 199 | if ((vcpu->arch.cpu_type != KVM_CPU_3S_64) && vcpu->arch.papr_enabled) |
193 | goto out; | 200 | goto out; |
194 | 201 | ||
195 | #ifdef CONFIG_KVM_BOOK3S_64_HV | ||
196 | /* HV KVM can only do PAPR mode for now */ | 202 | /* HV KVM can only do PAPR mode for now */ |
197 | if (!vcpu->arch.papr_enabled) | 203 | if (!vcpu->arch.papr_enabled && is_kvmppc_hv_enabled(vcpu->kvm)) |
198 | goto out; | 204 | goto out; |
199 | #endif | ||
200 | 205 | ||
201 | #ifdef CONFIG_KVM_BOOKE_HV | 206 | #ifdef CONFIG_KVM_BOOKE_HV |
202 | if (!cpu_has_feature(CPU_FTR_EMB_HV)) | 207 | if (!cpu_has_feature(CPU_FTR_EMB_HV)) |
@@ -209,6 +214,7 @@ out: | |||
209 | vcpu->arch.sane = r; | 214 | vcpu->arch.sane = r; |
210 | return r ? 0 : -EINVAL; | 215 | return r ? 0 : -EINVAL; |
211 | } | 216 | } |
217 | EXPORT_SYMBOL_GPL(kvmppc_sanity_check); | ||
212 | 218 | ||
213 | int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu) | 219 | int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu) |
214 | { | 220 | { |
@@ -243,6 +249,7 @@ int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu) | |||
243 | 249 | ||
244 | return r; | 250 | return r; |
245 | } | 251 | } |
252 | EXPORT_SYMBOL_GPL(kvmppc_emulate_mmio); | ||
246 | 253 | ||
247 | int kvm_arch_hardware_enable(void *garbage) | 254 | int kvm_arch_hardware_enable(void *garbage) |
248 | { | 255 | { |
@@ -269,10 +276,35 @@ void kvm_arch_check_processor_compat(void *rtn) | |||
269 | 276 | ||
270 | int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) | 277 | int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) |
271 | { | 278 | { |
272 | if (type) | 279 | struct kvmppc_ops *kvm_ops = NULL; |
273 | return -EINVAL; | 280 | /* |
274 | 281 | * if we have both HV and PR enabled, default is HV | |
282 | */ | ||
283 | if (type == 0) { | ||
284 | if (kvmppc_hv_ops) | ||
285 | kvm_ops = kvmppc_hv_ops; | ||
286 | else | ||
287 | kvm_ops = kvmppc_pr_ops; | ||
288 | if (!kvm_ops) | ||
289 | goto err_out; | ||
290 | } else if (type == KVM_VM_PPC_HV) { | ||
291 | if (!kvmppc_hv_ops) | ||
292 | goto err_out; | ||
293 | kvm_ops = kvmppc_hv_ops; | ||
294 | } else if (type == KVM_VM_PPC_PR) { | ||
295 | if (!kvmppc_pr_ops) | ||
296 | goto err_out; | ||
297 | kvm_ops = kvmppc_pr_ops; | ||
298 | } else | ||
299 | goto err_out; | ||
300 | |||
301 | if (kvm_ops->owner && !try_module_get(kvm_ops->owner)) | ||
302 | return -ENOENT; | ||
303 | |||
304 | kvm->arch.kvm_ops = kvm_ops; | ||
275 | return kvmppc_core_init_vm(kvm); | 305 | return kvmppc_core_init_vm(kvm); |
306 | err_out: | ||
307 | return -EINVAL; | ||
276 | } | 308 | } |
277 | 309 | ||
278 | void kvm_arch_destroy_vm(struct kvm *kvm) | 310 | void kvm_arch_destroy_vm(struct kvm *kvm) |
@@ -292,6 +324,9 @@ void kvm_arch_destroy_vm(struct kvm *kvm) | |||
292 | kvmppc_core_destroy_vm(kvm); | 324 | kvmppc_core_destroy_vm(kvm); |
293 | 325 | ||
294 | mutex_unlock(&kvm->lock); | 326 | mutex_unlock(&kvm->lock); |
327 | |||
328 | /* drop the module reference */ | ||
329 | module_put(kvm->arch.kvm_ops->owner); | ||
295 | } | 330 | } |
296 | 331 | ||
297 | void kvm_arch_sync_events(struct kvm *kvm) | 332 | void kvm_arch_sync_events(struct kvm *kvm) |
@@ -301,6 +336,10 @@ void kvm_arch_sync_events(struct kvm *kvm) | |||
301 | int kvm_dev_ioctl_check_extension(long ext) | 336 | int kvm_dev_ioctl_check_extension(long ext) |
302 | { | 337 | { |
303 | int r; | 338 | int r; |
339 | /* FIXME!! | ||
340 | * Should some of this be vm ioctl ? is it possible now ? | ||
341 | */ | ||
342 | int hv_enabled = kvmppc_hv_ops ? 1 : 0; | ||
304 | 343 | ||
305 | switch (ext) { | 344 | switch (ext) { |
306 | #ifdef CONFIG_BOOKE | 345 | #ifdef CONFIG_BOOKE |
@@ -320,22 +359,26 @@ int kvm_dev_ioctl_check_extension(long ext) | |||
320 | case KVM_CAP_DEVICE_CTRL: | 359 | case KVM_CAP_DEVICE_CTRL: |
321 | r = 1; | 360 | r = 1; |
322 | break; | 361 | break; |
323 | #ifndef CONFIG_KVM_BOOK3S_64_HV | ||
324 | case KVM_CAP_PPC_PAIRED_SINGLES: | 362 | case KVM_CAP_PPC_PAIRED_SINGLES: |
325 | case KVM_CAP_PPC_OSI: | 363 | case KVM_CAP_PPC_OSI: |
326 | case KVM_CAP_PPC_GET_PVINFO: | 364 | case KVM_CAP_PPC_GET_PVINFO: |
327 | #if defined(CONFIG_KVM_E500V2) || defined(CONFIG_KVM_E500MC) | 365 | #if defined(CONFIG_KVM_E500V2) || defined(CONFIG_KVM_E500MC) |
328 | case KVM_CAP_SW_TLB: | 366 | case KVM_CAP_SW_TLB: |
329 | #endif | 367 | #endif |
330 | #ifdef CONFIG_KVM_MPIC | 368 | /* We support this only for PR */ |
331 | case KVM_CAP_IRQ_MPIC: | 369 | r = !hv_enabled; |
332 | #endif | ||
333 | r = 1; | ||
334 | break; | 370 | break; |
371 | #ifdef CONFIG_KVM_MMIO | ||
335 | case KVM_CAP_COALESCED_MMIO: | 372 | case KVM_CAP_COALESCED_MMIO: |
336 | r = KVM_COALESCED_MMIO_PAGE_OFFSET; | 373 | r = KVM_COALESCED_MMIO_PAGE_OFFSET; |
337 | break; | 374 | break; |
338 | #endif | 375 | #endif |
376 | #ifdef CONFIG_KVM_MPIC | ||
377 | case KVM_CAP_IRQ_MPIC: | ||
378 | r = 1; | ||
379 | break; | ||
380 | #endif | ||
381 | |||
339 | #ifdef CONFIG_PPC_BOOK3S_64 | 382 | #ifdef CONFIG_PPC_BOOK3S_64 |
340 | case KVM_CAP_SPAPR_TCE: | 383 | case KVM_CAP_SPAPR_TCE: |
341 | case KVM_CAP_PPC_ALLOC_HTAB: | 384 | case KVM_CAP_PPC_ALLOC_HTAB: |
@@ -346,32 +389,37 @@ int kvm_dev_ioctl_check_extension(long ext) | |||
346 | r = 1; | 389 | r = 1; |
347 | break; | 390 | break; |
348 | #endif /* CONFIG_PPC_BOOK3S_64 */ | 391 | #endif /* CONFIG_PPC_BOOK3S_64 */ |
349 | #ifdef CONFIG_KVM_BOOK3S_64_HV | 392 | #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE |
350 | case KVM_CAP_PPC_SMT: | 393 | case KVM_CAP_PPC_SMT: |
351 | r = threads_per_core; | 394 | if (hv_enabled) |
395 | r = threads_per_core; | ||
396 | else | ||
397 | r = 0; | ||
352 | break; | 398 | break; |
353 | case KVM_CAP_PPC_RMA: | 399 | case KVM_CAP_PPC_RMA: |
354 | r = 1; | 400 | r = hv_enabled; |
355 | /* PPC970 requires an RMA */ | 401 | /* PPC970 requires an RMA */ |
356 | if (cpu_has_feature(CPU_FTR_ARCH_201)) | 402 | if (r && cpu_has_feature(CPU_FTR_ARCH_201)) |
357 | r = 2; | 403 | r = 2; |
358 | break; | 404 | break; |
359 | #endif | 405 | #endif |
360 | case KVM_CAP_SYNC_MMU: | 406 | case KVM_CAP_SYNC_MMU: |
361 | #ifdef CONFIG_KVM_BOOK3S_64_HV | 407 | #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE |
362 | r = cpu_has_feature(CPU_FTR_ARCH_206) ? 1 : 0; | 408 | if (hv_enabled) |
409 | r = cpu_has_feature(CPU_FTR_ARCH_206) ? 1 : 0; | ||
410 | else | ||
411 | r = 0; | ||
363 | #elif defined(KVM_ARCH_WANT_MMU_NOTIFIER) | 412 | #elif defined(KVM_ARCH_WANT_MMU_NOTIFIER) |
364 | r = 1; | 413 | r = 1; |
365 | #else | 414 | #else |
366 | r = 0; | 415 | r = 0; |
367 | break; | ||
368 | #endif | 416 | #endif |
369 | #ifdef CONFIG_KVM_BOOK3S_64_HV | 417 | break; |
418 | #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE | ||
370 | case KVM_CAP_PPC_HTAB_FD: | 419 | case KVM_CAP_PPC_HTAB_FD: |
371 | r = 1; | 420 | r = hv_enabled; |
372 | break; | 421 | break; |
373 | #endif | 422 | #endif |
374 | break; | ||
375 | case KVM_CAP_NR_VCPUS: | 423 | case KVM_CAP_NR_VCPUS: |
376 | /* | 424 | /* |
377 | * Recommending a number of CPUs is somewhat arbitrary; we | 425 | * Recommending a number of CPUs is somewhat arbitrary; we |
@@ -379,11 +427,10 @@ int kvm_dev_ioctl_check_extension(long ext) | |||
379 | * will have secondary threads "offline"), and for other KVM | 427 | * will have secondary threads "offline"), and for other KVM |
380 | * implementations just count online CPUs. | 428 | * implementations just count online CPUs. |
381 | */ | 429 | */ |
382 | #ifdef CONFIG_KVM_BOOK3S_64_HV | 430 | if (hv_enabled) |
383 | r = num_present_cpus(); | 431 | r = num_present_cpus(); |
384 | #else | 432 | else |
385 | r = num_online_cpus(); | 433 | r = num_online_cpus(); |
386 | #endif | ||
387 | break; | 434 | break; |
388 | case KVM_CAP_MAX_VCPUS: | 435 | case KVM_CAP_MAX_VCPUS: |
389 | r = KVM_MAX_VCPUS; | 436 | r = KVM_MAX_VCPUS; |
@@ -407,15 +454,16 @@ long kvm_arch_dev_ioctl(struct file *filp, | |||
407 | return -EINVAL; | 454 | return -EINVAL; |
408 | } | 455 | } |
409 | 456 | ||
410 | void kvm_arch_free_memslot(struct kvm_memory_slot *free, | 457 | void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free, |
411 | struct kvm_memory_slot *dont) | 458 | struct kvm_memory_slot *dont) |
412 | { | 459 | { |
413 | kvmppc_core_free_memslot(free, dont); | 460 | kvmppc_core_free_memslot(kvm, free, dont); |
414 | } | 461 | } |
415 | 462 | ||
416 | int kvm_arch_create_memslot(struct kvm_memory_slot *slot, unsigned long npages) | 463 | int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot, |
464 | unsigned long npages) | ||
417 | { | 465 | { |
418 | return kvmppc_core_create_memslot(slot, npages); | 466 | return kvmppc_core_create_memslot(kvm, slot, npages); |
419 | } | 467 | } |
420 | 468 | ||
421 | void kvm_arch_memslots_updated(struct kvm *kvm) | 469 | void kvm_arch_memslots_updated(struct kvm *kvm) |
@@ -659,6 +707,7 @@ int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
659 | 707 | ||
660 | return EMULATE_DO_MMIO; | 708 | return EMULATE_DO_MMIO; |
661 | } | 709 | } |
710 | EXPORT_SYMBOL_GPL(kvmppc_handle_load); | ||
662 | 711 | ||
663 | /* Same as above, but sign extends */ | 712 | /* Same as above, but sign extends */ |
664 | int kvmppc_handle_loads(struct kvm_run *run, struct kvm_vcpu *vcpu, | 713 | int kvmppc_handle_loads(struct kvm_run *run, struct kvm_vcpu *vcpu, |
@@ -720,6 +769,7 @@ int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
720 | 769 | ||
721 | return EMULATE_DO_MMIO; | 770 | return EMULATE_DO_MMIO; |
722 | } | 771 | } |
772 | EXPORT_SYMBOL_GPL(kvmppc_handle_store); | ||
723 | 773 | ||
724 | int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) | 774 | int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) |
725 | { | 775 | { |
@@ -1024,52 +1074,12 @@ long kvm_arch_vm_ioctl(struct file *filp, | |||
1024 | r = kvm_vm_ioctl_create_spapr_tce(kvm, &create_tce); | 1074 | r = kvm_vm_ioctl_create_spapr_tce(kvm, &create_tce); |
1025 | goto out; | 1075 | goto out; |
1026 | } | 1076 | } |
1027 | #endif /* CONFIG_PPC_BOOK3S_64 */ | ||
1028 | |||
1029 | #ifdef CONFIG_KVM_BOOK3S_64_HV | ||
1030 | case KVM_ALLOCATE_RMA: { | ||
1031 | struct kvm_allocate_rma rma; | ||
1032 | struct kvm *kvm = filp->private_data; | ||
1033 | |||
1034 | r = kvm_vm_ioctl_allocate_rma(kvm, &rma); | ||
1035 | if (r >= 0 && copy_to_user(argp, &rma, sizeof(rma))) | ||
1036 | r = -EFAULT; | ||
1037 | break; | ||
1038 | } | ||
1039 | |||
1040 | case KVM_PPC_ALLOCATE_HTAB: { | ||
1041 | u32 htab_order; | ||
1042 | |||
1043 | r = -EFAULT; | ||
1044 | if (get_user(htab_order, (u32 __user *)argp)) | ||
1045 | break; | ||
1046 | r = kvmppc_alloc_reset_hpt(kvm, &htab_order); | ||
1047 | if (r) | ||
1048 | break; | ||
1049 | r = -EFAULT; | ||
1050 | if (put_user(htab_order, (u32 __user *)argp)) | ||
1051 | break; | ||
1052 | r = 0; | ||
1053 | break; | ||
1054 | } | ||
1055 | |||
1056 | case KVM_PPC_GET_HTAB_FD: { | ||
1057 | struct kvm_get_htab_fd ghf; | ||
1058 | |||
1059 | r = -EFAULT; | ||
1060 | if (copy_from_user(&ghf, argp, sizeof(ghf))) | ||
1061 | break; | ||
1062 | r = kvm_vm_ioctl_get_htab_fd(kvm, &ghf); | ||
1063 | break; | ||
1064 | } | ||
1065 | #endif /* CONFIG_KVM_BOOK3S_64_HV */ | ||
1066 | |||
1067 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
1068 | case KVM_PPC_GET_SMMU_INFO: { | 1077 | case KVM_PPC_GET_SMMU_INFO: { |
1069 | struct kvm_ppc_smmu_info info; | 1078 | struct kvm_ppc_smmu_info info; |
1079 | struct kvm *kvm = filp->private_data; | ||
1070 | 1080 | ||
1071 | memset(&info, 0, sizeof(info)); | 1081 | memset(&info, 0, sizeof(info)); |
1072 | r = kvm_vm_ioctl_get_smmu_info(kvm, &info); | 1082 | r = kvm->arch.kvm_ops->get_smmu_info(kvm, &info); |
1073 | if (r >= 0 && copy_to_user(argp, &info, sizeof(info))) | 1083 | if (r >= 0 && copy_to_user(argp, &info, sizeof(info))) |
1074 | r = -EFAULT; | 1084 | r = -EFAULT; |
1075 | break; | 1085 | break; |
@@ -1080,11 +1090,15 @@ long kvm_arch_vm_ioctl(struct file *filp, | |||
1080 | r = kvm_vm_ioctl_rtas_define_token(kvm, argp); | 1090 | r = kvm_vm_ioctl_rtas_define_token(kvm, argp); |
1081 | break; | 1091 | break; |
1082 | } | 1092 | } |
1083 | #endif /* CONFIG_PPC_BOOK3S_64 */ | 1093 | default: { |
1094 | struct kvm *kvm = filp->private_data; | ||
1095 | r = kvm->arch.kvm_ops->arch_vm_ioctl(filp, ioctl, arg); | ||
1096 | } | ||
1097 | #else /* CONFIG_PPC_BOOK3S_64 */ | ||
1084 | default: | 1098 | default: |
1085 | r = -ENOTTY; | 1099 | r = -ENOTTY; |
1100 | #endif | ||
1086 | } | 1101 | } |
1087 | |||
1088 | out: | 1102 | out: |
1089 | return r; | 1103 | return r; |
1090 | } | 1104 | } |
@@ -1106,22 +1120,26 @@ long kvmppc_alloc_lpid(void) | |||
1106 | 1120 | ||
1107 | return lpid; | 1121 | return lpid; |
1108 | } | 1122 | } |
1123 | EXPORT_SYMBOL_GPL(kvmppc_alloc_lpid); | ||
1109 | 1124 | ||
1110 | void kvmppc_claim_lpid(long lpid) | 1125 | void kvmppc_claim_lpid(long lpid) |
1111 | { | 1126 | { |
1112 | set_bit(lpid, lpid_inuse); | 1127 | set_bit(lpid, lpid_inuse); |
1113 | } | 1128 | } |
1129 | EXPORT_SYMBOL_GPL(kvmppc_claim_lpid); | ||
1114 | 1130 | ||
1115 | void kvmppc_free_lpid(long lpid) | 1131 | void kvmppc_free_lpid(long lpid) |
1116 | { | 1132 | { |
1117 | clear_bit(lpid, lpid_inuse); | 1133 | clear_bit(lpid, lpid_inuse); |
1118 | } | 1134 | } |
1135 | EXPORT_SYMBOL_GPL(kvmppc_free_lpid); | ||
1119 | 1136 | ||
1120 | void kvmppc_init_lpid(unsigned long nr_lpids_param) | 1137 | void kvmppc_init_lpid(unsigned long nr_lpids_param) |
1121 | { | 1138 | { |
1122 | nr_lpids = min_t(unsigned long, KVMPPC_NR_LPIDS, nr_lpids_param); | 1139 | nr_lpids = min_t(unsigned long, KVMPPC_NR_LPIDS, nr_lpids_param); |
1123 | memset(lpid_inuse, 0, sizeof(lpid_inuse)); | 1140 | memset(lpid_inuse, 0, sizeof(lpid_inuse)); |
1124 | } | 1141 | } |
1142 | EXPORT_SYMBOL_GPL(kvmppc_init_lpid); | ||
1125 | 1143 | ||
1126 | int kvm_arch_init(void *opaque) | 1144 | int kvm_arch_init(void *opaque) |
1127 | { | 1145 | { |
@@ -1130,4 +1148,5 @@ int kvm_arch_init(void *opaque) | |||
1130 | 1148 | ||
1131 | void kvm_arch_exit(void) | 1149 | void kvm_arch_exit(void) |
1132 | { | 1150 | { |
1151 | |||
1133 | } | 1152 | } |
diff --git a/arch/powerpc/kvm/trace.h b/arch/powerpc/kvm/trace.h index e326489a5420..2e0e67ef3544 100644 --- a/arch/powerpc/kvm/trace.h +++ b/arch/powerpc/kvm/trace.h | |||
@@ -31,126 +31,6 @@ TRACE_EVENT(kvm_ppc_instr, | |||
31 | __entry->inst, __entry->pc, __entry->emulate) | 31 | __entry->inst, __entry->pc, __entry->emulate) |
32 | ); | 32 | ); |
33 | 33 | ||
34 | #ifdef CONFIG_PPC_BOOK3S | ||
35 | #define kvm_trace_symbol_exit \ | ||
36 | {0x100, "SYSTEM_RESET"}, \ | ||
37 | {0x200, "MACHINE_CHECK"}, \ | ||
38 | {0x300, "DATA_STORAGE"}, \ | ||
39 | {0x380, "DATA_SEGMENT"}, \ | ||
40 | {0x400, "INST_STORAGE"}, \ | ||
41 | {0x480, "INST_SEGMENT"}, \ | ||
42 | {0x500, "EXTERNAL"}, \ | ||
43 | {0x501, "EXTERNAL_LEVEL"}, \ | ||
44 | {0x502, "EXTERNAL_HV"}, \ | ||
45 | {0x600, "ALIGNMENT"}, \ | ||
46 | {0x700, "PROGRAM"}, \ | ||
47 | {0x800, "FP_UNAVAIL"}, \ | ||
48 | {0x900, "DECREMENTER"}, \ | ||
49 | {0x980, "HV_DECREMENTER"}, \ | ||
50 | {0xc00, "SYSCALL"}, \ | ||
51 | {0xd00, "TRACE"}, \ | ||
52 | {0xe00, "H_DATA_STORAGE"}, \ | ||
53 | {0xe20, "H_INST_STORAGE"}, \ | ||
54 | {0xe40, "H_EMUL_ASSIST"}, \ | ||
55 | {0xf00, "PERFMON"}, \ | ||
56 | {0xf20, "ALTIVEC"}, \ | ||
57 | {0xf40, "VSX"} | ||
58 | #else | ||
59 | #define kvm_trace_symbol_exit \ | ||
60 | {0, "CRITICAL"}, \ | ||
61 | {1, "MACHINE_CHECK"}, \ | ||
62 | {2, "DATA_STORAGE"}, \ | ||
63 | {3, "INST_STORAGE"}, \ | ||
64 | {4, "EXTERNAL"}, \ | ||
65 | {5, "ALIGNMENT"}, \ | ||
66 | {6, "PROGRAM"}, \ | ||
67 | {7, "FP_UNAVAIL"}, \ | ||
68 | {8, "SYSCALL"}, \ | ||
69 | {9, "AP_UNAVAIL"}, \ | ||
70 | {10, "DECREMENTER"}, \ | ||
71 | {11, "FIT"}, \ | ||
72 | {12, "WATCHDOG"}, \ | ||
73 | {13, "DTLB_MISS"}, \ | ||
74 | {14, "ITLB_MISS"}, \ | ||
75 | {15, "DEBUG"}, \ | ||
76 | {32, "SPE_UNAVAIL"}, \ | ||
77 | {33, "SPE_FP_DATA"}, \ | ||
78 | {34, "SPE_FP_ROUND"}, \ | ||
79 | {35, "PERFORMANCE_MONITOR"}, \ | ||
80 | {36, "DOORBELL"}, \ | ||
81 | {37, "DOORBELL_CRITICAL"}, \ | ||
82 | {38, "GUEST_DBELL"}, \ | ||
83 | {39, "GUEST_DBELL_CRIT"}, \ | ||
84 | {40, "HV_SYSCALL"}, \ | ||
85 | {41, "HV_PRIV"} | ||
86 | #endif | ||
87 | |||
88 | TRACE_EVENT(kvm_exit, | ||
89 | TP_PROTO(unsigned int exit_nr, struct kvm_vcpu *vcpu), | ||
90 | TP_ARGS(exit_nr, vcpu), | ||
91 | |||
92 | TP_STRUCT__entry( | ||
93 | __field( unsigned int, exit_nr ) | ||
94 | __field( unsigned long, pc ) | ||
95 | __field( unsigned long, msr ) | ||
96 | __field( unsigned long, dar ) | ||
97 | #ifdef CONFIG_KVM_BOOK3S_PR | ||
98 | __field( unsigned long, srr1 ) | ||
99 | #endif | ||
100 | __field( unsigned long, last_inst ) | ||
101 | ), | ||
102 | |||
103 | TP_fast_assign( | ||
104 | #ifdef CONFIG_KVM_BOOK3S_PR | ||
105 | struct kvmppc_book3s_shadow_vcpu *svcpu; | ||
106 | #endif | ||
107 | __entry->exit_nr = exit_nr; | ||
108 | __entry->pc = kvmppc_get_pc(vcpu); | ||
109 | __entry->dar = kvmppc_get_fault_dar(vcpu); | ||
110 | __entry->msr = vcpu->arch.shared->msr; | ||
111 | #ifdef CONFIG_KVM_BOOK3S_PR | ||
112 | svcpu = svcpu_get(vcpu); | ||
113 | __entry->srr1 = svcpu->shadow_srr1; | ||
114 | svcpu_put(svcpu); | ||
115 | #endif | ||
116 | __entry->last_inst = vcpu->arch.last_inst; | ||
117 | ), | ||
118 | |||
119 | TP_printk("exit=%s" | ||
120 | " | pc=0x%lx" | ||
121 | " | msr=0x%lx" | ||
122 | " | dar=0x%lx" | ||
123 | #ifdef CONFIG_KVM_BOOK3S_PR | ||
124 | " | srr1=0x%lx" | ||
125 | #endif | ||
126 | " | last_inst=0x%lx" | ||
127 | , | ||
128 | __print_symbolic(__entry->exit_nr, kvm_trace_symbol_exit), | ||
129 | __entry->pc, | ||
130 | __entry->msr, | ||
131 | __entry->dar, | ||
132 | #ifdef CONFIG_KVM_BOOK3S_PR | ||
133 | __entry->srr1, | ||
134 | #endif | ||
135 | __entry->last_inst | ||
136 | ) | ||
137 | ); | ||
138 | |||
139 | TRACE_EVENT(kvm_unmap_hva, | ||
140 | TP_PROTO(unsigned long hva), | ||
141 | TP_ARGS(hva), | ||
142 | |||
143 | TP_STRUCT__entry( | ||
144 | __field( unsigned long, hva ) | ||
145 | ), | ||
146 | |||
147 | TP_fast_assign( | ||
148 | __entry->hva = hva; | ||
149 | ), | ||
150 | |||
151 | TP_printk("unmap hva 0x%lx\n", __entry->hva) | ||
152 | ); | ||
153 | |||
154 | TRACE_EVENT(kvm_stlb_inval, | 34 | TRACE_EVENT(kvm_stlb_inval, |
155 | TP_PROTO(unsigned int stlb_index), | 35 | TP_PROTO(unsigned int stlb_index), |
156 | TP_ARGS(stlb_index), | 36 | TP_ARGS(stlb_index), |
@@ -236,315 +116,6 @@ TRACE_EVENT(kvm_check_requests, | |||
236 | __entry->cpu_nr, __entry->requests) | 116 | __entry->cpu_nr, __entry->requests) |
237 | ); | 117 | ); |
238 | 118 | ||
239 | |||
240 | /************************************************************************* | ||
241 | * Book3S trace points * | ||
242 | *************************************************************************/ | ||
243 | |||
244 | #ifdef CONFIG_KVM_BOOK3S_PR | ||
245 | |||
246 | TRACE_EVENT(kvm_book3s_reenter, | ||
247 | TP_PROTO(int r, struct kvm_vcpu *vcpu), | ||
248 | TP_ARGS(r, vcpu), | ||
249 | |||
250 | TP_STRUCT__entry( | ||
251 | __field( unsigned int, r ) | ||
252 | __field( unsigned long, pc ) | ||
253 | ), | ||
254 | |||
255 | TP_fast_assign( | ||
256 | __entry->r = r; | ||
257 | __entry->pc = kvmppc_get_pc(vcpu); | ||
258 | ), | ||
259 | |||
260 | TP_printk("reentry r=%d | pc=0x%lx", __entry->r, __entry->pc) | ||
261 | ); | ||
262 | |||
263 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
264 | |||
265 | TRACE_EVENT(kvm_book3s_64_mmu_map, | ||
266 | TP_PROTO(int rflags, ulong hpteg, ulong va, pfn_t hpaddr, | ||
267 | struct kvmppc_pte *orig_pte), | ||
268 | TP_ARGS(rflags, hpteg, va, hpaddr, orig_pte), | ||
269 | |||
270 | TP_STRUCT__entry( | ||
271 | __field( unsigned char, flag_w ) | ||
272 | __field( unsigned char, flag_x ) | ||
273 | __field( unsigned long, eaddr ) | ||
274 | __field( unsigned long, hpteg ) | ||
275 | __field( unsigned long, va ) | ||
276 | __field( unsigned long long, vpage ) | ||
277 | __field( unsigned long, hpaddr ) | ||
278 | ), | ||
279 | |||
280 | TP_fast_assign( | ||
281 | __entry->flag_w = ((rflags & HPTE_R_PP) == 3) ? '-' : 'w'; | ||
282 | __entry->flag_x = (rflags & HPTE_R_N) ? '-' : 'x'; | ||
283 | __entry->eaddr = orig_pte->eaddr; | ||
284 | __entry->hpteg = hpteg; | ||
285 | __entry->va = va; | ||
286 | __entry->vpage = orig_pte->vpage; | ||
287 | __entry->hpaddr = hpaddr; | ||
288 | ), | ||
289 | |||
290 | TP_printk("KVM: %c%c Map 0x%lx: [%lx] 0x%lx (0x%llx) -> %lx", | ||
291 | __entry->flag_w, __entry->flag_x, __entry->eaddr, | ||
292 | __entry->hpteg, __entry->va, __entry->vpage, __entry->hpaddr) | ||
293 | ); | ||
294 | |||
295 | #endif /* CONFIG_PPC_BOOK3S_64 */ | ||
296 | |||
297 | TRACE_EVENT(kvm_book3s_mmu_map, | ||
298 | TP_PROTO(struct hpte_cache *pte), | ||
299 | TP_ARGS(pte), | ||
300 | |||
301 | TP_STRUCT__entry( | ||
302 | __field( u64, host_vpn ) | ||
303 | __field( u64, pfn ) | ||
304 | __field( ulong, eaddr ) | ||
305 | __field( u64, vpage ) | ||
306 | __field( ulong, raddr ) | ||
307 | __field( int, flags ) | ||
308 | ), | ||
309 | |||
310 | TP_fast_assign( | ||
311 | __entry->host_vpn = pte->host_vpn; | ||
312 | __entry->pfn = pte->pfn; | ||
313 | __entry->eaddr = pte->pte.eaddr; | ||
314 | __entry->vpage = pte->pte.vpage; | ||
315 | __entry->raddr = pte->pte.raddr; | ||
316 | __entry->flags = (pte->pte.may_read ? 0x4 : 0) | | ||
317 | (pte->pte.may_write ? 0x2 : 0) | | ||
318 | (pte->pte.may_execute ? 0x1 : 0); | ||
319 | ), | ||
320 | |||
321 | TP_printk("Map: hvpn=%llx pfn=%llx ea=%lx vp=%llx ra=%lx [%x]", | ||
322 | __entry->host_vpn, __entry->pfn, __entry->eaddr, | ||
323 | __entry->vpage, __entry->raddr, __entry->flags) | ||
324 | ); | ||
325 | |||
326 | TRACE_EVENT(kvm_book3s_mmu_invalidate, | ||
327 | TP_PROTO(struct hpte_cache *pte), | ||
328 | TP_ARGS(pte), | ||
329 | |||
330 | TP_STRUCT__entry( | ||
331 | __field( u64, host_vpn ) | ||
332 | __field( u64, pfn ) | ||
333 | __field( ulong, eaddr ) | ||
334 | __field( u64, vpage ) | ||
335 | __field( ulong, raddr ) | ||
336 | __field( int, flags ) | ||
337 | ), | ||
338 | |||
339 | TP_fast_assign( | ||
340 | __entry->host_vpn = pte->host_vpn; | ||
341 | __entry->pfn = pte->pfn; | ||
342 | __entry->eaddr = pte->pte.eaddr; | ||
343 | __entry->vpage = pte->pte.vpage; | ||
344 | __entry->raddr = pte->pte.raddr; | ||
345 | __entry->flags = (pte->pte.may_read ? 0x4 : 0) | | ||
346 | (pte->pte.may_write ? 0x2 : 0) | | ||
347 | (pte->pte.may_execute ? 0x1 : 0); | ||
348 | ), | ||
349 | |||
350 | TP_printk("Flush: hva=%llx pfn=%llx ea=%lx vp=%llx ra=%lx [%x]", | ||
351 | __entry->host_vpn, __entry->pfn, __entry->eaddr, | ||
352 | __entry->vpage, __entry->raddr, __entry->flags) | ||
353 | ); | ||
354 | |||
355 | TRACE_EVENT(kvm_book3s_mmu_flush, | ||
356 | TP_PROTO(const char *type, struct kvm_vcpu *vcpu, unsigned long long p1, | ||
357 | unsigned long long p2), | ||
358 | TP_ARGS(type, vcpu, p1, p2), | ||
359 | |||
360 | TP_STRUCT__entry( | ||
361 | __field( int, count ) | ||
362 | __field( unsigned long long, p1 ) | ||
363 | __field( unsigned long long, p2 ) | ||
364 | __field( const char *, type ) | ||
365 | ), | ||
366 | |||
367 | TP_fast_assign( | ||
368 | __entry->count = to_book3s(vcpu)->hpte_cache_count; | ||
369 | __entry->p1 = p1; | ||
370 | __entry->p2 = p2; | ||
371 | __entry->type = type; | ||
372 | ), | ||
373 | |||
374 | TP_printk("Flush %d %sPTEs: %llx - %llx", | ||
375 | __entry->count, __entry->type, __entry->p1, __entry->p2) | ||
376 | ); | ||
377 | |||
378 | TRACE_EVENT(kvm_book3s_slb_found, | ||
379 | TP_PROTO(unsigned long long gvsid, unsigned long long hvsid), | ||
380 | TP_ARGS(gvsid, hvsid), | ||
381 | |||
382 | TP_STRUCT__entry( | ||
383 | __field( unsigned long long, gvsid ) | ||
384 | __field( unsigned long long, hvsid ) | ||
385 | ), | ||
386 | |||
387 | TP_fast_assign( | ||
388 | __entry->gvsid = gvsid; | ||
389 | __entry->hvsid = hvsid; | ||
390 | ), | ||
391 | |||
392 | TP_printk("%llx -> %llx", __entry->gvsid, __entry->hvsid) | ||
393 | ); | ||
394 | |||
395 | TRACE_EVENT(kvm_book3s_slb_fail, | ||
396 | TP_PROTO(u16 sid_map_mask, unsigned long long gvsid), | ||
397 | TP_ARGS(sid_map_mask, gvsid), | ||
398 | |||
399 | TP_STRUCT__entry( | ||
400 | __field( unsigned short, sid_map_mask ) | ||
401 | __field( unsigned long long, gvsid ) | ||
402 | ), | ||
403 | |||
404 | TP_fast_assign( | ||
405 | __entry->sid_map_mask = sid_map_mask; | ||
406 | __entry->gvsid = gvsid; | ||
407 | ), | ||
408 | |||
409 | TP_printk("%x/%x: %llx", __entry->sid_map_mask, | ||
410 | SID_MAP_MASK - __entry->sid_map_mask, __entry->gvsid) | ||
411 | ); | ||
412 | |||
413 | TRACE_EVENT(kvm_book3s_slb_map, | ||
414 | TP_PROTO(u16 sid_map_mask, unsigned long long gvsid, | ||
415 | unsigned long long hvsid), | ||
416 | TP_ARGS(sid_map_mask, gvsid, hvsid), | ||
417 | |||
418 | TP_STRUCT__entry( | ||
419 | __field( unsigned short, sid_map_mask ) | ||
420 | __field( unsigned long long, guest_vsid ) | ||
421 | __field( unsigned long long, host_vsid ) | ||
422 | ), | ||
423 | |||
424 | TP_fast_assign( | ||
425 | __entry->sid_map_mask = sid_map_mask; | ||
426 | __entry->guest_vsid = gvsid; | ||
427 | __entry->host_vsid = hvsid; | ||
428 | ), | ||
429 | |||
430 | TP_printk("%x: %llx -> %llx", __entry->sid_map_mask, | ||
431 | __entry->guest_vsid, __entry->host_vsid) | ||
432 | ); | ||
433 | |||
434 | TRACE_EVENT(kvm_book3s_slbmte, | ||
435 | TP_PROTO(u64 slb_vsid, u64 slb_esid), | ||
436 | TP_ARGS(slb_vsid, slb_esid), | ||
437 | |||
438 | TP_STRUCT__entry( | ||
439 | __field( u64, slb_vsid ) | ||
440 | __field( u64, slb_esid ) | ||
441 | ), | ||
442 | |||
443 | TP_fast_assign( | ||
444 | __entry->slb_vsid = slb_vsid; | ||
445 | __entry->slb_esid = slb_esid; | ||
446 | ), | ||
447 | |||
448 | TP_printk("%llx, %llx", __entry->slb_vsid, __entry->slb_esid) | ||
449 | ); | ||
450 | |||
451 | #endif /* CONFIG_PPC_BOOK3S */ | ||
452 | |||
453 | |||
454 | /************************************************************************* | ||
455 | * Book3E trace points * | ||
456 | *************************************************************************/ | ||
457 | |||
458 | #ifdef CONFIG_BOOKE | ||
459 | |||
460 | TRACE_EVENT(kvm_booke206_stlb_write, | ||
461 | TP_PROTO(__u32 mas0, __u32 mas8, __u32 mas1, __u64 mas2, __u64 mas7_3), | ||
462 | TP_ARGS(mas0, mas8, mas1, mas2, mas7_3), | ||
463 | |||
464 | TP_STRUCT__entry( | ||
465 | __field( __u32, mas0 ) | ||
466 | __field( __u32, mas8 ) | ||
467 | __field( __u32, mas1 ) | ||
468 | __field( __u64, mas2 ) | ||
469 | __field( __u64, mas7_3 ) | ||
470 | ), | ||
471 | |||
472 | TP_fast_assign( | ||
473 | __entry->mas0 = mas0; | ||
474 | __entry->mas8 = mas8; | ||
475 | __entry->mas1 = mas1; | ||
476 | __entry->mas2 = mas2; | ||
477 | __entry->mas7_3 = mas7_3; | ||
478 | ), | ||
479 | |||
480 | TP_printk("mas0=%x mas8=%x mas1=%x mas2=%llx mas7_3=%llx", | ||
481 | __entry->mas0, __entry->mas8, __entry->mas1, | ||
482 | __entry->mas2, __entry->mas7_3) | ||
483 | ); | ||
484 | |||
485 | TRACE_EVENT(kvm_booke206_gtlb_write, | ||
486 | TP_PROTO(__u32 mas0, __u32 mas1, __u64 mas2, __u64 mas7_3), | ||
487 | TP_ARGS(mas0, mas1, mas2, mas7_3), | ||
488 | |||
489 | TP_STRUCT__entry( | ||
490 | __field( __u32, mas0 ) | ||
491 | __field( __u32, mas1 ) | ||
492 | __field( __u64, mas2 ) | ||
493 | __field( __u64, mas7_3 ) | ||
494 | ), | ||
495 | |||
496 | TP_fast_assign( | ||
497 | __entry->mas0 = mas0; | ||
498 | __entry->mas1 = mas1; | ||
499 | __entry->mas2 = mas2; | ||
500 | __entry->mas7_3 = mas7_3; | ||
501 | ), | ||
502 | |||
503 | TP_printk("mas0=%x mas1=%x mas2=%llx mas7_3=%llx", | ||
504 | __entry->mas0, __entry->mas1, | ||
505 | __entry->mas2, __entry->mas7_3) | ||
506 | ); | ||
507 | |||
508 | TRACE_EVENT(kvm_booke206_ref_release, | ||
509 | TP_PROTO(__u64 pfn, __u32 flags), | ||
510 | TP_ARGS(pfn, flags), | ||
511 | |||
512 | TP_STRUCT__entry( | ||
513 | __field( __u64, pfn ) | ||
514 | __field( __u32, flags ) | ||
515 | ), | ||
516 | |||
517 | TP_fast_assign( | ||
518 | __entry->pfn = pfn; | ||
519 | __entry->flags = flags; | ||
520 | ), | ||
521 | |||
522 | TP_printk("pfn=%llx flags=%x", | ||
523 | __entry->pfn, __entry->flags) | ||
524 | ); | ||
525 | |||
526 | TRACE_EVENT(kvm_booke_queue_irqprio, | ||
527 | TP_PROTO(struct kvm_vcpu *vcpu, unsigned int priority), | ||
528 | TP_ARGS(vcpu, priority), | ||
529 | |||
530 | TP_STRUCT__entry( | ||
531 | __field( __u32, cpu_nr ) | ||
532 | __field( __u32, priority ) | ||
533 | __field( unsigned long, pending ) | ||
534 | ), | ||
535 | |||
536 | TP_fast_assign( | ||
537 | __entry->cpu_nr = vcpu->vcpu_id; | ||
538 | __entry->priority = priority; | ||
539 | __entry->pending = vcpu->arch.pending_exceptions; | ||
540 | ), | ||
541 | |||
542 | TP_printk("vcpu=%x prio=%x pending=%lx", | ||
543 | __entry->cpu_nr, __entry->priority, __entry->pending) | ||
544 | ); | ||
545 | |||
546 | #endif | ||
547 | |||
548 | #endif /* _TRACE_KVM_H */ | 119 | #endif /* _TRACE_KVM_H */ |
549 | 120 | ||
550 | /* This part must be outside protection */ | 121 | /* This part must be outside protection */ |
diff --git a/arch/powerpc/kvm/trace_booke.h b/arch/powerpc/kvm/trace_booke.h new file mode 100644 index 000000000000..f7537cf26ce7 --- /dev/null +++ b/arch/powerpc/kvm/trace_booke.h | |||
@@ -0,0 +1,177 @@ | |||
1 | #if !defined(_TRACE_KVM_BOOKE_H) || defined(TRACE_HEADER_MULTI_READ) | ||
2 | #define _TRACE_KVM_BOOKE_H | ||
3 | |||
4 | #include <linux/tracepoint.h> | ||
5 | |||
6 | #undef TRACE_SYSTEM | ||
7 | #define TRACE_SYSTEM kvm_booke | ||
8 | #define TRACE_INCLUDE_PATH . | ||
9 | #define TRACE_INCLUDE_FILE trace_booke | ||
10 | |||
11 | #define kvm_trace_symbol_exit \ | ||
12 | {0, "CRITICAL"}, \ | ||
13 | {1, "MACHINE_CHECK"}, \ | ||
14 | {2, "DATA_STORAGE"}, \ | ||
15 | {3, "INST_STORAGE"}, \ | ||
16 | {4, "EXTERNAL"}, \ | ||
17 | {5, "ALIGNMENT"}, \ | ||
18 | {6, "PROGRAM"}, \ | ||
19 | {7, "FP_UNAVAIL"}, \ | ||
20 | {8, "SYSCALL"}, \ | ||
21 | {9, "AP_UNAVAIL"}, \ | ||
22 | {10, "DECREMENTER"}, \ | ||
23 | {11, "FIT"}, \ | ||
24 | {12, "WATCHDOG"}, \ | ||
25 | {13, "DTLB_MISS"}, \ | ||
26 | {14, "ITLB_MISS"}, \ | ||
27 | {15, "DEBUG"}, \ | ||
28 | {32, "SPE_UNAVAIL"}, \ | ||
29 | {33, "SPE_FP_DATA"}, \ | ||
30 | {34, "SPE_FP_ROUND"}, \ | ||
31 | {35, "PERFORMANCE_MONITOR"}, \ | ||
32 | {36, "DOORBELL"}, \ | ||
33 | {37, "DOORBELL_CRITICAL"}, \ | ||
34 | {38, "GUEST_DBELL"}, \ | ||
35 | {39, "GUEST_DBELL_CRIT"}, \ | ||
36 | {40, "HV_SYSCALL"}, \ | ||
37 | {41, "HV_PRIV"} | ||
38 | |||
39 | TRACE_EVENT(kvm_exit, | ||
40 | TP_PROTO(unsigned int exit_nr, struct kvm_vcpu *vcpu), | ||
41 | TP_ARGS(exit_nr, vcpu), | ||
42 | |||
43 | TP_STRUCT__entry( | ||
44 | __field( unsigned int, exit_nr ) | ||
45 | __field( unsigned long, pc ) | ||
46 | __field( unsigned long, msr ) | ||
47 | __field( unsigned long, dar ) | ||
48 | __field( unsigned long, last_inst ) | ||
49 | ), | ||
50 | |||
51 | TP_fast_assign( | ||
52 | __entry->exit_nr = exit_nr; | ||
53 | __entry->pc = kvmppc_get_pc(vcpu); | ||
54 | __entry->dar = kvmppc_get_fault_dar(vcpu); | ||
55 | __entry->msr = vcpu->arch.shared->msr; | ||
56 | __entry->last_inst = vcpu->arch.last_inst; | ||
57 | ), | ||
58 | |||
59 | TP_printk("exit=%s" | ||
60 | " | pc=0x%lx" | ||
61 | " | msr=0x%lx" | ||
62 | " | dar=0x%lx" | ||
63 | " | last_inst=0x%lx" | ||
64 | , | ||
65 | __print_symbolic(__entry->exit_nr, kvm_trace_symbol_exit), | ||
66 | __entry->pc, | ||
67 | __entry->msr, | ||
68 | __entry->dar, | ||
69 | __entry->last_inst | ||
70 | ) | ||
71 | ); | ||
72 | |||
73 | TRACE_EVENT(kvm_unmap_hva, | ||
74 | TP_PROTO(unsigned long hva), | ||
75 | TP_ARGS(hva), | ||
76 | |||
77 | TP_STRUCT__entry( | ||
78 | __field( unsigned long, hva ) | ||
79 | ), | ||
80 | |||
81 | TP_fast_assign( | ||
82 | __entry->hva = hva; | ||
83 | ), | ||
84 | |||
85 | TP_printk("unmap hva 0x%lx\n", __entry->hva) | ||
86 | ); | ||
87 | |||
88 | TRACE_EVENT(kvm_booke206_stlb_write, | ||
89 | TP_PROTO(__u32 mas0, __u32 mas8, __u32 mas1, __u64 mas2, __u64 mas7_3), | ||
90 | TP_ARGS(mas0, mas8, mas1, mas2, mas7_3), | ||
91 | |||
92 | TP_STRUCT__entry( | ||
93 | __field( __u32, mas0 ) | ||
94 | __field( __u32, mas8 ) | ||
95 | __field( __u32, mas1 ) | ||
96 | __field( __u64, mas2 ) | ||
97 | __field( __u64, mas7_3 ) | ||
98 | ), | ||
99 | |||
100 | TP_fast_assign( | ||
101 | __entry->mas0 = mas0; | ||
102 | __entry->mas8 = mas8; | ||
103 | __entry->mas1 = mas1; | ||
104 | __entry->mas2 = mas2; | ||
105 | __entry->mas7_3 = mas7_3; | ||
106 | ), | ||
107 | |||
108 | TP_printk("mas0=%x mas8=%x mas1=%x mas2=%llx mas7_3=%llx", | ||
109 | __entry->mas0, __entry->mas8, __entry->mas1, | ||
110 | __entry->mas2, __entry->mas7_3) | ||
111 | ); | ||
112 | |||
113 | TRACE_EVENT(kvm_booke206_gtlb_write, | ||
114 | TP_PROTO(__u32 mas0, __u32 mas1, __u64 mas2, __u64 mas7_3), | ||
115 | TP_ARGS(mas0, mas1, mas2, mas7_3), | ||
116 | |||
117 | TP_STRUCT__entry( | ||
118 | __field( __u32, mas0 ) | ||
119 | __field( __u32, mas1 ) | ||
120 | __field( __u64, mas2 ) | ||
121 | __field( __u64, mas7_3 ) | ||
122 | ), | ||
123 | |||
124 | TP_fast_assign( | ||
125 | __entry->mas0 = mas0; | ||
126 | __entry->mas1 = mas1; | ||
127 | __entry->mas2 = mas2; | ||
128 | __entry->mas7_3 = mas7_3; | ||
129 | ), | ||
130 | |||
131 | TP_printk("mas0=%x mas1=%x mas2=%llx mas7_3=%llx", | ||
132 | __entry->mas0, __entry->mas1, | ||
133 | __entry->mas2, __entry->mas7_3) | ||
134 | ); | ||
135 | |||
136 | TRACE_EVENT(kvm_booke206_ref_release, | ||
137 | TP_PROTO(__u64 pfn, __u32 flags), | ||
138 | TP_ARGS(pfn, flags), | ||
139 | |||
140 | TP_STRUCT__entry( | ||
141 | __field( __u64, pfn ) | ||
142 | __field( __u32, flags ) | ||
143 | ), | ||
144 | |||
145 | TP_fast_assign( | ||
146 | __entry->pfn = pfn; | ||
147 | __entry->flags = flags; | ||
148 | ), | ||
149 | |||
150 | TP_printk("pfn=%llx flags=%x", | ||
151 | __entry->pfn, __entry->flags) | ||
152 | ); | ||
153 | |||
154 | TRACE_EVENT(kvm_booke_queue_irqprio, | ||
155 | TP_PROTO(struct kvm_vcpu *vcpu, unsigned int priority), | ||
156 | TP_ARGS(vcpu, priority), | ||
157 | |||
158 | TP_STRUCT__entry( | ||
159 | __field( __u32, cpu_nr ) | ||
160 | __field( __u32, priority ) | ||
161 | __field( unsigned long, pending ) | ||
162 | ), | ||
163 | |||
164 | TP_fast_assign( | ||
165 | __entry->cpu_nr = vcpu->vcpu_id; | ||
166 | __entry->priority = priority; | ||
167 | __entry->pending = vcpu->arch.pending_exceptions; | ||
168 | ), | ||
169 | |||
170 | TP_printk("vcpu=%x prio=%x pending=%lx", | ||
171 | __entry->cpu_nr, __entry->priority, __entry->pending) | ||
172 | ); | ||
173 | |||
174 | #endif | ||
175 | |||
176 | /* This part must be outside protection */ | ||
177 | #include <trace/define_trace.h> | ||
diff --git a/arch/powerpc/kvm/trace_pr.h b/arch/powerpc/kvm/trace_pr.h new file mode 100644 index 000000000000..8b22e4748344 --- /dev/null +++ b/arch/powerpc/kvm/trace_pr.h | |||
@@ -0,0 +1,297 @@ | |||
1 | |||
2 | #if !defined(_TRACE_KVM_PR_H) || defined(TRACE_HEADER_MULTI_READ) | ||
3 | #define _TRACE_KVM_PR_H | ||
4 | |||
5 | #include <linux/tracepoint.h> | ||
6 | |||
7 | #undef TRACE_SYSTEM | ||
8 | #define TRACE_SYSTEM kvm_pr | ||
9 | #define TRACE_INCLUDE_PATH . | ||
10 | #define TRACE_INCLUDE_FILE trace_pr | ||
11 | |||
12 | #define kvm_trace_symbol_exit \ | ||
13 | {0x100, "SYSTEM_RESET"}, \ | ||
14 | {0x200, "MACHINE_CHECK"}, \ | ||
15 | {0x300, "DATA_STORAGE"}, \ | ||
16 | {0x380, "DATA_SEGMENT"}, \ | ||
17 | {0x400, "INST_STORAGE"}, \ | ||
18 | {0x480, "INST_SEGMENT"}, \ | ||
19 | {0x500, "EXTERNAL"}, \ | ||
20 | {0x501, "EXTERNAL_LEVEL"}, \ | ||
21 | {0x502, "EXTERNAL_HV"}, \ | ||
22 | {0x600, "ALIGNMENT"}, \ | ||
23 | {0x700, "PROGRAM"}, \ | ||
24 | {0x800, "FP_UNAVAIL"}, \ | ||
25 | {0x900, "DECREMENTER"}, \ | ||
26 | {0x980, "HV_DECREMENTER"}, \ | ||
27 | {0xc00, "SYSCALL"}, \ | ||
28 | {0xd00, "TRACE"}, \ | ||
29 | {0xe00, "H_DATA_STORAGE"}, \ | ||
30 | {0xe20, "H_INST_STORAGE"}, \ | ||
31 | {0xe40, "H_EMUL_ASSIST"}, \ | ||
32 | {0xf00, "PERFMON"}, \ | ||
33 | {0xf20, "ALTIVEC"}, \ | ||
34 | {0xf40, "VSX"} | ||
35 | |||
36 | TRACE_EVENT(kvm_book3s_reenter, | ||
37 | TP_PROTO(int r, struct kvm_vcpu *vcpu), | ||
38 | TP_ARGS(r, vcpu), | ||
39 | |||
40 | TP_STRUCT__entry( | ||
41 | __field( unsigned int, r ) | ||
42 | __field( unsigned long, pc ) | ||
43 | ), | ||
44 | |||
45 | TP_fast_assign( | ||
46 | __entry->r = r; | ||
47 | __entry->pc = kvmppc_get_pc(vcpu); | ||
48 | ), | ||
49 | |||
50 | TP_printk("reentry r=%d | pc=0x%lx", __entry->r, __entry->pc) | ||
51 | ); | ||
52 | |||
53 | #ifdef CONFIG_PPC_BOOK3S_64 | ||
54 | |||
55 | TRACE_EVENT(kvm_book3s_64_mmu_map, | ||
56 | TP_PROTO(int rflags, ulong hpteg, ulong va, pfn_t hpaddr, | ||
57 | struct kvmppc_pte *orig_pte), | ||
58 | TP_ARGS(rflags, hpteg, va, hpaddr, orig_pte), | ||
59 | |||
60 | TP_STRUCT__entry( | ||
61 | __field( unsigned char, flag_w ) | ||
62 | __field( unsigned char, flag_x ) | ||
63 | __field( unsigned long, eaddr ) | ||
64 | __field( unsigned long, hpteg ) | ||
65 | __field( unsigned long, va ) | ||
66 | __field( unsigned long long, vpage ) | ||
67 | __field( unsigned long, hpaddr ) | ||
68 | ), | ||
69 | |||
70 | TP_fast_assign( | ||
71 | __entry->flag_w = ((rflags & HPTE_R_PP) == 3) ? '-' : 'w'; | ||
72 | __entry->flag_x = (rflags & HPTE_R_N) ? '-' : 'x'; | ||
73 | __entry->eaddr = orig_pte->eaddr; | ||
74 | __entry->hpteg = hpteg; | ||
75 | __entry->va = va; | ||
76 | __entry->vpage = orig_pte->vpage; | ||
77 | __entry->hpaddr = hpaddr; | ||
78 | ), | ||
79 | |||
80 | TP_printk("KVM: %c%c Map 0x%lx: [%lx] 0x%lx (0x%llx) -> %lx", | ||
81 | __entry->flag_w, __entry->flag_x, __entry->eaddr, | ||
82 | __entry->hpteg, __entry->va, __entry->vpage, __entry->hpaddr) | ||
83 | ); | ||
84 | |||
85 | #endif /* CONFIG_PPC_BOOK3S_64 */ | ||
86 | |||
87 | TRACE_EVENT(kvm_book3s_mmu_map, | ||
88 | TP_PROTO(struct hpte_cache *pte), | ||
89 | TP_ARGS(pte), | ||
90 | |||
91 | TP_STRUCT__entry( | ||
92 | __field( u64, host_vpn ) | ||
93 | __field( u64, pfn ) | ||
94 | __field( ulong, eaddr ) | ||
95 | __field( u64, vpage ) | ||
96 | __field( ulong, raddr ) | ||
97 | __field( int, flags ) | ||
98 | ), | ||
99 | |||
100 | TP_fast_assign( | ||
101 | __entry->host_vpn = pte->host_vpn; | ||
102 | __entry->pfn = pte->pfn; | ||
103 | __entry->eaddr = pte->pte.eaddr; | ||
104 | __entry->vpage = pte->pte.vpage; | ||
105 | __entry->raddr = pte->pte.raddr; | ||
106 | __entry->flags = (pte->pte.may_read ? 0x4 : 0) | | ||
107 | (pte->pte.may_write ? 0x2 : 0) | | ||
108 | (pte->pte.may_execute ? 0x1 : 0); | ||
109 | ), | ||
110 | |||
111 | TP_printk("Map: hvpn=%llx pfn=%llx ea=%lx vp=%llx ra=%lx [%x]", | ||
112 | __entry->host_vpn, __entry->pfn, __entry->eaddr, | ||
113 | __entry->vpage, __entry->raddr, __entry->flags) | ||
114 | ); | ||
115 | |||
116 | TRACE_EVENT(kvm_book3s_mmu_invalidate, | ||
117 | TP_PROTO(struct hpte_cache *pte), | ||
118 | TP_ARGS(pte), | ||
119 | |||
120 | TP_STRUCT__entry( | ||
121 | __field( u64, host_vpn ) | ||
122 | __field( u64, pfn ) | ||
123 | __field( ulong, eaddr ) | ||
124 | __field( u64, vpage ) | ||
125 | __field( ulong, raddr ) | ||
126 | __field( int, flags ) | ||
127 | ), | ||
128 | |||
129 | TP_fast_assign( | ||
130 | __entry->host_vpn = pte->host_vpn; | ||
131 | __entry->pfn = pte->pfn; | ||
132 | __entry->eaddr = pte->pte.eaddr; | ||
133 | __entry->vpage = pte->pte.vpage; | ||
134 | __entry->raddr = pte->pte.raddr; | ||
135 | __entry->flags = (pte->pte.may_read ? 0x4 : 0) | | ||
136 | (pte->pte.may_write ? 0x2 : 0) | | ||
137 | (pte->pte.may_execute ? 0x1 : 0); | ||
138 | ), | ||
139 | |||
140 | TP_printk("Flush: hva=%llx pfn=%llx ea=%lx vp=%llx ra=%lx [%x]", | ||
141 | __entry->host_vpn, __entry->pfn, __entry->eaddr, | ||
142 | __entry->vpage, __entry->raddr, __entry->flags) | ||
143 | ); | ||
144 | |||
145 | TRACE_EVENT(kvm_book3s_mmu_flush, | ||
146 | TP_PROTO(const char *type, struct kvm_vcpu *vcpu, unsigned long long p1, | ||
147 | unsigned long long p2), | ||
148 | TP_ARGS(type, vcpu, p1, p2), | ||
149 | |||
150 | TP_STRUCT__entry( | ||
151 | __field( int, count ) | ||
152 | __field( unsigned long long, p1 ) | ||
153 | __field( unsigned long long, p2 ) | ||
154 | __field( const char *, type ) | ||
155 | ), | ||
156 | |||
157 | TP_fast_assign( | ||
158 | __entry->count = to_book3s(vcpu)->hpte_cache_count; | ||
159 | __entry->p1 = p1; | ||
160 | __entry->p2 = p2; | ||
161 | __entry->type = type; | ||
162 | ), | ||
163 | |||
164 | TP_printk("Flush %d %sPTEs: %llx - %llx", | ||
165 | __entry->count, __entry->type, __entry->p1, __entry->p2) | ||
166 | ); | ||
167 | |||
168 | TRACE_EVENT(kvm_book3s_slb_found, | ||
169 | TP_PROTO(unsigned long long gvsid, unsigned long long hvsid), | ||
170 | TP_ARGS(gvsid, hvsid), | ||
171 | |||
172 | TP_STRUCT__entry( | ||
173 | __field( unsigned long long, gvsid ) | ||
174 | __field( unsigned long long, hvsid ) | ||
175 | ), | ||
176 | |||
177 | TP_fast_assign( | ||
178 | __entry->gvsid = gvsid; | ||
179 | __entry->hvsid = hvsid; | ||
180 | ), | ||
181 | |||
182 | TP_printk("%llx -> %llx", __entry->gvsid, __entry->hvsid) | ||
183 | ); | ||
184 | |||
185 | TRACE_EVENT(kvm_book3s_slb_fail, | ||
186 | TP_PROTO(u16 sid_map_mask, unsigned long long gvsid), | ||
187 | TP_ARGS(sid_map_mask, gvsid), | ||
188 | |||
189 | TP_STRUCT__entry( | ||
190 | __field( unsigned short, sid_map_mask ) | ||
191 | __field( unsigned long long, gvsid ) | ||
192 | ), | ||
193 | |||
194 | TP_fast_assign( | ||
195 | __entry->sid_map_mask = sid_map_mask; | ||
196 | __entry->gvsid = gvsid; | ||
197 | ), | ||
198 | |||
199 | TP_printk("%x/%x: %llx", __entry->sid_map_mask, | ||
200 | SID_MAP_MASK - __entry->sid_map_mask, __entry->gvsid) | ||
201 | ); | ||
202 | |||
203 | TRACE_EVENT(kvm_book3s_slb_map, | ||
204 | TP_PROTO(u16 sid_map_mask, unsigned long long gvsid, | ||
205 | unsigned long long hvsid), | ||
206 | TP_ARGS(sid_map_mask, gvsid, hvsid), | ||
207 | |||
208 | TP_STRUCT__entry( | ||
209 | __field( unsigned short, sid_map_mask ) | ||
210 | __field( unsigned long long, guest_vsid ) | ||
211 | __field( unsigned long long, host_vsid ) | ||
212 | ), | ||
213 | |||
214 | TP_fast_assign( | ||
215 | __entry->sid_map_mask = sid_map_mask; | ||
216 | __entry->guest_vsid = gvsid; | ||
217 | __entry->host_vsid = hvsid; | ||
218 | ), | ||
219 | |||
220 | TP_printk("%x: %llx -> %llx", __entry->sid_map_mask, | ||
221 | __entry->guest_vsid, __entry->host_vsid) | ||
222 | ); | ||
223 | |||
224 | TRACE_EVENT(kvm_book3s_slbmte, | ||
225 | TP_PROTO(u64 slb_vsid, u64 slb_esid), | ||
226 | TP_ARGS(slb_vsid, slb_esid), | ||
227 | |||
228 | TP_STRUCT__entry( | ||
229 | __field( u64, slb_vsid ) | ||
230 | __field( u64, slb_esid ) | ||
231 | ), | ||
232 | |||
233 | TP_fast_assign( | ||
234 | __entry->slb_vsid = slb_vsid; | ||
235 | __entry->slb_esid = slb_esid; | ||
236 | ), | ||
237 | |||
238 | TP_printk("%llx, %llx", __entry->slb_vsid, __entry->slb_esid) | ||
239 | ); | ||
240 | |||
241 | TRACE_EVENT(kvm_exit, | ||
242 | TP_PROTO(unsigned int exit_nr, struct kvm_vcpu *vcpu), | ||
243 | TP_ARGS(exit_nr, vcpu), | ||
244 | |||
245 | TP_STRUCT__entry( | ||
246 | __field( unsigned int, exit_nr ) | ||
247 | __field( unsigned long, pc ) | ||
248 | __field( unsigned long, msr ) | ||
249 | __field( unsigned long, dar ) | ||
250 | __field( unsigned long, srr1 ) | ||
251 | __field( unsigned long, last_inst ) | ||
252 | ), | ||
253 | |||
254 | TP_fast_assign( | ||
255 | __entry->exit_nr = exit_nr; | ||
256 | __entry->pc = kvmppc_get_pc(vcpu); | ||
257 | __entry->dar = kvmppc_get_fault_dar(vcpu); | ||
258 | __entry->msr = vcpu->arch.shared->msr; | ||
259 | __entry->srr1 = vcpu->arch.shadow_srr1; | ||
260 | __entry->last_inst = vcpu->arch.last_inst; | ||
261 | ), | ||
262 | |||
263 | TP_printk("exit=%s" | ||
264 | " | pc=0x%lx" | ||
265 | " | msr=0x%lx" | ||
266 | " | dar=0x%lx" | ||
267 | " | srr1=0x%lx" | ||
268 | " | last_inst=0x%lx" | ||
269 | , | ||
270 | __print_symbolic(__entry->exit_nr, kvm_trace_symbol_exit), | ||
271 | __entry->pc, | ||
272 | __entry->msr, | ||
273 | __entry->dar, | ||
274 | __entry->srr1, | ||
275 | __entry->last_inst | ||
276 | ) | ||
277 | ); | ||
278 | |||
279 | TRACE_EVENT(kvm_unmap_hva, | ||
280 | TP_PROTO(unsigned long hva), | ||
281 | TP_ARGS(hva), | ||
282 | |||
283 | TP_STRUCT__entry( | ||
284 | __field( unsigned long, hva ) | ||
285 | ), | ||
286 | |||
287 | TP_fast_assign( | ||
288 | __entry->hva = hva; | ||
289 | ), | ||
290 | |||
291 | TP_printk("unmap hva 0x%lx\n", __entry->hva) | ||
292 | ); | ||
293 | |||
294 | #endif /* _TRACE_KVM_H */ | ||
295 | |||
296 | /* This part must be outside protection */ | ||
297 | #include <trace/define_trace.h> | ||
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile index 450433276699..95a20e17dbff 100644 --- a/arch/powerpc/lib/Makefile +++ b/arch/powerpc/lib/Makefile | |||
@@ -10,15 +10,23 @@ CFLAGS_REMOVE_code-patching.o = -pg | |||
10 | CFLAGS_REMOVE_feature-fixups.o = -pg | 10 | CFLAGS_REMOVE_feature-fixups.o = -pg |
11 | 11 | ||
12 | obj-y := string.o alloc.o \ | 12 | obj-y := string.o alloc.o \ |
13 | checksum_$(CONFIG_WORD_SIZE).o crtsavres.o | 13 | crtsavres.o |
14 | obj-$(CONFIG_PPC32) += div64.o copy_32.o | 14 | obj-$(CONFIG_PPC32) += div64.o copy_32.o |
15 | obj-$(CONFIG_HAS_IOMEM) += devres.o | 15 | obj-$(CONFIG_HAS_IOMEM) += devres.o |
16 | 16 | ||
17 | obj-$(CONFIG_PPC64) += copypage_64.o copyuser_64.o \ | 17 | obj-$(CONFIG_PPC64) += copypage_64.o copyuser_64.o \ |
18 | memcpy_64.o usercopy_64.o mem_64.o string.o \ | 18 | usercopy_64.o mem_64.o string.o \ |
19 | checksum_wrappers_64.o hweight_64.o \ | 19 | hweight_64.o \ |
20 | copyuser_power7.o string_64.o copypage_power7.o \ | 20 | copyuser_power7.o string_64.o copypage_power7.o |
21 | memcpy_power7.o | 21 | ifeq ($(CONFIG_GENERIC_CSUM),) |
22 | obj-y += checksum_$(CONFIG_WORD_SIZE).o | ||
23 | obj-$(CONFIG_PPC64) += checksum_wrappers_64.o | ||
24 | endif | ||
25 | |||
26 | ifeq ($(CONFIG_CPU_LITTLE_ENDIAN),) | ||
27 | obj-$(CONFIG_PPC64) += memcpy_power7.o memcpy_64.o | ||
28 | endif | ||
29 | |||
22 | obj-$(CONFIG_PPC_EMULATE_SSTEP) += sstep.o ldstfp.o | 30 | obj-$(CONFIG_PPC_EMULATE_SSTEP) += sstep.o ldstfp.o |
23 | 31 | ||
24 | ifeq ($(CONFIG_PPC64),y) | 32 | ifeq ($(CONFIG_PPC64),y) |
@@ -31,3 +39,6 @@ obj-$(CONFIG_PPC_LIB_RHEAP) += rheap.o | |||
31 | obj-y += code-patching.o | 39 | obj-y += code-patching.o |
32 | obj-y += feature-fixups.o | 40 | obj-y += feature-fixups.o |
33 | obj-$(CONFIG_FTR_FIXUP_SELFTEST) += feature-fixups-test.o | 41 | obj-$(CONFIG_FTR_FIXUP_SELFTEST) += feature-fixups-test.o |
42 | |||
43 | obj-$(CONFIG_ALTIVEC) += xor_vmx.o | ||
44 | CFLAGS_xor_vmx.o += -maltivec -mabi=altivec | ||
diff --git a/arch/powerpc/lib/checksum_64.S b/arch/powerpc/lib/checksum_64.S index 167f72555d60..57a072065057 100644 --- a/arch/powerpc/lib/checksum_64.S +++ b/arch/powerpc/lib/checksum_64.S | |||
@@ -226,19 +226,35 @@ _GLOBAL(csum_partial) | |||
226 | blr | 226 | blr |
227 | 227 | ||
228 | 228 | ||
229 | .macro source | 229 | .macro srcnr |
230 | 100: | 230 | 100: |
231 | .section __ex_table,"a" | 231 | .section __ex_table,"a" |
232 | .align 3 | 232 | .align 3 |
233 | .llong 100b,.Lsrc_error | 233 | .llong 100b,.Lsrc_error_nr |
234 | .previous | 234 | .previous |
235 | .endm | 235 | .endm |
236 | 236 | ||
237 | .macro dest | 237 | .macro source |
238 | 150: | ||
239 | .section __ex_table,"a" | ||
240 | .align 3 | ||
241 | .llong 150b,.Lsrc_error | ||
242 | .previous | ||
243 | .endm | ||
244 | |||
245 | .macro dstnr | ||
238 | 200: | 246 | 200: |
239 | .section __ex_table,"a" | 247 | .section __ex_table,"a" |
240 | .align 3 | 248 | .align 3 |
241 | .llong 200b,.Ldest_error | 249 | .llong 200b,.Ldest_error_nr |
250 | .previous | ||
251 | .endm | ||
252 | |||
253 | .macro dest | ||
254 | 250: | ||
255 | .section __ex_table,"a" | ||
256 | .align 3 | ||
257 | .llong 250b,.Ldest_error | ||
242 | .previous | 258 | .previous |
243 | .endm | 259 | .endm |
244 | 260 | ||
@@ -269,16 +285,16 @@ _GLOBAL(csum_partial_copy_generic) | |||
269 | rldicl. r6,r3,64-1,64-2 /* r6 = (r3 & 0x3) >> 1 */ | 285 | rldicl. r6,r3,64-1,64-2 /* r6 = (r3 & 0x3) >> 1 */ |
270 | beq .Lcopy_aligned | 286 | beq .Lcopy_aligned |
271 | 287 | ||
272 | li r7,4 | 288 | li r9,4 |
273 | sub r6,r7,r6 | 289 | sub r6,r9,r6 |
274 | mtctr r6 | 290 | mtctr r6 |
275 | 291 | ||
276 | 1: | 292 | 1: |
277 | source; lhz r6,0(r3) /* align to doubleword */ | 293 | srcnr; lhz r6,0(r3) /* align to doubleword */ |
278 | subi r5,r5,2 | 294 | subi r5,r5,2 |
279 | addi r3,r3,2 | 295 | addi r3,r3,2 |
280 | adde r0,r0,r6 | 296 | adde r0,r0,r6 |
281 | dest; sth r6,0(r4) | 297 | dstnr; sth r6,0(r4) |
282 | addi r4,r4,2 | 298 | addi r4,r4,2 |
283 | bdnz 1b | 299 | bdnz 1b |
284 | 300 | ||
@@ -392,10 +408,10 @@ dest; std r16,56(r4) | |||
392 | 408 | ||
393 | mtctr r6 | 409 | mtctr r6 |
394 | 3: | 410 | 3: |
395 | source; ld r6,0(r3) | 411 | srcnr; ld r6,0(r3) |
396 | addi r3,r3,8 | 412 | addi r3,r3,8 |
397 | adde r0,r0,r6 | 413 | adde r0,r0,r6 |
398 | dest; std r6,0(r4) | 414 | dstnr; std r6,0(r4) |
399 | addi r4,r4,8 | 415 | addi r4,r4,8 |
400 | bdnz 3b | 416 | bdnz 3b |
401 | 417 | ||
@@ -405,10 +421,10 @@ dest; std r6,0(r4) | |||
405 | srdi. r6,r5,2 | 421 | srdi. r6,r5,2 |
406 | beq .Lcopy_tail_halfword | 422 | beq .Lcopy_tail_halfword |
407 | 423 | ||
408 | source; lwz r6,0(r3) | 424 | srcnr; lwz r6,0(r3) |
409 | addi r3,r3,4 | 425 | addi r3,r3,4 |
410 | adde r0,r0,r6 | 426 | adde r0,r0,r6 |
411 | dest; stw r6,0(r4) | 427 | dstnr; stw r6,0(r4) |
412 | addi r4,r4,4 | 428 | addi r4,r4,4 |
413 | subi r5,r5,4 | 429 | subi r5,r5,4 |
414 | 430 | ||
@@ -416,10 +432,10 @@ dest; stw r6,0(r4) | |||
416 | srdi. r6,r5,1 | 432 | srdi. r6,r5,1 |
417 | beq .Lcopy_tail_byte | 433 | beq .Lcopy_tail_byte |
418 | 434 | ||
419 | source; lhz r6,0(r3) | 435 | srcnr; lhz r6,0(r3) |
420 | addi r3,r3,2 | 436 | addi r3,r3,2 |
421 | adde r0,r0,r6 | 437 | adde r0,r0,r6 |
422 | dest; sth r6,0(r4) | 438 | dstnr; sth r6,0(r4) |
423 | addi r4,r4,2 | 439 | addi r4,r4,2 |
424 | subi r5,r5,2 | 440 | subi r5,r5,2 |
425 | 441 | ||
@@ -427,10 +443,10 @@ dest; sth r6,0(r4) | |||
427 | andi. r6,r5,1 | 443 | andi. r6,r5,1 |
428 | beq .Lcopy_finish | 444 | beq .Lcopy_finish |
429 | 445 | ||
430 | source; lbz r6,0(r3) | 446 | srcnr; lbz r6,0(r3) |
431 | sldi r9,r6,8 /* Pad the byte out to 16 bits */ | 447 | sldi r9,r6,8 /* Pad the byte out to 16 bits */ |
432 | adde r0,r0,r9 | 448 | adde r0,r0,r9 |
433 | dest; stb r6,0(r4) | 449 | dstnr; stb r6,0(r4) |
434 | 450 | ||
435 | .Lcopy_finish: | 451 | .Lcopy_finish: |
436 | addze r0,r0 /* add in final carry */ | 452 | addze r0,r0 /* add in final carry */ |
@@ -440,6 +456,11 @@ dest; stb r6,0(r4) | |||
440 | blr | 456 | blr |
441 | 457 | ||
442 | .Lsrc_error: | 458 | .Lsrc_error: |
459 | ld r14,STK_REG(R14)(r1) | ||
460 | ld r15,STK_REG(R15)(r1) | ||
461 | ld r16,STK_REG(R16)(r1) | ||
462 | addi r1,r1,STACKFRAMESIZE | ||
463 | .Lsrc_error_nr: | ||
443 | cmpdi 0,r7,0 | 464 | cmpdi 0,r7,0 |
444 | beqlr | 465 | beqlr |
445 | li r6,-EFAULT | 466 | li r6,-EFAULT |
@@ -447,6 +468,11 @@ dest; stb r6,0(r4) | |||
447 | blr | 468 | blr |
448 | 469 | ||
449 | .Ldest_error: | 470 | .Ldest_error: |
471 | ld r14,STK_REG(R14)(r1) | ||
472 | ld r15,STK_REG(R15)(r1) | ||
473 | ld r16,STK_REG(R16)(r1) | ||
474 | addi r1,r1,STACKFRAMESIZE | ||
475 | .Ldest_error_nr: | ||
450 | cmpdi 0,r8,0 | 476 | cmpdi 0,r8,0 |
451 | beqlr | 477 | beqlr |
452 | li r6,-EFAULT | 478 | li r6,-EFAULT |
diff --git a/arch/powerpc/lib/copyuser_power7.S b/arch/powerpc/lib/copyuser_power7.S index d1f11795a7ad..e8e9c36dc784 100644 --- a/arch/powerpc/lib/copyuser_power7.S +++ b/arch/powerpc/lib/copyuser_power7.S | |||
@@ -19,6 +19,14 @@ | |||
19 | */ | 19 | */ |
20 | #include <asm/ppc_asm.h> | 20 | #include <asm/ppc_asm.h> |
21 | 21 | ||
22 | #ifdef __BIG_ENDIAN__ | ||
23 | #define LVS(VRT,RA,RB) lvsl VRT,RA,RB | ||
24 | #define VPERM(VRT,VRA,VRB,VRC) vperm VRT,VRA,VRB,VRC | ||
25 | #else | ||
26 | #define LVS(VRT,RA,RB) lvsr VRT,RA,RB | ||
27 | #define VPERM(VRT,VRA,VRB,VRC) vperm VRT,VRB,VRA,VRC | ||
28 | #endif | ||
29 | |||
22 | .macro err1 | 30 | .macro err1 |
23 | 100: | 31 | 100: |
24 | .section __ex_table,"a" | 32 | .section __ex_table,"a" |
@@ -552,13 +560,13 @@ err3; stw r7,4(r3) | |||
552 | li r10,32 | 560 | li r10,32 |
553 | li r11,48 | 561 | li r11,48 |
554 | 562 | ||
555 | lvsl vr16,0,r4 /* Setup permute control vector */ | 563 | LVS(vr16,0,r4) /* Setup permute control vector */ |
556 | err3; lvx vr0,0,r4 | 564 | err3; lvx vr0,0,r4 |
557 | addi r4,r4,16 | 565 | addi r4,r4,16 |
558 | 566 | ||
559 | bf cr7*4+3,5f | 567 | bf cr7*4+3,5f |
560 | err3; lvx vr1,r0,r4 | 568 | err3; lvx vr1,r0,r4 |
561 | vperm vr8,vr0,vr1,vr16 | 569 | VPERM(vr8,vr0,vr1,vr16) |
562 | addi r4,r4,16 | 570 | addi r4,r4,16 |
563 | err3; stvx vr8,r0,r3 | 571 | err3; stvx vr8,r0,r3 |
564 | addi r3,r3,16 | 572 | addi r3,r3,16 |
@@ -566,9 +574,9 @@ err3; stvx vr8,r0,r3 | |||
566 | 574 | ||
567 | 5: bf cr7*4+2,6f | 575 | 5: bf cr7*4+2,6f |
568 | err3; lvx vr1,r0,r4 | 576 | err3; lvx vr1,r0,r4 |
569 | vperm vr8,vr0,vr1,vr16 | 577 | VPERM(vr8,vr0,vr1,vr16) |
570 | err3; lvx vr0,r4,r9 | 578 | err3; lvx vr0,r4,r9 |
571 | vperm vr9,vr1,vr0,vr16 | 579 | VPERM(vr9,vr1,vr0,vr16) |
572 | addi r4,r4,32 | 580 | addi r4,r4,32 |
573 | err3; stvx vr8,r0,r3 | 581 | err3; stvx vr8,r0,r3 |
574 | err3; stvx vr9,r3,r9 | 582 | err3; stvx vr9,r3,r9 |
@@ -576,13 +584,13 @@ err3; stvx vr9,r3,r9 | |||
576 | 584 | ||
577 | 6: bf cr7*4+1,7f | 585 | 6: bf cr7*4+1,7f |
578 | err3; lvx vr3,r0,r4 | 586 | err3; lvx vr3,r0,r4 |
579 | vperm vr8,vr0,vr3,vr16 | 587 | VPERM(vr8,vr0,vr3,vr16) |
580 | err3; lvx vr2,r4,r9 | 588 | err3; lvx vr2,r4,r9 |
581 | vperm vr9,vr3,vr2,vr16 | 589 | VPERM(vr9,vr3,vr2,vr16) |
582 | err3; lvx vr1,r4,r10 | 590 | err3; lvx vr1,r4,r10 |
583 | vperm vr10,vr2,vr1,vr16 | 591 | VPERM(vr10,vr2,vr1,vr16) |
584 | err3; lvx vr0,r4,r11 | 592 | err3; lvx vr0,r4,r11 |
585 | vperm vr11,vr1,vr0,vr16 | 593 | VPERM(vr11,vr1,vr0,vr16) |
586 | addi r4,r4,64 | 594 | addi r4,r4,64 |
587 | err3; stvx vr8,r0,r3 | 595 | err3; stvx vr8,r0,r3 |
588 | err3; stvx vr9,r3,r9 | 596 | err3; stvx vr9,r3,r9 |
@@ -611,21 +619,21 @@ err3; stvx vr11,r3,r11 | |||
611 | .align 5 | 619 | .align 5 |
612 | 8: | 620 | 8: |
613 | err4; lvx vr7,r0,r4 | 621 | err4; lvx vr7,r0,r4 |
614 | vperm vr8,vr0,vr7,vr16 | 622 | VPERM(vr8,vr0,vr7,vr16) |
615 | err4; lvx vr6,r4,r9 | 623 | err4; lvx vr6,r4,r9 |
616 | vperm vr9,vr7,vr6,vr16 | 624 | VPERM(vr9,vr7,vr6,vr16) |
617 | err4; lvx vr5,r4,r10 | 625 | err4; lvx vr5,r4,r10 |
618 | vperm vr10,vr6,vr5,vr16 | 626 | VPERM(vr10,vr6,vr5,vr16) |
619 | err4; lvx vr4,r4,r11 | 627 | err4; lvx vr4,r4,r11 |
620 | vperm vr11,vr5,vr4,vr16 | 628 | VPERM(vr11,vr5,vr4,vr16) |
621 | err4; lvx vr3,r4,r12 | 629 | err4; lvx vr3,r4,r12 |
622 | vperm vr12,vr4,vr3,vr16 | 630 | VPERM(vr12,vr4,vr3,vr16) |
623 | err4; lvx vr2,r4,r14 | 631 | err4; lvx vr2,r4,r14 |
624 | vperm vr13,vr3,vr2,vr16 | 632 | VPERM(vr13,vr3,vr2,vr16) |
625 | err4; lvx vr1,r4,r15 | 633 | err4; lvx vr1,r4,r15 |
626 | vperm vr14,vr2,vr1,vr16 | 634 | VPERM(vr14,vr2,vr1,vr16) |
627 | err4; lvx vr0,r4,r16 | 635 | err4; lvx vr0,r4,r16 |
628 | vperm vr15,vr1,vr0,vr16 | 636 | VPERM(vr15,vr1,vr0,vr16) |
629 | addi r4,r4,128 | 637 | addi r4,r4,128 |
630 | err4; stvx vr8,r0,r3 | 638 | err4; stvx vr8,r0,r3 |
631 | err4; stvx vr9,r3,r9 | 639 | err4; stvx vr9,r3,r9 |
@@ -649,13 +657,13 @@ err4; stvx vr15,r3,r16 | |||
649 | 657 | ||
650 | bf cr7*4+1,9f | 658 | bf cr7*4+1,9f |
651 | err3; lvx vr3,r0,r4 | 659 | err3; lvx vr3,r0,r4 |
652 | vperm vr8,vr0,vr3,vr16 | 660 | VPERM(vr8,vr0,vr3,vr16) |
653 | err3; lvx vr2,r4,r9 | 661 | err3; lvx vr2,r4,r9 |
654 | vperm vr9,vr3,vr2,vr16 | 662 | VPERM(vr9,vr3,vr2,vr16) |
655 | err3; lvx vr1,r4,r10 | 663 | err3; lvx vr1,r4,r10 |
656 | vperm vr10,vr2,vr1,vr16 | 664 | VPERM(vr10,vr2,vr1,vr16) |
657 | err3; lvx vr0,r4,r11 | 665 | err3; lvx vr0,r4,r11 |
658 | vperm vr11,vr1,vr0,vr16 | 666 | VPERM(vr11,vr1,vr0,vr16) |
659 | addi r4,r4,64 | 667 | addi r4,r4,64 |
660 | err3; stvx vr8,r0,r3 | 668 | err3; stvx vr8,r0,r3 |
661 | err3; stvx vr9,r3,r9 | 669 | err3; stvx vr9,r3,r9 |
@@ -665,9 +673,9 @@ err3; stvx vr11,r3,r11 | |||
665 | 673 | ||
666 | 9: bf cr7*4+2,10f | 674 | 9: bf cr7*4+2,10f |
667 | err3; lvx vr1,r0,r4 | 675 | err3; lvx vr1,r0,r4 |
668 | vperm vr8,vr0,vr1,vr16 | 676 | VPERM(vr8,vr0,vr1,vr16) |
669 | err3; lvx vr0,r4,r9 | 677 | err3; lvx vr0,r4,r9 |
670 | vperm vr9,vr1,vr0,vr16 | 678 | VPERM(vr9,vr1,vr0,vr16) |
671 | addi r4,r4,32 | 679 | addi r4,r4,32 |
672 | err3; stvx vr8,r0,r3 | 680 | err3; stvx vr8,r0,r3 |
673 | err3; stvx vr9,r3,r9 | 681 | err3; stvx vr9,r3,r9 |
@@ -675,7 +683,7 @@ err3; stvx vr9,r3,r9 | |||
675 | 683 | ||
676 | 10: bf cr7*4+3,11f | 684 | 10: bf cr7*4+3,11f |
677 | err3; lvx vr1,r0,r4 | 685 | err3; lvx vr1,r0,r4 |
678 | vperm vr8,vr0,vr1,vr16 | 686 | VPERM(vr8,vr0,vr1,vr16) |
679 | addi r4,r4,16 | 687 | addi r4,r4,16 |
680 | err3; stvx vr8,r0,r3 | 688 | err3; stvx vr8,r0,r3 |
681 | addi r3,r3,16 | 689 | addi r3,r3,16 |
diff --git a/arch/powerpc/lib/memcpy_power7.S b/arch/powerpc/lib/memcpy_power7.S index 0663630baf3b..e4177dbea6bd 100644 --- a/arch/powerpc/lib/memcpy_power7.S +++ b/arch/powerpc/lib/memcpy_power7.S | |||
@@ -20,6 +20,15 @@ | |||
20 | #include <asm/ppc_asm.h> | 20 | #include <asm/ppc_asm.h> |
21 | 21 | ||
22 | _GLOBAL(memcpy_power7) | 22 | _GLOBAL(memcpy_power7) |
23 | |||
24 | #ifdef __BIG_ENDIAN__ | ||
25 | #define LVS(VRT,RA,RB) lvsl VRT,RA,RB | ||
26 | #define VPERM(VRT,VRA,VRB,VRC) vperm VRT,VRA,VRB,VRC | ||
27 | #else | ||
28 | #define LVS(VRT,RA,RB) lvsr VRT,RA,RB | ||
29 | #define VPERM(VRT,VRA,VRB,VRC) vperm VRT,VRB,VRA,VRC | ||
30 | #endif | ||
31 | |||
23 | #ifdef CONFIG_ALTIVEC | 32 | #ifdef CONFIG_ALTIVEC |
24 | cmpldi r5,16 | 33 | cmpldi r5,16 |
25 | cmpldi cr1,r5,4096 | 34 | cmpldi cr1,r5,4096 |
@@ -485,13 +494,13 @@ _GLOBAL(memcpy_power7) | |||
485 | li r10,32 | 494 | li r10,32 |
486 | li r11,48 | 495 | li r11,48 |
487 | 496 | ||
488 | lvsl vr16,0,r4 /* Setup permute control vector */ | 497 | LVS(vr16,0,r4) /* Setup permute control vector */ |
489 | lvx vr0,0,r4 | 498 | lvx vr0,0,r4 |
490 | addi r4,r4,16 | 499 | addi r4,r4,16 |
491 | 500 | ||
492 | bf cr7*4+3,5f | 501 | bf cr7*4+3,5f |
493 | lvx vr1,r0,r4 | 502 | lvx vr1,r0,r4 |
494 | vperm vr8,vr0,vr1,vr16 | 503 | VPERM(vr8,vr0,vr1,vr16) |
495 | addi r4,r4,16 | 504 | addi r4,r4,16 |
496 | stvx vr8,r0,r3 | 505 | stvx vr8,r0,r3 |
497 | addi r3,r3,16 | 506 | addi r3,r3,16 |
@@ -499,9 +508,9 @@ _GLOBAL(memcpy_power7) | |||
499 | 508 | ||
500 | 5: bf cr7*4+2,6f | 509 | 5: bf cr7*4+2,6f |
501 | lvx vr1,r0,r4 | 510 | lvx vr1,r0,r4 |
502 | vperm vr8,vr0,vr1,vr16 | 511 | VPERM(vr8,vr0,vr1,vr16) |
503 | lvx vr0,r4,r9 | 512 | lvx vr0,r4,r9 |
504 | vperm vr9,vr1,vr0,vr16 | 513 | VPERM(vr9,vr1,vr0,vr16) |
505 | addi r4,r4,32 | 514 | addi r4,r4,32 |
506 | stvx vr8,r0,r3 | 515 | stvx vr8,r0,r3 |
507 | stvx vr9,r3,r9 | 516 | stvx vr9,r3,r9 |
@@ -509,13 +518,13 @@ _GLOBAL(memcpy_power7) | |||
509 | 518 | ||
510 | 6: bf cr7*4+1,7f | 519 | 6: bf cr7*4+1,7f |
511 | lvx vr3,r0,r4 | 520 | lvx vr3,r0,r4 |
512 | vperm vr8,vr0,vr3,vr16 | 521 | VPERM(vr8,vr0,vr3,vr16) |
513 | lvx vr2,r4,r9 | 522 | lvx vr2,r4,r9 |
514 | vperm vr9,vr3,vr2,vr16 | 523 | VPERM(vr9,vr3,vr2,vr16) |
515 | lvx vr1,r4,r10 | 524 | lvx vr1,r4,r10 |
516 | vperm vr10,vr2,vr1,vr16 | 525 | VPERM(vr10,vr2,vr1,vr16) |
517 | lvx vr0,r4,r11 | 526 | lvx vr0,r4,r11 |
518 | vperm vr11,vr1,vr0,vr16 | 527 | VPERM(vr11,vr1,vr0,vr16) |
519 | addi r4,r4,64 | 528 | addi r4,r4,64 |
520 | stvx vr8,r0,r3 | 529 | stvx vr8,r0,r3 |
521 | stvx vr9,r3,r9 | 530 | stvx vr9,r3,r9 |
@@ -544,21 +553,21 @@ _GLOBAL(memcpy_power7) | |||
544 | .align 5 | 553 | .align 5 |
545 | 8: | 554 | 8: |
546 | lvx vr7,r0,r4 | 555 | lvx vr7,r0,r4 |
547 | vperm vr8,vr0,vr7,vr16 | 556 | VPERM(vr8,vr0,vr7,vr16) |
548 | lvx vr6,r4,r9 | 557 | lvx vr6,r4,r9 |
549 | vperm vr9,vr7,vr6,vr16 | 558 | VPERM(vr9,vr7,vr6,vr16) |
550 | lvx vr5,r4,r10 | 559 | lvx vr5,r4,r10 |
551 | vperm vr10,vr6,vr5,vr16 | 560 | VPERM(vr10,vr6,vr5,vr16) |
552 | lvx vr4,r4,r11 | 561 | lvx vr4,r4,r11 |
553 | vperm vr11,vr5,vr4,vr16 | 562 | VPERM(vr11,vr5,vr4,vr16) |
554 | lvx vr3,r4,r12 | 563 | lvx vr3,r4,r12 |
555 | vperm vr12,vr4,vr3,vr16 | 564 | VPERM(vr12,vr4,vr3,vr16) |
556 | lvx vr2,r4,r14 | 565 | lvx vr2,r4,r14 |
557 | vperm vr13,vr3,vr2,vr16 | 566 | VPERM(vr13,vr3,vr2,vr16) |
558 | lvx vr1,r4,r15 | 567 | lvx vr1,r4,r15 |
559 | vperm vr14,vr2,vr1,vr16 | 568 | VPERM(vr14,vr2,vr1,vr16) |
560 | lvx vr0,r4,r16 | 569 | lvx vr0,r4,r16 |
561 | vperm vr15,vr1,vr0,vr16 | 570 | VPERM(vr15,vr1,vr0,vr16) |
562 | addi r4,r4,128 | 571 | addi r4,r4,128 |
563 | stvx vr8,r0,r3 | 572 | stvx vr8,r0,r3 |
564 | stvx vr9,r3,r9 | 573 | stvx vr9,r3,r9 |
@@ -582,13 +591,13 @@ _GLOBAL(memcpy_power7) | |||
582 | 591 | ||
583 | bf cr7*4+1,9f | 592 | bf cr7*4+1,9f |
584 | lvx vr3,r0,r4 | 593 | lvx vr3,r0,r4 |
585 | vperm vr8,vr0,vr3,vr16 | 594 | VPERM(vr8,vr0,vr3,vr16) |
586 | lvx vr2,r4,r9 | 595 | lvx vr2,r4,r9 |
587 | vperm vr9,vr3,vr2,vr16 | 596 | VPERM(vr9,vr3,vr2,vr16) |
588 | lvx vr1,r4,r10 | 597 | lvx vr1,r4,r10 |
589 | vperm vr10,vr2,vr1,vr16 | 598 | VPERM(vr10,vr2,vr1,vr16) |
590 | lvx vr0,r4,r11 | 599 | lvx vr0,r4,r11 |
591 | vperm vr11,vr1,vr0,vr16 | 600 | VPERM(vr11,vr1,vr0,vr16) |
592 | addi r4,r4,64 | 601 | addi r4,r4,64 |
593 | stvx vr8,r0,r3 | 602 | stvx vr8,r0,r3 |
594 | stvx vr9,r3,r9 | 603 | stvx vr9,r3,r9 |
@@ -598,9 +607,9 @@ _GLOBAL(memcpy_power7) | |||
598 | 607 | ||
599 | 9: bf cr7*4+2,10f | 608 | 9: bf cr7*4+2,10f |
600 | lvx vr1,r0,r4 | 609 | lvx vr1,r0,r4 |
601 | vperm vr8,vr0,vr1,vr16 | 610 | VPERM(vr8,vr0,vr1,vr16) |
602 | lvx vr0,r4,r9 | 611 | lvx vr0,r4,r9 |
603 | vperm vr9,vr1,vr0,vr16 | 612 | VPERM(vr9,vr1,vr0,vr16) |
604 | addi r4,r4,32 | 613 | addi r4,r4,32 |
605 | stvx vr8,r0,r3 | 614 | stvx vr8,r0,r3 |
606 | stvx vr9,r3,r9 | 615 | stvx vr9,r3,r9 |
@@ -608,7 +617,7 @@ _GLOBAL(memcpy_power7) | |||
608 | 617 | ||
609 | 10: bf cr7*4+3,11f | 618 | 10: bf cr7*4+3,11f |
610 | lvx vr1,r0,r4 | 619 | lvx vr1,r0,r4 |
611 | vperm vr8,vr0,vr1,vr16 | 620 | VPERM(vr8,vr0,vr1,vr16) |
612 | addi r4,r4,16 | 621 | addi r4,r4,16 |
613 | stvx vr8,r0,r3 | 622 | stvx vr8,r0,r3 |
614 | addi r3,r3,16 | 623 | addi r3,r3,16 |
diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c index a7ee978fb860..c0511c27a733 100644 --- a/arch/powerpc/lib/sstep.c +++ b/arch/powerpc/lib/sstep.c | |||
@@ -212,11 +212,19 @@ static int __kprobes read_mem_unaligned(unsigned long *dest, unsigned long ea, | |||
212 | { | 212 | { |
213 | int err; | 213 | int err; |
214 | unsigned long x, b, c; | 214 | unsigned long x, b, c; |
215 | #ifdef __LITTLE_ENDIAN__ | ||
216 | int len = nb; /* save a copy of the length for byte reversal */ | ||
217 | #endif | ||
215 | 218 | ||
216 | /* unaligned, do this in pieces */ | 219 | /* unaligned, do this in pieces */ |
217 | x = 0; | 220 | x = 0; |
218 | for (; nb > 0; nb -= c) { | 221 | for (; nb > 0; nb -= c) { |
222 | #ifdef __LITTLE_ENDIAN__ | ||
223 | c = 1; | ||
224 | #endif | ||
225 | #ifdef __BIG_ENDIAN__ | ||
219 | c = max_align(ea); | 226 | c = max_align(ea); |
227 | #endif | ||
220 | if (c > nb) | 228 | if (c > nb) |
221 | c = max_align(nb); | 229 | c = max_align(nb); |
222 | err = read_mem_aligned(&b, ea, c); | 230 | err = read_mem_aligned(&b, ea, c); |
@@ -225,7 +233,24 @@ static int __kprobes read_mem_unaligned(unsigned long *dest, unsigned long ea, | |||
225 | x = (x << (8 * c)) + b; | 233 | x = (x << (8 * c)) + b; |
226 | ea += c; | 234 | ea += c; |
227 | } | 235 | } |
236 | #ifdef __LITTLE_ENDIAN__ | ||
237 | switch (len) { | ||
238 | case 2: | ||
239 | *dest = byterev_2(x); | ||
240 | break; | ||
241 | case 4: | ||
242 | *dest = byterev_4(x); | ||
243 | break; | ||
244 | #ifdef __powerpc64__ | ||
245 | case 8: | ||
246 | *dest = byterev_8(x); | ||
247 | break; | ||
248 | #endif | ||
249 | } | ||
250 | #endif | ||
251 | #ifdef __BIG_ENDIAN__ | ||
228 | *dest = x; | 252 | *dest = x; |
253 | #endif | ||
229 | return 0; | 254 | return 0; |
230 | } | 255 | } |
231 | 256 | ||
@@ -273,9 +298,29 @@ static int __kprobes write_mem_unaligned(unsigned long val, unsigned long ea, | |||
273 | int err; | 298 | int err; |
274 | unsigned long c; | 299 | unsigned long c; |
275 | 300 | ||
301 | #ifdef __LITTLE_ENDIAN__ | ||
302 | switch (nb) { | ||
303 | case 2: | ||
304 | val = byterev_2(val); | ||
305 | break; | ||
306 | case 4: | ||
307 | val = byterev_4(val); | ||
308 | break; | ||
309 | #ifdef __powerpc64__ | ||
310 | case 8: | ||
311 | val = byterev_8(val); | ||
312 | break; | ||
313 | #endif | ||
314 | } | ||
315 | #endif | ||
276 | /* unaligned or little-endian, do this in pieces */ | 316 | /* unaligned or little-endian, do this in pieces */ |
277 | for (; nb > 0; nb -= c) { | 317 | for (; nb > 0; nb -= c) { |
318 | #ifdef __LITTLE_ENDIAN__ | ||
319 | c = 1; | ||
320 | #endif | ||
321 | #ifdef __BIG_ENDIAN__ | ||
278 | c = max_align(ea); | 322 | c = max_align(ea); |
323 | #endif | ||
279 | if (c > nb) | 324 | if (c > nb) |
280 | c = max_align(nb); | 325 | c = max_align(nb); |
281 | err = write_mem_aligned(val >> (nb - c) * 8, ea, c); | 326 | err = write_mem_aligned(val >> (nb - c) * 8, ea, c); |
@@ -310,22 +355,36 @@ static int __kprobes do_fp_load(int rn, int (*func)(int, unsigned long), | |||
310 | struct pt_regs *regs) | 355 | struct pt_regs *regs) |
311 | { | 356 | { |
312 | int err; | 357 | int err; |
313 | unsigned long val[sizeof(double) / sizeof(long)]; | 358 | union { |
359 | double dbl; | ||
360 | unsigned long ul[2]; | ||
361 | struct { | ||
362 | #ifdef __BIG_ENDIAN__ | ||
363 | unsigned _pad_; | ||
364 | unsigned word; | ||
365 | #endif | ||
366 | #ifdef __LITTLE_ENDIAN__ | ||
367 | unsigned word; | ||
368 | unsigned _pad_; | ||
369 | #endif | ||
370 | } single; | ||
371 | } data; | ||
314 | unsigned long ptr; | 372 | unsigned long ptr; |
315 | 373 | ||
316 | if (!address_ok(regs, ea, nb)) | 374 | if (!address_ok(regs, ea, nb)) |
317 | return -EFAULT; | 375 | return -EFAULT; |
318 | if ((ea & 3) == 0) | 376 | if ((ea & 3) == 0) |
319 | return (*func)(rn, ea); | 377 | return (*func)(rn, ea); |
320 | ptr = (unsigned long) &val[0]; | 378 | ptr = (unsigned long) &data.ul; |
321 | if (sizeof(unsigned long) == 8 || nb == 4) { | 379 | if (sizeof(unsigned long) == 8 || nb == 4) { |
322 | err = read_mem_unaligned(&val[0], ea, nb, regs); | 380 | err = read_mem_unaligned(&data.ul[0], ea, nb, regs); |
323 | ptr += sizeof(unsigned long) - nb; | 381 | if (nb == 4) |
382 | ptr = (unsigned long)&(data.single.word); | ||
324 | } else { | 383 | } else { |
325 | /* reading a double on 32-bit */ | 384 | /* reading a double on 32-bit */ |
326 | err = read_mem_unaligned(&val[0], ea, 4, regs); | 385 | err = read_mem_unaligned(&data.ul[0], ea, 4, regs); |
327 | if (!err) | 386 | if (!err) |
328 | err = read_mem_unaligned(&val[1], ea + 4, 4, regs); | 387 | err = read_mem_unaligned(&data.ul[1], ea + 4, 4, regs); |
329 | } | 388 | } |
330 | if (err) | 389 | if (err) |
331 | return err; | 390 | return err; |
@@ -337,28 +396,42 @@ static int __kprobes do_fp_store(int rn, int (*func)(int, unsigned long), | |||
337 | struct pt_regs *regs) | 396 | struct pt_regs *regs) |
338 | { | 397 | { |
339 | int err; | 398 | int err; |
340 | unsigned long val[sizeof(double) / sizeof(long)]; | 399 | union { |
400 | double dbl; | ||
401 | unsigned long ul[2]; | ||
402 | struct { | ||
403 | #ifdef __BIG_ENDIAN__ | ||
404 | unsigned _pad_; | ||
405 | unsigned word; | ||
406 | #endif | ||
407 | #ifdef __LITTLE_ENDIAN__ | ||
408 | unsigned word; | ||
409 | unsigned _pad_; | ||
410 | #endif | ||
411 | } single; | ||
412 | } data; | ||
341 | unsigned long ptr; | 413 | unsigned long ptr; |
342 | 414 | ||
343 | if (!address_ok(regs, ea, nb)) | 415 | if (!address_ok(regs, ea, nb)) |
344 | return -EFAULT; | 416 | return -EFAULT; |
345 | if ((ea & 3) == 0) | 417 | if ((ea & 3) == 0) |
346 | return (*func)(rn, ea); | 418 | return (*func)(rn, ea); |
347 | ptr = (unsigned long) &val[0]; | 419 | ptr = (unsigned long) &data.ul[0]; |
348 | if (sizeof(unsigned long) == 8 || nb == 4) { | 420 | if (sizeof(unsigned long) == 8 || nb == 4) { |
349 | ptr += sizeof(unsigned long) - nb; | 421 | if (nb == 4) |
422 | ptr = (unsigned long)&(data.single.word); | ||
350 | err = (*func)(rn, ptr); | 423 | err = (*func)(rn, ptr); |
351 | if (err) | 424 | if (err) |
352 | return err; | 425 | return err; |
353 | err = write_mem_unaligned(val[0], ea, nb, regs); | 426 | err = write_mem_unaligned(data.ul[0], ea, nb, regs); |
354 | } else { | 427 | } else { |
355 | /* writing a double on 32-bit */ | 428 | /* writing a double on 32-bit */ |
356 | err = (*func)(rn, ptr); | 429 | err = (*func)(rn, ptr); |
357 | if (err) | 430 | if (err) |
358 | return err; | 431 | return err; |
359 | err = write_mem_unaligned(val[0], ea, 4, regs); | 432 | err = write_mem_unaligned(data.ul[0], ea, 4, regs); |
360 | if (!err) | 433 | if (!err) |
361 | err = write_mem_unaligned(val[1], ea + 4, 4, regs); | 434 | err = write_mem_unaligned(data.ul[1], ea + 4, 4, regs); |
362 | } | 435 | } |
363 | return err; | 436 | return err; |
364 | } | 437 | } |
@@ -1505,6 +1578,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) | |||
1505 | */ | 1578 | */ |
1506 | if ((ra == 1) && !(regs->msr & MSR_PR) \ | 1579 | if ((ra == 1) && !(regs->msr & MSR_PR) \ |
1507 | && (val3 >= (regs->gpr[1] - STACK_INT_FRAME_SIZE))) { | 1580 | && (val3 >= (regs->gpr[1] - STACK_INT_FRAME_SIZE))) { |
1581 | #ifdef CONFIG_PPC32 | ||
1508 | /* | 1582 | /* |
1509 | * Check if we will touch kernel sack overflow | 1583 | * Check if we will touch kernel sack overflow |
1510 | */ | 1584 | */ |
@@ -1513,7 +1587,7 @@ int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr) | |||
1513 | err = -EINVAL; | 1587 | err = -EINVAL; |
1514 | break; | 1588 | break; |
1515 | } | 1589 | } |
1516 | 1590 | #endif /* CONFIG_PPC32 */ | |
1517 | /* | 1591 | /* |
1518 | * Check if we already set since that means we'll | 1592 | * Check if we already set since that means we'll |
1519 | * lose the previous value. | 1593 | * lose the previous value. |
diff --git a/arch/powerpc/lib/xor_vmx.c b/arch/powerpc/lib/xor_vmx.c new file mode 100644 index 000000000000..e905f7c2ea7b --- /dev/null +++ b/arch/powerpc/lib/xor_vmx.c | |||
@@ -0,0 +1,177 @@ | |||
1 | /* | ||
2 | * This program is free software; you can redistribute it and/or modify | ||
3 | * it under the terms of the GNU General Public License as published by | ||
4 | * the Free Software Foundation; either version 2 of the License, or | ||
5 | * (at your option) any later version. | ||
6 | * | ||
7 | * This program is distributed in the hope that it will be useful, | ||
8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
10 | * GNU General Public License for more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License | ||
13 | * along with this program; if not, write to the Free Software | ||
14 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
15 | * | ||
16 | * Copyright (C) IBM Corporation, 2012 | ||
17 | * | ||
18 | * Author: Anton Blanchard <anton@au.ibm.com> | ||
19 | */ | ||
20 | #include <altivec.h> | ||
21 | |||
22 | #include <linux/preempt.h> | ||
23 | #include <linux/export.h> | ||
24 | #include <linux/sched.h> | ||
25 | #include <asm/switch_to.h> | ||
26 | |||
27 | typedef vector signed char unative_t; | ||
28 | |||
29 | #define DEFINE(V) \ | ||
30 | unative_t *V = (unative_t *)V##_in; \ | ||
31 | unative_t V##_0, V##_1, V##_2, V##_3 | ||
32 | |||
33 | #define LOAD(V) \ | ||
34 | do { \ | ||
35 | V##_0 = V[0]; \ | ||
36 | V##_1 = V[1]; \ | ||
37 | V##_2 = V[2]; \ | ||
38 | V##_3 = V[3]; \ | ||
39 | } while (0) | ||
40 | |||
41 | #define STORE(V) \ | ||
42 | do { \ | ||
43 | V[0] = V##_0; \ | ||
44 | V[1] = V##_1; \ | ||
45 | V[2] = V##_2; \ | ||
46 | V[3] = V##_3; \ | ||
47 | } while (0) | ||
48 | |||
49 | #define XOR(V1, V2) \ | ||
50 | do { \ | ||
51 | V1##_0 = vec_xor(V1##_0, V2##_0); \ | ||
52 | V1##_1 = vec_xor(V1##_1, V2##_1); \ | ||
53 | V1##_2 = vec_xor(V1##_2, V2##_2); \ | ||
54 | V1##_3 = vec_xor(V1##_3, V2##_3); \ | ||
55 | } while (0) | ||
56 | |||
57 | void xor_altivec_2(unsigned long bytes, unsigned long *v1_in, | ||
58 | unsigned long *v2_in) | ||
59 | { | ||
60 | DEFINE(v1); | ||
61 | DEFINE(v2); | ||
62 | unsigned long lines = bytes / (sizeof(unative_t)) / 4; | ||
63 | |||
64 | preempt_disable(); | ||
65 | enable_kernel_altivec(); | ||
66 | |||
67 | do { | ||
68 | LOAD(v1); | ||
69 | LOAD(v2); | ||
70 | XOR(v1, v2); | ||
71 | STORE(v1); | ||
72 | |||
73 | v1 += 4; | ||
74 | v2 += 4; | ||
75 | } while (--lines > 0); | ||
76 | |||
77 | preempt_enable(); | ||
78 | } | ||
79 | EXPORT_SYMBOL(xor_altivec_2); | ||
80 | |||
81 | void xor_altivec_3(unsigned long bytes, unsigned long *v1_in, | ||
82 | unsigned long *v2_in, unsigned long *v3_in) | ||
83 | { | ||
84 | DEFINE(v1); | ||
85 | DEFINE(v2); | ||
86 | DEFINE(v3); | ||
87 | unsigned long lines = bytes / (sizeof(unative_t)) / 4; | ||
88 | |||
89 | preempt_disable(); | ||
90 | enable_kernel_altivec(); | ||
91 | |||
92 | do { | ||
93 | LOAD(v1); | ||
94 | LOAD(v2); | ||
95 | LOAD(v3); | ||
96 | XOR(v1, v2); | ||
97 | XOR(v1, v3); | ||
98 | STORE(v1); | ||
99 | |||
100 | v1 += 4; | ||
101 | v2 += 4; | ||
102 | v3 += 4; | ||
103 | } while (--lines > 0); | ||
104 | |||
105 | preempt_enable(); | ||
106 | } | ||
107 | EXPORT_SYMBOL(xor_altivec_3); | ||
108 | |||
109 | void xor_altivec_4(unsigned long bytes, unsigned long *v1_in, | ||
110 | unsigned long *v2_in, unsigned long *v3_in, | ||
111 | unsigned long *v4_in) | ||
112 | { | ||
113 | DEFINE(v1); | ||
114 | DEFINE(v2); | ||
115 | DEFINE(v3); | ||
116 | DEFINE(v4); | ||
117 | unsigned long lines = bytes / (sizeof(unative_t)) / 4; | ||
118 | |||
119 | preempt_disable(); | ||
120 | enable_kernel_altivec(); | ||
121 | |||
122 | do { | ||
123 | LOAD(v1); | ||
124 | LOAD(v2); | ||
125 | LOAD(v3); | ||
126 | LOAD(v4); | ||
127 | XOR(v1, v2); | ||
128 | XOR(v3, v4); | ||
129 | XOR(v1, v3); | ||
130 | STORE(v1); | ||
131 | |||
132 | v1 += 4; | ||
133 | v2 += 4; | ||
134 | v3 += 4; | ||
135 | v4 += 4; | ||
136 | } while (--lines > 0); | ||
137 | |||
138 | preempt_enable(); | ||
139 | } | ||
140 | EXPORT_SYMBOL(xor_altivec_4); | ||
141 | |||
142 | void xor_altivec_5(unsigned long bytes, unsigned long *v1_in, | ||
143 | unsigned long *v2_in, unsigned long *v3_in, | ||
144 | unsigned long *v4_in, unsigned long *v5_in) | ||
145 | { | ||
146 | DEFINE(v1); | ||
147 | DEFINE(v2); | ||
148 | DEFINE(v3); | ||
149 | DEFINE(v4); | ||
150 | DEFINE(v5); | ||
151 | unsigned long lines = bytes / (sizeof(unative_t)) / 4; | ||
152 | |||
153 | preempt_disable(); | ||
154 | enable_kernel_altivec(); | ||
155 | |||
156 | do { | ||
157 | LOAD(v1); | ||
158 | LOAD(v2); | ||
159 | LOAD(v3); | ||
160 | LOAD(v4); | ||
161 | LOAD(v5); | ||
162 | XOR(v1, v2); | ||
163 | XOR(v3, v4); | ||
164 | XOR(v1, v5); | ||
165 | XOR(v1, v3); | ||
166 | STORE(v1); | ||
167 | |||
168 | v1 += 4; | ||
169 | v2 += 4; | ||
170 | v3 += 4; | ||
171 | v4 += 4; | ||
172 | v5 += 4; | ||
173 | } while (--lines > 0); | ||
174 | |||
175 | preempt_enable(); | ||
176 | } | ||
177 | EXPORT_SYMBOL(xor_altivec_5); | ||
diff --git a/arch/powerpc/mm/dma-noncoherent.c b/arch/powerpc/mm/dma-noncoherent.c index 6747eece84af..7b6c10750179 100644 --- a/arch/powerpc/mm/dma-noncoherent.c +++ b/arch/powerpc/mm/dma-noncoherent.c | |||
@@ -287,9 +287,7 @@ void __dma_free_coherent(size_t size, void *vaddr) | |||
287 | pte_clear(&init_mm, addr, ptep); | 287 | pte_clear(&init_mm, addr, ptep); |
288 | if (pfn_valid(pfn)) { | 288 | if (pfn_valid(pfn)) { |
289 | struct page *page = pfn_to_page(pfn); | 289 | struct page *page = pfn_to_page(pfn); |
290 | 290 | __free_reserved_page(page); | |
291 | ClearPageReserved(page); | ||
292 | __free_page(page); | ||
293 | } | 291 | } |
294 | } | 292 | } |
295 | addr += PAGE_SIZE; | 293 | addr += PAGE_SIZE; |
diff --git a/arch/powerpc/mm/hash_native_64.c b/arch/powerpc/mm/hash_native_64.c index c33d939120c9..3ea26c25590b 100644 --- a/arch/powerpc/mm/hash_native_64.c +++ b/arch/powerpc/mm/hash_native_64.c | |||
@@ -35,7 +35,11 @@ | |||
35 | #define DBG_LOW(fmt...) | 35 | #define DBG_LOW(fmt...) |
36 | #endif | 36 | #endif |
37 | 37 | ||
38 | #ifdef __BIG_ENDIAN__ | ||
38 | #define HPTE_LOCK_BIT 3 | 39 | #define HPTE_LOCK_BIT 3 |
40 | #else | ||
41 | #define HPTE_LOCK_BIT (56+3) | ||
42 | #endif | ||
39 | 43 | ||
40 | DEFINE_RAW_SPINLOCK(native_tlbie_lock); | 44 | DEFINE_RAW_SPINLOCK(native_tlbie_lock); |
41 | 45 | ||
@@ -172,7 +176,7 @@ static inline void tlbie(unsigned long vpn, int psize, int apsize, | |||
172 | 176 | ||
173 | static inline void native_lock_hpte(struct hash_pte *hptep) | 177 | static inline void native_lock_hpte(struct hash_pte *hptep) |
174 | { | 178 | { |
175 | unsigned long *word = &hptep->v; | 179 | unsigned long *word = (unsigned long *)&hptep->v; |
176 | 180 | ||
177 | while (1) { | 181 | while (1) { |
178 | if (!test_and_set_bit_lock(HPTE_LOCK_BIT, word)) | 182 | if (!test_and_set_bit_lock(HPTE_LOCK_BIT, word)) |
@@ -184,7 +188,7 @@ static inline void native_lock_hpte(struct hash_pte *hptep) | |||
184 | 188 | ||
185 | static inline void native_unlock_hpte(struct hash_pte *hptep) | 189 | static inline void native_unlock_hpte(struct hash_pte *hptep) |
186 | { | 190 | { |
187 | unsigned long *word = &hptep->v; | 191 | unsigned long *word = (unsigned long *)&hptep->v; |
188 | 192 | ||
189 | clear_bit_unlock(HPTE_LOCK_BIT, word); | 193 | clear_bit_unlock(HPTE_LOCK_BIT, word); |
190 | } | 194 | } |
@@ -204,10 +208,10 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long vpn, | |||
204 | } | 208 | } |
205 | 209 | ||
206 | for (i = 0; i < HPTES_PER_GROUP; i++) { | 210 | for (i = 0; i < HPTES_PER_GROUP; i++) { |
207 | if (! (hptep->v & HPTE_V_VALID)) { | 211 | if (! (be64_to_cpu(hptep->v) & HPTE_V_VALID)) { |
208 | /* retry with lock held */ | 212 | /* retry with lock held */ |
209 | native_lock_hpte(hptep); | 213 | native_lock_hpte(hptep); |
210 | if (! (hptep->v & HPTE_V_VALID)) | 214 | if (! (be64_to_cpu(hptep->v) & HPTE_V_VALID)) |
211 | break; | 215 | break; |
212 | native_unlock_hpte(hptep); | 216 | native_unlock_hpte(hptep); |
213 | } | 217 | } |
@@ -226,14 +230,14 @@ static long native_hpte_insert(unsigned long hpte_group, unsigned long vpn, | |||
226 | i, hpte_v, hpte_r); | 230 | i, hpte_v, hpte_r); |
227 | } | 231 | } |
228 | 232 | ||
229 | hptep->r = hpte_r; | 233 | hptep->r = cpu_to_be64(hpte_r); |
230 | /* Guarantee the second dword is visible before the valid bit */ | 234 | /* Guarantee the second dword is visible before the valid bit */ |
231 | eieio(); | 235 | eieio(); |
232 | /* | 236 | /* |
233 | * Now set the first dword including the valid bit | 237 | * Now set the first dword including the valid bit |
234 | * NOTE: this also unlocks the hpte | 238 | * NOTE: this also unlocks the hpte |
235 | */ | 239 | */ |
236 | hptep->v = hpte_v; | 240 | hptep->v = cpu_to_be64(hpte_v); |
237 | 241 | ||
238 | __asm__ __volatile__ ("ptesync" : : : "memory"); | 242 | __asm__ __volatile__ ("ptesync" : : : "memory"); |
239 | 243 | ||
@@ -254,12 +258,12 @@ static long native_hpte_remove(unsigned long hpte_group) | |||
254 | 258 | ||
255 | for (i = 0; i < HPTES_PER_GROUP; i++) { | 259 | for (i = 0; i < HPTES_PER_GROUP; i++) { |
256 | hptep = htab_address + hpte_group + slot_offset; | 260 | hptep = htab_address + hpte_group + slot_offset; |
257 | hpte_v = hptep->v; | 261 | hpte_v = be64_to_cpu(hptep->v); |
258 | 262 | ||
259 | if ((hpte_v & HPTE_V_VALID) && !(hpte_v & HPTE_V_BOLTED)) { | 263 | if ((hpte_v & HPTE_V_VALID) && !(hpte_v & HPTE_V_BOLTED)) { |
260 | /* retry with lock held */ | 264 | /* retry with lock held */ |
261 | native_lock_hpte(hptep); | 265 | native_lock_hpte(hptep); |
262 | hpte_v = hptep->v; | 266 | hpte_v = be64_to_cpu(hptep->v); |
263 | if ((hpte_v & HPTE_V_VALID) | 267 | if ((hpte_v & HPTE_V_VALID) |
264 | && !(hpte_v & HPTE_V_BOLTED)) | 268 | && !(hpte_v & HPTE_V_BOLTED)) |
265 | break; | 269 | break; |
@@ -294,7 +298,7 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp, | |||
294 | 298 | ||
295 | native_lock_hpte(hptep); | 299 | native_lock_hpte(hptep); |
296 | 300 | ||
297 | hpte_v = hptep->v; | 301 | hpte_v = be64_to_cpu(hptep->v); |
298 | /* | 302 | /* |
299 | * We need to invalidate the TLB always because hpte_remove doesn't do | 303 | * We need to invalidate the TLB always because hpte_remove doesn't do |
300 | * a tlb invalidate. If a hash bucket gets full, we "evict" a more/less | 304 | * a tlb invalidate. If a hash bucket gets full, we "evict" a more/less |
@@ -308,8 +312,8 @@ static long native_hpte_updatepp(unsigned long slot, unsigned long newpp, | |||
308 | } else { | 312 | } else { |
309 | DBG_LOW(" -> hit\n"); | 313 | DBG_LOW(" -> hit\n"); |
310 | /* Update the HPTE */ | 314 | /* Update the HPTE */ |
311 | hptep->r = (hptep->r & ~(HPTE_R_PP | HPTE_R_N)) | | 315 | hptep->r = cpu_to_be64((be64_to_cpu(hptep->r) & ~(HPTE_R_PP | HPTE_R_N)) | |
312 | (newpp & (HPTE_R_PP | HPTE_R_N | HPTE_R_C)); | 316 | (newpp & (HPTE_R_PP | HPTE_R_N | HPTE_R_C))); |
313 | } | 317 | } |
314 | native_unlock_hpte(hptep); | 318 | native_unlock_hpte(hptep); |
315 | 319 | ||
@@ -334,7 +338,7 @@ static long native_hpte_find(unsigned long vpn, int psize, int ssize) | |||
334 | slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; | 338 | slot = (hash & htab_hash_mask) * HPTES_PER_GROUP; |
335 | for (i = 0; i < HPTES_PER_GROUP; i++) { | 339 | for (i = 0; i < HPTES_PER_GROUP; i++) { |
336 | hptep = htab_address + slot; | 340 | hptep = htab_address + slot; |
337 | hpte_v = hptep->v; | 341 | hpte_v = be64_to_cpu(hptep->v); |
338 | 342 | ||
339 | if (HPTE_V_COMPARE(hpte_v, want_v) && (hpte_v & HPTE_V_VALID)) | 343 | if (HPTE_V_COMPARE(hpte_v, want_v) && (hpte_v & HPTE_V_VALID)) |
340 | /* HPTE matches */ | 344 | /* HPTE matches */ |
@@ -369,8 +373,9 @@ static void native_hpte_updateboltedpp(unsigned long newpp, unsigned long ea, | |||
369 | hptep = htab_address + slot; | 373 | hptep = htab_address + slot; |
370 | 374 | ||
371 | /* Update the HPTE */ | 375 | /* Update the HPTE */ |
372 | hptep->r = (hptep->r & ~(HPTE_R_PP | HPTE_R_N)) | | 376 | hptep->r = cpu_to_be64((be64_to_cpu(hptep->r) & |
373 | (newpp & (HPTE_R_PP | HPTE_R_N)); | 377 | ~(HPTE_R_PP | HPTE_R_N)) | |
378 | (newpp & (HPTE_R_PP | HPTE_R_N))); | ||
374 | /* | 379 | /* |
375 | * Ensure it is out of the tlb too. Bolted entries base and | 380 | * Ensure it is out of the tlb too. Bolted entries base and |
376 | * actual page size will be same. | 381 | * actual page size will be same. |
@@ -392,7 +397,7 @@ static void native_hpte_invalidate(unsigned long slot, unsigned long vpn, | |||
392 | 397 | ||
393 | want_v = hpte_encode_avpn(vpn, bpsize, ssize); | 398 | want_v = hpte_encode_avpn(vpn, bpsize, ssize); |
394 | native_lock_hpte(hptep); | 399 | native_lock_hpte(hptep); |
395 | hpte_v = hptep->v; | 400 | hpte_v = be64_to_cpu(hptep->v); |
396 | 401 | ||
397 | /* | 402 | /* |
398 | * We need to invalidate the TLB always because hpte_remove doesn't do | 403 | * We need to invalidate the TLB always because hpte_remove doesn't do |
@@ -458,7 +463,7 @@ static void native_hugepage_invalidate(struct mm_struct *mm, | |||
458 | hptep = htab_address + slot; | 463 | hptep = htab_address + slot; |
459 | want_v = hpte_encode_avpn(vpn, psize, ssize); | 464 | want_v = hpte_encode_avpn(vpn, psize, ssize); |
460 | native_lock_hpte(hptep); | 465 | native_lock_hpte(hptep); |
461 | hpte_v = hptep->v; | 466 | hpte_v = be64_to_cpu(hptep->v); |
462 | 467 | ||
463 | /* Even if we miss, we need to invalidate the TLB */ | 468 | /* Even if we miss, we need to invalidate the TLB */ |
464 | if (!HPTE_V_COMPARE(hpte_v, want_v) || !(hpte_v & HPTE_V_VALID)) | 469 | if (!HPTE_V_COMPARE(hpte_v, want_v) || !(hpte_v & HPTE_V_VALID)) |
@@ -519,11 +524,12 @@ static void hpte_decode(struct hash_pte *hpte, unsigned long slot, | |||
519 | int *psize, int *apsize, int *ssize, unsigned long *vpn) | 524 | int *psize, int *apsize, int *ssize, unsigned long *vpn) |
520 | { | 525 | { |
521 | unsigned long avpn, pteg, vpi; | 526 | unsigned long avpn, pteg, vpi; |
522 | unsigned long hpte_v = hpte->v; | 527 | unsigned long hpte_v = be64_to_cpu(hpte->v); |
528 | unsigned long hpte_r = be64_to_cpu(hpte->r); | ||
523 | unsigned long vsid, seg_off; | 529 | unsigned long vsid, seg_off; |
524 | int size, a_size, shift; | 530 | int size, a_size, shift; |
525 | /* Look at the 8 bit LP value */ | 531 | /* Look at the 8 bit LP value */ |
526 | unsigned int lp = (hpte->r >> LP_SHIFT) & ((1 << LP_BITS) - 1); | 532 | unsigned int lp = (hpte_r >> LP_SHIFT) & ((1 << LP_BITS) - 1); |
527 | 533 | ||
528 | if (!(hpte_v & HPTE_V_LARGE)) { | 534 | if (!(hpte_v & HPTE_V_LARGE)) { |
529 | size = MMU_PAGE_4K; | 535 | size = MMU_PAGE_4K; |
@@ -612,7 +618,7 @@ static void native_hpte_clear(void) | |||
612 | * running, right? and for crash dump, we probably | 618 | * running, right? and for crash dump, we probably |
613 | * don't want to wait for a maybe bad cpu. | 619 | * don't want to wait for a maybe bad cpu. |
614 | */ | 620 | */ |
615 | hpte_v = hptep->v; | 621 | hpte_v = be64_to_cpu(hptep->v); |
616 | 622 | ||
617 | /* | 623 | /* |
618 | * Call __tlbie() here rather than tlbie() since we | 624 | * Call __tlbie() here rather than tlbie() since we |
@@ -664,7 +670,7 @@ static void native_flush_hash_range(unsigned long number, int local) | |||
664 | hptep = htab_address + slot; | 670 | hptep = htab_address + slot; |
665 | want_v = hpte_encode_avpn(vpn, psize, ssize); | 671 | want_v = hpte_encode_avpn(vpn, psize, ssize); |
666 | native_lock_hpte(hptep); | 672 | native_lock_hpte(hptep); |
667 | hpte_v = hptep->v; | 673 | hpte_v = be64_to_cpu(hptep->v); |
668 | if (!HPTE_V_COMPARE(hpte_v, want_v) || | 674 | if (!HPTE_V_COMPARE(hpte_v, want_v) || |
669 | !(hpte_v & HPTE_V_VALID)) | 675 | !(hpte_v & HPTE_V_VALID)) |
670 | native_unlock_hpte(hptep); | 676 | native_unlock_hpte(hptep); |
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index bde8b5589755..6176b3cdf579 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c | |||
@@ -251,19 +251,18 @@ static int __init htab_dt_scan_seg_sizes(unsigned long node, | |||
251 | void *data) | 251 | void *data) |
252 | { | 252 | { |
253 | char *type = of_get_flat_dt_prop(node, "device_type", NULL); | 253 | char *type = of_get_flat_dt_prop(node, "device_type", NULL); |
254 | u32 *prop; | 254 | __be32 *prop; |
255 | unsigned long size = 0; | 255 | unsigned long size = 0; |
256 | 256 | ||
257 | /* We are scanning "cpu" nodes only */ | 257 | /* We are scanning "cpu" nodes only */ |
258 | if (type == NULL || strcmp(type, "cpu") != 0) | 258 | if (type == NULL || strcmp(type, "cpu") != 0) |
259 | return 0; | 259 | return 0; |
260 | 260 | ||
261 | prop = (u32 *)of_get_flat_dt_prop(node, "ibm,processor-segment-sizes", | 261 | prop = of_get_flat_dt_prop(node, "ibm,processor-segment-sizes", &size); |
262 | &size); | ||
263 | if (prop == NULL) | 262 | if (prop == NULL) |
264 | return 0; | 263 | return 0; |
265 | for (; size >= 4; size -= 4, ++prop) { | 264 | for (; size >= 4; size -= 4, ++prop) { |
266 | if (prop[0] == 40) { | 265 | if (be32_to_cpu(prop[0]) == 40) { |
267 | DBG("1T segment support detected\n"); | 266 | DBG("1T segment support detected\n"); |
268 | cur_cpu_spec->mmu_features |= MMU_FTR_1T_SEGMENT; | 267 | cur_cpu_spec->mmu_features |= MMU_FTR_1T_SEGMENT; |
269 | return 1; | 268 | return 1; |
@@ -307,23 +306,22 @@ static int __init htab_dt_scan_page_sizes(unsigned long node, | |||
307 | void *data) | 306 | void *data) |
308 | { | 307 | { |
309 | char *type = of_get_flat_dt_prop(node, "device_type", NULL); | 308 | char *type = of_get_flat_dt_prop(node, "device_type", NULL); |
310 | u32 *prop; | 309 | __be32 *prop; |
311 | unsigned long size = 0; | 310 | unsigned long size = 0; |
312 | 311 | ||
313 | /* We are scanning "cpu" nodes only */ | 312 | /* We are scanning "cpu" nodes only */ |
314 | if (type == NULL || strcmp(type, "cpu") != 0) | 313 | if (type == NULL || strcmp(type, "cpu") != 0) |
315 | return 0; | 314 | return 0; |
316 | 315 | ||
317 | prop = (u32 *)of_get_flat_dt_prop(node, | 316 | prop = of_get_flat_dt_prop(node, "ibm,segment-page-sizes", &size); |
318 | "ibm,segment-page-sizes", &size); | ||
319 | if (prop != NULL) { | 317 | if (prop != NULL) { |
320 | pr_info("Page sizes from device-tree:\n"); | 318 | pr_info("Page sizes from device-tree:\n"); |
321 | size /= 4; | 319 | size /= 4; |
322 | cur_cpu_spec->mmu_features &= ~(MMU_FTR_16M_PAGE); | 320 | cur_cpu_spec->mmu_features &= ~(MMU_FTR_16M_PAGE); |
323 | while(size > 0) { | 321 | while(size > 0) { |
324 | unsigned int base_shift = prop[0]; | 322 | unsigned int base_shift = be32_to_cpu(prop[0]); |
325 | unsigned int slbenc = prop[1]; | 323 | unsigned int slbenc = be32_to_cpu(prop[1]); |
326 | unsigned int lpnum = prop[2]; | 324 | unsigned int lpnum = be32_to_cpu(prop[2]); |
327 | struct mmu_psize_def *def; | 325 | struct mmu_psize_def *def; |
328 | int idx, base_idx; | 326 | int idx, base_idx; |
329 | 327 | ||
@@ -356,8 +354,8 @@ static int __init htab_dt_scan_page_sizes(unsigned long node, | |||
356 | def->tlbiel = 0; | 354 | def->tlbiel = 0; |
357 | 355 | ||
358 | while (size > 0 && lpnum) { | 356 | while (size > 0 && lpnum) { |
359 | unsigned int shift = prop[0]; | 357 | unsigned int shift = be32_to_cpu(prop[0]); |
360 | int penc = prop[1]; | 358 | int penc = be32_to_cpu(prop[1]); |
361 | 359 | ||
362 | prop += 2; size -= 2; | 360 | prop += 2; size -= 2; |
363 | lpnum--; | 361 | lpnum--; |
@@ -390,8 +388,8 @@ static int __init htab_dt_scan_hugepage_blocks(unsigned long node, | |||
390 | const char *uname, int depth, | 388 | const char *uname, int depth, |
391 | void *data) { | 389 | void *data) { |
392 | char *type = of_get_flat_dt_prop(node, "device_type", NULL); | 390 | char *type = of_get_flat_dt_prop(node, "device_type", NULL); |
393 | unsigned long *addr_prop; | 391 | __be64 *addr_prop; |
394 | u32 *page_count_prop; | 392 | __be32 *page_count_prop; |
395 | unsigned int expected_pages; | 393 | unsigned int expected_pages; |
396 | long unsigned int phys_addr; | 394 | long unsigned int phys_addr; |
397 | long unsigned int block_size; | 395 | long unsigned int block_size; |
@@ -405,12 +403,12 @@ static int __init htab_dt_scan_hugepage_blocks(unsigned long node, | |||
405 | page_count_prop = of_get_flat_dt_prop(node, "ibm,expected#pages", NULL); | 403 | page_count_prop = of_get_flat_dt_prop(node, "ibm,expected#pages", NULL); |
406 | if (page_count_prop == NULL) | 404 | if (page_count_prop == NULL) |
407 | return 0; | 405 | return 0; |
408 | expected_pages = (1 << page_count_prop[0]); | 406 | expected_pages = (1 << be32_to_cpu(page_count_prop[0])); |
409 | addr_prop = of_get_flat_dt_prop(node, "reg", NULL); | 407 | addr_prop = of_get_flat_dt_prop(node, "reg", NULL); |
410 | if (addr_prop == NULL) | 408 | if (addr_prop == NULL) |
411 | return 0; | 409 | return 0; |
412 | phys_addr = addr_prop[0]; | 410 | phys_addr = be64_to_cpu(addr_prop[0]); |
413 | block_size = addr_prop[1]; | 411 | block_size = be64_to_cpu(addr_prop[1]); |
414 | if (block_size != (16 * GB)) | 412 | if (block_size != (16 * GB)) |
415 | return 0; | 413 | return 0; |
416 | printk(KERN_INFO "Huge page(16GB) memory: " | 414 | printk(KERN_INFO "Huge page(16GB) memory: " |
@@ -534,16 +532,16 @@ static int __init htab_dt_scan_pftsize(unsigned long node, | |||
534 | void *data) | 532 | void *data) |
535 | { | 533 | { |
536 | char *type = of_get_flat_dt_prop(node, "device_type", NULL); | 534 | char *type = of_get_flat_dt_prop(node, "device_type", NULL); |
537 | u32 *prop; | 535 | __be32 *prop; |
538 | 536 | ||
539 | /* We are scanning "cpu" nodes only */ | 537 | /* We are scanning "cpu" nodes only */ |
540 | if (type == NULL || strcmp(type, "cpu") != 0) | 538 | if (type == NULL || strcmp(type, "cpu") != 0) |
541 | return 0; | 539 | return 0; |
542 | 540 | ||
543 | prop = (u32 *)of_get_flat_dt_prop(node, "ibm,pft-size", NULL); | 541 | prop = of_get_flat_dt_prop(node, "ibm,pft-size", NULL); |
544 | if (prop != NULL) { | 542 | if (prop != NULL) { |
545 | /* pft_size[0] is the NUMA CEC cookie */ | 543 | /* pft_size[0] is the NUMA CEC cookie */ |
546 | ppc64_pft_size = prop[1]; | 544 | ppc64_pft_size = be32_to_cpu(prop[1]); |
547 | return 1; | 545 | return 1; |
548 | } | 546 | } |
549 | return 0; | 547 | return 0; |
diff --git a/arch/powerpc/mm/hugetlbpage.c b/arch/powerpc/mm/hugetlbpage.c index d67db4bd672d..90bb6d9409bf 100644 --- a/arch/powerpc/mm/hugetlbpage.c +++ b/arch/powerpc/mm/hugetlbpage.c | |||
@@ -633,8 +633,6 @@ static void hugetlb_free_pud_range(struct mmu_gather *tlb, pgd_t *pgd, | |||
633 | 633 | ||
634 | /* | 634 | /* |
635 | * This function frees user-level page tables of a process. | 635 | * This function frees user-level page tables of a process. |
636 | * | ||
637 | * Must be called with pagetable lock held. | ||
638 | */ | 636 | */ |
639 | void hugetlb_free_pgd_range(struct mmu_gather *tlb, | 637 | void hugetlb_free_pgd_range(struct mmu_gather *tlb, |
640 | unsigned long addr, unsigned long end, | 638 | unsigned long addr, unsigned long end, |
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c index d47d3dab4870..cff59f1bec23 100644 --- a/arch/powerpc/mm/init_32.c +++ b/arch/powerpc/mm/init_32.c | |||
@@ -213,7 +213,12 @@ void setup_initial_memory_limit(phys_addr_t first_memblock_base, | |||
213 | */ | 213 | */ |
214 | BUG_ON(first_memblock_base != 0); | 214 | BUG_ON(first_memblock_base != 0); |
215 | 215 | ||
216 | #ifdef CONFIG_PIN_TLB | ||
217 | /* 8xx can only access 24MB at the moment */ | ||
218 | memblock_set_current_limit(min_t(u64, first_memblock_size, 0x01800000)); | ||
219 | #else | ||
216 | /* 8xx can only access 8MB at the moment */ | 220 | /* 8xx can only access 8MB at the moment */ |
217 | memblock_set_current_limit(min_t(u64, first_memblock_size, 0x00800000)); | 221 | memblock_set_current_limit(min_t(u64, first_memblock_size, 0x00800000)); |
222 | #endif | ||
218 | } | 223 | } |
219 | #endif /* CONFIG_8xx */ | 224 | #endif /* CONFIG_8xx */ |
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index d0cd9e4c6837..e3734edffa69 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c | |||
@@ -300,5 +300,58 @@ void vmemmap_free(unsigned long start, unsigned long end) | |||
300 | { | 300 | { |
301 | } | 301 | } |
302 | 302 | ||
303 | #endif /* CONFIG_SPARSEMEM_VMEMMAP */ | 303 | void register_page_bootmem_memmap(unsigned long section_nr, |
304 | struct page *start_page, unsigned long size) | ||
305 | { | ||
306 | } | ||
307 | |||
308 | /* | ||
309 | * We do not have access to the sparsemem vmemmap, so we fallback to | ||
310 | * walking the list of sparsemem blocks which we already maintain for | ||
311 | * the sake of crashdump. In the long run, we might want to maintain | ||
312 | * a tree if performance of that linear walk becomes a problem. | ||
313 | * | ||
314 | * realmode_pfn_to_page functions can fail due to: | ||
315 | * 1) As real sparsemem blocks do not lay in RAM continously (they | ||
316 | * are in virtual address space which is not available in the real mode), | ||
317 | * the requested page struct can be split between blocks so get_page/put_page | ||
318 | * may fail. | ||
319 | * 2) When huge pages are used, the get_page/put_page API will fail | ||
320 | * in real mode as the linked addresses in the page struct are virtual | ||
321 | * too. | ||
322 | */ | ||
323 | struct page *realmode_pfn_to_page(unsigned long pfn) | ||
324 | { | ||
325 | struct vmemmap_backing *vmem_back; | ||
326 | struct page *page; | ||
327 | unsigned long page_size = 1 << mmu_psize_defs[mmu_vmemmap_psize].shift; | ||
328 | unsigned long pg_va = (unsigned long) pfn_to_page(pfn); | ||
329 | |||
330 | for (vmem_back = vmemmap_list; vmem_back; vmem_back = vmem_back->list) { | ||
331 | if (pg_va < vmem_back->virt_addr) | ||
332 | continue; | ||
333 | |||
334 | /* Check that page struct is not split between real pages */ | ||
335 | if ((pg_va + sizeof(struct page)) > | ||
336 | (vmem_back->virt_addr + page_size)) | ||
337 | return NULL; | ||
338 | |||
339 | page = (struct page *) (vmem_back->phys + pg_va - | ||
340 | vmem_back->virt_addr); | ||
341 | return page; | ||
342 | } | ||
343 | |||
344 | return NULL; | ||
345 | } | ||
346 | EXPORT_SYMBOL_GPL(realmode_pfn_to_page); | ||
347 | |||
348 | #elif defined(CONFIG_FLATMEM) | ||
349 | |||
350 | struct page *realmode_pfn_to_page(unsigned long pfn) | ||
351 | { | ||
352 | struct page *page = pfn_to_page(pfn); | ||
353 | return page; | ||
354 | } | ||
355 | EXPORT_SYMBOL_GPL(realmode_pfn_to_page); | ||
304 | 356 | ||
357 | #endif /* CONFIG_SPARSEMEM_VMEMMAP/CONFIG_FLATMEM */ | ||
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c index 1cf9c5b67f24..3fa93dc7fe75 100644 --- a/arch/powerpc/mm/mem.c +++ b/arch/powerpc/mm/mem.c | |||
@@ -297,12 +297,21 @@ void __init paging_init(void) | |||
297 | } | 297 | } |
298 | #endif /* ! CONFIG_NEED_MULTIPLE_NODES */ | 298 | #endif /* ! CONFIG_NEED_MULTIPLE_NODES */ |
299 | 299 | ||
300 | static void __init register_page_bootmem_info(void) | ||
301 | { | ||
302 | int i; | ||
303 | |||
304 | for_each_online_node(i) | ||
305 | register_page_bootmem_info_node(NODE_DATA(i)); | ||
306 | } | ||
307 | |||
300 | void __init mem_init(void) | 308 | void __init mem_init(void) |
301 | { | 309 | { |
302 | #ifdef CONFIG_SWIOTLB | 310 | #ifdef CONFIG_SWIOTLB |
303 | swiotlb_init(0); | 311 | swiotlb_init(0); |
304 | #endif | 312 | #endif |
305 | 313 | ||
314 | register_page_bootmem_info(); | ||
306 | high_memory = (void *) __va(max_low_pfn * PAGE_SIZE); | 315 | high_memory = (void *) __va(max_low_pfn * PAGE_SIZE); |
307 | set_max_mapnr(max_pfn); | 316 | set_max_mapnr(max_pfn); |
308 | free_all_bootmem(); | 317 | free_all_bootmem(); |
diff --git a/arch/powerpc/mm/numa.c b/arch/powerpc/mm/numa.c index c916127f10c3..078d3e00a616 100644 --- a/arch/powerpc/mm/numa.c +++ b/arch/powerpc/mm/numa.c | |||
@@ -195,7 +195,7 @@ static const __be32 *of_get_usable_memory(struct device_node *memory) | |||
195 | u32 len; | 195 | u32 len; |
196 | prop = of_get_property(memory, "linux,drconf-usable-memory", &len); | 196 | prop = of_get_property(memory, "linux,drconf-usable-memory", &len); |
197 | if (!prop || len < sizeof(unsigned int)) | 197 | if (!prop || len < sizeof(unsigned int)) |
198 | return 0; | 198 | return NULL; |
199 | return prop; | 199 | return prop; |
200 | } | 200 | } |
201 | 201 | ||
@@ -938,8 +938,7 @@ static void __init mark_reserved_regions_for_nid(int nid) | |||
938 | unsigned long start_pfn = physbase >> PAGE_SHIFT; | 938 | unsigned long start_pfn = physbase >> PAGE_SHIFT; |
939 | unsigned long end_pfn = PFN_UP(physbase + size); | 939 | unsigned long end_pfn = PFN_UP(physbase + size); |
940 | struct node_active_region node_ar; | 940 | struct node_active_region node_ar; |
941 | unsigned long node_end_pfn = node->node_start_pfn + | 941 | unsigned long node_end_pfn = pgdat_end_pfn(node); |
942 | node->node_spanned_pages; | ||
943 | 942 | ||
944 | /* | 943 | /* |
945 | * Check to make sure that this memblock.reserved area is | 944 | * Check to make sure that this memblock.reserved area is |
@@ -1154,7 +1153,7 @@ static int hot_add_drconf_scn_to_nid(struct device_node *memory, | |||
1154 | * represented in the device tree as a node (i.e. memory@XXXX) for | 1153 | * represented in the device tree as a node (i.e. memory@XXXX) for |
1155 | * each memblock. | 1154 | * each memblock. |
1156 | */ | 1155 | */ |
1157 | int hot_add_node_scn_to_nid(unsigned long scn_addr) | 1156 | static int hot_add_node_scn_to_nid(unsigned long scn_addr) |
1158 | { | 1157 | { |
1159 | struct device_node *memory; | 1158 | struct device_node *memory; |
1160 | int nid = -1; | 1159 | int nid = -1; |
@@ -1235,7 +1234,7 @@ static u64 hot_add_drconf_memory_max(void) | |||
1235 | struct device_node *memory = NULL; | 1234 | struct device_node *memory = NULL; |
1236 | unsigned int drconf_cell_cnt = 0; | 1235 | unsigned int drconf_cell_cnt = 0; |
1237 | u64 lmb_size = 0; | 1236 | u64 lmb_size = 0; |
1238 | const __be32 *dm = 0; | 1237 | const __be32 *dm = NULL; |
1239 | 1238 | ||
1240 | memory = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory"); | 1239 | memory = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory"); |
1241 | if (memory) { | 1240 | if (memory) { |
@@ -1535,7 +1534,7 @@ static void topology_work_fn(struct work_struct *work) | |||
1535 | } | 1534 | } |
1536 | static DECLARE_WORK(topology_work, topology_work_fn); | 1535 | static DECLARE_WORK(topology_work, topology_work_fn); |
1537 | 1536 | ||
1538 | void topology_schedule_update(void) | 1537 | static void topology_schedule_update(void) |
1539 | { | 1538 | { |
1540 | schedule_work(&topology_work); | 1539 | schedule_work(&topology_work); |
1541 | } | 1540 | } |
diff --git a/arch/powerpc/mm/pgtable.c b/arch/powerpc/mm/pgtable.c index edda589795c3..841e0d00863c 100644 --- a/arch/powerpc/mm/pgtable.c +++ b/arch/powerpc/mm/pgtable.c | |||
@@ -32,8 +32,6 @@ | |||
32 | #include <asm/tlbflush.h> | 32 | #include <asm/tlbflush.h> |
33 | #include <asm/tlb.h> | 33 | #include <asm/tlb.h> |
34 | 34 | ||
35 | #include "mmu_decl.h" | ||
36 | |||
37 | static inline int is_exec_fault(void) | 35 | static inline int is_exec_fault(void) |
38 | { | 36 | { |
39 | return current->thread.regs && TRAP(current->thread.regs) == 0x400; | 37 | return current->thread.regs && TRAP(current->thread.regs) == 0x400; |
@@ -72,7 +70,7 @@ struct page * maybe_pte_to_page(pte_t pte) | |||
72 | * support falls into the same category. | 70 | * support falls into the same category. |
73 | */ | 71 | */ |
74 | 72 | ||
75 | static pte_t set_pte_filter(pte_t pte, unsigned long addr) | 73 | static pte_t set_pte_filter(pte_t pte) |
76 | { | 74 | { |
77 | pte = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS); | 75 | pte = __pte(pte_val(pte) & ~_PAGE_HPTEFLAGS); |
78 | if (pte_looks_normal(pte) && !(cpu_has_feature(CPU_FTR_COHERENT_ICACHE) || | 76 | if (pte_looks_normal(pte) && !(cpu_has_feature(CPU_FTR_COHERENT_ICACHE) || |
@@ -81,17 +79,6 @@ static pte_t set_pte_filter(pte_t pte, unsigned long addr) | |||
81 | if (!pg) | 79 | if (!pg) |
82 | return pte; | 80 | return pte; |
83 | if (!test_bit(PG_arch_1, &pg->flags)) { | 81 | if (!test_bit(PG_arch_1, &pg->flags)) { |
84 | #ifdef CONFIG_8xx | ||
85 | /* On 8xx, cache control instructions (particularly | ||
86 | * "dcbst" from flush_dcache_icache) fault as write | ||
87 | * operation if there is an unpopulated TLB entry | ||
88 | * for the address in question. To workaround that, | ||
89 | * we invalidate the TLB here, thus avoiding dcbst | ||
90 | * misbehaviour. | ||
91 | */ | ||
92 | /* 8xx doesn't care about PID, size or ind args */ | ||
93 | _tlbil_va(addr, 0, 0, 0); | ||
94 | #endif /* CONFIG_8xx */ | ||
95 | flush_dcache_icache_page(pg); | 82 | flush_dcache_icache_page(pg); |
96 | set_bit(PG_arch_1, &pg->flags); | 83 | set_bit(PG_arch_1, &pg->flags); |
97 | } | 84 | } |
@@ -111,7 +98,7 @@ static pte_t set_access_flags_filter(pte_t pte, struct vm_area_struct *vma, | |||
111 | * as we don't have two bits to spare for _PAGE_EXEC and _PAGE_HWEXEC so | 98 | * as we don't have two bits to spare for _PAGE_EXEC and _PAGE_HWEXEC so |
112 | * instead we "filter out" the exec permission for non clean pages. | 99 | * instead we "filter out" the exec permission for non clean pages. |
113 | */ | 100 | */ |
114 | static pte_t set_pte_filter(pte_t pte, unsigned long addr) | 101 | static pte_t set_pte_filter(pte_t pte) |
115 | { | 102 | { |
116 | struct page *pg; | 103 | struct page *pg; |
117 | 104 | ||
@@ -193,7 +180,7 @@ void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, | |||
193 | * this context might not have been activated yet when this | 180 | * this context might not have been activated yet when this |
194 | * is called. | 181 | * is called. |
195 | */ | 182 | */ |
196 | pte = set_pte_filter(pte, addr); | 183 | pte = set_pte_filter(pte); |
197 | 184 | ||
198 | /* Perform the setting of the PTE */ | 185 | /* Perform the setting of the PTE */ |
199 | __set_pte_at(mm, addr, ptep, pte, 0); | 186 | __set_pte_at(mm, addr, ptep, pte, 0); |
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c index 6c856fb8c15b..5b9601715289 100644 --- a/arch/powerpc/mm/pgtable_32.c +++ b/arch/powerpc/mm/pgtable_32.c | |||
@@ -121,7 +121,10 @@ pgtable_t pte_alloc_one(struct mm_struct *mm, unsigned long address) | |||
121 | ptepage = alloc_pages(flags, 0); | 121 | ptepage = alloc_pages(flags, 0); |
122 | if (!ptepage) | 122 | if (!ptepage) |
123 | return NULL; | 123 | return NULL; |
124 | pgtable_page_ctor(ptepage); | 124 | if (!pgtable_page_ctor(ptepage)) { |
125 | __free_page(ptepage); | ||
126 | return NULL; | ||
127 | } | ||
125 | return ptepage; | 128 | return ptepage; |
126 | } | 129 | } |
127 | 130 | ||
diff --git a/arch/powerpc/mm/pgtable_64.c b/arch/powerpc/mm/pgtable_64.c index 536eec72c0f7..9d95786aa80f 100644 --- a/arch/powerpc/mm/pgtable_64.c +++ b/arch/powerpc/mm/pgtable_64.c | |||
@@ -378,6 +378,10 @@ static pte_t *__alloc_for_cache(struct mm_struct *mm, int kernel) | |||
378 | __GFP_REPEAT | __GFP_ZERO); | 378 | __GFP_REPEAT | __GFP_ZERO); |
379 | if (!page) | 379 | if (!page) |
380 | return NULL; | 380 | return NULL; |
381 | if (!kernel && !pgtable_page_ctor(page)) { | ||
382 | __free_page(page); | ||
383 | return NULL; | ||
384 | } | ||
381 | 385 | ||
382 | ret = page_address(page); | 386 | ret = page_address(page); |
383 | spin_lock(&mm->page_table_lock); | 387 | spin_lock(&mm->page_table_lock); |
@@ -392,9 +396,6 @@ static pte_t *__alloc_for_cache(struct mm_struct *mm, int kernel) | |||
392 | } | 396 | } |
393 | spin_unlock(&mm->page_table_lock); | 397 | spin_unlock(&mm->page_table_lock); |
394 | 398 | ||
395 | if (!kernel) | ||
396 | pgtable_page_ctor(page); | ||
397 | |||
398 | return (pte_t *)ret; | 399 | return (pte_t *)ret; |
399 | } | 400 | } |
400 | 401 | ||
diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h index 8a5dfaf5c6b7..9aee27c582dc 100644 --- a/arch/powerpc/net/bpf_jit.h +++ b/arch/powerpc/net/bpf_jit.h | |||
@@ -39,6 +39,7 @@ | |||
39 | #define r_X 5 | 39 | #define r_X 5 |
40 | #define r_addr 6 | 40 | #define r_addr 6 |
41 | #define r_scratch1 7 | 41 | #define r_scratch1 7 |
42 | #define r_scratch2 8 | ||
42 | #define r_D 14 | 43 | #define r_D 14 |
43 | #define r_HL 15 | 44 | #define r_HL 15 |
44 | #define r_M 16 | 45 | #define r_M 16 |
@@ -92,6 +93,8 @@ DECLARE_LOAD_FUNC(sk_load_byte_msh); | |||
92 | ___PPC_RA(base) | IMM_L(i)) | 93 | ___PPC_RA(base) | IMM_L(i)) |
93 | #define PPC_LHZ(r, base, i) EMIT(PPC_INST_LHZ | ___PPC_RT(r) | \ | 94 | #define PPC_LHZ(r, base, i) EMIT(PPC_INST_LHZ | ___PPC_RT(r) | \ |
94 | ___PPC_RA(base) | IMM_L(i)) | 95 | ___PPC_RA(base) | IMM_L(i)) |
96 | #define PPC_LHBRX(r, base, b) EMIT(PPC_INST_LHBRX | ___PPC_RT(r) | \ | ||
97 | ___PPC_RA(base) | ___PPC_RB(b)) | ||
95 | /* Convenience helpers for the above with 'far' offsets: */ | 98 | /* Convenience helpers for the above with 'far' offsets: */ |
96 | #define PPC_LD_OFFS(r, base, i) do { if ((i) < 32768) PPC_LD(r, base, i); \ | 99 | #define PPC_LD_OFFS(r, base, i) do { if ((i) < 32768) PPC_LD(r, base, i); \ |
97 | else { PPC_ADDIS(r, base, IMM_HA(i)); \ | 100 | else { PPC_ADDIS(r, base, IMM_HA(i)); \ |
@@ -186,6 +189,14 @@ DECLARE_LOAD_FUNC(sk_load_byte_msh); | |||
186 | PPC_ORI(d, d, (uintptr_t)(i) & 0xffff); \ | 189 | PPC_ORI(d, d, (uintptr_t)(i) & 0xffff); \ |
187 | } } while (0); | 190 | } } while (0); |
188 | 191 | ||
192 | #define PPC_LHBRX_OFFS(r, base, i) \ | ||
193 | do { PPC_LI32(r, i); PPC_LHBRX(r, r, base); } while(0) | ||
194 | #ifdef __LITTLE_ENDIAN__ | ||
195 | #define PPC_NTOHS_OFFS(r, base, i) PPC_LHBRX_OFFS(r, base, i) | ||
196 | #else | ||
197 | #define PPC_NTOHS_OFFS(r, base, i) PPC_LHZ_OFFS(r, base, i) | ||
198 | #endif | ||
199 | |||
189 | static inline bool is_nearbranch(int offset) | 200 | static inline bool is_nearbranch(int offset) |
190 | { | 201 | { |
191 | return (offset < 32768) && (offset >= -32768); | 202 | return (offset < 32768) && (offset >= -32768); |
diff --git a/arch/powerpc/net/bpf_jit_64.S b/arch/powerpc/net/bpf_jit_64.S index 7d3a3b5619a2..e76eba74d9da 100644 --- a/arch/powerpc/net/bpf_jit_64.S +++ b/arch/powerpc/net/bpf_jit_64.S | |||
@@ -43,8 +43,11 @@ sk_load_word_positive_offset: | |||
43 | cmpd r_scratch1, r_addr | 43 | cmpd r_scratch1, r_addr |
44 | blt bpf_slow_path_word | 44 | blt bpf_slow_path_word |
45 | /* Nope, just hitting the header. cr0 here is eq or gt! */ | 45 | /* Nope, just hitting the header. cr0 here is eq or gt! */ |
46 | #ifdef __LITTLE_ENDIAN__ | ||
47 | lwbrx r_A, r_D, r_addr | ||
48 | #else | ||
46 | lwzx r_A, r_D, r_addr | 49 | lwzx r_A, r_D, r_addr |
47 | /* When big endian we don't need to byteswap. */ | 50 | #endif |
48 | blr /* Return success, cr0 != LT */ | 51 | blr /* Return success, cr0 != LT */ |
49 | 52 | ||
50 | .globl sk_load_half | 53 | .globl sk_load_half |
@@ -56,7 +59,11 @@ sk_load_half_positive_offset: | |||
56 | subi r_scratch1, r_HL, 2 | 59 | subi r_scratch1, r_HL, 2 |
57 | cmpd r_scratch1, r_addr | 60 | cmpd r_scratch1, r_addr |
58 | blt bpf_slow_path_half | 61 | blt bpf_slow_path_half |
62 | #ifdef __LITTLE_ENDIAN__ | ||
63 | lhbrx r_A, r_D, r_addr | ||
64 | #else | ||
59 | lhzx r_A, r_D, r_addr | 65 | lhzx r_A, r_D, r_addr |
66 | #endif | ||
60 | blr | 67 | blr |
61 | 68 | ||
62 | .globl sk_load_byte | 69 | .globl sk_load_byte |
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c index bf56e33f8257..ac3c2a10dafd 100644 --- a/arch/powerpc/net/bpf_jit_comp.c +++ b/arch/powerpc/net/bpf_jit_comp.c | |||
@@ -17,14 +17,8 @@ | |||
17 | 17 | ||
18 | #include "bpf_jit.h" | 18 | #include "bpf_jit.h" |
19 | 19 | ||
20 | #ifndef __BIG_ENDIAN | ||
21 | /* There are endianness assumptions herein. */ | ||
22 | #error "Little-endian PPC not supported in BPF compiler" | ||
23 | #endif | ||
24 | |||
25 | int bpf_jit_enable __read_mostly; | 20 | int bpf_jit_enable __read_mostly; |
26 | 21 | ||
27 | |||
28 | static inline void bpf_flush_icache(void *start, void *end) | 22 | static inline void bpf_flush_icache(void *start, void *end) |
29 | { | 23 | { |
30 | smp_wmb(); | 24 | smp_wmb(); |
@@ -193,6 +187,26 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image, | |||
193 | PPC_MUL(r_A, r_A, r_scratch1); | 187 | PPC_MUL(r_A, r_A, r_scratch1); |
194 | } | 188 | } |
195 | break; | 189 | break; |
190 | case BPF_S_ALU_MOD_X: /* A %= X; */ | ||
191 | ctx->seen |= SEEN_XREG; | ||
192 | PPC_CMPWI(r_X, 0); | ||
193 | if (ctx->pc_ret0 != -1) { | ||
194 | PPC_BCC(COND_EQ, addrs[ctx->pc_ret0]); | ||
195 | } else { | ||
196 | PPC_BCC_SHORT(COND_NE, (ctx->idx*4)+12); | ||
197 | PPC_LI(r_ret, 0); | ||
198 | PPC_JMP(exit_addr); | ||
199 | } | ||
200 | PPC_DIVWU(r_scratch1, r_A, r_X); | ||
201 | PPC_MUL(r_scratch1, r_X, r_scratch1); | ||
202 | PPC_SUB(r_A, r_A, r_scratch1); | ||
203 | break; | ||
204 | case BPF_S_ALU_MOD_K: /* A %= K; */ | ||
205 | PPC_LI32(r_scratch2, K); | ||
206 | PPC_DIVWU(r_scratch1, r_A, r_scratch2); | ||
207 | PPC_MUL(r_scratch1, r_scratch2, r_scratch1); | ||
208 | PPC_SUB(r_A, r_A, r_scratch1); | ||
209 | break; | ||
196 | case BPF_S_ALU_DIV_X: /* A /= X; */ | 210 | case BPF_S_ALU_DIV_X: /* A /= X; */ |
197 | ctx->seen |= SEEN_XREG; | 211 | ctx->seen |= SEEN_XREG; |
198 | PPC_CMPWI(r_X, 0); | 212 | PPC_CMPWI(r_X, 0); |
@@ -346,18 +360,11 @@ static int bpf_jit_build_body(struct sk_filter *fp, u32 *image, | |||
346 | break; | 360 | break; |
347 | 361 | ||
348 | /*** Ancillary info loads ***/ | 362 | /*** Ancillary info loads ***/ |
349 | |||
350 | /* None of the BPF_S_ANC* codes appear to be passed by | ||
351 | * sk_chk_filter(). The interpreter and the x86 BPF | ||
352 | * compiler implement them so we do too -- they may be | ||
353 | * planted in future. | ||
354 | */ | ||
355 | case BPF_S_ANC_PROTOCOL: /* A = ntohs(skb->protocol); */ | 363 | case BPF_S_ANC_PROTOCOL: /* A = ntohs(skb->protocol); */ |
356 | BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, | 364 | BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, |
357 | protocol) != 2); | 365 | protocol) != 2); |
358 | PPC_LHZ_OFFS(r_A, r_skb, offsetof(struct sk_buff, | 366 | PPC_NTOHS_OFFS(r_A, r_skb, offsetof(struct sk_buff, |
359 | protocol)); | 367 | protocol)); |
360 | /* ntohs is a NOP with BE loads. */ | ||
361 | break; | 368 | break; |
362 | case BPF_S_ANC_IFINDEX: | 369 | case BPF_S_ANC_IFINDEX: |
363 | PPC_LD_OFFS(r_scratch1, r_skb, offsetof(struct sk_buff, | 370 | PPC_LD_OFFS(r_scratch1, r_skb, offsetof(struct sk_buff, |
@@ -691,4 +698,5 @@ void bpf_jit_free(struct sk_filter *fp) | |||
691 | { | 698 | { |
692 | if (fp->bpf_func != sk_run_filter) | 699 | if (fp->bpf_func != sk_run_filter) |
693 | module_free(NULL, fp->bpf_func); | 700 | module_free(NULL, fp->bpf_func); |
701 | kfree(fp); | ||
694 | } | 702 | } |
diff --git a/arch/powerpc/perf/power8-pmu.c b/arch/powerpc/perf/power8-pmu.c index 2ee4a707f0df..a3f7abd2f13f 100644 --- a/arch/powerpc/perf/power8-pmu.c +++ b/arch/powerpc/perf/power8-pmu.c | |||
@@ -199,6 +199,7 @@ | |||
199 | #define MMCR1_UNIT_SHIFT(pmc) (60 - (4 * ((pmc) - 1))) | 199 | #define MMCR1_UNIT_SHIFT(pmc) (60 - (4 * ((pmc) - 1))) |
200 | #define MMCR1_COMBINE_SHIFT(pmc) (35 - ((pmc) - 1)) | 200 | #define MMCR1_COMBINE_SHIFT(pmc) (35 - ((pmc) - 1)) |
201 | #define MMCR1_PMCSEL_SHIFT(pmc) (24 - (((pmc) - 1)) * 8) | 201 | #define MMCR1_PMCSEL_SHIFT(pmc) (24 - (((pmc) - 1)) * 8) |
202 | #define MMCR1_FAB_SHIFT 36 | ||
202 | #define MMCR1_DC_QUAL_SHIFT 47 | 203 | #define MMCR1_DC_QUAL_SHIFT 47 |
203 | #define MMCR1_IC_QUAL_SHIFT 46 | 204 | #define MMCR1_IC_QUAL_SHIFT 46 |
204 | 205 | ||
@@ -388,8 +389,8 @@ static int power8_compute_mmcr(u64 event[], int n_ev, | |||
388 | * the threshold bits are used for the match value. | 389 | * the threshold bits are used for the match value. |
389 | */ | 390 | */ |
390 | if (event_is_fab_match(event[i])) { | 391 | if (event_is_fab_match(event[i])) { |
391 | mmcr1 |= (event[i] >> EVENT_THR_CTL_SHIFT) & | 392 | mmcr1 |= ((event[i] >> EVENT_THR_CTL_SHIFT) & |
392 | EVENT_THR_CTL_MASK; | 393 | EVENT_THR_CTL_MASK) << MMCR1_FAB_SHIFT; |
393 | } else { | 394 | } else { |
394 | val = (event[i] >> EVENT_THR_CTL_SHIFT) & EVENT_THR_CTL_MASK; | 395 | val = (event[i] >> EVENT_THR_CTL_SHIFT) & EVENT_THR_CTL_MASK; |
395 | mmcra |= val << MMCRA_THR_CTL_SHIFT; | 396 | mmcra |= val << MMCRA_THR_CTL_SHIFT; |
diff --git a/arch/powerpc/platforms/512x/clock.c b/arch/powerpc/platforms/512x/clock.c index e504166e089a..fd8a37653417 100644 --- a/arch/powerpc/platforms/512x/clock.c +++ b/arch/powerpc/platforms/512x/clock.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/mutex.h> | 24 | #include <linux/mutex.h> |
25 | #include <linux/io.h> | 25 | #include <linux/io.h> |
26 | 26 | ||
27 | #include <linux/of_address.h> | ||
27 | #include <linux/of_platform.h> | 28 | #include <linux/of_platform.h> |
28 | #include <asm/mpc5xxx.h> | 29 | #include <asm/mpc5xxx.h> |
29 | #include <asm/mpc5121.h> | 30 | #include <asm/mpc5121.h> |
diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c b/arch/powerpc/platforms/512x/mpc512x_shared.c index a82a41b4fd91..36b5652aada2 100644 --- a/arch/powerpc/platforms/512x/mpc512x_shared.c +++ b/arch/powerpc/platforms/512x/mpc512x_shared.c | |||
@@ -60,8 +60,6 @@ void mpc512x_restart(char *cmd) | |||
60 | ; | 60 | ; |
61 | } | 61 | } |
62 | 62 | ||
63 | #if IS_ENABLED(CONFIG_FB_FSL_DIU) | ||
64 | |||
65 | struct fsl_diu_shared_fb { | 63 | struct fsl_diu_shared_fb { |
66 | u8 gamma[0x300]; /* 32-bit aligned! */ | 64 | u8 gamma[0x300]; /* 32-bit aligned! */ |
67 | struct diu_ad ad0; /* 32-bit aligned! */ | 65 | struct diu_ad ad0; /* 32-bit aligned! */ |
@@ -71,7 +69,7 @@ struct fsl_diu_shared_fb { | |||
71 | }; | 69 | }; |
72 | 70 | ||
73 | #define DIU_DIV_MASK 0x000000ff | 71 | #define DIU_DIV_MASK 0x000000ff |
74 | void mpc512x_set_pixel_clock(unsigned int pixclock) | 72 | static void mpc512x_set_pixel_clock(unsigned int pixclock) |
75 | { | 73 | { |
76 | unsigned long bestval, bestfreq, speed, busfreq; | 74 | unsigned long bestval, bestfreq, speed, busfreq; |
77 | unsigned long minpixclock, maxpixclock, pixval; | 75 | unsigned long minpixclock, maxpixclock, pixval; |
@@ -164,7 +162,7 @@ void mpc512x_set_pixel_clock(unsigned int pixclock) | |||
164 | iounmap(ccm); | 162 | iounmap(ccm); |
165 | } | 163 | } |
166 | 164 | ||
167 | enum fsl_diu_monitor_port | 165 | static enum fsl_diu_monitor_port |
168 | mpc512x_valid_monitor_port(enum fsl_diu_monitor_port port) | 166 | mpc512x_valid_monitor_port(enum fsl_diu_monitor_port port) |
169 | { | 167 | { |
170 | return FSL_DIU_PORT_DVI; | 168 | return FSL_DIU_PORT_DVI; |
@@ -179,7 +177,7 @@ static inline void mpc512x_free_bootmem(struct page *page) | |||
179 | free_reserved_page(page); | 177 | free_reserved_page(page); |
180 | } | 178 | } |
181 | 179 | ||
182 | void mpc512x_release_bootmem(void) | 180 | static void mpc512x_release_bootmem(void) |
183 | { | 181 | { |
184 | unsigned long addr = diu_shared_fb.fb_phys & PAGE_MASK; | 182 | unsigned long addr = diu_shared_fb.fb_phys & PAGE_MASK; |
185 | unsigned long size = diu_shared_fb.fb_len; | 183 | unsigned long size = diu_shared_fb.fb_len; |
@@ -205,7 +203,7 @@ void mpc512x_release_bootmem(void) | |||
205 | * address range will be reserved in setup_arch() after bootmem | 203 | * address range will be reserved in setup_arch() after bootmem |
206 | * allocator is up. | 204 | * allocator is up. |
207 | */ | 205 | */ |
208 | void __init mpc512x_init_diu(void) | 206 | static void __init mpc512x_init_diu(void) |
209 | { | 207 | { |
210 | struct device_node *np; | 208 | struct device_node *np; |
211 | struct diu __iomem *diu_reg; | 209 | struct diu __iomem *diu_reg; |
@@ -274,7 +272,7 @@ out: | |||
274 | iounmap(diu_reg); | 272 | iounmap(diu_reg); |
275 | } | 273 | } |
276 | 274 | ||
277 | void __init mpc512x_setup_diu(void) | 275 | static void __init mpc512x_setup_diu(void) |
278 | { | 276 | { |
279 | int ret; | 277 | int ret; |
280 | 278 | ||
@@ -303,8 +301,6 @@ void __init mpc512x_setup_diu(void) | |||
303 | diu_ops.release_bootmem = mpc512x_release_bootmem; | 301 | diu_ops.release_bootmem = mpc512x_release_bootmem; |
304 | } | 302 | } |
305 | 303 | ||
306 | #endif | ||
307 | |||
308 | void __init mpc512x_init_IRQ(void) | 304 | void __init mpc512x_init_IRQ(void) |
309 | { | 305 | { |
310 | struct device_node *np; | 306 | struct device_node *np; |
@@ -337,7 +333,7 @@ static struct of_device_id __initdata of_bus_ids[] = { | |||
337 | {}, | 333 | {}, |
338 | }; | 334 | }; |
339 | 335 | ||
340 | void __init mpc512x_declare_of_platform_devices(void) | 336 | static void __init mpc512x_declare_of_platform_devices(void) |
341 | { | 337 | { |
342 | if (of_platform_bus_probe(NULL, of_bus_ids, NULL)) | 338 | if (of_platform_bus_probe(NULL, of_bus_ids, NULL)) |
343 | printk(KERN_ERR __FILE__ ": " | 339 | printk(KERN_ERR __FILE__ ": " |
@@ -387,7 +383,7 @@ static unsigned int __init get_fifo_size(struct device_node *np, | |||
387 | ((u32)(_base) + sizeof(struct mpc52xx_psc))) | 383 | ((u32)(_base) + sizeof(struct mpc52xx_psc))) |
388 | 384 | ||
389 | /* Init PSC FIFO space for TX and RX slices */ | 385 | /* Init PSC FIFO space for TX and RX slices */ |
390 | void __init mpc512x_psc_fifo_init(void) | 386 | static void __init mpc512x_psc_fifo_init(void) |
391 | { | 387 | { |
392 | struct device_node *np; | 388 | struct device_node *np; |
393 | void __iomem *psc; | 389 | void __iomem *psc; |
diff --git a/arch/powerpc/platforms/512x/pdm360ng.c b/arch/powerpc/platforms/512x/pdm360ng.c index 24b314d7bd5f..116f2325b20b 100644 --- a/arch/powerpc/platforms/512x/pdm360ng.c +++ b/arch/powerpc/platforms/512x/pdm360ng.c | |||
@@ -14,6 +14,8 @@ | |||
14 | 14 | ||
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/io.h> | 16 | #include <linux/io.h> |
17 | #include <linux/of_address.h> | ||
18 | #include <linux/of_fdt.h> | ||
17 | #include <linux/of_platform.h> | 19 | #include <linux/of_platform.h> |
18 | 20 | ||
19 | #include <asm/machdep.h> | 21 | #include <asm/machdep.h> |
diff --git a/arch/powerpc/platforms/52xx/Kconfig b/arch/powerpc/platforms/52xx/Kconfig index 90f4496017e4..af54174801f7 100644 --- a/arch/powerpc/platforms/52xx/Kconfig +++ b/arch/powerpc/platforms/52xx/Kconfig | |||
@@ -57,5 +57,5 @@ config PPC_MPC5200_BUGFIX | |||
57 | 57 | ||
58 | config PPC_MPC5200_LPBFIFO | 58 | config PPC_MPC5200_LPBFIFO |
59 | tristate "MPC5200 LocalPlus bus FIFO driver" | 59 | tristate "MPC5200 LocalPlus bus FIFO driver" |
60 | depends on PPC_MPC52xx | 60 | depends on PPC_MPC52xx && PPC_BESTCOMM |
61 | select PPC_BESTCOMM_GEN_BD | 61 | select PPC_BESTCOMM_GEN_BD |
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pic.c b/arch/powerpc/platforms/52xx/mpc52xx_pic.c index b69221ba07fd..2898b737deb7 100644 --- a/arch/powerpc/platforms/52xx/mpc52xx_pic.c +++ b/arch/powerpc/platforms/52xx/mpc52xx_pic.c | |||
@@ -340,7 +340,7 @@ static int mpc52xx_irqhost_map(struct irq_domain *h, unsigned int virq, | |||
340 | { | 340 | { |
341 | int l1irq; | 341 | int l1irq; |
342 | int l2irq; | 342 | int l2irq; |
343 | struct irq_chip *irqchip; | 343 | struct irq_chip *uninitialized_var(irqchip); |
344 | void *hndlr; | 344 | void *hndlr; |
345 | int type; | 345 | int type; |
346 | u32 reg; | 346 | u32 reg; |
@@ -373,9 +373,8 @@ static int mpc52xx_irqhost_map(struct irq_domain *h, unsigned int virq, | |||
373 | case MPC52xx_IRQ_L1_PERP: irqchip = &mpc52xx_periph_irqchip; break; | 373 | case MPC52xx_IRQ_L1_PERP: irqchip = &mpc52xx_periph_irqchip; break; |
374 | case MPC52xx_IRQ_L1_SDMA: irqchip = &mpc52xx_sdma_irqchip; break; | 374 | case MPC52xx_IRQ_L1_SDMA: irqchip = &mpc52xx_sdma_irqchip; break; |
375 | case MPC52xx_IRQ_L1_CRIT: | 375 | case MPC52xx_IRQ_L1_CRIT: |
376 | default: | ||
377 | pr_warn("%s: Critical IRQ #%d is unsupported! Nopping it.\n", | 376 | pr_warn("%s: Critical IRQ #%d is unsupported! Nopping it.\n", |
378 | __func__, l1irq); | 377 | __func__, l2irq); |
379 | irq_set_chip(virq, &no_irq_chip); | 378 | irq_set_chip(virq, &no_irq_chip); |
380 | return 0; | 379 | return 0; |
381 | } | 380 | } |
diff --git a/arch/powerpc/platforms/82xx/mpc8272_ads.c b/arch/powerpc/platforms/82xx/mpc8272_ads.c index 30394b409b3f..6a14cf50f4a2 100644 --- a/arch/powerpc/platforms/82xx/mpc8272_ads.c +++ b/arch/powerpc/platforms/82xx/mpc8272_ads.c | |||
@@ -16,6 +16,8 @@ | |||
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
18 | #include <linux/fsl_devices.h> | 18 | #include <linux/fsl_devices.h> |
19 | #include <linux/of_address.h> | ||
20 | #include <linux/of_fdt.h> | ||
19 | #include <linux/of_platform.h> | 21 | #include <linux/of_platform.h> |
20 | #include <linux/io.h> | 22 | #include <linux/io.h> |
21 | 23 | ||
diff --git a/arch/powerpc/platforms/82xx/pq2fads.c b/arch/powerpc/platforms/82xx/pq2fads.c index e1dceeec4994..e5f82ec8df17 100644 --- a/arch/powerpc/platforms/82xx/pq2fads.c +++ b/arch/powerpc/platforms/82xx/pq2fads.c | |||
@@ -15,6 +15,8 @@ | |||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/interrupt.h> | 16 | #include <linux/interrupt.h> |
17 | #include <linux/fsl_devices.h> | 17 | #include <linux/fsl_devices.h> |
18 | #include <linux/of_address.h> | ||
19 | #include <linux/of_fdt.h> | ||
18 | #include <linux/of_platform.h> | 20 | #include <linux/of_platform.h> |
19 | 21 | ||
20 | #include <asm/io.h> | 22 | #include <asm/io.h> |
diff --git a/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c b/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c index 7bc315822935..fd71cfdf2380 100644 --- a/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c +++ b/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c | |||
@@ -204,7 +204,6 @@ static int mcu_remove(struct i2c_client *client) | |||
204 | ret = mcu_gpiochip_remove(mcu); | 204 | ret = mcu_gpiochip_remove(mcu); |
205 | if (ret) | 205 | if (ret) |
206 | return ret; | 206 | return ret; |
207 | i2c_set_clientdata(client, NULL); | ||
208 | kfree(mcu); | 207 | kfree(mcu); |
209 | return 0; | 208 | return 0; |
210 | } | 209 | } |
diff --git a/arch/powerpc/platforms/83xx/suspend.c b/arch/powerpc/platforms/83xx/suspend.c index 1d769a29249f..3d9716ccd327 100644 --- a/arch/powerpc/platforms/83xx/suspend.c +++ b/arch/powerpc/platforms/83xx/suspend.c | |||
@@ -20,6 +20,8 @@ | |||
20 | #include <linux/freezer.h> | 20 | #include <linux/freezer.h> |
21 | #include <linux/suspend.h> | 21 | #include <linux/suspend.h> |
22 | #include <linux/fsl_devices.h> | 22 | #include <linux/fsl_devices.h> |
23 | #include <linux/of_address.h> | ||
24 | #include <linux/of_irq.h> | ||
23 | #include <linux/of_platform.h> | 25 | #include <linux/of_platform.h> |
24 | #include <linux/export.h> | 26 | #include <linux/export.h> |
25 | 27 | ||
diff --git a/arch/powerpc/platforms/85xx/Kconfig b/arch/powerpc/platforms/85xx/Kconfig index de2eb9320993..4d4634958cfb 100644 --- a/arch/powerpc/platforms/85xx/Kconfig +++ b/arch/powerpc/platforms/85xx/Kconfig | |||
@@ -218,83 +218,16 @@ config GE_IMP3A | |||
218 | This board is a 3U CompactPCI Single Board Computer with a Freescale | 218 | This board is a 3U CompactPCI Single Board Computer with a Freescale |
219 | P2020 processor. | 219 | P2020 processor. |
220 | 220 | ||
221 | config P2041_RDB | ||
222 | bool "Freescale P2041 RDB" | ||
223 | select DEFAULT_UIMAGE | ||
224 | select PPC_E500MC | ||
225 | select PHYS_64BIT | ||
226 | select SWIOTLB | ||
227 | select ARCH_REQUIRE_GPIOLIB | ||
228 | select GPIO_MPC8XXX | ||
229 | select HAS_RAPIDIO | ||
230 | select PPC_EPAPR_HV_PIC | ||
231 | help | ||
232 | This option enables support for the P2041 RDB board | ||
233 | |||
234 | config P3041_DS | ||
235 | bool "Freescale P3041 DS" | ||
236 | select DEFAULT_UIMAGE | ||
237 | select PPC_E500MC | ||
238 | select PHYS_64BIT | ||
239 | select SWIOTLB | ||
240 | select ARCH_REQUIRE_GPIOLIB | ||
241 | select GPIO_MPC8XXX | ||
242 | select HAS_RAPIDIO | ||
243 | select PPC_EPAPR_HV_PIC | ||
244 | help | ||
245 | This option enables support for the P3041 DS board | ||
246 | |||
247 | config P4080_DS | ||
248 | bool "Freescale P4080 DS" | ||
249 | select DEFAULT_UIMAGE | ||
250 | select PPC_E500MC | ||
251 | select PHYS_64BIT | ||
252 | select SWIOTLB | ||
253 | select ARCH_REQUIRE_GPIOLIB | ||
254 | select GPIO_MPC8XXX | ||
255 | select HAS_RAPIDIO | ||
256 | select PPC_EPAPR_HV_PIC | ||
257 | help | ||
258 | This option enables support for the P4080 DS board | ||
259 | |||
260 | config SGY_CTS1000 | 221 | config SGY_CTS1000 |
261 | tristate "Servergy CTS-1000 support" | 222 | tristate "Servergy CTS-1000 support" |
262 | select GPIOLIB | 223 | select GPIOLIB |
263 | select OF_GPIO | 224 | select OF_GPIO |
264 | depends on P4080_DS | 225 | depends on CORENET_GENERIC |
265 | help | 226 | help |
266 | Enable this to support functionality in Servergy's CTS-1000 systems. | 227 | Enable this to support functionality in Servergy's CTS-1000 systems. |
267 | 228 | ||
268 | endif # PPC32 | 229 | endif # PPC32 |
269 | 230 | ||
270 | config P5020_DS | ||
271 | bool "Freescale P5020 DS" | ||
272 | select DEFAULT_UIMAGE | ||
273 | select E500 | ||
274 | select PPC_E500MC | ||
275 | select PHYS_64BIT | ||
276 | select SWIOTLB | ||
277 | select ARCH_REQUIRE_GPIOLIB | ||
278 | select GPIO_MPC8XXX | ||
279 | select HAS_RAPIDIO | ||
280 | select PPC_EPAPR_HV_PIC | ||
281 | help | ||
282 | This option enables support for the P5020 DS board | ||
283 | |||
284 | config P5040_DS | ||
285 | bool "Freescale P5040 DS" | ||
286 | select DEFAULT_UIMAGE | ||
287 | select E500 | ||
288 | select PPC_E500MC | ||
289 | select PHYS_64BIT | ||
290 | select SWIOTLB | ||
291 | select ARCH_REQUIRE_GPIOLIB | ||
292 | select GPIO_MPC8XXX | ||
293 | select HAS_RAPIDIO | ||
294 | select PPC_EPAPR_HV_PIC | ||
295 | help | ||
296 | This option enables support for the P5040 DS board | ||
297 | |||
298 | config PPC_QEMU_E500 | 231 | config PPC_QEMU_E500 |
299 | bool "QEMU generic e500 platform" | 232 | bool "QEMU generic e500 platform" |
300 | select DEFAULT_UIMAGE | 233 | select DEFAULT_UIMAGE |
@@ -310,10 +243,8 @@ config PPC_QEMU_E500 | |||
310 | unset based on the emulated CPU (or actual host CPU in the case | 243 | unset based on the emulated CPU (or actual host CPU in the case |
311 | of KVM). | 244 | of KVM). |
312 | 245 | ||
313 | if PPC64 | 246 | config CORENET_GENERIC |
314 | 247 | bool "Freescale CoreNet Generic" | |
315 | config T4240_QDS | ||
316 | bool "Freescale T4240 QDS" | ||
317 | select DEFAULT_UIMAGE | 248 | select DEFAULT_UIMAGE |
318 | select E500 | 249 | select E500 |
319 | select PPC_E500MC | 250 | select PPC_E500MC |
@@ -324,26 +255,14 @@ config T4240_QDS | |||
324 | select HAS_RAPIDIO | 255 | select HAS_RAPIDIO |
325 | select PPC_EPAPR_HV_PIC | 256 | select PPC_EPAPR_HV_PIC |
326 | help | 257 | help |
327 | This option enables support for the T4240 QDS board | 258 | This option enables support for the FSL CoreNet based boards. |
328 | 259 | For 32bit kernel, the following boards are supported: | |
329 | config B4_QDS | 260 | P2041 RDB, P3041 DS and P4080 DS |
330 | bool "Freescale B4 QDS" | 261 | For 64bit kernel, the following boards are supported: |
331 | select DEFAULT_UIMAGE | 262 | T4240 QDS and B4 QDS |
332 | select E500 | 263 | The following boards are supported for both 32bit and 64bit kernel: |
333 | select PPC_E500MC | 264 | P5020 DS and P5040 DS |
334 | select PHYS_64BIT | ||
335 | select SWIOTLB | ||
336 | select GPIOLIB | ||
337 | select ARCH_REQUIRE_GPIOLIB | ||
338 | select HAS_RAPIDIO | ||
339 | select PPC_EPAPR_HV_PIC | ||
340 | help | ||
341 | This option enables support for the B4 QDS board | ||
342 | The B4 application development system B4 QDS is a complete | ||
343 | debugging environment intended for engineers developing | ||
344 | applications for the B4. | ||
345 | 265 | ||
346 | endif | ||
347 | endif # FSL_SOC_BOOKE | 266 | endif # FSL_SOC_BOOKE |
348 | 267 | ||
349 | config TQM85xx | 268 | config TQM85xx |
diff --git a/arch/powerpc/platforms/85xx/Makefile b/arch/powerpc/platforms/85xx/Makefile index 53c9f75a6907..dd4c0b59577b 100644 --- a/arch/powerpc/platforms/85xx/Makefile +++ b/arch/powerpc/platforms/85xx/Makefile | |||
@@ -18,13 +18,7 @@ obj-$(CONFIG_P1010_RDB) += p1010rdb.o | |||
18 | obj-$(CONFIG_P1022_DS) += p1022_ds.o | 18 | obj-$(CONFIG_P1022_DS) += p1022_ds.o |
19 | obj-$(CONFIG_P1022_RDK) += p1022_rdk.o | 19 | obj-$(CONFIG_P1022_RDK) += p1022_rdk.o |
20 | obj-$(CONFIG_P1023_RDS) += p1023_rds.o | 20 | obj-$(CONFIG_P1023_RDS) += p1023_rds.o |
21 | obj-$(CONFIG_P2041_RDB) += p2041_rdb.o corenet_ds.o | 21 | obj-$(CONFIG_CORENET_GENERIC) += corenet_generic.o |
22 | obj-$(CONFIG_P3041_DS) += p3041_ds.o corenet_ds.o | ||
23 | obj-$(CONFIG_P4080_DS) += p4080_ds.o corenet_ds.o | ||
24 | obj-$(CONFIG_P5020_DS) += p5020_ds.o corenet_ds.o | ||
25 | obj-$(CONFIG_P5040_DS) += p5040_ds.o corenet_ds.o | ||
26 | obj-$(CONFIG_T4240_QDS) += t4240_qds.o corenet_ds.o | ||
27 | obj-$(CONFIG_B4_QDS) += b4_qds.o corenet_ds.o | ||
28 | obj-$(CONFIG_STX_GP3) += stx_gp3.o | 22 | obj-$(CONFIG_STX_GP3) += stx_gp3.o |
29 | obj-$(CONFIG_TQM85xx) += tqm85xx.o | 23 | obj-$(CONFIG_TQM85xx) += tqm85xx.o |
30 | obj-$(CONFIG_SBC8548) += sbc8548.o | 24 | obj-$(CONFIG_SBC8548) += sbc8548.o |
diff --git a/arch/powerpc/platforms/85xx/b4_qds.c b/arch/powerpc/platforms/85xx/b4_qds.c deleted file mode 100644 index 0c6702f8b88e..000000000000 --- a/arch/powerpc/platforms/85xx/b4_qds.c +++ /dev/null | |||
@@ -1,102 +0,0 @@ | |||
1 | /* | ||
2 | * B4 QDS Setup | ||
3 | * Should apply for QDS platform of B4860 and it's personalities. | ||
4 | * viz B4860/B4420/B4220QDS | ||
5 | * | ||
6 | * Copyright 2012 Freescale Semiconductor Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/pci.h> | ||
16 | #include <linux/kdev_t.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/phy.h> | ||
20 | |||
21 | #include <asm/time.h> | ||
22 | #include <asm/machdep.h> | ||
23 | #include <asm/pci-bridge.h> | ||
24 | #include <mm/mmu_decl.h> | ||
25 | #include <asm/prom.h> | ||
26 | #include <asm/udbg.h> | ||
27 | #include <asm/mpic.h> | ||
28 | |||
29 | #include <linux/of_platform.h> | ||
30 | #include <sysdev/fsl_soc.h> | ||
31 | #include <sysdev/fsl_pci.h> | ||
32 | #include <asm/ehv_pic.h> | ||
33 | |||
34 | #include "corenet_ds.h" | ||
35 | |||
36 | /* | ||
37 | * Called very early, device-tree isn't unflattened | ||
38 | */ | ||
39 | static int __init b4_qds_probe(void) | ||
40 | { | ||
41 | unsigned long root = of_get_flat_dt_root(); | ||
42 | #ifdef CONFIG_SMP | ||
43 | extern struct smp_ops_t smp_85xx_ops; | ||
44 | #endif | ||
45 | |||
46 | if ((of_flat_dt_is_compatible(root, "fsl,B4860QDS")) || | ||
47 | (of_flat_dt_is_compatible(root, "fsl,B4420QDS")) || | ||
48 | (of_flat_dt_is_compatible(root, "fsl,B4220QDS"))) | ||
49 | return 1; | ||
50 | |||
51 | /* Check if we're running under the Freescale hypervisor */ | ||
52 | if ((of_flat_dt_is_compatible(root, "fsl,B4860QDS-hv")) || | ||
53 | (of_flat_dt_is_compatible(root, "fsl,B4420QDS-hv")) || | ||
54 | (of_flat_dt_is_compatible(root, "fsl,B4220QDS-hv"))) { | ||
55 | ppc_md.init_IRQ = ehv_pic_init; | ||
56 | ppc_md.get_irq = ehv_pic_get_irq; | ||
57 | ppc_md.restart = fsl_hv_restart; | ||
58 | ppc_md.power_off = fsl_hv_halt; | ||
59 | ppc_md.halt = fsl_hv_halt; | ||
60 | #ifdef CONFIG_SMP | ||
61 | /* | ||
62 | * Disable the timebase sync operations because we can't write | ||
63 | * to the timebase registers under the hypervisor. | ||
64 | */ | ||
65 | smp_85xx_ops.give_timebase = NULL; | ||
66 | smp_85xx_ops.take_timebase = NULL; | ||
67 | #endif | ||
68 | return 1; | ||
69 | } | ||
70 | |||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | define_machine(b4_qds) { | ||
75 | .name = "B4 QDS", | ||
76 | .probe = b4_qds_probe, | ||
77 | .setup_arch = corenet_ds_setup_arch, | ||
78 | .init_IRQ = corenet_ds_pic_init, | ||
79 | #ifdef CONFIG_PCI | ||
80 | .pcibios_fixup_bus = fsl_pcibios_fixup_bus, | ||
81 | #endif | ||
82 | /* coreint doesn't play nice with lazy EE, use legacy mpic for now */ | ||
83 | #ifdef CONFIG_PPC64 | ||
84 | .get_irq = mpic_get_irq, | ||
85 | #else | ||
86 | .get_irq = mpic_get_coreint_irq, | ||
87 | #endif | ||
88 | .restart = fsl_rstcr_restart, | ||
89 | .calibrate_decr = generic_calibrate_decr, | ||
90 | .progress = udbg_progress, | ||
91 | #ifdef CONFIG_PPC64 | ||
92 | .power_save = book3e_idle, | ||
93 | #else | ||
94 | .power_save = e500_idle, | ||
95 | #endif | ||
96 | }; | ||
97 | |||
98 | machine_arch_initcall(b4_qds, corenet_ds_publish_devices); | ||
99 | |||
100 | #ifdef CONFIG_SWIOTLB | ||
101 | machine_arch_initcall(b4_qds, swiotlb_setup_bus_notifier); | ||
102 | #endif | ||
diff --git a/arch/powerpc/platforms/85xx/c293pcie.c b/arch/powerpc/platforms/85xx/c293pcie.c index 6208e49142bf..213d5b815827 100644 --- a/arch/powerpc/platforms/85xx/c293pcie.c +++ b/arch/powerpc/platforms/85xx/c293pcie.c | |||
@@ -11,6 +11,7 @@ | |||
11 | 11 | ||
12 | #include <linux/stddef.h> | 12 | #include <linux/stddef.h> |
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/of_fdt.h> | ||
14 | #include <linux/of_platform.h> | 15 | #include <linux/of_platform.h> |
15 | 16 | ||
16 | #include <asm/machdep.h> | 17 | #include <asm/machdep.h> |
diff --git a/arch/powerpc/platforms/85xx/common.c b/arch/powerpc/platforms/85xx/common.c index d0861a0d8360..eba78c85303f 100644 --- a/arch/powerpc/platforms/85xx/common.c +++ b/arch/powerpc/platforms/85xx/common.c | |||
@@ -5,6 +5,8 @@ | |||
5 | * it under the terms of the GNU General Public License version 2 as | 5 | * it under the terms of the GNU General Public License version 2 as |
6 | * published by the Free Software Foundation. | 6 | * published by the Free Software Foundation. |
7 | */ | 7 | */ |
8 | |||
9 | #include <linux/of_irq.h> | ||
8 | #include <linux/of_platform.h> | 10 | #include <linux/of_platform.h> |
9 | 11 | ||
10 | #include <sysdev/cpm2_pic.h> | 12 | #include <sysdev/cpm2_pic.h> |
diff --git a/arch/powerpc/platforms/85xx/corenet_ds.c b/arch/powerpc/platforms/85xx/corenet_ds.c deleted file mode 100644 index aa3690bae415..000000000000 --- a/arch/powerpc/platforms/85xx/corenet_ds.c +++ /dev/null | |||
@@ -1,96 +0,0 @@ | |||
1 | /* | ||
2 | * Corenet based SoC DS Setup | ||
3 | * | ||
4 | * Maintained by Kumar Gala (see MAINTAINERS for contact information) | ||
5 | * | ||
6 | * Copyright 2009-2011 Freescale Semiconductor Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/pci.h> | ||
16 | #include <linux/kdev_t.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | |||
20 | #include <asm/time.h> | ||
21 | #include <asm/machdep.h> | ||
22 | #include <asm/pci-bridge.h> | ||
23 | #include <asm/ppc-pci.h> | ||
24 | #include <mm/mmu_decl.h> | ||
25 | #include <asm/prom.h> | ||
26 | #include <asm/udbg.h> | ||
27 | #include <asm/mpic.h> | ||
28 | |||
29 | #include <linux/of_platform.h> | ||
30 | #include <sysdev/fsl_soc.h> | ||
31 | #include <sysdev/fsl_pci.h> | ||
32 | #include "smp.h" | ||
33 | |||
34 | void __init corenet_ds_pic_init(void) | ||
35 | { | ||
36 | struct mpic *mpic; | ||
37 | unsigned int flags = MPIC_BIG_ENDIAN | MPIC_SINGLE_DEST_CPU | | ||
38 | MPIC_NO_RESET; | ||
39 | |||
40 | if (ppc_md.get_irq == mpic_get_coreint_irq) | ||
41 | flags |= MPIC_ENABLE_COREINT; | ||
42 | |||
43 | mpic = mpic_alloc(NULL, 0, flags, 0, 512, " OpenPIC "); | ||
44 | BUG_ON(mpic == NULL); | ||
45 | |||
46 | mpic_init(mpic); | ||
47 | } | ||
48 | |||
49 | /* | ||
50 | * Setup the architecture | ||
51 | */ | ||
52 | void __init corenet_ds_setup_arch(void) | ||
53 | { | ||
54 | mpc85xx_smp_init(); | ||
55 | |||
56 | swiotlb_detect_4g(); | ||
57 | |||
58 | pr_info("%s board from Freescale Semiconductor\n", ppc_md.name); | ||
59 | } | ||
60 | |||
61 | static const struct of_device_id of_device_ids[] = { | ||
62 | { | ||
63 | .compatible = "simple-bus" | ||
64 | }, | ||
65 | { | ||
66 | .compatible = "fsl,srio", | ||
67 | }, | ||
68 | { | ||
69 | .compatible = "fsl,p4080-pcie", | ||
70 | }, | ||
71 | { | ||
72 | .compatible = "fsl,qoriq-pcie-v2.2", | ||
73 | }, | ||
74 | { | ||
75 | .compatible = "fsl,qoriq-pcie-v2.3", | ||
76 | }, | ||
77 | { | ||
78 | .compatible = "fsl,qoriq-pcie-v2.4", | ||
79 | }, | ||
80 | { | ||
81 | .compatible = "fsl,qoriq-pcie-v3.0", | ||
82 | }, | ||
83 | /* The following two are for the Freescale hypervisor */ | ||
84 | { | ||
85 | .name = "hypervisor", | ||
86 | }, | ||
87 | { | ||
88 | .name = "handles", | ||
89 | }, | ||
90 | {} | ||
91 | }; | ||
92 | |||
93 | int __init corenet_ds_publish_devices(void) | ||
94 | { | ||
95 | return of_platform_bus_probe(NULL, of_device_ids, NULL); | ||
96 | } | ||
diff --git a/arch/powerpc/platforms/85xx/corenet_ds.h b/arch/powerpc/platforms/85xx/corenet_ds.h deleted file mode 100644 index ddd700b23031..000000000000 --- a/arch/powerpc/platforms/85xx/corenet_ds.h +++ /dev/null | |||
@@ -1,19 +0,0 @@ | |||
1 | /* | ||
2 | * Corenet based SoC DS Setup | ||
3 | * | ||
4 | * Copyright 2009 Freescale Semiconductor Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #ifndef CORENET_DS_H | ||
13 | #define CORENET_DS_H | ||
14 | |||
15 | extern void __init corenet_ds_pic_init(void); | ||
16 | extern void __init corenet_ds_setup_arch(void); | ||
17 | extern int __init corenet_ds_publish_devices(void); | ||
18 | |||
19 | #endif | ||
diff --git a/arch/powerpc/platforms/85xx/corenet_generic.c b/arch/powerpc/platforms/85xx/corenet_generic.c new file mode 100644 index 000000000000..fbd871e69754 --- /dev/null +++ b/arch/powerpc/platforms/85xx/corenet_generic.c | |||
@@ -0,0 +1,182 @@ | |||
1 | /* | ||
2 | * Corenet based SoC DS Setup | ||
3 | * | ||
4 | * Maintained by Kumar Gala (see MAINTAINERS for contact information) | ||
5 | * | ||
6 | * Copyright 2009-2011 Freescale Semiconductor Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/pci.h> | ||
16 | #include <linux/kdev_t.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | |||
20 | #include <asm/time.h> | ||
21 | #include <asm/machdep.h> | ||
22 | #include <asm/pci-bridge.h> | ||
23 | #include <asm/ppc-pci.h> | ||
24 | #include <mm/mmu_decl.h> | ||
25 | #include <asm/prom.h> | ||
26 | #include <asm/udbg.h> | ||
27 | #include <asm/mpic.h> | ||
28 | #include <asm/ehv_pic.h> | ||
29 | |||
30 | #include <linux/of_platform.h> | ||
31 | #include <sysdev/fsl_soc.h> | ||
32 | #include <sysdev/fsl_pci.h> | ||
33 | #include "smp.h" | ||
34 | |||
35 | void __init corenet_gen_pic_init(void) | ||
36 | { | ||
37 | struct mpic *mpic; | ||
38 | unsigned int flags = MPIC_BIG_ENDIAN | MPIC_SINGLE_DEST_CPU | | ||
39 | MPIC_NO_RESET; | ||
40 | |||
41 | if (ppc_md.get_irq == mpic_get_coreint_irq) | ||
42 | flags |= MPIC_ENABLE_COREINT; | ||
43 | |||
44 | mpic = mpic_alloc(NULL, 0, flags, 0, 512, " OpenPIC "); | ||
45 | BUG_ON(mpic == NULL); | ||
46 | |||
47 | mpic_init(mpic); | ||
48 | } | ||
49 | |||
50 | /* | ||
51 | * Setup the architecture | ||
52 | */ | ||
53 | void __init corenet_gen_setup_arch(void) | ||
54 | { | ||
55 | mpc85xx_smp_init(); | ||
56 | |||
57 | swiotlb_detect_4g(); | ||
58 | |||
59 | pr_info("%s board from Freescale Semiconductor\n", ppc_md.name); | ||
60 | } | ||
61 | |||
62 | static const struct of_device_id of_device_ids[] = { | ||
63 | { | ||
64 | .compatible = "simple-bus" | ||
65 | }, | ||
66 | { | ||
67 | .compatible = "fsl,srio", | ||
68 | }, | ||
69 | { | ||
70 | .compatible = "fsl,p4080-pcie", | ||
71 | }, | ||
72 | { | ||
73 | .compatible = "fsl,qoriq-pcie-v2.2", | ||
74 | }, | ||
75 | { | ||
76 | .compatible = "fsl,qoriq-pcie-v2.3", | ||
77 | }, | ||
78 | { | ||
79 | .compatible = "fsl,qoriq-pcie-v2.4", | ||
80 | }, | ||
81 | { | ||
82 | .compatible = "fsl,qoriq-pcie-v3.0", | ||
83 | }, | ||
84 | /* The following two are for the Freescale hypervisor */ | ||
85 | { | ||
86 | .name = "hypervisor", | ||
87 | }, | ||
88 | { | ||
89 | .name = "handles", | ||
90 | }, | ||
91 | {} | ||
92 | }; | ||
93 | |||
94 | int __init corenet_gen_publish_devices(void) | ||
95 | { | ||
96 | return of_platform_bus_probe(NULL, of_device_ids, NULL); | ||
97 | } | ||
98 | |||
99 | static const char * const boards[] __initconst = { | ||
100 | "fsl,P2041RDB", | ||
101 | "fsl,P3041DS", | ||
102 | "fsl,P4080DS", | ||
103 | "fsl,P5020DS", | ||
104 | "fsl,P5040DS", | ||
105 | "fsl,T4240QDS", | ||
106 | "fsl,B4860QDS", | ||
107 | "fsl,B4420QDS", | ||
108 | "fsl,B4220QDS", | ||
109 | NULL | ||
110 | }; | ||
111 | |||
112 | static const char * const hv_boards[] __initconst = { | ||
113 | "fsl,P2041RDB-hv", | ||
114 | "fsl,P3041DS-hv", | ||
115 | "fsl,P4080DS-hv", | ||
116 | "fsl,P5020DS-hv", | ||
117 | "fsl,P5040DS-hv", | ||
118 | "fsl,T4240QDS-hv", | ||
119 | "fsl,B4860QDS-hv", | ||
120 | "fsl,B4420QDS-hv", | ||
121 | "fsl,B4220QDS-hv", | ||
122 | NULL | ||
123 | }; | ||
124 | |||
125 | /* | ||
126 | * Called very early, device-tree isn't unflattened | ||
127 | */ | ||
128 | static int __init corenet_generic_probe(void) | ||
129 | { | ||
130 | unsigned long root = of_get_flat_dt_root(); | ||
131 | #ifdef CONFIG_SMP | ||
132 | extern struct smp_ops_t smp_85xx_ops; | ||
133 | #endif | ||
134 | |||
135 | if (of_flat_dt_match(root, boards)) | ||
136 | return 1; | ||
137 | |||
138 | /* Check if we're running under the Freescale hypervisor */ | ||
139 | if (of_flat_dt_match(root, hv_boards)) { | ||
140 | ppc_md.init_IRQ = ehv_pic_init; | ||
141 | ppc_md.get_irq = ehv_pic_get_irq; | ||
142 | ppc_md.restart = fsl_hv_restart; | ||
143 | ppc_md.power_off = fsl_hv_halt; | ||
144 | ppc_md.halt = fsl_hv_halt; | ||
145 | #ifdef CONFIG_SMP | ||
146 | /* | ||
147 | * Disable the timebase sync operations because we can't write | ||
148 | * to the timebase registers under the hypervisor. | ||
149 | */ | ||
150 | smp_85xx_ops.give_timebase = NULL; | ||
151 | smp_85xx_ops.take_timebase = NULL; | ||
152 | #endif | ||
153 | return 1; | ||
154 | } | ||
155 | |||
156 | return 0; | ||
157 | } | ||
158 | |||
159 | define_machine(corenet_generic) { | ||
160 | .name = "CoreNet Generic", | ||
161 | .probe = corenet_generic_probe, | ||
162 | .setup_arch = corenet_gen_setup_arch, | ||
163 | .init_IRQ = corenet_gen_pic_init, | ||
164 | #ifdef CONFIG_PCI | ||
165 | .pcibios_fixup_bus = fsl_pcibios_fixup_bus, | ||
166 | #endif | ||
167 | .get_irq = mpic_get_coreint_irq, | ||
168 | .restart = fsl_rstcr_restart, | ||
169 | .calibrate_decr = generic_calibrate_decr, | ||
170 | .progress = udbg_progress, | ||
171 | #ifdef CONFIG_PPC64 | ||
172 | .power_save = book3e_idle, | ||
173 | #else | ||
174 | .power_save = e500_idle, | ||
175 | #endif | ||
176 | }; | ||
177 | |||
178 | machine_arch_initcall(corenet_generic, corenet_gen_publish_devices); | ||
179 | |||
180 | #ifdef CONFIG_SWIOTLB | ||
181 | machine_arch_initcall(corenet_generic, swiotlb_setup_bus_notifier); | ||
182 | #endif | ||
diff --git a/arch/powerpc/platforms/85xx/p1010rdb.c b/arch/powerpc/platforms/85xx/p1010rdb.c index 0252961392d5..d6a3dd311494 100644 --- a/arch/powerpc/platforms/85xx/p1010rdb.c +++ b/arch/powerpc/platforms/85xx/p1010rdb.c | |||
@@ -66,6 +66,8 @@ static int __init p1010_rdb_probe(void) | |||
66 | 66 | ||
67 | if (of_flat_dt_is_compatible(root, "fsl,P1010RDB")) | 67 | if (of_flat_dt_is_compatible(root, "fsl,P1010RDB")) |
68 | return 1; | 68 | return 1; |
69 | if (of_flat_dt_is_compatible(root, "fsl,P1010RDB-PB")) | ||
70 | return 1; | ||
69 | return 0; | 71 | return 0; |
70 | } | 72 | } |
71 | 73 | ||
diff --git a/arch/powerpc/platforms/85xx/p2041_rdb.c b/arch/powerpc/platforms/85xx/p2041_rdb.c deleted file mode 100644 index 000c0892fc40..000000000000 --- a/arch/powerpc/platforms/85xx/p2041_rdb.c +++ /dev/null | |||
@@ -1,87 +0,0 @@ | |||
1 | /* | ||
2 | * P2041 RDB Setup | ||
3 | * | ||
4 | * Copyright 2011 Freescale Semiconductor Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/pci.h> | ||
14 | #include <linux/kdev_t.h> | ||
15 | #include <linux/delay.h> | ||
16 | #include <linux/interrupt.h> | ||
17 | #include <linux/phy.h> | ||
18 | |||
19 | #include <asm/time.h> | ||
20 | #include <asm/machdep.h> | ||
21 | #include <asm/pci-bridge.h> | ||
22 | #include <mm/mmu_decl.h> | ||
23 | #include <asm/prom.h> | ||
24 | #include <asm/udbg.h> | ||
25 | #include <asm/mpic.h> | ||
26 | |||
27 | #include <linux/of_platform.h> | ||
28 | #include <sysdev/fsl_soc.h> | ||
29 | #include <sysdev/fsl_pci.h> | ||
30 | #include <asm/ehv_pic.h> | ||
31 | |||
32 | #include "corenet_ds.h" | ||
33 | |||
34 | /* | ||
35 | * Called very early, device-tree isn't unflattened | ||
36 | */ | ||
37 | static int __init p2041_rdb_probe(void) | ||
38 | { | ||
39 | unsigned long root = of_get_flat_dt_root(); | ||
40 | #ifdef CONFIG_SMP | ||
41 | extern struct smp_ops_t smp_85xx_ops; | ||
42 | #endif | ||
43 | |||
44 | if (of_flat_dt_is_compatible(root, "fsl,P2041RDB")) | ||
45 | return 1; | ||
46 | |||
47 | /* Check if we're running under the Freescale hypervisor */ | ||
48 | if (of_flat_dt_is_compatible(root, "fsl,P2041RDB-hv")) { | ||
49 | ppc_md.init_IRQ = ehv_pic_init; | ||
50 | ppc_md.get_irq = ehv_pic_get_irq; | ||
51 | ppc_md.restart = fsl_hv_restart; | ||
52 | ppc_md.power_off = fsl_hv_halt; | ||
53 | ppc_md.halt = fsl_hv_halt; | ||
54 | #ifdef CONFIG_SMP | ||
55 | /* | ||
56 | * Disable the timebase sync operations because we can't write | ||
57 | * to the timebase registers under the hypervisor. | ||
58 | */ | ||
59 | smp_85xx_ops.give_timebase = NULL; | ||
60 | smp_85xx_ops.take_timebase = NULL; | ||
61 | #endif | ||
62 | return 1; | ||
63 | } | ||
64 | |||
65 | return 0; | ||
66 | } | ||
67 | |||
68 | define_machine(p2041_rdb) { | ||
69 | .name = "P2041 RDB", | ||
70 | .probe = p2041_rdb_probe, | ||
71 | .setup_arch = corenet_ds_setup_arch, | ||
72 | .init_IRQ = corenet_ds_pic_init, | ||
73 | #ifdef CONFIG_PCI | ||
74 | .pcibios_fixup_bus = fsl_pcibios_fixup_bus, | ||
75 | #endif | ||
76 | .get_irq = mpic_get_coreint_irq, | ||
77 | .restart = fsl_rstcr_restart, | ||
78 | .calibrate_decr = generic_calibrate_decr, | ||
79 | .progress = udbg_progress, | ||
80 | .power_save = e500_idle, | ||
81 | }; | ||
82 | |||
83 | machine_arch_initcall(p2041_rdb, corenet_ds_publish_devices); | ||
84 | |||
85 | #ifdef CONFIG_SWIOTLB | ||
86 | machine_arch_initcall(p2041_rdb, swiotlb_setup_bus_notifier); | ||
87 | #endif | ||
diff --git a/arch/powerpc/platforms/85xx/p3041_ds.c b/arch/powerpc/platforms/85xx/p3041_ds.c deleted file mode 100644 index b3edc205daa9..000000000000 --- a/arch/powerpc/platforms/85xx/p3041_ds.c +++ /dev/null | |||
@@ -1,89 +0,0 @@ | |||
1 | /* | ||
2 | * P3041 DS Setup | ||
3 | * | ||
4 | * Maintained by Kumar Gala (see MAINTAINERS for contact information) | ||
5 | * | ||
6 | * Copyright 2009-2010 Freescale Semiconductor Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/pci.h> | ||
16 | #include <linux/kdev_t.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/phy.h> | ||
20 | |||
21 | #include <asm/time.h> | ||
22 | #include <asm/machdep.h> | ||
23 | #include <asm/pci-bridge.h> | ||
24 | #include <mm/mmu_decl.h> | ||
25 | #include <asm/prom.h> | ||
26 | #include <asm/udbg.h> | ||
27 | #include <asm/mpic.h> | ||
28 | |||
29 | #include <linux/of_platform.h> | ||
30 | #include <sysdev/fsl_soc.h> | ||
31 | #include <sysdev/fsl_pci.h> | ||
32 | #include <asm/ehv_pic.h> | ||
33 | |||
34 | #include "corenet_ds.h" | ||
35 | |||
36 | /* | ||
37 | * Called very early, device-tree isn't unflattened | ||
38 | */ | ||
39 | static int __init p3041_ds_probe(void) | ||
40 | { | ||
41 | unsigned long root = of_get_flat_dt_root(); | ||
42 | #ifdef CONFIG_SMP | ||
43 | extern struct smp_ops_t smp_85xx_ops; | ||
44 | #endif | ||
45 | |||
46 | if (of_flat_dt_is_compatible(root, "fsl,P3041DS")) | ||
47 | return 1; | ||
48 | |||
49 | /* Check if we're running under the Freescale hypervisor */ | ||
50 | if (of_flat_dt_is_compatible(root, "fsl,P3041DS-hv")) { | ||
51 | ppc_md.init_IRQ = ehv_pic_init; | ||
52 | ppc_md.get_irq = ehv_pic_get_irq; | ||
53 | ppc_md.restart = fsl_hv_restart; | ||
54 | ppc_md.power_off = fsl_hv_halt; | ||
55 | ppc_md.halt = fsl_hv_halt; | ||
56 | #ifdef CONFIG_SMP | ||
57 | /* | ||
58 | * Disable the timebase sync operations because we can't write | ||
59 | * to the timebase registers under the hypervisor. | ||
60 | */ | ||
61 | smp_85xx_ops.give_timebase = NULL; | ||
62 | smp_85xx_ops.take_timebase = NULL; | ||
63 | #endif | ||
64 | return 1; | ||
65 | } | ||
66 | |||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | define_machine(p3041_ds) { | ||
71 | .name = "P3041 DS", | ||
72 | .probe = p3041_ds_probe, | ||
73 | .setup_arch = corenet_ds_setup_arch, | ||
74 | .init_IRQ = corenet_ds_pic_init, | ||
75 | #ifdef CONFIG_PCI | ||
76 | .pcibios_fixup_bus = fsl_pcibios_fixup_bus, | ||
77 | #endif | ||
78 | .get_irq = mpic_get_coreint_irq, | ||
79 | .restart = fsl_rstcr_restart, | ||
80 | .calibrate_decr = generic_calibrate_decr, | ||
81 | .progress = udbg_progress, | ||
82 | .power_save = e500_idle, | ||
83 | }; | ||
84 | |||
85 | machine_arch_initcall(p3041_ds, corenet_ds_publish_devices); | ||
86 | |||
87 | #ifdef CONFIG_SWIOTLB | ||
88 | machine_arch_initcall(p3041_ds, swiotlb_setup_bus_notifier); | ||
89 | #endif | ||
diff --git a/arch/powerpc/platforms/85xx/p4080_ds.c b/arch/powerpc/platforms/85xx/p4080_ds.c deleted file mode 100644 index 54df10632aea..000000000000 --- a/arch/powerpc/platforms/85xx/p4080_ds.c +++ /dev/null | |||
@@ -1,87 +0,0 @@ | |||
1 | /* | ||
2 | * P4080 DS Setup | ||
3 | * | ||
4 | * Maintained by Kumar Gala (see MAINTAINERS for contact information) | ||
5 | * | ||
6 | * Copyright 2009 Freescale Semiconductor Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/pci.h> | ||
16 | #include <linux/kdev_t.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | |||
20 | #include <asm/time.h> | ||
21 | #include <asm/machdep.h> | ||
22 | #include <asm/pci-bridge.h> | ||
23 | #include <mm/mmu_decl.h> | ||
24 | #include <asm/prom.h> | ||
25 | #include <asm/udbg.h> | ||
26 | #include <asm/mpic.h> | ||
27 | |||
28 | #include <linux/of_platform.h> | ||
29 | #include <sysdev/fsl_soc.h> | ||
30 | #include <sysdev/fsl_pci.h> | ||
31 | #include <asm/ehv_pic.h> | ||
32 | |||
33 | #include "corenet_ds.h" | ||
34 | |||
35 | /* | ||
36 | * Called very early, device-tree isn't unflattened | ||
37 | */ | ||
38 | static int __init p4080_ds_probe(void) | ||
39 | { | ||
40 | unsigned long root = of_get_flat_dt_root(); | ||
41 | #ifdef CONFIG_SMP | ||
42 | extern struct smp_ops_t smp_85xx_ops; | ||
43 | #endif | ||
44 | |||
45 | if (of_flat_dt_is_compatible(root, "fsl,P4080DS")) | ||
46 | return 1; | ||
47 | |||
48 | /* Check if we're running under the Freescale hypervisor */ | ||
49 | if (of_flat_dt_is_compatible(root, "fsl,P4080DS-hv")) { | ||
50 | ppc_md.init_IRQ = ehv_pic_init; | ||
51 | ppc_md.get_irq = ehv_pic_get_irq; | ||
52 | ppc_md.restart = fsl_hv_restart; | ||
53 | ppc_md.power_off = fsl_hv_halt; | ||
54 | ppc_md.halt = fsl_hv_halt; | ||
55 | #ifdef CONFIG_SMP | ||
56 | /* | ||
57 | * Disable the timebase sync operations because we can't write | ||
58 | * to the timebase registers under the hypervisor. | ||
59 | */ | ||
60 | smp_85xx_ops.give_timebase = NULL; | ||
61 | smp_85xx_ops.take_timebase = NULL; | ||
62 | #endif | ||
63 | return 1; | ||
64 | } | ||
65 | |||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | define_machine(p4080_ds) { | ||
70 | .name = "P4080 DS", | ||
71 | .probe = p4080_ds_probe, | ||
72 | .setup_arch = corenet_ds_setup_arch, | ||
73 | .init_IRQ = corenet_ds_pic_init, | ||
74 | #ifdef CONFIG_PCI | ||
75 | .pcibios_fixup_bus = fsl_pcibios_fixup_bus, | ||
76 | #endif | ||
77 | .get_irq = mpic_get_coreint_irq, | ||
78 | .restart = fsl_rstcr_restart, | ||
79 | .calibrate_decr = generic_calibrate_decr, | ||
80 | .progress = udbg_progress, | ||
81 | .power_save = e500_idle, | ||
82 | }; | ||
83 | |||
84 | machine_arch_initcall(p4080_ds, corenet_ds_publish_devices); | ||
85 | #ifdef CONFIG_SWIOTLB | ||
86 | machine_arch_initcall(p4080_ds, swiotlb_setup_bus_notifier); | ||
87 | #endif | ||
diff --git a/arch/powerpc/platforms/85xx/p5020_ds.c b/arch/powerpc/platforms/85xx/p5020_ds.c deleted file mode 100644 index 39cfa4044e6c..000000000000 --- a/arch/powerpc/platforms/85xx/p5020_ds.c +++ /dev/null | |||
@@ -1,93 +0,0 @@ | |||
1 | /* | ||
2 | * P5020 DS Setup | ||
3 | * | ||
4 | * Maintained by Kumar Gala (see MAINTAINERS for contact information) | ||
5 | * | ||
6 | * Copyright 2009-2010 Freescale Semiconductor Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/pci.h> | ||
16 | #include <linux/kdev_t.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/phy.h> | ||
20 | |||
21 | #include <asm/time.h> | ||
22 | #include <asm/machdep.h> | ||
23 | #include <asm/pci-bridge.h> | ||
24 | #include <mm/mmu_decl.h> | ||
25 | #include <asm/prom.h> | ||
26 | #include <asm/udbg.h> | ||
27 | #include <asm/mpic.h> | ||
28 | |||
29 | #include <linux/of_platform.h> | ||
30 | #include <sysdev/fsl_soc.h> | ||
31 | #include <sysdev/fsl_pci.h> | ||
32 | #include <asm/ehv_pic.h> | ||
33 | |||
34 | #include "corenet_ds.h" | ||
35 | |||
36 | /* | ||
37 | * Called very early, device-tree isn't unflattened | ||
38 | */ | ||
39 | static int __init p5020_ds_probe(void) | ||
40 | { | ||
41 | unsigned long root = of_get_flat_dt_root(); | ||
42 | #ifdef CONFIG_SMP | ||
43 | extern struct smp_ops_t smp_85xx_ops; | ||
44 | #endif | ||
45 | |||
46 | if (of_flat_dt_is_compatible(root, "fsl,P5020DS")) | ||
47 | return 1; | ||
48 | |||
49 | /* Check if we're running under the Freescale hypervisor */ | ||
50 | if (of_flat_dt_is_compatible(root, "fsl,P5020DS-hv")) { | ||
51 | ppc_md.init_IRQ = ehv_pic_init; | ||
52 | ppc_md.get_irq = ehv_pic_get_irq; | ||
53 | ppc_md.restart = fsl_hv_restart; | ||
54 | ppc_md.power_off = fsl_hv_halt; | ||
55 | ppc_md.halt = fsl_hv_halt; | ||
56 | #ifdef CONFIG_SMP | ||
57 | /* | ||
58 | * Disable the timebase sync operations because we can't write | ||
59 | * to the timebase registers under the hypervisor. | ||
60 | */ | ||
61 | smp_85xx_ops.give_timebase = NULL; | ||
62 | smp_85xx_ops.take_timebase = NULL; | ||
63 | #endif | ||
64 | return 1; | ||
65 | } | ||
66 | |||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | define_machine(p5020_ds) { | ||
71 | .name = "P5020 DS", | ||
72 | .probe = p5020_ds_probe, | ||
73 | .setup_arch = corenet_ds_setup_arch, | ||
74 | .init_IRQ = corenet_ds_pic_init, | ||
75 | #ifdef CONFIG_PCI | ||
76 | .pcibios_fixup_bus = fsl_pcibios_fixup_bus, | ||
77 | #endif | ||
78 | .get_irq = mpic_get_coreint_irq, | ||
79 | .restart = fsl_rstcr_restart, | ||
80 | .calibrate_decr = generic_calibrate_decr, | ||
81 | .progress = udbg_progress, | ||
82 | #ifdef CONFIG_PPC64 | ||
83 | .power_save = book3e_idle, | ||
84 | #else | ||
85 | .power_save = e500_idle, | ||
86 | #endif | ||
87 | }; | ||
88 | |||
89 | machine_arch_initcall(p5020_ds, corenet_ds_publish_devices); | ||
90 | |||
91 | #ifdef CONFIG_SWIOTLB | ||
92 | machine_arch_initcall(p5020_ds, swiotlb_setup_bus_notifier); | ||
93 | #endif | ||
diff --git a/arch/powerpc/platforms/85xx/p5040_ds.c b/arch/powerpc/platforms/85xx/p5040_ds.c deleted file mode 100644 index f70e74cddf97..000000000000 --- a/arch/powerpc/platforms/85xx/p5040_ds.c +++ /dev/null | |||
@@ -1,84 +0,0 @@ | |||
1 | /* | ||
2 | * P5040 DS Setup | ||
3 | * | ||
4 | * Copyright 2009-2010 Freescale Semiconductor Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/pci.h> | ||
14 | |||
15 | #include <asm/machdep.h> | ||
16 | #include <asm/udbg.h> | ||
17 | #include <asm/mpic.h> | ||
18 | |||
19 | #include <linux/of_fdt.h> | ||
20 | |||
21 | #include <sysdev/fsl_soc.h> | ||
22 | #include <sysdev/fsl_pci.h> | ||
23 | #include <asm/ehv_pic.h> | ||
24 | |||
25 | #include "corenet_ds.h" | ||
26 | |||
27 | /* | ||
28 | * Called very early, device-tree isn't unflattened | ||
29 | */ | ||
30 | static int __init p5040_ds_probe(void) | ||
31 | { | ||
32 | unsigned long root = of_get_flat_dt_root(); | ||
33 | #ifdef CONFIG_SMP | ||
34 | extern struct smp_ops_t smp_85xx_ops; | ||
35 | #endif | ||
36 | |||
37 | if (of_flat_dt_is_compatible(root, "fsl,P5040DS")) | ||
38 | return 1; | ||
39 | |||
40 | /* Check if we're running under the Freescale hypervisor */ | ||
41 | if (of_flat_dt_is_compatible(root, "fsl,P5040DS-hv")) { | ||
42 | ppc_md.init_IRQ = ehv_pic_init; | ||
43 | ppc_md.get_irq = ehv_pic_get_irq; | ||
44 | ppc_md.restart = fsl_hv_restart; | ||
45 | ppc_md.power_off = fsl_hv_halt; | ||
46 | ppc_md.halt = fsl_hv_halt; | ||
47 | #ifdef CONFIG_SMP | ||
48 | /* | ||
49 | * Disable the timebase sync operations because we can't write | ||
50 | * to the timebase registers under the hypervisor. | ||
51 | */ | ||
52 | smp_85xx_ops.give_timebase = NULL; | ||
53 | smp_85xx_ops.take_timebase = NULL; | ||
54 | #endif | ||
55 | return 1; | ||
56 | } | ||
57 | |||
58 | return 0; | ||
59 | } | ||
60 | |||
61 | define_machine(p5040_ds) { | ||
62 | .name = "P5040 DS", | ||
63 | .probe = p5040_ds_probe, | ||
64 | .setup_arch = corenet_ds_setup_arch, | ||
65 | .init_IRQ = corenet_ds_pic_init, | ||
66 | #ifdef CONFIG_PCI | ||
67 | .pcibios_fixup_bus = fsl_pcibios_fixup_bus, | ||
68 | #endif | ||
69 | .get_irq = mpic_get_coreint_irq, | ||
70 | .restart = fsl_rstcr_restart, | ||
71 | .calibrate_decr = generic_calibrate_decr, | ||
72 | .progress = udbg_progress, | ||
73 | #ifdef CONFIG_PPC64 | ||
74 | .power_save = book3e_idle, | ||
75 | #else | ||
76 | .power_save = e500_idle, | ||
77 | #endif | ||
78 | }; | ||
79 | |||
80 | machine_arch_initcall(p5040_ds, corenet_ds_publish_devices); | ||
81 | |||
82 | #ifdef CONFIG_SWIOTLB | ||
83 | machine_arch_initcall(p5040_ds, swiotlb_setup_bus_notifier); | ||
84 | #endif | ||
diff --git a/arch/powerpc/platforms/85xx/ppa8548.c b/arch/powerpc/platforms/85xx/ppa8548.c index 6a7704b92c3b..3daff7c63569 100644 --- a/arch/powerpc/platforms/85xx/ppa8548.c +++ b/arch/powerpc/platforms/85xx/ppa8548.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
20 | #include <linux/reboot.h> | 20 | #include <linux/reboot.h> |
21 | #include <linux/seq_file.h> | 21 | #include <linux/seq_file.h> |
22 | #include <linux/of_fdt.h> | ||
22 | #include <linux/of_platform.h> | 23 | #include <linux/of_platform.h> |
23 | 24 | ||
24 | #include <asm/machdep.h> | 25 | #include <asm/machdep.h> |
diff --git a/arch/powerpc/platforms/85xx/sgy_cts1000.c b/arch/powerpc/platforms/85xx/sgy_cts1000.c index 7179726ba5c5..b9197cea1854 100644 --- a/arch/powerpc/platforms/85xx/sgy_cts1000.c +++ b/arch/powerpc/platforms/85xx/sgy_cts1000.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/of_gpio.h> | 18 | #include <linux/of_gpio.h> |
19 | #include <linux/of_irq.h> | ||
19 | #include <linux/workqueue.h> | 20 | #include <linux/workqueue.h> |
20 | #include <linux/reboot.h> | 21 | #include <linux/reboot.h> |
21 | #include <linux/interrupt.h> | 22 | #include <linux/interrupt.h> |
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c index 281b7f01df63..393f975ab397 100644 --- a/arch/powerpc/platforms/85xx/smp.c +++ b/arch/powerpc/platforms/85xx/smp.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
17 | #include <linux/of.h> | 17 | #include <linux/of.h> |
18 | #include <linux/of_address.h> | ||
18 | #include <linux/kexec.h> | 19 | #include <linux/kexec.h> |
19 | #include <linux/highmem.h> | 20 | #include <linux/highmem.h> |
20 | #include <linux/cpu.h> | 21 | #include <linux/cpu.h> |
diff --git a/arch/powerpc/platforms/85xx/socrates_fpga_pic.c b/arch/powerpc/platforms/85xx/socrates_fpga_pic.c index 3bbbf7489487..55a9682b9529 100644 --- a/arch/powerpc/platforms/85xx/socrates_fpga_pic.c +++ b/arch/powerpc/platforms/85xx/socrates_fpga_pic.c | |||
@@ -9,6 +9,8 @@ | |||
9 | */ | 9 | */ |
10 | 10 | ||
11 | #include <linux/irq.h> | 11 | #include <linux/irq.h> |
12 | #include <linux/of_address.h> | ||
13 | #include <linux/of_irq.h> | ||
12 | #include <linux/of_platform.h> | 14 | #include <linux/of_platform.h> |
13 | #include <linux/io.h> | 15 | #include <linux/io.h> |
14 | 16 | ||
diff --git a/arch/powerpc/platforms/85xx/t4240_qds.c b/arch/powerpc/platforms/85xx/t4240_qds.c deleted file mode 100644 index 91ead6b1b8af..000000000000 --- a/arch/powerpc/platforms/85xx/t4240_qds.c +++ /dev/null | |||
@@ -1,93 +0,0 @@ | |||
1 | /* | ||
2 | * T4240 QDS Setup | ||
3 | * | ||
4 | * Maintained by Kumar Gala (see MAINTAINERS for contact information) | ||
5 | * | ||
6 | * Copyright 2012 Freescale Semiconductor Inc. | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify it | ||
9 | * under the terms of the GNU General Public License as published by the | ||
10 | * Free Software Foundation; either version 2 of the License, or (at your | ||
11 | * option) any later version. | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/pci.h> | ||
16 | #include <linux/kdev_t.h> | ||
17 | #include <linux/delay.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/phy.h> | ||
20 | |||
21 | #include <asm/time.h> | ||
22 | #include <asm/machdep.h> | ||
23 | #include <asm/pci-bridge.h> | ||
24 | #include <mm/mmu_decl.h> | ||
25 | #include <asm/prom.h> | ||
26 | #include <asm/udbg.h> | ||
27 | #include <asm/mpic.h> | ||
28 | |||
29 | #include <linux/of_platform.h> | ||
30 | #include <sysdev/fsl_soc.h> | ||
31 | #include <sysdev/fsl_pci.h> | ||
32 | #include <asm/ehv_pic.h> | ||
33 | |||
34 | #include "corenet_ds.h" | ||
35 | |||
36 | /* | ||
37 | * Called very early, device-tree isn't unflattened | ||
38 | */ | ||
39 | static int __init t4240_qds_probe(void) | ||
40 | { | ||
41 | unsigned long root = of_get_flat_dt_root(); | ||
42 | #ifdef CONFIG_SMP | ||
43 | extern struct smp_ops_t smp_85xx_ops; | ||
44 | #endif | ||
45 | |||
46 | if (of_flat_dt_is_compatible(root, "fsl,T4240QDS")) | ||
47 | return 1; | ||
48 | |||
49 | /* Check if we're running under the Freescale hypervisor */ | ||
50 | if (of_flat_dt_is_compatible(root, "fsl,T4240QDS-hv")) { | ||
51 | ppc_md.init_IRQ = ehv_pic_init; | ||
52 | ppc_md.get_irq = ehv_pic_get_irq; | ||
53 | ppc_md.restart = fsl_hv_restart; | ||
54 | ppc_md.power_off = fsl_hv_halt; | ||
55 | ppc_md.halt = fsl_hv_halt; | ||
56 | #ifdef CONFIG_SMP | ||
57 | /* | ||
58 | * Disable the timebase sync operations because we can't write | ||
59 | * to the timebase registers under the hypervisor. | ||
60 | */ | ||
61 | smp_85xx_ops.give_timebase = NULL; | ||
62 | smp_85xx_ops.take_timebase = NULL; | ||
63 | #endif | ||
64 | return 1; | ||
65 | } | ||
66 | |||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | define_machine(t4240_qds) { | ||
71 | .name = "T4240 QDS", | ||
72 | .probe = t4240_qds_probe, | ||
73 | .setup_arch = corenet_ds_setup_arch, | ||
74 | .init_IRQ = corenet_ds_pic_init, | ||
75 | #ifdef CONFIG_PCI | ||
76 | .pcibios_fixup_bus = fsl_pcibios_fixup_bus, | ||
77 | #endif | ||
78 | .get_irq = mpic_get_coreint_irq, | ||
79 | .restart = fsl_rstcr_restart, | ||
80 | .calibrate_decr = generic_calibrate_decr, | ||
81 | .progress = udbg_progress, | ||
82 | #ifdef CONFIG_PPC64 | ||
83 | .power_save = book3e_idle, | ||
84 | #else | ||
85 | .power_save = e500_idle, | ||
86 | #endif | ||
87 | }; | ||
88 | |||
89 | machine_arch_initcall(t4240_qds, corenet_ds_publish_devices); | ||
90 | |||
91 | #ifdef CONFIG_SWIOTLB | ||
92 | machine_arch_initcall(t4240_qds, swiotlb_setup_bus_notifier); | ||
93 | #endif | ||
diff --git a/arch/powerpc/platforms/86xx/pic.c b/arch/powerpc/platforms/86xx/pic.c index 9982f57c98b9..d5b98c0f958a 100644 --- a/arch/powerpc/platforms/86xx/pic.c +++ b/arch/powerpc/platforms/86xx/pic.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/stddef.h> | 10 | #include <linux/stddef.h> |
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | #include <linux/interrupt.h> | 12 | #include <linux/interrupt.h> |
13 | #include <linux/of_irq.h> | ||
13 | #include <linux/of_platform.h> | 14 | #include <linux/of_platform.h> |
14 | 15 | ||
15 | #include <asm/mpic.h> | 16 | #include <asm/mpic.h> |
diff --git a/arch/powerpc/platforms/8xx/ep88xc.c b/arch/powerpc/platforms/8xx/ep88xc.c index 7d9ac6040d63..e62166681d08 100644 --- a/arch/powerpc/platforms/8xx/ep88xc.c +++ b/arch/powerpc/platforms/8xx/ep88xc.c | |||
@@ -10,6 +10,8 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/of_address.h> | ||
14 | #include <linux/of_fdt.h> | ||
13 | #include <linux/of_platform.h> | 15 | #include <linux/of_platform.h> |
14 | 16 | ||
15 | #include <asm/machdep.h> | 17 | #include <asm/machdep.h> |
diff --git a/arch/powerpc/platforms/8xx/mpc86xads_setup.c b/arch/powerpc/platforms/8xx/mpc86xads_setup.c index 866feff83c91..63084640c5c5 100644 --- a/arch/powerpc/platforms/8xx/mpc86xads_setup.c +++ b/arch/powerpc/platforms/8xx/mpc86xads_setup.c | |||
@@ -15,6 +15,8 @@ | |||
15 | */ | 15 | */ |
16 | 16 | ||
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/of_address.h> | ||
19 | #include <linux/of_fdt.h> | ||
18 | #include <linux/of_platform.h> | 20 | #include <linux/of_platform.h> |
19 | 21 | ||
20 | #include <asm/io.h> | 22 | #include <asm/io.h> |
diff --git a/arch/powerpc/platforms/8xx/mpc885ads_setup.c b/arch/powerpc/platforms/8xx/mpc885ads_setup.c index 5d98398c2f5e..c1262581b63c 100644 --- a/arch/powerpc/platforms/8xx/mpc885ads_setup.c +++ b/arch/powerpc/platforms/8xx/mpc885ads_setup.c | |||
@@ -25,6 +25,8 @@ | |||
25 | #include <linux/fs_uart_pd.h> | 25 | #include <linux/fs_uart_pd.h> |
26 | #include <linux/fsl_devices.h> | 26 | #include <linux/fsl_devices.h> |
27 | #include <linux/mii.h> | 27 | #include <linux/mii.h> |
28 | #include <linux/of_address.h> | ||
29 | #include <linux/of_fdt.h> | ||
28 | #include <linux/of_platform.h> | 30 | #include <linux/of_platform.h> |
29 | 31 | ||
30 | #include <asm/delay.h> | 32 | #include <asm/delay.h> |
diff --git a/arch/powerpc/platforms/8xx/tqm8xx_setup.c b/arch/powerpc/platforms/8xx/tqm8xx_setup.c index 8d21ab70e06c..251aba8759e4 100644 --- a/arch/powerpc/platforms/8xx/tqm8xx_setup.c +++ b/arch/powerpc/platforms/8xx/tqm8xx_setup.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/fs_uart_pd.h> | 28 | #include <linux/fs_uart_pd.h> |
29 | #include <linux/fsl_devices.h> | 29 | #include <linux/fsl_devices.h> |
30 | #include <linux/mii.h> | 30 | #include <linux/mii.h> |
31 | #include <linux/of_fdt.h> | ||
31 | #include <linux/of_platform.h> | 32 | #include <linux/of_platform.h> |
32 | 33 | ||
33 | #include <asm/delay.h> | 34 | #include <asm/delay.h> |
@@ -48,7 +49,7 @@ struct cpm_pin { | |||
48 | int port, pin, flags; | 49 | int port, pin, flags; |
49 | }; | 50 | }; |
50 | 51 | ||
51 | static struct __initdata cpm_pin tqm8xx_pins[] = { | 52 | static struct cpm_pin tqm8xx_pins[] __initdata = { |
52 | /* SMC1 */ | 53 | /* SMC1 */ |
53 | {CPM_PORTB, 24, CPM_PIN_INPUT}, /* RX */ | 54 | {CPM_PORTB, 24, CPM_PIN_INPUT}, /* RX */ |
54 | {CPM_PORTB, 25, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, /* TX */ | 55 | {CPM_PORTB, 25, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, /* TX */ |
@@ -63,7 +64,7 @@ static struct __initdata cpm_pin tqm8xx_pins[] = { | |||
63 | {CPM_PORTC, 11, CPM_PIN_INPUT | CPM_PIN_SECONDARY | CPM_PIN_GPIO}, | 64 | {CPM_PORTC, 11, CPM_PIN_INPUT | CPM_PIN_SECONDARY | CPM_PIN_GPIO}, |
64 | }; | 65 | }; |
65 | 66 | ||
66 | static struct __initdata cpm_pin tqm8xx_fec_pins[] = { | 67 | static struct cpm_pin tqm8xx_fec_pins[] __initdata = { |
67 | /* MII */ | 68 | /* MII */ |
68 | {CPM_PORTD, 3, CPM_PIN_OUTPUT}, | 69 | {CPM_PORTD, 3, CPM_PIN_OUTPUT}, |
69 | {CPM_PORTD, 4, CPM_PIN_OUTPUT}, | 70 | {CPM_PORTD, 4, CPM_PIN_OUTPUT}, |
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype index 6704e2e20e6b..c2a566fb8bb8 100644 --- a/arch/powerpc/platforms/Kconfig.cputype +++ b/arch/powerpc/platforms/Kconfig.cputype | |||
@@ -93,22 +93,23 @@ choice | |||
93 | 93 | ||
94 | config GENERIC_CPU | 94 | config GENERIC_CPU |
95 | bool "Generic" | 95 | bool "Generic" |
96 | depends on !CPU_LITTLE_ENDIAN | ||
96 | 97 | ||
97 | config CELL_CPU | 98 | config CELL_CPU |
98 | bool "Cell Broadband Engine" | 99 | bool "Cell Broadband Engine" |
99 | depends on PPC_BOOK3S_64 | 100 | depends on PPC_BOOK3S_64 && !CPU_LITTLE_ENDIAN |
100 | 101 | ||
101 | config POWER4_CPU | 102 | config POWER4_CPU |
102 | bool "POWER4" | 103 | bool "POWER4" |
103 | depends on PPC_BOOK3S_64 | 104 | depends on PPC_BOOK3S_64 && !CPU_LITTLE_ENDIAN |
104 | 105 | ||
105 | config POWER5_CPU | 106 | config POWER5_CPU |
106 | bool "POWER5" | 107 | bool "POWER5" |
107 | depends on PPC_BOOK3S_64 | 108 | depends on PPC_BOOK3S_64 && !CPU_LITTLE_ENDIAN |
108 | 109 | ||
109 | config POWER6_CPU | 110 | config POWER6_CPU |
110 | bool "POWER6" | 111 | bool "POWER6" |
111 | depends on PPC_BOOK3S_64 | 112 | depends on PPC_BOOK3S_64 && !CPU_LITTLE_ENDIAN |
112 | 113 | ||
113 | config POWER7_CPU | 114 | config POWER7_CPU |
114 | bool "POWER7" | 115 | bool "POWER7" |
diff --git a/arch/powerpc/platforms/cell/celleb_scc_pciex.c b/arch/powerpc/platforms/cell/celleb_scc_pciex.c index 14be2bd358b8..4278acfa2ede 100644 --- a/arch/powerpc/platforms/cell/celleb_scc_pciex.c +++ b/arch/powerpc/platforms/cell/celleb_scc_pciex.c | |||
@@ -486,7 +486,6 @@ static __init int celleb_setup_pciex(struct device_node *node, | |||
486 | struct pci_controller *phb) | 486 | struct pci_controller *phb) |
487 | { | 487 | { |
488 | struct resource r; | 488 | struct resource r; |
489 | struct of_irq oirq; | ||
490 | int virq; | 489 | int virq; |
491 | 490 | ||
492 | /* SMMIO registers; used inside this file */ | 491 | /* SMMIO registers; used inside this file */ |
@@ -507,12 +506,11 @@ static __init int celleb_setup_pciex(struct device_node *node, | |||
507 | phb->ops = &scc_pciex_pci_ops; | 506 | phb->ops = &scc_pciex_pci_ops; |
508 | 507 | ||
509 | /* internal interrupt handler */ | 508 | /* internal interrupt handler */ |
510 | if (of_irq_map_one(node, 1, &oirq)) { | 509 | virq = irq_of_parse_and_map(node, 1); |
510 | if (!virq) { | ||
511 | pr_err("PCIEXC:Failed to map irq\n"); | 511 | pr_err("PCIEXC:Failed to map irq\n"); |
512 | goto error; | 512 | goto error; |
513 | } | 513 | } |
514 | virq = irq_create_of_mapping(oirq.controller, oirq.specifier, | ||
515 | oirq.size); | ||
516 | if (request_irq(virq, pciex_handle_internal_irq, | 514 | if (request_irq(virq, pciex_handle_internal_irq, |
517 | 0, "pciex", (void *)phb)) { | 515 | 0, "pciex", (void *)phb)) { |
518 | pr_err("PCIEXC:Failed to request irq\n"); | 516 | pr_err("PCIEXC:Failed to request irq\n"); |
diff --git a/arch/powerpc/platforms/cell/celleb_scc_sio.c b/arch/powerpc/platforms/cell/celleb_scc_sio.c index 9c339ec646f5..c8eb57193826 100644 --- a/arch/powerpc/platforms/cell/celleb_scc_sio.c +++ b/arch/powerpc/platforms/cell/celleb_scc_sio.c | |||
@@ -45,7 +45,7 @@ static int __init txx9_serial_init(void) | |||
45 | struct device_node *node; | 45 | struct device_node *node; |
46 | int i; | 46 | int i; |
47 | struct uart_port req; | 47 | struct uart_port req; |
48 | struct of_irq irq; | 48 | struct of_phandle_args irq; |
49 | struct resource res; | 49 | struct resource res; |
50 | 50 | ||
51 | for_each_compatible_node(node, "serial", "toshiba,sio-scc") { | 51 | for_each_compatible_node(node, "serial", "toshiba,sio-scc") { |
@@ -53,7 +53,7 @@ static int __init txx9_serial_init(void) | |||
53 | if (!(txx9_serial_bitmap & (1<<i))) | 53 | if (!(txx9_serial_bitmap & (1<<i))) |
54 | continue; | 54 | continue; |
55 | 55 | ||
56 | if (of_irq_map_one(node, i, &irq)) | 56 | if (of_irq_parse_one(node, i, &irq)) |
57 | continue; | 57 | continue; |
58 | if (of_address_to_resource(node, | 58 | if (of_address_to_resource(node, |
59 | txx9_scc_tab[i].index, &res)) | 59 | txx9_scc_tab[i].index, &res)) |
@@ -66,8 +66,7 @@ static int __init txx9_serial_init(void) | |||
66 | #ifdef CONFIG_SERIAL_TXX9_CONSOLE | 66 | #ifdef CONFIG_SERIAL_TXX9_CONSOLE |
67 | req.membase = ioremap(req.mapbase, 0x24); | 67 | req.membase = ioremap(req.mapbase, 0x24); |
68 | #endif | 68 | #endif |
69 | req.irq = irq_create_of_mapping(irq.controller, | 69 | req.irq = irq_create_of_mapping(&irq); |
70 | irq.specifier, irq.size); | ||
71 | req.flags |= UPF_IOREMAP | UPF_BUGGY_UART | 70 | req.flags |= UPF_IOREMAP | UPF_BUGGY_UART |
72 | /*HAVE_CTS_LINE*/; | 71 | /*HAVE_CTS_LINE*/; |
73 | req.uartclk = 83300000; | 72 | req.uartclk = 83300000; |
diff --git a/arch/powerpc/platforms/cell/spider-pic.c b/arch/powerpc/platforms/cell/spider-pic.c index 8e299447127e..1f72f4ab6353 100644 --- a/arch/powerpc/platforms/cell/spider-pic.c +++ b/arch/powerpc/platforms/cell/spider-pic.c | |||
@@ -235,12 +235,9 @@ static unsigned int __init spider_find_cascade_and_node(struct spider_pic *pic) | |||
235 | /* First, we check whether we have a real "interrupts" in the device | 235 | /* First, we check whether we have a real "interrupts" in the device |
236 | * tree in case the device-tree is ever fixed | 236 | * tree in case the device-tree is ever fixed |
237 | */ | 237 | */ |
238 | struct of_irq oirq; | 238 | virq = irq_of_parse_and_map(pic->host->of_node, 0); |
239 | if (of_irq_map_one(pic->host->of_node, 0, &oirq) == 0) { | 239 | if (virq) |
240 | virq = irq_create_of_mapping(oirq.controller, oirq.specifier, | ||
241 | oirq.size); | ||
242 | return virq; | 240 | return virq; |
243 | } | ||
244 | 241 | ||
245 | /* Now do the horrible hacks */ | 242 | /* Now do the horrible hacks */ |
246 | tmp = of_get_property(pic->host->of_node, "#interrupt-cells", NULL); | 243 | tmp = of_get_property(pic->host->of_node, "#interrupt-cells", NULL); |
diff --git a/arch/powerpc/platforms/cell/spu_manage.c b/arch/powerpc/platforms/cell/spu_manage.c index 2bb6977c0a5a..c3327f3d8cf7 100644 --- a/arch/powerpc/platforms/cell/spu_manage.c +++ b/arch/powerpc/platforms/cell/spu_manage.c | |||
@@ -177,21 +177,20 @@ out: | |||
177 | 177 | ||
178 | static int __init spu_map_interrupts(struct spu *spu, struct device_node *np) | 178 | static int __init spu_map_interrupts(struct spu *spu, struct device_node *np) |
179 | { | 179 | { |
180 | struct of_irq oirq; | 180 | struct of_phandle_args oirq; |
181 | int ret; | 181 | int ret; |
182 | int i; | 182 | int i; |
183 | 183 | ||
184 | for (i=0; i < 3; i++) { | 184 | for (i=0; i < 3; i++) { |
185 | ret = of_irq_map_one(np, i, &oirq); | 185 | ret = of_irq_parse_one(np, i, &oirq); |
186 | if (ret) { | 186 | if (ret) { |
187 | pr_debug("spu_new: failed to get irq %d\n", i); | 187 | pr_debug("spu_new: failed to get irq %d\n", i); |
188 | goto err; | 188 | goto err; |
189 | } | 189 | } |
190 | ret = -EINVAL; | 190 | ret = -EINVAL; |
191 | pr_debug(" irq %d no 0x%x on %s\n", i, oirq.specifier[0], | 191 | pr_debug(" irq %d no 0x%x on %s\n", i, oirq.args[0], |
192 | oirq.controller->full_name); | 192 | oirq.np->full_name); |
193 | spu->irqs[i] = irq_create_of_mapping(oirq.controller, | 193 | spu->irqs[i] = irq_create_of_mapping(&oirq); |
194 | oirq.specifier, oirq.size); | ||
195 | if (spu->irqs[i] == NO_IRQ) { | 194 | if (spu->irqs[i] == NO_IRQ) { |
196 | pr_debug("spu_new: failed to map it !\n"); | 195 | pr_debug("spu_new: failed to map it !\n"); |
197 | goto err; | 196 | goto err; |
@@ -200,7 +199,7 @@ static int __init spu_map_interrupts(struct spu *spu, struct device_node *np) | |||
200 | return 0; | 199 | return 0; |
201 | 200 | ||
202 | err: | 201 | err: |
203 | pr_debug("failed to map irq %x for spu %s\n", *oirq.specifier, | 202 | pr_debug("failed to map irq %x for spu %s\n", *oirq.args, |
204 | spu->name); | 203 | spu->name); |
205 | for (; i >= 0; i--) { | 204 | for (; i >= 0; i--) { |
206 | if (spu->irqs[i] != NO_IRQ) | 205 | if (spu->irqs[i] != NO_IRQ) |
diff --git a/arch/powerpc/platforms/cell/spu_syscalls.c b/arch/powerpc/platforms/cell/spu_syscalls.c index db4e638cf408..3844f1397fc3 100644 --- a/arch/powerpc/platforms/cell/spu_syscalls.c +++ b/arch/powerpc/platforms/cell/spu_syscalls.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
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 | 29 | ||
29 | #include <asm/spu.h> | 30 | #include <asm/spu.h> |
30 | 31 | ||
@@ -126,7 +127,7 @@ int elf_coredump_extra_notes_size(void) | |||
126 | return ret; | 127 | return ret; |
127 | } | 128 | } |
128 | 129 | ||
129 | int elf_coredump_extra_notes_write(struct file *file, loff_t *foffset) | 130 | int elf_coredump_extra_notes_write(struct coredump_params *cprm) |
130 | { | 131 | { |
131 | struct spufs_calls *calls; | 132 | struct spufs_calls *calls; |
132 | int ret; | 133 | int ret; |
@@ -135,7 +136,7 @@ int elf_coredump_extra_notes_write(struct file *file, loff_t *foffset) | |||
135 | if (!calls) | 136 | if (!calls) |
136 | return 0; | 137 | return 0; |
137 | 138 | ||
138 | ret = calls->coredump_extra_notes_write(file, foffset); | 139 | ret = calls->coredump_extra_notes_write(cprm); |
139 | 140 | ||
140 | spufs_calls_put(calls); | 141 | spufs_calls_put(calls); |
141 | 142 | ||
diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c index c9500ea7be2f..be6212ddbf06 100644 --- a/arch/powerpc/platforms/cell/spufs/coredump.c +++ b/arch/powerpc/platforms/cell/spufs/coredump.c | |||
@@ -27,6 +27,8 @@ | |||
27 | #include <linux/gfp.h> | 27 | #include <linux/gfp.h> |
28 | #include <linux/list.h> | 28 | #include <linux/list.h> |
29 | #include <linux/syscalls.h> | 29 | #include <linux/syscalls.h> |
30 | #include <linux/coredump.h> | ||
31 | #include <linux/binfmts.h> | ||
30 | 32 | ||
31 | #include <asm/uaccess.h> | 33 | #include <asm/uaccess.h> |
32 | 34 | ||
@@ -48,44 +50,6 @@ static ssize_t do_coredump_read(int num, struct spu_context *ctx, void *buffer, | |||
48 | return ++ret; /* count trailing NULL */ | 50 | return ++ret; /* count trailing NULL */ |
49 | } | 51 | } |
50 | 52 | ||
51 | /* | ||
52 | * These are the only things you should do on a core-file: use only these | ||
53 | * functions to write out all the necessary info. | ||
54 | */ | ||
55 | static int spufs_dump_write(struct file *file, const void *addr, int nr, loff_t *foffset) | ||
56 | { | ||
57 | unsigned long limit = rlimit(RLIMIT_CORE); | ||
58 | ssize_t written; | ||
59 | |||
60 | if (*foffset + nr > limit) | ||
61 | return -EIO; | ||
62 | |||
63 | written = file->f_op->write(file, addr, nr, &file->f_pos); | ||
64 | *foffset += written; | ||
65 | |||
66 | if (written != nr) | ||
67 | return -EIO; | ||
68 | |||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | static int spufs_dump_align(struct file *file, char *buf, loff_t new_off, | ||
73 | loff_t *foffset) | ||
74 | { | ||
75 | int rc, size; | ||
76 | |||
77 | size = min((loff_t)PAGE_SIZE, new_off - *foffset); | ||
78 | memset(buf, 0, size); | ||
79 | |||
80 | rc = 0; | ||
81 | while (rc == 0 && new_off > *foffset) { | ||
82 | size = min((loff_t)PAGE_SIZE, new_off - *foffset); | ||
83 | rc = spufs_dump_write(file, buf, size, foffset); | ||
84 | } | ||
85 | |||
86 | return rc; | ||
87 | } | ||
88 | |||
89 | static int spufs_ctx_note_size(struct spu_context *ctx, int dfd) | 53 | static int spufs_ctx_note_size(struct spu_context *ctx, int dfd) |
90 | { | 54 | { |
91 | int i, sz, total = 0; | 55 | int i, sz, total = 0; |
@@ -165,10 +129,10 @@ int spufs_coredump_extra_notes_size(void) | |||
165 | } | 129 | } |
166 | 130 | ||
167 | static int spufs_arch_write_note(struct spu_context *ctx, int i, | 131 | static int spufs_arch_write_note(struct spu_context *ctx, int i, |
168 | struct file *file, int dfd, loff_t *foffset) | 132 | struct coredump_params *cprm, int dfd) |
169 | { | 133 | { |
170 | loff_t pos = 0; | 134 | loff_t pos = 0; |
171 | int sz, rc, nread, total = 0; | 135 | int sz, rc, total = 0; |
172 | const int bufsz = PAGE_SIZE; | 136 | const int bufsz = PAGE_SIZE; |
173 | char *name; | 137 | char *name; |
174 | char fullname[80], *buf; | 138 | char fullname[80], *buf; |
@@ -186,42 +150,39 @@ static int spufs_arch_write_note(struct spu_context *ctx, int i, | |||
186 | en.n_descsz = sz; | 150 | en.n_descsz = sz; |
187 | en.n_type = NT_SPU; | 151 | en.n_type = NT_SPU; |
188 | 152 | ||
189 | rc = spufs_dump_write(file, &en, sizeof(en), foffset); | 153 | if (!dump_emit(cprm, &en, sizeof(en))) |
190 | if (rc) | 154 | goto Eio; |
191 | goto out; | ||
192 | 155 | ||
193 | rc = spufs_dump_write(file, fullname, en.n_namesz, foffset); | 156 | if (!dump_emit(cprm, fullname, en.n_namesz)) |
194 | if (rc) | 157 | goto Eio; |
195 | goto out; | ||
196 | 158 | ||
197 | rc = spufs_dump_align(file, buf, roundup(*foffset, 4), foffset); | 159 | if (!dump_align(cprm, 4)) |
198 | if (rc) | 160 | goto Eio; |
199 | goto out; | ||
200 | 161 | ||
201 | do { | 162 | do { |
202 | nread = do_coredump_read(i, ctx, buf, bufsz, &pos); | 163 | rc = do_coredump_read(i, ctx, buf, bufsz, &pos); |
203 | if (nread > 0) { | 164 | if (rc > 0) { |
204 | rc = spufs_dump_write(file, buf, nread, foffset); | 165 | if (!dump_emit(cprm, buf, rc)) |
205 | if (rc) | 166 | goto Eio; |
206 | goto out; | 167 | total += rc; |
207 | total += nread; | ||
208 | } | 168 | } |
209 | } while (nread == bufsz && total < sz); | 169 | } while (rc == bufsz && total < sz); |
210 | 170 | ||
211 | if (nread < 0) { | 171 | if (rc < 0) |
212 | rc = nread; | ||
213 | goto out; | 172 | goto out; |
214 | } | ||
215 | |||
216 | rc = spufs_dump_align(file, buf, roundup(*foffset - total + sz, 4), | ||
217 | foffset); | ||
218 | 173 | ||
174 | if (!dump_skip(cprm, | ||
175 | roundup(cprm->written - total + sz, 4) - cprm->written)) | ||
176 | goto Eio; | ||
219 | out: | 177 | out: |
220 | free_page((unsigned long)buf); | 178 | free_page((unsigned long)buf); |
221 | return rc; | 179 | return rc; |
180 | Eio: | ||
181 | free_page((unsigned long)buf); | ||
182 | return -EIO; | ||
222 | } | 183 | } |
223 | 184 | ||
224 | int spufs_coredump_extra_notes_write(struct file *file, loff_t *foffset) | 185 | int spufs_coredump_extra_notes_write(struct coredump_params *cprm) |
225 | { | 186 | { |
226 | struct spu_context *ctx; | 187 | struct spu_context *ctx; |
227 | int fd, j, rc; | 188 | int fd, j, rc; |
@@ -233,7 +194,7 @@ int spufs_coredump_extra_notes_write(struct file *file, loff_t *foffset) | |||
233 | return rc; | 194 | return rc; |
234 | 195 | ||
235 | for (j = 0; spufs_coredump_read[j].name != NULL; j++) { | 196 | for (j = 0; spufs_coredump_read[j].name != NULL; j++) { |
236 | rc = spufs_arch_write_note(ctx, j, file, fd, foffset); | 197 | rc = spufs_arch_write_note(ctx, j, cprm, fd); |
237 | if (rc) { | 198 | if (rc) { |
238 | spu_release_saved(ctx); | 199 | spu_release_saved(ctx); |
239 | return rc; | 200 | return rc; |
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h index 67852ade4c01..0ba3c9598358 100644 --- a/arch/powerpc/platforms/cell/spufs/spufs.h +++ b/arch/powerpc/platforms/cell/spufs/spufs.h | |||
@@ -247,12 +247,13 @@ extern const struct spufs_tree_descr spufs_dir_debug_contents[]; | |||
247 | 247 | ||
248 | /* system call implementation */ | 248 | /* system call implementation */ |
249 | extern struct spufs_calls spufs_calls; | 249 | extern struct spufs_calls spufs_calls; |
250 | struct coredump_params; | ||
250 | long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *status); | 251 | long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *status); |
251 | long spufs_create(struct path *nd, struct dentry *dentry, unsigned int flags, | 252 | long spufs_create(struct path *nd, struct dentry *dentry, unsigned int flags, |
252 | umode_t mode, struct file *filp); | 253 | umode_t mode, struct file *filp); |
253 | /* ELF coredump callbacks for writing SPU ELF notes */ | 254 | /* ELF coredump callbacks for writing SPU ELF notes */ |
254 | extern int spufs_coredump_extra_notes_size(void); | 255 | extern int spufs_coredump_extra_notes_size(void); |
255 | extern int spufs_coredump_extra_notes_write(struct file *file, loff_t *foffset); | 256 | extern int spufs_coredump_extra_notes_write(struct coredump_params *cprm); |
256 | 257 | ||
257 | extern const struct file_operations spufs_context_fops; | 258 | extern const struct file_operations spufs_context_fops; |
258 | 259 | ||
diff --git a/arch/powerpc/platforms/chrp/nvram.c b/arch/powerpc/platforms/chrp/nvram.c index d3ceff04ffc7..9ef8cc3378d0 100644 --- a/arch/powerpc/platforms/chrp/nvram.c +++ b/arch/powerpc/platforms/chrp/nvram.c | |||
@@ -66,7 +66,7 @@ static void chrp_nvram_write(int addr, unsigned char val) | |||
66 | void __init chrp_nvram_init(void) | 66 | void __init chrp_nvram_init(void) |
67 | { | 67 | { |
68 | struct device_node *nvram; | 68 | struct device_node *nvram; |
69 | const unsigned int *nbytes_p; | 69 | const __be32 *nbytes_p; |
70 | unsigned int proplen; | 70 | unsigned int proplen; |
71 | 71 | ||
72 | nvram = of_find_node_by_type(NULL, "nvram"); | 72 | nvram = of_find_node_by_type(NULL, "nvram"); |
@@ -79,7 +79,7 @@ void __init chrp_nvram_init(void) | |||
79 | return; | 79 | return; |
80 | } | 80 | } |
81 | 81 | ||
82 | nvram_size = *nbytes_p; | 82 | nvram_size = be32_to_cpup(nbytes_p); |
83 | 83 | ||
84 | printk(KERN_INFO "CHRP nvram contains %u bytes\n", nvram_size); | 84 | printk(KERN_INFO "CHRP nvram contains %u bytes\n", nvram_size); |
85 | of_node_put(nvram); | 85 | of_node_put(nvram); |
diff --git a/arch/powerpc/platforms/embedded6xx/flipper-pic.c b/arch/powerpc/platforms/embedded6xx/flipper-pic.c index 53d6eee01963..4cde8e7da4b8 100644 --- a/arch/powerpc/platforms/embedded6xx/flipper-pic.c +++ b/arch/powerpc/platforms/embedded6xx/flipper-pic.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <linux/irq.h> | 19 | #include <linux/irq.h> |
20 | #include <linux/of.h> | 20 | #include <linux/of.h> |
21 | #include <linux/of_address.h> | ||
21 | #include <asm/io.h> | 22 | #include <asm/io.h> |
22 | 23 | ||
23 | #include "flipper-pic.h" | 24 | #include "flipper-pic.h" |
diff --git a/arch/powerpc/platforms/embedded6xx/hlwd-pic.c b/arch/powerpc/platforms/embedded6xx/hlwd-pic.c index 3006b5117ec6..6c03034dbbd3 100644 --- a/arch/powerpc/platforms/embedded6xx/hlwd-pic.c +++ b/arch/powerpc/platforms/embedded6xx/hlwd-pic.c | |||
@@ -18,6 +18,8 @@ | |||
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <linux/irq.h> | 19 | #include <linux/irq.h> |
20 | #include <linux/of.h> | 20 | #include <linux/of.h> |
21 | #include <linux/of_address.h> | ||
22 | #include <linux/of_irq.h> | ||
21 | #include <asm/io.h> | 23 | #include <asm/io.h> |
22 | 24 | ||
23 | #include "hlwd-pic.h" | 25 | #include "hlwd-pic.h" |
@@ -181,6 +183,7 @@ struct irq_domain *hlwd_pic_init(struct device_node *np) | |||
181 | &hlwd_irq_domain_ops, io_base); | 183 | &hlwd_irq_domain_ops, io_base); |
182 | if (!irq_domain) { | 184 | if (!irq_domain) { |
183 | pr_err("failed to allocate irq_domain\n"); | 185 | pr_err("failed to allocate irq_domain\n"); |
186 | iounmap(io_base); | ||
184 | return NULL; | 187 | return NULL; |
185 | } | 188 | } |
186 | 189 | ||
diff --git a/arch/powerpc/platforms/fsl_uli1575.c b/arch/powerpc/platforms/fsl_uli1575.c index 92ac9b52b32d..b97f6f3d3c5b 100644 --- a/arch/powerpc/platforms/fsl_uli1575.c +++ b/arch/powerpc/platforms/fsl_uli1575.c | |||
@@ -321,8 +321,7 @@ static void hpcd_final_uli5288(struct pci_dev *dev) | |||
321 | { | 321 | { |
322 | struct pci_controller *hose = pci_bus_to_host(dev->bus); | 322 | struct pci_controller *hose = pci_bus_to_host(dev->bus); |
323 | struct device_node *hosenode = hose ? hose->dn : NULL; | 323 | struct device_node *hosenode = hose ? hose->dn : NULL; |
324 | struct of_irq oirq; | 324 | struct of_phandle_args oirq; |
325 | int virq, pin = 2; | ||
326 | u32 laddr[3]; | 325 | u32 laddr[3]; |
327 | 326 | ||
328 | if (!machine_is(mpc86xx_hpcd)) | 327 | if (!machine_is(mpc86xx_hpcd)) |
@@ -331,12 +330,13 @@ static void hpcd_final_uli5288(struct pci_dev *dev) | |||
331 | if (!hosenode) | 330 | if (!hosenode) |
332 | return; | 331 | return; |
333 | 332 | ||
333 | oirq.np = hosenode; | ||
334 | oirq.args[0] = 2; | ||
335 | oirq.args_count = 1; | ||
334 | laddr[0] = (hose->first_busno << 16) | (PCI_DEVFN(31, 0) << 8); | 336 | laddr[0] = (hose->first_busno << 16) | (PCI_DEVFN(31, 0) << 8); |
335 | laddr[1] = laddr[2] = 0; | 337 | laddr[1] = laddr[2] = 0; |
336 | of_irq_map_raw(hosenode, &pin, 1, laddr, &oirq); | 338 | of_irq_parse_raw(laddr, &oirq); |
337 | virq = irq_create_of_mapping(oirq.controller, oirq.specifier, | 339 | dev->irq = irq_create_of_mapping(&oirq); |
338 | oirq.size); | ||
339 | dev->irq = virq; | ||
340 | } | 340 | } |
341 | 341 | ||
342 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x1575, hpcd_quirk_uli1575); | 342 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AL, 0x1575, hpcd_quirk_uli1575); |
diff --git a/arch/powerpc/platforms/pasemi/gpio_mdio.c b/arch/powerpc/platforms/pasemi/gpio_mdio.c index 0237ab782fb8..15adee544638 100644 --- a/arch/powerpc/platforms/pasemi/gpio_mdio.c +++ b/arch/powerpc/platforms/pasemi/gpio_mdio.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/ioport.h> | 30 | #include <linux/ioport.h> |
31 | #include <linux/interrupt.h> | 31 | #include <linux/interrupt.h> |
32 | #include <linux/phy.h> | 32 | #include <linux/phy.h> |
33 | #include <linux/of_address.h> | ||
33 | #include <linux/of_mdio.h> | 34 | #include <linux/of_mdio.h> |
34 | #include <linux/of_platform.h> | 35 | #include <linux/of_platform.h> |
35 | 36 | ||
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c index fc536f2971c0..7553b6a77c64 100644 --- a/arch/powerpc/platforms/powermac/low_i2c.c +++ b/arch/powerpc/platforms/powermac/low_i2c.c | |||
@@ -452,7 +452,7 @@ static int kw_i2c_xfer(struct pmac_i2c_bus *bus, u8 addrdir, int subsize, | |||
452 | */ | 452 | */ |
453 | if (use_irq) { | 453 | if (use_irq) { |
454 | /* Clear completion */ | 454 | /* Clear completion */ |
455 | INIT_COMPLETION(host->complete); | 455 | reinit_completion(&host->complete); |
456 | /* Ack stale interrupts */ | 456 | /* Ack stale interrupts */ |
457 | kw_write_reg(reg_isr, kw_read_reg(reg_isr)); | 457 | kw_write_reg(reg_isr, kw_read_reg(reg_isr)); |
458 | /* Arm timeout */ | 458 | /* Arm timeout */ |
@@ -717,7 +717,7 @@ static int pmu_i2c_xfer(struct pmac_i2c_bus *bus, u8 addrdir, int subsize, | |||
717 | return -EINVAL; | 717 | return -EINVAL; |
718 | } | 718 | } |
719 | 719 | ||
720 | INIT_COMPLETION(comp); | 720 | reinit_completion(&comp); |
721 | req->data[0] = PMU_I2C_CMD; | 721 | req->data[0] = PMU_I2C_CMD; |
722 | req->reply[0] = 0xff; | 722 | req->reply[0] = 0xff; |
723 | req->nbytes = sizeof(struct pmu_i2c_hdr) + 1; | 723 | req->nbytes = sizeof(struct pmu_i2c_hdr) + 1; |
@@ -748,7 +748,7 @@ static int pmu_i2c_xfer(struct pmac_i2c_bus *bus, u8 addrdir, int subsize, | |||
748 | 748 | ||
749 | hdr->bus = PMU_I2C_BUS_STATUS; | 749 | hdr->bus = PMU_I2C_BUS_STATUS; |
750 | 750 | ||
751 | INIT_COMPLETION(comp); | 751 | reinit_completion(&comp); |
752 | req->data[0] = PMU_I2C_CMD; | 752 | req->data[0] = PMU_I2C_CMD; |
753 | req->reply[0] = 0xff; | 753 | req->reply[0] = 0xff; |
754 | req->nbytes = 2; | 754 | req->nbytes = 2; |
diff --git a/arch/powerpc/platforms/powermac/pfunc_base.c b/arch/powerpc/platforms/powermac/pfunc_base.c index f5e3cda6660e..e49d07f3d542 100644 --- a/arch/powerpc/platforms/powermac/pfunc_base.c +++ b/arch/powerpc/platforms/powermac/pfunc_base.c | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <linux/kernel.h> | 4 | #include <linux/kernel.h> |
5 | #include <linux/interrupt.h> | 5 | #include <linux/interrupt.h> |
6 | #include <linux/spinlock.h> | 6 | #include <linux/spinlock.h> |
7 | #include <linux/of_irq.h> | ||
7 | 8 | ||
8 | #include <asm/pmac_feature.h> | 9 | #include <asm/pmac_feature.h> |
9 | #include <asm/pmac_pfunc.h> | 10 | #include <asm/pmac_pfunc.h> |
diff --git a/arch/powerpc/platforms/powermac/pic.c b/arch/powerpc/platforms/powermac/pic.c index 31036b56670e..4c24bf60d39d 100644 --- a/arch/powerpc/platforms/powermac/pic.c +++ b/arch/powerpc/platforms/powermac/pic.c | |||
@@ -393,8 +393,8 @@ static void __init pmac_pic_probe_oldstyle(void) | |||
393 | #endif | 393 | #endif |
394 | } | 394 | } |
395 | 395 | ||
396 | int of_irq_map_oldworld(struct device_node *device, int index, | 396 | int of_irq_parse_oldworld(struct device_node *device, int index, |
397 | struct of_irq *out_irq) | 397 | struct of_phandle_args *out_irq) |
398 | { | 398 | { |
399 | const u32 *ints = NULL; | 399 | const u32 *ints = NULL; |
400 | int intlen; | 400 | int intlen; |
@@ -422,9 +422,9 @@ int of_irq_map_oldworld(struct device_node *device, int index, | |||
422 | if (index >= intlen) | 422 | if (index >= intlen) |
423 | return -EINVAL; | 423 | return -EINVAL; |
424 | 424 | ||
425 | out_irq->controller = NULL; | 425 | out_irq->np = NULL; |
426 | out_irq->specifier[0] = ints[index]; | 426 | out_irq->args[0] = ints[index]; |
427 | out_irq->size = 1; | 427 | out_irq->args_count = 1; |
428 | 428 | ||
429 | return 0; | 429 | return 0; |
430 | } | 430 | } |
diff --git a/arch/powerpc/platforms/powernv/Kconfig b/arch/powerpc/platforms/powernv/Kconfig index 6fae5eb99ea6..9fced3f6d2dc 100644 --- a/arch/powerpc/platforms/powernv/Kconfig +++ b/arch/powerpc/platforms/powernv/Kconfig | |||
@@ -9,6 +9,8 @@ config PPC_POWERNV | |||
9 | select EPAPR_BOOT | 9 | select EPAPR_BOOT |
10 | select PPC_INDIRECT_PIO | 10 | select PPC_INDIRECT_PIO |
11 | select PPC_UDBG_16550 | 11 | select PPC_UDBG_16550 |
12 | select PPC_SCOM | ||
13 | select ARCH_RANDOM | ||
12 | default y | 14 | default y |
13 | 15 | ||
14 | config POWERNV_MSI | 16 | config POWERNV_MSI |
diff --git a/arch/powerpc/platforms/powernv/Makefile b/arch/powerpc/platforms/powernv/Makefile index 300c437d713c..873fa1370dc4 100644 --- a/arch/powerpc/platforms/powernv/Makefile +++ b/arch/powerpc/platforms/powernv/Makefile | |||
@@ -1,6 +1,8 @@ | |||
1 | obj-y += setup.o opal-takeover.o opal-wrappers.o opal.o | 1 | obj-y += setup.o opal-takeover.o opal-wrappers.o opal.o |
2 | obj-y += opal-rtc.o opal-nvram.o opal-lpc.o | 2 | obj-y += opal-rtc.o opal-nvram.o opal-lpc.o opal-flash.o |
3 | obj-y += rng.o | ||
3 | 4 | ||
4 | obj-$(CONFIG_SMP) += smp.o | 5 | obj-$(CONFIG_SMP) += smp.o |
5 | obj-$(CONFIG_PCI) += pci.o pci-p5ioc2.o pci-ioda.o | 6 | obj-$(CONFIG_PCI) += pci.o pci-p5ioc2.o pci-ioda.o |
6 | obj-$(CONFIG_EEH) += eeh-ioda.o eeh-powernv.o | 7 | obj-$(CONFIG_EEH) += eeh-ioda.o eeh-powernv.o |
8 | obj-$(CONFIG_PPC_SCOM) += opal-xscom.o | ||
diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c b/arch/powerpc/platforms/powernv/eeh-ioda.c index cf42e74514fa..02245cee7818 100644 --- a/arch/powerpc/platforms/powernv/eeh-ioda.c +++ b/arch/powerpc/platforms/powernv/eeh-ioda.c | |||
@@ -59,26 +59,60 @@ static struct notifier_block ioda_eeh_nb = { | |||
59 | }; | 59 | }; |
60 | 60 | ||
61 | #ifdef CONFIG_DEBUG_FS | 61 | #ifdef CONFIG_DEBUG_FS |
62 | static int ioda_eeh_dbgfs_set(void *data, u64 val) | 62 | static int ioda_eeh_dbgfs_set(void *data, int offset, u64 val) |
63 | { | 63 | { |
64 | struct pci_controller *hose = data; | 64 | struct pci_controller *hose = data; |
65 | struct pnv_phb *phb = hose->private_data; | 65 | struct pnv_phb *phb = hose->private_data; |
66 | 66 | ||
67 | out_be64(phb->regs + 0xD10, val); | 67 | out_be64(phb->regs + offset, val); |
68 | return 0; | 68 | return 0; |
69 | } | 69 | } |
70 | 70 | ||
71 | static int ioda_eeh_dbgfs_get(void *data, u64 *val) | 71 | static int ioda_eeh_dbgfs_get(void *data, int offset, u64 *val) |
72 | { | 72 | { |
73 | struct pci_controller *hose = data; | 73 | struct pci_controller *hose = data; |
74 | struct pnv_phb *phb = hose->private_data; | 74 | struct pnv_phb *phb = hose->private_data; |
75 | 75 | ||
76 | *val = in_be64(phb->regs + 0xD10); | 76 | *val = in_be64(phb->regs + offset); |
77 | return 0; | 77 | return 0; |
78 | } | 78 | } |
79 | 79 | ||
80 | DEFINE_SIMPLE_ATTRIBUTE(ioda_eeh_dbgfs_ops, ioda_eeh_dbgfs_get, | 80 | static int ioda_eeh_outb_dbgfs_set(void *data, u64 val) |
81 | ioda_eeh_dbgfs_set, "0x%llx\n"); | 81 | { |
82 | return ioda_eeh_dbgfs_set(data, 0xD10, val); | ||
83 | } | ||
84 | |||
85 | static int ioda_eeh_outb_dbgfs_get(void *data, u64 *val) | ||
86 | { | ||
87 | return ioda_eeh_dbgfs_get(data, 0xD10, val); | ||
88 | } | ||
89 | |||
90 | static int ioda_eeh_inbA_dbgfs_set(void *data, u64 val) | ||
91 | { | ||
92 | return ioda_eeh_dbgfs_set(data, 0xD90, val); | ||
93 | } | ||
94 | |||
95 | static int ioda_eeh_inbA_dbgfs_get(void *data, u64 *val) | ||
96 | { | ||
97 | return ioda_eeh_dbgfs_get(data, 0xD90, val); | ||
98 | } | ||
99 | |||
100 | static int ioda_eeh_inbB_dbgfs_set(void *data, u64 val) | ||
101 | { | ||
102 | return ioda_eeh_dbgfs_set(data, 0xE10, val); | ||
103 | } | ||
104 | |||
105 | static int ioda_eeh_inbB_dbgfs_get(void *data, u64 *val) | ||
106 | { | ||
107 | return ioda_eeh_dbgfs_get(data, 0xE10, val); | ||
108 | } | ||
109 | |||
110 | DEFINE_SIMPLE_ATTRIBUTE(ioda_eeh_outb_dbgfs_ops, ioda_eeh_outb_dbgfs_get, | ||
111 | ioda_eeh_outb_dbgfs_set, "0x%llx\n"); | ||
112 | DEFINE_SIMPLE_ATTRIBUTE(ioda_eeh_inbA_dbgfs_ops, ioda_eeh_inbA_dbgfs_get, | ||
113 | ioda_eeh_inbA_dbgfs_set, "0x%llx\n"); | ||
114 | DEFINE_SIMPLE_ATTRIBUTE(ioda_eeh_inbB_dbgfs_ops, ioda_eeh_inbB_dbgfs_get, | ||
115 | ioda_eeh_inbB_dbgfs_set, "0x%llx\n"); | ||
82 | #endif /* CONFIG_DEBUG_FS */ | 116 | #endif /* CONFIG_DEBUG_FS */ |
83 | 117 | ||
84 | /** | 118 | /** |
@@ -106,27 +140,30 @@ static int ioda_eeh_post_init(struct pci_controller *hose) | |||
106 | ioda_eeh_nb_init = 1; | 140 | ioda_eeh_nb_init = 1; |
107 | } | 141 | } |
108 | 142 | ||
109 | /* FIXME: Enable it for PHB3 later */ | 143 | /* We needn't HUB diag-data on PHB3 */ |
110 | if (phb->type == PNV_PHB_IODA1) { | 144 | if (phb->type == PNV_PHB_IODA1 && !hub_diag) { |
145 | hub_diag = (char *)__get_free_page(GFP_KERNEL | __GFP_ZERO); | ||
111 | if (!hub_diag) { | 146 | if (!hub_diag) { |
112 | hub_diag = (char *)__get_free_page(GFP_KERNEL | | 147 | pr_err("%s: Out of memory !\n", __func__); |
113 | __GFP_ZERO); | 148 | return -ENOMEM; |
114 | if (!hub_diag) { | ||
115 | pr_err("%s: Out of memory !\n", | ||
116 | __func__); | ||
117 | return -ENOMEM; | ||
118 | } | ||
119 | } | 149 | } |
150 | } | ||
120 | 151 | ||
121 | #ifdef CONFIG_DEBUG_FS | 152 | #ifdef CONFIG_DEBUG_FS |
122 | if (phb->dbgfs) | 153 | if (phb->dbgfs) { |
123 | debugfs_create_file("err_injct", 0600, | 154 | debugfs_create_file("err_injct_outbound", 0600, |
124 | phb->dbgfs, hose, | 155 | phb->dbgfs, hose, |
125 | &ioda_eeh_dbgfs_ops); | 156 | &ioda_eeh_outb_dbgfs_ops); |
157 | debugfs_create_file("err_injct_inboundA", 0600, | ||
158 | phb->dbgfs, hose, | ||
159 | &ioda_eeh_inbA_dbgfs_ops); | ||
160 | debugfs_create_file("err_injct_inboundB", 0600, | ||
161 | phb->dbgfs, hose, | ||
162 | &ioda_eeh_inbB_dbgfs_ops); | ||
163 | } | ||
126 | #endif | 164 | #endif |
127 | 165 | ||
128 | phb->eeh_state |= PNV_EEH_STATE_ENABLED; | 166 | phb->eeh_state |= PNV_EEH_STATE_ENABLED; |
129 | } | ||
130 | 167 | ||
131 | return 0; | 168 | return 0; |
132 | } | 169 | } |
@@ -546,8 +583,8 @@ static int ioda_eeh_get_log(struct eeh_pe *pe, int severity, | |||
546 | phb->diag.blob, PNV_PCI_DIAG_BUF_SIZE); | 583 | phb->diag.blob, PNV_PCI_DIAG_BUF_SIZE); |
547 | if (ret) { | 584 | if (ret) { |
548 | spin_unlock_irqrestore(&phb->lock, flags); | 585 | spin_unlock_irqrestore(&phb->lock, flags); |
549 | pr_warning("%s: Failed to get log for PHB#%x-PE#%x\n", | 586 | pr_warning("%s: Can't get log for PHB#%x-PE#%x (%lld)\n", |
550 | __func__, hose->global_number, pe->addr); | 587 | __func__, hose->global_number, pe->addr, ret); |
551 | return -EIO; | 588 | return -EIO; |
552 | } | 589 | } |
553 | 590 | ||
@@ -710,6 +747,73 @@ static void ioda_eeh_p7ioc_phb_diag(struct pci_controller *hose, | |||
710 | } | 747 | } |
711 | } | 748 | } |
712 | 749 | ||
750 | static void ioda_eeh_phb3_phb_diag(struct pci_controller *hose, | ||
751 | struct OpalIoPhbErrorCommon *common) | ||
752 | { | ||
753 | struct OpalIoPhb3ErrorData *data; | ||
754 | int i; | ||
755 | |||
756 | data = (struct OpalIoPhb3ErrorData*)common; | ||
757 | pr_info("PHB3 PHB#%x Diag-data (Version: %d)\n\n", | ||
758 | hose->global_number, common->version); | ||
759 | |||
760 | pr_info(" brdgCtl: %08x\n", data->brdgCtl); | ||
761 | |||
762 | pr_info(" portStatusReg: %08x\n", data->portStatusReg); | ||
763 | pr_info(" rootCmplxStatus: %08x\n", data->rootCmplxStatus); | ||
764 | pr_info(" busAgentStatus: %08x\n", data->busAgentStatus); | ||
765 | |||
766 | pr_info(" deviceStatus: %08x\n", data->deviceStatus); | ||
767 | pr_info(" slotStatus: %08x\n", data->slotStatus); | ||
768 | pr_info(" linkStatus: %08x\n", data->linkStatus); | ||
769 | pr_info(" devCmdStatus: %08x\n", data->devCmdStatus); | ||
770 | pr_info(" devSecStatus: %08x\n", data->devSecStatus); | ||
771 | |||
772 | pr_info(" rootErrorStatus: %08x\n", data->rootErrorStatus); | ||
773 | pr_info(" uncorrErrorStatus: %08x\n", data->uncorrErrorStatus); | ||
774 | pr_info(" corrErrorStatus: %08x\n", data->corrErrorStatus); | ||
775 | pr_info(" tlpHdr1: %08x\n", data->tlpHdr1); | ||
776 | pr_info(" tlpHdr2: %08x\n", data->tlpHdr2); | ||
777 | pr_info(" tlpHdr3: %08x\n", data->tlpHdr3); | ||
778 | pr_info(" tlpHdr4: %08x\n", data->tlpHdr4); | ||
779 | pr_info(" sourceId: %08x\n", data->sourceId); | ||
780 | pr_info(" errorClass: %016llx\n", data->errorClass); | ||
781 | pr_info(" correlator: %016llx\n", data->correlator); | ||
782 | pr_info(" nFir: %016llx\n", data->nFir); | ||
783 | pr_info(" nFirMask: %016llx\n", data->nFirMask); | ||
784 | pr_info(" nFirWOF: %016llx\n", data->nFirWOF); | ||
785 | pr_info(" PhbPlssr: %016llx\n", data->phbPlssr); | ||
786 | pr_info(" PhbCsr: %016llx\n", data->phbCsr); | ||
787 | pr_info(" lemFir: %016llx\n", data->lemFir); | ||
788 | pr_info(" lemErrorMask: %016llx\n", data->lemErrorMask); | ||
789 | pr_info(" lemWOF: %016llx\n", data->lemWOF); | ||
790 | pr_info(" phbErrorStatus: %016llx\n", data->phbErrorStatus); | ||
791 | pr_info(" phbFirstErrorStatus: %016llx\n", data->phbFirstErrorStatus); | ||
792 | pr_info(" phbErrorLog0: %016llx\n", data->phbErrorLog0); | ||
793 | pr_info(" phbErrorLog1: %016llx\n", data->phbErrorLog1); | ||
794 | pr_info(" mmioErrorStatus: %016llx\n", data->mmioErrorStatus); | ||
795 | pr_info(" mmioFirstErrorStatus: %016llx\n", data->mmioFirstErrorStatus); | ||
796 | pr_info(" mmioErrorLog0: %016llx\n", data->mmioErrorLog0); | ||
797 | pr_info(" mmioErrorLog1: %016llx\n", data->mmioErrorLog1); | ||
798 | pr_info(" dma0ErrorStatus: %016llx\n", data->dma0ErrorStatus); | ||
799 | pr_info(" dma0FirstErrorStatus: %016llx\n", data->dma0FirstErrorStatus); | ||
800 | pr_info(" dma0ErrorLog0: %016llx\n", data->dma0ErrorLog0); | ||
801 | pr_info(" dma0ErrorLog1: %016llx\n", data->dma0ErrorLog1); | ||
802 | pr_info(" dma1ErrorStatus: %016llx\n", data->dma1ErrorStatus); | ||
803 | pr_info(" dma1FirstErrorStatus: %016llx\n", data->dma1FirstErrorStatus); | ||
804 | pr_info(" dma1ErrorLog0: %016llx\n", data->dma1ErrorLog0); | ||
805 | pr_info(" dma1ErrorLog1: %016llx\n", data->dma1ErrorLog1); | ||
806 | |||
807 | for (i = 0; i < OPAL_PHB3_NUM_PEST_REGS; i++) { | ||
808 | if ((data->pestA[i] >> 63) == 0 && | ||
809 | (data->pestB[i] >> 63) == 0) | ||
810 | continue; | ||
811 | |||
812 | pr_info(" PE[%3d] PESTA: %016llx\n", i, data->pestA[i]); | ||
813 | pr_info(" PESTB: %016llx\n", data->pestB[i]); | ||
814 | } | ||
815 | } | ||
816 | |||
713 | static void ioda_eeh_phb_diag(struct pci_controller *hose) | 817 | static void ioda_eeh_phb_diag(struct pci_controller *hose) |
714 | { | 818 | { |
715 | struct pnv_phb *phb = hose->private_data; | 819 | struct pnv_phb *phb = hose->private_data; |
@@ -728,6 +832,9 @@ static void ioda_eeh_phb_diag(struct pci_controller *hose) | |||
728 | case OPAL_PHB_ERROR_DATA_TYPE_P7IOC: | 832 | case OPAL_PHB_ERROR_DATA_TYPE_P7IOC: |
729 | ioda_eeh_p7ioc_phb_diag(hose, common); | 833 | ioda_eeh_p7ioc_phb_diag(hose, common); |
730 | break; | 834 | break; |
835 | case OPAL_PHB_ERROR_DATA_TYPE_PHB3: | ||
836 | ioda_eeh_phb3_phb_diag(hose, common); | ||
837 | break; | ||
731 | default: | 838 | default: |
732 | pr_warning("%s: Unrecognized I/O chip %d\n", | 839 | pr_warning("%s: Unrecognized I/O chip %d\n", |
733 | __func__, common->ioType); | 840 | __func__, common->ioType); |
diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c index 79663d26e6ea..73b981438cc5 100644 --- a/arch/powerpc/platforms/powernv/eeh-powernv.c +++ b/arch/powerpc/platforms/powernv/eeh-powernv.c | |||
@@ -144,11 +144,8 @@ static int powernv_eeh_dev_probe(struct pci_dev *dev, void *flag) | |||
144 | /* | 144 | /* |
145 | * Enable EEH explicitly so that we will do EEH check | 145 | * Enable EEH explicitly so that we will do EEH check |
146 | * while accessing I/O stuff | 146 | * while accessing I/O stuff |
147 | * | ||
148 | * FIXME: Enable that for PHB3 later | ||
149 | */ | 147 | */ |
150 | if (phb->type == PNV_PHB_IODA1) | 148 | eeh_subsystem_enabled = 1; |
151 | eeh_subsystem_enabled = 1; | ||
152 | 149 | ||
153 | /* Save memory bars */ | 150 | /* Save memory bars */ |
154 | eeh_save_bars(edev); | 151 | eeh_save_bars(edev); |
diff --git a/arch/powerpc/platforms/powernv/opal-flash.c b/arch/powerpc/platforms/powernv/opal-flash.c new file mode 100644 index 000000000000..6ffa6b1ec5b7 --- /dev/null +++ b/arch/powerpc/platforms/powernv/opal-flash.c | |||
@@ -0,0 +1,667 @@ | |||
1 | /* | ||
2 | * PowerNV OPAL Firmware Update Interface | ||
3 | * | ||
4 | * Copyright 2013 IBM Corp. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #define DEBUG | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/reboot.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/kobject.h> | ||
18 | #include <linux/sysfs.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/mm.h> | ||
21 | #include <linux/vmalloc.h> | ||
22 | #include <linux/pagemap.h> | ||
23 | |||
24 | #include <asm/opal.h> | ||
25 | |||
26 | /* FLASH status codes */ | ||
27 | #define FLASH_NO_OP -1099 /* No operation initiated by user */ | ||
28 | #define FLASH_NO_AUTH -9002 /* Not a service authority partition */ | ||
29 | |||
30 | /* Validate image status values */ | ||
31 | #define VALIDATE_IMG_READY -1001 /* Image ready for validation */ | ||
32 | #define VALIDATE_IMG_INCOMPLETE -1002 /* User copied < VALIDATE_BUF_SIZE */ | ||
33 | |||
34 | /* Manage image status values */ | ||
35 | #define MANAGE_ACTIVE_ERR -9001 /* Cannot overwrite active img */ | ||
36 | |||
37 | /* Flash image status values */ | ||
38 | #define FLASH_IMG_READY 0 /* Img ready for flash on reboot */ | ||
39 | #define FLASH_INVALID_IMG -1003 /* Flash image shorter than expected */ | ||
40 | #define FLASH_IMG_NULL_DATA -1004 /* Bad data in sg list entry */ | ||
41 | #define FLASH_IMG_BAD_LEN -1005 /* Bad length in sg list entry */ | ||
42 | |||
43 | /* Manage operation tokens */ | ||
44 | #define FLASH_REJECT_TMP_SIDE 0 /* Reject temporary fw image */ | ||
45 | #define FLASH_COMMIT_TMP_SIDE 1 /* Commit temporary fw image */ | ||
46 | |||
47 | /* Update tokens */ | ||
48 | #define FLASH_UPDATE_CANCEL 0 /* Cancel update request */ | ||
49 | #define FLASH_UPDATE_INIT 1 /* Initiate update */ | ||
50 | |||
51 | /* Validate image update result tokens */ | ||
52 | #define VALIDATE_TMP_UPDATE 0 /* T side will be updated */ | ||
53 | #define VALIDATE_FLASH_AUTH 1 /* Partition does not have authority */ | ||
54 | #define VALIDATE_INVALID_IMG 2 /* Candidate image is not valid */ | ||
55 | #define VALIDATE_CUR_UNKNOWN 3 /* Current fixpack level is unknown */ | ||
56 | /* | ||
57 | * Current T side will be committed to P side before being replace with new | ||
58 | * image, and the new image is downlevel from current image | ||
59 | */ | ||
60 | #define VALIDATE_TMP_COMMIT_DL 4 | ||
61 | /* | ||
62 | * Current T side will be committed to P side before being replaced with new | ||
63 | * image | ||
64 | */ | ||
65 | #define VALIDATE_TMP_COMMIT 5 | ||
66 | /* | ||
67 | * T side will be updated with a downlevel image | ||
68 | */ | ||
69 | #define VALIDATE_TMP_UPDATE_DL 6 | ||
70 | /* | ||
71 | * The candidate image's release date is later than the system's firmware | ||
72 | * service entitlement date - service warranty period has expired | ||
73 | */ | ||
74 | #define VALIDATE_OUT_OF_WRNTY 7 | ||
75 | |||
76 | /* Validate buffer size */ | ||
77 | #define VALIDATE_BUF_SIZE 4096 | ||
78 | |||
79 | /* XXX: Assume candidate image size is <= 256MB */ | ||
80 | #define MAX_IMAGE_SIZE 0x10000000 | ||
81 | |||
82 | /* Flash sg list version */ | ||
83 | #define SG_LIST_VERSION (1UL) | ||
84 | |||
85 | /* Image status */ | ||
86 | enum { | ||
87 | IMAGE_INVALID, | ||
88 | IMAGE_LOADING, | ||
89 | IMAGE_READY, | ||
90 | }; | ||
91 | |||
92 | /* Candidate image data */ | ||
93 | struct image_data_t { | ||
94 | int status; | ||
95 | void *data; | ||
96 | uint32_t size; | ||
97 | }; | ||
98 | |||
99 | /* Candidate image header */ | ||
100 | struct image_header_t { | ||
101 | uint16_t magic; | ||
102 | uint16_t version; | ||
103 | uint32_t size; | ||
104 | }; | ||
105 | |||
106 | /* Scatter/gather entry */ | ||
107 | struct opal_sg_entry { | ||
108 | void *data; | ||
109 | long length; | ||
110 | }; | ||
111 | |||
112 | /* We calculate number of entries based on PAGE_SIZE */ | ||
113 | #define SG_ENTRIES_PER_NODE ((PAGE_SIZE - 16) / sizeof(struct opal_sg_entry)) | ||
114 | |||
115 | /* | ||
116 | * This struct is very similar but not identical to that | ||
117 | * needed by the opal flash update. All we need to do for | ||
118 | * opal is rewrite num_entries into a version/length and | ||
119 | * translate the pointers to absolute. | ||
120 | */ | ||
121 | struct opal_sg_list { | ||
122 | unsigned long num_entries; | ||
123 | struct opal_sg_list *next; | ||
124 | struct opal_sg_entry entry[SG_ENTRIES_PER_NODE]; | ||
125 | }; | ||
126 | |||
127 | struct validate_flash_t { | ||
128 | int status; /* Return status */ | ||
129 | void *buf; /* Candiate image buffer */ | ||
130 | uint32_t buf_size; /* Image size */ | ||
131 | uint32_t result; /* Update results token */ | ||
132 | }; | ||
133 | |||
134 | struct manage_flash_t { | ||
135 | int status; /* Return status */ | ||
136 | }; | ||
137 | |||
138 | struct update_flash_t { | ||
139 | int status; /* Return status */ | ||
140 | }; | ||
141 | |||
142 | static struct image_header_t image_header; | ||
143 | static struct image_data_t image_data; | ||
144 | static struct validate_flash_t validate_flash_data; | ||
145 | static struct manage_flash_t manage_flash_data; | ||
146 | static struct update_flash_t update_flash_data; | ||
147 | |||
148 | static DEFINE_MUTEX(image_data_mutex); | ||
149 | |||
150 | /* | ||
151 | * Validate candidate image | ||
152 | */ | ||
153 | static inline void opal_flash_validate(void) | ||
154 | { | ||
155 | struct validate_flash_t *args_buf = &validate_flash_data; | ||
156 | |||
157 | args_buf->status = opal_validate_flash(__pa(args_buf->buf), | ||
158 | &(args_buf->buf_size), | ||
159 | &(args_buf->result)); | ||
160 | } | ||
161 | |||
162 | /* | ||
163 | * Validate output format: | ||
164 | * validate result token | ||
165 | * current image version details | ||
166 | * new image version details | ||
167 | */ | ||
168 | static ssize_t validate_show(struct kobject *kobj, | ||
169 | struct kobj_attribute *attr, char *buf) | ||
170 | { | ||
171 | struct validate_flash_t *args_buf = &validate_flash_data; | ||
172 | int len; | ||
173 | |||
174 | /* Candidate image is not validated */ | ||
175 | if (args_buf->status < VALIDATE_TMP_UPDATE) { | ||
176 | len = sprintf(buf, "%d\n", args_buf->status); | ||
177 | goto out; | ||
178 | } | ||
179 | |||
180 | /* Result token */ | ||
181 | len = sprintf(buf, "%d\n", args_buf->result); | ||
182 | |||
183 | /* Current and candidate image version details */ | ||
184 | if ((args_buf->result != VALIDATE_TMP_UPDATE) && | ||
185 | (args_buf->result < VALIDATE_CUR_UNKNOWN)) | ||
186 | goto out; | ||
187 | |||
188 | if (args_buf->buf_size > (VALIDATE_BUF_SIZE - len)) { | ||
189 | memcpy(buf + len, args_buf->buf, VALIDATE_BUF_SIZE - len); | ||
190 | len = VALIDATE_BUF_SIZE; | ||
191 | } else { | ||
192 | memcpy(buf + len, args_buf->buf, args_buf->buf_size); | ||
193 | len += args_buf->buf_size; | ||
194 | } | ||
195 | out: | ||
196 | /* Set status to default */ | ||
197 | args_buf->status = FLASH_NO_OP; | ||
198 | return len; | ||
199 | } | ||
200 | |||
201 | /* | ||
202 | * Validate candidate firmware image | ||
203 | * | ||
204 | * Note: | ||
205 | * We are only interested in first 4K bytes of the | ||
206 | * candidate image. | ||
207 | */ | ||
208 | static ssize_t validate_store(struct kobject *kobj, | ||
209 | struct kobj_attribute *attr, | ||
210 | const char *buf, size_t count) | ||
211 | { | ||
212 | struct validate_flash_t *args_buf = &validate_flash_data; | ||
213 | |||
214 | if (buf[0] != '1') | ||
215 | return -EINVAL; | ||
216 | |||
217 | mutex_lock(&image_data_mutex); | ||
218 | |||
219 | if (image_data.status != IMAGE_READY || | ||
220 | image_data.size < VALIDATE_BUF_SIZE) { | ||
221 | args_buf->result = VALIDATE_INVALID_IMG; | ||
222 | args_buf->status = VALIDATE_IMG_INCOMPLETE; | ||
223 | goto out; | ||
224 | } | ||
225 | |||
226 | /* Copy first 4k bytes of candidate image */ | ||
227 | memcpy(args_buf->buf, image_data.data, VALIDATE_BUF_SIZE); | ||
228 | |||
229 | args_buf->status = VALIDATE_IMG_READY; | ||
230 | args_buf->buf_size = VALIDATE_BUF_SIZE; | ||
231 | |||
232 | /* Validate candidate image */ | ||
233 | opal_flash_validate(); | ||
234 | |||
235 | out: | ||
236 | mutex_unlock(&image_data_mutex); | ||
237 | return count; | ||
238 | } | ||
239 | |||
240 | /* | ||
241 | * Manage flash routine | ||
242 | */ | ||
243 | static inline void opal_flash_manage(uint8_t op) | ||
244 | { | ||
245 | struct manage_flash_t *const args_buf = &manage_flash_data; | ||
246 | |||
247 | args_buf->status = opal_manage_flash(op); | ||
248 | } | ||
249 | |||
250 | /* | ||
251 | * Show manage flash status | ||
252 | */ | ||
253 | static ssize_t manage_show(struct kobject *kobj, | ||
254 | struct kobj_attribute *attr, char *buf) | ||
255 | { | ||
256 | struct manage_flash_t *const args_buf = &manage_flash_data; | ||
257 | int rc; | ||
258 | |||
259 | rc = sprintf(buf, "%d\n", args_buf->status); | ||
260 | /* Set status to default*/ | ||
261 | args_buf->status = FLASH_NO_OP; | ||
262 | return rc; | ||
263 | } | ||
264 | |||
265 | /* | ||
266 | * Manage operations: | ||
267 | * 0 - Reject | ||
268 | * 1 - Commit | ||
269 | */ | ||
270 | static ssize_t manage_store(struct kobject *kobj, | ||
271 | struct kobj_attribute *attr, | ||
272 | const char *buf, size_t count) | ||
273 | { | ||
274 | uint8_t op; | ||
275 | switch (buf[0]) { | ||
276 | case '0': | ||
277 | op = FLASH_REJECT_TMP_SIDE; | ||
278 | break; | ||
279 | case '1': | ||
280 | op = FLASH_COMMIT_TMP_SIDE; | ||
281 | break; | ||
282 | default: | ||
283 | return -EINVAL; | ||
284 | } | ||
285 | |||
286 | /* commit/reject temporary image */ | ||
287 | opal_flash_manage(op); | ||
288 | return count; | ||
289 | } | ||
290 | |||
291 | /* | ||
292 | * Free sg list | ||
293 | */ | ||
294 | static void free_sg_list(struct opal_sg_list *list) | ||
295 | { | ||
296 | struct opal_sg_list *sg1; | ||
297 | while (list) { | ||
298 | sg1 = list->next; | ||
299 | kfree(list); | ||
300 | list = sg1; | ||
301 | } | ||
302 | list = NULL; | ||
303 | } | ||
304 | |||
305 | /* | ||
306 | * Build candidate image scatter gather list | ||
307 | * | ||
308 | * list format: | ||
309 | * ----------------------------------- | ||
310 | * | VER (8) | Entry length in bytes | | ||
311 | * ----------------------------------- | ||
312 | * | Pointer to next entry | | ||
313 | * ----------------------------------- | ||
314 | * | Address of memory area 1 | | ||
315 | * ----------------------------------- | ||
316 | * | Length of memory area 1 | | ||
317 | * ----------------------------------- | ||
318 | * | ......... | | ||
319 | * ----------------------------------- | ||
320 | * | ......... | | ||
321 | * ----------------------------------- | ||
322 | * | Address of memory area N | | ||
323 | * ----------------------------------- | ||
324 | * | Length of memory area N | | ||
325 | * ----------------------------------- | ||
326 | */ | ||
327 | static struct opal_sg_list *image_data_to_sglist(void) | ||
328 | { | ||
329 | struct opal_sg_list *sg1, *list = NULL; | ||
330 | void *addr; | ||
331 | int size; | ||
332 | |||
333 | addr = image_data.data; | ||
334 | size = image_data.size; | ||
335 | |||
336 | sg1 = kzalloc((sizeof(struct opal_sg_list)), GFP_KERNEL); | ||
337 | if (!sg1) | ||
338 | return NULL; | ||
339 | |||
340 | list = sg1; | ||
341 | sg1->num_entries = 0; | ||
342 | while (size > 0) { | ||
343 | /* Translate virtual address to physical address */ | ||
344 | sg1->entry[sg1->num_entries].data = | ||
345 | (void *)(vmalloc_to_pfn(addr) << PAGE_SHIFT); | ||
346 | |||
347 | if (size > PAGE_SIZE) | ||
348 | sg1->entry[sg1->num_entries].length = PAGE_SIZE; | ||
349 | else | ||
350 | sg1->entry[sg1->num_entries].length = size; | ||
351 | |||
352 | sg1->num_entries++; | ||
353 | if (sg1->num_entries >= SG_ENTRIES_PER_NODE) { | ||
354 | sg1->next = kzalloc((sizeof(struct opal_sg_list)), | ||
355 | GFP_KERNEL); | ||
356 | if (!sg1->next) { | ||
357 | pr_err("%s : Failed to allocate memory\n", | ||
358 | __func__); | ||
359 | goto nomem; | ||
360 | } | ||
361 | |||
362 | sg1 = sg1->next; | ||
363 | sg1->num_entries = 0; | ||
364 | } | ||
365 | addr += PAGE_SIZE; | ||
366 | size -= PAGE_SIZE; | ||
367 | } | ||
368 | return list; | ||
369 | nomem: | ||
370 | free_sg_list(list); | ||
371 | return NULL; | ||
372 | } | ||
373 | |||
374 | /* | ||
375 | * OPAL update flash | ||
376 | */ | ||
377 | static int opal_flash_update(int op) | ||
378 | { | ||
379 | struct opal_sg_list *sg, *list, *next; | ||
380 | unsigned long addr; | ||
381 | int64_t rc = OPAL_PARAMETER; | ||
382 | |||
383 | if (op == FLASH_UPDATE_CANCEL) { | ||
384 | pr_alert("FLASH: Image update cancelled\n"); | ||
385 | addr = '\0'; | ||
386 | goto flash; | ||
387 | } | ||
388 | |||
389 | list = image_data_to_sglist(); | ||
390 | if (!list) | ||
391 | goto invalid_img; | ||
392 | |||
393 | /* First entry address */ | ||
394 | addr = __pa(list); | ||
395 | |||
396 | /* Translate sg list address to absolute */ | ||
397 | for (sg = list; sg; sg = next) { | ||
398 | next = sg->next; | ||
399 | /* Don't translate NULL pointer for last entry */ | ||
400 | if (sg->next) | ||
401 | sg->next = (struct opal_sg_list *)__pa(sg->next); | ||
402 | else | ||
403 | sg->next = NULL; | ||
404 | |||
405 | /* Make num_entries into the version/length field */ | ||
406 | sg->num_entries = (SG_LIST_VERSION << 56) | | ||
407 | (sg->num_entries * sizeof(struct opal_sg_entry) + 16); | ||
408 | } | ||
409 | |||
410 | pr_alert("FLASH: Image is %u bytes\n", image_data.size); | ||
411 | pr_alert("FLASH: Image update requested\n"); | ||
412 | pr_alert("FLASH: Image will be updated during system reboot\n"); | ||
413 | pr_alert("FLASH: This will take several minutes. Do not power off!\n"); | ||
414 | |||
415 | flash: | ||
416 | rc = opal_update_flash(addr); | ||
417 | |||
418 | invalid_img: | ||
419 | return rc; | ||
420 | } | ||
421 | |||
422 | /* | ||
423 | * Show candidate image status | ||
424 | */ | ||
425 | static ssize_t update_show(struct kobject *kobj, | ||
426 | struct kobj_attribute *attr, char *buf) | ||
427 | { | ||
428 | struct update_flash_t *const args_buf = &update_flash_data; | ||
429 | return sprintf(buf, "%d\n", args_buf->status); | ||
430 | } | ||
431 | |||
432 | /* | ||
433 | * Set update image flag | ||
434 | * 1 - Flash new image | ||
435 | * 0 - Cancel flash request | ||
436 | */ | ||
437 | static ssize_t update_store(struct kobject *kobj, | ||
438 | struct kobj_attribute *attr, | ||
439 | const char *buf, size_t count) | ||
440 | { | ||
441 | struct update_flash_t *const args_buf = &update_flash_data; | ||
442 | int rc = count; | ||
443 | |||
444 | mutex_lock(&image_data_mutex); | ||
445 | |||
446 | switch (buf[0]) { | ||
447 | case '0': | ||
448 | if (args_buf->status == FLASH_IMG_READY) | ||
449 | opal_flash_update(FLASH_UPDATE_CANCEL); | ||
450 | args_buf->status = FLASH_NO_OP; | ||
451 | break; | ||
452 | case '1': | ||
453 | /* Image is loaded? */ | ||
454 | if (image_data.status == IMAGE_READY) | ||
455 | args_buf->status = | ||
456 | opal_flash_update(FLASH_UPDATE_INIT); | ||
457 | else | ||
458 | args_buf->status = FLASH_INVALID_IMG; | ||
459 | break; | ||
460 | default: | ||
461 | rc = -EINVAL; | ||
462 | } | ||
463 | |||
464 | mutex_unlock(&image_data_mutex); | ||
465 | return rc; | ||
466 | } | ||
467 | |||
468 | /* | ||
469 | * Free image buffer | ||
470 | */ | ||
471 | static void free_image_buf(void) | ||
472 | { | ||
473 | void *addr; | ||
474 | int size; | ||
475 | |||
476 | addr = image_data.data; | ||
477 | size = PAGE_ALIGN(image_data.size); | ||
478 | while (size > 0) { | ||
479 | ClearPageReserved(vmalloc_to_page(addr)); | ||
480 | addr += PAGE_SIZE; | ||
481 | size -= PAGE_SIZE; | ||
482 | } | ||
483 | vfree(image_data.data); | ||
484 | image_data.data = NULL; | ||
485 | image_data.status = IMAGE_INVALID; | ||
486 | } | ||
487 | |||
488 | /* | ||
489 | * Allocate image buffer. | ||
490 | */ | ||
491 | static int alloc_image_buf(char *buffer, size_t count) | ||
492 | { | ||
493 | void *addr; | ||
494 | int size; | ||
495 | |||
496 | if (count < sizeof(struct image_header_t)) { | ||
497 | pr_warn("FLASH: Invalid candidate image\n"); | ||
498 | return -EINVAL; | ||
499 | } | ||
500 | |||
501 | memcpy(&image_header, (void *)buffer, sizeof(struct image_header_t)); | ||
502 | image_data.size = be32_to_cpu(image_header.size); | ||
503 | pr_debug("FLASH: Candiate image size = %u\n", image_data.size); | ||
504 | |||
505 | if (image_data.size > MAX_IMAGE_SIZE) { | ||
506 | pr_warn("FLASH: Too large image\n"); | ||
507 | return -EINVAL; | ||
508 | } | ||
509 | if (image_data.size < VALIDATE_BUF_SIZE) { | ||
510 | pr_warn("FLASH: Image is shorter than expected\n"); | ||
511 | return -EINVAL; | ||
512 | } | ||
513 | |||
514 | image_data.data = vzalloc(PAGE_ALIGN(image_data.size)); | ||
515 | if (!image_data.data) { | ||
516 | pr_err("%s : Failed to allocate memory\n", __func__); | ||
517 | return -ENOMEM; | ||
518 | } | ||
519 | |||
520 | /* Pin memory */ | ||
521 | addr = image_data.data; | ||
522 | size = PAGE_ALIGN(image_data.size); | ||
523 | while (size > 0) { | ||
524 | SetPageReserved(vmalloc_to_page(addr)); | ||
525 | addr += PAGE_SIZE; | ||
526 | size -= PAGE_SIZE; | ||
527 | } | ||
528 | |||
529 | image_data.status = IMAGE_LOADING; | ||
530 | return 0; | ||
531 | } | ||
532 | |||
533 | /* | ||
534 | * Copy candidate image | ||
535 | * | ||
536 | * Parse candidate image header to get total image size | ||
537 | * and pre-allocate required memory. | ||
538 | */ | ||
539 | static ssize_t image_data_write(struct file *filp, struct kobject *kobj, | ||
540 | struct bin_attribute *bin_attr, | ||
541 | char *buffer, loff_t pos, size_t count) | ||
542 | { | ||
543 | int rc; | ||
544 | |||
545 | mutex_lock(&image_data_mutex); | ||
546 | |||
547 | /* New image ? */ | ||
548 | if (pos == 0) { | ||
549 | /* Free memory, if already allocated */ | ||
550 | if (image_data.data) | ||
551 | free_image_buf(); | ||
552 | |||
553 | /* Cancel outstanding image update request */ | ||
554 | if (update_flash_data.status == FLASH_IMG_READY) | ||
555 | opal_flash_update(FLASH_UPDATE_CANCEL); | ||
556 | |||
557 | /* Allocate memory */ | ||
558 | rc = alloc_image_buf(buffer, count); | ||
559 | if (rc) | ||
560 | goto out; | ||
561 | } | ||
562 | |||
563 | if (image_data.status != IMAGE_LOADING) { | ||
564 | rc = -ENOMEM; | ||
565 | goto out; | ||
566 | } | ||
567 | |||
568 | if ((pos + count) > image_data.size) { | ||
569 | rc = -EINVAL; | ||
570 | goto out; | ||
571 | } | ||
572 | |||
573 | memcpy(image_data.data + pos, (void *)buffer, count); | ||
574 | rc = count; | ||
575 | |||
576 | /* Set image status */ | ||
577 | if ((pos + count) == image_data.size) { | ||
578 | pr_debug("FLASH: Candidate image loaded....\n"); | ||
579 | image_data.status = IMAGE_READY; | ||
580 | } | ||
581 | |||
582 | out: | ||
583 | mutex_unlock(&image_data_mutex); | ||
584 | return rc; | ||
585 | } | ||
586 | |||
587 | /* | ||
588 | * sysfs interface : | ||
589 | * OPAL uses below sysfs files for code update. | ||
590 | * We create these files under /sys/firmware/opal. | ||
591 | * | ||
592 | * image : Interface to load candidate firmware image | ||
593 | * validate_flash : Validate firmware image | ||
594 | * manage_flash : Commit/Reject firmware image | ||
595 | * update_flash : Flash new firmware image | ||
596 | * | ||
597 | */ | ||
598 | static struct bin_attribute image_data_attr = { | ||
599 | .attr = {.name = "image", .mode = 0200}, | ||
600 | .size = MAX_IMAGE_SIZE, /* Limit image size */ | ||
601 | .write = image_data_write, | ||
602 | }; | ||
603 | |||
604 | static struct kobj_attribute validate_attribute = | ||
605 | __ATTR(validate_flash, 0600, validate_show, validate_store); | ||
606 | |||
607 | static struct kobj_attribute manage_attribute = | ||
608 | __ATTR(manage_flash, 0600, manage_show, manage_store); | ||
609 | |||
610 | static struct kobj_attribute update_attribute = | ||
611 | __ATTR(update_flash, 0600, update_show, update_store); | ||
612 | |||
613 | static struct attribute *image_op_attrs[] = { | ||
614 | &validate_attribute.attr, | ||
615 | &manage_attribute.attr, | ||
616 | &update_attribute.attr, | ||
617 | NULL /* need to NULL terminate the list of attributes */ | ||
618 | }; | ||
619 | |||
620 | static struct attribute_group image_op_attr_group = { | ||
621 | .attrs = image_op_attrs, | ||
622 | }; | ||
623 | |||
624 | void __init opal_flash_init(void) | ||
625 | { | ||
626 | int ret; | ||
627 | |||
628 | /* Allocate validate image buffer */ | ||
629 | validate_flash_data.buf = kzalloc(VALIDATE_BUF_SIZE, GFP_KERNEL); | ||
630 | if (!validate_flash_data.buf) { | ||
631 | pr_err("%s : Failed to allocate memory\n", __func__); | ||
632 | return; | ||
633 | } | ||
634 | |||
635 | /* Make sure /sys/firmware/opal directory is created */ | ||
636 | if (!opal_kobj) { | ||
637 | pr_warn("FLASH: opal kobject is not available\n"); | ||
638 | goto nokobj; | ||
639 | } | ||
640 | |||
641 | /* Create the sysfs files */ | ||
642 | ret = sysfs_create_group(opal_kobj, &image_op_attr_group); | ||
643 | if (ret) { | ||
644 | pr_warn("FLASH: Failed to create sysfs files\n"); | ||
645 | goto nokobj; | ||
646 | } | ||
647 | |||
648 | ret = sysfs_create_bin_file(opal_kobj, &image_data_attr); | ||
649 | if (ret) { | ||
650 | pr_warn("FLASH: Failed to create sysfs files\n"); | ||
651 | goto nosysfs_file; | ||
652 | } | ||
653 | |||
654 | /* Set default status */ | ||
655 | validate_flash_data.status = FLASH_NO_OP; | ||
656 | manage_flash_data.status = FLASH_NO_OP; | ||
657 | update_flash_data.status = FLASH_NO_OP; | ||
658 | image_data.status = IMAGE_INVALID; | ||
659 | return; | ||
660 | |||
661 | nosysfs_file: | ||
662 | sysfs_remove_group(opal_kobj, &image_op_attr_group); | ||
663 | |||
664 | nokobj: | ||
665 | kfree(validate_flash_data.buf); | ||
666 | return; | ||
667 | } | ||
diff --git a/arch/powerpc/platforms/powernv/opal-lpc.c b/arch/powerpc/platforms/powernv/opal-lpc.c index a7614bb14e17..e7e59e4f9892 100644 --- a/arch/powerpc/platforms/powernv/opal-lpc.c +++ b/arch/powerpc/platforms/powernv/opal-lpc.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <asm/firmware.h> | 17 | #include <asm/firmware.h> |
18 | #include <asm/xics.h> | 18 | #include <asm/xics.h> |
19 | #include <asm/opal.h> | 19 | #include <asm/opal.h> |
20 | #include <asm/prom.h> | ||
20 | 21 | ||
21 | static int opal_lpc_chip_id = -1; | 22 | static int opal_lpc_chip_id = -1; |
22 | 23 | ||
diff --git a/arch/powerpc/platforms/powernv/opal-nvram.c b/arch/powerpc/platforms/powernv/opal-nvram.c index 3f83e1ae26ac..acd9f7e96678 100644 --- a/arch/powerpc/platforms/powernv/opal-nvram.c +++ b/arch/powerpc/platforms/powernv/opal-nvram.c | |||
@@ -65,7 +65,7 @@ static ssize_t opal_nvram_write(char *buf, size_t count, loff_t *index) | |||
65 | void __init opal_nvram_init(void) | 65 | void __init opal_nvram_init(void) |
66 | { | 66 | { |
67 | struct device_node *np; | 67 | struct device_node *np; |
68 | const u32 *nbytes_p; | 68 | const __be32 *nbytes_p; |
69 | 69 | ||
70 | np = of_find_compatible_node(NULL, NULL, "ibm,opal-nvram"); | 70 | np = of_find_compatible_node(NULL, NULL, "ibm,opal-nvram"); |
71 | if (np == NULL) | 71 | if (np == NULL) |
@@ -76,7 +76,7 @@ void __init opal_nvram_init(void) | |||
76 | of_node_put(np); | 76 | of_node_put(np); |
77 | return; | 77 | return; |
78 | } | 78 | } |
79 | nvram_size = *nbytes_p; | 79 | nvram_size = be32_to_cpup(nbytes_p); |
80 | 80 | ||
81 | printk(KERN_INFO "OPAL nvram setup, %u bytes\n", nvram_size); | 81 | printk(KERN_INFO "OPAL nvram setup, %u bytes\n", nvram_size); |
82 | of_node_put(np); | 82 | of_node_put(np); |
diff --git a/arch/powerpc/platforms/powernv/opal-rtc.c b/arch/powerpc/platforms/powernv/opal-rtc.c index 2aa7641aac9b..7d07c7e80ec0 100644 --- a/arch/powerpc/platforms/powernv/opal-rtc.c +++ b/arch/powerpc/platforms/powernv/opal-rtc.c | |||
@@ -37,10 +37,12 @@ unsigned long __init opal_get_boot_time(void) | |||
37 | struct rtc_time tm; | 37 | struct rtc_time tm; |
38 | u32 y_m_d; | 38 | u32 y_m_d; |
39 | u64 h_m_s_ms; | 39 | u64 h_m_s_ms; |
40 | __be32 __y_m_d; | ||
41 | __be64 __h_m_s_ms; | ||
40 | long rc = OPAL_BUSY; | 42 | long rc = OPAL_BUSY; |
41 | 43 | ||
42 | while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) { | 44 | while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) { |
43 | rc = opal_rtc_read(&y_m_d, &h_m_s_ms); | 45 | rc = opal_rtc_read(&__y_m_d, &__h_m_s_ms); |
44 | if (rc == OPAL_BUSY_EVENT) | 46 | if (rc == OPAL_BUSY_EVENT) |
45 | opal_poll_events(NULL); | 47 | opal_poll_events(NULL); |
46 | else | 48 | else |
@@ -48,6 +50,8 @@ unsigned long __init opal_get_boot_time(void) | |||
48 | } | 50 | } |
49 | if (rc != OPAL_SUCCESS) | 51 | if (rc != OPAL_SUCCESS) |
50 | return 0; | 52 | return 0; |
53 | y_m_d = be32_to_cpu(__y_m_d); | ||
54 | h_m_s_ms = be64_to_cpu(__h_m_s_ms); | ||
51 | opal_to_tm(y_m_d, h_m_s_ms, &tm); | 55 | opal_to_tm(y_m_d, h_m_s_ms, &tm); |
52 | return mktime(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, | 56 | return mktime(tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, |
53 | tm.tm_hour, tm.tm_min, tm.tm_sec); | 57 | tm.tm_hour, tm.tm_min, tm.tm_sec); |
@@ -58,9 +62,11 @@ void opal_get_rtc_time(struct rtc_time *tm) | |||
58 | long rc = OPAL_BUSY; | 62 | long rc = OPAL_BUSY; |
59 | u32 y_m_d; | 63 | u32 y_m_d; |
60 | u64 h_m_s_ms; | 64 | u64 h_m_s_ms; |
65 | __be32 __y_m_d; | ||
66 | __be64 __h_m_s_ms; | ||
61 | 67 | ||
62 | while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) { | 68 | while (rc == OPAL_BUSY || rc == OPAL_BUSY_EVENT) { |
63 | rc = opal_rtc_read(&y_m_d, &h_m_s_ms); | 69 | rc = opal_rtc_read(&__y_m_d, &__h_m_s_ms); |
64 | if (rc == OPAL_BUSY_EVENT) | 70 | if (rc == OPAL_BUSY_EVENT) |
65 | opal_poll_events(NULL); | 71 | opal_poll_events(NULL); |
66 | else | 72 | else |
@@ -68,6 +74,8 @@ void opal_get_rtc_time(struct rtc_time *tm) | |||
68 | } | 74 | } |
69 | if (rc != OPAL_SUCCESS) | 75 | if (rc != OPAL_SUCCESS) |
70 | return; | 76 | return; |
77 | y_m_d = be32_to_cpu(__y_m_d); | ||
78 | h_m_s_ms = be64_to_cpu(__h_m_s_ms); | ||
71 | opal_to_tm(y_m_d, h_m_s_ms, tm); | 79 | opal_to_tm(y_m_d, h_m_s_ms, tm); |
72 | } | 80 | } |
73 | 81 | ||
diff --git a/arch/powerpc/platforms/powernv/opal-wrappers.S b/arch/powerpc/platforms/powernv/opal-wrappers.S index 8f3844535fbb..e7806504e976 100644 --- a/arch/powerpc/platforms/powernv/opal-wrappers.S +++ b/arch/powerpc/platforms/powernv/opal-wrappers.S | |||
@@ -24,7 +24,7 @@ | |||
24 | mflr r0; \ | 24 | mflr r0; \ |
25 | mfcr r12; \ | 25 | mfcr r12; \ |
26 | std r0,16(r1); \ | 26 | std r0,16(r1); \ |
27 | std r12,8(r1); \ | 27 | stw r12,8(r1); \ |
28 | std r1,PACAR1(r13); \ | 28 | std r1,PACAR1(r13); \ |
29 | li r0,0; \ | 29 | li r0,0; \ |
30 | mfmsr r12; \ | 30 | mfmsr r12; \ |
@@ -34,7 +34,7 @@ | |||
34 | mtmsrd r12,1; \ | 34 | mtmsrd r12,1; \ |
35 | LOAD_REG_ADDR(r0,.opal_return); \ | 35 | LOAD_REG_ADDR(r0,.opal_return); \ |
36 | mtlr r0; \ | 36 | mtlr r0; \ |
37 | li r0,MSR_DR|MSR_IR; \ | 37 | li r0,MSR_DR|MSR_IR|MSR_LE;\ |
38 | andc r12,r12,r0; \ | 38 | andc r12,r12,r0; \ |
39 | li r0,token; \ | 39 | li r0,token; \ |
40 | mtspr SPRN_HSRR1,r12; \ | 40 | mtspr SPRN_HSRR1,r12; \ |
@@ -45,8 +45,15 @@ | |||
45 | hrfid | 45 | hrfid |
46 | 46 | ||
47 | _STATIC(opal_return) | 47 | _STATIC(opal_return) |
48 | /* | ||
49 | * Fixup endian on OPAL return... we should be able to simplify | ||
50 | * this by instead converting the below trampoline to a set of | ||
51 | * bytes (always BE) since MSR:LE will end up fixed up as a side | ||
52 | * effect of the rfid. | ||
53 | */ | ||
54 | FIXUP_ENDIAN | ||
48 | ld r2,PACATOC(r13); | 55 | ld r2,PACATOC(r13); |
49 | ld r4,8(r1); | 56 | lwz r4,8(r1); |
50 | ld r5,16(r1); | 57 | ld r5,16(r1); |
51 | ld r6,PACASAVEDMSR(r13); | 58 | ld r6,PACASAVEDMSR(r13); |
52 | mtspr SPRN_SRR0,r5; | 59 | mtspr SPRN_SRR0,r5; |
@@ -116,3 +123,6 @@ OPAL_CALL(opal_xscom_write, OPAL_XSCOM_WRITE); | |||
116 | OPAL_CALL(opal_lpc_read, OPAL_LPC_READ); | 123 | OPAL_CALL(opal_lpc_read, OPAL_LPC_READ); |
117 | OPAL_CALL(opal_lpc_write, OPAL_LPC_WRITE); | 124 | OPAL_CALL(opal_lpc_write, OPAL_LPC_WRITE); |
118 | OPAL_CALL(opal_return_cpu, OPAL_RETURN_CPU); | 125 | OPAL_CALL(opal_return_cpu, OPAL_RETURN_CPU); |
126 | OPAL_CALL(opal_validate_flash, OPAL_FLASH_VALIDATE); | ||
127 | OPAL_CALL(opal_manage_flash, OPAL_FLASH_MANAGE); | ||
128 | OPAL_CALL(opal_update_flash, OPAL_FLASH_UPDATE); | ||
diff --git a/arch/powerpc/platforms/powernv/opal-xscom.c b/arch/powerpc/platforms/powernv/opal-xscom.c new file mode 100644 index 000000000000..4d99a8fd55ac --- /dev/null +++ b/arch/powerpc/platforms/powernv/opal-xscom.c | |||
@@ -0,0 +1,128 @@ | |||
1 | /* | ||
2 | * PowerNV LPC bus handling. | ||
3 | * | ||
4 | * Copyright 2013 IBM Corp. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/of.h> | ||
14 | #include <linux/bug.h> | ||
15 | #include <linux/gfp.h> | ||
16 | #include <linux/slab.h> | ||
17 | |||
18 | #include <asm/machdep.h> | ||
19 | #include <asm/firmware.h> | ||
20 | #include <asm/opal.h> | ||
21 | #include <asm/scom.h> | ||
22 | |||
23 | /* | ||
24 | * We could probably fit that inside the scom_map_t | ||
25 | * which is a void* after all but it's really too ugly | ||
26 | * so let's kmalloc it for now | ||
27 | */ | ||
28 | struct opal_scom_map { | ||
29 | uint32_t chip; | ||
30 | uint64_t addr; | ||
31 | }; | ||
32 | |||
33 | static scom_map_t opal_scom_map(struct device_node *dev, u64 reg, u64 count) | ||
34 | { | ||
35 | struct opal_scom_map *m; | ||
36 | const __be32 *gcid; | ||
37 | |||
38 | if (!of_get_property(dev, "scom-controller", NULL)) { | ||
39 | pr_err("%s: device %s is not a SCOM controller\n", | ||
40 | __func__, dev->full_name); | ||
41 | return SCOM_MAP_INVALID; | ||
42 | } | ||
43 | gcid = of_get_property(dev, "ibm,chip-id", NULL); | ||
44 | if (!gcid) { | ||
45 | pr_err("%s: device %s has no ibm,chip-id\n", | ||
46 | __func__, dev->full_name); | ||
47 | return SCOM_MAP_INVALID; | ||
48 | } | ||
49 | m = kmalloc(sizeof(struct opal_scom_map), GFP_KERNEL); | ||
50 | if (!m) | ||
51 | return NULL; | ||
52 | m->chip = be32_to_cpup(gcid); | ||
53 | m->addr = reg; | ||
54 | |||
55 | return (scom_map_t)m; | ||
56 | } | ||
57 | |||
58 | static void opal_scom_unmap(scom_map_t map) | ||
59 | { | ||
60 | kfree(map); | ||
61 | } | ||
62 | |||
63 | static int opal_xscom_err_xlate(int64_t rc) | ||
64 | { | ||
65 | switch(rc) { | ||
66 | case 0: | ||
67 | return 0; | ||
68 | /* Add more translations if necessary */ | ||
69 | default: | ||
70 | return -EIO; | ||
71 | } | ||
72 | } | ||
73 | |||
74 | static u64 opal_scom_unmangle(u64 reg) | ||
75 | { | ||
76 | /* | ||
77 | * XSCOM indirect addresses have the top bit set. Additionally | ||
78 | * the reset of the top 3 nibbles is always 0. | ||
79 | * | ||
80 | * Because the debugfs interface uses signed offsets and shifts | ||
81 | * the address left by 3, we basically cannot use the top 4 bits | ||
82 | * of the 64-bit address, and thus cannot use the indirect bit. | ||
83 | * | ||
84 | * To deal with that, we support the indirect bit being in bit | ||
85 | * 4 (IBM notation) instead of bit 0 in this API, we do the | ||
86 | * conversion here. To leave room for further xscom address | ||
87 | * expansion, we only clear out the top byte | ||
88 | * | ||
89 | */ | ||
90 | if (reg & (1ull << 59)) | ||
91 | reg = (reg & ~(0xffull << 56)) | (1ull << 63); | ||
92 | return reg; | ||
93 | } | ||
94 | |||
95 | static int opal_scom_read(scom_map_t map, u64 reg, u64 *value) | ||
96 | { | ||
97 | struct opal_scom_map *m = map; | ||
98 | int64_t rc; | ||
99 | |||
100 | reg = opal_scom_unmangle(reg); | ||
101 | rc = opal_xscom_read(m->chip, m->addr + reg, (uint64_t *)__pa(value)); | ||
102 | return opal_xscom_err_xlate(rc); | ||
103 | } | ||
104 | |||
105 | static int opal_scom_write(scom_map_t map, u64 reg, u64 value) | ||
106 | { | ||
107 | struct opal_scom_map *m = map; | ||
108 | int64_t rc; | ||
109 | |||
110 | reg = opal_scom_unmangle(reg); | ||
111 | rc = opal_xscom_write(m->chip, m->addr + reg, value); | ||
112 | return opal_xscom_err_xlate(rc); | ||
113 | } | ||
114 | |||
115 | static const struct scom_controller opal_scom_controller = { | ||
116 | .map = opal_scom_map, | ||
117 | .unmap = opal_scom_unmap, | ||
118 | .read = opal_scom_read, | ||
119 | .write = opal_scom_write | ||
120 | }; | ||
121 | |||
122 | static int opal_xscom_init(void) | ||
123 | { | ||
124 | if (firmware_has_feature(FW_FEATURE_OPALv3)) | ||
125 | scom_init(&opal_scom_controller); | ||
126 | return 0; | ||
127 | } | ||
128 | arch_initcall(opal_xscom_init); | ||
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c index 2911abe550f1..1c798cd55372 100644 --- a/arch/powerpc/platforms/powernv/opal.c +++ b/arch/powerpc/platforms/powernv/opal.c | |||
@@ -13,15 +13,20 @@ | |||
13 | 13 | ||
14 | #include <linux/types.h> | 14 | #include <linux/types.h> |
15 | #include <linux/of.h> | 15 | #include <linux/of.h> |
16 | #include <linux/of_fdt.h> | ||
16 | #include <linux/of_platform.h> | 17 | #include <linux/of_platform.h> |
17 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
18 | #include <linux/notifier.h> | 19 | #include <linux/notifier.h> |
19 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/kobject.h> | ||
20 | #include <asm/opal.h> | 22 | #include <asm/opal.h> |
21 | #include <asm/firmware.h> | 23 | #include <asm/firmware.h> |
22 | 24 | ||
23 | #include "powernv.h" | 25 | #include "powernv.h" |
24 | 26 | ||
27 | /* /sys/firmware/opal */ | ||
28 | struct kobject *opal_kobj; | ||
29 | |||
25 | struct opal { | 30 | struct opal { |
26 | u64 base; | 31 | u64 base; |
27 | u64 entry; | 32 | u64 entry; |
@@ -77,6 +82,7 @@ int __init early_init_dt_scan_opal(unsigned long node, | |||
77 | 82 | ||
78 | static int __init opal_register_exception_handlers(void) | 83 | static int __init opal_register_exception_handlers(void) |
79 | { | 84 | { |
85 | #ifdef __BIG_ENDIAN__ | ||
80 | u64 glue; | 86 | u64 glue; |
81 | 87 | ||
82 | if (!(powerpc_firmware_features & FW_FEATURE_OPAL)) | 88 | if (!(powerpc_firmware_features & FW_FEATURE_OPAL)) |
@@ -94,6 +100,7 @@ static int __init opal_register_exception_handlers(void) | |||
94 | 0, glue); | 100 | 0, glue); |
95 | glue += 128; | 101 | glue += 128; |
96 | opal_register_exception_handler(OPAL_SOFTPATCH_HANDLER, 0, glue); | 102 | opal_register_exception_handler(OPAL_SOFTPATCH_HANDLER, 0, glue); |
103 | #endif | ||
97 | 104 | ||
98 | return 0; | 105 | return 0; |
99 | } | 106 | } |
@@ -164,27 +171,28 @@ void opal_notifier_disable(void) | |||
164 | 171 | ||
165 | int opal_get_chars(uint32_t vtermno, char *buf, int count) | 172 | int opal_get_chars(uint32_t vtermno, char *buf, int count) |
166 | { | 173 | { |
167 | s64 len, rc; | 174 | s64 rc; |
168 | u64 evt; | 175 | __be64 evt, len; |
169 | 176 | ||
170 | if (!opal.entry) | 177 | if (!opal.entry) |
171 | return -ENODEV; | 178 | return -ENODEV; |
172 | opal_poll_events(&evt); | 179 | opal_poll_events(&evt); |
173 | if ((evt & OPAL_EVENT_CONSOLE_INPUT) == 0) | 180 | if ((be64_to_cpu(evt) & OPAL_EVENT_CONSOLE_INPUT) == 0) |
174 | return 0; | 181 | return 0; |
175 | len = count; | 182 | len = cpu_to_be64(count); |
176 | rc = opal_console_read(vtermno, &len, buf); | 183 | rc = opal_console_read(vtermno, &len, buf); |
177 | if (rc == OPAL_SUCCESS) | 184 | if (rc == OPAL_SUCCESS) |
178 | return len; | 185 | return be64_to_cpu(len); |
179 | return 0; | 186 | return 0; |
180 | } | 187 | } |
181 | 188 | ||
182 | int opal_put_chars(uint32_t vtermno, const char *data, int total_len) | 189 | int opal_put_chars(uint32_t vtermno, const char *data, int total_len) |
183 | { | 190 | { |
184 | int written = 0; | 191 | int written = 0; |
192 | __be64 olen; | ||
185 | s64 len, rc; | 193 | s64 len, rc; |
186 | unsigned long flags; | 194 | unsigned long flags; |
187 | u64 evt; | 195 | __be64 evt; |
188 | 196 | ||
189 | if (!opal.entry) | 197 | if (!opal.entry) |
190 | return -ENODEV; | 198 | return -ENODEV; |
@@ -199,13 +207,14 @@ int opal_put_chars(uint32_t vtermno, const char *data, int total_len) | |||
199 | */ | 207 | */ |
200 | spin_lock_irqsave(&opal_write_lock, flags); | 208 | spin_lock_irqsave(&opal_write_lock, flags); |
201 | if (firmware_has_feature(FW_FEATURE_OPALv2)) { | 209 | if (firmware_has_feature(FW_FEATURE_OPALv2)) { |
202 | rc = opal_console_write_buffer_space(vtermno, &len); | 210 | rc = opal_console_write_buffer_space(vtermno, &olen); |
211 | len = be64_to_cpu(olen); | ||
203 | if (rc || len < total_len) { | 212 | if (rc || len < total_len) { |
204 | spin_unlock_irqrestore(&opal_write_lock, flags); | 213 | spin_unlock_irqrestore(&opal_write_lock, flags); |
205 | /* Closed -> drop characters */ | 214 | /* Closed -> drop characters */ |
206 | if (rc) | 215 | if (rc) |
207 | return total_len; | 216 | return total_len; |
208 | opal_poll_events(&evt); | 217 | opal_poll_events(NULL); |
209 | return -EAGAIN; | 218 | return -EAGAIN; |
210 | } | 219 | } |
211 | } | 220 | } |
@@ -216,8 +225,9 @@ int opal_put_chars(uint32_t vtermno, const char *data, int total_len) | |||
216 | rc = OPAL_BUSY; | 225 | rc = OPAL_BUSY; |
217 | while(total_len > 0 && (rc == OPAL_BUSY || | 226 | while(total_len > 0 && (rc == OPAL_BUSY || |
218 | rc == OPAL_BUSY_EVENT || rc == OPAL_SUCCESS)) { | 227 | rc == OPAL_BUSY_EVENT || rc == OPAL_SUCCESS)) { |
219 | len = total_len; | 228 | olen = cpu_to_be64(total_len); |
220 | rc = opal_console_write(vtermno, &len, data); | 229 | rc = opal_console_write(vtermno, &olen, data); |
230 | len = be64_to_cpu(olen); | ||
221 | 231 | ||
222 | /* Closed or other error drop */ | 232 | /* Closed or other error drop */ |
223 | if (rc != OPAL_SUCCESS && rc != OPAL_BUSY && | 233 | if (rc != OPAL_SUCCESS && rc != OPAL_BUSY && |
@@ -237,7 +247,8 @@ int opal_put_chars(uint32_t vtermno, const char *data, int total_len) | |||
237 | */ | 247 | */ |
238 | do | 248 | do |
239 | opal_poll_events(&evt); | 249 | opal_poll_events(&evt); |
240 | while(rc == OPAL_SUCCESS && (evt & OPAL_EVENT_CONSOLE_OUTPUT)); | 250 | while(rc == OPAL_SUCCESS && |
251 | (be64_to_cpu(evt) & OPAL_EVENT_CONSOLE_OUTPUT)); | ||
241 | } | 252 | } |
242 | spin_unlock_irqrestore(&opal_write_lock, flags); | 253 | spin_unlock_irqrestore(&opal_write_lock, flags); |
243 | return written; | 254 | return written; |
@@ -360,7 +371,7 @@ int opal_machine_check(struct pt_regs *regs) | |||
360 | 371 | ||
361 | static irqreturn_t opal_interrupt(int irq, void *data) | 372 | static irqreturn_t opal_interrupt(int irq, void *data) |
362 | { | 373 | { |
363 | uint64_t events; | 374 | __be64 events; |
364 | 375 | ||
365 | opal_handle_interrupt(virq_to_hw(irq), &events); | 376 | opal_handle_interrupt(virq_to_hw(irq), &events); |
366 | 377 | ||
@@ -369,10 +380,21 @@ static irqreturn_t opal_interrupt(int irq, void *data) | |||
369 | return IRQ_HANDLED; | 380 | return IRQ_HANDLED; |
370 | } | 381 | } |
371 | 382 | ||
383 | static int opal_sysfs_init(void) | ||
384 | { | ||
385 | opal_kobj = kobject_create_and_add("opal", firmware_kobj); | ||
386 | if (!opal_kobj) { | ||
387 | pr_warn("kobject_create_and_add opal failed\n"); | ||
388 | return -ENOMEM; | ||
389 | } | ||
390 | |||
391 | return 0; | ||
392 | } | ||
393 | |||
372 | static int __init opal_init(void) | 394 | static int __init opal_init(void) |
373 | { | 395 | { |
374 | struct device_node *np, *consoles; | 396 | struct device_node *np, *consoles; |
375 | const u32 *irqs; | 397 | const __be32 *irqs; |
376 | int rc, i, irqlen; | 398 | int rc, i, irqlen; |
377 | 399 | ||
378 | opal_node = of_find_node_by_path("/ibm,opal"); | 400 | opal_node = of_find_node_by_path("/ibm,opal"); |
@@ -414,6 +436,14 @@ static int __init opal_init(void) | |||
414 | " (0x%x)\n", rc, irq, hwirq); | 436 | " (0x%x)\n", rc, irq, hwirq); |
415 | opal_irqs[i] = irq; | 437 | opal_irqs[i] = irq; |
416 | } | 438 | } |
439 | |||
440 | /* Create "opal" kobject under /sys/firmware */ | ||
441 | rc = opal_sysfs_init(); | ||
442 | if (rc == 0) { | ||
443 | /* Setup code update interface */ | ||
444 | opal_flash_init(); | ||
445 | } | ||
446 | |||
417 | return 0; | 447 | return 0; |
418 | } | 448 | } |
419 | subsys_initcall(opal_init); | 449 | subsys_initcall(opal_init); |
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index 74a5a5773b1f..084cdfa40682 100644 --- a/arch/powerpc/platforms/powernv/pci-ioda.c +++ b/arch/powerpc/platforms/powernv/pci-ioda.c | |||
@@ -70,6 +70,16 @@ define_pe_printk_level(pe_err, KERN_ERR); | |||
70 | define_pe_printk_level(pe_warn, KERN_WARNING); | 70 | define_pe_printk_level(pe_warn, KERN_WARNING); |
71 | define_pe_printk_level(pe_info, KERN_INFO); | 71 | define_pe_printk_level(pe_info, KERN_INFO); |
72 | 72 | ||
73 | /* | ||
74 | * stdcix is only supposed to be used in hypervisor real mode as per | ||
75 | * the architecture spec | ||
76 | */ | ||
77 | static inline void __raw_rm_writeq(u64 val, volatile void __iomem *paddr) | ||
78 | { | ||
79 | __asm__ __volatile__("stdcix %0,0,%1" | ||
80 | : : "r" (val), "r" (paddr) : "memory"); | ||
81 | } | ||
82 | |||
73 | static int pnv_ioda_alloc_pe(struct pnv_phb *phb) | 83 | static int pnv_ioda_alloc_pe(struct pnv_phb *phb) |
74 | { | 84 | { |
75 | unsigned long pe; | 85 | unsigned long pe; |
@@ -153,13 +163,23 @@ static int pnv_ioda_configure_pe(struct pnv_phb *phb, struct pnv_ioda_pe *pe) | |||
153 | rid_end = pe->rid + 1; | 163 | rid_end = pe->rid + 1; |
154 | } | 164 | } |
155 | 165 | ||
156 | /* Associate PE in PELT */ | 166 | /* |
167 | * Associate PE in PELT. We need add the PE into the | ||
168 | * corresponding PELT-V as well. Otherwise, the error | ||
169 | * originated from the PE might contribute to other | ||
170 | * PEs. | ||
171 | */ | ||
157 | rc = opal_pci_set_pe(phb->opal_id, pe->pe_number, pe->rid, | 172 | rc = opal_pci_set_pe(phb->opal_id, pe->pe_number, pe->rid, |
158 | bcomp, dcomp, fcomp, OPAL_MAP_PE); | 173 | bcomp, dcomp, fcomp, OPAL_MAP_PE); |
159 | if (rc) { | 174 | if (rc) { |
160 | pe_err(pe, "OPAL error %ld trying to setup PELT table\n", rc); | 175 | pe_err(pe, "OPAL error %ld trying to setup PELT table\n", rc); |
161 | return -ENXIO; | 176 | return -ENXIO; |
162 | } | 177 | } |
178 | |||
179 | rc = opal_pci_set_peltv(phb->opal_id, pe->pe_number, | ||
180 | pe->pe_number, OPAL_ADD_PE_TO_DOMAIN); | ||
181 | if (rc) | ||
182 | pe_warn(pe, "OPAL error %d adding self to PELTV\n", rc); | ||
163 | opal_pci_eeh_freeze_clear(phb->opal_id, pe->pe_number, | 183 | opal_pci_eeh_freeze_clear(phb->opal_id, pe->pe_number, |
164 | OPAL_EEH_ACTION_CLEAR_FREEZE_ALL); | 184 | OPAL_EEH_ACTION_CLEAR_FREEZE_ALL); |
165 | 185 | ||
@@ -454,10 +474,13 @@ static void pnv_ioda_setup_bus_dma(struct pnv_ioda_pe *pe, struct pci_bus *bus) | |||
454 | } | 474 | } |
455 | } | 475 | } |
456 | 476 | ||
457 | static void pnv_pci_ioda1_tce_invalidate(struct iommu_table *tbl, | 477 | static void pnv_pci_ioda1_tce_invalidate(struct pnv_ioda_pe *pe, |
458 | u64 *startp, u64 *endp) | 478 | struct iommu_table *tbl, |
479 | __be64 *startp, __be64 *endp, bool rm) | ||
459 | { | 480 | { |
460 | u64 __iomem *invalidate = (u64 __iomem *)tbl->it_index; | 481 | __be64 __iomem *invalidate = rm ? |
482 | (__be64 __iomem *)pe->tce_inval_reg_phys : | ||
483 | (__be64 __iomem *)tbl->it_index; | ||
461 | unsigned long start, end, inc; | 484 | unsigned long start, end, inc; |
462 | 485 | ||
463 | start = __pa(startp); | 486 | start = __pa(startp); |
@@ -484,7 +507,10 @@ static void pnv_pci_ioda1_tce_invalidate(struct iommu_table *tbl, | |||
484 | 507 | ||
485 | mb(); /* Ensure above stores are visible */ | 508 | mb(); /* Ensure above stores are visible */ |
486 | while (start <= end) { | 509 | while (start <= end) { |
487 | __raw_writeq(start, invalidate); | 510 | if (rm) |
511 | __raw_rm_writeq(cpu_to_be64(start), invalidate); | ||
512 | else | ||
513 | __raw_writeq(cpu_to_be64(start), invalidate); | ||
488 | start += inc; | 514 | start += inc; |
489 | } | 515 | } |
490 | 516 | ||
@@ -496,10 +522,12 @@ static void pnv_pci_ioda1_tce_invalidate(struct iommu_table *tbl, | |||
496 | 522 | ||
497 | static void pnv_pci_ioda2_tce_invalidate(struct pnv_ioda_pe *pe, | 523 | static void pnv_pci_ioda2_tce_invalidate(struct pnv_ioda_pe *pe, |
498 | struct iommu_table *tbl, | 524 | struct iommu_table *tbl, |
499 | u64 *startp, u64 *endp) | 525 | __be64 *startp, __be64 *endp, bool rm) |
500 | { | 526 | { |
501 | unsigned long start, end, inc; | 527 | unsigned long start, end, inc; |
502 | u64 __iomem *invalidate = (u64 __iomem *)tbl->it_index; | 528 | __be64 __iomem *invalidate = rm ? |
529 | (__be64 __iomem *)pe->tce_inval_reg_phys : | ||
530 | (__be64 __iomem *)tbl->it_index; | ||
503 | 531 | ||
504 | /* We'll invalidate DMA address in PE scope */ | 532 | /* We'll invalidate DMA address in PE scope */ |
505 | start = 0x2ul << 60; | 533 | start = 0x2ul << 60; |
@@ -515,22 +543,25 @@ static void pnv_pci_ioda2_tce_invalidate(struct pnv_ioda_pe *pe, | |||
515 | mb(); | 543 | mb(); |
516 | 544 | ||
517 | while (start <= end) { | 545 | while (start <= end) { |
518 | __raw_writeq(start, invalidate); | 546 | if (rm) |
547 | __raw_rm_writeq(cpu_to_be64(start), invalidate); | ||
548 | else | ||
549 | __raw_writeq(cpu_to_be64(start), invalidate); | ||
519 | start += inc; | 550 | start += inc; |
520 | } | 551 | } |
521 | } | 552 | } |
522 | 553 | ||
523 | void pnv_pci_ioda_tce_invalidate(struct iommu_table *tbl, | 554 | void pnv_pci_ioda_tce_invalidate(struct iommu_table *tbl, |
524 | u64 *startp, u64 *endp) | 555 | __be64 *startp, __be64 *endp, bool rm) |
525 | { | 556 | { |
526 | struct pnv_ioda_pe *pe = container_of(tbl, struct pnv_ioda_pe, | 557 | struct pnv_ioda_pe *pe = container_of(tbl, struct pnv_ioda_pe, |
527 | tce32_table); | 558 | tce32_table); |
528 | struct pnv_phb *phb = pe->phb; | 559 | struct pnv_phb *phb = pe->phb; |
529 | 560 | ||
530 | if (phb->type == PNV_PHB_IODA1) | 561 | if (phb->type == PNV_PHB_IODA1) |
531 | pnv_pci_ioda1_tce_invalidate(tbl, startp, endp); | 562 | pnv_pci_ioda1_tce_invalidate(pe, tbl, startp, endp, rm); |
532 | else | 563 | else |
533 | pnv_pci_ioda2_tce_invalidate(pe, tbl, startp, endp); | 564 | pnv_pci_ioda2_tce_invalidate(pe, tbl, startp, endp, rm); |
534 | } | 565 | } |
535 | 566 | ||
536 | static void pnv_pci_ioda_setup_dma_pe(struct pnv_phb *phb, | 567 | static void pnv_pci_ioda_setup_dma_pe(struct pnv_phb *phb, |
@@ -603,7 +634,9 @@ static void pnv_pci_ioda_setup_dma_pe(struct pnv_phb *phb, | |||
603 | * bus number, print that out instead. | 634 | * bus number, print that out instead. |
604 | */ | 635 | */ |
605 | tbl->it_busno = 0; | 636 | tbl->it_busno = 0; |
606 | tbl->it_index = (unsigned long)ioremap(be64_to_cpup(swinvp), 8); | 637 | pe->tce_inval_reg_phys = be64_to_cpup(swinvp); |
638 | tbl->it_index = (unsigned long)ioremap(pe->tce_inval_reg_phys, | ||
639 | 8); | ||
607 | tbl->it_type = TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE | | 640 | tbl->it_type = TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE | |
608 | TCE_PCI_SWINV_PAIR; | 641 | TCE_PCI_SWINV_PAIR; |
609 | } | 642 | } |
@@ -681,7 +714,9 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb, | |||
681 | * bus number, print that out instead. | 714 | * bus number, print that out instead. |
682 | */ | 715 | */ |
683 | tbl->it_busno = 0; | 716 | tbl->it_busno = 0; |
684 | tbl->it_index = (unsigned long)ioremap(be64_to_cpup(swinvp), 8); | 717 | pe->tce_inval_reg_phys = be64_to_cpup(swinvp); |
718 | tbl->it_index = (unsigned long)ioremap(pe->tce_inval_reg_phys, | ||
719 | 8); | ||
685 | tbl->it_type = TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE; | 720 | tbl->it_type = TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE; |
686 | } | 721 | } |
687 | iommu_init_table(tbl, phb->hose->node); | 722 | iommu_init_table(tbl, phb->hose->node); |
@@ -786,8 +821,7 @@ static int pnv_pci_ioda_msi_setup(struct pnv_phb *phb, struct pci_dev *dev, | |||
786 | struct irq_data *idata; | 821 | struct irq_data *idata; |
787 | struct irq_chip *ichip; | 822 | struct irq_chip *ichip; |
788 | unsigned int xive_num = hwirq - phb->msi_base; | 823 | unsigned int xive_num = hwirq - phb->msi_base; |
789 | uint64_t addr64; | 824 | __be32 data; |
790 | uint32_t addr32, data; | ||
791 | int rc; | 825 | int rc; |
792 | 826 | ||
793 | /* No PE assigned ? bail out ... no MSI for you ! */ | 827 | /* No PE assigned ? bail out ... no MSI for you ! */ |
@@ -811,6 +845,8 @@ static int pnv_pci_ioda_msi_setup(struct pnv_phb *phb, struct pci_dev *dev, | |||
811 | } | 845 | } |
812 | 846 | ||
813 | if (is_64) { | 847 | if (is_64) { |
848 | __be64 addr64; | ||
849 | |||
814 | rc = opal_get_msi_64(phb->opal_id, pe->mve_number, xive_num, 1, | 850 | rc = opal_get_msi_64(phb->opal_id, pe->mve_number, xive_num, 1, |
815 | &addr64, &data); | 851 | &addr64, &data); |
816 | if (rc) { | 852 | if (rc) { |
@@ -818,9 +854,11 @@ static int pnv_pci_ioda_msi_setup(struct pnv_phb *phb, struct pci_dev *dev, | |||
818 | pci_name(dev), rc); | 854 | pci_name(dev), rc); |
819 | return -EIO; | 855 | return -EIO; |
820 | } | 856 | } |
821 | msg->address_hi = addr64 >> 32; | 857 | msg->address_hi = be64_to_cpu(addr64) >> 32; |
822 | msg->address_lo = addr64 & 0xfffffffful; | 858 | msg->address_lo = be64_to_cpu(addr64) & 0xfffffffful; |
823 | } else { | 859 | } else { |
860 | __be32 addr32; | ||
861 | |||
824 | rc = opal_get_msi_32(phb->opal_id, pe->mve_number, xive_num, 1, | 862 | rc = opal_get_msi_32(phb->opal_id, pe->mve_number, xive_num, 1, |
825 | &addr32, &data); | 863 | &addr32, &data); |
826 | if (rc) { | 864 | if (rc) { |
@@ -829,9 +867,9 @@ static int pnv_pci_ioda_msi_setup(struct pnv_phb *phb, struct pci_dev *dev, | |||
829 | return -EIO; | 867 | return -EIO; |
830 | } | 868 | } |
831 | msg->address_hi = 0; | 869 | msg->address_hi = 0; |
832 | msg->address_lo = addr32; | 870 | msg->address_lo = be32_to_cpu(addr32); |
833 | } | 871 | } |
834 | msg->data = data; | 872 | msg->data = be32_to_cpu(data); |
835 | 873 | ||
836 | /* | 874 | /* |
837 | * Change the IRQ chip for the MSI interrupts on PHB3. | 875 | * Change the IRQ chip for the MSI interrupts on PHB3. |
@@ -1106,8 +1144,8 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np, | |||
1106 | struct pci_controller *hose; | 1144 | struct pci_controller *hose; |
1107 | struct pnv_phb *phb; | 1145 | struct pnv_phb *phb; |
1108 | unsigned long size, m32map_off, iomap_off, pemap_off; | 1146 | unsigned long size, m32map_off, iomap_off, pemap_off; |
1109 | const u64 *prop64; | 1147 | const __be64 *prop64; |
1110 | const u32 *prop32; | 1148 | const __be32 *prop32; |
1111 | int len; | 1149 | int len; |
1112 | u64 phb_id; | 1150 | u64 phb_id; |
1113 | void *aux; | 1151 | void *aux; |
@@ -1142,8 +1180,8 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np, | |||
1142 | spin_lock_init(&phb->lock); | 1180 | spin_lock_init(&phb->lock); |
1143 | prop32 = of_get_property(np, "bus-range", &len); | 1181 | prop32 = of_get_property(np, "bus-range", &len); |
1144 | if (prop32 && len == 8) { | 1182 | if (prop32 && len == 8) { |
1145 | hose->first_busno = prop32[0]; | 1183 | hose->first_busno = be32_to_cpu(prop32[0]); |
1146 | hose->last_busno = prop32[1]; | 1184 | hose->last_busno = be32_to_cpu(prop32[1]); |
1147 | } else { | 1185 | } else { |
1148 | pr_warn(" Broken <bus-range> on %s\n", np->full_name); | 1186 | pr_warn(" Broken <bus-range> on %s\n", np->full_name); |
1149 | hose->first_busno = 0; | 1187 | hose->first_busno = 0; |
@@ -1171,12 +1209,13 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np, | |||
1171 | pr_err(" Failed to map registers !\n"); | 1209 | pr_err(" Failed to map registers !\n"); |
1172 | 1210 | ||
1173 | /* Initialize more IODA stuff */ | 1211 | /* Initialize more IODA stuff */ |
1212 | phb->ioda.total_pe = 1; | ||
1174 | prop32 = of_get_property(np, "ibm,opal-num-pes", NULL); | 1213 | prop32 = of_get_property(np, "ibm,opal-num-pes", NULL); |
1175 | if (!prop32) | 1214 | if (prop32) |
1176 | phb->ioda.total_pe = 1; | 1215 | phb->ioda.total_pe = be32_to_cpup(prop32); |
1177 | else | 1216 | prop32 = of_get_property(np, "ibm,opal-reserved-pe", NULL); |
1178 | phb->ioda.total_pe = *prop32; | 1217 | if (prop32) |
1179 | 1218 | phb->ioda.reserved_pe = be32_to_cpup(prop32); | |
1180 | phb->ioda.m32_size = resource_size(&hose->mem_resources[0]); | 1219 | phb->ioda.m32_size = resource_size(&hose->mem_resources[0]); |
1181 | /* FW Has already off top 64k of M32 space (MSI space) */ | 1220 | /* FW Has already off top 64k of M32 space (MSI space) */ |
1182 | phb->ioda.m32_size += 0x10000; | 1221 | phb->ioda.m32_size += 0x10000; |
@@ -1205,7 +1244,7 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np, | |||
1205 | if (phb->type == PNV_PHB_IODA1) | 1244 | if (phb->type == PNV_PHB_IODA1) |
1206 | phb->ioda.io_segmap = aux + iomap_off; | 1245 | phb->ioda.io_segmap = aux + iomap_off; |
1207 | phb->ioda.pe_array = aux + pemap_off; | 1246 | phb->ioda.pe_array = aux + pemap_off; |
1208 | set_bit(0, phb->ioda.pe_alloc); | 1247 | set_bit(phb->ioda.reserved_pe, phb->ioda.pe_alloc); |
1209 | 1248 | ||
1210 | INIT_LIST_HEAD(&phb->ioda.pe_dma_list); | 1249 | INIT_LIST_HEAD(&phb->ioda.pe_dma_list); |
1211 | INIT_LIST_HEAD(&phb->ioda.pe_list); | 1250 | INIT_LIST_HEAD(&phb->ioda.pe_list); |
@@ -1230,8 +1269,10 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np, | |||
1230 | segment_size); | 1269 | segment_size); |
1231 | #endif | 1270 | #endif |
1232 | 1271 | ||
1233 | pr_info(" %d PE's M32: 0x%x [segment=0x%x] IO: 0x%x [segment=0x%x]\n", | 1272 | pr_info(" %d (%d) PE's M32: 0x%x [segment=0x%x]" |
1273 | " IO: 0x%x [segment=0x%x]\n", | ||
1234 | phb->ioda.total_pe, | 1274 | phb->ioda.total_pe, |
1275 | phb->ioda.reserved_pe, | ||
1235 | phb->ioda.m32_size, phb->ioda.m32_segsize, | 1276 | phb->ioda.m32_size, phb->ioda.m32_segsize, |
1236 | phb->ioda.io_size, phb->ioda.io_segsize); | 1277 | phb->ioda.io_size, phb->ioda.io_segsize); |
1237 | 1278 | ||
@@ -1268,13 +1309,6 @@ void __init pnv_pci_init_ioda_phb(struct device_node *np, | |||
1268 | rc = opal_pci_reset(phb_id, OPAL_PCI_IODA_TABLE_RESET, OPAL_ASSERT_RESET); | 1309 | rc = opal_pci_reset(phb_id, OPAL_PCI_IODA_TABLE_RESET, OPAL_ASSERT_RESET); |
1269 | if (rc) | 1310 | if (rc) |
1270 | pr_warning(" OPAL Error %ld performing IODA table reset !\n", rc); | 1311 | pr_warning(" OPAL Error %ld performing IODA table reset !\n", rc); |
1271 | |||
1272 | /* | ||
1273 | * On IODA1 map everything to PE#0, on IODA2 we assume the IODA reset | ||
1274 | * has cleared the RTT which has the same effect | ||
1275 | */ | ||
1276 | if (ioda_type == PNV_PHB_IODA1) | ||
1277 | opal_pci_set_pe(phb_id, 0, 0, 7, 1, 1 , OPAL_MAP_PE); | ||
1278 | } | 1312 | } |
1279 | 1313 | ||
1280 | void __init pnv_pci_init_ioda2_phb(struct device_node *np) | 1314 | void __init pnv_pci_init_ioda2_phb(struct device_node *np) |
@@ -1285,7 +1319,7 @@ void __init pnv_pci_init_ioda2_phb(struct device_node *np) | |||
1285 | void __init pnv_pci_init_ioda_hub(struct device_node *np) | 1319 | void __init pnv_pci_init_ioda_hub(struct device_node *np) |
1286 | { | 1320 | { |
1287 | struct device_node *phbn; | 1321 | struct device_node *phbn; |
1288 | const u64 *prop64; | 1322 | const __be64 *prop64; |
1289 | u64 hub_id; | 1323 | u64 hub_id; |
1290 | 1324 | ||
1291 | pr_info("Probing IODA IO-Hub %s\n", np->full_name); | 1325 | pr_info("Probing IODA IO-Hub %s\n", np->full_name); |
diff --git a/arch/powerpc/platforms/powernv/pci-p5ioc2.c b/arch/powerpc/platforms/powernv/pci-p5ioc2.c index b68db6325c1b..f8b4bd8afb2e 100644 --- a/arch/powerpc/platforms/powernv/pci-p5ioc2.c +++ b/arch/powerpc/platforms/powernv/pci-p5ioc2.c | |||
@@ -99,7 +99,7 @@ static void __init pnv_pci_init_p5ioc2_phb(struct device_node *np, u64 hub_id, | |||
99 | void *tce_mem, u64 tce_size) | 99 | void *tce_mem, u64 tce_size) |
100 | { | 100 | { |
101 | struct pnv_phb *phb; | 101 | struct pnv_phb *phb; |
102 | const u64 *prop64; | 102 | const __be64 *prop64; |
103 | u64 phb_id; | 103 | u64 phb_id; |
104 | int64_t rc; | 104 | int64_t rc; |
105 | static int primary = 1; | 105 | static int primary = 1; |
@@ -178,7 +178,7 @@ static void __init pnv_pci_init_p5ioc2_phb(struct device_node *np, u64 hub_id, | |||
178 | void __init pnv_pci_init_p5ioc2_hub(struct device_node *np) | 178 | void __init pnv_pci_init_p5ioc2_hub(struct device_node *np) |
179 | { | 179 | { |
180 | struct device_node *phbn; | 180 | struct device_node *phbn; |
181 | const u64 *prop64; | 181 | const __be64 *prop64; |
182 | u64 hub_id; | 182 | u64 hub_id; |
183 | void *tce_mem; | 183 | void *tce_mem; |
184 | uint64_t tce_per_phb; | 184 | uint64_t tce_per_phb; |
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c index a28d3b5e6393..4eb33a9ed532 100644 --- a/arch/powerpc/platforms/powernv/pci.c +++ b/arch/powerpc/platforms/powernv/pci.c | |||
@@ -236,17 +236,21 @@ static void pnv_pci_config_check_eeh(struct pnv_phb *phb, | |||
236 | { | 236 | { |
237 | s64 rc; | 237 | s64 rc; |
238 | u8 fstate; | 238 | u8 fstate; |
239 | u16 pcierr; | 239 | __be16 pcierr; |
240 | u32 pe_no; | 240 | u32 pe_no; |
241 | 241 | ||
242 | /* | 242 | /* |
243 | * Get the PE#. During the PCI probe stage, we might not | 243 | * Get the PE#. During the PCI probe stage, we might not |
244 | * setup that yet. So all ER errors should be mapped to | 244 | * setup that yet. So all ER errors should be mapped to |
245 | * PE#0 | 245 | * reserved PE. |
246 | */ | 246 | */ |
247 | pe_no = PCI_DN(dn)->pe_number; | 247 | pe_no = PCI_DN(dn)->pe_number; |
248 | if (pe_no == IODA_INVALID_PE) | 248 | if (pe_no == IODA_INVALID_PE) { |
249 | pe_no = 0; | 249 | if (phb->type == PNV_PHB_P5IOC2) |
250 | pe_no = 0; | ||
251 | else | ||
252 | pe_no = phb->ioda.reserved_pe; | ||
253 | } | ||
250 | 254 | ||
251 | /* Read freeze status */ | 255 | /* Read freeze status */ |
252 | rc = opal_pci_eeh_freeze_status(phb->opal_id, pe_no, &fstate, &pcierr, | 256 | rc = opal_pci_eeh_freeze_status(phb->opal_id, pe_no, &fstate, &pcierr, |
@@ -283,16 +287,16 @@ int pnv_pci_cfg_read(struct device_node *dn, | |||
283 | break; | 287 | break; |
284 | } | 288 | } |
285 | case 2: { | 289 | case 2: { |
286 | u16 v16; | 290 | __be16 v16; |
287 | rc = opal_pci_config_read_half_word(phb->opal_id, bdfn, where, | 291 | rc = opal_pci_config_read_half_word(phb->opal_id, bdfn, where, |
288 | &v16); | 292 | &v16); |
289 | *val = (rc == OPAL_SUCCESS) ? v16 : 0xffff; | 293 | *val = (rc == OPAL_SUCCESS) ? be16_to_cpu(v16) : 0xffff; |
290 | break; | 294 | break; |
291 | } | 295 | } |
292 | case 4: { | 296 | case 4: { |
293 | u32 v32; | 297 | __be32 v32; |
294 | rc = opal_pci_config_read_word(phb->opal_id, bdfn, where, &v32); | 298 | rc = opal_pci_config_read_word(phb->opal_id, bdfn, where, &v32); |
295 | *val = (rc == OPAL_SUCCESS) ? v32 : 0xffffffff; | 299 | *val = (rc == OPAL_SUCCESS) ? be32_to_cpu(v32) : 0xffffffff; |
296 | break; | 300 | break; |
297 | } | 301 | } |
298 | default: | 302 | default: |
@@ -401,10 +405,10 @@ struct pci_ops pnv_pci_ops = { | |||
401 | 405 | ||
402 | static int pnv_tce_build(struct iommu_table *tbl, long index, long npages, | 406 | static int pnv_tce_build(struct iommu_table *tbl, long index, long npages, |
403 | unsigned long uaddr, enum dma_data_direction direction, | 407 | unsigned long uaddr, enum dma_data_direction direction, |
404 | struct dma_attrs *attrs) | 408 | struct dma_attrs *attrs, bool rm) |
405 | { | 409 | { |
406 | u64 proto_tce; | 410 | u64 proto_tce; |
407 | u64 *tcep, *tces; | 411 | __be64 *tcep, *tces; |
408 | u64 rpn; | 412 | u64 rpn; |
409 | 413 | ||
410 | proto_tce = TCE_PCI_READ; // Read allowed | 414 | proto_tce = TCE_PCI_READ; // Read allowed |
@@ -412,33 +416,48 @@ static int pnv_tce_build(struct iommu_table *tbl, long index, long npages, | |||
412 | if (direction != DMA_TO_DEVICE) | 416 | if (direction != DMA_TO_DEVICE) |
413 | proto_tce |= TCE_PCI_WRITE; | 417 | proto_tce |= TCE_PCI_WRITE; |
414 | 418 | ||
415 | tces = tcep = ((u64 *)tbl->it_base) + index - tbl->it_offset; | 419 | tces = tcep = ((__be64 *)tbl->it_base) + index - tbl->it_offset; |
416 | rpn = __pa(uaddr) >> TCE_SHIFT; | 420 | rpn = __pa(uaddr) >> TCE_SHIFT; |
417 | 421 | ||
418 | while (npages--) | 422 | while (npages--) |
419 | *(tcep++) = proto_tce | (rpn++ << TCE_RPN_SHIFT); | 423 | *(tcep++) = cpu_to_be64(proto_tce | (rpn++ << TCE_RPN_SHIFT)); |
420 | 424 | ||
421 | /* Some implementations won't cache invalid TCEs and thus may not | 425 | /* Some implementations won't cache invalid TCEs and thus may not |
422 | * need that flush. We'll probably turn it_type into a bit mask | 426 | * need that flush. We'll probably turn it_type into a bit mask |
423 | * of flags if that becomes the case | 427 | * of flags if that becomes the case |
424 | */ | 428 | */ |
425 | if (tbl->it_type & TCE_PCI_SWINV_CREATE) | 429 | if (tbl->it_type & TCE_PCI_SWINV_CREATE) |
426 | pnv_pci_ioda_tce_invalidate(tbl, tces, tcep - 1); | 430 | pnv_pci_ioda_tce_invalidate(tbl, tces, tcep - 1, rm); |
427 | 431 | ||
428 | return 0; | 432 | return 0; |
429 | } | 433 | } |
430 | 434 | ||
431 | static void pnv_tce_free(struct iommu_table *tbl, long index, long npages) | 435 | static int pnv_tce_build_vm(struct iommu_table *tbl, long index, long npages, |
436 | unsigned long uaddr, | ||
437 | enum dma_data_direction direction, | ||
438 | struct dma_attrs *attrs) | ||
432 | { | 439 | { |
433 | u64 *tcep, *tces; | 440 | return pnv_tce_build(tbl, index, npages, uaddr, direction, attrs, |
441 | false); | ||
442 | } | ||
434 | 443 | ||
435 | tces = tcep = ((u64 *)tbl->it_base) + index - tbl->it_offset; | 444 | static void pnv_tce_free(struct iommu_table *tbl, long index, long npages, |
445 | bool rm) | ||
446 | { | ||
447 | __be64 *tcep, *tces; | ||
448 | |||
449 | tces = tcep = ((__be64 *)tbl->it_base) + index - tbl->it_offset; | ||
436 | 450 | ||
437 | while (npages--) | 451 | while (npages--) |
438 | *(tcep++) = 0; | 452 | *(tcep++) = cpu_to_be64(0); |
439 | 453 | ||
440 | if (tbl->it_type & TCE_PCI_SWINV_FREE) | 454 | if (tbl->it_type & TCE_PCI_SWINV_FREE) |
441 | pnv_pci_ioda_tce_invalidate(tbl, tces, tcep - 1); | 455 | pnv_pci_ioda_tce_invalidate(tbl, tces, tcep - 1, rm); |
456 | } | ||
457 | |||
458 | static void pnv_tce_free_vm(struct iommu_table *tbl, long index, long npages) | ||
459 | { | ||
460 | pnv_tce_free(tbl, index, npages, false); | ||
442 | } | 461 | } |
443 | 462 | ||
444 | static unsigned long pnv_tce_get(struct iommu_table *tbl, long index) | 463 | static unsigned long pnv_tce_get(struct iommu_table *tbl, long index) |
@@ -446,6 +465,19 @@ static unsigned long pnv_tce_get(struct iommu_table *tbl, long index) | |||
446 | return ((u64 *)tbl->it_base)[index - tbl->it_offset]; | 465 | return ((u64 *)tbl->it_base)[index - tbl->it_offset]; |
447 | } | 466 | } |
448 | 467 | ||
468 | static int pnv_tce_build_rm(struct iommu_table *tbl, long index, long npages, | ||
469 | unsigned long uaddr, | ||
470 | enum dma_data_direction direction, | ||
471 | struct dma_attrs *attrs) | ||
472 | { | ||
473 | return pnv_tce_build(tbl, index, npages, uaddr, direction, attrs, true); | ||
474 | } | ||
475 | |||
476 | static void pnv_tce_free_rm(struct iommu_table *tbl, long index, long npages) | ||
477 | { | ||
478 | pnv_tce_free(tbl, index, npages, true); | ||
479 | } | ||
480 | |||
449 | void pnv_pci_setup_iommu_table(struct iommu_table *tbl, | 481 | void pnv_pci_setup_iommu_table(struct iommu_table *tbl, |
450 | void *tce_mem, u64 tce_size, | 482 | void *tce_mem, u64 tce_size, |
451 | u64 dma_offset) | 483 | u64 dma_offset) |
@@ -484,8 +516,8 @@ static struct iommu_table *pnv_pci_setup_bml_iommu(struct pci_controller *hose) | |||
484 | swinvp = of_get_property(hose->dn, "linux,tce-sw-invalidate-info", | 516 | swinvp = of_get_property(hose->dn, "linux,tce-sw-invalidate-info", |
485 | NULL); | 517 | NULL); |
486 | if (swinvp) { | 518 | if (swinvp) { |
487 | tbl->it_busno = swinvp[1]; | 519 | tbl->it_busno = be64_to_cpu(swinvp[1]); |
488 | tbl->it_index = (unsigned long)ioremap(swinvp[0], 8); | 520 | tbl->it_index = (unsigned long)ioremap(be64_to_cpup(swinvp), 8); |
489 | tbl->it_type = TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE; | 521 | tbl->it_type = TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE; |
490 | } | 522 | } |
491 | return tbl; | 523 | return tbl; |
@@ -610,8 +642,10 @@ void __init pnv_pci_init(void) | |||
610 | 642 | ||
611 | /* Configure IOMMU DMA hooks */ | 643 | /* Configure IOMMU DMA hooks */ |
612 | ppc_md.pci_dma_dev_setup = pnv_pci_dma_dev_setup; | 644 | ppc_md.pci_dma_dev_setup = pnv_pci_dma_dev_setup; |
613 | ppc_md.tce_build = pnv_tce_build; | 645 | ppc_md.tce_build = pnv_tce_build_vm; |
614 | ppc_md.tce_free = pnv_tce_free; | 646 | ppc_md.tce_free = pnv_tce_free_vm; |
647 | ppc_md.tce_build_rm = pnv_tce_build_rm; | ||
648 | ppc_md.tce_free_rm = pnv_tce_free_rm; | ||
615 | ppc_md.tce_get = pnv_tce_get; | 649 | ppc_md.tce_get = pnv_tce_get; |
616 | ppc_md.pci_probe_mode = pnv_pci_probe_mode; | 650 | ppc_md.pci_probe_mode = pnv_pci_probe_mode; |
617 | set_pci_dma_ops(&dma_iommu_ops); | 651 | set_pci_dma_ops(&dma_iommu_ops); |
diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h index d633c64e05a1..911c24ef033e 100644 --- a/arch/powerpc/platforms/powernv/pci.h +++ b/arch/powerpc/platforms/powernv/pci.h | |||
@@ -17,7 +17,7 @@ enum pnv_phb_model { | |||
17 | PNV_PHB_MODEL_PHB3, | 17 | PNV_PHB_MODEL_PHB3, |
18 | }; | 18 | }; |
19 | 19 | ||
20 | #define PNV_PCI_DIAG_BUF_SIZE 4096 | 20 | #define PNV_PCI_DIAG_BUF_SIZE 8192 |
21 | #define PNV_IODA_PE_DEV (1 << 0) /* PE has single PCI device */ | 21 | #define PNV_IODA_PE_DEV (1 << 0) /* PE has single PCI device */ |
22 | #define PNV_IODA_PE_BUS (1 << 1) /* PE has primary PCI bus */ | 22 | #define PNV_IODA_PE_BUS (1 << 1) /* PE has primary PCI bus */ |
23 | #define PNV_IODA_PE_BUS_ALL (1 << 2) /* PE has subordinate buses */ | 23 | #define PNV_IODA_PE_BUS_ALL (1 << 2) /* PE has subordinate buses */ |
@@ -52,6 +52,7 @@ struct pnv_ioda_pe { | |||
52 | int tce32_seg; | 52 | int tce32_seg; |
53 | int tce32_segcount; | 53 | int tce32_segcount; |
54 | struct iommu_table tce32_table; | 54 | struct iommu_table tce32_table; |
55 | phys_addr_t tce_inval_reg_phys; | ||
55 | 56 | ||
56 | /* XXX TODO: Add support for additional 64-bit iommus */ | 57 | /* XXX TODO: Add support for additional 64-bit iommus */ |
57 | 58 | ||
@@ -124,6 +125,7 @@ struct pnv_phb { | |||
124 | struct { | 125 | struct { |
125 | /* Global bridge info */ | 126 | /* Global bridge info */ |
126 | unsigned int total_pe; | 127 | unsigned int total_pe; |
128 | unsigned int reserved_pe; | ||
127 | unsigned int m32_size; | 129 | unsigned int m32_size; |
128 | unsigned int m32_segsize; | 130 | unsigned int m32_segsize; |
129 | unsigned int m32_pci_base; | 131 | unsigned int m32_pci_base; |
@@ -193,6 +195,6 @@ extern void pnv_pci_init_p5ioc2_hub(struct device_node *np); | |||
193 | extern void pnv_pci_init_ioda_hub(struct device_node *np); | 195 | extern void pnv_pci_init_ioda_hub(struct device_node *np); |
194 | extern void pnv_pci_init_ioda2_phb(struct device_node *np); | 196 | extern void pnv_pci_init_ioda2_phb(struct device_node *np); |
195 | extern void pnv_pci_ioda_tce_invalidate(struct iommu_table *tbl, | 197 | extern void pnv_pci_ioda_tce_invalidate(struct iommu_table *tbl, |
196 | u64 *startp, u64 *endp); | 198 | __be64 *startp, __be64 *endp, bool rm); |
197 | 199 | ||
198 | #endif /* __POWERNV_PCI_H */ | 200 | #endif /* __POWERNV_PCI_H */ |
diff --git a/arch/powerpc/platforms/powernv/rng.c b/arch/powerpc/platforms/powernv/rng.c new file mode 100644 index 000000000000..8844628915dc --- /dev/null +++ b/arch/powerpc/platforms/powernv/rng.c | |||
@@ -0,0 +1,125 @@ | |||
1 | /* | ||
2 | * Copyright 2013, Michael Ellerman, IBM Corporation. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | */ | ||
9 | |||
10 | #define pr_fmt(fmt) "powernv-rng: " fmt | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/of.h> | ||
14 | #include <linux/of_address.h> | ||
15 | #include <linux/of_platform.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <linux/smp.h> | ||
18 | #include <asm/archrandom.h> | ||
19 | #include <asm/io.h> | ||
20 | #include <asm/prom.h> | ||
21 | #include <asm/machdep.h> | ||
22 | |||
23 | |||
24 | struct powernv_rng { | ||
25 | void __iomem *regs; | ||
26 | unsigned long mask; | ||
27 | }; | ||
28 | |||
29 | static DEFINE_PER_CPU(struct powernv_rng *, powernv_rng); | ||
30 | |||
31 | |||
32 | static unsigned long rng_whiten(struct powernv_rng *rng, unsigned long val) | ||
33 | { | ||
34 | unsigned long parity; | ||
35 | |||
36 | /* Calculate the parity of the value */ | ||
37 | asm ("popcntd %0,%1" : "=r" (parity) : "r" (val)); | ||
38 | |||
39 | /* xor our value with the previous mask */ | ||
40 | val ^= rng->mask; | ||
41 | |||
42 | /* update the mask based on the parity of this value */ | ||
43 | rng->mask = (rng->mask << 1) | (parity & 1); | ||
44 | |||
45 | return val; | ||
46 | } | ||
47 | |||
48 | int powernv_get_random_long(unsigned long *v) | ||
49 | { | ||
50 | struct powernv_rng *rng; | ||
51 | |||
52 | rng = get_cpu_var(powernv_rng); | ||
53 | |||
54 | *v = rng_whiten(rng, in_be64(rng->regs)); | ||
55 | |||
56 | put_cpu_var(rng); | ||
57 | |||
58 | return 1; | ||
59 | } | ||
60 | EXPORT_SYMBOL_GPL(powernv_get_random_long); | ||
61 | |||
62 | static __init void rng_init_per_cpu(struct powernv_rng *rng, | ||
63 | struct device_node *dn) | ||
64 | { | ||
65 | int chip_id, cpu; | ||
66 | |||
67 | chip_id = of_get_ibm_chip_id(dn); | ||
68 | if (chip_id == -1) | ||
69 | pr_warn("No ibm,chip-id found for %s.\n", dn->full_name); | ||
70 | |||
71 | for_each_possible_cpu(cpu) { | ||
72 | if (per_cpu(powernv_rng, cpu) == NULL || | ||
73 | cpu_to_chip_id(cpu) == chip_id) { | ||
74 | per_cpu(powernv_rng, cpu) = rng; | ||
75 | } | ||
76 | } | ||
77 | } | ||
78 | |||
79 | static __init int rng_create(struct device_node *dn) | ||
80 | { | ||
81 | struct powernv_rng *rng; | ||
82 | unsigned long val; | ||
83 | |||
84 | rng = kzalloc(sizeof(*rng), GFP_KERNEL); | ||
85 | if (!rng) | ||
86 | return -ENOMEM; | ||
87 | |||
88 | rng->regs = of_iomap(dn, 0); | ||
89 | if (!rng->regs) { | ||
90 | kfree(rng); | ||
91 | return -ENXIO; | ||
92 | } | ||
93 | |||
94 | val = in_be64(rng->regs); | ||
95 | rng->mask = val; | ||
96 | |||
97 | rng_init_per_cpu(rng, dn); | ||
98 | |||
99 | pr_info_once("Registering arch random hook.\n"); | ||
100 | |||
101 | ppc_md.get_random_long = powernv_get_random_long; | ||
102 | |||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | static __init int rng_init(void) | ||
107 | { | ||
108 | struct device_node *dn; | ||
109 | int rc; | ||
110 | |||
111 | for_each_compatible_node(dn, NULL, "ibm,power-rng") { | ||
112 | rc = rng_create(dn); | ||
113 | if (rc) { | ||
114 | pr_err("Failed creating rng for %s (%d).\n", | ||
115 | dn->full_name, rc); | ||
116 | continue; | ||
117 | } | ||
118 | |||
119 | /* Create devices for hwrng driver */ | ||
120 | of_platform_device_create(dn, NULL, NULL); | ||
121 | } | ||
122 | |||
123 | return 0; | ||
124 | } | ||
125 | subsys_initcall(rng_init); | ||
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c index e239dcfa224c..19884b2a51b4 100644 --- a/arch/powerpc/platforms/powernv/setup.c +++ b/arch/powerpc/platforms/powernv/setup.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/irq.h> | 23 | #include <linux/irq.h> |
24 | #include <linux/seq_file.h> | 24 | #include <linux/seq_file.h> |
25 | #include <linux/of.h> | 25 | #include <linux/of.h> |
26 | #include <linux/of_fdt.h> | ||
26 | #include <linux/interrupt.h> | 27 | #include <linux/interrupt.h> |
27 | #include <linux/bug.h> | 28 | #include <linux/bug.h> |
28 | 29 | ||
diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index 6c61ec5ee914..fbccac9cd2dc 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile | |||
@@ -3,7 +3,7 @@ ccflags-$(CONFIG_PPC_PSERIES_DEBUG) += -DDEBUG | |||
3 | 3 | ||
4 | obj-y := lpar.o hvCall.o nvram.o reconfig.o \ | 4 | obj-y := lpar.o hvCall.o nvram.o reconfig.o \ |
5 | setup.o iommu.o event_sources.o ras.o \ | 5 | setup.o iommu.o event_sources.o ras.o \ |
6 | firmware.o power.o dlpar.o mobility.o | 6 | firmware.o power.o dlpar.o mobility.o rng.o |
7 | obj-$(CONFIG_SMP) += smp.o | 7 | obj-$(CONFIG_SMP) += smp.o |
8 | obj-$(CONFIG_SCANLOG) += scanlog.o | 8 | obj-$(CONFIG_SCANLOG) += scanlog.o |
9 | obj-$(CONFIG_EEH) += eeh_pseries.o | 9 | obj-$(CONFIG_EEH) += eeh_pseries.o |
diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c index 7cfdaae1721a..a8fe5aa3d34f 100644 --- a/arch/powerpc/platforms/pseries/dlpar.c +++ b/arch/powerpc/platforms/pseries/dlpar.c | |||
@@ -404,46 +404,38 @@ static ssize_t dlpar_cpu_probe(const char *buf, size_t count) | |||
404 | unsigned long drc_index; | 404 | unsigned long drc_index; |
405 | int rc; | 405 | int rc; |
406 | 406 | ||
407 | cpu_hotplug_driver_lock(); | ||
408 | rc = strict_strtoul(buf, 0, &drc_index); | 407 | rc = strict_strtoul(buf, 0, &drc_index); |
409 | if (rc) { | 408 | if (rc) |
410 | rc = -EINVAL; | 409 | return -EINVAL; |
411 | goto out; | ||
412 | } | ||
413 | 410 | ||
414 | parent = of_find_node_by_path("/cpus"); | 411 | parent = of_find_node_by_path("/cpus"); |
415 | if (!parent) { | 412 | if (!parent) |
416 | rc = -ENODEV; | 413 | return -ENODEV; |
417 | goto out; | ||
418 | } | ||
419 | 414 | ||
420 | dn = dlpar_configure_connector(drc_index, parent); | 415 | dn = dlpar_configure_connector(drc_index, parent); |
421 | if (!dn) { | 416 | if (!dn) |
422 | rc = -EINVAL; | 417 | return -EINVAL; |
423 | goto out; | ||
424 | } | ||
425 | 418 | ||
426 | of_node_put(parent); | 419 | of_node_put(parent); |
427 | 420 | ||
428 | rc = dlpar_acquire_drc(drc_index); | 421 | rc = dlpar_acquire_drc(drc_index); |
429 | if (rc) { | 422 | if (rc) { |
430 | dlpar_free_cc_nodes(dn); | 423 | dlpar_free_cc_nodes(dn); |
431 | rc = -EINVAL; | 424 | return -EINVAL; |
432 | goto out; | ||
433 | } | 425 | } |
434 | 426 | ||
435 | rc = dlpar_attach_node(dn); | 427 | rc = dlpar_attach_node(dn); |
436 | if (rc) { | 428 | if (rc) { |
437 | dlpar_release_drc(drc_index); | 429 | dlpar_release_drc(drc_index); |
438 | dlpar_free_cc_nodes(dn); | 430 | dlpar_free_cc_nodes(dn); |
439 | goto out; | 431 | return rc; |
440 | } | 432 | } |
441 | 433 | ||
442 | rc = dlpar_online_cpu(dn); | 434 | rc = dlpar_online_cpu(dn); |
443 | out: | 435 | if (rc) |
444 | cpu_hotplug_driver_unlock(); | 436 | return rc; |
445 | 437 | ||
446 | return rc ? rc : count; | 438 | return count; |
447 | } | 439 | } |
448 | 440 | ||
449 | static int dlpar_offline_cpu(struct device_node *dn) | 441 | static int dlpar_offline_cpu(struct device_node *dn) |
@@ -516,30 +508,27 @@ static ssize_t dlpar_cpu_release(const char *buf, size_t count) | |||
516 | return -EINVAL; | 508 | return -EINVAL; |
517 | } | 509 | } |
518 | 510 | ||
519 | cpu_hotplug_driver_lock(); | ||
520 | rc = dlpar_offline_cpu(dn); | 511 | rc = dlpar_offline_cpu(dn); |
521 | if (rc) { | 512 | if (rc) { |
522 | of_node_put(dn); | 513 | of_node_put(dn); |
523 | rc = -EINVAL; | 514 | return -EINVAL; |
524 | goto out; | ||
525 | } | 515 | } |
526 | 516 | ||
527 | rc = dlpar_release_drc(*drc_index); | 517 | rc = dlpar_release_drc(*drc_index); |
528 | if (rc) { | 518 | if (rc) { |
529 | of_node_put(dn); | 519 | of_node_put(dn); |
530 | goto out; | 520 | return rc; |
531 | } | 521 | } |
532 | 522 | ||
533 | rc = dlpar_detach_node(dn); | 523 | rc = dlpar_detach_node(dn); |
534 | if (rc) { | 524 | if (rc) { |
535 | dlpar_acquire_drc(*drc_index); | 525 | dlpar_acquire_drc(*drc_index); |
536 | goto out; | 526 | return rc; |
537 | } | 527 | } |
538 | 528 | ||
539 | of_node_put(dn); | 529 | of_node_put(dn); |
540 | out: | 530 | |
541 | cpu_hotplug_driver_unlock(); | 531 | return count; |
542 | return rc ? rc : count; | ||
543 | } | 532 | } |
544 | 533 | ||
545 | static int __init pseries_dlpar_init(void) | 534 | static int __init pseries_dlpar_init(void) |
diff --git a/arch/powerpc/platforms/pseries/event_sources.c b/arch/powerpc/platforms/pseries/event_sources.c index 2605c310166a..18380e8f6dfe 100644 --- a/arch/powerpc/platforms/pseries/event_sources.c +++ b/arch/powerpc/platforms/pseries/event_sources.c | |||
@@ -25,7 +25,7 @@ void request_event_sources_irqs(struct device_node *np, | |||
25 | const char *name) | 25 | const char *name) |
26 | { | 26 | { |
27 | int i, index, count = 0; | 27 | int i, index, count = 0; |
28 | struct of_irq oirq; | 28 | struct of_phandle_args oirq; |
29 | const u32 *opicprop; | 29 | const u32 *opicprop; |
30 | unsigned int opicplen; | 30 | unsigned int opicplen; |
31 | unsigned int virqs[16]; | 31 | unsigned int virqs[16]; |
@@ -55,13 +55,11 @@ void request_event_sources_irqs(struct device_node *np, | |||
55 | /* Else use normal interrupt tree parsing */ | 55 | /* Else use normal interrupt tree parsing */ |
56 | else { | 56 | else { |
57 | /* First try to do a proper OF tree parsing */ | 57 | /* First try to do a proper OF tree parsing */ |
58 | for (index = 0; of_irq_map_one(np, index, &oirq) == 0; | 58 | for (index = 0; of_irq_parse_one(np, index, &oirq) == 0; |
59 | index++) { | 59 | index++) { |
60 | if (count > 15) | 60 | if (count > 15) |
61 | break; | 61 | break; |
62 | virqs[count] = irq_create_of_mapping(oirq.controller, | 62 | virqs[count] = irq_create_of_mapping(&oirq); |
63 | oirq.specifier, | ||
64 | oirq.size); | ||
65 | if (virqs[count] == NO_IRQ) { | 63 | if (virqs[count] == NO_IRQ) { |
66 | pr_err("event-sources: Unable to allocate " | 64 | pr_err("event-sources: Unable to allocate " |
67 | "interrupt number for %s\n", | 65 | "interrupt number for %s\n", |
diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c index 9a432de363b8..9590dbb756f2 100644 --- a/arch/powerpc/platforms/pseries/hotplug-memory.c +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c | |||
@@ -10,12 +10,14 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/of.h> | 12 | #include <linux/of.h> |
13 | #include <linux/of_address.h> | ||
13 | #include <linux/memblock.h> | 14 | #include <linux/memblock.h> |
14 | #include <linux/vmalloc.h> | 15 | #include <linux/vmalloc.h> |
15 | #include <linux/memory.h> | 16 | #include <linux/memory.h> |
16 | 17 | ||
17 | #include <asm/firmware.h> | 18 | #include <asm/firmware.h> |
18 | #include <asm/machdep.h> | 19 | #include <asm/machdep.h> |
20 | #include <asm/prom.h> | ||
19 | #include <asm/sparsemem.h> | 21 | #include <asm/sparsemem.h> |
20 | 22 | ||
21 | static unsigned long get_memblock_size(void) | 23 | static unsigned long get_memblock_size(void) |
diff --git a/arch/powerpc/platforms/pseries/iommu.c b/arch/powerpc/platforms/pseries/iommu.c index 0307901e4132..f253361552ae 100644 --- a/arch/powerpc/platforms/pseries/iommu.c +++ b/arch/powerpc/platforms/pseries/iommu.c | |||
@@ -52,7 +52,7 @@ | |||
52 | 52 | ||
53 | 53 | ||
54 | static void tce_invalidate_pSeries_sw(struct iommu_table *tbl, | 54 | static void tce_invalidate_pSeries_sw(struct iommu_table *tbl, |
55 | u64 *startp, u64 *endp) | 55 | __be64 *startp, __be64 *endp) |
56 | { | 56 | { |
57 | u64 __iomem *invalidate = (u64 __iomem *)tbl->it_index; | 57 | u64 __iomem *invalidate = (u64 __iomem *)tbl->it_index; |
58 | unsigned long start, end, inc; | 58 | unsigned long start, end, inc; |
@@ -86,7 +86,7 @@ static int tce_build_pSeries(struct iommu_table *tbl, long index, | |||
86 | struct dma_attrs *attrs) | 86 | struct dma_attrs *attrs) |
87 | { | 87 | { |
88 | u64 proto_tce; | 88 | u64 proto_tce; |
89 | u64 *tcep, *tces; | 89 | __be64 *tcep, *tces; |
90 | u64 rpn; | 90 | u64 rpn; |
91 | 91 | ||
92 | proto_tce = TCE_PCI_READ; // Read allowed | 92 | proto_tce = TCE_PCI_READ; // Read allowed |
@@ -94,12 +94,12 @@ static int tce_build_pSeries(struct iommu_table *tbl, long index, | |||
94 | if (direction != DMA_TO_DEVICE) | 94 | if (direction != DMA_TO_DEVICE) |
95 | proto_tce |= TCE_PCI_WRITE; | 95 | proto_tce |= TCE_PCI_WRITE; |
96 | 96 | ||
97 | tces = tcep = ((u64 *)tbl->it_base) + index; | 97 | tces = tcep = ((__be64 *)tbl->it_base) + index; |
98 | 98 | ||
99 | while (npages--) { | 99 | while (npages--) { |
100 | /* can't move this out since we might cross MEMBLOCK boundary */ | 100 | /* can't move this out since we might cross MEMBLOCK boundary */ |
101 | rpn = __pa(uaddr) >> TCE_SHIFT; | 101 | rpn = __pa(uaddr) >> TCE_SHIFT; |
102 | *tcep = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT; | 102 | *tcep = cpu_to_be64(proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT); |
103 | 103 | ||
104 | uaddr += TCE_PAGE_SIZE; | 104 | uaddr += TCE_PAGE_SIZE; |
105 | tcep++; | 105 | tcep++; |
@@ -113,9 +113,9 @@ static int tce_build_pSeries(struct iommu_table *tbl, long index, | |||
113 | 113 | ||
114 | static void tce_free_pSeries(struct iommu_table *tbl, long index, long npages) | 114 | static void tce_free_pSeries(struct iommu_table *tbl, long index, long npages) |
115 | { | 115 | { |
116 | u64 *tcep, *tces; | 116 | __be64 *tcep, *tces; |
117 | 117 | ||
118 | tces = tcep = ((u64 *)tbl->it_base) + index; | 118 | tces = tcep = ((__be64 *)tbl->it_base) + index; |
119 | 119 | ||
120 | while (npages--) | 120 | while (npages--) |
121 | *(tcep++) = 0; | 121 | *(tcep++) = 0; |
@@ -126,11 +126,11 @@ static void tce_free_pSeries(struct iommu_table *tbl, long index, long npages) | |||
126 | 126 | ||
127 | static unsigned long tce_get_pseries(struct iommu_table *tbl, long index) | 127 | static unsigned long tce_get_pseries(struct iommu_table *tbl, long index) |
128 | { | 128 | { |
129 | u64 *tcep; | 129 | __be64 *tcep; |
130 | 130 | ||
131 | tcep = ((u64 *)tbl->it_base) + index; | 131 | tcep = ((__be64 *)tbl->it_base) + index; |
132 | 132 | ||
133 | return *tcep; | 133 | return be64_to_cpu(*tcep); |
134 | } | 134 | } |
135 | 135 | ||
136 | static void tce_free_pSeriesLP(struct iommu_table*, long, long); | 136 | static void tce_free_pSeriesLP(struct iommu_table*, long, long); |
@@ -177,7 +177,7 @@ static int tce_build_pSeriesLP(struct iommu_table *tbl, long tcenum, | |||
177 | return ret; | 177 | return ret; |
178 | } | 178 | } |
179 | 179 | ||
180 | static DEFINE_PER_CPU(u64 *, tce_page); | 180 | static DEFINE_PER_CPU(__be64 *, tce_page); |
181 | 181 | ||
182 | static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, | 182 | static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, |
183 | long npages, unsigned long uaddr, | 183 | long npages, unsigned long uaddr, |
@@ -186,7 +186,7 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, | |||
186 | { | 186 | { |
187 | u64 rc = 0; | 187 | u64 rc = 0; |
188 | u64 proto_tce; | 188 | u64 proto_tce; |
189 | u64 *tcep; | 189 | __be64 *tcep; |
190 | u64 rpn; | 190 | u64 rpn; |
191 | long l, limit; | 191 | long l, limit; |
192 | long tcenum_start = tcenum, npages_start = npages; | 192 | long tcenum_start = tcenum, npages_start = npages; |
@@ -206,7 +206,7 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, | |||
206 | * from iommu_alloc{,_sg}() | 206 | * from iommu_alloc{,_sg}() |
207 | */ | 207 | */ |
208 | if (!tcep) { | 208 | if (!tcep) { |
209 | tcep = (u64 *)__get_free_page(GFP_ATOMIC); | 209 | tcep = (__be64 *)__get_free_page(GFP_ATOMIC); |
210 | /* If allocation fails, fall back to the loop implementation */ | 210 | /* If allocation fails, fall back to the loop implementation */ |
211 | if (!tcep) { | 211 | if (!tcep) { |
212 | local_irq_restore(flags); | 212 | local_irq_restore(flags); |
@@ -230,7 +230,7 @@ static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, | |||
230 | limit = min_t(long, npages, 4096/TCE_ENTRY_SIZE); | 230 | limit = min_t(long, npages, 4096/TCE_ENTRY_SIZE); |
231 | 231 | ||
232 | for (l = 0; l < limit; l++) { | 232 | for (l = 0; l < limit; l++) { |
233 | tcep[l] = proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT; | 233 | tcep[l] = cpu_to_be64(proto_tce | (rpn & TCE_RPN_MASK) << TCE_RPN_SHIFT); |
234 | rpn++; | 234 | rpn++; |
235 | } | 235 | } |
236 | 236 | ||
@@ -329,16 +329,16 @@ struct direct_window { | |||
329 | 329 | ||
330 | /* Dynamic DMA Window support */ | 330 | /* Dynamic DMA Window support */ |
331 | struct ddw_query_response { | 331 | struct ddw_query_response { |
332 | u32 windows_available; | 332 | __be32 windows_available; |
333 | u32 largest_available_block; | 333 | __be32 largest_available_block; |
334 | u32 page_size; | 334 | __be32 page_size; |
335 | u32 migration_capable; | 335 | __be32 migration_capable; |
336 | }; | 336 | }; |
337 | 337 | ||
338 | struct ddw_create_response { | 338 | struct ddw_create_response { |
339 | u32 liobn; | 339 | __be32 liobn; |
340 | u32 addr_hi; | 340 | __be32 addr_hi; |
341 | u32 addr_lo; | 341 | __be32 addr_lo; |
342 | }; | 342 | }; |
343 | 343 | ||
344 | static LIST_HEAD(direct_window_list); | 344 | static LIST_HEAD(direct_window_list); |
@@ -392,7 +392,8 @@ static int tce_setrange_multi_pSeriesLP(unsigned long start_pfn, | |||
392 | unsigned long num_pfn, const void *arg) | 392 | unsigned long num_pfn, const void *arg) |
393 | { | 393 | { |
394 | const struct dynamic_dma_window_prop *maprange = arg; | 394 | const struct dynamic_dma_window_prop *maprange = arg; |
395 | u64 *tcep, tce_size, num_tce, dma_offset, next, proto_tce, liobn; | 395 | u64 tce_size, num_tce, dma_offset, next, proto_tce, liobn; |
396 | __be64 *tcep; | ||
396 | u32 tce_shift; | 397 | u32 tce_shift; |
397 | u64 rc = 0; | 398 | u64 rc = 0; |
398 | long l, limit; | 399 | long l, limit; |
@@ -401,7 +402,7 @@ static int tce_setrange_multi_pSeriesLP(unsigned long start_pfn, | |||
401 | tcep = __get_cpu_var(tce_page); | 402 | tcep = __get_cpu_var(tce_page); |
402 | 403 | ||
403 | if (!tcep) { | 404 | if (!tcep) { |
404 | tcep = (u64 *)__get_free_page(GFP_ATOMIC); | 405 | tcep = (__be64 *)__get_free_page(GFP_ATOMIC); |
405 | if (!tcep) { | 406 | if (!tcep) { |
406 | local_irq_enable(); | 407 | local_irq_enable(); |
407 | return -ENOMEM; | 408 | return -ENOMEM; |
@@ -435,7 +436,7 @@ static int tce_setrange_multi_pSeriesLP(unsigned long start_pfn, | |||
435 | dma_offset = next + be64_to_cpu(maprange->dma_base); | 436 | dma_offset = next + be64_to_cpu(maprange->dma_base); |
436 | 437 | ||
437 | for (l = 0; l < limit; l++) { | 438 | for (l = 0; l < limit; l++) { |
438 | tcep[l] = proto_tce | next; | 439 | tcep[l] = cpu_to_be64(proto_tce | next); |
439 | next += tce_size; | 440 | next += tce_size; |
440 | } | 441 | } |
441 | 442 | ||
@@ -780,7 +781,7 @@ static u64 find_existing_ddw(struct device_node *pdn) | |||
780 | list_for_each_entry(window, &direct_window_list, list) { | 781 | list_for_each_entry(window, &direct_window_list, list) { |
781 | if (window->device == pdn) { | 782 | if (window->device == pdn) { |
782 | direct64 = window->prop; | 783 | direct64 = window->prop; |
783 | dma_addr = direct64->dma_base; | 784 | dma_addr = be64_to_cpu(direct64->dma_base); |
784 | break; | 785 | break; |
785 | } | 786 | } |
786 | } | 787 | } |
@@ -1045,11 +1046,11 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn) | |||
1045 | dev_dbg(&dev->dev, "no free dynamic windows"); | 1046 | dev_dbg(&dev->dev, "no free dynamic windows"); |
1046 | goto out_restore_window; | 1047 | goto out_restore_window; |
1047 | } | 1048 | } |
1048 | if (query.page_size & 4) { | 1049 | if (be32_to_cpu(query.page_size) & 4) { |
1049 | page_shift = 24; /* 16MB */ | 1050 | page_shift = 24; /* 16MB */ |
1050 | } else if (query.page_size & 2) { | 1051 | } else if (be32_to_cpu(query.page_size) & 2) { |
1051 | page_shift = 16; /* 64kB */ | 1052 | page_shift = 16; /* 64kB */ |
1052 | } else if (query.page_size & 1) { | 1053 | } else if (be32_to_cpu(query.page_size) & 1) { |
1053 | page_shift = 12; /* 4kB */ | 1054 | page_shift = 12; /* 4kB */ |
1054 | } else { | 1055 | } else { |
1055 | dev_dbg(&dev->dev, "no supported direct page size in mask %x", | 1056 | dev_dbg(&dev->dev, "no supported direct page size in mask %x", |
@@ -1059,7 +1060,7 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn) | |||
1059 | /* verify the window * number of ptes will map the partition */ | 1060 | /* verify the window * number of ptes will map the partition */ |
1060 | /* check largest block * page size > max memory hotplug addr */ | 1061 | /* check largest block * page size > max memory hotplug addr */ |
1061 | max_addr = memory_hotplug_max(); | 1062 | max_addr = memory_hotplug_max(); |
1062 | if (query.largest_available_block < (max_addr >> page_shift)) { | 1063 | if (be32_to_cpu(query.largest_available_block) < (max_addr >> page_shift)) { |
1063 | dev_dbg(&dev->dev, "can't map partiton max 0x%llx with %u " | 1064 | dev_dbg(&dev->dev, "can't map partiton max 0x%llx with %u " |
1064 | "%llu-sized pages\n", max_addr, query.largest_available_block, | 1065 | "%llu-sized pages\n", max_addr, query.largest_available_block, |
1065 | 1ULL << page_shift); | 1066 | 1ULL << page_shift); |
@@ -1085,7 +1086,7 @@ static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn) | |||
1085 | if (ret != 0) | 1086 | if (ret != 0) |
1086 | goto out_free_prop; | 1087 | goto out_free_prop; |
1087 | 1088 | ||
1088 | ddwprop->liobn = cpu_to_be32(create.liobn); | 1089 | ddwprop->liobn = create.liobn; |
1089 | ddwprop->dma_base = cpu_to_be64(of_read_number(&create.addr_hi, 2)); | 1090 | ddwprop->dma_base = cpu_to_be64(of_read_number(&create.addr_hi, 2)); |
1090 | ddwprop->tce_shift = cpu_to_be32(page_shift); | 1091 | ddwprop->tce_shift = cpu_to_be32(page_shift); |
1091 | ddwprop->window_shift = cpu_to_be32(len); | 1092 | ddwprop->window_shift = cpu_to_be32(len); |
diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c index d276cd3edd8f..057fc894be51 100644 --- a/arch/powerpc/platforms/pseries/nvram.c +++ b/arch/powerpc/platforms/pseries/nvram.c | |||
@@ -429,9 +429,6 @@ static int __init pseries_nvram_init_os_partition(struct nvram_os_partition | |||
429 | loff_t p; | 429 | loff_t p; |
430 | int size; | 430 | int size; |
431 | 431 | ||
432 | /* Scan nvram for partitions */ | ||
433 | nvram_scan_partitions(); | ||
434 | |||
435 | /* Look for ours */ | 432 | /* Look for ours */ |
436 | p = nvram_find_partition(part->name, NVRAM_SIG_OS, &size); | 433 | p = nvram_find_partition(part->name, NVRAM_SIG_OS, &size); |
437 | 434 | ||
@@ -795,6 +792,9 @@ static int __init pseries_nvram_init_log_partitions(void) | |||
795 | { | 792 | { |
796 | int rc; | 793 | int rc; |
797 | 794 | ||
795 | /* Scan nvram for partitions */ | ||
796 | nvram_scan_partitions(); | ||
797 | |||
798 | rc = pseries_nvram_init_os_partition(&rtas_log_partition); | 798 | rc = pseries_nvram_init_os_partition(&rtas_log_partition); |
799 | nvram_init_oops_partition(rc == 0); | 799 | nvram_init_oops_partition(rc == 0); |
800 | return 0; | 800 | return 0; |
@@ -804,7 +804,7 @@ machine_arch_initcall(pseries, pseries_nvram_init_log_partitions); | |||
804 | int __init pSeries_nvram_init(void) | 804 | int __init pSeries_nvram_init(void) |
805 | { | 805 | { |
806 | struct device_node *nvram; | 806 | struct device_node *nvram; |
807 | const unsigned int *nbytes_p; | 807 | const __be32 *nbytes_p; |
808 | unsigned int proplen; | 808 | unsigned int proplen; |
809 | 809 | ||
810 | nvram = of_find_node_by_type(NULL, "nvram"); | 810 | nvram = of_find_node_by_type(NULL, "nvram"); |
@@ -817,7 +817,7 @@ int __init pSeries_nvram_init(void) | |||
817 | return -EIO; | 817 | return -EIO; |
818 | } | 818 | } |
819 | 819 | ||
820 | nvram_size = *nbytes_p; | 820 | nvram_size = be32_to_cpup(nbytes_p); |
821 | 821 | ||
822 | nvram_fetch = rtas_token("nvram-fetch"); | 822 | nvram_fetch = rtas_token("nvram-fetch"); |
823 | nvram_store = rtas_token("nvram-store"); | 823 | nvram_store = rtas_token("nvram-store"); |
diff --git a/arch/powerpc/platforms/pseries/rng.c b/arch/powerpc/platforms/pseries/rng.c new file mode 100644 index 000000000000..a702f1c08242 --- /dev/null +++ b/arch/powerpc/platforms/pseries/rng.c | |||
@@ -0,0 +1,44 @@ | |||
1 | /* | ||
2 | * Copyright 2013, Michael Ellerman, IBM Corporation. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | */ | ||
9 | |||
10 | #define pr_fmt(fmt) "pseries-rng: " fmt | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/of.h> | ||
14 | #include <asm/archrandom.h> | ||
15 | #include <asm/machdep.h> | ||
16 | |||
17 | |||
18 | static int pseries_get_random_long(unsigned long *v) | ||
19 | { | ||
20 | unsigned long retbuf[PLPAR_HCALL_BUFSIZE]; | ||
21 | |||
22 | if (plpar_hcall(H_RANDOM, retbuf) == H_SUCCESS) { | ||
23 | *v = retbuf[0]; | ||
24 | return 1; | ||
25 | } | ||
26 | |||
27 | return 0; | ||
28 | } | ||
29 | |||
30 | static __init int rng_init(void) | ||
31 | { | ||
32 | struct device_node *dn; | ||
33 | |||
34 | dn = of_find_compatible_node(NULL, NULL, "ibm,random"); | ||
35 | if (!dn) | ||
36 | return -ENODEV; | ||
37 | |||
38 | pr_info("Registering arch random hook.\n"); | ||
39 | |||
40 | ppc_md.get_random_long = pseries_get_random_long; | ||
41 | |||
42 | return 0; | ||
43 | } | ||
44 | subsys_initcall(rng_init); | ||
diff --git a/arch/powerpc/platforms/pseries/smp.c b/arch/powerpc/platforms/pseries/smp.c index 1c1771a40250..24f58cb0a543 100644 --- a/arch/powerpc/platforms/pseries/smp.c +++ b/arch/powerpc/platforms/pseries/smp.c | |||
@@ -233,18 +233,24 @@ static void __init smp_init_pseries(void) | |||
233 | 233 | ||
234 | alloc_bootmem_cpumask_var(&of_spin_mask); | 234 | alloc_bootmem_cpumask_var(&of_spin_mask); |
235 | 235 | ||
236 | /* Mark threads which are still spinning in hold loops. */ | 236 | /* |
237 | if (cpu_has_feature(CPU_FTR_SMT)) { | 237 | * Mark threads which are still spinning in hold loops |
238 | for_each_present_cpu(i) { | 238 | * |
239 | if (cpu_thread_in_core(i) == 0) | 239 | * We know prom_init will not have started them if RTAS supports |
240 | cpumask_set_cpu(i, of_spin_mask); | 240 | * query-cpu-stopped-state. |
241 | } | 241 | */ |
242 | } else { | 242 | if (rtas_token("query-cpu-stopped-state") == RTAS_UNKNOWN_SERVICE) { |
243 | cpumask_copy(of_spin_mask, cpu_present_mask); | 243 | if (cpu_has_feature(CPU_FTR_SMT)) { |
244 | for_each_present_cpu(i) { | ||
245 | if (cpu_thread_in_core(i) == 0) | ||
246 | cpumask_set_cpu(i, of_spin_mask); | ||
247 | } | ||
248 | } else | ||
249 | cpumask_copy(of_spin_mask, cpu_present_mask); | ||
250 | |||
251 | cpumask_clear_cpu(boot_cpuid, of_spin_mask); | ||
244 | } | 252 | } |
245 | 253 | ||
246 | cpumask_clear_cpu(boot_cpuid, of_spin_mask); | ||
247 | |||
248 | /* Non-lpar has additional take/give timebase */ | 254 | /* Non-lpar has additional take/give timebase */ |
249 | if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) { | 255 | if (rtas_token("freeze-time-base") != RTAS_UNKNOWN_SERVICE) { |
250 | smp_ops->give_timebase = rtas_give_timebase; | 256 | smp_ops->give_timebase = rtas_give_timebase; |
diff --git a/arch/powerpc/platforms/pseries/suspend.c b/arch/powerpc/platforms/pseries/suspend.c index 5f997e79d570..16a255255d30 100644 --- a/arch/powerpc/platforms/pseries/suspend.c +++ b/arch/powerpc/platforms/pseries/suspend.c | |||
@@ -106,7 +106,7 @@ static int pseries_prepare_late(void) | |||
106 | atomic_set(&suspend_data.done, 0); | 106 | atomic_set(&suspend_data.done, 0); |
107 | atomic_set(&suspend_data.error, 0); | 107 | atomic_set(&suspend_data.error, 0); |
108 | suspend_data.complete = &suspend_work; | 108 | suspend_data.complete = &suspend_work; |
109 | INIT_COMPLETION(suspend_work); | 109 | reinit_completion(&suspend_work); |
110 | return 0; | 110 | return 0; |
111 | } | 111 | } |
112 | 112 | ||
diff --git a/arch/powerpc/platforms/wsp/scom_smp.c b/arch/powerpc/platforms/wsp/scom_smp.c index b56b70aeb497..268bc899c1f7 100644 --- a/arch/powerpc/platforms/wsp/scom_smp.c +++ b/arch/powerpc/platforms/wsp/scom_smp.c | |||
@@ -116,7 +116,14 @@ static int a2_scom_ram(scom_map_t scom, int thread, u32 insn, int extmask) | |||
116 | 116 | ||
117 | scom_write(scom, SCOM_RAMIC, cmd); | 117 | scom_write(scom, SCOM_RAMIC, cmd); |
118 | 118 | ||
119 | while (!((val = scom_read(scom, SCOM_RAMC)) & mask)) { | 119 | for (;;) { |
120 | if (scom_read(scom, SCOM_RAMC, &val) != 0) { | ||
121 | pr_err("SCOM error on instruction 0x%08x, thread %d\n", | ||
122 | insn, thread); | ||
123 | return -1; | ||
124 | } | ||
125 | if (val & mask) | ||
126 | break; | ||
120 | pr_devel("Waiting on RAMC = 0x%llx\n", val); | 127 | pr_devel("Waiting on RAMC = 0x%llx\n", val); |
121 | if (++n == 3) { | 128 | if (++n == 3) { |
122 | pr_err("RAMC timeout on instruction 0x%08x, thread %d\n", | 129 | pr_err("RAMC timeout on instruction 0x%08x, thread %d\n", |
@@ -151,9 +158,7 @@ static int a2_scom_getgpr(scom_map_t scom, int thread, int gpr, int alt, | |||
151 | if (rc) | 158 | if (rc) |
152 | return rc; | 159 | return rc; |
153 | 160 | ||
154 | *out_gpr = scom_read(scom, SCOM_RAMD); | 161 | return scom_read(scom, SCOM_RAMD, out_gpr); |
155 | |||
156 | return 0; | ||
157 | } | 162 | } |
158 | 163 | ||
159 | static int a2_scom_getspr(scom_map_t scom, int thread, int spr, u64 *out_spr) | 164 | static int a2_scom_getspr(scom_map_t scom, int thread, int spr, u64 *out_spr) |
@@ -353,7 +358,10 @@ int a2_scom_startup_cpu(unsigned int lcpu, int thr_idx, struct device_node *np) | |||
353 | 358 | ||
354 | pr_devel("Bringing up CPU%d using SCOM...\n", lcpu); | 359 | pr_devel("Bringing up CPU%d using SCOM...\n", lcpu); |
355 | 360 | ||
356 | pccr0 = scom_read(scom, SCOM_PCCR0); | 361 | if (scom_read(scom, SCOM_PCCR0, &pccr0) != 0) { |
362 | printk(KERN_ERR "XSCOM failure readng PCCR0 on CPU%d\n", lcpu); | ||
363 | return -1; | ||
364 | } | ||
357 | scom_write(scom, SCOM_PCCR0, pccr0 | SCOM_PCCR0_ENABLE_DEBUG | | 365 | scom_write(scom, SCOM_PCCR0, pccr0 | SCOM_PCCR0_ENABLE_DEBUG | |
358 | SCOM_PCCR0_ENABLE_RAM); | 366 | SCOM_PCCR0_ENABLE_RAM); |
359 | 367 | ||
diff --git a/arch/powerpc/platforms/wsp/scom_wsp.c b/arch/powerpc/platforms/wsp/scom_wsp.c index 4052e2259f30..8928507affea 100644 --- a/arch/powerpc/platforms/wsp/scom_wsp.c +++ b/arch/powerpc/platforms/wsp/scom_wsp.c | |||
@@ -50,18 +50,22 @@ static void wsp_scom_unmap(scom_map_t map) | |||
50 | iounmap((void *)map); | 50 | iounmap((void *)map); |
51 | } | 51 | } |
52 | 52 | ||
53 | static u64 wsp_scom_read(scom_map_t map, u32 reg) | 53 | static int wsp_scom_read(scom_map_t map, u64 reg, u64 *value) |
54 | { | 54 | { |
55 | u64 __iomem *addr = (u64 __iomem *)map; | 55 | u64 __iomem *addr = (u64 __iomem *)map; |
56 | 56 | ||
57 | return in_be64(addr + reg); | 57 | *value = in_be64(addr + reg); |
58 | |||
59 | return 0; | ||
58 | } | 60 | } |
59 | 61 | ||
60 | static void wsp_scom_write(scom_map_t map, u32 reg, u64 value) | 62 | static int wsp_scom_write(scom_map_t map, u64 reg, u64 value) |
61 | { | 63 | { |
62 | u64 __iomem *addr = (u64 __iomem *)map; | 64 | u64 __iomem *addr = (u64 __iomem *)map; |
63 | 65 | ||
64 | return out_be64(addr + reg, value); | 66 | out_be64(addr + reg, value); |
67 | |||
68 | return 0; | ||
65 | } | 69 | } |
66 | 70 | ||
67 | static const struct scom_controller wsp_scom_controller = { | 71 | static const struct scom_controller wsp_scom_controller = { |
diff --git a/arch/powerpc/platforms/wsp/wsp.c b/arch/powerpc/platforms/wsp/wsp.c index d25cc96c21b8..ddb6efe88914 100644 --- a/arch/powerpc/platforms/wsp/wsp.c +++ b/arch/powerpc/platforms/wsp/wsp.c | |||
@@ -89,6 +89,7 @@ void wsp_halt(void) | |||
89 | struct device_node *dn; | 89 | struct device_node *dn; |
90 | struct device_node *mine; | 90 | struct device_node *mine; |
91 | struct device_node *me; | 91 | struct device_node *me; |
92 | int rc; | ||
92 | 93 | ||
93 | me = of_get_cpu_node(smp_processor_id(), NULL); | 94 | me = of_get_cpu_node(smp_processor_id(), NULL); |
94 | mine = scom_find_parent(me); | 95 | mine = scom_find_parent(me); |
@@ -101,15 +102,15 @@ void wsp_halt(void) | |||
101 | 102 | ||
102 | /* read-modify-write it so the HW probe does not get | 103 | /* read-modify-write it so the HW probe does not get |
103 | * confused */ | 104 | * confused */ |
104 | val = scom_read(m, 0); | 105 | rc = scom_read(m, 0, &val); |
105 | val |= 1; | 106 | if (rc == 0) |
106 | scom_write(m, 0, val); | 107 | scom_write(m, 0, val | 1); |
107 | scom_unmap(m); | 108 | scom_unmap(m); |
108 | } | 109 | } |
109 | m = scom_map(mine, 0, 1); | 110 | m = scom_map(mine, 0, 1); |
110 | val = scom_read(m, 0); | 111 | rc = scom_read(m, 0, &val); |
111 | val |= 1; | 112 | if (rc == 0) |
112 | scom_write(m, 0, val); | 113 | scom_write(m, 0, val | 1); |
113 | /* should never return */ | 114 | /* should never return */ |
114 | scom_unmap(m); | 115 | scom_unmap(m); |
115 | } | 116 | } |
diff --git a/arch/powerpc/sysdev/Kconfig b/arch/powerpc/sysdev/Kconfig index ab4cb5476472..13ec968be4c7 100644 --- a/arch/powerpc/sysdev/Kconfig +++ b/arch/powerpc/sysdev/Kconfig | |||
@@ -28,7 +28,7 @@ config PPC_SCOM | |||
28 | 28 | ||
29 | config SCOM_DEBUGFS | 29 | config SCOM_DEBUGFS |
30 | bool "Expose SCOM controllers via debugfs" | 30 | bool "Expose SCOM controllers via debugfs" |
31 | depends on PPC_SCOM | 31 | depends on PPC_SCOM && DEBUG_FS |
32 | default n | 32 | default n |
33 | 33 | ||
34 | config GE_FPGA | 34 | config GE_FPGA |
diff --git a/arch/powerpc/sysdev/cpm_common.c b/arch/powerpc/sysdev/cpm_common.c index 4dd534194ae8..4f7869571290 100644 --- a/arch/powerpc/sysdev/cpm_common.c +++ b/arch/powerpc/sysdev/cpm_common.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/spinlock.h> | 22 | #include <linux/spinlock.h> |
23 | #include <linux/export.h> | 23 | #include <linux/export.h> |
24 | #include <linux/of.h> | 24 | #include <linux/of.h> |
25 | #include <linux/of_address.h> | ||
25 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
26 | 27 | ||
27 | #include <asm/udbg.h> | 28 | #include <asm/udbg.h> |
diff --git a/arch/powerpc/sysdev/ehv_pic.c b/arch/powerpc/sysdev/ehv_pic.c index 9cd0e60716fe..b74085cea1af 100644 --- a/arch/powerpc/sysdev/ehv_pic.c +++ b/arch/powerpc/sysdev/ehv_pic.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include <linux/spinlock.h> | 20 | #include <linux/spinlock.h> |
21 | #include <linux/of.h> | 21 | #include <linux/of.h> |
22 | #include <linux/of_address.h> | ||
22 | 23 | ||
23 | #include <asm/io.h> | 24 | #include <asm/io.h> |
24 | #include <asm/irq.h> | 25 | #include <asm/irq.h> |
diff --git a/arch/powerpc/sysdev/fsl_gtm.c b/arch/powerpc/sysdev/fsl_gtm.c index 0eb871cc3437..06ac3c61b3d0 100644 --- a/arch/powerpc/sysdev/fsl_gtm.c +++ b/arch/powerpc/sysdev/fsl_gtm.c | |||
@@ -19,6 +19,8 @@ | |||
19 | #include <linux/list.h> | 19 | #include <linux/list.h> |
20 | #include <linux/io.h> | 20 | #include <linux/io.h> |
21 | #include <linux/of.h> | 21 | #include <linux/of.h> |
22 | #include <linux/of_address.h> | ||
23 | #include <linux/of_irq.h> | ||
22 | #include <linux/spinlock.h> | 24 | #include <linux/spinlock.h> |
23 | #include <linux/bitops.h> | 25 | #include <linux/bitops.h> |
24 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
@@ -401,16 +403,15 @@ static int __init fsl_gtm_init(void) | |||
401 | gtm->clock = *clock; | 403 | gtm->clock = *clock; |
402 | 404 | ||
403 | for (i = 0; i < ARRAY_SIZE(gtm->timers); i++) { | 405 | for (i = 0; i < ARRAY_SIZE(gtm->timers); i++) { |
404 | int ret; | 406 | unsigned int irq; |
405 | struct resource irq; | ||
406 | 407 | ||
407 | ret = of_irq_to_resource(np, i, &irq); | 408 | irq = irq_of_parse_and_map(np, i); |
408 | if (ret == NO_IRQ) { | 409 | if (irq == NO_IRQ) { |
409 | pr_err("%s: not enough interrupts specified\n", | 410 | pr_err("%s: not enough interrupts specified\n", |
410 | np->full_name); | 411 | np->full_name); |
411 | goto err; | 412 | goto err; |
412 | } | 413 | } |
413 | gtm->timers[i].irq = irq.start; | 414 | gtm->timers[i].irq = irq; |
414 | gtm->timers[i].gtm = gtm; | 415 | gtm->timers[i].gtm = gtm; |
415 | } | 416 | } |
416 | 417 | ||
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c index ccfb50ddfe38..4dfd61df8aba 100644 --- a/arch/powerpc/sysdev/fsl_pci.c +++ b/arch/powerpc/sysdev/fsl_pci.c | |||
@@ -40,12 +40,12 @@ | |||
40 | 40 | ||
41 | static int fsl_pcie_bus_fixup, is_mpc83xx_pci; | 41 | static int fsl_pcie_bus_fixup, is_mpc83xx_pci; |
42 | 42 | ||
43 | static void quirk_fsl_pcie_header(struct pci_dev *dev) | 43 | static void quirk_fsl_pcie_early(struct pci_dev *dev) |
44 | { | 44 | { |
45 | u8 hdr_type; | 45 | u8 hdr_type; |
46 | 46 | ||
47 | /* if we aren't a PCIe don't bother */ | 47 | /* if we aren't a PCIe don't bother */ |
48 | if (!pci_find_capability(dev, PCI_CAP_ID_EXP)) | 48 | if (!pci_is_pcie(dev)) |
49 | return; | 49 | return; |
50 | 50 | ||
51 | /* if we aren't in host mode don't bother */ | 51 | /* if we aren't in host mode don't bother */ |
@@ -562,7 +562,8 @@ no_bridge: | |||
562 | } | 562 | } |
563 | #endif /* CONFIG_FSL_SOC_BOOKE || CONFIG_PPC_86xx */ | 563 | #endif /* CONFIG_FSL_SOC_BOOKE || CONFIG_PPC_86xx */ |
564 | 564 | ||
565 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_FREESCALE, PCI_ANY_ID, quirk_fsl_pcie_header); | 565 | DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_FREESCALE, PCI_ANY_ID, |
566 | quirk_fsl_pcie_early); | ||
566 | 567 | ||
567 | #if defined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_MPC512x) | 568 | #if defined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_MPC512x) |
568 | struct mpc83xx_pcie_priv { | 569 | struct mpc83xx_pcie_priv { |
diff --git a/arch/powerpc/sysdev/fsl_pmc.c b/arch/powerpc/sysdev/fsl_pmc.c index 592a0f8d527a..8cf4aa0e3a25 100644 --- a/arch/powerpc/sysdev/fsl_pmc.c +++ b/arch/powerpc/sysdev/fsl_pmc.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/suspend.h> | 18 | #include <linux/suspend.h> |
19 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
20 | #include <linux/device.h> | 20 | #include <linux/device.h> |
21 | #include <linux/of_address.h> | ||
21 | #include <linux/of_platform.h> | 22 | #include <linux/of_platform.h> |
22 | 23 | ||
23 | struct pmc_regs { | 24 | struct pmc_regs { |
diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index e2fb3171f41b..95dd892e9904 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c | |||
@@ -28,6 +28,8 @@ | |||
28 | #include <linux/dma-mapping.h> | 28 | #include <linux/dma-mapping.h> |
29 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
30 | #include <linux/device.h> | 30 | #include <linux/device.h> |
31 | #include <linux/of_address.h> | ||
32 | #include <linux/of_irq.h> | ||
31 | #include <linux/of_platform.h> | 33 | #include <linux/of_platform.h> |
32 | #include <linux/delay.h> | 34 | #include <linux/delay.h> |
33 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
diff --git a/arch/powerpc/sysdev/fsl_rmu.c b/arch/powerpc/sysdev/fsl_rmu.c index 14bd5221f28a..00e224a1048c 100644 --- a/arch/powerpc/sysdev/fsl_rmu.c +++ b/arch/powerpc/sysdev/fsl_rmu.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/types.h> | 27 | #include <linux/types.h> |
28 | #include <linux/dma-mapping.h> | 28 | #include <linux/dma-mapping.h> |
29 | #include <linux/interrupt.h> | 29 | #include <linux/interrupt.h> |
30 | #include <linux/of_irq.h> | ||
30 | #include <linux/of_platform.h> | 31 | #include <linux/of_platform.h> |
31 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
32 | 33 | ||
diff --git a/arch/powerpc/sysdev/fsl_soc.h b/arch/powerpc/sysdev/fsl_soc.h index c6d00736f07f..4c5a19ef4f0b 100644 --- a/arch/powerpc/sysdev/fsl_soc.h +++ b/arch/powerpc/sysdev/fsl_soc.h | |||
@@ -21,8 +21,6 @@ struct device_node; | |||
21 | 21 | ||
22 | extern void fsl_rstcr_restart(char *cmd); | 22 | extern void fsl_rstcr_restart(char *cmd); |
23 | 23 | ||
24 | #if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE) | ||
25 | |||
26 | /* The different ports that the DIU can be connected to */ | 24 | /* The different ports that the DIU can be connected to */ |
27 | enum fsl_diu_monitor_port { | 25 | enum fsl_diu_monitor_port { |
28 | FSL_DIU_PORT_DVI, /* DVI */ | 26 | FSL_DIU_PORT_DVI, /* DVI */ |
@@ -43,7 +41,6 @@ struct platform_diu_data_ops { | |||
43 | }; | 41 | }; |
44 | 42 | ||
45 | extern struct platform_diu_data_ops diu_ops; | 43 | extern struct platform_diu_data_ops diu_ops; |
46 | #endif | ||
47 | 44 | ||
48 | void fsl_hv_restart(char *cmd); | 45 | void fsl_hv_restart(char *cmd); |
49 | void fsl_hv_halt(void); | 46 | void fsl_hv_halt(void); |
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 1be54faf60dd..0e166ed4cd16 100644 --- a/arch/powerpc/sysdev/mpic.c +++ b/arch/powerpc/sysdev/mpic.c | |||
@@ -535,7 +535,7 @@ static void __init mpic_scan_ht_pic(struct mpic *mpic, u8 __iomem *devbase, | |||
535 | mpic->fixups[irq].data = readl(base + 4) | 0x80000000; | 535 | mpic->fixups[irq].data = readl(base + 4) | 0x80000000; |
536 | } | 536 | } |
537 | } | 537 | } |
538 | 538 | ||
539 | 539 | ||
540 | static void __init mpic_scan_ht_pics(struct mpic *mpic) | 540 | static void __init mpic_scan_ht_pics(struct mpic *mpic) |
541 | { | 541 | { |
@@ -1088,8 +1088,14 @@ static int mpic_host_map(struct irq_domain *h, unsigned int virq, | |||
1088 | * is done here. | 1088 | * is done here. |
1089 | */ | 1089 | */ |
1090 | if (!mpic_is_ipi(mpic, hw) && (mpic->flags & MPIC_NO_RESET)) { | 1090 | if (!mpic_is_ipi(mpic, hw) && (mpic->flags & MPIC_NO_RESET)) { |
1091 | int cpu; | ||
1092 | |||
1093 | preempt_disable(); | ||
1094 | cpu = mpic_processor_id(mpic); | ||
1095 | preempt_enable(); | ||
1096 | |||
1091 | mpic_set_vector(virq, hw); | 1097 | mpic_set_vector(virq, hw); |
1092 | mpic_set_destination(virq, mpic_processor_id(mpic)); | 1098 | mpic_set_destination(virq, cpu); |
1093 | mpic_irq_set_priority(virq, 8); | 1099 | mpic_irq_set_priority(virq, 8); |
1094 | } | 1100 | } |
1095 | 1101 | ||
@@ -1475,7 +1481,7 @@ struct mpic * __init mpic_alloc(struct device_node *node, | |||
1475 | * as a default instead of the value read from the HW. | 1481 | * as a default instead of the value read from the HW. |
1476 | */ | 1482 | */ |
1477 | last_irq = (greg_feature & MPIC_GREG_FEATURE_LAST_SRC_MASK) | 1483 | last_irq = (greg_feature & MPIC_GREG_FEATURE_LAST_SRC_MASK) |
1478 | >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT; | 1484 | >> MPIC_GREG_FEATURE_LAST_SRC_SHIFT; |
1479 | if (isu_size) | 1485 | if (isu_size) |
1480 | last_irq = isu_size * MPIC_MAX_ISU - 1; | 1486 | last_irq = isu_size * MPIC_MAX_ISU - 1; |
1481 | of_property_read_u32(mpic->node, "last-interrupt-source", &last_irq); | 1487 | of_property_read_u32(mpic->node, "last-interrupt-source", &last_irq); |
@@ -1625,7 +1631,7 @@ void __init mpic_init(struct mpic *mpic) | |||
1625 | /* start with vector = source number, and masked */ | 1631 | /* start with vector = source number, and masked */ |
1626 | u32 vecpri = MPIC_VECPRI_MASK | i | | 1632 | u32 vecpri = MPIC_VECPRI_MASK | i | |
1627 | (8 << MPIC_VECPRI_PRIORITY_SHIFT); | 1633 | (8 << MPIC_VECPRI_PRIORITY_SHIFT); |
1628 | 1634 | ||
1629 | /* check if protected */ | 1635 | /* check if protected */ |
1630 | if (mpic->protected && test_bit(i, mpic->protected)) | 1636 | if (mpic->protected && test_bit(i, mpic->protected)) |
1631 | continue; | 1637 | continue; |
@@ -1634,7 +1640,7 @@ void __init mpic_init(struct mpic *mpic) | |||
1634 | mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), 1 << cpu); | 1640 | mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), 1 << cpu); |
1635 | } | 1641 | } |
1636 | } | 1642 | } |
1637 | 1643 | ||
1638 | /* Init spurious vector */ | 1644 | /* Init spurious vector */ |
1639 | mpic_write(mpic->gregs, MPIC_INFO(GREG_SPURIOUS), mpic->spurious_vec); | 1645 | mpic_write(mpic->gregs, MPIC_INFO(GREG_SPURIOUS), mpic->spurious_vec); |
1640 | 1646 | ||
diff --git a/arch/powerpc/sysdev/mpic_msgr.c b/arch/powerpc/sysdev/mpic_msgr.c index c75325865a85..2c9b52aa266c 100644 --- a/arch/powerpc/sysdev/mpic_msgr.c +++ b/arch/powerpc/sysdev/mpic_msgr.c | |||
@@ -237,15 +237,13 @@ static int mpic_msgr_probe(struct platform_device *dev) | |||
237 | raw_spin_lock_init(&msgr->lock); | 237 | raw_spin_lock_init(&msgr->lock); |
238 | 238 | ||
239 | if (receive_mask & (1 << i)) { | 239 | if (receive_mask & (1 << i)) { |
240 | struct resource irq; | 240 | msgr->irq = irq_of_parse_and_map(np, irq_index); |
241 | 241 | if (msgr->irq == NO_IRQ) { | |
242 | if (of_irq_to_resource(np, irq_index, &irq) == NO_IRQ) { | ||
243 | dev_err(&dev->dev, | 242 | dev_err(&dev->dev, |
244 | "Missing interrupt specifier"); | 243 | "Missing interrupt specifier"); |
245 | kfree(msgr); | 244 | kfree(msgr); |
246 | return -EFAULT; | 245 | return -EFAULT; |
247 | } | 246 | } |
248 | msgr->irq = irq.start; | ||
249 | irq_index += 1; | 247 | irq_index += 1; |
250 | } else { | 248 | } else { |
251 | msgr->irq = NO_IRQ; | 249 | msgr->irq = NO_IRQ; |
diff --git a/arch/powerpc/sysdev/mpic_msi.c b/arch/powerpc/sysdev/mpic_msi.c index bbf342c88314..7dc39f35a4cc 100644 --- a/arch/powerpc/sysdev/mpic_msi.c +++ b/arch/powerpc/sysdev/mpic_msi.c | |||
@@ -35,7 +35,7 @@ static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic) | |||
35 | const struct irq_domain_ops *ops = mpic->irqhost->ops; | 35 | const struct irq_domain_ops *ops = mpic->irqhost->ops; |
36 | struct device_node *np; | 36 | struct device_node *np; |
37 | int flags, index, i; | 37 | int flags, index, i; |
38 | struct of_irq oirq; | 38 | struct of_phandle_args oirq; |
39 | 39 | ||
40 | pr_debug("mpic: found U3, guessing msi allocator setup\n"); | 40 | pr_debug("mpic: found U3, guessing msi allocator setup\n"); |
41 | 41 | ||
@@ -63,9 +63,9 @@ static int mpic_msi_reserve_u3_hwirqs(struct mpic *mpic) | |||
63 | pr_debug("mpic: mapping hwirqs for %s\n", np->full_name); | 63 | pr_debug("mpic: mapping hwirqs for %s\n", np->full_name); |
64 | 64 | ||
65 | index = 0; | 65 | index = 0; |
66 | while (of_irq_map_one(np, index++, &oirq) == 0) { | 66 | while (of_irq_parse_one(np, index++, &oirq) == 0) { |
67 | ops->xlate(mpic->irqhost, NULL, oirq.specifier, | 67 | ops->xlate(mpic->irqhost, NULL, oirq.args, |
68 | oirq.size, &hwirq, &flags); | 68 | oirq.args_count, &hwirq, &flags); |
69 | msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, hwirq); | 69 | msi_bitmap_reserve_hwirq(&mpic->msi_bitmap, hwirq); |
70 | } | 70 | } |
71 | } | 71 | } |
diff --git a/arch/powerpc/sysdev/mpic_timer.c b/arch/powerpc/sysdev/mpic_timer.c index c06db92a4fb1..22d7d57eead9 100644 --- a/arch/powerpc/sysdev/mpic_timer.c +++ b/arch/powerpc/sysdev/mpic_timer.c | |||
@@ -19,7 +19,9 @@ | |||
19 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/of.h> | 21 | #include <linux/of.h> |
22 | #include <linux/of_address.h> | ||
22 | #include <linux/of_device.h> | 23 | #include <linux/of_device.h> |
24 | #include <linux/of_irq.h> | ||
23 | #include <linux/syscore_ops.h> | 25 | #include <linux/syscore_ops.h> |
24 | #include <sysdev/fsl_soc.h> | 26 | #include <sysdev/fsl_soc.h> |
25 | #include <asm/io.h> | 27 | #include <asm/io.h> |
diff --git a/arch/powerpc/sysdev/mv64x60_dev.c b/arch/powerpc/sysdev/mv64x60_dev.c index 4a25c26f0bf4..a3a8fad8537d 100644 --- a/arch/powerpc/sysdev/mv64x60_dev.c +++ b/arch/powerpc/sysdev/mv64x60_dev.c | |||
@@ -228,7 +228,7 @@ static struct platform_device * __init mv64x60_eth_register_shared_pdev( | |||
228 | 228 | ||
229 | if (id == 0) { | 229 | if (id == 0) { |
230 | pdev = platform_device_register_simple("orion-mdio", -1, &r[1], 1); | 230 | pdev = platform_device_register_simple("orion-mdio", -1, &r[1], 1); |
231 | if (!pdev) | 231 | if (IS_ERR(pdev)) |
232 | return pdev; | 232 | return pdev; |
233 | } | 233 | } |
234 | 234 | ||
diff --git a/arch/powerpc/sysdev/of_rtc.c b/arch/powerpc/sysdev/of_rtc.c index c9e803f3e267..6f54b54b1328 100644 --- a/arch/powerpc/sysdev/of_rtc.c +++ b/arch/powerpc/sysdev/of_rtc.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
12 | #include <linux/of.h> | 12 | #include <linux/of.h> |
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/of_address.h> | ||
14 | #include <linux/of_platform.h> | 15 | #include <linux/of_platform.h> |
15 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
16 | 17 | ||
diff --git a/arch/powerpc/sysdev/ppc4xx_ocm.c b/arch/powerpc/sysdev/ppc4xx_ocm.c index 1b15f93479c3..b7c43453236d 100644 --- a/arch/powerpc/sysdev/ppc4xx_ocm.c +++ b/arch/powerpc/sysdev/ppc4xx_ocm.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
27 | #include <linux/dma-mapping.h> | 27 | #include <linux/dma-mapping.h> |
28 | #include <linux/of.h> | 28 | #include <linux/of.h> |
29 | #include <linux/of_address.h> | ||
29 | #include <asm/rheap.h> | 30 | #include <asm/rheap.h> |
30 | #include <asm/ppc4xx_ocm.h> | 31 | #include <asm/ppc4xx_ocm.h> |
31 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
diff --git a/arch/powerpc/sysdev/ppc4xx_soc.c b/arch/powerpc/sysdev/ppc4xx_soc.c index 0debcc31ad70..5c77c9ba33aa 100644 --- a/arch/powerpc/sysdev/ppc4xx_soc.c +++ b/arch/powerpc/sysdev/ppc4xx_soc.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/errno.h> | 19 | #include <linux/errno.h> |
20 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
21 | #include <linux/irq.h> | 21 | #include <linux/irq.h> |
22 | #include <linux/of_irq.h> | ||
22 | #include <linux/of_platform.h> | 23 | #include <linux/of_platform.h> |
23 | 24 | ||
24 | #include <asm/dcr.h> | 25 | #include <asm/dcr.h> |
diff --git a/arch/powerpc/sysdev/scom.c b/arch/powerpc/sysdev/scom.c index 9193e12df695..6f5a8d177c42 100644 --- a/arch/powerpc/sysdev/scom.c +++ b/arch/powerpc/sysdev/scom.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <asm/debug.h> | 25 | #include <asm/debug.h> |
26 | #include <asm/prom.h> | 26 | #include <asm/prom.h> |
27 | #include <asm/scom.h> | 27 | #include <asm/scom.h> |
28 | #include <asm/uaccess.h> | ||
28 | 29 | ||
29 | const struct scom_controller *scom_controller; | 30 | const struct scom_controller *scom_controller; |
30 | EXPORT_SYMBOL_GPL(scom_controller); | 31 | EXPORT_SYMBOL_GPL(scom_controller); |
@@ -53,7 +54,7 @@ scom_map_t scom_map_device(struct device_node *dev, int index) | |||
53 | { | 54 | { |
54 | struct device_node *parent; | 55 | struct device_node *parent; |
55 | unsigned int cells, size; | 56 | unsigned int cells, size; |
56 | const u32 *prop; | 57 | const __be32 *prop, *sprop; |
57 | u64 reg, cnt; | 58 | u64 reg, cnt; |
58 | scom_map_t ret; | 59 | scom_map_t ret; |
59 | 60 | ||
@@ -62,12 +63,24 @@ scom_map_t scom_map_device(struct device_node *dev, int index) | |||
62 | if (parent == NULL) | 63 | if (parent == NULL) |
63 | return 0; | 64 | return 0; |
64 | 65 | ||
65 | prop = of_get_property(parent, "#scom-cells", NULL); | 66 | /* |
66 | cells = prop ? *prop : 1; | 67 | * We support "scom-reg" properties for adding scom registers |
67 | 68 | * to a random device-tree node with an explicit scom-parent | |
69 | * | ||
70 | * We also support the simple "reg" property if the device is | ||
71 | * a direct child of a scom controller. | ||
72 | * | ||
73 | * In case both exist, "scom-reg" takes precedence. | ||
74 | */ | ||
68 | prop = of_get_property(dev, "scom-reg", &size); | 75 | prop = of_get_property(dev, "scom-reg", &size); |
76 | sprop = of_get_property(parent, "#scom-cells", NULL); | ||
77 | if (!prop && parent == dev->parent) { | ||
78 | prop = of_get_property(dev, "reg", &size); | ||
79 | sprop = of_get_property(parent, "#address-cells", NULL); | ||
80 | } | ||
69 | if (!prop) | 81 | if (!prop) |
70 | return 0; | 82 | return NULL; |
83 | cells = sprop ? be32_to_cpup(sprop) : 1; | ||
71 | size >>= 2; | 84 | size >>= 2; |
72 | 85 | ||
73 | if (index >= (size / (2*cells))) | 86 | if (index >= (size / (2*cells))) |
@@ -86,62 +99,89 @@ EXPORT_SYMBOL_GPL(scom_map_device); | |||
86 | #ifdef CONFIG_SCOM_DEBUGFS | 99 | #ifdef CONFIG_SCOM_DEBUGFS |
87 | struct scom_debug_entry { | 100 | struct scom_debug_entry { |
88 | struct device_node *dn; | 101 | struct device_node *dn; |
89 | unsigned long addr; | 102 | struct debugfs_blob_wrapper path; |
90 | scom_map_t map; | 103 | char name[16]; |
91 | spinlock_t lock; | ||
92 | char name[8]; | ||
93 | struct debugfs_blob_wrapper blob; | ||
94 | }; | 104 | }; |
95 | 105 | ||
96 | static int scom_addr_set(void *data, u64 val) | 106 | static ssize_t scom_debug_read(struct file *filp, char __user *ubuf, |
107 | size_t count, loff_t *ppos) | ||
97 | { | 108 | { |
98 | struct scom_debug_entry *ent = data; | 109 | struct scom_debug_entry *ent = filp->private_data; |
99 | 110 | u64 __user *ubuf64 = (u64 __user *)ubuf; | |
100 | ent->addr = 0; | 111 | loff_t off = *ppos; |
101 | scom_unmap(ent->map); | 112 | ssize_t done = 0; |
102 | 113 | u64 reg, reg_cnt, val; | |
103 | ent->map = scom_map(ent->dn, val, 1); | 114 | scom_map_t map; |
104 | if (scom_map_ok(ent->map)) | 115 | int rc; |
105 | ent->addr = val; | 116 | |
106 | else | 117 | if (off < 0 || (off & 7) || (count & 7)) |
107 | return -EFAULT; | 118 | return -EINVAL; |
108 | 119 | reg = off >> 3; | |
109 | return 0; | 120 | reg_cnt = count >> 3; |
110 | } | 121 | |
111 | 122 | map = scom_map(ent->dn, reg, reg_cnt); | |
112 | static int scom_addr_get(void *data, u64 *val) | 123 | if (!scom_map_ok(map)) |
113 | { | 124 | return -ENXIO; |
114 | struct scom_debug_entry *ent = data; | 125 | |
115 | *val = ent->addr; | 126 | for (reg = 0; reg < reg_cnt; reg++) { |
116 | return 0; | 127 | rc = scom_read(map, reg, &val); |
128 | if (!rc) | ||
129 | rc = put_user(val, ubuf64); | ||
130 | if (rc) { | ||
131 | if (!done) | ||
132 | done = rc; | ||
133 | break; | ||
134 | } | ||
135 | ubuf64++; | ||
136 | *ppos += 8; | ||
137 | done += 8; | ||
138 | } | ||
139 | scom_unmap(map); | ||
140 | return done; | ||
117 | } | 141 | } |
118 | DEFINE_SIMPLE_ATTRIBUTE(scom_addr_fops, scom_addr_get, scom_addr_set, | ||
119 | "0x%llx\n"); | ||
120 | 142 | ||
121 | static int scom_val_set(void *data, u64 val) | 143 | static ssize_t scom_debug_write(struct file* filp, const char __user *ubuf, |
144 | size_t count, loff_t *ppos) | ||
122 | { | 145 | { |
123 | struct scom_debug_entry *ent = data; | 146 | struct scom_debug_entry *ent = filp->private_data; |
124 | 147 | u64 __user *ubuf64 = (u64 __user *)ubuf; | |
125 | if (!scom_map_ok(ent->map)) | 148 | loff_t off = *ppos; |
126 | return -EFAULT; | 149 | ssize_t done = 0; |
127 | 150 | u64 reg, reg_cnt, val; | |
128 | scom_write(ent->map, 0, val); | 151 | scom_map_t map; |
129 | 152 | int rc; | |
130 | return 0; | 153 | |
154 | if (off < 0 || (off & 7) || (count & 7)) | ||
155 | return -EINVAL; | ||
156 | reg = off >> 3; | ||
157 | reg_cnt = count >> 3; | ||
158 | |||
159 | map = scom_map(ent->dn, reg, reg_cnt); | ||
160 | if (!scom_map_ok(map)) | ||
161 | return -ENXIO; | ||
162 | |||
163 | for (reg = 0; reg < reg_cnt; reg++) { | ||
164 | rc = get_user(val, ubuf64); | ||
165 | if (!rc) | ||
166 | rc = scom_write(map, reg, val); | ||
167 | if (rc) { | ||
168 | if (!done) | ||
169 | done = rc; | ||
170 | break; | ||
171 | } | ||
172 | ubuf64++; | ||
173 | done += 8; | ||
174 | } | ||
175 | scom_unmap(map); | ||
176 | return done; | ||
131 | } | 177 | } |
132 | 178 | ||
133 | static int scom_val_get(void *data, u64 *val) | 179 | static const struct file_operations scom_debug_fops = { |
134 | { | 180 | .read = scom_debug_read, |
135 | struct scom_debug_entry *ent = data; | 181 | .write = scom_debug_write, |
136 | 182 | .open = simple_open, | |
137 | if (!scom_map_ok(ent->map)) | 183 | .llseek = default_llseek, |
138 | return -EFAULT; | 184 | }; |
139 | |||
140 | *val = scom_read(ent->map, 0); | ||
141 | return 0; | ||
142 | } | ||
143 | DEFINE_SIMPLE_ATTRIBUTE(scom_val_fops, scom_val_get, scom_val_set, | ||
144 | "0x%llx\n"); | ||
145 | 185 | ||
146 | static int scom_debug_init_one(struct dentry *root, struct device_node *dn, | 186 | static int scom_debug_init_one(struct dentry *root, struct device_node *dn, |
147 | int i) | 187 | int i) |
@@ -154,11 +194,9 @@ static int scom_debug_init_one(struct dentry *root, struct device_node *dn, | |||
154 | return -ENOMEM; | 194 | return -ENOMEM; |
155 | 195 | ||
156 | ent->dn = of_node_get(dn); | 196 | ent->dn = of_node_get(dn); |
157 | ent->map = SCOM_MAP_INVALID; | 197 | snprintf(ent->name, 16, "%08x", i); |
158 | spin_lock_init(&ent->lock); | 198 | ent->path.data = (void*) dn->full_name; |
159 | snprintf(ent->name, 8, "scom%d", i); | 199 | ent->path.size = strlen(dn->full_name); |
160 | ent->blob.data = (void*) dn->full_name; | ||
161 | ent->blob.size = strlen(dn->full_name); | ||
162 | 200 | ||
163 | dir = debugfs_create_dir(ent->name, root); | 201 | dir = debugfs_create_dir(ent->name, root); |
164 | if (!dir) { | 202 | if (!dir) { |
@@ -167,9 +205,8 @@ static int scom_debug_init_one(struct dentry *root, struct device_node *dn, | |||
167 | return -1; | 205 | return -1; |
168 | } | 206 | } |
169 | 207 | ||
170 | debugfs_create_file("addr", 0600, dir, ent, &scom_addr_fops); | 208 | debugfs_create_blob("devspec", 0400, dir, &ent->path); |
171 | debugfs_create_file("value", 0600, dir, ent, &scom_val_fops); | 209 | debugfs_create_file("access", 0600, dir, ent, &scom_debug_fops); |
172 | debugfs_create_blob("path", 0400, dir, &ent->blob); | ||
173 | 210 | ||
174 | return 0; | 211 | return 0; |
175 | } | 212 | } |
@@ -185,8 +222,13 @@ static int scom_debug_init(void) | |||
185 | return -1; | 222 | return -1; |
186 | 223 | ||
187 | i = rc = 0; | 224 | i = rc = 0; |
188 | for_each_node_with_property(dn, "scom-controller") | 225 | for_each_node_with_property(dn, "scom-controller") { |
189 | rc |= scom_debug_init_one(root, dn, i++); | 226 | int id = of_get_ibm_chip_id(dn); |
227 | if (id == -1) | ||
228 | id = i; | ||
229 | rc |= scom_debug_init_one(root, dn, id); | ||
230 | i++; | ||
231 | } | ||
190 | 232 | ||
191 | return rc; | 233 | return rc; |
192 | } | 234 | } |
diff --git a/arch/powerpc/sysdev/xics/ics-opal.c b/arch/powerpc/sysdev/xics/ics-opal.c index 39d72212655e..3c6ee1b64e5d 100644 --- a/arch/powerpc/sysdev/xics/ics-opal.c +++ b/arch/powerpc/sysdev/xics/ics-opal.c | |||
@@ -112,6 +112,7 @@ static int ics_opal_set_affinity(struct irq_data *d, | |||
112 | bool force) | 112 | bool force) |
113 | { | 113 | { |
114 | unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d); | 114 | unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d); |
115 | __be16 oserver; | ||
115 | int16_t server; | 116 | int16_t server; |
116 | int8_t priority; | 117 | int8_t priority; |
117 | int64_t rc; | 118 | int64_t rc; |
@@ -120,13 +121,13 @@ static int ics_opal_set_affinity(struct irq_data *d, | |||
120 | if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS) | 121 | if (hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS) |
121 | return -1; | 122 | return -1; |
122 | 123 | ||
123 | rc = opal_get_xive(hw_irq, &server, &priority); | 124 | rc = opal_get_xive(hw_irq, &oserver, &priority); |
124 | if (rc != OPAL_SUCCESS) { | 125 | if (rc != OPAL_SUCCESS) { |
125 | pr_err("%s: opal_set_xive(irq=%d [hw 0x%x] server=%x)" | 126 | pr_err("%s: opal_get_xive(irq=%d [hw 0x%x]) error %lld\n", |
126 | " error %lld\n", | 127 | __func__, d->irq, hw_irq, rc); |
127 | __func__, d->irq, hw_irq, server, rc); | ||
128 | return -1; | 128 | return -1; |
129 | } | 129 | } |
130 | server = be16_to_cpu(oserver); | ||
130 | 131 | ||
131 | wanted_server = xics_get_irq_server(d->irq, cpumask, 1); | 132 | wanted_server = xics_get_irq_server(d->irq, cpumask, 1); |
132 | if (wanted_server < 0) { | 133 | if (wanted_server < 0) { |
@@ -181,7 +182,7 @@ static int ics_opal_map(struct ics *ics, unsigned int virq) | |||
181 | { | 182 | { |
182 | unsigned int hw_irq = (unsigned int)virq_to_hw(virq); | 183 | unsigned int hw_irq = (unsigned int)virq_to_hw(virq); |
183 | int64_t rc; | 184 | int64_t rc; |
184 | int16_t server; | 185 | __be16 server; |
185 | int8_t priority; | 186 | int8_t priority; |
186 | 187 | ||
187 | if (WARN_ON(hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS)) | 188 | if (WARN_ON(hw_irq == XICS_IPI || hw_irq == XICS_IRQ_SPURIOUS)) |
@@ -201,7 +202,7 @@ static int ics_opal_map(struct ics *ics, unsigned int virq) | |||
201 | static void ics_opal_mask_unknown(struct ics *ics, unsigned long vec) | 202 | static void ics_opal_mask_unknown(struct ics *ics, unsigned long vec) |
202 | { | 203 | { |
203 | int64_t rc; | 204 | int64_t rc; |
204 | int16_t server; | 205 | __be16 server; |
205 | int8_t priority; | 206 | int8_t priority; |
206 | 207 | ||
207 | /* Check if HAL knows about this interrupt */ | 208 | /* Check if HAL knows about this interrupt */ |
@@ -215,14 +216,14 @@ static void ics_opal_mask_unknown(struct ics *ics, unsigned long vec) | |||
215 | static long ics_opal_get_server(struct ics *ics, unsigned long vec) | 216 | static long ics_opal_get_server(struct ics *ics, unsigned long vec) |
216 | { | 217 | { |
217 | int64_t rc; | 218 | int64_t rc; |
218 | int16_t server; | 219 | __be16 server; |
219 | int8_t priority; | 220 | int8_t priority; |
220 | 221 | ||
221 | /* Check if HAL knows about this interrupt */ | 222 | /* Check if HAL knows about this interrupt */ |
222 | rc = opal_get_xive(vec, &server, &priority); | 223 | rc = opal_get_xive(vec, &server, &priority); |
223 | if (rc != OPAL_SUCCESS) | 224 | if (rc != OPAL_SUCCESS) |
224 | return -1; | 225 | return -1; |
225 | return ics_opal_unmangle_server(server); | 226 | return ics_opal_unmangle_server(be16_to_cpu(server)); |
226 | } | 227 | } |
227 | 228 | ||
228 | int __init ics_opal_init(void) | 229 | int __init ics_opal_init(void) |
diff --git a/arch/powerpc/sysdev/xilinx_intc.c b/arch/powerpc/sysdev/xilinx_intc.c index 8d73c3c0bee6..83f943a8e0db 100644 --- a/arch/powerpc/sysdev/xilinx_intc.c +++ b/arch/powerpc/sysdev/xilinx_intc.c | |||
@@ -23,6 +23,8 @@ | |||
23 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
24 | #include <linux/irq.h> | 24 | #include <linux/irq.h> |
25 | #include <linux/of.h> | 25 | #include <linux/of.h> |
26 | #include <linux/of_address.h> | ||
27 | #include <linux/of_irq.h> | ||
26 | #include <asm/io.h> | 28 | #include <asm/io.h> |
27 | #include <asm/processor.h> | 29 | #include <asm/processor.h> |
28 | #include <asm/i8259.h> | 30 | #include <asm/i8259.h> |