diff options
Diffstat (limited to 'arch/arm/mm')
-rw-r--r-- | arch/arm/mm/fault-common.c | 42 | ||||
-rw-r--r-- | arch/arm/mm/ioremap.c | 16 | ||||
-rw-r--r-- | arch/arm/mm/proc-arm2,3.S | 8 | ||||
-rw-r--r-- | arch/arm/mm/proc-arm6,7.S | 4 | ||||
-rw-r--r-- | arch/arm/mm/proc-sa110.S | 16 |
5 files changed, 45 insertions, 41 deletions
diff --git a/arch/arm/mm/fault-common.c b/arch/arm/mm/fault-common.c index 810dea699..1251525da 100644 --- a/arch/arm/mm/fault-common.c +++ b/arch/arm/mm/fault-common.c @@ -26,25 +26,14 @@ void __bad_pmd_kernel(pmd_t *pmd) set_pmd(pmd, mk_kernel_pmd(BAD_PAGETABLE)); } -static void -kernel_page_fault(unsigned long addr, int mode, struct pt_regs *regs, - struct task_struct *tsk, struct mm_struct *mm) +/* + * This is useful to dump out the page tables associated with + * 'addr' in mm 'mm'. + */ +void show_pte(struct mm_struct *mm, unsigned long addr) { - char *reason; - /* - * Oops. The kernel tried to access some bad page. We'll have to - * terminate things with extreme prejudice. - */ pgd_t *pgd; - if (addr < PAGE_SIZE) - reason = "NULL pointer dereference"; - else - reason = "paging request"; - - printk(KERN_ALERT "Unable to handle kernel %s at virtual address %08lx\n", - reason, addr); - printk(KERN_ALERT "memmap = %08lX, pgd = %p\n", tsk->tss.memmap, mm->pgd); pgd = pgd_offset(mm, addr); printk(KERN_ALERT "*pgd = %08lx", pgd_val(*pgd)); @@ -77,6 +66,27 @@ kernel_page_fault(unsigned long addr, int mode, struct pt_regs *regs, } while(0); printk("\n"); +} + +/* + * Oops. The kernel tried to access some bad page. We'll have to + * terminate things with extreme prejudice. + */ +static void +kernel_page_fault(unsigned long addr, int mode, struct pt_regs *regs, + struct task_struct *tsk, struct mm_struct *mm) +{ + char *reason; + + if (addr < PAGE_SIZE) + reason = "NULL pointer dereference"; + else + reason = "paging request"; + + printk(KERN_ALERT "Unable to handle kernel %s at virtual address %08lx\n", + reason, addr); + printk(KERN_ALERT "memmap = %08lX, pgd = %p\n", tsk->tss.memmap, mm->pgd); + show_pte(mm, addr); die("Oops", regs, mode); do_exit(SIGKILL); diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c index 70d7c77b9..48e34214e 100644 --- a/arch/arm/mm/ioremap.c +++ b/arch/arm/mm/ioremap.c @@ -115,19 +115,19 @@ void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flag { void * addr; struct vm_struct * area; - unsigned long offset; + unsigned long offset, last_addr; + + /* Don't allow wraparound or zero size */ + last_addr = phys_addr + size - 1; + if (!size || last_addr < phys_addr) + return NULL; /* * Mappings have to be page-aligned */ offset = phys_addr & ~PAGE_MASK; - size = PAGE_ALIGN(size + offset); - - /* - * Don't allow mappings that wrap.. - */ - if (!size || size > phys_addr + size) - return NULL; + phys_addr &= PAGE_MASK; + size = PAGE_ALIGN(last_addr) - phys_addr; /* * Ok, go for it.. diff --git a/arch/arm/mm/proc-arm2,3.S b/arch/arm/mm/proc-arm2,3.S index 263d79708..7e4871fe2 100644 --- a/arch/arm/mm/proc-arm2,3.S +++ b/arch/arm/mm/proc-arm2,3.S @@ -202,15 +202,11 @@ _arm2_3_check_bugs: LC0: .word SYMBOL_NAME(page_nr) /* * Function: arm2_switch_to (struct task_struct *prev, struct task_struct *next) - * * Params : prev Old task structure * : next New task structure for process to run - * * Returns : prev - * * Purpose : Perform a task switch, saving the old processes state, and restoring * the new. - * * Notes : We don't fiddle with the FP registers here - we postpone this until * the new task actually uses FP. This way, we don't swap FP for tasks * that do not require it. @@ -316,15 +312,11 @@ _arm2_proc_init: _arm2_proc_fin: movs pc, lr /* * Function: arm3_switch_to (struct task_struct *prev, struct task_struct *next) - * * Params : prev Old task structure * : next New task structure for process to run - * * Returns : prev - * * Purpose : Perform a task switch, saving the old processes state, and restoring * the new. - * * Notes : We don't fiddle with the FP registers here - we postpone this until * the new task actually uses FP. This way, we don't swap FP for tasks * that do not require it. diff --git a/arch/arm/mm/proc-arm6,7.S b/arch/arm/mm/proc-arm6,7.S index b817ae2b4..d1f31e35d 100644 --- a/arch/arm/mm/proc-arm6,7.S +++ b/arch/arm/mm/proc-arm6,7.S @@ -74,14 +74,14 @@ _arm6_7_switch_to: str sp, [r0, #TSS_SAVE] @ Save sp_SVC ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC ldr r2, [r1, #TSK_ADDR_LIMIT] + ldr r3, [r1, #TSS_MEMMAP] @ Page table pointer teq r2, #0 moveq r2, #DOM_KERNELDOMAIN movne r2, #DOM_USERDOMAIN mcr p15, 0, r2, c3, c0 @ Set domain reg - ldr r2, [r1, #TSS_MEMMAP] @ Page table pointer mov r1, #0 mcr p15, 0, r1, c7, c0, 0 @ flush cache - mcr p15, 0, r2, c2, c0, 0 @ update page table ptr + mcr p15, 0, r3, c2, c0, 0 @ update page table ptr mcr p15, 0, r1, c5, c0, 0 @ flush TLBs ldmfd sp!, {ip} msr spsr, ip @ Save tasks CPSR into SPSR for this return diff --git a/arch/arm/mm/proc-sa110.S b/arch/arm/mm/proc-sa110.S index ff55c8ffa..be9fad45e 100644 --- a/arch/arm/mm/proc-sa110.S +++ b/arch/arm/mm/proc-sa110.S @@ -29,11 +29,11 @@ _sa110_flush_cache_all: @ preserves r0 mov r2, #1 _sa110_flush_cache_all_r2: ldr r3, =Lclean_switch + ldr ip, =FLUSH_BASE ldr r1, [r3] ands r1, r1, #1 eor r1, r1, #1 str r1, [r3] - ldr ip, =FLUSH_BASE addne ip, ip, #32768 add r1, ip, #16384 @ only necessary for 16k 1: ldr r3, [ip], #32 @@ -226,12 +226,12 @@ _sa110_switch_to: ldr r2, [r0, #TSS_MEMMAP] @ Get old page tables str sp, [r0, #TSS_SAVE] @ Save sp_SVC ldr sp, [r1, #TSS_SAVE] @ Get saved sp_SVC - ldr r4, [r1, #TSK_ADDR_LIMIT] - teq r4, #0 - moveq r4, #DOM_KERNELDOMAIN - movne r4, #DOM_USERDOMAIN - mcr p15, 0, r4, c3, c0 @ Set segment + ldr r5, [r1, #TSK_ADDR_LIMIT] ldr r4, [r1, #TSS_MEMMAP] @ Page table pointer + teq r5, #0 + moveq r5, #DOM_KERNELDOMAIN + movne r5, #DOM_USERDOMAIN + mcr p15, 0, r5, c3, c0 @ Set segment /* * Flushing the cache is nightmarishly slow, so we take any excuse * to get out of it. If the old page table is the same as the new, @@ -288,7 +288,8 @@ _sa110_data_abort: */ .align 5 _sa110_set_pmd: str r1, [r0] - mcr p15, 0, r0, c7, c10, 1 @ clean D entry (drain is done by TLB fns) + mcr p15, 0, r0, c7, c10, 1 @ clean D entry + mcr p15, 0, r0, c7, c10, 4 @ drain WB (TLB bypasses WB) mov pc, lr /* @@ -318,6 +319,7 @@ _sa110_set_pte: str r1, [r0], #-1024 @ linux version str r2, [r0] @ hardware version mov r0, r0 mcr p15, 0, r0, c7, c10, 1 @ clean D entry (drain is done by TLB fns) + mcr p15, 0, r0, c7, c10, 4 @ drain WB (TLB bypasses WB) mov pc, lr /* |