summaryrefslogtreecommitdiff
path: root/arch/arm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm')
-rw-r--r--arch/arm/kernel/entry-armv.S12
-rw-r--r--arch/arm/kernel/time.c13
-rw-r--r--arch/arm/kernel/traps.c1
-rw-r--r--arch/arm/mm/flush.c39
4 files changed, 61 insertions, 4 deletions
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 2db42b18f53f..8517c3c3eb33 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -436,7 +436,7 @@ __und_usr:
usr_entry
tst r3, #PSR_T_BIT @ Thumb mode?
- bne fpundefinstr @ ignore FP
+ bne __und_usr_unknown @ ignore FP
sub r4, r2, #4
@
@@ -448,7 +448,7 @@ __und_usr:
@
1: ldrt r0, [r4]
adr r9, ret_from_exception
- adr lr, fpundefinstr
+ adr lr, __und_usr_unknown
@
@ fallthrough to call_fpe
@
@@ -476,7 +476,9 @@ __und_usr:
* Emulators may wish to make use of the following registers:
* r0 = instruction opcode.
* r2 = PC+4
+ * r9 = normal "successful" return address
* r10 = this threads thread_info structure.
+ * lr = unrecognised instruction return address
*/
call_fpe:
tst r0, #0x08000000 @ only CDP/CPRT/LDC/STC have bit 27
@@ -545,10 +547,12 @@ do_fpe:
.data
ENTRY(fp_enter)
- .word fpundefinstr
+ .word no_fp
.text
-fpundefinstr:
+no_fp: mov pc, lr
+
+__und_usr_unknown:
mov r0, sp
adr lr, ret_from_exception
b do_undefinstr
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index 6ff5e3ff6cb5..3c8cdcfe8d4a 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -29,6 +29,8 @@
#include <linux/timer.h>
#include <linux/irq.h>
+#include <linux/mc146818rtc.h>
+
#include <asm/leds.h>
#include <asm/thread_info.h>
#include <asm/mach/time.h>
@@ -85,6 +87,17 @@ unsigned long long __attribute__((weak)) sched_clock(void)
return (unsigned long long)jiffies * (1000000000 / HZ);
}
+/*
+ * An implementation of printk_clock() independent from
+ * sched_clock(). This avoids non-bootable kernels when
+ * printk_clock is enabled.
+ */
+unsigned long long printk_clock(void)
+{
+ return (unsigned long long)(jiffies - INITIAL_JIFFIES) *
+ (1000000000 / HZ);
+}
+
static unsigned long next_rtc_update;
/*
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 042a12982e98..908915675edc 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -27,6 +27,7 @@
#include <asm/uaccess.h>
#include <asm/unistd.h>
#include <asm/traps.h>
+#include <asm/io.h>
#include "ptrace.h"
#include "signal.h"
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c
index 628348c9f6c5..9df507d36e0b 100644
--- a/arch/arm/mm/flush.c
+++ b/arch/arm/mm/flush.c
@@ -202,3 +202,42 @@ void flush_dcache_page(struct page *page)
}
}
EXPORT_SYMBOL(flush_dcache_page);
+
+/*
+ * Flush an anonymous page so that users of get_user_pages()
+ * can safely access the data. The expected sequence is:
+ *
+ * get_user_pages()
+ * -> flush_anon_page
+ * memcpy() to/from page
+ * if written to page, flush_dcache_page()
+ */
+void __flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long vmaddr)
+{
+ unsigned long pfn;
+
+ /* VIPT non-aliasing caches need do nothing */
+ if (cache_is_vipt_nonaliasing())
+ return;
+
+ /*
+ * Write back and invalidate userspace mapping.
+ */
+ pfn = page_to_pfn(page);
+ if (cache_is_vivt()) {
+ flush_cache_page(vma, vmaddr, pfn);
+ } else {
+ /*
+ * For aliasing VIPT, we can flush an alias of the
+ * userspace address only.
+ */
+ flush_pfn_alias(pfn, vmaddr);
+ }
+
+ /*
+ * Invalidate kernel mapping. No data should be contained
+ * in this mapping of the page. FIXME: this is overkill
+ * since we actually ask for a write-back and invalidate.
+ */
+ __cpuc_flush_dcache_page(page_address(page));
+}