public inbox for linux-ia64@vger.kernel.org
 help / color / mirror / Atom feed
From: Mike Frysinger <vapier@gentoo.org>
To: linux-ia64@vger.kernel.org
Subject: getcpu() returns EFAULT when called via the vdso
Date: Sun, 06 May 2012 20:45:23 +0000	[thread overview]
Message-ID: <201205061645.24398.vapier@gentoo.org> (raw)

[-- Attachment #1: Type: Text/Plain, Size: 3324 bytes --]

sched_getcpu() on my ia64 systems is failing with EFAULT.  simple test code:

$ cat test.c
#define _GNU_SOURCE
#include <errno.h>
#include <sched.h>
#include <stdio.h>
#include <string.h>
#include <sys/syscall.h>
main() {
	int i, e;
	puts("");
close(444);
	kill(0, 0);
close(333);
	syscall(__NR_getcpu, &i, 0, 0);
close(123);
	errno = 0;
	i = sched_getcpu();
	e = errno;
close(321);
	printf("getcpu() = %i: %s\n", i, strerror(e));
}
the puts() is to force initialization of some internal libc stuff so the strace 
output is easier to read later on.  the close() calls make it easy to pick out 
the different steps.

when i run this with newer glibc versions (like 2.13+), i get:
	getcpu() = -1: Bad address

running it through strace, we see:
close(444)                              = -1 EBADF (Bad file descriptor)
kill(0, SIG_0)                          = 0
close(333)                              = -1 EBADF (Bad file descriptor)
getcpu([1], NULL, 0)                    = 0
close(123)                              = -1 EBADF (Bad file descriptor)
close(321)                              = -1 EBADF (Bad file descriptor)
write(1, "\ngetcpu() = -1: Bad address\n", 28) = 28

you can see the syscall() working, but the sched_getcpu() doesn't seem to make 
it into supervisor mode.  glibc internally uses the vdso for doing most 
syscalls (while the syscall() func sticks to the old break method).  since we 
know kill() and sched_getcpu() use the vdso, we know strace can handle both 
styles fine since kill() gets decoded.  so that leaves something funky.

the sched_getcpu() code is somewhat simple:
int sched_getcpu (void) {
	unsigned int cpu;
	int r = INLINE_SYSCALL (getcpu, 3, &cpu, NULL, NULL);
	return r == -1 ? r : cpu;
}
so it passes in a pointer to an int on the stack, and 2 null pointers ...

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;;

so we see:
 - b7 gets loaded with a pointer to the __kernel_syscall_via_epc entry point
 - r15 gets the right syscall number (1304 for __NR_getcpu)
 - r33 is a pointer to the stack (gdb shows it is in the $sp region)
 - r34 and r35 get zeroed out

yet once i step over the call to __kernel_syscall_via_epc, i see r8 is set to 
14 (EFAULT).  i can't see that value being setup in kernel/gate.S, but my 
knowledge of ia64 assembly isn't that great, nor the kernel paths, so i'm 
hoping someone can point out the obvious to me here.

i've tested linux 3.0.6 and 3.1.6, glibc 2.13 and 2.15/2.16, and gcc 4.5.3 
(just what i have access to).  they all behave the same.
-mike

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

             reply	other threads:[~2012-05-06 20:45 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-05-06 20:45 Mike Frysinger [this message]
2012-05-07 17:58 ` getcpu() returns EFAULT when called via the vdso Luck, Tony
2012-05-07 23:12 ` Mike Frysinger
2012-05-07 23:53 ` Mike Frysinger
2012-05-08 21:13 ` Tony Luck
2012-05-08 22:31 ` Mike Frysinger
2012-05-15  5:41 ` Mike Frysinger
2012-11-29 23:34 ` Mike Frysinger

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=201205061645.24398.vapier@gentoo.org \
    --to=vapier@gentoo.org \
    --cc=linux-ia64@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox