Hi,
would anyone care to look at diffs aiming to make diffs like below possible
for armv7 too? doesn't take 'much' fixing beyond removing cruft, and can
be done mostly w/o touching the files/headers shared with armish/zaurus, if
wanted.
-Artturi
sys/arch/arm/arm/cpuswitch7.S | 224 +++++++-----------------------------------
1 file changed, 38 insertions(+), 186 deletions(-)
diff --git a/sys/arch/arm/arm/cpuswitch7.S b/sys/arch/arm/arm/cpuswitch7.S
index 43bf7da..a5cc631 100644
--- a/sys/arch/arm/arm/cpuswitch7.S
+++ b/sys/arch/arm/arm/cpuswitch7.S
@@ -83,6 +83,7 @@
#include <machine/frame.h>
#include <machine/intr.h>
#include <machine/asm.h>
+#include <machine/sysreg.h>
/* LINTSTUB: include <sys/param.h> */
@@ -157,27 +158,25 @@ ENTRY(cpu_idle_leave)
*/
ENTRY(cpu_switchto)
- stmfd sp!, {r4-r7, lr}
+ push {r4-r7, lr}
+ sub sp, sp, #4
- /* Get curcpu from TPIDRPRW. */
- mrc p15, 0, r3, c13, c0, 4
+ /* Process is now on a processor. */
+ mov r2, #SONPROC /* p->p_stat = SONPROC */
+ strb r2, [r1, #P_STAT]
+
+ mrc CP15_TPIDRPRW(r3) /* r3 = curcpu */
#ifdef MULTIPROCESSOR
- str r3, [r1, #(P_CPU)]
+ str r3, [r1, #P_CPU]
#else
/* p->p_cpu initialized in fork1() for single-processor */
#endif
-
- /* Process is now on a processor. */
- mov r2, #SONPROC /* p->p_stat = SONPROC */
- strb r2, [r1, #(P_STAT)]
-
- /* We have a new curproc now so make a note it */
- str r1, [r3, #(CI_CURPROC)]
+ str r1, [r3, #CI_CURPROC] /* set new curproc */
+ ldr r6, [r3, #CI_CURPCB] /* r6 = old PCB */
/* Hook in a new pcb */
- ldr r6, [r3, #(CI_CURPCB)] /* Remember the old PCB */
- ldr r2, [r1, #(P_ADDR)]
- str r2, [r3, #(CI_CURPCB)]
+ ldr r2, [r1, #P_ADDR] /* r2 = new PCB */
+ str r2, [r3, #CI_CURPCB]
/*
* If the old proc on entry to cpu_switch was zero then the
@@ -186,192 +185,45 @@ ENTRY(cpu_switchto)
* to clear the cache and TLB).
*/
teq r0, #0x00000000
- beq .Lswitch_exited
-
- /* Stage two: Save old context */
-
- /* Save all the registers in the old proc's pcb */
- add r7, r6, #(PCB_R8)
- stmia r7, {r8-r13}
-
-.Lswitch_exited:
- /*
- * NOTE: We can now use r8-r13 until it is time to restore
- * them for the new process.
- */
-
- /* Remember the old PCB. */
- mov r8, r6
-
- /* Save new proc in r6 now. */
- mov r6, r1
-
- /* Get the user structure for the new process in r9 */
- ldr r9, [r6, #(P_ADDR)]
-
- /*
- * This can be optimised... We know we want to go from SVC32
- * mode to UND32 mode
- */
- mrs r3, cpsr
- bic r2, r3, #(PSR_MODE)
- orr r2, r2, #(PSR_UND32_MODE | PSR_I)
- msr cpsr_c, r2
-
-#ifdef notworthit
- teq r0, #0x00000000
- strne sp, [r8, #(PCB_UND_SP)]
-#else
- str sp, [r8, #(PCB_UND_SP)]
-#endif
-
- msr cpsr_c, r3 /* Restore the old mode */
-
- /* rem: r0 = old proc */
- /* rem: r1 = r6 = new process */
- /* rem: r8 = old PCB */
- /* rem: r9 = new PCB */
-
- /* What else needs to be saved Only FPA stuff when that is supported */
-
- /* Third phase: restore saved context */
+ beq .switch_exited__skip_save
+ add r7, r6, #PCB_R8 /* save registers in */
+ stmia r7, {r8-r13} /* the old proc's pcb */
+.switch_exited__skip_save:
/*
- * Get the new L1 table pointer into r11. If we're switching to
- * an LWP with the same address space as the outgoing one, we can
- * skip the cache purge and the TTB load.
- *
- * To avoid data dep stalls that would happen anyway, we try
- * and get some useful work done in the mean time.
+ * If we're switching to the same address space as the outgoing
+ * one, we can skip the cache purge and the TTB load.
*/
- ldr r10, [r8, #(PCB_PAGEDIR)] /* r10 = old L1 */
- ldr r11, [r9, #(PCB_PAGEDIR)] /* r11 = new L1 */
-
- ldr r0, [r8, #(PCB_DACR)] /* r0 = old DACR */
- ldr r1, [r9, #(PCB_DACR)] /* r1 = new DACR */
+ ldr r10, [r6, #PCB_PAGEDIR] /* r10 = old L1 */
+ ldr r9, [r1, #P_ADDR] /* r9 = new PCB */
+ ldr r11, [r9, #PCB_PAGEDIR] /* r11 = new L1 */
teq r10, r11 /* Same L1? */
- cmpeq r0, r1 /* Same DACR? */
- beq .Lcs_context_switched /* yes! */
-
- mov r2, #DOMAIN_CLIENT
- cmp r1, r2, lsl #(PMAP_DOMAIN_KERNEL * 2) /* Sw to kernel thread? */
- beq .Lcs_cache_purge_skipped /* Yup. Don't flush cache */
-
- stmfd sp!, {r0-r3}
- ldr r1, .Lcpufuncs
- mov lr, pc
- ldr pc, [r1, #CF_ICACHE_SYNC_ALL]
- ldmfd sp!, {r0-r3}
-
-.Lcs_cache_purge_skipped:
- /* rem: r1 = new DACR */
- /* rem: r6 = new proc */
- /* rem: r9 = new PCB */
- /* rem: r10 = old L1 */
- /* rem: r11 = new L1 */
-
- ldr r7, [r9, #(PCB_PL1VEC)]
+ beq .context_switched__skip_flush /* yes! */
/*
- * At this point we need to kill IRQ's again.
- *
- * XXXSCW: Don't need to block FIQs if vectors have been relocated
+ * Do a full context switch = full TLB flush.
*/
- IRQdisableALL
-
- /*
- * Ensure the vector table is accessible by fixing up the L1
- */
- cmp r7, #0 /* No need to fixup vector table? */
- ldrne r2, [r7] /* But if yes, fetch current value */
- ldrne r0, [r9, #(PCB_L1VEC)] /* Fetch new vector_page value */
- mcr p15, 0, r1, c3, c0, 0 /* Update DACR for new context */
- cmpne r2, r0 /* Stuffing the same value? */
-#ifndef PMAP_INCLUDE_PTE_SYNC
- strne r0, [r7] /* Nope, update it */
-#else
- beq .Lcs_same_vector
- str r0, [r7] /* Otherwise, update it */
-
- /*
- * Need to sync the cache to make sure that last store is
- * visible to the MMU.
- */
- ldr r2, .Lcpufuncs
- mov r0, r7
- mov r1, #4
- mov lr, pc
- ldr pc, [r2, #CF_DCACHE_WB_RANGE]
-
-.Lcs_same_vector:
-#endif /* PMAP_INCLUDE_PTE_SYNC */
-
- cmp r10, r11 /* Switching to the same L1? */
- ldr r10, .Lcpufuncs
- beq .Lcs_same_l1 /* Yup. */
-
- /*
- * Do a full context switch, including full TLB flush.
- */
- mov r0, r11
- mov lr, pc
- ldr pc, [r10, #CF_CONTEXT_SWITCH]
-
- b .Lcs_context_switched
-
- /*
- * We're switching to a different process in the same L1.
- * In this situation, we only need to flush the TLB for the
- * vector_page mapping, and even then only if r7 is non-NULL.
- */
-.Lcs_same_l1:
- cmp r7, #0
- movne r0, #0 /* We *know* vector_page's VA is 0x0 */
- movne lr, pc
- ldrne pc, [r10, #CF_TLB_FLUSHID_SE]
-
-.Lcs_context_switched:
-
- /* XXXSCW: Safe to re-enable FIQs here */
-
- /* rem: r6 = new proc */
- /* rem: r9 = new PCB */
-
- /*
- * This can be optimised... We know we want to go from SVC32
- * mode to UND32 mode
- */
- mrs r3, cpsr
- bic r2, r3, #(PSR_MODE)
- orr r2, r2, #(PSR_UND32_MODE)
- msr cpsr_c, r2
-
- ldr sp, [r9, #(PCB_UND_SP)]
-
- msr cpsr_c, r3 /* Restore the old mode */
-
- /* Restore all the save registers */
- add r7, r9, #PCB_R8
- ldmia r7, {r8-r13}
-
+ mcr CP15_ICIALLU
+ mcr CP15_BPIALL
+ dsb sy
+ isb sy
+ mcr CP15_TTBR0(r11)
+ mcr CP15_TLBIALL
+ dsb sy
+ isb sy
+
+.context_switched__skip_flush:
+ add r7, r9, #PCB_R8 /* restore registers saved */
+ ldmia r7, {r8-r13} /* in the new proc's pcb */
sub r7, r7, #PCB_R8 /* restore PCB pointer */
- /* rem: r6 = new proc */
- /* rem: r7 = new pcb */
-
- /* We can enable interrupts again */
- IRQenableALL
-
- /* rem: r6 = new proc */
- /* rem: r7 = new PCB */
-
-.Lswitch_return:
/*
* Pull the registers that got pushed when either savectx() or
* cpu_switch() was called and return.
*/
- ldmfd sp!, {r4-r7, pc}
+ add sp, sp, #4
+ pop {r4-r7, pc}
/* LINTSTUB: Func: void savectx(struct pcb *pcb) */
ENTRY(savectx)