diff --git a/block/iscsi.c b/block/iscsi.c index 267f160bf6..506bf5f875 100644 --- a/block/iscsi.c +++ b/block/iscsi.c @@ -225,9 +225,9 @@ static inline unsigned exp_random(double mean) static int iscsi_translate_sense(struct scsi_sense *sense) { - return - scsi_sense_to_errno(sense->key, - (sense->ascq & 0xFF00) >> 8, - sense->ascq & 0xFF); + return scsi_sense_to_errno(sense->key, + (sense->ascq & 0xFF00) >> 8, + sense->ascq & 0xFF); } /* Called (via iscsi_service) with QemuMutex held. */ @@ -244,13 +244,6 @@ iscsi_co_generic_cb(struct iscsi_context *iscsi, int status, if (status != SCSI_STATUS_GOOD) { if (iTask->retries++ < ISCSI_CMD_RETRIES) { - if (status == SCSI_STATUS_CHECK_CONDITION - && task->sense.key == SCSI_SENSE_UNIT_ATTENTION) { - error_report("iSCSI CheckCondition: %s", - iscsi_get_error(iscsi)); - iTask->do_retry = 1; - goto out; - } if (status == SCSI_STATUS_BUSY || status == SCSI_STATUS_TIMEOUT || status == SCSI_STATUS_TASK_SET_FULL) { @@ -272,14 +265,20 @@ iscsi_co_generic_cb(struct iscsi_context *iscsi, int status, timer_mod(&iTask->retry_timer, qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + retry_time); iTask->do_retry = 1; - return; + } + } else if (status == SCSI_STATUS_CHECK_CONDITION) { + int error = iscsi_translate_sense(&task->sense); + if (error == EAGAIN) { + error_report("iSCSI CheckCondition: %s", + iscsi_get_error(iscsi)); + iTask->do_retry = 1; + } else { + iTask->err_code = -error; + iTask->err_str = g_strdup(iscsi_get_error(iscsi)); } } - iTask->err_code = iscsi_translate_sense(&task->sense); - iTask->err_str = g_strdup(iscsi_get_error(iscsi)); } -out: if (iTask->co) { aio_bh_schedule_oneshot(iTask->iscsilun->aio_context, iscsi_co_generic_bh_cb, iTask); @@ -974,7 +973,7 @@ iscsi_aio_ioctl_cb(struct iscsi_context *iscsi, int status, if (status < 0) { error_report("Failed to ioctl(SG_IO) to iSCSI lun. %s", iscsi_get_error(iscsi)); - acb->status = iscsi_translate_sense(&acb->task->sense); + acb->status = -iscsi_translate_sense(&acb->task->sense); } acb->ioh->driver_status = 0; diff --git a/configure b/configure index 4983c8b533..eb635c3b9a 100755 --- a/configure +++ b/configure @@ -7159,7 +7159,7 @@ if test "$live_block_migration" = "yes" ; then fi if test "$tpm" = "yes"; then - echo 'CONFIG_TPM=$(CONFIG_SOFTMMU)' >> $config_host_mak + echo 'CONFIG_TPM=y' >> $config_host_mak fi echo "TRACE_BACKENDS=$trace_backends" >> $config_host_mak diff --git a/contrib/rdmacm-mux/main.c b/contrib/rdmacm-mux/main.c index 30c7052651..de53048f06 100644 --- a/contrib/rdmacm-mux/main.c +++ b/contrib/rdmacm-mux/main.c @@ -115,7 +115,7 @@ static void parse_args(int argc, char *argv[]) case 's': /* This is temporary, final name will build below */ - strncpy(unix_socket_path, optarg, SOCKET_PATH_MAX); + strncpy(unix_socket_path, optarg, SOCKET_PATH_MAX - 1); break; case 'p': diff --git a/hw/Makefile.objs b/hw/Makefile.objs index d770926ba9..ece6cc3755 100644 --- a/hw/Makefile.objs +++ b/hw/Makefile.objs @@ -1,42 +1,45 @@ +devices-dirs-y = core/ +ifeq ($(CONFIG_SOFTMMU), y) devices-dirs-$(call lor,$(CONFIG_VIRTIO_9P),$(call land,$(CONFIG_VIRTFS),$(CONFIG_XEN))) += 9pfs/ -devices-dirs-$(CONFIG_SOFTMMU) += acpi/ -devices-dirs-$(CONFIG_SOFTMMU) += adc/ -devices-dirs-$(CONFIG_SOFTMMU) += audio/ -devices-dirs-$(CONFIG_SOFTMMU) += block/ -devices-dirs-$(CONFIG_SOFTMMU) += bt/ -devices-dirs-$(CONFIG_SOFTMMU) += char/ -devices-dirs-$(CONFIG_SOFTMMU) += cpu/ -devices-dirs-$(CONFIG_SOFTMMU) += display/ -devices-dirs-$(CONFIG_SOFTMMU) += dma/ -devices-dirs-$(CONFIG_SOFTMMU) += gpio/ +devices-dirs-y += acpi/ +devices-dirs-y += adc/ +devices-dirs-y += audio/ +devices-dirs-y += block/ +devices-dirs-y += bt/ +devices-dirs-y += char/ +devices-dirs-y += cpu/ +devices-dirs-y += display/ +devices-dirs-y += dma/ +devices-dirs-y += gpio/ devices-dirs-$(CONFIG_HYPERV) += hyperv/ devices-dirs-$(CONFIG_I2C) += i2c/ -devices-dirs-$(CONFIG_SOFTMMU) += ide/ -devices-dirs-$(CONFIG_SOFTMMU) += input/ -devices-dirs-$(CONFIG_SOFTMMU) += intc/ +devices-dirs-y += ide/ +devices-dirs-y += input/ +devices-dirs-y += intc/ devices-dirs-$(CONFIG_IPACK) += ipack/ devices-dirs-$(CONFIG_IPMI) += ipmi/ -devices-dirs-$(CONFIG_SOFTMMU) += isa/ -devices-dirs-$(CONFIG_SOFTMMU) += misc/ -devices-dirs-$(CONFIG_SOFTMMU) += net/ -devices-dirs-$(CONFIG_SOFTMMU) += rdma/ -devices-dirs-$(CONFIG_SOFTMMU) += nvram/ -devices-dirs-$(CONFIG_SOFTMMU) += pci/ +devices-dirs-y += isa/ +devices-dirs-y += misc/ +devices-dirs-y += net/ +devices-dirs-y += rdma/ +devices-dirs-y += nvram/ +devices-dirs-y += pci/ devices-dirs-$(CONFIG_PCI) += pci-bridge/ pci-host/ -devices-dirs-$(CONFIG_SOFTMMU) += pcmcia/ +devices-dirs-y += pcmcia/ devices-dirs-$(CONFIG_SCSI) += scsi/ -devices-dirs-$(CONFIG_SOFTMMU) += sd/ -devices-dirs-$(CONFIG_SOFTMMU) += ssi/ -devices-dirs-$(CONFIG_SOFTMMU) += timer/ +devices-dirs-y += sd/ +devices-dirs-y += ssi/ +devices-dirs-y += timer/ devices-dirs-$(CONFIG_TPM) += tpm/ -devices-dirs-$(CONFIG_SOFTMMU) += usb/ +devices-dirs-y += usb/ devices-dirs-$(CONFIG_VFIO) += vfio/ -devices-dirs-$(CONFIG_SOFTMMU) += virtio/ -devices-dirs-$(CONFIG_SOFTMMU) += watchdog/ -devices-dirs-$(CONFIG_SOFTMMU) += xen/ +devices-dirs-y += virtio/ +devices-dirs-y += watchdog/ +devices-dirs-y += xen/ devices-dirs-$(CONFIG_MEM_DEVICE) += mem/ -devices-dirs-$(CONFIG_SOFTMMU) += smbios/ devices-dirs-y += semihosting/ -devices-dirs-y += core/ +devices-dirs-y += smbios/ +endif + common-obj-y += $(devices-dirs-y) obj-y += $(devices-dirs-y) diff --git a/hw/i386/Kconfig b/hw/i386/Kconfig index 4ddf2a9c55..b9c96ac361 100644 --- a/hw/i386/Kconfig +++ b/hw/i386/Kconfig @@ -51,6 +51,7 @@ config PC_ACPI config I440FX bool imply E1000_PCI + imply VMPORT select PC_PCI select PC_ACPI select ACPI_SMBUS @@ -58,7 +59,6 @@ config I440FX select IDE_PIIX select DIMM select SMBIOS - select VMPORT select VMMOUSE select FW_CFG_DMA @@ -77,6 +77,7 @@ config Q35 imply VTD imply AMD_IOMMU imply E1000E_PCI_EXPRESS + imply VMPORT select PC_PCI select PC_ACPI select PCI_EXPRESS_Q35 @@ -84,7 +85,6 @@ config Q35 select AHCI_ICH9 select DIMM select SMBIOS - select VMPORT select VMMOUSE select FW_CFG_DMA diff --git a/hw/i386/pc.c b/hw/i386/pc.c index c33ce47578..549c437050 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -83,6 +83,7 @@ #include "hw/mem/memory-device.h" #include "sysemu/replay.h" #include "qapi/qmp/qerror.h" +#include "config-devices.h" /* debug PC/ISA interrupts */ //#define DEBUG_IRQ @@ -2793,7 +2794,11 @@ static void pc_machine_initfn(Object *obj) pcms->max_ram_below_4g = 0; /* use default */ pcms->smm = ON_OFF_AUTO_AUTO; +#ifdef CONFIG_VMPORT pcms->vmport = ON_OFF_AUTO_AUTO; +#else + pcms->vmport = ON_OFF_AUTO_OFF; +#endif /* CONFIG_VMPORT */ /* acpi build is enabled by default if machine supports it */ pcms->acpi_build_enabled = PC_MACHINE_GET_CLASS(pcms)->has_acpi_build; pcms->smbus_enabled = true; diff --git a/hw/lm32/Kconfig b/hw/lm32/Kconfig index 3d09c2dd6f..ed2e3060b0 100644 --- a/hw/lm32/Kconfig +++ b/hw/lm32/Kconfig @@ -11,3 +11,4 @@ config MILKYMIST select PFLASH_CFI01 select FRAMEBUFFER select SD + select USB_OHCI diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index ed7295bfd7..8e95e3e38d 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -62,6 +62,7 @@ typedef struct SCSIDiskClass { DMAIOFunc *dma_readv; DMAIOFunc *dma_writev; bool (*need_fua_emulation)(SCSICommand *cmd); + void (*update_sense)(SCSIRequest *r); } SCSIDiskClass; typedef struct SCSIDiskReq { @@ -438,6 +439,7 @@ static bool scsi_handle_rw_error(SCSIDiskReq *r, int error, bool acct_failed) { bool is_read = (r->req.cmd.mode == SCSI_XFER_FROM_DEV); SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev); + SCSIDiskClass *sdc = (SCSIDiskClass *) object_get_class(OBJECT(s)); BlockErrorAction action = blk_get_error_action(s->qdev.conf.blk, is_read, error); @@ -452,13 +454,13 @@ static bool scsi_handle_rw_error(SCSIDiskReq *r, int error, bool acct_failed) * pause the host. */ assert(r->status && *r->status); - error = scsi_sense_buf_to_errno(r->req.sense, sizeof(r->req.sense)); - if (error == ECANCELED || error == EAGAIN || error == ENOTCONN || - error == 0) { + if (scsi_sense_buf_is_guest_recoverable(r->req.sense, sizeof(r->req.sense))) { /* These errors are handled by guest. */ + sdc->update_sense(&r->req); scsi_req_complete(&r->req, *r->status); return true; } + error = scsi_sense_buf_to_errno(r->req.sense, sizeof(r->req.sense)); break; case ENOMEDIUM: scsi_check_condition(r, SENSE_CODE(NO_MEDIUM)); @@ -2894,6 +2896,12 @@ static int scsi_block_parse_cdb(SCSIDevice *d, SCSICommand *cmd, } } +static void scsi_block_update_sense(SCSIRequest *req) +{ + SCSIDiskReq *r = DO_UPCAST(SCSIDiskReq, req, req); + SCSIBlockReq *br = DO_UPCAST(SCSIBlockReq, req, r); + r->req.sense_len = MIN(br->io_header.sb_len_wr, sizeof(r->req.sense)); +} #endif static @@ -3059,6 +3067,7 @@ static void scsi_block_class_initfn(ObjectClass *klass, void *data) sc->parse_cdb = scsi_block_parse_cdb; sdc->dma_readv = scsi_block_dma_readv; sdc->dma_writev = scsi_block_dma_writev; + sdc->update_sense = scsi_block_update_sense; sdc->need_fua_emulation = scsi_block_no_fua; dc->desc = "SCSI block device passthrough"; dc->props = scsi_block_properties; diff --git a/hw/usb/Kconfig b/hw/usb/Kconfig index 564305e283..555e09377b 100644 --- a/hw/usb/Kconfig +++ b/hw/usb/Kconfig @@ -19,13 +19,16 @@ config USB_OHCI_PCI config USB_EHCI bool - default y if PCI_DEVICES - depends on PCI select USB +config USB_EHCI_PCI + bool + default y if PCI_DEVICES + select USB_EHCI + config USB_EHCI_SYSBUS bool - select USB + select USB_EHCI config USB_XHCI bool @@ -37,7 +40,7 @@ config USB_XHCI_NEC bool default y if PCI_DEVICES depends on PCI - select USB + select USB_XHCI config USB_MUSB bool diff --git a/hw/usb/Makefile.objs b/hw/usb/Makefile.objs index 81688f6e70..303ac084a0 100644 --- a/hw/usb/Makefile.objs +++ b/hw/usb/Makefile.objs @@ -6,8 +6,9 @@ common-obj-$(CONFIG_USB) += desc.o desc-msos.o common-obj-$(CONFIG_USB_UHCI) += hcd-uhci.o common-obj-$(CONFIG_USB_OHCI) += hcd-ohci.o common-obj-$(CONFIG_USB_OHCI_PCI) += hcd-ohci-pci.o -common-obj-$(CONFIG_USB_EHCI) += hcd-ehci.o hcd-ehci-pci.o -common-obj-$(CONFIG_USB_EHCI_SYSBUS) += hcd-ehci.o hcd-ehci-sysbus.o +common-obj-$(CONFIG_USB_EHCI) += hcd-ehci.o +common-obj-$(CONFIG_USB_EHCI_PCI) += hcd-ehci-pci.o +common-obj-$(CONFIG_USB_EHCI_SYSBUS) += hcd-ehci-sysbus.o common-obj-$(CONFIG_USB_XHCI) += hcd-xhci.o common-obj-$(CONFIG_USB_XHCI_NEC) += hcd-xhci-nec.o common-obj-$(CONFIG_USB_MUSB) += hcd-musb.o diff --git a/include/scsi/utils.h b/include/scsi/utils.h index 9351b21ead..fbc5588279 100644 --- a/include/scsi/utils.h +++ b/include/scsi/utils.h @@ -106,6 +106,7 @@ extern const struct SCSISense sense_code_SPACE_ALLOC_FAILED; int scsi_sense_to_errno(int key, int asc, int ascq); int scsi_sense_buf_to_errno(const uint8_t *sense, size_t sense_size); +bool scsi_sense_buf_is_guest_recoverable(const uint8_t *sense, size_t sense_size); int scsi_convert_sense(uint8_t *in_buf, int in_len, uint8_t *buf, int len, bool fixed); diff --git a/memory.c b/memory.c index beac26e173..d4579bbaec 100644 --- a/memory.c +++ b/memory.c @@ -321,7 +321,7 @@ static bool can_merge(FlatRange *r1, FlatRange *r2) /* Attempt to simplify a view by merging adjacent ranges */ static void flatview_simplify(FlatView *view) { - unsigned i, j; + unsigned i, j, k; i = 0; while (i < view->nr) { @@ -332,6 +332,9 @@ static void flatview_simplify(FlatView *view) ++j; } ++i; + for (k = i; k < j; k++) { + memory_region_unref(view->ranges[k].mr); + } memmove(&view->ranges[i], &view->ranges[j], (view->nr - j) * sizeof(view->ranges[j])); view->nr -= j - i; diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 2f81371ffb..d24c9441ee 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -262,6 +262,19 @@ our $UTF8 = qr{ | $NON_ASCII_UTF8 }x; +# some readers default to ISO-8859-1 when showing email source. detect +# when UTF-8 is incorrectly interpreted as ISO-8859-1 and reencoded back. +# False positives are possible but very unlikely. +our $UTF8_MOJIBAKE = qr{ + \xC3[\x82-\x9F] \xC2[\x80-\xBF] # c2-df 80-bf + | \xC3\xA0 \xC2[\xA0-\xBF] \xC2[\x80-\xBF] # e0 a0-bf 80-bf + | \xC3[\xA1-\xAC\xAE\xAF] (?: \xC2[\x80-\xBF]){2} # e1-ec/ee/ef 80-bf 80-bf + | \xC3\xAD \xC2[\x80-\x9F] \xC2[\x80-\xBF] # ed 80-9f 80-bf + | \xC3\xB0 \xC2[\x90-\xBF] (?: \xC2[\x80-\xBF]){2} # f0 90-bf 80-bf 80-bf + | \xC3[\xB1-\xB3] (?: \xC2[\x80-\xBF]){3} # f1-f3 80-bf 80-bf 80-bf + | \xC3\xB4 \xC2[\x80-\x8F] (?: \xC2[\x80-\xBF]){2} # f4 80-b8 80-bf 80-bf +}x; + # There are still some false positives, but this catches most # common cases. our $typeTypedefs = qr{(?x: @@ -1506,6 +1519,9 @@ sub process { ERROR("Invalid UTF-8, patch and commit message should be encoded in UTF-8\n" . $hereptr); } + if ($rawline =~ m/$UTF8_MOJIBAKE/) { + ERROR("Doubly-encoded UTF-8\n" . $herecurr); + } # Check if it's the start of a commit log # (not a header line and we haven't seen the patch filename) if ($in_header_lines && $realfile =~ /^$/ && diff --git a/scripts/create_config b/scripts/create_config index 00e86c82b0..6d8f08b39d 100755 --- a/scripts/create_config +++ b/scripts/create_config @@ -54,7 +54,7 @@ case $line in done echo " NULL" ;; - CONFIG_*='$(CONFIG_SOFTMMU)'|CONFIG_*=y) # configuration + CONFIG_*=y) # configuration name=${line%=*} echo "#define $name 1" ;; diff --git a/scsi/utils.c b/scsi/utils.c index 8738522955..c50e81fdb8 100644 --- a/scsi/utils.c +++ b/scsi/utils.c @@ -336,14 +336,50 @@ int scsi_convert_sense(uint8_t *in_buf, int in_len, } } +static bool scsi_sense_is_guest_recoverable(int key, int asc, int ascq) +{ + switch (key) { + case NO_SENSE: + case RECOVERED_ERROR: + case UNIT_ATTENTION: + case ABORTED_COMMAND: + return true; + case NOT_READY: + case ILLEGAL_REQUEST: + case DATA_PROTECT: + /* Parse ASCQ */ + break; + default: + return false; + } + + switch ((asc << 8) | ascq) { + case 0x1a00: /* PARAMETER LIST LENGTH ERROR */ + case 0x2000: /* INVALID OPERATION CODE */ + case 0x2400: /* INVALID FIELD IN CDB */ + case 0x2500: /* LOGICAL UNIT NOT SUPPORTED */ + case 0x2600: /* INVALID FIELD IN PARAMETER LIST */ + + case 0x2104: /* UNALIGNED WRITE COMMAND */ + case 0x2105: /* WRITE BOUNDARY VIOLATION */ + case 0x2106: /* ATTEMPT TO READ INVALID DATA */ + case 0x550e: /* INSUFFICIENT ZONE RESOURCES */ + + case 0x0401: /* NOT READY, IN PROGRESS OF BECOMING READY */ + case 0x0402: /* NOT READY, INITIALIZING COMMAND REQUIRED */ + return true; + default: + return false; + } +} + int scsi_sense_to_errno(int key, int asc, int ascq) { switch (key) { case NO_SENSE: case RECOVERED_ERROR: case UNIT_ATTENTION: - /* These sense keys are not errors */ - return 0; + return EAGAIN; case ABORTED_COMMAND: /* COMMAND ABORTED */ return ECANCELED; case NOT_READY: @@ -372,7 +408,7 @@ int scsi_sense_to_errno(int key, int asc, int ascq) case 0x2700: /* WRITE PROTECTED */ return EACCES; case 0x0401: /* NOT READY, IN PROGRESS OF BECOMING READY */ - return EAGAIN; + return EINPROGRESS; case 0x0402: /* NOT READY, INITIALIZING COMMAND REQUIRED */ return ENOTCONN; default: @@ -391,6 +427,17 @@ int scsi_sense_buf_to_errno(const uint8_t *in_buf, size_t in_len) return scsi_sense_to_errno(sense.key, sense.asc, sense.ascq); } +bool scsi_sense_buf_is_guest_recoverable(const uint8_t *in_buf, size_t in_len) +{ + SCSISense sense; + if (in_len < 1) { + return false; + } + + sense = scsi_parse_sense_buf(in_buf, in_len); + return scsi_sense_is_guest_recoverable(sense.key, sense.asc, sense.ascq); +} + const char *scsi_command_name(uint8_t cmd) { static const char *names[] = { diff --git a/target/i386/sev.c b/target/i386/sev.c index 6dbdc3cdf1..5ba1384ea1 100644 --- a/target/i386/sev.c +++ b/target/i386/sev.c @@ -161,6 +161,17 @@ sev_ram_block_removed(RAMBlockNotifier *n, void *host, size_t size) { int r; struct kvm_enc_region range; + ram_addr_t offset; + MemoryRegion *mr; + + /* + * The RAM device presents a memory region that should be treated + * as IO region and should not have been pinned. + */ + mr = memory_region_from_host(host, &offset); + if (mr && memory_region_is_ram_device(mr)) { + return; + } range.addr = (__u64)(unsigned long)host; range.size = size; diff --git a/target/i386/whpx-all.c b/target/i386/whpx-all.c index 31d47320e4..ed95105eae 100644 --- a/target/i386/whpx-all.c +++ b/target/i386/whpx-all.c @@ -1396,7 +1396,7 @@ static int whpx_accel_init(MachineState *ms) } memset(&prop, 0, sizeof(WHV_PARTITION_PROPERTY)); - prop.ProcessorCount = smp_cpus; + prop.ProcessorCount = ms->smp.cpus; hr = whp_dispatch.WHvSetPartitionProperty( whpx->partition, WHvPartitionPropertyCodeProcessorCount, @@ -1405,7 +1405,7 @@ static int whpx_accel_init(MachineState *ms) if (FAILED(hr)) { error_report("WHPX: Failed to set partition core count to %d," - " hr=%08lx", smp_cores, hr); + " hr=%08lx", ms->smp.cores, hr); ret = -EINVAL; goto error; } diff --git a/util/Makefile.objs b/util/Makefile.objs index 38178201ff..41bf59d127 100644 --- a/util/Makefile.objs +++ b/util/Makefile.objs @@ -2,8 +2,7 @@ util-obj-y = osdep.o cutils.o unicode.o qemu-timer-common.o util-obj-y += bufferiszero.o util-obj-y += lockcnt.o util-obj-y += aiocb.o async.o aio-wait.o thread-pool.o qemu-timer.o -util-obj-y += main-loop.o iohandler.o -main-loop.o-cflags := $(SLIRP_CFLAGS) +util-obj-y += main-loop.o util-obj-$(call lnot,$(CONFIG_ATOMIC64)) += atomic64.o util-obj-$(CONFIG_POSIX) += aio-posix.o util-obj-$(CONFIG_POSIX) += compatfd.o diff --git a/util/iohandler.c b/util/iohandler.c deleted file mode 100644 index bece8825dc..0000000000 --- a/util/iohandler.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - * QEMU System Emulator - managing I/O handler - * - * Copyright (c) 2003-2008 Fabrice Bellard - * - * 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 "qemu/osdep.h" -#include "qapi/error.h" -#include "qemu/queue.h" -#include "block/aio.h" -#include "qemu/main-loop.h" - -#ifndef _WIN32 -#include -#endif - -/* This context runs on top of main loop. We can't reuse qemu_aio_context - * because iohandlers mustn't be polled by aio_poll(qemu_aio_context). */ -static AioContext *iohandler_ctx; - -static void iohandler_init(void) -{ - if (!iohandler_ctx) { - iohandler_ctx = aio_context_new(&error_abort); - } -} - -AioContext *iohandler_get_aio_context(void) -{ - iohandler_init(); - return iohandler_ctx; -} - -GSource *iohandler_get_g_source(void) -{ - iohandler_init(); - return aio_get_g_source(iohandler_ctx); -} - -void qemu_set_fd_handler(int fd, - IOHandler *fd_read, - IOHandler *fd_write, - void *opaque) -{ - iohandler_init(); - aio_set_fd_handler(iohandler_ctx, fd, false, - fd_read, fd_write, NULL, opaque); -} - -void event_notifier_set_handler(EventNotifier *e, - EventNotifierHandler *handler) -{ - iohandler_init(); - aio_set_event_notifier(iohandler_ctx, e, false, - handler, NULL); -} - -/* reaping of zombies. right now we're not passing the status to - anyone, but it would be possible to add a callback. */ -#ifndef _WIN32 -typedef struct ChildProcessRecord { - int pid; - QLIST_ENTRY(ChildProcessRecord) next; -} ChildProcessRecord; - -static QLIST_HEAD(, ChildProcessRecord) child_watches = - QLIST_HEAD_INITIALIZER(child_watches); - -static QEMUBH *sigchld_bh; - -static void sigchld_handler(int signal) -{ - qemu_bh_schedule(sigchld_bh); -} - -static void sigchld_bh_handler(void *opaque) -{ - ChildProcessRecord *rec, *next; - - QLIST_FOREACH_SAFE(rec, &child_watches, next, next) { - if (waitpid(rec->pid, NULL, WNOHANG) == rec->pid) { - QLIST_REMOVE(rec, next); - g_free(rec); - } - } -} - -static void qemu_init_child_watch(void) -{ - struct sigaction act; - sigchld_bh = qemu_bh_new(sigchld_bh_handler, NULL); - - memset(&act, 0, sizeof(act)); - act.sa_handler = sigchld_handler; - act.sa_flags = SA_NOCLDSTOP; - sigaction(SIGCHLD, &act, NULL); -} - -int qemu_add_child_watch(pid_t pid) -{ - ChildProcessRecord *rec; - - if (!sigchld_bh) { - qemu_init_child_watch(); - } - - QLIST_FOREACH(rec, &child_watches, next) { - if (rec->pid == pid) { - return 1; - } - } - rec = g_malloc0(sizeof(ChildProcessRecord)); - rec->pid = pid; - QLIST_INSERT_HEAD(&child_watches, rec, next); - return 0; -} -#endif diff --git a/util/main-loop.c b/util/main-loop.c index a9f4e8de75..e3eaa55866 100644 --- a/util/main-loop.c +++ b/util/main-loop.c @@ -32,6 +32,11 @@ #include "qemu/main-loop.h" #include "block/aio.h" #include "qemu/error-report.h" +#include "qemu/queue.h" + +#ifndef _WIN32 +#include +#endif #ifndef _WIN32 @@ -525,3 +530,108 @@ QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque) { return aio_bh_new(qemu_aio_context, cb, opaque); } + +/* + * Functions to operate on the I/O handler AioContext. + * This context runs on top of main loop. We can't reuse qemu_aio_context + * because iohandlers mustn't be polled by aio_poll(qemu_aio_context). + */ +static AioContext *iohandler_ctx; + +static void iohandler_init(void) +{ + if (!iohandler_ctx) { + iohandler_ctx = aio_context_new(&error_abort); + } +} + +AioContext *iohandler_get_aio_context(void) +{ + iohandler_init(); + return iohandler_ctx; +} + +GSource *iohandler_get_g_source(void) +{ + iohandler_init(); + return aio_get_g_source(iohandler_ctx); +} + +void qemu_set_fd_handler(int fd, + IOHandler *fd_read, + IOHandler *fd_write, + void *opaque) +{ + iohandler_init(); + aio_set_fd_handler(iohandler_ctx, fd, false, + fd_read, fd_write, NULL, opaque); +} + +void event_notifier_set_handler(EventNotifier *e, + EventNotifierHandler *handler) +{ + iohandler_init(); + aio_set_event_notifier(iohandler_ctx, e, false, + handler, NULL); +} + +/* reaping of zombies. right now we're not passing the status to + anyone, but it would be possible to add a callback. */ +#ifndef _WIN32 +typedef struct ChildProcessRecord { + int pid; + QLIST_ENTRY(ChildProcessRecord) next; +} ChildProcessRecord; + +static QLIST_HEAD(, ChildProcessRecord) child_watches = + QLIST_HEAD_INITIALIZER(child_watches); + +static QEMUBH *sigchld_bh; + +static void sigchld_handler(int signal) +{ + qemu_bh_schedule(sigchld_bh); +} + +static void sigchld_bh_handler(void *opaque) +{ + ChildProcessRecord *rec, *next; + + QLIST_FOREACH_SAFE(rec, &child_watches, next, next) { + if (waitpid(rec->pid, NULL, WNOHANG) == rec->pid) { + QLIST_REMOVE(rec, next); + g_free(rec); + } + } +} + +static void qemu_init_child_watch(void) +{ + struct sigaction act; + sigchld_bh = qemu_bh_new(sigchld_bh_handler, NULL); + + memset(&act, 0, sizeof(act)); + act.sa_handler = sigchld_handler; + act.sa_flags = SA_NOCLDSTOP; + sigaction(SIGCHLD, &act, NULL); +} + +int qemu_add_child_watch(pid_t pid) +{ + ChildProcessRecord *rec; + + if (!sigchld_bh) { + qemu_init_child_watch(); + } + + QLIST_FOREACH(rec, &child_watches, next) { + if (rec->pid == pid) { + return 1; + } + } + rec = g_malloc0(sizeof(ChildProcessRecord)); + rec->pid = pid; + QLIST_INSERT_HEAD(&child_watches, rec, next); + return 0; +} +#endif diff --git a/vl.c b/vl.c index 5089fce6c5..a5808f9a02 100644 --- a/vl.c +++ b/vl.c @@ -2890,6 +2890,8 @@ int main(int argc, char **argv, char **envp) char *dir, **dirs; BlockdevOptionsQueue bdo_queue = QSIMPLEQ_HEAD_INITIALIZER(bdo_queue); + os_set_line_buffering(); + error_init(argv[0]); module_call_init(MODULE_INIT_TRACE); @@ -4246,8 +4248,6 @@ int main(int argc, char **argv, char **envp) semihosting_arg_fallback(kernel_filename, kernel_cmdline); } - os_set_line_buffering(); - /* spice needs the timers to be initialized by this point */ qemu_spice_init();