#![cfg(target_arch = "x86_64")]
use devices::IrqChipX86_64;
use devices::Routes;
use hypervisor::IrqRoute;
use hypervisor::IrqSource;
use hypervisor::IrqSourceChip;
use hypervisor::PicSelect;
#[allow(unused)]
pub fn test_get_pic(mut chip: impl IrqChipX86_64) {
let state = chip
.get_pic_state(PicSelect::Primary)
.expect("could not get pic state");
assert_eq!(state.irr, 0);
chip.service_irq(0, true).expect("could not service irq");
let state = chip
.get_pic_state(PicSelect::Primary)
.expect("could not get pic state");
assert_eq!(state.irr, 1);
}
pub fn test_set_pic(mut chip: impl IrqChipX86_64) {
let mut state = chip
.get_pic_state(PicSelect::Primary)
.expect("could not get pic state");
state.irr = 3;
chip.set_pic_state(PicSelect::Primary, &state)
.expect("could not set the pic state");
let state = chip
.get_pic_state(PicSelect::Primary)
.expect("could not get pic state");
assert_eq!(state.irr, 3);
}
pub fn test_get_ioapic(mut chip: impl IrqChipX86_64) {
let state = chip.get_ioapic_state().expect("could not get ioapic state");
assert_eq!(state.current_interrupt_level_bitmap, 0);
for i in 0..24 {
assert_eq!(state.redirect_table[i].get(0, 64), 1 << 16);
}
chip.service_irq(1, true).expect("could not set irq line");
let state = chip.get_ioapic_state().expect("could not get ioapic state");
assert_eq!(state.current_interrupt_level_bitmap, 2);
}
pub fn test_set_ioapic(mut chip: impl IrqChipX86_64) {
let mut state = chip.get_ioapic_state().expect("could not get ioapic state");
state.redirect_table[2].set_vector(15);
state.current_interrupt_level_bitmap = 4;
chip.set_ioapic_state(&state)
.expect("could not set the ioapic state");
let state = chip.get_ioapic_state().expect("could not get ioapic state");
assert_eq!(state.redirect_table[2].get_vector(), 15);
assert_eq!(state.current_interrupt_level_bitmap, 4);
}
pub fn test_get_pit(chip: impl IrqChipX86_64) {
let state = chip.get_pit().expect("failed to get pit state");
assert_eq!(state.flags, 0);
for i in 0..3 {
assert_eq!(state.channels[i].count, 0x10000);
}
}
pub fn test_set_pit(mut chip: impl IrqChipX86_64) {
let mut state = chip.get_pit().expect("failed to get pit state");
state.channels[0].count = 500;
state.channels[0].mode = 1;
chip.set_pit(&state).expect("failed to set pit state");
let state = chip.get_pit().expect("failed to get pit state");
assert_eq!(state.channels[0].count, 500);
assert_eq!(state.channels[0].mode, 1);
}
#[allow(unused)]
pub fn test_get_lapic(chip: impl IrqChipX86_64) {
let state = chip.get_lapic_state(0).expect("failed to get lapic state");
assert_eq!(state.regs[0xe], 0xffffffff);
assert_eq!(state.regs[0xf], 0xff);
}
#[allow(unused)]
pub fn test_set_lapic(mut chip: impl IrqChipX86_64) {
let mut state = chip.get_lapic_state(0).expect("failed to get lapic state");
assert_eq!(state.regs[8], 0);
state.regs[8] = 1 << 8;
chip.set_lapic_state(0, &state)
.expect("failed to set lapic state");
let state = chip.get_lapic_state(0).expect("failed to get lapic state");
assert_eq!(state.regs[8], 1 << 8);
}
fn check_pic_interrupts(chip: &impl IrqChipX86_64, select: PicSelect, value: u8) {
let state = chip
.get_pic_state(select)
.expect("could not get ioapic state");
assert_eq!(state.irr, value);
}
fn check_ioapic_interrupts(chip: &impl IrqChipX86_64, value: u32) {
let state = chip.get_ioapic_state().expect("could not get ioapic state");
assert_eq!(state.current_interrupt_level_bitmap, value);
}
pub fn test_route_irq(mut chip: impl IrqChipX86_64) {
chip.set_irq_routes(&[])
.expect("failed to set empty irq routes");
chip.service_irq(1, true).expect("could not set irq line");
check_pic_interrupts(&chip, PicSelect::Primary, 0);
check_ioapic_interrupts(&chip, 0);
chip.route_irq(IrqRoute {
gsi: 1,
source: IrqSource::Irqchip {
chip: IrqSourceChip::Ioapic,
pin: 3,
},
})
.expect("failed to assert irq route");
chip.service_irq(1, true).expect("could not set irq line");
check_pic_interrupts(&chip, PicSelect::Primary, 0);
check_ioapic_interrupts(&chip, 1 << 3);
chip.service_irq(1, false).expect("could not set irq line");
check_pic_interrupts(&chip, PicSelect::Primary, 0);
check_ioapic_interrupts(&chip, 0);
chip.route_irq(IrqRoute {
gsi: 2,
source: IrqSource::Irqchip {
chip: IrqSourceChip::PicPrimary,
pin: 6,
},
})
.expect("failed to route irq");
chip.service_irq(1, true).expect("could not set irq line");
check_pic_interrupts(&chip, PicSelect::Primary, 0);
check_ioapic_interrupts(&chip, 1 << 3);
chip.service_irq(2, true).expect("could not set irq line");
check_pic_interrupts(&chip, PicSelect::Primary, 1 << 6);
check_ioapic_interrupts(&chip, 1 << 3);
}
#[test]
fn add_routes() {
let ioapic_pins = hypervisor::NUM_IOAPIC_PINS;
let mut r = Routes::new();
r.replace_all(&Routes::default_pic_ioapic_routes(ioapic_pins))
.unwrap();
assert_eq!(r[0].len(), 2);
assert_eq!(r[ioapic_pins - 1].len(), 1);
r.add(IrqRoute {
gsi: ioapic_pins as u32 - 1,
source: IrqSource::Irqchip {
chip: IrqSourceChip::Ioapic,
pin: 3,
},
})
.unwrap();
assert_eq!(r[ioapic_pins - 1].len(), 1);
r.add(IrqRoute {
gsi: ioapic_pins as u32 - 1,
source: IrqSource::Irqchip {
chip: IrqSourceChip::PicPrimary,
pin: 3,
},
})
.unwrap();
assert_eq!(r[ioapic_pins - 1].len(), 2);
assert!(r
.add(IrqRoute {
gsi: ioapic_pins as u32 - 1,
source: IrqSource::Msi {
address: 0,
data: 0,
},
})
.is_err(),);
assert_eq!(r[ioapic_pins - 1].len(), 2);
assert_eq!(r[ioapic_pins].len(), 0);
r.add(IrqRoute {
gsi: ioapic_pins as u32,
source: IrqSource::Msi {
address: 0,
data: 0,
},
})
.unwrap();
assert_eq!(r[ioapic_pins].len(), 1);
assert!(r
.add(IrqRoute {
gsi: ioapic_pins as u32,
source: IrqSource::Irqchip {
chip: IrqSourceChip::Ioapic,
pin: 3
},
})
.is_err(),);
assert_eq!(r[ioapic_pins].len(), 1);
assert_eq!(r[500].len(), 0);
}