diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-08 19:01:28 +0100 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-08 19:01:28 +0100 |
commit | 0cf975e16927fd70f34cee20d3856246c13bb4c8 (patch) | |
tree | bb955d50f28e5d98c198701798c8341d9763299a /arch/cris/arch-v10/mm | |
parent | Merge branch 'for-linus' of git://git.kernel.dk/linux-2.6-block (diff) | |
parent | CRIS v32: Remove hwregs/timer_defs.h, it is now architecture specific. (diff) | |
download | linux-0cf975e16927fd70f34cee20d3856246c13bb4c8.tar.xz linux-0cf975e16927fd70f34cee20d3856246c13bb4c8.zip |
Merge branch 'cris' of git://www.jni.nu/cris
* 'cris' of git://www.jni.nu/cris: (158 commits)
CRIS v32: Remove hwregs/timer_defs.h, it is now architecture specific.
CRIS v32: Change drivers/i2c.c locking.
CRIS v32: Rewrite ARTPEC-3 gpio driver to avoid volatiles and general cleanup.
CRIS: Add new timerfd syscall entries.
MAINTAINERS: Add my information for the CRIS port.
CRIS v32: Correct spelling of bandwidth in function name.
CRIS v32: Clean up nandflash.c for ARTPEC-3 and ETRAX FS.
CRIS v10: Cleanup of drivers/gpio.c
CRIS v10: drivers/net/cris/eth_v10.c rename LED defines to CRIS_LED to avoid name clash.
CRIS: Make io_pwm_set_period members unsigned in etraxgpio.h
CRIS: Move ETRAX_AXISFLASHMAP to common Kconfig file.
CRIS: Drop regs parameter from call to profile_tick in kernel/time.c
CRIS v32: Fix minor formatting issue in mach-a3/io.c
CRIS v32: Initialize GIO even if we're rambooting in kernel/head.S
CRIS v32: Remove kernel/arbiter.c, it now exists in machine dependent directory.
CRIS v32: Minor changes to avoid errors in asm-cris/arch-v32/hwregs/reg_rdwr.h
CRIS v32: arch-v32/hwregs/intr_vect_defs.h moved to machine dependent directory.
CRIS v32: Correct offset for TASK_pid in asm-cris/arch-v32/offset.h
CRIS v32: Move register map header to machine dependent directory.
CRIS v32: Let compiler know that memory is clobbered after a break op.
...
Diffstat (limited to 'arch/cris/arch-v10/mm')
-rw-r--r-- | arch/cris/arch-v10/mm/fault.c | 13 | ||||
-rw-r--r-- | arch/cris/arch-v10/mm/tlb.c | 58 |
2 files changed, 36 insertions, 35 deletions
diff --git a/arch/cris/arch-v10/mm/fault.c b/arch/cris/arch-v10/mm/fault.c index fe2615022b97..65504fd80928 100644 --- a/arch/cris/arch-v10/mm/fault.c +++ b/arch/cris/arch-v10/mm/fault.c @@ -4,10 +4,10 @@ * Low level bus fault handler * * - * Copyright (C) 2000, 2001 Axis Communications AB + * Copyright (C) 2000-2007 Axis Communications AB + * + * Authors: Bjorn Wesen * - * Authors: Bjorn Wesen - * */ #include <linux/mm.h> @@ -60,7 +60,7 @@ handle_mmu_bus_fault(struct pt_regs *regs) #ifdef DEBUG page_id = IO_EXTRACT(R_MMU_CAUSE, page_id, cause); acc = IO_EXTRACT(R_MMU_CAUSE, acc_excp, cause); - inv = IO_EXTRACT(R_MMU_CAUSE, inv_excp, cause); + inv = IO_EXTRACT(R_MMU_CAUSE, inv_excp, cause); index = IO_EXTRACT(R_TLB_SELECT, index, select); #endif miss = IO_EXTRACT(R_MMU_CAUSE, miss_excp, cause); @@ -84,12 +84,13 @@ handle_mmu_bus_fault(struct pt_regs *regs) local_irq_disable(); pmd = (pmd_t *)(pgd + pgd_index(address)); if (pmd_none(*pmd)) - return; + goto exit; pte = *pte_offset_kernel(pmd, address); if (!pte_present(pte)) - return; + goto exit; *R_TLB_SELECT = select; *R_TLB_HI = cause; *R_TLB_LO = pte_val(pte); +exit: local_irq_restore(flags); } diff --git a/arch/cris/arch-v10/mm/tlb.c b/arch/cris/arch-v10/mm/tlb.c index 7d9fec88dee5..6baf5bd209e7 100644 --- a/arch/cris/arch-v10/mm/tlb.c +++ b/arch/cris/arch-v10/mm/tlb.c @@ -4,8 +4,8 @@ * Low level TLB handling * * - * Copyright (C) 2000-2002 Axis Communications AB - * + * Copyright (C) 2000-2007 Axis Communications AB + * * Authors: Bjorn Wesen (bjornw@axis.com) * */ @@ -39,7 +39,7 @@ flush_tlb_all(void) unsigned long flags; /* the vpn of i & 0xf is so we dont write similar TLB entries - * in the same 4-way entry group. details.. + * in the same 4-way entry group. details... */ local_irq_save(flags); @@ -47,7 +47,7 @@ flush_tlb_all(void) *R_TLB_SELECT = ( IO_FIELD(R_TLB_SELECT, index, i) ); *R_TLB_HI = ( IO_FIELD(R_TLB_HI, page_id, INVALID_PAGEID ) | IO_FIELD(R_TLB_HI, vpn, i & 0xf ) ); - + *R_TLB_LO = ( IO_STATE(R_TLB_LO, global,no ) | IO_STATE(R_TLB_LO, valid, no ) | IO_STATE(R_TLB_LO, kernel,no ) | @@ -71,10 +71,10 @@ flush_tlb_mm(struct mm_struct *mm) if(page_id == NO_CONTEXT) return; - + /* mark the TLB entries that match the page_id as invalid. * here we could also check the _PAGE_GLOBAL bit and NOT flush - * global pages. is it worth the extra I/O ? + * global pages. is it worth the extra I/O ? */ local_irq_save(flags); @@ -83,7 +83,7 @@ flush_tlb_mm(struct mm_struct *mm) if (IO_EXTRACT(R_TLB_HI, page_id, *R_TLB_HI) == page_id) { *R_TLB_HI = ( IO_FIELD(R_TLB_HI, page_id, INVALID_PAGEID ) | IO_FIELD(R_TLB_HI, vpn, i & 0xf ) ); - + *R_TLB_LO = ( IO_STATE(R_TLB_LO, global,no ) | IO_STATE(R_TLB_LO, valid, no ) | IO_STATE(R_TLB_LO, kernel,no ) | @@ -96,9 +96,7 @@ flush_tlb_mm(struct mm_struct *mm) /* invalidate a single page */ -void -flush_tlb_page(struct vm_area_struct *vma, - unsigned long addr) +void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr) { struct mm_struct *mm = vma->vm_mm; int page_id = mm->context.page_id; @@ -113,7 +111,7 @@ flush_tlb_page(struct vm_area_struct *vma, addr &= PAGE_MASK; /* perhaps not necessary */ /* invalidate those TLB entries that match both the mm context - * and the virtual address requested + * and the virtual address requested */ local_irq_save(flags); @@ -125,7 +123,7 @@ flush_tlb_page(struct vm_area_struct *vma, (tlb_hi & PAGE_MASK) == addr) { *R_TLB_HI = IO_FIELD(R_TLB_HI, page_id, INVALID_PAGEID ) | addr; /* same addr as before works. */ - + *R_TLB_LO = ( IO_STATE(R_TLB_LO, global,no ) | IO_STATE(R_TLB_LO, valid, no ) | IO_STATE(R_TLB_LO, kernel,no ) | @@ -144,7 +142,7 @@ dump_tlb_all(void) { int i; unsigned long flags; - + printk("TLB dump. LO is: pfn | reserved | global | valid | kernel | we |\n"); local_save_flags(flags); @@ -172,27 +170,29 @@ init_new_context(struct task_struct *tsk, struct mm_struct *mm) /* called in schedule() just before actually doing the switch_to */ -void -switch_mm(struct mm_struct *prev, struct mm_struct *next, - struct task_struct *tsk) +void switch_mm(struct mm_struct *prev, struct mm_struct *next, + struct task_struct *tsk) { - /* make sure we have a context */ + if (prev != next) { + /* make sure we have a context */ + get_mmu_context(next); - get_mmu_context(next); + /* remember the pgd for the fault handlers + * this is similar to the pgd register in some other CPU's. + * we need our own copy of it because current and active_mm + * might be invalid at points where we still need to derefer + * the pgd. + */ - /* remember the pgd for the fault handlers - * this is similar to the pgd register in some other CPU's. - * we need our own copy of it because current and active_mm - * might be invalid at points where we still need to derefer - * the pgd. - */ + per_cpu(current_pgd, smp_processor_id()) = next->pgd; - per_cpu(current_pgd, smp_processor_id()) = next->pgd; + /* switch context in the MMU */ - /* switch context in the MMU */ - - D(printk("switching mmu_context to %d (%p)\n", next->context, next)); + D(printk(KERN_DEBUG "switching mmu_context to %d (%p)\n", + next->context, next)); - *R_MMU_CONTEXT = IO_FIELD(R_MMU_CONTEXT, page_id, next->context.page_id); + *R_MMU_CONTEXT = IO_FIELD(R_MMU_CONTEXT, + page_id, next->context.page_id); + } } |