Subject: Re: ARM1136 panic on arm32_sync_icache()
To: Todd Poynor <tpoynor@danger.com>
From: Matt Thomas <matt@3am-software.com>
List: port-arm
Date: 11/08/2007 17:53:37
On Nov 8, 2007, at 5:22 PM, Todd Poynor wrote:
> Matt Thomas wrote:
>> On Nov 7, 2007, at 4:58 PM, Todd Poynor wrote:
> ...
>>> The ARMv6 Virtually Indexed Physically Tagged cache maintenance
>>> system control coprocessor instructions that invalidate lines
>>> based on Modified Virtual Addresses throw Data Abort exceptions
>>> for virtual addresses not mapped in the PTE. ...
>> I prefer the of onfault since this error shouldn't normally happen.
>
> Here's a patch against -current (but only tested on -4.0rc3) that
> adds a "safe" wrapper around cpu_icache_sync_range via pcb_onfault
> and returns zero or EFAULT to the caller. Some notes on
> questionable stuff I wrestled with follow.
>
> The wrapper is added to arch/arm/arm32/locore.S as a handy place to
> put it within the arm32/ family. This might not be the best place
> for a cpufunc thing, but it needs some assym.h symbols only
> generated for arm32. The protototype is added to arch/arm/include/
> cpufunc.h, although it is arm32-only. (It would be nice to have
> fault catchers in C and do this in arch/arm/arm32/sys_machdep.c
> with a setjmp-style call.)
>
> The wrapper knows the called routine doesn't mess with sp or r4.
>
>
> --
> Todd
>
> Index: netbsd-current-11082007/src/sys/arch/arm/arm32/genassym.cf
> ===================================================================
> --- netbsd-current-11082007.orig/src/sys/arch/arm/arm32/genassym.cf
> +++ netbsd-current-11082007/src/sys/arch/arm/arm32/genassym.cf
> @@ -130,6 +130,7 @@ define TRAPFRAMESIZE sizeof(struct trap
>
> define CF_IDCACHE_WBINV_ALL offsetof(struct cpu_functions,
> cf_idcache_wbinv_all)
> define CF_DCACHE_WB_RANGE offsetof(struct cpu_functions,
> cf_dcache_wb_range)
> +define CF_ICACHE_SYNC_RANGE offsetof(struct cpu_functions,
> cf_icache_sync_range)
> define CF_TLB_FLUSHID_SE offsetof(struct cpu_functions,
> cf_tlb_flushID_SE)
> define CF_CONTEXT_SWITCH offsetof(struct cpu_functions,
> cf_context_switch)
> define CF_SLEEP offsetof(struct cpu_functions, cf_sleep)
> Index: netbsd-current-11082007/src/sys/arch/arm/arm32/locore.S
> ===================================================================
> --- netbsd-current-11082007.orig/src/sys/arch/arm/arm32/locore.S
> +++ netbsd-current-11082007/src/sys/arch/arm/arm32/locore.S
> @@ -212,5 +212,39 @@ _C_LABEL(esym): .word _C_LABEL(end)
> ENTRY_NP(abort)
> b _C_LABEL(abort)
>
> +#ifdef MULTIPROCESSOR
> +.Lcpu_info:
> + .word _C_LABEL(cpu_info)
> +#else
> +.Lcurpcb:
> + .word _C_LABEL(curpcb)
> +#endif
> +
> +ENTRY(cpufunc_safe_icache_sync_range)
> + stmfd sp!, {lr}
stmfd sp!, {r4, lr}
> +#ifdef MULTIPROCESSOR
> + /* XXX Probably not appropriate for non-Hydra SMPs */
> + stmfd sp!, {r0-r1}
> + bl _C_LABEL(cpu_number)
> + ldr r4, .Lcpu_info
> + ldr r4, [r4, r0, lsl #2]
> + ldr r4, [r4, #CI_CURPCB]
> + ldmfd sp!, {r0-r1}
> +#else
> + ldr r4, .Lcurpcb
> + ldr r4, [r4]
> +#endif
> + adr r3, .Licache_sync_fault
> + str r3, [r4, #PCB_ONFAULT]
> + ldr r2, .Lcpufuncs
> + mov lr, pc
For a call, the stack should be 8-byte aligned.
> + ldr pc, [r2, #CF_ICACHE_SYNC_RANGE]
> + mov r0, #0x00000000
str r0, [r4, #PCB_ONFAULT]
> + ldmfd sp!, {pc}
ldmfd sp!, {r4, pc}
> +
> +.Licache_sync_fault:
> + mov r1, #0x00000000
> + str r1, [r4, #PCB_ONFAULT]
> + ldmfd sp!, {pc}
ldmfd sp!, {r4, pc}
I think these r1's should be r0.
> /* End of locore.S */
> Index: netbsd-current-11082007/src/sys/arch/arm/arm32/sys_machdep.c
> ===================================================================
> --- netbsd-current-11082007.orig/src/sys/arch/arm/arm32/sys_machdep.c
> +++ netbsd-current-11082007/src/sys/arch/arm/arm32/sys_machdep.c
> @@ -70,10 +70,8 @@ arm32_sync_icache(p, args, retval)
> if ((error = copyin(args, &ua, sizeof(ua))) != 0)
> return (error);
>
> - cpu_icache_sync_range(ua.addr, ua.len);
> -
> - *retval = 0;
> - return(0);
> + *retval = cpufunc_safe_icache_sync_range(ua.addr, ua.len);
> + return(*retval);
retval should stay 0. 0 should be returned.
> }
>
> static int
> Index: netbsd-current-11082007/src/sys/arch/arm/include/cpufunc.h
> ===================================================================
> --- netbsd-current-11082007.orig/src/sys/arch/arm/include/cpufunc.h
> +++ netbsd-current-11082007/src/sys/arch/arm/include/cpufunc.h
> @@ -211,6 +211,7 @@ u_int cpufunc_control (u_int, u_int);
> void cpufunc_domains (u_int);
> u_int cpufunc_faultstatus (void);
> u_int cpufunc_faultaddress (void);
> +int cpufunc_safe_icache_sync_range(vaddr_t, vsize_t);
>
> #ifdef CPU_ARM2
> u_int arm2_id (void);
>