Merge remote branch 'qemu-kvm/uq/master' into staging
authorAnthony Liguori <aliguori@us.ibm.com>
Mon, 22 Feb 2010 22:16:22 +0000 (16:16 -0600)
committerAnthony Liguori <aliguori@us.ibm.com>
Mon, 22 Feb 2010 22:16:22 +0000 (16:16 -0600)
1  2 
cpu-exec.c
qemu-common.h
target-i386/kvm.c
vl.c

diff --combined cpu-exec.c
@@@ -210,7 -210,8 +210,7 @@@ static void cpu_handle_debug_exception(
  
  int cpu_exec(CPUState *env1)
  {
 -#define DECLARE_HOST_REGS 1
 -#include "hostregs_helper.h"
 +    host_reg_t saved_env_reg;
      int ret, interrupt_request;
      TranslationBlock *tb;
      uint8_t *tc_ptr;
  
      cpu_single_env = env1;
  
 -    /* first we save global registers */
 -#define SAVE_HOST_REGS 1
 -#include "hostregs_helper.h"
 +    /* the access to env below is actually saving the global register's
 +       value, so that files not including target-xyz/exec.h are free to
 +       use it.  */
 +    QEMU_BUILD_BUG_ON (sizeof (saved_env_reg) != sizeof (env));
 +    saved_env_reg = (host_reg_t) env;
 +    asm("");
      env = env1;
  
  #if defined(TARGET_I386)
-     /* put eflags in CPU temporary format */
-     CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
-     DF = 1 - (2 * ((env->eflags >> 10) & 1));
-     CC_OP = CC_OP_EFLAGS;
-     env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
+     if (!kvm_enabled()) {
+         /* put eflags in CPU temporary format */
+         CC_SRC = env->eflags & (CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
+         DF = 1 - (2 * ((env->eflags >> 10) & 1));
+         CC_OP = CC_OP_EFLAGS;
+         env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C);
+     }
  #elif defined(TARGET_SPARC)
  #elif defined(TARGET_M68K)
      env->cc_op = CC_OP_FLAGS;
  #endif
  
      /* restore global registers */
 -#include "hostregs_helper.h"
 +    asm("");
 +    env = (void *) saved_env_reg;
  
      /* fail safe : never use cpu_single_env outside cpu_exec() */
      cpu_single_env = NULL;
@@@ -924,20 -923,6 +926,20 @@@ int cpu_signal_handler(int host_signum
  # define TRAP_sig(context)                    REG_sig(trap, context)
  #endif /* linux */
  
 +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
 +#include <ucontext.h>
 +# define IAR_sig(context)             ((context)->uc_mcontext.mc_srr0)
 +# define MSR_sig(context)             ((context)->uc_mcontext.mc_srr1)
 +# define CTR_sig(context)             ((context)->uc_mcontext.mc_ctr)
 +# define XER_sig(context)             ((context)->uc_mcontext.mc_xer)
 +# define LR_sig(context)              ((context)->uc_mcontext.mc_lr)
 +# define CR_sig(context)              ((context)->uc_mcontext.mc_cr)
 +/* Exception Registers access */
 +# define DAR_sig(context)             ((context)->uc_mcontext.mc_dar)
 +# define DSISR_sig(context)           ((context)->uc_mcontext.mc_dsisr)
 +# define TRAP_sig(context)            ((context)->uc_mcontext.mc_exc)
 +#endif /* __FreeBSD__|| __FreeBSD_kernel__ */
 +
  #ifdef __APPLE__
  # include <sys/ucontext.h>
  typedef struct ucontext SIGCONTEXT;
@@@ -967,11 -952,7 +969,11 @@@ int cpu_signal_handler(int host_signum
                         void *puc)
  {
      siginfo_t *info = pinfo;
 +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
 +    ucontext_t *uc = puc;
 +#else
      struct ucontext *uc = puc;
 +#endif
      unsigned long pc;
      int is_write;
  
diff --combined qemu-common.h
@@@ -11,8 -11,6 +11,8 @@@
  #define QEMU_WARN_UNUSED_RESULT
  #endif
  
 +#define QEMU_BUILD_BUG_ON(x) typedef char __build_bug_on__##__LINE__[(x)?-1:1];
 +
  /* Hack around the mess dyngen-exec.h causes: We need QEMU_NORETURN in files that
     cannot include the following headers without conflicts. This condition has
     to be removed once dyngen is gone. */
@@@ -172,6 -170,7 +172,7 @@@ ssize_t qemu_write_full(int fd, const v
  void qemu_set_cloexec(int fd);
  
  #ifndef _WIN32
+ int qemu_eventfd(int pipefd[2]);
  int qemu_pipe(int pipefd[2]);
  #endif
  
@@@ -227,8 -226,6 +228,8 @@@ typedef struct I2SCodec I2SCodec
  typedef struct DeviceState DeviceState;
  typedef struct SSIBus SSIBus;
  
 +typedef uint64_t pcibus_t;
 +
  /* CPU save/load.  */
  void cpu_save(QEMUFile *f, void *opaque);
  int cpu_load(QEMUFile *f, void *opaque, int version_id);
diff --combined target-i386/kvm.c
@@@ -24,7 -24,6 +24,7 @@@
  #include "cpu.h"
  #include "gdbstub.h"
  #include "host-utils.h"
 +#include "hw/pc.h"
  
  #ifdef CONFIG_KVM_PARA
  #include <linux/kvm_para.h>
@@@ -159,9 -158,6 +159,6 @@@ struct kvm_para_features 
  #ifdef KVM_CAP_PV_MMU
          { KVM_CAP_PV_MMU, KVM_FEATURE_MMU_OP },
  #endif
- #ifdef KVM_CAP_CR3_CACHE
-         { KVM_CAP_CR3_CACHE, KVM_FEATURE_CR3_CACHE },
- #endif
          { -1, -1 }
  };
  
@@@ -363,13 -359,6 +360,13 @@@ int kvm_arch_init(KVMState *s, int smp_
       * as unavaible memory.  FIXME, need to ensure the e820 map deals with
       * this?
       */
 +    /*
 +     * Tell fw_cfg to notify the BIOS to reserve the range.
 +     */
 +    if (e820_add_entry(0xfffbc000, 0x4000, E820_RESERVED) < 0) {
 +        perror("e820_add_entry() table is full");
 +        exit(1);
 +    }
      return kvm_vm_ioctl(s, KVM_SET_TSS_ADDR, 0xfffbd000);
  }
                      
diff --combined vl.c
--- 1/vl.c
--- 2/vl.c
+++ b/vl.c
@@@ -182,6 -182,7 +182,6 @@@ const char *bios_name = NULL
  struct drivelist drives = QTAILQ_HEAD_INITIALIZER(drives);
  struct driveoptlist driveopts = QTAILQ_HEAD_INITIALIZER(driveopts);
  enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
 -static DisplayState *display_state;
  DisplayType display_type = DT_DEFAULT;
  const char* keyboard_layout = NULL;
  ram_addr_t ram_size;
@@@ -270,6 -271,12 +270,12 @@@ uint8_t qemu_uuid[16]
  static QEMUBootSetHandler *boot_set_handler;
  static void *boot_set_opaque;
  
+ #ifdef SIGRTMIN
+ #define SIG_IPI (SIGRTMIN+4)
+ #else
+ #define SIG_IPI SIGUSR1
+ #endif
  static int default_serial = 1;
  static int default_parallel = 1;
  static int default_virtcon = 1;
@@@ -2576,6 -2583,46 +2582,6 @@@ void pcmcia_info(Monitor *mon
  }
  
  /***********************************************************/
 -/* register display */
 -
 -struct DisplayAllocator default_allocator = {
 -    defaultallocator_create_displaysurface,
 -    defaultallocator_resize_displaysurface,
 -    defaultallocator_free_displaysurface
 -};
 -
 -void register_displaystate(DisplayState *ds)
 -{
 -    DisplayState **s;
 -    s = &display_state;
 -    while (*s != NULL)
 -        s = &(*s)->next;
 -    ds->next = NULL;
 -    *s = ds;
 -}
 -
 -DisplayState *get_displaystate(void)
 -{
 -    return display_state;
 -}
 -
 -DisplayAllocator *register_displayallocator(DisplayState *ds, DisplayAllocator *da)
 -{
 -    if(ds->allocator ==  &default_allocator) ds->allocator = da;
 -    return ds->allocator;
 -}
 -
 -/* dumb display */
 -
 -static void dumb_display_init(void)
 -{
 -    DisplayState *ds = qemu_mallocz(sizeof(DisplayState));
 -    ds->allocator = &default_allocator;
 -    ds->surface = qemu_create_displaysurface(ds, 640, 480);
 -    register_displaystate(ds);
 -}
 -
 -/***********************************************************/
  /* I/O handling */
  
  typedef struct IOHandlerRecord {
@@@ -3170,14 -3217,15 +3176,15 @@@ static int io_thread_fd = -1
  
  static void qemu_event_increment(void)
  {
-     static const char byte = 0;
+     /* Write 8 bytes to be compatible with eventfd.  */
+     static uint64_t val = 1;
      ssize_t ret;
  
      if (io_thread_fd == -1)
          return;
  
      do {
-         ret = write(io_thread_fd, &byte, sizeof(byte));
+         ret = write(io_thread_fd, &val, sizeof(val));
      } while (ret < 0 && errno == EINTR);
  
      /* EAGAIN is fine, a read must be pending.  */
@@@ -3194,7 -3242,7 +3201,7 @@@ static void qemu_event_read(void *opaqu
      ssize_t len;
      char buffer[512];
  
-     /* Drain the notify pipe */
+     /* Drain the notify pipe.  For eventfd, only 8 bytes will be read.  */
      do {
          len = read(fd, buffer, sizeof(buffer));
      } while ((len == -1 && errno == EINTR) || len == sizeof(buffer));
@@@ -3205,7 -3253,7 +3212,7 @@@ static int qemu_event_init(void
      int err;
      int fds[2];
  
-     err = qemu_pipe(fds);
+     err = qemu_eventfd(fds);
      if (err == -1)
          return -errno;
  
@@@ -3338,9 -3386,11 +3345,11 @@@ static QemuCond qemu_cpu_cond
  static QemuCond qemu_system_cond;
  static QemuCond qemu_pause_cond;
  
- static void block_io_signals(void);
+ static void tcg_block_io_signals(void);
+ static void kvm_block_io_signals(CPUState *env);
  static void unblock_io_signals(void);
  static int tcg_has_work(void);
+ static int cpu_has_work(CPUState *env);
  
  static int qemu_init_main_loop(void)
  {
      return 0;
  }
  
+ static void qemu_wait_io_event_common(CPUState *env)
+ {
+     if (env->stop) {
+         env->stop = 0;
+         env->stopped = 1;
+         qemu_cond_signal(&qemu_pause_cond);
+     }
+ }
  static void qemu_wait_io_event(CPUState *env)
  {
      while (!tcg_has_work())
      qemu_mutex_unlock(&qemu_fair_mutex);
  
      qemu_mutex_lock(&qemu_global_mutex);
-     if (env->stop) {
-         env->stop = 0;
-         env->stopped = 1;
-         qemu_cond_signal(&qemu_pause_cond);
+     qemu_wait_io_event_common(env);
+ }
+ static void qemu_kvm_eat_signal(CPUState *env, int timeout)
+ {
+     struct timespec ts;
+     int r, e;
+     siginfo_t siginfo;
+     sigset_t waitset;
+     ts.tv_sec = timeout / 1000;
+     ts.tv_nsec = (timeout % 1000) * 1000000;
+     sigemptyset(&waitset);
+     sigaddset(&waitset, SIG_IPI);
+     qemu_mutex_unlock(&qemu_global_mutex);
+     r = sigtimedwait(&waitset, &siginfo, &ts);
+     e = errno;
+     qemu_mutex_lock(&qemu_global_mutex);
+     if (r == -1 && !(e == EAGAIN || e == EINTR)) {
+         fprintf(stderr, "sigtimedwait: %s\n", strerror(e));
+         exit(1);
      }
  }
  
+ static void qemu_kvm_wait_io_event(CPUState *env)
+ {
+     while (!cpu_has_work(env))
+         qemu_cond_timedwait(env->halt_cond, &qemu_global_mutex, 1000);
+     qemu_kvm_eat_signal(env, 0);
+     qemu_wait_io_event_common(env);
+ }
  static int qemu_cpu_exec(CPUState *env);
  
  static void *kvm_cpu_thread_fn(void *arg)
  {
      CPUState *env = arg;
  
-     block_io_signals();
      qemu_thread_self(env->thread);
      if (kvm_enabled())
          kvm_init_vcpu(env);
  
+     kvm_block_io_signals(env);
      /* signal CPU creation */
      qemu_mutex_lock(&qemu_global_mutex);
      env->created = 1;
      while (1) {
          if (cpu_can_run(env))
              qemu_cpu_exec(env);
-         qemu_wait_io_event(env);
+         qemu_kvm_wait_io_event(env);
      }
  
      return NULL;
@@@ -3419,7 -3508,7 +3467,7 @@@ static void *tcg_cpu_thread_fn(void *ar
  {
      CPUState *env = arg;
  
-     block_io_signals();
+     tcg_block_io_signals();
      qemu_thread_self(env->thread);
  
      /* signal CPU creation */
@@@ -3445,7 -3534,7 +3493,7 @@@ void qemu_cpu_kick(void *_env
      CPUState *env = _env;
      qemu_cond_broadcast(env->halt_cond);
      if (kvm_enabled())
-         qemu_thread_signal(env->thread, SIGUSR1);
+         qemu_thread_signal(env->thread, SIG_IPI);
  }
  
  int qemu_cpu_self(void *_env)
@@@ -3464,7 -3553,7 +3512,7 @@@ static void cpu_signal(int sig
          cpu_exit(cpu_single_env);
  }
  
- static void block_io_signals(void)
+ static void tcg_block_io_signals(void)
  {
      sigset_t set;
      struct sigaction sigact;
      sigaddset(&set, SIGUSR2);
      sigaddset(&set, SIGIO);
      sigaddset(&set, SIGALRM);
+     sigaddset(&set, SIGCHLD);
      pthread_sigmask(SIG_BLOCK, &set, NULL);
  
      sigemptyset(&set);
-     sigaddset(&set, SIGUSR1);
+     sigaddset(&set, SIG_IPI);
      pthread_sigmask(SIG_UNBLOCK, &set, NULL);
  
      memset(&sigact, 0, sizeof(sigact));
      sigact.sa_handler = cpu_signal;
-     sigaction(SIGUSR1, &sigact, NULL);
+     sigaction(SIG_IPI, &sigact, NULL);
+ }
+ static void dummy_signal(int sig)
+ {
+ }
+ static void kvm_block_io_signals(CPUState *env)
+ {
+     int r;
+     sigset_t set;
+     struct sigaction sigact;
+     sigemptyset(&set);
+     sigaddset(&set, SIGUSR2);
+     sigaddset(&set, SIGIO);
+     sigaddset(&set, SIGALRM);
+     sigaddset(&set, SIGCHLD);
+     sigaddset(&set, SIG_IPI);
+     pthread_sigmask(SIG_BLOCK, &set, NULL);
+     pthread_sigmask(SIG_BLOCK, NULL, &set);
+     sigdelset(&set, SIG_IPI);
+     memset(&sigact, 0, sizeof(sigact));
+     sigact.sa_handler = dummy_signal;
+     sigaction(SIG_IPI, &sigact, NULL);
+     r = kvm_set_signal_mask(env, &set);
+     if (r) {
+         fprintf(stderr, "kvm_set_signal_mask: %s\n", strerror(r));
+         exit(1);
+     }
  }
  
  static void unblock_io_signals(void)
      pthread_sigmask(SIG_UNBLOCK, &set, NULL);
  
      sigemptyset(&set);
-     sigaddset(&set, SIGUSR1);
+     sigaddset(&set, SIG_IPI);
      pthread_sigmask(SIG_BLOCK, &set, NULL);
  }
  
@@@ -3504,7 -3626,7 +3585,7 @@@ static void qemu_signal_lock(unsigned i
      qemu_mutex_lock(&qemu_fair_mutex);
  
      while (qemu_mutex_trylock(&qemu_global_mutex)) {
-         qemu_thread_signal(tcg_cpu_thread, SIGUSR1);
+         qemu_thread_signal(tcg_cpu_thread, SIG_IPI);
          if (!qemu_mutex_timedlock(&qemu_global_mutex, msecs))
              break;
      }
@@@ -3545,7 -3667,7 +3626,7 @@@ static void pause_all_vcpus(void
  
      while (penv) {
          penv->stop = 1;
-         qemu_thread_signal(penv->thread, SIGUSR1);
+         qemu_thread_signal(penv->thread, SIG_IPI);
          qemu_cpu_kick(penv);
          penv = (CPUState *)penv->next_cpu;
      }
          qemu_cond_timedwait(&qemu_pause_cond, &qemu_global_mutex, 100);
          penv = first_cpu;
          while (penv) {
-             qemu_thread_signal(penv->thread, SIGUSR1);
+             qemu_thread_signal(penv->thread, SIG_IPI);
              penv = (CPUState *)penv->next_cpu;
          }
      }
@@@ -3567,7 -3689,7 +3648,7 @@@ static void resume_all_vcpus(void
      while (penv) {
          penv->stop = 0;
          penv->stopped = 0;
-         qemu_thread_signal(penv->thread, SIGUSR1);
+         qemu_thread_signal(penv->thread, SIG_IPI);
          qemu_cpu_kick(penv);
          penv = (CPUState *)penv->next_cpu;
      }
@@@ -4836,9 -4958,6 +4917,9 @@@ int main(int argc, char **argv, char **
              fclose(fp);
          }
      }
 +#if defined(cpudef_setup)
 +    cpudef_setup(); /* parse cpu definitions in target config file */
 +#endif
  
      /* second pass of option parsing */
      optind = 1;
                  /* hw initialization will check this */
                  if (*optarg == '?') {
  /* XXX: implement xxx_cpu_list for targets that still miss it */
 -#if defined(cpu_list)
 -                    cpu_list(stdout, &fprintf);
 +#if defined(cpu_list_id)
 +                    cpu_list_id(stdout, &fprintf, optarg);
 +#elif defined(cpu_list)
 +                    cpu_list(stdout, &fprintf);               /* deprecated */
  #endif
                      exit(0);
                  } else {
      if (qemu_opts_foreach(&qemu_device_opts, device_init_func, NULL, 1) != 0)
          exit(1);
  
 -    if (!display_state)
 -        dumb_display_init();
 +    net_check_clients();
 +
      /* just use the first displaystate for the moment */
 -    ds = display_state;
 +    ds = get_displaystate();
  
      if (display_type == DT_DEFAULT) {
  #if defined(CONFIG_SDL) || defined(CONFIG_COCOA)
          qemu_mod_timer(nographic_timer, qemu_get_clock(rt_clock));
      }
  
 -    text_consoles_set_display(display_state);
 +    text_consoles_set_display(ds);
  
      if (qemu_opts_foreach(&qemu_mon_opts, mon_init_func, NULL, 1) != 0)
          exit(1);