The last round of patches for soft freeze. Includes ivshmem bugfixes,
megasas 2108 emulation, and other small patches here and there. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQEcBAABAgAGBQJUU8RCAAoJEL/70l94x66Dvh0H/3CMdRSk9UugaHxn+VeSqGdz Z5KQpvUqZts03hISrFATOG9XZGTnsxuVtzGuR+kpW4luQXd4x4dv/pFIiS43FWNr hGKckxLsSYLM57eh5pUbRfoIAYwa+txe/PnCa1GGSyrEbBe6isF39LrZnkCEJWNc yEF4nIwTJqAAkvqgXv6SWzINr9vKUYHlGG2a6I2pSM3pofL3Pe8dr5Lg2rXCU3QS Petn3Xj45oKhQGX9mBrfFQR9xeJ/Uq1chF5GpIYWPqpeSFmHd7A6gW+cpGMN+RlT OG8JnOwWBxQ26ZOjS6Ek52RiDCr4fsEWmbrwYRYz1D5hi9jSnpOYxipj1kSOG5k= =479x -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging The last round of patches for soft freeze. Includes ivshmem bugfixes, megasas 2108 emulation, and other small patches here and there. # gpg: Signature made Fri 31 Oct 2014 17:17:54 GMT using RSA key ID 78C7AE83 # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" # gpg: WARNING: This key is not certified with sufficiently trusted signatures! # gpg: It is not certain that the signature belongs to the owner. # 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: (35 commits) virtio-scsi: fix dataplane ivshmem: use error_report ivshmem: Fix fd leak on error ivshmem: Fix potential OOB r/w access ivshmem: validate incoming_posn value from server ivshmem: Check ivshmem_read() size argument i386: fix breakpoints handling in icount mode kvm_stat: Add powerpc support kvm_stat: Abstract ioctl numbers kvm_stat: Rework platform detection kvm_stat: Fix the non-x86 exit reasons kvm_stat: Only consider online cpus virtio-scsi: Fix num_queue input validation scsi: devirtualize unrealize of SCSI devices virtio-scsi: Fix memory leak when realize failed iscsi: Refuse to open as writable if the LUN is write protected kvmvapic: patch_instruction fix vl.c: Fix Coverity complaining for vmstate_dump_file Add skip_dump flag to ignore memory region during dump -machine vmport=off: Allow disabling of VMWare ioport emulation ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
f67d23b1ae
@ -1219,6 +1219,40 @@ static void iscsi_attach_aio_context(BlockDriverState *bs,
|
||||
qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + NOP_INTERVAL);
|
||||
}
|
||||
|
||||
static bool iscsi_is_write_protected(IscsiLun *iscsilun)
|
||||
{
|
||||
struct scsi_task *task;
|
||||
struct scsi_mode_sense *ms = NULL;
|
||||
bool wrprotected = false;
|
||||
|
||||
task = iscsi_modesense6_sync(iscsilun->iscsi, iscsilun->lun,
|
||||
1, SCSI_MODESENSE_PC_CURRENT,
|
||||
0x3F, 0, 255);
|
||||
if (task == NULL) {
|
||||
error_report("iSCSI: Failed to send MODE_SENSE(6) command: %s",
|
||||
iscsi_get_error(iscsilun->iscsi));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (task->status != SCSI_STATUS_GOOD) {
|
||||
error_report("iSCSI: Failed MODE_SENSE(6), LUN assumed writable");
|
||||
goto out;
|
||||
}
|
||||
ms = scsi_datain_unmarshall(task);
|
||||
if (!ms) {
|
||||
error_report("iSCSI: Failed to unmarshall MODE_SENSE(6) data: %s",
|
||||
iscsi_get_error(iscsilun->iscsi));
|
||||
goto out;
|
||||
}
|
||||
wrprotected = ms->device_specific_parameter & 0x80;
|
||||
|
||||
out:
|
||||
if (task) {
|
||||
scsi_free_scsi_task(task);
|
||||
}
|
||||
return wrprotected;
|
||||
}
|
||||
|
||||
/*
|
||||
* We support iscsi url's on the form
|
||||
* iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun>
|
||||
@ -1339,6 +1373,14 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
|
||||
scsi_free_scsi_task(task);
|
||||
task = NULL;
|
||||
|
||||
/* Check the write protect flag of the LUN if we want to write */
|
||||
if (iscsilun->type == TYPE_DISK && (flags & BDRV_O_RDWR) &&
|
||||
iscsi_is_write_protected(iscsilun)) {
|
||||
error_setg(errp, "Cannot open a write protected LUN as read-write");
|
||||
ret = -EACCES;
|
||||
goto out;
|
||||
}
|
||||
|
||||
iscsi_readcapacity_sync(iscsilun, &local_err);
|
||||
if (local_err != NULL) {
|
||||
error_propagate(errp, local_err);
|
||||
|
@ -405,7 +405,6 @@ static void patch_instruction(VAPICROMState *s, X86CPU *cpu, target_ulong ip)
|
||||
}
|
||||
|
||||
if (!kvm_enabled()) {
|
||||
cpu_restore_state(cs, cs->mem_io_pc);
|
||||
cpu_get_tb_cpu_state(env, ¤t_pc, ¤t_cs_base,
|
||||
¤t_flags);
|
||||
}
|
||||
|
19
hw/i386/pc.c
19
hw/i386/pc.c
@ -1688,6 +1688,20 @@ static void pc_machine_set_max_ram_below_4g(Object *obj, Visitor *v,
|
||||
pcms->max_ram_below_4g = value;
|
||||
}
|
||||
|
||||
static bool pc_machine_get_vmport(Object *obj, Error **errp)
|
||||
{
|
||||
PCMachineState *pcms = PC_MACHINE(obj);
|
||||
|
||||
return pcms->vmport;
|
||||
}
|
||||
|
||||
static void pc_machine_set_vmport(Object *obj, bool value, Error **errp)
|
||||
{
|
||||
PCMachineState *pcms = PC_MACHINE(obj);
|
||||
|
||||
pcms->vmport = value;
|
||||
}
|
||||
|
||||
static void pc_machine_initfn(Object *obj)
|
||||
{
|
||||
PCMachineState *pcms = PC_MACHINE(obj);
|
||||
@ -1700,6 +1714,11 @@ static void pc_machine_initfn(Object *obj)
|
||||
pc_machine_get_max_ram_below_4g,
|
||||
pc_machine_set_max_ram_below_4g,
|
||||
NULL, NULL, NULL);
|
||||
pcms->vmport = !xen_enabled();
|
||||
object_property_add_bool(obj, PC_MACHINE_VMPORT,
|
||||
pc_machine_get_vmport,
|
||||
pc_machine_set_vmport,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void pc_machine_class_init(ObjectClass *oc, void *data)
|
||||
|
@ -234,8 +234,8 @@ static void pc_init1(MachineState *machine,
|
||||
pc_vga_init(isa_bus, pci_enabled ? pci_bus : NULL);
|
||||
|
||||
/* init basic PC hardware */
|
||||
pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, xen_enabled(),
|
||||
0x4);
|
||||
pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy,
|
||||
!pc_machine->vmport, 0x4);
|
||||
|
||||
pc_nic_init(isa_bus, pci_bus);
|
||||
|
||||
|
@ -242,7 +242,8 @@ static void pc_q35_init(MachineState *machine)
|
||||
pc_register_ferr_irq(gsi[13]);
|
||||
|
||||
/* init basic PC hardware */
|
||||
pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, false, 0xff0104);
|
||||
pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy,
|
||||
!pc_machine->vmport, 0xff0104);
|
||||
|
||||
/* connect pm stuff to lpc */
|
||||
ich9_lpc_pm_init(lpc);
|
||||
|
@ -24,10 +24,12 @@
|
||||
#include "migration/migration.h"
|
||||
#include "qapi/qmp/qerror.h"
|
||||
#include "qemu/event_notifier.h"
|
||||
#include "qemu/fifo8.h"
|
||||
#include "sysemu/char.h"
|
||||
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <limits.h>
|
||||
|
||||
#define PCI_VENDOR_ID_IVSHMEM PCI_VENDOR_ID_REDHAT_QUMRANET
|
||||
#define PCI_DEVICE_ID_IVSHMEM 0x1110
|
||||
@ -73,6 +75,7 @@ typedef struct IVShmemState {
|
||||
|
||||
CharDriverState **eventfd_chr;
|
||||
CharDriverState *server_chr;
|
||||
Fifo8 incoming_fifo;
|
||||
MemoryRegion ivshmem_mmio;
|
||||
|
||||
/* We might need to register the BAR before we actually have the memory.
|
||||
@ -297,8 +300,8 @@ static CharDriverState* create_eventfd_chr_device(void * opaque, EventNotifier *
|
||||
chr = qemu_chr_open_eventfd(eventfd);
|
||||
|
||||
if (chr == NULL) {
|
||||
fprintf(stderr, "creating eventfd for eventfd %d failed\n", eventfd);
|
||||
exit(-1);
|
||||
error_report("creating eventfd for eventfd %d failed", eventfd);
|
||||
exit(1);
|
||||
}
|
||||
qemu_chr_fe_claim_no_fail(chr);
|
||||
|
||||
@ -325,15 +328,14 @@ static int check_shm_size(IVShmemState *s, int fd) {
|
||||
struct stat buf;
|
||||
|
||||
if (fstat(fd, &buf) < 0) {
|
||||
fprintf(stderr, "ivshmem: exiting: fstat on fd %d failed: %s\n",
|
||||
error_report("exiting: fstat on fd %d failed: %s",
|
||||
fd, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (s->ivshmem_size > buf.st_size) {
|
||||
fprintf(stderr,
|
||||
"IVSHMEM ERROR: Requested memory size greater"
|
||||
" than shared object size (%" PRIu64 " > %" PRIu64")\n",
|
||||
error_report("Requested memory size greater"
|
||||
" than shared object size (%" PRIu64 " > %" PRIu64")",
|
||||
s->ivshmem_size, (uint64_t)buf.st_size);
|
||||
return -1;
|
||||
} else {
|
||||
@ -387,6 +389,9 @@ static void close_guest_eventfds(IVShmemState *s, int posn)
|
||||
if (!ivshmem_has_feature(s, IVSHMEM_IOEVENTFD)) {
|
||||
return;
|
||||
}
|
||||
if (posn < 0 || posn >= s->nb_peers) {
|
||||
return;
|
||||
}
|
||||
|
||||
guest_curr_max = s->peers[posn].nb_eventfds;
|
||||
|
||||
@ -405,14 +410,24 @@ static void close_guest_eventfds(IVShmemState *s, int posn)
|
||||
|
||||
/* this function increase the dynamic storage need to store data about other
|
||||
* guests */
|
||||
static void increase_dynamic_storage(IVShmemState *s, int new_min_size) {
|
||||
static int increase_dynamic_storage(IVShmemState *s, int new_min_size)
|
||||
{
|
||||
|
||||
int j, old_nb_alloc;
|
||||
|
||||
/* check for integer overflow */
|
||||
if (new_min_size >= INT_MAX / sizeof(Peer) - 1 || new_min_size <= 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
old_nb_alloc = s->nb_peers;
|
||||
|
||||
while (new_min_size >= s->nb_peers)
|
||||
s->nb_peers = s->nb_peers * 2;
|
||||
if (new_min_size >= s->nb_peers) {
|
||||
/* +1 because #new_min_size is used as last array index */
|
||||
s->nb_peers = new_min_size + 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
IVSHMEM_DPRINTF("bumping storage to %d guests\n", s->nb_peers);
|
||||
s->peers = g_realloc(s->peers, s->nb_peers * sizeof(Peer));
|
||||
@ -422,23 +437,57 @@ static void increase_dynamic_storage(IVShmemState *s, int new_min_size) {
|
||||
s->peers[j].eventfds = NULL;
|
||||
s->peers[j].nb_eventfds = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ivshmem_read(void *opaque, const uint8_t * buf, int flags)
|
||||
static void ivshmem_read(void *opaque, const uint8_t *buf, int size)
|
||||
{
|
||||
IVShmemState *s = opaque;
|
||||
int incoming_fd, tmp_fd;
|
||||
int guest_max_eventfd;
|
||||
long incoming_posn;
|
||||
|
||||
memcpy(&incoming_posn, buf, sizeof(long));
|
||||
if (fifo8_is_empty(&s->incoming_fifo) && size == sizeof(incoming_posn)) {
|
||||
memcpy(&incoming_posn, buf, size);
|
||||
} else {
|
||||
const uint8_t *p;
|
||||
uint32_t num;
|
||||
|
||||
IVSHMEM_DPRINTF("short read of %d bytes\n", size);
|
||||
num = MAX(size, sizeof(long) - fifo8_num_used(&s->incoming_fifo));
|
||||
fifo8_push_all(&s->incoming_fifo, buf, num);
|
||||
if (fifo8_num_used(&s->incoming_fifo) < sizeof(incoming_posn)) {
|
||||
return;
|
||||
}
|
||||
size -= num;
|
||||
buf += num;
|
||||
p = fifo8_pop_buf(&s->incoming_fifo, sizeof(incoming_posn), &num);
|
||||
g_assert(num == sizeof(incoming_posn));
|
||||
memcpy(&incoming_posn, p, sizeof(incoming_posn));
|
||||
if (size > 0) {
|
||||
fifo8_push_all(&s->incoming_fifo, buf, size);
|
||||
}
|
||||
}
|
||||
|
||||
if (incoming_posn < -1) {
|
||||
IVSHMEM_DPRINTF("invalid incoming_posn %ld\n", incoming_posn);
|
||||
return;
|
||||
}
|
||||
|
||||
/* pick off s->server_chr->msgfd and store it, posn should accompany msg */
|
||||
tmp_fd = qemu_chr_fe_get_msgfd(s->server_chr);
|
||||
IVSHMEM_DPRINTF("posn is %ld, fd is %d\n", incoming_posn, tmp_fd);
|
||||
|
||||
/* make sure we have enough space for this guest */
|
||||
if (incoming_posn >= s->nb_peers) {
|
||||
increase_dynamic_storage(s, incoming_posn);
|
||||
if (increase_dynamic_storage(s, incoming_posn) < 0) {
|
||||
error_report("increase_dynamic_storage() failed");
|
||||
if (tmp_fd != -1) {
|
||||
close(tmp_fd);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (tmp_fd == -1) {
|
||||
@ -460,8 +509,8 @@ static void ivshmem_read(void *opaque, const uint8_t * buf, int flags)
|
||||
incoming_fd = dup(tmp_fd);
|
||||
|
||||
if (incoming_fd == -1) {
|
||||
fprintf(stderr, "could not allocate file descriptor %s\n",
|
||||
strerror(errno));
|
||||
error_report("could not allocate file descriptor %s", strerror(errno));
|
||||
close(tmp_fd);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -473,7 +522,7 @@ static void ivshmem_read(void *opaque, const uint8_t * buf, int flags)
|
||||
s->max_peer = 0;
|
||||
|
||||
if (check_shm_size(s, incoming_fd) == -1) {
|
||||
exit(-1);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* mmap the region and map into the BAR2 */
|
||||
@ -567,13 +616,13 @@ static uint64_t ivshmem_get_size(IVShmemState * s) {
|
||||
value <<= 30;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "qemu: invalid ram size: %s\n", s->sizearg);
|
||||
error_report("invalid ram size: %s", s->sizearg);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* BARs must be a power of 2 */
|
||||
if (!is_power_of_two(value)) {
|
||||
fprintf(stderr, "ivshmem: size must be power of 2\n");
|
||||
error_report("size must be power of 2");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -625,7 +674,7 @@ static int ivshmem_load(QEMUFile* f, void *opaque, int version_id)
|
||||
}
|
||||
|
||||
if (proxy->role_val == IVSHMEM_PEER) {
|
||||
fprintf(stderr, "ivshmem: 'peer' devices are not migratable\n");
|
||||
error_report("'peer' devices are not migratable");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -663,13 +712,15 @@ static int pci_ivshmem_init(PCIDevice *dev)
|
||||
s->ivshmem_size = ivshmem_get_size(s);
|
||||
}
|
||||
|
||||
fifo8_create(&s->incoming_fifo, sizeof(long));
|
||||
|
||||
register_savevm(DEVICE(dev), "ivshmem", 0, 0, ivshmem_save, ivshmem_load,
|
||||
dev);
|
||||
|
||||
/* IRQFD requires MSI */
|
||||
if (ivshmem_has_feature(s, IVSHMEM_IOEVENTFD) &&
|
||||
!ivshmem_has_feature(s, IVSHMEM_MSI)) {
|
||||
fprintf(stderr, "ivshmem: ioeventfd/irqfd requires MSI\n");
|
||||
error_report("ioeventfd/irqfd requires MSI");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -680,7 +731,7 @@ static int pci_ivshmem_init(PCIDevice *dev)
|
||||
} else if (strncmp(s->role, "master", 7) == 0) {
|
||||
s->role_val = IVSHMEM_MASTER;
|
||||
} else {
|
||||
fprintf(stderr, "ivshmem: 'role' must be 'peer' or 'master'\n");
|
||||
error_report("'role' must be 'peer' or 'master'");
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
@ -720,8 +771,8 @@ static int pci_ivshmem_init(PCIDevice *dev)
|
||||
* to the ivshmem server to receive the memory region */
|
||||
|
||||
if (s->shmobj != NULL) {
|
||||
fprintf(stderr, "WARNING: do not specify both 'chardev' "
|
||||
"and 'shm' with ivshmem\n");
|
||||
error_report("WARNING: do not specify both 'chardev' "
|
||||
"and 'shm' with ivshmem");
|
||||
}
|
||||
|
||||
IVSHMEM_DPRINTF("using shared memory server (socket = %s)\n",
|
||||
@ -749,7 +800,7 @@ static int pci_ivshmem_init(PCIDevice *dev)
|
||||
int fd;
|
||||
|
||||
if (s->shmobj == NULL) {
|
||||
fprintf(stderr, "Must specify 'chardev' or 'shm' to ivshmem\n");
|
||||
error_report("Must specify 'chardev' or 'shm' to ivshmem");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -761,18 +812,18 @@ static int pci_ivshmem_init(PCIDevice *dev)
|
||||
S_IRWXU|S_IRWXG|S_IRWXO)) > 0) {
|
||||
/* truncate file to length PCI device's memory */
|
||||
if (ftruncate(fd, s->ivshmem_size) != 0) {
|
||||
fprintf(stderr, "ivshmem: could not truncate shared file\n");
|
||||
error_report("could not truncate shared file");
|
||||
}
|
||||
|
||||
} else if ((fd = shm_open(s->shmobj, O_CREAT|O_RDWR,
|
||||
S_IRWXU|S_IRWXG|S_IRWXO)) < 0) {
|
||||
fprintf(stderr, "ivshmem: could not open shared file\n");
|
||||
exit(-1);
|
||||
error_report("could not open shared file");
|
||||
exit(1);
|
||||
|
||||
}
|
||||
|
||||
if (check_shm_size(s, fd) == -1) {
|
||||
exit(-1);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
create_shared_memory_BAR(s, fd);
|
||||
@ -796,6 +847,7 @@ static void pci_ivshmem_uninit(PCIDevice *dev)
|
||||
memory_region_del_subregion(&s->bar, &s->ivshmem);
|
||||
vmstate_unregister_ram(&s->ivshmem, DEVICE(dev));
|
||||
unregister_savevm(DEVICE(dev), "ivshmem", s);
|
||||
fifo8_destroy(&s->incoming_fifo);
|
||||
}
|
||||
|
||||
static Property ivshmem_properties[] = {
|
||||
|
@ -2911,6 +2911,7 @@ static int vfio_mmap_bar(VFIODevice *vdev, VFIOBAR *bar,
|
||||
}
|
||||
|
||||
memory_region_init_ram_ptr(submem, OBJECT(vdev), name, size, *map);
|
||||
memory_region_set_skip_dump(submem);
|
||||
} else {
|
||||
empty_region:
|
||||
/* Create a zero sized sub-region to make cleanup easy. */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -60,6 +60,7 @@
|
||||
#define MFI_ODR0 0x9c /* outbound doorbell register0 */
|
||||
#define MFI_ODCR0 0xa0 /* outbound doorbell clear register0 */
|
||||
#define MFI_OSP0 0xb0 /* outbound scratch pad0 */
|
||||
#define MFI_OSP1 0xb4 /* outbound scratch pad1 */
|
||||
#define MFI_IQPL 0xc0 /* Inbound queue port (low bytes) */
|
||||
#define MFI_IQPH 0xc4 /* Inbound queue port (high bytes) */
|
||||
#define MFI_DIAG 0xf8 /* Host diag */
|
||||
@ -116,6 +117,12 @@
|
||||
#define MFI_FWINIT_STOP_ADP 0x00000020 /* Move to operational, stop */
|
||||
#define MFI_FWINIT_ADP_RESET 0x00000040 /* Reset ADP */
|
||||
|
||||
/*
|
||||
* Control bits for the DIAG register
|
||||
*/
|
||||
#define MFI_DIAG_WRITE_ENABLE 0x00000080
|
||||
#define MFI_DIAG_RESET_ADP 0x00000004
|
||||
|
||||
/* MFI Commands */
|
||||
typedef enum {
|
||||
MFI_CMD_INIT = 0x00,
|
||||
@ -1094,7 +1101,7 @@ struct mfi_pd_list {
|
||||
union mfi_ld_ref {
|
||||
struct {
|
||||
uint8_t target_id;
|
||||
uint8_t lun_id;
|
||||
uint8_t reserved;
|
||||
uint16_t seq;
|
||||
} v;
|
||||
uint32_t ref;
|
||||
@ -1111,6 +1118,13 @@ struct mfi_ld_list {
|
||||
} ld_list[MFI_MAX_LD];
|
||||
} QEMU_PACKED;
|
||||
|
||||
struct mfi_ld_targetid_list {
|
||||
uint32_t size;
|
||||
uint32_t ld_count;
|
||||
uint8_t pad[3];
|
||||
uint8_t targetid[MFI_MAX_LD];
|
||||
} QEMU_PACKED;
|
||||
|
||||
enum mfi_ld_access {
|
||||
MFI_LD_ACCESS_RW = 0,
|
||||
MFI_LD_ACCSSS_RO = 2,
|
||||
|
@ -51,14 +51,6 @@ static void scsi_device_realize(SCSIDevice *s, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
static void scsi_device_unrealize(SCSIDevice *s, Error **errp)
|
||||
{
|
||||
SCSIDeviceClass *sc = SCSI_DEVICE_GET_CLASS(s);
|
||||
if (sc->unrealize) {
|
||||
sc->unrealize(s, errp);
|
||||
}
|
||||
}
|
||||
|
||||
int scsi_bus_parse_cdb(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
|
||||
void *hba_private)
|
||||
{
|
||||
@ -84,7 +76,7 @@ static SCSIRequest *scsi_device_alloc_req(SCSIDevice *s, uint32_t tag, uint32_t
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void scsi_device_unit_attention_reported(SCSIDevice *s)
|
||||
void scsi_device_unit_attention_reported(SCSIDevice *s)
|
||||
{
|
||||
SCSIDeviceClass *sc = SCSI_DEVICE_GET_CLASS(s);
|
||||
if (sc->unit_attention_reported) {
|
||||
@ -218,7 +210,9 @@ static void scsi_qdev_unrealize(DeviceState *qdev, Error **errp)
|
||||
if (dev->vmsentry) {
|
||||
qemu_del_vm_change_state_handler(dev->vmsentry);
|
||||
}
|
||||
scsi_device_unrealize(dev, errp);
|
||||
|
||||
scsi_device_purge_requests(dev, SENSE_CODE(NO_SENSE));
|
||||
blockdev_mark_auto_del(dev->conf.blk);
|
||||
}
|
||||
|
||||
/* handle legacy '-drive if=scsi,...' cmd line args */
|
||||
@ -826,7 +820,7 @@ static int ata_passthrough_xfer_unit(SCSIDevice *dev, uint8_t *buf)
|
||||
return xfer_unit;
|
||||
}
|
||||
|
||||
static int ata_passthrough_12_xfer_size(SCSIDevice *dev, uint8_t *buf)
|
||||
static int ata_passthrough_12_xfer(SCSIDevice *dev, uint8_t *buf)
|
||||
{
|
||||
int length = buf[2] & 0x3;
|
||||
int xfer;
|
||||
@ -849,7 +843,7 @@ static int ata_passthrough_12_xfer_size(SCSIDevice *dev, uint8_t *buf)
|
||||
return xfer * unit;
|
||||
}
|
||||
|
||||
static int ata_passthrough_16_xfer_size(SCSIDevice *dev, uint8_t *buf)
|
||||
static int ata_passthrough_16_xfer(SCSIDevice *dev, uint8_t *buf)
|
||||
{
|
||||
int extend = buf[1] & 0x1;
|
||||
int length = buf[2] & 0x3;
|
||||
@ -875,16 +869,16 @@ static int ata_passthrough_16_xfer_size(SCSIDevice *dev, uint8_t *buf)
|
||||
return xfer * unit;
|
||||
}
|
||||
|
||||
uint32_t scsi_data_cdb_length(uint8_t *buf)
|
||||
uint32_t scsi_data_cdb_xfer(uint8_t *buf)
|
||||
{
|
||||
if ((buf[0] >> 5) == 0 && buf[4] == 0) {
|
||||
return 256;
|
||||
} else {
|
||||
return scsi_cdb_length(buf);
|
||||
return scsi_cdb_xfer(buf);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t scsi_cdb_length(uint8_t *buf)
|
||||
uint32_t scsi_cdb_xfer(uint8_t *buf)
|
||||
{
|
||||
switch (buf[0] >> 5) {
|
||||
case 0:
|
||||
@ -905,9 +899,9 @@ uint32_t scsi_cdb_length(uint8_t *buf)
|
||||
}
|
||||
}
|
||||
|
||||
static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
|
||||
static int scsi_req_xfer(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
|
||||
{
|
||||
cmd->xfer = scsi_cdb_length(buf);
|
||||
cmd->xfer = scsi_cdb_xfer(buf);
|
||||
switch (buf[0]) {
|
||||
case TEST_UNIT_READY:
|
||||
case REWIND:
|
||||
@ -1038,17 +1032,17 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
|
||||
/* BLANK command of MMC */
|
||||
cmd->xfer = 0;
|
||||
} else {
|
||||
cmd->xfer = ata_passthrough_12_xfer_size(dev, buf);
|
||||
cmd->xfer = ata_passthrough_12_xfer(dev, buf);
|
||||
}
|
||||
break;
|
||||
case ATA_PASSTHROUGH_16:
|
||||
cmd->xfer = ata_passthrough_16_xfer_size(dev, buf);
|
||||
cmd->xfer = ata_passthrough_16_xfer(dev, buf);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int scsi_req_stream_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
|
||||
static int scsi_req_stream_xfer(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
|
||||
{
|
||||
switch (buf[0]) {
|
||||
/* stream commands */
|
||||
@ -1103,12 +1097,12 @@ static int scsi_req_stream_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *bu
|
||||
break;
|
||||
/* generic commands */
|
||||
default:
|
||||
return scsi_req_length(cmd, dev, buf);
|
||||
return scsi_req_xfer(cmd, dev, buf);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int scsi_req_medium_changer_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
|
||||
static int scsi_req_medium_changer_xfer(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
|
||||
{
|
||||
switch (buf[0]) {
|
||||
/* medium changer commands */
|
||||
@ -1125,7 +1119,7 @@ static int scsi_req_medium_changer_length(SCSICommand *cmd, SCSIDevice *dev, uin
|
||||
|
||||
/* generic commands */
|
||||
default:
|
||||
return scsi_req_length(cmd, dev, buf);
|
||||
return scsi_req_xfer(cmd, dev, buf);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -1214,38 +1208,45 @@ static uint64_t scsi_cmd_lba(SCSICommand *cmd)
|
||||
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;
|
||||
|
||||
cmd->lba = -1;
|
||||
switch (buf[0] >> 5) {
|
||||
case 0:
|
||||
cmd->len = 6;
|
||||
break;
|
||||
case 1:
|
||||
case 2:
|
||||
cmd->len = 10;
|
||||
break;
|
||||
case 4:
|
||||
cmd->len = 16;
|
||||
break;
|
||||
case 5:
|
||||
cmd->len = 12;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
cmd->len = scsi_cdb_length(buf);
|
||||
|
||||
switch (dev->type) {
|
||||
case TYPE_TAPE:
|
||||
rc = scsi_req_stream_length(cmd, dev, buf);
|
||||
rc = scsi_req_stream_xfer(cmd, dev, buf);
|
||||
break;
|
||||
case TYPE_MEDIUM_CHANGER:
|
||||
rc = scsi_req_medium_changer_length(cmd, dev, buf);
|
||||
rc = scsi_req_medium_changer_xfer(cmd, dev, buf);
|
||||
break;
|
||||
default:
|
||||
rc = scsi_req_length(cmd, dev, buf);
|
||||
rc = scsi_req_xfer(cmd, dev, buf);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1666,7 +1666,7 @@ static void scsi_disk_emulate_write_same(SCSIDiskReq *r, uint8_t *inbuf)
|
||||
{
|
||||
SCSIRequest *req = &r->req;
|
||||
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, req->dev);
|
||||
uint32_t nb_sectors = scsi_data_cdb_length(r->req.cmd.buf);
|
||||
uint32_t nb_sectors = scsi_data_cdb_xfer(r->req.cmd.buf);
|
||||
WriteSameCBData *data;
|
||||
uint8_t *buf;
|
||||
int i;
|
||||
@ -2061,7 +2061,7 @@ static int32_t scsi_disk_dma_command(SCSIRequest *req, uint8_t *buf)
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = scsi_data_cdb_length(r->req.cmd.buf);
|
||||
len = scsi_data_cdb_xfer(r->req.cmd.buf);
|
||||
switch (command) {
|
||||
case READ_6:
|
||||
case READ_10:
|
||||
@ -2138,14 +2138,6 @@ static void scsi_disk_reset(DeviceState *dev)
|
||||
s->tray_open = 0;
|
||||
}
|
||||
|
||||
static void scsi_unrealize(SCSIDevice *dev, Error **errp)
|
||||
{
|
||||
SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev);
|
||||
|
||||
scsi_device_purge_requests(&s->qdev, SENSE_CODE(NO_SENSE));
|
||||
blockdev_mark_auto_del(s->qdev.conf.blk);
|
||||
}
|
||||
|
||||
static void scsi_disk_resize_cb(void *opaque)
|
||||
{
|
||||
SCSIDiskState *s = opaque;
|
||||
@ -2396,7 +2388,7 @@ static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
|
||||
DPRINTF("Command: lun=%d tag=0x%x data=0x%02x", lun, tag, buf[0]);
|
||||
{
|
||||
int i;
|
||||
for (i = 1; i < req->cmd.len; i++) {
|
||||
for (i = 1; i < scsi_cdb_length(buf); i++) {
|
||||
printf(" 0x%02x", buf[i]);
|
||||
}
|
||||
printf("\n");
|
||||
@ -2612,7 +2604,6 @@ static void scsi_hd_class_initfn(ObjectClass *klass, void *data)
|
||||
SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
|
||||
|
||||
sc->realize = scsi_hd_realize;
|
||||
sc->unrealize = scsi_unrealize;
|
||||
sc->alloc_req = scsi_new_request;
|
||||
sc->unit_attention_reported = scsi_disk_unit_attention_reported;
|
||||
dc->fw_name = "disk";
|
||||
@ -2643,7 +2634,6 @@ static void scsi_cd_class_initfn(ObjectClass *klass, void *data)
|
||||
SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
|
||||
|
||||
sc->realize = scsi_cd_realize;
|
||||
sc->unrealize = scsi_unrealize;
|
||||
sc->alloc_req = scsi_new_request;
|
||||
sc->unit_attention_reported = scsi_disk_unit_attention_reported;
|
||||
dc->fw_name = "disk";
|
||||
@ -2672,7 +2662,6 @@ static void scsi_block_class_initfn(ObjectClass *klass, void *data)
|
||||
SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
|
||||
|
||||
sc->realize = scsi_block_realize;
|
||||
sc->unrealize = scsi_unrealize;
|
||||
sc->alloc_req = scsi_block_new_request;
|
||||
sc->parse_cdb = scsi_block_parse_cdb;
|
||||
dc->fw_name = "disk";
|
||||
@ -2710,7 +2699,6 @@ static void scsi_disk_class_initfn(ObjectClass *klass, void *data)
|
||||
SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
|
||||
|
||||
sc->realize = scsi_disk_realize;
|
||||
sc->unrealize = scsi_unrealize;
|
||||
sc->alloc_req = scsi_new_request;
|
||||
sc->unit_attention_reported = scsi_disk_unit_attention_reported;
|
||||
dc->fw_name = "disk";
|
||||
|
@ -368,12 +368,6 @@ static void scsi_generic_reset(DeviceState *dev)
|
||||
scsi_device_purge_requests(s, SENSE_CODE(RESET));
|
||||
}
|
||||
|
||||
static void scsi_unrealize(SCSIDevice *s, Error **errp)
|
||||
{
|
||||
scsi_device_purge_requests(s, SENSE_CODE(NO_SENSE));
|
||||
blockdev_mark_auto_del(s->conf.blk);
|
||||
}
|
||||
|
||||
static void scsi_generic_realize(SCSIDevice *s, Error **errp)
|
||||
{
|
||||
int rc;
|
||||
@ -478,7 +472,6 @@ static void scsi_generic_class_initfn(ObjectClass *klass, void *data)
|
||||
SCSIDeviceClass *sc = SCSI_DEVICE_CLASS(klass);
|
||||
|
||||
sc->realize = scsi_generic_realize;
|
||||
sc->unrealize = scsi_unrealize;
|
||||
sc->alloc_req = scsi_new_request;
|
||||
sc->parse_cdb = scsi_generic_parse_cdb;
|
||||
dc->fw_name = "disk";
|
||||
|
@ -241,9 +241,10 @@ void virtio_scsi_dataplane_start(VirtIOSCSI *s)
|
||||
}
|
||||
}
|
||||
|
||||
aio_context_release(s->ctx);
|
||||
s->dataplane_starting = false;
|
||||
s->dataplane_started = true;
|
||||
aio_context_release(s->ctx);
|
||||
return;
|
||||
|
||||
fail_vrings:
|
||||
virtio_scsi_clear_aio(s);
|
||||
|
@ -804,10 +804,12 @@ void virtio_scsi_common_realize(DeviceState *dev, Error **errp,
|
||||
virtio_init(vdev, "virtio-scsi", VIRTIO_ID_SCSI,
|
||||
sizeof(VirtIOSCSIConfig));
|
||||
|
||||
if (s->conf.num_queues <= 0 || s->conf.num_queues > VIRTIO_PCI_QUEUE_MAX) {
|
||||
error_setg(errp, "Invalid number of queues (= %" PRId32 "), "
|
||||
if (s->conf.num_queues == 0 ||
|
||||
s->conf.num_queues > VIRTIO_PCI_QUEUE_MAX - 2) {
|
||||
error_setg(errp, "Invalid number of queues (= %" PRIu32 "), "
|
||||
"must be a positive integer less than %d.",
|
||||
s->conf.num_queues, VIRTIO_PCI_QUEUE_MAX);
|
||||
s->conf.num_queues, VIRTIO_PCI_QUEUE_MAX - 2);
|
||||
virtio_cleanup(vdev);
|
||||
return;
|
||||
}
|
||||
s->cmd_vqs = g_malloc0(s->conf.num_queues * sizeof(VirtQueue *));
|
||||
|
@ -150,6 +150,7 @@ struct MemoryRegion {
|
||||
bool terminates;
|
||||
bool romd_mode;
|
||||
bool ram;
|
||||
bool skip_dump;
|
||||
bool readonly; /* For RAM regions */
|
||||
bool enabled;
|
||||
bool rom_device;
|
||||
@ -456,6 +457,24 @@ uint64_t memory_region_size(MemoryRegion *mr);
|
||||
*/
|
||||
bool memory_region_is_ram(MemoryRegion *mr);
|
||||
|
||||
/**
|
||||
* memory_region_is_skip_dump: check whether a memory region should not be
|
||||
* dumped
|
||||
*
|
||||
* Returns %true is a memory region should not be dumped(e.g. VFIO BAR MMAP).
|
||||
*
|
||||
* @mr: the memory region being queried
|
||||
*/
|
||||
bool memory_region_is_skip_dump(MemoryRegion *mr);
|
||||
|
||||
/**
|
||||
* memory_region_set_skip_dump: Set skip_dump flag, dump will ignore this memory
|
||||
* region
|
||||
*
|
||||
* @mr: the memory region being queried
|
||||
*/
|
||||
void memory_region_set_skip_dump(MemoryRegion *mr);
|
||||
|
||||
/**
|
||||
* memory_region_is_romd: check whether a memory region is in ROMD mode
|
||||
*
|
||||
|
@ -35,11 +35,13 @@ struct PCMachineState {
|
||||
HotplugHandler *acpi_dev;
|
||||
|
||||
uint64_t max_ram_below_4g;
|
||||
bool vmport;
|
||||
};
|
||||
|
||||
#define PC_MACHINE_ACPI_DEVICE_PROP "acpi-device"
|
||||
#define PC_MACHINE_MEMHP_REGION_SIZE "hotplug-memory-region-size"
|
||||
#define PC_MACHINE_MAX_RAM_BELOW_4G "max-ram-below-4g"
|
||||
#define PC_MACHINE_VMPORT "vmport"
|
||||
|
||||
/**
|
||||
* PCMachineClass:
|
||||
|
@ -56,6 +56,7 @@
|
||||
#define PCI_DEVICE_ID_LSI_53C810 0x0001
|
||||
#define PCI_DEVICE_ID_LSI_53C895A 0x0012
|
||||
#define PCI_DEVICE_ID_LSI_SAS1078 0x0060
|
||||
#define PCI_DEVICE_ID_LSI_SAS0079 0x0079
|
||||
|
||||
#define PCI_VENDOR_ID_DEC 0x1011
|
||||
#define PCI_DEVICE_ID_DEC_21154 0x0026
|
||||
|
@ -84,7 +84,6 @@ struct SCSIRequest {
|
||||
typedef struct SCSIDeviceClass {
|
||||
DeviceClass parent_class;
|
||||
void (*realize)(SCSIDevice *dev, Error **errp);
|
||||
void (*unrealize)(SCSIDevice *dev, Error **errp);
|
||||
int (*parse_cdb)(SCSIDevice *dev, SCSICommand *cmd, uint8_t *buf,
|
||||
void *hba_private);
|
||||
SCSIRequest *(*alloc_req)(SCSIDevice *s, uint32_t tag, uint32_t lun,
|
||||
@ -239,8 +238,9 @@ extern const struct SCSISense sense_code_SPACE_ALLOC_FAILED;
|
||||
|
||||
#define SENSE_CODE(x) sense_code_ ## x
|
||||
|
||||
uint32_t scsi_data_cdb_length(uint8_t *buf);
|
||||
uint32_t scsi_cdb_length(uint8_t *buf);
|
||||
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_sense_valid(SCSISense sense);
|
||||
int scsi_build_sense(uint8_t *in_buf, int in_len,
|
||||
uint8_t *buf, int len, bool fixed);
|
||||
@ -271,6 +271,7 @@ void scsi_req_retry(SCSIRequest *req);
|
||||
void scsi_device_purge_requests(SCSIDevice *sdev, SCSISense sense);
|
||||
void scsi_device_set_ua(SCSIDevice *sdev, SCSISense sense);
|
||||
void scsi_device_report_change(SCSIDevice *dev, SCSISense sense);
|
||||
void scsi_device_unit_attention_reported(SCSIDevice *dev);
|
||||
int scsi_device_get_sense(SCSIDevice *dev, uint8_t *buf, int len, bool fixed);
|
||||
SCSIDevice *scsi_device_find(SCSIBus *bus, int channel, int target, int lun);
|
||||
|
||||
|
10
memory.c
10
memory.c
@ -1185,6 +1185,11 @@ void memory_region_init_ram_ptr(MemoryRegion *mr,
|
||||
mr->ram_addr = qemu_ram_alloc_from_ptr(size, ptr, mr, &error_abort);
|
||||
}
|
||||
|
||||
void memory_region_set_skip_dump(MemoryRegion *mr)
|
||||
{
|
||||
mr->skip_dump = true;
|
||||
}
|
||||
|
||||
void memory_region_init_alias(MemoryRegion *mr,
|
||||
Object *owner,
|
||||
const char *name,
|
||||
@ -1306,6 +1311,11 @@ bool memory_region_is_ram(MemoryRegion *mr)
|
||||
return mr->ram;
|
||||
}
|
||||
|
||||
bool memory_region_is_skip_dump(MemoryRegion *mr)
|
||||
{
|
||||
return mr->skip_dump;
|
||||
}
|
||||
|
||||
bool memory_region_is_logging(MemoryRegion *mr)
|
||||
{
|
||||
return mr->dirty_log_mask;
|
||||
|
@ -203,7 +203,8 @@ static void guest_phys_blocks_region_add(MemoryListener *listener,
|
||||
GuestPhysBlock *predecessor;
|
||||
|
||||
/* we only care about RAM */
|
||||
if (!memory_region_is_ram(section->mr)) {
|
||||
if (!memory_region_is_ram(section->mr) ||
|
||||
memory_region_is_skip_dump(section->mr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,7 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \
|
||||
" property accel=accel1[:accel2[:...]] selects accelerator\n"
|
||||
" supported accelerators are kvm, xen, tcg (default: tcg)\n"
|
||||
" kernel_irqchip=on|off controls accelerated irqchip support\n"
|
||||
" vmport=on|off controls emulation of vmport (default: on)\n"
|
||||
" kvm_shadow_mem=size of KVM shadow MMU\n"
|
||||
" dump-guest-core=on|off include guest memory in a core dump (default=on)\n"
|
||||
" mem-merge=on|off controls memory merge support (default: on)\n"
|
||||
@ -51,6 +52,8 @@ than one accelerator specified, the next one is used if the previous one fails
|
||||
to initialize.
|
||||
@item kernel_irqchip=on|off
|
||||
Enables in-kernel irqchip support for the chosen accelerator when available.
|
||||
@item vmport=on|off
|
||||
Enables emulation of VMWare IO port, for vmmouse etc. (enabled by default)
|
||||
@item kvm_shadow_mem=size
|
||||
Defines the size of the KVM shadow MMU.
|
||||
@item dump-guest-core=on|off
|
||||
|
@ -362,4 +362,9 @@ define unnest-vars
|
||||
# Include all the .d files
|
||||
$(eval -include $(addsuffix *.d, $(sort $(dir $($v)))))
|
||||
$(eval $v := $(filter-out %/,$($v))))
|
||||
|
||||
# For all %.mo objects that are directly added into -y, expand them to %.mo-objs
|
||||
$(foreach v,$2,
|
||||
$(eval $v := $(foreach o,$($v),$(if $($o-objs),$($o-objs),$o))))
|
||||
|
||||
endef
|
||||
|
@ -12,7 +12,7 @@
|
||||
# the COPYING file in the top-level directory.
|
||||
|
||||
import curses
|
||||
import sys, os, time, optparse
|
||||
import sys, os, time, optparse, ctypes
|
||||
|
||||
class DebugfsProvider(object):
|
||||
def __init__(self):
|
||||
@ -141,61 +141,97 @@ svm_exit_reasons = {
|
||||
0x400: 'NPF',
|
||||
}
|
||||
|
||||
s390_exit_reasons = {
|
||||
0x000: 'UNKNOWN',
|
||||
0x001: 'EXCEPTION',
|
||||
0x002: 'IO',
|
||||
0x003: 'HYPERCALL',
|
||||
0x004: 'DEBUG',
|
||||
0x005: 'HLT',
|
||||
0x006: 'MMIO',
|
||||
0x007: 'IRQ_WINDOW_OPEN',
|
||||
0x008: 'SHUTDOWN',
|
||||
0x009: 'FAIL_ENTRY',
|
||||
0x010: 'INTR',
|
||||
0x011: 'SET_TPR',
|
||||
0x012: 'TPR_ACCESS',
|
||||
0x013: 'S390_SIEIC',
|
||||
0x014: 'S390_RESET',
|
||||
0x015: 'DCR',
|
||||
0x016: 'NMI',
|
||||
0x017: 'INTERNAL_ERROR',
|
||||
0x018: 'OSI',
|
||||
0x019: 'PAPR_HCALL',
|
||||
# From include/uapi/linux/kvm.h, KVM_EXIT_xxx
|
||||
userspace_exit_reasons = {
|
||||
0: 'UNKNOWN',
|
||||
1: 'EXCEPTION',
|
||||
2: 'IO',
|
||||
3: 'HYPERCALL',
|
||||
4: 'DEBUG',
|
||||
5: 'HLT',
|
||||
6: 'MMIO',
|
||||
7: 'IRQ_WINDOW_OPEN',
|
||||
8: 'SHUTDOWN',
|
||||
9: 'FAIL_ENTRY',
|
||||
10: 'INTR',
|
||||
11: 'SET_TPR',
|
||||
12: 'TPR_ACCESS',
|
||||
13: 'S390_SIEIC',
|
||||
14: 'S390_RESET',
|
||||
15: 'DCR',
|
||||
16: 'NMI',
|
||||
17: 'INTERNAL_ERROR',
|
||||
18: 'OSI',
|
||||
19: 'PAPR_HCALL',
|
||||
20: 'S390_UCONTROL',
|
||||
21: 'WATCHDOG',
|
||||
22: 'S390_TSCH',
|
||||
23: 'EPR',
|
||||
}
|
||||
|
||||
vendor_exit_reasons = {
|
||||
x86_exit_reasons = {
|
||||
'vmx': vmx_exit_reasons,
|
||||
'svm': svm_exit_reasons,
|
||||
'IBM/S390': s390_exit_reasons,
|
||||
}
|
||||
|
||||
syscall_numbers = {
|
||||
'IBM/S390': 331,
|
||||
}
|
||||
|
||||
sc_perf_evt_open = 298
|
||||
|
||||
sc_perf_evt_open = None
|
||||
exit_reasons = None
|
||||
|
||||
for line in file('/proc/cpuinfo').readlines():
|
||||
if line.startswith('flags') or line.startswith('vendor_id'):
|
||||
for flag in line.split():
|
||||
if flag in vendor_exit_reasons:
|
||||
exit_reasons = vendor_exit_reasons[flag]
|
||||
if flag in syscall_numbers:
|
||||
sc_perf_evt_open = syscall_numbers[flag]
|
||||
filters = {
|
||||
'kvm_exit': ('exit_reason', exit_reasons)
|
||||
ioctl_numbers = {
|
||||
'SET_FILTER' : 0x40082406,
|
||||
'ENABLE' : 0x00002400,
|
||||
'DISABLE' : 0x00002401,
|
||||
}
|
||||
|
||||
def x86_init(flag):
|
||||
globals().update({
|
||||
'sc_perf_evt_open' : 298,
|
||||
'exit_reasons' : x86_exit_reasons[flag],
|
||||
})
|
||||
|
||||
def s390_init():
|
||||
globals().update({
|
||||
'sc_perf_evt_open' : 331
|
||||
})
|
||||
|
||||
def ppc_init():
|
||||
globals().update({
|
||||
'sc_perf_evt_open' : 319,
|
||||
'ioctl_numbers' : {
|
||||
'SET_FILTER' : 0x80002406 | (ctypes.sizeof(ctypes.c_char_p) << 16),
|
||||
'ENABLE' : 0x20002400,
|
||||
'DISABLE' : 0x20002401,
|
||||
}
|
||||
})
|
||||
|
||||
def detect_platform():
|
||||
if os.uname()[4].startswith('ppc'):
|
||||
ppc_init()
|
||||
return
|
||||
|
||||
for line in file('/proc/cpuinfo').readlines():
|
||||
if line.startswith('flags'):
|
||||
for flag in line.split():
|
||||
if flag in x86_exit_reasons:
|
||||
x86_init(flag)
|
||||
return
|
||||
elif line.startswith('vendor_id'):
|
||||
for flag in line.split():
|
||||
if flag == 'IBM/S390':
|
||||
s390_init()
|
||||
return
|
||||
|
||||
detect_platform()
|
||||
|
||||
def invert(d):
|
||||
return dict((x[1], x[0]) for x in d.iteritems())
|
||||
|
||||
for f in filters:
|
||||
filters[f] = (filters[f][0], invert(filters[f][1]))
|
||||
filters = {}
|
||||
filters['kvm_userspace_exit'] = ('reason', invert(userspace_exit_reasons))
|
||||
if exit_reasons:
|
||||
filters['kvm_exit'] = ('exit_reason', invert(exit_reasons))
|
||||
|
||||
import ctypes, struct, array
|
||||
import struct, array
|
||||
|
||||
libc = ctypes.CDLL('libc.so.6')
|
||||
syscall = libc.syscall
|
||||
@ -285,14 +321,14 @@ class Event(object):
|
||||
raise Exception('perf_event_open failed')
|
||||
if filter:
|
||||
import fcntl
|
||||
fcntl.ioctl(fd, 0x40082406, filter)
|
||||
fcntl.ioctl(fd, ioctl_numbers['SET_FILTER'], filter)
|
||||
self.fd = fd
|
||||
def enable(self):
|
||||
import fcntl
|
||||
fcntl.ioctl(self.fd, 0x00002400, 0)
|
||||
fcntl.ioctl(self.fd, ioctl_numbers['ENABLE'], 0)
|
||||
def disable(self):
|
||||
import fcntl
|
||||
fcntl.ioctl(self.fd, 0x00002401, 0)
|
||||
fcntl.ioctl(self.fd, ioctl_numbers['DISABLE'], 0)
|
||||
|
||||
class TracepointProvider(object):
|
||||
def __init__(self):
|
||||
@ -311,18 +347,30 @@ class TracepointProvider(object):
|
||||
self.select(fields)
|
||||
def fields(self):
|
||||
return self._fields
|
||||
|
||||
def _online_cpus(self):
|
||||
l = []
|
||||
pattern = r'cpu([0-9]+)'
|
||||
basedir = '/sys/devices/system/cpu'
|
||||
for entry in os.listdir(basedir):
|
||||
match = re.match(pattern, entry)
|
||||
if not match:
|
||||
continue
|
||||
path = os.path.join(basedir, entry, 'online')
|
||||
if os.path.exists(path) and open(path).read().strip() != '1':
|
||||
continue
|
||||
l.append(int(match.group(1)))
|
||||
return l
|
||||
|
||||
def _setup(self, _fields):
|
||||
self._fields = _fields
|
||||
cpure = r'cpu([0-9]+)'
|
||||
self.cpus = [int(re.match(cpure, x).group(1))
|
||||
for x in os.listdir('/sys/devices/system/cpu')
|
||||
if re.match(cpure, x)]
|
||||
cpus = self._online_cpus()
|
||||
import resource
|
||||
nfiles = len(self.cpus) * 1000
|
||||
nfiles = len(cpus) * 1000
|
||||
resource.setrlimit(resource.RLIMIT_NOFILE, (nfiles, nfiles))
|
||||
events = []
|
||||
self.group_leaders = []
|
||||
for cpu in self.cpus:
|
||||
for cpu in cpus:
|
||||
group = Group(cpu)
|
||||
for name in _fields:
|
||||
tracepoint = name
|
||||
|
@ -7987,7 +7987,7 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu,
|
||||
if (bp->pc == pc_ptr &&
|
||||
!((bp->flags & BP_CPU) && (tb->flags & HF_RF_MASK))) {
|
||||
gen_debug(dc, pc_ptr - dc->cs_base);
|
||||
break;
|
||||
goto done_generating;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -8038,6 +8038,7 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu,
|
||||
}
|
||||
if (tb->cflags & CF_LAST_IO)
|
||||
gen_io_end();
|
||||
done_generating:
|
||||
gen_tb_end(tb, num_insns);
|
||||
*tcg_ctx.gen_opc_ptr = INDEX_op_end;
|
||||
/* we don't forget to fill the last values */
|
||||
|
54
trace-events
54
trace-events
@ -697,35 +697,36 @@ lm32_uart_irq_state(int level) "irq state %d"
|
||||
megasas_init_firmware(uint64_t pa) "pa %" PRIx64 " "
|
||||
megasas_init_queue(uint64_t queue_pa, int queue_len, uint64_t head, uint64_t tail, uint32_t flags) "queue at %" PRIx64 " len %d head %" PRIx64 " tail %" PRIx64 " flags %x"
|
||||
megasas_initq_map_failed(int frame) "scmd %d: failed to map queue"
|
||||
megasas_initq_mapped(uint64_t pa) "queue already mapped at %" PRIx64 ""
|
||||
megasas_initq_mismatch(int queue_len, int fw_cmds) "queue size %d max fw cmds %d"
|
||||
megasas_qf_found(unsigned int index, uint64_t pa) "found mapped frame %x pa %" PRIx64 ""
|
||||
megasas_qf_new(unsigned int index, void *cmd) "return new frame %x cmd %p"
|
||||
megasas_qf_failed(unsigned long pa) "all frames busy for frame %lx"
|
||||
megasas_qf_enqueue(unsigned int index, unsigned int count, uint64_t context, unsigned int tail, int busy) "enqueue frame %x count %d context %" PRIx64 " tail %x busy %d"
|
||||
megasas_qf_update(unsigned int head, unsigned int busy) "update reply queue head %x busy %d"
|
||||
megasas_qf_mapped(unsigned int index) "skip mapped frame %x"
|
||||
megasas_qf_new(unsigned int index, uint64_t frame) "frame %x addr %" PRIx64 ""
|
||||
megasas_qf_busy(unsigned long pa) "all frames busy for frame %lx"
|
||||
megasas_qf_enqueue(unsigned int index, unsigned int count, uint64_t context, unsigned int head, unsigned int tail, int busy) "frame %x count %d context %" PRIx64 " head %x tail %x busy %d"
|
||||
megasas_qf_update(unsigned int head, unsigned int tail, unsigned int busy) "head %x tail %x busy %d"
|
||||
megasas_qf_map_failed(int cmd, unsigned long frame) "scmd %d: frame %lu"
|
||||
megasas_qf_complete_noirq(uint64_t context) "context %" PRIx64 " "
|
||||
megasas_qf_complete(uint64_t context, unsigned int tail, unsigned int offset, int busy, unsigned int doorbell) "context %" PRIx64 " tail %x offset %d busy %d doorbell %x"
|
||||
megasas_qf_complete(uint64_t context, unsigned int head, unsigned int tail, int busy) "context %" PRIx64 " head %x tail %x busy %d"
|
||||
megasas_frame_busy(uint64_t addr) "frame %" PRIx64 " busy"
|
||||
megasas_unhandled_frame_cmd(int cmd, uint8_t frame_cmd) "scmd %d: Unhandled MFI cmd %x"
|
||||
megasas_unhandled_frame_cmd(int cmd, uint8_t frame_cmd) "scmd %d: MFI cmd %x"
|
||||
megasas_handle_scsi(const char *frame, int bus, int dev, int lun, void *sdev, unsigned long size) "%s dev %x/%x/%x sdev %p xfer %lu"
|
||||
megasas_scsi_target_not_present(const char *frame, int bus, int dev, int lun) "%s dev %x/%x/%x target not present"
|
||||
megasas_scsi_target_not_present(const char *frame, int bus, int dev, int lun) "%s dev %x/%x/%x"
|
||||
megasas_scsi_invalid_cdb_len(const char *frame, int bus, int dev, int lun, int len) "%s dev %x/%x/%x invalid cdb len %d"
|
||||
megasas_iov_read_overflow(int cmd, int bytes, int len) "scmd %d: %d/%d bytes"
|
||||
megasas_iov_write_overflow(int cmd, int bytes, int len) "scmd %d: %d/%d bytes"
|
||||
megasas_iov_read_underflow(int cmd, int bytes, int len) "scmd %d: %d/%d bytes"
|
||||
megasas_iov_write_underflow(int cmd, int bytes, int len) "scmd %d: %d/%d bytes"
|
||||
megasas_scsi_req_alloc_failed(const char *frame, int dev, int lun) "%s dev %x/%x req allocation failed"
|
||||
megasas_scsi_req_alloc_failed(const char *frame, int dev, int lun) "%s dev %x/%x"
|
||||
megasas_scsi_read_start(int cmd, int len) "scmd %d: transfer %d bytes of data"
|
||||
megasas_scsi_write_start(int cmd, int len) "scmd %d: transfer %d bytes of data"
|
||||
megasas_scsi_nodata(int cmd) "scmd %d: no data to be transferred"
|
||||
megasas_scsi_complete(int cmd, uint32_t status, int len, int xfer) "scmd %d: finished with status %x, len %u/%u"
|
||||
megasas_command_complete(int cmd, uint32_t status, uint32_t resid) "scmd %d: command completed, status %x, residual %d"
|
||||
megasas_scsi_complete(int cmd, uint32_t status, int len, int xfer) "scmd %d: status %x, len %u/%u"
|
||||
megasas_command_complete(int cmd, uint32_t status, uint32_t resid) "scmd %d: status %x, residual %d"
|
||||
megasas_handle_io(int cmd, const char *frame, int dev, int lun, unsigned long lba, unsigned long count) "scmd %d: %s dev %x/%x lba %lx count %lu"
|
||||
megasas_io_target_not_present(int cmd, const char *frame, int dev, int lun) "scmd %d: %s dev 1/%x/%x LUN not present"
|
||||
megasas_io_read_start(int cmd, unsigned long lba, unsigned long count, unsigned long len) "scmd %d: start LBA %lx %lu blocks (%lu bytes)"
|
||||
megasas_io_write_start(int cmd, unsigned long lba, unsigned long count, unsigned long len) "scmd %d: start LBA %lx %lu blocks (%lu bytes)"
|
||||
megasas_io_complete(int cmd, uint32_t len) "scmd %d: %d bytes completed"
|
||||
megasas_io_complete(int cmd, uint32_t len) "scmd %d: %d bytes"
|
||||
megasas_iovec_sgl_overflow(int cmd, int index, int limit) "scmd %d: iovec count %d limit %d"
|
||||
megasas_iovec_sgl_underflow(int cmd, int index) "scmd %d: iovec count %d"
|
||||
megasas_iovec_sgl_invalid(int cmd, int index, uint64_t pa, uint32_t len) "scmd %d: element %d pa %" PRIx64 " len %u"
|
||||
@ -733,28 +734,29 @@ megasas_iovec_overflow(int cmd, int len, int limit) "scmd %d: len %d limit %d"
|
||||
megasas_iovec_underflow(int cmd, int len, int limit) "scmd %d: len %d limit %d"
|
||||
megasas_handle_dcmd(int cmd, int opcode) "scmd %d: MFI DCMD opcode %x"
|
||||
megasas_finish_dcmd(int cmd, int size) "scmd %d: MFI DCMD wrote %d bytes"
|
||||
megasas_dcmd_req_alloc_failed(int cmd, const char *desc) "scmd %d: %s alloc failed"
|
||||
megasas_dcmd_req_alloc_failed(int cmd, const char *desc) "scmd %d: %s"
|
||||
megasas_dcmd_internal_submit(int cmd, const char *desc, int dev) "scmd %d: %s to dev %d"
|
||||
megasas_dcmd_internal_finish(int cmd, int opcode, int lun) "scmd %d: DCMD finish internal cmd %x lun %d"
|
||||
megasas_dcmd_internal_invalid(int cmd, int opcode) "scmd %d: Invalid internal DCMD %x"
|
||||
megasas_dcmd_internal_finish(int cmd, int opcode, int lun) "scmd %d: cmd %x lun %d"
|
||||
megasas_dcmd_internal_invalid(int cmd, int opcode) "scmd %d: DCMD %x"
|
||||
megasas_dcmd_unhandled(int cmd, int opcode, int len) "scmd %d: opcode %x, len %d"
|
||||
megasas_dcmd_zero_sge(int cmd) "scmd %d: zero DCMD sge count"
|
||||
megasas_dcmd_invalid_sge(int cmd, int count) "scmd %d: invalid DCMD sge count %d"
|
||||
megasas_dcmd_invalid_xfer_len(int cmd, unsigned long size, unsigned long max) "scmd %d: invalid xfer len %ld, max %ld"
|
||||
megasas_dcmd_invalid_sge(int cmd, int count) "scmd %d: DCMD sge count %d"
|
||||
megasas_dcmd_invalid_xfer_len(int cmd, unsigned long size, unsigned long max) "scmd %d: xfer len %ld, max %ld"
|
||||
megasas_dcmd_enter(int cmd, const char *dcmd, int len) "scmd %d: DCMD %s len %d"
|
||||
megasas_dcmd_dummy(int cmd, unsigned long size) "scmd %d: DCMD dummy xfer len %ld"
|
||||
megasas_dcmd_dummy(int cmd, unsigned long size) "scmd %d: xfer len %ld"
|
||||
megasas_dcmd_set_fw_time(int cmd, unsigned long time) "scmd %d: Set FW time %lx"
|
||||
megasas_dcmd_pd_get_list(int cmd, int num, int max, int offset) "scmd %d: DCMD PD get list: %d / %d PDs, size %d"
|
||||
megasas_dcmd_ld_get_list(int cmd, int num, int max) "scmd %d: DCMD LD get list: found %d / %d LDs"
|
||||
megasas_dcmd_ld_get_info(int cmd, int ld_id) "scmd %d: DCMD LD get info for dev %d"
|
||||
megasas_dcmd_pd_get_info(int cmd, int pd_id) "scmd %d: DCMD PD get info for dev %d"
|
||||
megasas_dcmd_pd_list_query(int cmd, int flags) "scmd %d: DCMD PD list query flags %x"
|
||||
megasas_dcmd_ld_list_query(int cmd, int flags) "scmd %d: DCMD LD list query flags %x"
|
||||
megasas_dcmd_ld_get_info(int cmd, int ld_id) "scmd %d: dev %d"
|
||||
megasas_dcmd_ld_list_query(int cmd, int flags) "scmd %d: query flags %x"
|
||||
megasas_dcmd_pd_get_info(int cmd, int pd_id) "scmd %d: dev %d"
|
||||
megasas_dcmd_pd_list_query(int cmd, int flags) "scmd %d: query flags %x"
|
||||
megasas_dcmd_reset_ld(int cmd, int target_id) "scmd %d: dev %d"
|
||||
megasas_dcmd_unsupported(int cmd, unsigned long size) "scmd %d: set properties len %ld"
|
||||
megasas_abort_frame(int cmd, int abort_cmd) "scmd %d: aborting frame %x"
|
||||
megasas_abort_frame(int cmd, int abort_cmd) "scmd %d: frame %x"
|
||||
megasas_abort_no_cmd(int cmd, uint64_t context) "scmd %d: no active command for frame context %" PRIx64 ""
|
||||
megasas_abort_invalid_context(int cmd, uint64_t context, int abort_cmd) "scmd %d: invalid frame context %" PRIx64 " for abort frame %x"
|
||||
megasas_reset(void) "Reset"
|
||||
megasas_reset(int fw_state) "firmware state %x"
|
||||
megasas_init(int sges, int cmds, const char *mode) "Using %d sges, %d cmds, %s mode"
|
||||
megasas_msix_raise(int vector) "vector %d"
|
||||
megasas_msi_raise(int vector) "vector %d"
|
||||
@ -764,9 +766,9 @@ megasas_intr_enabled(void) "Interrupts enabled"
|
||||
megasas_intr_disabled(void) "Interrupts disabled"
|
||||
megasas_msix_enabled(int vector) "vector %d"
|
||||
megasas_msi_enabled(int vector) "vector %d"
|
||||
megasas_mmio_readl(unsigned long addr, uint32_t val) "addr 0x%lx: 0x%x"
|
||||
megasas_mmio_readl(const char *reg, uint32_t val) "reg %s: 0x%x"
|
||||
megasas_mmio_invalid_readl(unsigned long addr) "addr 0x%lx"
|
||||
megasas_mmio_writel(uint32_t addr, uint32_t val) "addr 0x%x: 0x%x"
|
||||
megasas_mmio_writel(const char *reg, uint32_t val) "reg %s: 0x%x"
|
||||
megasas_mmio_invalid_writel(uint32_t addr, uint32_t val) "addr 0x%x: 0x%x"
|
||||
|
||||
# hw/audio/milkymist-ac97.c
|
||||
|
@ -10,12 +10,13 @@ vnc-obj-y += vnc-jobs.o
|
||||
common-obj-y += keymaps.o console.o cursor.o qemu-pixman.o
|
||||
common-obj-y += input.o input-keymap.o input-legacy.o
|
||||
common-obj-$(CONFIG_SPICE) += spice-core.o spice-input.o spice-display.o
|
||||
common-obj-$(CONFIG_SDL) += sdl.o sdl_zoom.o x_keymap.o sdl2.o
|
||||
common-obj-$(CONFIG_SDL) += sdl.mo x_keymap.o
|
||||
common-obj-$(CONFIG_COCOA) += cocoa.o
|
||||
common-obj-$(CONFIG_CURSES) += curses.o
|
||||
common-obj-$(CONFIG_VNC) += $(vnc-obj-y)
|
||||
common-obj-$(CONFIG_GTK) += gtk.o x_keymap.o
|
||||
|
||||
$(obj)/sdl.o $(obj)/sdl_zoom.o $(obj)/sdl2.o: QEMU_CFLAGS += $(SDL_CFLAGS)
|
||||
sdl.mo-objs := sdl.o sdl_zoom.o sdl2.o
|
||||
sdl.mo-cflags := $(SDL_CFLAGS)
|
||||
|
||||
gtk.o-cflags := $(GTK_CFLAGS) $(VTE_CFLAGS)
|
||||
|
9
vl.c
9
vl.c
@ -376,6 +376,10 @@ static QemuOptsList qemu_machine_opts = {
|
||||
.name = PC_MACHINE_MAX_RAM_BELOW_4G,
|
||||
.type = QEMU_OPT_SIZE,
|
||||
.help = "maximum ram below the 4G boundary (32bit boundary)",
|
||||
}, {
|
||||
.name = PC_MACHINE_VMPORT,
|
||||
.type = QEMU_OPT_BOOL,
|
||||
.help = "Enable vmport (pc & q35)",
|
||||
},{
|
||||
.name = "iommu",
|
||||
.type = QEMU_OPT_BOOL,
|
||||
@ -3746,6 +3750,11 @@ int main(int argc, char **argv, char **envp)
|
||||
configure_msg(opts);
|
||||
break;
|
||||
case QEMU_OPTION_dump_vmstate:
|
||||
if (vmstate_dump_file) {
|
||||
fprintf(stderr, "qemu: only one '-dump-vmstate' "
|
||||
"option may be given\n");
|
||||
exit(1);
|
||||
}
|
||||
vmstate_dump_file = fopen(optarg, "w");
|
||||
if (vmstate_dump_file == NULL) {
|
||||
fprintf(stderr, "open %s: %s\n", optarg, strerror(errno));
|
||||
|
Loading…
Reference in New Issue
Block a user