[PATCH 08/13] lib: utils/irqchip: Add IMSIC library

Jessica Clarke jrtc27 at jrtc27.com
Wed Jan 19 08:12:36 PST 2022


On 19 Jan 2022, at 16:08, Xiang W <wxjstz at 126.com> wrote:
> 
> 在 2022-01-04星期二的 15:43 +0530,Anup Patel写道:
>> We add simple IMSIC library which is independent of hardware
>> description
>> format (FDT or ACPI). This IMSIC library can be used by custom OpenSBI
>> platform support to setup IMSIC for external interrupts.
>> 
>> Signed-off-by: Anup Patel <anup.patel at wdc.com>
>> Signed-off-by: Anup Patel <apatel at ventanamicro.com>
>> ---
>>  include/sbi_utils/irqchip/imsic.h |  50 ++++++
>>  lib/utils/irqchip/imsic.c         | 287
>> ++++++++++++++++++++++++++++++
>>  lib/utils/irqchip/objects.mk      |   1 +
>>  3 files changed, 338 insertions(+)
>>  create mode 100644 include/sbi_utils/irqchip/imsic.h
>>  create mode 100644 lib/utils/irqchip/imsic.c
>> 
>> diff --git a/include/sbi_utils/irqchip/imsic.h
>> b/include/sbi_utils/irqchip/imsic.h
>> new file mode 100644
>> index 0000000..cffcb5a
>> --- /dev/null
>> +++ b/include/sbi_utils/irqchip/imsic.h
>> @@ -0,0 +1,50 @@
>> +/*
>> + * SPDX-License-Identifier: BSD-2-Clause
>> + *
>> + * Copyright (c) 2021 Western Digital Corporation or its affiliates.
>> + * Copyright (c) 2022 Ventana Micro Systems Inc.
>> + *
>> + * Authors:
>> + *   Anup Patel <anup.patel at wdc.com>
>> + */
>> +
>> +#ifndef __IRQCHIP_IMSIC_H__
>> +#define __IRQCHIP_IMSIC_H__
>> +
>> +#include <sbi/sbi_types.h>
>> +
>> +#define IMSIC_MMIO_PAGE_SHIFT          12
>> +#define IMSIC_MMIO_PAGE_SZ             (1UL << IMSIC_MMIO_PAGE_SHIFT)
>> +
>> +#define IMSIC_MAX_REGS                 16
>> +
>> +struct imsic_regs {
>> +       unsigned long addr;
>> +       unsigned long size;
>> +};
>> +
>> +struct imsic_data {
>> +       bool targets_mmode;
>> +       u32 guest_index_bits;
>> +       u32 hart_index_bits;
>> +       u32 group_index_bits;
>> +       u32 group_index_shift;
>> +       unsigned long num_ids;
>> +       struct imsic_regs regs[IMSIC_MAX_REGS];
>> +};
>> +
>> +int imsic_map_hartid_to_data(u32 hartid, struct imsic_data *imsic,
>> int file);
>> +
>> +struct imsic_data *imsic_get_data(u32 hartid);
>> +
>> +int imsic_get_target_file(u32 hartid);
>> +
>> +void imsic_local_irqchip_init(void);
>> +
>> +int imsic_warm_irqchip_init(void);
>> +
>> +int imsic_data_check(struct imsic_data *imsic);
>> +
>> +int imsic_cold_irqchip_init(struct imsic_data *imsic);
>> +
>> +#endif
>> diff --git a/lib/utils/irqchip/imsic.c b/lib/utils/irqchip/imsic.c
>> new file mode 100644
>> index 0000000..f87321f
>> --- /dev/null
>> +++ b/lib/utils/irqchip/imsic.c
>> @@ -0,0 +1,287 @@
>> +/*
>> + * SPDX-License-Identifier: BSD-2-Clause
>> + *
>> + * Copyright (c) 2021 Western Digital Corporation or its affiliates.
>> + * Copyright (c) 2022 Ventana Micro Systems Inc.
>> + *
>> + * Authors:
>> + *   Anup Patel <anup.patel at wdc.com>
>> + */
>> +
>> +#include <sbi/riscv_asm.h>
>> +#include <sbi/riscv_io.h>
>> +#include <sbi/riscv_encoding.h>
>> +#include <sbi/sbi_console.h>
>> +#include <sbi/sbi_domain.h>
>> +#include <sbi/sbi_hartmask.h>
>> +#include <sbi/sbi_ipi.h>
>> +#include <sbi/sbi_error.h>
>> +#include <sbi/sbi_trap.h>
>> +#include <sbi_utils/irqchip/imsic.h>
>> +
>> +#define IMSIC_MMIO_PAGE_LE             0x00
>> +#define IMSIC_MMIO_PAGE_BE             0x04
>> +
>> +#define IMSIC_MIN_ID                   63
>> +#define IMSIC_MAX_ID                   2047
>> +
>> +#define IMSIC_EIDELIVERY               0x70
>> +
>> +#define IMSIC_EITHRESHOLD              0x72
>> +
>> +#define IMSIC_TOPEI                    0x76
>> +#define IMSIC_TOPEI_ID_SHIFT           16
>> +#define IMSIC_TOPEI_ID_MASK            0x7ff
>> +#define IMSIC_TOPEI_PRIO_MASK          0x7ff
>> +
>> +#define IMSIC_EIP0                     0x80
>> +
>> +#define IMSIC_EIP63                    0xbf
>> +
>> +#define IMSIC_EIE0                     0xc0
>> +
>> +#define IMSIC_EIE63                    0xff
>> +
>> +#define IMSIC_DISABLE_EIDELIVERY       0
>> +#define IMSIC_ENABLE_EIDELIVERY        1
>> +#define IMSIC_DISABLE_EITHRESHOLD      0
>> +#define IMSIC_ENABLE_EITHRESHOLD       IMSIC_MAX_ID
>> +
>> +#define IMSIC_IPI_ID                   1
>> +
>> +#define imsic_csr_write(__c, __v)      \
>> +do { \
>> +       csr_write(CSR_MISELECT, __c); \
>> +       csr_write(CSR_MIREG, __v); \
>> +} while (0)
>> +
>> +#define imsic_csr_read(__c)    \
>> +({ \
>> +       unsigned long __v; \
>> +       csr_write(CSR_MISELECT, __c); \
>> +       __v = csr_read(CSR_MIREG); \
>> +       __v; \
>> +})
>> +
>> +static struct imsic_data *imsic_hartid2data[SBI_HARTMASK_MAX_BITS];
>> +static int imsic_hartid2file[SBI_HARTMASK_MAX_BITS];
>> +
>> +int imsic_map_hartid_to_data(u32 hartid, struct imsic_data *imsic,
>> int file)
>> +{
>> +       if (!imsic || !imsic->targets_mmode ||
>> +           (SBI_HARTMASK_MAX_BITS <= hartid))
>> +               return SBI_EINVAL;
>> +
>> +       imsic_hartid2data[hartid] = imsic;
>> +       imsic_hartid2file[hartid] = file;
>> +       return 0;
>> +}
>> +
>> +struct imsic_data *imsic_get_data(u32 hartid)
>> +{
>> +       if (SBI_HARTMASK_MAX_BITS <= hartid)
>> +               return NULL;
>> +       return imsic_hartid2data[hartid];
>> +}
>> +
>> +int imsic_get_target_file(u32 hartid)
>> +{
>> +       if ((SBI_HARTMASK_MAX_BITS <= hartid) ||
>> +           !imsic_hartid2data[hartid])
>> +               return SBI_ENOENT;
>> +       return imsic_hartid2file[hartid];
>> +}
>> +
>> +static int imsic_external_irqfn(struct sbi_trap_regs *regs)
>> +{
>> +       ulong mirq;
>> +
>> +       while ((mirq = csr_swap(CSR_MTOPEI, 0))) {
>> +               mirq = (mirq >> IMSIC_TOPEI_ID_SHIFT);
>> +
>> +               switch (mirq) {
>> +               case IMSIC_IPI_ID:
>> +                       sbi_ipi_process();
>> +                       break;
> Why not add a timer interrupt?
>> +               default:
>> +                       sbi_printf("%s: unhandled IRQ%d\n",
>> +                                  __func__, (u32)mirq);
>> +                       break;
>> +               }
>> +       }
>> +
>> +       return 0;
>> +}
>> +
>> +static void imsic_ipi_send(u32 target_hart)
>> +{
>> +       unsigned long reloff;
>> +       struct imsic_regs *regs;
>> +       struct imsic_data *data = imsic_hartid2data[target_hart];
>> +       int file = imsic_hartid2file[target_hart];
>> +
>> +       if (!data || !data->targets_mmode)
>> +               return;
>> +
>> +       regs = &data->regs[0];
>> +       reloff = file * (1UL << data->guest_index_bits) *
>> IMSIC_MMIO_PAGE_SZ;
>> +       while (regs->size && (regs->size <= reloff)) {
>> +               reloff -= regs->size;
>> +               regs++;
>> +       }
>> +
>> +       if (regs->size && (reloff < regs->size))
>> +               writel(IMSIC_IPI_ID,
>> +                      (void *)(regs->addr + reloff +
>> IMSIC_MMIO_PAGE_LE));
> Using "void *" in arithmetic causes errors with -Werror=pointer-arith

The cast is outside the parentheses, the arithmetic happens first.

Jess




More information about the opensbi mailing list