X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fmips%2Fmm%2Fc-tx39.c;h=f32ebde30ccf1cee1dbe06b29a623b00ea07a744;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=9654d74c5019dd5075e054cd3f825acedda3af9e;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/arch/mips/mm/c-tx39.c b/arch/mips/mm/c-tx39.c index 9654d74c5..f32ebde30 100644 --- a/arch/mips/mm/c-tx39.c +++ b/arch/mips/mm/c-tx39.c @@ -44,8 +44,6 @@ __asm__ __volatile__( \ /* TX39H-style cache flush routines. */ static void tx39h_flush_icache_all(void) { - unsigned long start = KSEG0; - unsigned long end = (start + icache_size); unsigned long flags, config; /* disable icache (set ICE#) */ @@ -53,33 +51,18 @@ static void tx39h_flush_icache_all(void) config = read_c0_conf(); write_c0_conf(config & ~TX39_CONF_ICE); TX39_STOP_STREAMING(); - - /* invalidate icache */ - while (start < end) { - cache16_unroll32(start, Index_Invalidate_I); - start += 0x200; - } - + blast_icache16(); write_c0_conf(config); local_irq_restore(flags); } static void tx39h_dma_cache_wback_inv(unsigned long addr, unsigned long size) { - unsigned long end, a; - unsigned long dc_lsize = current_cpu_data.dcache.linesz; - /* Catch bad driver code */ BUG_ON(size == 0); iob(); - a = addr & ~(dc_lsize - 1); - end = (addr + size - 1) & ~(dc_lsize - 1); - while (1) { - invalidate_dcache_line(a); /* Hit_Invalidate_D */ - if (a == end) break; - a += dc_lsize; - } + blast_inv_dcache_range(addr, addr + size); } @@ -167,23 +150,24 @@ static void tx39_flush_cache_mm(struct mm_struct *mm) static void tx39_flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) { - struct mm_struct *mm = vma->vm_mm; + int exec; - if (!cpu_has_dc_aliases) + if (!(cpu_context(smp_processor_id(), vma->vm_mm))) return; - if (cpu_context(smp_processor_id(), mm) != 0) { + exec = vma->vm_flags & VM_EXEC; + if (cpu_has_dc_aliases || exec) tx39_blast_dcache(); + if (exec) tx39_blast_icache(); - } } -static void tx39_flush_cache_page(struct vm_area_struct *vma, - unsigned long page) +static void tx39_flush_cache_page(struct vm_area_struct *vma, unsigned long page, unsigned long pfn) { int exec = vma->vm_flags & VM_EXEC; struct mm_struct *mm = vma->vm_mm; pgd_t *pgdp; + pud_t *pudp; pmd_t *pmdp; pte_t *ptep; @@ -196,7 +180,8 @@ static void tx39_flush_cache_page(struct vm_area_struct *vma, page &= PAGE_MASK; pgdp = pgd_offset(mm, page); - pmdp = pmd_offset(pgdp, page); + pudp = pud_offset(pgdp, page); + pmdp = pmd_offset(pudp, page); ptep = pte_offset(pmdp, page); /* @@ -225,13 +210,17 @@ static void tx39_flush_cache_page(struct vm_area_struct *vma, * Do indexed flush, too much work to get the (possible) TLB refills * to work correctly. */ - page = (KSEG0 + (page & (dcache_size - 1))); if (cpu_has_dc_aliases || exec) tx39_blast_dcache_page_indexed(page); if (exec) tx39_blast_icache_page_indexed(page); } +static void local_tx39_flush_data_cache_page(void * addr) +{ + tx39_blast_dcache_page(addr); +} + static void tx39_flush_data_cache_page(unsigned long addr) { tx39_blast_dcache_page(addr); @@ -239,77 +228,29 @@ static void tx39_flush_data_cache_page(unsigned long addr) static void tx39_flush_icache_range(unsigned long start, unsigned long end) { - unsigned long dc_lsize = current_cpu_data.dcache.linesz; - unsigned long addr, aend; - if (end - start > dcache_size) tx39_blast_dcache(); - else { - addr = start & ~(dc_lsize - 1); - aend = (end - 1) & ~(dc_lsize - 1); - - while (1) { - /* Hit_Writeback_Inv_D */ - protected_writeback_dcache_line(addr); - if (addr == aend) - break; - addr += dc_lsize; - } - } + else + protected_blast_dcache_range(start, end); if (end - start > icache_size) tx39_blast_icache(); else { unsigned long flags, config; - addr = start & ~(dc_lsize - 1); - aend = (end - 1) & ~(dc_lsize - 1); /* disable icache (set ICE#) */ local_irq_save(flags); config = read_c0_conf(); write_c0_conf(config & ~TX39_CONF_ICE); TX39_STOP_STREAMING(); - while (1) { - /* Hit_Invalidate_I */ - protected_flush_icache_line(addr); - if (addr == aend) - break; - addr += dc_lsize; - } + protected_blast_icache_range(start, end); write_c0_conf(config); local_irq_restore(flags); } } -/* - * Ok, this seriously sucks. We use them to flush a user page but don't - * know the virtual address, so we have to blast away the whole icache - * which is significantly more expensive than the real thing. Otoh we at - * least know the kernel address of the page so we can flush it - * selectivly. - */ -static void tx39_flush_icache_page(struct vm_area_struct *vma, struct page *page) -{ - unsigned long addr; - /* - * If there's no context yet, or the page isn't executable, no icache - * flush is needed. - */ - if (!(vma->vm_flags & VM_EXEC)) - return; - - addr = (unsigned long) page_address(page); - tx39_blast_dcache_page(addr); - - /* - * We're not sure of the virtual address(es) involved here, so - * we have to flush the entire I-cache. - */ - tx39_blast_icache(); -} - static void tx39_dma_cache_wback_inv(unsigned long addr, unsigned long size) { - unsigned long end, a; + unsigned long end; if (((size | addr) & (PAGE_SIZE - 1)) == 0) { end = addr + size; @@ -320,20 +261,13 @@ static void tx39_dma_cache_wback_inv(unsigned long addr, unsigned long size) } else if (size > dcache_size) { tx39_blast_dcache(); } else { - unsigned long dc_lsize = current_cpu_data.dcache.linesz; - a = addr & ~(dc_lsize - 1); - end = (addr + size - 1) & ~(dc_lsize - 1); - while (1) { - flush_dcache_line(a); /* Hit_Writeback_Inv_D */ - if (a == end) break; - a += dc_lsize; - } + blast_dcache_range(addr, addr + size); } } static void tx39_dma_cache_inv(unsigned long addr, unsigned long size) { - unsigned long end, a; + unsigned long end; if (((size | addr) & (PAGE_SIZE - 1)) == 0) { end = addr + size; @@ -344,14 +278,7 @@ static void tx39_dma_cache_inv(unsigned long addr, unsigned long size) } else if (size > dcache_size) { tx39_blast_dcache(); } else { - unsigned long dc_lsize = current_cpu_data.dcache.linesz; - a = addr & ~(dc_lsize - 1); - end = (addr + size - 1) & ~(dc_lsize - 1); - while (1) { - invalidate_dcache_line(a); /* Hit_Invalidate_D */ - if (a == end) break; - a += dc_lsize; - } + blast_inv_dcache_range(addr, addr + size); } } @@ -408,7 +335,7 @@ static __init void tx39_probe_cache(void) } } -void __init ld_mmu_tx39(void) +void __init tx39_cache_init(void) { extern void build_clear_page(void); extern void build_copy_page(void); @@ -428,10 +355,10 @@ void __init ld_mmu_tx39(void) flush_cache_mm = (void *) tx39h_flush_icache_all; flush_cache_range = (void *) tx39h_flush_icache_all; flush_cache_page = (void *) tx39h_flush_icache_all; - flush_icache_page = (void *) tx39h_flush_icache_all; flush_icache_range = (void *) tx39h_flush_icache_all; flush_cache_sigtramp = (void *) tx39h_flush_icache_all; + local_flush_data_cache_page = (void *) tx39h_flush_icache_all; flush_data_cache_page = (void *) tx39h_flush_icache_all; _dma_cache_wback_inv = tx39h_dma_cache_wback_inv; @@ -453,10 +380,10 @@ void __init ld_mmu_tx39(void) flush_cache_mm = tx39_flush_cache_mm; flush_cache_range = tx39_flush_cache_range; flush_cache_page = tx39_flush_cache_page; - flush_icache_page = tx39_flush_icache_page; flush_icache_range = tx39_flush_icache_range; flush_cache_sigtramp = tx39_flush_cache_sigtramp; + local_flush_data_cache_page = local_tx39_flush_data_cache_page; flush_data_cache_page = tx39_flush_data_cache_page; _dma_cache_wback_inv = tx39_dma_cache_wback_inv; @@ -484,11 +411,12 @@ void __init ld_mmu_tx39(void) current_cpu_data.icache.waybit = 0; current_cpu_data.dcache.waybit = 0; - printk("Primary instruction cache %ldkb, linesize %d bytes\n", + printk("Primary instruction cache %ldkB, linesize %d bytes\n", icache_size >> 10, current_cpu_data.icache.linesz); - printk("Primary data cache %ldkb, linesize %d bytes\n", + printk("Primary data cache %ldkB, linesize %d bytes\n", dcache_size >> 10, current_cpu_data.dcache.linesz); build_clear_page(); build_copy_page(); + tx39h_flush_icache_all(); }