10 changes: 10 additions & 0 deletions backends/cryptodev.c
Expand Up @@ -191,6 +191,11 @@ static int cryptodev_backend_account(CryptoDevBackend *backend,
if (algtype == QCRYPTODEV_BACKEND_ALG_ASYM) {
CryptoDevBackendAsymOpInfo *asym_op_info = op_info->u.asym_op_info;
len = asym_op_info->src_len;

if (unlikely(!backend->asym_stat)) {
error_report("cryptodev: Unexpected asym operation");
return -VIRTIO_CRYPTO_NOTSUPP;
}
switch (op_info->op_code) {
case VIRTIO_CRYPTO_AKCIPHER_ENCRYPT:
CryptodevAsymStatIncEncrypt(backend, len);
Expand All @@ -210,6 +215,11 @@ static int cryptodev_backend_account(CryptoDevBackend *backend,
} else if (algtype == QCRYPTODEV_BACKEND_ALG_SYM) {
CryptoDevBackendSymOpInfo *sym_op_info = op_info->u.sym_op_info;
len = sym_op_info->src_len;

if (unlikely(!backend->sym_stat)) {
error_report("cryptodev: Unexpected sym operation");
return -VIRTIO_CRYPTO_NOTSUPP;
}
switch (op_info->op_code) {
case VIRTIO_CRYPTO_CIPHER_ENCRYPT:
CryptodevSymStatIncEncrypt(backend, len);
Expand Down
11 changes: 6 additions & 5 deletions hw/block/xen-block.c
Expand Up @@ -763,22 +763,22 @@ static XenBlockDrive *xen_block_drive_create(const char *id,
drive = g_new0(XenBlockDrive, 1);
drive->id = g_strdup(id);

file_layer = qdict_new();
driver_layer = qdict_new();

rc = stat(filename, &st);
if (rc) {
error_setg_errno(errp, errno, "Could not stat file '%s'", filename);
goto done;
}

file_layer = qdict_new();
driver_layer = qdict_new();

if (S_ISBLK(st.st_mode)) {
qdict_put_str(file_layer, "driver", "host_device");
} else {
qdict_put_str(file_layer, "driver", "file");
}

qdict_put_str(file_layer, "filename", filename);
g_free(filename);

if (mode && *mode != 'w') {
qdict_put_bool(file_layer, "read-only", true);
Expand Down Expand Up @@ -813,7 +813,6 @@ static XenBlockDrive *xen_block_drive_create(const char *id,
qdict_put_str(file_layer, "locking", "off");

qdict_put_str(driver_layer, "driver", driver);
g_free(driver);

qdict_put(driver_layer, "file", file_layer);

Expand All @@ -824,6 +823,8 @@ static XenBlockDrive *xen_block_drive_create(const char *id,
qobject_unref(driver_layer);

done:
g_free(filename);
g_free(driver);
if (*errp) {
xen_block_drive_destroy(drive, NULL);
return NULL;
Expand Down
23 changes: 14 additions & 9 deletions hw/i386/intel_iommu.c
Expand Up @@ -755,6 +755,8 @@ static int vtd_get_pdire_from_pdir_table(dma_addr_t pasid_dir_base,
return -VTD_FR_PASID_TABLE_INV;
}

pdire->val = le64_to_cpu(pdire->val);

return 0;
}

Expand All @@ -779,6 +781,9 @@ static int vtd_get_pe_in_pasid_leaf_table(IntelIOMMUState *s,
pe, entry_size, MEMTXATTRS_UNSPECIFIED)) {
return -VTD_FR_PASID_TABLE_INV;
}
for (size_t i = 0; i < ARRAY_SIZE(pe->val); i++) {
pe->val[i] = le64_to_cpu(pe->val[i]);
}

/* Do translation type check */
if (!vtd_pe_type_check(x86_iommu, pe)) {
Expand Down Expand Up @@ -3322,29 +3327,29 @@ static int vtd_irte_get(IntelIOMMUState *iommu, uint16_t index,
return -VTD_FR_IR_ROOT_INVAL;
}

trace_vtd_ir_irte_get(index, le64_to_cpu(entry->data[1]),
le64_to_cpu(entry->data[0]));
entry->data[0] = le64_to_cpu(entry->data[0]);
entry->data[1] = le64_to_cpu(entry->data[1]);

trace_vtd_ir_irte_get(index, entry->data[1], entry->data[0]);

if (!entry->irte.present) {
error_report_once("%s: detected non-present IRTE "
"(index=%u, high=0x%" PRIx64 ", low=0x%" PRIx64 ")",
__func__, index, le64_to_cpu(entry->data[1]),
le64_to_cpu(entry->data[0]));
__func__, index, entry->data[1], entry->data[0]);
return -VTD_FR_IR_ENTRY_P;
}

if (entry->irte.__reserved_0 || entry->irte.__reserved_1 ||
entry->irte.__reserved_2) {
error_report_once("%s: detected non-zero reserved IRTE "
"(index=%u, high=0x%" PRIx64 ", low=0x%" PRIx64 ")",
__func__, index, le64_to_cpu(entry->data[1]),
le64_to_cpu(entry->data[0]));
__func__, index, entry->data[1], entry->data[0]);
return -VTD_FR_IR_IRTE_RSVD;
}

if (sid != X86_IOMMU_SID_INVALID) {
/* Validate IRTE SID */
source_id = le32_to_cpu(entry->irte.source_id);
source_id = entry->irte.source_id;
switch (entry->irte.sid_vtype) {
case VTD_SVT_NONE:
break;
Expand Down Expand Up @@ -3398,7 +3403,7 @@ static int vtd_remap_irq_get(IntelIOMMUState *iommu, uint16_t index,
irq->trigger_mode = irte.irte.trigger_mode;
irq->vector = irte.irte.vector;
irq->delivery_mode = irte.irte.delivery_mode;
irq->dest = le32_to_cpu(irte.irte.dest_id);
irq->dest = irte.irte.dest_id;
if (!iommu->intr_eime) {
#define VTD_IR_APIC_DEST_MASK (0xff00ULL)
#define VTD_IR_APIC_DEST_SHIFT (8)
Expand Down Expand Up @@ -3453,7 +3458,7 @@ static int vtd_interrupt_remap_msi(IntelIOMMUState *iommu,
goto out;
}

index = addr.addr.index_h << 15 | le16_to_cpu(addr.addr.index_l);
index = addr.addr.index_h << 15 | addr.addr.index_l;

#define VTD_IR_MSI_DATA_SUBHANDLE (0x0000ffff)
#define VTD_IR_MSI_DATA_RESERVED (0xffff0000)
Expand Down
9 changes: 9 additions & 0 deletions hw/i386/intel_iommu_internal.h
Expand Up @@ -321,12 +321,21 @@ typedef enum VTDFaultReason {

/* Interrupt Entry Cache Invalidation Descriptor: VT-d 6.5.2.7. */
struct VTDInvDescIEC {
#if HOST_BIG_ENDIAN
uint64_t reserved_2:16;
uint64_t index:16; /* Start index to invalidate */
uint64_t index_mask:5; /* 2^N for continuous int invalidation */
uint64_t resved_1:22;
uint64_t granularity:1; /* If set, it's global IR invalidation */
uint64_t type:4; /* Should always be 0x4 */
#else
uint32_t type:4; /* Should always be 0x4 */
uint32_t granularity:1; /* If set, it's global IR invalidation */
uint32_t resved_1:22;
uint32_t index_mask:5; /* 2^N for continuous int invalidation */
uint32_t index:16; /* Start index to invalidate */
uint32_t reserved_2:16;
#endif
};
typedef struct VTDInvDescIEC VTDInvDescIEC;

Expand Down
4 changes: 2 additions & 2 deletions hw/i386/kvm/xen_evtchn.c
Expand Up @@ -1587,7 +1587,7 @@ static int allocate_pirq(XenEvtchnState *s, int type, int gsi)
found:
pirq_inuse_word(s, pirq) |= pirq_inuse_bit(pirq);
if (gsi >= 0) {
assert(gsi <= IOAPIC_NUM_PINS);
assert(gsi < IOAPIC_NUM_PINS);
s->gsi_pirq[gsi] = pirq;
}
s->pirq[pirq].gsi = gsi;
Expand All @@ -1601,7 +1601,7 @@ bool xen_evtchn_set_gsi(int gsi, int level)

assert(qemu_mutex_iothread_locked());

if (!s || gsi < 0 || gsi > IOAPIC_NUM_PINS) {
if (!s || gsi < 0 || gsi >= IOAPIC_NUM_PINS) {
return false;
}

Expand Down
2 changes: 1 addition & 1 deletion hw/i386/x86-iommu.c
Expand Up @@ -63,7 +63,7 @@ void x86_iommu_irq_to_msi_message(X86IOMMUIrq *irq, MSIMessage *msg_out)
msg.redir_hint = irq->redir_hint;
msg.dest = irq->dest;
msg.__addr_hi = irq->dest & 0xffffff00;
msg.__addr_head = cpu_to_le32(0xfee);
msg.__addr_head = 0xfee;
/* Keep this from original MSI address bits */
msg.__not_used = irq->msi_addr_last_bits;

Expand Down
15 changes: 13 additions & 2 deletions hw/pci/pci_host.c
Expand Up @@ -62,6 +62,17 @@ static void pci_adjust_config_limit(PCIBus *bus, uint32_t *limit)
}
}

static bool is_pci_dev_ejected(PCIDevice *pci_dev)
{
/*
* device unplug was requested and the guest acked it,
* so we stop responding config accesses even if the
* device is not deleted (failover flow)
*/
return pci_dev && pci_dev->partially_hotplugged &&
!pci_dev->qdev.pending_deleted_event;
}

void pci_host_config_write_common(PCIDevice *pci_dev, uint32_t addr,
uint32_t limit, uint32_t val, uint32_t len)
{
Expand All @@ -75,7 +86,7 @@ void pci_host_config_write_common(PCIDevice *pci_dev, uint32_t addr,
* allowing direct removal of unexposed functions.
*/
if ((pci_dev->qdev.hotplugged && !pci_get_function_0(pci_dev)) ||
!pci_dev->has_power) {
!pci_dev->has_power || is_pci_dev_ejected(pci_dev)) {
return;
}

Expand All @@ -100,7 +111,7 @@ uint32_t pci_host_config_read_common(PCIDevice *pci_dev, uint32_t addr,
* allowing direct removal of unexposed functions.
*/
if ((pci_dev->qdev.hotplugged && !pci_get_function_0(pci_dev)) ||
!pci_dev->has_power) {
!pci_dev->has_power || is_pci_dev_ejected(pci_dev)) {
return ~0x0;
}

Expand Down
2 changes: 2 additions & 0 deletions hw/virtio/vhost.c
Expand Up @@ -2059,6 +2059,8 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings)
event_notifier_test_and_clear(
&hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier);
event_notifier_test_and_clear(&vdev->config_notifier);
event_notifier_cleanup(
&hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier);

trace_vhost_dev_stop(hdev, vdev->name, vrings);

Expand Down
5 changes: 5 additions & 0 deletions hw/virtio/virtio-crypto.c
Expand Up @@ -635,6 +635,11 @@ virtio_crypto_sym_op_helper(VirtIODevice *vdev,
return NULL;
}

if (unlikely(src_len != dst_len)) {
virtio_error(vdev, "sym request src len is different from dst len");
return NULL;
}

max_len = (uint64_t)iv_len + aad_len + src_len + dst_len + hash_result_len;
if (unlikely(max_len > vcrypto->conf.max_size)) {
virtio_error(vdev, "virtio-crypto too big length");
Expand Down
4 changes: 3 additions & 1 deletion hw/virtio/virtio-iommu.c
Expand Up @@ -727,13 +727,15 @@ static void virtio_iommu_handle_command(VirtIODevice *vdev, VirtQueue *vq)
VirtIOIOMMU *s = VIRTIO_IOMMU(vdev);
struct virtio_iommu_req_head head;
struct virtio_iommu_req_tail tail = {};
size_t output_size = sizeof(tail), sz;
VirtQueueElement *elem;
unsigned int iov_cnt;
struct iovec *iov;
void *buf = NULL;
size_t sz;

for (;;) {
size_t output_size = sizeof(tail);

elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
if (!elem) {
return;
Expand Down
50 changes: 26 additions & 24 deletions include/hw/i386/intel_iommu.h
Expand Up @@ -178,37 +178,39 @@ enum {
union VTD_IR_TableEntry {
struct {
#if HOST_BIG_ENDIAN
uint32_t __reserved_1:8; /* Reserved 1 */
uint32_t vector:8; /* Interrupt Vector */
uint32_t irte_mode:1; /* IRTE Mode */
uint32_t __reserved_0:3; /* Reserved 0 */
uint32_t __avail:4; /* Available spaces for software */
uint32_t delivery_mode:3; /* Delivery Mode */
uint32_t trigger_mode:1; /* Trigger Mode */
uint32_t redir_hint:1; /* Redirection Hint */
uint32_t dest_mode:1; /* Destination Mode */
uint32_t fault_disable:1; /* Fault Processing Disable */
uint32_t present:1; /* Whether entry present/available */
uint64_t dest_id:32; /* Destination ID */
uint64_t __reserved_1:8; /* Reserved 1 */
uint64_t vector:8; /* Interrupt Vector */
uint64_t irte_mode:1; /* IRTE Mode */
uint64_t __reserved_0:3; /* Reserved 0 */
uint64_t __avail:4; /* Available spaces for software */
uint64_t delivery_mode:3; /* Delivery Mode */
uint64_t trigger_mode:1; /* Trigger Mode */
uint64_t redir_hint:1; /* Redirection Hint */
uint64_t dest_mode:1; /* Destination Mode */
uint64_t fault_disable:1; /* Fault Processing Disable */
uint64_t present:1; /* Whether entry present/available */
#else
uint32_t present:1; /* Whether entry present/available */
uint32_t fault_disable:1; /* Fault Processing Disable */
uint32_t dest_mode:1; /* Destination Mode */
uint32_t redir_hint:1; /* Redirection Hint */
uint32_t trigger_mode:1; /* Trigger Mode */
uint32_t delivery_mode:3; /* Delivery Mode */
uint32_t __avail:4; /* Available spaces for software */
uint32_t __reserved_0:3; /* Reserved 0 */
uint32_t irte_mode:1; /* IRTE Mode */
uint32_t vector:8; /* Interrupt Vector */
uint32_t __reserved_1:8; /* Reserved 1 */
uint64_t present:1; /* Whether entry present/available */
uint64_t fault_disable:1; /* Fault Processing Disable */
uint64_t dest_mode:1; /* Destination Mode */
uint64_t redir_hint:1; /* Redirection Hint */
uint64_t trigger_mode:1; /* Trigger Mode */
uint64_t delivery_mode:3; /* Delivery Mode */
uint64_t __avail:4; /* Available spaces for software */
uint64_t __reserved_0:3; /* Reserved 0 */
uint64_t irte_mode:1; /* IRTE Mode */
uint64_t vector:8; /* Interrupt Vector */
uint64_t __reserved_1:8; /* Reserved 1 */
uint64_t dest_id:32; /* Destination ID */
#endif
uint32_t dest_id; /* Destination ID */
uint16_t source_id; /* Source-ID */
#if HOST_BIG_ENDIAN
uint64_t __reserved_2:44; /* Reserved 2 */
uint64_t sid_vtype:2; /* Source-ID Validation Type */
uint64_t sid_q:2; /* Source-ID Qualifier */
uint64_t source_id:16; /* Source-ID */
#else
uint64_t source_id:16; /* Source-ID */
uint64_t sid_q:2; /* Source-ID Qualifier */
uint64_t sid_vtype:2; /* Source-ID Validation Type */
uint64_t __reserved_2:44; /* Reserved 2 */
Expand Down
50 changes: 26 additions & 24 deletions include/hw/i386/x86-iommu.h
Expand Up @@ -87,40 +87,42 @@ struct X86IOMMU_MSIMessage {
union {
struct {
#if HOST_BIG_ENDIAN
uint32_t __addr_head:12; /* 0xfee */
uint32_t dest:8;
uint32_t __reserved:8;
uint32_t redir_hint:1;
uint32_t dest_mode:1;
uint32_t __not_used:2;
uint64_t __addr_hi:32;
uint64_t __addr_head:12; /* 0xfee */
uint64_t dest:8;
uint64_t __reserved:8;
uint64_t redir_hint:1;
uint64_t dest_mode:1;
uint64_t __not_used:2;
#else
uint32_t __not_used:2;
uint32_t dest_mode:1;
uint32_t redir_hint:1;
uint32_t __reserved:8;
uint32_t dest:8;
uint32_t __addr_head:12; /* 0xfee */
uint64_t __not_used:2;
uint64_t dest_mode:1;
uint64_t redir_hint:1;
uint64_t __reserved:8;
uint64_t dest:8;
uint64_t __addr_head:12; /* 0xfee */
uint64_t __addr_hi:32;
#endif
uint32_t __addr_hi;
} QEMU_PACKED;
uint64_t msi_addr;
};
union {
struct {
#if HOST_BIG_ENDIAN
uint16_t trigger_mode:1;
uint16_t level:1;
uint16_t __resved:3;
uint16_t delivery_mode:3;
uint16_t vector:8;
uint32_t __resved1:16;
uint32_t trigger_mode:1;
uint32_t level:1;
uint32_t __resved:3;
uint32_t delivery_mode:3;
uint32_t vector:8;
#else
uint16_t vector:8;
uint16_t delivery_mode:3;
uint16_t __resved:3;
uint16_t level:1;
uint16_t trigger_mode:1;
uint32_t vector:8;
uint32_t delivery_mode:3;
uint32_t __resved:3;
uint32_t level:1;
uint32_t trigger_mode:1;
uint32_t __resved1:16;
#endif
uint16_t __resved1;
} QEMU_PACKED;
uint32_t msi_data;
};
Expand Down