summaryrefslogtreecommitdiffstats
path: root/arch/arm/mm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mm')
-rw-r--r--arch/arm/mm/fault-common.c42
-rw-r--r--arch/arm/mm/ioremap.c16
-rw-r--r--arch/arm/mm/proc-arm2,3.S8
-rw-r--r--arch/arm/mm/proc-arm6,7.S4
-rw-r--r--arch/arm/mm/proc-sa110.S16
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
/*