madt.rs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  1. use alloc::vec::Vec;
  2. use bit_field::BitField;
  3. use core::marker::PhantomData;
  4. use core::mem;
  5. use crate::interrupt::{
  6. InterruptModel, InterruptSourceOverride, IoApic, NmiSource, Polarity, TriggerMode,
  7. };
  8. use crate::sdt::SdtHeader;
  9. use crate::{Acpi, AcpiError, AcpiHandler, PhysicalMapping, Processor, ProcessorState};
  10. #[derive(Debug)]
  11. pub enum MadtError {
  12. UnexpectedEntry,
  13. InterruptOverrideEntryHasInvalidBus,
  14. InvalidLocalNmiLine,
  15. NoLocalNmiLineSpecified,
  16. MpsIntiInvalidPolarity,
  17. MpsIntiInvalidTriggerMode,
  18. }
  19. /// Represents the MADT - this contains the MADT header fields. You can then iterate over a `Madt`
  20. /// to read each entry from it.
  21. ///
  22. /// In modern versions of ACPI, the MADT can detail one of four interrupt models:
  23. /// * The ancient dual-i8259 legacy PIC model
  24. /// * The Advanced Programmable Interrupt Controller (APIC) model
  25. /// * The Streamlined Advanced Programmable Interrupt Controller (SAPIC) model
  26. /// * The Generic Interrupt Controller (GIC) model (ARM systems only)
  27. #[repr(C, packed)]
  28. pub(crate) struct Madt {
  29. header: SdtHeader,
  30. local_apic_address: u32,
  31. flags: u32,
  32. }
  33. impl Madt {
  34. fn entries(&self) -> MadtEntryIter {
  35. MadtEntryIter {
  36. pointer: unsafe {
  37. (self as *const Madt as *const u8).offset(mem::size_of::<Madt>() as isize)
  38. },
  39. remaining_length: self.header.length() - mem::size_of::<Madt>() as u32,
  40. _phantom: PhantomData,
  41. }
  42. }
  43. fn supports_8259(&self) -> bool {
  44. unsafe { self.flags.get_bit(0) }
  45. }
  46. }
  47. struct MadtEntryIter<'a> {
  48. pointer: *const u8,
  49. /*
  50. * The iterator can only have at most `u32::MAX` remaining bytes, because the length of the
  51. * whole SDT can only be at most `u32::MAX`.
  52. */
  53. remaining_length: u32,
  54. _phantom: PhantomData<&'a ()>,
  55. }
  56. enum MadtEntry<'a> {
  57. LocalApic(&'a LocalApicEntry),
  58. IoApic(&'a IoApicEntry),
  59. InterruptSourceOverride(&'a InterruptSourceOverrideEntry),
  60. NmiSource(&'a NmiSourceEntry),
  61. LocalApicNmi(&'a LocalApicNmiEntry),
  62. LocalApicAddressOverride(&'a LocalApicAddressOverrideEntry),
  63. IoSapic(&'a IoSapicEntry),
  64. LocalSapic(&'a LocalSapicEntry),
  65. PlatformInterruptSource(&'a PlatformInterruptSourceEntry),
  66. LocalX2Apic(&'a LocalX2ApicEntry),
  67. X2ApicNmi(&'a X2ApicNmiEntry),
  68. Gicc(&'a GiccEntry),
  69. Gicd(&'a GicdEntry),
  70. GicMsiFrame(&'a GicMsiFrameEntry),
  71. GicRedistributor(&'a GicRedistributorEntry),
  72. GicInterruptTranslationService(&'a GicInterruptTranslationServiceEntry),
  73. }
  74. impl<'a> Iterator for MadtEntryIter<'a> {
  75. type Item = MadtEntry<'a>;
  76. fn next(&mut self) -> Option<Self::Item> {
  77. while self.remaining_length > 0 {
  78. let entry_pointer = self.pointer;
  79. let header = unsafe { *(self.pointer as *const EntryHeader) };
  80. self.pointer = unsafe { self.pointer.offset(header.length as isize) };
  81. self.remaining_length -= header.length as u32;
  82. macro_rules! construct_entry {
  83. ($entry_type:expr,
  84. $entry_pointer:expr,
  85. $(($value:expr => $variant:path as $type:ty)),*
  86. ) => {
  87. match $entry_type {
  88. $(
  89. $value => {
  90. return Some($variant(unsafe {
  91. &*($entry_pointer as *const $type)
  92. }))
  93. }
  94. )*
  95. /*
  96. * These entry types are reserved by the ACPI standard. We should skip them
  97. * if they appear in a real MADT.
  98. */
  99. 0x10..=0x7f => {}
  100. /*
  101. * These entry types are reserved for OEM use. Atm, we just skip them too.
  102. * TODO: work out if we should ever do anything else here
  103. */
  104. 0x80..=0xff => {}
  105. }
  106. }
  107. }
  108. #[rustfmt::skip]
  109. construct_entry!(
  110. header.entry_type,
  111. entry_pointer,
  112. (0x0 => MadtEntry::LocalApic as LocalApicEntry),
  113. (0x1 => MadtEntry::IoApic as IoApicEntry),
  114. (0x2 => MadtEntry::InterruptSourceOverride as InterruptSourceOverrideEntry),
  115. (0x3 => MadtEntry::NmiSource as NmiSourceEntry),
  116. (0x4 => MadtEntry::LocalApicNmi as LocalApicNmiEntry),
  117. (0x5 => MadtEntry::LocalApicAddressOverride as LocalApicAddressOverrideEntry),
  118. (0x6 => MadtEntry::IoSapic as IoSapicEntry),
  119. (0x7 => MadtEntry::LocalSapic as LocalSapicEntry),
  120. (0x8 => MadtEntry::PlatformInterruptSource as PlatformInterruptSourceEntry),
  121. (0x9 => MadtEntry::LocalX2Apic as LocalX2ApicEntry),
  122. (0xa => MadtEntry::X2ApicNmi as X2ApicNmiEntry),
  123. (0xb => MadtEntry::Gicc as GiccEntry),
  124. (0xc => MadtEntry::Gicd as GicdEntry),
  125. (0xd => MadtEntry::GicMsiFrame as GicMsiFrameEntry),
  126. (0xe => MadtEntry::GicRedistributor as GicRedistributorEntry),
  127. (0xf => MadtEntry::GicInterruptTranslationService as GicInterruptTranslationServiceEntry)
  128. );
  129. }
  130. None
  131. }
  132. }
  133. #[derive(Clone, Copy)]
  134. #[repr(C, packed)]
  135. struct EntryHeader {
  136. entry_type: u8,
  137. length: u8,
  138. }
  139. #[repr(C, packed)]
  140. struct LocalApicEntry {
  141. header: EntryHeader,
  142. processor_id: u8,
  143. apic_id: u8,
  144. flags: u32,
  145. }
  146. #[repr(C, packed)]
  147. struct IoApicEntry {
  148. header: EntryHeader,
  149. io_apic_id: u8,
  150. _reserved: u8,
  151. io_apic_address: u32,
  152. global_system_interrupt_base: u32,
  153. }
  154. #[repr(C, packed)]
  155. struct InterruptSourceOverrideEntry {
  156. header: EntryHeader,
  157. bus: u8, // 0 - ISA bus
  158. irq: u8, // This is bus-relative
  159. global_system_interrupt: u32,
  160. flags: u16,
  161. }
  162. #[repr(C, packed)]
  163. struct NmiSourceEntry {
  164. header: EntryHeader,
  165. flags: u16,
  166. global_system_interrupt: u32,
  167. }
  168. #[repr(C, packed)]
  169. struct LocalApicNmiEntry {
  170. header: EntryHeader,
  171. processor_id: u8,
  172. flags: u16,
  173. nmi_line: u8, // Describes which LINTn is the NMI connected to
  174. }
  175. #[repr(C, packed)]
  176. struct LocalApicAddressOverrideEntry {
  177. header: EntryHeader,
  178. _reserved: u16,
  179. local_apic_address: u64,
  180. }
  181. /// If this entry is present, the system has an I/O SAPIC, which must be used instead of the I/O APIC.
  182. #[repr(C, packed)]
  183. struct IoSapicEntry {
  184. header: EntryHeader,
  185. io_apic_id: u8,
  186. _reserved: u8,
  187. global_system_interrupt_base: u32,
  188. io_sapic_address: u64,
  189. }
  190. #[repr(C, packed)]
  191. struct LocalSapicEntry {
  192. header: EntryHeader,
  193. processor_id: u8,
  194. local_sapic_id: u8,
  195. local_sapic_eid: u8,
  196. _reserved: [u8; 3],
  197. flags: u32,
  198. processor_uid: u32,
  199. /// This string can be used to associate this local SAPIC to a processor defined in the
  200. /// namespace when the `_UID` object is a string. It is a null-terminated ASCII string, and so
  201. /// this field will be `'\0'` if the string is not present, otherwise it extends from the
  202. /// address of this field.
  203. processor_uid_string: u8,
  204. }
  205. #[repr(C, packed)]
  206. struct PlatformInterruptSourceEntry {
  207. header: EntryHeader,
  208. flags: u16,
  209. interrupt_type: u8,
  210. processor_id: u8,
  211. processor_eid: u8,
  212. io_sapic_vector: u8,
  213. global_system_interrupt: u32,
  214. platform_interrupt_source_flags: u32,
  215. }
  216. #[repr(C, packed)]
  217. struct LocalX2ApicEntry {
  218. header: EntryHeader,
  219. _reserved: u16,
  220. x2apic_id: u32,
  221. flags: u32,
  222. processor_uid: u32,
  223. }
  224. #[repr(C, packed)]
  225. struct X2ApicNmiEntry {
  226. header: EntryHeader,
  227. flags: u16,
  228. processor_uid: u32,
  229. nmi_line: u8,
  230. _reserved: [u8; 3],
  231. }
  232. /// This field will appear for ARM processors that support ACPI and use the Generic Interrupt
  233. /// Controller. In the GICC interrupt model, each logical process has a Processor Device object in
  234. /// the namespace, and uses this structure to convey its GIC information.
  235. #[repr(C, packed)]
  236. struct GiccEntry {
  237. header: EntryHeader,
  238. _reserved1: u16,
  239. cpu_interface_number: u32,
  240. processor_uid: u32,
  241. flags: u32,
  242. parking_protocol_version: u32,
  243. performance_interrupt_gsiv: u32,
  244. parked_address: u64,
  245. gic_registers_address: u64,
  246. gic_control_block_address: u64,
  247. vgic_maintenance_interrupt: u32,
  248. gicr_base_address: u64,
  249. mpidr: u64,
  250. processor_power_efficiency_class: u8,
  251. _reserved2: [u8; 3],
  252. }
  253. #[repr(C, packed)]
  254. struct GicdEntry {
  255. header: EntryHeader,
  256. _reserved1: u16,
  257. gic_id: u32,
  258. physical_base_address: u64,
  259. system_vector_base: u32,
  260. /// The GIC version
  261. /// 0x00: Fall back to hardware discovery
  262. /// 0x01: GICv1
  263. /// 0x02: GICv2
  264. /// 0x03: GICv3
  265. /// 0x04: GICv4
  266. /// 0x05-0xff: Reserved for future use
  267. gic_version: u8,
  268. _reserved2: [u8; 3],
  269. }
  270. #[repr(C, packed)]
  271. struct GicMsiFrameEntry {
  272. header: EntryHeader,
  273. _reserved: u16,
  274. frame_id: u32,
  275. physical_base_address: u64,
  276. flags: u32,
  277. spi_count: u16,
  278. spi_base: u16,
  279. }
  280. #[repr(C, packed)]
  281. struct GicRedistributorEntry {
  282. header: EntryHeader,
  283. _reserved: u16,
  284. discovery_range_base_address: u64,
  285. discovery_range_length: u32,
  286. }
  287. #[repr(C, packed)]
  288. struct GicInterruptTranslationServiceEntry {
  289. header: EntryHeader,
  290. _reserved1: u16,
  291. id: u32,
  292. physical_base_address: u64,
  293. _reserved2: u32,
  294. }
  295. pub(crate) fn parse_madt<H>(
  296. acpi: &mut Acpi,
  297. _handler: &mut H,
  298. mapping: &PhysicalMapping<Madt>,
  299. ) -> Result<(), AcpiError>
  300. where
  301. H: AcpiHandler,
  302. {
  303. (*mapping).header.validate(b"APIC")?;
  304. /*
  305. * If the MADT doesn't contain another supported interrupt model (either APIC, SAPIC, X2APIC or
  306. * GIC), and the system supports the legacy i8259 PIC, recommend that.
  307. * TODO: It's not clear how trustworthy this field is - should we be relying on it in any way?
  308. */
  309. if (*mapping).supports_8259() {
  310. acpi.interrupt_model = Some(InterruptModel::Pic);
  311. }
  312. /*
  313. * We first do a pass through the MADT to determine which interrupt model is being used.
  314. */
  315. for entry in (*mapping).entries() {
  316. match entry {
  317. MadtEntry::LocalApic(_) |
  318. MadtEntry::IoApic(_) |
  319. MadtEntry::InterruptSourceOverride(_) |
  320. MadtEntry::NmiSource(_) | // TODO: is this one used by more than one model?
  321. MadtEntry::LocalApicNmi(_) |
  322. MadtEntry::LocalApicAddressOverride(_) => {
  323. acpi.interrupt_model = Some(parse_apic_model(acpi, mapping)?);
  324. break;
  325. }
  326. MadtEntry::IoSapic(_) |
  327. MadtEntry::LocalSapic(_) |
  328. MadtEntry::PlatformInterruptSource(_) => {
  329. unimplemented!();
  330. }
  331. MadtEntry::LocalX2Apic(_) |
  332. MadtEntry::X2ApicNmi(_) => {
  333. unimplemented!();
  334. }
  335. MadtEntry::Gicc(_) |
  336. MadtEntry::Gicd(_) |
  337. MadtEntry::GicMsiFrame(_) |
  338. MadtEntry::GicRedistributor(_) |
  339. MadtEntry::GicInterruptTranslationService(_) => {
  340. unimplemented!();
  341. }
  342. }
  343. }
  344. Ok(())
  345. }
  346. /// This parses the MADT and gathers information about a APIC interrupt model. We error if we
  347. /// encounter an entry that doesn't configure the APIC.
  348. fn parse_apic_model(
  349. acpi: &mut Acpi,
  350. mapping: &PhysicalMapping<Madt>,
  351. ) -> Result<InterruptModel, AcpiError> {
  352. use crate::interrupt::LocalInterruptLine;
  353. let mut local_apic_address = (*mapping).local_apic_address as u64;
  354. let mut io_apics = Vec::new();
  355. let mut local_apic_nmi_line = None;
  356. let mut interrupt_source_overrides = Vec::new();
  357. let mut nmi_sources = Vec::new();
  358. for entry in (*mapping).entries() {
  359. match entry {
  360. MadtEntry::LocalApic(ref entry) => {
  361. /*
  362. * The first processor is the BSP. Subsequent ones are APs. If we haven't found the
  363. * BSP yet, this must be it.
  364. */
  365. let is_ap = acpi.boot_processor.is_some();
  366. let is_disabled = !unsafe { entry.flags.get_bit(0) };
  367. let state = match (is_ap, is_disabled) {
  368. (_, true) => ProcessorState::Disabled,
  369. (true, false) => ProcessorState::WaitingForSipi,
  370. (false, false) => ProcessorState::Running,
  371. };
  372. let processor = Processor::new(entry.processor_id, entry.apic_id, state, is_ap);
  373. if is_ap {
  374. acpi.application_processors.push(processor);
  375. } else {
  376. acpi.boot_processor = Some(processor);
  377. }
  378. }
  379. MadtEntry::IoApic(ref entry) => {
  380. io_apics.push(IoApic {
  381. id: entry.io_apic_id,
  382. address: entry.io_apic_address,
  383. global_system_interrupt_base: entry.global_system_interrupt_base,
  384. });
  385. }
  386. MadtEntry::InterruptSourceOverride(ref entry) => {
  387. if entry.bus != 0 {
  388. return Err(AcpiError::InvalidMadt(
  389. MadtError::InterruptOverrideEntryHasInvalidBus,
  390. ));
  391. }
  392. let (polarity, trigger_mode) = parse_mps_inti_flags(entry.flags)?;
  393. interrupt_source_overrides.push(InterruptSourceOverride {
  394. isa_source: entry.irq,
  395. global_system_interrupt: entry.global_system_interrupt,
  396. polarity,
  397. trigger_mode,
  398. });
  399. }
  400. MadtEntry::NmiSource(ref entry) => {
  401. let (polarity, trigger_mode) = parse_mps_inti_flags(entry.flags)?;
  402. nmi_sources.push(NmiSource {
  403. global_system_interrupt: entry.global_system_interrupt,
  404. polarity,
  405. trigger_mode,
  406. });
  407. }
  408. MadtEntry::LocalApicNmi(ref entry) => {
  409. local_apic_nmi_line = Some(match entry.nmi_line {
  410. 0 => LocalInterruptLine::Lint0,
  411. 1 => LocalInterruptLine::Lint1,
  412. _ => return Err(AcpiError::InvalidMadt(MadtError::InvalidLocalNmiLine)),
  413. })
  414. }
  415. MadtEntry::LocalApicAddressOverride(ref entry) => {
  416. local_apic_address = entry.local_apic_address;
  417. }
  418. _ => {
  419. return Err(AcpiError::InvalidMadt(MadtError::UnexpectedEntry));
  420. }
  421. }
  422. }
  423. Ok(InterruptModel::Apic {
  424. local_apic_address,
  425. io_apics,
  426. local_apic_nmi_line: local_apic_nmi_line
  427. .ok_or(AcpiError::InvalidMadt(MadtError::NoLocalNmiLineSpecified))?,
  428. interrupt_source_overrides,
  429. nmi_sources,
  430. also_has_legacy_pics: (*mapping).supports_8259(),
  431. })
  432. }
  433. fn parse_mps_inti_flags(flags: u16) -> Result<(Polarity, TriggerMode), AcpiError> {
  434. let polarity = match flags.get_bits(0..2) {
  435. 0b00 => Polarity::SameAsBus,
  436. 0b01 => Polarity::ActiveHigh,
  437. 0b11 => Polarity::ActiveLow,
  438. _ => return Err(AcpiError::InvalidMadt(MadtError::MpsIntiInvalidPolarity)),
  439. };
  440. let trigger_mode = match flags.get_bits(2..4) {
  441. 0b00 => TriggerMode::SameAsBus,
  442. 0b01 => TriggerMode::Edge,
  443. 0b11 => TriggerMode::Level,
  444. _ => return Err(AcpiError::InvalidMadt(MadtError::MpsIntiInvalidTriggerMode)),
  445. };
  446. Ok((polarity, trigger_mode))
  447. }