[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH 07/28] ARM: GICv3 ITS: introduce device mapping



Hi Andre,


On 02/22/2017 01:06 AM, Vijay Kilari wrote:
Hi Andre,

On Tue, Jan 31, 2017 at 12:01 AM, Andre Przywara <andre.przywara@xxxxxxx> wrote:
The ITS uses device IDs to map LPIs to a device. Dom0 will later use
those IDs, which we directly pass on to the host.
For this we have to map each device that Dom0 may request to a host
ITS device with the same identifier.
Allocate the respective memory and enter each device into an rbtree to
later be able to iterate over it or to easily teardown guests.

Signed-off-by: Andre Przywara <andre.przywara@xxxxxxx>
---
  xen/arch/arm/gic-v3-its.c        | 188 ++++++++++++++++++++++++++++++++++++++-
  xen/arch/arm/vgic-v3.c           |   3 +
  xen/include/asm-arm/domain.h     |   3 +
  xen/include/asm-arm/gic_v3_its.h |  28 ++++++
  4 files changed, 221 insertions(+), 1 deletion(-)

diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c
index 6578e8a..4a3a394 100644
--- a/xen/arch/arm/gic-v3-its.c
+++ b/xen/arch/arm/gic-v3-its.c
@@ -21,8 +21,10 @@
  #include <xen/device_tree.h>
  #include <xen/delay.h>
  #include <xen/libfdt/libfdt.h>
-#include <xen/mm.h>
+#include <xen/rbtree.h>
+#include <xen/sched.h>
  #include <xen/sizes.h>
+#include <xen/domain.h>
  #include <asm/gic.h>
  #include <asm/gic_v3_defs.h>
  #include <asm/gic_v3_its.h>
@@ -94,6 +96,21 @@ static int its_send_cmd_mapc(struct host_its *its, int 
collection_id, int cpu)
      return its_send_command(its, cmd);
  }

+static int its_send_cmd_mapd(struct host_its *its, uint32_t deviceid,
+                             int size, uint64_t itt_addr, bool valid)
+{
+    uint64_t cmd[4];
+
+    cmd[0] = GITS_CMD_MAPD | ((uint64_t)deviceid << 32);
+    cmd[1] = size & GENMASK(4, 0);
+    cmd[2] = itt_addr & GENMASK(51, 8);
+    if ( valid )
+        cmd[2] |= GITS_VALID_BIT;
+    cmd[3] = 0x00;
+
+    return its_send_command(its, cmd);
+}
+
  /* Set up the (1:1) collection mapping for the given host CPU. */
  int gicv3_its_setup_collection(int cpu)
  {
@@ -293,6 +310,7 @@ int gicv3_its_init(struct host_its *hw_its)
      reg = readq_relaxed(hw_its->its_base + GITS_TYPER);
      if ( reg & GITS_TYPER_PTA )
          hw_its->flags |= HOST_ITS_USES_PTA;
+    hw_its->itte_size = GITS_TYPER_ITT_SIZE(reg);

      for ( i = 0; i < GITS_BASER_NR_REGS; i++ )
      {
@@ -339,6 +357,173 @@ int gicv3_its_init(struct host_its *hw_its)
      return 0;
  }

+static void remove_mapped_guest_device(struct its_devices *dev)
+{
+    if ( dev->hw_its )
+        its_send_cmd_mapd(dev->hw_its, dev->host_devid, 0, 0, false);
+
+    xfree(dev->itt_addr);
+    xfree(dev);
+}
+
+int gicv3_its_map_guest_device(struct domain *d, int host_devid,
+                               int guest_devid, int bits, bool valid)
+{
+    void *itt_addr = NULL;
+    struct its_devices *dev, *temp;
+    struct rb_node **new = &d->arch.vgic.its_devices.rb_node, *parent = NULL;
+    struct host_its *hw_its;
+    int ret;
+
+    /* check for already existing mappings */
+    spin_lock(&d->arch.vgic.its_devices_lock);
+    while (*new)
+    {
+        temp = rb_entry(*new, struct its_devices, rbnode);
+
+        if ( temp->guest_devid == guest_devid )
+        {
+            if ( !valid )
+                rb_erase(&temp->rbnode, &d->arch.vgic.its_devices);
+
+            spin_unlock(&d->arch.vgic.its_devices_lock);
+
+            if ( valid )
+                return -EBUSY;
+
+            remove_mapped_guest_device(temp);
+
+            return 0;
+        }
+
+        if ( guest_devid < temp->guest_devid )
+            new = &((*new)->rb_right);
Shouldn't be rb_left here?
+        else
+            new = &((*new)->rb_left);
Shouldn't be rb_right here?


I found the same thing when I tested ITS feature on Qualcomm platform.

+    }
I see duplicate code in find and inserting node into rb_tree.

+
+    if ( !valid )
+    {
+        ret = -ENOENT;
+        goto out_unlock;
+    }
+
+    /*
+     * TODO: Work out the correct hardware ITS to use here.
+     * Maybe a per-platform function: devid -> ITS?
+     * Or parsing the DT to find the msi_parent?
+     * Or get Dom0 to give us this information?
+     * For now just use the first ITS.
+     */
+    hw_its = list_first_entry(&host_its_list, struct host_its, entry);
+
+    ret = -ENOMEM;
+
+    itt_addr = _xmalloc(BIT(bits) * hw_its->itte_size, 256);

Please use _xzalloc() to avoid potential issues with ITS hardware prefetching feature.

--
Shanker Donthineni
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm 
Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux 
Foundation Collaborative Project.


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.