diff options
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | hw/file-op-9p.h | 13 | ||||
-rw-r--r-- | hw/fw_cfg.c | 80 | ||||
-rw-r--r-- | hw/marvell_88w8618_audio.c | 4 | ||||
-rw-r--r-- | hw/mips_jazz.c | 4 | ||||
-rw-r--r-- | hw/mips_malta.c | 4 | ||||
-rw-r--r-- | hw/musicpal.c | 4 | ||||
-rw-r--r-- | hw/omap2.c | 2 | ||||
-rw-r--r-- | hw/pc.c | 24 | ||||
-rw-r--r-- | hw/pc_piix.c | 2 | ||||
-rw-r--r-- | hw/slavio_intctl.c | 9 | ||||
-rw-r--r-- | hw/spitz.c | 4 | ||||
-rw-r--r-- | hw/virtio-9p-local.c | 292 | ||||
-rw-r--r-- | hw/virtio-9p.c | 92 | ||||
-rw-r--r-- | hw/virtio-pci.c | 2 | ||||
-rw-r--r-- | kvm-all.c | 16 | ||||
-rw-r--r-- | migration-exec.c | 14 | ||||
-rw-r--r-- | migration-fd.c | 14 | ||||
-rw-r--r-- | migration-tcp.c | 15 | ||||
-rw-r--r-- | migration-unix.c | 15 | ||||
-rw-r--r-- | migration.c | 29 | ||||
-rw-r--r-- | migration.h | 4 | ||||
-rw-r--r-- | osdep.c | 7 | ||||
-rw-r--r-- | qemu-os-win32.h | 4 | ||||
-rw-r--r-- | target-i386/helper.c | 1 | ||||
-rw-r--r-- | vl.c | 7 |
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; } @@ -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; } @@ -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); @@ -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) @@ -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(); } |