[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v2 11/16] xen/riscv: aplic_init() implementation
aplic_init() function does the following few things: - checks that IMSIC in device tree node ( by checking msi-parent property in APLIC node ) is present as current one implmenetaion of AIA is supported only MSI method. - initialize IMSIC based on IMSIC device tree node - Read value of APLIC's paddr start/end and size. - Map aplic.regs - Setup APLIC initial state interrupts (disable all interrupts, set interrupt type and default priority, confgifure APLIC domaincfg) by calling aplic_init_hw_interrutps(). aplic_init() is based on the code from [1] and [2]. Since Microchip originally developed aplic.c, an internal discussion with them led to the decision to use the MIT license. [1] https://gitlab.com/xen-project/people/olkur/xen/-/commit/7cfb4bd4748ca268142497ac5c327d2766fb342d [2] https://gitlab.com/xen-project/people/olkur/xen/-/commit/392a531bfad39bf4656ce8128e004b241b8b3f3e Co-developed-by: Romain Caritey <Romain.Caritey@xxxxxxxxxxxxx> Signed-off-by: Oleksii Kurochko <oleksii.kurochko@xxxxxxxxx> --- Changes in V2: - use __ro_after_init for aplic_ops. - s/nr_irqs/num_irqs. - s/dt_processor_hartid/dt_processor_cpuid. - Drop confusing comment in aplic_init_hw_interrupts(). - Code style fixes. - Drop years for Copyright. - Revert changes which drop nr_irq define from asm/irq.h, it shouldn't be, at least, part of this patch. - Drop paddr_enf from struct aplic_regs. It is enough to have pair (paddr_start, size). - Make struct aplic_priv of asm/aplic.h private by moving it to riscv/aplic-priv.h. - Add the comment above the initialization of APLIC's target register. - use writel() to access APLIC's registers. - use 'unsinged int' for local variable i in aplic_init_hw_interrupts. - Add the check that all modes in interrupts-extended property of imsic node are equal. And drop rc != EOVERFLOW when interrupts-extended property is read. - Add cf_check to aplic_init(). - Fix a cycle of clrie register initialization in aplic_init_hw_interrupts(). Previous implementation leads to out-of-boundary. - Declare member num_irqs in struct intc_info as it is used by APLIC code. --- xen/arch/riscv/aplic-priv.h | 34 +++++++++ xen/arch/riscv/aplic.c | 106 +++++++++++++++++++++++++++++ xen/arch/riscv/include/asm/aplic.h | 64 +++++++++++++++++ xen/arch/riscv/include/asm/intc.h | 3 + 4 files changed, 207 insertions(+) create mode 100644 xen/arch/riscv/aplic-priv.h create mode 100644 xen/arch/riscv/include/asm/aplic.h diff --git a/xen/arch/riscv/aplic-priv.h b/xen/arch/riscv/aplic-priv.h new file mode 100644 index 0000000000..8a208dba8a --- /dev/null +++ b/xen/arch/riscv/aplic-priv.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: MIT */ + +/* + * xen/arch/riscv/aplic.h + * + * Private part of aplic.h header. + * + * RISC-V Advanced Platform-Level Interrupt Controller support + * + * Copyright (c) Microchip. + * Copyright (c) Vates. + */ + +#ifndef ASM__RISCV_PRIV_APLIC_H +#define ASM__RISCV_PRIV_APLIC_H + +#include <xen/types.h> + +#include <asm/aplic.h> +#include <asm/imsic.h> + +struct aplic_priv { + /* base physical address and size */ + paddr_t paddr_start; + size_t size; + + /* registers */ + volatile struct aplic_regs *regs; + + /* imsic configuration */ + const struct imsic_config *imsic_cfg; +}; + +#endif /* ASM__RISCV_PRIV_APLIC_H */ diff --git a/xen/arch/riscv/aplic.c b/xen/arch/riscv/aplic.c index 10ae81f7ac..797e5df020 100644 --- a/xen/arch/riscv/aplic.c +++ b/xen/arch/riscv/aplic.c @@ -9,19 +9,121 @@ * Copyright (c) 2024-2025 Vates */ +#include <xen/device_tree.h> #include <xen/errno.h> #include <xen/init.h> #include <xen/irq.h> +#include <xen/mm.h> #include <xen/sections.h> #include <xen/types.h> +#include <xen/vmap.h> + +#include "aplic-priv.h" #include <asm/device.h> +#include <asm/imsic.h> #include <asm/intc.h> +#include <asm/riscv_encoding.h> + +#define APLIC_DEFAULT_PRIORITY 1 + +static struct aplic_priv aplic; static struct intc_info __ro_after_init aplic_info = { .hw_version = INTC_APLIC, }; +static void __init aplic_init_hw_interrupts(void) +{ + unsigned int i; + + /* Disable all interrupts */ + for ( i = 0; i < ARRAY_SIZE(aplic.regs->clrie); i++) + writel(-1U, &aplic.regs->clrie[i]); + + /* Set interrupt type and default priority for all interrupts */ + for ( i = 1; i <= aplic_info.num_irqs; i++ ) + { + writel(0, &aplic.regs->sourcecfg[i - 1]); + /* + * Low bits of target register contains Interrupt Priority bits which + * can't be zero according to AIA spec. + * Thereby they are initialized to APLIC_DEFAULT_PRIORITY. + */ + writel(APLIC_DEFAULT_PRIORITY, &aplic.regs->target[i - 1]); + } + + writel(APLIC_DOMAINCFG_IE | APLIC_DOMAINCFG_DM, &aplic.regs->domaincfg); +} + +static int __init cf_check aplic_init(void) +{ + int rc; + dt_phandle imsic_phandle; + uint32_t irq_range[num_possible_cpus() * 2]; + const __be32 *prop; + uint64_t size, paddr; + struct dt_device_node *imsic_node; + const struct dt_device_node *node = aplic_info.node; + + /* Check for associated imsic node */ + rc = dt_property_read_u32(node, "msi-parent", &imsic_phandle); + if ( !rc ) + panic("%s: IDC mode not supported\n", node->full_name); + + imsic_node = dt_find_node_by_phandle(imsic_phandle); + if ( !imsic_node ) + panic("%s: unable to find IMSIC node\n", node->full_name); + + rc = dt_property_read_u32_array(imsic_node, "interrupts-extended", + irq_range, ARRAY_SIZE(irq_range)); + if ( rc ) + panic("%s: unable to find interrupt-extended in %s node\n", + __func__, imsic_node->full_name); + + if ( irq_range[1] == IRQ_M_EXT ) + /* Machine mode imsic node, ignore this aplic node */ + return 0; + + for ( unsigned int i = 0; i < ARRAY_SIZE(irq_range); i += 2 ) + { + if ( irq_range[i + 1] != irq_range[1] ) + panic("%s: mode[%d] != %d\n", __func__, i + 1, irq_range[1]); + } + + rc = imsic_init(imsic_node); + if ( rc ) + panic("%s: Failded to initialize IMSIC\n", node->full_name); + + /* Find out number of interrupt sources */ + rc = dt_property_read_u32(node, "riscv,num-sources", &aplic_info.num_irqs); + if ( !rc ) + panic("%s: failed to get number of interrupt sources\n", + node->full_name); + + prop = dt_get_property(node, "reg", NULL); + dt_get_range(&prop, node, &paddr, &size); + if ( !paddr ) + panic("%s: first MMIO resource not found\n", node->full_name); + + aplic.paddr_start = paddr; + aplic.size = size; + + aplic.regs = ioremap(paddr, size); + if ( !aplic.regs ) + panic("%s: unable to map\n", node->full_name); + + /* Setup initial state APLIC interrupts */ + aplic_init_hw_interrupts(); + + return 0; +} + +static struct intc_hw_operations __ro_after_init aplic_ops = { + .info = &aplic_info, + .init = aplic_init, +}; + static int cf_check aplic_irq_xlate(const uint32_t *intspec, unsigned int intsize, unsigned int *out_hwirq, @@ -53,8 +155,12 @@ static int __init aplic_preinit(struct dt_device_node *node, const void *dat) aplic_info.node = node; + aplic.imsic_cfg = imsic_get_config(); + dt_irq_xlate = aplic_irq_xlate; + register_intc_ops(&aplic_ops); + return 0; } diff --git a/xen/arch/riscv/include/asm/aplic.h b/xen/arch/riscv/include/asm/aplic.h new file mode 100644 index 0000000000..6221030a68 --- /dev/null +++ b/xen/arch/riscv/include/asm/aplic.h @@ -0,0 +1,64 @@ +/* SPDX-License-Identifier: MIT */ + +/* + * xen/arch/riscv/asm/include/aplic.h + * + * RISC-V Advanced Platform-Level Interrupt Controller support + * + * Copyright (c) Microchip. + */ + +#ifndef ASM__RISCV__APLIC_H +#define ASM__RISCV__APLIC_H + +#include <xen/types.h> + +#include <asm/imsic.h> + +#define APLIC_DOMAINCFG_IE BIT(8, UL) +#define APLIC_DOMAINCFG_DM BIT(2, UL) + +struct aplic_regs { + uint32_t domaincfg; + uint32_t sourcecfg[1023]; + uint8_t _reserved1[0xBC0]; + + uint32_t mmsiaddrcfg; + uint32_t mmsiaddrcfgh; + uint32_t smsiaddrcfg; + uint32_t smsiaddrcfgh; + uint8_t _reserved2[0x30]; + + uint32_t setip[32]; + uint8_t _reserved3[92]; + + uint32_t setipnum; + uint8_t _reserved4[0x20]; + + uint32_t in_clrip[32]; + uint8_t _reserved5[92]; + + uint32_t clripnum; + uint8_t _reserved6[32]; + + uint32_t setie[32]; + uint8_t _reserved7[92]; + + uint32_t setienum; + uint8_t _reserved8[32]; + + uint32_t clrie[32]; + uint8_t _reserved9[92]; + + uint32_t clrienum; + uint8_t _reserved10[32]; + + uint32_t setipnum_le; + uint32_t setipnum_be; + uint8_t _reserved11[4088]; + + uint32_t genmsi; + uint32_t target[1023]; +}; + +#endif /* ASM__RISCV__APLIC_H */ diff --git a/xen/arch/riscv/include/asm/intc.h b/xen/arch/riscv/include/asm/intc.h index e72d5fd9d3..2d55d74a2e 100644 --- a/xen/arch/riscv/include/asm/intc.h +++ b/xen/arch/riscv/include/asm/intc.h @@ -17,6 +17,9 @@ enum intc_version { struct intc_info { enum intc_version hw_version; const struct dt_device_node *node; + + /* number of irqs */ + unsigned int num_irqs; }; struct irq_desc; -- 2.49.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |