[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Minios-devel] [UNIKRAFT RFC PATCH 1/2] Implement gic-v2 library for Arm



Hi,

Any comments on gicv2?
It's the key point and  emergency.

Bests
Jianyong wu
> -----Original Message-----
> From: Jianyong Wu <Jianyong.Wu@xxxxxxx>
> Sent: Friday, November 9, 2018 5:03 PM
> To: minios-devel@xxxxxxxxxxxxxxxxxxxx; simon.kuenzer@xxxxxxxxx
> Cc: Kaly Xin (Arm Technology China) <Kaly.Xin@xxxxxxx>; Wei Chen (Arm
> Technology China) <Wei.Chen@xxxxxxx>; Jianyong Wu (Arm Technology
> China) <Jianyong.Wu@xxxxxxx>; nd <nd@xxxxxxx>
> Subject: [Minios-devel] [UNIKRAFT RFC PATCH 1/2] Implement gic-v2 library
> for Arm
> 
> 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         | 394
> +++++++++++++++++++++++++++++++++++++++
>  plat/common/include/arm/gic-v2.h | 380
> +++++++++++++++++++++++++++++++++++++
>  plat/common/include/irq.h        |  15 ++
>  plat/kvm/Makefile.uk             |   1 +
>  plat/kvm/arm/setup.c             |  61 +++---
>  5 files changed, 824 insertions(+), 27 deletions(-)  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..d212cfa
> --- /dev/null
> +++ b/plat/common/arm/gic-v2.c
> @@ -0,0 +1,394 @@
> +/* 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>
> +
> +static void *gic_dist_addr, *gic_cpuif_addr; static uint64_t
> +gic_dist_size, gic_cpuif_size;
> +
> +#define GIC_DIST_REG(r)      (gic_dist_addr + (r))
> +#define GIC_CPU_REG(r)       (gic_cpuif_addr + (r))
> +
> +static 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)
> +{
> +     /* just set bit 0 to 1 to enable cpu interface */
> +     write_gicc32(GICC_CTLR, GICC_CTLR_ENABLE); }
> +
> +/* 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) {
> +     write_gicd8(GICD_ITARGETSR(irq), target); }
> +
> +/* 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)
> +{
> +     /* just set bit 0 to 1 to enable distributor */
> +     write_gicd32(GICD_CTLR, read_gicd32(GICD_CTLR) |
> GICD_CTLR_ENABLE); }
> +
> +/* disable distributor */
> +static void gic_disable_dist(void)
> +{
> +     /* just clear bit 0 to 0 to enable distributor */
> +     write_gicd32(GICD_CTLR, read_gicd32(GICD_CTLR) &
> (~GICD_CTLR_ENABLE));
> +}
> +
> +/* 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_printd(DLVL_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_printd(DLVL_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);
> +        /*
> +      * 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(void *dtb)
> +{
> +     uint32_t idx;
> +     int fdt_gic;
> +     uint32_t naddr, nsize;
> +     const uint64_t *regs;
> +
> +     uk_printd(DLVL_INFO, "Probing GICv2...\n");
> +     /* Currently, we only support 1 GIC per system */
> +     fdt_gic = uk_dtb_find_device(dtb, gic_device_list,
> +sizeof(gic_device_list));
> +
> +     /* Get region size at regs region in dtb */
> +     naddr = uk_dtb_read_region(dtb, fdt_gic, &nsize, &regs);
> +
> +     /* Get device address and size at regs region */
> +     gic_dist_addr = (void *)uk_dtb_read_term(regs, 0, naddr, nsize,
> &gic_dist_size);
> +     gic_cpuif_addr = (void *)uk_dtb_read_term(regs, 1, naddr, nsize,
> +&gic_cpuif_size);
> +
> +     uk_printd(DLVL_INFO, "Found GICv2 on:\n");
> +     uk_printd(DLVL_INFO, "\tCPU interface address: %p\n",
> gic_cpuif_addr);
> +     uk_printd(DLVL_INFO, "\tDistributor address: %p\n", gic_dist_addr);
> +
> +
> +     /* 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..dfee6a8
> --- /dev/null
> +++ b/plat/common/include/arm/gic-v2.h
> @@ -0,0 +1,380 @@
> +/* 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
> +#define      GICD_IPRIORITY_DEF      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 GICD_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(void *dtb);
> +
> +/* 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          1020
> +
> +#endif //__PLAT_CMN_ARM_GICV2_H__
> diff --git a/plat/common/include/irq.h b/plat/common/include/irq.h index
> edaccfe..c36d004 100644
> --- a/plat/common/include/irq.h
> +++ b/plat/common/include/irq.h
> @@ -43,5 +43,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
> 197175a..572f4c3 100644
> --- a/plat/kvm/Makefile.uk
> +++ b/plat/kvm/Makefile.uk
> @@ -61,6 +61,7 @@ LIBKVMPLAT_SRCS-$(CONFIG_ARCH_ARM_64) +=
> $(UK_PLAT_COMMON_BASE)/arm/time.c|commo
>  LIBKVMPLAT_SRCS-$(CONFIG_ARCH_ARM_64) +=
> $(UK_PLAT_COMMON_BASE)/arm/traps.c|common
>  LIBKVMPLAT_SRCS-$(CONFIG_ARCH_ARM_64) +=
> $(UK_PLAT_COMMON_BASE)/arm/fdt.c|common
>  LIBKVMPLAT_SRCS-$(CONFIG_ARCH_ARM_64) +=
> $(UK_PLAT_COMMON_BASE)/arm/rtc.c|common
> +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/pagetable.S
> diff --git a/plat/kvm/arm/setup.c b/plat/kvm/arm/setup.c index
> 09530bb..14e64ad 100644
> --- a/plat/kvm/arm/setup.c
> +++ b/plat/kvm/arm/setup.c
> @@ -18,18 +18,16 @@
>   * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
>   * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>   */
> +#include <limits.h>
>  #include <libfdt.h>
> -#include <kvm/console.h>
> +#include <uk/essentials.h>
>  #include <uk/assert.h>
> +#include <kvm/console.h>
>  #include <kvm-arm/mm.h>
>  #include <arm/cpu.h>
> -#include <uk/arch/limits.h>
> -
> -void *_libkvmplat_pagetable;
> -void *_libkvmplat_heap_start;
> -void *_libkvmplat_stack_top;
> -void *_libkvmplat_mem_end;
> -void *_libkvmplat_dtb;
> +#include <arm/rtc.h>
> +#include <arm/gic-v2.h>
> +#include <arm/fdt.h>
> 
>  #define MAX_CMDLINE_SIZE 1024
>  static char cmdline[MAX_CMDLINE_SIZE];
> @@ -47,7 +45,7 @@ static void _init_dtb(void *dtb_pointer)
>               UK_CRASH("Invalid DTB: %s\n", fdt_strerror(ret));
> 
>       _libkvmplat_dtb = dtb_pointer;
> -     uk_pr_info("Found device tree on: %p\n", dtb_pointer);
> +     uk_printd(DLVL_INFO, "Found device tree on: %p\n", dtb_pointer);
>  }
> 
>  static void _dtb_get_psci_method(void)
> @@ -65,13 +63,13 @@ static void _dtb_get_psci_method(void)
>               fdtpsci = fdt_node_offset_by_compatible(_libkvmplat_dtb,
>                                                       -1, "arm,psci-0.2");
>       if (fdtpsci < 0) {
> -             uk_pr_info("No PSCI conduit found in DTB\n");
> +             uk_printd(DLVL_INFO, "No PSCI conduit found in DTB\n");
>               goto enomethod;
>       }
> 
>       fdtmethod = fdt_getprop(_libkvmplat_dtb, fdtpsci, "method", &len);
>       if (!fdtmethod || (len <= 0)) {
> -             uk_pr_info("No PSCI method found\n");
> +             uk_printd(DLVL_INFO, "No PSCI method found\n");
>               goto enomethod;
>       }
> 
> @@ -80,16 +78,16 @@ static void _dtb_get_psci_method(void)
>       else if (!strcmp(fdtmethod, "smc"))
>               smcc_psci_call = smcc_psci_smc_call;
>       else {
> -             uk_pr_info("Invalid PSCI conduit method: %s\n",
> -                        fdtmethod);
> +             uk_printd(DLVL_INFO,
> +             "Invalid PSCI conduit method: %s\n", fdtmethod);
>               goto enomethod;
>       }
> 
> -     uk_pr_info("PSCI method: %s\n", fdtmethod);
> +     uk_printd(DLVL_INFO, "PSCI method: %s\n", fdtmethod);
>       return;
> 
>  enomethod:
> -     uk_pr_info("Support PSCI from PSCI-0.2\n");
> +     uk_printd(DLVL_INFO, "Support PSCI from PSCI-0.2\n");
>       smcc_psci_call = NULL;
>  }
> 
> @@ -104,13 +102,13 @@ static void _init_dtb_mem(void)
> 
>       /* search for assigned VM memory in DTB */
>       if (fdt_num_mem_rsv(_libkvmplat_dtb) != 0)
> -             uk_pr_warn("Reserved memory is not supported\n");
> +             uk_printd(DLVL_WARN, "Reserved memory is not
> supported\n");
> 
>       fdt_mem = fdt_node_offset_by_prop_value(_libkvmplat_dtb, -1,
>                                               "device_type",
>                                               "memory",
> sizeof("memory"));
>       if (fdt_mem < 0) {
> -             uk_pr_warn("No memory found in DTB\n");
> +             uk_printd(DLVL_WARN, "No memory found in DTB\n");
>               return;
>       }
> 
> @@ -138,7 +136,8 @@ static void _init_dtb_mem(void)
> 
>       /* If we have more than one memory bank, give a warning messasge
> */
>       if (prop_len > prop_min_len)
> -             uk_pr_warn("Currently, we support only one memory
> bank!\n");
> +             uk_printd(DLVL_WARN,
> +                     "Currently, we support only one memory bank!\n");
> 
>       mem_base = fdt64_to_cpu(regs[0]);
>       mem_size = fdt64_to_cpu(regs[1]);
> @@ -172,17 +171,25 @@ static void _dtb_get_cmdline(char *cmdline, size_t
> maxlen)
>       cmdline[((unsigned int) len - 1) <= (maxlen - 1) ?
>               ((unsigned int) len - 1) : (maxlen - 1)] = '\0';
> 
> -     uk_pr_info("Command line: %s\n", cmdline);
> +     uk_printd(DLVL_INFO, "Command line: %s\n", cmdline);
>       return;
> 
>  enocmdl:
> -     uk_pr_info("No command line found\n");
> +     uk_printd(DLVL_INFO, "No command line found\n");
>       strcpy(cmdline, CONFIG_UK_NAME);
>  }
> 
>  static void _libkvmplat_entry2(void *arg __attribute__((unused)))  {
> -       ukplat_entry_argp(NULL, (char *)cmdline, strlen(cmdline));
> +     /* After switch to new stack, we start initializing other devices */
> +
> +     /* Initialize GIC interrupt controller */
> +     _dtb_init_gic(_libkvmplat_dtb);
> +
> +     /* Initialize RTC */
> +     _dtb_init_rtc(_libkvmplat_dtb);
> +
> +     ukplat_entry_argp(NULL, (char *)cmdline, strlen(cmdline));
>  }
> 
>  void _libkvmplat_start(void *dtb_pointer) @@ -190,7 +197,7 @@ void
> _libkvmplat_start(void *dtb_pointer)
>       _init_dtb(dtb_pointer);
>       _libkvmplat_init_console();
> 
> -     uk_pr_info("Entering from KVM (arm64)...\n");
> +     uk_printd(DLVL_INFO, "Entering from KVM (arm64)...\n");
> 
>       /* Get command line from DTB */
> 
> @@ -202,15 +209,15 @@ void _libkvmplat_start(void *dtb_pointer)
>       /* Initialize memory from DTB */
>       _init_dtb_mem();
> 
> -     uk_pr_info("pagetable start: %p\n", _libkvmplat_pagetable);
> -     uk_pr_info("     heap start: %p\n", _libkvmplat_heap_start);
> -     uk_pr_info("      stack top: %p\n", _libkvmplat_stack_top);
> +     uk_printd(DLVL_INFO, "pagetable start: %p\n",
> _libkvmplat_pagetable);
> +     uk_printd(DLVL_INFO, "     heap start: %p\n",
> _libkvmplat_heap_start);
> +     uk_printd(DLVL_INFO, "      stack top: %p\n", _libkvmplat_stack_top);
> 
>       /*
>        * Switch away from the bootstrap stack as early as possible.
>        */
> -     uk_pr_info("Switch from bootstrap stack to stack @%p\n",
> -                _libkvmplat_stack_top);
> +     uk_printd(DLVL_INFO, "Switch from bootstrap stack to stack @%p\n",
> +                             _libkvmplat_stack_top);
> 
>       _libkvmplat_newstack((uint64_t) _libkvmplat_stack_top,
>                               _libkvmplat_entry2, NULL);
> --
> 2.7.4


_______________________________________________
Minios-devel mailing list
Minios-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/minios-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.