diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2013-10-11 03:23:53 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2013-10-11 03:23:53 -0400 |
commit | 3ad26e5c4459d3793ad65bc8929037c70515df83 (patch) | |
tree | 434327df7942878383e372988eb5f3bccb25de12 /arch/powerpc | |
parent | 5293bf97a27e1be8ac6096aa198ff6a9e3e6837c (diff) | |
parent | 18461960cbf50bf345ef0667d45d5f64de8fb893 (diff) |
Merge branch 'for-kvm' into next
Topic branch for commits that the KVM tree might want to pull
in separately.
Hand merged a few files due to conflicts with the LE stuff
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc')
24 files changed, 410 insertions, 383 deletions
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h index ce6cc2a7b8b9..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); |
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_asm.h b/arch/powerpc/include/asm/ppc_asm.h index ce05bba0bfc6..8deaaad3b32f 100644 --- a/arch/powerpc/include/asm/ppc_asm.h +++ b/arch/powerpc/include/asm/ppc_asm.h | |||
@@ -98,88 +98,32 @@ 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 | ||
128 | * thread_struct: | ||
129 | */ | ||
130 | #define SAVE_FPR_TRANSACT(n, base) stfd n,THREAD_TRANSACT_FPR0+ \ | ||
131 | 8*TS_FPRWIDTH*(n)(base) | ||
132 | #define SAVE_2FPRS_TRANSACT(n, base) SAVE_FPR_TRANSACT(n, base); \ | ||
133 | SAVE_FPR_TRANSACT(n+1, base) | ||
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 | #ifdef __BIG_ENDIAN__ | 127 | #ifdef __BIG_ENDIAN__ |
184 | #define STXVD2X_ROT(n,b,base) STXVD2X(n,b,base) | 128 | #define STXVD2X_ROT(n,b,base) STXVD2X(n,b,base) |
185 | #define LXVD2X_ROT(n,b,base) LXVD2X(n,b,base) | 129 | #define LXVD2X_ROT(n,b,base) LXVD2X(n,b,base) |
@@ -191,43 +135,14 @@ END_FW_FTR_SECTION_IFSET(FW_FEATURE_SPLPAR) | |||
191 | #define LXVD2X_ROT(n,b,base) LXVD2X(n,b,base); \ | 135 | #define LXVD2X_ROT(n,b,base) LXVD2X(n,b,base); \ |
192 | XXSWAPD(n,n) | 136 | XXSWAPD(n,n) |
193 | #endif | 137 | #endif |
194 | |||
195 | #define SAVE_VSR_TRANSACT(n,b,base) li b,THREAD_TRANSACT_VSR0+(16*(n)); \ | ||
196 | STXVD2X_ROT(n,R##base,R##b) | ||
197 | #define SAVE_2VSRS_TRANSACT(n,b,base) SAVE_VSR_TRANSACT(n,b,base); \ | ||
198 | SAVE_VSR_TRANSACT(n+1,b,base) | ||
199 | #define SAVE_4VSRS_TRANSACT(n,b,base) SAVE_2VSRS_TRANSACT(n,b,base); \ | ||
200 | SAVE_2VSRS_TRANSACT(n+2,b,base) | ||
201 | #define SAVE_8VSRS_TRANSACT(n,b,base) SAVE_4VSRS_TRANSACT(n,b,base); \ | ||
202 | SAVE_4VSRS_TRANSACT(n+4,b,base) | ||
203 | #define SAVE_16VSRS_TRANSACT(n,b,base) SAVE_8VSRS_TRANSACT(n,b,base); \ | ||
204 | SAVE_8VSRS_TRANSACT(n+8,b,base) | ||
205 | #define SAVE_32VSRS_TRANSACT(n,b,base) SAVE_16VSRS_TRANSACT(n,b,base); \ | ||
206 | SAVE_16VSRS_TRANSACT(n+16,b,base) | ||
207 | |||
208 | #define REST_VSR_TRANSACT(n,b,base) li b,THREAD_TRANSACT_VSR0+(16*(n)); \ | ||
209 | LXVD2X_ROT(n,R##base,R##b) | ||
210 | #define REST_2VSRS_TRANSACT(n,b,base) REST_VSR_TRANSACT(n,b,base); \ | ||
211 | REST_VSR_TRANSACT(n+1,b,base) | ||
212 | #define REST_4VSRS_TRANSACT(n,b,base) REST_2VSRS_TRANSACT(n,b,base); \ | ||
213 | REST_2VSRS_TRANSACT(n+2,b,base) | ||
214 | #define REST_8VSRS_TRANSACT(n,b,base) REST_4VSRS_TRANSACT(n,b,base); \ | ||
215 | REST_4VSRS_TRANSACT(n+4,b,base) | ||
216 | #define REST_16VSRS_TRANSACT(n,b,base) REST_8VSRS_TRANSACT(n,b,base); \ | ||
217 | REST_8VSRS_TRANSACT(n+8,b,base) | ||
218 | #define REST_32VSRS_TRANSACT(n,b,base) REST_16VSRS_TRANSACT(n,b,base); \ | ||
219 | REST_16VSRS_TRANSACT(n+16,b,base) | ||
220 | |||
221 | /* Save the lower 32 VSRs in the thread VSR region */ | 138 | /* Save the lower 32 VSRs in the thread VSR region */ |
222 | #define SAVE_VSR(n,b,base) li b,THREAD_VSR0+(16*(n)); \ | 139 | #define SAVE_VSR(n,b,base) li b,16*(n); STXVD2X_ROT(n,R##base,R##b) |
223 | STXVD2X_ROT(n,R##base,R##b) | ||
224 | #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) |
225 | #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) |
226 | #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) |
227 | #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) |
228 | #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) |
229 | #define REST_VSR(n,b,base) li b,THREAD_VSR0+(16*(n)); \ | 145 | #define REST_VSR(n,b,base) li b,16*(n); LXVD2X_ROT(n,R##base,R##b) |
230 | LXVD2X_ROT(n,R##base,R##b) | ||
231 | #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) |
232 | #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) |
233 | #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) |
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h index 82c6ee9df9a1..c1583070937d 100644 --- a/arch/powerpc/include/asm/processor.h +++ b/arch/powerpc/include/asm/processor.h | |||
@@ -152,8 +152,20 @@ typedef struct { | |||
152 | unsigned long seg; | 152 | unsigned long seg; |
153 | } mm_segment_t; | 153 | } mm_segment_t; |
154 | 154 | ||
155 | #define TS_FPR(i) fpr[i][TS_FPROFFSET] | 155 | #define TS_FPR(i) fp_state.fpr[i][TS_FPROFFSET] |
156 | #define TS_TRANS_FPR(i) transact_fpr[i][TS_FPROFFSET] | 156 | #define TS_TRANS_FPR(i) transact_fp.fpr[i][TS_FPROFFSET] |
157 | |||
158 | /* FP and VSX 0-31 register set */ | ||
159 | struct thread_fp_state { | ||
160 | u64 fpr[32][TS_FPRWIDTH] __attribute__((aligned(16))); | ||
161 | u64 fpscr; /* Floating point status */ | ||
162 | }; | ||
163 | |||
164 | /* Complete AltiVec register set including VSCR */ | ||
165 | struct thread_vr_state { | ||
166 | vector128 vr[32] __attribute__((aligned(16))); | ||
167 | vector128 vscr __attribute__((aligned(16))); | ||
168 | }; | ||
157 | 169 | ||
158 | struct thread_struct { | 170 | struct thread_struct { |
159 | unsigned long ksp; /* Kernel stack pointer */ | 171 | unsigned long ksp; /* Kernel stack pointer */ |
@@ -206,13 +218,8 @@ struct thread_struct { | |||
206 | unsigned long dvc2; | 218 | unsigned long dvc2; |
207 | #endif | 219 | #endif |
208 | #endif | 220 | #endif |
209 | /* FP and VSX 0-31 register set */ | 221 | struct thread_fp_state fp_state; |
210 | double fpr[32][TS_FPRWIDTH] __attribute__((aligned(16))); | 222 | struct thread_fp_state *fp_save_area; |
211 | struct { | ||
212 | |||
213 | unsigned int pad; | ||
214 | unsigned int val; /* Floating point status */ | ||
215 | } fpscr; | ||
216 | int fpexc_mode; /* floating-point exception mode */ | 223 | int fpexc_mode; /* floating-point exception mode */ |
217 | unsigned int align_ctl; /* alignment handling control */ | 224 | unsigned int align_ctl; /* alignment handling control */ |
218 | #ifdef CONFIG_PPC64 | 225 | #ifdef CONFIG_PPC64 |
@@ -230,10 +237,8 @@ struct thread_struct { | |||
230 | struct arch_hw_breakpoint hw_brk; /* info on the hardware breakpoint */ | 237 | struct arch_hw_breakpoint hw_brk; /* info on the hardware breakpoint */ |
231 | unsigned long trap_nr; /* last trap # on this thread */ | 238 | unsigned long trap_nr; /* last trap # on this thread */ |
232 | #ifdef CONFIG_ALTIVEC | 239 | #ifdef CONFIG_ALTIVEC |
233 | /* Complete AltiVec register set */ | 240 | struct thread_vr_state vr_state; |
234 | vector128 vr[32] __attribute__((aligned(16))); | 241 | struct thread_vr_state *vr_save_area; |
235 | /* AltiVec status */ | ||
236 | vector128 vscr __attribute__((aligned(16))); | ||
237 | unsigned long vrsave; | 242 | unsigned long vrsave; |
238 | int used_vr; /* set if process has used altivec */ | 243 | int used_vr; /* set if process has used altivec */ |
239 | #endif /* CONFIG_ALTIVEC */ | 244 | #endif /* CONFIG_ALTIVEC */ |
@@ -270,13 +275,8 @@ struct thread_struct { | |||
270 | * transact_fpr[] is the new set of transactional values. | 275 | * transact_fpr[] is the new set of transactional values. |
271 | * VRs work the same way. | 276 | * VRs work the same way. |
272 | */ | 277 | */ |
273 | double transact_fpr[32][TS_FPRWIDTH]; | 278 | struct thread_fp_state transact_fp; |
274 | struct { | 279 | struct thread_vr_state transact_vr; |
275 | unsigned int pad; | ||
276 | unsigned int val; /* Floating point status */ | ||
277 | } transact_fpscr; | ||
278 | vector128 transact_vr[32] __attribute__((aligned(16))); | ||
279 | vector128 transact_vscr __attribute__((aligned(16))); | ||
280 | unsigned long transact_vrsave; | 280 | unsigned long transact_vrsave; |
281 | #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ | 281 | #endif /* CONFIG_PPC_TRANSACTIONAL_MEM */ |
282 | #ifdef CONFIG_KVM_BOOK3S_32_HANDLER | 282 | #ifdef CONFIG_KVM_BOOK3S_32_HANDLER |
@@ -330,8 +330,6 @@ struct thread_struct { | |||
330 | .ksp = INIT_SP, \ | 330 | .ksp = INIT_SP, \ |
331 | .regs = (struct pt_regs *)INIT_SP - 1, /* XXX bogus, I think */ \ | 331 | .regs = (struct pt_regs *)INIT_SP - 1, /* XXX bogus, I think */ \ |
332 | .fs = KERNEL_DS, \ | 332 | .fs = KERNEL_DS, \ |
333 | .fpr = {{0}}, \ | ||
334 | .fpscr = { .val = 0, }, \ | ||
335 | .fpexc_mode = 0, \ | 333 | .fpexc_mode = 0, \ |
336 | .ppr = INIT_PPR, \ | 334 | .ppr = INIT_PPR, \ |
337 | } | 335 | } |
@@ -369,6 +367,11 @@ extern int set_endian(struct task_struct *tsk, unsigned int val); | |||
369 | extern int get_unalign_ctl(struct task_struct *tsk, unsigned long adr); | 367 | extern int get_unalign_ctl(struct task_struct *tsk, unsigned long adr); |
370 | extern int set_unalign_ctl(struct task_struct *tsk, unsigned int val); | 368 | extern int set_unalign_ctl(struct task_struct *tsk, unsigned int val); |
371 | 369 | ||
370 | extern void load_fp_state(struct thread_fp_state *fp); | ||
371 | extern void store_fp_state(struct thread_fp_state *fp); | ||
372 | extern void load_vr_state(struct thread_vr_state *vr); | ||
373 | extern void store_vr_state(struct thread_vr_state *vr); | ||
374 | |||
372 | static inline unsigned int __unpack_fe01(unsigned long msr_bits) | 375 | static inline unsigned int __unpack_fe01(unsigned long msr_bits) |
373 | { | 376 | { |
374 | return ((msr_bits & MSR_FE0) >> 10) | ((msr_bits & MSR_FE1) >> 8); | 377 | return ((msr_bits & MSR_FE0) >> 10) | ((msr_bits & MSR_FE1) >> 8); |
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/kernel/align.c b/arch/powerpc/kernel/align.c index 59f70adcbcd9..6e3f9772aaba 100644 --- a/arch/powerpc/kernel/align.c +++ b/arch/powerpc/kernel/align.c | |||
@@ -652,9 +652,9 @@ static int emulate_vsx(unsigned char __user *addr, unsigned int reg, | |||
652 | flush_vsx_to_thread(current); | 652 | flush_vsx_to_thread(current); |
653 | 653 | ||
654 | if (reg < 32) | 654 | if (reg < 32) |
655 | ptr = (char *) ¤t->thread.fpr[reg][0]; | 655 | ptr = (char *) ¤t->thread.fp_state.fpr[reg][0]; |
656 | else | 656 | else |
657 | ptr = (char *) ¤t->thread.vr[reg - 32]; | 657 | ptr = (char *) ¤t->thread.vr_state.vr[reg - 32]; |
658 | 658 | ||
659 | lptr = (unsigned long *) ptr; | 659 | lptr = (unsigned long *) ptr; |
660 | 660 | ||
@@ -944,7 +944,7 @@ int fix_alignment(struct pt_regs *regs) | |||
944 | return -EFAULT; | 944 | return -EFAULT; |
945 | 945 | ||
946 | } else if (flags & F) { | 946 | } else if (flags & F) { |
947 | data.dd = current->thread.TS_FPR(reg); | 947 | data.ll = current->thread.TS_FPR(reg); |
948 | if (flags & S) { | 948 | if (flags & S) { |
949 | /* Single-precision FP store requires conversion... */ | 949 | /* Single-precision FP store requires conversion... */ |
950 | #ifdef CONFIG_PPC_FPU | 950 | #ifdef CONFIG_PPC_FPU |
@@ -1021,7 +1021,7 @@ int fix_alignment(struct pt_regs *regs) | |||
1021 | if (unlikely(ret)) | 1021 | if (unlikely(ret)) |
1022 | return -EFAULT; | 1022 | return -EFAULT; |
1023 | } else if (flags & F) | 1023 | } else if (flags & F) |
1024 | current->thread.TS_FPR(reg) = data.dd; | 1024 | current->thread.TS_FPR(reg) = data.ll; |
1025 | else | 1025 | else |
1026 | regs->gpr[reg] = data.ll; | 1026 | regs->gpr[reg] = data.ll; |
1027 | 1027 | ||
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 502c7a4e73f7..6278edddc3f8 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
@@ -90,16 +90,17 @@ int main(void) | |||
90 | DEFINE(THREAD_NORMSAVES, offsetof(struct thread_struct, normsave[0])); | 90 | DEFINE(THREAD_NORMSAVES, offsetof(struct thread_struct, normsave[0])); |
91 | #endif | 91 | #endif |
92 | DEFINE(THREAD_FPEXC_MODE, offsetof(struct thread_struct, fpexc_mode)); | 92 | DEFINE(THREAD_FPEXC_MODE, offsetof(struct thread_struct, fpexc_mode)); |
93 | DEFINE(THREAD_FPR0, offsetof(struct thread_struct, fpr[0])); | 93 | DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fp_state)); |
94 | 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)); | ||
95 | #ifdef CONFIG_ALTIVEC | 96 | #ifdef CONFIG_ALTIVEC |
96 | 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)); | ||
97 | DEFINE(THREAD_VRSAVE, offsetof(struct thread_struct, vrsave)); | 99 | DEFINE(THREAD_VRSAVE, offsetof(struct thread_struct, vrsave)); |
98 | DEFINE(THREAD_VSCR, offsetof(struct thread_struct, vscr)); | ||
99 | 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)); | ||
100 | #endif /* CONFIG_ALTIVEC */ | 102 | #endif /* CONFIG_ALTIVEC */ |
101 | #ifdef CONFIG_VSX | 103 | #ifdef CONFIG_VSX |
102 | DEFINE(THREAD_VSR0, offsetof(struct thread_struct, fpr)); | ||
103 | DEFINE(THREAD_USED_VSR, offsetof(struct thread_struct, used_vsr)); | 104 | DEFINE(THREAD_USED_VSR, offsetof(struct thread_struct, used_vsr)); |
104 | #endif /* CONFIG_VSX */ | 105 | #endif /* CONFIG_VSX */ |
105 | #ifdef CONFIG_PPC64 | 106 | #ifdef CONFIG_PPC64 |
@@ -143,20 +144,12 @@ int main(void) | |||
143 | DEFINE(THREAD_TM_PPR, offsetof(struct thread_struct, tm_ppr)); | 144 | DEFINE(THREAD_TM_PPR, offsetof(struct thread_struct, tm_ppr)); |
144 | DEFINE(THREAD_TM_DSCR, offsetof(struct thread_struct, tm_dscr)); | 145 | DEFINE(THREAD_TM_DSCR, offsetof(struct thread_struct, tm_dscr)); |
145 | DEFINE(PT_CKPT_REGS, offsetof(struct thread_struct, ckpt_regs)); | 146 | DEFINE(PT_CKPT_REGS, offsetof(struct thread_struct, ckpt_regs)); |
146 | DEFINE(THREAD_TRANSACT_VR0, offsetof(struct thread_struct, | 147 | DEFINE(THREAD_TRANSACT_VRSTATE, offsetof(struct thread_struct, |
147 | transact_vr[0])); | 148 | transact_vr)); |
148 | DEFINE(THREAD_TRANSACT_VSCR, offsetof(struct thread_struct, | ||
149 | transact_vscr)); | ||
150 | DEFINE(THREAD_TRANSACT_VRSAVE, offsetof(struct thread_struct, | 149 | DEFINE(THREAD_TRANSACT_VRSAVE, offsetof(struct thread_struct, |
151 | transact_vrsave)); | 150 | transact_vrsave)); |
152 | DEFINE(THREAD_TRANSACT_FPR0, offsetof(struct thread_struct, | 151 | DEFINE(THREAD_TRANSACT_FPSTATE, offsetof(struct thread_struct, |
153 | transact_fpr[0])); | 152 | transact_fp)); |
154 | DEFINE(THREAD_TRANSACT_FPSCR, offsetof(struct thread_struct, | ||
155 | transact_fpscr)); | ||
156 | #ifdef CONFIG_VSX | ||
157 | DEFINE(THREAD_TRANSACT_VSR0, offsetof(struct thread_struct, | ||
158 | transact_fpr[0])); | ||
159 | #endif | ||
160 | /* Local pt_regs on stack for Transactional Memory funcs. */ | 153 | /* Local pt_regs on stack for Transactional Memory funcs. */ |
161 | DEFINE(TM_FRAME_SIZE, STACK_FRAME_OVERHEAD + | 154 | DEFINE(TM_FRAME_SIZE, STACK_FRAME_OVERHEAD + |
162 | sizeof(struct pt_regs) + 16); | 155 | sizeof(struct pt_regs) + 16); |
diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S index caeaabf11a2f..4dca05e91e95 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,6 +81,26 @@ 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. |
@@ -147,9 +131,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX) | |||
147 | beq 1f | 131 | beq 1f |
148 | toreal(r4) | 132 | toreal(r4) |
149 | addi r4,r4,THREAD /* want last_task_used_math->thread */ | 133 | addi r4,r4,THREAD /* want last_task_used_math->thread */ |
150 | SAVE_32FPVSRS(0, R5, R4) | 134 | addi r8,r4,THREAD_FPSTATE |
135 | SAVE_32FPVSRS(0, R5, R8) | ||
151 | mffs fr0 | 136 | mffs fr0 |
152 | stfd fr0,THREAD_FPSCR(r4) | 137 | stfd fr0,FPSTATE_FPSCR(r8) |
153 | PPC_LL r5,PT_REGS(r4) | 138 | PPC_LL r5,PT_REGS(r4) |
154 | toreal(r5) | 139 | toreal(r5) |
155 | PPC_LL r4,_MSR-STACK_FRAME_OVERHEAD(r5) | 140 | PPC_LL r4,_MSR-STACK_FRAME_OVERHEAD(r5) |
@@ -160,7 +145,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX) | |||
160 | #endif /* CONFIG_SMP */ | 145 | #endif /* CONFIG_SMP */ |
161 | /* enable use of FP after return */ | 146 | /* enable use of FP after return */ |
162 | #ifdef CONFIG_PPC32 | 147 | #ifdef CONFIG_PPC32 |
163 | mfspr r5,SPRN_SPRG_THREAD /* current task's THREAD (phys) */ | 148 | mfspr r5,SPRN_SPRG_THREAD /* current task's THREAD (phys) */ |
164 | lwz r4,THREAD_FPEXC_MODE(r5) | 149 | lwz r4,THREAD_FPEXC_MODE(r5) |
165 | ori r9,r9,MSR_FP /* enable FP for current */ | 150 | ori r9,r9,MSR_FP /* enable FP for current */ |
166 | or r9,r9,r4 | 151 | or r9,r9,r4 |
@@ -172,9 +157,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX) | |||
172 | or r12,r12,r4 | 157 | or r12,r12,r4 |
173 | std r12,_MSR(r1) | 158 | std r12,_MSR(r1) |
174 | #endif | 159 | #endif |
175 | lfd fr0,THREAD_FPSCR(r5) | 160 | addi r7,r5,THREAD_FPSTATE |
161 | lfd fr0,FPSTATE_FPSCR(r7) | ||
176 | MTFSF_L(fr0) | 162 | MTFSF_L(fr0) |
177 | REST_32FPVSRS(0, R4, R5) | 163 | REST_32FPVSRS(0, R4, R7) |
178 | #ifndef CONFIG_SMP | 164 | #ifndef CONFIG_SMP |
179 | subi r4,r5,THREAD | 165 | subi r4,r5,THREAD |
180 | fromreal(r4) | 166 | fromreal(r4) |
@@ -206,11 +192,15 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX) | |||
206 | PPC_LCMPI 0,r3,0 | 192 | PPC_LCMPI 0,r3,0 |
207 | beqlr- /* if no previous owner, done */ | 193 | beqlr- /* if no previous owner, done */ |
208 | addi r3,r3,THREAD /* want THREAD of task */ | 194 | addi r3,r3,THREAD /* want THREAD of task */ |
195 | PPC_LL r6,THREAD_FPSAVEAREA(r3) | ||
209 | PPC_LL r5,PT_REGS(r3) | 196 | PPC_LL r5,PT_REGS(r3) |
210 | PPC_LCMPI 0,r5,0 | 197 | PPC_LCMPI 0,r6,0 |
211 | SAVE_32FPVSRS(0, R4 ,R3) | 198 | bne 2f |
199 | addi r6,r3,THREAD_FPSTATE | ||
200 | 2: PPC_LCMPI 0,r5,0 | ||
201 | SAVE_32FPVSRS(0, R4, R6) | ||
212 | mffs fr0 | 202 | mffs fr0 |
213 | stfd fr0,THREAD_FPSCR(r3) | 203 | stfd fr0,FPSTATE_FPSCR(r6) |
214 | beq 1f | 204 | beq 1f |
215 | PPC_LL r4,_MSR-STACK_FRAME_OVERHEAD(r5) | 205 | PPC_LL r4,_MSR-STACK_FRAME_OVERHEAD(r5) |
216 | li r3,MSR_FP|MSR_FE0|MSR_FE1 | 206 | li r3,MSR_FP|MSR_FE0|MSR_FE1 |
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index d8c34073b42a..3bd77edd7610 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c | |||
@@ -100,9 +100,13 @@ EXPORT_SYMBOL(start_thread); | |||
100 | 100 | ||
101 | #ifdef CONFIG_PPC_FPU | 101 | #ifdef CONFIG_PPC_FPU |
102 | EXPORT_SYMBOL(giveup_fpu); | 102 | EXPORT_SYMBOL(giveup_fpu); |
103 | EXPORT_SYMBOL(load_fp_state); | ||
104 | EXPORT_SYMBOL(store_fp_state); | ||
103 | #endif | 105 | #endif |
104 | #ifdef CONFIG_ALTIVEC | 106 | #ifdef CONFIG_ALTIVEC |
105 | EXPORT_SYMBOL(giveup_altivec); | 107 | EXPORT_SYMBOL(giveup_altivec); |
108 | EXPORT_SYMBOL(load_vr_state); | ||
109 | EXPORT_SYMBOL(store_vr_state); | ||
106 | #endif /* CONFIG_ALTIVEC */ | 110 | #endif /* CONFIG_ALTIVEC */ |
107 | #ifdef CONFIG_VSX | 111 | #ifdef CONFIG_VSX |
108 | EXPORT_SYMBOL(giveup_vsx); | 112 | EXPORT_SYMBOL(giveup_vsx); |
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 96d2fdf3aa9e..8649a3d629e1 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
@@ -1008,6 +1008,11 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
1008 | p->thread.ptrace_bps[0] = NULL; | 1008 | p->thread.ptrace_bps[0] = NULL; |
1009 | #endif | 1009 | #endif |
1010 | 1010 | ||
1011 | p->thread.fp_save_area = NULL; | ||
1012 | #ifdef CONFIG_ALTIVEC | ||
1013 | p->thread.vr_save_area = NULL; | ||
1014 | #endif | ||
1015 | |||
1011 | #ifdef CONFIG_PPC_STD_MMU_64 | 1016 | #ifdef CONFIG_PPC_STD_MMU_64 |
1012 | if (mmu_has_feature(MMU_FTR_SLB)) { | 1017 | if (mmu_has_feature(MMU_FTR_SLB)) { |
1013 | unsigned long sp_vsid; | 1018 | unsigned long sp_vsid; |
@@ -1113,12 +1118,12 @@ void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp) | |||
1113 | #ifdef CONFIG_VSX | 1118 | #ifdef CONFIG_VSX |
1114 | current->thread.used_vsr = 0; | 1119 | current->thread.used_vsr = 0; |
1115 | #endif | 1120 | #endif |
1116 | memset(current->thread.fpr, 0, sizeof(current->thread.fpr)); | 1121 | memset(¤t->thread.fp_state, 0, sizeof(current->thread.fp_state)); |
1117 | current->thread.fpscr.val = 0; | 1122 | current->thread.fp_save_area = NULL; |
1118 | #ifdef CONFIG_ALTIVEC | 1123 | #ifdef CONFIG_ALTIVEC |
1119 | memset(current->thread.vr, 0, sizeof(current->thread.vr)); | 1124 | memset(¤t->thread.vr_state, 0, sizeof(current->thread.vr_state)); |
1120 | memset(¤t->thread.vscr, 0, sizeof(current->thread.vscr)); | 1125 | current->thread.vr_state.vscr.u[3] = 0x00010000; /* Java mode disabled */ |
1121 | current->thread.vscr.u[3] = 0x00010000; /* Java mode disabled */ | 1126 | current->thread.vr_save_area = NULL; |
1122 | current->thread.vrsave = 0; | 1127 | current->thread.vrsave = 0; |
1123 | current->thread.used_vr = 0; | 1128 | current->thread.used_vr = 0; |
1124 | #endif /* CONFIG_ALTIVEC */ | 1129 | #endif /* CONFIG_ALTIVEC */ |
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 8d5d4e921a5e..1ca589c9ec6d 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; |
@@ -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 | memcpy(&tmp, &child->thread.TS_FPR(fpidx), | 1558 | memcpy(&tmp, &child->thread.fp_state.fpr, |
1558 | sizeof(long)); | 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 | memcpy(&child->thread.TS_FPR(fpidx), &data, | 1591 | memcpy(&child->thread.fp_state.fpr, &data, |
1591 | sizeof(long)); | 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; |
diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c index f51599e941c7..097f8dc426a0 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; |
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index b386b0be8d02..c094e28b3f10 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 | ||
@@ -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); |
@@ -1463,7 +1465,7 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka, | |||
1463 | 1465 | ||
1464 | regs->link = tramp; | 1466 | regs->link = tramp; |
1465 | 1467 | ||
1466 | current->thread.fpscr.val = 0; /* turn off all fp exceptions */ | 1468 | current->thread.fp_state.fpscr = 0; /* turn off all fp exceptions */ |
1467 | 1469 | ||
1468 | /* create a stack frame for the caller of the handler */ | 1470 | /* create a stack frame for the caller of the handler */ |
1469 | 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 8b51b0278106..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 |
diff --git a/arch/powerpc/kernel/tm.S b/arch/powerpc/kernel/tm.S index cd809eaa8b5c..761af4f0a632 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 | ||
@@ -157,10 +156,11 @@ _GLOBAL(tm_reclaim) | |||
157 | andis. r0, r4, MSR_VEC@h | 156 | andis. r0, r4, MSR_VEC@h |
158 | beq dont_backup_vec | 157 | beq dont_backup_vec |
159 | 158 | ||
160 | 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 */ | ||
161 | mfvscr vr0 | 161 | mfvscr vr0 |
162 | li r6, THREAD_TRANSACT_VSCR | 162 | li r6, VRSTATE_VSCR |
163 | stvx vr0, r3, r6 | 163 | stvx vr0, r7, r6 |
164 | dont_backup_vec: | 164 | dont_backup_vec: |
165 | mfspr r0, SPRN_VRSAVE | 165 | mfspr r0, SPRN_VRSAVE |
166 | std r0, THREAD_TRANSACT_VRSAVE(r3) | 166 | std r0, THREAD_TRANSACT_VRSAVE(r3) |
@@ -168,10 +168,11 @@ dont_backup_vec: | |||
168 | andi. r0, r4, MSR_FP | 168 | andi. r0, r4, MSR_FP |
169 | beq dont_backup_fp | 169 | beq dont_backup_fp |
170 | 170 | ||
171 | 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 */ | ||
172 | 173 | ||
173 | mffs fr0 | 174 | mffs fr0 |
174 | stfd fr0,THREAD_TRANSACT_FPSCR(r3) | 175 | stfd fr0,FPSTATE_FPSCR(r7) |
175 | 176 | ||
176 | dont_backup_fp: | 177 | dont_backup_fp: |
177 | /* The moment we treclaim, ALL of our GPRs will switch | 178 | /* The moment we treclaim, ALL of our GPRs will switch |
@@ -358,10 +359,11 @@ _GLOBAL(tm_recheckpoint) | |||
358 | andis. r0, r4, MSR_VEC@h | 359 | andis. r0, r4, MSR_VEC@h |
359 | beq dont_restore_vec | 360 | beq dont_restore_vec |
360 | 361 | ||
361 | li r5, THREAD_VSCR | 362 | addi r8, r3, THREAD_VRSTATE |
362 | lvx vr0, r3, r5 | 363 | li r5, VRSTATE_VSCR |
364 | lvx vr0, r8, r5 | ||
363 | mtvscr vr0 | 365 | mtvscr vr0 |
364 | REST_32VRS(0, r5, r3) /* r5 scratch, r3 THREAD ptr */ | 366 | REST_32VRS(0, r5, r8) /* r5 scratch, r8 ptr */ |
365 | dont_restore_vec: | 367 | dont_restore_vec: |
366 | ld r5, THREAD_VRSAVE(r3) | 368 | ld r5, THREAD_VRSAVE(r3) |
367 | mtspr SPRN_VRSAVE, r5 | 369 | mtspr SPRN_VRSAVE, r5 |
@@ -370,9 +372,10 @@ dont_restore_vec: | |||
370 | andi. r0, r4, MSR_FP | 372 | andi. r0, r4, MSR_FP |
371 | beq dont_restore_fp | 373 | beq dont_restore_fp |
372 | 374 | ||
373 | lfd fr0, THREAD_FPSCR(r3) | 375 | addi r8, r3, THREAD_FPSTATE |
376 | lfd fr0, FPSTATE_FPSCR(r8) | ||
374 | MTFSF_L(fr0) | 377 | MTFSF_L(fr0) |
375 | REST_32FPRS_VSRS(0, R4, R3) | 378 | REST_32FPRS_VSRS(0, R4, R8) |
376 | 379 | ||
377 | dont_restore_fp: | 380 | dont_restore_fp: |
378 | mtmsr r6 /* FP/Vec off again! */ | 381 | mtmsr r6 /* FP/Vec off again! */ |
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index f783c932faeb..f0a6814007a5 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
@@ -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 | } |
@@ -1069,7 +1069,7 @@ static int emulate_math(struct pt_regs *regs) | |||
1069 | return 0; | 1069 | return 0; |
1070 | case 1: { | 1070 | case 1: { |
1071 | int code = 0; | 1071 | int code = 0; |
1072 | code = __parse_fpscr(current->thread.fpscr.val); | 1072 | code = __parse_fpscr(current->thread.fp_state.fpscr); |
1073 | _exception(SIGFPE, regs, code, regs->nip); | 1073 | _exception(SIGFPE, regs, code, regs->nip); |
1074 | return 0; | 1074 | return 0; |
1075 | } | 1075 | } |
@@ -1371,8 +1371,6 @@ void facility_unavailable_exception(struct pt_regs *regs) | |||
1371 | 1371 | ||
1372 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM | 1372 | #ifdef CONFIG_PPC_TRANSACTIONAL_MEM |
1373 | 1373 | ||
1374 | extern void do_load_up_fpu(struct pt_regs *regs); | ||
1375 | |||
1376 | void fp_unavailable_tm(struct pt_regs *regs) | 1374 | void fp_unavailable_tm(struct pt_regs *regs) |
1377 | { | 1375 | { |
1378 | /* Note: This does not handle any kind of FP laziness. */ | 1376 | /* Note: This does not handle any kind of FP laziness. */ |
@@ -1403,8 +1401,6 @@ void fp_unavailable_tm(struct pt_regs *regs) | |||
1403 | } | 1401 | } |
1404 | 1402 | ||
1405 | #ifdef CONFIG_ALTIVEC | 1403 | #ifdef CONFIG_ALTIVEC |
1406 | extern void do_load_up_altivec(struct pt_regs *regs); | ||
1407 | |||
1408 | void altivec_unavailable_tm(struct pt_regs *regs) | 1404 | void altivec_unavailable_tm(struct pt_regs *regs) |
1409 | { | 1405 | { |
1410 | /* See the comments in fp_unavailable_tm(). This function operates | 1406 | /* See the comments in fp_unavailable_tm(). This function operates |
@@ -1634,7 +1630,7 @@ void altivec_assist_exception(struct pt_regs *regs) | |||
1634 | /* XXX quick hack for now: set the non-Java bit in the VSCR */ | 1630 | /* XXX quick hack for now: set the non-Java bit in the VSCR */ |
1635 | printk_ratelimited(KERN_ERR "Unrecognized altivec instruction " | 1631 | printk_ratelimited(KERN_ERR "Unrecognized altivec instruction " |
1636 | "in %s at %lx\n", current->comm, regs->nip); | 1632 | "in %s at %lx\n", current->comm, regs->nip); |
1637 | current->thread.vscr.u[3] |= 0x10000; | 1633 | current->thread.vr_state.vscr.u[3] |= 0x10000; |
1638 | } | 1634 | } |
1639 | } | 1635 | } |
1640 | #endif /* CONFIG_ALTIVEC */ | 1636 | #endif /* CONFIG_ALTIVEC */ |
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..eacda4eea2d7 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,7 +37,28 @@ _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. |
@@ -90,10 +89,11 @@ _GLOBAL(load_up_altivec) | |||
90 | /* Save VMX state to last_task_used_altivec's THREAD struct */ | 89 | /* Save VMX state to last_task_used_altivec's THREAD struct */ |
91 | toreal(r4) | 90 | toreal(r4) |
92 | addi r4,r4,THREAD | 91 | addi r4,r4,THREAD |
93 | SAVE_32VRS(0,r5,r4) | 92 | addi r7,r4,THREAD_VRSTATE |
93 | SAVE_32VRS(0,r5,r7) | ||
94 | mfvscr vr0 | 94 | mfvscr vr0 |
95 | li r10,THREAD_VSCR | 95 | li r10,VRSTATE_VSCR |
96 | stvx vr0,r10,r4 | 96 | stvx vr0,r10,r7 |
97 | /* Disable VMX for last_task_used_altivec */ | 97 | /* Disable VMX for last_task_used_altivec */ |
98 | PPC_LL r5,PT_REGS(r4) | 98 | PPC_LL r5,PT_REGS(r4) |
99 | toreal(r5) | 99 | toreal(r5) |
@@ -125,12 +125,13 @@ _GLOBAL(load_up_altivec) | |||
125 | oris r12,r12,MSR_VEC@h | 125 | oris r12,r12,MSR_VEC@h |
126 | std r12,_MSR(r1) | 126 | std r12,_MSR(r1) |
127 | #endif | 127 | #endif |
128 | addi r7,r5,THREAD_VRSTATE | ||
128 | li r4,1 | 129 | li r4,1 |
129 | li r10,THREAD_VSCR | 130 | li r10,VRSTATE_VSCR |
130 | stw r4,THREAD_USED_VR(r5) | 131 | stw r4,THREAD_USED_VR(r5) |
131 | lvx vr0,r10,r5 | 132 | lvx vr0,r10,r7 |
132 | mtvscr vr0 | 133 | mtvscr vr0 |
133 | REST_32VRS(0,r4,r5) | 134 | REST_32VRS(0,r4,r7) |
134 | #ifndef CONFIG_SMP | 135 | #ifndef CONFIG_SMP |
135 | /* Update last_task_used_altivec to 'current' */ | 136 | /* Update last_task_used_altivec to 'current' */ |
136 | subi r4,r5,THREAD /* Back to 'current' */ | 137 | subi r4,r5,THREAD /* Back to 'current' */ |
@@ -165,12 +166,16 @@ _GLOBAL(giveup_altivec) | |||
165 | PPC_LCMPI 0,r3,0 | 166 | PPC_LCMPI 0,r3,0 |
166 | beqlr /* if no previous owner, done */ | 167 | beqlr /* if no previous owner, done */ |
167 | addi r3,r3,THREAD /* want THREAD of task */ | 168 | addi r3,r3,THREAD /* want THREAD of task */ |
169 | PPC_LL r7,THREAD_VRSAVEAREA(r3) | ||
168 | PPC_LL r5,PT_REGS(r3) | 170 | PPC_LL r5,PT_REGS(r3) |
169 | PPC_LCMPI 0,r5,0 | 171 | PPC_LCMPI 0,r7,0 |
170 | SAVE_32VRS(0,r4,r3) | 172 | bne 2f |
173 | addi r7,r3,THREAD_VRSTATE | ||
174 | 2: PPC_LCMPI 0,r5,0 | ||
175 | SAVE_32VRS(0,r4,r7) | ||
171 | mfvscr vr0 | 176 | mfvscr vr0 |
172 | li r4,THREAD_VSCR | 177 | li r4,VRSTATE_VSCR |
173 | stvx vr0,r4,r3 | 178 | stvx vr0,r4,r7 |
174 | beq 1f | 179 | beq 1f |
175 | PPC_LL r4,_MSR-STACK_FRAME_OVERHEAD(r5) | 180 | PPC_LL r4,_MSR-STACK_FRAME_OVERHEAD(r5) |
176 | #ifdef CONFIG_VSX | 181 | #ifdef CONFIG_VSX |
diff --git a/arch/powerpc/kvm/book3s_pr.c b/arch/powerpc/kvm/book3s_pr.c index 27db1e665959..c0b48f96a91c 100644 --- a/arch/powerpc/kvm/book3s_pr.c +++ b/arch/powerpc/kvm/book3s_pr.c | |||
@@ -444,7 +444,7 @@ void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr) | |||
444 | #ifdef CONFIG_VSX | 444 | #ifdef CONFIG_VSX |
445 | u64 *vcpu_vsx = vcpu->arch.vsr; | 445 | u64 *vcpu_vsx = vcpu->arch.vsr; |
446 | #endif | 446 | #endif |
447 | u64 *thread_fpr = (u64*)t->fpr; | 447 | u64 *thread_fpr = &t->fp_state.fpr[0][0]; |
448 | int i; | 448 | int i; |
449 | 449 | ||
450 | /* | 450 | /* |
@@ -466,14 +466,14 @@ void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr) | |||
466 | /* | 466 | /* |
467 | * Note that on CPUs with VSX, giveup_fpu stores | 467 | * Note that on CPUs with VSX, giveup_fpu stores |
468 | * both the traditional FP registers and the added VSX | 468 | * both the traditional FP registers and the added VSX |
469 | * registers into thread.fpr[]. | 469 | * registers into thread.fp_state.fpr[]. |
470 | */ | 470 | */ |
471 | if (current->thread.regs->msr & MSR_FP) | 471 | if (current->thread.regs->msr & MSR_FP) |
472 | giveup_fpu(current); | 472 | giveup_fpu(current); |
473 | for (i = 0; i < ARRAY_SIZE(vcpu->arch.fpr); i++) | 473 | for (i = 0; i < ARRAY_SIZE(vcpu->arch.fpr); i++) |
474 | vcpu_fpr[i] = thread_fpr[get_fpr_index(i)]; | 474 | vcpu_fpr[i] = thread_fpr[get_fpr_index(i)]; |
475 | 475 | ||
476 | vcpu->arch.fpscr = t->fpscr.val; | 476 | vcpu->arch.fpscr = t->fp_state.fpscr; |
477 | 477 | ||
478 | #ifdef CONFIG_VSX | 478 | #ifdef CONFIG_VSX |
479 | if (cpu_has_feature(CPU_FTR_VSX)) | 479 | if (cpu_has_feature(CPU_FTR_VSX)) |
@@ -486,8 +486,8 @@ void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr) | |||
486 | if (msr & MSR_VEC) { | 486 | if (msr & MSR_VEC) { |
487 | if (current->thread.regs->msr & MSR_VEC) | 487 | if (current->thread.regs->msr & MSR_VEC) |
488 | giveup_altivec(current); | 488 | giveup_altivec(current); |
489 | memcpy(vcpu->arch.vr, t->vr, sizeof(vcpu->arch.vr)); | 489 | memcpy(vcpu->arch.vr, t->vr_state.vr, sizeof(vcpu->arch.vr)); |
490 | vcpu->arch.vscr = t->vscr; | 490 | vcpu->arch.vscr = t->vr_state.vscr; |
491 | } | 491 | } |
492 | #endif | 492 | #endif |
493 | 493 | ||
@@ -539,7 +539,7 @@ static int kvmppc_handle_ext(struct kvm_vcpu *vcpu, unsigned int exit_nr, | |||
539 | #ifdef CONFIG_VSX | 539 | #ifdef CONFIG_VSX |
540 | u64 *vcpu_vsx = vcpu->arch.vsr; | 540 | u64 *vcpu_vsx = vcpu->arch.vsr; |
541 | #endif | 541 | #endif |
542 | u64 *thread_fpr = (u64*)t->fpr; | 542 | u64 *thread_fpr = &t->fp_state.fpr[0][0]; |
543 | int i; | 543 | int i; |
544 | 544 | ||
545 | /* When we have paired singles, we emulate in software */ | 545 | /* When we have paired singles, we emulate in software */ |
@@ -584,15 +584,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++) | 584 | for (i = 0; i < ARRAY_SIZE(vcpu->arch.vsr) / 2; i++) |
585 | thread_fpr[get_fpr_index(i) + 1] = vcpu_vsx[i]; | 585 | thread_fpr[get_fpr_index(i) + 1] = vcpu_vsx[i]; |
586 | #endif | 586 | #endif |
587 | t->fpscr.val = vcpu->arch.fpscr; | 587 | t->fp_state.fpscr = vcpu->arch.fpscr; |
588 | t->fpexc_mode = 0; | 588 | t->fpexc_mode = 0; |
589 | kvmppc_load_up_fpu(); | 589 | kvmppc_load_up_fpu(); |
590 | } | 590 | } |
591 | 591 | ||
592 | if (msr & MSR_VEC) { | 592 | if (msr & MSR_VEC) { |
593 | #ifdef CONFIG_ALTIVEC | 593 | #ifdef CONFIG_ALTIVEC |
594 | memcpy(t->vr, vcpu->arch.vr, sizeof(vcpu->arch.vr)); | 594 | memcpy(t->vr_state.vr, vcpu->arch.vr, sizeof(vcpu->arch.vr)); |
595 | t->vscr = vcpu->arch.vscr; | 595 | t->vr_state.vscr = vcpu->arch.vscr; |
596 | t->vrsave = -1; | 596 | t->vrsave = -1; |
597 | kvmppc_load_up_altivec(); | 597 | kvmppc_load_up_altivec(); |
598 | #endif | 598 | #endif |
@@ -1116,12 +1116,10 @@ void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu) | |||
1116 | int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) | 1116 | int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) |
1117 | { | 1117 | { |
1118 | int ret; | 1118 | int ret; |
1119 | double fpr[32][TS_FPRWIDTH]; | 1119 | struct thread_fp_state fp; |
1120 | unsigned int fpscr; | ||
1121 | int fpexc_mode; | 1120 | int fpexc_mode; |
1122 | #ifdef CONFIG_ALTIVEC | 1121 | #ifdef CONFIG_ALTIVEC |
1123 | vector128 vr[32]; | 1122 | struct thread_vr_state vr; |
1124 | vector128 vscr; | ||
1125 | unsigned long uninitialized_var(vrsave); | 1123 | unsigned long uninitialized_var(vrsave); |
1126 | int used_vr; | 1124 | int used_vr; |
1127 | #endif | 1125 | #endif |
@@ -1153,8 +1151,7 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) | |||
1153 | /* Save FPU state in stack */ | 1151 | /* Save FPU state in stack */ |
1154 | if (current->thread.regs->msr & MSR_FP) | 1152 | if (current->thread.regs->msr & MSR_FP) |
1155 | giveup_fpu(current); | 1153 | giveup_fpu(current); |
1156 | memcpy(fpr, current->thread.fpr, sizeof(current->thread.fpr)); | 1154 | fp = current->thread.fp_state; |
1157 | fpscr = current->thread.fpscr.val; | ||
1158 | fpexc_mode = current->thread.fpexc_mode; | 1155 | fpexc_mode = current->thread.fpexc_mode; |
1159 | 1156 | ||
1160 | #ifdef CONFIG_ALTIVEC | 1157 | #ifdef CONFIG_ALTIVEC |
@@ -1163,8 +1160,7 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) | |||
1163 | if (used_vr) { | 1160 | if (used_vr) { |
1164 | if (current->thread.regs->msr & MSR_VEC) | 1161 | if (current->thread.regs->msr & MSR_VEC) |
1165 | giveup_altivec(current); | 1162 | giveup_altivec(current); |
1166 | memcpy(vr, current->thread.vr, sizeof(current->thread.vr)); | 1163 | vr = current->thread.vr_state; |
1167 | vscr = current->thread.vscr; | ||
1168 | vrsave = current->thread.vrsave; | 1164 | vrsave = current->thread.vrsave; |
1169 | } | 1165 | } |
1170 | #endif | 1166 | #endif |
@@ -1196,15 +1192,13 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) | |||
1196 | current->thread.regs->msr = ext_msr; | 1192 | current->thread.regs->msr = ext_msr; |
1197 | 1193 | ||
1198 | /* Restore FPU/VSX state from stack */ | 1194 | /* Restore FPU/VSX state from stack */ |
1199 | memcpy(current->thread.fpr, fpr, sizeof(current->thread.fpr)); | 1195 | current->thread.fp_state = fp; |
1200 | current->thread.fpscr.val = fpscr; | ||
1201 | current->thread.fpexc_mode = fpexc_mode; | 1196 | current->thread.fpexc_mode = fpexc_mode; |
1202 | 1197 | ||
1203 | #ifdef CONFIG_ALTIVEC | 1198 | #ifdef CONFIG_ALTIVEC |
1204 | /* Restore Altivec state from stack */ | 1199 | /* Restore Altivec state from stack */ |
1205 | if (used_vr && current->thread.used_vr) { | 1200 | if (used_vr && current->thread.used_vr) { |
1206 | memcpy(current->thread.vr, vr, sizeof(current->thread.vr)); | 1201 | current->thread.vr_state = vr; |
1207 | current->thread.vscr = vscr; | ||
1208 | current->thread.vrsave = vrsave; | 1202 | current->thread.vrsave = vrsave; |
1209 | } | 1203 | } |
1210 | current->thread.used_vr = used_vr; | 1204 | current->thread.used_vr = used_vr; |
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index 17722d82f1d1..5133199f6cb7 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c | |||
@@ -656,9 +656,8 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) | |||
656 | { | 656 | { |
657 | int ret, s; | 657 | int ret, s; |
658 | #ifdef CONFIG_PPC_FPU | 658 | #ifdef CONFIG_PPC_FPU |
659 | unsigned int fpscr; | 659 | struct thread_fp_state fp; |
660 | int fpexc_mode; | 660 | int fpexc_mode; |
661 | u64 fpr[32]; | ||
662 | #endif | 661 | #endif |
663 | 662 | ||
664 | if (!vcpu->arch.sane) { | 663 | if (!vcpu->arch.sane) { |
@@ -677,13 +676,13 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) | |||
677 | #ifdef CONFIG_PPC_FPU | 676 | #ifdef CONFIG_PPC_FPU |
678 | /* Save userspace FPU state in stack */ | 677 | /* Save userspace FPU state in stack */ |
679 | enable_kernel_fp(); | 678 | enable_kernel_fp(); |
680 | memcpy(fpr, current->thread.fpr, sizeof(current->thread.fpr)); | 679 | fp = current->thread.fp_state; |
681 | fpscr = current->thread.fpscr.val; | ||
682 | fpexc_mode = current->thread.fpexc_mode; | 680 | fpexc_mode = current->thread.fpexc_mode; |
683 | 681 | ||
684 | /* Restore guest FPU state to thread */ | 682 | /* Restore guest FPU state to thread */ |
685 | memcpy(current->thread.fpr, vcpu->arch.fpr, sizeof(vcpu->arch.fpr)); | 683 | memcpy(current->thread.fp_state.fpr, vcpu->arch.fpr, |
686 | current->thread.fpscr.val = vcpu->arch.fpscr; | 684 | sizeof(vcpu->arch.fpr)); |
685 | current->thread.fp_state.fpscr = vcpu->arch.fpscr; | ||
687 | 686 | ||
688 | /* | 687 | /* |
689 | * Since we can't trap on MSR_FP in GS-mode, we consider the guest | 688 | * Since we can't trap on MSR_FP in GS-mode, we consider the guest |
@@ -709,12 +708,12 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) | |||
709 | vcpu->fpu_active = 0; | 708 | vcpu->fpu_active = 0; |
710 | 709 | ||
711 | /* Save guest FPU state from thread */ | 710 | /* Save guest FPU state from thread */ |
712 | memcpy(vcpu->arch.fpr, current->thread.fpr, sizeof(vcpu->arch.fpr)); | 711 | memcpy(vcpu->arch.fpr, current->thread.fp_state.fpr, |
713 | vcpu->arch.fpscr = current->thread.fpscr.val; | 712 | sizeof(vcpu->arch.fpr)); |
713 | vcpu->arch.fpscr = current->thread.fp_state.fpscr; | ||
714 | 714 | ||
715 | /* Restore userspace FPU state from stack */ | 715 | /* Restore userspace FPU state from stack */ |
716 | memcpy(current->thread.fpr, fpr, sizeof(current->thread.fpr)); | 716 | current->thread.fp_state = fp; |
717 | current->thread.fpscr.val = fpscr; | ||
718 | current->thread.fpexc_mode = fpexc_mode; | 717 | current->thread.fpexc_mode = fpexc_mode; |
719 | #endif | 718 | #endif |
720 | 719 | ||
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index 8ed035d2edb5..e3734edffa69 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c | |||
@@ -304,5 +304,54 @@ void register_page_bootmem_memmap(unsigned long section_nr, | |||
304 | struct page *start_page, unsigned long size) | 304 | struct page *start_page, unsigned long size) |
305 | { | 305 | { |
306 | } | 306 | } |
307 | #endif /* CONFIG_SPARSEMEM_VMEMMAP */ | ||
308 | 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); | ||
356 | |||
357 | #endif /* CONFIG_SPARSEMEM_VMEMMAP/CONFIG_FLATMEM */ | ||
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c index a6531d2ff6c2..c639af7d4826 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; |
@@ -454,10 +464,13 @@ static void pnv_ioda_setup_bus_dma(struct pnv_ioda_pe *pe, struct pci_bus *bus) | |||
454 | } | 464 | } |
455 | } | 465 | } |
456 | 466 | ||
457 | static void pnv_pci_ioda1_tce_invalidate(struct iommu_table *tbl, | 467 | static void pnv_pci_ioda1_tce_invalidate(struct pnv_ioda_pe *pe, |
458 | __be64 *startp, __be64 *endp) | 468 | struct iommu_table *tbl, |
469 | __be64 *startp, __be64 *endp, bool rm) | ||
459 | { | 470 | { |
460 | __be64 __iomem *invalidate = (__be64 __iomem *)tbl->it_index; | 471 | __be64 __iomem *invalidate = rm ? |
472 | (__be64 __iomem *)pe->tce_inval_reg_phys : | ||
473 | (__be64 __iomem *)tbl->it_index; | ||
461 | unsigned long start, end, inc; | 474 | unsigned long start, end, inc; |
462 | 475 | ||
463 | start = __pa(startp); | 476 | start = __pa(startp); |
@@ -484,7 +497,10 @@ static void pnv_pci_ioda1_tce_invalidate(struct iommu_table *tbl, | |||
484 | 497 | ||
485 | mb(); /* Ensure above stores are visible */ | 498 | mb(); /* Ensure above stores are visible */ |
486 | while (start <= end) { | 499 | while (start <= end) { |
487 | __raw_writeq(cpu_to_be64(start), invalidate); | 500 | if (rm) |
501 | __raw_rm_writeq(cpu_to_be64(start), invalidate); | ||
502 | else | ||
503 | __raw_writeq(cpu_to_be64(start), invalidate); | ||
488 | start += inc; | 504 | start += inc; |
489 | } | 505 | } |
490 | 506 | ||
@@ -496,10 +512,12 @@ static void pnv_pci_ioda1_tce_invalidate(struct iommu_table *tbl, | |||
496 | 512 | ||
497 | static void pnv_pci_ioda2_tce_invalidate(struct pnv_ioda_pe *pe, | 513 | static void pnv_pci_ioda2_tce_invalidate(struct pnv_ioda_pe *pe, |
498 | struct iommu_table *tbl, | 514 | struct iommu_table *tbl, |
499 | __be64 *startp, __be64 *endp) | 515 | __be64 *startp, __be64 *endp, bool rm) |
500 | { | 516 | { |
501 | unsigned long start, end, inc; | 517 | unsigned long start, end, inc; |
502 | __be64 __iomem *invalidate = (__be64 __iomem *)tbl->it_index; | 518 | __be64 __iomem *invalidate = rm ? |
519 | (__be64 __iomem *)pe->tce_inval_reg_phys : | ||
520 | (__be64 __iomem *)tbl->it_index; | ||
503 | 521 | ||
504 | /* We'll invalidate DMA address in PE scope */ | 522 | /* We'll invalidate DMA address in PE scope */ |
505 | start = 0x2ul << 60; | 523 | start = 0x2ul << 60; |
@@ -515,22 +533,25 @@ static void pnv_pci_ioda2_tce_invalidate(struct pnv_ioda_pe *pe, | |||
515 | mb(); | 533 | mb(); |
516 | 534 | ||
517 | while (start <= end) { | 535 | while (start <= end) { |
518 | __raw_writeq(cpu_to_be64(start), invalidate); | 536 | if (rm) |
537 | __raw_rm_writeq(cpu_to_be64(start), invalidate); | ||
538 | else | ||
539 | __raw_writeq(cpu_to_be64(start), invalidate); | ||
519 | start += inc; | 540 | start += inc; |
520 | } | 541 | } |
521 | } | 542 | } |
522 | 543 | ||
523 | void pnv_pci_ioda_tce_invalidate(struct iommu_table *tbl, | 544 | void pnv_pci_ioda_tce_invalidate(struct iommu_table *tbl, |
524 | __be64 *startp, __be64 *endp) | 545 | __be64 *startp, __be64 *endp, bool rm) |
525 | { | 546 | { |
526 | struct pnv_ioda_pe *pe = container_of(tbl, struct pnv_ioda_pe, | 547 | struct pnv_ioda_pe *pe = container_of(tbl, struct pnv_ioda_pe, |
527 | tce32_table); | 548 | tce32_table); |
528 | struct pnv_phb *phb = pe->phb; | 549 | struct pnv_phb *phb = pe->phb; |
529 | 550 | ||
530 | if (phb->type == PNV_PHB_IODA1) | 551 | if (phb->type == PNV_PHB_IODA1) |
531 | pnv_pci_ioda1_tce_invalidate(tbl, startp, endp); | 552 | pnv_pci_ioda1_tce_invalidate(pe, tbl, startp, endp, rm); |
532 | else | 553 | else |
533 | pnv_pci_ioda2_tce_invalidate(pe, tbl, startp, endp); | 554 | pnv_pci_ioda2_tce_invalidate(pe, tbl, startp, endp, rm); |
534 | } | 555 | } |
535 | 556 | ||
536 | static void pnv_pci_ioda_setup_dma_pe(struct pnv_phb *phb, | 557 | static void pnv_pci_ioda_setup_dma_pe(struct pnv_phb *phb, |
@@ -603,7 +624,9 @@ static void pnv_pci_ioda_setup_dma_pe(struct pnv_phb *phb, | |||
603 | * bus number, print that out instead. | 624 | * bus number, print that out instead. |
604 | */ | 625 | */ |
605 | tbl->it_busno = 0; | 626 | tbl->it_busno = 0; |
606 | tbl->it_index = (unsigned long)ioremap(be64_to_cpup(swinvp), 8); | 627 | pe->tce_inval_reg_phys = be64_to_cpup(swinvp); |
628 | tbl->it_index = (unsigned long)ioremap(pe->tce_inval_reg_phys, | ||
629 | 8); | ||
607 | tbl->it_type = TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE | | 630 | tbl->it_type = TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE | |
608 | TCE_PCI_SWINV_PAIR; | 631 | TCE_PCI_SWINV_PAIR; |
609 | } | 632 | } |
@@ -681,7 +704,9 @@ static void pnv_pci_ioda2_setup_dma_pe(struct pnv_phb *phb, | |||
681 | * bus number, print that out instead. | 704 | * bus number, print that out instead. |
682 | */ | 705 | */ |
683 | tbl->it_busno = 0; | 706 | tbl->it_busno = 0; |
684 | tbl->it_index = (unsigned long)ioremap(be64_to_cpup(swinvp), 8); | 707 | pe->tce_inval_reg_phys = be64_to_cpup(swinvp); |
708 | tbl->it_index = (unsigned long)ioremap(pe->tce_inval_reg_phys, | ||
709 | 8); | ||
685 | tbl->it_type = TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE; | 710 | tbl->it_type = TCE_PCI_SWINV_CREATE | TCE_PCI_SWINV_FREE; |
686 | } | 711 | } |
687 | iommu_init_table(tbl, phb->hose->node); | 712 | iommu_init_table(tbl, phb->hose->node); |
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c index a26956c5f38c..921ae673baf3 100644 --- a/arch/powerpc/platforms/powernv/pci.c +++ b/arch/powerpc/platforms/powernv/pci.c | |||
@@ -401,7 +401,7 @@ struct pci_ops pnv_pci_ops = { | |||
401 | 401 | ||
402 | static int pnv_tce_build(struct iommu_table *tbl, long index, long npages, | 402 | static int pnv_tce_build(struct iommu_table *tbl, long index, long npages, |
403 | unsigned long uaddr, enum dma_data_direction direction, | 403 | unsigned long uaddr, enum dma_data_direction direction, |
404 | struct dma_attrs *attrs) | 404 | struct dma_attrs *attrs, bool rm) |
405 | { | 405 | { |
406 | u64 proto_tce; | 406 | u64 proto_tce; |
407 | __be64 *tcep, *tces; | 407 | __be64 *tcep, *tces; |
@@ -423,12 +423,22 @@ static int pnv_tce_build(struct iommu_table *tbl, long index, long npages, | |||
423 | * of flags if that becomes the case | 423 | * of flags if that becomes the case |
424 | */ | 424 | */ |
425 | if (tbl->it_type & TCE_PCI_SWINV_CREATE) | 425 | if (tbl->it_type & TCE_PCI_SWINV_CREATE) |
426 | pnv_pci_ioda_tce_invalidate(tbl, tces, tcep - 1); | 426 | pnv_pci_ioda_tce_invalidate(tbl, tces, tcep - 1, rm); |
427 | 427 | ||
428 | return 0; | 428 | return 0; |
429 | } | 429 | } |
430 | 430 | ||
431 | static void pnv_tce_free(struct iommu_table *tbl, long index, long npages) | 431 | static int pnv_tce_build_vm(struct iommu_table *tbl, long index, long npages, |
432 | unsigned long uaddr, | ||
433 | enum dma_data_direction direction, | ||
434 | struct dma_attrs *attrs) | ||
435 | { | ||
436 | return pnv_tce_build(tbl, index, npages, uaddr, direction, attrs, | ||
437 | false); | ||
438 | } | ||
439 | |||
440 | static void pnv_tce_free(struct iommu_table *tbl, long index, long npages, | ||
441 | bool rm) | ||
432 | { | 442 | { |
433 | __be64 *tcep, *tces; | 443 | __be64 *tcep, *tces; |
434 | 444 | ||
@@ -438,7 +448,12 @@ static void pnv_tce_free(struct iommu_table *tbl, long index, long npages) | |||
438 | *(tcep++) = cpu_to_be64(0); | 448 | *(tcep++) = cpu_to_be64(0); |
439 | 449 | ||
440 | if (tbl->it_type & TCE_PCI_SWINV_FREE) | 450 | if (tbl->it_type & TCE_PCI_SWINV_FREE) |
441 | pnv_pci_ioda_tce_invalidate(tbl, tces, tcep - 1); | 451 | pnv_pci_ioda_tce_invalidate(tbl, tces, tcep - 1, rm); |
452 | } | ||
453 | |||
454 | static void pnv_tce_free_vm(struct iommu_table *tbl, long index, long npages) | ||
455 | { | ||
456 | pnv_tce_free(tbl, index, npages, false); | ||
442 | } | 457 | } |
443 | 458 | ||
444 | static unsigned long pnv_tce_get(struct iommu_table *tbl, long index) | 459 | static unsigned long pnv_tce_get(struct iommu_table *tbl, long index) |
@@ -446,6 +461,19 @@ static unsigned long pnv_tce_get(struct iommu_table *tbl, long index) | |||
446 | return ((u64 *)tbl->it_base)[index - tbl->it_offset]; | 461 | return ((u64 *)tbl->it_base)[index - tbl->it_offset]; |
447 | } | 462 | } |
448 | 463 | ||
464 | static int pnv_tce_build_rm(struct iommu_table *tbl, long index, long npages, | ||
465 | unsigned long uaddr, | ||
466 | enum dma_data_direction direction, | ||
467 | struct dma_attrs *attrs) | ||
468 | { | ||
469 | return pnv_tce_build(tbl, index, npages, uaddr, direction, attrs, true); | ||
470 | } | ||
471 | |||
472 | static void pnv_tce_free_rm(struct iommu_table *tbl, long index, long npages) | ||
473 | { | ||
474 | pnv_tce_free(tbl, index, npages, true); | ||
475 | } | ||
476 | |||
449 | void pnv_pci_setup_iommu_table(struct iommu_table *tbl, | 477 | void pnv_pci_setup_iommu_table(struct iommu_table *tbl, |
450 | void *tce_mem, u64 tce_size, | 478 | void *tce_mem, u64 tce_size, |
451 | u64 dma_offset) | 479 | u64 dma_offset) |
@@ -610,8 +638,10 @@ void __init pnv_pci_init(void) | |||
610 | 638 | ||
611 | /* Configure IOMMU DMA hooks */ | 639 | /* Configure IOMMU DMA hooks */ |
612 | ppc_md.pci_dma_dev_setup = pnv_pci_dma_dev_setup; | 640 | ppc_md.pci_dma_dev_setup = pnv_pci_dma_dev_setup; |
613 | ppc_md.tce_build = pnv_tce_build; | 641 | ppc_md.tce_build = pnv_tce_build_vm; |
614 | ppc_md.tce_free = pnv_tce_free; | 642 | ppc_md.tce_free = pnv_tce_free_vm; |
643 | ppc_md.tce_build_rm = pnv_tce_build_rm; | ||
644 | ppc_md.tce_free_rm = pnv_tce_free_rm; | ||
615 | ppc_md.tce_get = pnv_tce_get; | 645 | ppc_md.tce_get = pnv_tce_get; |
616 | ppc_md.pci_probe_mode = pnv_pci_probe_mode; | 646 | ppc_md.pci_probe_mode = pnv_pci_probe_mode; |
617 | set_pci_dma_ops(&dma_iommu_ops); | 647 | set_pci_dma_ops(&dma_iommu_ops); |
diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h index d0bb5204ece3..64d3b12e5b6d 100644 --- a/arch/powerpc/platforms/powernv/pci.h +++ b/arch/powerpc/platforms/powernv/pci.h | |||
@@ -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 | ||
@@ -193,6 +194,6 @@ extern void pnv_pci_init_p5ioc2_hub(struct device_node *np); | |||
193 | extern void pnv_pci_init_ioda_hub(struct device_node *np); | 194 | extern void pnv_pci_init_ioda_hub(struct device_node *np); |
194 | extern void pnv_pci_init_ioda2_phb(struct device_node *np); | 195 | extern void pnv_pci_init_ioda2_phb(struct device_node *np); |
195 | extern void pnv_pci_ioda_tce_invalidate(struct iommu_table *tbl, | 196 | extern void pnv_pci_ioda_tce_invalidate(struct iommu_table *tbl, |
196 | __be64 *startp, __be64 *endp); | 197 | __be64 *startp, __be64 *endp, bool rm); |
197 | 198 | ||
198 | #endif /* __POWERNV_PCI_H */ | 199 | #endif /* __POWERNV_PCI_H */ |