diff options
-rw-r--r-- | Changelog | 36 | ||||
-rw-r--r-- | VERSION | 2 | ||||
-rw-r--r-- | block/dmg.c | 28 | ||||
-rw-r--r-- | hw/fw_cfg.c | 18 | ||||
-rw-r--r-- | hw/loader.c | 55 | ||||
-rw-r--r-- | hw/loader.h | 7 | ||||
-rw-r--r-- | hw/pc.c | 29 | ||||
-rw-r--r-- | hw/pci.c | 15 | ||||
-rw-r--r-- | hw/pci.h | 1 | ||||
-rw-r--r-- | hw/virtio-pci.c | 2 | ||||
-rw-r--r-- | hw/vmware_vga.c | 7 | ||||
-rw-r--r-- | monitor.c | 5 | ||||
-rw-r--r-- | osdep.c | 2 | ||||
-rw-r--r-- | pc-bios/README | 3 | ||||
-rw-r--r-- | pc-bios/bios.bin | bin | 131072 -> 131072 bytes | |||
-rw-r--r-- | qemu-options.hx | 2 | ||||
m--------- | roms/seabios | 0 | ||||
-rw-r--r-- | slirp/tftp.c | 24 | ||||
-rw-r--r-- | target-i386/helper.c | 2 | ||||
-rw-r--r-- | target-i386/kvm.c | 1 | ||||
-rw-r--r-- | target-i386/translate.c | 2 | ||||
-rw-r--r-- | vl.c | 8 | ||||
-rw-r--r-- | vnc.c | 4 | ||||
-rw-r--r-- | vnchextile.h | 2 |
24 files changed, 193 insertions, 62 deletions
@@ -1,7 +1,41 @@ +version 0.12.2: + - Qemu's internal TFTP server breaks lock-step-iness of TFTP (Milan Plzik) + - osdep.c: Fix accept4 fallback (Kevin Wolf) + - pc: add rombar to compat properties for pc-0.10 and pc-0.11 (Gerd Hoffmann) + - pci: allow loading roms via fw_cfg. (Gerd Hoffmann) + - roms: rework rom loading via fw (Gerd Hoffmann) + - fw_cfg: rom loader tweaks. (Gerd Hoffmann) + - roms: minor fixes and cleanups. (Gerd Hoffmann) + - pc: add machine type for 0.12 (Gerd Hoffmann) + - loader: more ignores for rom intended to be loaded by the bios (Aurelien Jarno) + - vnc_refresh: return if vd->timer is NULL (Stefano Stabellini) + - QMP: Don't free async event's 'data' (Luiz Capitulino) + - Handle TFTP ERROR from client (Thomas Horsten) + - dmg: fix ->open failure (Christoph Hellwig) + - virtio-pci: thinko fix (Michael S. Tsirkin) + - pc-bios: Update README (SeaBIOS) (Stefan Weil) + - vmware_vga: Check cursor dimensions passed from guest to avoid buffer overflow (Roland Dreier) + - remove pending exception on vcpu reset. (Gleb Natapov) + - Fix CPU topology initialization (Jiri Denemark) + - MCE: Fix bug of IA32_MCG_STATUS after system reset (Huang Ying) + - linuxboot: fix gdt address calculation (Avi Kivity) + - QMP: Drop wrong assert() (Luiz Capitulino) + - vnc: Fix artifacts in hextile decoding (Anthony Liguori) + - target-i386: Fix "call im" on x86_64 when executing 32-bit code (Aurelien Jarno) + - Add missing newline at the end of options list (Michael Tokarev) + - Don't load options roms intended to be loaded by the bios in qemu (Avi Kivity) + - USB: Improve usbdevice error messages (Scott Tsai) + - cpu-all.h: fix cpu_get_real_ticks() #ifdef (Aurelien Jarno) + - alpha: fix compile (Blue Swirl) + - user_only: compile everything with -fpie (Kirill A. Shutemov) + - fdc/sparc32: don't hang on detection under OBP (Artyom Tarasenko) + - scsi-disk: Inquiry with allocation length of CDB < 36 (v4) (Artyom Tarasenko) + - e1000: fix init values for command register (Michael S. Tsirkin) + version 0.12.1: - loader: fix rom loading at address 0 (fixes target-arm) (Aurelien Jarno) - loader: fix rom_copy (fixes multiboot) (Kevin Wolf) - + version 0.12.0: - Update to SeaBIOS 0.5.0 @@ -1 +1 @@ -0.12.1 +0.12.2 diff --git a/block/dmg.c b/block/dmg.c index 262560ffd..f4c01c76b 100644 --- a/block/dmg.c +++ b/block/dmg.c @@ -90,24 +90,21 @@ static int dmg_open(BlockDriverState *bs, const char *filename, int flags) /* read offset of info blocks */ if(lseek(s->fd,-0x1d8,SEEK_END)<0) { -dmg_close: - close(s->fd); - /* open raw instead */ - bs->drv=bdrv_find_format("raw"); - return bs->drv->bdrv_open(bs, filename, flags); + goto fail; } + info_begin=read_off(s->fd); if(info_begin==0) - goto dmg_close; + goto fail; if(lseek(s->fd,info_begin,SEEK_SET)<0) - goto dmg_close; + goto fail; if(read_uint32(s->fd)!=0x100) - goto dmg_close; + goto fail; if((count = read_uint32(s->fd))==0) - goto dmg_close; + goto fail; info_end = info_begin+count; if(lseek(s->fd,0xf8,SEEK_CUR)<0) - goto dmg_close; + goto fail; /* read offsets */ last_in_offset = last_out_offset = 0; @@ -116,14 +113,14 @@ dmg_close: count = read_uint32(s->fd); if(count==0) - goto dmg_close; + goto fail; type = read_uint32(s->fd); if(type!=0x6d697368 || count<244) lseek(s->fd,count-4,SEEK_CUR); else { int new_size, chunk_count; if(lseek(s->fd,200,SEEK_CUR)<0) - goto dmg_close; + goto fail; chunk_count = (count-204)/40; new_size = sizeof(uint64_t) * (s->n_chunks + chunk_count); s->types = qemu_realloc(s->types, new_size/2); @@ -142,7 +139,7 @@ dmg_close: chunk_count--; i--; if(lseek(s->fd,36,SEEK_CUR)<0) - goto dmg_close; + goto fail; continue; } read_uint32(s->fd); @@ -163,11 +160,14 @@ dmg_close: s->compressed_chunk = qemu_malloc(max_compressed_size+1); s->uncompressed_chunk = qemu_malloc(512*max_sectors_per_chunk); if(inflateInit(&s->zstream) != Z_OK) - goto dmg_close; + goto fail; s->current_chunk = s->n_chunks; return 0; +fail: + close(s->fd); + return -1; } static inline int is_sector_in_chunk(BDRVDMGState* s, diff --git a/hw/fw_cfg.c b/hw/fw_cfg.c index fe9c52758..ea120ba55 100644 --- a/hw/fw_cfg.c +++ b/hw/fw_cfg.c @@ -278,7 +278,7 @@ int fw_cfg_add_file(FWCfgState *s, const char *dir, const char *filename, uint8_t *data, uint32_t len) { const char *basename; - int index; + int i, index; if (!s->files) { int dsize = sizeof(uint32_t) + sizeof(FWCfgFile) * FW_CFG_FILE_SLOTS; @@ -300,13 +300,17 @@ int fw_cfg_add_file(FWCfgState *s, const char *dir, const char *filename, } else { basename = filename; } - if (dir) { - snprintf(s->files->f[index].name, sizeof(s->files->f[index].name), - "%s/%s", dir, basename); - } else { - snprintf(s->files->f[index].name, sizeof(s->files->f[index].name), - "%s", basename); + + snprintf(s->files->f[index].name, sizeof(s->files->f[index].name), + "%s/%s", dir, basename); + for (i = 0; i < index; i++) { + if (strcmp(s->files->f[index].name, s->files->f[i].name) == 0) { + FW_CFG_DPRINTF("%s: skip duplicate: %s\n", __FUNCTION__, + s->files->f[index].name); + return 1; + } } + s->files->f[index].size = cpu_to_be32(len); s->files->f[index].select = cpu_to_be16(FW_CFG_FILE_FIRST + index); FW_CFG_DPRINTF("%s: #%d: %s (%d bytes)\n", __FUNCTION__, diff --git a/hw/loader.c b/hw/loader.c index eef385eb5..b3bbd77d1 100644 --- a/hw/loader.c +++ b/hw/loader.c @@ -535,6 +535,7 @@ struct Rom { QTAILQ_ENTRY(Rom) next; }; +static FWCfgState *fw_cfg; static QTAILQ_HEAD(, Rom) roms = QTAILQ_HEAD_INITIALIZER(roms); int rom_enable_driver_roms; @@ -556,7 +557,7 @@ static void rom_insert(Rom *rom) QTAILQ_INSERT_TAIL(&roms, rom, next); } -int rom_add_file(const char *file, const char *fw_dir, const char *fw_file, +int rom_add_file(const char *file, const char *fw_dir, target_phys_addr_t addr) { Rom *rom; @@ -576,8 +577,10 @@ int rom_add_file(const char *file, const char *fw_dir, const char *fw_file, goto err; } - rom->fw_dir = fw_dir ? qemu_strdup(fw_dir) : NULL; - rom->fw_file = fw_file ? qemu_strdup(fw_file) : NULL; + if (fw_dir) { + rom->fw_dir = qemu_strdup(fw_dir); + rom->fw_file = qemu_strdup(file); + } rom->addr = addr; rom->romsize = lseek(fd, 0, SEEK_END); rom->data = qemu_mallocz(rom->romsize); @@ -590,6 +593,8 @@ int rom_add_file(const char *file, const char *fw_dir, const char *fw_file, } close(fd); rom_insert(rom); + if (rom->fw_file && fw_cfg) + fw_cfg_add_file(fw_cfg, rom->fw_dir, rom->fw_file, rom->data, rom->romsize); return 0; err: @@ -621,14 +626,14 @@ int rom_add_vga(const char *file) { if (!rom_enable_driver_roms) return 0; - return rom_add_file(file, "vgaroms", file, 0); + return rom_add_file(file, "vgaroms", 0); } int rom_add_option(const char *file) { if (!rom_enable_driver_roms) return 0; - return rom_add_file(file, "genroms", file, 0); + return rom_add_file(file, "genroms", 0); } static void rom_reset(void *unused) @@ -639,8 +644,9 @@ static void rom_reset(void *unused) if (rom->fw_file) { continue; } - if (rom->data == NULL) + if (rom->data == NULL) { continue; + } cpu_physical_memory_write_rom(rom->addr, rom->data, rom->romsize); if (rom->isrom) { /* rom needs to be written only once */ @@ -678,16 +684,9 @@ int rom_load_all(void) return 0; } -int rom_load_fw(void *fw_cfg) +void rom_set_fw(void *f) { - Rom *rom; - - QTAILQ_FOREACH(rom, &roms, next) { - if (!rom->fw_file) - continue; - fw_cfg_add_file(fw_cfg, rom->fw_dir, rom->fw_file, rom->data, rom->romsize); - } - return 0; + fw_cfg = f; } static Rom *find_rom(target_phys_addr_t addr) @@ -695,10 +694,15 @@ static Rom *find_rom(target_phys_addr_t addr) Rom *rom; QTAILQ_FOREACH(rom, &roms, next) { - if (rom->addr > addr) + if (rom->fw_file) { continue; - if (rom->addr + rom->romsize < addr) + } + if (rom->addr > addr) { + continue; + } + if (rom->addr + rom->romsize < addr) { continue; + } return rom; } return NULL; @@ -717,12 +721,18 @@ int rom_copy(uint8_t *dest, target_phys_addr_t addr, size_t size) Rom *rom; QTAILQ_FOREACH(rom, &roms, next) { - if (rom->addr + rom->romsize < addr) + if (rom->fw_file) { continue; - if (rom->addr > end) + } + if (rom->addr + rom->romsize < addr) { + continue; + } + if (rom->addr > end) { break; - if (!rom->data) + } + if (!rom->data) { continue; + } d = dest + (rom->addr - addr); s = rom->data; @@ -765,10 +775,9 @@ void do_info_roms(Monitor *mon) rom->isrom ? "rom" : "ram", rom->name); } else { - monitor_printf(mon, "fw=%s%s%s" + monitor_printf(mon, "fw=%s/%s" " size=0x%06zx name=\"%s\" \n", - rom->fw_dir ? rom->fw_dir : "", - rom->fw_dir ? "/" : "", + rom->fw_dir, rom->fw_file, rom->romsize, rom->name); diff --git a/hw/loader.h b/hw/loader.h index 77beb0e93..8ff3c9445 100644 --- a/hw/loader.h +++ b/hw/loader.h @@ -19,18 +19,19 @@ void pstrcpy_targphys(const char *name, target_phys_addr_t dest, int buf_size, const char *source); -int rom_add_file(const char *file, const char *fw_dir, const char *fw_file, + +int rom_add_file(const char *file, const char *fw_dir, target_phys_addr_t addr); int rom_add_blob(const char *name, const void *blob, size_t len, target_phys_addr_t addr); int rom_load_all(void); -int rom_load_fw(void *fw_cfg); +void rom_set_fw(void *f); int rom_copy(uint8_t *dest, target_phys_addr_t addr, size_t size); void *rom_ptr(target_phys_addr_t addr); void do_info_roms(Monitor *mon); #define rom_add_file_fixed(_f, _a) \ - rom_add_file(_f, NULL, NULL, _a) + rom_add_file(_f, NULL, _a) #define rom_add_blob_fixed(_f, _b, _l, _a) \ rom_add_blob(_f, _b, _l, _a) @@ -1105,6 +1105,7 @@ static void pc_init1(ram_addr_t ram_size, bios_size, bios_offset | IO_MEM_ROM); fw_cfg = bochs_bios_init(); + rom_set_fw(fw_cfg); if (linux_boot) { load_linux(fw_cfg, kernel_filename, initrd_filename, kernel_cmdline, below_4g_mem_size); @@ -1292,8 +1293,6 @@ static void pc_init1(ram_addr_t ram_size, } } - rom_load_fw(fw_cfg); - #ifdef CONFIG_KVM_DEVICE_ASSIGNMENT if (kvm_enabled()) { add_assigned_devices(pci_bus, assigned_devices, assigned_devices_index); @@ -1336,7 +1335,7 @@ void cmos_set_s3_resume(void) } static QEMUMachine pc_machine = { - .name = "pc-0.11", + .name = "pc-0.12", .alias = "pc", .desc = "Standard PC", .init = pc_init_pci, @@ -1344,6 +1343,25 @@ static QEMUMachine pc_machine = { .is_default = 1, }; +static QEMUMachine pc_machine_v0_11 = { + .name = "pc-0.11", + .desc = "Standard PC, qemu 0.11", + .init = pc_init_pci, + .max_cpus = 255, + .compat_props = (GlobalProperty[]) { + { + .driver = "virtio-blk-pci", + .property = "vectors", + .value = stringify(0), + },{ + .driver = "PCI", + .property = "rombar", + .value = stringify(0), + }, + { /* end of list */ } + } +}; + static QEMUMachine pc_machine_v0_10 = { .name = "pc-0.10", .desc = "Standard PC, qemu 0.10", @@ -1366,6 +1384,10 @@ static QEMUMachine pc_machine_v0_10 = { .driver = "virtio-blk-pci", .property = "vectors", .value = stringify(0), + },{ + .driver = "PCI", + .property = "rombar", + .value = stringify(0), }, { /* end of list */ } }, @@ -1381,6 +1403,7 @@ static QEMUMachine isapc_machine = { static void pc_machine_init(void) { qemu_register_machine(&pc_machine); + qemu_register_machine(&pc_machine_v0_11); qemu_register_machine(&pc_machine_v0_10); qemu_register_machine(&isapc_machine); } @@ -67,6 +67,7 @@ static struct BusInfo pci_bus_info = { .props = (Property[]) { DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1), DEFINE_PROP_STRING("romfile", PCIDevice, romfile), + DEFINE_PROP_UINT32("rombar", PCIDevice, rom_bar, 1), DEFINE_PROP_END_OF_LIST() } }; @@ -1612,6 +1613,20 @@ static int pci_add_option_rom(PCIDevice *pdev) if (strlen(pdev->romfile) == 0) return 0; + if (!pdev->rom_bar) { + /* + * Load rom via fw_cfg instead of creating a rom bar, + * for 0.11 compatibility. + */ + int class = pci_get_word(pdev->config + PCI_CLASS_DEVICE); + if (class == 0x0300) { + rom_add_vga(pdev->romfile); + } else { + rom_add_option(pdev->romfile); + } + return 0; + } + path = qemu_find_file(QEMU_FILE_TYPE_BIOS, pdev->romfile); if (path == NULL) { path = qemu_strdup(pdev->romfile); @@ -271,6 +271,7 @@ struct PCIDevice { /* Location of option rom */ char *romfile; ram_addr_t rom_offset; + uint32_t rom_bar; /* How much space does an MSIX table need. */ /* The spec requires giving the table structure diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index 62b46bd48..359415226 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -372,7 +372,7 @@ static void virtio_write_config(PCIDevice *pci_dev, uint32_t address, if (PCI_COMMAND == address) { if (!(val & PCI_COMMAND_MASTER)) { - proxy->vdev->status &= !VIRTIO_CONFIG_S_DRIVER_OK; + proxy->vdev->status &= ~VIRTIO_CONFIG_S_DRIVER_OK; } } diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c index 7ab1c7910..5e969aedb 100644 --- a/hw/vmware_vga.c +++ b/hw/vmware_vga.c @@ -562,6 +562,13 @@ static void vmsvga_fifo_run(struct vmsvga_state_s *s) cursor.height = y = vmsvga_fifo_read(s); vmsvga_fifo_read(s); cursor.bpp = vmsvga_fifo_read(s); + + if (SVGA_BITMAP_SIZE(x, y) > sizeof cursor.mask || + SVGA_PIXMAP_SIZE(x, y, cursor.bpp) > sizeof cursor.image) { + args = SVGA_BITMAP_SIZE(x, y) + SVGA_PIXMAP_SIZE(x, y, cursor.bpp); + goto badcmd; + } + for (args = 0; args < SVGA_BITMAP_SIZE(x, y); args ++) cursor.mask[args] = vmsvga_fifo_read_raw(s); for (args = 0; args < SVGA_PIXMAP_SIZE(x, y, cursor.bpp); args ++) @@ -286,7 +286,6 @@ static void monitor_protocol_emitter(Monitor *mon, QObject *data) if (!monitor_has_error(mon)) { /* success response */ if (data) { - assert(qobject_type(data) == QTYPE_QDICT); qobject_incref(data); qdict_put_obj(qmp, "return", data); } else { @@ -369,8 +368,10 @@ void monitor_protocol_event(MonitorEvent event, QObject *data) qmp = qdict_new(); timestamp_put(qmp); qdict_put(qmp, "event", qstring_from_str(event_name)); - if (data) + if (data) { + qobject_incref(data); qdict_put_obj(qmp, "data", data); + } monitor_json_emitter(mon, QOBJECT(qmp)); QDECREF(qmp); @@ -310,7 +310,7 @@ int qemu_accept(int s, struct sockaddr *addr, socklen_t *addrlen) #ifdef CONFIG_ACCEPT4 ret = accept4(s, addr, addrlen, SOCK_CLOEXEC); - if (ret != -1 || errno != EINVAL) { + if (ret != -1 || errno != ENOSYS) { return ret; } #endif diff --git a/pc-bios/README b/pc-bios/README index 9eaa52262..5be01f829 100644 --- a/pc-bios/README +++ b/pc-bios/README @@ -1,4 +1,5 @@ -- The PC BIOS comes from the Bochs project (http://bochs.sourceforge.net/). +- SeaBIOS (bios.bin) is the successor of pc bios. + See http://www.seabios.org/ for more information. - The VGA BIOS and the Cirrus VGA BIOS come from the LGPL VGA bios project (http://www.nongnu.org/vgabios/). diff --git a/pc-bios/bios.bin b/pc-bios/bios.bin Binary files differindex 827327db9..1741eeced 100644 --- a/pc-bios/bios.bin +++ b/pc-bios/bios.bin diff --git a/qemu-options.hx b/qemu-options.hx index 812d0670a..ca73ba5db 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1937,7 +1937,7 @@ DEF("readconfig", HAS_ARG, QEMU_OPTION_readconfig, "-readconfig <file>\n") DEF("writeconfig", HAS_ARG, QEMU_OPTION_writeconfig, "-writeconfig <file>\n" - " read/write config file") + " read/write config file\n") DEF("no-kvm", 0, QEMU_OPTION_no_kvm, "-no-kvm disable KVM hardware virtualization\n") diff --git a/roms/seabios b/roms/seabios -Subproject 494302fe196f7016d56814f0adc83ba1d54c051 +Subproject 5da68339ecf44677b8f4f115cdf3cb1da46a9f6 diff --git a/slirp/tftp.c b/slirp/tftp.c index 082f5d040..96c0e0c67 100644 --- a/slirp/tftp.c +++ b/slirp/tftp.c @@ -264,6 +264,12 @@ static void tftp_handle_rrq(Slirp *slirp, struct tftp_t *tp, int pktlen) size_t prefix_len; char *req_fname; + /* check if a session already exists and if so terminate it */ + s = tftp_session_find(slirp, tp); + if (s >= 0) { + tftp_session_terminate(&slirp->tftp_sessions[s]); + } + s = tftp_session_allocate(slirp, tp); if (s < 0) { @@ -362,6 +368,7 @@ static void tftp_handle_rrq(Slirp *slirp, struct tftp_t *tp, int pktlen) } tftp_send_oack(spt, "tsize", tsize, tp); + return; } } @@ -385,6 +392,19 @@ static void tftp_handle_ack(Slirp *slirp, struct tftp_t *tp, int pktlen) } } +static void tftp_handle_error(Slirp *slirp, struct tftp_t *tp, int pktlen) +{ + int s; + + s = tftp_session_find(slirp, tp); + + if (s < 0) { + return; + } + + tftp_session_terminate(&slirp->tftp_sessions[s]); +} + void tftp_input(struct mbuf *m) { struct tftp_t *tp = (struct tftp_t *)m->m_data; @@ -397,5 +417,9 @@ void tftp_input(struct mbuf *m) case TFTP_ACK: tftp_handle_ack(m->slirp, tp, m->m_len); break; + + case TFTP_ERROR: + tftp_handle_error(m->slirp, tp, m->m_len); + break; } } diff --git a/target-i386/helper.c b/target-i386/helper.c index b58fd8253..fb22f88d8 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -619,6 +619,8 @@ void cpu_reset(CPUX86State *env) env->dr[7] = DR7_FIXED_1; cpu_breakpoint_remove_all(env, BP_CPU); cpu_watchpoint_remove_all(env, BP_CPU); + + env->mcg_status = 0; } void cpu_x86_close(CPUX86State *env) diff --git a/target-i386/kvm.c b/target-i386/kvm.c index 8584507ab..c338bf7cd 100644 --- a/target-i386/kvm.c +++ b/target-i386/kvm.c @@ -228,6 +228,7 @@ int kvm_arch_init_vcpu(CPUState *env) void kvm_arch_reset_vcpu(CPUState *env) { + env->exception_injected = -1; env->interrupt_injected = -1; env->nmi_injected = 0; env->nmi_pending = 0; diff --git a/target-i386/translate.c b/target-i386/translate.c index 64bc0a3f3..511a4eae9 100644 --- a/target-i386/translate.c +++ b/target-i386/translate.c @@ -6259,6 +6259,8 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start) tval += next_eip; if (s->dflag == 0) tval &= 0xffff; + else if(!CODE64(s)) + tval &= 0xffffffff; gen_movtl_T0_im(next_eip); gen_push_T0(s); gen_jmp(s, tval); @@ -3528,10 +3528,10 @@ void qemu_init_vcpu(void *_env) { CPUState *env = _env; - if (kvm_enabled()) - kvm_init_vcpu(env); env->nr_cores = smp_cores; env->nr_threads = smp_threads; + if (kvm_enabled()) + kvm_init_vcpu(env); return; } @@ -3863,12 +3863,12 @@ void qemu_init_vcpu(void *_env) { CPUState *env = _env; + env->nr_cores = smp_cores; + env->nr_threads = smp_threads; if (kvm_enabled()) kvm_start_vcpu(env); else tcg_init_vcpu(env); - env->nr_cores = smp_cores; - env->nr_threads = smp_threads; } void qemu_notify_event(void) @@ -2305,6 +2305,10 @@ static void vnc_refresh(void *opaque) rects += vnc_update_client(vs, has_dirty); vs = vs->next; } + /* vd->timer could be NULL now if the last client disconnected, + * in this case don't update the timer */ + if (vd->timer == NULL) + return; if (has_dirty && rects) { vd->timer_interval /= 2; diff --git a/vnchextile.h b/vnchextile.h index 432ed89af..78ed8c4e9 100644 --- a/vnchextile.h +++ b/vnchextile.h @@ -165,6 +165,8 @@ static void CONCAT(send_hextile_tile_, NAME)(VncState *vs, irow += ds_get_linesize(vs->ds) / sizeof(pixel_t); } + /* A SubrectsColoured subtile invalidates the foreground color */ + *has_fg = 0; if (n_data > (w * h * sizeof(pixel_t))) { n_colors = 4; flags = 0x01; |