[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v2 05/27] ARM: GICv3 ITS: introduce ITS command handling
Hi Andre, On 03/16/2017 06:20 AM, Andre Przywara wrote: > To be able to easily send commands to the ITS, create the respective > wrapper functions, which take care of the ring buffer. > The first two commands we implement provide methods to map a collection > to a redistributor (aka host core) and to flush the command queue (SYNC). > Start using these commands for mapping one collection to each host CPU. > > Signed-off-by: Andre Przywara <andre.przywara@xxxxxxx> > --- > xen/arch/arm/gic-v3-its.c | 181 > +++++++++++++++++++++++++++++++++++++- > xen/arch/arm/gic-v3-lpi.c | 22 +++++ > xen/arch/arm/gic-v3.c | 19 +++- > xen/include/asm-arm/gic_v3_defs.h | 2 + > xen/include/asm-arm/gic_v3_its.h | 38 ++++++++ > 5 files changed, 260 insertions(+), 2 deletions(-) > > diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c > index e5601ed..5c11b0d 100644 > --- a/xen/arch/arm/gic-v3-its.c > +++ b/xen/arch/arm/gic-v3-its.c > @@ -19,11 +19,14 @@ > */ > > #include <xen/lib.h> > +#include <xen/delay.h> > #include <xen/mm.h> > #include <xen/sizes.h> > +#include <asm/gic.h> > #include <asm/gic_v3_defs.h> > #include <asm/gic_v3_its.h> > #include <asm/io.h> > +#include <asm/page.h> > > #define ITS_CMD_QUEUE_SZ SZ_64K > > @@ -34,6 +37,145 @@ bool gicv3_its_host_has_its(void) > return !list_empty(&host_its_list); > } > > +#define BUFPTR_MASK GENMASK(19, 5) > +static int its_send_command(struct host_its *hw_its, const void *its_cmd) > +{ > + s_time_t deadline = NOW() + MILLISECS(1); > + uint64_t readp, writep; > + int ret = -EBUSY; > + > + /* No ITS commands from an interrupt handler (at the moment). */ > + ASSERT(!in_irq()); > + > + spin_lock(&hw_its->cmd_lock); > + > + do { > + readp = readq_relaxed(hw_its->its_base + GITS_CREADR) & BUFPTR_MASK; > + writep = readq_relaxed(hw_its->its_base + GITS_CWRITER) & > BUFPTR_MASK; > + > + if ( ((writep + ITS_CMD_SIZE) % ITS_CMD_QUEUE_SZ) != readp ) > + { > + ret = 0; > + break; > + } > + > + /* > + * If the command queue is full, wait for a bit in the hope it drains > + * before giving up. > + */ > + spin_unlock(&hw_its->cmd_lock); > + cpu_relax(); > + udelay(1); > + spin_lock(&hw_its->cmd_lock); > + } while ( NOW() <= deadline ); > + > + if ( ret ) > + { > + spin_unlock(&hw_its->cmd_lock); > + printk(XENLOG_WARNING "ITS: command queue full.\n"); > + return ret; > + } > + > + memcpy(hw_its->cmd_buf + writep, its_cmd, ITS_CMD_SIZE); > + if ( hw_its->flags & HOST_ITS_FLUSH_CMD_QUEUE ) > + clean_and_invalidate_dcache_va_range(hw_its->cmd_buf + writep, > + ITS_CMD_SIZE); > + else > + dsb(ishst); > + > + writep = (writep + ITS_CMD_SIZE) % ITS_CMD_QUEUE_SZ; > + writeq_relaxed(writep & BUFPTR_MASK, hw_its->its_base + GITS_CWRITER); > + > + spin_unlock(&hw_its->cmd_lock); > + > + return 0; > +} > + > +/* Wait for an ITS to finish processing all commands. */ > +static int gicv3_its_wait_commands(struct host_its *hw_its) > +{ > + s_time_t deadline = NOW() + MILLISECS(100); > + uint64_t readp, writep; > + > + do { > + spin_lock(&hw_its->cmd_lock); > + readp = readq_relaxed(hw_its->its_base + GITS_CREADR) & BUFPTR_MASK; > + writep = readq_relaxed(hw_its->its_base + GITS_CWRITER) & > BUFPTR_MASK; > + spin_unlock(&hw_its->cmd_lock); > + > + if ( readp == writep ) > + return 0; > + > + cpu_relax(); > + udelay(1); > + } while ( NOW() <= deadline ); > + > + return -ETIMEDOUT; > +} > + > +static uint64_t encode_rdbase(struct host_its *hw_its, unsigned int cpu, > + uint64_t reg) > +{ > + reg &= ~GENMASK(51, 16); > + > + reg |= gicv3_get_redist_address(cpu, hw_its->flags & HOST_ITS_USES_PTA); > + > + return reg; > +} > + > +static int its_send_cmd_sync(struct host_its *its, unsigned int cpu) > +{ > + uint64_t cmd[4]; > + > + cmd[0] = GITS_CMD_SYNC; > + cmd[1] = 0x00; > + cmd[2] = encode_rdbase(its, cpu, 0x0); > + cmd[3] = 0x00; > + > + return its_send_command(its, cmd); > +} > + > +static int its_send_cmd_mapc(struct host_its *its, uint32_t collection_id, > + unsigned int cpu) > +{ > + uint64_t cmd[4]; > + > + cmd[0] = GITS_CMD_MAPC; > + cmd[1] = 0x00; > + cmd[2] = encode_rdbase(its, cpu, (collection_id & GENMASK(15, 0))); > + 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(unsigned int cpu) > +{ > + struct host_its *its; > + int ret; > + > + list_for_each_entry(its, &host_its_list, entry) > + { > + if ( !its->cmd_buf ) > + continue; > + > + ret = its_send_cmd_mapc(its, cpu, cpu); > + if ( ret ) > + return ret; > + > + ret = its_send_cmd_sync(its, cpu); > + if ( ret ) > + return ret; > + > + ret = gicv3_its_wait_commands(its); > + if ( ret ) > + return ret; > + } > + > + return 0; > +} > + > #define BASER_ATTR_MASK \ > ((0x3UL << GITS_BASER_SHAREABILITY_SHIFT) | \ > (0x7UL << GITS_BASER_OUTER_CACHEABILITY_SHIFT) | \ > @@ -184,22 +326,59 @@ retry: > return -EINVAL; > } > > +/* > + * Before an ITS gets initialized, it should be in a quiescent state, where > + * all outstanding commands and transactions have finished. > + * So if the ITS is already enabled, turn it off and wait for all outstanding > + * operations to get processed by polling the QUIESCENT bit. > + */ > +static int gicv3_disable_its(struct host_its *hw_its) > +{ > + uint32_t reg; > + s_time_t deadline = NOW() + MILLISECS(100); > + > + reg = readl_relaxed(hw_its->its_base + GITS_CTLR); > + if ( (reg & GITS_CTLR_QUIESCENT) && !(reg & GITS_CTLR_ENABLE) ) nit: I prefer changing to 'if ( !(reg & GITS_CTLR_ENABLE) && (reg & GITS_CTLR_QUIESCENT) ) ' because bit GITS_CTLR_QUIESCENT is not valid if ITS hardware is in enabled state. > #endif -- 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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |