mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-24 03:59:52 +00:00
* warning improvements (Alistair)
* KVM code cleanup (David) * scsi-block support for rerror/werror (Fam) * support for >64 vCPUs in Windows (Gonglei) * SCSI fix (Hannes) * SSE bugfixes (Joseph) * SmartOS compilation fixes (Kamil) * Hyper-V frequency MSR support (Ladi) * move more files to accel/tcg (Philippe, Thomas) * multiboot validation (PJP) * virtqueue size configuration for virtio-scsi (Richard) * Hyper-V header cleanup (Roman) * Maintainer email update (Guangrong) * checkpatch.pl --branch (Daniel), fixes (Greg) * introducing scsi/ (me) -----BEGIN PGP SIGNATURE----- iQFIBAABCAAyFiEE8TM4V0tmI4mGbHaCv/vSX3jHroMFAlnBJ+YUHHBib256aW5p QHJlZGhhdC5jb20ACgkQv/vSX3jHroMBuwf+Ou4VjZQkSZu8GTIZOaRBOzMLZeKQ h+CZ4c7WO5ECsVPJMoLcvHhzLk9uBF0BXfcdbbJ435ppLaDOBnDznYzDL9uAeyFD lqz6vXfyHHb+9fMR2cvCb40DGFKwUkjmkNtjpTJLXH01JXyw+LLD5iuGEok33/OZ SZss5tM42eZj1JD/VtG5chGct/yhlipEx6sZ4b3/KZ/3wAqM6OR/IOKWUCV+cV/t UXtphOeLEdhWSf9pNeuUib0ij80p/degGU9o4Yo6mGjO94ev2mvMe3xqfsr7UMlU bhp3fUJvSTR6MqPnqh5dHnzWw8HVDudZoiRQ/nNybiO7NNfv4LceSKdLnA== =6us/ -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging * warning improvements (Alistair) * KVM code cleanup (David) * scsi-block support for rerror/werror (Fam) * support for >64 vCPUs in Windows (Gonglei) * SCSI fix (Hannes) * SSE bugfixes (Joseph) * SmartOS compilation fixes (Kamil) * Hyper-V frequency MSR support (Ladi) * move more files to accel/tcg (Philippe, Thomas) * multiboot validation (PJP) * virtqueue size configuration for virtio-scsi (Richard) * Hyper-V header cleanup (Roman) * Maintainer email update (Guangrong) * checkpatch.pl --branch (Daniel), fixes (Greg) * introducing scsi/ (me) # gpg: Signature made Tue 19 Sep 2017 15:21:26 BST # gpg: using RSA key 0xBFFBD25F78C7AE83 # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" # 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/tags/for-upstream: (51 commits) docker: fix creation of archives default-configs: Replace $(and ...) with $(call land, ...) osdep.h: Prohibit disabling assert() in supported builds checkpatch: add hwaddr to @typeList accel/hax: move hax-stub.c to accel/stubs/ target/i386: fix "info mem" for LA57 mode scripts: let checkpatch.pl process an entire GIT branch update-linux-headers: prepare for hyperv.h removal hyperv: add header with protocol definitions i386/cpu/hyperv: support over 64 vcpus for windows guests Convert remaining single line fprintf() to warn_report() Makefile: Remove libqemustub.a ptimer-test: do not link to libqemustub.a/libqemuutil.a target/mips: Convert VM clock update prints to warn_report General warn report fixups Convert multi-line fprintf() to warn_report() Convert single line fprintf(.../n) to warn_report() Convert remaining error_report() to warn_report() hw/i386: Improve some of the warning messages test-qga: add missing qemu-ga tool dependency ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
7ec6a36491
14
MAINTAINERS
14
MAINTAINERS
@ -968,7 +968,9 @@ SCSI
|
||||
M: Paolo Bonzini <pbonzini@redhat.com>
|
||||
S: Supported
|
||||
F: include/hw/scsi/*
|
||||
F: include/scsi/*
|
||||
F: hw/scsi/*
|
||||
F: util/scsi*
|
||||
F: tests/virtio-scsi-test.c
|
||||
T: git git://github.com/bonzini/qemu.git scsi-next
|
||||
|
||||
@ -1101,11 +1103,12 @@ F: hw/block/nvme*
|
||||
F: tests/nvme-test.c
|
||||
|
||||
megasas
|
||||
M: Hannes Reinecke <hare@suse.de>
|
||||
M: Hannes Reinecke <hare@suse.com>
|
||||
L: qemu-block@nongnu.org
|
||||
S: Supported
|
||||
F: hw/scsi/megasas.c
|
||||
F: hw/scsi/mfi.h
|
||||
F: tests/megasas-test.c
|
||||
|
||||
Network packet abstractions
|
||||
M: Dmitry Fleytman <dmitry@daynix.com>
|
||||
@ -1129,7 +1132,7 @@ F: tests/rocker/
|
||||
F: docs/specs/rocker.txt
|
||||
|
||||
NVDIMM
|
||||
M: Xiao Guangrong <guangrong.xiao@linux.intel.com>
|
||||
M: Xiao Guangrong <xiaoguangrong.eric@gmail.com>
|
||||
S: Maintained
|
||||
F: hw/acpi/nvdimm.c
|
||||
F: hw/mem/nvdimm.c
|
||||
@ -1213,6 +1216,13 @@ F: migration/block*
|
||||
F: include/block/aio.h
|
||||
T: git git://github.com/stefanha/qemu.git block
|
||||
|
||||
Block SCSI subsystem
|
||||
M: Paolo Bonzini <pbonzini@redhat.com>
|
||||
L: qemu-block@nongnu.org
|
||||
S: Supported
|
||||
F: include/scsi/*
|
||||
F: scsi/*
|
||||
|
||||
Block Jobs
|
||||
M: Jeff Cody <jcody@redhat.com>
|
||||
L: qemu-block@nongnu.org
|
||||
|
7
Makefile
7
Makefile
@ -335,7 +335,7 @@ subdir-dtc:dtc/libfdt dtc/tests
|
||||
dtc/%:
|
||||
mkdir -p $@
|
||||
|
||||
$(SUBDIR_RULES): libqemuutil.a libqemustub.a $(common-obj-y) $(chardev-obj-y) \
|
||||
$(SUBDIR_RULES): libqemuutil.a $(common-obj-y) $(chardev-obj-y) \
|
||||
$(qom-obj-y) $(crypto-aes-obj-$(CONFIG_USER_ONLY))
|
||||
|
||||
ROMSUBDIR_RULES=$(patsubst %,romsubdir-%, $(ROMS))
|
||||
@ -355,12 +355,11 @@ Makefile: $(version-obj-y)
|
||||
######################################################################
|
||||
# Build libraries
|
||||
|
||||
libqemustub.a: $(stub-obj-y)
|
||||
libqemuutil.a: $(util-obj-y) $(trace-obj-y)
|
||||
libqemuutil.a: $(util-obj-y) $(trace-obj-y) $(stub-obj-y)
|
||||
|
||||
######################################################################
|
||||
|
||||
COMMON_LDADDS = libqemuutil.a libqemustub.a
|
||||
COMMON_LDADDS = libqemuutil.a
|
||||
|
||||
qemu-img.o: qemu-img-cmds.h
|
||||
|
||||
|
@ -11,7 +11,7 @@ chardev-obj-y = chardev/
|
||||
|
||||
block-obj-y += nbd/
|
||||
block-obj-y += block.o blockjob.o
|
||||
block-obj-y += block/
|
||||
block-obj-y += block/ scsi/
|
||||
block-obj-y += qemu-io-cmds.o
|
||||
block-obj-$(CONFIG_REPLICATION) += replication.o
|
||||
|
||||
|
@ -101,7 +101,6 @@ obj-y += fpu/softfloat.o
|
||||
obj-y += target/$(TARGET_BASE_ARCH)/
|
||||
obj-y += disas.o
|
||||
obj-$(call notempty,$(TARGET_XML_FILES)) += gdbstub-xml.o
|
||||
obj-$(call lnot,$(CONFIG_HAX)) += hax-stub.o
|
||||
|
||||
obj-$(CONFIG_LIBDECNUMBER) += libdecnumber/decContext.o
|
||||
obj-$(CONFIG_LIBDECNUMBER) += libdecnumber/decNumber.o
|
||||
@ -193,7 +192,7 @@ all-obj-$(CONFIG_SOFTMMU) += $(io-obj-y)
|
||||
|
||||
$(QEMU_PROG_BUILD): config-devices.mak
|
||||
|
||||
COMMON_LDADDS = ../libqemuutil.a ../libqemustub.a
|
||||
COMMON_LDADDS = ../libqemuutil.a
|
||||
|
||||
# build either PROG or PROGW
|
||||
$(QEMU_PROG_BUILD): $(all-obj-y) $(COMMON_LDADDS)
|
||||
|
@ -79,7 +79,6 @@ struct KVMState
|
||||
int coalesced_mmio;
|
||||
struct kvm_coalesced_mmio_ring *coalesced_mmio_ring;
|
||||
bool coalesced_flush_in_progress;
|
||||
int broken_set_mem_region;
|
||||
int vcpu_events;
|
||||
int robust_singlestep;
|
||||
int debugregs;
|
||||
@ -127,6 +126,7 @@ static bool kvm_immediate_exit;
|
||||
static const KVMCapabilityInfo kvm_required_capabilites[] = {
|
||||
KVM_CAP_INFO(USER_MEMORY),
|
||||
KVM_CAP_INFO(DESTROY_MEMORY_REGION_WORKS),
|
||||
KVM_CAP_INFO(JOIN_MEMORY_REGIONS_WORKS),
|
||||
KVM_CAP_LAST_INFO
|
||||
};
|
||||
|
||||
@ -172,7 +172,7 @@ static KVMSlot *kvm_alloc_slot(KVMMemoryListener *kml)
|
||||
|
||||
static KVMSlot *kvm_lookup_matching_slot(KVMMemoryListener *kml,
|
||||
hwaddr start_addr,
|
||||
hwaddr end_addr)
|
||||
hwaddr size)
|
||||
{
|
||||
KVMState *s = kvm_state;
|
||||
int i;
|
||||
@ -180,8 +180,7 @@ static KVMSlot *kvm_lookup_matching_slot(KVMMemoryListener *kml,
|
||||
for (i = 0; i < s->nr_slots; i++) {
|
||||
KVMSlot *mem = &kml->slots[i];
|
||||
|
||||
if (start_addr == mem->start_addr &&
|
||||
end_addr == mem->start_addr + mem->memory_size) {
|
||||
if (start_addr == mem->start_addr && size == mem->memory_size) {
|
||||
return mem;
|
||||
}
|
||||
}
|
||||
@ -190,31 +189,33 @@ static KVMSlot *kvm_lookup_matching_slot(KVMMemoryListener *kml,
|
||||
}
|
||||
|
||||
/*
|
||||
* Find overlapping slot with lowest start address
|
||||
* Calculate and align the start address and the size of the section.
|
||||
* Return the size. If the size is 0, the aligned section is empty.
|
||||
*/
|
||||
static KVMSlot *kvm_lookup_overlapping_slot(KVMMemoryListener *kml,
|
||||
hwaddr start_addr,
|
||||
hwaddr end_addr)
|
||||
static hwaddr kvm_align_section(MemoryRegionSection *section,
|
||||
hwaddr *start)
|
||||
{
|
||||
KVMState *s = kvm_state;
|
||||
KVMSlot *found = NULL;
|
||||
int i;
|
||||
hwaddr size = int128_get64(section->size);
|
||||
hwaddr delta;
|
||||
|
||||
for (i = 0; i < s->nr_slots; i++) {
|
||||
KVMSlot *mem = &kml->slots[i];
|
||||
*start = section->offset_within_address_space;
|
||||
|
||||
if (mem->memory_size == 0 ||
|
||||
(found && found->start_addr < mem->start_addr)) {
|
||||
continue;
|
||||
/* kvm works in page size chunks, but the function may be called
|
||||
with sub-page size and unaligned start address. Pad the start
|
||||
address to next and truncate size to previous page boundary. */
|
||||
delta = qemu_real_host_page_size - (*start & ~qemu_real_host_page_mask);
|
||||
delta &= ~qemu_real_host_page_mask;
|
||||
*start += delta;
|
||||
if (delta > size) {
|
||||
return 0;
|
||||
}
|
||||
size -= delta;
|
||||
size &= qemu_real_host_page_mask;
|
||||
if (*start & ~qemu_real_host_page_mask) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (end_addr > mem->start_addr &&
|
||||
start_addr < mem->start_addr + mem->memory_size) {
|
||||
found = mem;
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
return size;
|
||||
}
|
||||
|
||||
int kvm_physical_memory_addr_from_host(KVMState *s, void *ram,
|
||||
@ -382,15 +383,21 @@ static int kvm_slot_update_flags(KVMMemoryListener *kml, KVMSlot *mem,
|
||||
static int kvm_section_update_flags(KVMMemoryListener *kml,
|
||||
MemoryRegionSection *section)
|
||||
{
|
||||
hwaddr phys_addr = section->offset_within_address_space;
|
||||
ram_addr_t size = int128_get64(section->size);
|
||||
KVMSlot *mem = kvm_lookup_matching_slot(kml, phys_addr, phys_addr + size);
|
||||
hwaddr start_addr, size;
|
||||
KVMSlot *mem;
|
||||
|
||||
if (mem == NULL) {
|
||||
size = kvm_align_section(section, &start_addr);
|
||||
if (!size) {
|
||||
return 0;
|
||||
} else {
|
||||
return kvm_slot_update_flags(kml, mem, section->mr);
|
||||
}
|
||||
|
||||
mem = kvm_lookup_matching_slot(kml, start_addr, size);
|
||||
if (!mem) {
|
||||
fprintf(stderr, "%s: error finding slot\n", __func__);
|
||||
abort();
|
||||
}
|
||||
|
||||
return kvm_slot_update_flags(kml, mem, section->mr);
|
||||
}
|
||||
|
||||
static void kvm_log_start(MemoryListener *listener,
|
||||
@ -454,18 +461,16 @@ static int kvm_physical_sync_dirty_bitmap(KVMMemoryListener *kml,
|
||||
MemoryRegionSection *section)
|
||||
{
|
||||
KVMState *s = kvm_state;
|
||||
unsigned long size, allocated_size = 0;
|
||||
struct kvm_dirty_log d = {};
|
||||
KVMSlot *mem;
|
||||
int ret = 0;
|
||||
hwaddr start_addr = section->offset_within_address_space;
|
||||
hwaddr end_addr = start_addr + int128_get64(section->size);
|
||||
hwaddr start_addr, size;
|
||||
|
||||
d.dirty_bitmap = NULL;
|
||||
while (start_addr < end_addr) {
|
||||
mem = kvm_lookup_overlapping_slot(kml, start_addr, end_addr);
|
||||
if (mem == NULL) {
|
||||
break;
|
||||
size = kvm_align_section(section, &start_addr);
|
||||
if (size) {
|
||||
mem = kvm_lookup_matching_slot(kml, start_addr, size);
|
||||
if (!mem) {
|
||||
fprintf(stderr, "%s: error finding slot\n", __func__);
|
||||
abort();
|
||||
}
|
||||
|
||||
/* XXX bad kernel interface alert
|
||||
@ -482,27 +487,20 @@ static int kvm_physical_sync_dirty_bitmap(KVMMemoryListener *kml,
|
||||
*/
|
||||
size = ALIGN(((mem->memory_size) >> TARGET_PAGE_BITS),
|
||||
/*HOST_LONG_BITS*/ 64) / 8;
|
||||
if (!d.dirty_bitmap) {
|
||||
d.dirty_bitmap = g_malloc(size);
|
||||
} else if (size > allocated_size) {
|
||||
d.dirty_bitmap = g_realloc(d.dirty_bitmap, size);
|
||||
}
|
||||
allocated_size = size;
|
||||
memset(d.dirty_bitmap, 0, allocated_size);
|
||||
d.dirty_bitmap = g_malloc0(size);
|
||||
|
||||
d.slot = mem->slot | (kml->as_id << 16);
|
||||
if (kvm_vm_ioctl(s, KVM_GET_DIRTY_LOG, &d) == -1) {
|
||||
DPRINTF("ioctl failed %d\n", errno);
|
||||
ret = -1;
|
||||
break;
|
||||
g_free(d.dirty_bitmap);
|
||||
return -1;
|
||||
}
|
||||
|
||||
kvm_get_dirty_pages_log_range(section, d.dirty_bitmap);
|
||||
start_addr = mem->start_addr + mem->memory_size;
|
||||
}
|
||||
g_free(d.dirty_bitmap);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void kvm_coalesce_mmio_region(MemoryListener *listener,
|
||||
@ -696,30 +694,12 @@ kvm_check_extension_list(KVMState *s, const KVMCapabilityInfo *list)
|
||||
static void kvm_set_phys_mem(KVMMemoryListener *kml,
|
||||
MemoryRegionSection *section, bool add)
|
||||
{
|
||||
KVMState *s = kvm_state;
|
||||
KVMSlot *mem, old;
|
||||
KVMSlot *mem;
|
||||
int err;
|
||||
MemoryRegion *mr = section->mr;
|
||||
bool writeable = !mr->readonly && !mr->rom_device;
|
||||
hwaddr start_addr = section->offset_within_address_space;
|
||||
ram_addr_t size = int128_get64(section->size);
|
||||
void *ram = NULL;
|
||||
unsigned delta;
|
||||
|
||||
/* kvm works in page size chunks, but the function may be called
|
||||
with sub-page size and unaligned start address. Pad the start
|
||||
address to next and truncate size to previous page boundary. */
|
||||
delta = qemu_real_host_page_size - (start_addr & ~qemu_real_host_page_mask);
|
||||
delta &= ~qemu_real_host_page_mask;
|
||||
if (delta > size) {
|
||||
return;
|
||||
}
|
||||
start_addr += delta;
|
||||
size -= delta;
|
||||
size &= qemu_real_host_page_mask;
|
||||
if (!size || (start_addr & ~qemu_real_host_page_mask)) {
|
||||
return;
|
||||
}
|
||||
hwaddr start_addr, size;
|
||||
void *ram;
|
||||
|
||||
if (!memory_region_is_ram(mr)) {
|
||||
if (writeable || !kvm_readonly_mem_allowed) {
|
||||
@ -731,30 +711,25 @@ static void kvm_set_phys_mem(KVMMemoryListener *kml,
|
||||
}
|
||||
}
|
||||
|
||||
ram = memory_region_get_ram_ptr(mr) + section->offset_within_region + delta;
|
||||
|
||||
while (1) {
|
||||
mem = kvm_lookup_overlapping_slot(kml, start_addr, start_addr + size);
|
||||
if (!mem) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (add && start_addr >= mem->start_addr &&
|
||||
(start_addr + size <= mem->start_addr + mem->memory_size) &&
|
||||
(ram - start_addr == mem->ram - mem->start_addr)) {
|
||||
/* The new slot fits into the existing one and comes with
|
||||
* identical parameters - update flags and done. */
|
||||
kvm_slot_update_flags(kml, mem, mr);
|
||||
size = kvm_align_section(section, &start_addr);
|
||||
if (!size) {
|
||||
return;
|
||||
}
|
||||
|
||||
old = *mem;
|
||||
ram = memory_region_get_ram_ptr(mr) + section->offset_within_region +
|
||||
(section->offset_within_address_space - start_addr);
|
||||
|
||||
mem = kvm_lookup_matching_slot(kml, start_addr, size);
|
||||
if (!add) {
|
||||
if (!mem) {
|
||||
g_assert(!memory_region_is_ram(mr) && !writeable && !mr->romd_mode);
|
||||
return;
|
||||
}
|
||||
if (mem->flags & KVM_MEM_LOG_DIRTY_PAGES) {
|
||||
kvm_physical_sync_dirty_bitmap(kml, section);
|
||||
}
|
||||
|
||||
/* unregister the overlapping slot */
|
||||
/* unregister the slot */
|
||||
mem->memory_size = 0;
|
||||
err = kvm_set_user_memory_region(kml, mem);
|
||||
if (err) {
|
||||
@ -762,84 +737,16 @@ static void kvm_set_phys_mem(KVMMemoryListener *kml,
|
||||
__func__, strerror(-err));
|
||||
abort();
|
||||
}
|
||||
|
||||
/* Workaround for older KVM versions: we can't join slots, even not by
|
||||
* unregistering the previous ones and then registering the larger
|
||||
* slot. We have to maintain the existing fragmentation. Sigh.
|
||||
*
|
||||
* This workaround assumes that the new slot starts at the same
|
||||
* address as the first existing one. If not or if some overlapping
|
||||
* slot comes around later, we will fail (not seen in practice so far)
|
||||
* - and actually require a recent KVM version. */
|
||||
if (s->broken_set_mem_region &&
|
||||
old.start_addr == start_addr && old.memory_size < size && add) {
|
||||
mem = kvm_alloc_slot(kml);
|
||||
mem->memory_size = old.memory_size;
|
||||
mem->start_addr = old.start_addr;
|
||||
mem->ram = old.ram;
|
||||
mem->flags = kvm_mem_flags(mr);
|
||||
|
||||
err = kvm_set_user_memory_region(kml, mem);
|
||||
if (err) {
|
||||
fprintf(stderr, "%s: error updating slot: %s\n", __func__,
|
||||
strerror(-err));
|
||||
abort();
|
||||
}
|
||||
|
||||
start_addr += old.memory_size;
|
||||
ram += old.memory_size;
|
||||
size -= old.memory_size;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* register prefix slot */
|
||||
if (old.start_addr < start_addr) {
|
||||
mem = kvm_alloc_slot(kml);
|
||||
mem->memory_size = start_addr - old.start_addr;
|
||||
mem->start_addr = old.start_addr;
|
||||
mem->ram = old.ram;
|
||||
mem->flags = kvm_mem_flags(mr);
|
||||
|
||||
err = kvm_set_user_memory_region(kml, mem);
|
||||
if (err) {
|
||||
fprintf(stderr, "%s: error registering prefix slot: %s\n",
|
||||
__func__, strerror(-err));
|
||||
#ifdef TARGET_PPC
|
||||
fprintf(stderr, "%s: This is probably because your kernel's " \
|
||||
"PAGE_SIZE is too big. Please try to use 4k " \
|
||||
"PAGE_SIZE!\n", __func__);
|
||||
#endif
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
/* register suffix slot */
|
||||
if (old.start_addr + old.memory_size > start_addr + size) {
|
||||
ram_addr_t size_delta;
|
||||
|
||||
mem = kvm_alloc_slot(kml);
|
||||
mem->start_addr = start_addr + size;
|
||||
size_delta = mem->start_addr - old.start_addr;
|
||||
mem->memory_size = old.memory_size - size_delta;
|
||||
mem->ram = old.ram + size_delta;
|
||||
mem->flags = kvm_mem_flags(mr);
|
||||
|
||||
err = kvm_set_user_memory_region(kml, mem);
|
||||
if (err) {
|
||||
fprintf(stderr, "%s: error registering suffix slot: %s\n",
|
||||
__func__, strerror(-err));
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* in case the KVM bug workaround already "consumed" the new slot */
|
||||
if (!size) {
|
||||
return;
|
||||
}
|
||||
if (!add) {
|
||||
|
||||
if (mem) {
|
||||
/* update the slot */
|
||||
kvm_slot_update_flags(kml, mem, mr);
|
||||
return;
|
||||
}
|
||||
|
||||
/* register the new slot */
|
||||
mem = kvm_alloc_slot(kml);
|
||||
mem->memory_size = size;
|
||||
mem->start_addr = start_addr;
|
||||
@ -1629,9 +1536,8 @@ static int kvm_init(MachineState *ms)
|
||||
|
||||
while (nc->name) {
|
||||
if (nc->num > soft_vcpus_limit) {
|
||||
fprintf(stderr,
|
||||
"Warning: Number of %s cpus requested (%d) exceeds "
|
||||
"the recommended cpus supported by KVM (%d)\n",
|
||||
warn_report("Number of %s cpus requested (%d) exceeds "
|
||||
"the recommended cpus supported by KVM (%d)",
|
||||
nc->name, nc->num, soft_vcpus_limit);
|
||||
|
||||
if (nc->num > hard_vcpus_limit) {
|
||||
@ -1692,12 +1598,6 @@ static int kvm_init(MachineState *ms)
|
||||
|
||||
s->coalesced_mmio = kvm_check_extension(s, KVM_CAP_COALESCED_MMIO);
|
||||
|
||||
s->broken_set_mem_region = 1;
|
||||
ret = kvm_check_extension(s, KVM_CAP_JOIN_MEMORY_REGIONS_WORKS);
|
||||
if (ret > 0) {
|
||||
s->broken_set_mem_region = 0;
|
||||
}
|
||||
|
||||
#ifdef KVM_CAP_VCPU_EVENTS
|
||||
s->vcpu_events = kvm_check_extension(s, KVM_CAP_VCPU_EVENTS);
|
||||
#endif
|
||||
|
@ -1,2 +1,3 @@
|
||||
obj-$(call lnot,$(CONFIG_HAX)) += hax-stub.o
|
||||
obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
|
||||
obj-$(call lnot,$(CONFIG_TCG)) += tcg-stub.o
|
||||
|
@ -34,15 +34,20 @@
|
||||
#include "qemu/bitops.h"
|
||||
#include "qemu/bitmap.h"
|
||||
#include "block/block_int.h"
|
||||
#include "block/scsi.h"
|
||||
#include "scsi/constants.h"
|
||||
#include "qemu/iov.h"
|
||||
#include "qemu/uuid.h"
|
||||
#include "qmp-commands.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
#include "crypto/secret.h"
|
||||
#include "scsi/utils.h"
|
||||
|
||||
/* Conflict between scsi/utils.h and libiscsi! :( */
|
||||
#define SCSI_XFER_NONE ISCSI_XFER_NONE
|
||||
#include <iscsi/iscsi.h>
|
||||
#include <iscsi/scsi-lowlevel.h>
|
||||
#undef SCSI_XFER_NONE
|
||||
QEMU_BUILD_BUG_ON((int)SCSI_XFER_NONE != (int)ISCSI_XFER_NONE);
|
||||
|
||||
#ifdef __linux__
|
||||
#include <scsi/sg.h>
|
||||
@ -209,47 +214,9 @@ static inline unsigned exp_random(double mean)
|
||||
|
||||
static int iscsi_translate_sense(struct scsi_sense *sense)
|
||||
{
|
||||
int ret;
|
||||
|
||||
switch (sense->key) {
|
||||
case SCSI_SENSE_NOT_READY:
|
||||
return -EBUSY;
|
||||
case SCSI_SENSE_DATA_PROTECTION:
|
||||
return -EACCES;
|
||||
case SCSI_SENSE_COMMAND_ABORTED:
|
||||
return -ECANCELED;
|
||||
case SCSI_SENSE_ILLEGAL_REQUEST:
|
||||
/* Parse ASCQ */
|
||||
break;
|
||||
default:
|
||||
return -EIO;
|
||||
}
|
||||
switch (sense->ascq) {
|
||||
case SCSI_SENSE_ASCQ_PARAMETER_LIST_LENGTH_ERROR:
|
||||
case SCSI_SENSE_ASCQ_INVALID_OPERATION_CODE:
|
||||
case SCSI_SENSE_ASCQ_INVALID_FIELD_IN_CDB:
|
||||
case SCSI_SENSE_ASCQ_INVALID_FIELD_IN_PARAMETER_LIST:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
case SCSI_SENSE_ASCQ_LBA_OUT_OF_RANGE:
|
||||
ret = -ENOSPC;
|
||||
break;
|
||||
case SCSI_SENSE_ASCQ_LOGICAL_UNIT_NOT_SUPPORTED:
|
||||
ret = -ENOTSUP;
|
||||
break;
|
||||
case SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT:
|
||||
case SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT_TRAY_CLOSED:
|
||||
case SCSI_SENSE_ASCQ_MEDIUM_NOT_PRESENT_TRAY_OPEN:
|
||||
ret = -ENOMEDIUM;
|
||||
break;
|
||||
case SCSI_SENSE_ASCQ_WRITE_PROTECTED:
|
||||
ret = -EACCES;
|
||||
break;
|
||||
default:
|
||||
ret = -EIO;
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
return - scsi_sense_to_errno(sense->key,
|
||||
(sense->ascq & 0xFF00) >> 8,
|
||||
sense->ascq & 0xFF);
|
||||
}
|
||||
|
||||
/* Called (via iscsi_service) with QemuMutex held. */
|
||||
|
@ -301,10 +301,11 @@ static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
|
||||
}
|
||||
|
||||
if (!(s->autoclear_features & QCOW2_AUTOCLEAR_BITMAPS)) {
|
||||
error_report("WARNING: a program lacking bitmap support "
|
||||
warn_report("a program lacking bitmap support "
|
||||
"modified this file, so all bitmaps are now "
|
||||
"considered inconsistent. Some clusters may be "
|
||||
"leaked, run 'qemu-img check -r' on the image "
|
||||
"considered inconsistent");
|
||||
error_printf("Some clusters may be leaked, "
|
||||
"run 'qemu-img check -r' on the image "
|
||||
"file to fix.");
|
||||
if (need_update_header != NULL) {
|
||||
/* Updating is needed to drop invalid bitmap extension. */
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "qapi/qmp/qbool.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qemu/error-report.h"
|
||||
|
||||
#ifndef S_IWGRP
|
||||
#define S_IWGRP 0
|
||||
@ -1226,8 +1227,7 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
|
||||
switch (s->fat_type) {
|
||||
case 32:
|
||||
fprintf(stderr, "Big fat greek warning: FAT32 has not been tested. "
|
||||
"You are welcome to do so!\n");
|
||||
warn_report("FAT32 has not been tested. You are welcome to do so!");
|
||||
break;
|
||||
case 16:
|
||||
case 12:
|
||||
@ -3028,7 +3028,8 @@ DLOG(checkpoint());
|
||||
if (memcmp(direntries + k,
|
||||
array_get(&(s->directory), dir_index + k),
|
||||
sizeof(direntry_t))) {
|
||||
fprintf(stderr, "Warning: tried to write to write-protected file\n");
|
||||
warn_report("tried to write to write-protected "
|
||||
"file");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -43,4 +43,4 @@ CONFIG_VGA=y
|
||||
CONFIG_VGA_PCI=y
|
||||
CONFIG_IVSHMEM_DEVICE=$(CONFIG_IVSHMEM)
|
||||
CONFIG_ROCKER=y
|
||||
CONFIG_VHOST_USER_SCSI=$(and $(CONFIG_VHOST_USER),$(CONFIG_LINUX))
|
||||
CONFIG_VHOST_USER_SCSI=$(call land,$(CONFIG_VHOST_USER),$(CONFIG_LINUX))
|
||||
|
@ -43,7 +43,7 @@ CONFIG_XILINX_ETHLITE=y
|
||||
CONFIG_PREP=y
|
||||
CONFIG_MAC=y
|
||||
CONFIG_E500=y
|
||||
CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM))
|
||||
CONFIG_OPENPIC_KVM=$(call land,$(CONFIG_E500),$(CONFIG_KVM))
|
||||
CONFIG_PLATFORM_BUS=y
|
||||
CONFIG_ETSEC=y
|
||||
CONFIG_LIBDECNUMBER=y
|
||||
|
@ -48,7 +48,7 @@ CONFIG_POWERNV=y
|
||||
CONFIG_PREP=y
|
||||
CONFIG_MAC=y
|
||||
CONFIG_E500=y
|
||||
CONFIG_OPENPIC_KVM=$(and $(CONFIG_E500),$(CONFIG_KVM))
|
||||
CONFIG_OPENPIC_KVM=$(call land,$(CONFIG_E500),$(CONFIG_KVM))
|
||||
CONFIG_PLATFORM_BUS=y
|
||||
CONFIG_ETSEC=y
|
||||
CONFIG_LIBDECNUMBER=y
|
||||
@ -56,7 +56,7 @@ CONFIG_SM501=y
|
||||
# For pSeries
|
||||
CONFIG_XICS=$(CONFIG_PSERIES)
|
||||
CONFIG_XICS_SPAPR=$(CONFIG_PSERIES)
|
||||
CONFIG_XICS_KVM=$(and $(CONFIG_PSERIES),$(CONFIG_KVM))
|
||||
CONFIG_XICS_KVM=$(call land,$(CONFIG_PSERIES),$(CONFIG_KVM))
|
||||
# For PReP
|
||||
CONFIG_SERIAL_ISA=y
|
||||
CONFIG_MC146818RTC=y
|
||||
|
@ -1,6 +1,6 @@
|
||||
CONFIG_PCI=y
|
||||
CONFIG_VIRTIO_PCI=$(CONFIG_PCI)
|
||||
CONFIG_VHOST_USER_SCSI=$(and $(CONFIG_VHOST_USER),$(CONFIG_LINUX))
|
||||
CONFIG_VHOST_USER_SCSI=$(call land,$(CONFIG_VHOST_USER),$(CONFIG_LINUX))
|
||||
CONFIG_VIRTIO=y
|
||||
CONFIG_SCLPCONSOLE=y
|
||||
CONFIG_TERMINAL3270=y
|
||||
|
@ -232,15 +232,15 @@ The utility code that is used by all binaries is built into a
|
||||
static archive called libqemuutil.a, which is then linked to all the
|
||||
binaries. In order to provide hooks that are only needed by some of the
|
||||
binaries, code in libqemuutil.a may depend on other functions that are
|
||||
not fully implemented by all QEMU binaries. To deal with this there is a
|
||||
second library called libqemustub.a which provides dummy stubs for all
|
||||
these functions. These will get lazy linked into the binary if the real
|
||||
implementation is not present. In this way, the libqemustub.a static
|
||||
library can be thought of as a portable implementation of the weak
|
||||
symbols concept. All binaries should link to both libqemuutil.a and
|
||||
libqemustub.a. e.g.
|
||||
not fully implemented by all QEMU binaries. Dummy stubs for all these
|
||||
functions are also provided by this library, and will only be linked
|
||||
into the binary if the real implementation is not present. In a way,
|
||||
the stubs can be thought of as a portable implementation of the weak
|
||||
symbols concept.
|
||||
|
||||
qemu-img$(EXESUF): qemu-img.o ..snip.. libqemuutil.a libqemustub.a
|
||||
All binaries should link to libqemuutil.a, e.g.:
|
||||
|
||||
qemu-img$(EXESUF): qemu-img.o ..snip.. libqemuutil.a
|
||||
|
||||
|
||||
Windows platform portability
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "qapi/opts-visitor.h"
|
||||
#include "qapi-visit.h"
|
||||
#include "qapi-event.h"
|
||||
#include "qemu/error-report.h"
|
||||
|
||||
struct acpi_table_header {
|
||||
uint16_t _length; /* our length, not actual part of the hdr */
|
||||
@ -183,9 +184,8 @@ static void acpi_table_install(const char unsigned *blob, size_t bloblen,
|
||||
}
|
||||
|
||||
if (has_header && le32_to_cpu(ext_hdr->length) != acpi_payload_size) {
|
||||
fprintf(stderr,
|
||||
"warning: ACPI table has wrong length, header says "
|
||||
"%" PRIu32 ", actual size %zu bytes\n",
|
||||
warn_report("ACPI table has wrong length, header says "
|
||||
"%" PRIu32 ", actual size %zu bytes",
|
||||
le32_to_cpu(ext_hdr->length), acpi_payload_size);
|
||||
}
|
||||
ext_hdr->length = cpu_to_le32(acpi_payload_size);
|
||||
@ -221,7 +221,7 @@ static void acpi_table_install(const char unsigned *blob, size_t bloblen,
|
||||
}
|
||||
|
||||
if (!has_header && changed_fields == 0) {
|
||||
fprintf(stderr, "warning: ACPI table: no headers are specified\n");
|
||||
warn_report("ACPI table: no headers are specified");
|
||||
}
|
||||
|
||||
/* recalculate checksum */
|
||||
|
@ -493,8 +493,8 @@ static void vexpress_modify_dtb(const struct arm_boot_info *info, void *fdt)
|
||||
/* Not fatal, we just won't provide virtio. This will
|
||||
* happen with older device tree blobs.
|
||||
*/
|
||||
fprintf(stderr, "QEMU: warning: couldn't find interrupt controller in "
|
||||
"dtb; will not include virtio-mmio devices in the dtb.\n");
|
||||
warn_report("couldn't find interrupt controller in "
|
||||
"dtb; will not include virtio-mmio devices in the dtb");
|
||||
} else {
|
||||
int i;
|
||||
const hwaddr *map = daughterboard->motherboard_map;
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include "sysemu/blockdev.h"
|
||||
#include "hw/virtio/virtio-blk.h"
|
||||
#include "dataplane/virtio-blk.h"
|
||||
#include "block/scsi.h"
|
||||
#include "scsi/constants.h"
|
||||
#ifdef __linux__
|
||||
# include <scsi/sg.h>
|
||||
#endif
|
||||
|
@ -2750,17 +2750,22 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
|
||||
ACPI_BUILD_ALIGN_SIZE);
|
||||
if (tables_blob->len > legacy_table_size) {
|
||||
/* Should happen only with PCI bridges and -M pc-i440fx-2.0. */
|
||||
warn_report("migration may not work.");
|
||||
warn_report("ACPI table size %u exceeds %d bytes,"
|
||||
" migration may not work",
|
||||
tables_blob->len, legacy_table_size);
|
||||
error_printf("Try removing CPUs, NUMA nodes, memory slots"
|
||||
" or PCI bridges.");
|
||||
}
|
||||
g_array_set_size(tables_blob, legacy_table_size);
|
||||
} else {
|
||||
/* Make sure we have a buffer in case we need to resize the tables. */
|
||||
if (tables_blob->len > ACPI_BUILD_TABLE_SIZE / 2) {
|
||||
/* As of QEMU 2.1, this fires with 160 VCPUs and 255 memory slots. */
|
||||
warn_report("ACPI tables are larger than 64k.");
|
||||
warn_report("migration may not work.");
|
||||
warn_report("please remove CPUs, NUMA nodes, "
|
||||
"memory slots or PCI bridges.");
|
||||
warn_report("ACPI table size %u exceeds %d bytes,"
|
||||
" migration may not work",
|
||||
tables_blob->len, ACPI_BUILD_TABLE_SIZE / 2);
|
||||
error_printf("Try removing CPUs, NUMA nodes, memory slots"
|
||||
" or PCI bridges.");
|
||||
}
|
||||
acpi_align_size(tables_blob, ACPI_BUILD_TABLE_SIZE);
|
||||
}
|
||||
|
@ -221,15 +221,34 @@ int load_multiboot(FWCfgState *fw_cfg,
|
||||
uint32_t mh_header_addr = ldl_p(header+i+12);
|
||||
uint32_t mh_load_end_addr = ldl_p(header+i+20);
|
||||
uint32_t mh_bss_end_addr = ldl_p(header+i+24);
|
||||
|
||||
mh_load_addr = ldl_p(header+i+16);
|
||||
if (mh_header_addr < mh_load_addr) {
|
||||
fprintf(stderr, "invalid mh_load_addr address\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uint32_t mb_kernel_text_offset = i - (mh_header_addr - mh_load_addr);
|
||||
uint32_t mb_load_size = 0;
|
||||
mh_entry_addr = ldl_p(header+i+28);
|
||||
|
||||
if (mh_load_end_addr) {
|
||||
if (mh_bss_end_addr < mh_load_addr) {
|
||||
fprintf(stderr, "invalid mh_bss_end_addr address\n");
|
||||
exit(1);
|
||||
}
|
||||
mb_kernel_size = mh_bss_end_addr - mh_load_addr;
|
||||
|
||||
if (mh_load_end_addr < mh_load_addr) {
|
||||
fprintf(stderr, "invalid mh_load_end_addr address\n");
|
||||
exit(1);
|
||||
}
|
||||
mb_load_size = mh_load_end_addr - mh_load_addr;
|
||||
} else {
|
||||
if (kernel_file_size < mb_kernel_text_offset) {
|
||||
fprintf(stderr, "invalid kernel_file_size\n");
|
||||
exit(1);
|
||||
}
|
||||
mb_kernel_size = kernel_file_size - mb_kernel_text_offset;
|
||||
mb_load_size = mb_kernel_size;
|
||||
}
|
||||
|
@ -384,7 +384,7 @@ ISADevice *pc_find_fdc0(void)
|
||||
warn_report("multiple floppy disk controllers with "
|
||||
"iobase=0x3f0 have been found");
|
||||
error_printf("the one being picked for CMOS setup might not reflect "
|
||||
"your intent\n");
|
||||
"your intent");
|
||||
}
|
||||
|
||||
return state.floppy;
|
||||
@ -1310,7 +1310,7 @@ void pc_acpi_init(const char *default_dsdt)
|
||||
|
||||
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, default_dsdt);
|
||||
if (filename == NULL) {
|
||||
fprintf(stderr, "WARNING: failed to find %s\n", default_dsdt);
|
||||
warn_report("failed to find %s", default_dsdt);
|
||||
} else {
|
||||
QemuOpts *opts = qemu_opts_create(qemu_find_opts("acpi"), NULL, 0,
|
||||
&error_abort);
|
||||
@ -2098,9 +2098,8 @@ static void pc_machine_set_max_ram_below_4g(Object *obj, Visitor *v,
|
||||
}
|
||||
|
||||
if (value < (1ULL << 20)) {
|
||||
warn_report("small max_ram_below_4g(%"PRIu64
|
||||
") less than 1M. BIOS may not work..",
|
||||
value);
|
||||
warn_report("Only %" PRIu64 " bytes of RAM below the 4GiB boundary,"
|
||||
"BIOS may not work with less than 1MiB", value);
|
||||
}
|
||||
|
||||
pcms->max_ram_below_4g = value;
|
||||
|
@ -101,9 +101,11 @@ static void pc_q35_init(MachineState *machine)
|
||||
lowmem = pcms->max_ram_below_4g;
|
||||
if (machine->ram_size - lowmem > lowmem &&
|
||||
lowmem & ((1ULL << 30) - 1)) {
|
||||
warn_report("Large machine and max_ram_below_4g(%"PRIu64
|
||||
") not a multiple of 1G; possible bad performance.",
|
||||
pcms->max_ram_below_4g);
|
||||
warn_report("There is possibly poor performance as the ram size "
|
||||
" (0x%" PRIx64 ") is more then twice the size of"
|
||||
" max-ram-below-4g (%"PRIu64") and"
|
||||
" max-ram-below-4g is not a multiple of 1G.",
|
||||
(uint64_t)machine->ram_size, pcms->max_ram_below_4g);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/error-report.h"
|
||||
|
||||
#include <sys/resource.h>
|
||||
|
||||
@ -125,8 +126,8 @@ void xen_map_cache_init(phys_offset_to_gaddr_t f, void *opaque)
|
||||
rlimit_as.rlim_cur = rlimit_as.rlim_max;
|
||||
|
||||
if (rlimit_as.rlim_max != RLIM_INFINITY) {
|
||||
fprintf(stderr, "Warning: QEMU's maximum size of virtual"
|
||||
" memory is not infinity.\n");
|
||||
warn_report("QEMU's maximum size of virtual"
|
||||
" memory is not infinity");
|
||||
}
|
||||
if (rlimit_as.rlim_max < MCACHE_MAX_SIZE + NON_MCACHE_MEMORY_SIZE) {
|
||||
mapcache->max_mcache_size = rlimit_as.rlim_max -
|
||||
|
@ -216,8 +216,8 @@ static void generate_eeprom_spd(uint8_t *eeprom, ram_addr_t ram_size)
|
||||
}
|
||||
|
||||
if (ram_size) {
|
||||
fprintf(stderr, "Warning: SPD cannot represent final %dMB"
|
||||
" of SDRAM\n", (int)ram_size);
|
||||
warn_report("SPD cannot represent final " RAM_ADDR_FMT "MB"
|
||||
" of SDRAM", ram_size);
|
||||
}
|
||||
|
||||
/* fill in SPD memory information */
|
||||
|
@ -254,8 +254,7 @@ void mips_r4k_init(MachineState *machine)
|
||||
}
|
||||
} else if (!qtest_enabled()) {
|
||||
/* not fatal */
|
||||
fprintf(stderr, "qemu: Warning, could not load MIPS bios '%s'\n",
|
||||
bios_name);
|
||||
warn_report("could not load MIPS bios '%s'", bios_name);
|
||||
}
|
||||
g_free(filename);
|
||||
|
||||
|
@ -331,7 +331,7 @@ static void applesmc_isa_realize(DeviceState *dev, Error **errp)
|
||||
s->iobase + APPLESMC_ERR_PORT);
|
||||
|
||||
if (!s->osk || (strlen(s->osk) != 64)) {
|
||||
fprintf(stderr, "WARNING: Using AppleSMC with invalid key\n");
|
||||
warn_report("Using AppleSMC with invalid key");
|
||||
s->osk = default_osk;
|
||||
}
|
||||
|
||||
|
@ -141,9 +141,10 @@ void gtod_save(QEMUFile *f, void *opaque)
|
||||
|
||||
r = s390_get_clock(&tod_high, &tod_low);
|
||||
if (r) {
|
||||
fprintf(stderr, "WARNING: Unable to get guest clock for migration. "
|
||||
"Error code %d. Guest clock will not be migrated "
|
||||
"which could cause the guest to hang.\n", r);
|
||||
warn_report("Unable to get guest clock for migration: %s",
|
||||
strerror(-r));
|
||||
error_printf("Guest clock will not be migrated "
|
||||
"which could cause the guest to hang.");
|
||||
qemu_put_byte(f, S390_TOD_CLOCK_VALUE_MISSING);
|
||||
return;
|
||||
}
|
||||
@ -160,8 +161,8 @@ int gtod_load(QEMUFile *f, void *opaque, int version_id)
|
||||
int r;
|
||||
|
||||
if (qemu_get_byte(f) == S390_TOD_CLOCK_VALUE_MISSING) {
|
||||
fprintf(stderr, "WARNING: Guest clock was not migrated. This could "
|
||||
"cause the guest to hang.\n");
|
||||
warn_report("Guest clock was not migrated. This could "
|
||||
"cause the guest to hang.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -170,9 +171,10 @@ int gtod_load(QEMUFile *f, void *opaque, int version_id)
|
||||
|
||||
r = s390_set_clock(&tod_high, &tod_low);
|
||||
if (r) {
|
||||
fprintf(stderr, "WARNING: Unable to set guest clock value. "
|
||||
"s390_get_clock returned error %d. This could cause "
|
||||
"the guest to hang.\n", r);
|
||||
warn_report("Unable to set guest clock for migration: %s",
|
||||
strerror(-r));
|
||||
error_printf("Guest clock will not be restored "
|
||||
"which could cause the guest to hang.");
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -593,7 +593,7 @@ const VMStateDescription vmstate_esp = {
|
||||
};
|
||||
|
||||
#define TYPE_ESP "esp"
|
||||
#define ESP(obj) OBJECT_CHECK(SysBusESPState, (obj), TYPE_ESP)
|
||||
#define ESP_STATE(obj) OBJECT_CHECK(SysBusESPState, (obj), TYPE_ESP)
|
||||
|
||||
typedef struct {
|
||||
/*< private >*/
|
||||
@ -644,7 +644,7 @@ void esp_init(hwaddr espaddr, int it_shift,
|
||||
ESPState *esp;
|
||||
|
||||
dev = qdev_create(NULL, TYPE_ESP);
|
||||
sysbus = ESP(dev);
|
||||
sysbus = ESP_STATE(dev);
|
||||
esp = &sysbus->esp;
|
||||
esp->dma_memory_read = dma_memory_read;
|
||||
esp->dma_memory_write = dma_memory_write;
|
||||
@ -672,7 +672,7 @@ static const struct SCSIBusInfo esp_scsi_info = {
|
||||
|
||||
static void sysbus_esp_gpio_demux(void *opaque, int irq, int level)
|
||||
{
|
||||
SysBusESPState *sysbus = ESP(opaque);
|
||||
SysBusESPState *sysbus = ESP_STATE(opaque);
|
||||
ESPState *s = &sysbus->esp;
|
||||
|
||||
switch (irq) {
|
||||
@ -688,7 +688,7 @@ static void sysbus_esp_gpio_demux(void *opaque, int irq, int level)
|
||||
static void sysbus_esp_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
SysBusESPState *sysbus = ESP(dev);
|
||||
SysBusESPState *sysbus = ESP_STATE(dev);
|
||||
ESPState *s = &sysbus->esp;
|
||||
|
||||
sysbus_init_irq(sbd, &s->irq);
|
||||
@ -706,7 +706,7 @@ static void sysbus_esp_realize(DeviceState *dev, Error **errp)
|
||||
|
||||
static void sysbus_esp_hard_reset(DeviceState *dev)
|
||||
{
|
||||
SysBusESPState *sysbus = ESP(dev);
|
||||
SysBusESPState *sysbus = ESP_STATE(dev);
|
||||
esp_hard_reset(&sysbus->esp);
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include "hw/pci/msix.h"
|
||||
#include "qemu/iov.h"
|
||||
#include "hw/scsi/scsi.h"
|
||||
#include "block/scsi.h"
|
||||
#include "scsi/constants.h"
|
||||
#include "trace.h"
|
||||
#include "qapi/error.h"
|
||||
#include "mfi.h"
|
||||
|
@ -28,7 +28,7 @@
|
||||
#include "hw/pci/msi.h"
|
||||
#include "qemu/iov.h"
|
||||
#include "hw/scsi/scsi.h"
|
||||
#include "block/scsi.h"
|
||||
#include "scsi/constants.h"
|
||||
#include "trace.h"
|
||||
|
||||
#include "mptsas.h"
|
||||
|
@ -30,7 +30,7 @@
|
||||
#include "hw/pci/msi.h"
|
||||
#include "qemu/iov.h"
|
||||
#include "hw/scsi/scsi.h"
|
||||
#include "block/scsi.h"
|
||||
#include "scsi/constants.h"
|
||||
#include "trace.h"
|
||||
#include "qapi/error.h"
|
||||
#include "mptsas.h"
|
||||
@ -1236,11 +1236,9 @@ static void *mptsas_load_request(QEMUFile *f, SCSIRequest *sreq)
|
||||
n = qemu_get_be32(f);
|
||||
/* TODO: add a way for SCSIBusInfo's load_request to fail,
|
||||
* and fail migration instead of asserting here.
|
||||
* When we do, we might be able to re-enable NDEBUG below.
|
||||
* This is just one thing (there are probably more) that must be
|
||||
* fixed before we can allow NDEBUG compilation.
|
||||
*/
|
||||
#ifdef NDEBUG
|
||||
#error building with NDEBUG is not supported
|
||||
#endif
|
||||
assert(n >= 0);
|
||||
|
||||
pci_dma_sglist_init(&req->qsg, pci, n);
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "hw/scsi/scsi.h"
|
||||
#include "block/scsi.h"
|
||||
#include "scsi/constants.h"
|
||||
#include "hw/qdev.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "sysemu/blockdev.h"
|
||||
@ -516,8 +516,10 @@ static size_t scsi_sense_len(SCSIRequest *req)
|
||||
static int32_t scsi_target_send_command(SCSIRequest *req, uint8_t *buf)
|
||||
{
|
||||
SCSITargetReq *r = DO_UPCAST(SCSITargetReq, req, req);
|
||||
int fixed_sense = (req->cmd.buf[1] & 1) == 0;
|
||||
|
||||
if (req->lun != 0) {
|
||||
if (req->lun != 0 &&
|
||||
buf[0] != INQUIRY && buf[0] != REQUEST_SENSE) {
|
||||
scsi_req_build_sense(req, SENSE_CODE(LUN_NOT_SUPPORTED));
|
||||
scsi_req_complete(req, CHECK_CONDITION);
|
||||
return 0;
|
||||
@ -535,9 +537,28 @@ static int32_t scsi_target_send_command(SCSIRequest *req, uint8_t *buf)
|
||||
break;
|
||||
case REQUEST_SENSE:
|
||||
scsi_target_alloc_buf(&r->req, scsi_sense_len(req));
|
||||
if (req->lun != 0) {
|
||||
const struct SCSISense sense = SENSE_CODE(LUN_NOT_SUPPORTED);
|
||||
|
||||
if (fixed_sense) {
|
||||
r->buf[0] = 0x70;
|
||||
r->buf[2] = sense.key;
|
||||
r->buf[10] = 10;
|
||||
r->buf[12] = sense.asc;
|
||||
r->buf[13] = sense.ascq;
|
||||
r->len = MIN(req->cmd.xfer, SCSI_SENSE_LEN);
|
||||
} else {
|
||||
r->buf[0] = 0x72;
|
||||
r->buf[1] = sense.key;
|
||||
r->buf[2] = sense.asc;
|
||||
r->buf[3] = sense.ascq;
|
||||
r->len = 8;
|
||||
}
|
||||
} else {
|
||||
r->len = scsi_device_get_sense(r->req.dev, r->buf,
|
||||
MIN(req->cmd.xfer, r->buf_len),
|
||||
(req->cmd.buf[1] & 1) == 0);
|
||||
fixed_sense);
|
||||
}
|
||||
if (r->req.dev->sense_is_ua) {
|
||||
scsi_device_unit_attention_reported(req->dev);
|
||||
r->req.dev->sense_len = 0;
|
||||
@ -769,7 +790,7 @@ int scsi_req_get_sense(SCSIRequest *req, uint8_t *buf, int len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = scsi_build_sense(req->sense, req->sense_len, buf, len, true);
|
||||
ret = scsi_convert_sense(req->sense, req->sense_len, buf, len, true);
|
||||
|
||||
/*
|
||||
* FIXME: clearing unit attention conditions upon autosense should be done
|
||||
@ -790,20 +811,14 @@ int scsi_req_get_sense(SCSIRequest *req, uint8_t *buf, int len)
|
||||
|
||||
int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fixed)
|
||||
{
|
||||
return scsi_build_sense(dev->sense, dev->sense_len, buf, len, fixed);
|
||||
return scsi_convert_sense(dev->sense, dev->sense_len, buf, len, fixed);
|
||||
}
|
||||
|
||||
void scsi_req_build_sense(SCSIRequest *req, SCSISense sense)
|
||||
{
|
||||
trace_scsi_req_build_sense(req->dev->id, req->lun, req->tag,
|
||||
sense.key, sense.asc, sense.ascq);
|
||||
memset(req->sense, 0, 18);
|
||||
req->sense[0] = 0x70;
|
||||
req->sense[2] = sense.key;
|
||||
req->sense[7] = 10;
|
||||
req->sense[12] = sense.asc;
|
||||
req->sense[13] = sense.ascq;
|
||||
req->sense_len = 18;
|
||||
req->sense_len = scsi_build_sense(req->sense, sense);
|
||||
}
|
||||
|
||||
static void scsi_req_enqueue_internal(SCSIRequest *req)
|
||||
@ -935,36 +950,6 @@ static int ata_passthrough_16_xfer(SCSIDevice *dev, uint8_t *buf)
|
||||
return xfer * unit;
|
||||
}
|
||||
|
||||
uint32_t scsi_data_cdb_xfer(uint8_t *buf)
|
||||
{
|
||||
if ((buf[0] >> 5) == 0 && buf[4] == 0) {
|
||||
return 256;
|
||||
} else {
|
||||
return scsi_cdb_xfer(buf);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t scsi_cdb_xfer(uint8_t *buf)
|
||||
{
|
||||
switch (buf[0] >> 5) {
|
||||
case 0:
|
||||
return buf[4];
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
return lduw_be_p(&buf[7]);
|
||||
break;
|
||||
case 4:
|
||||
return ldl_be_p(&buf[10]) & 0xffffffffULL;
|
||||
break;
|
||||
case 5:
|
||||
return ldl_be_p(&buf[6]) & 0xffffffffULL;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int scsi_req_xfer(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
|
||||
{
|
||||
cmd->xfer = scsi_cdb_xfer(buf);
|
||||
@ -1277,53 +1262,6 @@ static void scsi_cmd_xfer_mode(SCSICommand *cmd)
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t scsi_cmd_lba(SCSICommand *cmd)
|
||||
{
|
||||
uint8_t *buf = cmd->buf;
|
||||
uint64_t lba;
|
||||
|
||||
switch (buf[0] >> 5) {
|
||||
case 0:
|
||||
lba = ldl_be_p(&buf[0]) & 0x1fffff;
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
case 5:
|
||||
lba = ldl_be_p(&buf[2]) & 0xffffffffULL;
|
||||
break;
|
||||
case 4:
|
||||
lba = ldq_be_p(&buf[2]);
|
||||
break;
|
||||
default:
|
||||
lba = -1;
|
||||
|
||||
}
|
||||
return lba;
|
||||
}
|
||||
|
||||
int scsi_cdb_length(uint8_t *buf) {
|
||||
int cdb_len;
|
||||
|
||||
switch (buf[0] >> 5) {
|
||||
case 0:
|
||||
cdb_len = 6;
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
cdb_len = 10;
|
||||
break;
|
||||
case 4:
|
||||
cdb_len = 16;
|
||||
break;
|
||||
case 5:
|
||||
cdb_len = 12;
|
||||
break;
|
||||
default:
|
||||
cdb_len = -1;
|
||||
}
|
||||
return cdb_len;
|
||||
}
|
||||
|
||||
int scsi_req_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf)
|
||||
{
|
||||
int rc;
|
||||
@ -1370,326 +1308,6 @@ void scsi_device_report_change(SCSIDevice *dev, SCSISense sense)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Predefined sense codes
|
||||
*/
|
||||
|
||||
/* No sense data available */
|
||||
const struct SCSISense sense_code_NO_SENSE = {
|
||||
.key = NO_SENSE , .asc = 0x00 , .ascq = 0x00
|
||||
};
|
||||
|
||||
/* LUN not ready, Manual intervention required */
|
||||
const struct SCSISense sense_code_LUN_NOT_READY = {
|
||||
.key = NOT_READY, .asc = 0x04, .ascq = 0x03
|
||||
};
|
||||
|
||||
/* LUN not ready, Medium not present */
|
||||
const struct SCSISense sense_code_NO_MEDIUM = {
|
||||
.key = NOT_READY, .asc = 0x3a, .ascq = 0x00
|
||||
};
|
||||
|
||||
/* LUN not ready, medium removal prevented */
|
||||
const struct SCSISense sense_code_NOT_READY_REMOVAL_PREVENTED = {
|
||||
.key = NOT_READY, .asc = 0x53, .ascq = 0x02
|
||||
};
|
||||
|
||||
/* Hardware error, internal target failure */
|
||||
const struct SCSISense sense_code_TARGET_FAILURE = {
|
||||
.key = HARDWARE_ERROR, .asc = 0x44, .ascq = 0x00
|
||||
};
|
||||
|
||||
/* Illegal request, invalid command operation code */
|
||||
const struct SCSISense sense_code_INVALID_OPCODE = {
|
||||
.key = ILLEGAL_REQUEST, .asc = 0x20, .ascq = 0x00
|
||||
};
|
||||
|
||||
/* Illegal request, LBA out of range */
|
||||
const struct SCSISense sense_code_LBA_OUT_OF_RANGE = {
|
||||
.key = ILLEGAL_REQUEST, .asc = 0x21, .ascq = 0x00
|
||||
};
|
||||
|
||||
/* Illegal request, Invalid field in CDB */
|
||||
const struct SCSISense sense_code_INVALID_FIELD = {
|
||||
.key = ILLEGAL_REQUEST, .asc = 0x24, .ascq = 0x00
|
||||
};
|
||||
|
||||
/* Illegal request, Invalid field in parameter list */
|
||||
const struct SCSISense sense_code_INVALID_PARAM = {
|
||||
.key = ILLEGAL_REQUEST, .asc = 0x26, .ascq = 0x00
|
||||
};
|
||||
|
||||
/* Illegal request, Parameter list length error */
|
||||
const struct SCSISense sense_code_INVALID_PARAM_LEN = {
|
||||
.key = ILLEGAL_REQUEST, .asc = 0x1a, .ascq = 0x00
|
||||
};
|
||||
|
||||
/* Illegal request, LUN not supported */
|
||||
const struct SCSISense sense_code_LUN_NOT_SUPPORTED = {
|
||||
.key = ILLEGAL_REQUEST, .asc = 0x25, .ascq = 0x00
|
||||
};
|
||||
|
||||
/* Illegal request, Saving parameters not supported */
|
||||
const struct SCSISense sense_code_SAVING_PARAMS_NOT_SUPPORTED = {
|
||||
.key = ILLEGAL_REQUEST, .asc = 0x39, .ascq = 0x00
|
||||
};
|
||||
|
||||
/* Illegal request, Incompatible medium installed */
|
||||
const struct SCSISense sense_code_INCOMPATIBLE_FORMAT = {
|
||||
.key = ILLEGAL_REQUEST, .asc = 0x30, .ascq = 0x00
|
||||
};
|
||||
|
||||
/* Illegal request, medium removal prevented */
|
||||
const struct SCSISense sense_code_ILLEGAL_REQ_REMOVAL_PREVENTED = {
|
||||
.key = ILLEGAL_REQUEST, .asc = 0x53, .ascq = 0x02
|
||||
};
|
||||
|
||||
/* Illegal request, Invalid Transfer Tag */
|
||||
const struct SCSISense sense_code_INVALID_TAG = {
|
||||
.key = ILLEGAL_REQUEST, .asc = 0x4b, .ascq = 0x01
|
||||
};
|
||||
|
||||
/* Command aborted, I/O process terminated */
|
||||
const struct SCSISense sense_code_IO_ERROR = {
|
||||
.key = ABORTED_COMMAND, .asc = 0x00, .ascq = 0x06
|
||||
};
|
||||
|
||||
/* Command aborted, I_T Nexus loss occurred */
|
||||
const struct SCSISense sense_code_I_T_NEXUS_LOSS = {
|
||||
.key = ABORTED_COMMAND, .asc = 0x29, .ascq = 0x07
|
||||
};
|
||||
|
||||
/* Command aborted, Logical Unit failure */
|
||||
const struct SCSISense sense_code_LUN_FAILURE = {
|
||||
.key = ABORTED_COMMAND, .asc = 0x3e, .ascq = 0x01
|
||||
};
|
||||
|
||||
/* Command aborted, Overlapped Commands Attempted */
|
||||
const struct SCSISense sense_code_OVERLAPPED_COMMANDS = {
|
||||
.key = ABORTED_COMMAND, .asc = 0x4e, .ascq = 0x00
|
||||
};
|
||||
|
||||
/* Unit attention, Capacity data has changed */
|
||||
const struct SCSISense sense_code_CAPACITY_CHANGED = {
|
||||
.key = UNIT_ATTENTION, .asc = 0x2a, .ascq = 0x09
|
||||
};
|
||||
|
||||
/* Unit attention, Power on, reset or bus device reset occurred */
|
||||
const struct SCSISense sense_code_RESET = {
|
||||
.key = UNIT_ATTENTION, .asc = 0x29, .ascq = 0x00
|
||||
};
|
||||
|
||||
/* Unit attention, No medium */
|
||||
const struct SCSISense sense_code_UNIT_ATTENTION_NO_MEDIUM = {
|
||||
.key = UNIT_ATTENTION, .asc = 0x3a, .ascq = 0x00
|
||||
};
|
||||
|
||||
/* Unit attention, Medium may have changed */
|
||||
const struct SCSISense sense_code_MEDIUM_CHANGED = {
|
||||
.key = UNIT_ATTENTION, .asc = 0x28, .ascq = 0x00
|
||||
};
|
||||
|
||||
/* Unit attention, Reported LUNs data has changed */
|
||||
const struct SCSISense sense_code_REPORTED_LUNS_CHANGED = {
|
||||
.key = UNIT_ATTENTION, .asc = 0x3f, .ascq = 0x0e
|
||||
};
|
||||
|
||||
/* Unit attention, Device internal reset */
|
||||
const struct SCSISense sense_code_DEVICE_INTERNAL_RESET = {
|
||||
.key = UNIT_ATTENTION, .asc = 0x29, .ascq = 0x04
|
||||
};
|
||||
|
||||
/* Data Protection, Write Protected */
|
||||
const struct SCSISense sense_code_WRITE_PROTECTED = {
|
||||
.key = DATA_PROTECT, .asc = 0x27, .ascq = 0x00
|
||||
};
|
||||
|
||||
/* Data Protection, Space Allocation Failed Write Protect */
|
||||
const struct SCSISense sense_code_SPACE_ALLOC_FAILED = {
|
||||
.key = DATA_PROTECT, .asc = 0x27, .ascq = 0x07
|
||||
};
|
||||
|
||||
/*
|
||||
* scsi_build_sense
|
||||
*
|
||||
* Convert between fixed and descriptor sense buffers
|
||||
*/
|
||||
int scsi_build_sense(uint8_t *in_buf, int in_len,
|
||||
uint8_t *buf, int len, bool fixed)
|
||||
{
|
||||
bool fixed_in;
|
||||
SCSISense sense;
|
||||
if (!fixed && len < 8) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (in_len == 0) {
|
||||
sense.key = NO_SENSE;
|
||||
sense.asc = 0;
|
||||
sense.ascq = 0;
|
||||
} else {
|
||||
fixed_in = (in_buf[0] & 2) == 0;
|
||||
|
||||
if (fixed == fixed_in) {
|
||||
memcpy(buf, in_buf, MIN(len, in_len));
|
||||
return MIN(len, in_len);
|
||||
}
|
||||
|
||||
if (fixed_in) {
|
||||
sense.key = in_buf[2];
|
||||
sense.asc = in_buf[12];
|
||||
sense.ascq = in_buf[13];
|
||||
} else {
|
||||
sense.key = in_buf[1];
|
||||
sense.asc = in_buf[2];
|
||||
sense.ascq = in_buf[3];
|
||||
}
|
||||
}
|
||||
|
||||
memset(buf, 0, len);
|
||||
if (fixed) {
|
||||
/* Return fixed format sense buffer */
|
||||
buf[0] = 0x70;
|
||||
buf[2] = sense.key;
|
||||
buf[7] = 10;
|
||||
buf[12] = sense.asc;
|
||||
buf[13] = sense.ascq;
|
||||
return MIN(len, SCSI_SENSE_LEN);
|
||||
} else {
|
||||
/* Return descriptor format sense buffer */
|
||||
buf[0] = 0x72;
|
||||
buf[1] = sense.key;
|
||||
buf[2] = sense.asc;
|
||||
buf[3] = sense.ascq;
|
||||
return 8;
|
||||
}
|
||||
}
|
||||
|
||||
const char *scsi_command_name(uint8_t cmd)
|
||||
{
|
||||
static const char *names[] = {
|
||||
[ TEST_UNIT_READY ] = "TEST_UNIT_READY",
|
||||
[ REWIND ] = "REWIND",
|
||||
[ REQUEST_SENSE ] = "REQUEST_SENSE",
|
||||
[ FORMAT_UNIT ] = "FORMAT_UNIT",
|
||||
[ READ_BLOCK_LIMITS ] = "READ_BLOCK_LIMITS",
|
||||
[ REASSIGN_BLOCKS ] = "REASSIGN_BLOCKS/INITIALIZE ELEMENT STATUS",
|
||||
/* LOAD_UNLOAD and INITIALIZE_ELEMENT_STATUS use the same operation code */
|
||||
[ READ_6 ] = "READ_6",
|
||||
[ WRITE_6 ] = "WRITE_6",
|
||||
[ SET_CAPACITY ] = "SET_CAPACITY",
|
||||
[ READ_REVERSE ] = "READ_REVERSE",
|
||||
[ WRITE_FILEMARKS ] = "WRITE_FILEMARKS",
|
||||
[ SPACE ] = "SPACE",
|
||||
[ INQUIRY ] = "INQUIRY",
|
||||
[ RECOVER_BUFFERED_DATA ] = "RECOVER_BUFFERED_DATA",
|
||||
[ MAINTENANCE_IN ] = "MAINTENANCE_IN",
|
||||
[ MAINTENANCE_OUT ] = "MAINTENANCE_OUT",
|
||||
[ MODE_SELECT ] = "MODE_SELECT",
|
||||
[ RESERVE ] = "RESERVE",
|
||||
[ RELEASE ] = "RELEASE",
|
||||
[ COPY ] = "COPY",
|
||||
[ ERASE ] = "ERASE",
|
||||
[ MODE_SENSE ] = "MODE_SENSE",
|
||||
[ START_STOP ] = "START_STOP/LOAD_UNLOAD",
|
||||
/* LOAD_UNLOAD and START_STOP use the same operation code */
|
||||
[ RECEIVE_DIAGNOSTIC ] = "RECEIVE_DIAGNOSTIC",
|
||||
[ SEND_DIAGNOSTIC ] = "SEND_DIAGNOSTIC",
|
||||
[ ALLOW_MEDIUM_REMOVAL ] = "ALLOW_MEDIUM_REMOVAL",
|
||||
[ READ_CAPACITY_10 ] = "READ_CAPACITY_10",
|
||||
[ READ_10 ] = "READ_10",
|
||||
[ WRITE_10 ] = "WRITE_10",
|
||||
[ SEEK_10 ] = "SEEK_10/POSITION_TO_ELEMENT",
|
||||
/* SEEK_10 and POSITION_TO_ELEMENT use the same operation code */
|
||||
[ WRITE_VERIFY_10 ] = "WRITE_VERIFY_10",
|
||||
[ VERIFY_10 ] = "VERIFY_10",
|
||||
[ SEARCH_HIGH ] = "SEARCH_HIGH",
|
||||
[ SEARCH_EQUAL ] = "SEARCH_EQUAL",
|
||||
[ SEARCH_LOW ] = "SEARCH_LOW",
|
||||
[ SET_LIMITS ] = "SET_LIMITS",
|
||||
[ PRE_FETCH ] = "PRE_FETCH/READ_POSITION",
|
||||
/* READ_POSITION and PRE_FETCH use the same operation code */
|
||||
[ SYNCHRONIZE_CACHE ] = "SYNCHRONIZE_CACHE",
|
||||
[ LOCK_UNLOCK_CACHE ] = "LOCK_UNLOCK_CACHE",
|
||||
[ READ_DEFECT_DATA ] = "READ_DEFECT_DATA/INITIALIZE_ELEMENT_STATUS_WITH_RANGE",
|
||||
/* READ_DEFECT_DATA and INITIALIZE_ELEMENT_STATUS_WITH_RANGE use the same operation code */
|
||||
[ MEDIUM_SCAN ] = "MEDIUM_SCAN",
|
||||
[ COMPARE ] = "COMPARE",
|
||||
[ COPY_VERIFY ] = "COPY_VERIFY",
|
||||
[ WRITE_BUFFER ] = "WRITE_BUFFER",
|
||||
[ READ_BUFFER ] = "READ_BUFFER",
|
||||
[ UPDATE_BLOCK ] = "UPDATE_BLOCK",
|
||||
[ READ_LONG_10 ] = "READ_LONG_10",
|
||||
[ WRITE_LONG_10 ] = "WRITE_LONG_10",
|
||||
[ CHANGE_DEFINITION ] = "CHANGE_DEFINITION",
|
||||
[ WRITE_SAME_10 ] = "WRITE_SAME_10",
|
||||
[ UNMAP ] = "UNMAP",
|
||||
[ READ_TOC ] = "READ_TOC",
|
||||
[ REPORT_DENSITY_SUPPORT ] = "REPORT_DENSITY_SUPPORT",
|
||||
[ SANITIZE ] = "SANITIZE",
|
||||
[ GET_CONFIGURATION ] = "GET_CONFIGURATION",
|
||||
[ LOG_SELECT ] = "LOG_SELECT",
|
||||
[ LOG_SENSE ] = "LOG_SENSE",
|
||||
[ MODE_SELECT_10 ] = "MODE_SELECT_10",
|
||||
[ RESERVE_10 ] = "RESERVE_10",
|
||||
[ RELEASE_10 ] = "RELEASE_10",
|
||||
[ MODE_SENSE_10 ] = "MODE_SENSE_10",
|
||||
[ PERSISTENT_RESERVE_IN ] = "PERSISTENT_RESERVE_IN",
|
||||
[ PERSISTENT_RESERVE_OUT ] = "PERSISTENT_RESERVE_OUT",
|
||||
[ WRITE_FILEMARKS_16 ] = "WRITE_FILEMARKS_16",
|
||||
[ EXTENDED_COPY ] = "EXTENDED_COPY",
|
||||
[ ATA_PASSTHROUGH_16 ] = "ATA_PASSTHROUGH_16",
|
||||
[ ACCESS_CONTROL_IN ] = "ACCESS_CONTROL_IN",
|
||||
[ ACCESS_CONTROL_OUT ] = "ACCESS_CONTROL_OUT",
|
||||
[ READ_16 ] = "READ_16",
|
||||
[ COMPARE_AND_WRITE ] = "COMPARE_AND_WRITE",
|
||||
[ WRITE_16 ] = "WRITE_16",
|
||||
[ WRITE_VERIFY_16 ] = "WRITE_VERIFY_16",
|
||||
[ VERIFY_16 ] = "VERIFY_16",
|
||||
[ PRE_FETCH_16 ] = "PRE_FETCH_16",
|
||||
[ SYNCHRONIZE_CACHE_16 ] = "SPACE_16/SYNCHRONIZE_CACHE_16",
|
||||
/* SPACE_16 and SYNCHRONIZE_CACHE_16 use the same operation code */
|
||||
[ LOCATE_16 ] = "LOCATE_16",
|
||||
[ WRITE_SAME_16 ] = "ERASE_16/WRITE_SAME_16",
|
||||
/* ERASE_16 and WRITE_SAME_16 use the same operation code */
|
||||
[ SERVICE_ACTION_IN_16 ] = "SERVICE_ACTION_IN_16",
|
||||
[ WRITE_LONG_16 ] = "WRITE_LONG_16",
|
||||
[ REPORT_LUNS ] = "REPORT_LUNS",
|
||||
[ ATA_PASSTHROUGH_12 ] = "BLANK/ATA_PASSTHROUGH_12",
|
||||
[ MOVE_MEDIUM ] = "MOVE_MEDIUM",
|
||||
[ EXCHANGE_MEDIUM ] = "EXCHANGE MEDIUM",
|
||||
[ READ_12 ] = "READ_12",
|
||||
[ WRITE_12 ] = "WRITE_12",
|
||||
[ ERASE_12 ] = "ERASE_12/GET_PERFORMANCE",
|
||||
/* ERASE_12 and GET_PERFORMANCE use the same operation code */
|
||||
[ SERVICE_ACTION_IN_12 ] = "SERVICE_ACTION_IN_12",
|
||||
[ WRITE_VERIFY_12 ] = "WRITE_VERIFY_12",
|
||||
[ VERIFY_12 ] = "VERIFY_12",
|
||||
[ SEARCH_HIGH_12 ] = "SEARCH_HIGH_12",
|
||||
[ SEARCH_EQUAL_12 ] = "SEARCH_EQUAL_12",
|
||||
[ SEARCH_LOW_12 ] = "SEARCH_LOW_12",
|
||||
[ READ_ELEMENT_STATUS ] = "READ_ELEMENT_STATUS",
|
||||
[ SEND_VOLUME_TAG ] = "SEND_VOLUME_TAG/SET_STREAMING",
|
||||
/* SEND_VOLUME_TAG and SET_STREAMING use the same operation code */
|
||||
[ READ_CD ] = "READ_CD",
|
||||
[ READ_DEFECT_DATA_12 ] = "READ_DEFECT_DATA_12",
|
||||
[ READ_DVD_STRUCTURE ] = "READ_DVD_STRUCTURE",
|
||||
[ RESERVE_TRACK ] = "RESERVE_TRACK",
|
||||
[ SEND_CUE_SHEET ] = "SEND_CUE_SHEET",
|
||||
[ SEND_DVD_STRUCTURE ] = "SEND_DVD_STRUCTURE",
|
||||
[ SET_CD_SPEED ] = "SET_CD_SPEED",
|
||||
[ SET_READ_AHEAD ] = "SET_READ_AHEAD",
|
||||
[ ALLOW_OVERWRITE ] = "ALLOW_OVERWRITE",
|
||||
[ MECHANISM_STATUS ] = "MECHANISM_STATUS",
|
||||
[ GET_EVENT_STATUS_NOTIFICATION ] = "GET_EVENT_STATUS_NOTIFICATION",
|
||||
[ READ_DISC_INFORMATION ] = "READ_DISC_INFORMATION",
|
||||
};
|
||||
|
||||
if (cmd >= ARRAY_SIZE(names) || names[cmd] == NULL)
|
||||
return "*UNKNOWN*";
|
||||
return names[cmd];
|
||||
}
|
||||
|
||||
SCSIRequest *scsi_req_ref(SCSIRequest *req)
|
||||
{
|
||||
assert(req->refcount > 0);
|
||||
|
@ -32,7 +32,7 @@ do { printf("scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "hw/scsi/scsi.h"
|
||||
#include "block/scsi.h"
|
||||
#include "scsi/constants.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "sysemu/blockdev.h"
|
||||
@ -106,7 +106,7 @@ typedef struct SCSIDiskState
|
||||
bool tray_locked;
|
||||
} SCSIDiskState;
|
||||
|
||||
static int scsi_handle_rw_error(SCSIDiskReq *r, int error, bool acct_failed);
|
||||
static bool scsi_handle_rw_error(SCSIDiskReq *r, int error, bool acct_failed);
|
||||
|
||||
static void scsi_free_request(SCSIRequest *req)
|
||||
{
|
||||
@ -184,19 +184,10 @@ static bool scsi_disk_req_check_error(SCSIDiskReq *r, int ret, bool acct_failed)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
if (ret < 0 || (r->status && *r->status)) {
|
||||
return scsi_handle_rw_error(r, -ret, acct_failed);
|
||||
}
|
||||
|
||||
if (r->status && *r->status) {
|
||||
if (acct_failed) {
|
||||
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, r->req.dev);
|
||||
block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct);
|
||||
}
|
||||
scsi_req_complete(&r->req, *r->status);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -422,13 +413,13 @@ static void scsi_read_data(SCSIRequest *req)
|
||||
}
|
||||
|
||||
/*
|
||||
* scsi_handle_rw_error has two return values. 0 means that the error
|
||||
* must be ignored, 1 means that the error has been processed and the
|
||||
* scsi_handle_rw_error has two return values. False means that the error
|
||||
* must be ignored, true means that the error has been processed and the
|
||||
* caller should not do anything else for this request. Note that
|
||||
* scsi_handle_rw_error always manages its reference counts, independent
|
||||
* of the return value.
|
||||
*/
|
||||
static int scsi_handle_rw_error(SCSIDiskReq *r, int error, bool acct_failed)
|
||||
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);
|
||||
@ -440,6 +431,11 @@ static int scsi_handle_rw_error(SCSIDiskReq *r, int error, bool acct_failed)
|
||||
block_acct_failed(blk_get_stats(s->qdev.conf.blk), &r->acct);
|
||||
}
|
||||
switch (error) {
|
||||
case 0:
|
||||
/* The command has run, no need to fake sense. */
|
||||
assert(r->status && *r->status);
|
||||
scsi_req_complete(&r->req, *r->status);
|
||||
break;
|
||||
case ENOMEDIUM:
|
||||
scsi_check_condition(r, SENSE_CODE(NO_MEDIUM));
|
||||
break;
|
||||
@ -457,6 +453,18 @@ static int scsi_handle_rw_error(SCSIDiskReq *r, int error, bool acct_failed)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!error) {
|
||||
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) {
|
||||
/* These errors are handled by guest. */
|
||||
scsi_req_complete(&r->req, *r->status);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
blk_error_action(s->qdev.conf.blk, action, is_read, error);
|
||||
if (action == BLOCK_ERROR_ACTION_STOP) {
|
||||
scsi_req_retry(&r->req);
|
||||
@ -1978,7 +1986,7 @@ static int32_t scsi_disk_emulate_command(SCSIRequest *req, uint8_t *buf)
|
||||
break;
|
||||
case REQUEST_SENSE:
|
||||
/* Just return "NO SENSE". */
|
||||
buflen = scsi_build_sense(NULL, 0, outbuf, r->buflen,
|
||||
buflen = scsi_convert_sense(NULL, 0, outbuf, r->buflen,
|
||||
(req->cmd.buf[1] & 1) == 0);
|
||||
if (buflen < 0) {
|
||||
goto illegal_request;
|
||||
@ -2972,6 +2980,7 @@ static const TypeInfo scsi_cd_info = {
|
||||
|
||||
#ifdef __linux__
|
||||
static Property scsi_block_properties[] = {
|
||||
DEFINE_BLOCK_ERROR_PROPERTIES(SCSIDiskState, qdev.conf), \
|
||||
DEFINE_PROP_DRIVE("drive", SCSIDiskState, qdev.conf.blk),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
@ -34,15 +34,7 @@ do { printf("scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
|
||||
do { fprintf(stderr, "scsi-generic: " fmt , ## __VA_ARGS__); } while (0)
|
||||
|
||||
#include <scsi/sg.h>
|
||||
#include "block/scsi.h"
|
||||
|
||||
#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
|
||||
#include "scsi/constants.h"
|
||||
|
||||
#ifndef MAX_UINT
|
||||
#define MAX_UINT ((unsigned int)-1)
|
||||
@ -89,6 +81,7 @@ static void scsi_free_request(SCSIRequest *req)
|
||||
static void scsi_command_complete_noio(SCSIGenericReq *r, int ret)
|
||||
{
|
||||
int status;
|
||||
SCSISense sense;
|
||||
|
||||
assert(r->req.aiocb == NULL);
|
||||
|
||||
@ -96,42 +89,15 @@ 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 {
|
||||
scsi_req_build_sense(&r->req, sense);
|
||||
}
|
||||
}
|
||||
|
||||
if (ret != 0) {
|
||||
switch (ret) {
|
||||
case -EDOM:
|
||||
status = TASK_SET_FULL;
|
||||
break;
|
||||
case -ENOMEM:
|
||||
status = CHECK_CONDITION;
|
||||
scsi_req_build_sense(&r->req, SENSE_CODE(TARGET_FAILURE));
|
||||
break;
|
||||
default:
|
||||
status = CHECK_CONDITION;
|
||||
scsi_req_build_sense(&r->req, SENSE_CODE(IO_ERROR));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (r->io_header.host_status == SG_ERR_DID_NO_CONNECT ||
|
||||
r->io_header.host_status == SG_ERR_DID_BUS_BUSY ||
|
||||
r->io_header.host_status == SG_ERR_DID_TIME_OUT ||
|
||||
(r->io_header.driver_status & SG_ERR_DRIVER_TIMEOUT)) {
|
||||
status = BUSY;
|
||||
BADF("Driver Timeout\n");
|
||||
} else if (r->io_header.host_status) {
|
||||
status = CHECK_CONDITION;
|
||||
scsi_req_build_sense(&r->req, SENSE_CODE(I_T_NEXUS_LOSS));
|
||||
} else if (r->io_header.status) {
|
||||
status = r->io_header.status;
|
||||
} else if (r->io_header.driver_status & SG_ERR_DRIVER_SENSE) {
|
||||
status = CHECK_CONDITION;
|
||||
} else {
|
||||
status = GOOD;
|
||||
}
|
||||
}
|
||||
DPRINTF("Command complete 0x%p tag=0x%x status=%d\n",
|
||||
r, r->req.tag, status);
|
||||
|
||||
|
@ -36,7 +36,7 @@
|
||||
#include "cpu.h"
|
||||
#include "hw/hw.h"
|
||||
#include "hw/scsi/scsi.h"
|
||||
#include "block/scsi.h"
|
||||
#include "scsi/constants.h"
|
||||
#include "srp.h"
|
||||
#include "hw/qdev.h"
|
||||
#include "hw/ppc/spapr.h"
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include "qemu/error-report.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "hw/scsi/scsi.h"
|
||||
#include "block/scsi.h"
|
||||
#include "scsi/constants.h"
|
||||
#include "hw/virtio/virtio-bus.h"
|
||||
#include "hw/virtio/virtio-access.h"
|
||||
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include "qemu/iov.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "hw/scsi/scsi.h"
|
||||
#include "block/scsi.h"
|
||||
#include "scsi/constants.h"
|
||||
#include "hw/virtio/virtio-bus.h"
|
||||
#include "hw/virtio/virtio-access.h"
|
||||
|
||||
@ -867,10 +867,10 @@ void virtio_scsi_common_realize(DeviceState *dev,
|
||||
s->sense_size = VIRTIO_SCSI_SENSE_DEFAULT_SIZE;
|
||||
s->cdb_size = VIRTIO_SCSI_CDB_DEFAULT_SIZE;
|
||||
|
||||
s->ctrl_vq = virtio_add_queue(vdev, VIRTIO_SCSI_VQ_SIZE, ctrl);
|
||||
s->event_vq = virtio_add_queue(vdev, VIRTIO_SCSI_VQ_SIZE, evt);
|
||||
s->ctrl_vq = virtio_add_queue(vdev, s->conf.virtqueue_size, ctrl);
|
||||
s->event_vq = virtio_add_queue(vdev, s->conf.virtqueue_size, evt);
|
||||
for (i = 0; i < s->conf.num_queues; i++) {
|
||||
s->cmd_vqs[i] = virtio_add_queue(vdev, VIRTIO_SCSI_VQ_SIZE, cmd);
|
||||
s->cmd_vqs[i] = virtio_add_queue(vdev, s->conf.virtqueue_size, cmd);
|
||||
}
|
||||
}
|
||||
|
||||
@ -917,6 +917,8 @@ static void virtio_scsi_device_unrealize(DeviceState *dev, Error **errp)
|
||||
|
||||
static Property virtio_scsi_properties[] = {
|
||||
DEFINE_PROP_UINT32("num_queues", VirtIOSCSI, parent_obj.conf.num_queues, 1),
|
||||
DEFINE_PROP_UINT32("virtqueue_size", VirtIOSCSI,
|
||||
parent_obj.conf.virtqueue_size, 128),
|
||||
DEFINE_PROP_UINT32("max_sectors", VirtIOSCSI, parent_obj.conf.max_sectors,
|
||||
0xFFFF),
|
||||
DEFINE_PROP_UINT32("cmd_per_lun", VirtIOSCSI, parent_obj.conf.cmd_per_lun,
|
||||
|
@ -28,7 +28,7 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "hw/scsi/scsi.h"
|
||||
#include "block/scsi.h"
|
||||
#include "scsi/constants.h"
|
||||
#include "hw/pci/msi.h"
|
||||
#include "vmw_pvscsi.h"
|
||||
#include "trace.h"
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include "hw/usb.h"
|
||||
#include "hw/usb/desc.h"
|
||||
#include "hw/scsi/scsi.h"
|
||||
#include "block/scsi.h"
|
||||
#include "scsi/constants.h"
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "hw/usb/ehci-regs.h"
|
||||
#include "hw/usb/hcd-ehci.h"
|
||||
#include "trace.h"
|
||||
#include "qemu/error-report.h"
|
||||
|
||||
#define FRAME_TIMER_FREQ 1000
|
||||
#define FRAME_TIMER_NS (NANOSECONDS_PER_SECOND / FRAME_TIMER_FREQ)
|
||||
@ -348,7 +349,7 @@ static void ehci_trace_sitd(EHCIState *s, hwaddr addr,
|
||||
static void ehci_trace_guest_bug(EHCIState *s, const char *message)
|
||||
{
|
||||
trace_usb_ehci_guest_bug(message);
|
||||
fprintf(stderr, "ehci warning: %s\n", message);
|
||||
warn_report("%s", message);
|
||||
}
|
||||
|
||||
static inline bool ehci_enabled(EHCIState *s)
|
||||
@ -1728,7 +1729,7 @@ static int ehci_state_fetchsitd(EHCIState *ehci, int async)
|
||||
/* siTD is not active, nothing to do */;
|
||||
} else {
|
||||
/* TODO: split transfers are not implemented */
|
||||
fprintf(stderr, "WARNING: Skipping active siTD\n");
|
||||
warn_report("Skipping active siTD");
|
||||
}
|
||||
|
||||
ehci_set_fetch_addr(ehci, async, sitd.next);
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "qapi/visitor.h"
|
||||
#include "qapi-event.h"
|
||||
#include "trace.h"
|
||||
#include "qemu/error-report.h"
|
||||
|
||||
#include "hw/virtio/virtio-bus.h"
|
||||
#include "hw/virtio/virtio-access.h"
|
||||
@ -292,7 +293,7 @@ static void virtio_balloon_receive_stats(VirtIODevice *vdev, VirtQueue *vq)
|
||||
s->stats_vq_offset = offset;
|
||||
|
||||
if (qemu_gettimeofday(&tv) < 0) {
|
||||
fprintf(stderr, "warning: %s: failed to get time of day\n", __func__);
|
||||
warn_report("%s: failed to get time of day", __func__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -1025,11 +1025,9 @@ void *qemu_get_virtqueue_element(VirtIODevice *vdev, QEMUFile *f, size_t sz)
|
||||
|
||||
/* TODO: teach all callers that this can fail, and return failure instead
|
||||
* of asserting here.
|
||||
* When we do, we might be able to re-enable NDEBUG below.
|
||||
* This is just one thing (there are probably more) that must be
|
||||
* fixed before we can allow NDEBUG compilation.
|
||||
*/
|
||||
#ifdef NDEBUG
|
||||
#error building with NDEBUG is not supported
|
||||
#endif
|
||||
assert(ARRAY_SIZE(data.in_addr) >= data.in_num);
|
||||
assert(ARRAY_SIZE(data.out_addr) >= data.out_num);
|
||||
|
||||
|
@ -371,6 +371,11 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
|
||||
|
||||
#define PC_COMPAT_2_10 \
|
||||
HW_COMPAT_2_10 \
|
||||
{\
|
||||
.driver = TYPE_X86_CPU,\
|
||||
.property = "x-hv-max-vps",\
|
||||
.value = "0x40",\
|
||||
},
|
||||
|
||||
#define PC_COMPAT_2_9 \
|
||||
HW_COMPAT_2_9 \
|
||||
|
@ -11,7 +11,7 @@
|
||||
#include "sysemu/dma.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "hw/block/block.h"
|
||||
#include "block/scsi.h"
|
||||
#include "scsi/constants.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
/* debug IDE devices */
|
||||
|
@ -4,45 +4,20 @@
|
||||
#include "hw/qdev.h"
|
||||
#include "hw/block/block.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "scsi/utils.h"
|
||||
#include "qemu/notify.h"
|
||||
|
||||
#define MAX_SCSI_DEVS 255
|
||||
|
||||
#define SCSI_CMD_BUF_SIZE 16
|
||||
#define SCSI_SENSE_LEN 18
|
||||
#define SCSI_SENSE_LEN_SCANNER 32
|
||||
#define SCSI_INQUIRY_LEN 36
|
||||
|
||||
typedef struct SCSIBus SCSIBus;
|
||||
typedef struct SCSIBusInfo SCSIBusInfo;
|
||||
typedef struct SCSICommand SCSICommand;
|
||||
typedef struct SCSIDevice SCSIDevice;
|
||||
typedef struct SCSIRequest SCSIRequest;
|
||||
typedef struct SCSIReqOps SCSIReqOps;
|
||||
|
||||
enum SCSIXferMode {
|
||||
SCSI_XFER_NONE, /* TEST_UNIT_READY, ... */
|
||||
SCSI_XFER_FROM_DEV, /* READ, INQUIRY, MODE_SENSE, ... */
|
||||
SCSI_XFER_TO_DEV, /* WRITE, MODE_SELECT, ... */
|
||||
};
|
||||
|
||||
typedef struct SCSISense {
|
||||
uint8_t key;
|
||||
uint8_t asc;
|
||||
uint8_t ascq;
|
||||
} SCSISense;
|
||||
|
||||
#define SCSI_SENSE_BUF_SIZE_OLD 96
|
||||
#define SCSI_SENSE_BUF_SIZE 252
|
||||
|
||||
struct SCSICommand {
|
||||
uint8_t buf[SCSI_CMD_BUF_SIZE];
|
||||
int len;
|
||||
size_t xfer;
|
||||
uint64_t lba;
|
||||
enum SCSIXferMode mode;
|
||||
};
|
||||
|
||||
struct SCSIRequest {
|
||||
SCSIBus *bus;
|
||||
SCSIDevice *dev;
|
||||
@ -180,73 +155,6 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockBackend *blk,
|
||||
void scsi_bus_legacy_handle_cmdline(SCSIBus *bus, bool deprecated);
|
||||
void scsi_legacy_handle_cmdline(void);
|
||||
|
||||
/*
|
||||
* Predefined sense codes
|
||||
*/
|
||||
|
||||
/* No sense data available */
|
||||
extern const struct SCSISense sense_code_NO_SENSE;
|
||||
/* LUN not ready, Manual intervention required */
|
||||
extern const struct SCSISense sense_code_LUN_NOT_READY;
|
||||
/* LUN not ready, Medium not present */
|
||||
extern const struct SCSISense sense_code_NO_MEDIUM;
|
||||
/* LUN not ready, medium removal prevented */
|
||||
extern const struct SCSISense sense_code_NOT_READY_REMOVAL_PREVENTED;
|
||||
/* Hardware error, internal target failure */
|
||||
extern const struct SCSISense sense_code_TARGET_FAILURE;
|
||||
/* Illegal request, invalid command operation code */
|
||||
extern const struct SCSISense sense_code_INVALID_OPCODE;
|
||||
/* Illegal request, LBA out of range */
|
||||
extern const struct SCSISense sense_code_LBA_OUT_OF_RANGE;
|
||||
/* Illegal request, Invalid field in CDB */
|
||||
extern const struct SCSISense sense_code_INVALID_FIELD;
|
||||
/* Illegal request, Invalid field in parameter list */
|
||||
extern const struct SCSISense sense_code_INVALID_PARAM;
|
||||
/* Illegal request, Parameter list length error */
|
||||
extern const struct SCSISense sense_code_INVALID_PARAM_LEN;
|
||||
/* Illegal request, LUN not supported */
|
||||
extern const struct SCSISense sense_code_LUN_NOT_SUPPORTED;
|
||||
/* Illegal request, Saving parameters not supported */
|
||||
extern const struct SCSISense sense_code_SAVING_PARAMS_NOT_SUPPORTED;
|
||||
/* Illegal request, Incompatible format */
|
||||
extern const struct SCSISense sense_code_INCOMPATIBLE_FORMAT;
|
||||
/* Illegal request, medium removal prevented */
|
||||
extern const struct SCSISense sense_code_ILLEGAL_REQ_REMOVAL_PREVENTED;
|
||||
/* Illegal request, Invalid Transfer Tag */
|
||||
extern const struct SCSISense sense_code_INVALID_TAG;
|
||||
/* Command aborted, I/O process terminated */
|
||||
extern const struct SCSISense sense_code_IO_ERROR;
|
||||
/* Command aborted, I_T Nexus loss occurred */
|
||||
extern const struct SCSISense sense_code_I_T_NEXUS_LOSS;
|
||||
/* Command aborted, Logical Unit failure */
|
||||
extern const struct SCSISense sense_code_LUN_FAILURE;
|
||||
/* Command aborted, Overlapped Commands Attempted */
|
||||
extern const struct SCSISense sense_code_OVERLAPPED_COMMANDS;
|
||||
/* LUN not ready, Capacity data has changed */
|
||||
extern const struct SCSISense sense_code_CAPACITY_CHANGED;
|
||||
/* LUN not ready, Medium not present */
|
||||
extern const struct SCSISense sense_code_UNIT_ATTENTION_NO_MEDIUM;
|
||||
/* Unit attention, Power on, reset or bus device reset occurred */
|
||||
extern const struct SCSISense sense_code_RESET;
|
||||
/* Unit attention, Medium may have changed*/
|
||||
extern const struct SCSISense sense_code_MEDIUM_CHANGED;
|
||||
/* Unit attention, Reported LUNs data has changed */
|
||||
extern const struct SCSISense sense_code_REPORTED_LUNS_CHANGED;
|
||||
/* Unit attention, Device internal reset */
|
||||
extern const struct SCSISense sense_code_DEVICE_INTERNAL_RESET;
|
||||
/* Data Protection, Write Protected */
|
||||
extern const struct SCSISense sense_code_WRITE_PROTECTED;
|
||||
/* Data Protection, Space Allocation Failed Write Protect */
|
||||
extern const struct SCSISense sense_code_SPACE_ALLOC_FAILED;
|
||||
|
||||
#define SENSE_CODE(x) sense_code_ ## x
|
||||
|
||||
uint32_t scsi_data_cdb_xfer(uint8_t *buf);
|
||||
uint32_t scsi_cdb_xfer(uint8_t *buf);
|
||||
int scsi_cdb_length(uint8_t *buf);
|
||||
int scsi_build_sense(uint8_t *in_buf, int in_len,
|
||||
uint8_t *buf, int len, bool fixed);
|
||||
|
||||
SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d,
|
||||
uint32_t tag, uint32_t lun, void *hba_private);
|
||||
SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
|
||||
|
@ -32,7 +32,6 @@
|
||||
#define VIRTIO_SCSI(obj) \
|
||||
OBJECT_CHECK(VirtIOSCSI, (obj), TYPE_VIRTIO_SCSI)
|
||||
|
||||
#define VIRTIO_SCSI_VQ_SIZE 128
|
||||
#define VIRTIO_SCSI_MAX_CHANNEL 0
|
||||
#define VIRTIO_SCSI_MAX_TARGET 255
|
||||
#define VIRTIO_SCSI_MAX_LUN 16383
|
||||
@ -48,6 +47,7 @@ typedef struct virtio_scsi_config VirtIOSCSIConfig;
|
||||
|
||||
struct VirtIOSCSIConf {
|
||||
uint32_t num_queues;
|
||||
uint32_t virtqueue_size;
|
||||
uint32_t max_sectors;
|
||||
uint32_t cmd_per_lun;
|
||||
#ifdef CONFIG_VHOST_SCSI
|
||||
|
@ -107,6 +107,22 @@ extern int daemon(int, int);
|
||||
#include "glib-compat.h"
|
||||
#include "qemu/typedefs.h"
|
||||
|
||||
/*
|
||||
* We have a lot of unaudited code that may fail in strange ways, or
|
||||
* even be a security risk during migration, if you disable assertions
|
||||
* at compile-time. You may comment out these safety checks if you
|
||||
* absolutely want to disable assertion overhead, but it is not
|
||||
* supported upstream so the risk is all yours. Meanwhile, please
|
||||
* submit patches to remove any side-effects inside an assertion, or
|
||||
* fixing error handling that should use Error instead of assert.
|
||||
*/
|
||||
#ifdef NDEBUG
|
||||
#error building with NDEBUG is not supported
|
||||
#endif
|
||||
#ifdef G_DISABLE_ASSERT
|
||||
#error building with G_DISABLE_ASSERT is not supported
|
||||
#endif
|
||||
|
||||
#ifndef O_LARGEFILE
|
||||
#define O_LARGEFILE 0
|
||||
#endif
|
||||
|
@ -150,8 +150,6 @@
|
||||
#define READ_CD 0xbe
|
||||
#define SEND_DVD_STRUCTURE 0xbf
|
||||
|
||||
const char *scsi_command_name(uint8_t cmd);
|
||||
|
||||
/*
|
||||
* SERVICE ACTION IN subcodes
|
||||
*/
|
124
include/scsi/utils.h
Normal file
124
include/scsi/utils.h
Normal file
@ -0,0 +1,124 @@
|
||||
#ifndef SCSI_UTILS_H
|
||||
#define SCSI_UTILS_H 1
|
||||
|
||||
#ifdef CONFIG_LINUX
|
||||
#include <scsi/sg.h>
|
||||
#endif
|
||||
|
||||
#define SCSI_CMD_BUF_SIZE 16
|
||||
#define SCSI_SENSE_LEN 18
|
||||
#define SCSI_SENSE_LEN_SCANNER 32
|
||||
#define SCSI_INQUIRY_LEN 36
|
||||
|
||||
enum SCSIXferMode {
|
||||
SCSI_XFER_NONE, /* TEST_UNIT_READY, ... */
|
||||
SCSI_XFER_FROM_DEV, /* READ, INQUIRY, MODE_SENSE, ... */
|
||||
SCSI_XFER_TO_DEV, /* WRITE, MODE_SELECT, ... */
|
||||
};
|
||||
|
||||
typedef struct SCSICommand {
|
||||
uint8_t buf[SCSI_CMD_BUF_SIZE];
|
||||
int len;
|
||||
size_t xfer;
|
||||
uint64_t lba;
|
||||
enum SCSIXferMode mode;
|
||||
} SCSICommand;
|
||||
|
||||
typedef struct SCSISense {
|
||||
uint8_t key;
|
||||
uint8_t asc;
|
||||
uint8_t ascq;
|
||||
} SCSISense;
|
||||
|
||||
int scsi_build_sense(uint8_t *buf, SCSISense sense);
|
||||
|
||||
/*
|
||||
* Predefined sense codes
|
||||
*/
|
||||
|
||||
/* No sense data available */
|
||||
extern const struct SCSISense sense_code_NO_SENSE;
|
||||
/* LUN not ready, Manual intervention required */
|
||||
extern const struct SCSISense sense_code_LUN_NOT_READY;
|
||||
/* LUN not ready, Medium not present */
|
||||
extern const struct SCSISense sense_code_NO_MEDIUM;
|
||||
/* LUN not ready, medium removal prevented */
|
||||
extern const struct SCSISense sense_code_NOT_READY_REMOVAL_PREVENTED;
|
||||
/* Hardware error, internal target failure */
|
||||
extern const struct SCSISense sense_code_TARGET_FAILURE;
|
||||
/* Illegal request, invalid command operation code */
|
||||
extern const struct SCSISense sense_code_INVALID_OPCODE;
|
||||
/* Illegal request, LBA out of range */
|
||||
extern const struct SCSISense sense_code_LBA_OUT_OF_RANGE;
|
||||
/* Illegal request, Invalid field in CDB */
|
||||
extern const struct SCSISense sense_code_INVALID_FIELD;
|
||||
/* Illegal request, Invalid field in parameter list */
|
||||
extern const struct SCSISense sense_code_INVALID_PARAM;
|
||||
/* Illegal request, Parameter list length error */
|
||||
extern const struct SCSISense sense_code_INVALID_PARAM_LEN;
|
||||
/* Illegal request, LUN not supported */
|
||||
extern const struct SCSISense sense_code_LUN_NOT_SUPPORTED;
|
||||
/* Illegal request, Saving parameters not supported */
|
||||
extern const struct SCSISense sense_code_SAVING_PARAMS_NOT_SUPPORTED;
|
||||
/* Illegal request, Incompatible format */
|
||||
extern const struct SCSISense sense_code_INCOMPATIBLE_FORMAT;
|
||||
/* Illegal request, medium removal prevented */
|
||||
extern const struct SCSISense sense_code_ILLEGAL_REQ_REMOVAL_PREVENTED;
|
||||
/* Illegal request, Invalid Transfer Tag */
|
||||
extern const struct SCSISense sense_code_INVALID_TAG;
|
||||
/* Command aborted, I/O process terminated */
|
||||
extern const struct SCSISense sense_code_IO_ERROR;
|
||||
/* Command aborted, I_T Nexus loss occurred */
|
||||
extern const struct SCSISense sense_code_I_T_NEXUS_LOSS;
|
||||
/* Command aborted, Logical Unit failure */
|
||||
extern const struct SCSISense sense_code_LUN_FAILURE;
|
||||
/* Command aborted, Overlapped Commands Attempted */
|
||||
extern const struct SCSISense sense_code_OVERLAPPED_COMMANDS;
|
||||
/* LUN not ready, Capacity data has changed */
|
||||
extern const struct SCSISense sense_code_CAPACITY_CHANGED;
|
||||
/* LUN not ready, Medium not present */
|
||||
extern const struct SCSISense sense_code_UNIT_ATTENTION_NO_MEDIUM;
|
||||
/* Unit attention, Power on, reset or bus device reset occurred */
|
||||
extern const struct SCSISense sense_code_RESET;
|
||||
/* Unit attention, Medium may have changed*/
|
||||
extern const struct SCSISense sense_code_MEDIUM_CHANGED;
|
||||
/* Unit attention, Reported LUNs data has changed */
|
||||
extern const struct SCSISense sense_code_REPORTED_LUNS_CHANGED;
|
||||
/* Unit attention, Device internal reset */
|
||||
extern const struct SCSISense sense_code_DEVICE_INTERNAL_RESET;
|
||||
/* Data Protection, Write Protected */
|
||||
extern const struct SCSISense sense_code_WRITE_PROTECTED;
|
||||
/* Data Protection, Space Allocation Failed Write Protect */
|
||||
extern const struct SCSISense sense_code_SPACE_ALLOC_FAILED;
|
||||
|
||||
#define SENSE_CODE(x) sense_code_ ## x
|
||||
|
||||
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);
|
||||
|
||||
int scsi_convert_sense(uint8_t *in_buf, int in_len,
|
||||
uint8_t *buf, int len, bool fixed);
|
||||
const char *scsi_command_name(uint8_t cmd);
|
||||
|
||||
uint64_t scsi_cmd_lba(SCSICommand *cmd);
|
||||
uint32_t scsi_data_cdb_xfer(uint8_t *buf);
|
||||
uint32_t scsi_cdb_xfer(uint8_t *buf);
|
||||
int scsi_cdb_length(uint8_t *buf);
|
||||
|
||||
/* Linux SG_IO interface. */
|
||||
#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
|
||||
|
||||
#endif
|
22
memory.c
22
memory.c
@ -2701,10 +2701,10 @@ typedef struct MemoryRegionList MemoryRegionList;
|
||||
|
||||
struct MemoryRegionList {
|
||||
const MemoryRegion *mr;
|
||||
QTAILQ_ENTRY(MemoryRegionList) queue;
|
||||
QTAILQ_ENTRY(MemoryRegionList) mrqueue;
|
||||
};
|
||||
|
||||
typedef QTAILQ_HEAD(queue, MemoryRegionList) MemoryRegionListHead;
|
||||
typedef QTAILQ_HEAD(mrqueue, MemoryRegionList) MemoryRegionListHead;
|
||||
|
||||
#define MR_SIZE(size) (int128_nz(size) ? (hwaddr)int128_get64( \
|
||||
int128_sub((size), int128_one())) : 0)
|
||||
@ -2746,7 +2746,7 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f,
|
||||
bool found = false;
|
||||
|
||||
/* check if the alias is already in the queue */
|
||||
QTAILQ_FOREACH(ml, alias_print_queue, queue) {
|
||||
QTAILQ_FOREACH(ml, alias_print_queue, mrqueue) {
|
||||
if (ml->mr == mr->alias) {
|
||||
found = true;
|
||||
}
|
||||
@ -2755,7 +2755,7 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f,
|
||||
if (!found) {
|
||||
ml = g_new(MemoryRegionList, 1);
|
||||
ml->mr = mr->alias;
|
||||
QTAILQ_INSERT_TAIL(alias_print_queue, ml, queue);
|
||||
QTAILQ_INSERT_TAIL(alias_print_queue, ml, mrqueue);
|
||||
}
|
||||
mon_printf(f, TARGET_FMT_plx "-" TARGET_FMT_plx
|
||||
" (prio %d, %s): alias %s @%s " TARGET_FMT_plx
|
||||
@ -2783,26 +2783,26 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f,
|
||||
QTAILQ_FOREACH(submr, &mr->subregions, subregions_link) {
|
||||
new_ml = g_new(MemoryRegionList, 1);
|
||||
new_ml->mr = submr;
|
||||
QTAILQ_FOREACH(ml, &submr_print_queue, queue) {
|
||||
QTAILQ_FOREACH(ml, &submr_print_queue, mrqueue) {
|
||||
if (new_ml->mr->addr < ml->mr->addr ||
|
||||
(new_ml->mr->addr == ml->mr->addr &&
|
||||
new_ml->mr->priority > ml->mr->priority)) {
|
||||
QTAILQ_INSERT_BEFORE(ml, new_ml, queue);
|
||||
QTAILQ_INSERT_BEFORE(ml, new_ml, mrqueue);
|
||||
new_ml = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (new_ml) {
|
||||
QTAILQ_INSERT_TAIL(&submr_print_queue, new_ml, queue);
|
||||
QTAILQ_INSERT_TAIL(&submr_print_queue, new_ml, mrqueue);
|
||||
}
|
||||
}
|
||||
|
||||
QTAILQ_FOREACH(ml, &submr_print_queue, queue) {
|
||||
QTAILQ_FOREACH(ml, &submr_print_queue, mrqueue) {
|
||||
mtree_print_mr(mon_printf, f, ml->mr, level + 1, cur_start,
|
||||
alias_print_queue);
|
||||
}
|
||||
|
||||
QTAILQ_FOREACH_SAFE(ml, &submr_print_queue, queue, next_ml) {
|
||||
QTAILQ_FOREACH_SAFE(ml, &submr_print_queue, mrqueue, next_ml) {
|
||||
g_free(ml);
|
||||
}
|
||||
}
|
||||
@ -2872,13 +2872,13 @@ void mtree_info(fprintf_function mon_printf, void *f, bool flatview)
|
||||
}
|
||||
|
||||
/* print aliased regions */
|
||||
QTAILQ_FOREACH(ml, &ml_head, queue) {
|
||||
QTAILQ_FOREACH(ml, &ml_head, mrqueue) {
|
||||
mon_printf(f, "memory-region: %s\n", memory_region_name(ml->mr));
|
||||
mtree_print_mr(mon_printf, f, ml->mr, 1, 0, &ml_head);
|
||||
mon_printf(f, "\n");
|
||||
}
|
||||
|
||||
QTAILQ_FOREACH_SAFE(ml, &ml_head, queue, ml2) {
|
||||
QTAILQ_FOREACH_SAFE(ml, &ml_head, mrqueue, ml2) {
|
||||
g_free(ml);
|
||||
}
|
||||
}
|
||||
|
10
net/hub.c
10
net/hub.c
@ -18,6 +18,7 @@
|
||||
#include "clients.h"
|
||||
#include "hub.h"
|
||||
#include "qemu/iov.h"
|
||||
#include "qemu/error-report.h"
|
||||
|
||||
/*
|
||||
* A hub broadcasts incoming packets to all its ports except the source port.
|
||||
@ -309,8 +310,7 @@ void net_hub_check_clients(void)
|
||||
QLIST_FOREACH(port, &hub->ports, next) {
|
||||
peer = port->nc.peer;
|
||||
if (!peer) {
|
||||
fprintf(stderr, "Warning: hub port %s has no peer\n",
|
||||
port->nc.name);
|
||||
warn_report("hub port %s has no peer", port->nc.name);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -330,12 +330,10 @@ void net_hub_check_clients(void)
|
||||
}
|
||||
}
|
||||
if (has_host_dev && !has_nic) {
|
||||
fprintf(stderr, "Warning: vlan %d with no nics\n", hub->id);
|
||||
warn_report("vlan %d with no nics", hub->id);
|
||||
}
|
||||
if (has_nic && !has_host_dev) {
|
||||
fprintf(stderr,
|
||||
"Warning: vlan %d is not connected to host network\n",
|
||||
hub->id);
|
||||
warn_report("vlan %d is not connected to host network", hub->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
11
net/net.c
11
net/net.c
@ -1493,9 +1493,10 @@ void net_check_clients(void)
|
||||
|
||||
QTAILQ_FOREACH(nc, &net_clients, next) {
|
||||
if (!nc->peer) {
|
||||
fprintf(stderr, "Warning: %s %s has no peer\n",
|
||||
nc->info->type == NET_CLIENT_DRIVER_NIC ?
|
||||
"nic" : "netdev", nc->name);
|
||||
warn_report("%s %s has no peer",
|
||||
nc->info->type == NET_CLIENT_DRIVER_NIC
|
||||
? "nic" : "netdev",
|
||||
nc->name);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1506,8 +1507,8 @@ void net_check_clients(void)
|
||||
for (i = 0; i < MAX_NICS; i++) {
|
||||
NICInfo *nd = &nd_table[i];
|
||||
if (nd->used && !nd->instantiated) {
|
||||
fprintf(stderr, "Warning: requested NIC (%s, model %s) "
|
||||
"was not created (not supported by this machine?)\n",
|
||||
warn_report("requested NIC (%s, model %s) "
|
||||
"was not created (not supported by this machine?)",
|
||||
nd->name ? nd->name : "anonymous",
|
||||
nd->model ? nd->model : "unspecified");
|
||||
}
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include <windows.h>
|
||||
#include "qemu/error-report.h"
|
||||
#include "qga/guest-agent-core.h"
|
||||
#include "qga/vss-win32.h"
|
||||
#include "qga/vss-win32/requester.h"
|
||||
@ -61,7 +62,7 @@ static bool vss_check_os_version(void)
|
||||
return false;
|
||||
}
|
||||
if (wow64) {
|
||||
fprintf(stderr, "Warning: Running under WOW64\n");
|
||||
warn_report("Running under WOW64");
|
||||
}
|
||||
#endif
|
||||
return !wow64;
|
||||
|
@ -18,11 +18,12 @@ use Getopt::Long qw(:config no_auto_abbrev);
|
||||
my $quiet = 0;
|
||||
my $tree = 1;
|
||||
my $chk_signoff = 1;
|
||||
my $chk_patch = 1;
|
||||
my $chk_patch = undef;
|
||||
my $chk_branch = undef;
|
||||
my $tst_only;
|
||||
my $emacs = 0;
|
||||
my $terse = 0;
|
||||
my $file = 0;
|
||||
my $file = undef;
|
||||
my $no_warnings = 0;
|
||||
my $summary = 1;
|
||||
my $mailback = 0;
|
||||
@ -35,14 +36,19 @@ sub help {
|
||||
my ($exitcode) = @_;
|
||||
|
||||
print << "EOM";
|
||||
Usage: $P [OPTION]... [FILE]...
|
||||
Usage:
|
||||
|
||||
$P [OPTION]... [FILE]...
|
||||
$P [OPTION]... [GIT-REV-LIST]
|
||||
|
||||
Version: $V
|
||||
|
||||
Options:
|
||||
-q, --quiet quiet
|
||||
--no-tree run without a kernel tree
|
||||
--no-signoff do not check for 'Signed-off-by' line
|
||||
--patch treat FILE as patchfile (default)
|
||||
--patch treat FILE as patchfile
|
||||
--branch treat args as GIT revision list
|
||||
--emacs emacs compile window format
|
||||
--terse one line per report
|
||||
-f, --file treat FILE as regular source file
|
||||
@ -69,6 +75,7 @@ GetOptions(
|
||||
'tree!' => \$tree,
|
||||
'signoff!' => \$chk_signoff,
|
||||
'patch!' => \$chk_patch,
|
||||
'branch!' => \$chk_branch,
|
||||
'emacs!' => \$emacs,
|
||||
'terse!' => \$terse,
|
||||
'f|file!' => \$file,
|
||||
@ -93,6 +100,49 @@ if ($#ARGV < 0) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!defined $chk_branch && !defined $chk_patch && !defined $file) {
|
||||
$chk_branch = $ARGV[0] =~ /\.\./ ? 1 : 0;
|
||||
$chk_patch = $chk_branch ? 0 :
|
||||
$ARGV[0] =~ /\.patch$/ || $ARGV[0] eq "-" ? 1 : 0;
|
||||
$file = $chk_branch || $chk_patch ? 0 : 1;
|
||||
} elsif (!defined $chk_branch && !defined $chk_patch) {
|
||||
if ($file) {
|
||||
$chk_branch = $chk_patch = 0;
|
||||
} else {
|
||||
$chk_branch = $ARGV[0] =~ /\.\./ ? 1 : 0;
|
||||
$chk_patch = $chk_branch ? 0 : 1;
|
||||
}
|
||||
} elsif (!defined $chk_branch && !defined $file) {
|
||||
if ($chk_patch) {
|
||||
$chk_branch = $file = 0;
|
||||
} else {
|
||||
$chk_branch = $ARGV[0] =~ /\.\./ ? 1 : 0;
|
||||
$file = $chk_branch ? 0 : 1;
|
||||
}
|
||||
} elsif (!defined $chk_patch && !defined $file) {
|
||||
if ($chk_branch) {
|
||||
$chk_patch = $file = 0;
|
||||
} else {
|
||||
$chk_patch = $ARGV[0] =~ /\.patch$/ || $ARGV[0] eq "-" ? 1 : 0;
|
||||
$file = $chk_patch ? 0 : 1;
|
||||
}
|
||||
} elsif (!defined $chk_branch) {
|
||||
$chk_branch = $chk_patch || $file ? 0 : 1;
|
||||
} elsif (!defined $chk_patch) {
|
||||
$chk_patch = $chk_branch || $file ? 0 : 1;
|
||||
} elsif (!defined $file) {
|
||||
$file = $chk_patch || $chk_branch ? 0 : 1;
|
||||
}
|
||||
|
||||
if (($chk_patch && $chk_branch) ||
|
||||
($chk_patch && $file) ||
|
||||
($chk_branch && $file)) {
|
||||
die "Only one of --file, --branch, --patch is permitted\n";
|
||||
}
|
||||
if (!$chk_patch && !$chk_branch && !$file) {
|
||||
die "One of --file, --branch, --patch is required\n";
|
||||
}
|
||||
|
||||
my $dbg_values = 0;
|
||||
my $dbg_possible = 0;
|
||||
my $dbg_type = 0;
|
||||
@ -213,6 +263,7 @@ our @typeList = (
|
||||
qr{${Ident}_handler},
|
||||
qr{${Ident}_handler_fn},
|
||||
qr{target_(?:u)?long},
|
||||
qr{hwaddr},
|
||||
);
|
||||
|
||||
# This can be modified by sub possible. Since it can be empty, be careful
|
||||
@ -251,6 +302,39 @@ $chk_signoff = 0 if ($file);
|
||||
my @rawlines = ();
|
||||
my @lines = ();
|
||||
my $vname;
|
||||
if ($chk_branch) {
|
||||
my @patches;
|
||||
my $HASH;
|
||||
open($HASH, "-|", "git", "log", "--format=%H", $ARGV[0]) ||
|
||||
die "$P: git log --format=%H $ARGV[0] failed - $!\n";
|
||||
|
||||
while (<$HASH>) {
|
||||
chomp;
|
||||
push @patches, $_;
|
||||
}
|
||||
|
||||
close $HASH;
|
||||
|
||||
die "$P: no revisions returned for revlist '$chk_branch'\n"
|
||||
unless @patches;
|
||||
|
||||
for my $hash (@patches) {
|
||||
my $FILE;
|
||||
open($FILE, '-|', "git", "show", $hash) ||
|
||||
die "$P: git show $hash - $!\n";
|
||||
$vname = $hash;
|
||||
while (<$FILE>) {
|
||||
chomp;
|
||||
push(@rawlines, $_);
|
||||
}
|
||||
close($FILE);
|
||||
if (!process($hash)) {
|
||||
$exit = 1;
|
||||
}
|
||||
@rawlines = ();
|
||||
@lines = ();
|
||||
}
|
||||
} else {
|
||||
for my $filename (@ARGV) {
|
||||
my $FILE;
|
||||
if ($file) {
|
||||
@ -278,6 +362,7 @@ for my $filename (@ARGV) {
|
||||
@rawlines = ();
|
||||
@lines = ();
|
||||
}
|
||||
}
|
||||
|
||||
exit($exit);
|
||||
|
||||
|
@ -104,7 +104,9 @@ for arch in $ARCHLIST; do
|
||||
cp "$tmpdir/include/asm/unistd-common.h" "$output/linux-headers/asm-arm/"
|
||||
fi
|
||||
if [ $arch = x86 ]; then
|
||||
cp_portable "$tmpdir/include/asm/hyperv.h" "$output/include/standard-headers/asm-x86/"
|
||||
cat <<-EOF >"$output/include/standard-headers/asm-x86/hyperv.h"
|
||||
/* this is a temporary placeholder until kvm_para.h stops including it */
|
||||
EOF
|
||||
cp "$tmpdir/include/asm/unistd_32.h" "$output/linux-headers/asm-x86/"
|
||||
cp "$tmpdir/include/asm/unistd_x32.h" "$output/linux-headers/asm-x86/"
|
||||
cp "$tmpdir/include/asm/unistd_64.h" "$output/linux-headers/asm-x86/"
|
||||
|
1
scsi/Makefile.objs
Normal file
1
scsi/Makefile.objs
Normal file
@ -0,0 +1 @@
|
||||
block-obj-y += utils.o
|
538
scsi/utils.c
Normal file
538
scsi/utils.c
Normal file
@ -0,0 +1,538 @@
|
||||
/*
|
||||
* SCSI helpers
|
||||
*
|
||||
* Copyright 2017 Red Hat, Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Fam Zheng <famz@redhat.com>
|
||||
* Paolo Bonzini <pbonzini@redhat.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "scsi/constants.h"
|
||||
#include "scsi/utils.h"
|
||||
#include "qemu/bswap.h"
|
||||
|
||||
uint32_t scsi_data_cdb_xfer(uint8_t *buf)
|
||||
{
|
||||
if ((buf[0] >> 5) == 0 && buf[4] == 0) {
|
||||
return 256;
|
||||
} else {
|
||||
return scsi_cdb_xfer(buf);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t scsi_cdb_xfer(uint8_t *buf)
|
||||
{
|
||||
switch (buf[0] >> 5) {
|
||||
case 0:
|
||||
return buf[4];
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
return lduw_be_p(&buf[7]);
|
||||
break;
|
||||
case 4:
|
||||
return ldl_be_p(&buf[10]) & 0xffffffffULL;
|
||||
break;
|
||||
case 5:
|
||||
return ldl_be_p(&buf[6]) & 0xffffffffULL;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t scsi_cmd_lba(SCSICommand *cmd)
|
||||
{
|
||||
uint8_t *buf = cmd->buf;
|
||||
uint64_t lba;
|
||||
|
||||
switch (buf[0] >> 5) {
|
||||
case 0:
|
||||
lba = ldl_be_p(&buf[0]) & 0x1fffff;
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
case 5:
|
||||
lba = ldl_be_p(&buf[2]) & 0xffffffffULL;
|
||||
break;
|
||||
case 4:
|
||||
lba = ldq_be_p(&buf[2]);
|
||||
break;
|
||||
default:
|
||||
lba = -1;
|
||||
|
||||
}
|
||||
return lba;
|
||||
}
|
||||
|
||||
int scsi_cdb_length(uint8_t *buf)
|
||||
{
|
||||
int cdb_len;
|
||||
|
||||
switch (buf[0] >> 5) {
|
||||
case 0:
|
||||
cdb_len = 6;
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
cdb_len = 10;
|
||||
break;
|
||||
case 4:
|
||||
cdb_len = 16;
|
||||
break;
|
||||
case 5:
|
||||
cdb_len = 12;
|
||||
break;
|
||||
default:
|
||||
cdb_len = -1;
|
||||
}
|
||||
return cdb_len;
|
||||
}
|
||||
|
||||
int scsi_build_sense(uint8_t *buf, SCSISense sense)
|
||||
{
|
||||
memset(buf, 0, 18);
|
||||
buf[0] = 0x70;
|
||||
buf[2] = sense.key;
|
||||
buf[7] = 10;
|
||||
buf[12] = sense.asc;
|
||||
buf[13] = sense.ascq;
|
||||
return 18;
|
||||
}
|
||||
|
||||
/*
|
||||
* Predefined sense codes
|
||||
*/
|
||||
|
||||
/* No sense data available */
|
||||
const struct SCSISense sense_code_NO_SENSE = {
|
||||
.key = NO_SENSE , .asc = 0x00 , .ascq = 0x00
|
||||
};
|
||||
|
||||
/* LUN not ready, Manual intervention required */
|
||||
const struct SCSISense sense_code_LUN_NOT_READY = {
|
||||
.key = NOT_READY, .asc = 0x04, .ascq = 0x03
|
||||
};
|
||||
|
||||
/* LUN not ready, Medium not present */
|
||||
const struct SCSISense sense_code_NO_MEDIUM = {
|
||||
.key = NOT_READY, .asc = 0x3a, .ascq = 0x00
|
||||
};
|
||||
|
||||
/* LUN not ready, medium removal prevented */
|
||||
const struct SCSISense sense_code_NOT_READY_REMOVAL_PREVENTED = {
|
||||
.key = NOT_READY, .asc = 0x53, .ascq = 0x02
|
||||
};
|
||||
|
||||
/* Hardware error, internal target failure */
|
||||
const struct SCSISense sense_code_TARGET_FAILURE = {
|
||||
.key = HARDWARE_ERROR, .asc = 0x44, .ascq = 0x00
|
||||
};
|
||||
|
||||
/* Illegal request, invalid command operation code */
|
||||
const struct SCSISense sense_code_INVALID_OPCODE = {
|
||||
.key = ILLEGAL_REQUEST, .asc = 0x20, .ascq = 0x00
|
||||
};
|
||||
|
||||
/* Illegal request, LBA out of range */
|
||||
const struct SCSISense sense_code_LBA_OUT_OF_RANGE = {
|
||||
.key = ILLEGAL_REQUEST, .asc = 0x21, .ascq = 0x00
|
||||
};
|
||||
|
||||
/* Illegal request, Invalid field in CDB */
|
||||
const struct SCSISense sense_code_INVALID_FIELD = {
|
||||
.key = ILLEGAL_REQUEST, .asc = 0x24, .ascq = 0x00
|
||||
};
|
||||
|
||||
/* Illegal request, Invalid field in parameter list */
|
||||
const struct SCSISense sense_code_INVALID_PARAM = {
|
||||
.key = ILLEGAL_REQUEST, .asc = 0x26, .ascq = 0x00
|
||||
};
|
||||
|
||||
/* Illegal request, Parameter list length error */
|
||||
const struct SCSISense sense_code_INVALID_PARAM_LEN = {
|
||||
.key = ILLEGAL_REQUEST, .asc = 0x1a, .ascq = 0x00
|
||||
};
|
||||
|
||||
/* Illegal request, LUN not supported */
|
||||
const struct SCSISense sense_code_LUN_NOT_SUPPORTED = {
|
||||
.key = ILLEGAL_REQUEST, .asc = 0x25, .ascq = 0x00
|
||||
};
|
||||
|
||||
/* Illegal request, Saving parameters not supported */
|
||||
const struct SCSISense sense_code_SAVING_PARAMS_NOT_SUPPORTED = {
|
||||
.key = ILLEGAL_REQUEST, .asc = 0x39, .ascq = 0x00
|
||||
};
|
||||
|
||||
/* Illegal request, Incompatible medium installed */
|
||||
const struct SCSISense sense_code_INCOMPATIBLE_FORMAT = {
|
||||
.key = ILLEGAL_REQUEST, .asc = 0x30, .ascq = 0x00
|
||||
};
|
||||
|
||||
/* Illegal request, medium removal prevented */
|
||||
const struct SCSISense sense_code_ILLEGAL_REQ_REMOVAL_PREVENTED = {
|
||||
.key = ILLEGAL_REQUEST, .asc = 0x53, .ascq = 0x02
|
||||
};
|
||||
|
||||
/* Illegal request, Invalid Transfer Tag */
|
||||
const struct SCSISense sense_code_INVALID_TAG = {
|
||||
.key = ILLEGAL_REQUEST, .asc = 0x4b, .ascq = 0x01
|
||||
};
|
||||
|
||||
/* Command aborted, I/O process terminated */
|
||||
const struct SCSISense sense_code_IO_ERROR = {
|
||||
.key = ABORTED_COMMAND, .asc = 0x00, .ascq = 0x06
|
||||
};
|
||||
|
||||
/* Command aborted, I_T Nexus loss occurred */
|
||||
const struct SCSISense sense_code_I_T_NEXUS_LOSS = {
|
||||
.key = ABORTED_COMMAND, .asc = 0x29, .ascq = 0x07
|
||||
};
|
||||
|
||||
/* Command aborted, Logical Unit failure */
|
||||
const struct SCSISense sense_code_LUN_FAILURE = {
|
||||
.key = ABORTED_COMMAND, .asc = 0x3e, .ascq = 0x01
|
||||
};
|
||||
|
||||
/* Command aborted, Overlapped Commands Attempted */
|
||||
const struct SCSISense sense_code_OVERLAPPED_COMMANDS = {
|
||||
.key = ABORTED_COMMAND, .asc = 0x4e, .ascq = 0x00
|
||||
};
|
||||
|
||||
/* Unit attention, Capacity data has changed */
|
||||
const struct SCSISense sense_code_CAPACITY_CHANGED = {
|
||||
.key = UNIT_ATTENTION, .asc = 0x2a, .ascq = 0x09
|
||||
};
|
||||
|
||||
/* Unit attention, Power on, reset or bus device reset occurred */
|
||||
const struct SCSISense sense_code_RESET = {
|
||||
.key = UNIT_ATTENTION, .asc = 0x29, .ascq = 0x00
|
||||
};
|
||||
|
||||
/* Unit attention, No medium */
|
||||
const struct SCSISense sense_code_UNIT_ATTENTION_NO_MEDIUM = {
|
||||
.key = UNIT_ATTENTION, .asc = 0x3a, .ascq = 0x00
|
||||
};
|
||||
|
||||
/* Unit attention, Medium may have changed */
|
||||
const struct SCSISense sense_code_MEDIUM_CHANGED = {
|
||||
.key = UNIT_ATTENTION, .asc = 0x28, .ascq = 0x00
|
||||
};
|
||||
|
||||
/* Unit attention, Reported LUNs data has changed */
|
||||
const struct SCSISense sense_code_REPORTED_LUNS_CHANGED = {
|
||||
.key = UNIT_ATTENTION, .asc = 0x3f, .ascq = 0x0e
|
||||
};
|
||||
|
||||
/* Unit attention, Device internal reset */
|
||||
const struct SCSISense sense_code_DEVICE_INTERNAL_RESET = {
|
||||
.key = UNIT_ATTENTION, .asc = 0x29, .ascq = 0x04
|
||||
};
|
||||
|
||||
/* Data Protection, Write Protected */
|
||||
const struct SCSISense sense_code_WRITE_PROTECTED = {
|
||||
.key = DATA_PROTECT, .asc = 0x27, .ascq = 0x00
|
||||
};
|
||||
|
||||
/* Data Protection, Space Allocation Failed Write Protect */
|
||||
const struct SCSISense sense_code_SPACE_ALLOC_FAILED = {
|
||||
.key = DATA_PROTECT, .asc = 0x27, .ascq = 0x07
|
||||
};
|
||||
|
||||
/*
|
||||
* scsi_convert_sense
|
||||
*
|
||||
* Convert between fixed and descriptor sense buffers
|
||||
*/
|
||||
int scsi_convert_sense(uint8_t *in_buf, int in_len,
|
||||
uint8_t *buf, int len, bool fixed)
|
||||
{
|
||||
bool fixed_in;
|
||||
SCSISense sense;
|
||||
if (!fixed && len < 8) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (in_len == 0) {
|
||||
sense.key = NO_SENSE;
|
||||
sense.asc = 0;
|
||||
sense.ascq = 0;
|
||||
} else {
|
||||
fixed_in = (in_buf[0] & 2) == 0;
|
||||
|
||||
if (fixed == fixed_in) {
|
||||
memcpy(buf, in_buf, MIN(len, in_len));
|
||||
return MIN(len, in_len);
|
||||
}
|
||||
|
||||
if (fixed_in) {
|
||||
sense.key = in_buf[2];
|
||||
sense.asc = in_buf[12];
|
||||
sense.ascq = in_buf[13];
|
||||
} else {
|
||||
sense.key = in_buf[1];
|
||||
sense.asc = in_buf[2];
|
||||
sense.ascq = in_buf[3];
|
||||
}
|
||||
}
|
||||
|
||||
memset(buf, 0, len);
|
||||
if (fixed) {
|
||||
/* Return fixed format sense buffer */
|
||||
buf[0] = 0x70;
|
||||
buf[2] = sense.key;
|
||||
buf[7] = 10;
|
||||
buf[12] = sense.asc;
|
||||
buf[13] = sense.ascq;
|
||||
return MIN(len, SCSI_SENSE_LEN);
|
||||
} else {
|
||||
/* Return descriptor format sense buffer */
|
||||
buf[0] = 0x72;
|
||||
buf[1] = sense.key;
|
||||
buf[2] = sense.asc;
|
||||
buf[3] = sense.ascq;
|
||||
return 8;
|
||||
}
|
||||
}
|
||||
|
||||
int scsi_sense_to_errno(int key, int asc, int ascq)
|
||||
{
|
||||
switch (key) {
|
||||
case 0x00: /* NO SENSE */
|
||||
case 0x01: /* RECOVERED ERROR */
|
||||
case 0x06: /* UNIT ATTENTION */
|
||||
/* These sense keys are not errors */
|
||||
return 0;
|
||||
case 0x0b: /* COMMAND ABORTED */
|
||||
return ECANCELED;
|
||||
case 0x02: /* NOT READY */
|
||||
case 0x05: /* ILLEGAL REQUEST */
|
||||
case 0x07: /* DATA PROTECTION */
|
||||
/* Parse ASCQ */
|
||||
break;
|
||||
default:
|
||||
return EIO;
|
||||
}
|
||||
switch ((asc << 8) | ascq) {
|
||||
case 0x1a00: /* PARAMETER LIST LENGTH ERROR */
|
||||
case 0x2000: /* INVALID OPERATION CODE */
|
||||
case 0x2400: /* INVALID FIELD IN CDB */
|
||||
case 0x2600: /* INVALID FIELD IN PARAMETER LIST */
|
||||
return EINVAL;
|
||||
case 0x2100: /* LBA OUT OF RANGE */
|
||||
case 0x2707: /* SPACE ALLOC FAILED */
|
||||
return ENOSPC;
|
||||
case 0x2500: /* LOGICAL UNIT NOT SUPPORTED */
|
||||
return ENOTSUP;
|
||||
case 0x3a00: /* MEDIUM NOT PRESENT */
|
||||
case 0x3a01: /* MEDIUM NOT PRESENT TRAY CLOSED */
|
||||
case 0x3a02: /* MEDIUM NOT PRESENT TRAY OPEN */
|
||||
return ENOMEDIUM;
|
||||
case 0x2700: /* WRITE PROTECTED */
|
||||
return EACCES;
|
||||
case 0x0401: /* NOT READY, IN PROGRESS OF BECOMING READY */
|
||||
return EAGAIN;
|
||||
case 0x0402: /* NOT READY, INITIALIZING COMMAND REQUIRED */
|
||||
return ENOTCONN;
|
||||
default:
|
||||
return EIO;
|
||||
}
|
||||
}
|
||||
|
||||
int scsi_sense_buf_to_errno(const uint8_t *sense, size_t sense_size)
|
||||
{
|
||||
int key, asc, ascq;
|
||||
if (sense_size < 1) {
|
||||
return EIO;
|
||||
}
|
||||
switch (sense[0]) {
|
||||
case 0x70: /* Fixed format sense data. */
|
||||
if (sense_size < 14) {
|
||||
return EIO;
|
||||
}
|
||||
key = sense[2] & 0xF;
|
||||
asc = sense[12];
|
||||
ascq = sense[13];
|
||||
break;
|
||||
case 0x72: /* Descriptor format sense data. */
|
||||
if (sense_size < 4) {
|
||||
return EIO;
|
||||
}
|
||||
key = sense[1] & 0xF;
|
||||
asc = sense[2];
|
||||
ascq = sense[3];
|
||||
break;
|
||||
default:
|
||||
return EIO;
|
||||
break;
|
||||
}
|
||||
return scsi_sense_to_errno(key, asc, ascq);
|
||||
}
|
||||
|
||||
const char *scsi_command_name(uint8_t cmd)
|
||||
{
|
||||
static const char *names[] = {
|
||||
[ TEST_UNIT_READY ] = "TEST_UNIT_READY",
|
||||
[ REWIND ] = "REWIND",
|
||||
[ REQUEST_SENSE ] = "REQUEST_SENSE",
|
||||
[ FORMAT_UNIT ] = "FORMAT_UNIT",
|
||||
[ READ_BLOCK_LIMITS ] = "READ_BLOCK_LIMITS",
|
||||
[ REASSIGN_BLOCKS ] = "REASSIGN_BLOCKS/INITIALIZE ELEMENT STATUS",
|
||||
/* LOAD_UNLOAD and INITIALIZE_ELEMENT_STATUS use the same operation code */
|
||||
[ READ_6 ] = "READ_6",
|
||||
[ WRITE_6 ] = "WRITE_6",
|
||||
[ SET_CAPACITY ] = "SET_CAPACITY",
|
||||
[ READ_REVERSE ] = "READ_REVERSE",
|
||||
[ WRITE_FILEMARKS ] = "WRITE_FILEMARKS",
|
||||
[ SPACE ] = "SPACE",
|
||||
[ INQUIRY ] = "INQUIRY",
|
||||
[ RECOVER_BUFFERED_DATA ] = "RECOVER_BUFFERED_DATA",
|
||||
[ MAINTENANCE_IN ] = "MAINTENANCE_IN",
|
||||
[ MAINTENANCE_OUT ] = "MAINTENANCE_OUT",
|
||||
[ MODE_SELECT ] = "MODE_SELECT",
|
||||
[ RESERVE ] = "RESERVE",
|
||||
[ RELEASE ] = "RELEASE",
|
||||
[ COPY ] = "COPY",
|
||||
[ ERASE ] = "ERASE",
|
||||
[ MODE_SENSE ] = "MODE_SENSE",
|
||||
[ START_STOP ] = "START_STOP/LOAD_UNLOAD",
|
||||
/* LOAD_UNLOAD and START_STOP use the same operation code */
|
||||
[ RECEIVE_DIAGNOSTIC ] = "RECEIVE_DIAGNOSTIC",
|
||||
[ SEND_DIAGNOSTIC ] = "SEND_DIAGNOSTIC",
|
||||
[ ALLOW_MEDIUM_REMOVAL ] = "ALLOW_MEDIUM_REMOVAL",
|
||||
[ READ_CAPACITY_10 ] = "READ_CAPACITY_10",
|
||||
[ READ_10 ] = "READ_10",
|
||||
[ WRITE_10 ] = "WRITE_10",
|
||||
[ SEEK_10 ] = "SEEK_10/POSITION_TO_ELEMENT",
|
||||
/* SEEK_10 and POSITION_TO_ELEMENT use the same operation code */
|
||||
[ WRITE_VERIFY_10 ] = "WRITE_VERIFY_10",
|
||||
[ VERIFY_10 ] = "VERIFY_10",
|
||||
[ SEARCH_HIGH ] = "SEARCH_HIGH",
|
||||
[ SEARCH_EQUAL ] = "SEARCH_EQUAL",
|
||||
[ SEARCH_LOW ] = "SEARCH_LOW",
|
||||
[ SET_LIMITS ] = "SET_LIMITS",
|
||||
[ PRE_FETCH ] = "PRE_FETCH/READ_POSITION",
|
||||
/* READ_POSITION and PRE_FETCH use the same operation code */
|
||||
[ SYNCHRONIZE_CACHE ] = "SYNCHRONIZE_CACHE",
|
||||
[ LOCK_UNLOCK_CACHE ] = "LOCK_UNLOCK_CACHE",
|
||||
[ READ_DEFECT_DATA ] = "READ_DEFECT_DATA/INITIALIZE_ELEMENT_STATUS_WITH_RANGE",
|
||||
/* READ_DEFECT_DATA and INITIALIZE_ELEMENT_STATUS_WITH_RANGE use the same operation code */
|
||||
[ MEDIUM_SCAN ] = "MEDIUM_SCAN",
|
||||
[ COMPARE ] = "COMPARE",
|
||||
[ COPY_VERIFY ] = "COPY_VERIFY",
|
||||
[ WRITE_BUFFER ] = "WRITE_BUFFER",
|
||||
[ READ_BUFFER ] = "READ_BUFFER",
|
||||
[ UPDATE_BLOCK ] = "UPDATE_BLOCK",
|
||||
[ READ_LONG_10 ] = "READ_LONG_10",
|
||||
[ WRITE_LONG_10 ] = "WRITE_LONG_10",
|
||||
[ CHANGE_DEFINITION ] = "CHANGE_DEFINITION",
|
||||
[ WRITE_SAME_10 ] = "WRITE_SAME_10",
|
||||
[ UNMAP ] = "UNMAP",
|
||||
[ READ_TOC ] = "READ_TOC",
|
||||
[ REPORT_DENSITY_SUPPORT ] = "REPORT_DENSITY_SUPPORT",
|
||||
[ SANITIZE ] = "SANITIZE",
|
||||
[ GET_CONFIGURATION ] = "GET_CONFIGURATION",
|
||||
[ LOG_SELECT ] = "LOG_SELECT",
|
||||
[ LOG_SENSE ] = "LOG_SENSE",
|
||||
[ MODE_SELECT_10 ] = "MODE_SELECT_10",
|
||||
[ RESERVE_10 ] = "RESERVE_10",
|
||||
[ RELEASE_10 ] = "RELEASE_10",
|
||||
[ MODE_SENSE_10 ] = "MODE_SENSE_10",
|
||||
[ PERSISTENT_RESERVE_IN ] = "PERSISTENT_RESERVE_IN",
|
||||
[ PERSISTENT_RESERVE_OUT ] = "PERSISTENT_RESERVE_OUT",
|
||||
[ WRITE_FILEMARKS_16 ] = "WRITE_FILEMARKS_16",
|
||||
[ EXTENDED_COPY ] = "EXTENDED_COPY",
|
||||
[ ATA_PASSTHROUGH_16 ] = "ATA_PASSTHROUGH_16",
|
||||
[ ACCESS_CONTROL_IN ] = "ACCESS_CONTROL_IN",
|
||||
[ ACCESS_CONTROL_OUT ] = "ACCESS_CONTROL_OUT",
|
||||
[ READ_16 ] = "READ_16",
|
||||
[ COMPARE_AND_WRITE ] = "COMPARE_AND_WRITE",
|
||||
[ WRITE_16 ] = "WRITE_16",
|
||||
[ WRITE_VERIFY_16 ] = "WRITE_VERIFY_16",
|
||||
[ VERIFY_16 ] = "VERIFY_16",
|
||||
[ PRE_FETCH_16 ] = "PRE_FETCH_16",
|
||||
[ SYNCHRONIZE_CACHE_16 ] = "SPACE_16/SYNCHRONIZE_CACHE_16",
|
||||
/* SPACE_16 and SYNCHRONIZE_CACHE_16 use the same operation code */
|
||||
[ LOCATE_16 ] = "LOCATE_16",
|
||||
[ WRITE_SAME_16 ] = "ERASE_16/WRITE_SAME_16",
|
||||
/* ERASE_16 and WRITE_SAME_16 use the same operation code */
|
||||
[ SERVICE_ACTION_IN_16 ] = "SERVICE_ACTION_IN_16",
|
||||
[ WRITE_LONG_16 ] = "WRITE_LONG_16",
|
||||
[ REPORT_LUNS ] = "REPORT_LUNS",
|
||||
[ ATA_PASSTHROUGH_12 ] = "BLANK/ATA_PASSTHROUGH_12",
|
||||
[ MOVE_MEDIUM ] = "MOVE_MEDIUM",
|
||||
[ EXCHANGE_MEDIUM ] = "EXCHANGE MEDIUM",
|
||||
[ READ_12 ] = "READ_12",
|
||||
[ WRITE_12 ] = "WRITE_12",
|
||||
[ ERASE_12 ] = "ERASE_12/GET_PERFORMANCE",
|
||||
/* ERASE_12 and GET_PERFORMANCE use the same operation code */
|
||||
[ SERVICE_ACTION_IN_12 ] = "SERVICE_ACTION_IN_12",
|
||||
[ WRITE_VERIFY_12 ] = "WRITE_VERIFY_12",
|
||||
[ VERIFY_12 ] = "VERIFY_12",
|
||||
[ SEARCH_HIGH_12 ] = "SEARCH_HIGH_12",
|
||||
[ SEARCH_EQUAL_12 ] = "SEARCH_EQUAL_12",
|
||||
[ SEARCH_LOW_12 ] = "SEARCH_LOW_12",
|
||||
[ READ_ELEMENT_STATUS ] = "READ_ELEMENT_STATUS",
|
||||
[ SEND_VOLUME_TAG ] = "SEND_VOLUME_TAG/SET_STREAMING",
|
||||
/* SEND_VOLUME_TAG and SET_STREAMING use the same operation code */
|
||||
[ READ_CD ] = "READ_CD",
|
||||
[ READ_DEFECT_DATA_12 ] = "READ_DEFECT_DATA_12",
|
||||
[ READ_DVD_STRUCTURE ] = "READ_DVD_STRUCTURE",
|
||||
[ RESERVE_TRACK ] = "RESERVE_TRACK",
|
||||
[ SEND_CUE_SHEET ] = "SEND_CUE_SHEET",
|
||||
[ SEND_DVD_STRUCTURE ] = "SEND_DVD_STRUCTURE",
|
||||
[ SET_CD_SPEED ] = "SET_CD_SPEED",
|
||||
[ SET_READ_AHEAD ] = "SET_READ_AHEAD",
|
||||
[ ALLOW_OVERWRITE ] = "ALLOW_OVERWRITE",
|
||||
[ MECHANISM_STATUS ] = "MECHANISM_STATUS",
|
||||
[ GET_EVENT_STATUS_NOTIFICATION ] = "GET_EVENT_STATUS_NOTIFICATION",
|
||||
[ READ_DISC_INFORMATION ] = "READ_DISC_INFORMATION",
|
||||
};
|
||||
|
||||
if (cmd >= ARRAY_SIZE(names) || names[cmd] == NULL) {
|
||||
return "*UNKNOWN*";
|
||||
}
|
||||
return names[cmd];
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LINUX
|
||||
int sg_io_sense_from_errno(int errno_value, struct sg_io_hdr *io_hdr,
|
||||
SCSISense *sense)
|
||||
{
|
||||
if (errno_value != 0) {
|
||||
switch (errno_value) {
|
||||
case EDOM:
|
||||
return TASK_SET_FULL;
|
||||
case ENOMEM:
|
||||
*sense = SENSE_CODE(TARGET_FAILURE);
|
||||
return CHECK_CONDITION;
|
||||
default:
|
||||
*sense = SENSE_CODE(IO_ERROR);
|
||||
return CHECK_CONDITION;
|
||||
}
|
||||
} else {
|
||||
if (io_hdr->host_status == SG_ERR_DID_NO_CONNECT ||
|
||||
io_hdr->host_status == SG_ERR_DID_BUS_BUSY ||
|
||||
io_hdr->host_status == SG_ERR_DID_TIME_OUT ||
|
||||
(io_hdr->driver_status & SG_ERR_DRIVER_TIMEOUT)) {
|
||||
return BUSY;
|
||||
} else if (io_hdr->host_status) {
|
||||
*sense = SENSE_CODE(I_T_NEXUS_LOSS);
|
||||
return CHECK_CONDITION;
|
||||
} else if (io_hdr->status) {
|
||||
return io_hdr->status;
|
||||
} else if (io_hdr->driver_status & SG_ERR_DRIVER_SENSE) {
|
||||
return CHECK_CONDITION;
|
||||
} else {
|
||||
return GOOD;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
@ -1766,8 +1766,8 @@ static void report_unavailable_features(FeatureWord w, uint32_t mask)
|
||||
if ((1UL << i) & mask) {
|
||||
const char *reg = get_register_name_32(f->cpuid_reg);
|
||||
assert(reg);
|
||||
fprintf(stderr, "warning: %s doesn't support requested feature: "
|
||||
"CPUID.%02XH:%s%s%s [bit %d]\n",
|
||||
warn_report("%s doesn't support requested feature: "
|
||||
"CPUID.%02XH:%s%s%s [bit %d]",
|
||||
kvm_enabled() ? "host" : "TCG",
|
||||
f->cpuid_eax, reg,
|
||||
f->feat_names[i] ? "." : "",
|
||||
@ -3934,12 +3934,12 @@ static GuestPanicInformation *x86_cpu_get_crash_info(CPUState *cs)
|
||||
CPUX86State *env = &cpu->env;
|
||||
GuestPanicInformation *panic_info = NULL;
|
||||
|
||||
if (env->features[FEAT_HYPERV_EDX] & HV_X64_GUEST_CRASH_MSR_AVAILABLE) {
|
||||
if (env->features[FEAT_HYPERV_EDX] & HV_GUEST_CRASH_MSR_AVAILABLE) {
|
||||
panic_info = g_malloc0(sizeof(GuestPanicInformation));
|
||||
|
||||
panic_info->type = GUEST_PANIC_INFORMATION_TYPE_HYPER_V;
|
||||
|
||||
assert(HV_X64_MSR_CRASH_PARAMS >= 5);
|
||||
assert(HV_CRASH_PARAMS >= 5);
|
||||
panic_info->u.hyper_v.arg1 = env->msr_hv_crash_params[0];
|
||||
panic_info->u.hyper_v.arg2 = env->msr_hv_crash_params[1];
|
||||
panic_info->u.hyper_v.arg3 = env->msr_hv_crash_params[2];
|
||||
@ -4145,6 +4145,20 @@ static Property x86_cpu_properties[] = {
|
||||
false),
|
||||
DEFINE_PROP_BOOL("vmware-cpuid-freq", X86CPU, vmware_cpuid_freq, true),
|
||||
DEFINE_PROP_BOOL("tcg-cpuid", X86CPU, expose_tcg, true),
|
||||
|
||||
/*
|
||||
* From "Requirements for Implementing the Microsoft
|
||||
* Hypervisor Interface":
|
||||
* https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/reference/tlfs
|
||||
*
|
||||
* "Starting with Windows Server 2012 and Windows 8, if
|
||||
* CPUID.40000005.EAX contains a value of -1, Windows assumes that
|
||||
* the hypervisor imposes no specific limit to the number of VPs.
|
||||
* In this case, Windows Server 2012 guest VMs may use more than
|
||||
* 64 VPs, up to the maximum supported number of processors applicable
|
||||
* to the specific Windows version being used."
|
||||
*/
|
||||
DEFINE_PROP_INT32("x-hv-max-vps", X86CPU, hv_max_vps, -1),
|
||||
DEFINE_PROP_END_OF_LIST()
|
||||
};
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "cpu-qom.h"
|
||||
#include "standard-headers/asm-x86/hyperv.h"
|
||||
#include "hyperv-proto.h"
|
||||
|
||||
#ifdef TARGET_X86_64
|
||||
#define TARGET_LONG_BITS 64
|
||||
@ -1095,15 +1095,15 @@ typedef struct CPUX86State {
|
||||
uint64_t msr_hv_guest_os_id;
|
||||
uint64_t msr_hv_vapic;
|
||||
uint64_t msr_hv_tsc;
|
||||
uint64_t msr_hv_crash_params[HV_X64_MSR_CRASH_PARAMS];
|
||||
uint64_t msr_hv_crash_params[HV_CRASH_PARAMS];
|
||||
uint64_t msr_hv_runtime;
|
||||
uint64_t msr_hv_synic_control;
|
||||
uint64_t msr_hv_synic_version;
|
||||
uint64_t msr_hv_synic_evt_page;
|
||||
uint64_t msr_hv_synic_msg_page;
|
||||
uint64_t msr_hv_synic_sint[HV_SYNIC_SINT_COUNT];
|
||||
uint64_t msr_hv_stimer_config[HV_SYNIC_STIMER_COUNT];
|
||||
uint64_t msr_hv_stimer_count[HV_SYNIC_STIMER_COUNT];
|
||||
uint64_t msr_hv_synic_sint[HV_SINT_COUNT];
|
||||
uint64_t msr_hv_stimer_config[HV_STIMER_COUNT];
|
||||
uint64_t msr_hv_stimer_count[HV_STIMER_COUNT];
|
||||
|
||||
/* exception/interrupt handling */
|
||||
int error_code;
|
||||
@ -1282,6 +1282,8 @@ struct X86CPU {
|
||||
int32_t socket_id;
|
||||
int32_t core_id;
|
||||
int32_t thread_id;
|
||||
|
||||
int32_t hv_max_vps;
|
||||
};
|
||||
|
||||
static inline X86CPU *x86_env_get_cpu(CPUX86State *env)
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "cpu.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "qemu/error-report.h"
|
||||
|
||||
#include "target/i386/hax-i386.h"
|
||||
#include "qemu/queue.h"
|
||||
@ -178,9 +179,8 @@ static void hax_process_section(MemoryRegionSection *section, uint8_t flags)
|
||||
if (!memory_region_is_ram(mr)) {
|
||||
if (memory_region_is_romd(mr)) {
|
||||
/* HAXM kernel module does not support ROMD yet */
|
||||
fprintf(stderr, "%s: Warning: Ignoring ROMD region 0x%016" PRIx64
|
||||
"->0x%016" PRIx64 "\n", __func__, start_pa,
|
||||
start_pa + size);
|
||||
warn_report("Ignoring ROMD region 0x%016" PRIx64 "->0x%016" PRIx64,
|
||||
start_pa, start_pa + size);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
260
target/i386/hyperv-proto.h
Normal file
260
target/i386/hyperv-proto.h
Normal file
@ -0,0 +1,260 @@
|
||||
/*
|
||||
* Definitions for Hyper-V guest/hypervisor interaction
|
||||
*
|
||||
* Copyright (C) 2017 Parallels International GmbH
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef TARGET_I386_HYPERV_PROTO_H
|
||||
#define TARGET_I386_HYPERV_PROTO_H
|
||||
|
||||
#include "qemu/bitmap.h"
|
||||
|
||||
#define HV_CPUID_VENDOR_AND_MAX_FUNCTIONS 0x40000000
|
||||
#define HV_CPUID_INTERFACE 0x40000001
|
||||
#define HV_CPUID_VERSION 0x40000002
|
||||
#define HV_CPUID_FEATURES 0x40000003
|
||||
#define HV_CPUID_ENLIGHTMENT_INFO 0x40000004
|
||||
#define HV_CPUID_IMPLEMENT_LIMITS 0x40000005
|
||||
#define HV_CPUID_MIN 0x40000005
|
||||
#define HV_CPUID_MAX 0x4000ffff
|
||||
#define HV_HYPERVISOR_PRESENT_BIT 0x80000000
|
||||
|
||||
/*
|
||||
* HV_CPUID_FEATURES.EAX bits
|
||||
*/
|
||||
#define HV_VP_RUNTIME_AVAILABLE (1u << 0)
|
||||
#define HV_TIME_REF_COUNT_AVAILABLE (1u << 1)
|
||||
#define HV_SYNIC_AVAILABLE (1u << 2)
|
||||
#define HV_SYNTIMERS_AVAILABLE (1u << 3)
|
||||
#define HV_APIC_ACCESS_AVAILABLE (1u << 4)
|
||||
#define HV_HYPERCALL_AVAILABLE (1u << 5)
|
||||
#define HV_VP_INDEX_AVAILABLE (1u << 6)
|
||||
#define HV_RESET_AVAILABLE (1u << 7)
|
||||
#define HV_REFERENCE_TSC_AVAILABLE (1u << 9)
|
||||
#define HV_ACCESS_FREQUENCY_MSRS (1u << 11)
|
||||
|
||||
|
||||
/*
|
||||
* HV_CPUID_FEATURES.EDX bits
|
||||
*/
|
||||
#define HV_MWAIT_AVAILABLE (1u << 0)
|
||||
#define HV_GUEST_DEBUGGING_AVAILABLE (1u << 1)
|
||||
#define HV_PERF_MONITOR_AVAILABLE (1u << 2)
|
||||
#define HV_CPU_DYNAMIC_PARTITIONING_AVAILABLE (1u << 3)
|
||||
#define HV_HYPERCALL_PARAMS_XMM_AVAILABLE (1u << 4)
|
||||
#define HV_GUEST_IDLE_STATE_AVAILABLE (1u << 5)
|
||||
#define HV_FREQUENCY_MSRS_AVAILABLE (1u << 8)
|
||||
#define HV_GUEST_CRASH_MSR_AVAILABLE (1u << 10)
|
||||
|
||||
/*
|
||||
* HV_CPUID_ENLIGHTMENT_INFO.EAX bits
|
||||
*/
|
||||
#define HV_AS_SWITCH_RECOMMENDED (1u << 0)
|
||||
#define HV_LOCAL_TLB_FLUSH_RECOMMENDED (1u << 1)
|
||||
#define HV_REMOTE_TLB_FLUSH_RECOMMENDED (1u << 2)
|
||||
#define HV_APIC_ACCESS_RECOMMENDED (1u << 3)
|
||||
#define HV_SYSTEM_RESET_RECOMMENDED (1u << 4)
|
||||
#define HV_RELAXED_TIMING_RECOMMENDED (1u << 5)
|
||||
|
||||
/*
|
||||
* Basic virtualized MSRs
|
||||
*/
|
||||
#define HV_X64_MSR_GUEST_OS_ID 0x40000000
|
||||
#define HV_X64_MSR_HYPERCALL 0x40000001
|
||||
#define HV_X64_MSR_VP_INDEX 0x40000002
|
||||
#define HV_X64_MSR_RESET 0x40000003
|
||||
#define HV_X64_MSR_VP_RUNTIME 0x40000010
|
||||
#define HV_X64_MSR_TIME_REF_COUNT 0x40000020
|
||||
#define HV_X64_MSR_REFERENCE_TSC 0x40000021
|
||||
#define HV_X64_MSR_TSC_FREQUENCY 0x40000022
|
||||
#define HV_X64_MSR_APIC_FREQUENCY 0x40000023
|
||||
|
||||
/*
|
||||
* Virtual APIC MSRs
|
||||
*/
|
||||
#define HV_X64_MSR_EOI 0x40000070
|
||||
#define HV_X64_MSR_ICR 0x40000071
|
||||
#define HV_X64_MSR_TPR 0x40000072
|
||||
#define HV_X64_MSR_APIC_ASSIST_PAGE 0x40000073
|
||||
|
||||
/*
|
||||
* Synthetic interrupt controller MSRs
|
||||
*/
|
||||
#define HV_X64_MSR_SCONTROL 0x40000080
|
||||
#define HV_X64_MSR_SVERSION 0x40000081
|
||||
#define HV_X64_MSR_SIEFP 0x40000082
|
||||
#define HV_X64_MSR_SIMP 0x40000083
|
||||
#define HV_X64_MSR_EOM 0x40000084
|
||||
#define HV_X64_MSR_SINT0 0x40000090
|
||||
#define HV_X64_MSR_SINT1 0x40000091
|
||||
#define HV_X64_MSR_SINT2 0x40000092
|
||||
#define HV_X64_MSR_SINT3 0x40000093
|
||||
#define HV_X64_MSR_SINT4 0x40000094
|
||||
#define HV_X64_MSR_SINT5 0x40000095
|
||||
#define HV_X64_MSR_SINT6 0x40000096
|
||||
#define HV_X64_MSR_SINT7 0x40000097
|
||||
#define HV_X64_MSR_SINT8 0x40000098
|
||||
#define HV_X64_MSR_SINT9 0x40000099
|
||||
#define HV_X64_MSR_SINT10 0x4000009A
|
||||
#define HV_X64_MSR_SINT11 0x4000009B
|
||||
#define HV_X64_MSR_SINT12 0x4000009C
|
||||
#define HV_X64_MSR_SINT13 0x4000009D
|
||||
#define HV_X64_MSR_SINT14 0x4000009E
|
||||
#define HV_X64_MSR_SINT15 0x4000009F
|
||||
|
||||
/*
|
||||
* Synthetic timer MSRs
|
||||
*/
|
||||
#define HV_X64_MSR_STIMER0_CONFIG 0x400000B0
|
||||
#define HV_X64_MSR_STIMER0_COUNT 0x400000B1
|
||||
#define HV_X64_MSR_STIMER1_CONFIG 0x400000B2
|
||||
#define HV_X64_MSR_STIMER1_COUNT 0x400000B3
|
||||
#define HV_X64_MSR_STIMER2_CONFIG 0x400000B4
|
||||
#define HV_X64_MSR_STIMER2_COUNT 0x400000B5
|
||||
#define HV_X64_MSR_STIMER3_CONFIG 0x400000B6
|
||||
#define HV_X64_MSR_STIMER3_COUNT 0x400000B7
|
||||
|
||||
/*
|
||||
* Guest crash notification MSRs
|
||||
*/
|
||||
#define HV_X64_MSR_CRASH_P0 0x40000100
|
||||
#define HV_X64_MSR_CRASH_P1 0x40000101
|
||||
#define HV_X64_MSR_CRASH_P2 0x40000102
|
||||
#define HV_X64_MSR_CRASH_P3 0x40000103
|
||||
#define HV_X64_MSR_CRASH_P4 0x40000104
|
||||
#define HV_CRASH_PARAMS (HV_X64_MSR_CRASH_P4 - HV_X64_MSR_CRASH_P0 + 1)
|
||||
#define HV_X64_MSR_CRASH_CTL 0x40000105
|
||||
#define HV_CRASH_CTL_NOTIFY (1ull << 63)
|
||||
|
||||
/*
|
||||
* Hypercall status code
|
||||
*/
|
||||
#define HV_STATUS_SUCCESS 0
|
||||
#define HV_STATUS_INVALID_HYPERCALL_CODE 2
|
||||
#define HV_STATUS_INVALID_HYPERCALL_INPUT 3
|
||||
#define HV_STATUS_INVALID_ALIGNMENT 4
|
||||
#define HV_STATUS_INVALID_PARAMETER 5
|
||||
#define HV_STATUS_INSUFFICIENT_MEMORY 11
|
||||
#define HV_STATUS_INVALID_CONNECTION_ID 18
|
||||
#define HV_STATUS_INSUFFICIENT_BUFFERS 19
|
||||
|
||||
/*
|
||||
* Hypercall numbers
|
||||
*/
|
||||
#define HV_POST_MESSAGE 0x005c
|
||||
#define HV_SIGNAL_EVENT 0x005d
|
||||
#define HV_HYPERCALL_FAST (1u << 16)
|
||||
|
||||
/*
|
||||
* Hypercall MSR bits
|
||||
*/
|
||||
#define HV_HYPERCALL_ENABLE (1u << 0)
|
||||
|
||||
/*
|
||||
* Synthetic interrupt controller definitions
|
||||
*/
|
||||
#define HV_SYNIC_VERSION 1
|
||||
#define HV_SINT_COUNT 16
|
||||
#define HV_SYNIC_ENABLE (1u << 0)
|
||||
#define HV_SIMP_ENABLE (1u << 0)
|
||||
#define HV_SIEFP_ENABLE (1u << 0)
|
||||
#define HV_SINT_MASKED (1u << 16)
|
||||
#define HV_SINT_AUTO_EOI (1u << 17)
|
||||
#define HV_SINT_VECTOR_MASK 0xff
|
||||
|
||||
#define HV_STIMER_COUNT 4
|
||||
|
||||
/*
|
||||
* Message size
|
||||
*/
|
||||
#define HV_MESSAGE_PAYLOAD_SIZE 240
|
||||
|
||||
/*
|
||||
* Message types
|
||||
*/
|
||||
#define HV_MESSAGE_NONE 0x00000000
|
||||
#define HV_MESSAGE_VMBUS 0x00000001
|
||||
#define HV_MESSAGE_UNMAPPED_GPA 0x80000000
|
||||
#define HV_MESSAGE_GPA_INTERCEPT 0x80000001
|
||||
#define HV_MESSAGE_TIMER_EXPIRED 0x80000010
|
||||
#define HV_MESSAGE_INVALID_VP_REGISTER_VALUE 0x80000020
|
||||
#define HV_MESSAGE_UNRECOVERABLE_EXCEPTION 0x80000021
|
||||
#define HV_MESSAGE_UNSUPPORTED_FEATURE 0x80000022
|
||||
#define HV_MESSAGE_EVENTLOG_BUFFERCOMPLETE 0x80000040
|
||||
#define HV_MESSAGE_X64_IOPORT_INTERCEPT 0x80010000
|
||||
#define HV_MESSAGE_X64_MSR_INTERCEPT 0x80010001
|
||||
#define HV_MESSAGE_X64_CPUID_INTERCEPT 0x80010002
|
||||
#define HV_MESSAGE_X64_EXCEPTION_INTERCEPT 0x80010003
|
||||
#define HV_MESSAGE_X64_APIC_EOI 0x80010004
|
||||
#define HV_MESSAGE_X64_LEGACY_FP_ERROR 0x80010005
|
||||
|
||||
/*
|
||||
* Message flags
|
||||
*/
|
||||
#define HV_MESSAGE_FLAG_PENDING 0x1
|
||||
|
||||
/*
|
||||
* Event flags number per SINT
|
||||
*/
|
||||
#define HV_EVENT_FLAGS_COUNT (256 * 8)
|
||||
|
||||
/*
|
||||
* Connection id valid bits
|
||||
*/
|
||||
#define HV_CONNECTION_ID_MASK 0x00ffffff
|
||||
|
||||
/*
|
||||
* Input structure for POST_MESSAGE hypercall
|
||||
*/
|
||||
struct hyperv_post_message_input {
|
||||
uint32_t connection_id;
|
||||
uint32_t _reserved;
|
||||
uint32_t message_type;
|
||||
uint32_t payload_size;
|
||||
uint8_t payload[HV_MESSAGE_PAYLOAD_SIZE];
|
||||
};
|
||||
|
||||
/*
|
||||
* Input structure for SIGNAL_EVENT hypercall
|
||||
*/
|
||||
struct hyperv_signal_event_input {
|
||||
uint32_t connection_id;
|
||||
uint16_t flag_number;
|
||||
uint16_t _reserved_zero;
|
||||
};
|
||||
|
||||
/*
|
||||
* SynIC message structures
|
||||
*/
|
||||
struct hyperv_message_header {
|
||||
uint32_t message_type;
|
||||
uint8_t payload_size;
|
||||
uint8_t message_flags; /* HV_MESSAGE_FLAG_XX */
|
||||
uint8_t _reserved[2];
|
||||
uint64_t sender;
|
||||
};
|
||||
|
||||
struct hyperv_message {
|
||||
struct hyperv_message_header header;
|
||||
uint8_t payload[HV_MESSAGE_PAYLOAD_SIZE];
|
||||
};
|
||||
|
||||
struct hyperv_message_page {
|
||||
struct hyperv_message slot[HV_SINT_COUNT];
|
||||
};
|
||||
|
||||
/*
|
||||
* SynIC event flags structures
|
||||
*/
|
||||
struct hyperv_event_flags {
|
||||
DECLARE_BITMAP(flags, HV_EVENT_FLAGS_COUNT);
|
||||
};
|
||||
|
||||
struct hyperv_event_flags_page {
|
||||
struct hyperv_event_flags slot[HV_SINT_COUNT];
|
||||
};
|
||||
|
||||
#endif
|
@ -14,7 +14,7 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "hyperv.h"
|
||||
#include "standard-headers/asm-x86/hyperv.h"
|
||||
#include "hyperv-proto.h"
|
||||
|
||||
int kvm_hv_handle_exit(X86CPU *cpu, struct kvm_hyperv_exit *exit)
|
||||
{
|
||||
@ -50,8 +50,8 @@ int kvm_hv_handle_exit(X86CPU *cpu, struct kvm_hyperv_exit *exit)
|
||||
|
||||
code = exit->u.hcall.input & 0xffff;
|
||||
switch (code) {
|
||||
case HVCALL_POST_MESSAGE:
|
||||
case HVCALL_SIGNAL_EVENT:
|
||||
case HV_POST_MESSAGE:
|
||||
case HV_SIGNAL_EVENT:
|
||||
default:
|
||||
exit->u.hcall.result = HV_STATUS_INVALID_HYPERCALL_CODE;
|
||||
return 0;
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "sysemu/kvm_int.h"
|
||||
#include "kvm_i386.h"
|
||||
#include "hyperv.h"
|
||||
#include "hyperv-proto.h"
|
||||
|
||||
#include "exec/gdbstub.h"
|
||||
#include "qemu/host-utils.h"
|
||||
@ -40,7 +41,6 @@
|
||||
#include "hw/i386/x86-iommu.h"
|
||||
|
||||
#include "exec/ioport.h"
|
||||
#include "standard-headers/asm-x86/hyperv.h"
|
||||
#include "hw/pci/pci.h"
|
||||
#include "hw/pci/msi.h"
|
||||
#include "hw/pci/msix.h"
|
||||
@ -89,6 +89,7 @@ static bool has_msr_hv_vpindex;
|
||||
static bool has_msr_hv_runtime;
|
||||
static bool has_msr_hv_synic;
|
||||
static bool has_msr_hv_stimer;
|
||||
static bool has_msr_hv_frequencies;
|
||||
static bool has_msr_xss;
|
||||
|
||||
static bool has_msr_architectural_pmu;
|
||||
@ -611,6 +612,15 @@ static int kvm_arch_set_tsc_khz(CPUState *cs)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool tsc_is_stable_and_known(CPUX86State *env)
|
||||
{
|
||||
if (!env->tsc_khz) {
|
||||
return false;
|
||||
}
|
||||
return (env->features[FEAT_8000_0007_EDX] & CPUID_APM_INVTSC)
|
||||
|| env->user_tsc_khz;
|
||||
}
|
||||
|
||||
static int hyperv_handle_properties(CPUState *cs)
|
||||
{
|
||||
X86CPU *cpu = X86_CPU(cs);
|
||||
@ -622,29 +632,34 @@ static int hyperv_handle_properties(CPUState *cs)
|
||||
}
|
||||
|
||||
if (cpu->hyperv_relaxed_timing) {
|
||||
env->features[FEAT_HYPERV_EAX] |= HV_X64_MSR_HYPERCALL_AVAILABLE;
|
||||
env->features[FEAT_HYPERV_EAX] |= HV_HYPERCALL_AVAILABLE;
|
||||
}
|
||||
if (cpu->hyperv_vapic) {
|
||||
env->features[FEAT_HYPERV_EAX] |= HV_X64_MSR_HYPERCALL_AVAILABLE;
|
||||
env->features[FEAT_HYPERV_EAX] |= HV_X64_MSR_APIC_ACCESS_AVAILABLE;
|
||||
env->features[FEAT_HYPERV_EAX] |= HV_HYPERCALL_AVAILABLE;
|
||||
env->features[FEAT_HYPERV_EAX] |= HV_APIC_ACCESS_AVAILABLE;
|
||||
}
|
||||
if (cpu->hyperv_time) {
|
||||
env->features[FEAT_HYPERV_EAX] |= HV_X64_MSR_HYPERCALL_AVAILABLE;
|
||||
env->features[FEAT_HYPERV_EAX] |= HV_X64_MSR_TIME_REF_COUNT_AVAILABLE;
|
||||
env->features[FEAT_HYPERV_EAX] |= 0x200;
|
||||
env->features[FEAT_HYPERV_EAX] |= HV_HYPERCALL_AVAILABLE;
|
||||
env->features[FEAT_HYPERV_EAX] |= HV_TIME_REF_COUNT_AVAILABLE;
|
||||
env->features[FEAT_HYPERV_EAX] |= HV_REFERENCE_TSC_AVAILABLE;
|
||||
|
||||
if (has_msr_hv_frequencies && tsc_is_stable_and_known(env)) {
|
||||
env->features[FEAT_HYPERV_EAX] |= HV_ACCESS_FREQUENCY_MSRS;
|
||||
env->features[FEAT_HYPERV_EDX] |= HV_FREQUENCY_MSRS_AVAILABLE;
|
||||
}
|
||||
}
|
||||
if (cpu->hyperv_crash && has_msr_hv_crash) {
|
||||
env->features[FEAT_HYPERV_EDX] |= HV_X64_GUEST_CRASH_MSR_AVAILABLE;
|
||||
env->features[FEAT_HYPERV_EDX] |= HV_GUEST_CRASH_MSR_AVAILABLE;
|
||||
}
|
||||
env->features[FEAT_HYPERV_EDX] |= HV_X64_CPU_DYNAMIC_PARTITIONING_AVAILABLE;
|
||||
env->features[FEAT_HYPERV_EDX] |= HV_CPU_DYNAMIC_PARTITIONING_AVAILABLE;
|
||||
if (cpu->hyperv_reset && has_msr_hv_reset) {
|
||||
env->features[FEAT_HYPERV_EAX] |= HV_X64_MSR_RESET_AVAILABLE;
|
||||
env->features[FEAT_HYPERV_EAX] |= HV_RESET_AVAILABLE;
|
||||
}
|
||||
if (cpu->hyperv_vpindex && has_msr_hv_vpindex) {
|
||||
env->features[FEAT_HYPERV_EAX] |= HV_X64_MSR_VP_INDEX_AVAILABLE;
|
||||
env->features[FEAT_HYPERV_EAX] |= HV_VP_INDEX_AVAILABLE;
|
||||
}
|
||||
if (cpu->hyperv_runtime && has_msr_hv_runtime) {
|
||||
env->features[FEAT_HYPERV_EAX] |= HV_X64_MSR_VP_RUNTIME_AVAILABLE;
|
||||
env->features[FEAT_HYPERV_EAX] |= HV_VP_RUNTIME_AVAILABLE;
|
||||
}
|
||||
if (cpu->hyperv_synic) {
|
||||
int sint;
|
||||
@ -655,10 +670,10 @@ static int hyperv_handle_properties(CPUState *cs)
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
env->features[FEAT_HYPERV_EAX] |= HV_X64_MSR_SYNIC_AVAILABLE;
|
||||
env->msr_hv_synic_version = HV_SYNIC_VERSION_1;
|
||||
env->features[FEAT_HYPERV_EAX] |= HV_SYNIC_AVAILABLE;
|
||||
env->msr_hv_synic_version = HV_SYNIC_VERSION;
|
||||
for (sint = 0; sint < ARRAY_SIZE(env->msr_hv_synic_sint); sint++) {
|
||||
env->msr_hv_synic_sint[sint] = HV_SYNIC_SINT_MASKED;
|
||||
env->msr_hv_synic_sint[sint] = HV_SINT_MASKED;
|
||||
}
|
||||
}
|
||||
if (cpu->hyperv_stimer) {
|
||||
@ -666,7 +681,7 @@ static int hyperv_handle_properties(CPUState *cs)
|
||||
fprintf(stderr, "Hyper-V timers aren't supported by kernel\n");
|
||||
return -ENOSYS;
|
||||
}
|
||||
env->features[FEAT_HYPERV_EAX] |= HV_X64_MSR_SYNTIMER_AVAILABLE;
|
||||
env->features[FEAT_HYPERV_EAX] |= HV_SYNTIMERS_AVAILABLE;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -695,10 +710,29 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
||||
|
||||
cpuid_i = 0;
|
||||
|
||||
r = kvm_arch_set_tsc_khz(cs);
|
||||
if (r < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* vcpu's TSC frequency is either specified by user, or following
|
||||
* the value used by KVM if the former is not present. In the
|
||||
* latter case, we query it from KVM and record in env->tsc_khz,
|
||||
* so that vcpu's TSC frequency can be migrated later via this field.
|
||||
*/
|
||||
if (!env->tsc_khz) {
|
||||
r = kvm_check_extension(cs->kvm_state, KVM_CAP_GET_TSC_KHZ) ?
|
||||
kvm_vcpu_ioctl(cs, KVM_GET_TSC_KHZ) :
|
||||
-ENOTSUP;
|
||||
if (r > 0) {
|
||||
env->tsc_khz = r;
|
||||
}
|
||||
}
|
||||
|
||||
/* Paravirtualization CPUIDs */
|
||||
if (hyperv_enabled(cpu)) {
|
||||
c = &cpuid_data.entries[cpuid_i++];
|
||||
c->function = HYPERV_CPUID_VENDOR_AND_MAX_FUNCTIONS;
|
||||
c->function = HV_CPUID_VENDOR_AND_MAX_FUNCTIONS;
|
||||
if (!cpu->hyperv_vendor_id) {
|
||||
memcpy(signature, "Microsoft Hv", 12);
|
||||
} else {
|
||||
@ -711,13 +745,13 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
||||
memset(signature, 0, 12);
|
||||
memcpy(signature, cpu->hyperv_vendor_id, len);
|
||||
}
|
||||
c->eax = HYPERV_CPUID_MIN;
|
||||
c->eax = HV_CPUID_MIN;
|
||||
c->ebx = signature[0];
|
||||
c->ecx = signature[1];
|
||||
c->edx = signature[2];
|
||||
|
||||
c = &cpuid_data.entries[cpuid_i++];
|
||||
c->function = HYPERV_CPUID_INTERFACE;
|
||||
c->function = HV_CPUID_INTERFACE;
|
||||
memcpy(signature, "Hv#1\0\0\0\0\0\0\0\0", 12);
|
||||
c->eax = signature[0];
|
||||
c->ebx = 0;
|
||||
@ -725,12 +759,12 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
||||
c->edx = 0;
|
||||
|
||||
c = &cpuid_data.entries[cpuid_i++];
|
||||
c->function = HYPERV_CPUID_VERSION;
|
||||
c->function = HV_CPUID_VERSION;
|
||||
c->eax = 0x00001bbc;
|
||||
c->ebx = 0x00060001;
|
||||
|
||||
c = &cpuid_data.entries[cpuid_i++];
|
||||
c->function = HYPERV_CPUID_FEATURES;
|
||||
c->function = HV_CPUID_FEATURES;
|
||||
r = hyperv_handle_properties(cs);
|
||||
if (r) {
|
||||
return r;
|
||||
@ -740,18 +774,19 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
||||
c->edx = env->features[FEAT_HYPERV_EDX];
|
||||
|
||||
c = &cpuid_data.entries[cpuid_i++];
|
||||
c->function = HYPERV_CPUID_ENLIGHTMENT_INFO;
|
||||
c->function = HV_CPUID_ENLIGHTMENT_INFO;
|
||||
if (cpu->hyperv_relaxed_timing) {
|
||||
c->eax |= HV_X64_RELAXED_TIMING_RECOMMENDED;
|
||||
c->eax |= HV_RELAXED_TIMING_RECOMMENDED;
|
||||
}
|
||||
if (cpu->hyperv_vapic) {
|
||||
c->eax |= HV_X64_APIC_ACCESS_RECOMMENDED;
|
||||
c->eax |= HV_APIC_ACCESS_RECOMMENDED;
|
||||
}
|
||||
c->ebx = cpu->hyperv_spinlock_attempts;
|
||||
|
||||
c = &cpuid_data.entries[cpuid_i++];
|
||||
c->function = HYPERV_CPUID_IMPLEMENT_LIMITS;
|
||||
c->eax = 0x40;
|
||||
c->function = HV_CPUID_IMPLEMENT_LIMITS;
|
||||
|
||||
c->eax = cpu->hv_max_vps;
|
||||
c->ebx = 0x40;
|
||||
|
||||
kvm_base = KVM_CPUID_SIGNATURE_NEXT;
|
||||
@ -961,34 +996,13 @@ int kvm_arch_init_vcpu(CPUState *cs)
|
||||
}
|
||||
}
|
||||
|
||||
r = kvm_arch_set_tsc_khz(cs);
|
||||
if (r < 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* vcpu's TSC frequency is either specified by user, or following
|
||||
* the value used by KVM if the former is not present. In the
|
||||
* latter case, we query it from KVM and record in env->tsc_khz,
|
||||
* so that vcpu's TSC frequency can be migrated later via this field.
|
||||
*/
|
||||
if (!env->tsc_khz) {
|
||||
r = kvm_check_extension(cs->kvm_state, KVM_CAP_GET_TSC_KHZ) ?
|
||||
kvm_vcpu_ioctl(cs, KVM_GET_TSC_KHZ) :
|
||||
-ENOTSUP;
|
||||
if (r > 0) {
|
||||
env->tsc_khz = r;
|
||||
}
|
||||
}
|
||||
|
||||
if (cpu->vmware_cpuid_freq
|
||||
/* Guests depend on 0x40000000 to detect this feature, so only expose
|
||||
* it if KVM exposes leaf 0x40000000. (Conflicts with Hyper-V) */
|
||||
&& cpu->expose_kvm
|
||||
&& kvm_base == KVM_CPUID_SIGNATURE
|
||||
/* TSC clock must be stable and known for this feature. */
|
||||
&& ((env->features[FEAT_8000_0007_EDX] & CPUID_APM_INVTSC)
|
||||
|| env->user_tsc_khz != 0)
|
||||
&& env->tsc_khz != 0) {
|
||||
&& tsc_is_stable_and_known(env)) {
|
||||
|
||||
c = &cpuid_data.entries[cpuid_i++];
|
||||
c->function = KVM_CPUID_SIGNATURE | 0x10;
|
||||
@ -1081,65 +1095,55 @@ static int kvm_get_supported_msrs(KVMState *s)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < kvm_msr_list->nmsrs; i++) {
|
||||
if (kvm_msr_list->indices[i] == MSR_STAR) {
|
||||
switch (kvm_msr_list->indices[i]) {
|
||||
case MSR_STAR:
|
||||
has_msr_star = true;
|
||||
continue;
|
||||
}
|
||||
if (kvm_msr_list->indices[i] == MSR_VM_HSAVE_PA) {
|
||||
break;
|
||||
case MSR_VM_HSAVE_PA:
|
||||
has_msr_hsave_pa = true;
|
||||
continue;
|
||||
}
|
||||
if (kvm_msr_list->indices[i] == MSR_TSC_AUX) {
|
||||
break;
|
||||
case MSR_TSC_AUX:
|
||||
has_msr_tsc_aux = true;
|
||||
continue;
|
||||
}
|
||||
if (kvm_msr_list->indices[i] == MSR_TSC_ADJUST) {
|
||||
break;
|
||||
case MSR_TSC_ADJUST:
|
||||
has_msr_tsc_adjust = true;
|
||||
continue;
|
||||
}
|
||||
if (kvm_msr_list->indices[i] == MSR_IA32_TSCDEADLINE) {
|
||||
break;
|
||||
case MSR_IA32_TSCDEADLINE:
|
||||
has_msr_tsc_deadline = true;
|
||||
continue;
|
||||
}
|
||||
if (kvm_msr_list->indices[i] == MSR_IA32_SMBASE) {
|
||||
break;
|
||||
case MSR_IA32_SMBASE:
|
||||
has_msr_smbase = true;
|
||||
continue;
|
||||
}
|
||||
if (kvm_msr_list->indices[i] == MSR_IA32_MISC_ENABLE) {
|
||||
break;
|
||||
case MSR_IA32_MISC_ENABLE:
|
||||
has_msr_misc_enable = true;
|
||||
continue;
|
||||
}
|
||||
if (kvm_msr_list->indices[i] == MSR_IA32_BNDCFGS) {
|
||||
break;
|
||||
case MSR_IA32_BNDCFGS:
|
||||
has_msr_bndcfgs = true;
|
||||
continue;
|
||||
}
|
||||
if (kvm_msr_list->indices[i] == MSR_IA32_XSS) {
|
||||
break;
|
||||
case MSR_IA32_XSS:
|
||||
has_msr_xss = true;
|
||||
continue;
|
||||
}
|
||||
if (kvm_msr_list->indices[i] == HV_X64_MSR_CRASH_CTL) {
|
||||
break;;
|
||||
case HV_X64_MSR_CRASH_CTL:
|
||||
has_msr_hv_crash = true;
|
||||
continue;
|
||||
}
|
||||
if (kvm_msr_list->indices[i] == HV_X64_MSR_RESET) {
|
||||
break;
|
||||
case HV_X64_MSR_RESET:
|
||||
has_msr_hv_reset = true;
|
||||
continue;
|
||||
}
|
||||
if (kvm_msr_list->indices[i] == HV_X64_MSR_VP_INDEX) {
|
||||
break;
|
||||
case HV_X64_MSR_VP_INDEX:
|
||||
has_msr_hv_vpindex = true;
|
||||
continue;
|
||||
}
|
||||
if (kvm_msr_list->indices[i] == HV_X64_MSR_VP_RUNTIME) {
|
||||
break;
|
||||
case HV_X64_MSR_VP_RUNTIME:
|
||||
has_msr_hv_runtime = true;
|
||||
continue;
|
||||
}
|
||||
if (kvm_msr_list->indices[i] == HV_X64_MSR_SCONTROL) {
|
||||
break;
|
||||
case HV_X64_MSR_SCONTROL:
|
||||
has_msr_hv_synic = true;
|
||||
continue;
|
||||
}
|
||||
if (kvm_msr_list->indices[i] == HV_X64_MSR_STIMER0_CONFIG) {
|
||||
break;
|
||||
case HV_X64_MSR_STIMER0_CONFIG:
|
||||
has_msr_hv_stimer = true;
|
||||
continue;
|
||||
break;
|
||||
case HV_X64_MSR_TSC_FREQUENCY:
|
||||
has_msr_hv_frequencies = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1690,12 +1694,11 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
|
||||
if (has_msr_hv_crash) {
|
||||
int j;
|
||||
|
||||
for (j = 0; j < HV_X64_MSR_CRASH_PARAMS; j++)
|
||||
for (j = 0; j < HV_CRASH_PARAMS; j++)
|
||||
kvm_msr_entry_add(cpu, HV_X64_MSR_CRASH_P0 + j,
|
||||
env->msr_hv_crash_params[j]);
|
||||
|
||||
kvm_msr_entry_add(cpu, HV_X64_MSR_CRASH_CTL,
|
||||
HV_X64_MSR_CRASH_CTL_NOTIFY);
|
||||
kvm_msr_entry_add(cpu, HV_X64_MSR_CRASH_CTL, HV_CRASH_CTL_NOTIFY);
|
||||
}
|
||||
if (has_msr_hv_runtime) {
|
||||
kvm_msr_entry_add(cpu, HV_X64_MSR_VP_RUNTIME, env->msr_hv_runtime);
|
||||
@ -2059,7 +2062,7 @@ static int kvm_get_msrs(X86CPU *cpu)
|
||||
if (has_msr_hv_crash) {
|
||||
int j;
|
||||
|
||||
for (j = 0; j < HV_X64_MSR_CRASH_PARAMS; j++) {
|
||||
for (j = 0; j < HV_CRASH_PARAMS; j++) {
|
||||
kvm_msr_entry_add(cpu, HV_X64_MSR_CRASH_P0 + j, 0);
|
||||
}
|
||||
}
|
||||
|
@ -587,7 +587,7 @@ static bool hyperv_crash_enable_needed(void *opaque)
|
||||
CPUX86State *env = &cpu->env;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < HV_X64_MSR_CRASH_PARAMS; i++) {
|
||||
for (i = 0; i < HV_CRASH_PARAMS; i++) {
|
||||
if (env->msr_hv_crash_params[i]) {
|
||||
return true;
|
||||
}
|
||||
@ -601,8 +601,7 @@ static const VMStateDescription vmstate_msr_hyperv_crash = {
|
||||
.minimum_version_id = 1,
|
||||
.needed = hyperv_crash_enable_needed,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT64_ARRAY(env.msr_hv_crash_params,
|
||||
X86CPU, HV_X64_MSR_CRASH_PARAMS),
|
||||
VMSTATE_UINT64_ARRAY(env.msr_hv_crash_params, X86CPU, HV_CRASH_PARAMS),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
@ -660,8 +659,7 @@ static const VMStateDescription vmstate_msr_hyperv_synic = {
|
||||
VMSTATE_UINT64(env.msr_hv_synic_control, X86CPU),
|
||||
VMSTATE_UINT64(env.msr_hv_synic_evt_page, X86CPU),
|
||||
VMSTATE_UINT64(env.msr_hv_synic_msg_page, X86CPU),
|
||||
VMSTATE_UINT64_ARRAY(env.msr_hv_synic_sint, X86CPU,
|
||||
HV_SYNIC_SINT_COUNT),
|
||||
VMSTATE_UINT64_ARRAY(env.msr_hv_synic_sint, X86CPU, HV_SINT_COUNT),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
@ -686,10 +684,9 @@ static const VMStateDescription vmstate_msr_hyperv_stimer = {
|
||||
.minimum_version_id = 1,
|
||||
.needed = hyperv_stimer_enable_needed,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT64_ARRAY(env.msr_hv_stimer_config,
|
||||
X86CPU, HV_SYNIC_STIMER_COUNT),
|
||||
VMSTATE_UINT64_ARRAY(env.msr_hv_stimer_count,
|
||||
X86CPU, HV_SYNIC_STIMER_COUNT),
|
||||
VMSTATE_UINT64_ARRAY(env.msr_hv_stimer_config, X86CPU,
|
||||
HV_STIMER_COUNT),
|
||||
VMSTATE_UINT64_ARRAY(env.msr_hv_stimer_count, X86CPU, HV_STIMER_COUNT),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
@ -447,7 +447,7 @@ static void mem_info_la57(Monitor *mon, CPUArchState *env)
|
||||
start = -1;
|
||||
for (l0 = 0; l0 < 512; l0++) {
|
||||
cpu_physical_memory_read(pml5_addr + l0 * 8, &pml5e, 8);
|
||||
pml4e = le64_to_cpu(pml5e);
|
||||
pml5e = le64_to_cpu(pml5e);
|
||||
end = l0 << 48;
|
||||
if (!(pml5e & PG_PRESENT_MASK)) {
|
||||
prot = 0;
|
||||
@ -480,7 +480,7 @@ static void mem_info_la57(Monitor *mon, CPUArchState *env)
|
||||
if (pdpe & PG_PSE_MASK) {
|
||||
prot = pdpe & (PG_USER_MASK | PG_RW_MASK |
|
||||
PG_PRESENT_MASK);
|
||||
prot &= pml4e;
|
||||
prot &= pml5e & pml4e;
|
||||
mem_print(mon, &start, &last_prot, end, prot);
|
||||
continue;
|
||||
}
|
||||
@ -499,7 +499,7 @@ static void mem_info_la57(Monitor *mon, CPUArchState *env)
|
||||
if (pde & PG_PSE_MASK) {
|
||||
prot = pde & (PG_USER_MASK | PG_RW_MASK |
|
||||
PG_PRESENT_MASK);
|
||||
prot &= pml4e & pdpe;
|
||||
prot &= pml5e & pml4e & pdpe;
|
||||
mem_print(mon, &start, &last_prot, end, prot);
|
||||
continue;
|
||||
}
|
||||
@ -513,7 +513,7 @@ static void mem_info_la57(Monitor *mon, CPUArchState *env)
|
||||
if (pte & PG_PRESENT_MASK) {
|
||||
prot = pte & (PG_USER_MASK | PG_RW_MASK |
|
||||
PG_PRESENT_MASK);
|
||||
prot &= pml4e & pdpe & pde;
|
||||
prot &= pml5e & pml4e & pdpe & pde;
|
||||
} else {
|
||||
prot = 0;
|
||||
}
|
||||
|
@ -1617,18 +1617,18 @@ void glue(helper_ptest, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)
|
||||
#define SSE_HELPER_F(name, elem, num, F) \
|
||||
void glue(name, SUFFIX)(CPUX86State *env, Reg *d, Reg *s) \
|
||||
{ \
|
||||
d->elem(0) = F(0); \
|
||||
d->elem(1) = F(1); \
|
||||
if (num > 2) { \
|
||||
d->elem(2) = F(2); \
|
||||
d->elem(3) = F(3); \
|
||||
if (num > 4) { \
|
||||
d->elem(4) = F(4); \
|
||||
d->elem(5) = F(5); \
|
||||
d->elem(6) = F(6); \
|
||||
d->elem(7) = F(7); \
|
||||
d->elem(6) = F(6); \
|
||||
d->elem(5) = F(5); \
|
||||
d->elem(4) = F(4); \
|
||||
} \
|
||||
d->elem(3) = F(3); \
|
||||
d->elem(2) = F(2); \
|
||||
} \
|
||||
d->elem(1) = F(1); \
|
||||
d->elem(0) = F(0); \
|
||||
}
|
||||
|
||||
SSE_HELPER_F(helper_pmovsxbw, W, 8, (int8_t) s->B)
|
||||
@ -1655,14 +1655,17 @@ SSE_HELPER_Q(helper_pcmpeqq, FCMPEQQ)
|
||||
|
||||
void glue(helper_packusdw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)
|
||||
{
|
||||
d->W(0) = satuw((int32_t) d->L(0));
|
||||
d->W(1) = satuw((int32_t) d->L(1));
|
||||
d->W(2) = satuw((int32_t) d->L(2));
|
||||
d->W(3) = satuw((int32_t) d->L(3));
|
||||
d->W(4) = satuw((int32_t) s->L(0));
|
||||
d->W(5) = satuw((int32_t) s->L(1));
|
||||
d->W(6) = satuw((int32_t) s->L(2));
|
||||
d->W(7) = satuw((int32_t) s->L(3));
|
||||
Reg r;
|
||||
|
||||
r.W(0) = satuw((int32_t) d->L(0));
|
||||
r.W(1) = satuw((int32_t) d->L(1));
|
||||
r.W(2) = satuw((int32_t) d->L(2));
|
||||
r.W(3) = satuw((int32_t) d->L(3));
|
||||
r.W(4) = satuw((int32_t) s->L(0));
|
||||
r.W(5) = satuw((int32_t) s->L(1));
|
||||
r.W(6) = satuw((int32_t) s->L(2));
|
||||
r.W(7) = satuw((int32_t) s->L(3));
|
||||
*d = r;
|
||||
}
|
||||
|
||||
#define FMINSB(d, s) MIN((int8_t)d, (int8_t)s)
|
||||
@ -1707,10 +1710,10 @@ void glue(helper_phminposuw, SUFFIX)(CPUX86State *env, Reg *d, Reg *s)
|
||||
idx = 7;
|
||||
}
|
||||
|
||||
d->Q(1) = 0;
|
||||
d->L(1) = 0;
|
||||
d->W(1) = idx;
|
||||
d->W(0) = s->W(idx);
|
||||
d->W(1) = idx;
|
||||
d->L(1) = 0;
|
||||
d->Q(1) = 0;
|
||||
}
|
||||
|
||||
void glue(helper_roundps, SUFFIX)(CPUX86State *env, Reg *d, Reg *s,
|
||||
@ -2037,10 +2040,14 @@ static inline unsigned pcmpxstrx(CPUX86State *env, Reg *d, Reg *s,
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
for (j = valids; j >= 0; j--) {
|
||||
if (validd == -1) {
|
||||
res = (2 << upper) - 1;
|
||||
break;
|
||||
}
|
||||
for (j = valids - validd; j >= 0; j--) {
|
||||
res <<= 1;
|
||||
v = 1;
|
||||
for (i = MIN(valids - j, validd); i >= 0; i--) {
|
||||
for (i = validd; i >= 0; i--) {
|
||||
v &= (pcmp_val(s, ctrl, i + j) == pcmp_val(d, ctrl, i));
|
||||
}
|
||||
res |= v;
|
||||
|
@ -4076,10 +4076,11 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
|
||||
if (!(s->cpuid_ext_features & sse_op_table7[b].ext_mask))
|
||||
goto illegal_op;
|
||||
|
||||
s->rip_offset = 1;
|
||||
|
||||
if (sse_fn_eppi == SSE_SPECIAL) {
|
||||
ot = mo_64_32(s->dflag);
|
||||
rm = (modrm & 7) | REX_B(s);
|
||||
s->rip_offset = 1;
|
||||
if (mod != 3)
|
||||
gen_lea_modrm(env, s, modrm);
|
||||
reg = ((modrm >> 3) & 7) | rex_r;
|
||||
|
@ -95,11 +95,11 @@ void kvm_mips_reset_vcpu(MIPSCPU *cpu)
|
||||
CPUMIPSState *env = &cpu->env;
|
||||
|
||||
if (!kvm_mips_fpu_cap && env->CP0_Config1 & (1 << CP0C1_FP)) {
|
||||
fprintf(stderr, "Warning: KVM does not support FPU, disabling\n");
|
||||
warn_report("KVM does not support FPU, disabling");
|
||||
env->CP0_Config1 &= ~(1 << CP0C1_FP);
|
||||
}
|
||||
if (!kvm_mips_msa_cap && env->CP0_Config3 & (1 << CP0C3_MSAP)) {
|
||||
fprintf(stderr, "Warning: KVM does not support MSA, disabling\n");
|
||||
warn_report("KVM does not support MSA, disabling");
|
||||
env->CP0_Config3 &= ~(1 << CP0C3_MSAP);
|
||||
}
|
||||
|
||||
@ -526,7 +526,7 @@ static void kvm_mips_update_state(void *opaque, int running, RunState state)
|
||||
if (!cs->vcpu_dirty) {
|
||||
ret = kvm_mips_save_count(cs);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Failed saving count\n");
|
||||
warn_report("Failed saving count");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -535,14 +535,14 @@ static void kvm_mips_update_state(void *opaque, int running, RunState state)
|
||||
ret = kvm_mips_put_one_ureg64(cs, KVM_REG_MIPS_COUNT_RESUME,
|
||||
&count_resume);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Failed setting COUNT_RESUME\n");
|
||||
warn_report("Failed setting COUNT_RESUME");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cs->vcpu_dirty) {
|
||||
ret = kvm_mips_restore_count(cs);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Failed restoring count\n");
|
||||
warn_report("Failed restoring count");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9316,14 +9316,13 @@ static void init_ppc_proc(PowerPCCPU *cpu)
|
||||
env->tlb_per_way = env->nb_tlb / env->nb_ways;
|
||||
}
|
||||
if (env->irq_inputs == NULL) {
|
||||
fprintf(stderr, "WARNING: no internal IRQ controller registered.\n"
|
||||
" Attempt QEMU to crash very soon !\n");
|
||||
warn_report("no internal IRQ controller registered."
|
||||
" Attempt QEMU to crash very soon !");
|
||||
}
|
||||
#endif
|
||||
if (env->check_pow == NULL) {
|
||||
fprintf(stderr, "WARNING: no power management check handler "
|
||||
"registered.\n"
|
||||
" Attempt QEMU to crash very soon !\n");
|
||||
warn_report("no power management check handler registered."
|
||||
" Attempt QEMU to crash very soon !");
|
||||
}
|
||||
}
|
||||
|
||||
@ -9877,8 +9876,8 @@ static int ppc_fixup_cpu(PowerPCCPU *cpu)
|
||||
* tree. */
|
||||
if ((env->insns_flags & ~PPC_TCG_INSNS)
|
||||
|| (env->insns_flags2 & ~PPC_TCG_INSNS2)) {
|
||||
fprintf(stderr, "Warning: Disabling some instructions which are not "
|
||||
"emulated by TCG (0x%" PRIx64 ", 0x%" PRIx64 ")\n",
|
||||
warn_report("Disabling some instructions which are not "
|
||||
"emulated by TCG (0x%" PRIx64 ", 0x%" PRIx64 ")",
|
||||
env->insns_flags & ~PPC_TCG_INSNS,
|
||||
env->insns_flags2 & ~PPC_TCG_INSNS2);
|
||||
}
|
||||
|
@ -224,8 +224,8 @@ static void kvm_s390_enable_cmma(void)
|
||||
};
|
||||
|
||||
if (mem_path) {
|
||||
error_report("Warning: CMM will not be enabled because it is not "
|
||||
"compatible to hugetlbfs.");
|
||||
warn_report("CMM will not be enabled because it is not "
|
||||
"compatible with hugetlbfs.");
|
||||
return;
|
||||
}
|
||||
rc = kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, &attr);
|
||||
|
@ -561,7 +561,7 @@ QEMU_CFLAGS += -I$(SRC_PATH)/tests
|
||||
|
||||
|
||||
# Deps that are common to various different sets of tests below
|
||||
test-util-obj-y = libqemuutil.a libqemustub.a
|
||||
test-util-obj-y = libqemuutil.a
|
||||
test-qom-obj-y = $(qom-obj-y) $(test-util-obj-y)
|
||||
test-qapi-obj-y = tests/test-qapi-visit.o tests/test-qapi-types.o \
|
||||
tests/test-qapi-event.o tests/test-qmp-introspect.o \
|
||||
@ -593,7 +593,7 @@ tests/test-iov$(EXESUF): tests/test-iov.o $(test-util-obj-y)
|
||||
tests/test-hbitmap$(EXESUF): tests/test-hbitmap.o $(test-util-obj-y) $(test-crypto-obj-y)
|
||||
tests/test-x86-cpuid$(EXESUF): tests/test-x86-cpuid.o
|
||||
tests/test-xbzrle$(EXESUF): tests/test-xbzrle.o migration/xbzrle.o migration/page_cache.o $(test-util-obj-y)
|
||||
tests/test-cutils$(EXESUF): tests/test-cutils.o util/cutils.o
|
||||
tests/test-cutils$(EXESUF): tests/test-cutils.o util/cutils.o $(test-util-obj-y)
|
||||
tests/test-int128$(EXESUF): tests/test-int128.o
|
||||
tests/rcutorture$(EXESUF): tests/rcutorture.o $(test-util-obj-y)
|
||||
tests/test-rcu-list$(EXESUF): tests/test-rcu-list.o $(test-util-obj-y)
|
||||
@ -616,9 +616,8 @@ tests/test-vmstate$(EXESUF): tests/test-vmstate.o \
|
||||
migration/qemu-file-channel.o migration/qjson.o \
|
||||
$(test-io-obj-y)
|
||||
tests/test-timed-average$(EXESUF): tests/test-timed-average.o $(test-util-obj-y)
|
||||
tests/test-base64$(EXESUF): tests/test-base64.o \
|
||||
libqemuutil.a libqemustub.a
|
||||
tests/ptimer-test$(EXESUF): tests/ptimer-test.o tests/ptimer-test-stubs.o hw/core/ptimer.o libqemustub.a
|
||||
tests/test-base64$(EXESUF): tests/test-base64.o $(test-util-obj-y)
|
||||
tests/ptimer-test$(EXESUF): tests/ptimer-test.o tests/ptimer-test-stubs.o hw/core/ptimer.o
|
||||
|
||||
tests/test-logging$(EXESUF): tests/test-logging.o $(test-util-obj-y)
|
||||
|
||||
@ -832,7 +831,8 @@ endif
|
||||
qtest-obj-y = tests/libqtest.o $(test-util-obj-y)
|
||||
$(check-qtest-y): $(qtest-obj-y)
|
||||
|
||||
tests/test-qga: tests/test-qga.o $(qtest-obj-y)
|
||||
tests/test-qga$(EXESUF): qemu-ga$(EXESUF)
|
||||
tests/test-qga$(EXESUF): tests/test-qga.o $(qtest-obj-y)
|
||||
|
||||
SPEED = quick
|
||||
GTESTER_OPTIONS = -k $(if $(V),--verbose,-q)
|
||||
|
@ -34,7 +34,6 @@ $(DOCKER_SRC_COPY):
|
||||
@mkdir $@
|
||||
$(call make-archive-maybe, $(SRC_PATH), $@/qemu.tgz)
|
||||
$(call make-archive-maybe, $(SRC_PATH)/dtc, $@/dtc.tgz)
|
||||
$(call make-archive-maybe, $(SRC_PATH)/pixman, $@/pixman.tgz)
|
||||
$(call quiet-command, cp $(SRC_PATH)/tests/docker/run $@/run, \
|
||||
"COPY","RUNNER")
|
||||
|
||||
|
@ -30,6 +30,10 @@ QEMUTimerListGroup main_loop_tlg;
|
||||
|
||||
int64_t ptimer_test_time_ns;
|
||||
|
||||
/* Do not artificially limit period - see hw/core/ptimer.c. */
|
||||
int use_icount = 1;
|
||||
bool qtest_allowed;
|
||||
|
||||
void timer_init_tl(QEMUTimer *ts,
|
||||
QEMUTimerList *timer_list, int scale,
|
||||
QEMUTimerCB *cb, void *opaque)
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "libqtest.h"
|
||||
#include "block/scsi.h"
|
||||
#include "scsi/constants.h"
|
||||
#include "libqos/libqos-pc.h"
|
||||
#include "libqos/libqos-spapr.h"
|
||||
#include "libqos/virtio.h"
|
||||
|
@ -72,7 +72,7 @@ void trace_event_register_group(TraceEvent **events)
|
||||
if (likely(next_vcpu_id < CPU_TRACE_DSTATE_MAX_EVENTS)) {
|
||||
events[i]->vcpu_id = next_vcpu_id++;
|
||||
} else {
|
||||
error_report("WARNING: too many vcpu trace events; dropping '%s'",
|
||||
warn_report("too many vcpu trace events; dropping '%s'",
|
||||
events[i]->name);
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "qemu/timer.h"
|
||||
#include "trace/control.h"
|
||||
#include "trace/simple.h"
|
||||
#include "qemu/error-report.h"
|
||||
|
||||
/** Trace file header event ID, picked to avoid conflict with real event IDs */
|
||||
#define HEADER_EVENT_ID (~(uint64_t)0)
|
||||
@ -405,7 +406,7 @@ bool st_init(void)
|
||||
|
||||
thread = trace_thread_create(writeout_thread);
|
||||
if (!thread) {
|
||||
fprintf(stderr, "warning: unable to initialize simple trace backend\n");
|
||||
warn_report("unable to initialize simple trace backend");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
10
ui/keymaps.c
10
ui/keymaps.c
@ -26,6 +26,7 @@
|
||||
#include "keymaps.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "trace.h"
|
||||
#include "qemu/error-report.h"
|
||||
|
||||
static int get_keysym(const name2keysym_t *table,
|
||||
const char *name)
|
||||
@ -76,8 +77,8 @@ static void add_keysym(char *line, int keysym, int keycode, kbd_layout_t *k) {
|
||||
k->keysym2keycode[keysym] = keycode;
|
||||
} else {
|
||||
if (k->extra_count >= MAX_EXTRA_COUNT) {
|
||||
fprintf(stderr, "Warning: Could not assign keysym %s (0x%x)"
|
||||
" because of memory constraints.\n", line, keysym);
|
||||
warn_report("Could not assign keysym %s (0x%x)"
|
||||
" because of memory constraints.", line, keysym);
|
||||
} else {
|
||||
trace_keymap_add("extra", keysym, keycode, line);
|
||||
k->keysym2keycode_extra[k->extra_count].
|
||||
@ -141,7 +142,7 @@ static kbd_layout_t *parse_keyboard_layout(const name2keysym_t *table,
|
||||
int keysym;
|
||||
keysym = get_keysym(table, keyname);
|
||||
if (keysym == 0) {
|
||||
/* fprintf(stderr, "Warning: unknown keysym %s\n", line);*/
|
||||
/* warn_report("unknown keysym %s", line);*/
|
||||
} else {
|
||||
const char *rest = line + offset + 1;
|
||||
int keycode = strtol(rest, NULL, 0);
|
||||
@ -197,8 +198,7 @@ int keysym2scancode(void *kbd_layout, int keysym)
|
||||
if (keysym < MAX_NORMAL_KEYCODE) {
|
||||
if (k->keysym2keycode[keysym] == 0) {
|
||||
trace_keymap_unmapped(keysym);
|
||||
fprintf(stderr, "Warning: no scancode found for keysym %d\n",
|
||||
keysym);
|
||||
warn_report("no scancode found for keysym %d", keysym);
|
||||
}
|
||||
return k->keysym2keycode[keysym];
|
||||
} else {
|
||||
|
@ -850,7 +850,7 @@ static void qemu_spice_gl_unblock_bh(void *opaque)
|
||||
|
||||
static void qemu_spice_gl_block_timer(void *opaque)
|
||||
{
|
||||
fprintf(stderr, "WARNING: spice: no gl-draw-done within one second\n");
|
||||
warn_report("spice: no gl-draw-done within one second");
|
||||
}
|
||||
|
||||
static void spice_gl_refresh(DisplayChangeListener *dcl)
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "qemu/iov.h"
|
||||
#include "net/net.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qemu/error-report.h"
|
||||
|
||||
void strpadcpy(char *buf, int buf_size, const char *str, char pad)
|
||||
{
|
||||
@ -601,7 +602,7 @@ int parse_debug_env(const char *name, int max, int initial)
|
||||
return initial;
|
||||
}
|
||||
if (debug < 0 || debug > max || errno != 0) {
|
||||
fprintf(stderr, "warning: %s not in [0, %d]", name, max);
|
||||
warn_report("%s not in [0, %d]", name, max);
|
||||
return initial;
|
||||
}
|
||||
return debug;
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "slirp/libslirp.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "block/aio.h"
|
||||
#include "qemu/error-report.h"
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
@ -236,8 +237,7 @@ static int os_host_main_loop_wait(int64_t timeout)
|
||||
static bool notified;
|
||||
|
||||
if (!notified && !qtest_enabled() && !qtest_driver()) {
|
||||
fprintf(stderr,
|
||||
"main-loop: WARNING: I/O thread spun for %d iterations\n",
|
||||
warn_report("I/O thread spun for %d iterations",
|
||||
MAX_MAIN_LOOP_SPIN);
|
||||
notified = true;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user