summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVineet Gupta <vgupta@synopsys.com>2013-05-22 15:08:10 +0200
committerVineet Gupta <vgupta@synopsys.com>2013-05-23 10:54:52 +0200
commit3e87974dec5ec25a8a4852d9292db6be659164e6 (patch)
treece7d2e84901ade9ff8f56a9319eb1a690200c2f5
parentARC: copy_(to|from)_user() to honor usermode-access permissions (diff)
downloadlinux-3e87974dec5ec25a8a4852d9292db6be659164e6.tar.xz
linux-3e87974dec5ec25a8a4852d9292db6be659164e6.zip
ARC: Brown paper bag bug in macro for checking cache color
The VM_EXEC check in update_mmu_cache() was getting optimized away because of a stupid error in definition of macro addr_not_cache_congruent() The intention was to have the equivalent of following: if (a || (1 ? b : 0)) but we ended up with following: if (a || 1 ? b : 0) And because precedence of '||' is more that that of '?', gcc was optimizing away evaluation of <a> Nasty Repercussions: 1. For non-aliasing configs it would mean some extraneous dcache flushes for non-code pages if U/K mappings were not congruent. 2. For aliasing config, some needed dcache flush for code pages might be missed if U/K mappings were congruent. Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
-rw-r--r--arch/arc/include/asm/cacheflush.h4
-rw-r--r--arch/arc/mm/tlb.c3
2 files changed, 5 insertions, 2 deletions
diff --git a/arch/arc/include/asm/cacheflush.h b/arch/arc/include/asm/cacheflush.h
index 9f841af41092..7d819749478c 100644
--- a/arch/arc/include/asm/cacheflush.h
+++ b/arch/arc/include/asm/cacheflush.h
@@ -99,8 +99,10 @@ static inline int cache_is_vipt_aliasing(void)
* checks if two addresses (after page aligning) index into same cache set
*/
#define addr_not_cache_congruent(addr1, addr2) \
+({ \
cache_is_vipt_aliasing() ? \
- (CACHE_COLOR(addr1) != CACHE_COLOR(addr2)) : 0 \
+ (CACHE_COLOR(addr1) != CACHE_COLOR(addr2)) : 0; \
+})
#define copy_to_user_page(vma, page, vaddr, dst, src, len) \
do { \
diff --git a/arch/arc/mm/tlb.c b/arch/arc/mm/tlb.c
index 066145b5f348..fe1c5a073afe 100644
--- a/arch/arc/mm/tlb.c
+++ b/arch/arc/mm/tlb.c
@@ -444,7 +444,8 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long vaddr_unaligned,
* so userspace sees the right data.
* (Avoids the flush for Non-exec + congruent mapping case)
*/
- if (vma->vm_flags & VM_EXEC || addr_not_cache_congruent(paddr, vaddr)) {
+ if ((vma->vm_flags & VM_EXEC) ||
+ addr_not_cache_congruent(paddr, vaddr)) {
struct page *page = pfn_to_page(pte_pfn(*ptep));
int dirty = test_and_clear_bit(PG_arch_1, &page->flags);