From patchwork Fri Mar 16 09:23:45 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lee Essen X-Patchwork-Id: 147172 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 49CDDB6FDC for ; Fri, 16 Mar 2012 20:24:24 +1100 (EST) Received: from localhost ([::1]:48404 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S8TOX-0004z8-3Q for incoming@patchwork.ozlabs.org; Fri, 16 Mar 2012 05:24:21 -0400 Received: from eggs.gnu.org ([208.118.235.92]:46016) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S8TOB-0004qr-If for qemu-devel@nongnu.org; Fri, 16 Mar 2012 05:24:09 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1S8TO1-0000lm-1y for qemu-devel@nongnu.org; Fri, 16 Mar 2012 05:23:59 -0400 Received: from 204.146.238.178.in-addr.arpa ([178.238.146.204]:52740 helo=mail.local) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1S8TNz-0000lU-Vu for qemu-devel@nongnu.org; Fri, 16 Mar 2012 05:23:48 -0400 Received: from 187.146.238.178.in-addr.arpa (187.146.238.178.in-addr.arpa [178.238.146.187]) by mail.local (Postfix) with ESMTPSA id 3A10D4D21; Fri, 16 Mar 2012 09:23:46 +0000 (UTC) From: Lee Essen Date: Fri, 16 Mar 2012 09:23:45 +0000 Message-Id: To: qemu-devel@nongnu.org Mime-Version: 1.0 (Apple Message framework v1251.1) X-Mailer: Apple Mail (2.1251.1) X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 178.238.146.204 Cc: =?iso-8859-1?Q?Andreas_F=E4rber?= Subject: [Qemu-devel] [PATCH] Initial support for Ilumos build and Illumos-kvm X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org This fixes a number of issues with the build process (namely ensuring the use of bash), adds specific support for the Illumos port of KVM and fixes a few general Solaris compatibility issues. There are still some things outstanding: - there's a duplicate smb_wmb() definition in qemu-barrier.h and the illumos kvm_x86.h which generates some warnings. - there's a repeated call to page_size() that should probably be fixed. - dtrace support needs to be fixed (-m64/32 option, reserved words and linking issues) - vnics need to be added - the original illumos code added another timer source (multiticks) - the issue with Linux needs to be resolved Other than that, this gets it to the point where it will build and run with illumos kvm, and works fine for Windows. It's my first patch to qemu, and most of the real kvm stuff has come from the original illumos-kvm-cmd tree, so be gentle with me! Signed-off-by: Lee Essen --- Makefile.objs | 6 +- Makefile.target | 6 +- configure | 8 +++- cpus.c | 4 +- exec.c | 88 ++++++++++++++++++++++++++++++++++++++++++++ fpu/softfloat-specialize.h | 4 ++ hw/kvm/clock.c | 4 ++ kvm-all.c | 81 ++++++++++++++++++++++++++++++++++++++++- kvm.h | 15 +++++++ qemu-timer.c | 10 ++-- qga/channel-posix.c | 16 ++++++++ qga/commands-posix.c | 9 ++++ target-i386/hyperv.h | 4 ++ target-i386/kvm.c | 53 +++++++++++++++++++++++++- 14 files changed, 291 insertions(+), 17 deletions(-) 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-" 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 +#else #include #include +#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 #include +#ifdef __sun__ +#include +#else #include +#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 +/* + * 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 #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 +#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 +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 +#else #include #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 #include +#ifdef __sun__ +#include +#else #include #include +#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;