diff options
author | gonzo <gonzo@FreeBSD.org> | 2012-08-15 03:03:03 +0000 |
---|---|---|
committer | gonzo <gonzo@FreeBSD.org> | 2012-08-15 03:03:03 +0000 |
commit | 032427f3e9854fccfdddaea8fb15ae4603391a11 (patch) | |
tree | 68d86df1ea7d9bfea335c91632747716f5a0df4a /sys/arm/arm/swtch.S | |
parent | eca813ad76756aea4f70787cf7827d4b319cfe94 (diff) | |
download | FreeBSD-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.S | 161 |
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) |