Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/tests/lib/libc/gen ATF test for SIGBUS => BUS_ADRALN (invali...



details:   https://anonhg.NetBSD.org/src/rev/06bdb02d6f47
branches:  trunk
changeset: 778914:06bdb02d6f47
user:      jym <jym%NetBSD.org@localhost>
date:      Fri Apr 20 00:40:31 2012 +0000

description:
ATF test for SIGBUS => BUS_ADRALN (invalid address alignment).

That one is tedious to test under x86: alignment exceptions are
not reported by this architecture unless you ask for them explicitely (by
setting the PSL_AC bit). The brokenness does not end there: %cr2 should
contain the address where the unaligned access occured, alas, it does not.

I am not aware of other architectures where this could happen. Still, my
knowledge is limited; if there is one, feel free to send me a mail and I
will update the test accordingly.

Adding insult to injury, this test can fail in various funny ways with VMs:
- under x86 QEMU, no trap() happens. As ring 3 code stays almost untouched by
QEMU VMM, I suppose the exception can only be triggered when the host
itself is capable of catching unaligned accesses.
- under Virtual Box with HVM support, i386 works fine, but amd64 fails with a
SIGILL (Illegal instruction) that happens right before entering the
signal handler. No idea why, and trying to debug it with gdb freezes the VM
(including ddb breaks).

Anyway, tested with:
- i386: P4 host, anita, Virtual Box HVM (Mac OS X)
- amd64: anita, Virtual Box HVM (Mac OS X)

XXX I would appreciate if someone could test it under a real amd64 host with
an up-to-date kernel, so I can reasonably assume that the culprit is
Virtual Box and not our amd64 port (my test machine being off line
I cannot do it myself). Results from other arches would be a plus too.

Initial issue reported by Nicolas Joly on port-amd64. Thanks!

diffstat:

 tests/lib/libc/gen/t_siginfo.c |  70 +++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 69 insertions(+), 1 deletions(-)

diffs (98 lines):

diff -r 9fe5014665d9 -r 06bdb02d6f47 tests/lib/libc/gen/t_siginfo.c
--- a/tests/lib/libc/gen/t_siginfo.c    Thu Apr 19 21:32:01 2012 +0000
+++ b/tests/lib/libc/gen/t_siginfo.c    Fri Apr 20 00:40:31 2012 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: t_siginfo.c,v 1.14 2012/03/18 07:14:08 jruoho Exp $ */
+/* $NetBSD: t_siginfo.c,v 1.15 2012/04/20 00:40:31 jym Exp $ */
 
 /*-
  * Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -48,6 +48,9 @@
 #include <ieeefp.h>
 #endif
 
+/* for sigbus */
+char *addr;
+
 /* for sigchild */
 pid_t child;
 int code;
@@ -405,6 +408,70 @@
        atf_tc_fail("Test did not fault as expected");
 }
 
+static void
+sigbus_action(int signo, siginfo_t *info, void *ptr)
+{
+
+       sig_debug(signo, info, (ucontext_t *)ptr);
+
+       ATF_REQUIRE_EQ(info->si_signo, SIGBUS);
+       ATF_REQUIRE_EQ(info->si_errno, 0);
+       ATF_REQUIRE_EQ(info->si_code, BUS_ADRALN);
+
+       if (strcmp(atf_config_get("atf_arch"), "i386") == 0 ||
+           strcmp(atf_config_get("atf_arch"), "x86_64") == 0) {
+               atf_tc_expect_fail("x86 architecture does not correctly "
+                   "report the address where the unaligned access occured");
+       }
+
+       ATF_REQUIRE_EQ(info->si_addr, (void *)addr);
+       atf_tc_pass();
+       /* NOTREACHED */
+}
+
+ATF_TC(sigbus_adraln);
+ATF_TC_HEAD(sigbus_adraln, tc)
+{
+
+       atf_tc_set_md_var(tc, "descr",
+           "Checks that signal trampoline correctly calls SIGBUS handler "
+           "for invalid address alignment");
+}
+
+ATF_TC_BODY(sigbus_adraln, tc)
+{
+       struct sigaction sa;
+
+       sa.sa_flags = SA_SIGINFO;
+       sa.sa_sigaction = sigbus_action;
+       sigemptyset(&sa.sa_mask);
+       sigaction(SIGBUS, &sa, NULL);
+
+       /* Enable alignement checks for x86. 0x40000 is PSL_AC. */
+#if defined(__i386__)
+       __asm__("pushf; orl $0x40000, (%esp); popf");
+#elif defined(__amd64__)
+       __asm__("pushf; orl $0x40000, (%rsp); popf");
+#endif
+
+       addr = calloc(2, sizeof(int));
+       ATF_REQUIRE(addr != NULL);
+
+       if (strcmp(atf_config_get("atf_arch"), "i386") == 0 ||
+           strcmp(atf_config_get("atf_arch"), "x86_64") == 0) {
+               if (system("cpuctl identify 0 | grep -q QEMU") == 0) {
+                       atf_tc_expect_fail("QEMU fails to trap unaligned "
+                           "accesses");
+               }
+       }
+
+       /* Force an unaligned access */
+       addr++;
+       ATF_REQUIRE_EQ(*(volatile int *)addr, 0);
+
+       atf_tc_fail("Test did not fault as expected");
+}
+
 ATF_TP_ADD_TCS(tp)
 {
 
@@ -415,6 +482,7 @@
        ATF_TP_ADD_TC(tp, sigfpe_flt);
        ATF_TP_ADD_TC(tp, sigfpe_int);
        ATF_TP_ADD_TC(tp, sigsegv);
+       ATF_TP_ADD_TC(tp, sigbus_adraln);
 
        return atf_no_error();
 }



Home | Main Index | Thread Index | Old Index