debuggers.hg

changeset 20691:1e9441f4dcbd

xen-detect: Avoid dumping core

F12 introduces a tool to automatically report bugs when there are core
dumps. Since xen-detect relies on fork+waitpid in order to trap a
SIGILL from a child, every time someone runs xen-detect on a bare
metal kernel a bug is reported into Red Hat's Bugzilla. :-)

However, even without this contingent need, leaving core dumps around
is not nice. So this patch just traps SIGILL using
signal/sentjmp/longjmp, without the need to fork.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Mon Dec 14 11:58:45 2009 +0000 (2009-12-14)
parents 4bde3bb310b4
children d7403d17d03a
files tools/misc/xen-detect.c
line diff
     1.1 --- a/tools/misc/xen-detect.c	Mon Dec 14 11:38:15 2009 +0000
     1.2 +++ b/tools/misc/xen-detect.c	Mon Dec 14 11:58:45 2009 +0000
     1.3 @@ -26,19 +26,16 @@
     1.4  
     1.5  #include <stdint.h>
     1.6  #include <stdio.h>
     1.7 -#include <stdlib.h>
     1.8  #include <string.h>
     1.9 -#include <sys/types.h>
    1.10 -#include <sys/wait.h>
    1.11 -#include <unistd.h>
    1.12 -
    1.13 -static int pv_context;
    1.14 +#include <setjmp.h>
    1.15 +#include <signal.h>
    1.16  
    1.17  static void cpuid(uint32_t idx,
    1.18                    uint32_t *eax,
    1.19                    uint32_t *ebx,
    1.20                    uint32_t *ecx,
    1.21 -                  uint32_t *edx)
    1.22 +                  uint32_t *edx,
    1.23 +                  int pv_context)
    1.24  {
    1.25      asm volatile (
    1.26          "test %1,%1 ; jz 1f ; ud2a ; .ascii \"xen\" ; 1: cpuid"
    1.27 @@ -46,7 +43,7 @@ static void cpuid(uint32_t idx,
    1.28          : "0" (idx), "1" (pv_context) );
    1.29  }
    1.30  
    1.31 -static int check_for_xen(void)
    1.32 +static int check_for_xen(int pv_context)
    1.33  {
    1.34      uint32_t eax, ebx, ecx, edx;
    1.35      char signature[13];
    1.36 @@ -54,7 +51,7 @@ static int check_for_xen(void)
    1.37  
    1.38      for ( base = 0x40000000; base < 0x40010000; base += 0x100 )
    1.39      {
    1.40 -        cpuid(base, &eax, &ebx, &ecx, &edx);
    1.41 +        cpuid(base, &eax, &ebx, &ecx, &edx, pv_context);
    1.42  
    1.43          *(uint32_t *)(signature + 0) = ebx;
    1.44          *(uint32_t *)(signature + 4) = ecx;
    1.45 @@ -68,47 +65,32 @@ static int check_for_xen(void)
    1.46      return 0;
    1.47  
    1.48   found:
    1.49 -    cpuid(base + 1, &eax, &ebx, &ecx, &edx);
    1.50 +    cpuid(base + 1, &eax, &ebx, &ecx, &edx, pv_context);
    1.51      printf("Running in %s context on Xen v%d.%d.\n",
    1.52             pv_context ? "PV" : "HVM", (uint16_t)(eax >> 16), (uint16_t)eax);
    1.53      return 1;
    1.54  }
    1.55  
    1.56 +static jmp_buf sigill_jmp;
    1.57 +void sigill_handler(int sig)
    1.58 +{
    1.59 +    longjmp(sigill_jmp, 1);
    1.60 +}
    1.61 +
    1.62  int main(void)
    1.63  {
    1.64 -    pid_t pid;
    1.65 -    int status;
    1.66 -    uint32_t dummy;
    1.67 -
    1.68      /* Check for execution in HVM context. */
    1.69 -    if ( check_for_xen() )
    1.70 +    if ( check_for_xen(0) )
    1.71          return 0;
    1.72  
    1.73 -    /* Now we check for execution in PV context. */
    1.74 -    pv_context = 1;
    1.75 -
    1.76      /*
    1.77 -     * Fork a child to test the paravirtualised CPUID instruction.
    1.78 -     * If executed outside Xen PV context, the extended opcode will fault.
    1.79 +     * Set up a signal handler to test the paravirtualised CPUID instruction.
    1.80 +     * If executed outside Xen PV context, the extended opcode will fault, we
    1.81 +     * will longjmp via the signal handler, and print "Not running on Xen".
    1.82       */
    1.83 -    pid = fork();
    1.84 -    switch ( pid )
    1.85 -    {
    1.86 -    case 0:
    1.87 -        /* Child: test paravirtualised CPUID opcode and then exit cleanly. */
    1.88 -        cpuid(0x40000000, &dummy, &dummy, &dummy, &dummy);
    1.89 -        exit(0);
    1.90 -    case -1:
    1.91 -        fprintf(stderr, "Fork failed.\n");
    1.92 -        return 0;
    1.93 -    }
    1.94 -
    1.95 -    /*
    1.96 -     * Parent waits for child to terminate and checks for clean exit.
    1.97 -     * Only if the exit is clean is it safe for us to try the extended CPUID.
    1.98 -     */
    1.99 -    waitpid(pid, &status, 0);
   1.100 -    if ( WIFEXITED(status) && check_for_xen() )
   1.101 +    if ( !setjmp(sigill_jmp)
   1.102 +         && (signal(SIGILL, sigill_handler) != SIG_ERR)
   1.103 +         && check_for_xen(1) )
   1.104          return 0;
   1.105  
   1.106      printf("Not running on Xen.\n");