Hi, since ARMv6 the coprocessor provides special registers to store software defined values. Those registers are:
* TPIDRURW -> kernel RW, user RW * TPIDRURO -> kernel RW, user RO * TPIDRPRW -> kernel RW TPIDRPRW is typically used to store the pointer to the curcpu struct, while TPIDRURO is used to point to the TCB. The following diff implements using TPIDRPRW to store and retrieve the curcpu struct pointer. This will especially be helpful in future MP efforts. I have guarded it for ARMv7 only, as that's the only hardware I have that supports it and I was able to test on. I have removed a few #ifdef MULTIPROCESSOR as they wouldn't be needed with curcpu stored in that register and there'll probably never be support for MP on non-ARMv7 machines. If TCB_GET()'s only user is libpthread, then it could make sense to store the TCB pointer in TPIDRURO. If it's possible that it's also used in ports, then the arm packages won't be compatible to armish/zaurus anymore. But the TCB stuff is not part of this diff. Patrick diff --git sys/arch/arm/arm/bcopyinout.S sys/arch/arm/arm/bcopyinout.S index 4d423e5..be9bb47 100644 --- sys/arch/arm/arm/bcopyinout.S +++ sys/arch/arm/arm/bcopyinout.S @@ -82,18 +82,14 @@ ENTRY(copyin) moveq pc, lr SAVE_REGS -#ifdef MULTIPROCESSOR - /* XXX Probably not appropriate for non-Hydra SMPs */ - stmfd sp!, {r0-r2, r14} - bl _C_LABEL(cpu_number) - ldr r4, .Lcpu_info - ldr r4, [r4, r0, lsl #2] - ldr r4, [r4, #CI_CURPCB] - ldmfd sp!, {r0-r2, r14} + +#ifdef CPU_ARMv7 + /* Get curcpu from TPIDRPRW. */ + mrc p15, 0, r4, c13, c0, 4 #else ldr r4, .Lcpu_info_primary - ldr r4, [r4, #CI_CURPCB] #endif + ldr r4, [r4, #CI_CURPCB] ldr r5, [r4, #PCB_ONFAULT] adr r3, .Lcopyfault @@ -305,18 +301,14 @@ ENTRY(copyout) moveq pc, lr SAVE_REGS -#ifdef MULTIPROCESSOR - /* XXX Probably not appropriate for non-Hydra SMPs */ - stmfd sp!, {r0-r2, r14} - bl _C_LABEL(cpu_number) - ldr r4, .Lcpu_info - ldr r4, [r4, r0, lsl #2] - ldr r4, [r4, #CI_CURPCB] - ldmfd sp!, {r0-r2, r14} + +#ifdef CPU_ARMv7 + /* Get curcpu from TPIDRPRW. */ + mrc p15, 0, r4, c13, c0, 4 #else ldr r4, .Lcpu_info_primary - ldr r4, [r4, #CI_CURPCB] #endif + ldr r4, [r4, #CI_CURPCB] ldr r5, [r4, #PCB_ONFAULT] adr r3, .Lcopyfault @@ -518,18 +510,14 @@ ENTRY(kcopy) moveq pc, lr SAVE_REGS -#ifdef MULTIPROCESSOR - /* XXX Probably not appropriate for non-Hydra SMPs */ - stmfd sp!, {r0-r2, r14} - bl _C_LABEL(cpu_number) - ldr r4, .Lcpu_info - ldr r4, [r4, r0, lsl #2] - ldr r4, [r4, #CI_CURPCB] - ldmfd sp!, {r0-r2, r14} + +#ifdef CPU_ARMv7 + /* Get curcpu from TPIDRPRW. */ + mrc p15, 0, r4, c13, c0, 4 #else ldr r4, .Lcpu_info_primary - ldr r4, [r4, #CI_CURPCB] #endif + ldr r4, [r4, #CI_CURPCB] ldr r5, [r4, #PCB_ONFAULT] adr r3, .Lcopyfault @@ -711,18 +699,13 @@ ENTRY(kcopy) * else EFAULT if a page fault occurred. */ ENTRY(badaddr_read_1) -#ifdef MULTIPROCESSOR - /* XXX Probably not appropriate for non-Hydra SMPs */ - stmfd sp!, {r0-r1, r14} - bl _C_LABEL(cpu_number) - ldr r2, .Lcpu_info - ldr r2, [r2, r0, lsl #2] - ldr r2, [r2, #CI_CURPCB] - ldmfd sp!, {r0-r1, r14} +#ifdef CPU_ARMv7 + /* Get curcpu from TPIDRPRW. */ + mrc p15, 0, r2, c13, c0, 4 #else ldr r2, .Lcpu_info_primary - ldr r2, [r2, #CI_CURPCB] #endif + ldr r2, [r2, #CI_CURPCB] ldr ip, [r2, #PCB_ONFAULT] adr r3, 1f str r3, [r2, #PCB_ONFAULT] @@ -745,18 +728,13 @@ ENTRY(badaddr_read_1) * else EFAULT if a page fault occurred. */ ENTRY(badaddr_read_2) -#ifdef MULTIPROCESSOR - /* XXX Probably not appropriate for non-Hydra SMPs */ - stmfd sp!, {r0-r1, r14} - bl _C_LABEL(cpu_number) - ldr r2, .Lcpu_info - ldr r2, [r2, r0, lsl #2] - ldr r2, [r2, #CI_CURPCB] - ldmfd sp!, {r0-r1, r14} +#ifdef CPU_ARMv7 + /* Get curcpu from TPIDRPRW. */ + mrc p15, 0, r2, c13, c0, 4 #else ldr r2, .Lcpu_info_primary - ldr r2, [r2, #CI_CURPCB] #endif + ldr r2, [r2, #CI_CURPCB] ldr ip, [r2, #PCB_ONFAULT] adr r3, 1f str r3, [r2, #PCB_ONFAULT] @@ -779,18 +757,13 @@ ENTRY(badaddr_read_2) * else EFAULT if a page fault occurred. */ ENTRY(badaddr_read_4) -#ifdef MULTIPROCESSOR - /* XXX Probably not appropriate for non-Hydra SMPs */ - stmfd sp!, {r0-r1, r14} - bl _C_LABEL(cpu_number) - ldr r2, .Lcpu_info - ldr r2, [r2, r0, lsl #2] - ldr r2, [r2, #CI_CURPCB] - ldmfd sp!, {r0-r1, r14} +#ifdef CPU_ARMv7 + /* Get curcpu from TPIDRPRW. */ + mrc p15, 0, r2, c13, c0, 4 #else ldr r2, .Lcpu_info_primary - ldr r2, [r2, #CI_CURPCB] #endif + ldr r2, [r2, #CI_CURPCB] ldr ip, [r2, #PCB_ONFAULT] adr r3, 1f str r3, [r2, #PCB_ONFAULT] diff --git sys/arch/arm/arm/copystr.S sys/arch/arm/arm/copystr.S index 3723f18..3941553 100644 --- sys/arch/arm/arm/copystr.S +++ sys/arch/arm/arm/copystr.S @@ -104,18 +104,13 @@ ENTRY(copyinstr) moveq r0, #ENAMETOOLONG beq 2f -#ifdef MULTIPROCESSOR - /* XXX Probably not appropriate for non-Hydra SMPs */ - stmfd sp!, {r0-r3, r14} - bl _C_LABEL(cpu_number) - ldr r4, .Lcpu_info - ldr r4, [r4, r0, lsl #2] - ldr r4, [r4, #CI_CURPCB] - ldmfd sp!, {r0-r3, r14} +#ifdef CPU_ARMv7 + /* Get curcpu from TPIDRPRW. */ + mrc p15, 0, r4, c13, c0, 4 #else ldr r4, .Lcpu_info_primary - ldr r4, [r4, #CI_CURPCB] #endif + ldr r4, [r4, #CI_CURPCB] #ifdef DEBUG teq r4, #0x00000000 @@ -161,18 +156,13 @@ ENTRY(copyoutstr) moveq r0, #ENAMETOOLONG beq 2f -#ifdef MULTIPROCESSOR - /* XXX Probably not appropriate for non-Hydra SMPs */ - stmfd sp!, {r0-r3, r14} - bl _C_LABEL(cpu_number) - ldr r4, .Lcpu_info - ldr r4, [r4, r0, lsl #2] - ldr r4, [r4, #CI_CURPCB] - ldmfd sp!, {r0-r3, r14} +#ifdef CPU_ARMv7 + /* Get curcpu from TPIDRPRW. */ + mrc p15, 0, r4, c13, c0, 4 #else ldr r4, .Lcpu_info_primary - ldr r4, [r4, #CI_CURPCB] #endif + ldr r4, [r4, #CI_CURPCB] #ifdef DEBUG teq r4, #0x00000000 diff --git sys/arch/arm/arm/cpuswitch7.S sys/arch/arm/arm/cpuswitch7.S index 126b41a..f6f78a6 100644 --- sys/arch/arm/arm/cpuswitch7.S +++ sys/arch/arm/arm/cpuswitch7.S @@ -105,13 +105,6 @@ .text -.Lcpu_info_primary: - .word _C_LABEL(cpu_info_primary) -.Lcurproc: - .word _C_LABEL(cpu_info_primary) + CI_CURPROC -.Lcurpcb: - .word _C_LABEL(cpu_info_primary) + CI_CURPCB - .Lcpufuncs: .word _C_LABEL(cpufuncs) @@ -166,10 +159,10 @@ ENTRY(cpu_idle_leave) ENTRY(cpu_switchto) stmfd sp!, {r4-r7, lr} + /* Get curcpu from TPIDRPRW. */ + mrc p15, 0, r3, c13, c0, 4 #ifdef MULTIPROCESSOR - /* XXX use curcpu() */ - ldr r2, .Lcpu_info_primary - str r2, [r1, #(P_CPU)] + str r3, [r1, #(P_CPU)] #else /* p->p_cpu initialized in fork1() for single-processor */ #endif @@ -179,14 +172,12 @@ ENTRY(cpu_switchto) strb r2, [r1, #(P_STAT)] /* We have a new curproc now so make a note it */ - ldr r7, .Lcurproc - str r1, [r7] + str r1, [r3, #(CI_CURPROC)] /* Hook in a new pcb */ - ldr r7, .Lcurpcb - ldr r6, [r7] /* Remember the old PCB */ + ldr r6, [r3, #(CI_CURPCB)] /* Remember the old PCB */ ldr r2, [r1, #(P_ADDR)] - str r2, [r7] + str r2, [r3, #(CI_CURPCB)] /* * If the old proc on entry to cpu_switch was zero then the diff --git sys/arch/arm/arm/irq_dispatch.S sys/arch/arm/arm/irq_dispatch.S index c84b131..8c2736e 100644 --- sys/arch/arm/arm/irq_dispatch.S +++ sys/arch/arm/arm/irq_dispatch.S @@ -105,7 +105,11 @@ ASENTRY_NP(irq_entry) * r5 address of the curcpu struct * r6 old value of curcpu()->ci_idepth */ +#ifdef CPU_ARMv7 + mrc p15, 0, r5, c13, c0, 4 /* Get curcpu from TPIDRPRW. */ +#else ldr r5, .Lcpu_info_primary +#endif mov r0, sp /* arg for dispatcher */ ldr r6, [r5, #CI_IDEPTH] add r1, r6, #1 diff --git sys/arch/arm/arm/locore.S sys/arch/arm/arm/locore.S index 6fb7b62..e45011e 100644 --- sys/arch/arm/arm/locore.S +++ sys/arch/arm/arm/locore.S @@ -56,7 +56,12 @@ ASENTRY_NP(start) mov r5, r1 mov r6, r2 adr r1, .Lstart - ldmia r1, {r1, r2, sp} /* Set initial stack and */ + ldmia r1, {r1, r2, r8, sp} /* Set initial stack and */ + +#ifdef CPU_ARMv7 + mcr p15, 0, r8, c13, c0, 4 /* put curcpu into the TPIDRPRW */ +#endif + sub r2, r2, r1 /* get zero init data */ mov r3, #0 @@ -87,6 +92,7 @@ ASENTRY_NP(start) .Lstart: .word _edata .word _end + .word _C_LABEL(cpu_info_primary) .word svcstk + INIT_ARM_STACK_SIZE .Lmainreturned: diff --git sys/arch/arm/include/cpu.h sys/arch/arm/include/cpu.h index 2587991..563a101 100644 --- sys/arch/arm/include/cpu.h +++ sys/arch/arm/include/cpu.h @@ -208,8 +208,19 @@ struct cpu_info { extern struct cpu_info cpu_info_primary; extern struct cpu_info *cpu_info_list; -#ifndef MULTIPROCESSOR +#ifdef CPU_ARMv7 +static inline struct cpu_info * +curcpu(void) +{ + struct cpu_info *__ci; + __asm volatile("mrc p15, 0, %0, c13, c0, 4" : "=r" (__ci)); + return (__ci); +} +#else #define curcpu() (&cpu_info_primary) +#endif + +#ifndef MULTIPROCESSOR #define cpu_number() 0 #define CPU_IS_PRIMARY(ci) 1 #define CPU_INFO_ITERATOR int