[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Minios-devel] [UNIKRAFT PATCH 4/7] plat/common: Implement gic-v2 library for Arm
Hi sharan, > -----Original Message----- > From: Sharan Santhanam <sharan.santhanam@xxxxxxxxx> > Sent: Friday, March 22, 2019 11:35 PM > To: Jianyong Wu (Arm Technology China) <Jianyong.Wu@xxxxxxx>; Wei > Chen (Arm Technology China) <Wei.Chen@xxxxxxx>; minios- > devel@xxxxxxxxxxxxxxxxxxxx; simon.kuenzer@xxxxxxxxx; > florian.schmidt@xxxxxxxxx; yuri.volchkov@xxxxxxxxx; > Felipe.Huici@xxxxxxxxx > Cc: Kaly Xin (Arm Technology China) <Kaly.Xin@xxxxxxx>; Justin He (Arm > Technology China) <Justin.He@xxxxxxx>; nd <nd@xxxxxxx> > Subject: Re: [Minios-devel] [UNIKRAFT PATCH 4/7] plat/common: Implement > gic-v2 library for Arm > > Hello Jianyong Wu, > > Please find the comment inline. > > Thanks & Regards > Sharan > > > On 3/22/19 6:06 AM, Jianyong Wu (Arm Technology China) wrote: > > Hi sharan, > > > >> -----Original Message----- > >> From: Sharan Santhanam <sharan.santhanam@xxxxxxxxx> > >> Sent: Friday, March 22, 2019 1:14 AM > >> To: Wei Chen (Arm Technology China) <Wei.Chen@xxxxxxx>; minios- > >> devel@xxxxxxxxxxxxxxxxxxxx; simon.kuenzer@xxxxxxxxx; > >> florian.schmidt@xxxxxxxxx; yuri.volchkov@xxxxxxxxx; > >> Felipe.Huici@xxxxxxxxx > >> Cc: Kaly Xin (Arm Technology China) <Kaly.Xin@xxxxxxx>; Justin He > >> (Arm Technology China) <Justin.He@xxxxxxx>; Jianyong Wu (Arm > >> Technology > >> China) <Jianyong.Wu@xxxxxxx>; nd <nd@xxxxxxx> > >> Subject: Re: [Minios-devel] [UNIKRAFT PATCH 4/7] plat/common: > >> Implement > >> gic-v2 library for Arm > >> > >> Hello, > >> > >> There is a dependency on this patch with the below libfdt patches. > >> > >> https://patchwork.unikraft.org/patch/725130/ > >> https://patchwork.unikraft.org/patch/725131/ > >> > >> There are also checkpatch failure in this patch. > > I will check and fix it > >> > >> I was also wondering if this entire gic belongs under the > >> plat/drivers/gic/. > > Yh, maybe better > >> > >> Please find rest of the comments inline. > >> > >> Thanks & Regards > >> Sharan > >> > >> On 12/13/18 10:18 AM, Wei Chen wrote: > >>> This library has implemented basic GICv2 functions. We don't support > >>> GICv2M and security extension in this library. > >>> > >>> Signed-off-by: Wei Chen <wei.chen@xxxxxxx> > >>> Signed-off-by: Jianyong Wu <jianyong.wu@xxxxxxx> > >>> --- > >>> plat/common/arm/gic-v2.c | 415 > >> +++++++++++++++++++++++++++++++ > >>> plat/common/include/arm/gic-v2.h | 368 > >> +++++++++++++++++++++++++++ > >>> plat/common/include/irq.h | 15 ++ > >>> plat/kvm/Makefile.uk | 1 + > >>> 4 files changed, 799 insertions(+) > >>> create mode 100644 plat/common/arm/gic-v2.c > >>> create mode 100644 plat/common/include/arm/gic-v2.h > >>> > >>> diff --git a/plat/common/arm/gic-v2.c b/plat/common/arm/gic-v2.c new > >>> file mode 100644 index 0000000..26f4a7f > >>> --- /dev/null > >>> +++ b/plat/common/arm/gic-v2.c > >>> @@ -0,0 +1,415 @@ > >>> +/* SPDX-License-Identifier: BSD-3-Clause */ > >>> +/* > >>> + * Authors: Wei Chen <Wei.Chen@xxxxxxx> > >>> + * Jianyong Wu <Jianyong.Wu@xxxxxxx> > >>> + * > >>> + * Copyright (c) 2018, Arm Ltd. All rights reserved. > >>> + * > >>> + * Redistribution and use in source and binary forms, with or > >>> +without > >>> + * modification, are permitted provided that the following > >>> +conditions > >>> + * are met: > >>> + * > >>> + * 1. Redistributions of source code must retain the above copyright > >>> + * notice, this list of conditions and the following disclaimer. > >>> + * 2. Redistributions in binary form must reproduce the above copyright > >>> + * notice, this list of conditions and the following disclaimer in the > >>> + * documentation and/or other materials provided with the > distribution. > >>> + * 3. Neither the name of the copyright holder nor the names of its > >>> + * contributors may be used to endorse or promote products derived > >> from > >>> + * this software without specific prior written permission. > >>> + * > >>> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND > >> CONTRIBUTORS "AS IS" > >>> + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT > >> LIMITED > >>> +TO, THE > >>> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A > >> PARTICULAR > >>> +PURPOSE > >>> + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR > >>> +CONTRIBUTORS BE > >>> + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, > EXEMPLARY, > >>> +OR > >>> + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, > >> PROCUREMENT > >>> +OF > >>> + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; > OR > >>> +BUSINESS > >>> + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF > LIABILITY, > >>> +WHETHER IN > >>> + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR > >>> +OTHERWISE) > >>> + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF > >>> +ADVISED OF THE > >>> + * POSSIBILITY OF SUCH DAMAGE. > >>> + * > >>> + * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY. > >>> + */ > >>> +#include <string.h> > >>> +#include <libfdt.h> > >>> +#include <uk/essentials.h> > >>> +#include <uk/print.h> > >>> +#include <uk/assert.h> > >>> +#include <uk/bitops.h> > >>> +#include <uk/asm.h> > >>> +#include <irq.h> > >>> +#include <arm/cpu.h> > >>> +#include <arm/gic-v2.h> > >>> + > >>> +/* Max CPU interface for GICv2 */ > >>> +#define GIC_MAX_CPUIF 8 > >>> + > >>> +/* SPI interrupt base ID */ > >>> +#define GIC_SPI_BASE 32 > >>> + > >>> +/* PPI interrupt base ID */ > >>> +#define GIC_PPI_BASE 16 > >>> + > >>> +/* Max support interrupt number for GICv2 */ > >>> +#define GIC_MAX_IRQ __MAX_IRQ > >>> + > >>> +static uint64_t gic_dist_addr, gic_cpuif_addr; static uint64_t > >>> +gic_dist_size, gic_cpuif_size; > >>> + > >>> +#define GIC_DIST_REG(r) ((void *)(gic_dist_addr + (r))) > >>> +#define GIC_CPU_REG(r) ((void *)(gic_cpuif_addr + (r))) > >>> + > >>> +static const char *gic_device_list[] = { > >>> + "arm,cortex-a15-gic", > >>> + "arm,cortex-a7-gic", > >>> + "arm,cortex-a9-gic", > >>> + "arm,gic-400", > >>> + "arm,eb11mp-gic", > >>> + "arm,pl390", > >>> + "arm,arm1176jzf-devchip-gic", > >>> + "arm,arm11mp-gic", > >>> + "arm,tc11mp-gic", > >>> + "brcm,brahma-b15-gic", > >>> + "nvidia,tegra210-agic", > >>> + "qcom,msm-8660-qgic", > >>> + "qcom,msm-qgic2", > >>> +}; > >>> + > >>> +/* inline functions to access GICC & GICD registers */ static > >>> +inline void write_gicd8(uint64_t offset, uint8_t val) { > >>> + ioreg_write8(GIC_DIST_REG(offset), val); } > >>> + > >>> +static inline void write_gicd32(uint64_t offset, uint32_t val) { > >>> + ioreg_write32(GIC_DIST_REG(offset), val); } > >>> + > >>> +static inline uint32_t read_gicd32(uint64_t offset) { > >>> + return ioreg_read32(GIC_DIST_REG(offset)); > >>> +} > >>> + > >>> +static inline void write_gicc32(uint64_t offset, uint32_t val) { > >>> + ioreg_write32(GIC_CPU_REG(offset), val); } > >>> + > >>> +static inline uint32_t read_gicc32(uint64_t offset) { > >>> + return ioreg_read32(GIC_CPU_REG(offset)); > >>> +} > >>> + > >>> +/* > >>> + * Functions of GIC CPU interface > >>> + */ > >>> + > >>> +/* Enable GIC cpu interface */ > >>> +static void gic_enable_cpuif(void) > >>> +{ > >> > >> Does the below comment belong here? > >>> + /* just set bit 0 to 1 to enable cpu interface */ > >>> + write_gicc32(GICC_CTLR, GICC_CTLR_ENABLE); } > > Yeah, GICC_CTLR_ENABLE equals 1, write bit 0 of GICC_CTLR to 1 to enable > gic cpu interface. > >>> + > >>> +/* Set priority threshold for processor */ static void > >>> +gic_set_threshold_priority(uint32_t threshold_prio) { > >>> + /* GICC_PMR allocate 1 byte for each irq */ > >>> + UK_ASSERT(threshold_prio <= GICC_PMR_PRIO_MAX); > >>> + write_gicc32(GICC_PMR, threshold_prio); } > >>> + > >>> +/* > >>> + * Acknowledging irq equals reading GICC_IAR also > >>> + * get the interrupt ID as the side effect. > >>> + */ > >>> +uint32_t gic_ack_irq(void) > >>> +{ > >>> + return read_gicc32(GICC_IAR); > >>> +} > >>> + > >>> +/* > >>> + * write to GICC_EOIR to inform cpu interface completation > >>> + * of interrupt processing. If GICC_CTLR.EOImode sets to 1 > >>> + * this func just gets priority drop. > >>> + */ > >>> +void gic_eoi_irq(uint32_t irq) > >>> +{ > >>> + write_gicc32(GICC_EOIR, irq); > >>> +} > >>> + > >>> +/* Functions of GIC Distributor */ > >>> + > >>> +/* > >>> + * @sgintid denotes the sgi ID; > >>> + * @targetfilter : this term is TargetListFilter > >>> + * 0 denotes forwarding interrupt to cpu specified in the > >>> + * target list; 1 denotes forwarding interrupt to cpu execpt the > >>> + * processor that request the intrrupt; 2 denotes forwarding the > >>> + * interrupt only to the cpu that requtest the interrupt. > >>> + * @targetlist is bitmask, which bit 1 denotes forwarding to and > >>> +only low 8 > >>> + * bit is in use. > >>> + */ > >>> +static void gic_sgi_gen(uint32_t sgintid, uint8_t targetfilter, > >>> + uint8_t targetlist) > >>> +{ > >>> + uint32_t val; > >>> + > >>> + /* Only INTID 0-15 allocated to sgi */ > >>> + UK_ASSERT(sgintid <= GICD_SGI_MAX_INITID); > >>> + > >>> + /* Set SGI tagetfileter field */ > >>> + val = (targetfilter & GICD_SGI_FILTER_MASK) << > >>> +GICD_SGI_FILTER_SHIFT; > >>> + > >>> + /* Set SGI targetlist field */ > >>> + val |= (targetlist & GICD_SGI_TARGET_MASK) << > >> GICD_SGI_TARGET_SHIFT; > >>> + > >>> + /* Set SGI INITID field */ > >>> + val |= sgintid; > >>> + > >>> + /* Generate SGI */ > >>> + write_gicd32(GICD_SGIR, val); > >>> +} > >>> + > >>> +/* > >>> + * Forward the SIG to the CPU interfaces specified in the > >>> + * targetlist. Targetlist is a 8-bit bitmap for 0~7 CPU. > >>> + * TODO: this will not work untill SMP is supported */ void > >>> +gic_sgi_gen_to_list(uint32_t sgintid, uint8_t targetlist) { > >>> + gic_sgi_gen(sgintid, GICD_SGI_FILTER_TO_LIST, targetlist); } > >>> + > >>> +/* > >>> + * Forward the SGI to all CPU interfaces except that of the > >>> + * processor that requested the interrupt. > >>> + * TODO: this will not work untill SMP is supported */ void > >>> +gic_sgi_gen_to_others(uint32_t sgintid) { > >>> + gic_sgi_gen(sgintid, GICD_SGI_FILTER_TO_OTHERS, 0); } > >>> + > >>> +/* > >>> + * Forward the SGI only to the CPU interface of the processor > >>> + * that requested the interrupt. > >>> + */ > >>> +void gic_sgi_gen_to_self(uint32_t sgintid) { > >>> + gic_sgi_gen(sgintid, GICD_SGI_FILTER_TO_SELF, 0); } > >>> + > >>> +/* > >>> + * set target cpu for irq in distributor, > >>> + * @target: bitmask value, bit 1 indicates target to > >>> + * corresponding cpu interface > >>> + */ > >>> +void gic_set_irq_target(uint32_t irq, uint8_t target) { > >> > >> > >> SGI and PPI interrupt cannot be written to. Should we check irq > > >> GIC_SPI_BASE > >>> + write_gicd8(GICD_ITARGETSR(irq), target); > > Ok, check is better, I will fix it. > > > >>> +} > >>> + > >>> +/* set priority for irq in distributor */ void > >>> +gic_set_irq_prio(uint32_t irq, uint8_t priority) { > >>> + write_gicd8(GICD_IPRIORITYR(irq), priority); } > >>> + > >>> +/* > >>> + * Enable an irq in distributor, each irq occupies one bit > >>> + * to configure in corresponding registor */ void > >>> +gic_enable_irq(uint32_t irq) { > >>> + write_gicd32(GICD_ISENABLER(irq), > >>> + UK_BIT(irq % GICD_I_PER_ISENABLERn)); } > >>> + > >>> +/* > >>> + * Disable an irq in distributor, one bit reserved for an irq > >>> + * to configure in corresponding register */ void > >>> +gic_disable_irq(uint32_t irq) { > >>> + write_gicd32(GICD_ICENABLER(irq), > >>> + UK_BIT(irq % GICD_I_PER_ICENABLERn)); } > >>> + > >>> +/* Enable distributor */ > >>> +static void gic_enable_dist(void) > >>> +{ > >>> + > >> > >> > >> According to the documentation[1] page(4-85), bit 0 and 1 enables > >> group 0 and group 1. According to fig 3-11 group zero correspond to > >> FIQ and Group 1 contains IRQ. > >> Shouldn't we disable both these bits in this case or is this > >> configuration valid for secure group that we do not support yet? > >> /* just set bit 0 to 1 to enable distributor */ > > > > It is confused in gic spec. in our case it should refer to figure4-1 > > in [1] page(4-85) for it is The Non-secure copy of the register in our > implementation. > > So no fiq and group0 should be considered. > > I will remove all the group related part in gic-v2 implementation. > > > >>> + write_gicd32(GICD_CTLR, read_gicd32(GICD_CTLR) | > >> GICD_CTLR_ENABLE); > >>> +} > >>> + > >>> +/* disable distributor */ > >>> +static void gic_disable_dist(void) > >>> +{ > >> > >> s/enable/disable > >>> + /* just clear bit 0 to 0 to enable distributor */ > >>> + write_gicd32(GICD_CTLR, read_gicd32(GICD_CTLR) & > >> (~GICD_CTLR_ENABLE)); > >>> +} > >>> + > > > Why do we want to separate the trigger and polarity? > From the [2], isn't it the case for the interrupt can either be low-to-high > edge > triggered or active high level-sensitive for SPI. > For PPI there are the 4 possible value. > > [2] > https://elixir.bootlin.com/linux/v4.3/source/Documentation/devicetree/bin > dings/arm/gic.txt > Yeah, set polarity maybe meaningless, I will remove polarity. > >>> +/* Config intrrupt trigger type and polarity */ void > >>> +gic_set_irq_type(uint32_t irq, int trigger, int polarity) { > >>> + uint32_t val, mask, oldmask; > >>> + > >>> + if ((trigger >= UK_IRQ_TRIGGER_MAX) || > >>> + (polarity >= UK_IRQ_POLARITY_MAX)) > >>> + return; > >>> + > >>> + val = read_gicd32(GICD_ICFGR(irq)); > >>> + mask = oldmask = (val >> ((irq % GICD_I_PER_ICFGRn) * 2)) & > >>> + GICD_ICFGR_MASK; > >>> + > >>> + if (trigger == UK_IRQ_TRIGGER_LEVEL) { > >>> + mask &= ~GICD_ICFGR_TRIG_MASK; > >>> + mask |= GICD_ICFGR_TRIG_LVL; > >>> + } else if (trigger == UK_IRQ_TRIGGER_EDGE) { > >>> + mask &= ~GICD_ICFGR_TRIG_MASK; > >>> + mask |= GICD_ICFGR_TRIG_EDGE; > >>> + } > >>> + > >>> + if (polarity == UK_IRQ_POLARITY_LOW) { > >>> + mask &= ~GICD_ICFGR_POL_MASK; > >>> + mask |= GICD_ICFGR_POL_LOW; > >>> + } else if (polarity == UK_IRQ_POLARITY_HIGH) { > >>> + mask &= ~GICD_ICFGR_POL_MASK; > >>> + mask |= GICD_ICFGR_POL_HIGH; > >>> + } > >>> + > >>> + /* Check if nothing changed */ > >>> + if (mask == oldmask) > >>> + return; > >>> + > >>> + /* Update new interrupt type */ > >>> + val &= (~(GICD_ICFGR_MASK << (irq % GICD_I_PER_ICFGRn) * 2)); > >>> + val |= (mask << (irq % GICD_I_PER_ICFGRn) * 2); > >>> + write_gicd32(GICD_ICFGR(irq), val); } > >>> + > >>> +static void gic_init_dist(void) > >>> +{ > >>> + uint32_t val, cpuif_number, irq_number; > >>> + uint32_t i; > >>> + > >>> + /* Turn down distributor */ > >>> + gic_disable_dist(); > >>> + > >>> + /* Get GIC CPU interface */ > >>> + val = read_gicd32(GICD_TYPER); > >>> + cpuif_number = GICD_TYPER_CPUI_NUM(val); > >>> + if (cpuif_number > GIC_MAX_CPUIF) > >>> + cpuif_number = GIC_MAX_CPUIF; > >>> + uk_pr_info("GICv2 Max CPU interface:%d\n", cpuif_number); > >>> + > >>> + /* Get the maximum number of interrupts that the GIC supports */ > >>> + irq_number = GICD_TYPER_LINE_NUM(val); > >>> + if (irq_number > GIC_MAX_IRQ) > >>> + irq_number = GIC_MAX_IRQ; > >>> + uk_pr_info("GICv2 Max interrupt lines:%d\n", irq_number); > >>> + /* > >>> + * Set all SPI interrupts targets to all CPU. > >>> + */ > >>> + for (i = GIC_SPI_BASE; i < irq_number; i += GICD_I_PER_ITARGETSRn) > >>> + write_gicd32(GICD_ITARGETSR(i), GICD_ITARGETSR_DEF); > >>> + > >>> + /* > >>> + * Set all SPI interrupts type to be polarity low level triggered > >>> + */ > >>> + for (i = GIC_SPI_BASE; i < irq_number; i += GICD_I_PER_ICFGRn) > >>> + write_gicd32(GICD_ICFGR(i), GICD_ICFGR_DEF_TYPE); > >>> + > >>> + /* > >>> + * Set all SPI priority to a default value. > >>> + */ > >>> + for (i = GIC_SPI_BASE; i < irq_number; i += GICD_I_PER_IPRIORITYn) > >>> + write_gicd32(GICD_IPRIORITYR(i), GICD_IPRIORITY_DEF); > >>> + > >>> + /* > >>> + * Deactivate and disable all SPIs. > >>> + */ > >>> + for (i = GIC_SPI_BASE; i < irq_number; i += GICD_I_PER_ICACTIVERn) > >> { > >>> + write_gicd32(GICD_ICACTIVER(i), GICD_DEF_ICACTIVERn); > >>> + write_gicd32(GICD_ICENABLER(i), GICD_DEF_ICENABLERn); > >>> + } > >>> + > >>> + /* turn on distributor */ > >>> + gic_enable_dist(); > >>> +} > >>> + > >>> +static void gic_init_cpuif(void) > >>> +{ > >>> + uint32_t i; > >>> + /* set priority mask to the lowest priority to let all irq visible > >>> +to cpu > >> interface */ > >>> + gic_set_threshold_priority(GICC_PMR_PRIO_MAX); > >>> + > >>> + /* set PPI and SGI to polarity low level triggered */ > >>> + for (i = 0; i < GIC_SPI_BASE; i += GICD_I_PER_ICFGRn) > >>> + write_gicd32(GICD_ICFGR(i), GICD_ICFGR_DEF_TYPE); > >>> + > >>> + /* set PPI and SGI to a default value */ > >>> + for (i = 0; i < GIC_SPI_BASE; i += GICD_I_PER_IPRIORITYn) > >>> + write_gicd32(GICD_IPRIORITYR(i), GICD_IPRIORITY_DEF); > >>> + > >> > >> Shouldn't it be (i <= GICD_SGI_MAX_INITID) > > If GICD_SGI_MAX_INITID is 15, it should be <=, if > GICD_SGI_MAX_INITID=16 it should be keep. > > I will check and fix it if necessary. maybe GIC_SPI_BASE better > >>> + /* > >>> + * Deactivate and disable all PPIs. > >>> + */ > >>> + for (i = 0; i < GICD_SGI_MAX_INITID; i += GICD_I_PER_ICACTIVERn) > { > >>> + write_gicd32(GICD_ICACTIVER(i), GICD_DEF_ICACTIVERn); > >>> + write_gicd32(GICD_ICENABLER(i), > >> GICD_DEF_PPI_ICENABLERn); > >>> + } > >>> + > >>> + /* Deactivate and enable all SGIs */ > >>> + for (i = 0; i < GIC_PPI_BASE; i += GICD_I_PER_ICACTIVERn) > >>> + { > >>> + write_gicd32(GICD_ICACTIVER(i), GICD_DEF_ICACTIVERn); > >>> + write_gicd32(GICD_ISENABLER(i), > >> GICD_DEF_SGI_ISENABLERn); > >>> + } > >>> + > >>> + /* enable cpu interface */ > >>> + gic_enable_cpuif(); > >>> +} > >>> + > >>> +int _dtb_init_gic(const void *fdt) > >>> +{ > >>> + int fdt_gic, ret; > >>> + > >>> + uk_pr_info("Probing GICv2...\n"); > >>> + > >> > >> Shouldn't the last parameter be count of the number of element in the > >> array instead? > >> sizeof(gic_device_list) / sizeof(gic_device_list[0]) > > > > Yeah, I will fix it. > >>> + /* Currently, we only support 1 GIC per system */ > >>> + fdt_gic = fdt_node_offset_by_compatible_list(fdt, -1, > >>> + gic_device_list, sizeof(gic_device_list)); > >>> + if (fdt_gic < 0) > >>> + UK_CRASH("Could not find GICv2 Interrupt Controller!\n"); > >>> + > >>> + /* Get device address and size at regs region */ > >>> + ret = fdt_get_address(fdt, fdt_gic, 0, > >>> + &gic_dist_addr, &gic_dist_size); > >>> + if (ret < 0) > >>> + UK_CRASH("Could not find GICv2 distributor region!\n"); > >>> + > >>> + ret = fdt_get_address(fdt, fdt_gic, 1, > >>> + &gic_cpuif_addr, &gic_cpuif_size); > >>> + if (ret < 0) > >>> + UK_CRASH("Could not find GICv2 cpuif region!\n"); > >>> + > >>> + uk_pr_info("Found GICv2 on:\n"); > >>> + uk_pr_info("\tDistributor : 0x%lx - 0x%lx\n", > >>> + gic_dist_addr, gic_dist_addr + gic_dist_size - 1); > >>> + uk_pr_info("\tCPU interface: 0x%lx - 0x%lx\n", > >>> + gic_cpuif_addr, gic_cpuif_addr + gic_cpuif_size - 1); > >>> + > >>> + > >>> + /* Initialize GICv2 distributor */ > >>> + gic_init_dist(); > >>> + > >>> + /* Initialize GICv2 CPU interface */ > >>> + gic_init_cpuif(); > >>> + > >>> + return 0; > >>> +} > >>> diff --git a/plat/common/include/arm/gic-v2.h > >> b/plat/common/include/arm/gic-v2.h > >>> new file mode 100644 > >>> index 0000000..7412a4f > >>> --- /dev/null > >>> +++ b/plat/common/include/arm/gic-v2.h > >>> @@ -0,0 +1,368 @@ > >>> +/* SPDX-License-Identifier: BSD-3-Clause */ > >>> +/* > >>> + * Authors: Wei Chen <Wei.Chen@xxxxxxx> > >>> + * Jianyong Wu <Jianyong.Wu@xxxxxxx> > >>> + * > >>> + * Copyright (c) 2018, Arm Ltd. All rights reserved. > >>> + * > >>> + * Redistribution and use in source and binary forms, with or > >>> +without > >>> + * modification, are permitted provided that the following > >>> +conditions > >>> + * are met: > >>> + * > >>> + * 1. Redistributions of source code must retain the above copyright > >>> + * notice, this list of conditions and the following disclaimer. > >>> + * 2. Redistributions in binary form must reproduce the above copyright > >>> + * notice, this list of conditions and the following disclaimer in the > >>> + * documentation and/or other materials provided with the > distribution. > >>> + * 3. Neither the name of the copyright holder nor the names of its > >>> + * contributors may be used to endorse or promote products derived > >> from > >>> + * this software without specific prior written permission. > >>> + * > >>> + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND > >> CONTRIBUTORS "AS IS" > >>> + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT > >> LIMITED TO, THE > >>> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A > >> PARTICULAR PURPOSE > >>> + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR > >> CONTRIBUTORS BE > >>> + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, > EXEMPLARY, > >> OR > >>> + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, > >> PROCUREMENT OF > >>> + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; > OR > >> BUSINESS > >>> + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF > LIABILITY, > >> WHETHER IN > >>> + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR > >> OTHERWISE) > >>> + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF > >> ADVISED OF THE > >>> + * POSSIBILITY OF SUCH DAMAGE. > >>> + * > >>> + * THIS HEADER MAY NOT BE EXTRACTED OR MODIFIED IN ANY WAY. > >>> + */ > >>> +#ifndef __PLAT_CMN_ARM_GIC_H__ > >>> +#define __PLAT_CMN_ARM_GIC_H__ > >>> + > >>> +/* > >>> + * Distributor registers. Unikraft only support run on non-secure > >>> + * so we just describe non-secure registers. > >>> + */ > >>> + > >>> +/* > >>> + * Distributor Control Register, GICD_CTLR. > >>> + * Enables the forwarding of pending interrupts from the > >>> + * Distributor to the CPU interfaces */ > >>> +#define GICD_CTLR 0x0000 > >>> +#define GICD_CTLR_ENABLE 0x1 > >>> + > >>> +/* > >>> + * Interrupt Controller Type Register, GICD_TYPER. > >>> + * Provides information about the configuration of the GIC. > >>> + */ > >>> +#define GICD_TYPER 0x0004 > >>> +#define GICD_TYPER_LINE_NUM(r) ((((r) & 0x1f) + 1) << 5) > >>> +#define GICD_TYPER_CPUI_NUM(r) ((((r) >> 5) & 0x3) + 1) > >>> + > >>> +/* > >>> + * Distributor Implementer Identification Register, GICD_IIDR. > >>> + * Provides information about the implementer and revision of the > >> Distributor. > >>> + */ > >>> +#define GICD_IIDR 0x0008 > >>> +#define GICD_IIDR_PROD(r) (((r) >> 24) & 0xff) > >>> +#define GICD_IIDR_VAR(r) (((r) >> 16) & 0xf) > >>> +#define GICD_IIDR_REV(r) (((r) >> 12) & 0xf) > >>> +#define GICD_IIDR_IMPL(r) ((r) & 0xfff) > >>> + > >>> +/* > >>> + * Interrupt Group Registers, GICD_IGROUPRn > >>> + * These registers provide a status bit for each interrupt > >>> +supported by > >>> + * the GIC. Each bit controls whether the corresponding interrupt > >>> +is in > >>> + * Group 0 or Group 1 > >>> + */ > >>> +#define GICD_IGROUPR(n) (0x0080 + 4 * ((n) >> 5)) > >>> +#define GICD_I_PER_IGROUPRn 32 > >>> + > >>> +/* > >>> + * Interrupt Set-Enable Registers, GICD_ISENABLERn. > >>> + * These registers provide a Set-enable bit for each interrupt > >>> +supported > >>> + * by the GIC. Writing 1 to a Set-enable bit enables forwarding of > >>> +the > >>> + * corresponding interrupt from the Distributor to the CPU interfaces. > >>> + * Reading a bit identifies whether the interrupt is enabled. > >>> + */ > >>> +#define GICD_ISENABLER(n) (0x0100 + 4 * ((n) >> 5)) > >>> +#define GICD_I_PER_ISENABLERn 32 > >>> +#define GICD_DEF_SGI_ISENABLERn 0xffff > >>> + > >>> +/* > >>> + * Interrupt Clear-Enable Registers, GICD_ICENABLERn. > >>> + * Provide a Clear-enable bit for each interrupt supported by the GIC. > >>> + * Writing 1 to a Clear-enable bit disables forwarding of the > >>> + * corresponding interrupt from the Distributor to the CPU interfaces. > >>> + * Reading a bit identifies whether the interrupt is enabled. > >>> + */ > >>> +#define GICD_ICENABLER(n) (0x0180 + 4 * ((n) >> 5)) > >>> +#define GICD_I_PER_ICENABLERn 32 > >>> +#define GICD_DEF_ICENABLERn 0xffffffff > >>> +#define GICD_DEF_PPI_ICENABLERn 0xffff0000 > >>> + > >>> +/* > >>> + * Interrupt Set-Pending Registers, GICD_ISPENDRn. > >>> + * Provide a Set-pending bit for each interrupt supported by the GIC. > >>> + * Writing 1 to a Set-pending bit sets the status of the > >>> +corresponding > >>> + * peripheral interrupt to pending. Reading a bit identifies > >>> +whether > >>> + * the interrupt is pending. > >>> + */ > >>> +#define GICD_ISPENDR(n) (0x0200 + 4 * ((n) >> 5)) > >>> +#define GICD_I_PER_ISPENDRn 32 > >>> +/* > >>> + * Interrupt Clear-Pending Registers, GICD_ICPENDRn > >>> + * Provide a Clear-pending bit for each interrupt supported by the GIC. > >>> + * Writing 1 to a Clear-pending bit clears the pending state of the > >>> + * corresponding peripheral interrupt. Reading a bit identifies > >>> +whether > >>> + * the interrupt is pending. > >>> + */ > >>> +#define GICD_ICPENDR(n) (0x0280 + 4 * ((n) >> 5)) > >>> +#define GICD_I_PER_ICPENDRn 32 > >>> + > >>> +/* > >>> + * Interrupt Set-Active Registers, GICD_ISACTIVERn > >>> + * Provide a Set-active bit for each interrupt that the GIC supports. > >>> + * Writing to a Set-active bit Activates the corresponding interrupt. > >>> + * These registers are used when preserving and restoring GIC state. > >>> + */ > >>> +#define GICD_ISACTIVER(n) (0x0300 + 4 * ((n) >> 5)) > >>> +#define GICD_I_PER_ISACTIVERn 32 > >>> +/* > >>> + * Interrupt Clear-Active Registers, GICD_ICACTIVERn > >>> + * Provide a Clear-active bit for each interrupt that the GIC supports. > >>> + * Writing to a Clear-active bit Deactivates the corresponding interrupt. > >>> + * These registers are used when preserving and restoring GIC state. > >>> + */ > >>> +#define GICD_ICACTIVER(n) (0x0380 + 4 * ((n) >> 5)) > >>> +#define GICD_I_PER_ICACTIVERn 32 > >>> +#define GICD_DEF_ICACTIVERn 0xffffffff > >>> + > >>> +/* > >>> + * Interrupt ID mask for GICD_ISENABLER, GICD_ICENABLER, > >> GICD_ISPENDR, > >>> + * GICD_ICPENDR, GICD_ISACTIVER and GICD_ICACTIVER */ > >>> +#define GICD_I_MASK(n) (1ul << ((n) & 0x1f)) > >>> + > >>> +/* > >>> + * Interrupt Priority Registers, GICD_IPRIORITYRn > >>> + * Provide an 8-bit priority field for each interrupt supported by > >>> +the > >>> + * GIC. > >>> + * > >>> + * These registers are byte-accessible, so we define this macro > >>> + * for byte-access. > >>> + */ > >>> +#define GICD_IPRIORITYR(n) (0x0400 + (n)) > >>> +#define GICD_I_PER_IPRIORITYn 4 > >> > >> How did we select '0xa0a0a0a0'? From the documentation[1] page 3-54, > >> 1) the value is right-shifted by one bit > >> 2) bit [7] of the value is set to 1. > >> Maybe comment would be useful. > > > > I will remove this. I check it again, maybe we have no need to refer to [1] page 3-54 for that is security extension part. Selecting 0xa0a0a0ao is discretionary. Just in the center of 0~255. Maybe 0x80808080 is better. Bests Jianyong Wu > > > >>> +#define 0xa0a0a0a0 > >>> + > >>> +/* > >>> + * Interrupt Processor Targets Registers, GICD_ITARGETSRn > >>> + * Provide an 8-bit CPU targets field for each interrupt supported > >>> +by > >>> + * the GIC. > >>> + * > >>> + * These registers are byte-accessible, so we define this macro > >>> + * for byte-access. > >>> + */ > >>> +#define GICD_ITARGETSR(n) (0x0800 + (n)) > >>> +#define GICD_I_PER_ITARGETSRn 4 > >>> +#define GICD_ITARGETSR_DEF 0xffffffff > >>> + > >>> +/* > >>> + * Interrupt Configuration Registers, GICD_ICFGRn > >>> + * The GICD_ICFGRs provide a 2-bit Int_config field for each > >>> +interrupt > >>> + * supported by the GIC. This field identifies whether the > >>> +corresponding > >>> + * interrupt is edge-triggered or level-sensitive. > >>> + */ > >>> +#define GICD_ICFGR(n) (0x0C00 + 4 * ((n) >> 4)) > >>> +#define GICD_I_PER_ICFGRn 16 > >>> +#define GICD_ICFGR_DEF_TYPE 0 > >>> +#define GICD_ICFGR_MASK 0x3 > >>> +/* First bit is a polarity bit (0 - low, 1 - high) */ > >>> +#define GICD_ICFGR_POL_LOW (0 << 0) > >>> +#define GICD_ICFGR_POL_HIGH (1 << 0) > >>> +#define GICD_ICFGR_POL_MASK 0x1 > >>> +/* Second bit is a trigger bit (0 - level, 1 - edge) */ > >>> +#define GICD_ICFGR_TRIG_LVL (0 << 1) > >>> +#define GICD_ICFGR_TRIG_EDGE (1 << 1) > >>> +#define GICD_ICFGR_TRIG_MASK 0x2 > >>> + > >>> +/* > >>> + * Software Generated Interrupt Register, GICD_SGIR */ > >>> +#define GIC D_SGIR 0x0F00 > >>> +#define GICD_SGI_TARGET_SHIFT 16 > >>> +#define GICD_SGI_TARGET_MASK 0xff > >>> +#define GICD_SGI_FILTER_SHIFT 24 > >>> +#define GICD_SGI_FILTER_MASK 0x3 > >>> +#define GICD_SGI_MAX_INITID 15 > >>> +#define GICD_PPI_START > >>> + > >>> +/* > >>> + * Forward the interrupt to the CPU interfaces specified in the > >>> + * CPUTargetList field > >>> + */ > >>> +#define GICD_SGI_FILTER_TO_LIST 0x0 > >>> +/* > >>> + * Forward the interrupt to all CPU interfaces except that of the > >>> + * processor that requested the interrupt. > >>> + */ > >>> +#define GICD_SGI_FILTER_TO_OTHERS 0x1 > >>> +/* > >>> + * Forward the interrupt only to the CPU interface of the processor > >>> + * that requested the interrupt. > >>> + */ > >>> +#define GICD_SGI_FILTER_TO_SELF 0x2 > >>> + > >>> +/* > >>> + * SGI Clear-Pending Registers, GICD_CPENDSGIRn > >>> + * Provide a clear-pending bit for each supported SGI and source > >>> + * processor combination. When a processor writes a 1 to a > >>> +clear-pending > >>> + * bit, the pending state of the corresponding SGI for the > >>> +corresponding > >>> + * source processor is removed, and no longer targets the processor > >>> + * performing the write. Writing a 0 has no effect. Reading a bit > >>> +identifies > >>> + * whether the SGI is pending, from the corresponding source > >>> +processor, > >> on > >>> + * the reading processor. > >>> + */ > >>> +#define GICD_CPENDSGIRn (0x0F10 + 4 *((n) >> 2)) > >>> +#define GICD_I_PER_CPENDSGIRn 4 > >>> + > >>> +/* > >>> + * SGI Set-Pending Registers, GICD_SPENDSGIRn > >>> + * Provide a set-pending bit for each supported SGI and source > >>> +processor > >>> + * combination. When a processor writes a 1 to a set-pending bit, > >>> +the > >> pending > >>> + * state is applied to the corresponding SGI for the corresponding > >>> +source > >>> + * processor. Writing a 0 has no effect. Reading a bit identifies > >>> +whether > >>> + * the SGI is pending, from the corresponding source processor, on > >>> +the > >>> + * reading processor. > >>> + */ > >>> +#define GICD_SPENDSGIRn (0x0F20 + 4 *((n) >> 2)) > >>> +#define GICD_I_PER_SPENDSGIRn 4 > >>> + > >>> + > >>> +/* > >>> + * CPU interface registers. Unikraft only support run on non-secure > >>> + * so we just describe non-secure registers. > >>> + */ > >>> + > >>> +/* CPU Interface Control Register */ > >>> +#define GICC_CTLR 0x0000 > >>> +#define GICC_CTLR_ENABLE 0x1 > >>> + > >>> +/* Interrupt Priority Mask Register */ > >>> +#define GICC_PMR 0x0004 > >>> +#define GICC_PMR_PRIO_MAX 255 > >>> + > >>> +/* Binary Point Register */ > >>> +#define GICC_BPR 0x0008 > >>> + > >>> +/* Interrupt Acknowledge Register */ > >>> +#define GICC_IAR 0x000C > >>> +#define GICC_IAR_INTID_MASK 0x3FF > >>> +#define GICC_IAR_INTID_SPURIOUS 1023 > >>> + > >>> +/* End of Interrupt Register */ > >>> +#define GICC_EOIR 0x0010 > >>> + > >>> +/* Running Priority Register */ > >>> +#define GICC_RPR 0x0014 > >>> + > >>> +/* Highest Priority Pending Interrupt Register */ > >>> +#define GICC_HPPIR 0x0018 > >>> + > >>> +/* Aliased Binary Point Register */ > >>> +#define GICC_ABPR 0x001C > >>> + > >>> +/* CPU Interface Identification Register */ > >>> +#define GICC_IIDR 0x00FC > >>> + > >>> +/* Deactivate Interrupt Register */ > >>> +#define GICC_DIR 0x1000 > >>> + > >>> +/* > >>> + * Acknowledging irq equals reading GICC_IAR also > >>> + * get the intrrupt ID as the side effect. > >>> + */ > >>> +uint32_t gic_ack_irq(void); > >>> + > >>> +/* > >>> + * write to GICC_EOIR to inform cpu interface completation > >>> + * of interrupt processing. If GICC_CTLR.EOImode sets to 1 > >>> + * this func just gets priority drop. > >>> + */ > >>> +void gic_eoi_irq(uint32_t irq); > >>> + > >>> +/* > >>> + * Forward the SIG to the CPU interfaces specified in the > >>> + * targetlist. Targetlist is a 8-bit bitmap for 0~7 CPU. > >>> + */ > >>> +void gic_sgi_gen_to_list(uint32_t sgintid, uint8_t targetlist); > >>> + > >>> +/* > >>> + * Forward the SGI to all CPU interfaces except that of the > >>> + * processor that requested the interrupt. > >>> + */ > >>> +void gic_sgi_gen_to_others(uint32_t sgintid); > >>> + > >>> +/* > >>> + * Forward the SGI only to the CPU interface of the processor > >>> + * that requested the interrupt. > >>> + */ > >>> +void gic_sgi_gen_to_self(uint32_t sgintid); > >>> + > >>> +/* > >>> + * set target cpu for irq in distributor, > >>> + * @target: bitmask value, bit 1 indicates target to > >>> + * corresponding cpu interface > >>> + */ > >>> +void gic_set_irq_target(uint32_t irq, uint8_t target); > >>> + > >>> +/* set priority for irq in distributor */ void > >>> +gic_set_irq_prio(uint32_t irq, uint8_t priority); > >>> + > >>> +/* > >>> + * Enable an irq in distributor, each irq occupies one bit > >>> + * to configure in corresponding registor */ void > >>> +gic_enable_irq(uint32_t irq); > >>> + > >>> +/* > >>> + * Disable an irq in distributor, one bit reserved for an irq > >>> + * to configure in corresponding register */ void > >>> +gic_disable_irq(uint32_t irq); > >>> + > >>> +/* > >>> + * set pending state for an irq in distributor, one bit > >>> + * reserved for an irq to configure in corresponding register */ > >>> +void gic_set_irq_pending(uint32_t irq); > >>> + > >>> +/* > >>> + * clear pending state for an irq in distributor, one bit > >>> + * reserved for an irq to configure in corresponding register */ > >>> +void gic_clear_irq_pending(uint32_t irq); > >>> + > >>> +/* > >>> + * inspect that if an irq is in pending state, every bit > >>> + * holds the value for the corresponding irq */ int > >>> +gic_is_irq_pending(uint32_t irq); > >>> + > >>> +/* set active state for an irq in distributor */ void > >>> +gic_set_irq_active(uint32_t irq); > >>> + > >>> +/* clear active state for an irq in distributor */ void > >>> +gic_clear_irq_active(uint32_t irq); > >>> + > >>> +/* > >>> + * inspect that if an irq is in active state, > >>> + * every bit holds the value for an irq */ int > >>> +gic_is_irq_active(uint32_t irq); > >>> + > >>> +/* Config intrrupt trigger type and polarity */ void > >>> +gic_set_irq_type(uint32_t irq, int trigger, int polarity); > >>> + > >>> +/* Initialize GICv2 from device tree */ int _dtb_init_gic(const > >>> +void *fdt); > >>> + > >>> +#endif //__PLAT_CMN_ARM_GICV2_H__ > >>> diff --git a/plat/common/include/irq.h b/plat/common/include/irq.h > >>> index a09685d..fac5022 100644 > >>> --- a/plat/common/include/irq.h > >>> +++ b/plat/common/include/irq.h > >>> @@ -45,5 +45,20 @@ > >>> #error "Add irq.h for current architecture." > >>> #endif > >>> > >>> +/* define IRQ trigger types */ > >>> +enum uk_irq_trigger { > >>> + UK_IRQ_TRIGGER_NONE = 0, > >>> + UK_IRQ_TRIGGER_EDGE = 1, > >>> + UK_IRQ_TRIGGER_LEVEL = 2, > >>> + UK_IRQ_TRIGGER_MAX > >>> +}; > >>> + > >>> +/* define IRQ trigger polarities */ enum uk_irq_polarity { > >>> + UK_IRQ_POLARITY_NONE = 0, > >>> + UK_IRQ_POLARITY_HIGH = 1, > >>> + UK_IRQ_POLARITY_LOW = 2, > >>> + UK_IRQ_POLARITY_MAX > >>> +}; > >>> > >>> #endif /* __PLAT_CMN_IRQ_H__ */ > >>> diff --git a/plat/kvm/Makefile.uk b/plat/kvm/Makefile.uk index > >>> 540b60b..e86ad1a 100644 > >>> --- a/plat/kvm/Makefile.uk > >>> +++ b/plat/kvm/Makefile.uk > >>> @@ -59,6 +59,7 @@ LIBKVMPLAT_SRCS-$(CONFIG_ARCH_ARM_64) += > >> $(UK_PLAT_COMMON_BASE)/arm/cache64.S|co > >>> LIBKVMPLAT_SRCS-$(CONFIG_ARCH_ARM_64) += > >> $(UK_PLAT_COMMON_BASE)/arm/psci_arm64.S|common > >>> LIBKVMPLAT_SRCS-$(CONFIG_ARCH_ARM_64) += > >> $(UK_PLAT_COMMON_BASE)/arm/time.c|common > >>> LIBKVMPLAT_SRCS-$(CONFIG_ARCH_ARM_64) += > >> $(UK_PLAT_COMMON_BASE)/arm/traps.c|common > >> > >> Wise to have CONFIG_GIC_V2 and enable the compilation if we need it. > >>> +LIBKVMPLAT_SRCS-$(CONFIG_ARCH_ARM_64) += > >> $(UK_PLAT_COMMON_BASE)/arm/gic-v2.c|common > >>> LIBKVMPLAT_SRCS-$(CONFIG_ARCH_ARM_64) += > >> $(LIBKVMPLAT_BASE)/arm/entry64.S > >>> LIBKVMPLAT_SRCS-$(CONFIG_ARCH_ARM_64) += > >> $(LIBKVMPLAT_BASE)/arm/exceptions.S > >>> LIBKVMPLAT_SRCS-$(CONFIG_ARCH_ARM_64) += > >> $(LIBKVMPLAT_BASE)/arm/pagetable64.S > >>> > >> > >> > >> [1] > >> https://www.cl.cam.ac.uk/research/srg/han/ACS- > >> P35/zynq/arm_gic_architecture_specification.pdf _______________________________________________ Minios-devel mailing list Minios-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/minios-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |