madt.rs 16 KB

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