Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 163345
b: refs/heads/master
c: 2277ab4
h: refs/heads/master
i:
  163343: c73622d
v: v3
  • Loading branch information
Paul Mundt committed Jul 22, 2009
1 parent eee9c91 commit adbd0b0
Show file tree
Hide file tree
Showing 12 changed files with 82 additions and 143 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: c0b96cf639aa1bfa8983f734d4225091aa813e00
refs/heads/master: 2277ab4a1df50e05bc732fe9488d4e902bb8399a
6 changes: 6 additions & 0 deletions trunk/arch/sh/include/asm/page.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,12 @@ extern unsigned long shm_align_mask;
extern unsigned long max_low_pfn, min_low_pfn;
extern unsigned long memory_start, memory_end;

static inline unsigned long
pages_do_alias(unsigned long addr1, unsigned long addr2)
{
return (addr1 ^ addr2) & shm_align_mask;
}

extern void clear_page(void *to);
extern void copy_page(void *to, void *from);

Expand Down
7 changes: 0 additions & 7 deletions trunk/arch/sh/include/asm/pgtable.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,13 +133,6 @@ typedef pte_t *pte_addr_t;
*/
#define pgtable_cache_init() do { } while (0)

#if !defined(CONFIG_CACHE_OFF) && (defined(CONFIG_CPU_SH4) || \
defined(CONFIG_SH7705_CACHE_32KB))
struct mm_struct;
#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep);
#endif

struct vm_area_struct;
extern void update_mmu_cache(struct vm_area_struct * vma,
unsigned long address, pte_t pte);
Expand Down
5 changes: 1 addition & 4 deletions trunk/arch/sh/include/cpu-sh3/cpu/cacheflush.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,7 @@
* SH4. Unlike the SH4 this is a unified cache so we need to do some work
* in mmap when 'exec'ing a new binary
*/
/* 32KB cache, 4kb PAGE sizes need to check bit 12 */
#define CACHE_ALIAS 0x00001000

#define PG_mapped PG_arch_1
#define PG_dcache_dirty PG_arch_1

void flush_cache_all(void);
void flush_cache_mm(struct mm_struct *mm);
Expand Down
2 changes: 1 addition & 1 deletion trunk/arch/sh/include/cpu-sh4/cpu/cacheflush.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,6 @@ void flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
/* Initialization of P3 area for copy_user_page */
void p3_cache_init(void);

#define PG_mapped PG_arch_1
#define PG_dcache_dirty PG_arch_1

#endif /* __ASM_CPU_SH4_CACHEFLUSH_H */
10 changes: 9 additions & 1 deletion trunk/arch/sh/mm/cache-sh4.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <linux/mm.h>
#include <linux/io.h>
#include <linux/mutex.h>
#include <linux/fs.h>
#include <asm/mmu_context.h>
#include <asm/cacheflush.h>

Expand Down Expand Up @@ -246,7 +247,14 @@ static inline void flush_cache_4096(unsigned long start,
*/
void flush_dcache_page(struct page *page)
{
if (test_bit(PG_mapped, &page->flags)) {
struct address_space *mapping = page_mapping(page);

#ifndef CONFIG_SMP
if (mapping && !mapping_mapped(mapping))
set_bit(PG_dcache_dirty, &page->flags);
else
#endif
{
unsigned long phys = PHYSADDR(page_address(page));
unsigned long addr = CACHE_OC_ADDRESS_ARRAY;
int i, n;
Expand Down
7 changes: 6 additions & 1 deletion trunk/arch/sh/mm/cache-sh7705.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <linux/init.h>
#include <linux/mman.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/threads.h>
#include <asm/addrspace.h>
#include <asm/page.h>
Expand Down Expand Up @@ -128,7 +129,11 @@ static void __uses_jump_to_uncached __flush_dcache_page(unsigned long phys)
*/
void flush_dcache_page(struct page *page)
{
if (test_bit(PG_mapped, &page->flags))
struct address_space *mapping = page_mapping(page);

if (mapping && !mapping_mapped(mapping))
set_bit(PG_dcache_dirty, &page->flags);
else
__flush_dcache_page(PHYSADDR(page_address(page)));
}

Expand Down
74 changes: 29 additions & 45 deletions trunk/arch/sh/mm/pg-sh4.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@
#include <asm/mmu_context.h>
#include <asm/cacheflush.h>

#define CACHE_ALIAS (current_cpu_data.dcache.alias_mask)

#define kmap_get_fixmap_pte(vaddr) \
pte_offset_kernel(pmd_offset(pud_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr)), (vaddr))

Expand Down Expand Up @@ -68,24 +66,24 @@ static inline void kunmap_coherent(struct page *page)
*/
void clear_user_page(void *to, unsigned long address, struct page *page)
{
__set_bit(PG_mapped, &page->flags);

clear_page(to);
if ((((address & PAGE_MASK) ^ (unsigned long)to) & CACHE_ALIAS))

if (pages_do_alias((unsigned long)to, address & PAGE_MASK))
__flush_wback_region(to, PAGE_SIZE);
}

void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
unsigned long vaddr, void *dst, const void *src,
unsigned long len)
{
void *vto;

__set_bit(PG_mapped, &page->flags);

vto = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK);
memcpy(vto, src, len);
kunmap_coherent(vto);
if (page_mapped(page) && !test_bit(PG_dcache_dirty, &page->flags)) {
void *vto = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK);
memcpy(vto, src, len);
kunmap_coherent(vto);
} else {
memcpy(dst, src, len);
set_bit(PG_dcache_dirty, &page->flags);
}

if (vma->vm_flags & VM_EXEC)
flush_cache_page(vma, vaddr, page_to_pfn(page));
Expand All @@ -95,52 +93,38 @@ void copy_from_user_page(struct vm_area_struct *vma, struct page *page,
unsigned long vaddr, void *dst, const void *src,
unsigned long len)
{
void *vfrom;

__set_bit(PG_mapped, &page->flags);

vfrom = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK);
memcpy(dst, vfrom, len);
kunmap_coherent(vfrom);
if (page_mapped(page) && !test_bit(PG_dcache_dirty, &page->flags)) {
void *vfrom = kmap_coherent(page, vaddr) + (vaddr & ~PAGE_MASK);
memcpy(dst, vfrom, len);
kunmap_coherent(vfrom);
} else {
memcpy(dst, src, len);
set_bit(PG_dcache_dirty, &page->flags);
}
}

