[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 13/13] exec: abstract address_space_do_translate()
From: |
Michael S. Tsirkin |
Subject: |
[Qemu-devel] [PULL 13/13] exec: abstract address_space_do_translate() |
Date: |
Thu, 18 May 2017 00:45:35 +0300 |
From: Peter Xu <address@hidden>
This function is an abstraction helper for address_space_translate() and
address_space_get_iotlb_entry(). It does the lookup of address into
memory region section, then does proper IOMMU translation if necessary.
Refactor the two existing functions to use it.
This fixes vhost when IOMMU is disabled by guest.
Tested-by: Maxime Coquelin <address@hidden>
Signed-off-by: Peter Xu <address@hidden>
Reviewed-by: Michael S. Tsirkin <address@hidden>
Signed-off-by: Michael S. Tsirkin <address@hidden>
---
exec.c | 103 +++++++++++++++++++++++++++++++++++++++++++----------------------
1 file changed, 69 insertions(+), 34 deletions(-)
diff --git a/exec.c b/exec.c
index eac6085..f942eb2 100644
--- a/exec.c
+++ b/exec.c
@@ -463,18 +463,20 @@ address_space_translate_internal(AddressSpaceDispatch *d,
hwaddr addr, hwaddr *x
}
/* Called from RCU critical section */
-IOMMUTLBEntry address_space_get_iotlb_entry(AddressSpace *as, hwaddr addr,
- bool is_write)
+static MemoryRegionSection address_space_do_translate(AddressSpace *as,
+ hwaddr addr,
+ hwaddr *xlat,
+ hwaddr *plen,
+ bool is_write,
+ bool is_mmio)
{
- IOMMUTLBEntry iotlb = {0};
+ IOMMUTLBEntry iotlb;
MemoryRegionSection *section;
MemoryRegion *mr;
for (;;) {
AddressSpaceDispatch *d = atomic_rcu_read(&as->dispatch);
- section = address_space_lookup_region(d, addr, false);
- addr = addr - section->offset_within_address_space
- + section->offset_within_region;
+ section = address_space_translate_internal(d, addr, &addr, plen,
is_mmio);
mr = section->mr;
if (!mr->iommu_ops) {
@@ -482,55 +484,88 @@ IOMMUTLBEntry address_space_get_iotlb_entry(AddressSpace
*as, hwaddr addr,
}
iotlb = mr->iommu_ops->translate(mr, addr, is_write);
+ addr = ((iotlb.translated_addr & ~iotlb.addr_mask)
+ | (addr & iotlb.addr_mask));
+ *plen = MIN(*plen, (addr | iotlb.addr_mask) - addr + 1);
if (!(iotlb.perm & (1 << is_write))) {
- iotlb.target_as = NULL;
- break;
+ goto translate_fail;
}
- addr = ((iotlb.translated_addr & ~iotlb.addr_mask)
- | (addr & iotlb.addr_mask));
as = iotlb.target_as;
}
- return iotlb;
+ *xlat = addr;
+
+ return *section;
+
+translate_fail:
+ return (MemoryRegionSection) { .mr = &io_mem_unassigned };
}
/* Called from RCU critical section */
-MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr,
- hwaddr *xlat, hwaddr *plen,
- bool is_write)
+IOMMUTLBEntry address_space_get_iotlb_entry(AddressSpace *as, hwaddr addr,
+ bool is_write)
{
- IOMMUTLBEntry iotlb;
- MemoryRegionSection *section;
- MemoryRegion *mr;
+ MemoryRegionSection section;
+ hwaddr xlat, plen;
- for (;;) {
- AddressSpaceDispatch *d = atomic_rcu_read(&as->dispatch);
- section = address_space_translate_internal(d, addr, &addr, plen, true);
- mr = section->mr;
+ /* Try to get maximum page mask during translation. */
+ plen = (hwaddr)-1;
- if (!mr->iommu_ops) {
- break;
- }
+ /* This can never be MMIO. */
+ section = address_space_do_translate(as, addr, &xlat, &plen,
+ is_write, false);
- iotlb = mr->iommu_ops->translate(mr, addr, is_write);
- addr = ((iotlb.translated_addr & ~iotlb.addr_mask)
- | (addr & iotlb.addr_mask));
- *plen = MIN(*plen, (addr | iotlb.addr_mask) - addr + 1);
- if (!(iotlb.perm & (1 << is_write))) {
- mr = &io_mem_unassigned;
- break;
- }
+ /* Illegal translation */
+ if (section.mr == &io_mem_unassigned) {
+ goto iotlb_fail;
+ }
- as = iotlb.target_as;
+ /* Convert memory region offset into address space offset */
+ xlat += section.offset_within_address_space -
+ section.offset_within_region;
+
+ if (plen == (hwaddr)-1) {
+ /*
+ * We use default page size here. Logically it only happens
+ * for identity mappings.
+ */
+ plen = TARGET_PAGE_SIZE;
}
+ /* Convert to address mask */
+ plen -= 1;
+
+ return (IOMMUTLBEntry) {
+ .target_as = section.address_space,
+ .iova = addr & ~plen,
+ .translated_addr = xlat & ~plen,
+ .addr_mask = plen,
+ /* IOTLBs are for DMAs, and DMA only allows on RAMs. */
+ .perm = IOMMU_RW,
+ };
+
+iotlb_fail:
+ return (IOMMUTLBEntry) {0};
+}
+
+/* Called from RCU critical section */
+MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr,
+ hwaddr *xlat, hwaddr *plen,
+ bool is_write)
+{
+ MemoryRegion *mr;
+ MemoryRegionSection section;
+
+ /* This can be MMIO, so setup MMIO bit. */
+ section = address_space_do_translate(as, addr, xlat, plen, is_write, true);
+ mr = section.mr;
+
if (xen_enabled() && memory_access_is_direct(mr, is_write)) {
hwaddr page = ((addr & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE) - addr;
*plen = MIN(page, *plen);
}
- *xlat = addr;
return mr;
}
--
MST
- [Qemu-devel] [PULL 04/13] libvhost-user: fix crash when rings aren't ready, (continued)
- [Qemu-devel] [PULL 04/13] libvhost-user: fix crash when rings aren't ready, Michael S. Tsirkin, 2017/05/17
- [Qemu-devel] [PULL 05/13] pc/fwcfg: unbreak migration from qemu-2.5 and qemu-2.6 during firmware boot, Michael S. Tsirkin, 2017/05/17
- [Qemu-devel] [PULL 02/13] hw/arm/virt: generate 64-bit addressable ACPI objects, Michael S. Tsirkin, 2017/05/17
- [Qemu-devel] [PULL 08/13] ACPI: don't call acpi_pcihp_device_plug_cb on xen, Michael S. Tsirkin, 2017/05/17
- [Qemu-devel] [PULL 07/13] iommu: Don't crash if machine is not PC_MACHINE, Michael S. Tsirkin, 2017/05/17
- [Qemu-devel] [PULL 09/13] acpi-defs: clean up open brace usage, Michael S. Tsirkin, 2017/05/17
- [Qemu-devel] [PULL 06/13] pc: add 2.10 machine type, Michael S. Tsirkin, 2017/05/17
- [Qemu-devel] [PULL 10/13] Revert "hw/pci: disable pci-bridge's shpc by default", Michael S. Tsirkin, 2017/05/17
- [Qemu-devel] [PULL 11/13] virtio: allow broken device to notify guest, Michael S. Tsirkin, 2017/05/17
- [Qemu-devel] [PULL 12/13] pci: deassert intx when pci device unrealize, Michael S. Tsirkin, 2017/05/17
- [Qemu-devel] [PULL 13/13] exec: abstract address_space_do_translate(),
Michael S. Tsirkin <=
- Re: [Qemu-devel] [PULL 00/13] pci, virtio, vhost: fixes, no-reply, 2017/05/17
- Re: [Qemu-devel] [PULL 00/13] pci, virtio, vhost: fixes, Stefan Hajnoczi, 2017/05/18
- [Qemu-devel] [PULL 00/13] pci, virtio, vhost: fixes, Michael S. Tsirkin, 2017/05/28
- [Qemu-devel] [PULL 01/13] memory: tune last param of iommu_ops.translate(), Michael S. Tsirkin, 2017/05/28
- [Qemu-devel] [PULL 02/13] memory: remove the last param in memory_region_iommu_replay(), Michael S. Tsirkin, 2017/05/28
- [Qemu-devel] [PULL 06/13] intel_iommu: use IOMMU_ACCESS_FLAG(), Michael S. Tsirkin, 2017/05/28
- [Qemu-devel] [PULL 05/13] intel_iommu: provide vtd_ce_get_type(), Michael S. Tsirkin, 2017/05/28
- [Qemu-devel] [PULL 04/13] intel_iommu: renaming context entry helpers, Michael S. Tsirkin, 2017/05/28
- [Qemu-devel] [PULL 07/13] intel_iommu: allow dev-iotlb context entry conditionally, Michael S. Tsirkin, 2017/05/28