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

[Xen-devel] [RFC PATCH 07/19] xen/arm: vits: Move LPI handling to basic virtual its driver



From: Vijaya Kumar K <Vijaya.Kumar@xxxxxxxxxxxxxxxxxx>

The LPI allocation is handled by virtual ITS driver on
receiving ITS commands from domain. So move this functionality
from physical ITS driver to Virtual ITS driver.

This patch does not add any virtual its funtionality
except moving required code for handling LPIs

Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@xxxxxxxxxxxxxxxxxx>
---
 xen/arch/arm/Makefile         |    1 +
 xen/arch/arm/gic-v3-its.c     |  101 -------------------------
 xen/arch/arm/vgic-v3-its.c    |  167 +++++++++++++++++++++++++++++++++++++++++
 xen/include/asm-arm/gic-its.h |   21 ++++++
 xen/include/asm-arm/gic.h     |    1 +
 5 files changed, 190 insertions(+), 101 deletions(-)

diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index f6eb834..c47dcc0 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -32,6 +32,7 @@ obj-y += shutdown.o
 obj-y += traps.o
 obj-y += vgic.o vgic-v2.o
 obj-$(CONFIG_ARM_64) += vgic-v3.o
+obj-$(CONFIG_ARM_64) += vgic-v3-its.o
 obj-y += vtimer.o
 obj-y += vuart.o
 obj-y += hvm.o
diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c
index 2ec7866..b1c599f 100644
--- a/xen/arch/arm/gic-v3-its.c
+++ b/xen/arch/arm/gic-v3-its.c
@@ -333,106 +333,6 @@ static void its_send_invall(struct its_node *its, struct 
its_collection *col)
 }
 
 /*
- * How we allocate LPIs:
- *
- * The GIC has id_bits bits for interrupt identifiers. From there, we
- * must subtract 8192 which are reserved for SGIs/PPIs/SPIs. Then, as
- * we allocate LPIs by chunks of 32, we can shift the whole thing by 5
- * bits to the right.
- *
- * This gives us (((1UL << id_bits) - 8192) >> 5) possible allocations.
- */
-#define IRQS_PER_CHUNK_SHIFT    5
-#define IRQS_PER_CHUNK        (1 << IRQS_PER_CHUNK_SHIFT)
-
-static unsigned long *lpi_bitmap;
-static u32 lpi_chunks;
-static DEFINE_SPINLOCK(lpi_lock);
-
-static int its_lpi_to_chunk(int lpi)
-{
-    return (lpi - 8192) >> IRQS_PER_CHUNK_SHIFT;
-}
-
-int its_chunk_to_lpi(int chunk)
-{
-    return (chunk << IRQS_PER_CHUNK_SHIFT) + 8192;
-}
-
-static int its_lpi_init(u32 id_bits)
-{
-    lpi_chunks = its_lpi_to_chunk(1UL << id_bits);
-
-    lpi_bitmap =  xzalloc_bytes(lpi_chunks / 8);
-    if (!lpi_bitmap) {
-        lpi_chunks = 0;
-        return -ENOMEM;
-    }
-
-    its_info("ITS: Allocated %d chunks for LPIs\n", (int)lpi_chunks);
-    return 0;
-}
-
-unsigned long *its_lpi_alloc_chunks(int nr_irq, int *base, int *nr_ids)
-{
-    unsigned long *bitmap = NULL;
-    int chunk_id;
-    int nr_chunks;
-    int i;
-
-    nr_chunks = DIV_ROUND_UP(nr_irq, IRQS_PER_CHUNK);
-
-    spin_lock(&lpi_lock);
-
-    do {
-        chunk_id = find_next_zero_bit(lpi_bitmap, lpi_chunks, 0);
-        if (chunk_id < lpi_chunks)
-            break;
-
-        nr_chunks--;
-    } while (nr_chunks > 0);
-
-    if (!nr_chunks)
-        goto out;
-
-    bitmap = xzalloc_bytes(BITS_TO_LONGS(nr_chunks * IRQS_PER_CHUNK) * sizeof 
(long));
-    if (!bitmap)
-        goto out;
-
-    for (i = 0; i < nr_chunks; i++)
-        set_bit(chunk_id + i, lpi_bitmap);
-
-    *base = its_chunk_to_lpi(chunk_id);
-    *nr_ids = nr_chunks * IRQS_PER_CHUNK;
-
-out:
-    spin_unlock(&lpi_lock);
-
-    return bitmap;
-}
-
-void its_lpi_free(unsigned long *bitmap, int base, int nr_ids)
-{
-    int lpi;
-
-    spin_lock(&lpi_lock);
-
-    for (lpi = base; lpi < (base + nr_ids); lpi += IRQS_PER_CHUNK) {
-        int chunk = its_lpi_to_chunk(lpi);
-        BUG_ON(chunk > lpi_chunks);
-        if (test_bit(chunk, lpi_bitmap)) {
-            clear_bit(chunk, lpi_bitmap);
-        } else {
-            its_err("Bad LPI chunk %d\n", chunk);
-        }
-    }
-
-    spin_unlock(&lpi_lock);
-
-    xfree(bitmap);
-}
-
-/*
  * We allocate 64kB for PROPBASE. That gives us at most 64K LPIs to
  * deal with (one configuration byte per interrupt). PENDBASE has to
  * be 64kB aligned (one bit per LPI, plus 8192 bits for SPI/PPI/SGI).
@@ -864,7 +764,6 @@ int its_init(struct dt_device_node *node, struct rdist_prop 
*rdists)
     gic_root_node = node;
 
     its_alloc_lpi_tables();
-    its_lpi_init(rdists->id_bits);
 
     return 0;
 }
diff --git a/xen/arch/arm/vgic-v3-its.c b/xen/arch/arm/vgic-v3-its.c
new file mode 100644
index 0000000..08e9787
--- /dev/null
+++ b/xen/arch/arm/vgic-v3-its.c
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2013, 2014 ARM Limited, All Rights Reserved.
+ * Author: Marc Zyngier <marc.zyngier@xxxxxxx>
+ *
+ * Xen changes:
+ * Vijaya Kumar K <Vijaya.Kumar@xxxxxxxxxxxxxxxxxx>
+ * Copyright (C) 2014 Cavium Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <xen/bitops.h>
+#include <xen/config.h>
+#include <xen/lib.h>
+#include <xen/init.h>
+#include <xen/softirq.h>
+#include <xen/irq.h>
+#include <xen/list.h>
+#include <xen/sched.h>
+#include <xen/sizes.h>
+#include <xen/xmalloc.h>
+#include <asm/current.h>
+#include <asm/device.h>
+#include <asm/mmio.h>
+#include <asm/io.h>
+#include <asm/gic_v3_defs.h>
+#include <asm/gic.h>
+#include <asm/vgic.h>
+#include <asm/gic-its.h>
+
+//#define DEBUG_ITS
+
+#ifdef DEBUG_ITS
+# define DPRINTK(fmt, args...) printk(XENLOG_DEBUG fmt, ##args)
+#else
+# define DPRINTK(fmt, args...) do {} while ( 0 )
+#endif
+
+#ifdef DEBUG_ITS
+static void dump_cmd(struct its_cmd_block *cmd)
+{
+    printk("CMD[0] = 0x%lx CMD[1] = 0x%lx CMD[2] = 0x%lx CMD[3] = 0x%lx\n",
+           cmd->raw_cmd[0], cmd->raw_cmd[1], cmd->raw_cmd[2], cmd->raw_cmd[3]);
+}
+#endif
+
+/*
+ * How we allocate LPIs:
+ *
+ * The GIC has id_bits bits for interrupt identifiers. From there, we
+ * must subtract 8192 which are reserved for SGIs/PPIs/SPIs. Then, as
+ * we allocate LPIs by chunks of 32, we can shift the whole thing by 5
+ * bits to the right.
+ *
+ * This gives us (((1UL << id_bits) - 8192) >> 5) possible allocations.
+ */
+
+#define IRQS_PER_CHUNK_SHIFT    5
+#define IRQS_PER_CHUNK          (1 << IRQS_PER_CHUNK_SHIFT)
+
+static unsigned long *lpi_bitmap;
+static uint32_t lpi_chunks;
+static DEFINE_SPINLOCK(lpi_lock);
+
+static int its_lpi_to_chunk(int lpi)
+{
+    return (lpi - NR_GIC_LPI) >> IRQS_PER_CHUNK_SHIFT;
+}
+
+static int its_chunk_to_lpi(int chunk)
+{
+    return (chunk << IRQS_PER_CHUNK_SHIFT) + NR_GIC_LPI;
+}
+
+int its_lpi_init(uint32_t id_bits)
+{
+    spin_lock(&lpi_lock);
+
+    lpi_chunks = its_lpi_to_chunk(1UL << id_bits);
+
+    lpi_bitmap =  xzalloc_bytes(lpi_chunks / 8);
+    if ( !lpi_bitmap )
+    {
+        lpi_chunks = 0;
+        spin_unlock(&lpi_lock);
+        return -ENOMEM;
+    }
+
+    spin_unlock(&lpi_lock);
+    DPRINTK("vITS: Allocated %d chunks for LPIs\n", (int)lpi_chunks);
+    return 0;
+}
+
+
+struct its_lpi_chunk *its_lpi_alloc(void)
+{
+    struct its_lpi_chunk *chunk;
+    int lpi;
+
+    chunk = xzalloc(struct its_lpi_chunk);
+    if ( !chunk )
+        return NULL;
+
+    spin_lock(&lpi_lock);
+
+    lpi = find_first_zero_bit(lpi_bitmap, lpi_chunks);
+    if ( lpi < lpi_chunks )
+    {
+        set_bit(lpi, lpi_bitmap);
+        chunk->lpi_base = its_chunk_to_lpi(lpi);
+        chunk->lpi_map = 0;
+        INIT_LIST_HEAD(&chunk->entry);
+        DPRINTK("vITS: Allocated LPI %d LPI_BASE %d\n", lpi, chunk->lpi_base);
+    }
+    else
+        lpi = -ENOSPC;
+
+    spin_unlock(&lpi_lock);
+
+    if ( lpi < 0 )
+    {
+        xfree(chunk);
+        return NULL;
+    }
+
+    return chunk;
+}
+
+void its_lpi_free(struct its_lpi_chunk *chunk)
+{
+    int lpi;
+
+    spin_lock(&lpi_lock);
+
+    lpi = its_lpi_to_chunk(chunk->lpi_base);
+    BUG_ON(lpi > lpi_chunks);
+    if ( test_bit(lpi, lpi_bitmap) )
+    {
+        clear_bit(lpi, lpi_bitmap);
+        DPRINTK("vITS: Freeing lpi chunk %d\n", lpi);
+    }
+    else
+        dprintk(XENLOG_ERR, "Bad LPI chunk %d\n", lpi);
+
+    spin_unlock(&lpi_lock);
+
+    xfree(chunk);
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-arm/gic-its.h b/xen/include/asm-arm/gic-its.h
index ff13c91..2fca1ef 100644
--- a/xen/include/asm-arm/gic-its.h
+++ b/xen/include/asm-arm/gic-its.h
@@ -22,6 +22,27 @@
 #ifndef __ASM_ARM_GIC_ITS_H__
 #define __ASM_ARM_GIC_ITS_H__
 
+#define IRQ_PER_CHUNK 32
+
+/*
+ * Our LPI allocation unit - Chunks of 32 IDs
+ */
+struct its_lpi_chunk {
+    struct list_head entry;
+    /* physical lpi starting number of this chunk */
+    int lpi_base;
+    /* bitmap of allocated plpi */
+    unsigned long lpi_map;
+    /* vlpi vs plpi mapping vs virtual collection */
+    uint32_t vid[IRQ_PER_CHUNK];
+    /* Physical id */
+    uint32_t pid[IRQ_PER_CHUNK];
+    /* Virtual collection id on which this virtual lpi is mapped */
+    uint32_t vcol_id[IRQ_PER_CHUNK];
+    /* LPI ID */
+    uint32_t id[IRQ_PER_CHUNK];
+};
+
 /*
  * The ITS command block, which is what the ITS actually parses.
  */
diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
index 187dc46..1b4b7d1 100644
--- a/xen/include/asm-arm/gic.h
+++ b/xen/include/asm-arm/gic.h
@@ -20,6 +20,7 @@
 
 #define NR_GIC_LOCAL_IRQS  NR_LOCAL_IRQS
 #define NR_GIC_SGI         16
+#define NR_GIC_LPI         8192
 #define MAX_RDIST_COUNT    4
 
 #define GICD_CTLR       (0x000)
-- 
1.7.9.5


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


 


Rackspace

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