在GIC on ARM中屏蔽/解除屏蔽中断时是否需要锁

在GIC on ARM中屏蔽/解除屏蔽中断时是否需要锁,arm,hardware,interrupt,Arm,Hardware,Interrupt,这个问题是to回答的后续问题。如图所示 对于分发寄存器,通常全局中断具有读/写启用/禁用。每个CPU的寄存器在分发服务器中可能是只读的,并指示中断存在。每个CPU的另一组寄存器是启用/禁用每个CPU中断的正常机制。软件在访问分发服务器时应具有互锁信号量,因为它对系统是全局的 现在,体系结构规范版本2指出,GICD_ISENABLERn取消屏蔽中断和GICD_ICENABLERn屏蔽中断仅在写入1时改变状态,而忽略0的写入。因此,这些寄存器可以在不进行读取的情况下写入,例如在Linux实现中 /*

这个问题是to回答的后续问题。如图所示

对于分发寄存器,通常全局中断具有读/写启用/禁用。每个CPU的寄存器在分发服务器中可能是只读的,并指示中断存在。每个CPU的另一组寄存器是启用/禁用每个CPU中断的正常机制。软件在访问分发服务器时应具有互锁信号量,因为它对系统是全局的

现在,体系结构规范版本2指出,GICD_ISENABLERn取消屏蔽中断和GICD_ICENABLERn屏蔽中断仅在写入1时改变状态,而忽略0的写入。因此,这些寄存器可以在不进行读取的情况下写入,例如在Linux实现中

/*
 * Routines to acknowledge, disable and enable interrupts
 */
static void gic_mask_irq(struct irq_data *d)
{
    u32 mask = 1 << (gic_irq(d) % 32);

    raw_spin_lock(&irq_controller_lock);
    gic_writel_relaxed(mask, gic_dist_base(d) +
                GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4);
    if (gic_arch_extn.irq_mask)
        gic_arch_extn.irq_mask(d);
    raw_spin_unlock(&irq_controller_lock);
}

static void gic_unmask_irq(struct irq_data *d)
{
    u32 mask = 1 << (gic_irq(d) % 32);

    raw_spin_lock(&irq_controller_lock);
    if (gic_arch_extn.irq_unmask)
        gic_arch_extn.irq_unmask(d);
    gic_writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_SET +
                            (gic_irq(d) / 32) * 4);
    raw_spin_unlock(&irq_controller_lock);
}
此代码确实包含分发服务器配置寄存器的锁,但我不确定是否真的需要这些锁,或者如果删除这些锁,会发生什么情况

如果两个内核试图同时屏蔽同一寄存器配置的不同中断,这将导致两个1写入同一寄存器的不同位置。但是,互连会导致两个写操作都通过,因此这会导致两个中断按预期被屏蔽

类似地,如果两个内核都试图屏蔽相同的中断,那么即使其中一个写丢失也无关紧要

我能看到的唯一一种情况是,如果一个内核试图屏蔽一个中断,而另一个内核同时试图取消屏蔽同一个中断,这将意味着麻烦。但在这种情况下,结果将相当不可预测,即使在没有锁的情况下使用锁,分发服务器也必须以某种方式做出决定,在锁的情况下,行为取决于谁首先获得锁。因此,锁同样没有帮助


或者我可能弄错了,从不同内核到同一个字的两次写操作都必须通过,内存优化可能会导致其中一次写操作丢失。这必须在互连中进行,因为不涉及实际内存。这在哪里指定?

自旋锁不是为了保护启用/禁用位。带有设置/清除寄存器的GIC硬件是无竞争的。但是,我认为gic_arch_extn可能需要它们。@artlessnoise:如果我理解正确,它们是为了保持硬件状态和gic_arch_extn.irq_maskd等跟踪的数据一致?那就有道理了。谢谢你的帮助。