aboutsummaryrefslogtreecommitdiff
path: root/target/arm/kvm.c
diff options
context:
space:
mode:
authorEric Auger <eric.auger@redhat.com>2018-05-04 18:05:52 +0100
committerPeter Maydell <peter.maydell@linaro.org>2018-05-04 18:52:58 +0100
commitb05c81d292be96e27bd61ed1f67d313eafbda4d9 (patch)
tree3d64cc20537d09255a379008a67982748764d379 /target/arm/kvm.c
parent0d1ac82eced6bb641a98cd5d7f3b829635f95fac (diff)
target/arm/kvm: Translate the MSI doorbell in kvm_arch_fixup_msi_route
In case the MSI is translated by an IOMMU we need to fixup the MSI route with the translated address. Signed-off-by: Eric Auger <eric.auger@redhat.com> Signed-off-by: Bharat Bhushan <Bharat.Bhushan@nxp.com> Message-id: 1524665762-31355-12-git-send-email-eric.auger@redhat.com Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target/arm/kvm.c')
-rw-r--r--target/arm/kvm.c38
1 files changed, 37 insertions, 1 deletions
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index ecc39ac295..5141d0adc5 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -20,8 +20,10 @@
#include "sysemu/kvm.h"
#include "kvm_arm.h"
#include "cpu.h"
+#include "trace.h"
#include "internals.h"
#include "hw/arm/arm.h"
+#include "hw/pci/pci.h"
#include "exec/memattrs.h"
#include "exec/address-spaces.h"
#include "hw/boards.h"
@@ -649,7 +651,41 @@ int kvm_arm_vgic_probe(void)
int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
uint64_t address, uint32_t data, PCIDevice *dev)
{
- return 0;
+ AddressSpace *as = pci_device_iommu_address_space(dev);
+ hwaddr xlat, len, doorbell_gpa;
+ MemoryRegionSection mrs;
+ MemoryRegion *mr;
+ int ret = 1;
+
+ if (as == &address_space_memory) {
+ return 0;
+ }
+
+ /* MSI doorbell address is translated by an IOMMU */
+
+ rcu_read_lock();
+ mr = address_space_translate(as, address, &xlat, &len, true);
+ if (!mr) {
+ goto unlock;
+ }
+ mrs = memory_region_find(mr, xlat, 1);
+ if (!mrs.mr) {
+ goto unlock;
+ }
+
+ doorbell_gpa = mrs.offset_within_address_space;
+ memory_region_unref(mrs.mr);
+
+ route->u.msi.address_lo = doorbell_gpa;
+ route->u.msi.address_hi = doorbell_gpa >> 32;
+
+ trace_kvm_arm_fixup_msi_route(address, doorbell_gpa);
+
+ ret = 0;
+
+unlock:
+ rcu_read_unlock();
+ return ret;
}
int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route,