diff --git a/drivers/ukintctlr/bcm_intc/bcm_intc_initialize.c b/drivers/ukintctlr/bcm_intc/bcm_intc_initialize.c index 4ed040cd0441aa33137af7b03b46c638ea0e1861..c96c299f50b3bbd88567cb6df777e510422d94fb 100644 --- a/drivers/ukintctlr/bcm_intc/bcm_intc_initialize.c +++ b/drivers/ukintctlr/bcm_intc/bcm_intc_initialize.c @@ -69,7 +69,7 @@ static int fdt_xlat(const void *fdt, int nodeoffset, __u32 index, #endif /* CONFIG_LIBUKOFW */ /* 根据设备树参数来设置中断属性 */ -static int configure_irq(struct uk_intctlr_irq *irq) +static int irq_set_trigger(struct uk_intctlr_irq *irq) { if (irq->trigger != UK_INTCTLR_IRQ_TRIGGER_NONE) /* 调用函数配置irq_trigger */ @@ -101,10 +101,17 @@ init: intctlr.name = "BCM-INTC"; ops.initialize = bcm_intc->ops.initialize; ops.percpu_init = __NULL; - ops.configure_irq = configure_irq; + ops.irq_set_trigger = irq_set_trigger; ops.mask_irq = bcm_intc->ops.disable_irq; ops.unmask_irq = bcm_intc->ops.enable_irq; ops.handle = bcm_intc->ops.handle_irq; + ops.irq_set_affinity = __NULL; + ops.irq_set_priority = __NULL; +#ifdef CONFIG_LIBUKINTCTLR_TEST + ops.irq_get_priority = __NULL; + ops.spi_get_affinity = __NULL; + ops.simulate_spi = __NULL; +#endif /* reserved for software general interrupt to specified core */ ops.sgi_op = __NULL; #if CONFIG_LIBUKOFW diff --git a/drivers/ukintctlr/gic/Config.uk b/drivers/ukintctlr/gic/Config.uk index a62ae03850eee019c739262c51db1d7bdf31d00e..331fc6d1f131201d1a10cf1dad1b39f9d80e9309 100644 --- a/drivers/ukintctlr/gic/Config.uk +++ b/drivers/ukintctlr/gic/Config.uk @@ -7,7 +7,38 @@ config LIBUKINTCTLR_GICV2 depends on (HAVE_INTCTLR && ARCH_ARM_64) select LIBUKINTCTLR_GIC -config LIBUKINTCTLR_GICV3 +menuconfig LIBUKINTCTLR_GICV3 bool "Arm Generic Interrupt Controller (GICv3)" depends on (HAVE_INTCTLR && ARCH_ARM_64) select LIBUKINTCTLR_GIC + default n + +if LIBUKINTCTLR_GICV3 +choice + prompt "GICV3 max priority level" + help + Numbers of interrupt priorities supported in non-secure mode + choose from 16/32/64/128 + +config PRIORITY_MAX_16 + bool "16 non-secure priority levels" + help + The available interrupt priority is [0..15] + +config PRIORITY_MAX_32 + bool "32 non-secure priority levels" + help + The available interrupt priority is [0..31] + +config PRIORITY_MAX_64 + bool "64 non-secure priority levels" + help + The available interrupt priority is [0..63] + +config PRIORITY_MAX_128 + bool "128 non-secure priority levels" + help + The available interrupt priority is [0..127] + +endchoice +endif diff --git a/drivers/ukintctlr/gic/gic-v2.c b/drivers/ukintctlr/gic/gic-v2.c index e6278e76167c0ed71f553f9d3a070532a76e7b8b..c3102f0d442e30a313aa3a590a8346632a4ce41a 100644 --- a/drivers/ukintctlr/gic/gic-v2.c +++ b/drivers/ukintctlr/gic/gic-v2.c @@ -210,9 +210,11 @@ void gicv2_sgi_gen_to_list(uint32_t sgintid, uint8_t targetlist) /** * Forward the SGI to the CPU specified by cpuid. */ -static void gicv2_sgi_gen_to_cpu(uint8_t sgintid, uint32_t cpuid) +static int gicv2_sgi_gen_to_cpu(uint8_t sgintid, uint32_t cpuid, + va_list cpuid_args __unused) { gicv2_sgi_gen_to_list((uint32_t) sgintid, (uint8_t) (1 << (cpuid % 8))); + return 0; } /** @@ -507,6 +509,11 @@ static void gicv2_set_ops(void) .disable_irq = gicv2_disable_irq, .set_irq_trigger = gicv2_set_irq_trigger, .set_irq_prio = gicv2_set_irq_prio, +#ifdef CONFIG_LIBUKINTCTLR_TEST + .get_irq_prio = NULL, + .simulate_spi = NULL, + .get_spi_affinity = NULL, +#endif .set_irq_affinity = gicv2_set_irq_target, .handle_irq = gicv2_handle_irq, .gic_sgi_gen = gicv2_sgi_gen_to_cpu, diff --git a/drivers/ukintctlr/gic/gic-v3.c b/drivers/ukintctlr/gic/gic-v3.c index 7dc092ccf557e7ddb9a9f70d449636ace8831e6f..1667a04cfafa402e153e4c2141b35ed5680a4e2b 100644 --- a/drivers/ukintctlr/gic/gic-v3.c +++ b/drivers/ukintctlr/gic/gic-v3.c @@ -111,6 +111,11 @@ static inline void write_gicd64(uint64_t offset, uint64_t val) ioreg_write64(GIC_DIST_REG(gicv3_drv, offset), val); } +static inline uint64_t read_gicd64(uint64_t offset) +{ + return ioreg_read64(GIC_DIST_REG(gicv3_drv, offset)); +} + static inline uint32_t read_gicd32(uint64_t offset) { return ioreg_read32(GIC_DIST_REG(gicv3_drv, offset)); @@ -126,6 +131,16 @@ static inline uint32_t read_gicrd32(uint64_t offset) return ioreg_read32(GIC_RDIST_REG(gicv3_drv, offset)); } +static inline uint32_t read_gicd8(uint64_t offset) +{ + return ioreg_read8(GIC_DIST_REG(gicv3_drv, offset)); +} + +static inline uint32_t read_gicrd8(uint64_t offset) +{ + return ioreg_read8(GIC_RDIST_REG(gicv3_drv, offset)); +} + /** * Wait for a write completion in [re]distributor * @@ -160,6 +175,26 @@ static uint32_t get_cpu_affinity(void) } #endif /* CONFIG_HAVE_SMP */ +/** + * Affinitize all SPI interrupts to the current cpu + * + * @param irq_number SPI interrupt number + */ +static void affinitize_all_spi_to_current_cpu(uint32_t irq_number) +{ + uint32_t i; + uint64_t mpidr = SYSREG_READ64(MPIDR_EL1); + uint64_t aff = ((mpidr & MPIDR_AFF3_MASK) >> 8) | + (mpidr & MPIDR_AFF2_MASK) | + (mpidr & MPIDR_AFF1_MASK) | + (mpidr & MPIDR_AFF0_MASK); + /* Route all global SPIs to this CPU */ + uint64_t irouter_val = GIC_AFF_TO_ROUTER(aff, 0); + + for (i = GIC_SPI_BASE; i < irq_number; i++) + write_gicd64(GICD_IROUTER(i), irouter_val); +} + /** * Acknowledge IRQ and retrieve highest priority pending interrupt * @@ -175,6 +210,59 @@ static uint32_t gicv3_ack_irq(void) return irq; } +#ifdef CONFIG_LIBUKINTCTLR_TEST +/** + * Set pending bit to simulate specified SPI being triggered + */ +static void gicv3_simulate_spi(uint32_t irq) +{ + UK_ASSERT(irq >= GIC_SPI_BASE && irq <= GIC_MAX_IRQ); + uint32_t pending_offset; + + pending_offset = GICD_ISPENDR(irq); + dist_lock(gicv3_drv); + write_gicd32(pending_offset, 1UL << (irq % 32)); + dist_unlock(gicv3_drv); +} + +/** + * Get the interrupt priority level in non-secure mode + * @param irq irq to get priority information + * @return priority level of irq + */ +static uint8_t gicv3_get_irq_prio(uint32_t irq) +{ + uint8_t prio_level; + + dist_lock(gicv3_drv); + if (irq < GIC_SPI_BASE) /* Change in redistributor */ + prio_level = + read_gicrd8(GICR_IPRIORITYR(irq)); + else + prio_level = + read_gicd8(GICD_IPRIORITYR(irq)); + dist_unlock(gicv3_drv); + return prio_level; +} + +/** + * Get the spi affinity stats + * @param irq irq to get affinity information + * @return affinity information of irq + */ +static uint32_t gicv3_get_spi_affinity(uint32_t irq) +{ + UK_ASSERT(irq >= GIC_SPI_BASE && irq <= GIC_MAX_IRQ); + dist_lock(gicv3_drv); + uint64_t router_value = read_gicd64(GICD_IROUTER(irq)); + + uint32_t aff = (uint32_t)((router_value >> 8) & 0xFFFFFF); + + dist_unlock(gicv3_drv); + return aff; +} +#endif /* CONFIG_LIBUKINTCTLR_TEST */ + /** * Signal completion of interrupt processing * @@ -186,10 +274,11 @@ static void gicv3_eoi_irq(uint32_t irq) /* Lower the priority */ SYSREG_WRITE32(ICC_EOIR1_EL1, irq); isb(); - +#ifdef CONFIG_VIRTUALIZE_PLAT /* Deactivate */ SYSREG_WRITE32(ICC_DIR_EL1, irq); isb(); +#endif } /** @@ -203,20 +292,6 @@ static void gicv3_enable_irq(uint32_t irq) dist_lock(gicv3_drv); -#ifdef CONFIG_HAVE_SMP - /* Route this IRQ to the running core, i.e., route to the CPU interface - * of the core calling this function - */ - if (irq >= GIC_SPI_BASE) { - uint64_t aff = (uint64_t)get_cpu_affinity(); - uint64_t irouter_val = GIC_AFF_TO_ROUTER(aff, 0); - - write_gicd64(GICD_IROUTER(irq), irouter_val); - uk_pr_debug("IRQ %d routed to 0x%lx (REG: 0x%lx)\n", - irq, aff, irouter_val); - } -#endif /* CONFIG_HAVE_SMP */ - if (irq >= GIC_SPI_BASE) write_gicd32(GICD_ISENABLER(irq), UK_BIT(irq % GICD_I_PER_ISENABLERn)); @@ -228,50 +303,87 @@ static void gicv3_enable_irq(uint32_t irq) } /** - * Send a software generated interrupt to the specified core. + * Send a software generated interrupt to the specified cores. * - * @sgintid the software generated interrupt id - * @cpuid the id of the targeted cpu + * @param sgintid the software generated interrupt id + * @param target_count the number of target cpus, + * zero means sending sgi to a11 PEs in the system except the current one. + * @param va_list argument list of cpuid, could be empty. type: uint32_t + * @return zero on success, negative value on failure */ -static void gicv3_sgi_gen(uint8_t sgintid, uint32_t cpuid) +static int gicv3_sgi_gen(uint8_t sgintid, + uint32_t target_count, va_list cpuid_args) { - uint64_t sgi_register = 0, control_register_rss, type_register_rss; + uint64_t sgi_register = 0, affinity_and_rs_checker = 0; + uint64_t control_register_rss, type_register_rss; uint64_t range_selector = 0, extended_cpuid; uint32_t aff0; - extended_cpuid = (uint64_t) cpuid; - /* Only INTID 0-15 allocated to sgi */ UK_ASSERT(sgintid <= GICD_SGI_MAX_INITID); + UK_ASSERT(target_count <= GICD_SGI_MAX_TARGETLIST); + sgi_register |= (sgintid << 24); - /* Set affinity fields and optional range selector */ - sgi_register |= (extended_cpuid & MPIDR_AFF3_MASK) << 48; - sgi_register |= (extended_cpuid & MPIDR_AFF2_MASK) << 32; - sgi_register |= (extended_cpuid & MPIDR_AFF1_MASK) << 16; - /** - ** For affinity 0, we need to find which group of 16 values is - ** represented by the TargetList field in ICC_SGI1R_EL1. - **/ - aff0 = extended_cpuid & MPIDR_AFF0_MASK; - if (aff0 >= 16) { - control_register_rss = SYSREG_READ64(ICC_CTLR_EL1) & (1 << 18); - type_register_rss = read_gicd32(GICD_TYPER) & (1 << 26); - if (control_register_rss == 1 && type_register_rss == 1) { - range_selector = aff0 / 16; - sgi_register |= (range_selector << 44); - } else { - uk_pr_err("Can't generate interrupt!\n"); - return; - } + if (!target_count) { + sgi_register |= ICC_SGI1R_EL1_IRM_ALL; + dist_lock(gicv3_drv); + SYSREG_WRITE64(ICC_SGI1R_EL1, sgi_register); + dist_unlock(gicv3_drv); + return 0; } - sgi_register |= (1 << (aff0 % 16)); + control_register_rss = + SYSREG_READ64(ICC_CTLR_EL1) & (1 << 18); + type_register_rss = + read_gicd32(GICD_TYPER) & (1 << 26); + + uint8_t i; + + for (i = 0; i < target_count; i++) { + extended_cpuid = (uint64_t)va_arg(cpuid_args, uint32_t); + + /* Set affinity fields and optional range selector */ + sgi_register |= + (extended_cpuid & MPIDR_AFF3_MASK) << 48; + sgi_register |= + (extended_cpuid & MPIDR_AFF2_MASK) << 32; + sgi_register |= + (extended_cpuid & MPIDR_AFF1_MASK) << 16; + + aff0 = extended_cpuid & MPIDR_AFF0_MASK; + range_selector = aff0 / 16; + sgi_register |= ((1 << (aff0 % 16)) | (range_selector << 44)); + + if (i == 0) { + if (range_selector >= 1 && + (control_register_rss != 1 || type_register_rss != 1)) { + uk_pr_err( + "send sgi to target core(s) failed: \r\n" + "mismatch cpuid(0x%lx) and rs(GICD_TYPER.RS: %lu, ICC_CTLR.RS: %lu)\n" + , extended_cpuid, + type_register_rss, + control_register_rss); + return -1; + } + + affinity_and_rs_checker = sgi_register; + continue; + } + + if ((sgi_register & MPIDR_AFFx_AND_RS_MASK) + != (affinity_and_rs_checker & MPIDR_AFFx_AND_RS_MASK)) { + uk_pr_err("send sgi to target core(s) failed: \r\n" + "there are cores having different affinity or range selector\n"); + return -1; + } + } - /* Generate interrupt */ dist_lock(gicv3_drv); SYSREG_WRITE64(ICC_SGI1R_EL1, sgi_register); dist_unlock(gicv3_drv); + + return 0; } /** @@ -315,19 +427,21 @@ static void gicv3_set_irq_affinity(uint32_t irq, uint32_t affinity) * Set priority for an interrupt * * @param irq interrupt number [0..GIC_MAX_IRQ] - * @param priority priority [0..255]. The GIC implementation may not support - * all levels. For example, if only 128 levels are supported every two levels - * (e.g., 0 and 1) map to the same effective value. Lower values correspond - * to higher priority + * @param priority Available interrupt priority range in non-secure mode, + * Lower values correspond to higher priorities + * Refer to the gic documentation for more details. */ static void gicv3_set_irq_prio(uint32_t irq, uint8_t priority) { - dist_lock(gicv3_drv); + UK_ASSERT(priority < (1 << (8 - TRANS_PRIORITY_SHIFT))); + dist_lock(gicv3_drv); if (irq < GIC_SPI_BASE) /* Change in redistributor */ - write_gicrd8(GICR_IPRIORITYR(irq), priority); + write_gicrd8(GICR_IPRIORITYR(irq), + priority << TRANS_PRIORITY_SHIFT); else - write_gicd8(GICD_IPRIORITYR(irq), priority); + write_gicd8(GICD_IPRIORITYR(irq), + priority << TRANS_PRIORITY_SHIFT); dist_unlock(gicv3_drv); } @@ -440,8 +554,7 @@ static void gicv3_init_redist(void) /* Set priority mask register */ SYSREG_WRITE32(ICC_PMR_EL1, 0xff); - /* EOI drops priority, DIR deactivates the interrupt (mode 1) */ - SYSREG_WRITE32(ICC_CTLR_EL1, GICC_CTLR_EL1_EOImode_drop); + SYSREG_WRITE32(ICC_CTLR_EL1, ICC_CTLR_EL1_EOImode); /* Enable Group 1 interrupts */ SYSREG_WRITE32(ICC_IGRPEN1_EL1, 1); @@ -475,14 +588,18 @@ static void gicv3_init_dist(void) for (i = GIC_SPI_BASE; i < irq_number; i += GICD_I_PER_IGROUPRn) write_gicd32(GICD_IGROUPR(i), GICD_DEF_IGROUPRn); + /* Check for 1 of N SPI interrupts support */ + if (val & GICD_TYPE_NO1N_MASK) { + affinitize_all_spi_to_current_cpu(irq_number); + } else { #ifdef CONFIG_HAVE_SMP - /* Route all global SPIs to this CPU */ - uint64_t aff = (uint64_t)get_cpu_affinity(); - uint64_t irouter_val = GIC_AFF_TO_ROUTER(aff, 0); - - for (i = GIC_SPI_BASE; i < irq_number; i++) - write_gicd64(GICD_IROUTER(i), irouter_val); + for (i = GIC_SPI_BASE; i < irq_number; i++) + write_gicd64(GICD_IROUTER(i), + GIC_AFF_TO_ROUTER(0ULL, 1)); +#else + affinitize_all_spi_to_current_cpu(irq_number); #endif /* CONFIG_HAVE_SMP */ + } /* Set all SPI's interrupt type to be level-sensitive */ for (i = GIC_SPI_BASE; i < irq_number; i += GICD_I_PER_ICFGRn) @@ -557,14 +674,14 @@ static int gicv3_initialize(void) } #endif /* CONFIG_HAVE_SMP */ - gicv3_drv.is_initialized = 1; - /* Initialize GICv3 distributor */ gicv3_init_dist(); /* Initialize GICv3 CPU redistributor */ gicv3_init_redist(); + gicv3_drv.is_initialized = 1; + return 0; } @@ -581,6 +698,11 @@ static inline void gicv3_set_ops(void) .set_irq_affinity = gicv3_set_irq_affinity, .handle_irq = gicv3_handle_irq, .gic_sgi_gen = gicv3_sgi_gen, +#ifdef CONFIG_LIBUKINTCTLR_TEST + .get_irq_prio = gicv3_get_irq_prio, + .simulate_spi = gicv3_simulate_spi, + .get_spi_affinity = gicv3_get_spi_affinity, +#endif }; /* Set driver functions */ diff --git a/drivers/ukintctlr/gic/include/uk/intctlr/gic-v3.h b/drivers/ukintctlr/gic/include/uk/intctlr/gic-v3.h index 0338000365f88f887e11fd3ebe7f3157525f37b0..9f9e299bf9433962750a69905663dd0ef6088d3c 100644 --- a/drivers/ukintctlr/gic/include/uk/intctlr/gic-v3.h +++ b/drivers/ukintctlr/gic/include/uk/intctlr/gic-v3.h @@ -48,6 +48,8 @@ #define MPIDR_AFF1_MASK 0x000000ff00 /** Affinity AFF0 bit mask */ #define MPIDR_AFF0_MASK 0x00000000ff +/** Affinity AFFx and range selector bit mask */ +#define MPIDR_AFFx_AND_RS_MASK 0xfffff0ffff00 /* * GIC System register assembly aliases @@ -62,10 +64,34 @@ #define ICC_SRE_EL1 S3_0_C12_C12_5 #define ICC_IGRPEN1_EL1 S3_0_C12_C12_7 +/* + * Set Group 1 SGIs routing mode + * ICC_SGI1R_EL1_IRM_ALL, SGI routed to all PEs, excluding "self". + * ICC_SGI1R_EL1_IRM, SGI routed to the PEs specified by Aff3.Aff2.Aff1. + */ +#define ICC_SGI1R_EL1_IRM_ALL (1UL << 40) +#define ICC_SGI1R_EL1_IRM (0UL << 40) + +/* + * ICC_CTLR_EL1_EOImode Controls + * whether a write to an End of Interrupt register + * also deactivates the interrupt + * ICC_CTLR_EL1_EOImode_drop provide priority drop functionality only + * ICC_CTLR_EL1_EOImode_drop_deactivation + * provide both priority drop and interrupt deactivation functionality + */ +#define ICC_CTLR_EL1_EOImode_drop (1U << 1) +#define ICC_CTLR_EL1_EOImode_drop_and_deactivation (0U << 1) + +#if defined CONFIG_VIRTUALIZE_PLAT +#define ICC_CTLR_EL1_EOImode ICC_CTLR_EL1_EOImode_drop +#else +#define ICC_CTLR_EL1_EOImode ICC_CTLR_EL1_EOImode_drop_and_deactivation +#endif + /* * Distributor and Redistributor registers */ -#define GICC_CTLR_EL1_EOImode_drop (1U << 1) /* Default size according to ARM Generic Interrupt Controller Architecture * Specification GIC Architecture version 3 and version 4 Issue H. @@ -80,6 +106,7 @@ #define GICD_IROUTER_BASE (0x6000) #define GICD_IROUTER32 (0x6100) #define GICD_IROUTER1019 (0x7FD8) +#define GICD_IROUTER_IRM (1UL << 31) #define GICD_PIDR2 (0xFFE8) #define GICD_CTLR_RWP (1UL << 31) @@ -98,6 +125,11 @@ ((((r) >> GICD_TYPE_ID_BITS_SHIFT) & 0x1f) + 1) #define GICD_TYPE_LPIS (1U << 17) +/* Indicates whether 1 of N SPI interrupts are supported. + * 0b0 1 of N SPI interrupts are supported. + * 0b1 1 of N SPI interrupts are not supported. + */ +#define GICD_TYPE_NO1N_MASK (1U << 25) #define GICR_WAKER_ProcessorSleep (1U << 1) #define GICR_WAKER_ChildrenAsleep (1U << 2) @@ -339,6 +371,7 @@ #define GICD_SGI_FILTER_SHIFT 24 #define GICD_SGI_FILTER_MASK 0x3 #define GICD_SGI_MAX_INITID 15 +#define GICD_SGI_MAX_TARGETLIST 16 #define GICD_PPI_START /* @@ -370,6 +403,22 @@ #define GICC_IAR_INTID_MASK 0x3FF #define GICC_IAR_INTID_SPURIOUS 1023 +/* + * Select the corresponding priority shift bit + * based on the number of interrupt priorities + */ +#if defined(CONFIG_PRIORITY_MAX_16) + #define TRANS_PRIORITY_SHIFT 4 +#elif defined(CONFIG_PRIORITY_MAX_32) + #define TRANS_PRIORITY_SHIFT 3 +#elif defined(CONFIG_PRIORITY_MAX_64) + #define TRANS_PRIORITY_SHIFT 2 +#elif defined(CONFIG_PRIORITY_MAX_128) + #define TRANS_PRIORITY_SHIFT 1 +#else + #define TRANS_PRIORITY_SHIFT 4 +#endif + /** * Probe device tree or ACPI for GICv3 * NOTE: First time must not be called from multiple CPUs in parallel diff --git a/drivers/ukintctlr/gic/include/uk/intctlr/gic.h b/drivers/ukintctlr/gic/include/uk/intctlr/gic.h index 6c7591a8d035281c9d8c416f4d2c042e8ba8647f..ba2335ba73a6c14577f4fabbde5ac10018c84c89 100644 --- a/drivers/ukintctlr/gic/include/uk/intctlr/gic.h +++ b/drivers/ukintctlr/gic/include/uk/intctlr/gic.h @@ -68,27 +68,36 @@ typedef enum _GIC_HW_VER { /** GIC driver operations */ struct _gic_operations { - /** Initialize GIC controller */ + /* Initialize GIC controller */ int (*initialize)(void); - /** Acknowledging IRQ */ + /* Acknowledging IRQ */ uint32_t (*ack_irq)(void); - /** Finish interrupt handling */ + /* Finish interrupt handling */ void (*eoi_irq)(uint32_t irq); - /** Enable IRQ */ + /* Enable IRQ */ void (*enable_irq)(uint32_t irq); - /** Disable IRQ */ + /* Disable IRQ */ void (*disable_irq)(uint32_t irq); - /** Set IRQ trigger type */ + /* Set IRQ trigger type */ void (*set_irq_trigger)(uint32_t irq, enum uk_intctlr_irq_trigger trigger); - /** Set priority for IRQ */ + /* Set priority for IRQ */ void (*set_irq_prio)(uint32_t irq, uint8_t priority); - /** Set IRQ affinity (or "target" for GICv2) */ + /* Set IRQ affinity (or "target" for GICv2) */ void (*set_irq_affinity)(uint32_t irq, uint32_t affinity); - /** Handle IRQ */ + /* Handle IRQ */ void (*handle_irq)(struct __regs *regs); - /** Send a SGI to the specifiec core */ - void (*gic_sgi_gen)(uint8_t sgintid, uint32_t cpuid); + /* Send a SGI to the specified cores or all cores excluding "self" */ + int (*gic_sgi_gen)(uint8_t sgintid, uint32_t target_amount, + va_list cpuid_args); +#ifdef CONFIG_LIBUKINTCTLR_TEST + /* Simulate spi */ + void (*simulate_spi)(uint32_t irq); + /* Get IRQ priority level */ + uint8_t (*get_irq_prio)(uint32_t irq); + /* Get spi affinity */ + uint32_t (*get_spi_affinity)(uint32_t irq); +#endif }; /** GIC controller structure */ diff --git a/drivers/ukintctlr/gic/ukintctlr.c b/drivers/ukintctlr/gic/ukintctlr.c index 4b50c33773e0866337932bf030ad970c670c9d22..154928a9f5dacd6fcc304a7caf5e7d6f081317b2 100644 --- a/drivers/ukintctlr/gic/ukintctlr.c +++ b/drivers/ukintctlr/gic/ukintctlr.c @@ -75,7 +75,7 @@ static int fdt_xlat(const void *fdt, int nodeoffset, __u32 index, } #endif /* CONFIG_LIBUKOFW */ -static int configure_irq(struct uk_intctlr_irq *irq) +static int set_irq_trigger(struct uk_intctlr_irq *irq) { if (irq->trigger != UK_INTCTLR_IRQ_TRIGGER_NONE) gic->ops.set_irq_trigger(irq->id, irq->trigger); @@ -111,9 +111,16 @@ init: if (unlikely(rc)) return rc; - ops.configure_irq = configure_irq; + ops.irq_set_trigger = set_irq_trigger; ops.mask_irq = gic->ops.disable_irq; ops.unmask_irq = gic->ops.enable_irq; + ops.irq_set_priority = gic->ops.set_irq_prio; +#ifdef CONFIG_LIBUKINTCTLR_TEST + ops.irq_get_priority = gic->ops.get_irq_prio; + ops.spi_get_affinity = gic->ops.get_spi_affinity; + ops.simulate_spi = gic->ops.simulate_spi; +#endif + ops.irq_set_affinity = gic->ops.set_irq_affinity; #if CONFIG_LIBUKOFW ops.fdt_xlat = fdt_xlat; #endif /* CONFIG_LIBUKOFW */ diff --git a/drivers/ukintctlr/xpic/ukintctlr.c b/drivers/ukintctlr/xpic/ukintctlr.c index 5581aa9d8ab1a9b5ad40529d938a6d142250fe59..610a3c1795aabf72bca6d49e181b37e94dff49bf 100644 --- a/drivers/ukintctlr/xpic/ukintctlr.c +++ b/drivers/ukintctlr/xpic/ukintctlr.c @@ -15,7 +15,7 @@ static struct uk_intctlr_desc intctlr; -static int configure_irq(struct uk_intctlr_irq *irq __unused) +static int irq_set_trigger(struct uk_intctlr_irq *irq __unused) { return 0; } @@ -56,12 +56,18 @@ int uk_intctlr_probe(void) #endif /* CONFIG_LIBUKINTCTLR_APIC */ intctlr.ops = ops; - intctlr.ops->configure_irq = configure_irq; + intctlr.ops->irq_set_trigger = irq_set_trigger; intctlr.ops->initialize = __NULL; intctlr.ops->handle = uk_intctlr_xpic_handle_irq; intctlr.ops->fdt_xlat = __NULL; intctlr.ops->sgi_op = __NULL; intctlr.ops->percpu_init = __NULL; - + intctlr.ops->irq_set_priority = __NULL; + intctlr.ops->irq_set_affinity = __NULL; +#ifdef CONFIG_LIBUKINTCTLR_TEST + intctlr.ops->irq_get_priority = __NULL; + intctlr.ops->spi_get_affinity = __NULL; + intctlr.ops->simulate_spi = __NULL; +#endif return uk_intctlr_register(&intctlr); } diff --git a/drivers/virtio/mmio/virtio_mmio.c b/drivers/virtio/mmio/virtio_mmio.c index 881a3181b123d9a278bd8cc8372bf389c1bca290..087e7cf8196342250c2beb839dc5ff4df2194359 100644 --- a/drivers/virtio/mmio/virtio_mmio.c +++ b/drivers/virtio/mmio/virtio_mmio.c @@ -439,7 +439,7 @@ static int virtio_mmio_probe_fdt(struct pf_device *pfdev) if (unlikely(rc < 0)) return -EINVAL; - uk_intctlr_irq_configure(&irq); + uk_intctlr_irq_set_trigger(&irq); prop = fdt_getprop(dtb, offs, "reg", &prop_len); if (unlikely(!prop)) diff --git a/lib/ukintctlr/exportsyms.uk b/lib/ukintctlr/exportsyms.uk index 80ce0e8b0a7f8323f924a466011bbd65ab6cc6a2..5035f1d18e134b5d68e9e44fd843b7cbea0996b3 100644 --- a/lib/ukintctlr/exportsyms.uk +++ b/lib/ukintctlr/exportsyms.uk @@ -1,13 +1,18 @@ uk_intctlr -uk_intctlr_init -uk_intctlr_irq_configure -uk_intctlr_irq_fdt_xlat +uk_intctlr_handle uk_intctlr_irq_alloc +uk_intctlr_irq_fdt_xlat uk_intctlr_irq_free +uk_intctlr_irq_get_priority uk_intctlr_irq_handle -uk_intctlr_handle -uk_intctlr_sgi_op -uk_intctlr_percpu_init uk_intctlr_irq_register +uk_intctlr_irq_set_affinity +uk_intctlr_irq_set_priority +uk_intctlr_irq_set_trigger uk_intctlr_irq_unregister +uk_intctlr_init +uk_intctlr_percpu_init uk_intctlr_register +uk_intctlr_simulate_spi +uk_intctlr_sgi_op +uk_intctlr_spi_get_affinity diff --git a/lib/ukintctlr/include/uk/intctlr.h b/lib/ukintctlr/include/uk/intctlr.h index c49eb62d02eb73fec733ce84624d59398c35ea9b..55d82c352a7c7388af458e7e85779a6c2097be32 100644 --- a/lib/ukintctlr/include/uk/intctlr.h +++ b/lib/ukintctlr/include/uk/intctlr.h @@ -54,15 +54,74 @@ struct uk_intctlr_irq { * These must be implemented by the interrupt controller */ struct uk_intctlr_driver_ops { - int (*configure_irq)(struct uk_intctlr_irq *irq); + /** + * Configure trigger type for an interrupt + * + * @param irq Interrupt configuration + * @return zero on success or negative value on error + */ + int (*irq_set_trigger)(struct uk_intctlr_irq *irq); int (*fdt_xlat)(const void *fdt, int nodeoffset, __u32 index, struct uk_intctlr_irq *irq); void (*mask_irq)(unsigned int irq); void (*unmask_irq)(unsigned int irq); void (*initialize)(void); void (*handle)(struct __regs *regs); - void (*sgi_op)(uint8_t sgintid, uint32_t cpuid); int (*percpu_init)(void); + + /** + * Send a SGI to the specified core(s). + * + * @param sgintid the software generated interrupt id + * @param target_count the number of target cpus, + * zero means sending sgi to all PEs in the system except "self". + * @param cpuid_args argument list of cpuid, + * could be empty. type: uint32_t + * @return zero on success , negative value on failure + */ + int (*sgi_op)(uint8_t sgintid, uint32_t target_count, + va_list cpuid_args); + + /** + * set priority for interrupt + * + * @param irq IRQ to set priority + * @param priority priority number value [0..GIC_MAX_IRQ] + * smaller priority number indicates a higher priority + */ + void (*irq_set_priority)(unsigned int irq, uint8_t priority); + + /** + * set affinity for SPI interrupt + * + * @param irq IRQ to set affinity + * @param cpuid target CPU id to cope with SPI + */ + void (*irq_set_affinity)(unsigned int irq, uint32_t cpuid); +#ifdef CONFIG_LIBUKINTCTLR_TEST + /** + * Get IRQ priority level in non-secure mode + * + * @param irq IRQ to get priority + * @return IRQ priority level + */ + uint8_t (*irq_get_priority)(unsigned int irq); + + /** + * Get spi affinity status + * + * @param irq spi to get affinity + * @return spi affinity status + */ + uint32_t (*spi_get_affinity)(unsigned int irq); + + /** + * Set pending bit to simulate spi being triggered + * + * @param irq spi to set pending status + */ + void (*simulate_spi)(unsigned int irq); +#endif }; /** Interrupt controller descriptor */ @@ -96,12 +155,12 @@ int uk_intctlr_probe(void); void uk_intctlr_irq_handle(struct __regs *regs, unsigned int irq); /** - * Configure an interrupt + * Configure trigger type for an interrupt * * @param irq Interrupt configuration * @return zero on success or negative value on error */ -int uk_intctlr_irq_configure(struct uk_intctlr_irq *irq); +int uk_intctlr_irq_set_trigger(struct uk_intctlr_irq *irq); /** * Register interrupt controller driver with the uk_intctlr subsystem @@ -198,19 +257,65 @@ int uk_intctlr_irq_fdt_xlat(const void *fdt, int nodeoffset, __u32 index, void uk_intctlr_handle(struct __regs *regs); /** - * Handle function for interrupt controller + * Send a SGI to the specified core(s). * * @param sgintid the software generated interrupt id - * @param cpuid the id of the targeted cpu - * @return zero on success , error code on failure + * @param target_count the number of target cpus, + * zero means sending sgi to all PEs in the system except the current one. + * @param ... optional argument list of cpuid,type:uint32_t + * @return zero on success, negative value on failure */ -int uk_intctlr_sgi_op(uint8_t sgintid, uint32_t cpuid); +int uk_intctlr_sgi_op(uint8_t sgintid, uint32_t target_count, ...); /** * extra initialize function for each cpu core * @return zero on success , error code on failure */ int uk_intctlr_percpu_init(void); + +/** + * set priority for interrupt + * + * @param irq IRQ to set priority + * @param priority priority number value [0..GIC_MAX_IRQ] + * smaller priority number indicates a higher priority + */ +void uk_intctlr_irq_set_priority(unsigned int irq, uint8_t priority); + +/** + * set affinity for SPI interrupt + * + * @param irq SPI Interrupt to set affinity + * @param cpuid target CPU id to cope with SPI + */ +void uk_intctlr_irq_set_affinity(unsigned int irq, uint32_t cpuid); + +#ifdef CONFIG_LIBUKINTCTLR_TEST +/** + * Get IRQ priority level in non-secure mode + * + * @param irq irq to get priority information + * @return irq priority level + */ +uint8_t uk_intctlr_irq_get_priority(unsigned int irq); + +/** + * Get spi affinity status + * + * @param irq spi to get affinity + * @return spi affinity status + */ +uint32_t uk_intctlr_spi_get_affinity(unsigned int irq); + +/** + * sets the status of the corresponding + * peripheral interrupt to pending status + * + * @param irq spi to set pending + */ +void uk_intctlr_simulate_spi(unsigned int irq); +#endif + #endif /* __ASSEMBLY__ */ #ifdef __cplusplus diff --git a/lib/ukintctlr/tests/test_intctlr.c b/lib/ukintctlr/tests/test_intctlr.c index c10e3c54edae07551e9a9deab0783e197817a51f..b0418bbbc15d486520a66ff1fa61afe5a2263892 100644 --- a/lib/ukintctlr/tests/test_intctlr.c +++ b/lib/ukintctlr/tests/test_intctlr.c @@ -17,199 +17,145 @@ #include #include -static struct uk_intctlr_desc *ori_intctlr; -static struct uk_intctlr_desc test_intctlr; -struct uk_intctlr_driver_ops test_ops; -static int ret; - -enum ukintctlr_test_ret { - TEST_DEFAULT, - TEST_CONFIGURE_IRQ_SUCCESS, - TEST_FDT_XLAT_SUCCESS, - TEST_MASK_IRQ_SUCCESS, - TEST_UNMASK_IRQ_SUCCESS, - TEST_INITIALIZE_SUCCESS, - TEST_HANDLE_SUCCESS, - TEST_SGI_OP_SUCCESS, - TEST_PERCPU_INIT_SUCCESS, -}; - -static int test_configure_irq(struct uk_intctlr_irq *irq __unused) -{ - ret = TEST_CONFIGURE_IRQ_SUCCESS; - return 0; -} - -static int test_fdt_xlat(const void *fdt __unused, int nodeoffset __unused, - __u32 index __unused, - struct uk_intctlr_irq *irq __unused) -{ - ret = TEST_FDT_XLAT_SUCCESS; - return 0; -} -static void test_mask_irq(unsigned int irq __unused) -{ - ret = TEST_MASK_IRQ_SUCCESS; -} +#ifdef CONFIG_LIBUKINTCTLR_GICV3 +#include -static void test_unmask_irq(unsigned int irq __unused) -{ - ret = TEST_UNMASK_IRQ_SUCCESS; -} +static uint32_t global_current_cpu; -static void test_handle(struct __regs *regs __unused) +static int spi_handler(void *args __unused) { - ret = TEST_HANDLE_SUCCESS; -} - -static void test_sgi_op(uint8_t sgintid __unused, uint32_t cpuid __unused) -{ - ret = TEST_SGI_OP_SUCCESS; -} - -static int test_percpu_init(void) -{ - ret = TEST_PERCPU_INIT_SUCCESS; - + printf("spi handler start.\n"); + uint64_t mpidr = SYSREG_READ64(MPIDR_EL1); + uint64_t aff = ((mpidr & MPIDR_AFF3_MASK) >> 8) | + (mpidr & MPIDR_AFF2_MASK) | + (mpidr & MPIDR_AFF1_MASK) | + (mpidr & MPIDR_AFF0_MASK); + + global_current_cpu = (uint32_t)aff; return 0; } -static inline void test_intctlr_init(void) +UK_TESTCASE_DESC(ukintctlr, set_spi_pendings_test_affx_api, + "Affinity irq40 to the current cpu") { - ori_intctlr = uk_intctlr; - ret = 0; - - test_intctlr.name = "TEST_INTCTLR"; - test_ops.configure_irq = test_configure_irq; - test_ops.fdt_xlat = test_fdt_xlat; - test_ops.mask_irq = test_mask_irq; - test_ops.unmask_irq = test_unmask_irq; - test_ops.handle = test_handle; - test_ops.sgi_op = test_sgi_op; - test_ops.percpu_init = test_percpu_init; - test_intctlr.ops = &test_ops; - - uk_intctlr_register(&test_intctlr); -} - -/* 测试configure_irq接口 */ -UK_TESTCASE(ukintctlr, call_intctlr_configure_irq) -{ - struct uk_intctlr_irq irq = {0}; - struct uk_intctlr_irq *p_irq = &irq; - - /* 1.备份原有uk_intctlr,初始化测试环境 */ - test_intctlr_init(); - - /* 2.通过统一接口调用configure_irq,并校验调用结果 */ - (void)uk_intctlr_irq_configure(p_irq); - UK_TEST_EXPECT_SNUM_EQ(ret, TEST_CONFIGURE_IRQ_SUCCESS); + /* 中断号40,亲和至当前cpu */ + uint32_t original_cpu_affinity = uk_intctlr_spi_get_affinity(40); - /* 3.恢复环境 */ - uk_intctlr_register(ori_intctlr); -} + uint64_t current_cpu = SYSREG_READ64(MPIDR_EL1); + uint64_t aff = ((current_cpu & MPIDR_AFF3_MASK) >> 8) | + (current_cpu & MPIDR_AFF2_MASK) | + (current_cpu & MPIDR_AFF1_MASK) | + (current_cpu & MPIDR_AFF0_MASK); -/* 测试fdt_xlat接口 */ -UK_TESTCASE(ukintctlr, call_fdt_xlat) -{ - struct uk_intctlr_irq irq = {0}; - struct uk_intctlr_irq *p_irq = &irq; - const char *fdt = "FDT"; - int nodeoffset = 0; - __u32 index = 0; + uk_intctlr_irq_set_affinity(40, (uint32_t)aff); + uk_intctlr_irq_register(40, spi_handler, NULL); + isb(); - /* 1.备份原有uk_intctlr,初始化测试环境 */ - test_intctlr_init(); + uk_intctlr_simulate_spi(40); + __asm__ __volatile__("wfi"); - /* 2.通过统一接口调用fdt_xlat,并校验调用结果 */ - (void)uk_intctlr_irq_fdt_xlat(fdt, nodeoffset, index, p_irq); - UK_TEST_EXPECT_SNUM_EQ(ret, TEST_FDT_XLAT_SUCCESS); + UK_TEST_EXPECT_SNUM_EQ((uint32_t)aff, global_current_cpu); - /* 3.恢复环境 */ - uk_intctlr_register(ori_intctlr); + /* 恢复现场 */ + uk_intctlr_irq_unregister(40, spi_handler); + uk_intctlr_irq_set_affinity(40, original_cpu_affinity); } -/* 测试mask_irq接口 */ -UK_TESTCASE(ukintctlr, call_mask_irq) -{ - int irq = 0; - - /* 1.备份原有uk_intctlr,初始化测试环境 */ - test_intctlr_init(); - - /* 2.通过统一接口调用mask_irq,并校验调用结果 */ - uk_intctlr_irq_mask(irq); - UK_TEST_EXPECT_SNUM_EQ(ret, TEST_MASK_IRQ_SUCCESS); - - /* 3.恢复环境 */ - uk_intctlr_register(ori_intctlr); -} -/* 测试unmask_irq接口 */ -UK_TESTCASE(ukintctlr, call_unmask_irq) +UK_TESTCASE_DESC(ukintctlr, verify_spi_priority_level_setting, + "Compare the priority of interrupt 60/70") { - int irq = 0; - - /* 1.备份原有uk_intctlr,初始化测试环境 */ - test_intctlr_init(); - - /* 2.通过统一接口调用unmask_irq,并校验调用结果 */ - uk_intctlr_irq_unmask(irq); - UK_TEST_EXPECT_SNUM_EQ(ret, TEST_UNMASK_IRQ_SUCCESS); - - /* 3.恢复环境 */ - uk_intctlr_register(ori_intctlr); + uint8_t irq60_original_prio_level = + uk_intctlr_irq_get_priority(60) >> TRANS_PRIORITY_SHIFT; + uint8_t irq70_original_prio_level = + uk_intctlr_irq_get_priority(70) >> TRANS_PRIORITY_SHIFT; + + +#if defined(CONFIG_PRIORITY_MAX_16) + uk_intctlr_irq_set_priority(60, 15); + uk_intctlr_irq_set_priority(70, 14); + isb(); + UK_TEST_EXPECT_SNUM_GT(uk_intctlr_irq_get_priority(60), + uk_intctlr_irq_get_priority(70)); +#elif defined(CONFIG_PRIORITY_MAX_32) + uk_intctlr_irq_set_priority(60, 30); + uk_intctlr_irq_set_priority(70, 31); + isb(); + UK_TEST_EXPECT_SNUM_GT(uk_intctlr_irq_get_priority(60), + uk_intctlr_irq_get_priority(70)); +#elif defined(CONFIG_PRIORITY_MAX_64) + uk_intctlr_irq_set_priority(60, 62); + uk_intctlr_irq_set_priority(70, 63); + isb(); + UK_TEST_EXPECT_SNUM_GT(uk_intctlr_irq_get_priority(60), + uk_intctlr_irq_get_priority(70)); +#elif defined(CONFIG_PRIORITY_MAX_128) + uk_intctlr_irq_set_priority(60, 126); + uk_intctlr_irq_set_priority(70, 127); + isb(); + UK_TEST_EXPECT_SNUM_GT(uk_intctlr_irq_get_priority(60), + uk_intctlr_irq_get_priority(70)); +#endif + + /*恢复现场*/ + uk_intctlr_irq_set_priority(60, irq60_original_prio_level); + uk_intctlr_irq_set_priority(70, irq70_original_prio_level); } -/* 测试handle接口 */ -UK_TESTCASE(ukintctlr, call_handler) +/* 测试sgi生成接口uk_intctlr_sgi_op + * 场景: 向当前cpu发送/向除自己外的所有cpu发送 + */ +UK_TESTCASE_DESC(ukintctlr, send_sgi_to_bsp_or_all, + "Send a SGI to current cpu/all cpu excluding self") { - struct __regs *regs = NULL; - - /* 1.备份原有uk_intctlr,初始化测试环境 */ - test_intctlr_init(); - - /* 2.通过统一接口调用handle,并校验调用结果 */ - uk_intctlr_handle(regs); - UK_TEST_EXPECT_SNUM_EQ(ret, TEST_HANDLE_SUCCESS); + int r; - /* 3.恢复环境 */ - uk_intctlr_register(ori_intctlr); -} + uint64_t current_cpu = SYSREG_READ64(MPIDR_EL1); + uint64_t aff = ((current_cpu & MPIDR_AFF3_MASK) >> 8) | + (current_cpu & MPIDR_AFF2_MASK) | + (current_cpu & MPIDR_AFF1_MASK) | + (current_cpu & MPIDR_AFF0_MASK); -/* 测试sgi_op接口 */ -UK_TESTCASE(ukintctlr, call_sgi_op) -{ - uint8_t sgintid = 0; - uint32_t cpuid = 0; + /* 将sgi亲和到当前cpu */ + r = uk_intctlr_sgi_op(5, 1, (uint32_t)aff); - /* 1.备份原有uk_intctlr,初始化测试环境 */ - test_intctlr_init(); + UK_TEST_EXPECT_ZERO(r); - /* 2.通过统一接口调用sgi_op,并校验调用结果 */ - (void)uk_intctlr_sgi_op(sgintid, cpuid); - UK_TEST_EXPECT_SNUM_EQ(ret, TEST_SGI_OP_SUCCESS); + /* 将sgi亲和到除自己外的所有cpu */ + r = uk_intctlr_sgi_op(5, 0); - /* 3.恢复环境 */ - uk_intctlr_register(ori_intctlr); + UK_TEST_EXPECT_ZERO(r); } -/* 测试percpu_init接口 */ -UK_TESTCASE(ukintctlr, call_percpu_init) +/* 测试sgi生成接口uk_intctlr_sgi_op + * 场景: cpulist中含有range_selector不同/亲和属性不同/id > 15的cpu + */ +UK_TESTCASE_DESC(ukintctlr, affx_and_rs_check, +"Send a SGI to cpu list with 4 cases: different rs/affx, cpuid>15, normal") { int r; + /* 检测接口是否会检查出targetlist AFFx属性及 + * range selector 不同并报错 + */ - /* 1.备份原有uk_intctlr,初始化测试环境 */ - test_intctlr_init(); + /* 检查是否支持发送至idx 16 及以上的cpu */ + r = uk_intctlr_sgi_op(4, 4, 19, 1, 2, 0); + UK_TEST_EXPECT_SNUM_EQ(r, -1); - /* 2.通过统一接口调用percpu_init,并校验调用结果 */ - r = uk_intctlr_percpu_init(); - UK_TEST_EXPECT_SNUM_EQ(ret, TEST_PERCPU_INIT_SUCCESS); - UK_TEST_EXPECT_ZERO(r); + /* 不同的range selector */ + r = uk_intctlr_sgi_op(4, 4, 0, 1, 2, 19); + UK_TEST_EXPECT_SNUM_EQ(r, -1); + + /* 不同的affx */ + r = uk_intctlr_sgi_op(4, 4, 0, 1, 2, 132000); + UK_TEST_EXPECT_SNUM_EQ(r, -1); - /* 3.恢复环境 */ - uk_intctlr_register(ori_intctlr); + /* affx/rs 相同*/ + r = uk_intctlr_sgi_op(4, 3, 0, 1, 2); + UK_TEST_EXPECT_ZERO(r); } +#endif + uk_testsuite_register(ukintctlr, NULL); diff --git a/lib/ukintctlr/ukintctlr.c b/lib/ukintctlr/ukintctlr.c index 4e2a826b20026f7f6814f40edc6f6dbf7214b52b..66352c4b86e5b3e3d497b2684c1994f4f89eab1f 100644 --- a/lib/ukintctlr/ukintctlr.c +++ b/lib/ukintctlr/ukintctlr.c @@ -233,12 +233,12 @@ void uk_intctlr_irq_unmask(unsigned int irq) return uk_intctlr->ops->unmask_irq(irq); } -int uk_intctlr_irq_configure(struct uk_intctlr_irq *irq) +int uk_intctlr_irq_set_trigger(struct uk_intctlr_irq *irq) { - UK_ASSERT(uk_intctlr && uk_intctlr->ops->configure_irq); + UK_ASSERT(uk_intctlr && uk_intctlr->ops->irq_set_trigger); UK_ASSERT(irq); - return uk_intctlr->ops->configure_irq(irq); + return uk_intctlr->ops->irq_set_trigger(irq); } int uk_intctlr_irq_fdt_xlat(const void *fdt, int nodeoffset, __u32 index, @@ -319,13 +319,16 @@ void uk_intctlr_handle(struct __regs *regs) return uk_intctlr->ops->handle(regs); } -int uk_intctlr_sgi_op(uint8_t sgintid, uint32_t cpuid) +int uk_intctlr_sgi_op(uint8_t sgintid, uint32_t target_count, ...) { - UK_ASSERT(uk_intctlr->ops->sgi_op); - - uk_intctlr->ops->sgi_op(sgintid, cpuid); - - return 0; + UK_ASSERT(uk_intctlr && uk_intctlr->ops->sgi_op); + va_list cpuid_args; + int ret; + + va_start(cpuid_args, target_count); + ret = uk_intctlr->ops->sgi_op(sgintid, target_count, cpuid_args); + va_end(cpuid_args); + return ret; } int uk_intctlr_percpu_init(void) @@ -335,3 +338,40 @@ int uk_intctlr_percpu_init(void) /* initialize interrupt controller of specified cpu core */ return uk_intctlr->ops->percpu_init(); } + +void uk_intctlr_irq_set_priority(unsigned int irq, uint8_t priority) +{ + UK_ASSERT(uk_intctlr && uk_intctlr->ops->irq_set_priority); + + return uk_intctlr->ops->irq_set_priority(irq, priority); +} + +void uk_intctlr_irq_set_affinity(unsigned int irq, uint32_t cpuid) +{ + UK_ASSERT(uk_intctlr && uk_intctlr->ops->irq_set_affinity); + + return uk_intctlr->ops->irq_set_affinity(irq, cpuid); +} + +#ifdef CONFIG_LIBUKINTCTLR_TEST +uint8_t uk_intctlr_irq_get_priority(unsigned int irq) +{ + UK_ASSERT(uk_intctlr && uk_intctlr->ops->irq_get_priority); + + return uk_intctlr->ops->irq_get_priority(irq); +} + +uint32_t uk_intctlr_spi_get_affinity(unsigned int irq) +{ + UK_ASSERT(uk_intctlr && uk_intctlr->ops->spi_get_affinity); + + return uk_intctlr->ops->spi_get_affinity(irq); +} + +void uk_intctlr_simulate_spi(unsigned int irq) +{ + UK_ASSERT(uk_intctlr && uk_intctlr->ops->simulate_spi); + + return uk_intctlr->ops->simulate_spi(irq); +} +#endif diff --git a/plat/Config.uk b/plat/Config.uk index 1ef6e042cfb946afb41137eddc324e15a454ee81..af2692194c63282afc73e560127cdd1c9598a6f2 100644 --- a/plat/Config.uk +++ b/plat/Config.uk @@ -86,6 +86,13 @@ config HAVE_PAGING default y if PAGING default n +config VIRTUALIZE_PLAT + bool + default n + depends on PLAT_KVM + help + The virtualization platform is currently being used + config HAVE_PAGING_DIRECTMAP bool default y if PAGING && ARCH_X86_64 diff --git a/plat/common/arm/lcpu.c b/plat/common/arm/lcpu.c index 927989f47b9991ec82afa5493ed8146df9bdce51..8e14691c7b208a550ea6403d57d504bd072add19 100644 --- a/plat/common/arm/lcpu.c +++ b/plat/common/arm/lcpu.c @@ -341,17 +341,15 @@ int lcpu_arch_run(struct lcpu *lcpu, const struct ukplat_lcpu_func *fn, if (unlikely(rc)) return rc; - uk_intctlr_sgi_op(*lcpu_run_irqv, lcpu->id); + return uk_intctlr_sgi_op(*lcpu_run_irqv, 1, lcpu->id); - return 0; } int lcpu_arch_wakeup(struct lcpu *lcpu) { UK_ASSERT(lcpu->id != lcpu_arch_id()); - uk_intctlr_sgi_op(*lcpu_wakeup_irqv, lcpu->id); + return uk_intctlr_sgi_op(*lcpu_wakeup_irqv, 1, lcpu->id); - return 0; } #endif /* CONFIG_HAVE_SMP */ diff --git a/plat/common/arm/time.c b/plat/common/arm/time.c index 8d89036a098581217ee5e8246a86669a7def487a..402fca69ac29810a4b71282581f531cc80f90518 100644 --- a/plat/common/arm/time.c +++ b/plat/common/arm/time.c @@ -131,7 +131,7 @@ void ukplat_time_init(void) if (unlikely(rc < 0)) UK_CRASH("Could not get IRQ from dtb (%d)\n", rc); - uk_intctlr_irq_configure(&irq); + uk_intctlr_irq_set_trigger(&irq); rc = uk_intctlr_irq_register(irq.id, generic_timer_irq_handler, NULL); if (unlikely(rc < 0)) diff --git a/plat/drivers/rtc/pl031.c b/plat/drivers/rtc/pl031.c index 805085df5da4893d0a668f0afd14ec026e4927d9..12a1b22344030504273fe46cb6300bfe79abe4ff 100644 --- a/plat/drivers/rtc/pl031.c +++ b/plat/drivers/rtc/pl031.c @@ -181,7 +181,7 @@ int pl031_init_rtc(void *dtb) if (unlikely(rc)) return rc; - uk_intctlr_irq_configure(&irq); + uk_intctlr_irq_set_trigger(&irq); pl031_irq = irq.id; diff --git a/plat/kvm/Config.uk b/plat/kvm/Config.uk index c628487d7de98f9d41c7d1d5cfaa256be0bb6d72..ad3d97663df8211294c9994f4446bcf18b44d403 100644 --- a/plat/kvm/Config.uk +++ b/plat/kvm/Config.uk @@ -5,6 +5,7 @@ menuconfig PLAT_KVM select LIBUKDEBUG select LIBUKALLOC select LIBUKTIMECONV + select VIRTUALIZE_PLAT select LIBNOLIBC if !HAVE_LIBC select HAVE_FDT if ARCH_ARM_64 imply LIBFDT if ARCH_ARM_64