From 1894df02811f6b79ea3ffbf1084599d96f316173 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Wed, 29 Oct 2014 13:00:04 +0100 Subject: scsi: Rename scsi_*_length() to scsi_*_xfer(), add scsi_cdb_length() scsi_cdb_length() does not return the length of the cdb, but the transfersize encoded in the cdb. So rename it to scsi_cdb_xfer() and also rename all other related functions to end with _xfer. We can then add a new scsi_cdb_length() which actually does return the length of the cdb. With that DEBUG_SCSI can now display the correct CDB buffer. Signed-off-by: Hannes Reinecke Signed-off-by: Paolo Bonzini --- include/hw/scsi/scsi.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h index 6bc841ab8b..fd48177fa6 100644 --- a/include/hw/scsi/scsi.h +++ b/include/hw/scsi/scsi.h @@ -239,8 +239,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); -- cgit v1.2.3-55-g7522 From e23d04984a78490d8aaa5c45724a3a334933331f Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Wed, 29 Oct 2014 13:00:08 +0100 Subject: megasas: add MegaRAID SAS 2108 emulation The 2108 chip supports MSI and MSI-X, so update the emulation to support both chips. Signed-off-by: Hannes Reinecke [Make VMStateDescription const. - Paolo] Signed-off-by: Paolo Bonzini --- hw/scsi/megasas.c | 218 +++++++++++++++++++++++++++++++++++++++++------ hw/scsi/mfi.h | 7 ++ include/hw/pci/pci_ids.h | 1 + 3 files changed, 201 insertions(+), 25 deletions(-) (limited to 'include') diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index 3a7e85e75e..7401b6b778 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -31,9 +31,11 @@ #include "mfi.h" -#define MEGASAS_VERSION "1.70" +#define MEGASAS_VERSION_GEN1 "1.70" +#define MEGASAS_VERSION_GEN2 "1.80" #define MEGASAS_MAX_FRAMES 2048 /* Firmware limit at 65535 */ #define MEGASAS_DEFAULT_FRAMES 1000 /* Windows requires this */ +#define MEGASAS_GEN2_DEFAULT_FRAMES 1008 /* Windows requires this */ #define MEGASAS_MAX_SGE 128 /* Firmware limit */ #define MEGASAS_DEFAULT_SGE 80 #define MEGASAS_MAX_SECTORS 0xFFFF /* No real limit */ @@ -91,6 +93,8 @@ typedef struct MegasasState { int intr_mask; int doorbell; int busy; + int diag; + int adp_reset; MegasasCmd *event_cmd; int event_locale; @@ -115,10 +119,26 @@ typedef struct MegasasState { SCSIBus bus; } MegasasState; -#define TYPE_MEGASAS "megasas" +typedef struct MegasasBaseClass { + PCIDeviceClass parent_class; + const char *product_name; + const char *product_version; + int mmio_bar; + int ioport_bar; + int osts; +} MegasasBaseClass; + +#define TYPE_MEGASAS_BASE "megasas-base" +#define TYPE_MEGASAS_GEN1 "megasas" +#define TYPE_MEGASAS_GEN2 "megasas-gen2" #define MEGASAS(obj) \ - OBJECT_CHECK(MegasasState, (obj), TYPE_MEGASAS) + OBJECT_CHECK(MegasasState, (obj), TYPE_MEGASAS_BASE) + +#define MEGASAS_DEVICE_CLASS(oc) \ + OBJECT_CLASS_CHECK(MegasasBaseClass, (oc), TYPE_MEGASAS_BASE) +#define MEGASAS_DEVICE_GET_CLASS(oc) \ + OBJECT_GET_CLASS(MegasasBaseClass, (oc), TYPE_MEGASAS_BASE) #define MEGASAS_INTR_DISABLED_MASK 0xFFFFFFFF @@ -686,6 +706,8 @@ static void megasas_finish_dcmd(MegasasCmd *cmd, uint32_t iov_size) static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd) { PCIDevice *pci_dev = PCI_DEVICE(s); + PCIDeviceClass *pci_class = PCI_DEVICE_GET_CLASS(pci_dev); + MegasasBaseClass *base_class = MEGASAS_DEVICE_GET_CLASS(s); struct mfi_ctrl_info info; size_t dcmd_size = sizeof(info); BusChild *kid; @@ -698,10 +720,10 @@ static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd) return MFI_STAT_INVALID_PARAMETER; } - info.pci.vendor = cpu_to_le16(PCI_VENDOR_ID_LSI_LOGIC); - info.pci.device = cpu_to_le16(PCI_DEVICE_ID_LSI_SAS1078); - info.pci.subvendor = cpu_to_le16(PCI_VENDOR_ID_LSI_LOGIC); - info.pci.subdevice = cpu_to_le16(0x1013); + info.pci.vendor = cpu_to_le16(pci_class->vendor_id); + info.pci.device = cpu_to_le16(pci_class->device_id); + info.pci.subvendor = cpu_to_le16(pci_class->subsystem_vendor_id); + info.pci.subdevice = cpu_to_le16(pci_class->subsystem_id); /* * For some reason the firmware supports @@ -728,11 +750,12 @@ static int megasas_ctrl_get_info(MegasasState *s, MegasasCmd *cmd) num_pd_disks++; } - memcpy(info.product_name, "MegaRAID SAS 8708EM2", 20); + memcpy(info.product_name, base_class->product_name, 24); snprintf(info.serial_number, 32, "%s", s->hba_serial); snprintf(info.package_version, 0x60, "%s-QEMU", QEMU_VERSION); memcpy(info.image_component[0].name, "APP", 3); - memcpy(info.image_component[0].version, MEGASAS_VERSION "-QEMU", 9); + snprintf(info.image_component[0].version, 10, "%s-QEMU", + base_class->product_version); memcpy(info.image_component[0].build_date, "Apr 1 2014", 11); memcpy(info.image_component[0].build_time, "12:34:56", 8); info.image_component_count = 1; @@ -1960,6 +1983,8 @@ static uint64_t megasas_mmio_read(void *opaque, hwaddr addr, unsigned size) { MegasasState *s = opaque; + PCIDevice *pci_dev = PCI_DEVICE(s); + MegasasBaseClass *base_class = MEGASAS_DEVICE_GET_CLASS(s); uint32_t retval = 0; switch (addr) { @@ -1968,14 +1993,14 @@ static uint64_t megasas_mmio_read(void *opaque, hwaddr addr, break; case MFI_OMSG0: case MFI_OSP0: - retval = (megasas_use_msix(s) ? MFI_FWSTATE_MSIX_SUPPORTED : 0) | + retval = (msix_present(pci_dev) ? MFI_FWSTATE_MSIX_SUPPORTED : 0) | (s->fw_state & MFI_FWSTATE_MASK) | ((s->fw_sge & 0xff) << 16) | (s->fw_cmds & 0xFFFF); break; case MFI_OSTS: if (megasas_intr_enabled(s) && s->doorbell) { - retval = MFI_1078_RM | 1; + retval = base_class->osts; } break; case MFI_OMSK: @@ -1984,6 +2009,12 @@ static uint64_t megasas_mmio_read(void *opaque, hwaddr addr, case MFI_ODCR0: retval = s->doorbell; break; + case MFI_DIAG: + retval = s->diag; + break; + case MFI_OSP1: + retval = 15; + break; default: trace_megasas_mmio_invalid_readl(addr); break; @@ -1992,6 +2023,8 @@ static uint64_t megasas_mmio_read(void *opaque, hwaddr addr, return retval; } +static int adp_reset_seq[] = {0x00, 0x04, 0x0b, 0x02, 0x07, 0x0d}; + static void megasas_mmio_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { @@ -2017,6 +2050,10 @@ static void megasas_mmio_write(void *opaque, hwaddr addr, if (val & MFI_FWINIT_MFIMODE) { /* discard MFIs */ } + if (val & MFI_FWINIT_STOP_ADP) { + /* Terminal error, stop processing */ + s->fw_state = MFI_FWSTATE_FAULT; + } break; case MFI_OMSK: s->intr_mask = val; @@ -2036,6 +2073,7 @@ static void megasas_mmio_write(void *opaque, hwaddr addr, } } else { trace_megasas_intr_disabled(); + megasas_soft_reset(s); } break; case MFI_ODCR0: @@ -2057,8 +2095,9 @@ static void megasas_mmio_write(void *opaque, hwaddr addr, break; case MFI_IQPL: /* Received low 32 bits of a 64 bit MFI frame address */ + /* Fallthrough */ case MFI_IQP: - /* Received 32 bit MFI frame address */ + /* Received 64 bit MFI frame address */ frame_addr = (val & ~0x1F); /* Add possible 64 bit offset */ frame_addr |= ((uint64_t)s->frame_hi << 32); @@ -2066,6 +2105,28 @@ static void megasas_mmio_write(void *opaque, hwaddr addr, frame_count = (val >> 1) & 0xF; megasas_handle_frame(s, frame_addr, frame_count); break; + case MFI_SEQ: + /* Magic sequence to start ADP reset */ + if (adp_reset_seq[s->adp_reset] == val) { + s->adp_reset++; + } else { + s->adp_reset = 0; + s->diag = 0; + } + if (s->adp_reset == 6) { + s->diag = MFI_DIAG_WRITE_ENABLE; + } + break; + case MFI_DIAG: + /* ADP reset */ + if ((s->diag & MFI_DIAG_WRITE_ENABLE) && + (val & MFI_DIAG_RESET_ADP)) { + s->diag |= MFI_DIAG_RESET_ADP; + megasas_soft_reset(s); + s->adp_reset = 0; + s->diag = 0; + } + break; default: trace_megasas_mmio_invalid_writel(addr, val); break; @@ -2150,7 +2211,7 @@ static void megasas_scsi_reset(DeviceState *dev) megasas_soft_reset(s); } -static const VMStateDescription vmstate_megasas = { +static const VMStateDescription vmstate_megasas_gen1 = { .name = "megasas", .version_id = 0, .minimum_version_id = 0, @@ -2168,6 +2229,25 @@ static const VMStateDescription vmstate_megasas = { } }; +static const VMStateDescription vmstate_megasas_gen2 = { + .name = "megasas-gen2", + .version_id = 0, + .minimum_version_id = 0, + .minimum_version_id_old = 0, + .fields = (VMStateField[]) { + VMSTATE_PCIE_DEVICE(parent_obj, MegasasState), + VMSTATE_MSIX(parent_obj, MegasasState), + + VMSTATE_INT32(fw_state, MegasasState), + VMSTATE_INT32(intr_mask, MegasasState), + VMSTATE_INT32(doorbell, MegasasState), + VMSTATE_UINT64(reply_queue_pa, MegasasState), + VMSTATE_UINT64(consumer_pa, MegasasState), + VMSTATE_UINT64(producer_pa, MegasasState), + VMSTATE_END_OF_LIST() + } +}; + static void megasas_scsi_uninit(PCIDevice *d) { MegasasState *s = MEGASAS(d); @@ -2195,6 +2275,7 @@ static int megasas_scsi_init(PCIDevice *dev) { DeviceState *d = DEVICE(dev); MegasasState *s = MEGASAS(dev); + MegasasBaseClass *b = MEGASAS_DEVICE_GET_CLASS(s); uint8_t *pci_conf; int i, bar_type; Error *err = NULL; @@ -2218,14 +2299,18 @@ static int megasas_scsi_init(PCIDevice *dev) s->flags &= ~MEGASAS_MASK_USE_MSI; } if (megasas_use_msix(s) && - msix_init(dev, 15, &s->mmio_io, 0, 0x2000, - &s->mmio_io, 0, 0x3800, 0x68)) { + msix_init(dev, 15, &s->mmio_io, b->mmio_bar, 0x2000, + &s->mmio_io, b->mmio_bar, 0x3800, 0x68)) { s->flags &= ~MEGASAS_MASK_USE_MSIX; } + if (pci_is_express(dev)) { + pcie_endpoint_cap_init(dev, 0xa0); + } bar_type = PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64; - pci_register_bar(dev, 0, bar_type, &s->mmio_io); - pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_IO, &s->port_io); + pci_register_bar(dev, b->ioport_bar, + PCI_BASE_ADDRESS_SPACE_IO, &s->port_io); + pci_register_bar(dev, b->mmio_bar, bar_type, &s->mmio_io); pci_register_bar(dev, 3, bar_type, &s->queue_io); if (megasas_use_msix(s)) { @@ -2288,7 +2373,7 @@ megasas_write_config(PCIDevice *pci, uint32_t addr, uint32_t val, int len) msi_write_config(pci, addr, val, len); } -static Property megasas_properties[] = { +static Property megasas_properties_gen1[] = { DEFINE_PROP_UINT32("max_sge", MegasasState, fw_sge, MEGASAS_DEFAULT_SGE), DEFINE_PROP_UINT32("max_cmds", MegasasState, fw_cmds, @@ -2304,36 +2389,119 @@ static Property megasas_properties[] = { DEFINE_PROP_END_OF_LIST(), }; +static Property megasas_properties_gen2[] = { + DEFINE_PROP_UINT32("max_sge", MegasasState, fw_sge, + MEGASAS_DEFAULT_SGE), + DEFINE_PROP_UINT32("max_cmds", MegasasState, fw_cmds, + MEGASAS_GEN2_DEFAULT_FRAMES), + DEFINE_PROP_STRING("hba_serial", MegasasState, hba_serial), + DEFINE_PROP_UINT64("sas_address", MegasasState, sas_addr, 0), + DEFINE_PROP_BIT("use_msi", MegasasState, flags, + MEGASAS_FLAG_USE_MSI, true), + DEFINE_PROP_BIT("use_msix", MegasasState, flags, + MEGASAS_FLAG_USE_MSIX, true), + DEFINE_PROP_BIT("use_jbod", MegasasState, flags, + MEGASAS_FLAG_USE_JBOD, false), + DEFINE_PROP_END_OF_LIST(), +}; + +typedef struct MegasasInfo { + const char *name; + const char *desc; + const char *product_name; + const char *product_version; + uint16_t device_id; + uint16_t subsystem_id; + int ioport_bar; + int mmio_bar; + bool is_express; + int osts; + const VMStateDescription *vmsd; + Property *props; +} MegasasInfo; + +static struct MegasasInfo megasas_devices[] = { + { + .name = TYPE_MEGASAS_GEN1, + .desc = "LSI MegaRAID SAS 1078", + .product_name = "LSI MegaRAID SAS 8708EM2", + .product_version = MEGASAS_VERSION_GEN1, + .device_id = PCI_DEVICE_ID_LSI_SAS1078, + .subsystem_id = 0x1013, + .ioport_bar = 2, + .mmio_bar = 0, + .osts = MFI_1078_RM | 1, + .is_express = false, + .vmsd = &vmstate_megasas_gen1, + .props = megasas_properties_gen1, + },{ + .name = TYPE_MEGASAS_GEN2, + .desc = "LSI MegaRAID SAS 2108", + .product_name = "LSI MegaRAID SAS 9260-8i", + .product_version = MEGASAS_VERSION_GEN2, + .device_id = PCI_DEVICE_ID_LSI_SAS0079, + .subsystem_id = 0x9261, + .ioport_bar = 0, + .mmio_bar = 1, + .osts = MFI_GEN2_RM, + .is_express = true, + .vmsd = &vmstate_megasas_gen2, + .props = megasas_properties_gen2, + } +}; + static void megasas_class_init(ObjectClass *oc, void *data) { DeviceClass *dc = DEVICE_CLASS(oc); PCIDeviceClass *pc = PCI_DEVICE_CLASS(oc); + MegasasBaseClass *e = MEGASAS_DEVICE_CLASS(oc); + const MegasasInfo *info = data; pc->init = megasas_scsi_init; pc->exit = megasas_scsi_uninit; pc->vendor_id = PCI_VENDOR_ID_LSI_LOGIC; - pc->device_id = PCI_DEVICE_ID_LSI_SAS1078; + pc->device_id = info->device_id; pc->subsystem_vendor_id = PCI_VENDOR_ID_LSI_LOGIC; - pc->subsystem_id = 0x1013; + pc->subsystem_id = info->subsystem_id; pc->class_id = PCI_CLASS_STORAGE_RAID; - dc->props = megasas_properties; + pc->is_express = info->is_express; + e->mmio_bar = info->mmio_bar; + e->ioport_bar = info->ioport_bar; + e->osts = info->osts; + e->product_name = info->product_name; + e->product_version = info->product_version; + dc->props = info->props; dc->reset = megasas_scsi_reset; - dc->vmsd = &vmstate_megasas; + dc->vmsd = info->vmsd; set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); - dc->desc = "LSI MegaRAID SAS 1078"; + dc->desc = info->desc; pc->config_write = megasas_write_config; } static const TypeInfo megasas_info = { - .name = TYPE_MEGASAS, + .name = TYPE_MEGASAS_BASE, .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(MegasasState), - .class_init = megasas_class_init, + .class_size = sizeof(MegasasBaseClass), + .abstract = true, }; static void megasas_register_types(void) { + int i; + type_register_static(&megasas_info); + for (i = 0; i < ARRAY_SIZE(megasas_devices); i++) { + const MegasasInfo *info = &megasas_devices[i]; + TypeInfo type_info = {}; + + type_info.name = info->name; + type_info.parent = TYPE_MEGASAS_BASE; + type_info.class_data = (void *)info; + type_info.class_init = megasas_class_init; + + type_register(&type_info); + } } type_init(megasas_register_types) diff --git a/hw/scsi/mfi.h b/hw/scsi/mfi.h index 455c96b782..29d41775d4 100644 --- a/hw/scsi/mfi.h +++ b/hw/scsi/mfi.h @@ -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, diff --git a/include/hw/pci/pci_ids.h b/include/hw/pci/pci_ids.h index e597070ab8..321d622b78 100644 --- a/include/hw/pci/pci_ids.h +++ b/include/hw/pci/pci_ids.h @@ -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 -- cgit v1.2.3-55-g7522 From 8d72db68fe7b45c7e01f815c4ac3e6c7ac0e26c1 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Wed, 29 Oct 2014 13:00:11 +0100 Subject: megasas: Clear unit attention on initial reset The EFI firmware doesn't handle unit attentions properly, so we need to clear the Power On/Reset unit attention upon initial reset. Signed-off-by: Hannes Reinecke Signed-off-by: Paolo Bonzini --- hw/scsi/megasas.c | 18 +++++++++++++++++- hw/scsi/scsi-bus.c | 2 +- include/hw/scsi/scsi.h | 1 + trace-events | 2 +- 4 files changed, 20 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/hw/scsi/megasas.c b/hw/scsi/megasas.c index 58e29aed71..57d52885b7 100644 --- a/hw/scsi/megasas.c +++ b/hw/scsi/megasas.c @@ -2202,11 +2202,26 @@ static void megasas_soft_reset(MegasasState *s) int i; MegasasCmd *cmd; - trace_megasas_reset(); + trace_megasas_reset(s->fw_state); for (i = 0; i < s->fw_cmds; i++) { cmd = &s->frames[i]; megasas_abort_command(cmd); } + if (s->fw_state == MFI_FWSTATE_READY) { + BusChild *kid; + + /* + * The EFI firmware doesn't handle UA, + * so we need to clear the Power On/Reset UA + * after the initial reset. + */ + QTAILQ_FOREACH(kid, &s->bus.qbus.children, sibling) { + SCSIDevice *sdev = DO_UPCAST(SCSIDevice, qdev, kid->child); + + sdev->unit_attention = SENSE_CODE(NO_SENSE); + scsi_device_unit_attention_reported(sdev); + } + } megasas_reset_frames(s); s->reply_queue_len = s->fw_cmds; s->reply_queue_pa = 0; @@ -2334,6 +2349,7 @@ static int megasas_scsi_init(PCIDevice *dev) msix_vector_use(dev, 0); } + s->fw_state = MFI_FWSTATE_READY; if (!s->sas_addr) { s->sas_addr = ((NAA_LOCALLY_ASSIGNED_ID << 24) | IEEE_COMPANY_LOCALLY_ASSIGNED) << 36; diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c index 6fce8471d4..6376b88722 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c @@ -84,7 +84,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) { diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h index fd48177fa6..f4aabfd0e7 100644 --- a/include/hw/scsi/scsi.h +++ b/include/hw/scsi/scsi.h @@ -272,6 +272,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); diff --git a/trace-events b/trace-events index cd149cb3f7..2ceb8e426c 100644 --- a/trace-events +++ b/trace-events @@ -754,7 +754,7 @@ megasas_dcmd_unsupported(int cmd, unsigned long size) "scmd %d: set properties l 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" -- cgit v1.2.3-55-g7522 From b154537ad07598377ebf98252fb7d2aff127983b Mon Sep 17 00:00:00 2001 From: Dr. David Alan Gilbert Date: Fri, 3 Oct 2014 17:33:37 -0400 Subject: -machine vmport=off: Allow disabling of VMWare ioport emulation This is a pc & q35 only machine opt. VMWare apparently doesn't like running under QEMU due to our incomplete emulation of it's special IO Port. This adds a pc & q35 property to allow it to be turned off. Signed-off-by: Dr. David Alan Gilbert Signed-off-by: Don Slutz Signed-off-by: Paolo Bonzini --- hw/i386/pc.c | 19 +++++++++++++++++++ hw/i386/pc_piix.c | 4 ++-- hw/i386/pc_q35.c | 3 ++- include/hw/i386/pc.h | 2 ++ qemu-options.hx | 3 +++ vl.c | 4 ++++ 6 files changed, 32 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 61aba9fc54..889e888c6a 100644 --- a/hw/i386/pc.c +++ b/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) diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 91a20cb8f4..1cda5dd068 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -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); diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c index e225c6d110..4d9e3cd69d 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -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); diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index c4ee520e20..2545268a6c 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -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: diff --git a/qemu-options.hx b/qemu-options.hx index 1e7d5b8362..da9851d483 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -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 diff --git a/vl.c b/vl.c index f6b3546942..f5721d1f25 100644 --- a/vl.c +++ b/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, -- cgit v1.2.3-55-g7522 From e4dc3f5909ab90520bc1a27b381c3017ff65ed68 Mon Sep 17 00:00:00 2001 From: Nikunj A Dadhania Date: Mon, 15 Sep 2014 09:28:23 +0530 Subject: Add skip_dump flag to ignore memory region during dump The PCI MMIO might be disabled or the device in the reset state. Make sure we do not dump these memory regions. Signed-off-by: Nikunj A Dadhania Acked-by: Alex Williamson CC: Paolo Bonzini Signed-off-by: Paolo Bonzini --- hw/misc/vfio.c | 1 + include/exec/memory.h | 19 +++++++++++++++++++ memory.c | 10 ++++++++++ memory_mapping.c | 3 ++- 4 files changed, 32 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c index b5e798173b..fd318a122d 100644 --- a/hw/misc/vfio.c +++ b/hw/misc/vfio.c @@ -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. */ diff --git a/include/exec/memory.h b/include/exec/memory.h index 072aad2239..74a58b4883 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -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 * diff --git a/memory.c b/memory.c index 30f77b2a6a..0f4fdc7db7 100644 --- a/memory.c +++ b/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; diff --git a/memory_mapping.c b/memory_mapping.c index 87a6ed5c8e..7b69801cb8 100644 --- a/memory_mapping.c +++ b/memory_mapping.c @@ -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; } -- cgit v1.2.3-55-g7522 From fb7b5c0df6e3c501973ce4d57eb2b1d4344a519d Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 17 Sep 2013 15:09:15 +0200 Subject: scsi: devirtualize unrealize of SCSI devices All implementations are the same. Signed-off-by: Paolo Bonzini --- hw/scsi/scsi-bus.c | 12 +++--------- hw/scsi/scsi-disk.c | 12 ------------ hw/scsi/scsi-generic.c | 7 ------- include/hw/scsi/scsi.h | 1 - 4 files changed, 3 insertions(+), 29 deletions(-) (limited to 'include') diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c index 6376b88722..24f7b74ae8 100644 --- a/hw/scsi/scsi-bus.c +++ b/hw/scsi/scsi-bus.c @@ -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) { @@ -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 */ diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c index 7b58488b0e..2f75d7d51c 100644 --- a/hw/scsi/scsi-disk.c +++ b/hw/scsi/scsi-disk.c @@ -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; @@ -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"; diff --git a/hw/scsi/scsi-generic.c b/hw/scsi/scsi-generic.c index f2e53afd09..6b9e4e1ef9 100644 --- a/hw/scsi/scsi-generic.c +++ b/hw/scsi/scsi-generic.c @@ -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"; diff --git a/include/hw/scsi/scsi.h b/include/hw/scsi/scsi.h index f4aabfd0e7..cdaf0f8eb7 100644 --- a/include/hw/scsi/scsi.h +++ b/include/hw/scsi/scsi.h @@ -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, -- cgit v1.2.3-55-g7522