diff options
-rw-r--r-- | Makefile.objs | 8 | ||||
-rwxr-xr-x | build.sh | 36 | ||||
-rwxr-xr-x | configure | 29 | ||||
-rw-r--r-- | exec.c | 14 | ||||
-rw-r--r-- | hw/hw.h | 9 | ||||
-rw-r--r-- | hw/pc.c | 2 | ||||
-rw-r--r-- | kvm-all.c | 39 | ||||
-rw-r--r-- | kvm.h | 6 | ||||
-rw-r--r-- | net.c | 30 | ||||
-rw-r--r-- | net.h | 3 | ||||
-rw-r--r-- | net/vnic.c | 316 | ||||
-rw-r--r-- | net/vnic.h | 34 | ||||
-rw-r--r-- | qemu-kvm-x86.c | 4 | ||||
-rw-r--r-- | qemu-kvm.c | 30 | ||||
-rw-r--r-- | qemu-kvm.h | 4 | ||||
-rw-r--r-- | qemu-malloc.c | 21 | ||||
-rw-r--r-- | qemu-timer.c | 16 | ||||
-rw-r--r-- | target-i386/kvm.c | 9 |
18 files changed, 599 insertions, 11 deletions
diff --git a/Makefile.objs b/Makefile.objs index a647c45..3e841e4 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -44,8 +44,16 @@ net-nested-$(CONFIG_AIX) += tap-aix.o net-nested-$(CONFIG_HAIKU) += tap-haiku.o net-nested-$(CONFIG_SLIRP) += slirp.o net-nested-$(CONFIG_VDE) += vde.o +net-nested-$(CONFIG_SUNOS_VNIC) += vnic.o net-obj-y += $(addprefix net/, $(net-nested-y)) +# +# We need to link against libdlpi if we have CONFIG_SUNOS_VNIC +# +ifeq ($(CONFIG_SUNOS_VNIC),y) +LDFLAGS+=-ldlpi +endif + ifeq ($(CONFIG_VIRTIO)$(CONFIG_VIRTFS),yy) # Lots of the fsdev/9pcode is pulled in by vl.c via qemu_fsdev_add. # only pull in the actual virtio-9p device if we also enabled virtio. diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..e6d4b92 --- /dev/null +++ b/build.sh @@ -0,0 +1,36 @@ +#!/bin/bash +# +# Copyright (c) 2011, Joyent Inc., All rights reserved. +# + +for dir in seabios vgabios kvm/test; do + cp roms/${dir}/config.mak.tmpl roms/${dir}/config.mak +done + +# +# Temporairly removed +# +# --enable-kvm \ +# --enable-kvm-pit \ +# + +echo "==> Running configure" +./configure \ + --prefix=. \ + --audio-card-list= \ + --audio-drv-list= \ + --disable-bluez \ + --disable-brlapi \ + --disable-curl \ + --enable-debug \ + --disable-kvm-device-assignment \ + --disable-sdl \ + --disable-vnc-jpeg \ + --disable-vnc-png \ + --disable-vnc-sasl \ + --disable-vnc-tls \ + --kerneldir=$(cd `pwd`/../kvm; pwd) \ + --cpu=x86_64 + +echo "==> Make" +gmake -j10 @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # # qemu configure script (c) 2003 Fabrice Bellard # @@ -1693,8 +1693,16 @@ fi ########################################## # kvm probe if test "$kvm" != "no" ; then + if test "$targetos" = "SunOS" ; then + cat > $TMPC <<EOF +#include <sys/kvm.h> +EOF + else cat > $TMPC <<EOF #include <linux/kvm.h> +EOF + fi + cat >> $TMPC <<EOF #if !defined(KVM_API_VERSION) || KVM_API_VERSION < 12 || KVM_API_VERSION > 12 #error Invalid KVM version #endif @@ -1725,7 +1733,7 @@ EOF cat >> $TMPC <<EOF int main(void) { return 0; } EOF - if test "$kerneldir" != "" ; then + if test "$kerneldir" != "" -a "$targetos" = "Linux" ; then kvm_cflags=-I"$kerneldir"/include if test \( "$cpu" = "i386" -o "$cpu" = "x86_64" \) \ -a -d "$kerneldir/arch/x86/include" ; then @@ -1737,6 +1745,8 @@ EOF elif test -d "$kerneldir/arch/$cpu/include" ; then kvm_cflags="$kvm_cflags -I$kerneldir/arch/$cpu/include" fi + elif test "$kerneldir" != "" -a "$targetos" = "SunOS" ; then + kvm_cflags=-I"$kerneldir" else kvm_cflags=`$pkg_config --cflags kvm-kmod 2>/dev/null` if test "$kvm_cflags" = ""; then @@ -1791,8 +1801,16 @@ if test "$kvm_cap_pit" != "no" ; then if test "$kvm" = "no" -a "$kvm_cap_pit" = "yes" ; then feature_not_found "kvm_cap_pit (kvm is not enabled)" fi - cat > $TMPC <<EOF + if test "$targetos" = "SunOS" ; then + cat > $TMPC <<EOF +#include <sys/kvm.h> +EOF + else + cat > $TMPC <<EOF #include <linux/kvm.h> +EOF + fi + cat >> $TMPC <<EOF #ifndef KVM_CAP_PIT #error "kvm no pit capability" #endif @@ -1815,6 +1833,9 @@ if test "$kvm_cap_device_assignment" != "no" ; then if test "$kvm" = "no" -a "$kvm_cap_device_assignment" = "yes" ; then feature_not_found "kvm_cap_device_assignment (kvm is not enabled)" fi + if test "$targetos" = "SunOS" ; then + feature_not_found "kvm_cap_device_assignment (not supported on SunOS)" + fi cat > $TMPC <<EOF #include <linux/kvm.h> #ifndef KVM_CAP_DEVICE_ASSIGNMENT @@ -2673,6 +2694,8 @@ fi if test "$solaris" = "yes" ; then echo "CONFIG_SOLARIS=y" >> $config_host_mak echo "CONFIG_SOLARIS_VERSION=$solarisrev" >> $config_host_mak +# XXX rm needs to test / make this be a part of configure + echo "CONFIG_SUNOS_VNIC=y" >> $config_host_mak if test "$needs_libsunmath" = "yes" ; then echo "CONFIG_NEEDS_LIBSUNMATH=y" >> $config_host_mak fi @@ -2874,6 +2874,20 @@ ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name, #else 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 (mlock(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); } } @@ -350,7 +350,7 @@ extern const VMStateInfo vmstate_info_uint16; extern const VMStateInfo vmstate_info_uint32; extern const VMStateInfo vmstate_info_uint64; -#ifdef __linux__ +#if defined(__linux__) || defined(__sun__) extern const VMStateInfo vmstate_info_u64; #endif @@ -673,11 +673,16 @@ extern const VMStateDescription vmstate_usb_device; /* This is needed because on linux __u64 is unsigned long long and on glibc uint64_t is unsigned long on 64 bits */ -#ifdef __linux__ +#if defined(__linux__) #define VMSTATE_U64_V(_f, _s, _v) \ VMSTATE_SINGLE(_f, _s, _v, vmstate_info_u64, __u64) #define VMSTATE_U64(_f, _s) \ VMSTATE_U64_V(_f, _s, 0) +#else +#define VMSTATE_U64_V(_f, _s, _v) \ + VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint64, uint64_t) +#define VMSTATE_U64(_f, _s) \ + VMSTATE_U64_V(_f, _s, 0) #endif #define VMSTATE_UINT8_EQUAL(_f, _s) \ @@ -45,7 +45,7 @@ #include "ui/qemu-spice.h" /* output Bochs bios info messages */ -//#define DEBUG_BIOS +#define DEBUG_BIOS /* debug PC/ISA interrupts */ //#define DEBUG_IRQ @@ -18,7 +18,12 @@ #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" @@ -175,12 +180,23 @@ int kvm_physical_memory_addr_from_ram(KVMState *s, ram_addr_t ram_addr, 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)qemu_safe_ram_ptr(slot->phys_offset); 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; } @@ -1059,6 +1075,29 @@ int kvm_vm_ioctl(KVMState *s, int type, ...) return ret; } +#ifdef CONFIG_SOLARIS +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_vcpu_ioctl(CPUState *env, int type, ...) { int ret; @@ -22,9 +22,15 @@ #endif #ifdef CONFIG_KVM +#ifdef __sun__ +#include <sys/kvm.h> +#else #include <linux/kvm.h> #endif + +#endif + extern int kvm_allowed; #if defined CONFIG_KVM || !defined NEED_CPU_H @@ -37,6 +37,10 @@ #include "qemu_socket.h" #include "hw/qdev.h" +#ifdef CONFIG_SUNOS_VNIC +#include "net/vnic.h" +#endif + static QTAILQ_HEAD(, VLANState) vlans; static QTAILQ_HEAD(, VLANClientState) non_vlan_clients; @@ -1087,6 +1091,25 @@ static const struct { { /* end of list */ } }, #endif +#ifdef CONFIG_SUNOS_VNIC + }, { + .type = "vnic", + .init = net_init_vnic, + .desc = { + NET_COMMON_PARAMS_DESC, + { + .name = "ifname", + .type = QEMU_OPT_STRING, + .help = "vnic interface name", + }, + { + .name = "macaddr", + .type = QEMU_OPT_STRING, + .help = "MAC address", + }, + { /* end of list */ } + }, +#endif }, { .type = "dump", .init = net_init_dump, @@ -1127,6 +1150,9 @@ int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev) #ifdef CONFIG_VDE strcmp(type, "vde") != 0 && #endif +#ifdef CONFIG_SUNOS_VNIC + strcmp(type, "vnic") != 0 && +#endif strcmp(type, "socket") != 0) { qerror_report(QERR_INVALID_PARAMETER_VALUE, "type", "a netdev backend type"); @@ -1196,6 +1222,9 @@ static int net_host_check_device(const char *device) #ifdef CONFIG_VDE ,"vde" #endif +#ifdef CONFIG_SUNOS_VNIC + ,"vnic" +#endif }; for (i = 0; i < sizeof(valid_param_list) / sizeof(char *); i++) { if (!strncmp(valid_param_list[i], device, @@ -1363,6 +1392,7 @@ void net_check_clients(void) case NET_CLIENT_TYPE_TAP: case NET_CLIENT_TYPE_SOCKET: case NET_CLIENT_TYPE_VDE: + case NET_CLIENT_TYPE_VNIC: has_host_dev = 1; break; default: ; @@ -35,7 +35,8 @@ typedef enum { NET_CLIENT_TYPE_TAP, NET_CLIENT_TYPE_SOCKET, NET_CLIENT_TYPE_VDE, - NET_CLIENT_TYPE_DUMP + NET_CLIENT_TYPE_DUMP, + NET_CLIENT_TYPE_VNIC } net_client_type; typedef void (NetPoll)(VLANClientState *, bool enable); diff --git a/net/vnic.c b/net/vnic.c new file mode 100644 index 0000000..c6a7e8f --- /dev/null +++ b/net/vnic.c @@ -0,0 +1,316 @@ +/* + * QEMU System Emulator + * Solaris VNIC support + * + * Copyright (c) 2011 Joyent, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <assert.h> +#include <errno.h> +#include <libdlpi.h> +#include <string.h> +#include <stdio.h> +#include <stropts.h> +#include <unistd.h> + +#include <net/if_dl.h> +#include <sys/ethernet.h> +#include <sys/dlpi.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include "net/vnic.h" + +#include "config-host.h" +#include "qemu-common.h" +#include "qemu-error.h" +#include "qemu-option.h" +#include "qemu-char.h" + +/* + * XXX We should determine a good way to get this buffer size. 64k feels like + * such an arbitrary number... + */ +#define VNIC_BUFFSIZE 65536 + +typedef struct VNICState { + VLANClientState vns_nc; + int vns_fd; + unsigned int vns_rpoll; + unsigned int vns_wpoll; + uint8_t vns_buf[VNIC_BUFFSIZE]; + uint_t vns_sap; + dlpi_handle_t vns_hdl; +} VNICState; + +static void vnic_update_fd_handler(VNICState *); + +static void +vnic_read_poll(VNICState *vsp, int enable) +{ + vsp->vns_rpoll = enable; + vnic_update_fd_handler(vsp); +} + +static void +vnic_write_poll(VNICState *vsp, int enable) +{ + vsp->vns_wpoll = enable; + vnic_update_fd_handler(vsp); +} + +static void +vnic_poll(VLANClientState *ncp, bool enable) +{ + VNICState *vsp = DO_UPCAST(VNICState, vns_nc, ncp); + vnic_read_poll(vsp, 1); + vnic_write_poll(vsp, 1); +} + +static int +vnic_read_packet(VNICState *vsp, uint8_t *buf, int len) +{ + struct strbuf sbuf; + int flags, ret; + + flags = 0; + sbuf.maxlen = len; + sbuf.buf = (char *)buf; + + do { + ret = getmsg(vsp->vns_fd, NULL, &sbuf, &flags); + } while (ret == -1 && errno == EINTR); + + if (ret == -1 && errno == EAGAIN) { + vnic_write_poll(vsp, 1); + return (0); + } + + if (ret == -1) { + return (-1); + } + + return (sbuf.len); +} + +static int +vnic_write_packet(VNICState *vsp, const uint8_t *buf, int len) +{ + struct strbuf sbuf; + int flags, ret; + + flags = 0; + sbuf.len = len; + sbuf.buf = (char *)buf; + + do { + ret = putmsg(vsp->vns_fd, NULL, &sbuf, flags); + } while (ret == -1 && errno == EINTR); + + if (ret == -1 && errno == EAGAIN) { + vnic_write_poll(vsp, 1); + return (0); + } + + if (ret == -1) + return (-1); + + return (len); +} + +static int +vnic_can_send(void *opaque) +{ + VNICState *vsp = opaque; + return (qemu_can_send_packet(&vsp->vns_nc)); +} + +static void +vnic_send_completed(VLANClientState *nc, ssize_t len) +{ + VNICState *vsp = DO_UPCAST(VNICState, vns_nc, nc); + vnic_read_poll(vsp, 1); +} + +static void +vnic_send(void *opaque) +{ + VNICState *vsp = opaque; + int ret; + + do { + ret = vnic_read_packet(vsp, vsp->vns_buf, + sizeof (vsp->vns_buf)); + if (ret <= 0) + break; + + ret = qemu_send_packet_async(&vsp->vns_nc, vsp->vns_buf, ret, + vnic_send_completed); + + if (ret == 0) + vnic_read_poll(vsp, 0); + + } while (ret > 0 && qemu_can_send_packet(&vsp->vns_nc)); +} + +static void +vnic_writable(void *opaque) +{ + VNICState *vsp = opaque; + vnic_write_poll(vsp, 0); + qemu_flush_queued_packets(&vsp->vns_nc); +} + +static ssize_t +vnic_receive(VLANClientState *ncp, const uint8_t *buf, size_t size) +{ + VNICState *vsp = DO_UPCAST(VNICState, vns_nc, ncp); + + return (vnic_write_packet(vsp, buf, size)); +} + +static void +vnic_cleanup(VLANClientState *ncp) +{ + VNICState *vsp; + + vsp = DO_UPCAST(VNICState, vns_nc, ncp); + + qemu_purge_queued_packets(ncp); + + dlpi_close(vsp->vns_hdl); +} + +static void +vnic_update_fd_handler(VNICState *vsp) +{ + qemu_set_fd_handler2(vsp->vns_fd, + vsp->vns_rpoll ? vnic_can_send : NULL, + vsp->vns_rpoll ? vnic_send : NULL, + vsp->vns_wpoll ? vnic_writable : NULL, + vsp); +} + +static NetClientInfo net_vnic_info = { + .type = NET_CLIENT_TYPE_VNIC, + .size = sizeof (VNICState), + .receive = vnic_receive, + .poll = vnic_poll, + .cleanup = vnic_cleanup +}; + +static int +net_init_kvm(int vfd) +{ + int kfd; + + if ((kfd = open("/dev/kvm", O_RDWR)) < 0) { + error_report("can't open /dev/kvm for vnic: %s\n", + strerror(errno)); + return (-1); + } + + /* XXX We shouldn't be embedding the KVM_NET_QUEUE fd */ + if (ioctl(kfd, 0x2000ae21, vfd) < 0) { + error_report("can't ioctl: %s\n", strerror(errno)); + return (-1); + } + + (void) close(kfd); + + return (0); +} + +int +net_init_vnic(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan) +{ + int fd, len; + const char *ifname, *mac; + uchar_t *macaddr; + VLANClientState *ncp; + VNICState *vsp; + + if ((ifname = qemu_opt_get(opts, "ifname")) == NULL) { + error_report("missing ifname required for vnic\n"); + return (-1); + } + + if ((mac = qemu_opt_get(opts, "macaddr")) == NULL) { + error_report("missing macaddr required for vnic\n"); + return (-1); + } + + macaddr = _link_aton(mac, &len); + if (macaddr == NULL || len != ETHERADDRL) { + error_report("invalid macaddr for vnic: %s\n", mac); + return (-1); + } + + ncp = qemu_new_net_client(&net_vnic_info, vlan, NULL, "vnic", name); + vsp = DO_UPCAST(VNICState, vns_nc, ncp); + + if (dlpi_open(ifname, &vsp->vns_hdl, DLPI_RAW) != DLPI_SUCCESS) { + error_report("vnic: failed to open interface %s", ifname); + return (-1); + } + + if (dlpi_bind(vsp->vns_hdl, DLPI_ANY_SAP, &vsp->vns_sap) != DLPI_SUCCESS) { + error_report("vnic: failed to bind interface %s", ifname); + return (-1); + } + + assert(len == ETHERADDRL); + if (dlpi_set_physaddr(vsp->vns_hdl, DL_CURR_PHYS_ADDR, macaddr, + ETHERADDRL) != DLPI_SUCCESS) { + error_report("vnic: failed to set mac address\n"); + return (-1); + } + + if (dlpi_promiscon(vsp->vns_hdl, DL_PROMISC_SAP) != DLPI_SUCCESS) { + error_report("vnic: failed to be promiscous with interface %s", + ifname); + return (-1); + } + + fd = dlpi_fd(vsp->vns_hdl); + + if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) { + error_report("vnic: failed to set fd on interface %s to " + "non-blocking: %s\n", ifname, strerror(errno)); + return (-1); + } + + vsp->vns_fd = fd; + + snprintf(vsp->vns_nc.info_str, sizeof (vsp->vns_nc.info_str), "ifname=%s", + qemu_opt_get(opts, "ifname")); + + /* XXX This should be ifdef'd around whether or not KVM is present */ +#ifdef CONFIG_KVM + net_init_kvm(fd); +#endif + + /* We have to manually intialize the polling for read */ + vnic_read_poll(vsp, 1); + + return (0); +} diff --git a/net/vnic.h b/net/vnic.h new file mode 100644 index 0000000..1fd6748 --- /dev/null +++ b/net/vnic.h @@ -0,0 +1,34 @@ +/* + * QEMU System Emulator + * Solaris VNIC support + * + * Copyright (c) 2011 Joyent, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef QEMU_NET_VNIC_H +#define QEMU_NET_VNIC_H + +#include "net.h" +#include "qemu-common.h" + +int net_init_vnic(QemuOpts *opts, Monitor *mon, const char *name, + VLANState *vlan); + +#endif /* QEMU_NET_VNIC_H */ diff --git a/qemu-kvm-x86.c b/qemu-kvm-x86.c index 4be5e32..7de3098 100644 --- a/qemu-kvm-x86.c +++ b/qemu-kvm-x86.c @@ -12,13 +12,17 @@ #include <string.h> #include "hw/hw.h" #include "gdbstub.h" +#ifdef __linux__ #include <sys/io.h> +#endif #include "qemu-kvm.h" #include "libkvm.h" #include <pthread.h> #include <sys/utsname.h> +#ifdef CONFIG_KVM_PARA #include <linux/kvm_para.h> +#endif #include <sys/ioctl.h> #include "kvm.h" @@ -28,7 +28,9 @@ #include <sys/mman.h> #include <sys/ioctl.h> #include "compatfd.h" +#ifdef __linux__ #include <sys/prctl.h> +#endif #define false 0 #define true 1 @@ -250,15 +252,32 @@ static void kvm_create_vcpu(CPUState *env, int id) int r; KVMState *s = kvm_state; +#ifdef CONFIG_SOLARIS + r = kvm_vm_clone(kvm_state); + + if (r < 0) { + fprintf(stderr, "kvm_create_vcpu could not clone fd: %m\n"); + goto err; + } + + env->kvm_fd = r; + env->kvm_state = kvm_state; + + r = ioctl(env->kvm_fd, KVM_CREATE_VCPU, id); +#else r = kvm_vm_ioctl(kvm_state, KVM_CREATE_VCPU, id); +#endif + if (r < 0) { fprintf(stderr, "kvm_create_vcpu: %m\n"); fprintf(stderr, "Failed to create vCPU. Check the -smp parameter.\n"); goto err; } +#ifndef CONFIG_SOLARIS env->kvm_fd = r; env->kvm_state = kvm_state; +#endif mmap_size = kvm_ioctl(kvm_state, KVM_GET_VCPU_MMAP_SIZE, 0); if (mmap_size < 0) { @@ -318,7 +337,11 @@ int kvm_create_vm(kvm_context_t kvm) fprintf(stderr, "kvm_create_vm: %m\n"); return -1; } +#ifdef CONFIG_SOLARIS + kvm_state->vmfd = kvm_state->fd; +#else kvm_state->vmfd = fd; +#endif return 0; } @@ -631,6 +654,9 @@ int kvm_run(CPUState *env) r = kvm_arch_halt(env); break; case KVM_EXIT_IRQ_WINDOW_OPEN: +#ifdef CONFIG_SOLARIS + case KVM_EXIT_INTR: +#endif break; case KVM_EXIT_SHUTDOWN: r = handle_shutdown(kvm, env); @@ -1097,7 +1123,7 @@ int kvm_irqfd(kvm_context_t kvm, int gsi, int flags) #endif /* KVM_CAP_IRQFD */ unsigned long kvm_get_thread_id(void) { - return syscall(SYS_gettid); + return pthread_self(); } static void qemu_cond_wait(pthread_cond_t *cond) @@ -1515,7 +1541,9 @@ int kvm_init_ap(void) action.sa_flags = SA_SIGINFO; action.sa_sigaction = (void (*)(int, siginfo_t*, void*))sigbus_handler; sigaction(SIGBUS, &action, NULL); +#ifdef __linux__ prctl(PR_MCE_KILL, 1, 1, 0, 0); +#endif return 0; } @@ -25,7 +25,11 @@ #define __user /* temporary, until installed via make headers_install */ #endif +#ifdef __sun__ +#include <sys/kvm.h> +#else #include <linux/kvm.h> +#endif #include <signal.h> diff --git a/qemu-malloc.c b/qemu-malloc.c index b9b3851..d27d595 100644 --- a/qemu-malloc.c +++ b/qemu-malloc.c @@ -62,9 +62,29 @@ void *qemu_realloc(void *ptr, size_t size) return newptr; } +#ifdef CONFIG_SOLARIS +void *qemu_mallocz(size_t size) +{ + char *ptr; + int i; + char x; + + if (!size && !allow_zero_malloc()) { + abort(); + } + ptr = qemu_oom_check(calloc(1, size ? size : 1)); + for (i = 0; i < size; i++) + x = (char)*ptr+i; + + trace_qemu_malloc(size, ptr); + return ptr; +} + +#else void *qemu_mallocz(size_t size) { void *ptr; + if (!size && !allow_zero_malloc()) { abort(); } @@ -72,6 +92,7 @@ void *qemu_mallocz(size_t size) trace_qemu_malloc(size, ptr); return ptr; } +#endif /* CONFIG_SOLARIS */ char *qemu_strdup(const char *str) { diff --git a/qemu-timer.c b/qemu-timer.c index 218a2a3..0c475d9 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -216,12 +216,16 @@ static void win32_rearm_timer(struct qemu_alarm_timer *t); static int unix_start_timer(struct qemu_alarm_timer *t); static void unix_stop_timer(struct qemu_alarm_timer *t); -#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); static void dynticks_rearm_timer(struct qemu_alarm_timer *t); +#endif + +#ifdef __linux__ + static int hpet_start_timer(struct qemu_alarm_timer *t); static void hpet_stop_timer(struct qemu_alarm_timer *t); @@ -289,9 +293,11 @@ int64_t qemu_icount_round(int64_t count) 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, NULL}, +#endif +#ifdef __linux__ /* HPET - if available - is preferred */ {"hpet", hpet_start_timer, hpet_stop_timer, NULL, NULL}, /* ...otherwise try RTC */ @@ -838,6 +844,10 @@ static void rtc_stop_timer(struct qemu_alarm_timer *t) close(rtc_fd); } +#endif /* defined(__linux__) */ + +#if defined(__linux__) || defined(__sun__) + static int dynticks_start_timer(struct qemu_alarm_timer *t) { struct sigevent ev; @@ -918,7 +928,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/target-i386/kvm.c b/target-i386/kvm.c index f389b85..5533f20 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -17,7 +17,11 @@ #include <sys/mman.h> #include <sys/utsname.h> +#ifdef __sun__ +#include <sys/kvm.h> +#else #include <linux/kvm.h> +#endif #include "qemu-common.h" #include "sysemu.h" @@ -33,6 +37,11 @@ #ifdef CONFIG_KVM_PARA #include <linux/kvm_para.h> #endif + +#ifdef __sun__ +#define __u64 uint64_t +#endif + // //#define DEBUG_KVM |