mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-06 01:03:55 -06:00
virtio,pc,pci: features, cleanups
infrastructure for vhost-vdpa shadow work piix south bridge rework reconnect for vhost-user-scsi dummy ACPI QTG DSM for cxl tests, cleanups, fixes all over the place Signed-off-by: Michael S. Tsirkin <mst@redhat.com> -----BEGIN PGP SIGNATURE----- iQFDBAABCAAtFiEEXQn9CHHI+FuUyooNKB8NuNKNVGkFAmU06PMPHG1zdEByZWRo YXQuY29tAAoJECgfDbjSjVRpNIsH/0DlKti86VZLJ6PbNqsnKxoK2gg05TbEhPZU pQ+RPDaCHpFBsLC5qsoMJwvaEQFe0e49ZFemw7bXRzBxgmbbNnZ9ArCIPqT+rvQd 7UBmyC+kacVyybZatq69aK2BHKFtiIRlT78d9Izgtjmp8V7oyKoz14Esh8wkE+FT ypHUa70Addi6alNm6BVkm7bxZxi0Wrmf3THqF8ViYvufzHKl7JR5e17fKWEG0BqV 9W7AeHMnzJ7jkTvBGUw7g5EbzFn7hPLTbO4G/VW97k0puS4WRX5aIMkVhUazsRIa zDOuXCCskUWuRapiCwY0E4g7cCaT8/JR6JjjBaTgkjJgvo5Y8Eg= =ILek -----END PGP SIGNATURE----- Merge tag 'for_upstream' of https://git.kernel.org/pub/scm/virt/kvm/mst/qemu into staging virtio,pc,pci: features, cleanups infrastructure for vhost-vdpa shadow work piix south bridge rework reconnect for vhost-user-scsi dummy ACPI QTG DSM for cxl tests, cleanups, fixes all over the place Signed-off-by: Michael S. Tsirkin <mst@redhat.com> # -----BEGIN PGP SIGNATURE----- # # iQFDBAABCAAtFiEEXQn9CHHI+FuUyooNKB8NuNKNVGkFAmU06PMPHG1zdEByZWRo # YXQuY29tAAoJECgfDbjSjVRpNIsH/0DlKti86VZLJ6PbNqsnKxoK2gg05TbEhPZU # pQ+RPDaCHpFBsLC5qsoMJwvaEQFe0e49ZFemw7bXRzBxgmbbNnZ9ArCIPqT+rvQd # 7UBmyC+kacVyybZatq69aK2BHKFtiIRlT78d9Izgtjmp8V7oyKoz14Esh8wkE+FT # ypHUa70Addi6alNm6BVkm7bxZxi0Wrmf3THqF8ViYvufzHKl7JR5e17fKWEG0BqV # 9W7AeHMnzJ7jkTvBGUw7g5EbzFn7hPLTbO4G/VW97k0puS4WRX5aIMkVhUazsRIa # zDOuXCCskUWuRapiCwY0E4g7cCaT8/JR6JjjBaTgkjJgvo5Y8Eg= # =ILek # -----END PGP SIGNATURE----- # gpg: Signature made Sun 22 Oct 2023 02:18:43 PDT # gpg: using RSA key 5D09FD0871C8F85B94CA8A0D281F0DB8D28D5469 # gpg: issuer "mst@redhat.com" # gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>" [full] # gpg: aka "Michael S. Tsirkin <mst@redhat.com>" [full] # Primary key fingerprint: 0270 606B 6F3C DF3D 0B17 0970 C350 3912 AFBE 8E67 # Subkey fingerprint: 5D09 FD08 71C8 F85B 94CA 8A0D 281F 0DB8 D28D 5469 * tag 'for_upstream' of https://git.kernel.org/pub/scm/virt/kvm/mst/qemu: (62 commits) intel-iommu: Report interrupt remapping faults, fix return value MAINTAINERS: Add include/hw/intc/i8259.h to the PC chip section vhost-user: Fix protocol feature bit conflict tests/acpi: Update DSDT.cxl with QTG DSM hw/cxl: Add QTG _DSM support for ACPI0017 device tests/acpi: Allow update of DSDT.cxl hw/i386/cxl: ensure maxram is greater than ram size for calculating cxl range vhost-user: fix lost reconnect vhost-user-scsi: start vhost when guest kicks vhost-user-scsi: support reconnect to backend vhost: move and rename the conn retry times vhost-user-common: send get_inflight_fd once hw/i386/pc_piix: Make PIIX4 south bridge usable in PC machine hw/isa/piix: Implement multi-process QEMU support also for PIIX4 hw/isa/piix: Resolve duplicate code regarding PCI interrupt wiring hw/isa/piix: Reuse PIIX3's PCI interrupt triggering in PIIX4 hw/isa/piix: Rename functions to be shared for PCI interrupt triggering hw/isa/piix: Reuse PIIX3 base class' realize method in PIIX4 hw/isa/piix: Share PIIX3's base class with PIIX4 hw/isa/piix: Harmonize names of reset control memory regions ... Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
commit
1b4a5a20da
43 changed files with 1218 additions and 836 deletions
|
@ -469,21 +469,12 @@ static void vtd_set_frcd_and_update_ppf(IntelIOMMUState *s, uint16_t index)
|
|||
|
||||
/* Must not update F field now, should be done later */
|
||||
static void vtd_record_frcd(IntelIOMMUState *s, uint16_t index,
|
||||
uint16_t source_id, hwaddr addr,
|
||||
VTDFaultReason fault, bool is_write,
|
||||
bool is_pasid, uint32_t pasid)
|
||||
uint64_t hi, uint64_t lo)
|
||||
{
|
||||
uint64_t hi = 0, lo;
|
||||
hwaddr frcd_reg_addr = DMAR_FRCD_REG_OFFSET + (((uint64_t)index) << 4);
|
||||
|
||||
assert(index < DMAR_FRCD_REG_NR);
|
||||
|
||||
lo = VTD_FRCD_FI(addr);
|
||||
hi = VTD_FRCD_SID(source_id) | VTD_FRCD_FR(fault) |
|
||||
VTD_FRCD_PV(pasid) | VTD_FRCD_PP(is_pasid);
|
||||
if (!is_write) {
|
||||
hi |= VTD_FRCD_T;
|
||||
}
|
||||
vtd_set_quad_raw(s, frcd_reg_addr, lo);
|
||||
vtd_set_quad_raw(s, frcd_reg_addr + 8, hi);
|
||||
|
||||
|
@ -509,17 +500,11 @@ static bool vtd_try_collapse_fault(IntelIOMMUState *s, uint16_t source_id)
|
|||
}
|
||||
|
||||
/* Log and report an DMAR (address translation) fault to software */
|
||||
static void vtd_report_dmar_fault(IntelIOMMUState *s, uint16_t source_id,
|
||||
hwaddr addr, VTDFaultReason fault,
|
||||
bool is_write, bool is_pasid,
|
||||
uint32_t pasid)
|
||||
static void vtd_report_frcd_fault(IntelIOMMUState *s, uint64_t source_id,
|
||||
uint64_t hi, uint64_t lo)
|
||||
{
|
||||
uint32_t fsts_reg = vtd_get_long_raw(s, DMAR_FSTS_REG);
|
||||
|
||||
assert(fault < VTD_FR_MAX);
|
||||
|
||||
trace_vtd_dmar_fault(source_id, fault, addr, is_write);
|
||||
|
||||
if (fsts_reg & VTD_FSTS_PFO) {
|
||||
error_report_once("New fault is not recorded due to "
|
||||
"Primary Fault Overflow");
|
||||
|
@ -539,8 +524,7 @@ static void vtd_report_dmar_fault(IntelIOMMUState *s, uint16_t source_id,
|
|||
return;
|
||||
}
|
||||
|
||||
vtd_record_frcd(s, s->next_frcd_reg, source_id, addr, fault,
|
||||
is_write, is_pasid, pasid);
|
||||
vtd_record_frcd(s, s->next_frcd_reg, hi, lo);
|
||||
|
||||
if (fsts_reg & VTD_FSTS_PPF) {
|
||||
error_report_once("There are pending faults already, "
|
||||
|
@ -565,6 +549,40 @@ static void vtd_report_dmar_fault(IntelIOMMUState *s, uint16_t source_id,
|
|||
}
|
||||
}
|
||||
|
||||
/* Log and report an DMAR (address translation) fault to software */
|
||||
static void vtd_report_dmar_fault(IntelIOMMUState *s, uint16_t source_id,
|
||||
hwaddr addr, VTDFaultReason fault,
|
||||
bool is_write, bool is_pasid,
|
||||
uint32_t pasid)
|
||||
{
|
||||
uint64_t hi, lo;
|
||||
|
||||
assert(fault < VTD_FR_MAX);
|
||||
|
||||
trace_vtd_dmar_fault(source_id, fault, addr, is_write);
|
||||
|
||||
lo = VTD_FRCD_FI(addr);
|
||||
hi = VTD_FRCD_SID(source_id) | VTD_FRCD_FR(fault) |
|
||||
VTD_FRCD_PV(pasid) | VTD_FRCD_PP(is_pasid);
|
||||
if (!is_write) {
|
||||
hi |= VTD_FRCD_T;
|
||||
}
|
||||
|
||||
vtd_report_frcd_fault(s, source_id, hi, lo);
|
||||
}
|
||||
|
||||
|
||||
static void vtd_report_ir_fault(IntelIOMMUState *s, uint64_t source_id,
|
||||
VTDFaultReason fault, uint16_t index)
|
||||
{
|
||||
uint64_t hi, lo;
|
||||
|
||||
lo = VTD_FRCD_IR_IDX(index);
|
||||
hi = VTD_FRCD_SID(source_id) | VTD_FRCD_FR(fault);
|
||||
|
||||
vtd_report_frcd_fault(s, source_id, hi, lo);
|
||||
}
|
||||
|
||||
/* Handle Invalidation Queue Errors of queued invalidation interface error
|
||||
* conditions.
|
||||
*/
|
||||
|
@ -3305,8 +3323,9 @@ static Property vtd_properties[] = {
|
|||
};
|
||||
|
||||
/* Read IRTE entry with specific index */
|
||||
static int vtd_irte_get(IntelIOMMUState *iommu, uint16_t index,
|
||||
VTD_IR_TableEntry *entry, uint16_t sid)
|
||||
static bool vtd_irte_get(IntelIOMMUState *iommu, uint16_t index,
|
||||
VTD_IR_TableEntry *entry, uint16_t sid,
|
||||
bool do_fault)
|
||||
{
|
||||
static const uint16_t vtd_svt_mask[VTD_SQ_MAX] = \
|
||||
{0xffff, 0xfffb, 0xfff9, 0xfff8};
|
||||
|
@ -3317,7 +3336,10 @@ static int vtd_irte_get(IntelIOMMUState *iommu, uint16_t index,
|
|||
if (index >= iommu->intr_size) {
|
||||
error_report_once("%s: index too large: ind=0x%x",
|
||||
__func__, index);
|
||||
return -VTD_FR_IR_INDEX_OVER;
|
||||
if (do_fault) {
|
||||
vtd_report_ir_fault(iommu, sid, VTD_FR_IR_INDEX_OVER, index);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
addr = iommu->intr_root + index * sizeof(*entry);
|
||||
|
@ -3325,7 +3347,10 @@ static int vtd_irte_get(IntelIOMMUState *iommu, uint16_t index,
|
|||
entry, sizeof(*entry), MEMTXATTRS_UNSPECIFIED)) {
|
||||
error_report_once("%s: read failed: ind=0x%x addr=0x%" PRIx64,
|
||||
__func__, index, addr);
|
||||
return -VTD_FR_IR_ROOT_INVAL;
|
||||
if (do_fault) {
|
||||
vtd_report_ir_fault(iommu, sid, VTD_FR_IR_ROOT_INVAL, index);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
entry->data[0] = le64_to_cpu(entry->data[0]);
|
||||
|
@ -3333,11 +3358,24 @@ static int vtd_irte_get(IntelIOMMUState *iommu, uint16_t index,
|
|||
|
||||
trace_vtd_ir_irte_get(index, entry->data[1], entry->data[0]);
|
||||
|
||||
/*
|
||||
* The remaining potential fault conditions are "qualified" by the
|
||||
* Fault Processing Disable bit in the IRTE. Even "not present".
|
||||
* So just clear the do_fault flag if PFD is set, which will
|
||||
* prevent faults being raised.
|
||||
*/
|
||||
if (entry->irte.fault_disable) {
|
||||
do_fault = false;
|
||||
}
|
||||
|
||||
if (!entry->irte.present) {
|
||||
error_report_once("%s: detected non-present IRTE "
|
||||
"(index=%u, high=0x%" PRIx64 ", low=0x%" PRIx64 ")",
|
||||
__func__, index, entry->data[1], entry->data[0]);
|
||||
return -VTD_FR_IR_ENTRY_P;
|
||||
if (do_fault) {
|
||||
vtd_report_ir_fault(iommu, sid, VTD_FR_IR_ENTRY_P, index);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (entry->irte.__reserved_0 || entry->irte.__reserved_1 ||
|
||||
|
@ -3345,7 +3383,10 @@ static int vtd_irte_get(IntelIOMMUState *iommu, uint16_t index,
|
|||
error_report_once("%s: detected non-zero reserved IRTE "
|
||||
"(index=%u, high=0x%" PRIx64 ", low=0x%" PRIx64 ")",
|
||||
__func__, index, entry->data[1], entry->data[0]);
|
||||
return -VTD_FR_IR_IRTE_RSVD;
|
||||
if (do_fault) {
|
||||
vtd_report_ir_fault(iommu, sid, VTD_FR_IR_IRTE_RSVD, index);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sid != X86_IOMMU_SID_INVALID) {
|
||||
|
@ -3361,7 +3402,10 @@ static int vtd_irte_get(IntelIOMMUState *iommu, uint16_t index,
|
|||
error_report_once("%s: invalid IRTE SID "
|
||||
"(index=%u, sid=%u, source_id=%u)",
|
||||
__func__, index, sid, source_id);
|
||||
return -VTD_FR_IR_SID_ERR;
|
||||
if (do_fault) {
|
||||
vtd_report_ir_fault(iommu, sid, VTD_FR_IR_SID_ERR, index);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -3373,7 +3417,10 @@ static int vtd_irte_get(IntelIOMMUState *iommu, uint16_t index,
|
|||
error_report_once("%s: invalid SVT_BUS "
|
||||
"(index=%u, bus=%u, min=%u, max=%u)",
|
||||
__func__, index, bus, bus_min, bus_max);
|
||||
return -VTD_FR_IR_SID_ERR;
|
||||
if (do_fault) {
|
||||
vtd_report_ir_fault(iommu, sid, VTD_FR_IR_SID_ERR, index);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -3382,23 +3429,24 @@ static int vtd_irte_get(IntelIOMMUState *iommu, uint16_t index,
|
|||
"(index=%u, type=%d)", __func__,
|
||||
index, entry->irte.sid_vtype);
|
||||
/* Take this as verification failure. */
|
||||
return -VTD_FR_IR_SID_ERR;
|
||||
if (do_fault) {
|
||||
vtd_report_ir_fault(iommu, sid, VTD_FR_IR_SID_ERR, index);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Fetch IRQ information of specific IR index */
|
||||
static int vtd_remap_irq_get(IntelIOMMUState *iommu, uint16_t index,
|
||||
X86IOMMUIrq *irq, uint16_t sid)
|
||||
static bool vtd_remap_irq_get(IntelIOMMUState *iommu, uint16_t index,
|
||||
X86IOMMUIrq *irq, uint16_t sid, bool do_fault)
|
||||
{
|
||||
VTD_IR_TableEntry irte = {};
|
||||
int ret = 0;
|
||||
|
||||
ret = vtd_irte_get(iommu, index, &irte, sid);
|
||||
if (ret) {
|
||||
return ret;
|
||||
if (!vtd_irte_get(iommu, index, &irte, sid, do_fault)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
irq->trigger_mode = irte.irte.trigger_mode;
|
||||
|
@ -3417,16 +3465,15 @@ static int vtd_remap_irq_get(IntelIOMMUState *iommu, uint16_t index,
|
|||
trace_vtd_ir_remap(index, irq->trigger_mode, irq->vector,
|
||||
irq->delivery_mode, irq->dest, irq->dest_mode);
|
||||
|
||||
return 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Interrupt remapping for MSI/MSI-X entry */
|
||||
static int vtd_interrupt_remap_msi(IntelIOMMUState *iommu,
|
||||
MSIMessage *origin,
|
||||
MSIMessage *translated,
|
||||
uint16_t sid)
|
||||
uint16_t sid, bool do_fault)
|
||||
{
|
||||
int ret = 0;
|
||||
VTD_IR_MSIAddress addr;
|
||||
uint16_t index;
|
||||
X86IOMMUIrq irq = {};
|
||||
|
@ -3443,14 +3490,20 @@ static int vtd_interrupt_remap_msi(IntelIOMMUState *iommu,
|
|||
if (origin->address & VTD_MSI_ADDR_HI_MASK) {
|
||||
error_report_once("%s: MSI address high 32 bits non-zero detected: "
|
||||
"address=0x%" PRIx64, __func__, origin->address);
|
||||
return -VTD_FR_IR_REQ_RSVD;
|
||||
if (do_fault) {
|
||||
vtd_report_ir_fault(iommu, sid, VTD_FR_IR_REQ_RSVD, 0);
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
addr.data = origin->address & VTD_MSI_ADDR_LO_MASK;
|
||||
if (addr.addr.__head != 0xfee) {
|
||||
error_report_once("%s: MSI address low 32 bit invalid: 0x%" PRIx32,
|
||||
__func__, addr.data);
|
||||
return -VTD_FR_IR_REQ_RSVD;
|
||||
if (do_fault) {
|
||||
vtd_report_ir_fault(iommu, sid, VTD_FR_IR_REQ_RSVD, 0);
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* This is compatible mode. */
|
||||
|
@ -3469,9 +3522,8 @@ static int vtd_interrupt_remap_msi(IntelIOMMUState *iommu,
|
|||
index += origin->data & VTD_IR_MSI_DATA_SUBHANDLE;
|
||||
}
|
||||
|
||||
ret = vtd_remap_irq_get(iommu, index, &irq, sid);
|
||||
if (ret) {
|
||||
return ret;
|
||||
if (!vtd_remap_irq_get(iommu, index, &irq, sid, do_fault)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (addr.addr.sub_valid) {
|
||||
|
@ -3481,7 +3533,10 @@ static int vtd_interrupt_remap_msi(IntelIOMMUState *iommu,
|
|||
"(sid=%u, address=0x%" PRIx64
|
||||
", data=0x%" PRIx32 ")",
|
||||
__func__, sid, origin->address, origin->data);
|
||||
return -VTD_FR_IR_REQ_RSVD;
|
||||
if (do_fault) {
|
||||
vtd_report_ir_fault(iommu, sid, VTD_FR_IR_REQ_RSVD, 0);
|
||||
}
|
||||
return -EINVAL;
|
||||
}
|
||||
} else {
|
||||
uint8_t vector = origin->data & 0xff;
|
||||
|
@ -3521,7 +3576,7 @@ static int vtd_int_remap(X86IOMMUState *iommu, MSIMessage *src,
|
|||
MSIMessage *dst, uint16_t sid)
|
||||
{
|
||||
return vtd_interrupt_remap_msi(INTEL_IOMMU_DEVICE(iommu),
|
||||
src, dst, sid);
|
||||
src, dst, sid, false);
|
||||
}
|
||||
|
||||
static MemTxResult vtd_mem_ir_read(void *opaque, hwaddr addr,
|
||||
|
@ -3547,9 +3602,8 @@ static MemTxResult vtd_mem_ir_write(void *opaque, hwaddr addr,
|
|||
sid = attrs.requester_id;
|
||||
}
|
||||
|
||||
ret = vtd_interrupt_remap_msi(opaque, &from, &to, sid);
|
||||
ret = vtd_interrupt_remap_msi(opaque, &from, &to, sid, true);
|
||||
if (ret) {
|
||||
/* TODO: report error */
|
||||
/* Drop this interrupt */
|
||||
return MEMTX_ERROR;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue