summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/include/asm/page_32.h
diff options
context:
space:
mode:
authorChristophe Leroy <christophe.leroy@c-s.fr>2019-08-16 07:52:20 +0000
committerMichael Ellerman <mpe@ellerman.id.au>2019-08-20 21:22:15 +1000
commit7ab0b7cb8951d4095d73e203759b74d41916e455 (patch)
tree4f63c162df91aa9231a46dcf1f4abc83b3cba0a5 /arch/powerpc/include/asm/page_32.h
parentf204338f8e29777302042cba578b0da44f69695f (diff)
downloadlinux-7ab0b7cb8951d4095d73e203759b74d41916e455.tar.bz2
powerpc/32: Add warning on misaligned copy_page() or clear_page()
copy_page() and clear_page() expect page aligned destination, and use dcbz instruction to clear entire cache lines based on the assumption that the destination is cache aligned. As shown during analysis of a bug in BTRFS filesystem, a misaligned copy_page() can create bugs that are difficult to locate (see Link). Add an explicit WARNING when copy_page() or clear_page() are called with misaligned destination. Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://bugzilla.kernel.org/show_bug.cgi?id=204371 Link: https://lore.kernel.org/r/c6cea38f90480268d439ca44a645647e260fff09.1565941808.git.christophe.leroy@c-s.fr
Diffstat (limited to 'arch/powerpc/include/asm/page_32.h')
-rw-r--r--arch/powerpc/include/asm/page_32.h4
1 files changed, 4 insertions, 0 deletions
diff --git a/arch/powerpc/include/asm/page_32.h b/arch/powerpc/include/asm/page_32.h
index 683dfbc67ca8..d64dfe3ac712 100644
--- a/arch/powerpc/include/asm/page_32.h
+++ b/arch/powerpc/include/asm/page_32.h
@@ -40,6 +40,8 @@ typedef unsigned long long pte_basic_t;
typedef unsigned long pte_basic_t;
#endif
+#include <asm/bug.h>
+
/*
* Clear page using the dcbz instruction, which doesn't cause any
* memory traffic (except to write out any cache lines which get
@@ -49,6 +51,8 @@ static inline void clear_page(void *addr)
{
unsigned int i;
+ WARN_ON((unsigned long)addr & (L1_CACHE_BYTES - 1));
+
for (i = 0; i < PAGE_SIZE / L1_CACHE_BYTES; i++, addr += L1_CACHE_BYTES)
dcbz(addr);
}