use std::result;
use devices::IrqChipX86_64;
use remain::sorted;
use thiserror::Error;
#[sorted]
#[derive(Error, Debug)]
pub enum Error {
#[error("GetLapic ioctl failed: {0}")]
GetLapic(base::Error),
#[error("SetLapic ioctl failed: {0}")]
SetLapic(base::Error),
}
pub type Result<T> = result::Result<T, Error>;
const APIC_LVT0_OFFSET: usize = 0x350;
const APIC_LVT1_OFFSET: usize = 0x360;
const APIC_LVT0_REGISTER: usize = lapic_byte_offset_to_register(APIC_LVT0_OFFSET);
const APIC_LVT1_REGISTER: usize = lapic_byte_offset_to_register(APIC_LVT1_OFFSET);
const APIC_MODE_NMI: u32 = 0x4;
const APIC_MODE_EXTINT: u32 = 0x7;
const fn lapic_byte_offset_to_register(offset_bytes: usize) -> usize {
offset_bytes / 16
}
fn set_apic_delivery_mode(reg: u32, mode: u32) -> u32 {
((reg) & !0x700) | ((mode) << 8)
}
pub fn set_lint(vcpu_id: usize, irqchip: &mut dyn IrqChipX86_64) -> Result<()> {
let mut lapic = irqchip.get_lapic_state(vcpu_id).map_err(Error::GetLapic)?;
for (reg, mode) in &[
(APIC_LVT0_REGISTER, APIC_MODE_EXTINT),
(APIC_LVT1_REGISTER, APIC_MODE_NMI),
] {
lapic.regs[*reg] = set_apic_delivery_mode(lapic.regs[*reg], *mode);
}
irqchip
.set_lapic_state(vcpu_id, &lapic)
.map_err(Error::SetLapic)
}