mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
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:
@@ -149,7 +149,7 @@ $(ninja-targets): run-ninja
|
||||
# --output-sync line.
|
||||
run-ninja: config-host.mak
|
||||
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)
|
||||
endif
|
||||
endif
|
||||
|
||||
+12
-1
@@ -598,8 +598,12 @@ static void kvm_memslot_init_dirty_bitmap(KVMSlot *mem)
|
||||
* too, in most cases).
|
||||
* 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.
|
||||
*
|
||||
* 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;
|
||||
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_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,
|
||||
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;
|
||||
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
|
||||
* satisfy the KVM interface requirement. Firstly, do the start
|
||||
|
||||
+1
-2
@@ -279,9 +279,8 @@ static int read_config(BDRVBlkdebugState *s, const char *filename,
|
||||
return -errno;
|
||||
}
|
||||
|
||||
ret = qemu_config_parse(f, config_groups, filename);
|
||||
ret = qemu_config_parse(f, config_groups, filename, errp);
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Could not parse blkdebug config file");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
+11
-2
@@ -1472,8 +1472,17 @@ static void qemu_chr_parse_socket(QemuOpts *opts, ChardevBackend *backend,
|
||||
sock = backend->u.socket.data = g_new0(ChardevSocket, 1);
|
||||
qemu_chr_parse_common(opts, qapi_ChardevSocket_base(sock));
|
||||
|
||||
sock->has_nodelay = qemu_opt_get(opts, "delay");
|
||||
sock->nodelay = !qemu_opt_get_bool(opts, "delay", true);
|
||||
if (qemu_opt_get(opts, "delay") && qemu_opt_get(opts, "nodelay")) {
|
||||
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 can't just check for existence of 'server'
|
||||
|
||||
@@ -867,6 +867,9 @@ QemuOptsList qemu_chardev_opts = {
|
||||
},{
|
||||
.name = "delay",
|
||||
.type = QEMU_OPT_BOOL,
|
||||
},{
|
||||
.name = "nodelay",
|
||||
.type = QEMU_OPT_BOOL,
|
||||
},{
|
||||
.name = "reconnect",
|
||||
.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
|
||||
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)
|
||||
'''''''''''''''''''''''''''''
|
||||
|
||||
@@ -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
|
||||
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
|
||||
------------------------------------
|
||||
|
||||
|
||||
@@ -3505,7 +3505,7 @@ int gdbserver_start(const char *device)
|
||||
if (strstart(device, "tcp:", NULL)) {
|
||||
/* enforce required TCP attributes */
|
||||
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;
|
||||
}
|
||||
#ifndef _WIN32
|
||||
|
||||
+4
-2
@@ -690,6 +690,8 @@ static uint64_t read_pvh_start_addr(void *arg1, void *arg2, bool is64)
|
||||
elf_note_data_addr =
|
||||
((void *)nhdr64) + nhdr_size64 +
|
||||
QEMU_ALIGN_UP(nhdr_namesz, phdr_align);
|
||||
|
||||
pvh_start_addr = *elf_note_data_addr;
|
||||
} else {
|
||||
struct elf32_note *nhdr32 = (struct elf32_note *)arg1;
|
||||
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 =
|
||||
((void *)nhdr32) + nhdr_size32 +
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "hw/intc/i8259.h"
|
||||
#include "hw/pci/msi.h"
|
||||
#include "qemu/host-utils.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "trace.h"
|
||||
#include "hw/i386/apic-msidef.h"
|
||||
#include "qapi/error.h"
|
||||
@@ -875,6 +876,11 @@ static void apic_realize(DeviceState *dev, Error **errp)
|
||||
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",
|
||||
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);
|
||||
}
|
||||
|
||||
static void lsi_scsi_unrealize(DeviceState *dev)
|
||||
static void lsi_scsi_exit(PCIDevice *dev)
|
||||
{
|
||||
LSIState *s = LSI53C895A(dev);
|
||||
|
||||
@@ -2325,11 +2325,11 @@ static void lsi_class_init(ObjectClass *klass, void *data)
|
||||
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
|
||||
|
||||
k->realize = lsi_scsi_realize;
|
||||
k->exit = lsi_scsi_exit;
|
||||
k->vendor_id = PCI_VENDOR_ID_LSI_LOGIC;
|
||||
k->device_id = PCI_DEVICE_ID_LSI_53C895A;
|
||||
k->class_id = PCI_CLASS_STORAGE_SCSI;
|
||||
k->subsystem_id = 0x1000;
|
||||
dc->unrealize = lsi_scsi_unrealize;
|
||||
dc->reset = lsi_scsi_reset;
|
||||
dc->vmsd = &vmstate_lsi_scsi;
|
||||
set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
|
||||
|
||||
+31
-2
@@ -692,6 +692,7 @@ SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d,
|
||||
req->lun = lun;
|
||||
req->hba_private = hba_private;
|
||||
req->status = -1;
|
||||
req->host_status = -1;
|
||||
req->ops = reqops;
|
||||
object_ref(OBJECT(d));
|
||||
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)
|
||||
{
|
||||
assert(req->status == -1);
|
||||
assert(req->status == -1 && req->host_status == -1);
|
||||
req->status = status;
|
||||
req->host_status = SCSI_HOST_OK;
|
||||
|
||||
assert(req->sense_len <= sizeof(req->sense));
|
||||
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) {
|
||||
assert(!req->io_canceled);
|
||||
assert(req->status == -1);
|
||||
assert(req->status == -1 && req->host_status == -1);
|
||||
assert(req->enqueued);
|
||||
|
||||
qemu_put_sbyte(f, req->retry ? 1 : 2);
|
||||
|
||||
+42
-5
@@ -77,7 +77,6 @@ typedef struct SCSIDiskReq {
|
||||
struct iovec iov;
|
||||
QEMUIOVector qiov;
|
||||
BlockAcctCookie acct;
|
||||
unsigned char *status;
|
||||
} SCSIDiskReq;
|
||||
|
||||
#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) {
|
||||
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;
|
||||
@@ -2697,8 +2694,47 @@ typedef struct SCSIBlockReq {
|
||||
|
||||
/* CDB passed to SG_IO. */
|
||||
uint8_t cdb[16];
|
||||
BlockCompletionFunc *cb;
|
||||
void *cb_opaque;
|
||||
} 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,
|
||||
int64_t offset, QEMUIOVector *iov,
|
||||
int direction,
|
||||
@@ -2777,9 +2813,11 @@ static BlockAIOCB *scsi_block_do_sgio(SCSIBlockReq *req,
|
||||
io_header->timeout = s->qdev.io_timeout * 1000;
|
||||
io_header->usr_ptr = r;
|
||||
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,
|
||||
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);
|
||||
return aiocb;
|
||||
}
|
||||
@@ -2893,7 +2931,6 @@ static int32_t scsi_block_dma_command(SCSIRequest *req, uint8_t *buf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
r->req.status = &r->io_header.status;
|
||||
return scsi_disk_dma_command(req, buf);
|
||||
}
|
||||
|
||||
|
||||
+18
-7
@@ -75,6 +75,7 @@ static void scsi_command_complete_noio(SCSIGenericReq *r, int ret)
|
||||
{
|
||||
int status;
|
||||
SCSISense sense;
|
||||
sg_io_hdr_t *io_hdr = &r->io_header;
|
||||
|
||||
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);
|
||||
goto done;
|
||||
}
|
||||
status = sg_io_sense_from_errno(-ret, &r->io_header, &sense);
|
||||
if (status == CHECK_CONDITION) {
|
||||
if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
|
||||
r->req.sense_len = r->io_header.sb_len_wr;
|
||||
} else {
|
||||
if (ret < 0) {
|
||||
status = scsi_sense_from_errno(-ret, &sense);
|
||||
if (status == CHECK_CONDITION) {
|
||||
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);
|
||||
|
||||
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);
|
||||
goto done;
|
||||
}
|
||||
|
||||
@@ -500,6 +500,51 @@ static void virtio_scsi_complete_cmd_req(VirtIOSCSIReq *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)
|
||||
{
|
||||
VirtIOSCSIReq *req = r->hba_private;
|
||||
@@ -908,6 +953,7 @@ static struct SCSIBusInfo virtio_scsi_scsi_info = {
|
||||
.max_lun = VIRTIO_SCSI_MAX_LUN,
|
||||
|
||||
.complete = virtio_scsi_command_complete,
|
||||
.fail = virtio_scsi_command_failed,
|
||||
.cancel = virtio_scsi_request_cancelled,
|
||||
.change = virtio_scsi_change,
|
||||
.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);
|
||||
}
|
||||
|
||||
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
|
||||
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,
|
||||
.complete = pvscsi_command_complete,
|
||||
.cancel = pvscsi_request_cancelled,
|
||||
.fail = pvscsi_command_failed,
|
||||
};
|
||||
|
||||
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,
|
||||
*(uint64_t *)translate_opaque);
|
||||
if (nhdr != NULL) {
|
||||
bool is64 =
|
||||
sizeof(struct elf_note) == sizeof(struct elf64_note);
|
||||
elf_note_fn((void *)nhdr, (void *)&ph->p_align, is64);
|
||||
elf_note_fn((void *)nhdr, (void *)&ph->p_align, SZ == 64);
|
||||
}
|
||||
data = NULL;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,8 @@ struct SCSIRequest {
|
||||
uint32_t refcount;
|
||||
uint32_t tag;
|
||||
uint32_t lun;
|
||||
uint32_t status;
|
||||
int16_t status;
|
||||
int16_t host_status;
|
||||
void *hba_private;
|
||||
size_t resid;
|
||||
SCSICommand cmd;
|
||||
@@ -123,6 +124,7 @@ struct SCSIBusInfo {
|
||||
int (*parse_cdb)(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
|
||||
void *hba_private);
|
||||
void (*transfer_data)(SCSIRequest *req, uint32_t arg);
|
||||
void (*fail)(SCSIRequest *req);
|
||||
void (*complete)(SCSIRequest *req, size_t resid);
|
||||
void (*cancel)(SCSIRequest *req);
|
||||
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_data(SCSIRequest *req, int len);
|
||||
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);
|
||||
int scsi_req_get_sense(SCSIRequest *req, uint8_t *buf, int len);
|
||||
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);
|
||||
|
||||
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
|
||||
enumerated (0..(n-1)) configuration "sections") */
|
||||
|
||||
+17
-10
@@ -16,6 +16,22 @@ enum SCSIXferMode {
|
||||
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 {
|
||||
uint8_t buf[SCSI_CMD_BUF_SIZE];
|
||||
int len;
|
||||
@@ -123,18 +139,9 @@ int scsi_cdb_length(uint8_t *buf);
|
||||
#ifdef CONFIG_LINUX
|
||||
#define SG_ERR_DRIVER_TIMEOUT 0x06
|
||||
#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
|
||||
|
||||
int scsi_sense_from_errno(int errno_value, SCSISense *sense);
|
||||
int scsi_sense_from_host_status(uint8_t host_status, SCSISense *sense);
|
||||
|
||||
#endif
|
||||
|
||||
+12
@@ -1574,6 +1574,18 @@ if have_system
|
||||
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_opt = get_option('fdt')
|
||||
if have_system
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user