On 2014/11/24 22:35, Marc Zyngier wrote:

[...]

> +static struct its_collection *its_build_mapd_cmd(struct its_cmd_block *cmd,
> +                                              struct its_cmd_desc *desc)
> +{
> +     unsigned long itt_addr;
> +     u8 size = order_base_2(desc->its_mapd_cmd.dev->nr_ites);

If @nr_ites is 1, then @size becomes 0, and... (see below)

> +
> +     itt_addr = virt_to_phys(desc->its_mapd_cmd.dev->itt);
> +     itt_addr = ALIGN(itt_addr, ITS_ITT_ALIGN);
> +
> +     its_encode_cmd(cmd, GITS_CMD_MAPD);
> +     its_encode_devid(cmd, desc->its_mapd_cmd.dev->device_id);
> +     its_encode_size(cmd, size - 1);

here (size - 1) becomes the value of ~0, which will exceed the maximum
supported bits of identifier.

Regards,
        Abel

> +     its_encode_itt(cmd, itt_addr);
> +     its_encode_valid(cmd, desc->its_mapd_cmd.valid);
> +
> +     its_fixup_cmd(cmd);
> +
> +     return desc->its_mapd_cmd.dev->collection;
> +}
> +
> +static struct its_collection *its_build_mapc_cmd(struct its_cmd_block *cmd,
> +                                              struct its_cmd_desc *desc)
> +{
> +     its_encode_cmd(cmd, GITS_CMD_MAPC);
> +     its_encode_collection(cmd, desc->its_mapc_cmd.col->col_id);
> +     its_encode_target(cmd, desc->its_mapc_cmd.col->target_address);
> +     its_encode_valid(cmd, desc->its_mapc_cmd.valid);
> +
> +     its_fixup_cmd(cmd);
> +
> +     return desc->its_mapc_cmd.col;
> +}
> +
> +static struct its_collection *its_build_mapvi_cmd(struct its_cmd_block *cmd,
> +                                               struct its_cmd_desc *desc)
> +{
> +     its_encode_cmd(cmd, GITS_CMD_MAPVI);
> +     its_encode_devid(cmd, desc->its_mapvi_cmd.dev->device_id);
> +     its_encode_event_id(cmd, desc->its_mapvi_cmd.event_id);
> +     its_encode_phys_id(cmd, desc->its_mapvi_cmd.phys_id);
> +     its_encode_collection(cmd, desc->its_mapvi_cmd.dev->collection->col_id);
> +
> +     its_fixup_cmd(cmd);
> +
> +     return desc->its_mapvi_cmd.dev->collection;
> +}
> +
> +static struct its_collection *its_build_movi_cmd(struct its_cmd_block *cmd,
> +                                              struct its_cmd_desc *desc)
> +{
> +     its_encode_cmd(cmd, GITS_CMD_MOVI);
> +     its_encode_devid(cmd, desc->its_movi_cmd.dev->device_id);
> +     its_encode_event_id(cmd, desc->its_movi_cmd.id);
> +     its_encode_collection(cmd, desc->its_movi_cmd.col->col_id);
> +
> +     its_fixup_cmd(cmd);
> +
> +     return desc->its_movi_cmd.dev->collection;
> +}
> +
> +static struct its_collection *its_build_discard_cmd(struct its_cmd_block 
> *cmd,
> +                                                 struct its_cmd_desc *desc)
> +{
> +     its_encode_cmd(cmd, GITS_CMD_DISCARD);
> +     its_encode_devid(cmd, desc->its_discard_cmd.dev->device_id);
> +     its_encode_event_id(cmd, desc->its_discard_cmd.event_id);
> +
> +     its_fixup_cmd(cmd);
> +
> +     return desc->its_discard_cmd.dev->collection;
> +}
> +
> +static struct its_collection *its_build_inv_cmd(struct its_cmd_block *cmd,
> +                                             struct its_cmd_desc *desc)
> +{
> +     its_encode_cmd(cmd, GITS_CMD_INV);
> +     its_encode_devid(cmd, desc->its_inv_cmd.dev->device_id);
> +     its_encode_event_id(cmd, desc->its_inv_cmd.event_id);
> +
> +     its_fixup_cmd(cmd);
> +
> +     return desc->its_inv_cmd.dev->collection;
> +}
> +
> +static struct its_collection *its_build_invall_cmd(struct its_cmd_block *cmd,
> +                                                struct its_cmd_desc *desc)
> +{
> +     its_encode_cmd(cmd, GITS_CMD_INVALL);
> +     its_encode_collection(cmd, desc->its_mapc_cmd.col->col_id);
> +
> +     its_fixup_cmd(cmd);
> +
> +     return NULL;
> +}
> +
> +static u64 its_cmd_ptr_to_offset(struct its_node *its,
> +                              struct its_cmd_block *ptr)
> +{
> +     return (ptr - its->cmd_base) * sizeof(*ptr);
> +}
> +
> +static int its_queue_full(struct its_node *its)
> +{
> +     int widx;
> +     int ridx;
> +
> +     widx = its->cmd_write - its->cmd_base;
> +     ridx = readl_relaxed(its->base + GITS_CREADR) / sizeof(struct 
> its_cmd_block);
> +
> +     /* This is incredibly unlikely to happen, unless the ITS locks up. */
> +     if (((widx + 1) % ITS_CMD_QUEUE_NR_ENTRIES) == ridx)
> +             return 1;
> +
> +     return 0;
> +}
> +
> +static struct its_cmd_block *its_allocate_entry(struct its_node *its)
> +{
> +     struct its_cmd_block *cmd;
> +     u32 count = 1000000;    /* 1s! */
> +
> +     while (its_queue_full(its)) {
> +             count--;
> +             if (!count) {
> +                     pr_err_ratelimited("ITS queue not draining\n");
> +                     return NULL;
> +             }
> +             cpu_relax();
> +             udelay(1);
> +     }
> +
> +     cmd = its->cmd_write++;
> +
> +     /* Handle queue wrapping */
> +     if (its->cmd_write == (its->cmd_base + ITS_CMD_QUEUE_NR_ENTRIES))
> +             its->cmd_write = its->cmd_base;
> +
> +     return cmd;
> +}
> +
> +static struct its_cmd_block *its_post_commands(struct its_node *its)
> +{
> +     u64 wr = its_cmd_ptr_to_offset(its, its->cmd_write);
> +
> +     writel_relaxed(wr, its->base + GITS_CWRITER);
> +
> +     return its->cmd_write;
> +}
> +
> +static void its_flush_cmd(struct its_node *its, struct its_cmd_block *cmd)
> +{
> +     /*
> +      * Make sure the commands written to memory are observable by
> +      * the ITS.
> +      */
> +     if (its->flags & ITS_FLAGS_CMDQ_NEEDS_FLUSHING)
> +             __flush_dcache_area(cmd, sizeof(*cmd));
> +     else
> +             dsb(ishst);
> +}
> +
> +static void its_wait_for_range_completion(struct its_node *its,
> +                                       struct its_cmd_block *from,
> +                                       struct its_cmd_block *to)
> +{
> +     u64 rd_idx, from_idx, to_idx;
> +     u32 count = 1000000;    /* 1s! */
> +
> +     from_idx = its_cmd_ptr_to_offset(its, from);
> +     to_idx = its_cmd_ptr_to_offset(its, to);
> +
> +     while (1) {
> +             rd_idx = readl_relaxed(its->base + GITS_CREADR);
> +             if (rd_idx >= to_idx || rd_idx < from_idx)
> +                     break;
> +
> +             count--;
> +             if (!count) {
> +                     pr_err_ratelimited("ITS queue timeout\n");
> +                     return;
> +             }
> +             cpu_relax();
> +             udelay(1);
> +     }
> +}
> +
> +static void its_send_single_command(struct its_node *its,
> +                                 its_cmd_builder_t builder,
> +                                 struct its_cmd_desc *desc)
> +{
> +     struct its_cmd_block *cmd, *sync_cmd, *next_cmd;
> +     struct its_collection *sync_col;
> +
> +     raw_spin_lock(&its->lock);
> +
> +     cmd = its_allocate_entry(its);
> +     if (!cmd) {             /* We're soooooo screewed... */
> +             pr_err_ratelimited("ITS can't allocate, dropping command\n");
> +             raw_spin_unlock(&its->lock);
> +             return;
> +     }
> +     sync_col = builder(cmd, desc);
> +     its_flush_cmd(its, cmd);
> +
> +     if (sync_col) {
> +             sync_cmd = its_allocate_entry(its);
> +             if (!sync_cmd) {
> +                     pr_err_ratelimited("ITS can't SYNC, skipping\n");
> +                     goto post;
> +             }
> +             its_encode_cmd(sync_cmd, GITS_CMD_SYNC);
> +             its_encode_target(sync_cmd, sync_col->target_address);
> +             its_fixup_cmd(sync_cmd);
> +             its_flush_cmd(its, sync_cmd);
> +     }
> +
> +post:
> +     next_cmd = its_post_commands(its);
> +     raw_spin_unlock(&its->lock);
> +
> +     its_wait_for_range_completion(its, cmd, next_cmd);
> +}
> +
> +static void its_send_inv(struct its_device *dev, u32 event_id)
> +{
> +     struct its_cmd_desc desc;
> +
> +     desc.its_inv_cmd.dev = dev;
> +     desc.its_inv_cmd.event_id = event_id;
> +
> +     its_send_single_command(dev->its, its_build_inv_cmd, &desc);
> +}
> +
> +static void its_send_mapd(struct its_device *dev, int valid)
> +{
> +     struct its_cmd_desc desc;
> +
> +     desc.its_mapd_cmd.dev = dev;
> +     desc.its_mapd_cmd.valid = !!valid;
> +
> +     its_send_single_command(dev->its, its_build_mapd_cmd, &desc);
> +}
> +
> +static void its_send_mapc(struct its_node *its, struct its_collection *col,
> +                       int valid)
> +{
> +     struct its_cmd_desc desc;
> +
> +     desc.its_mapc_cmd.col = col;
> +     desc.its_mapc_cmd.valid = !!valid;
> +
> +     its_send_single_command(its, its_build_mapc_cmd, &desc);
> +}
> +
> +static void its_send_mapvi(struct its_device *dev, u32 irq_id, u32 id)
> +{
> +     struct its_cmd_desc desc;
> +
> +     desc.its_mapvi_cmd.dev = dev;
> +     desc.its_mapvi_cmd.phys_id = irq_id;
> +     desc.its_mapvi_cmd.event_id = id;
> +
> +     its_send_single_command(dev->its, its_build_mapvi_cmd, &desc);
> +}
> +
> +static void its_send_movi(struct its_device *dev,
> +                       struct its_collection *col, u32 id)
> +{
> +     struct its_cmd_desc desc;
> +
> +     desc.its_movi_cmd.dev = dev;
> +     desc.its_movi_cmd.col = col;
> +     desc.its_movi_cmd.id = id;
> +
> +     its_send_single_command(dev->its, its_build_movi_cmd, &desc);
> +}
> +
> +static void its_send_discard(struct its_device *dev, u32 id)
> +{
> +     struct its_cmd_desc desc;
> +
> +     desc.its_discard_cmd.dev = dev;
> +     desc.its_discard_cmd.event_id = id;
> +
> +     its_send_single_command(dev->its, its_build_discard_cmd, &desc);
> +}
> +
> +static void its_send_invall(struct its_node *its, struct its_collection *col)
> +{
> +     struct its_cmd_desc desc;
> +
> +     desc.its_invall_cmd.col = col;
> +
> +     its_send_single_command(its, its_build_invall_cmd, &desc);
> +}
> diff --git a/include/linux/irqchip/arm-gic-v3.h 
> b/include/linux/irqchip/arm-gic-v3.h
> index 040615a..21c9d70 100644
> --- a/include/linux/irqchip/arm-gic-v3.h
> +++ b/include/linux/irqchip/arm-gic-v3.h
> @@ -80,9 +80,27 @@
>  #define GICR_MOVALLR                 0x0110
>  #define GICR_PIDR2                   GICD_PIDR2
>  
> +#define GICR_CTLR_ENABLE_LPIS                (1UL << 0)
> +
> +#define GICR_TYPER_CPU_NUMBER(r)     (((r) >> 8) & 0xffff)
> +
>  #define GICR_WAKER_ProcessorSleep    (1U << 1)
>  #define GICR_WAKER_ChildrenAsleep    (1U << 2)
>  
> +#define GICR_PROPBASER_NonShareable  (0U << 10)
> +#define GICR_PROPBASER_InnerShareable        (1U << 10)
> +#define GICR_PROPBASER_OuterShareable        (2U << 10)
> +#define GICR_PROPBASER_SHAREABILITY_MASK (3UL << 10)
> +#define GICR_PROPBASER_nCnB          (0U << 7)
> +#define GICR_PROPBASER_nC            (1U << 7)
> +#define GICR_PROPBASER_RaWt          (2U << 7)
> +#define GICR_PROPBASER_RaWb          (3U << 7)
> +#define GICR_PROPBASER_WaWt          (4U << 7)
> +#define GICR_PROPBASER_WaWb          (5U << 7)
> +#define GICR_PROPBASER_RaWaWt                (6U << 7)
> +#define GICR_PROPBASER_RaWaWb                (7U << 7)
> +#define GICR_PROPBASER_IDBITS_MASK   (0x1f)
> +
>  /*
>   * Re-Distributor registers, offsets from SGI_base
>   */
> @@ -95,9 +113,93 @@
>  #define GICR_IPRIORITYR0             GICD_IPRIORITYR
>  #define GICR_ICFGR0                  GICD_ICFGR
>  
> +#define GICR_TYPER_PLPIS             (1U << 0)
>  #define GICR_TYPER_VLPIS             (1U << 1)
>  #define GICR_TYPER_LAST                      (1U << 4)
>  
> +#define LPI_PROP_GROUP1                      (1 << 1)
> +#define LPI_PROP_ENABLED             (1 << 0)
> +
> +/*
> + * ITS registers, offsets from ITS_base
> + */
> +#define GITS_CTLR                    0x0000
> +#define GITS_IIDR                    0x0004
> +#define GITS_TYPER                   0x0008
> +#define GITS_CBASER                  0x0080
> +#define GITS_CWRITER                 0x0088
> +#define GITS_CREADR                  0x0090
> +#define GITS_BASER                   0x0100
> +#define GITS_PIDR2                   GICR_PIDR2
> +
> +#define GITS_TRANSLATER                      0x10040
> +
> +#define GITS_TYPER_PTA                       (1UL << 19)
> +
> +#define GITS_CBASER_VALID            (1UL << 63)
> +#define GITS_CBASER_nCnB             (0UL << 59)
> +#define GITS_CBASER_nC                       (1UL << 59)
> +#define GITS_CBASER_RaWt             (2UL << 59)
> +#define GITS_CBASER_RaWb             (3UL << 59)
> +#define GITS_CBASER_WaWt             (4UL << 59)
> +#define GITS_CBASER_WaWb             (5UL << 59)
> +#define GITS_CBASER_RaWaWt           (6UL << 59)
> +#define GITS_CBASER_RaWaWb           (7UL << 59)
> +#define GITS_CBASER_NonShareable     (0UL << 10)
> +#define GITS_CBASER_InnerShareable   (1UL << 10)
> +#define GITS_CBASER_OuterShareable   (2UL << 10)
> +#define GITS_CBASER_SHAREABILITY_MASK        (3UL << 10)
> +
> +#define GITS_BASER_NR_REGS           8
> +
> +#define GITS_BASER_VALID             (1UL << 63)
> +#define GITS_BASER_nCnB                      (0UL << 59)
> +#define GITS_BASER_nC                        (1UL << 59)
> +#define GITS_BASER_RaWt                      (2UL << 59)
> +#define GITS_BASER_RaWb                      (3UL << 59)
> +#define GITS_BASER_WaWt                      (4UL << 59)
> +#define GITS_BASER_WaWb                      (5UL << 59)
> +#define GITS_BASER_RaWaWt            (6UL << 59)
> +#define GITS_BASER_RaWaWb            (7UL << 59)
> +#define GITS_BASER_TYPE_SHIFT                (56)
> +#define GITS_BASER_TYPE(r)           (((r) >> GITS_BASER_TYPE_SHIFT) & 7)
> +#define GITS_BASER_ENTRY_SIZE_SHIFT  (48)
> +#define GITS_BASER_ENTRY_SIZE(r)     ((((r) >> GITS_BASER_ENTRY_SIZE_SHIFT) 
> & 0xff) + 1)
> +#define GITS_BASER_NonShareable              (0UL << 10)
> +#define GITS_BASER_InnerShareable    (1UL << 10)
> +#define GITS_BASER_OuterShareable    (2UL << 10)
> +#define GITS_BASER_SHAREABILITY_SHIFT        (10)
> +#define GITS_BASER_SHAREABILITY_MASK (3UL << GITS_BASER_SHAREABILITY_SHIFT)
> +#define GITS_BASER_PAGE_SIZE_SHIFT   (8)
> +#define GITS_BASER_PAGE_SIZE_4K              (0UL << 
> GITS_BASER_PAGE_SIZE_SHIFT)
> +#define GITS_BASER_PAGE_SIZE_16K     (1UL << GITS_BASER_PAGE_SIZE_SHIFT)
> +#define GITS_BASER_PAGE_SIZE_64K     (2UL << GITS_BASER_PAGE_SIZE_SHIFT)
> +#define GITS_BASER_PAGE_SIZE_MASK    (3UL << GITS_BASER_PAGE_SIZE_SHIFT)
> +
> +#define GITS_BASER_TYPE_NONE         0
> +#define GITS_BASER_TYPE_DEVICE               1
> +#define GITS_BASER_TYPE_VCPU         2
> +#define GITS_BASER_TYPE_CPU          3
> +#define GITS_BASER_TYPE_COLLECTION   4
> +#define GITS_BASER_TYPE_RESERVED5    5
> +#define GITS_BASER_TYPE_RESERVED6    6
> +#define GITS_BASER_TYPE_RESERVED7    7
> +
> +/*
> + * ITS commands
> + */
> +#define GITS_CMD_MAPD                        0x08
> +#define GITS_CMD_MAPC                        0x09
> +#define GITS_CMD_MAPVI                       0x0a
> +#define GITS_CMD_MOVI                        0x01
> +#define GITS_CMD_DISCARD             0x0f
> +#define GITS_CMD_INV                 0x0c
> +#define GITS_CMD_MOVALL                      0x0e
> +#define GITS_CMD_INVALL                      0x0d
> +#define GITS_CMD_INT                 0x03
> +#define GITS_CMD_CLEAR                       0x04
> +#define GITS_CMD_SYNC                        0x05
> +
>  /*
>   * CPU interface registers
>   */



--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to