mod.rs 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  1. use core::sync::atomic::Ordering;
  2. use atomic_enum::atomic_enum;
  3. use log::{debug, info};
  4. use system_error::SystemError;
  5. use x86::{apic::Icr, msr::IA32_APIC_BASE};
  6. use crate::{
  7. arch::{
  8. driver::apic::{hw_irq::ApicId, x2apic::X2Apic, xapic::XApic},
  9. io::PortIOArch,
  10. CurrentPortIOArch,
  11. },
  12. mm::PhysAddr,
  13. smp::core::smp_get_processor_id,
  14. };
  15. use self::{
  16. apic_timer::LocalApicTimerMode,
  17. xapic::{current_xapic_instance, XApicOffset},
  18. };
  19. pub mod apic_timer;
  20. pub mod hw_irq;
  21. pub mod ioapic;
  22. pub mod lapic_vector;
  23. pub mod x2apic;
  24. pub mod xapic;
  25. /// 当前启用的APIC类型
  26. #[atomic_enum]
  27. #[derive(PartialEq, Eq)]
  28. pub enum LocalApicEnableType {
  29. XApic,
  30. X2Apic,
  31. }
  32. static LOCAL_APIC_ENABLE_TYPE: AtomicLocalApicEnableType =
  33. AtomicLocalApicEnableType::new(LocalApicEnableType::XApic);
  34. pub trait LocalAPIC {
  35. /// @brief 判断当前处理器是否支持这个类型的apic
  36. ///
  37. /// @return true 当前处理器支持这个类型的apic
  38. /// @return false 当前处理器不支持这个类型的apic
  39. fn support() -> bool;
  40. /// @brief 为当前处理器初始化local apic
  41. ///
  42. /// @return true 初始化成功
  43. /// @return false 初始化失败
  44. fn init_current_cpu(&mut self) -> bool;
  45. /// @brief 发送EOI信号(End of interrupt)
  46. fn send_eoi(&self);
  47. /// @brief 获取APIC版本号
  48. #[allow(dead_code)]
  49. fn version(&self) -> u8;
  50. /// @brief 判断当前处理器是否支持EOI广播抑制
  51. fn support_eoi_broadcast_suppression(&self) -> bool;
  52. /// 获取最多支持的LVT寄存器数量
  53. #[allow(dead_code)]
  54. fn max_lvt_entry(&self) -> u8;
  55. /// @brief 获取当前处理器的APIC ID
  56. #[allow(dead_code)]
  57. fn id(&self) -> ApicId;
  58. /// @brief 设置LVT寄存器
  59. ///
  60. /// @param register 寄存器
  61. /// @param lvt 要被设置成的值
  62. fn set_lvt(&mut self, lvt: LVT);
  63. /// 读取LVT寄存器
  64. fn read_lvt(&self, reg: LVTRegister) -> LVT;
  65. fn mask_all_lvt(&mut self);
  66. /// 写入ICR寄存器
  67. fn write_icr(&self, icr: Icr);
  68. }
  69. /// @brief 所有LVT寄存器的枚举类型
  70. #[allow(dead_code)]
  71. #[repr(u32)]
  72. #[derive(Debug, Clone, Copy)]
  73. pub enum LVTRegister {
  74. /// CMCI寄存器
  75. ///
  76. /// 如果支持CMCI功能,那么,当修正的机器错误超过阈值时,Local APIC通过CMCI寄存器的配置,
  77. /// 向处理器核心投递中断消息
  78. CMCI = 0x82f,
  79. /// 定时器寄存器
  80. ///
  81. /// 当APIC定时器产生中断信号时,Local APIC通过定时器寄存器的设置,向处理器投递中断消息
  82. Timer = 0x832,
  83. /// 温度传感器寄存器
  84. ///
  85. /// 当处理器内部的温度传感器产生中断请求信号时,Local APIC会通过温度传感器寄存器的设置,
  86. /// 向处理器投递中断消息。
  87. Thermal = 0x833,
  88. /// 性能监控计数器寄存器
  89. ///
  90. /// 当性能检测计数器寄存器溢出,产生中断请求时,Local APIC将会根据这个寄存器的配置,
  91. /// 向处理器投递中断消息
  92. PerformanceMonitor = 0x834,
  93. /// 当处理器的LINT0引脚接收到中断请求信号时,Local APIC会根据这个寄存器的配置,
  94. /// 向处理器投递中断消息
  95. LINT0 = 0x835,
  96. /// 当处理器的LINT0引脚接收到中断请求信号时,Local APIC会根据这个寄存器的配置,
  97. /// 向处理器投递中断消息
  98. LINT1 = 0x836,
  99. /// 错误寄存器
  100. ///
  101. /// 当APIC检测到内部错误而产生中断请求信号时,它将会通过错误寄存器的设置,向处理器投递中断消息
  102. ErrorReg = 0x837,
  103. }
  104. impl From<LVTRegister> for u32 {
  105. fn from(val: LVTRegister) -> Self {
  106. val as u32
  107. }
  108. }
  109. #[derive(Debug)]
  110. pub struct LVT {
  111. register: LVTRegister,
  112. data: u32,
  113. }
  114. impl LVT {
  115. /// 当第16位为1时,表示屏蔽中断
  116. pub const MASKED: u32 = 1 << 16;
  117. pub fn new(register: LVTRegister, data: u32) -> Option<Self> {
  118. // vector: u8, mode: DeliveryMode, status: DeliveryStatus
  119. let mut result = Self { register, data: 0 };
  120. result.set_vector((data & 0xFF) as u8);
  121. match result.register {
  122. LVTRegister::Timer | LVTRegister::ErrorReg => {}
  123. _ => {
  124. result
  125. .set_delivery_mode(DeliveryMode::try_from(((data >> 8) & 0b111) as u8).ok()?)
  126. .ok()?;
  127. }
  128. }
  129. if let LVTRegister::LINT0 | LVTRegister::LINT1 = result.register {
  130. result.set_interrupt_input_pin_polarity((data & (1 << 13)) == 0);
  131. if data & (1 << 15) != 0 {
  132. result.set_trigger_mode(TriggerMode::Level).ok()?;
  133. } else {
  134. result.set_trigger_mode(TriggerMode::Edge).ok()?;
  135. }
  136. }
  137. result.set_mask((data & (1 << 16)) != 0);
  138. if let LVTRegister::Timer = result.register {
  139. result
  140. .set_timer_mode(LocalApicTimerMode::try_from(((data >> 17) & 0b11) as u8).ok()?)
  141. .ok()?;
  142. }
  143. return Some(result);
  144. }
  145. /// 获取LVT寄存器的原始值
  146. #[allow(dead_code)]
  147. pub fn data(&self) -> u32 {
  148. return self.data;
  149. }
  150. pub fn register(&self) -> LVTRegister {
  151. return self.register;
  152. }
  153. pub fn set_vector(&mut self, vector: u8) {
  154. self.data &= !((1 << 8) - 1);
  155. self.data |= vector as u32;
  156. }
  157. /// 获取中断向量号
  158. #[allow(dead_code)]
  159. pub fn vector(&self) -> u8 {
  160. return (self.data & 0xFF) as u8;
  161. }
  162. /// 设置中断投递模式
  163. ///
  164. /// Timer、ErrorReg寄存器不支持这个功能
  165. ///
  166. /// ## 参数
  167. ///
  168. /// - `mode`:投递模式
  169. pub fn set_delivery_mode(&mut self, mode: DeliveryMode) -> Result<(), SystemError> {
  170. match self.register {
  171. LVTRegister::Timer | LVTRegister::ErrorReg => {
  172. return Err(SystemError::EINVAL);
  173. }
  174. _ => {}
  175. }
  176. self.data &= 0xFFFF_F8FF;
  177. self.data |= ((mode as u32) & 0x7) << 8;
  178. return Ok(());
  179. }
  180. /// 获取中断投递模式
  181. /// Timer、ErrorReg寄存器不支持这个功能
  182. #[allow(dead_code)]
  183. pub fn delivery_mode(&self) -> Option<DeliveryMode> {
  184. if let LVTRegister::Timer | LVTRegister::ErrorReg = self.register {
  185. return None;
  186. }
  187. return DeliveryMode::try_from(((self.data >> 8) & 0b111) as u8).ok();
  188. }
  189. /// Get the delivery status of the interrupt
  190. #[allow(dead_code)]
  191. pub fn delivery_status(&self) -> DeliveryStatus {
  192. return DeliveryStatus::from(self.data);
  193. }
  194. /// 设置中断输入引脚的极性
  195. ///
  196. /// ## 参数
  197. ///
  198. /// - `high`:true表示高电平有效,false表示低电平有效
  199. pub fn set_interrupt_input_pin_polarity(&mut self, high: bool) {
  200. self.data &= 0xFFFF_DFFF;
  201. // 0表示高电平有效,1表示低电平有效
  202. if !high {
  203. self.data |= 1 << 13;
  204. }
  205. }
  206. /// 获取中断输入引脚的极性
  207. ///
  208. /// true表示高电平有效,false表示低电平有效
  209. #[allow(dead_code)]
  210. pub fn interrupt_input_pin_polarity(&self) -> bool {
  211. return (self.data & (1 << 13)) == 0;
  212. }
  213. /// 设置中断输入引脚的触发模式
  214. ///
  215. /// 只有LINT0和LINT1寄存器支持这个功能
  216. ///
  217. /// ## 参数
  218. ///
  219. /// - `trigger_mode`:触发模式
  220. pub fn set_trigger_mode(&mut self, trigger_mode: TriggerMode) -> Result<(), SystemError> {
  221. match self.register {
  222. LVTRegister::LINT0 | LVTRegister::LINT1 => {
  223. self.data &= 0xFFFF_7FFF;
  224. if trigger_mode == TriggerMode::Level {
  225. self.data |= 1 << 15;
  226. }
  227. return Ok(());
  228. }
  229. _ => {
  230. return Err(SystemError::EINVAL);
  231. }
  232. }
  233. }
  234. /// 获取中断输入引脚的触发模式
  235. ///
  236. /// 只有LINT0和LINT1寄存器支持这个功能
  237. #[allow(dead_code)]
  238. pub fn trigger_mode(&self) -> Option<TriggerMode> {
  239. match self.register {
  240. LVTRegister::LINT0 | LVTRegister::LINT1 => {
  241. if self.data & (1 << 15) != 0 {
  242. return Some(TriggerMode::Level);
  243. } else {
  244. return Some(TriggerMode::Edge);
  245. }
  246. }
  247. _ => {
  248. return None;
  249. }
  250. }
  251. }
  252. /// 设置是否屏蔽中断
  253. ///
  254. /// ## 参数
  255. ///
  256. /// - `mask`:true表示屏蔽中断,false表示不屏蔽中断
  257. pub fn set_mask(&mut self, mask: bool) {
  258. self.data &= 0xFFFE_FFFF;
  259. if mask {
  260. self.data |= 1 << 16;
  261. }
  262. }
  263. /// Check if the interrupt is masked
  264. ///
  265. /// true表示屏蔽中断,false表示不屏蔽中断
  266. #[allow(dead_code)]
  267. pub fn mask(&self) -> bool {
  268. return (self.data & (1 << 16)) != 0;
  269. }
  270. /// 设置定时器模式
  271. pub fn set_timer_mode(&mut self, mode: LocalApicTimerMode) -> Result<(), SystemError> {
  272. match self.register {
  273. LVTRegister::Timer => {
  274. self.data &= 0xFFF9_FFFF;
  275. match mode {
  276. LocalApicTimerMode::Oneshot => {
  277. self.data |= 0b00 << 17;
  278. }
  279. LocalApicTimerMode::Periodic => {
  280. self.data |= 0b01 << 17;
  281. }
  282. LocalApicTimerMode::Deadline => {
  283. self.data |= 0b10 << 17;
  284. }
  285. }
  286. return Ok(());
  287. }
  288. _ => {
  289. return Err(SystemError::EINVAL);
  290. }
  291. }
  292. }
  293. /// 获取定时器模式
  294. #[allow(dead_code)]
  295. pub fn timer_mode(&self) -> Option<LocalApicTimerMode> {
  296. if let LVTRegister::Timer = self.register {
  297. let mode = (self.data >> 17) & 0b11;
  298. match mode {
  299. 0b00 => {
  300. return Some(LocalApicTimerMode::Oneshot);
  301. }
  302. 0b01 => {
  303. return Some(LocalApicTimerMode::Periodic);
  304. }
  305. 0b10 => {
  306. return Some(LocalApicTimerMode::Deadline);
  307. }
  308. _ => {
  309. return None;
  310. }
  311. }
  312. }
  313. return None;
  314. }
  315. }
  316. /// @brief
  317. #[allow(dead_code)]
  318. #[derive(Debug, PartialEq)]
  319. pub enum DeliveryMode {
  320. /// 由LVT寄存器的向量号区域指定中断向量号
  321. Fixed = 0b000,
  322. /// 通过处理器的SMI信号线,向处理器投递SMI中断请求。
  323. /// 由于兼容性的原因,使用此投递模式时,LVT的中断向量号区域必须设置为0。
  324. SMI = 0b010,
  325. /// 向处理器投递不可屏蔽中断,并忽略向量号区域
  326. NMI = 0b100,
  327. /// 向处理器投递INIT中断请求,处理器会执行初始化的过程。
  328. /// 由于兼容性的原因,使用此投递模式时,LVT的中断向量号区域必须设置为0。
  329. /// CMCI、温度传感器、性能监控计数器等寄存器均不支持INIT投递模式
  330. INIT = 0b101,
  331. /// 向目标处理器投递Start-Up IPI。
  332. ///
  333. /// 这个向量通常由多核引导模块调用(请参阅Intel开发手册Volume3 Section 8.4,
  334. /// Multiple-Processor (MP) Initialization)。
  335. /// 如果源APIC无法投递这个IPI,它不会自动重发。如果Start-Up IPI未成功投递,
  336. /// 则交由软件决定是否在必要时重新投递SIPI
  337. StartUp = 0b110,
  338. /// ExtINT模式可以将类8259A中断控制器产生的中断请求投递到处理器,并接收类
  339. /// 8259A中断控制器提供的中断向量号。
  340. /// CMCI、温度传感器、性能监控计数器等寄存器均不支持ExtINT投递模式
  341. ExtINT = 0b111,
  342. }
  343. impl TryFrom<u8> for DeliveryMode {
  344. type Error = SystemError;
  345. fn try_from(value: u8) -> Result<Self, Self::Error> {
  346. match value {
  347. 0b000 => {
  348. return Ok(DeliveryMode::Fixed);
  349. }
  350. 0b010 => {
  351. return Ok(DeliveryMode::SMI);
  352. }
  353. 0b100 => {
  354. return Ok(DeliveryMode::NMI);
  355. }
  356. 0b101 => {
  357. return Ok(DeliveryMode::INIT);
  358. }
  359. 0b110 => {
  360. return Ok(DeliveryMode::StartUp);
  361. }
  362. 0b111 => {
  363. return Ok(DeliveryMode::ExtINT);
  364. }
  365. _ => {
  366. return Err(SystemError::EINVAL);
  367. }
  368. }
  369. }
  370. }
  371. /// @brief 投递状态
  372. #[derive(Debug)]
  373. #[allow(dead_code)]
  374. pub enum DeliveryStatus {
  375. /// 空闲态。
  376. /// 此状态表明,当前中断源未产生中断,或者产生的中断已经投递到处理器,并被处理器处理。
  377. Idle = 0,
  378. /// 发送挂起状态。
  379. /// 此状态表明,中断源产生的请求已经投递至处理器,但尚未被处理器处理。
  380. SendPending = 1,
  381. }
  382. impl DeliveryStatus {
  383. pub fn from(data: u32) -> Self {
  384. if data & (1 << 12) == 0 {
  385. return DeliveryStatus::Idle;
  386. } else {
  387. return DeliveryStatus::SendPending;
  388. }
  389. }
  390. }
  391. /// IPI Trigger Mode
  392. #[derive(Debug, Eq, PartialEq)]
  393. #[repr(u64)]
  394. pub enum TriggerMode {
  395. Edge = 0,
  396. Level = 1,
  397. }
  398. #[derive(Debug)]
  399. pub struct CurrentApic;
  400. impl CurrentApic {
  401. /// x2apic是否启用
  402. pub fn x2apic_enabled(&self) -> bool {
  403. return LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic;
  404. }
  405. pub(self) unsafe fn write_xapic_register(&self, reg: XApicOffset, value: u32) {
  406. if let Some(xapic) = current_xapic_instance().borrow_mut().as_mut() {
  407. xapic.write(reg, value);
  408. }
  409. }
  410. /// 屏蔽类8259A芯片
  411. unsafe fn mask8259a(&self) {
  412. CurrentPortIOArch::out8(0x21, 0xff);
  413. CurrentPortIOArch::out8(0xa1, 0xff);
  414. // 写入8259A pic的EOI位
  415. CurrentPortIOArch::out8(0x20, 0x20);
  416. CurrentPortIOArch::out8(0xa0, 0x20);
  417. debug!("8259A Masked.");
  418. // enable IMCR
  419. CurrentPortIOArch::out8(0x22, 0x70);
  420. CurrentPortIOArch::out8(0x23, 0x01);
  421. }
  422. }
  423. impl LocalAPIC for CurrentApic {
  424. fn support() -> bool {
  425. true
  426. }
  427. fn init_current_cpu(&mut self) -> bool {
  428. let cpu_id = smp_get_processor_id();
  429. if cpu_id.data() == 0 {
  430. unsafe {
  431. self.mask8259a();
  432. }
  433. }
  434. info!("Initializing apic for cpu {:?}", cpu_id);
  435. if X2Apic::support() && X2Apic.init_current_cpu() {
  436. if cpu_id.data() == 0 {
  437. LOCAL_APIC_ENABLE_TYPE.store(LocalApicEnableType::X2Apic, Ordering::SeqCst);
  438. }
  439. info!("x2APIC initialized for cpu {:?}", cpu_id);
  440. } else {
  441. info!("x2APIC not supported or failed to initialize, fallback to xAPIC.");
  442. if cpu_id.data() == 0 {
  443. LOCAL_APIC_ENABLE_TYPE.store(LocalApicEnableType::XApic, Ordering::SeqCst);
  444. }
  445. let apic_base =
  446. PhysAddr::new(unsafe { x86::msr::rdmsr(IA32_APIC_BASE) as usize & 0xFFFF_0000 });
  447. let xapic_instance = unsafe { XApic::new(apic_base) };
  448. let mut cur = current_xapic_instance().borrow_mut();
  449. if cur.is_none() {
  450. *cur = Some(xapic_instance);
  451. } else {
  452. panic!("xapic instance already initialized.");
  453. }
  454. if let Some(xapic) = cur.as_mut() {
  455. xapic.init_current_cpu();
  456. }
  457. info!("xAPIC initialized for cpu {:?}", cpu_id);
  458. }
  459. info!("Apic initialized.");
  460. return true;
  461. }
  462. fn send_eoi(&self) {
  463. if LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic {
  464. X2Apic.send_eoi();
  465. } else if let Some(xapic) = current_xapic_instance().borrow().as_ref() {
  466. xapic.send_eoi();
  467. }
  468. }
  469. fn version(&self) -> u8 {
  470. if LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic {
  471. return X2Apic.version();
  472. } else {
  473. return current_xapic_instance()
  474. .borrow()
  475. .as_ref()
  476. .map(|xapic| xapic.version())
  477. .unwrap_or(0);
  478. }
  479. }
  480. fn support_eoi_broadcast_suppression(&self) -> bool {
  481. if LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic {
  482. return X2Apic.support_eoi_broadcast_suppression();
  483. } else {
  484. return current_xapic_instance()
  485. .borrow()
  486. .as_ref()
  487. .map(|xapic| xapic.support_eoi_broadcast_suppression())
  488. .unwrap_or(false);
  489. }
  490. }
  491. fn max_lvt_entry(&self) -> u8 {
  492. if LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic {
  493. return X2Apic.max_lvt_entry();
  494. } else {
  495. return current_xapic_instance()
  496. .borrow()
  497. .as_ref()
  498. .map(|xapic| xapic.max_lvt_entry())
  499. .unwrap_or(0);
  500. }
  501. }
  502. fn id(&self) -> ApicId {
  503. if LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic {
  504. return X2Apic.id();
  505. } else {
  506. return current_xapic_instance()
  507. .borrow()
  508. .as_ref()
  509. .map(|xapic| xapic.id())
  510. .unwrap_or(ApicId::new(0));
  511. }
  512. }
  513. fn set_lvt(&mut self, lvt: LVT) {
  514. if LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic {
  515. X2Apic.set_lvt(lvt);
  516. } else if let Some(xapic) = current_xapic_instance().borrow_mut().as_mut() {
  517. xapic.set_lvt(lvt);
  518. }
  519. }
  520. fn read_lvt(&self, reg: LVTRegister) -> LVT {
  521. if LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic {
  522. return X2Apic.read_lvt(reg);
  523. } else {
  524. return current_xapic_instance()
  525. .borrow()
  526. .as_ref()
  527. .map(|xapic| xapic.read_lvt(reg))
  528. .expect("xapic instance not initialized.");
  529. }
  530. }
  531. fn mask_all_lvt(&mut self) {
  532. if LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic {
  533. X2Apic.mask_all_lvt();
  534. } else if let Some(xapic) = current_xapic_instance().borrow_mut().as_mut() {
  535. xapic.mask_all_lvt();
  536. }
  537. }
  538. fn write_icr(&self, icr: Icr) {
  539. if LOCAL_APIC_ENABLE_TYPE.load(Ordering::SeqCst) == LocalApicEnableType::X2Apic {
  540. X2Apic.write_icr(icr);
  541. } else if let Some(xapic) = current_xapic_instance().borrow().as_ref() {
  542. xapic.write_icr(icr);
  543. }
  544. }
  545. }