diff options
author | Peter Maydell | 2020-01-07 17:25:00 +0100 |
---|---|---|
committer | Peter Maydell | 2020-01-07 17:25:00 +0100 |
commit | 973d306dd64bba7fc13f7e8b12ef43c089243d31 (patch) | |
tree | 088a5983b6f2c0305111eaff06ea5731594308e7 /hw/i386/intel_iommu.c | |
parent | tests/iothread: Always connect iothread GSource to a GMainContext (diff) | |
parent | intel_iommu: add present bit check for pasid table entries (diff) | |
download | qemu-973d306dd64bba7fc13f7e8b12ef43c089243d31.tar.gz qemu-973d306dd64bba7fc13f7e8b12ef43c089243d31.tar.xz qemu-973d306dd64bba7fc13f7e8b12ef43c089243d31.zip |
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging
virtio, pci, pc: fixes, features
Bugfixes all over the place.
HMAT support.
New flags for vhost-user-blk utility.
Auto-tuning of seg max for virtio storage.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
# gpg: Signature made Mon 06 Jan 2020 17:05:05 GMT
# 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
* remotes/mst/tags/for_upstream: (32 commits)
intel_iommu: add present bit check for pasid table entries
intel_iommu: a fix to vtd_find_as_from_bus_num()
virtio-net: delete also control queue when TX/RX deleted
virtio: reset region cache when on queue deletion
virtio-mmio: update queue size on guest write
tests: add virtio-scsi and virtio-blk seg_max_adjust test
virtio: make seg_max virtqueue size dependent
hw: fix using 4.2 compat in 5.0 machine types for i440fx/q35
vhost-user-scsi: reset the device if supported
vhost-user: add VHOST_USER_RESET_DEVICE to reset devices
hw/pci/pci_host: Let pci_data_[read/write] use unsigned 'size' argument
hw/pci/pci_host: Remove redundant PCI_DPRINTF()
virtio-mmio: Clear v2 transport state on soft reset
ACPI: add expected files for HMAT tests (acpihmat)
tests/bios-tables-test: add test cases for ACPI HMAT
tests/numa: Add case for QMP build HMAT
hmat acpi: Build Memory Side Cache Information Structure(s)
hmat acpi: Build System Locality Latency and Bandwidth Information Structure(s)
hmat acpi: Build Memory Proximity Domain Attributes Structure(s)
numa: Extend CLI to provide memory side cache information
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/i386/intel_iommu.c')
-rw-r--r-- | hw/i386/intel_iommu.c | 100 |
1 files changed, 77 insertions, 23 deletions
diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index 43c94b993b..a523ef0e65 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -686,9 +686,18 @@ static inline bool vtd_pe_type_check(X86IOMMUState *x86_iommu, return true; } -static int vtd_get_pasid_dire(dma_addr_t pasid_dir_base, - uint32_t pasid, - VTDPASIDDirEntry *pdire) +static inline bool vtd_pdire_present(VTDPASIDDirEntry *pdire) +{ + return pdire->val & 1; +} + +/** + * Caller of this function should check present bit if wants + * to use pdir entry for futher usage except for fpd bit check. + */ +static int vtd_get_pdire_from_pdir_table(dma_addr_t pasid_dir_base, + uint32_t pasid, + VTDPASIDDirEntry *pdire) { uint32_t index; dma_addr_t addr, entry_size; @@ -703,18 +712,22 @@ static int vtd_get_pasid_dire(dma_addr_t pasid_dir_base, return 0; } -static int vtd_get_pasid_entry(IntelIOMMUState *s, - uint32_t pasid, - VTDPASIDDirEntry *pdire, - VTDPASIDEntry *pe) +static inline bool vtd_pe_present(VTDPASIDEntry *pe) +{ + return pe->val[0] & VTD_PASID_ENTRY_P; +} + +static int vtd_get_pe_in_pasid_leaf_table(IntelIOMMUState *s, + uint32_t pasid, + dma_addr_t addr, + VTDPASIDEntry *pe) { uint32_t index; - dma_addr_t addr, entry_size; + dma_addr_t entry_size; X86IOMMUState *x86_iommu = X86_IOMMU_DEVICE(s); index = VTD_PASID_TABLE_INDEX(pasid); entry_size = VTD_PASID_ENTRY_SIZE; - addr = pdire->val & VTD_PASID_TABLE_BASE_ADDR_MASK; addr = addr + index * entry_size; if (dma_memory_read(&address_space_memory, addr, pe, entry_size)) { return -VTD_FR_PASID_TABLE_INV; @@ -732,25 +745,54 @@ static int vtd_get_pasid_entry(IntelIOMMUState *s, return 0; } -static int vtd_get_pasid_entry_from_pasid(IntelIOMMUState *s, - dma_addr_t pasid_dir_base, - uint32_t pasid, - VTDPASIDEntry *pe) +/** + * Caller of this function should check present bit if wants + * to use pasid entry for futher usage except for fpd bit check. + */ +static int vtd_get_pe_from_pdire(IntelIOMMUState *s, + uint32_t pasid, + VTDPASIDDirEntry *pdire, + VTDPASIDEntry *pe) +{ + dma_addr_t addr = pdire->val & VTD_PASID_TABLE_BASE_ADDR_MASK; + + return vtd_get_pe_in_pasid_leaf_table(s, pasid, addr, pe); +} + +/** + * This function gets a pasid entry from a specified pasid + * table (includes dir and leaf table) with a specified pasid. + * Sanity check should be done to ensure return a present + * pasid entry to caller. + */ +static int vtd_get_pe_from_pasid_table(IntelIOMMUState *s, + dma_addr_t pasid_dir_base, + uint32_t pasid, + VTDPASIDEntry *pe) { int ret; VTDPASIDDirEntry pdire; - ret = vtd_get_pasid_dire(pasid_dir_base, pasid, &pdire); + ret = vtd_get_pdire_from_pdir_table(pasid_dir_base, + pasid, &pdire); if (ret) { return ret; } - ret = vtd_get_pasid_entry(s, pasid, &pdire, pe); + if (!vtd_pdire_present(&pdire)) { + return -VTD_FR_PASID_TABLE_INV; + } + + ret = vtd_get_pe_from_pdire(s, pasid, &pdire, pe); if (ret) { return ret; } - return ret; + if (!vtd_pe_present(pe)) { + return -VTD_FR_PASID_TABLE_INV; + } + + return 0; } static int vtd_ce_get_rid2pasid_entry(IntelIOMMUState *s, @@ -763,7 +805,7 @@ static int vtd_ce_get_rid2pasid_entry(IntelIOMMUState *s, pasid = VTD_CE_GET_RID2PASID(ce); pasid_dir_base = VTD_CE_GET_PASID_DIR_TABLE(ce); - ret = vtd_get_pasid_entry_from_pasid(s, pasid_dir_base, pasid, pe); + ret = vtd_get_pe_from_pasid_table(s, pasid_dir_base, pasid, pe); return ret; } @@ -781,7 +823,11 @@ static int vtd_ce_get_pasid_fpd(IntelIOMMUState *s, pasid = VTD_CE_GET_RID2PASID(ce); pasid_dir_base = VTD_CE_GET_PASID_DIR_TABLE(ce); - ret = vtd_get_pasid_dire(pasid_dir_base, pasid, &pdire); + /* + * No present bit check since fpd is meaningful even + * if the present bit is clear. + */ + ret = vtd_get_pdire_from_pdir_table(pasid_dir_base, pasid, &pdire); if (ret) { return ret; } @@ -791,7 +837,15 @@ static int vtd_ce_get_pasid_fpd(IntelIOMMUState *s, return 0; } - ret = vtd_get_pasid_entry(s, pasid, &pdire, &pe); + if (!vtd_pdire_present(&pdire)) { + return -VTD_FR_PASID_TABLE_INV; + } + + /* + * No present bit check since fpd is meaningful even + * if the present bit is clear. + */ + ret = vtd_get_pe_from_pdire(s, pasid, &pdire, &pe); if (ret) { return ret; } @@ -948,6 +1002,7 @@ static VTDBus *vtd_find_as_from_bus_num(IntelIOMMUState *s, uint8_t bus_num) return vtd_bus; } } + vtd_bus = NULL; } return vtd_bus; } @@ -2610,16 +2665,15 @@ static uint64_t vtd_mem_read(void *opaque, hwaddr addr, unsigned size) switch (addr) { /* Root Table Address Register, 64-bit */ case DMAR_RTADDR_REG: + val = vtd_get_quad_raw(s, DMAR_RTADDR_REG); if (size == 4) { - val = s->root & ((1ULL << 32) - 1); - } else { - val = s->root; + val = val & ((1ULL << 32) - 1); } break; case DMAR_RTADDR_REG_HI: assert(size == 4); - val = s->root >> 32; + val = vtd_get_quad_raw(s, DMAR_RTADDR_REG) >> 32; break; /* Invalidation Queue Address Register, 64-bit */ |