Skip to content

Commit

Permalink
sh: Assume new page cache pages have dirty dcache lines.
Browse files Browse the repository at this point in the history
This follows the ARM change c017780
("ARM: 6379/1: Assume new page cache pages have dirty D-cache") for the
same rationale:

    There are places in Linux where writes to newly allocated page
    cache pages happen without a subsequent call to flush_dcache_page()
    (several PIO drivers including USB HCD). This patch changes the
    meaning of PG_arch_1 to be PG_dcache_clean and always flush the
    D-cache for a newly mapped page in update_mmu_cache().

This addresses issues seen with executing binaries from MMC, in
addition to some of the other HCDs that don't explicitly do cache
management for their pipe-in buffers.

Requested-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
  • Loading branch information
Paul Mundt committed Dec 1, 2010
1 parent 22a5b56 commit 55661fc
Show file tree
Hide file tree
Showing 5 changed files with 12 additions and 12 deletions.
2 changes: 1 addition & 1 deletion arch/sh/include/asm/cacheflush.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ void kmap_coherent_init(void);
void *kmap_coherent(struct page *page, unsigned long addr);
void kunmap_coherent(void *kvaddr);

#define PG_dcache_dirty PG_arch_1
#define PG_dcache_clean PG_arch_1

void cpu_cache_init(void);

Expand Down
4 changes: 2 additions & 2 deletions arch/sh/mm/cache-sh4.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ static void sh4_flush_dcache_page(void *arg)
struct address_space *mapping = page_mapping(page);

if (mapping && !mapping_mapped(mapping))
set_bit(PG_dcache_dirty, &page->flags);
clear_bit(PG_dcache_clean, &page->flags);
else
#endif
flush_cache_one(CACHE_OC_ADDRESS_ARRAY |
Expand Down Expand Up @@ -239,7 +239,7 @@ static void sh4_flush_cache_page(void *args)
* another ASID than the current one.
*/
map_coherent = (current_cpu_data.dcache.n_aliases &&
!test_bit(PG_dcache_dirty, &page->flags) &&
test_bit(PG_dcache_clean, &page->flags) &&
page_mapped(page));
if (map_coherent)
vaddr = kmap_coherent(page, address);
Expand Down
2 changes: 1 addition & 1 deletion arch/sh/mm/cache-sh7705.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ static void sh7705_flush_dcache_page(void *arg)
struct address_space *mapping = page_mapping(page);

if (mapping && !mapping_mapped(mapping))
set_bit(PG_dcache_dirty, &page->flags);
clear_bit(PG_dcache_clean, &page->flags);
else
__flush_dcache_page(__pa(page_address(page)));
}
Expand Down
14 changes: 7 additions & 7 deletions arch/sh/mm/cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,14 @@ void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
unsigned long len)
{
if (boot_cpu_data.dcache.n_aliases && page_mapped(page) &&
!test_bit(PG_dcache_dirty, &page->flags)) {
test_bit(PG_dcache_clean, &page->flags)) {
void *vto = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK);
memcpy(vto, src, len);
kunmap_coherent(vto);
} else {
memcpy(dst, src, len);
if (boot_cpu_data.dcache.n_aliases)
set_bit(PG_dcache_dirty, &page->flags);
clear_bit(PG_dcache_clean, &page->flags);
}

if (vma->vm_flags & VM_EXEC)
Expand All @@ -79,14 +79,14 @@ void copy_from_user_page(struct vm_area_struct *vma, struct page *page,
unsigned long len)
{
if (boot_cpu_data.dcache.n_aliases && page_mapped(page) &&
!test_bit(PG_dcache_dirty, &page->flags)) {
test_bit(PG_dcache_clean, &page->flags)) {
void *vfrom = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK);
memcpy(dst, vfrom, len);
kunmap_coherent(vfrom);
} else {
memcpy(dst, src, len);
if (boot_cpu_data.dcache.n_aliases)
set_bit(PG_dcache_dirty, &page->flags);
clear_bit(PG_dcache_clean, &page->flags);
}
}

Expand All @@ -98,7 +98,7 @@ void copy_user_highpage(struct page *to, struct page *from,
vto = kmap_atomic(to, KM_USER1);

if (boot_cpu_data.dcache.n_aliases && page_mapped(from) &&
!test_bit(PG_dcache_dirty, &from->flags)) {
test_bit(PG_dcache_clean, &from->flags)) {
vfrom = kmap_coherent(from, vaddr);
copy_page(vto, vfrom);
kunmap_coherent(vfrom);
Expand Down Expand Up @@ -141,7 +141,7 @@ void __update_cache(struct vm_area_struct *vma,

page = pfn_to_page(pfn);
if (pfn_valid(pfn)) {
int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags);
int dirty = !test_and_set_bit(PG_dcache_clean, &page->flags);
if (dirty)
__flush_purge_region(page_address(page), PAGE_SIZE);
}
Expand All @@ -153,7 +153,7 @@ void __flush_anon_page(struct page *page, unsigned long vmaddr)

if (pages_do_alias(addr, vmaddr)) {
if (boot_cpu_data.dcache.n_aliases && page_mapped(page) &&
!test_bit(PG_dcache_dirty, &page->flags)) {
test_bit(PG_dcache_clean, &page->flags)) {
void *kaddr;

kaddr = kmap_coherent(page, vmaddr);
Expand Down
2 changes: 1 addition & 1 deletion arch/sh/mm/kmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ void *kmap_coherent(struct page *page, unsigned long addr)
enum fixed_addresses idx;
unsigned long vaddr;

BUG_ON(test_bit(PG_dcache_dirty, &page->flags));
BUG_ON(!test_bit(PG_dcache_clean, &page->flags));

pagefault_disable();

Expand Down

0 comments on commit 55661fc

Please sign in to comment.