On Monday 07 May 2012 13:58:53 Luck, Tony wrote: > the disassembly of the sched_getcpu() code at runtime looks like: > 0x2000000000203940 <+0>: [MMI] alloc r32=ar.pfs,9,1,0 > 0x2000000000203941 <+1>: adds r14=8,r13 > 0x2000000000203942 <+2>: mov r33=r12;; > 0x2000000000203950 <+16>: [MMI] ld8 r14=[r14] > 0x2000000000203951 <+17>: nop.m 0x0 > 0x2000000000203952 <+18>: mov r15=1304 > 0x2000000000203960 <+32>: [MII] mov r35=r0 <<<<<<<<<<<<<<<<<<< > 0x2000000000203961 <+33>: mov r34=r0;;<<<<<<<<<<<<<<<<<<< > 0x2000000000203962 <+34>: mov b7=r14;; > 0x2000000000203970 <+48>: [MIB] nop.m 0x0 > 0x2000000000203971 <+49>: nop.i 0x0 > 0x2000000000203972 <+50>: br.call.sptk.many b6=b7;; > > When the "br.call" is executed, we flip to the new register > frame and r34/r35 in the sched_getcpu() frame become r32/r33 > in the new frame. i think only one register is rotated because we called alloc with locals=1. stepping through with gdb shows that -- on the first insn in __kernel_syscall_via_epc, r32 is now the local variable on the stack, r33 and r34 are 0. > So you get -EFAULT because the VDSO tries to dereference a NULL > pointer for each of the *cpu and *node arguments. the kernel doesn't care if cpu/node are NULL: SYSCALL_DEFINE3(getcpu, unsigned __user *, cpup, unsigned __user *, nodep, struct getcpu_cache __user *, unused) { int err = 0; int cpu = raw_smp_processor_id(); if (cpup) err |= put_user(cpu, cpup); if (nodep) err |= put_user(cpu_to_node(cpu), nodep); return err ? -EFAULT : 0; } -mike
Attachment:
signature.asc
Description: This is a digitally signed message part.