void copy_user_highpage(struct page *to, struct page *from,
unsigned long vaddr, struct vm_area_struct *vma)
{
void *vfrom, *vto;

__set_bit(PG_mapped, &to->flags);

vto = kmap_atomic(to, KM_USER1);
vfrom = kmap_coherent(from, vaddr);
copy_page(vto, vfrom);
kunmap_coherent(vfrom);

if (((vaddr ^ (unsigned long)vto) & CACHE_ALIAS))
if (page_mapped(from) && !test_bit(PG_dcache_dirty, &from->flags)) {
vfrom = kmap_coherent(from, vaddr);
copy_page(vto, vfrom);
kunmap_coherent(vfrom);
} else {
vfrom = kmap_atomic(from, KM_USER0);
copy_page(vto, vfrom);
kunmap_atomic(vfrom, KM_USER0);
}

if (pages_do_alias((unsigned long)vto, vaddr & PAGE_MASK))
__flush_wback_region(vto, PAGE_SIZE);

kunmap_atomic(vto, KM_USER1);
/* Make sure this page is cleared on other CPU's too before using it */
smp_wmb();
}
EXPORT_SYMBOL(copy_user_highpage);

/*
* For SH-4, we have our own implementation for ptep_get_and_clear
*/
pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
pte_t pte = *ptep;

pte_clear(mm, addr, ptep);
if (!pte_not_present(pte)) {
unsigned long pfn = pte_pfn(pte);
if (pfn_valid(pfn)) {
struct page *page = pfn_to_page(pfn);
struct address_space *mapping = page_mapping(page);
if (!mapping || !mapping_writably_mapped(mapping))
__clear_bit(PG_mapped, &page->flags);
}
}
return pte;
}
52 changes: 8 additions & 44 deletions trunk/arch/sh/mm/pg-sh7705.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
#include <asm/mmu_context.h>
#include <asm/cacheflush.h>

static inline void __flush_purge_virtual_region(void *p1, void *virt, int size)
static void __flush_purge_virtual_region(void *p1, void *virt, int size)
{
unsigned long v;
unsigned long begin, end;
Expand Down Expand Up @@ -75,19 +75,13 @@ static inline void __flush_purge_virtual_region(void *p1, void *virt, int size)
*/
void clear_user_page(void *to, unsigned long address, struct page *pg)
{
struct page *page = virt_to_page(to);

__set_bit(PG_mapped, &page->flags);
if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) {
clear_page(to);
__flush_wback_region(to, PAGE_SIZE);
} else {
if (pages_do_alias(address, (unsigned long)to))
__flush_purge_virtual_region(to,
(void *)(address & 0xfffff000),
PAGE_SIZE);
clear_page(to);
__flush_wback_region(to, PAGE_SIZE);
}

clear_page(to);
__flush_wback_region(to, PAGE_SIZE);
}

/*
Expand All @@ -98,41 +92,11 @@ void clear_user_page(void *to, unsigned long address, struct page *pg)
*/
void copy_user_page(void *to, void *from, unsigned long address, struct page *pg)
{
struct page *page = virt_to_page(to);


__set_bit(PG_mapped, &page->flags);
if (((address ^ (unsigned long)to) & CACHE_ALIAS) == 0) {
copy_page(to, from);
__flush_wback_region(to, PAGE_SIZE);
} else {
if (pages_do_alias(address, (unsigned long)to))
__flush_purge_virtual_region(to,
(void *)(address & 0xfffff000),
PAGE_SIZE);
copy_page(to, from);
__flush_wback_region(to, PAGE_SIZE);
}
}

/*
* For SH7705, we have our own implementation for ptep_get_and_clear
* Copied from pg-sh4.c
*/
pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
{
pte_t pte = *ptep;

pte_clear(mm, addr, ptep);
if (!pte_not_present(pte)) {
unsigned long pfn = pte_pfn(pte);
if (pfn_valid(pfn)) {
struct page *page = pfn_to_page(pfn);
struct address_space *mapping = page_mapping(page);
if (!mapping || !mapping_writably_mapped(mapping))
__clear_bit(PG_mapped, &page->flags);
}
}

return pte;
copy_page(to, from);
__flush_wback_region(to, PAGE_SIZE);
}

17 changes: 0 additions & 17 deletions trunk/arch/sh/mm/tlb-pteaex.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,6 @@ void update_mmu_cache(struct vm_area_struct * vma,
if (vma && current->active_mm != vma->vm_mm)
return;

#ifndef CONFIG_CACHE_OFF
{
unsigned long pfn = pte_pfn(pte);

if (pfn_valid(pfn)) {
struct page *page = pfn_to_page(pfn);

if (!test_bit(PG_mapped, &page->flags)) {
unsigned long phys = pte_val(pte) & PTE_PHYS_MASK;
__flush_wback_region((void *)P1SEGADDR(phys),
PAGE_SIZE);
__set_bit(PG_mapped, &page->flags);
}
}
}
#endif

local_irq_save(flags);

/* Set PTEH register */
Expand Down
20 changes: 10 additions & 10 deletions trunk/arch/sh/mm/tlb-sh3.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,25 +33,25 @@ void update_mmu_cache(struct vm_area_struct * vma,
unsigned long flags;
unsigned long pteval;
unsigned long vpn;
unsigned long pfn = pte_pfn(pte);
struct page *page;

/* Ptrace may call this routine. */
if (vma && current->active_mm != vma->vm_mm)
return;

page = pfn_to_page(pfn);
if (pfn_valid(pfn) && page_mapping(page)) {
#if defined(CONFIG_SH7705_CACHE_32KB)
{
struct page *page = pte_page(pte);
unsigned long pfn = pte_pfn(pte);
int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags);
if (dirty) {
unsigned long addr = (unsigned long)page_address(page);

if (pfn_valid(pfn) && !test_bit(PG_mapped, &page->flags)) {
unsigned long phys = pte_val(pte) & PTE_PHYS_MASK;

__flush_wback_region((void *)P1SEGADDR(phys),
PAGE_SIZE);
__set_bit(PG_mapped, &page->flags);
if (pages_do_alias(addr, address & PAGE_MASK))
__flush_wback_region((void *)addr, PAGE_SIZE);
}
}
#endif
}

local_irq_save(flags);

Expand Down
23 changes: 11 additions & 12 deletions trunk/arch/sh/mm/tlb-sh4.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,27 +21,26 @@ void update_mmu_cache(struct vm_area_struct * vma,
unsigned long flags;
unsigned long pteval;
unsigned long vpn;
unsigned long pfn = pte_pfn(pte);
struct page *page;

/* Ptrace may call this routine. */
if (vma && current->active_mm != vma->vm_mm)
return;

#ifndef CONFIG_CACHE_OFF
{
unsigned long pfn = pte_pfn(pte);
page = pfn_to_page(pfn);
if (pfn_valid(pfn) && page_mapping(page)) {
#ifndef CONFIG_SMP
int dirty = test_and_clear_bit(PG_dcache_dirty, &page->flags);
if (dirty) {

if (pfn_valid(pfn)) {
struct page *page = pfn_to_page(pfn);
unsigned long addr = (unsigned long)page_address(page);

if (!test_bit(PG_mapped, &page->flags)) {
unsigned long phys = pte_val(pte) & PTE_PHYS_MASK;
__flush_wback_region((void *)P1SEGADDR(phys),
PAGE_SIZE);
__set_bit(PG_mapped, &page->flags);
}
if (pages_do_alias(addr, address & PAGE_MASK))
__flush_wback_region((void *)addr, PAGE_SIZE);
}
}
#endif
}

local_irq_save(flags);

Expand Down

0 comments on commit adbd0b0

Please sign in to comment.