summaryrefslogtreecommitdiffstats
path: root/sys/arm/arm/swtch.S
diff options
context:
space:
mode:
authorgonzo <gonzo@FreeBSD.org>2012-08-15 03:03:03 +0000
committergonzo <gonzo@FreeBSD.org>2012-08-15 03:03:03 +0000
commit032427f3e9854fccfdddaea8fb15ae4603391a11 (patch)
tree68d86df1ea7d9bfea335c91632747716f5a0df4a /sys/arm/arm/swtch.S
parenteca813ad76756aea4f70787cf7827d4b319cfe94 (diff)
downloadFreeBSD-src-032427f3e9854fccfdddaea8fb15ae4603391a11.zip
FreeBSD-src-032427f3e9854fccfdddaea8fb15ae4603391a11.tar.gz
Merging projects/armv6, part 1
Cummulative patch of changes that are not vendor-specific: - ARMv6 and ARMv7 architecture support - ARM SMP support - VFP/Neon support - ARM Generic Interrupt Controller driver - Simplification of startup code for all platforms
Diffstat (limited to 'sys/arm/arm/swtch.S')
-rw-r--r--sys/arm/arm/swtch.S161
1 files changed, 101 insertions, 60 deletions
diff --git a/sys/arm/arm/swtch.S b/sys/arm/arm/swtch.S
index a293c5c..e93b948 100644
--- a/sys/arm/arm/swtch.S
+++ b/sys/arm/arm/swtch.S
@@ -85,64 +85,55 @@
#include <machine/armreg.h>
__FBSDID("$FreeBSD$");
+#define DOMAIN_CLIENT 0x01
-/*
- * New experimental definitions of IRQdisable and IRQenable
- * These keep FIQ's enabled since FIQ's are special.
- */
+#ifdef _ARM_ARCH_6
+#define GET_PCPU(tmp) \
+ mrc p15, 0, tmp, c13, c0, 4;
+#else
+.Lcurpcpu:
+ .word _C_LABEL(__pcpu)
+
+#define GET_PCPU(tmp) \
+ ldr tmp, .Lcurpcpu
+#endif
-#define DOMAIN_CLIENT 0x01
-#define IRQdisable \
- mrs r14, cpsr ; \
- orr r14, r14, #(I32_bit) ; \
- msr cpsr_c, r14 ; \
-
-#define IRQenable \
- mrs r14, cpsr ; \
- bic r14, r14, #(I32_bit) ; \
- msr cpsr_c, r14 ; \
-
-/*
- * These are used for switching the translation table/DACR.
- * Since the vector page can be invalid for a short time, we must
- * disable both regular IRQs *and* FIQs.
- *
- * XXX: This is not necessary if the vector table is relocated.
- */
-#define IRQdisableALL \
- mrs r14, cpsr ; \
- orr r14, r14, #(I32_bit | F32_bit) ; \
- msr cpsr_c, r14
-
-#define IRQenableALL \
- mrs r14, cpsr ; \
- bic r14, r14, #(I32_bit | F32_bit) ; \
- msr cpsr_c, r14
-
-.Lcurpcb:
- .word _C_LABEL(__pcpu) + PC_CURPCB
.Lcpufuncs:
.word _C_LABEL(cpufuncs)
-.Lblock_userspace_access:
- .word _C_LABEL(block_userspace_access)
-.Lcpu_do_powersave:
- .word _C_LABEL(cpu_do_powersave)
.Lblocked_lock:
.word _C_LABEL(blocked_lock)
+
ENTRY(cpu_throw)
mov r5, r1
/*
+ * r0 = oldtd
* r5 = newtd
*/
- ldr r7, [r5, #(TD_PCB)] /* r7 = new thread's PCB */
+ GET_PCPU(r7)
+#ifdef ARM_VFP_SUPPORT
+ /*
+ * vfp_discard will clear pcpu->pc_vfpcthread, and modify
+ * and modify the control as needed.
+ */
+ ldr r4, [r7, #(PC_VFPCTHREAD)] /* this thread using vfp? */
+ cmp r0, r4
+ bne 3f
+ bl _C_LABEL(vfp_discard) /* yes, shut down vfp */
+3:
+#endif /* ARM_VFP_SUPPORT */
+
+ ldr r7, [r5, #(TD_PCB)] /* r7 = new thread's PCB */
+
/* Switch to lwp0 context */
ldr r9, .Lcpufuncs
+#if !defined(CPU_ARM11) && !defined(CPU_CORTEXA) && !defined(CPU_MV_PJ4B)
mov lr, pc
ldr pc, [r9, #CF_IDCACHE_WBINV_ALL]
+#endif
ldr r0, [r7, #(PCB_PL1VEC)]
ldr r1, [r7, #(PCB_DACR)]
/*
@@ -200,21 +191,24 @@ ENTRY(cpu_throw)
#endif
/* We have a new curthread now so make a note it */
- ldr r6, .Lcurthread
+ GET_CURTHREAD_PTR(r6)
str r5, [r6]
/* Set the new tp */
ldr r6, [r5, #(TD_MD + MD_TP)]
+#ifdef ARM_TP_ADDRESS
ldr r4, =ARM_TP_ADDRESS
str r6, [r4]
ldr r6, [r5, #(TD_MD + MD_RAS_START)]
str r6, [r4, #4] /* ARM_RAS_START */
ldr r6, [r5, #(TD_MD + MD_RAS_END)]
str r6, [r4, #8] /* ARM_RAS_END */
-
+#else
+ mcr p15, 0, r6, c13, c0, 3
+#endif
/* Hook in a new pcb */
- ldr r6, .Lcurpcb
- str r7, [r6]
+ GET_PCPU(r6)
+ str r7, [r6, #PC_CURPCB]
ldmfd sp!, {r4-r7, pc}
@@ -226,22 +220,15 @@ ENTRY(cpu_switch)
/* rem: r0 = old lwp */
/* rem: interrupts are disabled */
-#ifdef MULTIPROCESSOR
- /* XXX use curcpu() */
- ldr r2, .Lcpu_info_store
- str r2, [r6, #(L_CPU)]
-#endif
-
/* Process is now on a processor. */
-
/* We have a new curthread now so make a note it */
- ldr r7, .Lcurthread
+ GET_CURTHREAD_PTR(r7)
str r1, [r7]
/* Hook in a new pcb */
- ldr r7, .Lcurpcb
+ GET_PCPU(r7)
ldr r2, [r1, #TD_PCB]
- str r2, [r7]
+ str r2, [r7, #PC_CURPCB]
/* rem: r1 = new process */
/* rem: interrupts are enabled */
@@ -267,6 +254,7 @@ ENTRY(cpu_switch)
* NOTE: We can now use r8-r13 until it is time to restore
* them for the new process.
*/
+#ifdef ARM_TP_ADDRESS
/* Store the old tp */
ldr r3, =ARM_TP_ADDRESS
ldr r9, [r3]
@@ -283,12 +271,19 @@ ENTRY(cpu_switch)
str r9, [r3, #4]
ldr r9, [r1, #(TD_MD + MD_RAS_END)]
str r9, [r3, #8]
+#else
+ /* Store the old tp */
+ mrc p15, 0, r9, c13, c0, 3
+ str r9, [r0, #(TD_MD + MD_TP)]
+ /* Set the new tp */
+ ldr r9, [r1, #(TD_MD + MD_TP)]
+ mcr p15, 0, r9, c13, c0, 3
+#endif
+
/* Get the user structure for the new process in r9 */
ldr r9, [r1, #(TD_PCB)]
- /* r1 now free! */
-
mrs r3, cpsr
/*
* We can do that, since
@@ -300,15 +295,39 @@ ENTRY(cpu_switch)
str sp, [r2, #(PCB_UND_SP)]
msr cpsr_c, r3 /* Restore the old mode */
- /* rem: r8 = old PCB */
+ /* rem: r2 = old PCB */
/* rem: r9 = new PCB */
/* rem: interrupts are enabled */
- /* What else needs to be saved Only FPA stuff when that is supported */
+#ifdef ARM_VFP_SUPPORT
+ /*
+ * vfp_store will clear pcpu->pc_vfpcthread, save
+ * registers and state, and modify the control as needed.
+ * a future exception will bounce the backup settings in the fp unit.
+ * XXX vfp_store can't change r4
+ */
+ GET_PCPU(r7)
+ ldr r8, [r7, #(PC_VFPCTHREAD)]
+ cmp r4, r8 /* old thread used vfp? */
+ bne 1f /* no, don't save */
+ cmp r1, r4 /* same thread ? */
+ beq 1f /* yes, skip vfp store */
+#ifdef SMP
+ ldr r8, [r7, #(PC_CPU)] /* last used on this cpu? */
+ ldr r3, [r2, #(PCB_VFPCPU)]
+ cmp r8, r3 /* last cpu to use these registers? */
+ bne 1f /* no. these values are stale */
+#endif
+ add r0, r2, #(PCB_VFPSTATE)
+ bl _C_LABEL(vfp_store)
+1:
+#endif /* ARM_VFP_SUPPORT */
+
+ /* r1 now free! */
/* Third phase : restore saved context */
- /* rem: r8 = old PCB */
+ /* rem: r2 = old PCB */
/* rem: r9 = new PCB */
/* rem: interrupts are enabled */
@@ -333,6 +352,7 @@ ENTRY(cpu_switch)
cmpeq r0, r5 /* Same DACR? */
beq .Lcs_context_switched /* yes! */
+#if !defined(CPU_ARM11) && !defined(CPU_CORTEXA) && !defined(CPU_MV_PJ4B)
/*
* Definately need to flush the cache.
*/
@@ -340,6 +360,7 @@ ENTRY(cpu_switch)
ldr r1, .Lcpufuncs
mov lr, pc
ldr pc, [r1, #CF_IDCACHE_WBINV_ALL]
+#endif
.Lcs_cache_purge_skipped:
/* rem: r6 = lock */
/* rem: r9 = new PCB */
@@ -408,8 +429,7 @@ ENTRY(cpu_switch)
/* Release the old thread */
str r6, [r4, #TD_LOCK]
ldr r6, .Lblocked_lock
- ldr r3, .Lcurthread
- ldr r3, [r3]
+ GET_CURTHREAD_PTR(r3)
1:
ldr r4, [r3, #TD_LOCK]
@@ -484,6 +504,27 @@ ENTRY(savectx)
/* Store all the registers in the process's pcb */
add r2, r0, #(PCB_R8)
stmia r2, {r8-r13}
+#ifdef ARM_VFP_SUPPORT
+ /*
+ * vfp_store will clear pcpu->pc_vfpcthread, save
+ * registers and state, and modify the control as needed.
+ * a future exception will bounce the backup settings in the fp unit.
+ */
+ GET_PCPU(r7)
+ ldr r4, [r7, #(PC_VFPCTHREAD)] /* vfp thread */
+ ldr r2, [r7, #(PC_CURTHREAD)] /* current thread */
+ cmp r4, r2
+ bne 1f
+#ifdef SMP
+ ldr r2, [r7, #(PC_CPU)] /* last used on this cpu? */
+ ldr r3, [r0, #(PCB_VFPCPU)]
+ cmp r2, r3
+ bne 1f /* no. these values are stale */
+#endif
+ add r0, r0, #(PCB_VFPSTATE)
+ bl _C_LABEL(vfp_store)
+1:
+#endif /* ARM_VFP_SUPPORT */
ldmfd sp!, {r4-r7, pc}
ENTRY(fork_trampoline)
OpenPOWER on IntegriCloud