From owner-freebsd-current@FreeBSD.ORG Wed Jan 9 10:55:47 2013 Return-Path: Delivered-To: freebsd-current@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id ED8F9C4F for ; Wed, 9 Jan 2013 10:55:47 +0000 (UTC) (envelope-from okuno.kohji@jp.panasonic.com) Received: from smtp.mei.co.jp (smtp.mei.co.jp [133.183.100.20]) by mx1.freebsd.org (Postfix) with ESMTP id 920DE3F9 for ; Wed, 9 Jan 2013 10:55:47 +0000 (UTC) Received: from mail-gw.jp.panasonic.com ([157.8.1.157]) by smtp.mei.co.jp (8.12.11.20060614/3.7W/kc-maile11) with ESMTP id r09AdmWU002545 for ; Wed, 9 Jan 2013 19:39:48 +0900 (JST) Received: from epochmail.jp.panasonic.com ([157.8.1.130]) by mail.jp.panasonic.com (8.11.6p2/3.7W/kc-maili14) with ESMTP id r09Adm529282 for ; Wed, 9 Jan 2013 19:39:48 +0900 Received: by epochmail.jp.panasonic.com (8.12.11.20060308/3.7W/lomi16) id r09Admn7001273 for freebsd-current@FreeBSD.org; Wed, 9 Jan 2013 19:39:48 +0900 Received: from localhost by lomi16.jp.panasonic.com (8.12.11.20060308/3.7W) with ESMTP id r09Admx1001239 for ; Wed, 9 Jan 2013 19:39:48 +0900 Date: Wed, 09 Jan 2013 19:39:45 +0900 (JST) Message-Id: <20130109.193945.561808600309975779.okuno.kohji@jp.panasonic.com> To: freebsd-current@FreeBSD.org Subject: arm: cpu_switch() has bug? From: Kohji Okuno Organization: Panasonic Corporation X-Mailer: Mew version 6.5 on Emacs 23.4 / Mule 6.0 (HANACHIRUSATO) Mime-Version: 1.0 Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-BeenThere: freebsd-current@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Discussions about the use of FreeBSD-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 09 Jan 2013 10:55:48 -0000 Hi, I have doubt if cpu_switch() of arm has a bug. In swtch.S:L.334, if newtd->td_pcb (this is in stack pointer for kernel) has an address accessed first for the old(current) thread, data_abort_fault may occur. When data_abort_fault occurs, data_abort_handler() tries to solve this address from kernel_map. In this time, curthread and curpcb are already updated in swtch.S:L.223-231. As this result, data_abort_handler() will occur data_abort_fault in trap.c:L.301, again. When I check, in other CPUs, after updating the root pointer of MMU, curthread and curpcb are updated. Would you please check this? Thanks, Kohji Okuno <> 215 ENTRY(cpu_switch) 216 stmfd sp!, {r4-r7, lr} 217 mov r6, r2 /* Save the mutex */ 218 219 .Lswitch_resume: 220 /* rem: r0 = old lwp */ 221 /* rem: interrupts are disabled */ 222 223 /* Process is now on a processor. */ 224 /* We have a new curthread now so make a note it */ 225 GET_CURTHREAD_PTR(r7) 226 str r1, [r7] 227 228 /* Hook in a new pcb */ 229 GET_PCPU(r7) 230 ldr r2, [r1, #TD_PCB] 231 str r2, [r7, #PC_CURPCB] 232 233 /* rem: r1 = new process */ 234 /* rem: interrupts are enabled */ ==== SNIP ==== 298 /* rem: r2 = old PCB */ 299 /* rem: r9 = new PCB */ 300 /* rem: interrupts are enabled */ 301 302 #ifdef ARM_VFP_SUPPORT 303 /* 304 * vfp_store will clear pcpu->pc_vfpcthread, save 305 * registers and state, and modify the control as needed. 306 * a future exception will bounce the backup settings in the fp unit. 307 * XXX vfp_store can't change r4 308 */ 309 GET_PCPU(r7) 310 ldr r8, [r7, #(PC_VFPCTHREAD)] 311 cmp r4, r8 /* old thread used vfp? */ 312 bne 1f /* no, don't save */ 313 cmp r1, r4 /* same thread ? */ 314 beq 1f /* yes, skip vfp store */ 315 #ifdef SMP 316 ldr r8, [r7, #(PC_CPU)] /* last used on this cpu? */ 317 ldr r3, [r2, #(PCB_VFPCPU)] 318 cmp r8, r3 /* last cpu to use these registers? */ 319 bne 1f /* no. these values are stale */ 320 #endif 321 add r0, r2, #(PCB_VFPSTATE) 322 bl _C_LABEL(vfp_store) 323 1: 324 #endif /* ARM_VFP_SUPPORT */ 325 326 /* r1 now free! */ 327 328 /* Third phase : restore saved context */ 329 330 /* rem: r2 = old PCB */ 331 /* rem: r9 = new PCB */ 332 /* rem: interrupts are enabled */ 333 334 ldr r5, [r9, #(PCB_DACR)] /* r5 = new DACR */ 335 mov r2, #DOMAIN_CLIENT 336 cmp r5, r2, lsl #(PMAP_DOMAIN_KERNEL * 2) /* Sw to kernel thread? */ 337 beq .Lcs_context_switched /* Yup. Don't flush cache */ 338 mrc p15, 0, r0, c3, c0, 0 /* r0 = old DACR */ <> 224 void 225 data_abort_handler(trapframe_t *tf) 226 { 227 struct vm_map *map; 228 struct pcb *pcb; 229 struct thread *td; 230 u_int user, far, fsr; 231 vm_prot_t ftype; 232 void *onfault; 233 vm_offset_t va; 234 int error = 0; 235 struct ksig ksig; 236 struct proc *p; 237 238 239 /* Grab FAR/FSR before enabling interrupts */ 240 far = cpu_faultaddress(); 241 fsr = cpu_faultstatus(); 242 #if 0 243 printf("data abort: %p (from %p %p)\n", (void*)far, (void*)tf->tf_pc, 244 (void*)tf->tf_svc_lr); 245 #endif 246 247 /* Update vmmeter statistics */ 248 #if 0 249 vmexp.traps++; 250 #endif 251 252 td = curthread; 253 p = td->td_proc; 254 255 PCPU_INC(cnt.v_trap); 256 /* Data abort came from user mode? */ 257 user = TRAP_USERMODE(tf); 258 259 if (user) { 260 td->td_pticks = 0; 261 td->td_frame = tf; 262 if (td->td_ucred != td->td_proc->p_ucred) 263 cred_update_thread(td); 264 265 } 266 /* Grab the current pcb */ 267 pcb = td->td_pcb; ==== SNIP ==== 299 300 /* fusubailout is used by [fs]uswintr to avoid page faulting */ 301 if (__predict_false(pcb->pcb_onfault == fusubailout)) { 302 tf->tf_r0 = EFAULT; 303 tf->tf_pc = (register_t)(intptr_t) pcb->pcb_onfault; 304 return; 305 }