summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.objs8
-rwxr-xr-xbuild.sh36
-rwxr-xr-xconfigure29
-rw-r--r--exec.c14
-rw-r--r--hw/hw.h9
-rw-r--r--hw/pc.c2
-rw-r--r--kvm-all.c39
-rw-r--r--kvm.h6
-rw-r--r--net.c30
-rw-r--r--net.h3
-rw-r--r--net/vnic.c316
-rw-r--r--net/vnic.h34
-rw-r--r--qemu-kvm-x86.c4
-rw-r--r--qemu-kvm.c30
-rw-r--r--qemu-kvm.h4
-rw-r--r--qemu-malloc.c21
-rw-r--r--qemu-timer.c16
-rw-r--r--target-i386/kvm.c9
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
diff --git a/configure b/configure
index 50f5de9..100af30 100755
--- a/configure
+++ b/configure
@@ -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
diff --git a/exec.c b/exec.c
index 9f748bc..009e1d2 100644
--- a/exec.c
+++ b/exec.c
@@ -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);
}
}
diff --git a/hw/hw.h b/hw/hw.h
index 6d3d106..a412c18 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -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) \
diff --git a/hw/pc.c b/hw/pc.c
index b7bf319..3d7ed27 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -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
diff --git a/kvm-all.c b/kvm-all.c
index 0e404d6..4a4bebf 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -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;
diff --git a/kvm.h b/kvm.h
index f06676c..401b960 100644
--- a/kvm.h
+++ b/kvm.h
@@ -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
diff --git a/net.c b/net.c
index 21d4443..73ee212 100644
--- a/net.c
+++ b/net.c
@@ -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: ;
diff --git a/net.h b/net.h
index 6ceca50..e206f15 100644
--- a/net.h
+++ b/net.h
@@ -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"
diff --git a/qemu-kvm.c b/qemu-kvm.c
index 49cd683..fd46173 100644
--- a/qemu-kvm.c
+++ b/qemu-kvm.c
@@ -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;
}
diff --git a/qemu-kvm.h b/qemu-kvm.h
index 88cf276..febd73f 100644
--- a/qemu-kvm.h
+++ b/qemu-kvm.h
@@ -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