arm_vgic 0.6.1

ARM Virtual Generic Interrupt Controller (VGIC) implementation.
Documentation
use super::*;

struct NoopWake;

impl GicV3VcpuWake for NoopWake {
    fn wake(&self) -> VgicResult {
        Ok(())
    }
}

#[test]
fn software_level_delivery_preserves_eoi_maintenance_in_list_register() {
    let mut redistributor = RedistributorState::new(
        GicVcpuId::new(0),
        GicAffinity::new(0, 0, 0, 0),
        4,
        0,
        Arc::new(NoopWake),
    )
    .unwrap();
    let timer = IntId::new(27).unwrap();
    let software_edge = IntId::new(1).unwrap();

    redistributor.queue(timer, TriggerMode::Level);
    redistributor.queue(software_edge, TriggerMode::Edge);
    redistributor
        .refill_list_registers(|_| unreachable!("private interrupts have local priorities"))
        .unwrap();

    let timer_entry = redistributor
        .cpu_interface()
        .list_registers()
        .iter()
        .flatten()
        .find(|entry| entry.intid() == timer)
        .unwrap();
    let edge_entry = redistributor
        .cpu_interface()
        .list_registers()
        .iter()
        .flatten()
        .find(|entry| entry.intid() == software_edge)
        .unwrap();

    assert!(timer_entry.maintenance_on_eoi());
    assert!(!edge_entry.maintenance_on_eoi());
}

#[test]
fn physical_delivery_uses_only_preallocated_queue_slots() {
    let mut redistributor = RedistributorState::new(
        GicVcpuId::new(0),
        GicAffinity::new(0, 0, 0, 0),
        4,
        4,
        Arc::new(NoopWake),
    )
    .unwrap();
    let capacity = redistributor.queued_deliveries.capacity();

    for raw in 0..32 {
        let trigger = if raw < 16 {
            TriggerMode::Edge
        } else {
            TriggerMode::Level
        };
        redistributor.queue(IntId::new(raw).unwrap(), trigger);
    }
    for raw in 32..36 {
        redistributor
            .queue_physical(IntId::new(raw).unwrap(), PhysicalIrqId::new(u64::from(raw)))
            .unwrap();
    }

    assert_eq!(redistributor.queued_deliveries.capacity(), capacity);
    assert!(matches!(
        redistributor.queue_physical(IntId::new(36).unwrap(), PhysicalIrqId::new(36),),
        Err(VgicError::DeliveryQueueFull { .. })
    ));
    assert_eq!(redistributor.queued_deliveries.capacity(), capacity);
}