summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorCatalin Marinas <catalin.marinas@arm.com>2009-06-23 18:16:03 +0100
committerCatalin Marinas <catalin.marinas@arm.com>2009-09-08 13:19:43 +0100
commit053d9d0f117f5b3112eb17f2224b36447abbdc5c (patch)
treeb54b0a8f33e2b506bf14a8b35c6d56829b722876 /arch
parent7860173c5e251e9be14d33873ad769d314180df7 (diff)
Cortex-M3: Add base support for Cortex-M3
This patch adds the base support for the Cortex-M3 processor (ARMv7-M architecture). It consists of the corresponding arch/arm/mm/ files and various #ifdef's around the kernel. Exception handling is implemented by a subsequent patch. Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/boot/compressed/head.S18
-rw-r--r--arch/arm/include/asm/assembler.h13
-rw-r--r--arch/arm/include/asm/cacheflush.h24
-rw-r--r--arch/arm/include/asm/cputype.h2
-rw-r--r--arch/arm/include/asm/glue.h8
-rw-r--r--arch/arm/include/asm/irqflags.h41
-rw-r--r--arch/arm/include/asm/proc-fns.h8
-rw-r--r--arch/arm/include/asm/processor.h10
-rw-r--r--arch/arm/include/asm/ptrace.h38
-rw-r--r--arch/arm/include/asm/system.h3
-rw-r--r--arch/arm/kernel/armksyms.c4
-rw-r--r--arch/arm/kernel/asm-offsets.c4
-rw-r--r--arch/arm/kernel/head-common.S4
-rw-r--r--arch/arm/kernel/head-nommu.S9
-rw-r--r--arch/arm/kernel/setup.c15
-rw-r--r--arch/arm/kernel/signal.c2
-rw-r--r--arch/arm/kernel/traps.c2
-rw-r--r--arch/arm/lib/backtrace.S2
-rw-r--r--arch/arm/mm/abort-ev7m.S9
-rw-r--r--arch/arm/mm/nommu.c2
-rw-r--r--arch/arm/mm/proc-v7m.S184
21 files changed, 390 insertions, 12 deletions
diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S
index c7b8109fb412..6e20b2ed0c1f 100644
--- a/arch/arm/boot/compressed/head.S
+++ b/arch/arm/boot/compressed/head.S
@@ -130,6 +130,7 @@ start:
1: mov r7, r1 @ save architecture ID
mov r8, r2 @ save atags pointer
+#ifndef CONFIG_CPU_V7M
#ifndef __ARM_ARCH_2__
/*
* Booting from Angel - need to enter SVC mode and disable
@@ -149,6 +150,7 @@ not_angel:
#else
teqp pc, #0x0c000003 @ turn off interrupts
#endif
+#endif
/*
* Note that some cache flushing and other stuff may
@@ -568,16 +570,20 @@ call_kernel: bl cache_clean_flush
* r12 = corrupted
*/
-call_cache_fn: adr r12, proc_types
+call_cache_fn:
+ adr r12, proc_types
#ifdef CONFIG_CPU_CP15
mrc p15, 0, r6, c0, c0 @ get processor ID
+#elif defined(CONFIG_CPU_V7M)
+ ldr r6, =0xe000ed00 @ CPUID register address
+ ldr r6, [r6]
#else
ldr r6, =CONFIG_PROCESSOR_ID
#endif
-1: ldr r1, [r12, #0] @ get value
- ldr r2, [r12, #4] @ get mask
- eor r1, r1, r6 @ (real ^ match)
- tst r1, r2 @ & mask
+1: ldr r2, [r12, #4] @ get mask
+ ldr r1, [r12, #0] @ get value
+ and r2, r6, r2 @ keep the relevant bits
+ teq r1, r2 @ match with the value
itt eq
ARM( addeq pc, r12, r3 ) @ call cache function
THUMB( addeq r12, r3 )
@@ -702,11 +708,13 @@ proc_types:
W(b) __armv4_mmu_cache_off
W(b) __armv6_mmu_cache_flush
+#ifndef CONFIG_CPU_V7M
.word 0x000f0000 @ new CPU Id
.word 0x000f0000
W(b) __armv7_mmu_cache_on
W(b) __armv7_mmu_cache_off
W(b) __armv7_mmu_cache_flush
+#endif
.word 0 @ unrecognised type
.word 0
diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h
index 550cdcfb1f1c..2539d254caa7 100644
--- a/arch/arm/include/asm/assembler.h
+++ b/arch/arm/include/asm/assembler.h
@@ -96,7 +96,11 @@
* assumes FIQs are enabled, and that the processor is in SVC mode.
*/
.macro save_and_disable_irqs, oldcpsr
+#ifdef CONFIG_CPU_V7M
+ mrs \oldcpsr, primask
+#else
mrs \oldcpsr, cpsr
+#endif
disable_irq
.endm
@@ -105,7 +109,11 @@
* guarantee that this will preserve the flags.
*/
.macro restore_irqs, oldcpsr
+#ifdef CONFIG_CPU_V7M
+ msr primask, \oldcpsr
+#else
msr cpsr_c, \oldcpsr
+#endif
.endm
#define USER(x...) \
@@ -115,7 +123,10 @@
.long 9999b,9001f; \
.previous
-#ifdef CONFIG_THUMB2_KERNEL
+#if defined(CONFIG_CPU_V7M)
+ .macro setmode, mode, reg
+ .endm
+#elif defined(CONFIG_THUMB2_KERNEL)
.macro setmode, mode, reg
mov \reg, #\mode
msr cpsr_c, \reg
diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h
index a8076bfdead4..91aec141aa15 100644
--- a/arch/arm/include/asm/cacheflush.h
+++ b/arch/arm/include/asm/cacheflush.h
@@ -115,6 +115,14 @@
//# endif
#endif
+#if defined(CONFIG_CPU_V7M)
+# ifdef _CACHE
+# error "Multi-cache not supported on ARMv7-M"
+# else
+# define _CACHE v7m
+# endif
+#endif
+
#if !defined(_CACHE) && !defined(MULTI_CACHE)
#error Unknown cache maintainence model
#endif
@@ -235,6 +243,22 @@ extern struct cpu_cache_fns cpu_cache;
#else
+#ifdef CONFIG_CPU_V7M
+
+static inline void v7m_flush_kern_all(void) { }
+static inline void v7m_flush_user_all(void) { }
+static inline void v7m_flush_user_range(unsigned long a, unsigned long b, unsigned int c) { }
+
+static inline void v7m_coherent_kern_range(unsigned long a, unsigned long b) { }
+static inline void v7m_coherent_user_range(unsigned long a, unsigned long b) { }
+static inline void v7m_flush_kern_dcache_page(void *a) { }
+
+static inline void v7m_dma_inv_range(const void *a, const void *b) { }
+static inline void v7m_dma_clean_range(const void *a, const void *b) { }
+static inline void v7m_dma_flush_range(const void *a, const void *b) { }
+
+#endif
+
#define __cpuc_flush_kern_all __glue(_CACHE,_flush_kern_cache_all)
#define __cpuc_flush_user_all __glue(_CACHE,_flush_user_cache_all)
#define __cpuc_flush_user_range __glue(_CACHE,_flush_user_cache_range)
diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h
index b3e656c6fb78..c2fe374fcb7f 100644
--- a/arch/arm/include/asm/cputype.h
+++ b/arch/arm/include/asm/cputype.h
@@ -42,6 +42,8 @@
: "cc"); \
__val; \
})
+#elif defined(CONFIG_CPU_V7M)
+#define read_cpuid(reg) (*(unsigned int *)0xe000ed00)
#else
extern unsigned int processor_id;
#define read_cpuid(reg) (processor_id)
diff --git a/arch/arm/include/asm/glue.h b/arch/arm/include/asm/glue.h
index a0e39d5d00c9..0a3bb3d8fab6 100644
--- a/arch/arm/include/asm/glue.h
+++ b/arch/arm/include/asm/glue.h
@@ -115,6 +115,14 @@
# endif
#endif
+#ifdef CONFIG_CPU_ABRT_EV7M
+# ifdef CPU_DABORT_HANDLER
+# define MULTI_DABORT 1
+# else
+# define CPU_DABORT_HANDLER v7m_early_abort
+# endif
+#endif
+
#ifndef CPU_DABORT_HANDLER
#error Unknown data abort handler type
#endif
diff --git a/arch/arm/include/asm/irqflags.h b/arch/arm/include/asm/irqflags.h
index 6d09974e6646..5dbb6de221ce 100644
--- a/arch/arm/include/asm/irqflags.h
+++ b/arch/arm/include/asm/irqflags.h
@@ -10,6 +10,15 @@
*/
#if __LINUX_ARM_ARCH__ >= 6
+#ifdef CONFIG_CPU_V7M
+#define raw_local_irq_save(x) \
+ ({ \
+ __asm__ __volatile__( \
+ "mrs %0, primask @ local_irq_save\n" \
+ "cpsid i" \
+ : "=r" (x) : : "memory", "cc"); \
+ })
+#else
#define raw_local_irq_save(x) \
({ \
__asm__ __volatile__( \
@@ -17,6 +26,7 @@
"cpsid i" \
: "=r" (x) : : "memory", "cc"); \
})
+#endif
#define raw_local_irq_enable() __asm__("cpsie i @ __sti" : : : "memory", "cc")
#define raw_local_irq_disable() __asm__("cpsid i @ __cli" : : : "memory", "cc")
@@ -103,6 +113,35 @@
#endif
+#ifdef CONFIG_CPU_V7M
+
+/*
+ * Save the current interrupt enable state.
+ */
+#define raw_local_save_flags(x) \
+ ({ \
+ __asm__ __volatile__( \
+ "mrs %0, primask @ local_save_flags" \
+ : "=r" (x) : : "memory", "cc"); \
+ })
+
+/*
+ * restore saved IRQ & FIQ state
+ */
+#define raw_local_irq_restore(x) \
+ __asm__ __volatile__( \
+ "msr primask, %0 @ local_irq_restore\n" \
+ : \
+ : "r" (x) \
+ : "memory", "cc")
+
+#define raw_irqs_disabled_flags(flags) \
+({ \
+ (int)((flags) & 1); \
+})
+
+#else
+
/*
* Save the current interrupt enable state.
*/
@@ -128,5 +167,7 @@
(int)((flags) & PSR_I_BIT); \
})
+#endif /* CONFIG_CPU_V7M */
+
#endif
#endif
diff --git a/arch/arm/include/asm/proc-fns.h b/arch/arm/include/asm/proc-fns.h
index db80203b68e0..d9faa2b32dfb 100644
--- a/arch/arm/include/asm/proc-fns.h
+++ b/arch/arm/include/asm/proc-fns.h
@@ -209,6 +209,14 @@
# define CPU_NAME cpu_v7
# endif
# endif
+# ifdef CONFIG_CPU_V7M
+# ifdef CPU_NAME
+# undef MULTI_CPU
+# define MULTI_CPU
+# else
+# define CPU_NAME cpu_v7m
+# endif
+# endif
#endif
#ifndef __ASSEMBLY__
diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h
index 0b3478c3010d..64409f343381 100644
--- a/arch/arm/include/asm/processor.h
+++ b/arch/arm/include/asm/processor.h
@@ -57,7 +57,15 @@ struct thread_struct {
#ifdef CONFIG_MMU
#define nommu_start_thread(regs) do { } while (0)
#else
+#ifndef CONFIG_CPU_V7M
#define nommu_start_thread(regs) regs->ARM_r10 = current->mm->start_data
+#else
+#define nommu_start_thread(regs) do { \
+ regs->ARM_r10 = current->mm->start_data; \
+ regs->ARM_sp -= 32; /* exception return state */ \
+ regs->ARM_EXC_lr = 0xfffffffdL; /* exception lr */ \
+} while (0)
+#endif
#endif
#define start_thread(regs,pc,sp) \
@@ -72,7 +80,7 @@ struct thread_struct {
if (elf_hwcap & HWCAP_THUMB && pc & 1) \
regs->ARM_cpsr |= PSR_T_BIT; \
regs->ARM_cpsr |= PSR_ENDSTATE; \
- regs->ARM_pc = pc & ~1; /* pc */ \
+ regs->ARM_pc = pc /*& ~1*/; /* pc */ \
regs->ARM_sp = sp; /* sp */ \
regs->ARM_r2 = stack[2]; /* r2 (envp) */ \
regs->ARM_r1 = stack[1]; /* r1 (argv) */ \
diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h
index bbecccda76d0..1f7419c9fcc0 100644
--- a/arch/arm/include/asm/ptrace.h
+++ b/arch/arm/include/asm/ptrace.h
@@ -37,16 +37,25 @@
#define FIQ26_MODE 0x00000001
#define IRQ26_MODE 0x00000002
#define SVC26_MODE 0x00000003
+#ifndef CONFIG_CPU_V7M
#define USR_MODE 0x00000010
+#define SVC_MODE 0x00000013
+#else
+#define USR_MODE 0x00000000
+#define SVC_MODE 0x00000000
+#endif
#define FIQ_MODE 0x00000011
#define IRQ_MODE 0x00000012
-#define SVC_MODE 0x00000013
#define ABT_MODE 0x00000017
#define UND_MODE 0x0000001b
#define SYSTEM_MODE 0x0000001f
#define MODE32_BIT 0x00000010
#define MODE_MASK 0x0000001f
+#ifndef CONFIG_CPU_V7M
#define PSR_T_BIT 0x00000020
+#else
+#define PSR_T_BIT 0x01000000
+#endif
#define PSR_F_BIT 0x00000040
#define PSR_I_BIT 0x00000080
#define PSR_A_BIT 0x00000100
@@ -101,6 +110,28 @@ struct pt_regs {
long uregs[18];
};
+#ifdef CONFIG_CPU_V7M
+/* Automatically saved registers */
+#define ARM_cpsr uregs[17]
+#define ARM_pc uregs[16]
+#define ARM_lr uregs[15]
+#define ARM_ip uregs[14]
+#define ARM_r3 uregs[13]
+#define ARM_r2 uregs[12]
+#define ARM_r1 uregs[11]
+#define ARM_r0 uregs[10]
+/* saved by the exception entry code */
+#define ARM_EXC_lr uregs[9]
+#define ARM_sp uregs[8]
+#define ARM_fp uregs[7]
+#define ARM_r10 uregs[6]
+#define ARM_r9 uregs[5]
+#define ARM_r8 uregs[4]
+#define ARM_r7 uregs[3]
+#define ARM_r6 uregs[2]
+#define ARM_r5 uregs[1]
+#define ARM_r4 uregs[0]
+#else
#define ARM_cpsr uregs[16]
#define ARM_pc uregs[15]
#define ARM_lr uregs[14]
@@ -119,6 +150,7 @@ struct pt_regs {
#define ARM_r1 uregs[1]
#define ARM_r0 uregs[0]
#define ARM_ORIG_r0 uregs[17]
+#endif
#ifdef __KERNEL__
@@ -150,6 +182,7 @@ struct pt_regs {
*/
static inline int valid_user_regs(struct pt_regs *regs)
{
+#ifndef CONFIG_CPU_V7M
if (user_mode(regs) && (regs->ARM_cpsr & PSR_I_BIT) == 0) {
regs->ARM_cpsr &= ~(PSR_F_BIT | PSR_A_BIT);
return 1;
@@ -163,6 +196,9 @@ static inline int valid_user_regs(struct pt_regs *regs)
regs->ARM_cpsr |= USR_MODE;
return 0;
+#else
+ return 1;
+#endif
}
#define instruction_pointer(regs) (regs)->ARM_pc
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h
index a6367611cd70..4851e9d0eba5 100644
--- a/arch/arm/include/asm/system.h
+++ b/arch/arm/include/asm/system.h
@@ -15,6 +15,7 @@
#define CPU_ARCH_ARMv5TEJ 7
#define CPU_ARCH_ARMv6 8
#define CPU_ARCH_ARMv7 9
+#define CPU_ARCH_ARMv7M 10
/*
* CR1 bits (CP#15 CR1)
@@ -200,7 +201,9 @@ static inline void set_copro_access(unsigned int val)
* so enable interrupts over the context switch to avoid high
* latency.
*/
+#ifndef CONFIG_CPU_V7M
#define __ARCH_WANT_INTERRUPTS_ON_CTXSW
+#endif
/*
* switch_to(prev, next) should switch from task `prev' to `next'
diff --git a/arch/arm/kernel/armksyms.c b/arch/arm/kernel/armksyms.c
index 23af3c972c9a..76e8b036306c 100644
--- a/arch/arm/kernel/armksyms.c
+++ b/arch/arm/kernel/armksyms.c
@@ -46,8 +46,10 @@ extern void __aeabi_uidiv(void);
extern void __aeabi_uidivmod(void);
extern void __aeabi_ulcmp(void);
+#ifndef CONFIG_CPU_V7M
extern void fpundefinstr(void);
extern void fp_enter(void);
+#endif
/*
* This has a special calling convention; it doesn't
@@ -65,7 +67,9 @@ extern void fp_enter(void);
* floating point math emulator support.
* These symbols will never change their calling convention...
*/
+#ifndef CONFIG_CPU_V7M
EXPORT_SYMBOL_ALIAS(kern_fp_enter,fp_enter);
+#endif
EXPORT_SYMBOL_ALIAS(fp_printk,printk);
EXPORT_SYMBOL_ALIAS(fp_send_sig,send_sig);
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 4a881258bb17..009c1a126c05 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -79,7 +79,11 @@ int main(void)
DEFINE(S_LR, offsetof(struct pt_regs, ARM_lr));
DEFINE(S_PC, offsetof(struct pt_regs, ARM_pc));
DEFINE(S_PSR, offsetof(struct pt_regs, ARM_cpsr));
+#ifdef CONFIG_CPU_V7M
+ DEFINE(S_EXC_LR, offsetof(struct pt_regs, ARM_EXC_lr));
+#else
DEFINE(S_OLD_R0, offsetof(struct pt_regs, ARM_ORIG_r0));
+#endif
DEFINE(S_FRAME_SIZE, sizeof(struct pt_regs));
BLANK();
#ifdef CONFIG_CPU_HAS_ASID
diff --git a/arch/arm/kernel/head-common.S b/arch/arm/kernel/head-common.S
index b409417e6110..1b6a85751b8c 100644
--- a/arch/arm/kernel/head-common.S
+++ b/arch/arm/kernel/head-common.S
@@ -25,7 +25,11 @@ __switch_data:
.long processor_id @ r4
.long __machine_arch_type @ r5
.long __atags_pointer @ r6
+#ifdef CONFIG_CPU_CP15
.long cr_alignment @ r7
+#else
+ .long 0 @ r7
+#endif
.long init_thread_union + THREAD_START_SP @ sp
/*
diff --git a/arch/arm/kernel/head-nommu.S b/arch/arm/kernel/head-nommu.S
index e5dfc2895e24..07a0fa7bb7bd 100644
--- a/arch/arm/kernel/head-nommu.S
+++ b/arch/arm/kernel/head-nommu.S
@@ -36,10 +36,13 @@
ENTRY(stext)
setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode
@ and irqs disabled
-#ifndef CONFIG_CPU_CP15
- ldr r9, =CONFIG_PROCESSOR_ID
-#else
+#if defined(CONFIG_CPU_CP15)
mrc p15, 0, r9, c0, c0 @ get processor id
+#elif defined(CONFIG_CPU_V7M)
+ ldr r9, =0xe000ed00 @ CPUID register address
+ ldr r9, [r9]
+#else
+ ldr r9, =CONFIG_PROCESSOR_ID
#endif
bl __lookup_processor_type @ r5=procinfo r9=cpuid
movs r10, r5 @ invalid processor (r5=0)?
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 4ae74ae59f9c..e38ca7038168 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -198,6 +198,12 @@ static const char *proc_arch[] = {
"?(17)",
};
+#ifdef CONFIG_CPU_V7M
+int cpu_architecture(void)
+{
+ return CPU_ARCH_ARMv7M;
+}
+#else
int cpu_architecture(void)
{
int cpu_arch;
@@ -230,6 +236,7 @@ int cpu_architecture(void)
return cpu_arch;
}
+#endif
EXPORT_SYMBOL(cpu_architecture);
static void __init cacheid_init(void)
@@ -299,9 +306,15 @@ static void __init setup_processor(void)
cpu_cache = *list->cache;
#endif
+#ifdef CONFIG_CPU_V7M
+ printk("CPU: %s [%08x] revision %d (ARMv%sM)\n",
+ cpu_name, processor_id, (int)processor_id & 15,
+ proc_arch[cpu_architecture()]);
+#else
printk("CPU: %s [%08x] revision %d (ARMv%s), cr=%08lx\n",
cpu_name, read_cpuid_id(), read_cpuid_id() & 15,
proc_arch[cpu_architecture()], cr_alignment);
+#endif
sprintf(init_utsname()->machine, "%s%c", list->arch_name, ENDIANNESS);
sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
@@ -339,6 +352,7 @@ void cpu_init(void)
#define PLC "I"
#endif
+#ifndef CONFIG_CPU_V7M
/*
* setup stacks for re-entrant exception handlers
*/
@@ -363,6 +377,7 @@ void cpu_init(void)
"I" (offsetof(struct stack, und[0])),
PLC (PSR_F_BIT | PSR_I_BIT | SVC_MODE)
: "r14");
+#endif
}
static struct machine_desc * __init setup_machine(unsigned int nr)
diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c
index 442b87476f97..48487cc8284d 100644
--- a/arch/arm/kernel/signal.c
+++ b/arch/arm/kernel/signal.c
@@ -538,7 +538,9 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
static inline void restart_syscall(struct pt_regs *regs)
{
+#ifndef CONFIG_CPU_V7M
regs->ARM_r0 = regs->ARM_ORIG_r0;
+#endif
regs->ARM_pc -= thumb_mode(regs) ? 2 : 4;
}
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index 219fc282f3bf..6977342aa139 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -729,6 +729,7 @@ void __init trap_init(void)
void __init early_trap_init(void)
{
+#ifndef CONFIG_CPU_V7M
unsigned long vectors = CONFIG_VECTORS_BASE;
extern char __stubs_start[], __stubs_end[];
extern char __vectors_start[], __vectors_end[];
@@ -753,4 +754,5 @@ void __init early_trap_init(void)
flush_icache_range(vectors, vectors + PAGE_SIZE);
modify_domain(DOMAIN_USER, DOMAIN_CLIENT);
+#endif
}
diff --git a/arch/arm/lib/backtrace.S b/arch/arm/lib/backtrace.S
index 42e62dd54188..41c4d3561b8f 100644
--- a/arch/arm/lib/backtrace.S
+++ b/arch/arm/lib/backtrace.S
@@ -28,7 +28,7 @@ ENTRY(__backtrace)
ENTRY(c_backtrace)
-#if !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK)
+#if defined(CONFIG_THUMB2_KERNEL) || !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK)
mov pc, lr
ENDPROC(__backtrace)
ENDPROC(c_backtrace)
diff --git a/arch/arm/mm/abort-ev7m.S b/arch/arm/mm/abort-ev7m.S
new file mode 100644
index 000000000000..083e85b27850
--- /dev/null
+++ b/arch/arm/mm/abort-ev7m.S
@@ -0,0 +1,9 @@
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+/*
+ * Function: v7m_early_abort
+ */
+ .align 5
+ENTRY(v7m_early_abort)
+ mov pc, lr
+ENDPROC(v7m_early_abort)
diff --git a/arch/arm/mm/nommu.c b/arch/arm/mm/nommu.c
index fd26a44e9f33..869e4ef5bed0 100644
--- a/arch/arm/mm/nommu.c
+++ b/arch/arm/mm/nommu.c
@@ -33,6 +33,7 @@ void __init reserve_node_zero(pg_data_t *pgdat)
BOOTMEM_DEFAULT);
#endif
+#ifndef CONFIG_CPU_V7M
/*
* Register the exception vector page.
* some architectures which the DRAM is the exception vector to trap,
@@ -40,6 +41,7 @@ void __init reserve_node_zero(pg_data_t *pgdat)
*/
reserve_bootmem_node(pgdat, CONFIG_VECTORS_BASE, PAGE_SIZE,
BOOTMEM_DEFAULT);
+#endif
}
static void __init sanity_check_meminfo(struct meminfo *mi)
diff --git a/arch/arm/mm/proc-v7m.S b/arch/arm/mm/proc-v7m.S
new file mode 100644
index 000000000000..ff97c011ae60
--- /dev/null
+++ b/arch/arm/mm/proc-v7m.S
@@ -0,0 +1,184 @@
+/*
+ * linux/arch/arm/mm/proc-v7m.S
+ *
+ * Copyright (C) 2008 ARM Ltd.
+ * Copyright (C) 2001 Deep Blue Solutions Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This is the "shell" of the ARMv7-M processor support.
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+ENTRY(cpu_v7m_proc_init)
+ mov pc, lr
+ENDPROC(cpu_v7m_proc_init)
+
+ENTRY(cpu_v7m_proc_fin)
+ mov pc, lr
+ENDPROC(cpu_v7m_proc_fin)
+
+/*
+ * cpu_v7m_reset(loc)
+ *
+ * Perform a soft reset of the system. Put the CPU into the
+ * same state as it would be if it had been reset, and branch
+ * to what would be the reset vector.
+ *
+ * - loc - location to jump to for soft reset
+ *
+ * It is assumed that:
+ */
+ .align 5
+ENTRY(cpu_v7m_reset)
+ mov pc, r0
+ENDPROC(cpu_v7m_reset)
+
+/*
+ * cpu_v7m_do_idle()
+ *
+ * Idle the processor (eg, wait for interrupt).
+ *
+ * IRQs are already disabled.
+ */
+ENTRY(cpu_v7m_do_idle)
+ wfi
+ mov pc, lr
+ENDPROC(cpu_v7m_do_idle)
+
+ENTRY(cpu_v7m_dcache_clean_area)
+ mov pc, lr
+ENDPROC(cpu_v7m_dcache_clean_area)
+
+/*
+ * cpu_v7m_switch_mm(pgd_phys, tsk)
+ *
+ * Set the translation table base pointer to be pgd_phys
+ *
+ * - pgd_phys - physical address of new TTB
+ *
+ * It is assumed that:
+ * - we are not using split page tables
+ */
+ENTRY(cpu_v7m_switch_mm)
+ mov pc, lr
+ENDPROC(cpu_v7m_switch_mm)
+
+ENTRY(cpu_v7m_set_pte_ext)
+ mov pc, lr
+ENDPROC(cpu_v7m_set_pte_ext)
+
+cpu_v7m_name:
+ .ascii "ARMv7-M Processor"
+ .align
+
+ .section ".text.init", #alloc, #execinstr
+
+/*
+ * __v7m_setup
+ *
+ * Initialise TLB, Caches, and MMU state ready to switch the MMU
+ * on. Return in r0 the new CP15 C1 control register setting.
+ *
+ * We automatically detect if we have a Harvard cache, and use the
+ * Harvard cache control instructions insead of the unified cache
+ * control instructions.
+ *
+ * This should be able to cover all ARMv7-M cores.
+ *
+ * It is assumed that:
+ * - cache type register is implemented
+ */
+__v7m_setup:
+ @ Configure the vector table base address
+ ldr r0, =0xe000ed08 @ vector table base address
+ ldr r12, =vector_table
+ str r12, [r0]
+
+ @ Lower the priority of the SVC and PendSV exceptions
+ ldr r0, =0xe000ed1c
+ mov r5, #0x80000000
+ str r5, [r0] @ set SVC priority
+ ldr r0, =0xe000ed20
+ mov r5, #0x00800000
+ str r5, [r0] @ set PendSV priority
+
+ @ SVC to run the kernel in this mode
+ adr r0, BSYM(1f)
+ ldr r5, [r12, #11 * 4] @ read the SVC vector entry
+ str r0, [r12, #11 * 4] @ write the temporary SVC vector entry
+ mov r6, lr @ save LR
+ mov r7, sp @ save SP
+ ldr sp, =__v7m_setup_stack_top
+ cpsie i
+ svc #0
+1: cpsid i
+ str r5, [r12, #11 * 4] @ restore the original SVC vector entry
+ mov lr, r6 @ restore LR
+ mov sp, r7 @ restore SP
+
+ @ Special-purpose control register
+ mov r0, #1
+ msr control, r0 @ Thread mode has unpriviledged access
+
+ @ Configure the System Control Register
+ ldr r0, =0xe000ed14 @ system control register
+ ldr r12, [r0]
+ orr r12, #1 << 9 @ STKALIGN
+ str r12, [r0]
+ mov pc, lr
+ENDPROC(__v7m_setup)
+
+ .align 2
+ .type v7m_processor_functions, #object
+ENTRY(v7m_processor_functions)
+ .word v7m_early_abort
+ .word cpu_v7m_proc_init
+ .word cpu_v7m_proc_fin
+ .word cpu_v7m_reset
+ .word cpu_v7m_do_idle
+ .word cpu_v7m_dcache_clean_area
+ .word cpu_v7m_switch_mm
+ .word cpu_v7m_set_pte_ext
+ .word pabort_noifar
+ .size v7m_processor_functions, . - v7m_processor_functions
+
+ .type cpu_arch_name, #object
+cpu_arch_name:
+ .asciz "armv7m"
+ .size cpu_arch_name, . - cpu_arch_name
+
+ .type cpu_elf_name, #object
+cpu_elf_name:
+ .asciz "v7m"
+ .size cpu_elf_name, . - cpu_elf_name
+ .align
+
+ .section ".proc.info.init", #alloc, #execinstr
+
+ /*
+ * Match any ARMv7-M processor core.
+ */
+ .type __v7m_proc_info, #object
+__v7m_proc_info:
+ .long 0x000f0000 @ Required ID value
+ .long 0x000f0000 @ Mask for ID
+ .long 0 @ proc_info_list.__cpu_mm_mmu_flags
+ .long 0 @ proc_info_list.__cpu_io_mmu_flags
+ b __v7m_setup @ proc_info_list.__cpu_flush
+ .long cpu_arch_name
+ .long cpu_elf_name
+ .long HWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
+ .long cpu_v7m_name
+ .long v7m_processor_functions @ proc_info_list.proc
+ .long 0 @ proc_info_list.tlb
+ .long 0 @ proc_info_list.user
+ .long 0 @ proc_info_list.cache
+ .size __v7m_proc_info, . - __v7m_proc_info
+
+__v7m_setup_stack:
+ .space 4 * 8 @ 8 registers
+__v7m_setup_stack_top: