diff --git a/Makefile.objs b/Makefile.objs
index 226b01d..c2a440a 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -373,12 +373,12 @@ else
 trace.h: trace.h-timestamp
 endif
 trace.h-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak
-       $(call quiet-command,sh $(SRC_PATH)/scripts/tracetool --$(TRACE_BACKEND) -h < $< > $@,"  GEN   trace.h")
+       $(call quiet-command,$(SHELL) $(SRC_PATH)/scripts/tracetool --$(TRACE_BACKEND) -h < $< > $@,"  GEN   trace.h")
        @cmp -s $@ trace.h || cp $@ trace.h
 
 trace.c: trace.c-timestamp
 trace.c-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak
-       $(call quiet-command,sh $(SRC_PATH)/scripts/tracetool --$(TRACE_BACKEND) -c < $< > $@,"  GEN   trace.c")
+       $(call quiet-command,$(SHELL) $(SRC_PATH)/scripts/tracetool --$(TRACE_BACKEND) -c < $< > $@,"  GEN   trace.c")
        @cmp -s $@ trace.c || cp $@ trace.c
 
 trace.o: trace.c $(GENERATED_HEADERS)
@@ -391,7 +391,7 @@ trace-dtrace.h: trace-dtrace.dtrace
 # rule file. So we use '.dtrace' instead
 trace-dtrace.dtrace: trace-dtrace.dtrace-timestamp
 trace-dtrace.dtrace-timestamp: $(SRC_PATH)/trace-events $(BUILD_DIR)/config-host.mak
-       $(call quiet-command,sh $(SRC_PATH)/scripts/tracetool --$(TRACE_BACKEND) -d < $< > $@,"  GEN   trace-dtrace.dtrace")
+       $(call quiet-command,$(SHELL) $(SRC_PATH)/scripts/tracetool --$(TRACE_BACKEND) -d < $< > $@,"  GEN   trace-dtrace.dtrace")
        @cmp -s $@ trace-dtrace.dtrace || cp $@ trace-dtrace.dtrace
 
 trace-dtrace.o: trace-dtrace.dtrace $(GENERATED_HEADERS)
diff --git a/Makefile.target b/Makefile.target
index eb25941..d32afc9 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -59,7 +59,7 @@ TARGET_TYPE=system
 endif
 
 $(QEMU_PROG).stp:
-       $(call quiet-command,sh $(SRC_PATH)/scripts/tracetool \
+       $(call quiet-command,$(SHELL) $(SRC_PATH)/scripts/tracetool \
                --$(TRACE_BACKEND) \
                --binary $(bindir)/$(QEMU_PROG) \
                --target-arch $(TARGET_ARCH) \
@@ -443,10 +443,10 @@ gdbstub-xml.c: $(TARGET_XML_FILES) $(SRC_PATH)/scripts/feature_to_c.sh
        $(call quiet-command,rm -f $@ && $(SHELL) $(SRC_PATH)/scripts/feature_to_c.sh $@ $(TARGET_XML_FILES),"  GEN   $(TARGET_DIR)$@")
 
 hmp-commands.h: $(SRC_PATH)/hmp-commands.hx
-       $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@,"  GEN   $(TARGET_DIR)$@")
+       $(call quiet-command,$(SHELL) $(SRC_PATH)/scripts/hxtool -h < $< > $@,"  GEN   $(TARGET_DIR)$@")
 
 qmp-commands-old.h: $(SRC_PATH)/qmp-commands.hx
-       $(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@,"  GEN   $(TARGET_DIR)$@")
+       $(call quiet-command,$(SHELL) $(SRC_PATH)/scripts/hxtool -h < $< > $@,"  GEN   $(TARGET_DIR)$@")
 
 clean:
        rm -f *.o *.a *~ $(PROGS) nwfpe/*.o fpu/*.o
diff --git a/configure b/configure
index afe7395..601f77a 100755
--- a/configure
+++ b/configure
@@ -101,6 +101,7 @@ audio_win_int=""
 cc_i386=i386-pc-linux-gnu-gcc
 libs_qga=""
 debug_info="yes"
+shell="sh"
 
 target_list=""
 
@@ -442,6 +443,7 @@ SunOS)
   # have to select again, because `uname -m` returns i86pc
   # even on an x86_64 box.
   solariscpu=`isainfo -k`
+  shell="bash"
   if test "${solariscpu}" = "amd64" ; then
     cpu="x86_64"
   fi
@@ -471,6 +473,7 @@ SunOS)
   QEMU_CFLAGS="-D__EXTENSIONS__ $QEMU_CFLAGS"
   QEMU_CFLAGS="-std=gnu99 $QEMU_CFLAGS"
   LIBS="-lsocket -lnsl -lresolv $LIBS"
+  libs_qga="-lsocket -lxnet $lib_qga"
 ;;
 AIX)
   aix="yes"
@@ -1097,7 +1100,7 @@ echo "  --disable-docs           disable documentation build"
 echo "  --disable-vhost-net      disable vhost-net acceleration support"
 echo "  --enable-vhost-net       enable vhost-net acceleration support"
 echo "  --enable-trace-backend=B Set trace backend"
-echo "                           Available backends:" $("$source_path"/scripts/tracetool --list-backends)
+echo "                           Available backends:" $($shell "$source_path"/scripts/tracetool --list-backends)
 echo "  --with-trace-file=NAME   Full PATH,NAME of file to store traces"
 echo "                           Default:trace-<pid>"
 echo "  --disable-spice          disable spice"
@@ -2654,7 +2657,7 @@ fi
 ##########################################
 # check if trace backend exists
 
-sh "$source_path/scripts/tracetool" "--$trace_backend" --check-backend > /dev/null 2> /dev/null
+$shell "$source_path/scripts/tracetool" "--$trace_backend" --check-backend > /dev/null 2> /dev/null
 if test "$?" -ne 0 ; then
   echo
   echo "Error: invalid trace backend"
@@ -3358,6 +3361,7 @@ echo "LIBS+=$LIBS" >> $config_host_mak
 echo "LIBS_TOOLS+=$libs_tools" >> $config_host_mak
 echo "EXESUF=$EXESUF" >> $config_host_mak
 echo "LIBS_QGA+=$libs_qga" >> $config_host_mak
+echo "SHELL=$shell" >> $config_host_mak
 
 # generate list of library paths for linker script
 
diff --git a/cpus.c b/cpus.c
index 25ba621..7a32ee6 100644
--- a/cpus.c
+++ b/cpus.c
@@ -455,7 +455,7 @@ static void cpu_signal(int sig)
     exit_request = 1;
 }
 
-#ifdef CONFIG_LINUX
+#if defined(CONFIG_LINUX) || defined(CONFIG_SOLARIS)
 static void sigbus_reraise(void)
 {
     sigset_t set;
@@ -491,7 +491,9 @@ static void qemu_init_sigbus(void)
     action.sa_sigaction = (void (*)(int, siginfo_t*, void*))sigbus_handler;
     sigaction(SIGBUS, &action, NULL);
 
+#ifndef __sun__
     prctl(PR_MCE_KILL, PR_MCE_KILL_SET, PR_MCE_KILL_EARLY, 0, 0);
+#endif
 }
 
 static void qemu_kvm_eat_signals(CPUArchState *env)
diff --git a/exec.c b/exec.c
index 8fd50a1..57e2890 100644
--- a/exec.c
+++ b/exec.c
@@ -2853,6 +2853,79 @@ static ram_addr_t last_ram_offset(void)
     return last;
 }
 
+#ifdef CONFIG_SOLARIS
+static int
+qemu_mlock(caddr_t base, ram_addr_t size)
+{
+  /* LEE - todo */
+  qemu_real_host_page_size = getpagesize();
+
+  ram_addr_t ps = qemu_real_host_page_size, nbytes, locked = 0;
+  ram_addr_t remaining = size / ps;
+  ram_addr_t step = remaining;
+  timespec_t tv;
+  hrtime_t waiting = 0, threshold;
+
+  tv.tv_sec = 0;
+  tv.tv_nsec = NANOSEC / MILLISEC;
+  threshold = 10 * (hrtime_t)NANOSEC;
+
+  /*
+   * We cannot lock memory with a single call to mlock() because it
+   * won't result in sustained memory pressure:  if there is a
+   * substantial amount of kernel memory in use electively (e.g., for
+   * the ARC) a single call to mlock() may fail where sustained memory
+   * pressure would succeed.  We therefore start by trying to lock the
+   * entire region, adjusting our size down as we fail with EAGAIN; once
+   * we successfully lock a portion of the region, we advance to the
+   * unlocked portion of the region (if any remains) and increase the
+   * size.  Note that this will continue to hoard memory until it locks
+   * what it needs -- it won't give up.  To help debug situations in
+   * which one has mistakenly overprovisioned, we emit a message every
+   * ten seconds with no forward progress.
+   */
+  while (remaining) {
+    if (step > remaining) {
+        step = remaining;
+    }
+
+    while (mlock(base, (nbytes = step * ps)) == -1) {
+        if (errno != EAGAIN) {
+            return -1;
+        }
+
+        if (waiting == 0) {
+            waiting = gethrtime();
+        }
+
+        if (step > 1) {
+            step >>= 1;
+            continue;
+        }
+
+        (void) nanosleep(&tv, NULL);
+
+        if (gethrtime() - waiting > threshold) {
+            (void) fprintf(stderr, "qemu_mlock: have only "
+              "locked %ld of %ld bytes; still "
+              "trying...\n", locked, size);
+            waiting = 0;
+        }
+    }
+
+    waiting = 0;
+    base += nbytes;
+    locked += nbytes;
+    remaining -= step;
+
+    step <<= 1;
+  }
+
+  return 0;
+}
+#endif
+
+
 void qemu_ram_set_idstr(ram_addr_t addr, const char *name, DeviceState *dev)
 {
     RAMBlock *new_block, *block;
@@ -2931,6 +3004,21 @@ ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host,
                 new_block->host = qemu_vmalloc(size);
             }
 #endif
