1 // Copyright 2019 The Chromium OS Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 // 5 // Copyright © 2019 Intel Corporation 6 // 7 // SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause 8 // 9 // Implementation of an intel 82093AA Input/Output Advanced Programmable Interrupt Controller 10 // See https://pdos.csail.mit.edu/6.828/2016/readings/ia32/ioapic.pdf for a specification. 11 12 use super::interrupt_controller::{Error, InterruptController}; 13 use anyhow::anyhow; 14 use byteorder::{ByteOrder, LittleEndian}; 15 use std::result; 16 use std::sync::{Arc, Barrier}; 17 use versionize::{VersionMap, Versionize, VersionizeResult}; 18 use versionize_derive::Versionize; 19 use vm_device::interrupt::{ 20 InterruptIndex, InterruptManager, InterruptSourceConfig, InterruptSourceGroup, 21 MsiIrqGroupConfig, MsiIrqSourceConfig, 22 }; 23 use vm_device::BusDevice; 24 use vm_memory::GuestAddress; 25 use vm_migration::{ 26 Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped, 27 }; 28 use vmm_sys_util::eventfd::EventFd; 29 30 type Result<T> = result::Result<T, Error>; 31 32 // I/O REDIRECTION TABLE REGISTER 33 // 34 // There are 24 I/O Redirection Table entry registers. Each register is a 35 // dedicated entry for each interrupt input signal. Each register is 64 bits 36 // split between two 32 bits registers as follow: 37 // 38 // 63-56: Destination Field - R/W 39 // 55-17: Reserved 40 // 16: Interrupt Mask - R/W 41 // 15: Trigger Mode - R/W 42 // 14: Remote IRR - RO 43 // 13: Interrupt Input Pin Polarity - R/W 44 // 12: Delivery Status - RO 45 // 11: Destination Mode - R/W 46 // 10-8: Delivery Mode - R/W 47 // 7-0: Interrupt Vector - R/W 48 pub type RedirectionTableEntry = u64; 49 50 fn vector(entry: RedirectionTableEntry) -> u8 { 51 (entry & 0xffu64) as u8 52 } 53 fn delivery_mode(entry: RedirectionTableEntry) -> u8 { 54 ((entry >> 8) & 0x7u64) as u8 55 } 56 fn destination_mode(entry: RedirectionTableEntry) -> u8 { 57 ((entry >> 11) & 0x1u64) as u8 58 } 59 fn remote_irr(entry: RedirectionTableEntry) -> u8 { 60 ((entry >> 14) & 0x1u64) as u8 61 } 62 fn trigger_mode(entry: RedirectionTableEntry) -> u8 { 63 ((entry >> 15) & 0x1u64) as u8 64 } 65 fn interrupt_mask(entry: RedirectionTableEntry) -> u8 { 66 ((entry >> 16) & 0x1u64) as u8 67 } 68 fn destination_field(entry: RedirectionTableEntry) -> u8 { 69 // When the destination mode is physical, the destination field should only 70 // be defined through bits 56-59, as defined in the IOAPIC specification. 71 // But from the APIC specification, the APIC ID is always defined on 8 bits 72 // no matter which destination mode is selected. That's why we always 73 // retrieve the destination field based on bits 56-63. 74 ((entry >> 56) & 0xffu64) as u8 75 } 76 fn set_delivery_status(entry: &mut RedirectionTableEntry, val: u8) { 77 // Clear bit 12 78 *entry &= 0xffff_ffff_ffff_efff; 79 // Set it with the expected value 80 *entry |= u64::from(val & 0x1) << 12; 81 } 82 fn set_remote_irr(entry: &mut RedirectionTableEntry, val: u8) { 83 // Clear bit 14 84 *entry &= 0xffff_ffff_ffff_bfff; 85 // Set it with the expected value 86 *entry |= u64::from(val & 0x1) << 14; 87 } 88 89 pub const NUM_IOAPIC_PINS: usize = 24; 90 const IOAPIC_VERSION_ID: u32 = 0x0017_0011; 91 92 // Constants for IOAPIC direct register offset 93 const IOAPIC_REG_ID: u8 = 0x00; 94 const IOAPIC_REG_VERSION: u8 = 0x01; 95 const IOAPIC_REG_ARBITRATION_ID: u8 = 0x02; 96 97 // Register offsets 98 const IOREGSEL_OFF: u8 = 0x0; 99 const IOWIN_OFF: u8 = 0x10; 100 const IOWIN_SCALE: u8 = 0x2; 101 const REG_MAX_OFFSET: u8 = IOWIN_OFF + (NUM_IOAPIC_PINS as u8 * 2) - 1; 102 103 #[repr(u8)] 104 enum TriggerMode { 105 Edge = 0, 106 Level = 1, 107 } 108 109 #[repr(u8)] 110 enum DeliveryMode { 111 Fixed = 0b000, 112 Lowest = 0b001, 113 Smi = 0b010, // System management interrupt 114 RemoteRead = 0b011, // This is no longer supported by intel. 115 Nmi = 0b100, // Non maskable interrupt 116 Init = 0b101, 117 Startup = 0b110, 118 External = 0b111, 119 } 120 121 /// Given an offset that was read from/written to, return a tuple of the relevant IRQ and whether 122 /// the offset refers to the high bits of that register. 123 fn decode_irq_from_selector(selector: u8) -> (usize, bool) { 124 ( 125 ((selector - IOWIN_OFF) / IOWIN_SCALE) as usize, 126 selector & 1 != 0, 127 ) 128 } 129 130 pub struct Ioapic { 131 id: String, 132 id_reg: u32, 133 reg_sel: u32, 134 reg_entries: [RedirectionTableEntry; NUM_IOAPIC_PINS], 135 used_entries: [bool; NUM_IOAPIC_PINS], 136 apic_address: GuestAddress, 137 interrupt_source_group: Arc<dyn InterruptSourceGroup>, 138 } 139 140 #[derive(Versionize)] 141 pub struct IoapicState { 142 id_reg: u32, 143 reg_sel: u32, 144 reg_entries: [RedirectionTableEntry; NUM_IOAPIC_PINS], 145 used_entries: [bool; NUM_IOAPIC_PINS], 146 apic_address: u64, 147 } 148 impl VersionMapped for IoapicState {} 149 150 impl BusDevice for Ioapic { 151 fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) { 152 assert!(data.len() == 4); 153 154 debug!("IOAPIC_R @ offset 0x{:x}", offset); 155 156 let value: u32 = match offset as u8 { 157 IOREGSEL_OFF => self.reg_sel, 158 IOWIN_OFF => self.ioapic_read(), 159 _ => { 160 error!("IOAPIC: failed reading at offset {}", offset); 161 return; 162 } 163 }; 164 165 LittleEndian::write_u32(data, value); 166 } 167 168 fn write(&mut self, _base: u64, offset: u64, data: &[u8]) -> Option<Arc<Barrier>> { 169 assert!(data.len() == 4); 170 171 debug!("IOAPIC_W @ offset 0x{:x}", offset); 172 173 let value = LittleEndian::read_u32(data); 174 175 match offset as u8 { 176 IOREGSEL_OFF => self.reg_sel = value, 177 IOWIN_OFF => self.ioapic_write(value), 178 _ => { 179 error!("IOAPIC: failed writing at offset {}", offset); 180 } 181 } 182 None 183 } 184 } 185 186 impl Ioapic { 187 pub fn new( 188 id: String, 189 apic_address: GuestAddress, 190 interrupt_manager: Arc<dyn InterruptManager<GroupConfig = MsiIrqGroupConfig>>, 191 ) -> Result<Ioapic> { 192 let interrupt_source_group = interrupt_manager 193 .create_group(MsiIrqGroupConfig { 194 base: 0, 195 count: NUM_IOAPIC_PINS as InterruptIndex, 196 }) 197 .map_err(Error::CreateInterruptSourceGroup)?; 198 199 // The IOAPIC is created with entries already masked. The guest will be 200 // in charge of unmasking them if/when necessary. 201 Ok(Ioapic { 202 id, 203 id_reg: 0, 204 reg_sel: 0, 205 reg_entries: [0x10000; NUM_IOAPIC_PINS], 206 used_entries: [false; NUM_IOAPIC_PINS], 207 apic_address, 208 interrupt_source_group, 209 }) 210 } 211 212 fn ioapic_write(&mut self, val: u32) { 213 debug!("IOAPIC_W reg 0x{:x}, val 0x{:x}", self.reg_sel, val); 214 215 match self.reg_sel as u8 { 216 IOAPIC_REG_VERSION => { 217 if val == 0 { 218 // Windows writes zero here (see #1791) 219 } else { 220 error!( 221 "IOAPIC: invalid write to version register (0x{:x}): 0x{:x}", 222 self.reg_sel, val 223 ); 224 } 225 } 226 IOAPIC_REG_ID => self.id_reg = (val >> 24) & 0xf, 227 IOWIN_OFF..=REG_MAX_OFFSET => { 228 let (index, is_high_bits) = decode_irq_from_selector(self.reg_sel as u8); 229 if is_high_bits { 230 self.reg_entries[index] &= 0xffff_ffff; 231 self.reg_entries[index] |= u64::from(val) << 32; 232 } else { 233 // Ensure not to override read-only bits: 234 // - Delivery Status (bit 12) 235 // - Remote IRR (bit 14) 236 self.reg_entries[index] &= 0xffff_ffff_0000_5000; 237 self.reg_entries[index] |= u64::from(val) & 0xffff_afff; 238 } 239 // The entry must be updated through the interrupt source 240 // group. 241 if let Err(e) = self.update_entry(index) { 242 error!("Failed updating IOAPIC entry: {:?}", e); 243 } 244 // Store the information this IRQ is now being used. 245 self.used_entries[index] = true; 246 } 247 _ => error!( 248 "IOAPIC: invalid write to register offset 0x{:x}", 249 self.reg_sel 250 ), 251 } 252 } 253 254 fn ioapic_read(&self) -> u32 { 255 debug!("IOAPIC_R reg 0x{:x}", self.reg_sel); 256 257 match self.reg_sel as u8 { 258 IOAPIC_REG_VERSION => IOAPIC_VERSION_ID, 259 IOAPIC_REG_ID | IOAPIC_REG_ARBITRATION_ID => (self.id_reg & 0xf) << 24, 260 IOWIN_OFF..=REG_MAX_OFFSET => { 261 let (index, is_high_bits) = decode_irq_from_selector(self.reg_sel as u8); 262 if is_high_bits { 263 (self.reg_entries[index] >> 32) as u32 264 } else { 265 (self.reg_entries[index] & 0xffff_ffff) as u32 266 } 267 } 268 _ => { 269 error!( 270 "IOAPIC: invalid read from register offset 0x{:x}", 271 self.reg_sel 272 ); 273 0 274 } 275 } 276 } 277 278 fn state(&self) -> IoapicState { 279 IoapicState { 280 id_reg: self.id_reg, 281 reg_sel: self.reg_sel, 282 reg_entries: self.reg_entries, 283 used_entries: self.used_entries, 284 apic_address: self.apic_address.0, 285 } 286 } 287 288 fn set_state(&mut self, state: &IoapicState) -> Result<()> { 289 self.id_reg = state.id_reg; 290 self.reg_sel = state.reg_sel; 291 self.reg_entries = state.reg_entries; 292 self.used_entries = state.used_entries; 293 self.apic_address = GuestAddress(state.apic_address); 294 for (irq, entry) in self.used_entries.iter().enumerate() { 295 if *entry { 296 self.update_entry(irq)?; 297 } 298 } 299 300 Ok(()) 301 } 302 303 fn update_entry(&self, irq: usize) -> Result<()> { 304 let entry = self.reg_entries[irq]; 305 306 // Validate Destination Mode value, and retrieve Destination ID 307 let destination_mode = destination_mode(entry); 308 let destination_id = destination_field(entry); 309 310 // When this bit is set, the message is directed to the processor with 311 // the lowest interrupt priority among processors that can receive the 312 // interrupt. 313 let redirection_hint: u8 = 1; 314 315 // Generate MSI message address 316 let low_addr: u32 = self.apic_address.0 as u32 317 | u32::from(destination_id) << 12 318 | u32::from(redirection_hint) << 3 319 | u32::from(destination_mode) << 2; 320 321 // Validate Trigger Mode value 322 let trigger_mode = trigger_mode(entry); 323 match trigger_mode { 324 x if (x == TriggerMode::Edge as u8) || (x == TriggerMode::Level as u8) => {} 325 _ => return Err(Error::InvalidTriggerMode), 326 } 327 328 // Validate Delivery Mode value 329 let delivery_mode = delivery_mode(entry); 330 match delivery_mode { 331 x if (x == DeliveryMode::Fixed as u8) 332 || (x == DeliveryMode::Lowest as u8) 333 || (x == DeliveryMode::Smi as u8) 334 || (x == DeliveryMode::RemoteRead as u8) 335 || (x == DeliveryMode::Nmi as u8) 336 || (x == DeliveryMode::Init as u8) 337 || (x == DeliveryMode::Startup as u8) 338 || (x == DeliveryMode::External as u8) => {} 339 _ => return Err(Error::InvalidDeliveryMode), 340 } 341 342 // Generate MSI message data 343 let data: u32 = u32::from(trigger_mode) << 15 344 | u32::from(remote_irr(entry)) << 14 345 | u32::from(delivery_mode) << 8 346 | u32::from(vector(entry)); 347 348 let config = MsiIrqSourceConfig { 349 high_addr: 0x0, 350 low_addr, 351 data, 352 devid: 0, 353 }; 354 355 self.interrupt_source_group 356 .update(irq as InterruptIndex, InterruptSourceConfig::MsiIrq(config)) 357 .map_err(Error::UpdateInterrupt)?; 358 359 if interrupt_mask(entry) == 1 { 360 self.interrupt_source_group 361 .mask(irq as InterruptIndex) 362 .map_err(Error::MaskInterrupt)?; 363 } else { 364 self.interrupt_source_group 365 .unmask(irq as InterruptIndex) 366 .map_err(Error::UnmaskInterrupt)?; 367 } 368 369 Ok(()) 370 } 371 } 372 373 impl InterruptController for Ioapic { 374 // The ioapic must be informed about EOIs in order to deassert interrupts 375 // already sent. 376 fn end_of_interrupt(&mut self, vec: u8) { 377 for i in 0..NUM_IOAPIC_PINS { 378 let entry = &mut self.reg_entries[i]; 379 // Clear Remote IRR bit 380 if vector(*entry) == vec && trigger_mode(*entry) == 1 { 381 set_remote_irr(entry, 0); 382 } 383 } 384 } 385 386 // This should be called anytime an interrupt needs to be injected into the 387 // running guest. 388 fn service_irq(&mut self, irq: usize) -> Result<()> { 389 let entry = &mut self.reg_entries[irq]; 390 391 self.interrupt_source_group 392 .trigger(irq as InterruptIndex) 393 .map_err(Error::TriggerInterrupt)?; 394 debug!("Interrupt successfully delivered"); 395 396 // If trigger mode is level sensitive, set the Remote IRR bit. 397 // It will be cleared when the EOI is received. 398 if trigger_mode(*entry) == 1 { 399 set_remote_irr(entry, 1); 400 } 401 // Clear the Delivery Status bit 402 set_delivery_status(entry, 0); 403 404 Ok(()) 405 } 406 407 fn notifier(&self, irq: usize) -> Option<EventFd> { 408 self.interrupt_source_group.notifier(irq as InterruptIndex) 409 } 410 } 411 412 impl Snapshottable for Ioapic { 413 fn id(&self) -> String { 414 self.id.clone() 415 } 416 417 fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> { 418 Snapshot::new_from_versioned_state(&self.id, &self.state()) 419 } 420 421 fn restore(&mut self, snapshot: Snapshot) -> std::result::Result<(), MigratableError> { 422 self.set_state(&snapshot.to_versioned_state(&self.id)?) 423 .map_err(|e| { 424 MigratableError::Restore(anyhow!( 425 "Could not restore state for {}: {:?}", 426 self.id, 427 e 428 )) 429 }) 430 } 431 } 432 433 impl Pausable for Ioapic {} 434 impl Transportable for Ioapic {} 435 impl Migratable for Ioapic {} 436