Commit 3e87974d authored by Vineet Gupta's avatar Vineet Gupta

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: default avatarVineet Gupta <vgupta@synopsys.com>
parent a950549c
...@@ -99,8 +99,10 @@ static inline int cache_is_vipt_aliasing(void) ...@@ -99,8 +99,10 @@ static inline int cache_is_vipt_aliasing(void)
* checks if two addresses (after page aligning) index into same cache set * checks if two addresses (after page aligning) index into same cache set
*/ */
#define addr_not_cache_congruent(addr1, addr2) \ #define addr_not_cache_congruent(addr1, addr2) \
({ \
cache_is_vipt_aliasing() ? \ 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) \ #define copy_to_user_page(vma, page, vaddr, dst, src, len) \
do { \ do { \
......
...@@ -444,7 +444,8 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long vaddr_unaligned, ...@@ -444,7 +444,8 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long vaddr_unaligned,
* so userspace sees the right data. * so userspace sees the right data.
* (Avoids the flush for Non-exec + congruent mapping case) * (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)); struct page *page = pfn_to_page(pte_pfn(*ptep));
int dirty = test_and_clear_bit(PG_arch_1, &page->flags); int dirty = test_and_clear_bit(PG_arch_1, &page->flags);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment