[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Xen-devel] [PATCH 06/28] ARM: GICv3 ITS: introduce ITS command handling
Hi Andre,
Continuing the review where I left it yesterday.
On 30/01/2017 18:31, Andre Przywara wrote:
[...]
+/* Wait for an ITS to become quiescient (all ITS operations completed). */
+static int gicv3_its_wait_quiescient(struct host_its *hw_its)
+{
+ uint32_t reg;
+ s_time_t deadline = NOW() + MILLISECS(1000);
+
+ reg = readl_relaxed(hw_its->its_base + GITS_CTLR);
+ if ( (reg & (GITS_CTLR_QUIESCENT | GITS_CTLR_ENABLE)) ==
GITS_CTLR_QUIESCENT )
It would be clearer if you rewrite this:
(reg & GITS_CTLR_QUIESCENT) && !(reg & GITS_CTLR_ENABLE).
+ return 0;
+
+ writel_relaxed(reg & ~GITS_CTLR_ENABLE, hw_its->its_base + GITS_CTLR);
It feels a bit odd to disable the ITS in a function containing "wait" in
the name. You may want to rename the function to reflect the behavior.
+
+ do {
+ reg = readl_relaxed(hw_its->its_base + GITS_CTLR);
+ if ( reg & GITS_CTLR_QUIESCENT )
+ return 0;
+
+ cpu_relax();
+ udelay(1);
+ } while ( NOW() <= deadline );
+
+ dprintk(XENLOG_ERR, "ITS not quiescient\n");
+ return -ETIMEDOUT;
+}
+
static unsigned int max_its_device_bits = CONFIG_MAX_PHYS_ITS_DEVICE_BITS;
integer_param("max_its_device_bits", max_its_device_bits);
int gicv3_its_init(struct host_its *hw_its)
{
uint64_t reg;
- int i;
+ int i, ret;
hw_its->its_base = ioremap_nocache(hw_its->addr, hw_its->size);
if ( !hw_its->its_base )
return -ENOMEM;
+ ret = gicv3_its_wait_quiescient(hw_its);
+ if ( ret )
+ return ret;
+
+ reg = readq_relaxed(hw_its->its_base + GITS_TYPER);
+ if ( reg & GITS_TYPER_PTA )
+ hw_its->flags |= HOST_ITS_USES_PTA;
+
for ( i = 0; i < GITS_BASER_NR_REGS; i++ )
{
void __iomem *basereg = hw_its->its_base + GITS_BASER0 + i * 8;
@@ -196,6 +322,20 @@ int gicv3_its_init(struct host_its *hw_its)
return -ENOMEM;
writeq_relaxed(0, hw_its->its_base + GITS_CWRITER);
[...]
diff --git a/xen/arch/arm/gic-v3-lpi.c b/xen/arch/arm/gic-v3-lpi.c
index e2fc901..5911b91 100644
--- a/xen/arch/arm/gic-v3-lpi.c
+++ b/xen/arch/arm/gic-v3-lpi.c
@@ -30,11 +30,31 @@ static struct {
unsigned int host_lpi_bits;
} lpi_data;
+/* Physical redistributor address */
+static DEFINE_PER_CPU(paddr_t, redist_addr);
+/* Redistributor ID */
+static DEFINE_PER_CPU(int, redist_id);
s/int/unsigned int/
/* Pending table for each redistributor */
static DEFINE_PER_CPU(void *, pending_table);
Rather than defining 3 per-cpu variables, could we merge all in a single
structure?
#define MAX_PHYS_LPIS (BIT_ULL(lpi_data.host_lpi_bits) - LPI_OFFSET)
+/* Stores this redistributor's physical address and ID in a per-CPU variable */
+void gicv3_set_redist_address(paddr_t address, int redist_id)
s/int/unsigned int/
+{
+ this_cpu(redist_addr) = address;
+ this_cpu(redist_id) = redist_id;
+}
+
+/* Returns a redistributor's ID (either as an address or as an ID) */
+uint64_t gicv3_get_redist_address(int cpu, bool use_pta)
s/int/unsigned int/
+{
+ if ( use_pta )
+ return per_cpu(redist_addr, cpu) & GENMASK(51, 16);
+ else
+ return per_cpu(redist_id, cpu) << 16;
What if the function is called before the CPU has been setup? If it
cannot happen, please document it.
+}
+
uint64_t gicv3_lpi_allocate_pendtable(void)
{
uint64_t reg;
diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
index 440c079..5f825a6 100644
--- a/xen/arch/arm/gic-v3.c
+++ b/xen/arch/arm/gic-v3.c
@@ -644,7 +644,7 @@ static int gicv3_rdist_init_lpis(void __iomem * rdist_base)
return -ENOMEM;
writeq_relaxed(table_reg, rdist_base + GICR_PROPBASER);
- return 0;
+ return gicv3_its_setup_collection(smp_processor_id());
}
static int __init gicv3_populate_rdist(void)
@@ -692,7 +692,21 @@ static int __init gicv3_populate_rdist(void)
if ( typer & GICR_TYPER_PLPIS )
{
- int ret;
+ paddr_t rdist_addr;
+ int procnum, ret;
procnum should be unsigned.
+
+ rdist_addr = gicv3.rdist_regions[i].base;
+ rdist_addr += ptr - gicv3.rdist_regions[i].map_base;
+ procnum = (typer & GICR_TYPER_PROC_NUM_MASK);
+ procnum >>= GICR_TYPER_PROC_NUM_SHIFT;
+
+ /*
+ * The ITS refers to redistributors either by their
physical
+ * address or by their ID. Determine those two values and
+ * let the ITS code store them in per host CPU variables to
+ * later be able to address those redistributors.
+ */
This comment does not look useful and is misleading as the code to
get/set the redistributor information is living in gic-v3-lpi.c and not
gic-v3-its.c.
+ gicv3_set_redist_address(rdist_addr, procnum);
ret = gicv3_rdist_init_lpis(ptr);
if ( ret && ret != -ENODEV )
diff --git a/xen/include/asm-arm/gic_v3_defs.h
b/xen/include/asm-arm/gic_v3_defs.h
index b307322..878bae2 100644
--- a/xen/include/asm-arm/gic_v3_defs.h
+++ b/xen/include/asm-arm/gic_v3_defs.h
@@ -101,6 +101,8 @@
#define GICR_TYPER_PLPIS (1U << 0)
#define GICR_TYPER_VLPIS (1U << 1)
#define GICR_TYPER_LAST (1U << 4)
+#define GICR_TYPER_PROC_NUM_SHIFT 8
+#define GICR_TYPER_PROC_NUM_MASK (0xffff << GICR_TYPER_PROC_NUM_SHIFT)
/* For specifying the inner cacheability type only */
#define GIC_BASER_CACHE_nCnB 0ULL
diff --git a/xen/include/asm-arm/gic_v3_its.h b/xen/include/asm-arm/gic_v3_its.h
index ff5572f..8288185 100644
--- a/xen/include/asm-arm/gic_v3_its.h
+++ b/xen/include/asm-arm/gic_v3_its.h
@@ -40,6 +40,9 @@
#define GITS_CTLR_QUIESCENT BIT(31)
#define GITS_CTLR_ENABLE BIT(0)
+#define GITS_TYPER_PTA BIT_ULL(19)
+#define GITS_TYPER_IDBITS_SHIFT 8
+
#define GITS_IIDR_VALUE 0x34c
#define GITS_BASER_INDIRECT BIT_ULL(62)
@@ -67,10 +70,27 @@
#define GITS_CBASER_SIZE_MASK 0xff
+/* ITS command definitions */
+#define ITS_CMD_SIZE 32
+
+#define GITS_CMD_MOVI 0x01
+#define GITS_CMD_INT 0x03
+#define GITS_CMD_CLEAR 0x04
+#define GITS_CMD_SYNC 0x05
+#define GITS_CMD_MAPD 0x08
+#define GITS_CMD_MAPC 0x09
+#define GITS_CMD_MAPTI 0x0a
+#define GITS_CMD_MAPI 0x0b
+#define GITS_CMD_INV 0x0c
+#define GITS_CMD_INVALL 0x0d
+#define GITS_CMD_MOVALL 0x0e
+#define GITS_CMD_DISCARD 0x0f
+
#ifndef __ASSEMBLY__
#include <xen/device_tree.h>
#define HOST_ITS_FLUSH_CMD_QUEUE (1U << 0)
+#define HOST_ITS_USES_PTA (1U << 1)
/* data structure for each hardware ITS */
struct host_its {
@@ -79,6 +99,7 @@ struct host_its {
paddr_t addr;
paddr_t size;
void __iomem *its_base;
+ spinlock_t cmd_lock;
I was expecting to see a code to initialize the spinlock. So please
initialize the spinlock.
void *cmd_buf;
unsigned int flags;
};
Cheers,
--
Julien Grall
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel
|