+
+#ifdef CONFIG_SOLARIS
+            /*
+              * XXX For right now, we'll lock down the memory.  This needs
+              * to be revisited if we implement mmu notifiers in the kernel.
+              * Note also that pages are touched in kvm_set_user_memory_region.
+              */
+            if (qemu_mlock((caddr_t)new_block->host, size) != 0) {
+                fprintf(stderr, "qemu_ram_alloc: Could not lock %ld memory,"
+                    " errno = %d\n",
+                    size, errno);
+                exit(1);
+            }
+#endif /*CONFIG_SOLARIS*/
+
             qemu_madvise(new_block->host, size, QEMU_MADV_MERGEABLE);
         }
     }
diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index c5e2dab..3889041 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -89,8 +89,10 @@ const float64 float64_default_nan = const_float64(LIT64( 0xFFF8000000000000 ));
 #define floatx80_default_nan_low  LIT64( 0xC000000000000000 )
 #endif
 
+#ifndef __sun__
 const floatx80 floatx80_default_nan = make_floatx80(floatx80_default_nan_high,
                                                     floatx80_default_nan_low);
+#endif
 
 /*----------------------------------------------------------------------------
 | The pattern for a default generated quadruple-precision NaN.  The `high' and
@@ -104,8 +106,10 @@ const floatx80 floatx80_default_nan = make_floatx80(floatx80_default_nan_high,
 #define float128_default_nan_low  LIT64( 0x0000000000000000 )
 #endif
 
+#ifndef __sun__
 const float128 float128_default_nan = make_float128(float128_default_nan_high,
                                                     float128_default_nan_low);
+#endif
 
 /*----------------------------------------------------------------------------
 | Raises the exceptions specified by `flags'.  Floating-point traps can be
diff --git a/hw/kvm/clock.c b/hw/kvm/clock.c
index 446bd62..3fd5e1e 100644
--- a/hw/kvm/clock.c
+++ b/hw/kvm/clock.c
@@ -19,8 +19,12 @@
 #include "hw/sysbus.h"
 #include "hw/kvm/clock.h"
 
+#ifdef __sun__
+#include <sys/kvm.h>
+#else
 #include <linux/kvm.h>
 #include <linux/kvm_para.h>
+#endif
 
 typedef struct KVMClockState {
     SysBusDevice busdev;
diff --git a/kvm-all.c b/kvm-all.c
index 42e5e23..27f3177 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -18,7 +18,11 @@
 #include <sys/mman.h>
 #include <stdarg.h>
 
+#ifdef __sun__
+#include <sys/kvm.h>
+#else
 #include <linux/kvm.h>
+#endif
 
 #include "qemu-common.h"
 #include "qemu-barrier.h"
@@ -176,12 +180,23 @@ int kvm_physical_memory_addr_from_host(KVMState *s, void *ram,
 static int kvm_set_user_memory_region(KVMState *s, KVMSlot *slot)
 {
     struct kvm_userspace_memory_region mem;
+#ifdef CONFIG_SOLARIS
+    caddr_t p;
+    char c;
+#endif
 
     mem.slot = slot->slot;
     mem.guest_phys_addr = slot->start_addr;
     mem.memory_size = slot->memory_size;
     mem.userspace_addr = (unsigned long)slot->ram;
     mem.flags = slot->flags;
+#ifdef CONFIG_SOLARIS
+    for (p = (caddr_t)mem.userspace_addr;
+      p < (caddr_t)mem.userspace_addr + mem.memory_size;
+      p += PAGE_SIZE)
+        c = *p;
+#endif /* CONFIG_SOLARIS */
+
     if (s->migration_log) {
         mem.flags |= KVM_MEM_LOG_DIRTY_PAGES;
     }
@@ -200,6 +215,31 @@ int kvm_pit_in_kernel(void)
     return kvm_state->pit_in_kernel;
 }
 
+#ifdef CONFIG_SOLARIS
+static int kvm_vm_clone(KVMState *s)
+{
+    struct stat stat;
+    int fd;
+
+    if (fstat(s->fd, &stat) != 0) {
+        return -errno;
+    }
+
+    fd = qemu_open("/dev/kvm", O_RDWR);
+
+    if (fd == -1) {
+        return -errno;
+    }
+
+    if (ioctl(fd, KVM_CLONE, stat.st_rdev) == -1) {
+        close(fd);
+        return -errno;
+    }
+
+    return fd;
+}
+#endif
+
 int kvm_init_vcpu(CPUArchState *env)
 {
     KVMState *s = kvm_state;
@@ -208,14 +248,29 @@ int kvm_init_vcpu(CPUArchState *env)
 
     DPRINTF("kvm_init_vcpu\n");
 
+#ifdef CONFIG_SOLARIS
+    ret = kvm_vm_clone(kvm_state);
+
+    if (ret < 0) {
+        fprintf(stderr, "kvm_init_vcpu could not clone fd: %m\n");
+        goto err;
+    }
+    env->kvm_fd = ret;
+    env->kvm_state = kvm_state;
+
+    ret = ioctl(env->kvm_fd, KVM_CREATE_VCPU, env->cpu_index);
+#else
     ret = kvm_vm_ioctl(s, KVM_CREATE_VCPU, env->cpu_index);
+#endif
     if (ret < 0) {
         DPRINTF("kvm_create_vcpu failed\n");
         goto err;
     }
 
+#ifndef CONFIG_SOLARIS
     env->kvm_fd = ret;
     env->kvm_state = s;
+#endif
     env->kvm_vcpu_dirty = 1;
 
     mmap_size = kvm_ioctl(s, KVM_GET_VCPU_MMAP_SIZE, 0);
@@ -1021,6 +1076,9 @@ int kvm_init(void)
         ret = s->vmfd;
         goto err;
     }
+#ifdef CONFIG_SOLARIS
+    s->vmfd = s->fd;
+#endif
 
     missing_cap = kvm_check_extension_list(s, kvm_required_capabilites);
     if (!missing_cap) {
@@ -1287,6 +1345,19 @@ int kvm_cpu_exec(CPUArchState *env)
             DPRINTF("irq_window_open\n");
             ret = EXCP_INTERRUPT;
             break;
+#ifdef CONFIG_SOLARIS
+        /*
+         * In the case of an external interrupt we can get a zero
+         * return from the ioctl, with a KVM_EXIT_INTR. This doesn't
+         * happen on linux
+         *
+         * Not entirely sure what to do here.
+         */
+        case KVM_EXIT_INTR:
+            DPRINTF("exit_intr (run_ret is %d)\n", run_ret);
+            ret = EXCP_INTERRUPT;
+            break;
+#endif
         case KVM_EXIT_SHUTDOWN:
             DPRINTF("shutdown\n");
             qemu_system_reset_request();
@@ -1631,7 +1702,7 @@ int kvm_set_signal_mask(CPUArchState *env, const sigset_t *sigset)
 
     sigmask = g_malloc(sizeof(*sigmask) + sizeof(*sigset));
 
-    sigmask->len = 8;
+    sigmask->len = sizeof(sigset_t);
     memcpy(sigmask->sigset, sigset, sizeof(*sigset));
     r = kvm_vcpu_ioctl(env, KVM_SET_SIGNAL_MASK, sigmask);
     g_free(sigmask);
@@ -1641,6 +1712,7 @@ int kvm_set_signal_mask(CPUArchState *env, const sigset_t *sigset)
 
 int kvm_set_ioeventfd_mmio_long(int fd, uint32_t addr, uint32_t val, bool assign)
 {
+#ifdef CONFIG_EVENTFD
     int ret;
     struct kvm_ioeventfd iofd;
 
@@ -1665,10 +1737,14 @@ int kvm_set_ioeventfd_mmio_long(int fd, uint32_t addr, uint32_t val, bool assign
     }
 
     return 0;
+#else
+    return -ENOSYS;
+#endif
 }
 
 int kvm_set_ioeventfd_pio_word(int fd, uint16_t addr, uint16_t val, bool assign)
 {
+#ifdef CONFIG_EVENTFD
     struct kvm_ioeventfd kick = {
         .datamatch = val,
         .addr = addr,
@@ -1688,6 +1764,9 @@ int kvm_set_ioeventfd_pio_word(int fd, uint16_t addr, uint16_t val, bool assign)
         return r;
     }
     return 0;
+#else
+    return -ENOSYS;
+#endif
 }
 
 int kvm_on_sigbus_vcpu(CPUArchState *env, int code, void *addr)
diff --git a/kvm.h b/kvm.h
index 330f17b..8960b4e 100644
--- a/kvm.h
+++ b/kvm.h
@@ -19,8 +19,23 @@
 #include "qemu-queue.h"
 
 #ifdef CONFIG_KVM
+#ifdef __sun__
+#include <sys/kvm.h>
+/*
+ * it's a bit horrible to include these here, but the kvm_para.h include file
+ * isn't public with the illumos kvm implementation
+ */
+#define KVM_CPUID_SIGNATURE       0x40000000
+#define KVM_CPUID_FEATURES        0x40000001
+#define KVM_FEATURE_CLOCKSOURCE   0
+#define KVM_FEATURE_NOP_IO_DELAY  1
+#define KVM_FEATURE_MMU_OP        2
+#define KVM_FEATURE_CLOCKSOURCE2  3
+#define HYPERV_CPUID_MIN          0x40000005
+#else
 #include <linux/kvm.h>
 #endif
+#endif
 
 extern int kvm_allowed;
 extern bool kvm_kernel_irqchip;
diff --git a/qemu-timer.c b/qemu-timer.c
index d7f56e5..f35ad4e 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -77,7 +77,7 @@ struct qemu_alarm_timer {
     int (*start)(struct qemu_alarm_timer *t);
     void (*stop)(struct qemu_alarm_timer *t);
     void (*rearm)(struct qemu_alarm_timer *t, int64_t nearest_delta_ns);
-#if defined(__linux__)
+#if defined(__linux__) || defined(__sun__)
     int fd;
     timer_t timer;
 #elif defined(_WIN32)
@@ -165,7 +165,7 @@ static int unix_start_timer(struct qemu_alarm_timer *t);
 static void unix_stop_timer(struct qemu_alarm_timer *t);
 static void unix_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
 
-#ifdef __linux__
+#if defined(__linux__) || defined(__sun__)
 
 static int dynticks_start_timer(struct qemu_alarm_timer *t);
 static void dynticks_stop_timer(struct qemu_alarm_timer *t);
@@ -177,7 +177,7 @@ static void dynticks_rearm_timer(struct qemu_alarm_timer *t, int64_t delta);
 
 static struct qemu_alarm_timer alarm_timers[] = {
 #ifndef _WIN32
-#ifdef __linux__
+#if defined(__linux__) || defined(__sun__)
     {"dynticks", dynticks_start_timer,
      dynticks_stop_timer, dynticks_rearm_timer},
 #endif
@@ -502,7 +502,7 @@ static void host_alarm_handler(int host_signum)
     }
 }
 
-#if defined(__linux__)
+#if defined(__linux__) || defined(__sun__)
 
 #include "compatfd.h"
 
@@ -585,7 +585,7 @@ static void dynticks_rearm_timer(struct qemu_alarm_timer *t,
     }
 }
 
-#endif /* defined(__linux__) */
+#endif /* defined(__linux__) || defined(__sun__) */
 
 #if !defined(_WIN32)
 
diff --git a/qga/channel-posix.c b/qga/channel-posix.c
index 40f7658..86245c1 100644
--- a/qga/channel-posix.c
+++ b/qga/channel-posix.c
@@ -3,6 +3,10 @@
 #include "qemu_socket.h"
 #include "qga/channel.h"
 
