ATF:Gicv源码解读系列-gicv2_secure_spis_configure_props

2、gicv2_secure_spis_configure_props

前面的函数一是对于gicv2的spi中断的默认配置,这里是设置对于spi g0组的属性配置。

/*******************************************************************************

  • Helper function to configure properties of secure G0 SPIs.
    ******************************************************************************/
    void gicv2_secure_spis_configure_props(uintptr_t gicd_base,
    const interrupt_prop_t *interrupt_props,
    unsigned int interrupt_props_num)
    {
    unsigned int i;
    const interrupt_prop_t *prop_desc;

     typedef struct gicv2_driver_data {
     	uintptr_t gicd_base;
     	uintptr_t gicc_base;
     	unsigned int *target_masks;
     	unsigned int target_masks_num;
     	const interrupt_prop_t *interrupt_props;
     	unsigned int interrupt_props_num;
     } gicv2_driver_data_t;
    
     *此结构描述了GICv2 IP的一些实现定义属性。平台端口使用它来指定这些属性,以便初始化GICv2驱动程序。属性描述如下。
     *
     *“gicd_base”字段包含分发器接口程序员视图的基地址。
     *
     *“gicc_base”字段包含CPU接口程序员视图的基地址。
     *
     *“target_mask”是指向包含“target_masks_num”元素的数组的指针。GIC驱动程序将使用每个PE目标掩码填充阵列,以便在确定中断目标时使用。
     *
     *“interrupt_props”字段是指向枚举安全中断及其属性的数组的指针。如果此字段不为NULL,将忽略“g0_trupt_array”和“g1s_interrupt_aArray”字段。
     *
     *“interrupt_props_num”字段包含“interrupt _props”数组中的条目数。如果此字段为非零,则忽略“g0_crupt_num”。
     		列出GIC驱动程序的中断属性。所有中断目标EL3
     	   /* List interrupt properties for GIC driver. All interrupts target EL3 */
     	   const interrupt_prop_t plat_interrupts[] = {
     	        /* Dispatcher 1 owns interrupts d1_0 and d1_1, so assigns priority DISP1_PRIO */
     	        INTR_PROP_DESC(d1_0, DISP1_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL),
     	        INTR_PROP_DESC(d1_1, DISP1_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL),
     	
     	        /* Dispatcher 2 owns interrupts d2_0 and d2_1, so assigns priority DISP2_PRIO */
     	        INTR_PROP_DESC(d2_0, DISP2_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL),
     	        INTR_PROP_DESC(d2_1, DISP2_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL),
     	
     	        /* Dispatcher 3 owns interrupts d3_0 and d3_1, so assigns priority DISP3_PRIO */
     	        INTR_PROP_DESC(d3_0, DISP3_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL),
     	        INTR_PROP_DESC(d3_1, DISP3_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL),
     	   };
     		
     		typedef struct interrupt_prop {
     			unsigned int intr_num:10;
     			unsigned int intr_pri:8;
     			unsigned int intr_grp:2;
     			unsigned int intr_cfg:2;
     		} interrupt_prop_t;
     		这个数组是中断的属性,这个我们之前说过。通过这个INTR_PROP_DESC声明的。
    

/* Make sure there’s a valid property array */
if (interrupt_props_num != 0U)
assert(interrupt_props != NULL);

	interrupt_props_num
	*“interrupt_props_num”字段包含“interrupt _props”数组中的条目数。如果此字段为非零,则忽略“g0_crupt_num”。
	interrupt_props这个是一个中断的属性,interrupt_props_num就是表明中断的数量。

for (i = 0; i < interrupt_props_num; i++) {
prop_desc = &interrupt_props[i];

if (prop_desc->intr_num < MIN_SPI_ID)
continue;

						确定这个中断的中断号符合要求			

1-根据中断group分组将该中断设置为secure中断

/* Configure this interrupt as a secure interrupt */
assert(prop_desc->intr_grp == GICV2_INTR_GROUP0);
gicd_clr_igroupr(gicd_base, prop_desc->intr_num);

	设置成安全中断前,得先看一下是不是属于group0
gicd_clr_igroupr:将该中断设置为secure中断。
				
void gicd_clr_igroupr(uintptr_t base, unsigned int id)
	{
		unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U);
		unsigned int reg_val = gicd_read_igroupr(base, id);
	
		gicd_write_igroupr(base, id, reg_val & ~(1U << bit_num));
	}			

2-设置该中断的优先级

/* Set the priority of this interrupt */
gicd_set_ipriorityr(gicd_base, prop_desc->intr_num,
prop_desc->intr_pri);

	设置该中断的优先级
		
	void gicd_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri)
	{
		uint8_t val = pri & GIC_PRI_MASK;
	
		mmio_write_8(base + GICD_IPRIORITYR + id, val);
	}

3-将该中断设置绑定到primary cpu

/* Target the secure interrupts to primary CPU */ (类似于gicd_write_irouter,路由亲和)
gicd_set_itargetsr(gicd_base, prop_desc->intr_num,
gicv2_get_cpuif_id(gicd_base));

	static inline void gicd_set_itargetsr(uintptr_t base, unsigned int id,
	unsigned int target)
	{
		uint8_t val = target & GIC_TARGET_CPU_MASK;
	
		mmio_write_8(base + GICD_ITARGETSR + id, val);
	}
	
	GICD_ITARGETSR 
	未启用关联路由时,保留中断的目标PE列表。也就是说,如果中断被断言并且具有足够的优先级,它将保存分发器转发中断的CPU接口列表
	未启用关联路由时使用这些寄存器。**当为中断的安全状态启用关联路由时,中断的目标PE由GICD_IROUTER<n>定义**,GICD_ITARGETSR<n>中的关联字节为RES0。在这种情况下,允许实现字节RAZ/WI。

	•这些寄存器可通过字节访问。
	•未实现中断对应的寄存器字段为RAZ/WI。
	•未实现CPU接口对应的字段位为RAZ/WI。
	•GICD_ITARGETSR0-GICD_ITARGETSR7为只读。每个字段返回一个仅对应于读取寄存器的PE的值。
	•它是由硬件静态配置的SPIs(如果有的话)定义的实现。此类SPI的字段是只读的,并返回一个值,**该值指示中断的PE目标。**
	•如果GICD_CTLR.DS==0,**除非GICD_NSACR<n>寄存器允许非安全软件控制组0和安全组1中断**,否则与组0或安全组1的中断对应的任何位只能通过安全访问访问,并且是非安全访问的RAZ/WI。
	在单连接PE实现中,所有中断都以一个PE为目标,这些寄存器是RAZ/WI。
	笔记
	实现必须确保在写入时挂起的中断使用旧值或新值,并且必须确保中断不会丢失或处理多次。变化的影响必须在有限的时间内可见。
	
	配置
	这些寄存器在GIC的所有配置中都可用。如果GIC实现支持两种安全状态,则这些寄存器是公共的。
	实现的GICD_ITARGETSR<n>寄存器的数量为8*(GICD_TYPER.ITLinesNumber+1)。寄存器从0开始编号。
	在多处理器实现中,GICD_ITARGETSR0到GICD_ITARGETSR7为每个连接的PE存储。这些寄存器为中断0-31提供PE目标字段。

4-设置该中断实际的触发方式

/* Set interrupt configuration */
gicd_set_icfgr(gicd_base, prop_desc->intr_num,
prop_desc->intr_cfg);

	设置该中断实际的触发方式
	void gicd_set_icfgr(uintptr_t base, unsigned int id, unsigned int cfg)
	{
		/* Interrupt configuration is a 2-bit field */
		unsigned int bit_num = id & ((1U << ICFGR_SHIFT) - 1U);
		unsigned int bit_shift = bit_num << 1;
		
		//读取电平触发方式
		uint32_t reg_val = gicd_read_icfgr(base, id);
	
		/* Clear the field, and insert required configuration */
		reg_val &= ~(GIC_CFG_MASK << bit_shift);
		reg_val |= ((cfg & GIC_CFG_MASK) << bit_shift);
		
		//写电平触发方式
		gicd_write_icfgr(base, id, reg_val);
	}

5-使能该中断

/* Enable this interrupt */

	允许将相应的中断转发到CPU接口。使能该中断

gicd_set_isenabler(gicd_base, prop_desc->intr_num);
}
}

猜你喜欢

转载自blog.csdn.net/weixin_45264425/article/details/129434429