diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-17 15:50:54 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-04-17 15:50:54 -0400 |
commit | bfaf245022b4b8661af2e35f467cf0e91943c24c (patch) | |
tree | b5a6ee49a047557a791eb897c8c9545a155e36b7 /arch/mips/kernel/unaligned.c | |
parent | 96d928ed75c4ba4253e82910a697ec7b06ace8b4 (diff) | |
parent | 3e20a26b02bd4f24945c87407df51948dd488620 (diff) |
Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus
Pull MIPS updates from Ralf Baechle:
"This is the main pull request for MIPS for Linux 4.1. Most
noteworthy:
- Add more Octeon-optimized crypto functions
- Octeon crypto preemption and locking fixes
- Little endian support for Octeon
- Use correct CSR to soft reset Octeons
- Support LEDs on the Octeon-based DSR-1000N
- Fix PCI interrupt mapping for the Octeon-based DSR-1000N
- Mark prom_free_prom_memory() as __init for a number of systems
- Support for Imagination's Pistachio SOC. This includes arch and
CLK bits. I'd like to merge pinctrl bits later
- Improve parallelism of csum_partial for certain pipelines
- Organize DTB files in subdirs like other architectures
- Implement read_sched_clock for all MIPS platforms other than
Octeon
- Massive series of 38 fixes and cleanups for the FPU emulator /
kernel
- Further FPU remulator work to support new features. This sits on a
separate branch which also has been pulled into the 4.1 KVM branch
- Clean up and fixes for the SEAD3 eval board; remove unused file
- Various updates for Netlogic platforms
- A number of small updates for Loongson 3 platforms
- Increase the memory limit for ATH79 platforms to 256MB
- A fair number of fixes and updates for BCM47xx platforms
- Finish the implementation of XPA support
- MIPS FDC support. No, not floppy controller but Fast Debug Channel :)
- Detect the R16000 used in SGI legacy platforms
- Fix Kconfig dependencies for the SSB bus support"
* 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus: (265 commits)
MIPS: Makefile: Fix MIPS ASE detection code
MIPS: asm: elf: Set O32 default FPU flags
MIPS: BCM47XX: Fix detecting Microsoft MN-700 & Asus WL500G
MIPS: Kconfig: Disable SMP/CPS for 64-bit
MIPS: Hibernate: flush TLB entries earlier
MIPS: smp-cps: cpu_set FPU mask if FPU present
MIPS: lose_fpu(): Disable FPU when MSA enabled
MIPS: ralink: add missing symbol for RALINK_ILL_ACC
MIPS: ralink: Fix bad config symbol in PCI makefile.
SSB: fix Kconfig dependencies
MIPS: Malta: Detect and fix bad memsize values
Revert "MIPS: Avoid pipeline stalls on some MIPS32R2 cores."
MIPS: Octeon: Delete override of cpu_has_mips_r2_exec_hazard.
MIPS: Fix cpu_has_mips_r2_exec_hazard.
MIPS: kernel: entry.S: Set correct ISA level for mips_ihb
MIPS: asm: spinlock: Fix addiu instruction for R10000_LLSC_WAR case
MIPS: r4kcache: Use correct base register for MIPS R6 cache flushes
MIPS: Kconfig: Fix typo for the r2-to-r6 emulator kernel parameter
MIPS: unaligned: Fix regular load/store instruction emulation for EVA
MIPS: unaligned: Surround load/store macros in do {} while statements
...
Diffstat (limited to 'arch/mips/kernel/unaligned.c')
-rw-r--r-- | arch/mips/kernel/unaligned.c | 346 |
1 files changed, 233 insertions, 113 deletions
diff --git a/arch/mips/kernel/unaligned.c b/arch/mips/kernel/unaligned.c index bbb69695a0a1..af84bef0c90d 100644 --- a/arch/mips/kernel/unaligned.c +++ b/arch/mips/kernel/unaligned.c | |||
@@ -89,8 +89,6 @@ | |||
89 | #include <asm/fpu_emulator.h> | 89 | #include <asm/fpu_emulator.h> |
90 | #include <asm/inst.h> | 90 | #include <asm/inst.h> |
91 | #include <asm/uaccess.h> | 91 | #include <asm/uaccess.h> |
92 | #include <asm/fpu.h> | ||
93 | #include <asm/fpu_emulator.h> | ||
94 | 92 | ||
95 | #define STR(x) __STR(x) | 93 | #define STR(x) __STR(x) |
96 | #define __STR(x) #x | 94 | #define __STR(x) #x |
@@ -109,10 +107,11 @@ static u32 unaligned_action; | |||
109 | extern void show_registers(struct pt_regs *regs); | 107 | extern void show_registers(struct pt_regs *regs); |
110 | 108 | ||
111 | #ifdef __BIG_ENDIAN | 109 | #ifdef __BIG_ENDIAN |
112 | #define LoadHW(addr, value, res) \ | 110 | #define _LoadHW(addr, value, res, type) \ |
111 | do { \ | ||
113 | __asm__ __volatile__ (".set\tnoat\n" \ | 112 | __asm__ __volatile__ (".set\tnoat\n" \ |
114 | "1:\t"user_lb("%0", "0(%2)")"\n" \ | 113 | "1:\t"type##_lb("%0", "0(%2)")"\n" \ |
115 | "2:\t"user_lbu("$1", "1(%2)")"\n\t" \ | 114 | "2:\t"type##_lbu("$1", "1(%2)")"\n\t"\ |
116 | "sll\t%0, 0x8\n\t" \ | 115 | "sll\t%0, 0x8\n\t" \ |
117 | "or\t%0, $1\n\t" \ | 116 | "or\t%0, $1\n\t" \ |
118 | "li\t%1, 0\n" \ | 117 | "li\t%1, 0\n" \ |
@@ -127,13 +126,15 @@ extern void show_registers(struct pt_regs *regs); | |||
127 | STR(PTR)"\t2b, 4b\n\t" \ | 126 | STR(PTR)"\t2b, 4b\n\t" \ |
128 | ".previous" \ | 127 | ".previous" \ |
129 | : "=&r" (value), "=r" (res) \ | 128 | : "=&r" (value), "=r" (res) \ |
130 | : "r" (addr), "i" (-EFAULT)); | 129 | : "r" (addr), "i" (-EFAULT)); \ |
130 | } while(0) | ||
131 | 131 | ||
132 | #ifndef CONFIG_CPU_MIPSR6 | 132 | #ifndef CONFIG_CPU_MIPSR6 |
133 | #define LoadW(addr, value, res) \ | 133 | #define _LoadW(addr, value, res, type) \ |
134 | do { \ | ||
134 | __asm__ __volatile__ ( \ | 135 | __asm__ __volatile__ ( \ |
135 | "1:\t"user_lwl("%0", "(%2)")"\n" \ | 136 | "1:\t"type##_lwl("%0", "(%2)")"\n" \ |
136 | "2:\t"user_lwr("%0", "3(%2)")"\n\t" \ | 137 | "2:\t"type##_lwr("%0", "3(%2)")"\n\t"\ |
137 | "li\t%1, 0\n" \ | 138 | "li\t%1, 0\n" \ |
138 | "3:\n\t" \ | 139 | "3:\n\t" \ |
139 | ".insn\n\t" \ | 140 | ".insn\n\t" \ |
@@ -146,21 +147,24 @@ extern void show_registers(struct pt_regs *regs); | |||
146 | STR(PTR)"\t2b, 4b\n\t" \ | 147 | STR(PTR)"\t2b, 4b\n\t" \ |
147 | ".previous" \ | 148 | ".previous" \ |
148 | : "=&r" (value), "=r" (res) \ | 149 | : "=&r" (value), "=r" (res) \ |
149 | : "r" (addr), "i" (-EFAULT)); | 150 | : "r" (addr), "i" (-EFAULT)); \ |
151 | } while(0) | ||
152 | |||
150 | #else | 153 | #else |
151 | /* MIPSR6 has no lwl instruction */ | 154 | /* MIPSR6 has no lwl instruction */ |
152 | #define LoadW(addr, value, res) \ | 155 | #define _LoadW(addr, value, res, type) \ |
156 | do { \ | ||
153 | __asm__ __volatile__ ( \ | 157 | __asm__ __volatile__ ( \ |
154 | ".set\tpush\n" \ | 158 | ".set\tpush\n" \ |
155 | ".set\tnoat\n\t" \ | 159 | ".set\tnoat\n\t" \ |
156 | "1:"user_lb("%0", "0(%2)")"\n\t" \ | 160 | "1:"type##_lb("%0", "0(%2)")"\n\t" \ |
157 | "2:"user_lbu("$1", "1(%2)")"\n\t" \ | 161 | "2:"type##_lbu("$1", "1(%2)")"\n\t" \ |
158 | "sll\t%0, 0x8\n\t" \ | 162 | "sll\t%0, 0x8\n\t" \ |
159 | "or\t%0, $1\n\t" \ | 163 | "or\t%0, $1\n\t" \ |
160 | "3:"user_lbu("$1", "2(%2)")"\n\t" \ | 164 | "3:"type##_lbu("$1", "2(%2)")"\n\t" \ |
161 | "sll\t%0, 0x8\n\t" \ | 165 | "sll\t%0, 0x8\n\t" \ |
162 | "or\t%0, $1\n\t" \ | 166 | "or\t%0, $1\n\t" \ |
163 | "4:"user_lbu("$1", "3(%2)")"\n\t" \ | 167 | "4:"type##_lbu("$1", "3(%2)")"\n\t" \ |
164 | "sll\t%0, 0x8\n\t" \ | 168 | "sll\t%0, 0x8\n\t" \ |
165 | "or\t%0, $1\n\t" \ | 169 | "or\t%0, $1\n\t" \ |
166 | "li\t%1, 0\n" \ | 170 | "li\t%1, 0\n" \ |
@@ -178,14 +182,17 @@ extern void show_registers(struct pt_regs *regs); | |||
178 | STR(PTR)"\t4b, 11b\n\t" \ | 182 | STR(PTR)"\t4b, 11b\n\t" \ |
179 | ".previous" \ | 183 | ".previous" \ |
180 | : "=&r" (value), "=r" (res) \ | 184 | : "=&r" (value), "=r" (res) \ |
181 | : "r" (addr), "i" (-EFAULT)); | 185 | : "r" (addr), "i" (-EFAULT)); \ |
186 | } while(0) | ||
187 | |||
182 | #endif /* CONFIG_CPU_MIPSR6 */ | 188 | #endif /* CONFIG_CPU_MIPSR6 */ |
183 | 189 | ||
184 | #define LoadHWU(addr, value, res) \ | 190 | #define _LoadHWU(addr, value, res, type) \ |
191 | do { \ | ||
185 | __asm__ __volatile__ ( \ | 192 | __asm__ __volatile__ ( \ |
186 | ".set\tnoat\n" \ | 193 | ".set\tnoat\n" \ |
187 | "1:\t"user_lbu("%0", "0(%2)")"\n" \ | 194 | "1:\t"type##_lbu("%0", "0(%2)")"\n" \ |
188 | "2:\t"user_lbu("$1", "1(%2)")"\n\t" \ | 195 | "2:\t"type##_lbu("$1", "1(%2)")"\n\t"\ |
189 | "sll\t%0, 0x8\n\t" \ | 196 | "sll\t%0, 0x8\n\t" \ |
190 | "or\t%0, $1\n\t" \ | 197 | "or\t%0, $1\n\t" \ |
191 | "li\t%1, 0\n" \ | 198 | "li\t%1, 0\n" \ |
@@ -201,13 +208,15 @@ extern void show_registers(struct pt_regs *regs); | |||
201 | STR(PTR)"\t2b, 4b\n\t" \ | 208 | STR(PTR)"\t2b, 4b\n\t" \ |
202 | ".previous" \ | 209 | ".previous" \ |
203 | : "=&r" (value), "=r" (res) \ | 210 | : "=&r" (value), "=r" (res) \ |
204 | : "r" (addr), "i" (-EFAULT)); | 211 | : "r" (addr), "i" (-EFAULT)); \ |
212 | } while(0) | ||
205 | 213 | ||
206 | #ifndef CONFIG_CPU_MIPSR6 | 214 | #ifndef CONFIG_CPU_MIPSR6 |
207 | #define LoadWU(addr, value, res) \ | 215 | #define _LoadWU(addr, value, res, type) \ |
216 | do { \ | ||
208 | __asm__ __volatile__ ( \ | 217 | __asm__ __volatile__ ( \ |
209 | "1:\t"user_lwl("%0", "(%2)")"\n" \ | 218 | "1:\t"type##_lwl("%0", "(%2)")"\n" \ |
210 | "2:\t"user_lwr("%0", "3(%2)")"\n\t" \ | 219 | "2:\t"type##_lwr("%0", "3(%2)")"\n\t"\ |
211 | "dsll\t%0, %0, 32\n\t" \ | 220 | "dsll\t%0, %0, 32\n\t" \ |
212 | "dsrl\t%0, %0, 32\n\t" \ | 221 | "dsrl\t%0, %0, 32\n\t" \ |
213 | "li\t%1, 0\n" \ | 222 | "li\t%1, 0\n" \ |
@@ -222,9 +231,11 @@ extern void show_registers(struct pt_regs *regs); | |||
222 | STR(PTR)"\t2b, 4b\n\t" \ | 231 | STR(PTR)"\t2b, 4b\n\t" \ |
223 | ".previous" \ | 232 | ".previous" \ |
224 | : "=&r" (value), "=r" (res) \ | 233 | : "=&r" (value), "=r" (res) \ |
225 | : "r" (addr), "i" (-EFAULT)); | 234 | : "r" (addr), "i" (-EFAULT)); \ |
235 | } while(0) | ||
226 | 236 | ||
227 | #define LoadDW(addr, value, res) \ | 237 | #define _LoadDW(addr, value, res) \ |
238 | do { \ | ||
228 | __asm__ __volatile__ ( \ | 239 | __asm__ __volatile__ ( \ |
229 | "1:\tldl\t%0, (%2)\n" \ | 240 | "1:\tldl\t%0, (%2)\n" \ |
230 | "2:\tldr\t%0, 7(%2)\n\t" \ | 241 | "2:\tldr\t%0, 7(%2)\n\t" \ |
@@ -240,21 +251,24 @@ extern void show_registers(struct pt_regs *regs); | |||
240 | STR(PTR)"\t2b, 4b\n\t" \ | 251 | STR(PTR)"\t2b, 4b\n\t" \ |
241 | ".previous" \ | 252 | ".previous" \ |
242 | : "=&r" (value), "=r" (res) \ | 253 | : "=&r" (value), "=r" (res) \ |
243 | : "r" (addr), "i" (-EFAULT)); | 254 | : "r" (addr), "i" (-EFAULT)); \ |
255 | } while(0) | ||
256 | |||
244 | #else | 257 | #else |
245 | /* MIPSR6 has not lwl and ldl instructions */ | 258 | /* MIPSR6 has not lwl and ldl instructions */ |
246 | #define LoadWU(addr, value, res) \ | 259 | #define _LoadWU(addr, value, res, type) \ |
260 | do { \ | ||
247 | __asm__ __volatile__ ( \ | 261 | __asm__ __volatile__ ( \ |
248 | ".set\tpush\n\t" \ | 262 | ".set\tpush\n\t" \ |
249 | ".set\tnoat\n\t" \ | 263 | ".set\tnoat\n\t" \ |
250 | "1:"user_lbu("%0", "0(%2)")"\n\t" \ | 264 | "1:"type##_lbu("%0", "0(%2)")"\n\t" \ |
251 | "2:"user_lbu("$1", "1(%2)")"\n\t" \ | 265 | "2:"type##_lbu("$1", "1(%2)")"\n\t" \ |
252 | "sll\t%0, 0x8\n\t" \ | 266 | "sll\t%0, 0x8\n\t" \ |
253 | "or\t%0, $1\n\t" \ | 267 | "or\t%0, $1\n\t" \ |
254 | "3:"user_lbu("$1", "2(%2)")"\n\t" \ | 268 | "3:"type##_lbu("$1", "2(%2)")"\n\t" \ |
255 | "sll\t%0, 0x8\n\t" \ | 269 | "sll\t%0, 0x8\n\t" \ |
256 | "or\t%0, $1\n\t" \ | 270 | "or\t%0, $1\n\t" \ |
257 | "4:"user_lbu("$1", "3(%2)")"\n\t" \ | 271 | "4:"type##_lbu("$1", "3(%2)")"\n\t" \ |
258 | "sll\t%0, 0x8\n\t" \ | 272 | "sll\t%0, 0x8\n\t" \ |
259 | "or\t%0, $1\n\t" \ | 273 | "or\t%0, $1\n\t" \ |
260 | "li\t%1, 0\n" \ | 274 | "li\t%1, 0\n" \ |
@@ -272,9 +286,11 @@ extern void show_registers(struct pt_regs *regs); | |||
272 | STR(PTR)"\t4b, 11b\n\t" \ | 286 | STR(PTR)"\t4b, 11b\n\t" \ |
273 | ".previous" \ | 287 | ".previous" \ |
274 | : "=&r" (value), "=r" (res) \ | 288 | : "=&r" (value), "=r" (res) \ |
275 | : "r" (addr), "i" (-EFAULT)); | 289 | : "r" (addr), "i" (-EFAULT)); \ |
290 | } while(0) | ||
276 | 291 | ||
277 | #define LoadDW(addr, value, res) \ | 292 | #define _LoadDW(addr, value, res) \ |
293 | do { \ | ||
278 | __asm__ __volatile__ ( \ | 294 | __asm__ __volatile__ ( \ |
279 | ".set\tpush\n\t" \ | 295 | ".set\tpush\n\t" \ |
280 | ".set\tnoat\n\t" \ | 296 | ".set\tnoat\n\t" \ |
@@ -319,16 +335,19 @@ extern void show_registers(struct pt_regs *regs); | |||
319 | STR(PTR)"\t8b, 11b\n\t" \ | 335 | STR(PTR)"\t8b, 11b\n\t" \ |
320 | ".previous" \ | 336 | ".previous" \ |
321 | : "=&r" (value), "=r" (res) \ | 337 | : "=&r" (value), "=r" (res) \ |
322 | : "r" (addr), "i" (-EFAULT)); | 338 | : "r" (addr), "i" (-EFAULT)); \ |
339 | } while(0) | ||
340 | |||
323 | #endif /* CONFIG_CPU_MIPSR6 */ | 341 | #endif /* CONFIG_CPU_MIPSR6 */ |
324 | 342 | ||
325 | 343 | ||
326 | #define StoreHW(addr, value, res) \ | 344 | #define _StoreHW(addr, value, res, type) \ |
345 | do { \ | ||
327 | __asm__ __volatile__ ( \ | 346 | __asm__ __volatile__ ( \ |
328 | ".set\tnoat\n" \ | 347 | ".set\tnoat\n" \ |
329 | "1:\t"user_sb("%1", "1(%2)")"\n" \ | 348 | "1:\t"type##_sb("%1", "1(%2)")"\n" \ |
330 | "srl\t$1, %1, 0x8\n" \ | 349 | "srl\t$1, %1, 0x8\n" \ |
331 | "2:\t"user_sb("$1", "0(%2)")"\n" \ | 350 | "2:\t"type##_sb("$1", "0(%2)")"\n" \ |
332 | ".set\tat\n\t" \ | 351 | ".set\tat\n\t" \ |
333 | "li\t%0, 0\n" \ | 352 | "li\t%0, 0\n" \ |
334 | "3:\n\t" \ | 353 | "3:\n\t" \ |
@@ -342,13 +361,15 @@ extern void show_registers(struct pt_regs *regs); | |||
342 | STR(PTR)"\t2b, 4b\n\t" \ | 361 | STR(PTR)"\t2b, 4b\n\t" \ |
343 | ".previous" \ | 362 | ".previous" \ |
344 | : "=r" (res) \ | 363 | : "=r" (res) \ |
345 | : "r" (value), "r" (addr), "i" (-EFAULT)); | 364 | : "r" (value), "r" (addr), "i" (-EFAULT));\ |
365 | } while(0) | ||
346 | 366 | ||
347 | #ifndef CONFIG_CPU_MIPSR6 | 367 | #ifndef CONFIG_CPU_MIPSR6 |
348 | #define StoreW(addr, value, res) \ | 368 | #define _StoreW(addr, value, res, type) \ |
369 | do { \ | ||
349 | __asm__ __volatile__ ( \ | 370 | __asm__ __volatile__ ( \ |
350 | "1:\t"user_swl("%1", "(%2)")"\n" \ | 371 | "1:\t"type##_swl("%1", "(%2)")"\n" \ |
351 | "2:\t"user_swr("%1", "3(%2)")"\n\t" \ | 372 | "2:\t"type##_swr("%1", "3(%2)")"\n\t"\ |
352 | "li\t%0, 0\n" \ | 373 | "li\t%0, 0\n" \ |
353 | "3:\n\t" \ | 374 | "3:\n\t" \ |
354 | ".insn\n\t" \ | 375 | ".insn\n\t" \ |
@@ -361,9 +382,11 @@ extern void show_registers(struct pt_regs *regs); | |||
361 | STR(PTR)"\t2b, 4b\n\t" \ | 382 | STR(PTR)"\t2b, 4b\n\t" \ |
362 | ".previous" \ | 383 | ".previous" \ |
363 | : "=r" (res) \ | 384 | : "=r" (res) \ |
364 | : "r" (value), "r" (addr), "i" (-EFAULT)); | 385 | : "r" (value), "r" (addr), "i" (-EFAULT)); \ |
386 | } while(0) | ||
365 | 387 | ||
366 | #define StoreDW(addr, value, res) \ | 388 | #define _StoreDW(addr, value, res) \ |
389 | do { \ | ||
367 | __asm__ __volatile__ ( \ | 390 | __asm__ __volatile__ ( \ |
368 | "1:\tsdl\t%1,(%2)\n" \ | 391 | "1:\tsdl\t%1,(%2)\n" \ |
369 | "2:\tsdr\t%1, 7(%2)\n\t" \ | 392 | "2:\tsdr\t%1, 7(%2)\n\t" \ |
@@ -379,20 +402,23 @@ extern void show_registers(struct pt_regs *regs); | |||
379 | STR(PTR)"\t2b, 4b\n\t" \ | 402 | STR(PTR)"\t2b, 4b\n\t" \ |
380 | ".previous" \ | 403 | ".previous" \ |
381 | : "=r" (res) \ | 404 | : "=r" (res) \ |
382 | : "r" (value), "r" (addr), "i" (-EFAULT)); | 405 | : "r" (value), "r" (addr), "i" (-EFAULT)); \ |
406 | } while(0) | ||
407 | |||
383 | #else | 408 | #else |
384 | /* MIPSR6 has no swl and sdl instructions */ | 409 | /* MIPSR6 has no swl and sdl instructions */ |
385 | #define StoreW(addr, value, res) \ | 410 | #define _StoreW(addr, value, res, type) \ |
411 | do { \ | ||
386 | __asm__ __volatile__ ( \ | 412 | __asm__ __volatile__ ( \ |
387 | ".set\tpush\n\t" \ | 413 | ".set\tpush\n\t" \ |
388 | ".set\tnoat\n\t" \ | 414 | ".set\tnoat\n\t" \ |
389 | "1:"user_sb("%1", "3(%2)")"\n\t" \ | 415 | "1:"type##_sb("%1", "3(%2)")"\n\t" \ |
390 | "srl\t$1, %1, 0x8\n\t" \ | 416 | "srl\t$1, %1, 0x8\n\t" \ |
391 | "2:"user_sb("$1", "2(%2)")"\n\t" \ | 417 | "2:"type##_sb("$1", "2(%2)")"\n\t" \ |
392 | "srl\t$1, $1, 0x8\n\t" \ | 418 | "srl\t$1, $1, 0x8\n\t" \ |
393 | "3:"user_sb("$1", "1(%2)")"\n\t" \ | 419 | "3:"type##_sb("$1", "1(%2)")"\n\t" \ |
394 | "srl\t$1, $1, 0x8\n\t" \ | 420 | "srl\t$1, $1, 0x8\n\t" \ |
395 | "4:"user_sb("$1", "0(%2)")"\n\t" \ | 421 | "4:"type##_sb("$1", "0(%2)")"\n\t" \ |
396 | ".set\tpop\n\t" \ | 422 | ".set\tpop\n\t" \ |
397 | "li\t%0, 0\n" \ | 423 | "li\t%0, 0\n" \ |
398 | "10:\n\t" \ | 424 | "10:\n\t" \ |
@@ -409,9 +435,11 @@ extern void show_registers(struct pt_regs *regs); | |||
409 | ".previous" \ | 435 | ".previous" \ |
410 | : "=&r" (res) \ | 436 | : "=&r" (res) \ |
411 | : "r" (value), "r" (addr), "i" (-EFAULT) \ | 437 | : "r" (value), "r" (addr), "i" (-EFAULT) \ |
412 | : "memory"); | 438 | : "memory"); \ |
439 | } while(0) | ||
413 | 440 | ||
414 | #define StoreDW(addr, value, res) \ | 441 | #define StoreDW(addr, value, res) \ |
442 | do { \ | ||
415 | __asm__ __volatile__ ( \ | 443 | __asm__ __volatile__ ( \ |
416 | ".set\tpush\n\t" \ | 444 | ".set\tpush\n\t" \ |
417 | ".set\tnoat\n\t" \ | 445 | ".set\tnoat\n\t" \ |
@@ -451,15 +479,18 @@ extern void show_registers(struct pt_regs *regs); | |||
451 | ".previous" \ | 479 | ".previous" \ |
452 | : "=&r" (res) \ | 480 | : "=&r" (res) \ |
453 | : "r" (value), "r" (addr), "i" (-EFAULT) \ | 481 | : "r" (value), "r" (addr), "i" (-EFAULT) \ |
454 | : "memory"); | 482 | : "memory"); \ |
483 | } while(0) | ||
484 | |||
455 | #endif /* CONFIG_CPU_MIPSR6 */ | 485 | #endif /* CONFIG_CPU_MIPSR6 */ |
456 | 486 | ||
457 | #else /* __BIG_ENDIAN */ | 487 | #else /* __BIG_ENDIAN */ |
458 | 488 | ||
459 | #define LoadHW(addr, value, res) \ | 489 | #define _LoadHW(addr, value, res, type) \ |
490 | do { \ | ||
460 | __asm__ __volatile__ (".set\tnoat\n" \ | 491 | __asm__ __volatile__ (".set\tnoat\n" \ |
461 | "1:\t"user_lb("%0", "1(%2)")"\n" \ | 492 | "1:\t"type##_lb("%0", "1(%2)")"\n" \ |
462 | "2:\t"user_lbu("$1", "0(%2)")"\n\t" \ | 493 | "2:\t"type##_lbu("$1", "0(%2)")"\n\t"\ |
463 | "sll\t%0, 0x8\n\t" \ | 494 | "sll\t%0, 0x8\n\t" \ |
464 | "or\t%0, $1\n\t" \ | 495 | "or\t%0, $1\n\t" \ |
465 | "li\t%1, 0\n" \ | 496 | "li\t%1, 0\n" \ |
@@ -474,13 +505,15 @@ extern void show_registers(struct pt_regs *regs); | |||
474 | STR(PTR)"\t2b, 4b\n\t" \ | 505 | STR(PTR)"\t2b, 4b\n\t" \ |
475 | ".previous" \ | 506 | ".previous" \ |
476 | : "=&r" (value), "=r" (res) \ | 507 | : "=&r" (value), "=r" (res) \ |
477 | : "r" (addr), "i" (-EFAULT)); | 508 | : "r" (addr), "i" (-EFAULT)); \ |
509 | } while(0) | ||
478 | 510 | ||
479 | #ifndef CONFIG_CPU_MIPSR6 | 511 | #ifndef CONFIG_CPU_MIPSR6 |
480 | #define LoadW(addr, value, res) \ | 512 | #define _LoadW(addr, value, res, type) \ |
513 | do { \ | ||
481 | __asm__ __volatile__ ( \ | 514 | __asm__ __volatile__ ( \ |
482 | "1:\t"user_lwl("%0", "3(%2)")"\n" \ | 515 | "1:\t"type##_lwl("%0", "3(%2)")"\n" \ |
483 | "2:\t"user_lwr("%0", "(%2)")"\n\t" \ | 516 | "2:\t"type##_lwr("%0", "(%2)")"\n\t"\ |
484 | "li\t%1, 0\n" \ | 517 | "li\t%1, 0\n" \ |
485 | "3:\n\t" \ | 518 | "3:\n\t" \ |
486 | ".insn\n\t" \ | 519 | ".insn\n\t" \ |
@@ -493,21 +526,24 @@ extern void show_registers(struct pt_regs *regs); | |||
493 | STR(PTR)"\t2b, 4b\n\t" \ | 526 | STR(PTR)"\t2b, 4b\n\t" \ |
494 | ".previous" \ | 527 | ".previous" \ |
495 | : "=&r" (value), "=r" (res) \ | 528 | : "=&r" (value), "=r" (res) \ |
496 | : "r" (addr), "i" (-EFAULT)); | 529 | : "r" (addr), "i" (-EFAULT)); \ |
530 | } while(0) | ||
531 | |||
497 | #else | 532 | #else |
498 | /* MIPSR6 has no lwl instruction */ | 533 | /* MIPSR6 has no lwl instruction */ |
499 | #define LoadW(addr, value, res) \ | 534 | #define _LoadW(addr, value, res, type) \ |
535 | do { \ | ||
500 | __asm__ __volatile__ ( \ | 536 | __asm__ __volatile__ ( \ |
501 | ".set\tpush\n" \ | 537 | ".set\tpush\n" \ |
502 | ".set\tnoat\n\t" \ | 538 | ".set\tnoat\n\t" \ |
503 | "1:"user_lb("%0", "3(%2)")"\n\t" \ | 539 | "1:"type##_lb("%0", "3(%2)")"\n\t" \ |
504 | "2:"user_lbu("$1", "2(%2)")"\n\t" \ | 540 | "2:"type##_lbu("$1", "2(%2)")"\n\t" \ |
505 | "sll\t%0, 0x8\n\t" \ | 541 | "sll\t%0, 0x8\n\t" \ |
506 | "or\t%0, $1\n\t" \ | 542 | "or\t%0, $1\n\t" \ |
507 | "3:"user_lbu("$1", "1(%2)")"\n\t" \ | 543 | "3:"type##_lbu("$1", "1(%2)")"\n\t" \ |
508 | "sll\t%0, 0x8\n\t" \ | 544 | "sll\t%0, 0x8\n\t" \ |
509 | "or\t%0, $1\n\t" \ | 545 | "or\t%0, $1\n\t" \ |
510 | "4:"user_lbu("$1", "0(%2)")"\n\t" \ | 546 | "4:"type##_lbu("$1", "0(%2)")"\n\t" \ |
511 | "sll\t%0, 0x8\n\t" \ | 547 | "sll\t%0, 0x8\n\t" \ |
512 | "or\t%0, $1\n\t" \ | 548 | "or\t%0, $1\n\t" \ |
513 | "li\t%1, 0\n" \ | 549 | "li\t%1, 0\n" \ |
@@ -525,15 +561,18 @@ extern void show_registers(struct pt_regs *regs); | |||
525 | STR(PTR)"\t4b, 11b\n\t" \ | 561 | STR(PTR)"\t4b, 11b\n\t" \ |
526 | ".previous" \ | 562 | ".previous" \ |
527 | : "=&r" (value), "=r" (res) \ | 563 | : "=&r" (value), "=r" (res) \ |
528 | : "r" (addr), "i" (-EFAULT)); | 564 | : "r" (addr), "i" (-EFAULT)); \ |
565 | } while(0) | ||
566 | |||
529 | #endif /* CONFIG_CPU_MIPSR6 */ | 567 | #endif /* CONFIG_CPU_MIPSR6 */ |
530 | 568 | ||
531 | 569 | ||
532 | #define LoadHWU(addr, value, res) \ | 570 | #define _LoadHWU(addr, value, res, type) \ |
571 | do { \ | ||
533 | __asm__ __volatile__ ( \ | 572 | __asm__ __volatile__ ( \ |
534 | ".set\tnoat\n" \ | 573 | ".set\tnoat\n" \ |
535 | "1:\t"user_lbu("%0", "1(%2)")"\n" \ | 574 | "1:\t"type##_lbu("%0", "1(%2)")"\n" \ |
536 | "2:\t"user_lbu("$1", "0(%2)")"\n\t" \ | 575 | "2:\t"type##_lbu("$1", "0(%2)")"\n\t"\ |
537 | "sll\t%0, 0x8\n\t" \ | 576 | "sll\t%0, 0x8\n\t" \ |
538 | "or\t%0, $1\n\t" \ | 577 | "or\t%0, $1\n\t" \ |
539 | "li\t%1, 0\n" \ | 578 | "li\t%1, 0\n" \ |
@@ -549,13 +588,15 @@ extern void show_registers(struct pt_regs *regs); | |||
549 | STR(PTR)"\t2b, 4b\n\t" \ | 588 | STR(PTR)"\t2b, 4b\n\t" \ |
550 | ".previous" \ | 589 | ".previous" \ |
551 | : "=&r" (value), "=r" (res) \ | 590 | : "=&r" (value), "=r" (res) \ |
552 | : "r" (addr), "i" (-EFAULT)); | 591 | : "r" (addr), "i" (-EFAULT)); \ |
592 | } while(0) | ||
553 | 593 | ||
554 | #ifndef CONFIG_CPU_MIPSR6 | 594 | #ifndef CONFIG_CPU_MIPSR6 |
555 | #define LoadWU(addr, value, res) \ | 595 | #define _LoadWU(addr, value, res, type) \ |
596 | do { \ | ||
556 | __asm__ __volatile__ ( \ | 597 | __asm__ __volatile__ ( \ |
557 | "1:\t"user_lwl("%0", "3(%2)")"\n" \ | 598 | "1:\t"type##_lwl("%0", "3(%2)")"\n" \ |
558 | "2:\t"user_lwr("%0", "(%2)")"\n\t" \ | 599 | "2:\t"type##_lwr("%0", "(%2)")"\n\t"\ |
559 | "dsll\t%0, %0, 32\n\t" \ | 600 | "dsll\t%0, %0, 32\n\t" \ |
560 | "dsrl\t%0, %0, 32\n\t" \ | 601 | "dsrl\t%0, %0, 32\n\t" \ |
561 | "li\t%1, 0\n" \ | 602 | "li\t%1, 0\n" \ |
@@ -570,9 +611,11 @@ extern void show_registers(struct pt_regs *regs); | |||
570 | STR(PTR)"\t2b, 4b\n\t" \ | 611 | STR(PTR)"\t2b, 4b\n\t" \ |
571 | ".previous" \ | 612 | ".previous" \ |
572 | : "=&r" (value), "=r" (res) \ | 613 | : "=&r" (value), "=r" (res) \ |
573 | : "r" (addr), "i" (-EFAULT)); | 614 | : "r" (addr), "i" (-EFAULT)); \ |
615 | } while(0) | ||
574 | 616 | ||
575 | #define LoadDW(addr, value, res) \ | 617 | #define _LoadDW(addr, value, res) \ |
618 | do { \ | ||
576 | __asm__ __volatile__ ( \ | 619 | __asm__ __volatile__ ( \ |
577 | "1:\tldl\t%0, 7(%2)\n" \ | 620 | "1:\tldl\t%0, 7(%2)\n" \ |
578 | "2:\tldr\t%0, (%2)\n\t" \ | 621 | "2:\tldr\t%0, (%2)\n\t" \ |
@@ -588,21 +631,24 @@ extern void show_registers(struct pt_regs *regs); | |||
588 | STR(PTR)"\t2b, 4b\n\t" \ | 631 | STR(PTR)"\t2b, 4b\n\t" \ |
589 | ".previous" \ | 632 | ".previous" \ |
590 | : "=&r" (value), "=r" (res) \ | 633 | : "=&r" (value), "=r" (res) \ |
591 | : "r" (addr), "i" (-EFAULT)); | 634 | : "r" (addr), "i" (-EFAULT)); \ |
635 | } while(0) | ||
636 | |||
592 | #else | 637 | #else |
593 | /* MIPSR6 has not lwl and ldl instructions */ | 638 | /* MIPSR6 has not lwl and ldl instructions */ |
594 | #define LoadWU(addr, value, res) \ | 639 | #define _LoadWU(addr, value, res, type) \ |
640 | do { \ | ||
595 | __asm__ __volatile__ ( \ | 641 | __asm__ __volatile__ ( \ |
596 | ".set\tpush\n\t" \ | 642 | ".set\tpush\n\t" \ |
597 | ".set\tnoat\n\t" \ | 643 | ".set\tnoat\n\t" \ |
598 | "1:"user_lbu("%0", "3(%2)")"\n\t" \ | 644 | "1:"type##_lbu("%0", "3(%2)")"\n\t" \ |
599 | "2:"user_lbu("$1", "2(%2)")"\n\t" \ | 645 | "2:"type##_lbu("$1", "2(%2)")"\n\t" \ |
600 | "sll\t%0, 0x8\n\t" \ | 646 | "sll\t%0, 0x8\n\t" \ |
601 | "or\t%0, $1\n\t" \ | 647 | "or\t%0, $1\n\t" \ |
602 | "3:"user_lbu("$1", "1(%2)")"\n\t" \ | 648 | "3:"type##_lbu("$1", "1(%2)")"\n\t" \ |
603 | "sll\t%0, 0x8\n\t" \ | 649 | "sll\t%0, 0x8\n\t" \ |
604 | "or\t%0, $1\n\t" \ | 650 | "or\t%0, $1\n\t" \ |
605 | "4:"user_lbu("$1", "0(%2)")"\n\t" \ | 651 | "4:"type##_lbu("$1", "0(%2)")"\n\t" \ |
606 | "sll\t%0, 0x8\n\t" \ | 652 | "sll\t%0, 0x8\n\t" \ |
607 | "or\t%0, $1\n\t" \ | 653 | "or\t%0, $1\n\t" \ |
608 | "li\t%1, 0\n" \ | 654 | "li\t%1, 0\n" \ |
@@ -620,9 +666,11 @@ extern void show_registers(struct pt_regs *regs); | |||
620 | STR(PTR)"\t4b, 11b\n\t" \ | 666 | STR(PTR)"\t4b, 11b\n\t" \ |
621 | ".previous" \ | 667 | ".previous" \ |
622 | : "=&r" (value), "=r" (res) \ | 668 | : "=&r" (value), "=r" (res) \ |
623 | : "r" (addr), "i" (-EFAULT)); | 669 | : "r" (addr), "i" (-EFAULT)); \ |
670 | } while(0) | ||
624 | 671 | ||
625 | #define LoadDW(addr, value, res) \ | 672 | #define _LoadDW(addr, value, res) \ |
673 | do { \ | ||
626 | __asm__ __volatile__ ( \ | 674 | __asm__ __volatile__ ( \ |
627 | ".set\tpush\n\t" \ | 675 | ".set\tpush\n\t" \ |
628 | ".set\tnoat\n\t" \ | 676 | ".set\tnoat\n\t" \ |
@@ -667,15 +715,17 @@ extern void show_registers(struct pt_regs *regs); | |||
667 | STR(PTR)"\t8b, 11b\n\t" \ | 715 | STR(PTR)"\t8b, 11b\n\t" \ |
668 | ".previous" \ | 716 | ".previous" \ |
669 | : "=&r" (value), "=r" (res) \ | 717 | : "=&r" (value), "=r" (res) \ |
670 | : "r" (addr), "i" (-EFAULT)); | 718 | : "r" (addr), "i" (-EFAULT)); \ |
719 | } while(0) | ||
671 | #endif /* CONFIG_CPU_MIPSR6 */ | 720 | #endif /* CONFIG_CPU_MIPSR6 */ |
672 | 721 | ||
673 | #define StoreHW(addr, value, res) \ | 722 | #define _StoreHW(addr, value, res, type) \ |
723 | do { \ | ||
674 | __asm__ __volatile__ ( \ | 724 | __asm__ __volatile__ ( \ |
675 | ".set\tnoat\n" \ | 725 | ".set\tnoat\n" \ |
676 | "1:\t"user_sb("%1", "0(%2)")"\n" \ | 726 | "1:\t"type##_sb("%1", "0(%2)")"\n" \ |
677 | "srl\t$1,%1, 0x8\n" \ | 727 | "srl\t$1,%1, 0x8\n" \ |
678 | "2:\t"user_sb("$1", "1(%2)")"\n" \ | 728 | "2:\t"type##_sb("$1", "1(%2)")"\n" \ |
679 | ".set\tat\n\t" \ | 729 | ".set\tat\n\t" \ |
680 | "li\t%0, 0\n" \ | 730 | "li\t%0, 0\n" \ |
681 | "3:\n\t" \ | 731 | "3:\n\t" \ |
@@ -689,12 +739,15 @@ extern void show_registers(struct pt_regs *regs); | |||
689 | STR(PTR)"\t2b, 4b\n\t" \ | 739 | STR(PTR)"\t2b, 4b\n\t" \ |
690 | ".previous" \ | 740 | ".previous" \ |
691 | : "=r" (res) \ | 741 | : "=r" (res) \ |
692 | : "r" (value), "r" (addr), "i" (-EFAULT)); | 742 | : "r" (value), "r" (addr), "i" (-EFAULT));\ |
743 | } while(0) | ||
744 | |||
693 | #ifndef CONFIG_CPU_MIPSR6 | 745 | #ifndef CONFIG_CPU_MIPSR6 |
694 | #define StoreW(addr, value, res) \ | 746 | #define _StoreW(addr, value, res, type) \ |
747 | do { \ | ||
695 | __asm__ __volatile__ ( \ | 748 | __asm__ __volatile__ ( \ |
696 | "1:\t"user_swl("%1", "3(%2)")"\n" \ | 749 | "1:\t"type##_swl("%1", "3(%2)")"\n" \ |
697 | "2:\t"user_swr("%1", "(%2)")"\n\t" \ | 750 | "2:\t"type##_swr("%1", "(%2)")"\n\t"\ |
698 | "li\t%0, 0\n" \ | 751 | "li\t%0, 0\n" \ |
699 | "3:\n\t" \ | 752 | "3:\n\t" \ |
700 | ".insn\n\t" \ | 753 | ".insn\n\t" \ |
@@ -707,9 +760,11 @@ extern void show_registers(struct pt_regs *regs); | |||
707 | STR(PTR)"\t2b, 4b\n\t" \ | 760 | STR(PTR)"\t2b, 4b\n\t" \ |
708 | ".previous" \ | 761 | ".previous" \ |
709 | : "=r" (res) \ | 762 | : "=r" (res) \ |
710 | : "r" (value), "r" (addr), "i" (-EFAULT)); | 763 | : "r" (value), "r" (addr), "i" (-EFAULT)); \ |
764 | } while(0) | ||
711 | 765 | ||
712 | #define StoreDW(addr, value, res) \ | 766 | #define _StoreDW(addr, value, res) \ |
767 | do { \ | ||
713 | __asm__ __volatile__ ( \ | 768 | __asm__ __volatile__ ( \ |
714 | "1:\tsdl\t%1, 7(%2)\n" \ | 769 | "1:\tsdl\t%1, 7(%2)\n" \ |
715 | "2:\tsdr\t%1, (%2)\n\t" \ | 770 | "2:\tsdr\t%1, (%2)\n\t" \ |
@@ -725,20 +780,23 @@ extern void show_registers(struct pt_regs *regs); | |||
725 | STR(PTR)"\t2b, 4b\n\t" \ | 780 | STR(PTR)"\t2b, 4b\n\t" \ |
726 | ".previous" \ | 781 | ".previous" \ |
727 | : "=r" (res) \ | 782 | : "=r" (res) \ |
728 | : "r" (value), "r" (addr), "i" (-EFAULT)); | 783 | : "r" (value), "r" (addr), "i" (-EFAULT)); \ |
784 | } while(0) | ||
785 | |||
729 | #else | 786 | #else |
730 | /* MIPSR6 has no swl and sdl instructions */ | 787 | /* MIPSR6 has no swl and sdl instructions */ |
731 | #define StoreW(addr, value, res) \ | 788 | #define _StoreW(addr, value, res, type) \ |
789 | do { \ | ||
732 | __asm__ __volatile__ ( \ | 790 | __asm__ __volatile__ ( \ |
733 | ".set\tpush\n\t" \ | 791 | ".set\tpush\n\t" \ |
734 | ".set\tnoat\n\t" \ | 792 | ".set\tnoat\n\t" \ |
735 | "1:"user_sb("%1", "0(%2)")"\n\t" \ | 793 | "1:"type##_sb("%1", "0(%2)")"\n\t" \ |
736 | "srl\t$1, %1, 0x8\n\t" \ | 794 | "srl\t$1, %1, 0x8\n\t" \ |
737 | "2:"user_sb("$1", "1(%2)")"\n\t" \ | 795 | "2:"type##_sb("$1", "1(%2)")"\n\t" \ |
738 | "srl\t$1, $1, 0x8\n\t" \ | 796 | "srl\t$1, $1, 0x8\n\t" \ |
739 | "3:"user_sb("$1", "2(%2)")"\n\t" \ | 797 | "3:"type##_sb("$1", "2(%2)")"\n\t" \ |
740 | "srl\t$1, $1, 0x8\n\t" \ | 798 | "srl\t$1, $1, 0x8\n\t" \ |
741 | "4:"user_sb("$1", "3(%2)")"\n\t" \ | 799 | "4:"type##_sb("$1", "3(%2)")"\n\t" \ |
742 | ".set\tpop\n\t" \ | 800 | ".set\tpop\n\t" \ |
743 | "li\t%0, 0\n" \ | 801 | "li\t%0, 0\n" \ |
744 | "10:\n\t" \ | 802 | "10:\n\t" \ |
@@ -755,9 +813,11 @@ extern void show_registers(struct pt_regs *regs); | |||
755 | ".previous" \ | 813 | ".previous" \ |
756 | : "=&r" (res) \ | 814 | : "=&r" (res) \ |
757 | : "r" (value), "r" (addr), "i" (-EFAULT) \ | 815 | : "r" (value), "r" (addr), "i" (-EFAULT) \ |
758 | : "memory"); | 816 | : "memory"); \ |
817 | } while(0) | ||
759 | 818 | ||
760 | #define StoreDW(addr, value, res) \ | 819 | #define _StoreDW(addr, value, res) \ |
820 | do { \ | ||
761 | __asm__ __volatile__ ( \ | 821 | __asm__ __volatile__ ( \ |
762 | ".set\tpush\n\t" \ | 822 | ".set\tpush\n\t" \ |
763 | ".set\tnoat\n\t" \ | 823 | ".set\tnoat\n\t" \ |
@@ -797,10 +857,28 @@ extern void show_registers(struct pt_regs *regs); | |||
797 | ".previous" \ | 857 | ".previous" \ |
798 | : "=&r" (res) \ | 858 | : "=&r" (res) \ |
799 | : "r" (value), "r" (addr), "i" (-EFAULT) \ | 859 | : "r" (value), "r" (addr), "i" (-EFAULT) \ |
800 | : "memory"); | 860 | : "memory"); \ |
861 | } while(0) | ||
862 | |||
801 | #endif /* CONFIG_CPU_MIPSR6 */ | 863 | #endif /* CONFIG_CPU_MIPSR6 */ |
802 | #endif | 864 | #endif |
803 | 865 | ||
866 | #define LoadHWU(addr, value, res) _LoadHWU(addr, value, res, kernel) | ||
867 | #define LoadHWUE(addr, value, res) _LoadHWU(addr, value, res, user) | ||
868 | #define LoadWU(addr, value, res) _LoadWU(addr, value, res, kernel) | ||
869 | #define LoadWUE(addr, value, res) _LoadWU(addr, value, res, user) | ||
870 | #define LoadHW(addr, value, res) _LoadHW(addr, value, res, kernel) | ||
871 | #define LoadHWE(addr, value, res) _LoadHW(addr, value, res, user) | ||
872 | #define LoadW(addr, value, res) _LoadW(addr, value, res, kernel) | ||
873 | #define LoadWE(addr, value, res) _LoadW(addr, value, res, user) | ||
874 | #define LoadDW(addr, value, res) _LoadDW(addr, value, res) | ||
875 | |||
876 | #define StoreHW(addr, value, res) _StoreHW(addr, value, res, kernel) | ||
877 | #define StoreHWE(addr, value, res) _StoreHW(addr, value, res, user) | ||
878 | #define StoreW(addr, value, res) _StoreW(addr, value, res, kernel) | ||
879 | #define StoreWE(addr, value, res) _StoreW(addr, value, res, user) | ||
880 | #define StoreDW(addr, value, res) _StoreDW(addr, value, res) | ||
881 | |||
804 | static void emulate_load_store_insn(struct pt_regs *regs, | 882 | static void emulate_load_store_insn(struct pt_regs *regs, |
805 | void __user *addr, unsigned int __user *pc) | 883 | void __user *addr, unsigned int __user *pc) |
806 | { | 884 | { |
@@ -872,7 +950,7 @@ static void emulate_load_store_insn(struct pt_regs *regs, | |||
872 | set_fs(seg); | 950 | set_fs(seg); |
873 | goto sigbus; | 951 | goto sigbus; |
874 | } | 952 | } |
875 | LoadHW(addr, value, res); | 953 | LoadHWE(addr, value, res); |
876 | if (res) { | 954 | if (res) { |
877 | set_fs(seg); | 955 | set_fs(seg); |
878 | goto fault; | 956 | goto fault; |
@@ -885,7 +963,7 @@ static void emulate_load_store_insn(struct pt_regs *regs, | |||
885 | set_fs(seg); | 963 | set_fs(seg); |
886 | goto sigbus; | 964 | goto sigbus; |
887 | } | 965 | } |
888 | LoadW(addr, value, res); | 966 | LoadWE(addr, value, res); |
889 | if (res) { | 967 | if (res) { |
890 | set_fs(seg); | 968 | set_fs(seg); |
891 | goto fault; | 969 | goto fault; |
@@ -898,7 +976,7 @@ static void emulate_load_store_insn(struct pt_regs *regs, | |||
898 | set_fs(seg); | 976 | set_fs(seg); |
899 | goto sigbus; | 977 | goto sigbus; |
900 | } | 978 | } |
901 | LoadHWU(addr, value, res); | 979 | LoadHWUE(addr, value, res); |
902 | if (res) { | 980 | if (res) { |
903 | set_fs(seg); | 981 | set_fs(seg); |
904 | goto fault; | 982 | goto fault; |
@@ -913,7 +991,7 @@ static void emulate_load_store_insn(struct pt_regs *regs, | |||
913 | } | 991 | } |
914 | compute_return_epc(regs); | 992 | compute_return_epc(regs); |
915 | value = regs->regs[insn.spec3_format.rt]; | 993 | value = regs->regs[insn.spec3_format.rt]; |
916 | StoreHW(addr, value, res); | 994 | StoreHWE(addr, value, res); |
917 | if (res) { | 995 | if (res) { |
918 | set_fs(seg); | 996 | set_fs(seg); |
919 | goto fault; | 997 | goto fault; |
@@ -926,7 +1004,7 @@ static void emulate_load_store_insn(struct pt_regs *regs, | |||
926 | } | 1004 | } |
927 | compute_return_epc(regs); | 1005 | compute_return_epc(regs); |
928 | value = regs->regs[insn.spec3_format.rt]; | 1006 | value = regs->regs[insn.spec3_format.rt]; |
929 | StoreW(addr, value, res); | 1007 | StoreWE(addr, value, res); |
930 | if (res) { | 1008 | if (res) { |
931 | set_fs(seg); | 1009 | set_fs(seg); |
932 | goto fault; | 1010 | goto fault; |
@@ -943,7 +1021,15 @@ static void emulate_load_store_insn(struct pt_regs *regs, | |||
943 | if (!access_ok(VERIFY_READ, addr, 2)) | 1021 | if (!access_ok(VERIFY_READ, addr, 2)) |
944 | goto sigbus; | 1022 | goto sigbus; |
945 | 1023 | ||
946 | LoadHW(addr, value, res); | 1024 | if (config_enabled(CONFIG_EVA)) { |
1025 | if (segment_eq(get_fs(), get_ds())) | ||
1026 | LoadHW(addr, value, res); | ||
1027 | else | ||
1028 | LoadHWE(addr, value, res); | ||
1029 | } else { | ||
1030 | LoadHW(addr, value, res); | ||
1031 | } | ||
1032 | |||
947 | if (res) | 1033 | if (res) |
948 | goto fault; | 1034 | goto fault; |
949 | compute_return_epc(regs); | 1035 | compute_return_epc(regs); |
@@ -954,7 +1040,15 @@ static void emulate_load_store_insn(struct pt_regs *regs, | |||
954 | if (!access_ok(VERIFY_READ, addr, 4)) | 1040 | if (!access_ok(VERIFY_READ, addr, 4)) |
955 | goto sigbus; | 1041 | goto sigbus; |
956 | 1042 | ||
957 | LoadW(addr, value, res); | 1043 | if (config_enabled(CONFIG_EVA)) { |
1044 | if (segment_eq(get_fs(), get_ds())) | ||
1045 | LoadW(addr, value, res); | ||
1046 | else | ||
1047 | LoadWE(addr, value, res); | ||
1048 | } else { | ||
1049 | LoadW(addr, value, res); | ||
1050 | } | ||
1051 | |||
958 | if (res) | 1052 | if (res) |
959 | goto fault; | 1053 | goto fault; |
960 | compute_return_epc(regs); | 1054 | compute_return_epc(regs); |
@@ -965,7 +1059,15 @@ static void emulate_load_store_insn(struct pt_regs *regs, | |||
965 | if (!access_ok(VERIFY_READ, addr, 2)) | 1059 | if (!access_ok(VERIFY_READ, addr, 2)) |
966 | goto sigbus; | 1060 | goto sigbus; |
967 | 1061 | ||
968 | LoadHWU(addr, value, res); | 1062 | if (config_enabled(CONFIG_EVA)) { |
1063 | if (segment_eq(get_fs(), get_ds())) | ||
1064 | LoadHWU(addr, value, res); | ||
1065 | else | ||
1066 | LoadHWUE(addr, value, res); | ||
1067 | } else { | ||
1068 | LoadHWU(addr, value, res); | ||
1069 | } | ||
1070 | |||
969 | if (res) | 1071 | if (res) |
970 | goto fault; | 1072 | goto fault; |
971 | compute_return_epc(regs); | 1073 | compute_return_epc(regs); |
@@ -1024,7 +1126,16 @@ static void emulate_load_store_insn(struct pt_regs *regs, | |||
1024 | 1126 | ||
1025 | compute_return_epc(regs); | 1127 | compute_return_epc(regs); |
1026 | value = regs->regs[insn.i_format.rt]; | 1128 | value = regs->regs[insn.i_format.rt]; |
1027 | StoreHW(addr, value, res); | 1129 | |
1130 | if (config_enabled(CONFIG_EVA)) { | ||
1131 | if (segment_eq(get_fs(), get_ds())) | ||
1132 | StoreHW(addr, value, res); | ||
1133 | else | ||
1134 | StoreHWE(addr, value, res); | ||
1135 | } else { | ||
1136 | StoreHW(addr, value, res); | ||
1137 | } | ||
1138 | |||
1028 | if (res) | 1139 | if (res) |
1029 | goto fault; | 1140 | goto fault; |
1030 | break; | 1141 | break; |
@@ -1035,7 +1146,16 @@ static void emulate_load_store_insn(struct pt_regs *regs, | |||
1035 | 1146 | ||
1036 | compute_return_epc(regs); | 1147 | compute_return_epc(regs); |
1037 | value = regs->regs[insn.i_format.rt]; | 1148 | value = regs->regs[insn.i_format.rt]; |
1038 | StoreW(addr, value, res); | 1149 | |
1150 | if (config_enabled(CONFIG_EVA)) { | ||
1151 | if (segment_eq(get_fs(), get_ds())) | ||
1152 | StoreW(addr, value, res); | ||
1153 | else | ||
1154 | StoreWE(addr, value, res); | ||
1155 | } else { | ||
1156 | StoreW(addr, value, res); | ||
1157 | } | ||
1158 | |||
1039 | if (res) | 1159 | if (res) |
1040 | goto fault; | 1160 | goto fault; |
1041 | break; | 1161 | break; |
@@ -1076,7 +1196,7 @@ static void emulate_load_store_insn(struct pt_regs *regs, | |||
1076 | own_fpu(1); /* Restore FPU state. */ | 1196 | own_fpu(1); /* Restore FPU state. */ |
1077 | 1197 | ||
1078 | /* Signal if something went wrong. */ | 1198 | /* Signal if something went wrong. */ |
1079 | process_fpemu_return(res, fault_addr); | 1199 | process_fpemu_return(res, fault_addr, 0); |
1080 | 1200 | ||
1081 | if (res == 0) | 1201 | if (res == 0) |
1082 | break; | 1202 | break; |
@@ -1511,7 +1631,7 @@ fpu_emul: | |||
1511 | own_fpu(1); /* restore FPU state */ | 1631 | own_fpu(1); /* restore FPU state */ |
1512 | 1632 | ||
1513 | /* If something went wrong, signal */ | 1633 | /* If something went wrong, signal */ |
1514 | process_fpemu_return(res, fault_addr); | 1634 | process_fpemu_return(res, fault_addr, 0); |
1515 | 1635 | ||
1516 | if (res == 0) | 1636 | if (res == 0) |
1517 | goto success; | 1637 | goto success; |