Skip to content
  • Heyi Guo's avatar
    irqchip/gic-v3-its: Fix command queue pointer comparison bug · a050fa54
    Heyi Guo authored
    
    
    When we run several VMs with PCI passthrough and GICv4 enabled, not
    pinning vCPUs, we will occasionally see below warnings in dmesg:
    
    ITS queue timeout (65440 65504 480)
    ITS cmd its_build_vmovp_cmd failed
    
    The reason for the above issue is that in BUILD_SINGLE_CMD_FUNC:
    1. Post the write command.
    2. Release the lock.
    3. Start to read GITS_CREADR to get the reader pointer.
    4. Compare the reader pointer to the target pointer.
    5. If reader pointer does not reach the target, sleep 1us and continue
    to try.
    
    If we have several processors running the above concurrently, other
    CPUs will post write commands while the 1st CPU is waiting the
    completion. So we may have below issue:
    
    phase 1:
    ---rd_idx-----from_idx-----to_idx--0---------
    
    wait 1us:
    
    phase 2:
    --------------from_idx-----to_idx--0-rd_idx--
    
    That is the rd_idx may fly ahead of to_idx, and if in case to_idx is
    near the wrap point, rd_idx will wrap around. So the below condition
    will not be met even after 1s:
    
    if (from_idx < to_idx && rd_idx >= to_idx)
    
    There is another theoretical issue. For a slow and busy ITS, the
    initial rd_idx may fall behind from_idx a lot, just as below:
    
    ---rd_idx---0--from_idx-----to_idx-----------
    
    This will cause the wait function exit too early.
    
    Actually, it does not make much sense to use from_idx to judge if
    to_idx is wrapped, but we need a initial rd_idx when lock is still
    acquired, and it can be used to judge whether to_idx is wrapped and
    the current rd_idx is wrapped.
    
    We switch to a method of calculating the delta of two adjacent reads
    and accumulating it to get the sum, so that we can get the real rd_idx
    from the wrapped value even when the queue is almost full.
    
    Cc: Thomas Gleixner <tglx@linutronix.de>
    Cc: Jason Cooper <jason@lakedaemon.net>
    Signed-off-by: default avatarHeyi Guo <guoheyi@huawei.com>
    Signed-off-by: default avatarMarc Zyngier <marc.zyngier@arm.com>
    a050fa54