* fix tracing vs -daemonize (Daniel)
* detect invalid CFI configuration (Daniele) * 32-bit PVH fix (David) * forward SCSI passthrough host-status to the SCSI HBA (Hannes) * detect ill-formed id in QMP object-add (Kevin) * miscellaneous bugfixes and cleanups (Keqian, Kostiantyn, myself, Peng Liang) * add nodelay option for chardev (myself) * deprecate -M kernel-irqchip=off on x86 (myself) * keep .d files (myself) * Fix -trace file (myself) -----BEGIN PGP SIGNATURE----- iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAmBDXMAUHHBib256aW5p QHJlZGhhdC5jb20ACgkQv/vSX3jHroPYPwf/YeM8TYqCFCt3Th4Ap2IuMqI/7HRq iNFlKWfM2S7Gk87RaNINL96MHadOteeYSQLuh4Y6FHL1OGpWX2ZByXR//z2DARLC AuV1IncevVyQiSDQzwZj6BU7G4b8xSU3Ey5yseYv+hjUhVbiscDvpioV2USkUvD5 IJFXwL5+eRAOGma0SAcumgwu5xc5/GGh5D63vZ0R7q5eDCu69Q6/ZYvK93b6+TP7 GWboGJFcbTvYku56S4ip8VdEzxiNhfQgGNa3nNDx4ejiTt4mYAft7wy+j/iQjPW9 P0y4AYuvInCrUy1RBR1BqAE+ZXNxqby3AQ0ZTujG+YMiWLIvz5FZtGEvyg== =aCET -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/bonzini-gitlab/tags/for-upstream' into staging * fix tracing vs -daemonize (Daniel) * detect invalid CFI configuration (Daniele) * 32-bit PVH fix (David) * forward SCSI passthrough host-status to the SCSI HBA (Hannes) * detect ill-formed id in QMP object-add (Kevin) * miscellaneous bugfixes and cleanups (Keqian, Kostiantyn, myself, Peng Liang) * add nodelay option for chardev (myself) * deprecate -M kernel-irqchip=off on x86 (myself) * keep .d files (myself) * Fix -trace file (myself) # gpg: Signature made Sat 06 Mar 2021 10:43:12 GMT # gpg: using RSA key F13338574B662389866C7682BFFBD25F78C7AE83 # gpg: issuer "pbonzini@redhat.com" # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" [full] # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" [full] # Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1 # Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83 * remotes/bonzini-gitlab/tags/for-upstream: (23 commits) meson: Stop if cfi is enabled with system slirp trace: skip qemu_set_log_filename if no "-D" option was passed trace: fix "-trace file=..." meson: adjust timeouts for some slower tests build-sys: invoke ninja with -d keepdepfile qemu-option: do not suggest using the delay option scsi: move host_status handling into SCSI drivers scsi: inline sg_io_sense_from_errno() into the callers. scsi-generic: do not snoop the output of failed commands scsi: Add mapping for generic SCSI_HOST status to sense codes scsi: Rename linux-specific SG_ERR codes to generic SCSI_HOST error codes qemu-config: add error propagation to qemu_config_parse x86/pvh: extract only 4 bytes of start address for 32 bit kernels elf_ops: correct loading of 32 bit PVH kernel lsilogic: Use PCIDevice::exit instead of DeviceState::unrealize accel: kvm: Add aligment assert for kvm_log_clear_one_slot accel: kvm: Fix memory waste under mismatch page size vl.c: do not execute trace_init_backends() before daemonizing qom: Check for wellformed id in user_creatable_add_type() chardev: add nodelay option ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
0436c55edf
2
Makefile
2
Makefile
|
@ -149,7 +149,7 @@ $(ninja-targets): run-ninja
|
||||||
# --output-sync line.
|
# --output-sync line.
|
||||||
run-ninja: config-host.mak
|
run-ninja: config-host.mak
|
||||||
ifneq ($(filter $(ninja-targets), $(ninja-cmd-goals)),)
|
ifneq ($(filter $(ninja-targets), $(ninja-cmd-goals)),)
|
||||||
+$(quiet-@)$(if $(MAKE.nq),@:, $(NINJA) \
|
+$(quiet-@)$(if $(MAKE.nq),@:, $(NINJA) -d keepdepfile \
|
||||||
$(NINJAFLAGS) $(sort $(filter $(ninja-targets), $(ninja-cmd-goals))) | cat)
|
$(NINJAFLAGS) $(sort $(filter $(ninja-targets), $(ninja-cmd-goals))) | cat)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -598,8 +598,12 @@ static void kvm_memslot_init_dirty_bitmap(KVMSlot *mem)
|
||||||
* too, in most cases).
|
* too, in most cases).
|
||||||
* So for now, let's align to 64 instead of HOST_LONG_BITS here, in
|
* So for now, let's align to 64 instead of HOST_LONG_BITS here, in
|
||||||
* a hope that sizeof(long) won't become >8 any time soon.
|
* a hope that sizeof(long) won't become >8 any time soon.
|
||||||
|
*
|
||||||
|
* Note: the granule of kvm dirty log is qemu_real_host_page_size.
|
||||||
|
* And mem->memory_size is aligned to it (otherwise this mem can't
|
||||||
|
* be registered to KVM).
|
||||||
*/
|
*/
|
||||||
hwaddr bitmap_size = ALIGN(((mem->memory_size) >> TARGET_PAGE_BITS),
|
hwaddr bitmap_size = ALIGN(mem->memory_size / qemu_real_host_page_size,
|
||||||
/*HOST_LONG_BITS*/ 64) / 8;
|
/*HOST_LONG_BITS*/ 64) / 8;
|
||||||
mem->dirty_bmap = g_malloc0(bitmap_size);
|
mem->dirty_bmap = g_malloc0(bitmap_size);
|
||||||
}
|
}
|
||||||
|
@ -669,6 +673,10 @@ out:
|
||||||
#define KVM_CLEAR_LOG_ALIGN (qemu_real_host_page_size << KVM_CLEAR_LOG_SHIFT)
|
#define KVM_CLEAR_LOG_ALIGN (qemu_real_host_page_size << KVM_CLEAR_LOG_SHIFT)
|
||||||
#define KVM_CLEAR_LOG_MASK (-KVM_CLEAR_LOG_ALIGN)
|
#define KVM_CLEAR_LOG_MASK (-KVM_CLEAR_LOG_ALIGN)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* As the granule of kvm dirty log is qemu_real_host_page_size,
|
||||||
|
* @start and @size are expected and restricted to align to it.
|
||||||
|
*/
|
||||||
static int kvm_log_clear_one_slot(KVMSlot *mem, int as_id, uint64_t start,
|
static int kvm_log_clear_one_slot(KVMSlot *mem, int as_id, uint64_t start,
|
||||||
uint64_t size)
|
uint64_t size)
|
||||||
{
|
{
|
||||||
|
@ -678,6 +686,9 @@ static int kvm_log_clear_one_slot(KVMSlot *mem, int as_id, uint64_t start,
|
||||||
unsigned long *bmap_clear = NULL, psize = qemu_real_host_page_size;
|
unsigned long *bmap_clear = NULL, psize = qemu_real_host_page_size;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
/* Make sure start and size are qemu_real_host_page_size aligned */
|
||||||
|
assert(QEMU_IS_ALIGNED(start | size, psize));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We need to extend either the start or the size or both to
|
* We need to extend either the start or the size or both to
|
||||||
* satisfy the KVM interface requirement. Firstly, do the start
|
* satisfy the KVM interface requirement. Firstly, do the start
|
||||||
|
|
|
@ -279,9 +279,8 @@ static int read_config(BDRVBlkdebugState *s, const char *filename,
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = qemu_config_parse(f, config_groups, filename);
|
ret = qemu_config_parse(f, config_groups, filename, errp);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
error_setg(errp, "Could not parse blkdebug config file");
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1472,8 +1472,17 @@ static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
|
||||||
sock = backend->u.socket.data = g_new0(ChardevSocket, 1);
|
sock = backend->u.socket.data = g_new0(ChardevSocket, 1);
|
||||||
qemu_chr_parse_common(opts, qapi_ChardevSocket_base(sock));
|
qemu_chr_parse_common(opts, qapi_ChardevSocket_base(sock));
|
||||||
|
|
||||||
sock->has_nodelay = qemu_opt_get(opts, "delay");
|
if (qemu_opt_get(opts, "delay") && qemu_opt_get(opts, "nodelay")) {
|
||||||
sock->nodelay = !qemu_opt_get_bool(opts, "delay", true);
|
error_setg(errp, "'delay' and 'nodelay' are mutually exclusive");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sock->has_nodelay =
|
||||||
|
qemu_opt_get(opts, "delay") ||
|
||||||
|
qemu_opt_get(opts, "nodelay");
|
||||||
|
sock->nodelay =
|
||||||
|
!qemu_opt_get_bool(opts, "delay", true) ||
|
||||||
|
qemu_opt_get_bool(opts, "nodelay", false);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We have different default to QMP for 'server', hence
|
* We have different default to QMP for 'server', hence
|
||||||
* we can't just check for existence of 'server'
|
* we can't just check for existence of 'server'
|
||||||
|
|
|
@ -867,6 +867,9 @@ QemuOptsList qemu_chardev_opts = {
|
||||||
},{
|
},{
|
||||||
.name = "delay",
|
.name = "delay",
|
||||||
.type = QEMU_OPT_BOOL,
|
.type = QEMU_OPT_BOOL,
|
||||||
|
},{
|
||||||
|
.name = "nodelay",
|
||||||
|
.type = QEMU_OPT_BOOL,
|
||||||
},{
|
},{
|
||||||
.name = "reconnect",
|
.name = "reconnect",
|
||||||
.type = QEMU_OPT_NUMBER,
|
.type = QEMU_OPT_NUMBER,
|
||||||
|
|
|
@ -134,6 +134,12 @@ Boolean options such as ``share=on``/``share=off`` could be written
|
||||||
in short form as ``share`` and ``noshare``. This is now deprecated
|
in short form as ``share`` and ``noshare``. This is now deprecated
|
||||||
and will cause a warning.
|
and will cause a warning.
|
||||||
|
|
||||||
|
``delay`` option for socket character devices (since 6.0)
|
||||||
|
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
||||||
|
|
||||||
|
The replacement for the ``nodelay`` short-form boolean option is ``nodelay=on``
|
||||||
|
rather than ``delay=off``.
|
||||||
|
|
||||||
``--enable-fips`` (since 6.0)
|
``--enable-fips`` (since 6.0)
|
||||||
'''''''''''''''''''''''''''''
|
'''''''''''''''''''''''''''''
|
||||||
|
|
||||||
|
@ -153,6 +159,13 @@ The ``-writeconfig`` option is not able to serialize the entire contents
|
||||||
of the QEMU command line. It is thus considered a failed experiment
|
of the QEMU command line. It is thus considered a failed experiment
|
||||||
and deprecated, with no current replacement.
|
and deprecated, with no current replacement.
|
||||||
|
|
||||||
|
Userspace local APIC with KVM (x86, since 6.0)
|
||||||
|
''''''''''''''''''''''''''''''''''''''''''''''
|
||||||
|
|
||||||
|
Using ``-M kernel-irqchip=off`` with x86 machine types that include a local
|
||||||
|
APIC is deprecated. The ``split`` setting is supported, as is using
|
||||||
|
``-M kernel-irqchip=off`` with the ISA PC machine type.
|
||||||
|
|
||||||
QEMU Machine Protocol (QMP) commands
|
QEMU Machine Protocol (QMP) commands
|
||||||
------------------------------------
|
------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -3505,7 +3505,7 @@ int gdbserver_start(const char *device)
|
||||||
if (strstart(device, "tcp:", NULL)) {
|
if (strstart(device, "tcp:", NULL)) {
|
||||||
/* enforce required TCP attributes */
|
/* enforce required TCP attributes */
|
||||||
snprintf(gdbstub_device_name, sizeof(gdbstub_device_name),
|
snprintf(gdbstub_device_name, sizeof(gdbstub_device_name),
|
||||||
"%s,wait=off,delay=off,server=on", device);
|
"%s,wait=off,nodelay=on,server=on", device);
|
||||||
device = gdbstub_device_name;
|
device = gdbstub_device_name;
|
||||||
}
|
}
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
|
|
@ -690,6 +690,8 @@ static uint64_t read_pvh_start_addr(void *arg1, void *arg2, bool is64)
|
||||||
elf_note_data_addr =
|
elf_note_data_addr =
|
||||||
((void *)nhdr64) + nhdr_size64 +
|
((void *)nhdr64) + nhdr_size64 +
|
||||||
QEMU_ALIGN_UP(nhdr_namesz, phdr_align);
|
QEMU_ALIGN_UP(nhdr_namesz, phdr_align);
|
||||||
|
|
||||||
|
pvh_start_addr = *elf_note_data_addr;
|
||||||
} else {
|
} else {
|
||||||
struct elf32_note *nhdr32 = (struct elf32_note *)arg1;
|
struct elf32_note *nhdr32 = (struct elf32_note *)arg1;
|
||||||
uint32_t nhdr_size32 = sizeof(struct elf32_note);
|
uint32_t nhdr_size32 = sizeof(struct elf32_note);
|
||||||
|
@ -699,9 +701,9 @@ static uint64_t read_pvh_start_addr(void *arg1, void *arg2, bool is64)
|
||||||
elf_note_data_addr =
|
elf_note_data_addr =
|
||||||
((void *)nhdr32) + nhdr_size32 +
|
((void *)nhdr32) + nhdr_size32 +
|
||||||
QEMU_ALIGN_UP(nhdr_namesz, phdr_align);
|
QEMU_ALIGN_UP(nhdr_namesz, phdr_align);
|
||||||
}
|
|
||||||
|
|
||||||
pvh_start_addr = *elf_note_data_addr;
|
pvh_start_addr = *(uint32_t *)elf_note_data_addr;
|
||||||
|
}
|
||||||
|
|
||||||
return pvh_start_addr;
|
return pvh_start_addr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "hw/intc/i8259.h"
|
#include "hw/intc/i8259.h"
|
||||||
#include "hw/pci/msi.h"
|
#include "hw/pci/msi.h"
|
||||||
#include "qemu/host-utils.h"
|
#include "qemu/host-utils.h"
|
||||||
|
#include "sysemu/kvm.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
#include "hw/i386/apic-msidef.h"
|
#include "hw/i386/apic-msidef.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
|
@ -875,6 +876,11 @@ static void apic_realize(DeviceState *dev, Error **errp)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (kvm_enabled()) {
|
||||||
|
warn_report("Userspace local APIC is deprecated for KVM.");
|
||||||
|
warn_report("Do not use kernel-irqchip except for the -M isapc machine type.");
|
||||||
|
}
|
||||||
|
|
||||||
memory_region_init_io(&s->io_memory, OBJECT(s), &apic_io_ops, s, "apic-msi",
|
memory_region_init_io(&s->io_memory, OBJECT(s), &apic_io_ops, s, "apic-msi",
|
||||||
APIC_SPACE_SIZE);
|
APIC_SPACE_SIZE);
|
||||||
|
|
||||||
|
|
|
@ -2312,7 +2312,7 @@ static void lsi_scsi_realize(PCIDevice *dev, Error **errp)
|
||||||
scsi_bus_new(&s->bus, sizeof(s->bus), d, &lsi_scsi_info, NULL);
|
scsi_bus_new(&s->bus, sizeof(s->bus), d, &lsi_scsi_info, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lsi_scsi_unrealize(DeviceState *dev)
|
static void lsi_scsi_exit(PCIDevice *dev)
|
||||||
{
|
{
|
||||||
LSIState *s = LSI53C895A(dev);
|
LSIState *s = LSI53C895A(dev);
|
||||||
|
|
||||||
|
@ -2325,11 +2325,11 @@ static void lsi_class_init(ObjectClass *klass, void *data)
|
||||||
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
|
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
|
||||||
|
|
||||||
k->realize = lsi_scsi_realize;
|
k->realize = lsi_scsi_realize;
|
||||||
|
k->exit = lsi_scsi_exit;
|
||||||
k->vendor_id = PCI_VENDOR_ID_LSI_LOGIC;
|
k->vendor_id = PCI_VENDOR_ID_LSI_LOGIC;
|
||||||
k->device_id = PCI_DEVICE_ID_LSI_53C895A;
|
k->device_id = PCI_DEVICE_ID_LSI_53C895A;
|
||||||
k->class_id = PCI_CLASS_STORAGE_SCSI;
|
k->class_id = PCI_CLASS_STORAGE_SCSI;
|
||||||
k->subsystem_id = 0x1000;
|
k->subsystem_id = 0x1000;
|
||||||
dc->unrealize = lsi_scsi_unrealize;
|
|
||||||
dc->reset = lsi_scsi_reset;
|
dc->reset = lsi_scsi_reset;
|
||||||
dc->vmsd = &vmstate_lsi_scsi;
|
dc->vmsd = &vmstate_lsi_scsi;
|
||||||
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
|
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
|
||||||
|
|
|
@ -692,6 +692,7 @@ SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d,
|
||||||
req->lun = lun;
|
req->lun = lun;
|
||||||
req->hba_private = hba_private;
|
req->hba_private = hba_private;
|
||||||
req->status = -1;
|
req->status = -1;
|
||||||
|
req->host_status = -1;
|
||||||
req->ops = reqops;
|
req->ops = reqops;
|
||||||
object_ref(OBJECT(d));
|
object_ref(OBJECT(d));
|
||||||
object_ref(OBJECT(qbus->parent));
|
object_ref(OBJECT(qbus->parent));
|
||||||
|
@ -1455,10 +1456,38 @@ void scsi_req_print(SCSIRequest *req)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void scsi_req_complete_failed(SCSIRequest *req, int host_status)
|
||||||
|
{
|
||||||
|
SCSISense sense;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
assert(req->status == -1 && req->host_status == -1);
|
||||||
|
assert(req->ops != &reqops_unit_attention);
|
||||||
|
|
||||||
|
if (!req->bus->info->fail) {
|
||||||
|
status = scsi_sense_from_host_status(req->host_status, &sense);
|
||||||
|
if (status == CHECK_CONDITION) {
|
||||||
|
scsi_req_build_sense(req, sense);
|
||||||
|
}
|
||||||
|
scsi_req_complete(req, status);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
req->host_status = host_status;
|
||||||
|
scsi_req_ref(req);
|
||||||
|
scsi_req_dequeue(req);
|
||||||
|
req->bus->info->fail(req);
|
||||||
|
|
||||||
|
/* Cancelled requests might end up being completed instead of cancelled */
|
||||||
|
notifier_list_notify(&req->cancel_notifiers, req);
|
||||||
|
scsi_req_unref(req);
|
||||||
|
}
|
||||||
|
|
||||||
void scsi_req_complete(SCSIRequest *req, int status)
|
void scsi_req_complete(SCSIRequest *req, int status)
|
||||||
{
|
{
|
||||||
assert(req->status == -1);
|
assert(req->status == -1 && req->host_status == -1);
|
||||||
req->status = status;
|
req->status = status;
|
||||||
|
req->host_status = SCSI_HOST_OK;
|
||||||
|
|
||||||
assert(req->sense_len <= sizeof(req->sense));
|
assert(req->sense_len <= sizeof(req->sense));
|
||||||
if (status == GOOD) {
|
if (status == GOOD) {
|
||||||
|
@ -1646,7 +1675,7 @@ static int put_scsi_requests(QEMUFile *f, void *pv, size_t size,
|
||||||
|
|
||||||
QTAILQ_FOREACH(req, &s->requests, next) {
|
QTAILQ_FOREACH(req, &s->requests, next) {
|
||||||
assert(!req->io_canceled);
|
assert(!req->io_canceled);
|
||||||
assert(req->status == -1);
|
assert(req->status == -1 && req->host_status == -1);
|
||||||
assert(req->enqueued);
|
assert(req->enqueued);
|
||||||
|
|
||||||
qemu_put_sbyte(f, req->retry ? 1 : 2);
|
qemu_put_sbyte(f, req->retry ? 1 : 2);
|
||||||
|
|
|
@ -77,7 +77,6 @@ typedef struct SCSIDiskReq {
|
||||||
struct iovec iov;
|
struct iovec iov;
|
||||||
QEMUIOVector qiov;
|
QEMUIOVector qiov;
|
||||||
BlockAcctCookie acct;
|
BlockAcctCookie acct;
|
||||||
unsigned char *status;
|
|
||||||
} SCSIDiskReq;
|
} SCSIDiskReq;
|
||||||
|
|
||||||
#define SCSI_DISK_F_REMOVABLE 0
|
#define SCSI_DISK_F_REMOVABLE 0
|
||||||
|
@ -261,8 +260,6 @@ static bool scsi_disk_req_check_error(SCSIDiskReq *r, int ret, bool acct_failed)
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return scsi_handle_rw_error(r, ret, acct_failed);
|
return scsi_handle_rw_error(r, ret, acct_failed);
|
||||||
} else if (r->status && *r->status) {
|
|
||||||
return scsi_handle_rw_error(r, *r->status, acct_failed);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -2697,8 +2694,47 @@ typedef struct SCSIBlockReq {
|
||||||
|
|
||||||
/* CDB passed to SG_IO. */
|
/* CDB passed to SG_IO. */
|
||||||
uint8_t cdb[16];
|
uint8_t cdb[16];
|
||||||
|
BlockCompletionFunc *cb;
|
||||||
|
void *cb_opaque;
|
||||||
} SCSIBlockReq;
|
} SCSIBlockReq;
|
||||||
|
|
||||||
|
static void scsi_block_sgio_complete(void *opaque, int ret)
|
||||||
|
{
|
||||||
|
SCSIBlockReq *req = (SCSIBlockReq *)opaque;
|
||||||
|
SCSIDiskReq *r = &req->req;
|
||||||
|
SCSIDevice *s = r->req.dev;
|
||||||
|
sg_io_hdr_t *io_hdr = &req->io_header;
|
||||||
|
|
||||||
|
if (ret == 0) {
|
||||||
|
if (io_hdr->host_status != SCSI_HOST_OK) {
|
||||||
|
scsi_req_complete_failed(&r->req, io_hdr->host_status);
|
||||||
|
scsi_req_unref(&r->req);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (io_hdr->driver_status & SG_ERR_DRIVER_TIMEOUT) {
|
||||||
|
ret = BUSY;
|
||||||
|
} else {
|
||||||
|
ret = io_hdr->status;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret > 0) {
|
||||||
|
aio_context_acquire(blk_get_aio_context(s->conf.blk));
|
||||||
|
if (scsi_handle_rw_error(r, ret, true)) {
|
||||||
|
aio_context_release(blk_get_aio_context(s->conf.blk));
|
||||||
|
scsi_req_unref(&r->req);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
aio_context_release(blk_get_aio_context(s->conf.blk));
|
||||||
|
|
||||||
|
/* Ignore error. */
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
req->cb(req->cb_opaque, ret);
|
||||||
|
}
|
||||||
|
|
||||||
static BlockAIOCB *scsi_block_do_sgio(SCSIBlockReq *req,
|
static BlockAIOCB *scsi_block_do_sgio(SCSIBlockReq *req,
|
||||||
int64_t offset, QEMUIOVector *iov,
|
int64_t offset, QEMUIOVector *iov,
|
||||||
int direction,
|
int direction,
|
||||||
|
@ -2777,9 +2813,11 @@ static BlockAIOCB *scsi_block_do_sgio(SCSIBlockReq *req,
|
||||||
io_header->timeout = s->qdev.io_timeout * 1000;
|
io_header->timeout = s->qdev.io_timeout * 1000;
|
||||||
io_header->usr_ptr = r;
|
io_header->usr_ptr = r;
|
||||||
io_header->flags |= SG_FLAG_DIRECT_IO;
|
io_header->flags |= SG_FLAG_DIRECT_IO;
|
||||||
|
req->cb = cb;
|
||||||
|
req->cb_opaque = opaque;
|
||||||
trace_scsi_disk_aio_sgio_command(r->req.tag, req->cdb[0], lba,
|
trace_scsi_disk_aio_sgio_command(r->req.tag, req->cdb[0], lba,
|
||||||
nb_logical_blocks, io_header->timeout);
|
nb_logical_blocks, io_header->timeout);
|
||||||
aiocb = blk_aio_ioctl(s->qdev.conf.blk, SG_IO, io_header, cb, opaque);
|
aiocb = blk_aio_ioctl(s->qdev.conf.blk, SG_IO, io_header, scsi_block_sgio_complete, req);
|
||||||
assert(aiocb != NULL);
|
assert(aiocb != NULL);
|
||||||
return aiocb;
|
return aiocb;
|
||||||
}
|
}
|
||||||
|
@ -2893,7 +2931,6 @@ static int32_t scsi_block_dma_command(SCSIRequest *req, uint8_t *buf)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
r->req.status = &r->io_header.status;
|
|
||||||
return scsi_disk_dma_command(req, buf);
|
return scsi_disk_dma_command(req, buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,6 +75,7 @@ static void scsi_command_complete_noio(SCSIGenericReq *r, int ret)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
SCSISense sense;
|
SCSISense sense;
|
||||||
|
sg_io_hdr_t *io_hdr = &r->io_header;
|
||||||
|
|
||||||
assert(r->req.aiocb == NULL);
|
assert(r->req.aiocb == NULL);
|
||||||
|
|
||||||
|
@ -82,15 +83,22 @@ static void scsi_command_complete_noio(SCSIGenericReq *r, int ret)
|
||||||
scsi_req_cancel_complete(&r->req);
|
scsi_req_cancel_complete(&r->req);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
status = sg_io_sense_from_errno(-ret, &r->io_header, &sense);
|
if (ret < 0) {
|
||||||
if (status == CHECK_CONDITION) {
|
status = scsi_sense_from_errno(-ret, &sense);
|
||||||
if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
|
if (status == CHECK_CONDITION) {
|
||||||
r->req.sense_len = r->io_header.sb_len_wr;
|
|
||||||
} else {
|
|
||||||
scsi_req_build_sense(&r->req, sense);
|
scsi_req_build_sense(&r->req, sense);
|
||||||
}
|
}
|
||||||
|
} else if (io_hdr->host_status != SCSI_HOST_OK) {
|
||||||
|
scsi_req_complete_failed(&r->req, io_hdr->host_status);
|
||||||
|
goto done;
|
||||||
|
} else if (io_hdr->driver_status & SG_ERR_DRIVER_TIMEOUT) {
|
||||||
|
status = BUSY;
|
||||||
|
} else {
|
||||||
|
status = io_hdr->status;
|
||||||
|
if (io_hdr->driver_status & SG_ERR_DRIVER_SENSE) {
|
||||||
|
r->req.sense_len = io_hdr->sb_len_wr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trace_scsi_generic_command_complete_noio(r, r->req.tag, status);
|
trace_scsi_generic_command_complete_noio(r, r->req.tag, status);
|
||||||
|
|
||||||
scsi_req_complete(&r->req, status);
|
scsi_req_complete(&r->req, status);
|
||||||
|
@ -288,7 +296,10 @@ static void scsi_read_complete(void * opaque, int ret)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len == 0) {
|
if (r->io_header.host_status != SCSI_HOST_OK ||
|
||||||
|
(r->io_header.driver_status & SG_ERR_DRIVER_TIMEOUT) ||
|
||||||
|
r->io_header.status != GOOD ||
|
||||||
|
len == 0) {
|
||||||
scsi_command_complete_noio(r, 0);
|
scsi_command_complete_noio(r, 0);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
|
@ -500,6 +500,51 @@ static void virtio_scsi_complete_cmd_req(VirtIOSCSIReq *req)
|
||||||
virtio_scsi_complete_req(req);
|
virtio_scsi_complete_req(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void virtio_scsi_command_failed(SCSIRequest *r)
|
||||||
|
{
|
||||||
|
VirtIOSCSIReq *req = r->hba_private;
|
||||||
|
|
||||||
|
if (r->io_canceled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
req->resp.cmd.status = GOOD;
|
||||||
|
switch (r->host_status) {
|
||||||
|
case SCSI_HOST_NO_LUN:
|
||||||
|
req->resp.cmd.response = VIRTIO_SCSI_S_INCORRECT_LUN;
|
||||||
|
break;
|
||||||
|
case SCSI_HOST_BUSY:
|
||||||
|
req->resp.cmd.response = VIRTIO_SCSI_S_BUSY;
|
||||||
|
break;
|
||||||
|
case SCSI_HOST_TIME_OUT:
|
||||||
|
case SCSI_HOST_ABORTED:
|
||||||
|
req->resp.cmd.response = VIRTIO_SCSI_S_ABORTED;
|
||||||
|
break;
|
||||||
|
case SCSI_HOST_BAD_RESPONSE:
|
||||||
|
req->resp.cmd.response = VIRTIO_SCSI_S_BAD_TARGET;
|
||||||
|
break;
|
||||||
|
case SCSI_HOST_RESET:
|
||||||
|
req->resp.cmd.response = VIRTIO_SCSI_S_RESET;
|
||||||
|
break;
|
||||||
|
case SCSI_HOST_TRANSPORT_DISRUPTED:
|
||||||
|
req->resp.cmd.response = VIRTIO_SCSI_S_TRANSPORT_FAILURE;
|
||||||
|
break;
|
||||||
|
case SCSI_HOST_TARGET_FAILURE:
|
||||||
|
req->resp.cmd.response = VIRTIO_SCSI_S_TARGET_FAILURE;
|
||||||
|
break;
|
||||||
|
case SCSI_HOST_RESERVATION_ERROR:
|
||||||
|
req->resp.cmd.response = VIRTIO_SCSI_S_NEXUS_FAILURE;
|
||||||
|
break;
|
||||||
|
case SCSI_HOST_ALLOCATION_FAILURE:
|
||||||
|
case SCSI_HOST_MEDIUM_ERROR:
|
||||||
|
case SCSI_HOST_ERROR:
|
||||||
|
default:
|
||||||
|
req->resp.cmd.response = VIRTIO_SCSI_S_FAILURE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
virtio_scsi_complete_cmd_req(req);
|
||||||
|
}
|
||||||
|
|
||||||
static void virtio_scsi_command_complete(SCSIRequest *r, size_t resid)
|
static void virtio_scsi_command_complete(SCSIRequest *r, size_t resid)
|
||||||
{
|
{
|
||||||
VirtIOSCSIReq *req = r->hba_private;
|
VirtIOSCSIReq *req = r->hba_private;
|
||||||
|
@ -908,6 +953,7 @@ static struct SCSIBusInfo virtio_scsi_scsi_info = {
|
||||||
.max_lun = VIRTIO_SCSI_MAX_LUN,
|
.max_lun = VIRTIO_SCSI_MAX_LUN,
|
||||||
|
|
||||||
.complete = virtio_scsi_command_complete,
|
.complete = virtio_scsi_command_complete,
|
||||||
|
.fail = virtio_scsi_command_failed,
|
||||||
.cancel = virtio_scsi_request_cancelled,
|
.cancel = virtio_scsi_request_cancelled,
|
||||||
.change = virtio_scsi_change,
|
.change = virtio_scsi_change,
|
||||||
.parse_cdb = virtio_scsi_parse_cdb,
|
.parse_cdb = virtio_scsi_parse_cdb,
|
||||||
|
|
|
@ -510,6 +510,44 @@ pvscsi_write_sense(PVSCSIRequest *r, uint8_t *sense, int len)
|
||||||
cpu_physical_memory_write(r->req.senseAddr, sense, r->cmp.senseLen);
|
cpu_physical_memory_write(r->req.senseAddr, sense, r->cmp.senseLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pvscsi_command_failed(SCSIRequest *req)
|
||||||
|
{
|
||||||
|
PVSCSIRequest *pvscsi_req = req->hba_private;
|
||||||
|
PVSCSIState *s;
|
||||||
|
|
||||||
|
if (!pvscsi_req) {
|
||||||
|
trace_pvscsi_command_complete_not_found(req->tag);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
s = pvscsi_req->dev;
|
||||||
|
|
||||||
|
switch (req->host_status) {
|
||||||
|
case SCSI_HOST_NO_LUN:
|
||||||
|
pvscsi_req->cmp.hostStatus = BTSTAT_LUNMISMATCH;
|
||||||
|
break;
|
||||||
|
case SCSI_HOST_BUSY:
|
||||||
|
pvscsi_req->cmp.hostStatus = BTSTAT_ABORTQUEUE;
|
||||||
|
break;
|
||||||
|
case SCSI_HOST_TIME_OUT:
|
||||||
|
case SCSI_HOST_ABORTED:
|
||||||
|
pvscsi_req->cmp.hostStatus = BTSTAT_SENTRST;
|
||||||
|
break;
|
||||||
|
case SCSI_HOST_BAD_RESPONSE:
|
||||||
|
pvscsi_req->cmp.hostStatus = BTSTAT_SELTIMEO;
|
||||||
|
break;
|
||||||
|
case SCSI_HOST_RESET:
|
||||||
|
pvscsi_req->cmp.hostStatus = BTSTAT_BUSRESET;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pvscsi_req->cmp.hostStatus = BTSTAT_HASOFTWARE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
pvscsi_req->cmp.scsiStatus = GOOD;
|
||||||
|
qemu_sglist_destroy(&pvscsi_req->sgl);
|
||||||
|
pvscsi_complete_request(s, pvscsi_req);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pvscsi_command_complete(SCSIRequest *req, size_t resid)
|
pvscsi_command_complete(SCSIRequest *req, size_t resid)
|
||||||
{
|
{
|
||||||
|
@ -1103,6 +1141,7 @@ static const struct SCSIBusInfo pvscsi_scsi_info = {
|
||||||
.get_sg_list = pvscsi_get_sg_list,
|
.get_sg_list = pvscsi_get_sg_list,
|
||||||
.complete = pvscsi_command_complete,
|
.complete = pvscsi_command_complete,
|
||||||
.cancel = pvscsi_request_cancelled,
|
.cancel = pvscsi_request_cancelled,
|
||||||
|
.fail = pvscsi_command_failed,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -598,9 +598,7 @@ static int glue(load_elf, SZ)(const char *name, int fd,
|
||||||
nhdr = glue(get_elf_note_type, SZ)(nhdr, file_size, ph->p_align,
|
nhdr = glue(get_elf_note_type, SZ)(nhdr, file_size, ph->p_align,
|
||||||
*(uint64_t *)translate_opaque);
|
*(uint64_t *)translate_opaque);
|
||||||
if (nhdr != NULL) {
|
if (nhdr != NULL) {
|
||||||
bool is64 =
|
elf_note_fn((void *)nhdr, (void *)&ph->p_align, SZ == 64);
|
||||||
sizeof(struct elf_note) == sizeof(struct elf64_note);
|
|
||||||
elf_note_fn((void *)nhdr, (void *)&ph->p_align, is64);
|
|
||||||
}
|
}
|
||||||
data = NULL;
|
data = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,8 @@ struct SCSIRequest {
|
||||||
uint32_t refcount;
|
uint32_t refcount;
|
||||||
uint32_t tag;
|
uint32_t tag;
|
||||||
uint32_t lun;
|
uint32_t lun;
|
||||||
uint32_t status;
|
int16_t status;
|
||||||
|
int16_t host_status;
|
||||||
void *hba_private;
|
void *hba_private;
|
||||||
size_t resid;
|
size_t resid;
|
||||||
SCSICommand cmd;
|
SCSICommand cmd;
|
||||||
|
@ -123,6 +124,7 @@ struct SCSIBusInfo {
|
||||||
int (*parse_cdb)(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
|
int (*parse_cdb)(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
|
||||||
void *hba_private);
|
void *hba_private);
|
||||||
void (*transfer_data)(SCSIRequest *req, uint32_t arg);
|
void (*transfer_data)(SCSIRequest *req, uint32_t arg);
|
||||||
|
void (*fail)(SCSIRequest *req);
|
||||||
void (*complete)(SCSIRequest *req, size_t resid);
|
void (*complete)(SCSIRequest *req, size_t resid);
|
||||||
void (*cancel)(SCSIRequest *req);
|
void (*cancel)(SCSIRequest *req);
|
||||||
void (*change)(SCSIBus *bus, SCSIDevice *dev, SCSISense sense);
|
void (*change)(SCSIBus *bus, SCSIDevice *dev, SCSISense sense);
|
||||||
|
@ -177,6 +179,7 @@ void scsi_req_print(SCSIRequest *req);
|
||||||
void scsi_req_continue(SCSIRequest *req);
|
void scsi_req_continue(SCSIRequest *req);
|
||||||
void scsi_req_data(SCSIRequest *req, int len);
|
void scsi_req_data(SCSIRequest *req, int len);
|
||||||
void scsi_req_complete(SCSIRequest *req, int status);
|
void scsi_req_complete(SCSIRequest *req, int status);
|
||||||
|
void scsi_req_complete_failed(SCSIRequest *req, int host_status);
|
||||||
uint8_t *scsi_req_get_buf(SCSIRequest *req);
|
uint8_t *scsi_req_get_buf(SCSIRequest *req);
|
||||||
int scsi_req_get_sense(SCSIRequest *req, uint8_t *buf, int len);
|
int scsi_req_get_sense(SCSIRequest *req, uint8_t *buf, int len);
|
||||||
void scsi_req_cancel_complete(SCSIRequest *req);
|
void scsi_req_cancel_complete(SCSIRequest *req);
|
||||||
|
|
|
@ -11,9 +11,10 @@ void qemu_add_drive_opts(QemuOptsList *list);
|
||||||
int qemu_global_option(const char *str);
|
int qemu_global_option(const char *str);
|
||||||
|
|
||||||
void qemu_config_write(FILE *fp);
|
void qemu_config_write(FILE *fp);
|
||||||
int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname);
|
int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname,
|
||||||
|
Error **errp);
|
||||||
|
|
||||||
int qemu_read_config_file(const char *filename);
|
int qemu_read_config_file(const char *filename, Error **errp);
|
||||||
|
|
||||||
/* Parse QDict options as a replacement for a config file (allowing multiple
|
/* Parse QDict options as a replacement for a config file (allowing multiple
|
||||||
enumerated (0..(n-1)) configuration "sections") */
|
enumerated (0..(n-1)) configuration "sections") */
|
||||||
|
|
|
@ -16,6 +16,22 @@ enum SCSIXferMode {
|
||||||
SCSI_XFER_TO_DEV, /* WRITE, MODE_SELECT, ... */
|
SCSI_XFER_TO_DEV, /* WRITE, MODE_SELECT, ... */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum SCSIHostStatus {
|
||||||
|
SCSI_HOST_OK,
|
||||||
|
SCSI_HOST_NO_LUN,
|
||||||
|
SCSI_HOST_BUSY,
|
||||||
|
SCSI_HOST_TIME_OUT,
|
||||||
|
SCSI_HOST_BAD_RESPONSE,
|
||||||
|
SCSI_HOST_ABORTED,
|
||||||
|
SCSI_HOST_ERROR = 0x07,
|
||||||
|
SCSI_HOST_RESET = 0x08,
|
||||||
|
SCSI_HOST_TRANSPORT_DISRUPTED = 0xe,
|
||||||
|
SCSI_HOST_TARGET_FAILURE = 0x10,
|
||||||
|
SCSI_HOST_RESERVATION_ERROR = 0x11,
|
||||||
|
SCSI_HOST_ALLOCATION_FAILURE = 0x12,
|
||||||
|
SCSI_HOST_MEDIUM_ERROR = 0x13,
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct SCSICommand {
|
typedef struct SCSICommand {
|
||||||
uint8_t buf[SCSI_CMD_BUF_SIZE];
|
uint8_t buf[SCSI_CMD_BUF_SIZE];
|
||||||
int len;
|
int len;
|
||||||
|
@ -123,18 +139,9 @@ int scsi_cdb_length(uint8_t *buf);
|
||||||
#ifdef CONFIG_LINUX
|
#ifdef CONFIG_LINUX
|
||||||
#define SG_ERR_DRIVER_TIMEOUT 0x06
|
#define SG_ERR_DRIVER_TIMEOUT 0x06
|
||||||
#define SG_ERR_DRIVER_SENSE 0x08
|
#define SG_ERR_DRIVER_SENSE 0x08
|
||||||
|
|
||||||
#define SG_ERR_DID_OK 0x00
|
|
||||||
#define SG_ERR_DID_NO_CONNECT 0x01
|
|
||||||
#define SG_ERR_DID_BUS_BUSY 0x02
|
|
||||||
#define SG_ERR_DID_TIME_OUT 0x03
|
|
||||||
|
|
||||||
#define SG_ERR_DRIVER_SENSE 0x08
|
|
||||||
|
|
||||||
int sg_io_sense_from_errno(int errno_value, struct sg_io_hdr *io_hdr,
|
|
||||||
SCSISense *sense);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int scsi_sense_from_errno(int errno_value, SCSISense *sense);
|
int scsi_sense_from_errno(int errno_value, SCSISense *sense);
|
||||||
|
int scsi_sense_from_host_status(uint8_t host_status, SCSISense *sense);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
12
meson.build
12
meson.build
|
@ -1574,6 +1574,18 @@ if have_system
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# For CFI, we need to compile slirp as a static library together with qemu.
|
||||||
|
# This is because we register slirp functions as callbacks for QEMU Timers.
|
||||||
|
# When using a system-wide shared libslirp, the type information for the
|
||||||
|
# callback is missing and the timer call produces a false positive with CFI.
|
||||||
|
#
|
||||||
|
# Now that slirp_opt has been defined, check if the selected slirp is compatible
|
||||||
|
# with control-flow integrity.
|
||||||
|
if get_option('cfi') and slirp_opt == 'system'
|
||||||
|
error('Control-Flow Integrity is not compatible with system-wide slirp.' \
|
||||||
|
+ ' Please configure with --enable-slirp=git')
|
||||||
|
endif
|
||||||
|
|
||||||
fdt = not_found
|
fdt = not_found
|
||||||
fdt_opt = get_option('fdt')
|
fdt_opt = get_option('fdt')
|
||||||
if have_system
|
if have_system
|
||||||
|
|
|
@ -3033,7 +3033,7 @@ DEFHEADING(Character device options:)
|
||||||
DEF("chardev", HAS_ARG, QEMU_OPTION_chardev,
|
DEF("chardev", HAS_ARG, QEMU_OPTION_chardev,
|
||||||
"-chardev help\n"
|
"-chardev help\n"
|
||||||
"-chardev null,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
|
"-chardev null,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
|
||||||
"-chardev socket,id=id[,host=host],port=port[,to=to][,ipv4=on|off][,ipv6=on|off][,delay=on|off][,reconnect=seconds]\n"
|
"-chardev socket,id=id[,host=host],port=port[,to=to][,ipv4=on|off][,ipv6=on|off][,nodelay=on|off][,reconnect=seconds]\n"
|
||||||
" [,server=on|off][,wait=on|off][,telnet=on|off][,websocket=on|off][,reconnect=seconds][,mux=on|off]\n"
|
" [,server=on|off][,wait=on|off][,telnet=on|off][,websocket=on|off][,reconnect=seconds][,mux=on|off]\n"
|
||||||
" [,logfile=PATH][,logappend=on|off][,tls-creds=ID][,tls-authz=ID] (tcp)\n"
|
" [,logfile=PATH][,logappend=on|off][,tls-creds=ID][,tls-authz=ID] (tcp)\n"
|
||||||
"-chardev socket,id=id,path=path[,server=on|off][,wait=on|off][,telnet=on|off][,websocket=on|off][,reconnect=seconds]\n"
|
"-chardev socket,id=id,path=path[,server=on|off][,wait=on|off][,telnet=on|off][,websocket=on|off][,reconnect=seconds]\n"
|
||||||
|
@ -3184,7 +3184,7 @@ The available backends are:
|
||||||
|
|
||||||
TCP and unix socket options are given below:
|
TCP and unix socket options are given below:
|
||||||
|
|
||||||
``TCP options: port=port[,host=host][,to=to][,ipv4=on|off][,ipv6=on|off][,delay=on|off]``
|
``TCP options: port=port[,host=host][,to=to][,ipv4=on|off][,ipv6=on|off][,nodelay=on|off]``
|
||||||
``host`` for a listening socket specifies the local address to
|
``host`` for a listening socket specifies the local address to
|
||||||
be bound. For a connecting socket species the remote host to
|
be bound. For a connecting socket species the remote host to
|
||||||
connect to. ``host`` is optional for listening sockets. If not
|
connect to. ``host`` is optional for listening sockets. If not
|
||||||
|
@ -3204,7 +3204,7 @@ The available backends are:
|
||||||
or IPv6 must be used. If neither is specified the socket may
|
or IPv6 must be used. If neither is specified the socket may
|
||||||
use either protocol.
|
use either protocol.
|
||||||
|
|
||||||
``delay=on|off`` disables the Nagle algorithm.
|
``nodelay=on|off`` disables the Nagle algorithm.
|
||||||
|
|
||||||
``unix options: path=path[,abstract=on|off][,tight=on|off]``
|
``unix options: path=path[,abstract=on|off][,tight=on|off]``
|
||||||
``path`` specifies the local path of the unix socket. ``path``
|
``path`` specifies the local path of the unix socket. ``path``
|
||||||
|
@ -3593,13 +3593,13 @@ SRST
|
||||||
``telnet options:``
|
``telnet options:``
|
||||||
localhost 5555
|
localhost 5555
|
||||||
|
|
||||||
``tcp:[host]:port[,server=on|off][,wait=on|off][,delay=on|off][,reconnect=seconds]``
|
``tcp:[host]:port[,server=on|off][,wait=on|off][,nodelay=on|off][,reconnect=seconds]``
|
||||||
The TCP Net Console has two modes of operation. It can send the
|
The TCP Net Console has two modes of operation. It can send the
|
||||||
serial I/O to a location or wait for a connection from a
|
serial I/O to a location or wait for a connection from a
|
||||||
location. By default the TCP Net Console is sent to host at the
|
location. By default the TCP Net Console is sent to host at the
|
||||||
port. If you use the ``server=on`` option QEMU will wait for a client
|
port. If you use the ``server=on`` option QEMU will wait for a client
|
||||||
socket application to connect to the port before continuing,
|
socket application to connect to the port before continuing,
|
||||||
unless the ``wait=on|off`` option was specified. The ``delay=on|off``
|
unless the ``wait=on|off`` option was specified. The ``nodelay=on|off``
|
||||||
option disables the Nagle buffering algorithm. The ``reconnect=on``
|
option disables the Nagle buffering algorithm. The ``reconnect=on``
|
||||||
option only applies if ``server=no`` is set, if the connection goes
|
option only applies if ``server=no`` is set, if the connection goes
|
||||||
down it will attempt to reconnect at the given interval. If host
|
down it will attempt to reconnect at the given interval. If host
|
||||||
|
@ -3616,7 +3616,7 @@ SRST
|
||||||
``Example to not wait and listen on ip 192.168.0.100 port 4444``
|
``Example to not wait and listen on ip 192.168.0.100 port 4444``
|
||||||
-serial tcp:192.168.0.100:4444,server=on,wait=off
|
-serial tcp:192.168.0.100:4444,server=on,wait=off
|
||||||
|
|
||||||
``telnet:host:port[,server=on|off][,wait=on|off][,delay=on|off]``
|
``telnet:host:port[,server=on|off][,wait=on|off][,nodelay=on|off]``
|
||||||
The telnet protocol is used instead of raw tcp sockets. The
|
The telnet protocol is used instead of raw tcp sockets. The
|
||||||
options work the same as if you had specified ``-serial tcp``.
|
options work the same as if you had specified ``-serial tcp``.
|
||||||
The difference is that the port acts like a telnet server or
|
The difference is that the port acts like a telnet server or
|
||||||
|
@ -3626,7 +3626,7 @@ SRST
|
||||||
you do it with Control-] and then type "send break" followed by
|
you do it with Control-] and then type "send break" followed by
|
||||||
pressing the enter key.
|
pressing the enter key.
|
||||||
|
|
||||||
``websocket:host:port,server=on[,wait=on|off][,delay=on|off]``
|
``websocket:host:port,server=on[,wait=on|off][,nodelay=on|off]``
|
||||||
The WebSocket protocol is used instead of raw tcp socket. The
|
The WebSocket protocol is used instead of raw tcp socket. The
|
||||||
port acts as a WebSocket server. Client mode is not supported.
|
port acts as a WebSocket server. Client mode is not supported.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
if add_languages('cpp', required: false)
|
if add_languages('cpp', required: false)
|
||||||
glib_static = dependency('glib-2.0', static: true)
|
glib_dynamic = dependency('glib-2.0', static: false)
|
||||||
link_args = cc.get_supported_link_arguments(['-fstack-protector-all', '-fstack-protector-strong',
|
link_args = cc.get_supported_link_arguments(['-fstack-protector-all', '-fstack-protector-strong',
|
||||||
'-Wl,--add-stdcall-alias', '-Wl,--enable-stdcall-fixup'])
|
'-Wl,--add-stdcall-alias', '-Wl,--enable-stdcall-fixup'])
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ if add_languages('cpp', required: false)
|
||||||
cpp_args: ['-Wno-unknown-pragmas', '-Wno-delete-non-virtual-dtor', '-Wno-non-virtual-dtor'],
|
cpp_args: ['-Wno-unknown-pragmas', '-Wno-delete-non-virtual-dtor', '-Wno-non-virtual-dtor'],
|
||||||
link_args: link_args,
|
link_args: link_args,
|
||||||
vs_module_defs: 'qga-vss.def',
|
vs_module_defs: 'qga-vss.def',
|
||||||
dependencies: [glib_static, socket,
|
dependencies: [glib_dynamic, socket,
|
||||||
cc.find_library('ole32'),
|
cc.find_library('ole32'),
|
||||||
cc.find_library('oleaut32'),
|
cc.find_library('oleaut32'),
|
||||||
cc.find_library('shlwapi'),
|
cc.find_library('shlwapi'),
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "qapi/qobject-input-visitor.h"
|
#include "qapi/qobject-input-visitor.h"
|
||||||
#include "qom/object_interfaces.h"
|
#include "qom/object_interfaces.h"
|
||||||
#include "qemu/help_option.h"
|
#include "qemu/help_option.h"
|
||||||
|
#include "qemu/id.h"
|
||||||
#include "qemu/module.h"
|
#include "qemu/module.h"
|
||||||
#include "qemu/option.h"
|
#include "qemu/option.h"
|
||||||
#include "qapi/opts-visitor.h"
|
#include "qapi/opts-visitor.h"
|
||||||
|
@ -41,11 +42,19 @@ Object *user_creatable_add_type(const char *type, const char *id,
|
||||||
const QDict *qdict,
|
const QDict *qdict,
|
||||||
Visitor *v, Error **errp)
|
Visitor *v, Error **errp)
|
||||||
{
|
{
|
||||||
|
ERRP_GUARD();
|
||||||
Object *obj;
|
Object *obj;
|
||||||
ObjectClass *klass;
|
ObjectClass *klass;
|
||||||
const QDictEntry *e;
|
const QDictEntry *e;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
|
|
||||||
|
if (id != NULL && !id_wellformed(id)) {
|
||||||
|
error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "id", "an identifier");
|
||||||
|
error_append_hint(errp, "Identifiers consist of letters, digits, "
|
||||||
|
"'-', '.', '_', starting with a letter.\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
klass = object_class_by_name(type);
|
klass = object_class_by_name(type);
|
||||||
if (!klass) {
|
if (!klass) {
|
||||||
error_setg(errp, "invalid object type: %s", type);
|
error_setg(errp, "invalid object type: %s", type);
|
||||||
|
|
|
@ -149,19 +149,29 @@ static int do_sgio_worker(void *opaque)
|
||||||
io_hdr.dxferp = (char *)data->buf;
|
io_hdr.dxferp = (char *)data->buf;
|
||||||
io_hdr.dxfer_len = data->sz;
|
io_hdr.dxfer_len = data->sz;
|
||||||
ret = ioctl(data->fd, SG_IO, &io_hdr);
|
ret = ioctl(data->fd, SG_IO, &io_hdr);
|
||||||
status = sg_io_sense_from_errno(ret < 0 ? errno : 0, &io_hdr,
|
|
||||||
&sense_code);
|
if (ret < 0) {
|
||||||
|
status = scsi_sense_from_errno(errno, &sense_code);
|
||||||
|
if (status == CHECK_CONDITION) {
|
||||||
|
scsi_build_sense(data->sense, sense_code);
|
||||||
|
}
|
||||||
|
} else if (io_hdr.host_status != SCSI_HOST_OK) {
|
||||||
|
status = scsi_sense_from_host_status(io_hdr.host_status, &sense_code);
|
||||||
|
if (status == CHECK_CONDITION) {
|
||||||
|
scsi_build_sense(data->sense, sense_code);
|
||||||
|
}
|
||||||
|
} else if (io_hdr.driver_status & SG_ERR_DRIVER_TIMEOUT) {
|
||||||
|
status = BUSY;
|
||||||
|
} else {
|
||||||
|
status = io_hdr.status;
|
||||||
|
}
|
||||||
|
|
||||||
if (status == GOOD) {
|
if (status == GOOD) {
|
||||||
data->sz -= io_hdr.resid;
|
data->sz -= io_hdr.resid;
|
||||||
} else {
|
} else {
|
||||||
data->sz = 0;
|
data->sz = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status == CHECK_CONDITION &&
|
|
||||||
!(io_hdr.driver_status & SG_ERR_DRIVER_SENSE)) {
|
|
||||||
scsi_build_sense(data->sense, sense_code);
|
|
||||||
}
|
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
72
scsi/utils.c
72
scsi/utils.c
|
@ -257,6 +257,21 @@ const struct SCSISense sense_code_LUN_COMM_FAILURE = {
|
||||||
.key = ABORTED_COMMAND, .asc = 0x08, .ascq = 0x00
|
.key = ABORTED_COMMAND, .asc = 0x08, .ascq = 0x00
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Command aborted, LUN does not respond to selection */
|
||||||
|
const struct SCSISense sense_code_LUN_NOT_RESPONDING = {
|
||||||
|
.key = ABORTED_COMMAND, .asc = 0x05, .ascq = 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Command aborted, Command Timeout during processing */
|
||||||
|
const struct SCSISense sense_code_COMMAND_TIMEOUT = {
|
||||||
|
.key = ABORTED_COMMAND, .asc = 0x2e, .ascq = 0x02
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Command aborted, Commands cleared by device server */
|
||||||
|
const struct SCSISense sense_code_COMMAND_ABORTED = {
|
||||||
|
.key = ABORTED_COMMAND, .asc = 0x2f, .ascq = 0x02
|
||||||
|
};
|
||||||
|
|
||||||
/* Medium Error, Unrecovered read error */
|
/* Medium Error, Unrecovered read error */
|
||||||
const struct SCSISense sense_code_READ_ERROR = {
|
const struct SCSISense sense_code_READ_ERROR = {
|
||||||
.key = MEDIUM_ERROR, .asc = 0x11, .ascq = 0x00
|
.key = MEDIUM_ERROR, .asc = 0x11, .ascq = 0x00
|
||||||
|
@ -605,28 +620,41 @@ int scsi_sense_from_errno(int errno_value, SCSISense *sense)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_LINUX
|
int scsi_sense_from_host_status(uint8_t host_status,
|
||||||
int sg_io_sense_from_errno(int errno_value, struct sg_io_hdr *io_hdr,
|
SCSISense *sense)
|
||||||
SCSISense *sense)
|
|
||||||
{
|
{
|
||||||
if (errno_value != 0) {
|
switch (host_status) {
|
||||||
return scsi_sense_from_errno(errno_value, sense);
|
case SCSI_HOST_NO_LUN:
|
||||||
} else {
|
*sense = SENSE_CODE(LUN_NOT_RESPONDING);
|
||||||
if (io_hdr->host_status == SG_ERR_DID_NO_CONNECT ||
|
return CHECK_CONDITION;
|
||||||
io_hdr->host_status == SG_ERR_DID_BUS_BUSY ||
|
case SCSI_HOST_BUSY:
|
||||||
io_hdr->host_status == SG_ERR_DID_TIME_OUT ||
|
return BUSY;
|
||||||
(io_hdr->driver_status & SG_ERR_DRIVER_TIMEOUT)) {
|
case SCSI_HOST_TIME_OUT:
|
||||||
return BUSY;
|
*sense = SENSE_CODE(COMMAND_TIMEOUT);
|
||||||
} else if (io_hdr->host_status) {
|
return CHECK_CONDITION;
|
||||||
*sense = SENSE_CODE(I_T_NEXUS_LOSS);
|
case SCSI_HOST_BAD_RESPONSE:
|
||||||
return CHECK_CONDITION;
|
*sense = SENSE_CODE(LUN_COMM_FAILURE);
|
||||||
} else if (io_hdr->status) {
|
return CHECK_CONDITION;
|
||||||
return io_hdr->status;
|
case SCSI_HOST_ABORTED:
|
||||||
} else if (io_hdr->driver_status & SG_ERR_DRIVER_SENSE) {
|
*sense = SENSE_CODE(COMMAND_ABORTED);
|
||||||
return CHECK_CONDITION;
|
return CHECK_CONDITION;
|
||||||
} else {
|
case SCSI_HOST_RESET:
|
||||||
return GOOD;
|
*sense = SENSE_CODE(RESET);
|
||||||
}
|
return CHECK_CONDITION;
|
||||||
|
case SCSI_HOST_TRANSPORT_DISRUPTED:
|
||||||
|
*sense = SENSE_CODE(I_T_NEXUS_LOSS);
|
||||||
|
return CHECK_CONDITION;
|
||||||
|
case SCSI_HOST_TARGET_FAILURE:
|
||||||
|
*sense = SENSE_CODE(TARGET_FAILURE);
|
||||||
|
return CHECK_CONDITION;
|
||||||
|
case SCSI_HOST_RESERVATION_ERROR:
|
||||||
|
return RESERVATION_CONFLICT;
|
||||||
|
case SCSI_HOST_ALLOCATION_FAILURE:
|
||||||
|
*sense = SENSE_CODE(SPACE_ALLOC_FAILED);
|
||||||
|
return CHECK_CONDITION;
|
||||||
|
case SCSI_HOST_MEDIUM_ERROR:
|
||||||
|
*sense = SENSE_CODE(READ_ERROR);
|
||||||
|
return CHECK_CONDITION;
|
||||||
}
|
}
|
||||||
|
return GOOD;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
51
softmmu/vl.c
51
softmmu/vl.c
|
@ -2062,17 +2062,19 @@ static int global_init_func(void *opaque, QemuOpts *opts, Error **errp)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int qemu_read_default_config_file(void)
|
static void qemu_read_default_config_file(Error **errp)
|
||||||
{
|
{
|
||||||
|
ERRP_GUARD();
|
||||||
int ret;
|
int ret;
|
||||||
g_autofree char *file = get_relocated_path(CONFIG_QEMU_CONFDIR "/qemu.conf");
|
g_autofree char *file = get_relocated_path(CONFIG_QEMU_CONFDIR "/qemu.conf");
|
||||||
|
|
||||||
ret = qemu_read_config_file(file);
|
ret = qemu_read_config_file(file, errp);
|
||||||
if (ret < 0 && ret != -ENOENT) {
|
if (ret < 0) {
|
||||||
return ret;
|
if (ret == -ENOENT) {
|
||||||
|
error_free(*errp);
|
||||||
|
*errp = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int qemu_set_option(const char *str)
|
static int qemu_set_option(const char *str)
|
||||||
|
@ -2361,13 +2363,10 @@ static void qemu_process_early_options(void)
|
||||||
cleanup_add_fd, NULL, &error_fatal);
|
cleanup_add_fd, NULL, &error_fatal);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!trace_init_backends()) {
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
trace_init_file();
|
|
||||||
|
|
||||||
/* Open the logfile at this point and set the log mask if necessary. */
|
/* Open the logfile at this point and set the log mask if necessary. */
|
||||||
qemu_set_log_filename(log_file, &error_fatal);
|
if (log_file) {
|
||||||
|
qemu_set_log_filename(log_file, &error_fatal);
|
||||||
|
}
|
||||||
if (log_mask) {
|
if (log_mask) {
|
||||||
int mask;
|
int mask;
|
||||||
mask = qemu_str_to_log_mask(log_mask);
|
mask = qemu_str_to_log_mask(log_mask);
|
||||||
|
@ -2638,9 +2637,7 @@ void qemu_init(int argc, char **argv, char **envp)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userconfig) {
|
if (userconfig) {
|
||||||
if (qemu_read_default_config_file() < 0) {
|
qemu_read_default_config_file(&error_fatal);
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* second pass of option parsing */
|
/* second pass of option parsing */
|
||||||
|
@ -3328,15 +3325,8 @@ void qemu_init(int argc, char **argv, char **envp)
|
||||||
qemu_plugin_opt_parse(optarg, &plugin_list);
|
qemu_plugin_opt_parse(optarg, &plugin_list);
|
||||||
break;
|
break;
|
||||||
case QEMU_OPTION_readconfig:
|
case QEMU_OPTION_readconfig:
|
||||||
{
|
qemu_read_config_file(optarg, &error_fatal);
|
||||||
int ret = qemu_read_config_file(optarg);
|
break;
|
||||||
if (ret < 0) {
|
|
||||||
error_report("read config %s: %s", optarg,
|
|
||||||
strerror(-ret));
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case QEMU_OPTION_spice:
|
case QEMU_OPTION_spice:
|
||||||
olist = qemu_find_opts_err("spice", NULL);
|
olist = qemu_find_opts_err("spice", NULL);
|
||||||
if (!olist) {
|
if (!olist) {
|
||||||
|
@ -3475,6 +3465,19 @@ void qemu_init(int argc, char **argv, char **envp)
|
||||||
qemu_process_help_options();
|
qemu_process_help_options();
|
||||||
qemu_maybe_daemonize(pid_file);
|
qemu_maybe_daemonize(pid_file);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The trace backend must be initialized after daemonizing.
|
||||||
|
* trace_init_backends() will call st_init(), which will create the
|
||||||
|
* trace thread in the parent, and also register st_flush_trace_buffer()
|
||||||
|
* in atexit(). This function will force the parent to wait for the
|
||||||
|
* writeout thread to finish, which will not occur, and the parent
|
||||||
|
* process will be left in the host.
|
||||||
|
*/
|
||||||
|
if (!trace_init_backends()) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
trace_init_file();
|
||||||
|
|
||||||
qemu_init_main_loop(&error_fatal);
|
qemu_init_main_loop(&error_fatal);
|
||||||
cpu_timers_init();
|
cpu_timers_init();
|
||||||
|
|
||||||
|
|
|
@ -4352,8 +4352,13 @@ int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
|
||||||
{
|
{
|
||||||
uint8_t int3;
|
uint8_t int3;
|
||||||
|
|
||||||
if (cpu_memory_rw_debug(cs, bp->pc, &int3, 1, 0) || int3 != 0xcc ||
|
if (cpu_memory_rw_debug(cs, bp->pc, &int3, 1, 0)) {
|
||||||
cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&bp->saved_insn, 1, 1)) {
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if (int3 != 0xcc) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&bp->saved_insn, 1, 1)) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -624,7 +624,7 @@ test('fp-test-mulAdd', fptest,
|
||||||
# no fptest_rounding_args
|
# no fptest_rounding_args
|
||||||
args: fptest_args +
|
args: fptest_args +
|
||||||
['f16_mulAdd', 'f32_mulAdd', 'f64_mulAdd', 'f128_mulAdd'],
|
['f16_mulAdd', 'f32_mulAdd', 'f64_mulAdd', 'f128_mulAdd'],
|
||||||
suite: ['softfloat-slow', 'softfloat-ops-slow'], timeout: 60)
|
suite: ['softfloat-slow', 'softfloat-ops-slow'], timeout: 90)
|
||||||
|
|
||||||
fpbench = executable(
|
fpbench = executable(
|
||||||
'fp-bench',
|
'fp-bench',
|
||||||
|
|
|
@ -237,6 +237,11 @@ test_env = environment()
|
||||||
test_env.set('G_TEST_SRCDIR', meson.current_source_dir())
|
test_env.set('G_TEST_SRCDIR', meson.current_source_dir())
|
||||||
test_env.set('G_TEST_BUILDDIR', meson.current_build_dir())
|
test_env.set('G_TEST_BUILDDIR', meson.current_build_dir())
|
||||||
|
|
||||||
|
slow_tests = {
|
||||||
|
'test-crypto-tlscredsx509': 45,
|
||||||
|
'test-crypto-tlssession': 45
|
||||||
|
}
|
||||||
|
|
||||||
foreach test_name, extra: tests
|
foreach test_name, extra: tests
|
||||||
src = [test_name + '.c']
|
src = [test_name + '.c']
|
||||||
deps = [qemuutil]
|
deps = [qemuutil]
|
||||||
|
@ -254,6 +259,8 @@ foreach test_name, extra: tests
|
||||||
env: test_env,
|
env: test_env,
|
||||||
args: ['--tap', '-k'],
|
args: ['--tap', '-k'],
|
||||||
protocol: 'tap',
|
protocol: 'tap',
|
||||||
|
timeout: slow_tests.get(test_name, 30),
|
||||||
|
priority: slow_tests.get(test_name, 30),
|
||||||
suite: ['unit'])
|
suite: ['unit'])
|
||||||
endforeach
|
endforeach
|
||||||
|
|
||||||
|
@ -263,6 +270,7 @@ foreach bench_name, deps: benchs
|
||||||
benchmark(bench_name, exe,
|
benchmark(bench_name, exe,
|
||||||
args: ['--tap', '-k'],
|
args: ['--tap', '-k'],
|
||||||
protocol: 'tap',
|
protocol: 'tap',
|
||||||
|
timeout: 0,
|
||||||
suite: ['speed'])
|
suite: ['speed'])
|
||||||
endforeach
|
endforeach
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,19 @@ if not config_host.has_key('CONFIG_POSIX')
|
||||||
subdir_done()
|
subdir_done()
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
slow_qtests = {
|
||||||
|
'ahci-test' : 60,
|
||||||
|
'bios-tables-test' : 120,
|
||||||
|
'boot-serial-test' : 60,
|
||||||
|
'migration-test' : 150,
|
||||||
|
'npcm7xx_pwm-test': 150,
|
||||||
|
'prom-env-test' : 60,
|
||||||
|
'pxe-test' : 60,
|
||||||
|
'qos-test' : 60,
|
||||||
|
'qom-test' : 300,
|
||||||
|
'test-hmp' : 120,
|
||||||
|
}
|
||||||
|
|
||||||
qtests_generic = [
|
qtests_generic = [
|
||||||
'cdrom-test',
|
'cdrom-test',
|
||||||
'device-introspect-test',
|
'device-introspect-test',
|
||||||
|
@ -274,6 +287,8 @@ foreach dir : target_dirs
|
||||||
env: qtest_env,
|
env: qtest_env,
|
||||||
args: ['--tap', '-k'],
|
args: ['--tap', '-k'],
|
||||||
protocol: 'tap',
|
protocol: 'tap',
|
||||||
|
timeout: slow_qtests.get(test, 30),
|
||||||
|
priority: slow_qtests.get(test, 30),
|
||||||
suite: ['qtest', 'qtest-' + target_base])
|
suite: ['qtest', 'qtest-' + target_base])
|
||||||
endforeach
|
endforeach
|
||||||
endforeach
|
endforeach
|
||||||
|
|
|
@ -40,6 +40,7 @@ static size_t nevent_groups;
|
||||||
static uint32_t next_id;
|
static uint32_t next_id;
|
||||||
static uint32_t next_vcpu_id;
|
static uint32_t next_vcpu_id;
|
||||||
static bool init_trace_on_startup;
|
static bool init_trace_on_startup;
|
||||||
|
static char *trace_opts_file;
|
||||||
|
|
||||||
QemuOptsList qemu_trace_opts = {
|
QemuOptsList qemu_trace_opts = {
|
||||||
.name = "trace",
|
.name = "trace",
|
||||||
|
@ -224,10 +225,8 @@ static void trace_init_events(const char *fname)
|
||||||
|
|
||||||
void trace_init_file(void)
|
void trace_init_file(void)
|
||||||
{
|
{
|
||||||
QemuOpts *opts = qemu_find_opts_singleton("trace");
|
|
||||||
const char *file = qemu_opt_get(opts, "file");
|
|
||||||
#ifdef CONFIG_TRACE_SIMPLE
|
#ifdef CONFIG_TRACE_SIMPLE
|
||||||
st_set_trace_file(file);
|
st_set_trace_file(trace_opts_file);
|
||||||
if (init_trace_on_startup) {
|
if (init_trace_on_startup) {
|
||||||
st_set_trace_file_enabled(true);
|
st_set_trace_file_enabled(true);
|
||||||
}
|
}
|
||||||
|
@ -238,11 +237,11 @@ void trace_init_file(void)
|
||||||
* backend. However we should only override -D if we actually have
|
* backend. However we should only override -D if we actually have
|
||||||
* something to override it with.
|
* something to override it with.
|
||||||
*/
|
*/
|
||||||
if (file) {
|
if (trace_opts_file) {
|
||||||
qemu_set_log_filename(file, &error_fatal);
|
qemu_set_log_filename(trace_opts_file, &error_fatal);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (file) {
|
if (trace_opts_file) {
|
||||||
fprintf(stderr, "error: --trace file=...: "
|
fprintf(stderr, "error: --trace file=...: "
|
||||||
"option not supported by the selected tracing backends\n");
|
"option not supported by the selected tracing backends\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -303,6 +302,8 @@ void trace_opt_parse(const char *optarg)
|
||||||
}
|
}
|
||||||
trace_init_events(qemu_opt_get(opts, "events"));
|
trace_init_events(qemu_opt_get(opts, "events"));
|
||||||
init_trace_on_startup = true;
|
init_trace_on_startup = true;
|
||||||
|
g_free(trace_opts_file);
|
||||||
|
trace_opts_file = g_strdup(qemu_opt_get(opts, "file"));
|
||||||
qemu_opts_del(opts);
|
qemu_opts_del(opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -350,7 +350,7 @@ void qemu_config_write(FILE *fp)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns number of config groups on success, -errno on error */
|
/* Returns number of config groups on success, -errno on error */
|
||||||
int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname)
|
int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname, Error **errp)
|
||||||
{
|
{
|
||||||
char line[1024], group[64], id[64], arg[64], value[1024];
|
char line[1024], group[64], id[64], arg[64], value[1024];
|
||||||
Location loc;
|
Location loc;
|
||||||
|
@ -375,7 +375,7 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname)
|
||||||
/* group with id */
|
/* group with id */
|
||||||
list = find_list(lists, group, &local_err);
|
list = find_list(lists, group, &local_err);
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
error_report_err(local_err);
|
error_propagate(errp, local_err);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
opts = qemu_opts_create(list, id, 1, NULL);
|
opts = qemu_opts_create(list, id, 1, NULL);
|
||||||
|
@ -386,7 +386,7 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname)
|
||||||
/* group without id */
|
/* group without id */
|
||||||
list = find_list(lists, group, &local_err);
|
list = find_list(lists, group, &local_err);
|
||||||
if (local_err) {
|
if (local_err) {
|
||||||
error_report_err(local_err);
|
error_propagate(errp, local_err);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
opts = qemu_opts_create(list, NULL, 0, &error_abort);
|
opts = qemu_opts_create(list, NULL, 0, &error_abort);
|
||||||
|
@ -398,21 +398,21 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname)
|
||||||
sscanf(line, " %63s = \"\"", arg) == 1) {
|
sscanf(line, " %63s = \"\"", arg) == 1) {
|
||||||
/* arg = value */
|
/* arg = value */
|
||||||
if (opts == NULL) {
|
if (opts == NULL) {
|
||||||
error_report("no group defined");
|
error_setg(errp, "no group defined");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (!qemu_opt_set(opts, arg, value, &local_err)) {
|
if (!qemu_opt_set(opts, arg, value, errp)) {
|
||||||
error_report_err(local_err);
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
error_report("parse error");
|
error_setg(errp, "parse error");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (ferror(fp)) {
|
if (ferror(fp)) {
|
||||||
error_report("error reading file");
|
loc_pop(&loc);
|
||||||
goto out;
|
error_setg_errno(errp, errno, "Cannot read config file");
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
res = count;
|
res = count;
|
||||||
out:
|
out:
|
||||||
|
@ -420,16 +420,17 @@ out:
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
int qemu_read_config_file(const char *filename)
|
int qemu_read_config_file(const char *filename, Error **errp)
|
||||||
{
|
{
|
||||||
FILE *f = fopen(filename, "r");
|
FILE *f = fopen(filename, "r");
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (f == NULL) {
|
if (f == NULL) {
|
||||||
|
error_setg_file_open(errp, errno, filename);
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = qemu_config_parse(f, vm_config_groups, filename);
|
ret = qemu_config_parse(f, vm_config_groups, filename, errp);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -785,7 +785,11 @@ static const char *get_opt_name_value(const char *params,
|
||||||
}
|
}
|
||||||
if (!is_help && warn_on_flag) {
|
if (!is_help && warn_on_flag) {
|
||||||
warn_report("short-form boolean option '%s%s' deprecated", prefix, *name);
|
warn_report("short-form boolean option '%s%s' deprecated", prefix, *name);
|
||||||
error_printf("Please use %s=%s instead\n", *name, *value);
|
if (g_str_equal(*name, "delay")) {
|
||||||
|
error_printf("Please use nodelay=%s instead\n", prefix[0] ? "on" : "off");
|
||||||
|
} else {
|
||||||
|
error_printf("Please use %s=%s instead\n", *name, *value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue