Patch "MIPS: unaligned: Prevent EVA instructions on kernel unaligned accesses" has been added to the 4.0-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
MIPS: unaligned: Prevent EVA instructions on kernel unaligned accesses
to the 4.0-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
mips-unaligned-prevent-eva-instructions-on-kernel-unaligned-accesses.patch
and it can be found in the queue-4.0 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
eeb538950367e3966cbf0237ab1a1dc30e059818Mon Sep 17 00:00:00 2001
From: Markos Chandras <[email protected]>
Date: Mon, 9 Mar 2015 14:54:50 +0000
Subject: MIPS: unaligned: Prevent EVA instructions on kernel unaligned accesses
From: Markos Chandras <[email protected]>
commit eeb538950367e3966cbf0237ab1a1dc30e059818 upstream.
Commit c1771216ab48 ("MIPS: kernel: unaligned: Handle unaligned accesses for EVA") allowed unaligned accesses to be emulated for EVA. However, when emulating regular load/store unaligned accesses, we need to use the appropriate "address space" instructions for that. Previously, an unaligned load/store instruction in kernel space would have used the corresponding EVA instructions to emulate it which led to segmentation faults because of the address translation that happens with EVA instructions. This is now fixed by using the EVA instruction only when emulating EVA unaligned accesses.
Patchwork: https://patchwork.linux-mips.org/patch/9501/
--- arch/mips/kernel/unaligned.c | 172 +++++++++++++++++++++++-------------------- 1 file changed, 94 insertions(+), 78 deletions(-)
arch/mips/kernel/unaligned.c +94 -78
@@ -109,10 +109,10 @@ static u32 unaligned_action;extern void show_registers (struct pt_regs *regs);#ifdef __BIG_ENDIAN -#define LoadHW (addr, value, res) \ +#define _LoadHW (addr, value, res, type) \ __asm__ __volatile__ (".set\tnoat\n" \ - "1:\t"user_lb("%0", "0(%2)")"\n" \ - "2:\t"user_lbu("$1", "1(%2)")"\n\t" \ + "1:\t"type##_lb("%0", "0(%2)")"\n" \ + "2:\t"type##_lbu("$1", "1(%2)")"\n\t"\ "sll\t%0, 0x8\n\t" \ "or\t%0, $1\n\t" \ "li\t%1, 0\n" \
@@ -130,10 +130,10 @@ extern void show_registers(struct pt_reg : "r" (addr), "i" (-EFAULT));#ifndef CONFIG_CPU_MIPSR6 -#define LoadW (addr, value, res) \ +#define _LoadW (addr, value, res, type) \ __asm__ __volatile__ ( \ - "1:\t"user_lwl("%0", "(%2)")"\n" \ - "2:\t"user_lwr("%0", "3(%2)")"\n\t" \ + "1:\t"type##_lwl("%0", "(%2)")"\n" \ + "2:\t"type##_lwr("%0", "3(%2)")"\n\t"\ "li\t%1, 0\n" \ "3:\n\t" \ ".insn\n\t" \
@@ -149,18 +149,18 @@ extern void show_registers(struct pt_reg : "r" (addr), "i" (-EFAULT));#else /* MIPSR6 has no lwl instruction */ -#define LoadW (addr, value, res) \ +#define _LoadW (addr, value, res, type) \ __asm__ __volatile__ ( \ ".set\tpush\n" \ ".set\tnoat\n\t" \ - "1:"user_lb("%0", "0(%2)")"\n\t" \ - "2:"user_lbu("$1", "1(%2)")"\n\t" \ + "1:"type##_lb("%0", "0(%2)")"\n\t" \ + "2:"type##_lbu("$1", "1(%2)")"\n\t" \ "sll\t%0, 0x8\n\t" \ "or\t%0, $1\n\t" \ - "3:"user_lbu("$1", "2(%2)")"\n\t" \ + "3:"type##_lbu("$1", "2(%2)")"\n\t" \ "sll\t%0, 0x8\n\t" \ "or\t%0, $1\n\t" \ - "4:"user_lbu("$1", "3(%2)")"\n\t" \ + "4:"type##_lbu("$1", "3(%2)")"\n\t" \ "sll\t%0, 0x8\n\t" \ "or\t%0, $1\n\t" \ "li\t%1, 0\n" \
@@ -181,11 +181,11 @@ extern void show_registers(struct pt_reg : "r" (addr), "i" (-EFAULT));#endif /* CONFIG_CPU_MIPSR6 */ -#define LoadHWU (addr, value, res) \ +#define _LoadHWU (addr, value, res, type) \ __asm__ __volatile__ ( \ ".set\tnoat\n" \ - "1:\t"user_lbu("%0", "0(%2)")"\n" \ - "2:\t"user_lbu("$1", "1(%2)")"\n\t" \ + "1:\t"type##_lbu("%0", "0(%2)")"\n" \ + "2:\t"type##_lbu("$1", "1(%2)")"\n\t"\ "sll\t%0, 0x8\n\t" \ "or\t%0, $1\n\t" \ "li\t%1, 0\n" \
@@ -204,10 +204,10 @@ extern void show_registers(struct pt_reg : "r" (addr), "i" (-EFAULT));#ifndef CONFIG_CPU_MIPSR6 -#define LoadWU (addr, value, res) \ +#define _LoadWU (addr, value, res, type) \ __asm__ __volatile__ ( \ - "1:\t"user_lwl("%0", "(%2)")"\n" \ - "2:\t"user_lwr("%0", "3(%2)")"\n\t" \ + "1:\t"type##_lwl("%0", "(%2)")"\n" \ + "2:\t"type##_lwr("%0", "3(%2)")"\n\t"\ "dsll\t%0, %0, 32\n\t" \ "dsrl\t%0, %0, 32\n\t" \ "li\t%1, 0\n" \
@@ -224,7 +224,7 @@ extern void show_registers(struct pt_reg : "=&r" (value), "=r" (res) \ : "r" (addr), "i" (-EFAULT)); -#define LoadDW (addr, value, res) \ +#define _LoadDW (addr, value, res) \ __asm__ __volatile__ ( \ "1:\tldl\t%0, (%2)\n" \ "2:\tldr\t%0, 7(%2)\n\t" \
@@ -243,18 +243,18 @@ extern void show_registers(struct pt_reg : "r" (addr), "i" (-EFAULT));#else /* MIPSR6 has not lwl and ldl instructions */ -#define LoadWU (addr, value, res) \ +#define _LoadWU (addr, value, res, type) \ __asm__ __volatile__ ( \ ".set\tpush\n\t" \ ".set\tnoat\n\t" \ - "1:"user_lbu("%0", "0(%2)")"\n\t" \ - "2:"user_lbu("$1", "1(%2)")"\n\t" \ + "1:"type##_lbu("%0", "0(%2)")"\n\t" \ + "2:"type##_lbu("$1", "1(%2)")"\n\t" \ "sll\t%0, 0x8\n\t" \ "or\t%0, $1\n\t" \ - "3:"user_lbu("$1", "2(%2)")"\n\t" \ + "3:"type##_lbu("$1", "2(%2)")"\n\t" \ "sll\t%0, 0x8\n\t" \ "or\t%0, $1\n\t" \ - "4:"user_lbu("$1", "3(%2)")"\n\t" \ + "4:"type##_lbu("$1", "3(%2)")"\n\t" \ "sll\t%0, 0x8\n\t" \ "or\t%0, $1\n\t" \ "li\t%1, 0\n" \
@@ -274,7 +274,7 @@ extern void show_registers(struct pt_reg : "=&r" (value), "=r" (res) \ : "r" (addr), "i" (-EFAULT)); -#define LoadDW (addr, value, res) \ +#define _LoadDW (addr, value, res) \ __asm__ __volatile__ ( \ ".set\tpush\n\t" \ ".set\tnoat\n\t" \
@@ -323,12 +323,12 @@ extern void show_registers(struct pt_reg#endif /* CONFIG_CPU_MIPSR6 */ -#define StoreHW (addr, value, res) \ +#define _StoreHW (addr, value, res, type) \ __asm__ __volatile__ ( \ ".set\tnoat\n" \ - "1:\t"user_sb("%1", "1(%2)")"\n" \ + "1:\t"type##_sb("%1", "1(%2)")"\n" \ "srl\t$1, %1, 0x8\n" \ - "2:\t"user_sb("$1", "0(%2)")"\n" \ + "2:\t"type##_sb("$1", "0(%2)")"\n" \ ".set\tat\n\t" \ "li\t%0, 0\n" \ "3:\n\t" \
@@ -345,10 +345,10 @@ extern void show_registers(struct pt_reg : "r" (value), "r" (addr), "i" (-EFAULT));#ifndef CONFIG_CPU_MIPSR6 -#define StoreW (addr, value, res) \ +#define _StoreW (addr, value, res, type) \ __asm__ __volatile__ ( \ - "1:\t"user_swl("%1", "(%2)")"\n" \ - "2:\t"user_swr("%1", "3(%2)")"\n\t" \ + "1:\t"type##_swl("%1", "(%2)")"\n" \ + "2:\t"type##_swr("%1", "3(%2)")"\n\t"\ "li\t%0, 0\n" \ "3:\n\t" \ ".insn\n\t" \
@@ -363,7 +363,7 @@ extern void show_registers(struct pt_reg : "=r" (res) \ : "r" (value), "r" (addr), "i" (-EFAULT)); -#define StoreDW (addr, value, res) \ +#define _StoreDW (addr, value, res) \ __asm__ __volatile__ ( \ "1:\tsdl\t%1,(%2)\n" \ "2:\tsdr\t%1, 7(%2)\n\t" \
@@ -382,17 +382,17 @@ extern void show_registers(struct pt_reg : "r" (value), "r" (addr), "i" (-EFAULT));#else /* MIPSR6 has no swl and sdl instructions */ -#define StoreW (addr, value, res) \ +#define _StoreW (addr, value, res, type) \ __asm__ __volatile__ ( \ ".set\tpush\n\t" \ ".set\tnoat\n\t" \ - "1:"user_sb("%1", "3(%2)")"\n\t" \ + "1:"type##_sb("%1", "3(%2)")"\n\t" \ "srl\t$1, %1, 0x8\n\t" \ - "2:"user_sb("$1", "2(%2)")"\n\t" \ + "2:"type##_sb("$1", "2(%2)")"\n\t" \ "srl\t$1, $1, 0x8\n\t" \ - "3:"user_sb("$1", "1(%2)")"\n\t" \ + "3:"type##_sb("$1", "1(%2)")"\n\t" \ "srl\t$1, $1, 0x8\n\t" \ - "4:"user_sb("$1", "0(%2)")"\n\t" \ + "4:"type##_sb("$1", "0(%2)")"\n\t" \ ".set\tpop\n\t" \ "li\t%0, 0\n" \ "10:\n\t" \
@@ -456,10 +456,10 @@ extern void show_registers(struct pt_reg#else /* __BIG_ENDIAN */ -#define LoadHW (addr, value, res) \ +#define _LoadHW (addr, value, res, type) \ __asm__ __volatile__ (".set\tnoat\n" \ - "1:\t"user_lb("%0", "1(%2)")"\n" \ - "2:\t"user_lbu("$1", "0(%2)")"\n\t" \ + "1:\t"type##_lb("%0", "1(%2)")"\n" \ + "2:\t"type##_lbu("$1", "0(%2)")"\n\t"\ "sll\t%0, 0x8\n\t" \ "or\t%0, $1\n\t" \ "li\t%1, 0\n" \
@@ -477,10 +477,10 @@ extern void show_registers(struct pt_reg : "r" (addr), "i" (-EFAULT));#ifndef CONFIG_CPU_MIPSR6 -#define LoadW (addr, value, res) \ +#define _LoadW (addr, value, res, type) \ __asm__ __volatile__ ( \ - "1:\t"user_lwl("%0", "3(%2)")"\n" \ - "2:\t"user_lwr("%0", "(%2)")"\n\t" \ + "1:\t"type##_lwl("%0", "3(%2)")"\n" \ + "2:\t"type##_lwr("%0", "(%2)")"\n\t"\ "li\t%1, 0\n" \ "3:\n\t" \ ".insn\n\t" \
@@ -496,18 +496,18 @@ extern void show_registers(struct pt_reg : "r" (addr), "i" (-EFAULT));#else /* MIPSR6 has no lwl instruction */ -#define LoadW (addr, value, res) \ +#define _LoadW (addr, value, res, type) \ __asm__ __volatile__ ( \ ".set\tpush\n" \ ".set\tnoat\n\t" \ - "1:"user_lb("%0", "3(%2)")"\n\t" \ - "2:"user_lbu("$1", "2(%2)")"\n\t" \ + "1:"type##_lb("%0", "3(%2)")"\n\t" \ + "2:"type##_lbu("$1", "2(%2)")"\n\t" \ "sll\t%0, 0x8\n\t" \ "or\t%0, $1\n\t" \ - "3:"user_lbu("$1", "1(%2)")"\n\t" \ + "3:"type##_lbu("$1", "1(%2)")"\n\t" \ "sll\t%0, 0x8\n\t" \ "or\t%0, $1\n\t" \ - "4:"user_lbu("$1", "0(%2)")"\n\t" \ + "4:"type##_lbu("$1", "0(%2)")"\n\t" \ "sll\t%0, 0x8\n\t" \ "or\t%0, $1\n\t" \ "li\t%1, 0\n" \
@@ -529,11 +529,11 @@ extern void show_registers(struct pt_reg#endif /* CONFIG_CPU_MIPSR6 */ -#define LoadHWU (addr, value, res) \ +#define _LoadHWU (addr, value, res, type) \ __asm__ __volatile__ ( \ ".set\tnoat\n" \ - "1:\t"user_lbu("%0", "1(%2)")"\n" \ - "2:\t"user_lbu("$1", "0(%2)")"\n\t" \ + "1:\t"type##_lbu("%0", "1(%2)")"\n" \ + "2:\t"type##_lbu("$1", "0(%2)")"\n\t"\ "sll\t%0, 0x8\n\t" \ "or\t%0, $1\n\t" \ "li\t%1, 0\n" \
@@ -552,10 +552,10 @@ extern void show_registers(struct pt_reg : "r" (addr), "i" (-EFAULT));#ifndef CONFIG_CPU_MIPSR6 -#define LoadWU (addr, value, res) \ +#define _LoadWU (addr, value, res, type) \ __asm__ __volatile__ ( \ - "1:\t"user_lwl("%0", "3(%2)")"\n" \ - "2:\t"user_lwr("%0", "(%2)")"\n\t" \ + "1:\t"type##_lwl("%0", "3(%2)")"\n" \ + "2:\t"type##_lwr("%0", "(%2)")"\n\t"\ "dsll\t%0, %0, 32\n\t" \ "dsrl\t%0, %0, 32\n\t" \ "li\t%1, 0\n" \
@@ -572,7 +572,7 @@ extern void show_registers(struct pt_reg : "=&r" (value), "=r" (res) \ : "r" (addr), "i" (-EFAULT)); -#define LoadDW (addr, value, res) \ +#define _LoadDW (addr, value, res) \ __asm__ __volatile__ ( \ "1:\tldl\t%0, 7(%2)\n" \ "2:\tldr\t%0, (%2)\n\t" \
@@ -591,18 +591,18 @@ extern void show_registers(struct pt_reg : "r" (addr), "i" (-EFAULT));#else /* MIPSR6 has not lwl and ldl instructions */ -#define LoadWU (addr, value, res) \ +#define _LoadWU (addr, value, res, type) \ __asm__ __volatile__ ( \ ".set\tpush\n\t" \ ".set\tnoat\n\t" \ - "1:"user_lbu("%0", "3(%2)")"\n\t" \ - "2:"user_lbu("$1", "2(%2)")"\n\t" \ + "1:"type##_lbu("%0", "3(%2)")"\n\t" \ + "2:"type##_lbu("$1", "2(%2)")"\n\t" \ "sll\t%0, 0x8\n\t" \ "or\t%0, $1\n\t" \ - "3:"user_lbu("$1", "1(%2)")"\n\t" \ + "3:"type##_lbu("$1", "1(%2)")"\n\t" \ "sll\t%0, 0x8\n\t" \ "or\t%0, $1\n\t" \ - "4:"user_lbu("$1", "0(%2)")"\n\t" \ + "4:"type##_lbu("$1", "0(%2)")"\n\t" \ "sll\t%0, 0x8\n\t" \ "or\t%0, $1\n\t" \ "li\t%1, 0\n" \
@@ -622,7 +622,7 @@ extern void show_registers(struct pt_reg : "=&r" (value), "=r" (res) \ : "r" (addr), "i" (-EFAULT)); -#define LoadDW (addr, value, res) \ +#define _LoadDW (addr, value, res) \ __asm__ __volatile__ ( \ ".set\tpush\n\t" \ ".set\tnoat\n\t" \
@@ -670,12 +670,12 @@ extern void show_registers(struct pt_reg : "r" (addr), "i" (-EFAULT));#endif /* CONFIG_CPU_MIPSR6 */ -#define StoreHW (addr, value, res) \ +#define _StoreHW (addr, value, res, type) \ __asm__ __volatile__ ( \ ".set\tnoat\n" \ - "1:\t"user_sb("%1", "0(%2)")"\n" \ + "1:\t"type##_sb("%1", "0(%2)")"\n" \ "srl\t$1,%1, 0x8\n" \ - "2:\t"user_sb("$1", "1(%2)")"\n" \ + "2:\t"type##_sb("$1", "1(%2)")"\n" \ ".set\tat\n\t" \ "li\t%0, 0\n" \ "3:\n\t" \
@@ -691,10 +691,10 @@ extern void show_registers(struct pt_reg : "=r" (res) \ : "r" (value), "r" (addr), "i" (-EFAULT));#ifndef CONFIG_CPU_MIPSR6 -#define StoreW (addr, value, res) \ +#define _StoreW (addr, value, res, type) \ __asm__ __volatile__ ( \ - "1:\t"user_swl("%1", "3(%2)")"\n" \ - "2:\t"user_swr("%1", "(%2)")"\n\t" \ + "1:\t"type##_swl("%1", "3(%2)")"\n" \ + "2:\t"type##_swr("%1", "(%2)")"\n\t"\ "li\t%0, 0\n" \ "3:\n\t" \ ".insn\n\t" \
@@ -709,7 +709,7 @@ extern void show_registers(struct pt_reg : "=r" (res) \ : "r" (value), "r" (addr), "i" (-EFAULT)); -#define StoreDW (addr, value, res) \ +#define _StoreDW (addr, value, res) \ __asm__ __volatile__ ( \ "1:\tsdl\t%1, 7(%2)\n" \ "2:\tsdr\t%1, (%2)\n\t" \
@@ -728,17 +728,17 @@ extern void show_registers(struct pt_reg : "r" (value), "r" (addr), "i" (-EFAULT));#else /* MIPSR6 has no swl and sdl instructions */ -#define StoreW (addr, value, res) \ +#define _StoreW (addr, value, res, type) \ __asm__ __volatile__ ( \ ".set\tpush\n\t" \ ".set\tnoat\n\t" \ - "1:"user_sb("%1", "0(%2)")"\n\t" \ + "1:"type##_sb("%1", "0(%2)")"\n\t" \ "srl\t$1, %1, 0x8\n\t" \ - "2:"user_sb("$1", "1(%2)")"\n\t" \ + "2:"type##_sb("$1", "1(%2)")"\n\t" \ "srl\t$1, $1, 0x8\n\t" \ - "3:"user_sb("$1", "2(%2)")"\n\t" \ + "3:"type##_sb("$1", "2(%2)")"\n\t" \ "srl\t$1, $1, 0x8\n\t" \ - "4:"user_sb("$1", "3(%2)")"\n\t" \ + "4:"type##_sb("$1", "3(%2)")"\n\t" \ ".set\tpop\n\t" \ "li\t%0, 0\n" \ "10:\n\t" \
@@ -757,7 +757,7 @@ extern void show_registers(struct pt_reg : "r" (value), "r" (addr), "i" (-EFAULT) \ : "memory"); -#define StoreDW (addr, value, res) \ +#define _StoreDW (addr, value, res) \ __asm__ __volatile__ ( \ ".set\tpush\n\t" \ ".set\tnoat\n\t" \
@@ -801,6 +801,22 @@ extern void show_registers(struct pt_reg#endif /* CONFIG_CPU_MIPSR6 */ #endif +#define LoadHWU (addr, value, res) _LoadHWU(addr, value, res, kernel) +#define LoadHWUE (addr, value, res) _LoadHWU(addr, value, res, user) +#define LoadWU (addr, value, res) _LoadWU(addr, value, res, kernel) +#define LoadWUE (addr, value, res) _LoadWU(addr, value, res, user) +#define LoadHW (addr, value, res) _LoadHW(addr, value, res, kernel) +#define LoadHWE (addr, value, res) _LoadHW(addr, value, res, user) +#define LoadW (addr, value, res) _LoadW(addr, value, res, kernel) +#define LoadWE (addr, value, res) _LoadW(addr, value, res, user) +#define LoadDW (addr, value, res) _LoadDW(addr, value, res) + +#define StoreHW (addr, value, res) _StoreHW(addr, value, res, kernel) +#define StoreHWE (addr, value, res) _StoreHW(addr, value, res, user) +#define StoreW (addr, value, res) _StoreW(addr, value, res, kernel) +#define StoreWE (addr, value, res) _StoreW(addr, value, res, user) +#define StoreDW (addr, value, res) _StoreDW(addr, value, res) +static void emulate_load_store_insn (struct pt_regs *regs,void __user *addr,unsigned int __user *pc) {
@@ -872,7 +888,7 @@ static void emulate_load_store_insn(struset_fs (seg); goto sigbus; } -LoadHW (addr, value, res); +LoadHWE (addr, value, res);if (res) {set_fs (seg); goto fault;
@@ -885,7 +901,7 @@ static void emulate_load_store_insn(struset_fs (seg); goto sigbus; } -LoadW (addr, value, res); +LoadWE (addr, value, res);if (res) {set_fs (seg); goto fault;
@@ -898,7 +914,7 @@ static void emulate_load_store_insn(struset_fs (seg); goto sigbus; } -LoadHWU (addr, value, res); +LoadHWUE (addr, value, res);if (res) {set_fs (seg); goto fault;
@@ -913,7 +929,7 @@ static void emulate_load_store_insn(stru }compute_return_epc (regs); value = regs->regs[insn.spec3_format.rt]; -StoreHW (addr, value, res); +StoreHWE (addr, value, res);if (res) {set_fs (seg); goto fault;
@@ -926,7 +942,7 @@ static void emulate_load_store_insn(stru }compute_return_epc (regs); value = regs->regs[insn.spec3_format.rt]; -StoreW (addr, value, res); +StoreWE (addr, value, res);if (res) {set_fs (seg); goto fault;
Patches currently in stable-queue which might be from [email protected] are
queue-4.0/mips-unaligned-fix-regular-load-store-instruction-emulation-for-eva.patch queue-4.0/mips-unaligned-prevent-eva-instructions-on-kernel-unaligned-accesses.patch queue-4.0/mips-malta-detect-and-fix-bad-memsize-values.patch queue-4.0/mips-unaligned-surround-load-store-macros-in-do-while-statements.patch queue-4.0/mips-asm-asm-eva-introduce-kernel-load-store-variants.patch