summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--hw/file-op-9p.h13
-rw-r--r--hw/fw_cfg.c80
-rw-r--r--hw/marvell_88w8618_audio.c4
-rw-r--r--hw/mips_jazz.c4
-rw-r--r--hw/mips_malta.c4
-rw-r--r--hw/musicpal.c4
-rw-r--r--hw/omap2.c2
-rw-r--r--hw/pc.c24
-rw-r--r--hw/pc_piix.c2
-rw-r--r--hw/slavio_intctl.c9
-rw-r--r--hw/spitz.c4
-rw-r--r--hw/virtio-9p-local.c292
-rw-r--r--hw/virtio-9p.c92
-rw-r--r--hw/virtio-pci.c2
-rw-r--r--kvm-all.c16
-rw-r--r--migration-exec.c14
-rw-r--r--migration-fd.c14
-rw-r--r--migration-tcp.c15
-rw-r--r--migration-unix.c15
-rw-r--r--migration.c29
-rw-r--r--migration.h4
-rw-r--r--osdep.c7
-rw-r--r--qemu-os-win32.h4
-rw-r--r--target-i386/helper.c1
-rw-r--r--vl.c7
26 files changed, 434 insertions, 230 deletions
diff --git a/.gitignore b/.gitignore
index 6e04a311c..b3afd4b33 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,6 +6,7 @@ config-target.*
*-darwin-user
*-linux-user
*-bsd-user
+libdis*
libhw32
libhw64
libuser
@@ -21,6 +22,7 @@ qemu-img
qemu-nbd
qemu-nbd.8
qemu-nbd.pod
+qemu-options.def
qemu-options.texi
qemu-img-cmds.texi
qemu-img-cmds.h
diff --git a/hw/file-op-9p.h b/hw/file-op-9p.h
index 307bd1eee..a741c9352 100644
--- a/hw/file-op-9p.h
+++ b/hw/file-op-9p.h
@@ -49,20 +49,19 @@ typedef struct FileOperations
{
int (*lstat)(FsContext *, const char *, struct stat *);
ssize_t (*readlink)(FsContext *, const char *, char *, size_t);
- int (*chmod)(FsContext *, const char *, mode_t);
- int (*chown)(FsContext *, const char *, uid_t, gid_t);
- int (*mknod)(FsContext *, const char *, mode_t, dev_t);
- int (*mksock)(FsContext *, const char *);
+ int (*chmod)(FsContext *, const char *, FsCred *);
+ int (*chown)(FsContext *, const char *, FsCred *);
+ int (*mknod)(FsContext *, const char *, FsCred *);
int (*utime)(FsContext *, const char *, const struct utimbuf *);
int (*remove)(FsContext *, const char *);
- int (*symlink)(FsContext *, const char *, const char *);
+ int (*symlink)(FsContext *, const char *, const char *, FsCred *);
int (*link)(FsContext *, const char *, const char *);
int (*setuid)(FsContext *, uid_t);
int (*close)(FsContext *, int);
int (*closedir)(FsContext *, DIR *);
DIR *(*opendir)(FsContext *, const char *);
int (*open)(FsContext *, const char *, int);
- int (*open2)(FsContext *, const char *, int, mode_t);
+ int (*open2)(FsContext *, const char *, int, FsCred *);
void (*rewinddir)(FsContext *, DIR *);
off_t (*telldir)(FsContext *, DIR *);
struct dirent *(*readdir)(FsContext *, DIR *);
@@ -70,7 +69,7 @@ typedef struct FileOperations
ssize_t (*readv)(FsContext *, int, const struct iovec *, int);
ssize_t (*writev)(FsContext *, int, const struct iovec *, int);
off_t (*lseek)(FsContext *, int, off_t, int);
- int (*mkdir)(FsContext *, const char *, mode_t);
+ int (*mkdir)(FsContext *, const char *, FsCred *);
int (*fstat)(FsContext *, int, struct stat *);
int (*rename)(FsContext *, const char *, const char *);
int (*truncate)(FsContext *, const char *, off_t);
diff --git a/hw/fw_cfg.c b/hw/fw_cfg.c
index 22ebb5001..72866aea9 100644
--- a/hw/fw_cfg.c
+++ b/hw/fw_cfg.c
@@ -25,6 +25,7 @@
#include "sysemu.h"
#include "isa.h"
#include "fw_cfg.h"
+#include "sysbus.h"
/* debug firmware config */
//#define DEBUG_FW_CFG
@@ -46,6 +47,8 @@ typedef struct FWCfgEntry {
} FWCfgEntry;
struct FWCfgState {
+ SysBusDevice busdev;
+ uint32_t ctl_iobase, data_iobase;
FWCfgEntry entries[2][FW_CFG_MAX_ENTRY];
FWCfgFiles *files;
uint16_t cur_entry;
@@ -158,9 +161,9 @@ static CPUWriteMemoryFunc * const fw_cfg_data_mem_write[3] = {
NULL,
};
-static void fw_cfg_reset(void *opaque)
+static void fw_cfg_reset(DeviceState *d)
{
- FWCfgState *s = opaque;
+ FWCfgState *s = DO_UPCAST(FWCfgState, busdev.qdev, d);
fw_cfg_select(s, 0);
}
@@ -323,27 +326,23 @@ int fw_cfg_add_file(FWCfgState *s, const char *dir, const char *filename,
FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
target_phys_addr_t ctl_addr, target_phys_addr_t data_addr)
{
+ DeviceState *dev;
+ SysBusDevice *d;
FWCfgState *s;
- int io_ctl_memory, io_data_memory;
- s = qemu_mallocz(sizeof(FWCfgState));
+ dev = qdev_create(NULL, "fw_cfg");
+ qdev_prop_set_uint32(dev, "ctl_iobase", ctl_port);
+ qdev_prop_set_uint32(dev, "data_iobase", data_port);
+ qdev_init_nofail(dev);
+ d = sysbus_from_qdev(dev);
+
+ s = DO_UPCAST(FWCfgState, busdev.qdev, dev);
- if (ctl_port) {
- register_ioport_write(ctl_port, 2, 2, fw_cfg_io_writew, s);
- }
- if (data_port) {
- register_ioport_read(data_port, 1, 1, fw_cfg_io_readb, s);
- register_ioport_write(data_port, 1, 1, fw_cfg_io_writeb, s);
- }
if (ctl_addr) {
- io_ctl_memory = cpu_register_io_memory(fw_cfg_ctl_mem_read,
- fw_cfg_ctl_mem_write, s);
- cpu_register_physical_memory(ctl_addr, FW_CFG_SIZE, io_ctl_memory);
+ sysbus_mmio_map(d, 0, ctl_addr);
}
if (data_addr) {
- io_data_memory = cpu_register_io_memory(fw_cfg_data_mem_read,
- fw_cfg_data_mem_write, s);
- cpu_register_physical_memory(data_addr, FW_CFG_SIZE, io_data_memory);
+ sysbus_mmio_map(d, 1, data_addr);
}
fw_cfg_add_bytes(s, FW_CFG_SIGNATURE, (uint8_t *)"QEMU", 4);
fw_cfg_add_bytes(s, FW_CFG_UUID, qemu_uuid, 16);
@@ -352,8 +351,49 @@ FWCfgState *fw_cfg_init(uint32_t ctl_port, uint32_t data_port,
fw_cfg_add_i16(s, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
fw_cfg_add_i16(s, FW_CFG_BOOT_MENU, (uint16_t)boot_menu);
- vmstate_register(-1, &vmstate_fw_cfg, s);
- qemu_register_reset(fw_cfg_reset, s);
-
return s;
}
+
+static int fw_cfg_init1(SysBusDevice *dev)
+{
+ FWCfgState *s = FROM_SYSBUS(FWCfgState, dev);
+ int io_ctl_memory, io_data_memory;
+
+ io_ctl_memory = cpu_register_io_memory(fw_cfg_ctl_mem_read,
+ fw_cfg_ctl_mem_write, s);
+ sysbus_init_mmio(dev, FW_CFG_SIZE, io_ctl_memory);
+
+ io_data_memory = cpu_register_io_memory(fw_cfg_data_mem_read,
+ fw_cfg_data_mem_write, s);
+ sysbus_init_mmio(dev, FW_CFG_SIZE, io_data_memory);
+
+ if (s->ctl_iobase) {
+ register_ioport_write(s->ctl_iobase, 2, 2, fw_cfg_io_writew, s);
+ }
+ if (s->data_iobase) {
+ register_ioport_read(s->data_iobase, 1, 1, fw_cfg_io_readb, s);
+ register_ioport_write(s->data_iobase, 1, 1, fw_cfg_io_writeb, s);
+ }
+ return 0;
+}
+
+static SysBusDeviceInfo fw_cfg_info = {
+ .init = fw_cfg_init1,
+ .qdev.name = "fw_cfg",
+ .qdev.size = sizeof(FWCfgState),
+ .qdev.vmsd = &vmstate_fw_cfg,
+ .qdev.reset = fw_cfg_reset,
+ .qdev.no_user = 1,
+ .qdev.props = (Property[]) {
+ DEFINE_PROP_HEX32("ctl_iobase", FWCfgState, ctl_iobase, -1),
+ DEFINE_PROP_HEX32("data_iobase", FWCfgState, data_iobase, -1),
+ DEFINE_PROP_END_OF_LIST(),
+ },
+};
+
+static void fw_cfg_register_devices(void)
+{
+ sysbus_register_withprop(&fw_cfg_info);
+}
+
+device_init(fw_cfg_register_devices)
diff --git a/hw/marvell_88w8618_audio.c b/hw/marvell_88w8618_audio.c
index 57c3d5a61..307b58471 100644
--- a/hw/marvell_88w8618_audio.c
+++ b/hw/marvell_88w8618_audio.c
@@ -34,7 +34,6 @@
#define MP_AUDIO_CLOCK_24MHZ (1 << 9)
#define MP_AUDIO_MONO (1 << 14)
-#ifdef HAS_AUDIO
typedef struct mv88w8618_audio_state {
SysBusDevice busdev;
qemu_irq irq;
@@ -290,13 +289,10 @@ static SysBusDeviceInfo mv88w8618_audio_info = {
{/* end of list */}
}
};
-#endif
static void mv88w8618_register_devices(void)
{
-#ifdef HAS_AUDIO
sysbus_register_withprop(&mv88w8618_audio_info);
-#endif
}
device_init(mv88w8618_register_devices)
diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index 22db7a2f7..606cd23ef 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -89,7 +89,6 @@ static CPUWriteMemoryFunc * const dma_dummy_write[3] = {
dma_dummy_writeb,
};
-#ifdef HAS_AUDIO
static void audio_init(qemu_irq *pic)
{
struct soundhw *c;
@@ -109,7 +108,6 @@ static void audio_init(qemu_irq *pic)
}
}
}
-#endif
#define MAGNUM_BIOS_SIZE_MAX 0x7e000
#define MAGNUM_BIOS_SIZE (BIOS_SIZE < MAGNUM_BIOS_SIZE_MAX ? BIOS_SIZE : MAGNUM_BIOS_SIZE_MAX)
@@ -288,9 +286,7 @@ void mips_jazz_init (ram_addr_t ram_size,
/* Sound card */
/* FIXME: missing Jazz sound at 0x8000c000, rc4030[2] */
-#ifdef HAS_AUDIO
audio_init(i8259);
-#endif
/* NVRAM: Unprotected at 0x9000, Protected at 0xa000, Read only at 0xb000 */
ds1225y_init(0x80009000, "nvram");
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index 23de7f0f3..9042b57dd 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -456,7 +456,6 @@ static MaltaFPGAState *malta_fpga_init(target_phys_addr_t base, qemu_irq uart_ir
}
/* Audio support */
-#ifdef HAS_AUDIO
static void audio_init (PCIBus *pci_bus)
{
struct soundhw *c;
@@ -474,7 +473,6 @@ static void audio_init (PCIBus *pci_bus)
}
}
}
-#endif
/* Network support */
static void network_init(void)
@@ -970,9 +968,7 @@ void mips_malta_init (ram_addr_t ram_size,
floppy_controller = fdctrl_init_isa(fd);
/* Sound card */
-#ifdef HAS_AUDIO
audio_init(pci_bus);
-#endif
/* Network card */
network_init();
diff --git a/hw/musicpal.c b/hw/musicpal.c
index d44c5a0d4..95ef2c674 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -1486,10 +1486,8 @@ static void musicpal_init(ram_addr_t ram_size,
DeviceState *i2c_dev;
DeviceState *lcd_dev;
DeviceState *key_dev;
-#ifdef HAS_AUDIO
DeviceState *wm8750_dev;
SysBusDevice *s;
-#endif
i2c_bus *i2c;
int i;
unsigned long flash_size;
@@ -1611,7 +1609,6 @@ static void musicpal_init(ram_addr_t ram_size,
qdev_connect_gpio_out(key_dev, i, qdev_get_gpio_in(dev, i + 15));
}
-#ifdef HAS_AUDIO
wm8750_dev = i2c_create_slave(i2c, "wm8750", MP_WM_ADDR);
dev = qdev_create(NULL, "mv88w8618_audio");
s = sysbus_from_qdev(dev);
@@ -1619,7 +1616,6 @@ static void musicpal_init(ram_addr_t ram_size,
qdev_init_nofail(dev);
sysbus_mmio_map(s, 0, MP_AUDIO_BASE);
sysbus_connect_irq(s, 0, pic[MP_AUDIO_IRQ]);
-#endif
musicpal_binfo.ram_size = MP_RAM_DEFAULT_SIZE;
musicpal_binfo.kernel_filename = kernel_filename;
diff --git a/hw/omap2.c b/hw/omap2.c
index 666c15adb..f2c47feef 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -1973,13 +1973,11 @@ struct omap_eac_s *omap_eac_init(struct omap_target_agent_s *ta,
s->codec.txdrq = *drq;
omap_eac_reset(s);
-#ifdef HAS_AUDIO
AUD_register_card("OMAP EAC", &s->codec.card);
iomemtype = cpu_register_io_memory(omap_eac_readfn,
omap_eac_writefn, s);
omap_l4_attach(ta, 0, iomemtype);
-#endif
return s;
}
diff --git a/hw/pc.c b/hw/pc.c
index 1f61609ba..186e322e1 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -725,7 +725,6 @@ static const int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 };
static const int parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc };
static const int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 };
-#ifdef HAS_AUDIO
void pc_audio_init (PCIBus *pci_bus, qemu_irq *pic)
{
struct soundhw *c;
@@ -742,7 +741,6 @@ void pc_audio_init (PCIBus *pci_bus, qemu_irq *pic)
}
}
}
-#endif
void pc_init_ne2k_isa(NICInfo *nd)
{
@@ -816,20 +814,12 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level)
}
}
-static void bsp_cpu_reset(void *opaque)
+static void pc_cpu_reset(void *opaque)
{
CPUState *env = opaque;
cpu_reset(env);
- env->halted = 0;
-}
-
-static void ap_cpu_reset(void *opaque)
-{
- CPUState *env = opaque;
-
- cpu_reset(env);
- env->halted = 1;
+ env->halted = !cpu_is_bsp(env);
}
CPUState *pc_new_cpu(const char *cpu_model)
@@ -851,16 +841,10 @@ CPUState *pc_new_cpu(const char *cpu_model)
}
if ((env->cpuid_features & CPUID_APIC) || smp_cpus > 1) {
env->cpuid_apic_id = env->cpu_index;
- /* APIC reset callback resets cpu */
env->apic_state = apic_init(env, env->cpuid_apic_id);
}
- if (cpu_is_bsp(env)) {
- qemu_register_reset(bsp_cpu_reset, env);
- env->halted = 0;
- } else {
- qemu_register_reset(ap_cpu_reset, env);
- env->halted = 1;
- }
+ qemu_register_reset(pc_cpu_reset, env);
+ pc_cpu_reset(env);
return env;
}
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index a099797ab..6f477eda0 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -159,9 +159,7 @@ static void pc_init1(ram_addr_t ram_size,
}
}
-#ifdef HAS_AUDIO
pc_audio_init(pci_enabled ? pci_bus : NULL, isa_irq);
-#endif
pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, hd,
floppy_controller, rtc_state);
diff --git a/hw/slavio_intctl.c b/hw/slavio_intctl.c
index b76d3acad..10362a365 100644
--- a/hw/slavio_intctl.c
+++ b/hw/slavio_intctl.c
@@ -289,9 +289,12 @@ static void slavio_check_interrupts(SLAVIO_INTCTLState *s, int set_irqs)
}
}
- /* Level 15 and CPU timer interrupts are not maskable */
- pil_pending |= s->slaves[i].intreg_pending &
- (CPU_IRQ_INT15_IN | CPU_IRQ_TIMER_IN);
+ /* Level 15 and CPU timer interrupts are only masked when
+ the MASTER_DISABLE bit is set */
+ if (!(s->intregm_disabled & MASTER_DISABLE)) {
+ pil_pending |= s->slaves[i].intreg_pending &
+ (CPU_IRQ_INT15_IN | CPU_IRQ_TIMER_IN);
+ }
/* Add soft interrupts */
pil_pending |= (s->slaves[i].intreg_pending & CPU_SOFTIRQ_MASK) >> 16;
diff --git a/hw/spitz.c b/hw/spitz.c
index 4f82e2449..b3e5318e3 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -768,7 +768,6 @@ static void spitz_microdrive_attach(PXA2xxState *cpu, int slot)
#define SPITZ_GPIO_WM 5
-#ifdef HAS_AUDIO
static void spitz_wm8750_addr(void *opaque, int line, int level)
{
i2c_slave *wm = (i2c_slave *) opaque;
@@ -777,14 +776,12 @@ static void spitz_wm8750_addr(void *opaque, int line, int level)
else
i2c_set_slave_address(wm, SPITZ_WM_ADDRL);
}
-#endif
static void spitz_i2c_setup(PXA2xxState *cpu)
{
/* Attach the CPU on one end of our I2C bus. */
i2c_bus *bus = pxa2xx_i2c_bus(cpu->i2c[0]);
-#ifdef HAS_AUDIO
DeviceState *wm;
/* Attach a WM8750 to the bus */
@@ -798,7 +795,6 @@ static void spitz_i2c_setup(PXA2xxState *cpu)
cpu->i2s->codec_out = wm8750_dac_dat;
cpu->i2s->codec_in = wm8750_adc_dat;
wm8750_data_req_set(wm, cpu->i2s->data_req, cpu->i2s);
-#endif
}
static void spitz_akita_i2c_setup(PXA2xxState *cpu)
diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
index 056b4ba04..04f7f6f50 100644
--- a/hw/virtio-9p-local.c
+++ b/hw/virtio-9p-local.c
@@ -27,9 +27,38 @@ static const char *rpath(FsContext *ctx, const char *path)
return buffer;
}
-static int local_lstat(FsContext *ctx, const char *path, struct stat *stbuf)
+
+static int local_lstat(FsContext *fs_ctx, const char *path, struct stat *stbuf)
{
- return lstat(rpath(ctx, path), stbuf);
+ int err;
+ err = lstat(rpath(fs_ctx, path), stbuf);
+ if (err) {
+ return err;
+ }
+ if (fs_ctx->fs_sm == SM_MAPPED) {
+ /* Actual credentials are part of extended attrs */
+ uid_t tmp_uid;
+ gid_t tmp_gid;
+ mode_t tmp_mode;
+ dev_t tmp_dev;
+ if (getxattr(rpath(fs_ctx, path), "user.virtfs.uid", &tmp_uid,
+ sizeof(uid_t)) > 0) {
+ stbuf->st_uid = tmp_uid;
+ }
+ if (getxattr(rpath(fs_ctx, path), "user.virtfs.gid", &tmp_gid,
+ sizeof(gid_t)) > 0) {
+ stbuf->st_gid = tmp_gid;
+ }
+ if (getxattr(rpath(fs_ctx, path), "user.virtfs.mode", &tmp_mode,
+ sizeof(mode_t)) > 0) {
+ stbuf->st_mode = tmp_mode;
+ }
+ if (getxattr(rpath(fs_ctx, path), "user.virtfs.rdev", &tmp_dev,
+ sizeof(dev_t)) > 0) {
+ stbuf->st_rdev = tmp_dev;
+ }
+ }
+ return err;
}
static int local_set_xattr(const char *path, FsCred *credp)
@@ -66,10 +95,37 @@ static int local_set_xattr(const char *path, FsCred *credp)
return 0;
}
-static ssize_t local_readlink(FsContext *ctx, const char *path,
- char *buf, size_t bufsz)
+static int local_post_create_passthrough(FsContext *fs_ctx, const char *path,
+ FsCred *credp)
{
- return readlink(rpath(ctx, path), buf, bufsz);
+ if (chmod(rpath(fs_ctx, path), credp->fc_mode & 07777) < 0) {
+ return -1;
+ }
+ if (chown(rpath(fs_ctx, path), credp->fc_uid, credp->fc_gid) < 0) {
+ return -1;
+ }
+ return 0;
+}
+
+static ssize_t local_readlink(FsContext *fs_ctx, const char *path,
+ char *buf, size_t bufsz)
+{
+ ssize_t tsize = -1;
+ if (fs_ctx->fs_sm == SM_MAPPED) {
+ int fd;
+ fd = open(rpath(fs_ctx, path), O_RDONLY);
+ if (fd == -1) {
+ return -1;
+ }
+ do {
+ tsize = read(fd, (void *)buf, bufsz);
+ } while (tsize == -1 && errno == EINTR);
+ close(fd);
+ return tsize;
+ } else if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
+ tsize = readlink(rpath(fs_ctx, path), buf, bufsz);
+ }
+ return tsize;
}
static int local_close(FsContext *ctx, int fd)
@@ -129,58 +185,210 @@ static ssize_t local_writev(FsContext *ctx, int fd, const struct iovec *iov,
return writev(fd, iov, iovcnt);
}
-static int local_chmod(FsContext *ctx, const char *path, mode_t mode)
+static int local_chmod(FsContext *fs_ctx, const char *path, FsCred *credp)
{
- return chmod(rpath(ctx, path), mode);
+ if (fs_ctx->fs_sm == SM_MAPPED) {
+ return local_set_xattr(rpath(fs_ctx, path), credp);
+ } else if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
+ return chmod(rpath(fs_ctx, path), credp->fc_mode);
+ }
+ return -1;
}
-static int local_mknod(FsContext *ctx, const char *path, mode_t mode, dev_t dev)
+static int local_mknod(FsContext *fs_ctx, const char *path, FsCred *credp)
{
- return mknod(rpath(ctx, path), mode, dev);
-}
+ int err = -1;
+ int serrno = 0;
-static int local_mksock(FsContext *ctx2, const char *path)
-{
- struct sockaddr_un addr;
- int s;
+ /* Determine the security model */
+ if (fs_ctx->fs_sm == SM_MAPPED) {
+ err = mknod(rpath(fs_ctx, path), SM_LOCAL_MODE_BITS|S_IFREG, 0);
+ if (err == -1) {
+ return err;
+ }
+ local_set_xattr(rpath(fs_ctx, path), credp);
+ if (err == -1) {
+ serrno = errno;
+ goto err_end;
+ }
+ } else if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
+ err = mknod(rpath(fs_ctx, path), credp->fc_mode, credp->fc_rdev);
+ if (err == -1) {
+ return err;
+ }
+ err = local_post_create_passthrough(fs_ctx, path, credp);
+ if (err == -1) {
+ serrno = errno;
+ goto err_end;
+ }
+ }
+ return err;
- addr.sun_family = AF_UNIX;
- snprintf(addr.sun_path, 108, "%s", rpath(ctx2, path));
+err_end:
+ remove(rpath(fs_ctx, path));
+ errno = serrno;
+ return err;
+}
- s = socket(PF_UNIX, SOCK_STREAM, 0);
- if (s == -1) {
- return -1;
- }
+static int local_mkdir(FsContext *fs_ctx, const char *path, FsCred *credp)
+{
+ int err = -1;
+ int serrno = 0;
- if (bind(s, (struct sockaddr *)&addr, sizeof(addr))) {
- close(s);
- return -1;
+ /* Determine the security model */
+ if (fs_ctx->fs_sm == SM_MAPPED) {
+ err = mkdir(rpath(fs_ctx, path), SM_LOCAL_DIR_MODE_BITS);
+ if (err == -1) {
+ return err;
+ }
+ credp->fc_mode = credp->fc_mode|S_IFDIR;
+ err = local_set_xattr(rpath(fs_ctx, path), credp);
+ if (err == -1) {
+ serrno = errno;
+ goto err_end;
+ }
+ } else if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
+ err = mkdir(rpath(fs_ctx, path), credp->fc_mode);
+ if (err == -1) {
+ return err;
+ }
+ err = local_post_create_passthrough(fs_ctx, path, credp);
+ if (err == -1) {
+ serrno = errno;
+ goto err_end;
+ }
}
+ return err;
- close(s);
- return 0;
+err_end:
+ remove(rpath(fs_ctx, path));
+ errno = serrno;
+ return err;
}
-static int local_mkdir(FsContext *ctx, const char *path, mode_t mode)
+static int local_fstat(FsContext *fs_ctx, int fd, struct stat *stbuf)
{
- return mkdir(rpath(ctx, path), mode);
+ int err;
+ err = fstat(fd, stbuf);
+ if (err) {
+ return err;
+ }
+ if (fs_ctx->fs_sm == SM_MAPPED) {
+ /* Actual credentials are part of extended attrs */
+ uid_t tmp_uid;
+ gid_t tmp_gid;
+ mode_t tmp_mode;
+ dev_t tmp_dev;
+
+ if (fgetxattr(fd, "user.virtfs.uid", &tmp_uid, sizeof(uid_t)) > 0) {
+ stbuf->st_uid = tmp_uid;
+ }
+ if (fgetxattr(fd, "user.virtfs.gid", &tmp_gid, sizeof(gid_t)) > 0) {
+ stbuf->st_gid = tmp_gid;
+ }
+ if (fgetxattr(fd, "user.virtfs.mode", &tmp_mode, sizeof(mode_t)) > 0) {
+ stbuf->st_mode = tmp_mode;
+ }
+ if (fgetxattr(fd, "user.virtfs.rdev", &tmp_dev, sizeof(dev_t)) > 0) {
+ stbuf->st_rdev = tmp_dev;
+ }
+ }
+ return err;
}
-static int local_fstat(FsContext *ctx, int fd, struct stat *stbuf)
+static int local_open2(FsContext *fs_ctx, const char *path, int flags,
+ FsCred *credp)
{
- return fstat(fd, stbuf);
-}
+ int fd = -1;
+ int err = -1;
+ int serrno = 0;
+
+ /* Determine the security model */
+ if (fs_ctx->fs_sm == SM_MAPPED) {
+ fd = open(rpath(fs_ctx, path), flags, SM_LOCAL_MODE_BITS);
+ if (fd == -1) {
+ return fd;
+ }
+ credp->fc_mode = credp->fc_mode|S_IFREG;
+ /* Set cleint credentials in xattr */
+ err = local_set_xattr(rpath(fs_ctx, path), credp);
+ if (err == -1) {
+ serrno = errno;
+ goto err_end;
+ }
+ } else if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
+ fd = open(rpath(fs_ctx, path), flags, credp->fc_mode);
+ if (fd == -1) {
+ return fd;
+ }
+ err = local_post_create_passthrough(fs_ctx, path, credp);
+ if (err == -1) {
+ serrno = errno;
+ goto err_end;
+ }
+ }
+ return fd;
-static int local_open2(FsContext *ctx, const char *path, int flags, mode_t mode)
-{
- return open(rpath(ctx, path), flags, mode);
+err_end:
+ close(fd);
+ remove(rpath(fs_ctx, path));
+ errno = serrno;
+ return err;
}
-static int local_symlink(FsContext *ctx, const char *oldpath,
- const char *newpath)
+static int local_symlink(FsContext *fs_ctx, const char *oldpath,
+ const char *newpath, FsCred *credp)
{
- return symlink(oldpath, rpath(ctx, newpath));
+ int err = -1;
+ int serrno = 0;
+
+ /* Determine the security model */
+ if (fs_ctx->fs_sm == SM_MAPPED) {
+ int fd;
+ ssize_t oldpath_size, write_size;
+ fd = open(rpath(fs_ctx, newpath), O_CREAT|O_EXCL|O_RDWR,
+ SM_LOCAL_MODE_BITS);
+ if (fd == -1) {
+ return fd;
+ }
+ /* Write the oldpath (target) to the file. */
+ oldpath_size = strlen(oldpath) + 1;
+ do {
+ write_size = write(fd, (void *)oldpath, oldpath_size);
+ } while (write_size == -1 && errno == EINTR);
+
+ if (write_size != oldpath_size) {
+ serrno = errno;
+ close(fd);
+ err = -1;
+ goto err_end;
+ }
+ close(fd);
+ /* Set cleint credentials in symlink's xattr */
+ credp->fc_mode = credp->fc_mode|S_IFLNK;
+ err = local_set_xattr(rpath(fs_ctx, newpath), credp);
+ if (err == -1) {
+ serrno = errno;
+ goto err_end;
+ }
+ } else if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
+ err = symlink(oldpath, rpath(fs_ctx, newpath));
+ if (err) {
+ return err;
+ }
+ err = lchown(rpath(fs_ctx, newpath), credp->fc_uid, credp->fc_gid);
+ if (err == -1) {
+ serrno = errno;
+ goto err_end;
+ }
+ }
+ return err;
+
+err_end:
+ remove(rpath(fs_ctx, newpath));
+ errno = serrno;
+ return err;
}
static int local_link(FsContext *ctx, const char *oldpath, const char *newpath)
@@ -235,9 +443,14 @@ static int local_rename(FsContext *ctx, const char *oldpath,
}
-static int local_chown(FsContext *ctx, const char *path, uid_t uid, gid_t gid)
+static int local_chown(FsContext *fs_ctx, const char *path, FsCred *credp)
{
- return chown(rpath(ctx, path), uid, gid);
+ if (fs_ctx->fs_sm == SM_MAPPED) {
+ return local_set_xattr(rpath(fs_ctx, path), credp);
+ } else if (fs_ctx->fs_sm == SM_PASSTHROUGH) {
+ return lchown(rpath(fs_ctx, path), credp->fc_uid, credp->fc_gid);
+ }
+ return -1;
}
static int local_utime(FsContext *ctx, const char *path,
@@ -253,8 +466,6 @@ static int local_remove(FsContext *ctx, const char *path)
static int local_fsync(FsContext *ctx, int fd)
{
- if (0) /* Just to supress the warning. Will be removed in next patch. */
- (void)local_set_xattr(NULL, NULL);
return fsync(fd);
}
@@ -274,7 +485,6 @@ FileOperations local_ops = {
.writev = local_writev,
.chmod = local_chmod,
.mknod = local_mknod,
- .mksock = local_mksock,
.mkdir = local_mkdir,
.fstat = local_fstat,
.open2 = local_open2,
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index a7ba4b6ab..f8c85c3d2 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -154,22 +154,32 @@ static int v9fs_do_writev(V9fsState *s, int fd, const struct iovec *iov,
static int v9fs_do_chmod(V9fsState *s, V9fsString *path, mode_t mode)
{
- return s->ops->chmod(&s->ctx, path->data, mode);
+ FsCred cred;
+ cred_init(&cred);
+ cred.fc_mode = mode;
+ return s->ops->chmod(&s->ctx, path->data, &cred);
}
-static int v9fs_do_mknod(V9fsState *s, V9fsString *path, mode_t mode, dev_t dev)
+static int v9fs_do_mknod(V9fsState *s, V9fsCreateState *vs, mode_t mode,
+ dev_t dev)
{
- return s->ops->mknod(&s->ctx, path->data, mode, dev);
+ FsCred cred;
+ cred_init(&cred);
+ cred.fc_uid = vs->fidp->uid;
+ cred.fc_mode = mode;
+ cred.fc_rdev = dev;
+ return s->ops->mknod(&s->ctx, vs->fullname.data, &cred);
}
-static int v9fs_do_mksock(V9fsState *s, V9fsString *path)
+static int v9fs_do_mkdir(V9fsState *s, V9fsCreateState *vs)
{
- return s->ops->mksock(&s->ctx, path->data);
-}
+ FsCred cred;
-static int v9fs_do_mkdir(V9fsState *s, V9fsString *path, mode_t mode)
-{
- return s->ops->mkdir(&s->ctx, path->data, mode);
+ cred_init(&cred);
+ cred.fc_uid = vs->fidp->uid;
+ cred.fc_mode = vs->perm & 0777;
+
+ return s->ops->mkdir(&s->ctx, vs->fullname.data, &cred);
}
static int v9fs_do_fstat(V9fsState *s, int fd, struct stat *stbuf)
@@ -177,15 +187,28 @@ static int v9fs_do_fstat(V9fsState *s, int fd, struct stat *stbuf)
return s->ops->fstat(&s->ctx, fd, stbuf);
}
-static int v9fs_do_open2(V9fsState *s, V9fsString *path, int flags, mode_t mode)
+static int v9fs_do_open2(V9fsState *s, V9fsCreateState *vs)
{
- return s->ops->open2(&s->ctx, path->data, flags, mode);
+ FsCred cred;
+ int flags;
+
+ cred_init(&cred);
+ cred.fc_uid = vs->fidp->uid;
+ cred.fc_mode = vs->perm & 0777;
+ flags = omode_to_uflags(vs->mode) | O_CREAT;
+
+ return s->ops->open2(&s->ctx, vs->fullname.data, flags, &cred);
}
-static int v9fs_do_symlink(V9fsState *s, V9fsString *oldpath,
- V9fsString *newpath)
+static int v9fs_do_symlink(V9fsState *s, V9fsCreateState *vs)
{
- return s->ops->symlink(&s->ctx, oldpath->data, newpath->data);
+ FsCred cred;
+ cred_init(&cred);
+ cred.fc_uid = vs->fidp->uid;
+ cred.fc_mode = vs->perm | 0777;
+
+ return s->ops->symlink(&s->ctx, vs->extension.data, vs->fullname.data,
+ &cred);
}
static int v9fs_do_link(V9fsState *s, V9fsString *oldpath, V9fsString *newpath)
@@ -206,7 +229,12 @@ static int v9fs_do_rename(V9fsState *s, V9fsString *oldpath,
static int v9fs_do_chown(V9fsState *s, V9fsString *path, uid_t uid, gid_t gid)
{
- return s->ops->chown(&s->ctx, path->data, uid, gid);
+ FsCred cred;
+ cred_init(&cred);
+ cred.fc_uid = uid;
+ cred.fc_gid = gid;
+
+ return s->ops->chown(&s->ctx, path->data, &cred);
}
static int v9fs_do_utime(V9fsState *s, V9fsString *path,
@@ -1707,22 +1735,6 @@ out:
v9fs_post_create(s, vs, err);
}
-static void v9fs_create_post_mksock(V9fsState *s, V9fsCreateState *vs,
- int err)
-{
- if (err) {
- err = -errno;
- goto out;
- }
-
- err = v9fs_do_chmod(s, &vs->fullname, vs->perm & 0777);
- v9fs_create_post_perms(s, vs, err);
- return;
-
-out:
- v9fs_post_create(s, vs, err);
-}
-
static void v9fs_create_post_fstat(V9fsState *s, V9fsCreateState *vs, int err)
{
if (err) {
@@ -1760,10 +1772,10 @@ static void v9fs_create_post_lstat(V9fsState *s, V9fsCreateState *vs, int err)
}
if (vs->perm & P9_STAT_MODE_DIR) {
- err = v9fs_do_mkdir(s, &vs->fullname, vs->perm & 0777);
+ err = v9fs_do_mkdir(s, vs);
v9fs_create_post_mkdir(s, vs, err);
} else if (vs->perm & P9_STAT_MODE_SYMLINK) {
- err = v9fs_do_symlink(s, &vs->extension, &vs->fullname);
+ err = v9fs_do_symlink(s, vs);
v9fs_create_post_perms(s, vs, err);
} else if (vs->perm & P9_STAT_MODE_LINK) {
int32_t nfid = atoi(vs->extension.data);
@@ -1798,18 +1810,16 @@ static void v9fs_create_post_lstat(V9fsState *s, V9fsCreateState *vs, int err)
}
nmode |= vs->perm & 0777;
- err = v9fs_do_mknod(s, &vs->fullname, nmode, makedev(major, minor));
+ err = v9fs_do_mknod(s, vs, nmode, makedev(major, minor));
v9fs_create_post_perms(s, vs, err);
} else if (vs->perm & P9_STAT_MODE_NAMED_PIPE) {
- err = v9fs_do_mknod(s, &vs->fullname, S_IFIFO | (vs->mode & 0777), 0);
+ err = v9fs_do_mknod(s, vs, S_IFIFO | (vs->perm & 0777), 0);
v9fs_post_create(s, vs, err);
} else if (vs->perm & P9_STAT_MODE_SOCKET) {
- err = v9fs_do_mksock(s, &vs->fullname);
- v9fs_create_post_mksock(s, vs, err);
+ err = v9fs_do_mknod(s, vs, S_IFSOCK | (vs->perm & 0777), 0);
+ v9fs_post_create(s, vs, err);
} else {
- vs->fidp->fd = v9fs_do_open2(s, &vs->fullname,
- omode_to_uflags(vs->mode) | O_CREAT,
- vs->perm & 0777);
+ vs->fidp->fd = v9fs_do_open2(s, vs);
v9fs_create_post_open2(s, vs, err);
}
@@ -2011,7 +2021,7 @@ static void v9fs_wstat_post_utime(V9fsState *s, V9fsWstatState *vs, int err)
goto out;
}
- if (vs->v9stat.n_gid != -1) {
+ if (vs->v9stat.n_gid != -1 || vs->v9stat.n_uid != -1) {
if (v9fs_do_chown(s, &vs->fidp->path, vs->v9stat.n_uid,
vs->v9stat.n_gid)) {
err = -errno;
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 00b367369..a592b86d7 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -155,7 +155,7 @@ static int virtio_pci_load_config(void * opaque, QEMUFile *f)
/* Try to find out if the guest has bus master disabled, but is
in ready state. Then we have a buggy guest OS. */
- if (!(proxy->vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) &&
+ if ((proxy->vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) &&
!(proxy->pci_dev.config[PCI_COMMAND] & PCI_COMMAND_MASTER)) {
proxy->bugs |= VIRTIO_PCI_BUG_BUS_MASTER;
}
diff --git a/kvm-all.c b/kvm-all.c
index 47f58a610..5f1a5535d 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -1053,18 +1053,8 @@ void kvm_setup_guest_memory(void *start, size_t size)
}
#ifdef KVM_CAP_SET_GUEST_DEBUG
-
-#ifdef KVM_UPSTREAM
-static void on_vcpu(CPUState *env, void (*func)(void *data), void *data)
-{
-#ifdef CONFIG_IOTHREAD
- if (env != cpu_single_env) {
- abort();
- }
-#endif
- func(data);
-}
-#else /* !KVM_UPSTREAM */
+#ifndef KVM_UPSTREAM
+#define run_on_cpu on_vcpu
static void on_vcpu(CPUState *env, void (*func)(void *data), void *data);
#endif /* !KVM_UPSTREAM */
@@ -1111,7 +1101,7 @@ int kvm_update_guest_debug(CPUState *env, unsigned long reinject_trap)
kvm_arch_update_guest_debug(env, &data.dbg);
data.env = env;
- on_vcpu(env, kvm_invoke_set_guest_debug, &data);
+ run_on_cpu(env, kvm_invoke_set_guest_debug, &data);
return data.err;
}
diff --git a/migration-exec.c b/migration-exec.c
index a8813b4fb..14718dd1d 100644
--- a/migration-exec.c
+++ b/migration-exec.c
@@ -121,20 +121,8 @@ err_after_alloc:
static void exec_accept_incoming_migration(void *opaque)
{
QEMUFile *f = opaque;
- int ret;
- ret = qemu_loadvm_state(f);
- if (ret < 0) {
- fprintf(stderr, "load of migration failed\n");
- goto err;
- }
- qemu_announce_self();
- DPRINTF("successfully loaded vm state\n");
-
- if (autostart)
- vm_start();
-
-err:
+ process_incoming_migration(f);
qemu_set_fd_handler2(qemu_stdio_fd(f), NULL, NULL, NULL, NULL);
qemu_fclose(f);
}
diff --git a/migration-fd.c b/migration-fd.c
index 0abd372af..6d1450563 100644
--- a/migration-fd.c
+++ b/migration-fd.c
@@ -104,20 +104,8 @@ err_after_alloc:
static void fd_accept_incoming_migration(void *opaque)
{
QEMUFile *f = opaque;
- int ret;
- ret = qemu_loadvm_state(f);
- if (ret < 0) {
- fprintf(stderr, "load of migration failed\n");
- goto err;
- }
- qemu_announce_self();
- DPRINTF("successfully loaded vm state\n");
-
- if (autostart)
- vm_start();
-
-err:
+ process_incoming_migration(f);
qemu_set_fd_handler2(qemu_stdio_fd(f), NULL, NULL, NULL, NULL);
qemu_fclose(f);
}
diff --git a/migration-tcp.c b/migration-tcp.c
index 43af2e045..78b56dc3f 100644
--- a/migration-tcp.c
+++ b/migration-tcp.c
@@ -141,7 +141,7 @@ static void tcp_accept_incoming_migration(void *opaque)
socklen_t addrlen = sizeof(addr);
int s = (unsigned long)opaque;
QEMUFile *f;
- int c, ret;
+ int c;
do {
c = qemu_accept(s, (struct sockaddr *)&addr, &addrlen);
@@ -160,18 +160,7 @@ static void tcp_accept_incoming_migration(void *opaque)
goto out;
}
- ret = qemu_loadvm_state(f);
- if (ret < 0) {
- fprintf(stderr, "load of migration failed\n");
- goto out_fopen;
- }
- qemu_announce_self();
- DPRINTF("successfully loaded vm state\n");
-
- if (autostart)
- vm_start();
-
-out_fopen:
+ process_incoming_migration(f);
qemu_fclose(f);
out:
qemu_set_fd_handler2(s, NULL, NULL, NULL, NULL);
diff --git a/migration-unix.c b/migration-unix.c
index 49de1b9e8..57232c07a 100644
--- a/migration-unix.c
+++ b/migration-unix.c
@@ -149,7 +149,7 @@ static void unix_accept_incoming_migration(void *opaque)
socklen_t addrlen = sizeof(addr);
int s = (unsigned long)opaque;
QEMUFile *f;
- int c, ret;
+ int c;
do {
c = qemu_accept(s, (struct sockaddr *)&addr, &addrlen);
@@ -168,18 +168,7 @@ static void unix_accept_incoming_migration(void *opaque)
goto out;
}
- ret = qemu_loadvm_state(f);
- if (ret < 0) {
- fprintf(stderr, "load of migration failed\n");
- goto out_fopen;
- }
- qemu_announce_self();
- DPRINTF("successfully loaded vm state\n");
-
- if (autostart)
- vm_start();
-
-out_fopen:
+ process_incoming_migration(f);
qemu_fclose(f);
out:
qemu_set_fd_handler2(s, NULL, NULL, NULL, NULL);
diff --git a/migration.c b/migration.c
index 64ed36e5e..b49964c5e 100644
--- a/migration.c
+++ b/migration.c
@@ -36,22 +36,39 @@ static uint32_t max_throttle = (32 << 20);
static MigrationState *current_migration;
-void qemu_start_incoming_migration(const char *uri)
+int qemu_start_incoming_migration(const char *uri)
{
const char *p;
+ int ret;
if (strstart(uri, "tcp:", &p))
- tcp_start_incoming_migration(p);
+ ret = tcp_start_incoming_migration(p);
#if !defined(WIN32)
else if (strstart(uri, "exec:", &p))
- exec_start_incoming_migration(p);
+ ret = exec_start_incoming_migration(p);
else if (strstart(uri, "unix:", &p))
- unix_start_incoming_migration(p);
+ ret = unix_start_incoming_migration(p);
else if (strstart(uri, "fd:", &p))
- fd_start_incoming_migration(p);
+ ret = fd_start_incoming_migration(p);
#endif
- else
+ else {
fprintf(stderr, "unknown migration protocol: %s\n", uri);
+ ret = -EPROTONOSUPPORT;
+ }
+ return ret;
+}
+
+void process_incoming_migration(QEMUFile *f)
+{
+ if (qemu_loadvm_state(f) < 0) {
+ fprintf(stderr, "load of migration failed\n");
+ exit(0);
+ }
+ qemu_announce_self();
+ DPRINTF("successfully loaded vm state\n");
+
+ if (autostart)
+ vm_start();
}
int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
diff --git a/migration.h b/migration.h
index 97eef4a0e..d13ed4fca 100644
--- a/migration.h
+++ b/migration.h
@@ -50,7 +50,9 @@ struct FdMigrationState
void *opaque;
};
-void qemu_start_incoming_migration(const char *uri);
+void process_incoming_migration(QEMUFile *f);
+
+int qemu_start_incoming_migration(const char *uri);
int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data);
diff --git a/osdep.c b/osdep.c
index 8a710e784..2375a69df 100644
--- a/osdep.c
+++ b/osdep.c
@@ -171,6 +171,13 @@ int qemu_create_pidfile(const char *filename)
#ifdef _WIN32
+/* mingw32 needs ffs for compilations without optimization. */
+int ffs(int i)
+{
+ /* Use gcc's builtin ffs. */
+ return __builtin_ffs(i);
+}
+
/* Offset between 1/1/1601 and 1/1/1970 in 100 nanosec units */
#define _W32_FT_OFFSET (116444736000000000ULL)
diff --git a/qemu-os-win32.h b/qemu-os-win32.h
index 6323f7f1a..2ff9f45a6 100644
--- a/qemu-os-win32.h
+++ b/qemu-os-win32.h
@@ -49,4 +49,8 @@ static inline void os_setup_post(void) {}
static inline void os_set_line_buffering(void) {}
static inline void os_set_proc_name(const char *dummy) {}
+#if !defined(EPROTONOSUPPORT)
+# define EPROTONOSUPPORT EINVAL
+#endif
+
#endif
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 9072a3495..a49bb9219 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -1158,6 +1158,7 @@ void do_cpu_init(CPUState *env)
cpu_reset(env);
env->interrupt_request = sipi;
apic_init_reset(env->apic_state);
+ env->halted = !cpu_is_bsp(env);
}
void do_cpu_sipi(CPUState *env)
diff --git a/vl.c b/vl.c
index 4211c46e4..80a929d5a 100644
--- a/vl.c
+++ b/vl.c
@@ -3054,7 +3054,12 @@ int main(int argc, char **argv, char **envp)
}
if (incoming) {
- qemu_start_incoming_migration(incoming);
+ int ret = qemu_start_incoming_migration(incoming);
+ if (ret < 0) {
+ fprintf(stderr, "Migration failed. Exit code %s(%d), exiting.\n",
+ incoming, ret);
+ exit(ret);
+ }
} else if (autostart) {
vm_start();
}