+#ifdef CONFIG_SOLARIS
+#include <sys/stropts.h>
+#endif
+
 #define GA_CHANNEL_BAUDRATE_DEFAULT B38400 /* for isa-serial channels */
 
 struct GAChannel {
@@ -123,7 +127,19 @@ static gboolean ga_channel_open(GAChannel *c, const gchar *path, GAChannelMethod
 
     switch (c->method) {
     case GA_CHANNEL_VIRTIO_SERIAL: {
+#ifdef CONFIG_SOLARIS
+        int fd = qemu_open(path, O_RDWR | O_NONBLOCK);
+        if (fd == -1) {
+            g_critical("error opening channel: %s", strerror(errno));
+            exit(EXIT_FAILURE);
+        }
+        if (ioctl(fd, I_SETSIG, S_OUTPUT | S_INPUT | S_HIPRI) < 0) {
+            g_critical("error with setsig on channel: %s", strerror(errno));
+            exit(EXIT_FAILURE);
+        }
+#else
         int fd = qemu_open(path, O_RDWR | O_NONBLOCK | O_ASYNC);
+#endif
         if (fd == -1) {
             g_critical("error opening channel: %s", strerror(errno));
             exit(EXIT_FAILURE);
diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index 7b2be2f..67531aa 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -35,6 +35,11 @@
 #include "qemu-queue.h"
 #include "host-utils.h"
 
+#if defined(__sun__)
+#include <sys/sockio.h>
+extern char **environ;
+#endif
+
 static void reopen_fd_to_null(int fd)
 {
     int nullfd;
@@ -807,7 +812,11 @@ GuestNetworkInterfaceList *qmp_guest_network_get_interfaces(Error **errp)
                 goto error;
             }
 
+#if defined(__sun__)
+            mac_addr = (unsigned char *) &ifr.ifr_enaddr;
+#else
             mac_addr = (unsigned char *) &ifr.ifr_hwaddr.sa_data;
+#endif
 
             if (asprintf(&info->value->hardware_address,
                          "%02x:%02x:%02x:%02x:%02x:%02x",
diff --git a/target-i386/hyperv.h b/target-i386/hyperv.h
index bacb1d4..9c08750 100644
--- a/target-i386/hyperv.h
+++ b/target-i386/hyperv.h
@@ -15,8 +15,12 @@
 
 #include "qemu-common.h"
 #ifdef CONFIG_KVM
+#ifdef __sun__
+#include <hyperv.h>
+#else
 #include <asm/hyperv.h>
 #endif
+#endif
 
 #ifndef HYPERV_SPINLOCK_NEVER_RETRY
 #define HYPERV_SPINLOCK_NEVER_RETRY             0xFFFFFFFF
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index e74a9e4..6d007cc 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -17,8 +17,12 @@
 #include <sys/mman.h>
 #include <sys/utsname.h>
 
+#ifdef __sun__
+#include <sys/kvm.h>
+#else
 #include <linux/kvm.h>
 #include <linux/kvm_para.h>
+#endif
 
 #include "qemu-common.h"
 #include "sysemu.h"
@@ -61,7 +65,9 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
 static bool has_msr_star;
 static bool has_msr_hsave_pa;
 static bool has_msr_tsc_deadline;
+#ifdef KVM_CAP_ASYNC_PF
 static bool has_msr_async_pf_en;
+#endif
 static bool has_msr_misc_enable;
 static int lm_capable_kernel;
 
@@ -97,7 +103,9 @@ struct kvm_para_features {
     { KVM_CAP_CLOCKSOURCE, KVM_FEATURE_CLOCKSOURCE },
     { KVM_CAP_NOP_IO_DELAY, KVM_FEATURE_NOP_IO_DELAY },
     { KVM_CAP_PV_MMU, KVM_FEATURE_MMU_OP },
+#ifdef KVM_CAP_ASYNC_PF
     { KVM_CAP_ASYNC_PF, KVM_FEATURE_ASYNC_PF },
+#endif
     { -1, -1 }
 };
 
@@ -442,7 +450,9 @@ int kvm_arch_init_vcpu(CPUX86State *env)
         c->edx = signature[2];
     }
 
+#ifdef KVM_CAP_ASYNC_PF
     has_msr_async_pf_en = c->eax & (1 << KVM_FEATURE_ASYNC_PF);
+#endif
 
     cpu_x86_cpuid(env, 0, 0, &limit, &unused, &unused, &unused);
 
@@ -561,6 +571,7 @@ int kvm_arch_init_vcpu(CPUX86State *env)
         return r;
     }
 
+#ifdef KVM_CAP_TSC_CONTROL
     r = kvm_check_extension(env->kvm_state, KVM_CAP_TSC_CONTROL);
     if (r && env->tsc_khz) {
         r = kvm_vcpu_ioctl(env, KVM_SET_TSC_KHZ, env->tsc_khz);
@@ -569,10 +580,12 @@ int kvm_arch_init_vcpu(CPUX86State *env)
             return r;
         }
     }
-
+#endif
+#ifdef KVM_CAP_XSAVE
     if (kvm_has_xsave()) {
         env->kvm_xsave_buf = qemu_memalign(4096, sizeof(struct kvm_xsave));
     }
+#endif
 
     return 0;
 }
@@ -759,7 +772,7 @@ static void get_seg(SegmentCache *lhs, const struct kvm_segment *rhs)
                  (rhs->avl * DESC_AVL_MASK);
 }
 
-static void kvm_getput_reg(__u64 *kvm_reg, target_ulong *qemu_reg, int set)
+static void kvm_getput_reg(uint64_t *kvm_reg, target_ulong *qemu_reg, int set)
 {
     if (set) {
         *kvm_reg = *qemu_reg;
@@ -841,6 +854,7 @@ static int kvm_put_fpu(CPUX86State *env)
 #define XSAVE_XSTATE_BV   128
 #define XSAVE_YMMH_SPACE  144
 
+#ifdef KVM_CAP_XSAVE
 static int kvm_put_xsave(CPUX86State *env)
 {
     struct kvm_xsave* xsave = env->kvm_xsave_buf;
@@ -874,7 +888,9 @@ static int kvm_put_xsave(CPUX86State *env)
     r = kvm_vcpu_ioctl(env, KVM_SET_XSAVE, xsave);
     return r;
 }
+#endif
 
+#ifdef KVM_CAP_XSCRS
 static int kvm_put_xcrs(CPUX86State *env)
 {
     struct kvm_xcrs xcrs;
@@ -889,6 +905,7 @@ static int kvm_put_xcrs(CPUX86State *env)
     xcrs.xcrs[0].value = env->xcr0;
     return kvm_vcpu_ioctl(env, KVM_SET_XCRS, &xcrs);
 }
+#endif
 
 static int kvm_put_sregs(CPUX86State *env)
 {
@@ -1000,10 +1017,12 @@ static int kvm_put_msrs(CPUX86State *env, int level)
         kvm_msr_entry_set(&msrs[n++], MSR_KVM_SYSTEM_TIME,
                           env->system_time_msr);
         kvm_msr_entry_set(&msrs[n++], MSR_KVM_WALL_CLOCK, env->wall_clock_msr);
+#ifdef KVM_CAP_ASYNC_PF
         if (has_msr_async_pf_en) {
             kvm_msr_entry_set(&msrs[n++], MSR_KVM_ASYNC_PF_EN,
                               env->async_pf_en_msr);
         }
+#endif
         if (hyperv_hypercall_available()) {
             kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_GUEST_OS_ID, 0);
             kvm_msr_entry_set(&msrs[n++], HV_X64_MSR_HYPERCALL, 0);
@@ -1055,6 +1074,7 @@ static int kvm_get_fpu(CPUX86State *env)
     return 0;
 }
 
+#ifdef KVM_CAP_XSAVE
 static int kvm_get_xsave(CPUX86State *env)
 {
     struct kvm_xsave* xsave = env->kvm_xsave_buf;
@@ -1092,7 +1112,9 @@ static int kvm_get_xsave(CPUX86State *env)
             sizeof env->ymmh_regs);
     return 0;
 }
+#endif
 
+#ifdef KVM_CAP_XCRS
 static int kvm_get_xcrs(CPUX86State *env)
 {
     int i, ret;
@@ -1116,6 +1138,7 @@ static int kvm_get_xcrs(CPUX86State *env)
     }
     return 0;
 }
+#endif
 
 static int kvm_get_sregs(CPUX86State *env)
 {
@@ -1243,9 +1266,11 @@ static int kvm_get_msrs(CPUX86State *env)
 #endif
     msrs[n++].index = MSR_KVM_SYSTEM_TIME;
     msrs[n++].index = MSR_KVM_WALL_CLOCK;
+#ifdef KVM_CAP_ASYNC_PF
     if (has_msr_async_pf_en) {
         msrs[n++].index = MSR_KVM_ASYNC_PF_EN;
     }
+#endif
 
     if (env->mcg_cap) {
         msrs[n++].index = MSR_MCG_STATUS;
@@ -1322,9 +1347,11 @@ static int kvm_get_msrs(CPUX86State *env)
                 env->mce_banks[msrs[i].index - MSR_MC0_CTL] = msrs[i].data;
             }
             break;
+#ifdef KVM_CAP_ASYNC_PF
         case MSR_KVM_ASYNC_PF_EN:
             env->async_pf_en_msr = msrs[i].data;
             break;
+#endif
         }
     }
 
@@ -1482,6 +1509,7 @@ static int kvm_guest_debug_workarounds(CPUX86State *env)
     return ret;
 }
 
+#ifdef KVM_CAP_DEBUGREGS
 static int kvm_put_debugregs(CPUX86State *env)
 {
     struct kvm_debugregs dbgregs;
@@ -1522,6 +1550,7 @@ static int kvm_get_debugregs(CPUX86State *env)
 
     return 0;
 }
+#endif
 
 int kvm_arch_put_registers(CPUX86State *env, int level)
 {
@@ -1533,14 +1562,20 @@ int kvm_arch_put_registers(CPUX86State *env, int level)
     if (ret < 0) {
         return ret;
     }
+#ifdef KVM_CAP_XSAVE
     ret = kvm_put_xsave(env);
+#else
+    ret = kvm_put_fpu(env);
+#endif
     if (ret < 0) {
         return ret;
     }
+#ifdef KVM_CAP_XCRS
     ret = kvm_put_xcrs(env);
     if (ret < 0) {
         return ret;
     }
+#endif
     ret = kvm_put_sregs(env);
     if (ret < 0) {
         return ret;
@@ -1568,10 +1603,12 @@ int kvm_arch_put_registers(CPUX86State *env, int level)
     if (ret < 0) {
         return ret;
     }
+#ifdef KVM_CAP_DEBUGREGS
     ret = kvm_put_debugregs(env);
     if (ret < 0) {
         return ret;
     }
+#endif
     /* must be last */
     ret = kvm_guest_debug_workarounds(env);
     if (ret < 0) {
@@ -1590,14 +1627,20 @@ int kvm_arch_get_registers(CPUX86State *env)
     if (ret < 0) {
         return ret;
     }
+#ifdef KVM_CAP_XSAVE
     ret = kvm_get_xsave(env);
+#else
+    ret = kvm_get_fpu(env);
+#endif
     if (ret < 0) {
         return ret;
     }
+#ifdef KVM_CAP_XCRS
     ret = kvm_get_xcrs(env);
     if (ret < 0) {
         return ret;
     }
+#endif
     ret = kvm_get_sregs(env);
     if (ret < 0) {
         return ret;
@@ -1618,10 +1661,12 @@ int kvm_arch_get_registers(CPUX86State *env)
     if (ret < 0) {
         return ret;
     }
+#ifdef KVM_CAP_DEBUGREGS
     ret = kvm_get_debugregs(env);
     if (ret < 0) {
         return ret;
     }
+#endif
     return 0;
 }
 
@@ -1770,6 +1815,7 @@ static int kvm_handle_tpr_access(CPUX86State *env)
     return 1;
 }
 
+#ifdef KVM_CAP_SET_GUEST_DEBUG
 int kvm_arch_insert_sw_breakpoint(CPUX86State *env, struct kvm_sw_breakpoint *bp)
 {
     static const uint8_t int3 = 0xcc;
@@ -1950,6 +1996,7 @@ void kvm_arch_update_guest_debug(CPUX86State *env, struct kvm_guest_debug *dbg)
         }
     }
 }
+#endif /* KVM_CAP_SET_GUEST_DEBUG */
 
 static bool host_supports_vmx(void)
 {
@@ -1999,10 +2046,12 @@ int kvm_arch_handle_exit(CPUX86State *env, struct kvm_run *run)
                 run->ex.exception, run->ex.error_code);
         ret = -1;
         break;
+#ifdef KVM_CAP_SET_GUEST_DEBUG
     case KVM_EXIT_DEBUG:
         DPRINTF("kvm_exit_debug\n");
         ret = kvm_handle_debug(&run->debug.arch);
         break;
+#endif
     default:
         fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
         ret = -1;
