static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val, bool force)
{
void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3);
unsigned int cpu, shift = (gic_irq(d) % 4) * 8;
u32 val, mask, bit;
if (!force)
cpu = cpumask_any_and(mask_val, cpu_online_mask);---随机选取一个online的cpu
else
cpu = cpumask_first(mask_val); --------选取mask中的第一个cpu,不管是否online
raw_spin_lock(&irq_controller_lock);
mask = 0xff << shift;
bit = gic_cpu_map[cpu] << shift;-------将CPU的逻辑ID转换成要设定的cpu mask
val = readl_relaxed(reg) & ~mask;
writel_relaxed(val | bit, reg);
raw_spin_unlock(&irq_controller_lock);
return IRQ_SET_MASK_OK;
}
GIC Distributor中有一个寄存器叫做Interrupt Processor Targets Registers,这个寄存器用来设定制定的中断送到哪个process去。由于GIC最大支持8个process,因此每个hw interrupt ID需要8个bit来表示送达的process。每一个Interrupt Processor Targets Registers由32个bit组成,因此每个Interrupt Processor Targets Registers可以表示4个HW interrupt ID的affinity,因此上面的代码中的shift就是计算该HW interrupt ID在寄存器中的偏移。
(7)gic_set_wake
这个接口用来设定唤醒CPU的interrupt source。对于GIC,代码如下:
static int gic_set_wake(struct irq_data *d, unsigned int on)
{
int ret = -ENXIO;
if (gic_arch_extn.irq_set_wake)
ret = gic_arch_extn.irq_set_wake(d, on);
return ret;
}
设定唤醒的interrupt和具体的厂商相关,这里不再赘述。
4、BSP(bootstrap processor)之外,其他CPU的callback函数
对于multi processor系统,不可能初始化代码在所有的processor上都执行一遍,实际上,系统的硬件会选取一个processor作为引导处理器,我们称之BSP。这个processor会首先执行,其他的CPU都是处于reset状态,等到BSP初始化完成之后,release所有的non-BSP,这时候,系统中的各种外设硬件条件和软件条件(例如per CPU变量)都准备好了,各个non-BSP执行自己CPU specific的初始化就OK了。
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/shumachanpin/article-76887-19.html
不喜欢舒淇