diff options
author | Stefan Hajnoczi <stefanha@redhat.com> | 2017-05-18 10:01:00 +0100 |
---|---|---|
committer | Stefan Hajnoczi <stefanha@redhat.com> | 2017-05-18 10:01:08 +0100 |
commit | adb354dd1e00aa6b8bd674f0e1f70008badded0f (patch) | |
tree | 51c2422717a6421bdc36a54c22bcb1b292aa44b0 /exec.c | |
parent | 897eee242bc081d72ffbf84664c907dcba620ee3 (diff) | |
parent | a764040cc831cfe5b8bf1c80e8341b9bf2de3ce8 (diff) | |
download | qemu-adb354dd1e00aa6b8bd674f0e1f70008badded0f.zip qemu-adb354dd1e00aa6b8bd674f0e1f70008badded0f.tar.gz qemu-adb354dd1e00aa6b8bd674f0e1f70008badded0f.tar.bz2 |
Merge remote-tracking branch 'mst/tags/for_upstream' into staging
pci, virtio, vhost: fixes
A bunch of fixes that missed the release.
Most notably we are reverting shpc back to enabled by default state
as guests uses that as an indicator that hotplug is supported
(even though it's unused). Unfortunately we can't fix this
on the stable branch since that would break migration.
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
# gpg: Signature made Wed 17 May 2017 10:42:06 PM BST
# gpg: using RSA key 0x281F0DB8D28D5469
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>"
# gpg: aka "Michael S. Tsirkin <mst@redhat.com>"
# 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
* mst/tags/for_upstream:
exec: abstract address_space_do_translate()
pci: deassert intx when pci device unrealize
virtio: allow broken device to notify guest
Revert "hw/pci: disable pci-bridge's shpc by default"
acpi-defs: clean up open brace usage
ACPI: don't call acpi_pcihp_device_plug_cb on xen
iommu: Don't crash if machine is not PC_MACHINE
pc: add 2.10 machine type
pc/fwcfg: unbreak migration from qemu-2.5 and qemu-2.6 during firmware boot
libvhost-user: fix crash when rings aren't ready
hw/virtio: fix vhost user fails to startup when MQ
hw/arm/virt: generate 64-bit addressable ACPI objects
hw/acpi-defs: replace leading X with x_ in FADT field names
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'exec.c')
-rw-r--r-- | exec.c | 103 |
1 files changed, 69 insertions, 34 deletions
@@ -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; } |