acpi_pm.rs 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. use crate::{
  2. alloc::string::ToString,
  3. arch::{io::PortIOArch, CurrentPortIOArch},
  4. driver::acpi::{
  5. acpi_manager,
  6. pmtmr::{ACPI_PM_MASK, PMTMR_TICKS_PER_SEC},
  7. },
  8. libs::spinlock::SpinLock,
  9. time::{
  10. clocksource::{Clocksource, ClocksourceData, ClocksourceFlags, ClocksourceMask, CycleNum},
  11. PIT_TICK_RATE,
  12. },
  13. };
  14. use acpi::fadt::Fadt;
  15. use alloc::sync::{Arc, Weak};
  16. use core::intrinsics::unlikely;
  17. use core::sync::atomic::{AtomicU32, Ordering};
  18. use system_error::SystemError;
  19. // 参考:https://code.dragonos.org.cn/xref/linux-6.6.21/drivers/clocksource/acpi_pm.c
  20. /// acpi_pmtmr所在的I/O端口
  21. pub static mut PMTMR_IO_PORT: AtomicU32 = AtomicU32::new(0);
  22. /// # 读取acpi_pmtmr当前值,并对齐进行掩码操作
  23. #[inline(always)]
  24. fn read_pmtmr() -> u32 {
  25. return unsafe { CurrentPortIOArch::in32(PMTMR_IO_PORT.load(Ordering::SeqCst) as u16) }
  26. & ACPI_PM_MASK as u32;
  27. }
  28. //参考: https://code.dragonos.org.cn/xref/linux-6.6.21/drivers/clocksource/acpi_pm.c#41
  29. /// # 读取acpi_pmtmr的值,并进行多次读取以保证获取正确的值
  30. ///
  31. /// ## 返回值
  32. /// - u32: 读取到的acpi_pmtmr值
  33. #[allow(dead_code)]
  34. pub fn acpi_pm_read_verified() -> u32 {
  35. let mut v2: u32;
  36. // 因为某些损坏芯片组(如ICH4、PIIX4和PIIX4E)可能导致APCI PM时钟源未锁存
  37. // 因此需要多次读取以保证获取正确的值
  38. loop {
  39. let v1 = read_pmtmr();
  40. v2 = read_pmtmr();
  41. let v3 = read_pmtmr();
  42. if !(unlikely((v2 > v3 || v1 < v3) && v1 > v2 || v1 < v3 && v2 > v3)) {
  43. break;
  44. }
  45. }
  46. return v2;
  47. }
  48. /// # 作为时钟源的读取函数
  49. ///
  50. /// ## 返回值
  51. /// - u64: acpi_pmtmr的当前值
  52. fn acpi_pm_read() -> u64 {
  53. return read_pmtmr() as u64;
  54. }
  55. pub static mut CLOCKSOURCE_ACPI_PM: Option<Arc<Acpipm>> = None;
  56. pub fn clocksource_acpi_pm() -> Arc<Acpipm> {
  57. return unsafe { CLOCKSOURCE_ACPI_PM.as_ref().unwrap().clone() };
  58. }
  59. #[derive(Debug)]
  60. pub struct Acpipm(SpinLock<InnerAcpipm>);
  61. #[derive(Debug)]
  62. struct InnerAcpipm {
  63. data: ClocksourceData,
  64. self_reaf: Weak<Acpipm>,
  65. }
  66. impl Acpipm {
  67. pub fn new() -> Arc<Self> {
  68. let data = ClocksourceData {
  69. name: "acpi_pm".to_string(),
  70. rating: 200,
  71. mask: ClocksourceMask::new(ACPI_PM_MASK),
  72. mult: 0,
  73. shift: 0,
  74. max_idle_ns: Default::default(),
  75. flags: ClocksourceFlags::CLOCK_SOURCE_IS_CONTINUOUS,
  76. watchdog_last: CycleNum::new(0),
  77. uncertainty_margin: 0,
  78. maxadj: 0,
  79. };
  80. let acpi_pm = Arc::new(Acpipm(SpinLock::new(InnerAcpipm {
  81. data,
  82. self_reaf: Default::default(),
  83. })));
  84. acpi_pm.0.lock().self_reaf = Arc::downgrade(&acpi_pm);
  85. return acpi_pm;
  86. }
  87. }
  88. impl Clocksource for Acpipm {
  89. fn read(&self) -> CycleNum {
  90. return CycleNum::new(acpi_pm_read());
  91. }
  92. fn clocksource_data(&self) -> ClocksourceData {
  93. let inner = self.0.lock_irqsave();
  94. return inner.data.clone();
  95. }
  96. fn clocksource(&self) -> Arc<dyn Clocksource> {
  97. return self.0.lock_irqsave().self_reaf.upgrade().unwrap();
  98. }
  99. fn update_clocksource_data(&self, data: ClocksourceData) -> Result<(), SystemError> {
  100. let d = &mut self.0.lock_irqsave().data;
  101. d.set_flags(data.flags);
  102. d.set_mask(data.mask);
  103. d.set_max_idle_ns(data.max_idle_ns);
  104. d.set_mult(data.mult);
  105. d.set_name(data.name);
  106. d.set_rating(data.rating);
  107. d.set_shift(data.shift);
  108. d.watchdog_last = data.watchdog_last;
  109. return Ok(());
  110. }
  111. }
  112. // 参考:https://code.dragonos.org.cn/xref/linux-6.6.21/arch/x86/include/asm/mach_timer.h?fi=mach_prepare_counter
  113. #[allow(dead_code)]
  114. pub const CALIBRATE_TIME_MSEC: u64 = 30;
  115. pub const CALIBRATE_LATCH: u64 = (PIT_TICK_RATE * CALIBRATE_TIME_MSEC + 1000 / 2) / 1000;
  116. #[inline(always)]
  117. #[allow(dead_code)]
  118. pub fn mach_prepare_counter() {
  119. unsafe {
  120. // 将Gate位设置为高电平,从而禁用扬声器
  121. CurrentPortIOArch::out8(0x61, (CurrentPortIOArch::in8(0x61) & !0x02) | 0x01);
  122. // 针对计数器/定时器控制器的通道2进行配置,设置为模式0,二进制计数
  123. CurrentPortIOArch::out8(0x43, 0xb0);
  124. CurrentPortIOArch::out8(0x42, (CALIBRATE_LATCH & 0xff) as u8);
  125. CurrentPortIOArch::out8(0x42, (CALIBRATE_LATCH >> 8) as u8);
  126. }
  127. }
  128. #[allow(dead_code)]
  129. pub fn mach_countup(count: &mut u32) {
  130. let mut tmp: u32 = 0;
  131. loop {
  132. tmp += 1;
  133. if (unsafe { CurrentPortIOArch::in8(0x61) } & 0x20) != 0 {
  134. break;
  135. }
  136. }
  137. *count = tmp;
  138. }
  139. #[allow(dead_code)]
  140. const PMTMR_EXPECTED_RATE: u64 =
  141. (CALIBRATE_LATCH * (PMTMR_TICKS_PER_SEC >> 10)) / (PIT_TICK_RATE >> 10);
  142. /// # 验证ACPI PM Timer的运行速率是否在预期范围内(在x86_64架构以外的情况下验证)
  143. ///
  144. /// ## 返回值
  145. /// - i32:如果为0则表示在预期范围内,否则不在
  146. #[cfg(not(target_arch = "x86_64"))]
  147. #[allow(dead_code)]
  148. fn verify_pmtmr_rate() -> bool {
  149. let mut count: u32 = 0;
  150. mach_prepare_counter();
  151. let value1 = clocksource_acpi_pm().read().data();
  152. mach_countup(&mut count);
  153. let value2 = clocksource_acpi_pm().read().data();
  154. let delta = (value2 - value1) & ACPI_PM_MASK;
  155. if (delta < (PMTMR_EXPECTED_RATE * 19) / 20) || (delta > (PMTMR_EXPECTED_RATE * 21) / 20) {
  156. kinfo!(
  157. "PM Timer running at invalid rate: {}",
  158. 100 * delta / PMTMR_EXPECTED_RATE
  159. );
  160. return false;
  161. }
  162. return true;
  163. }
  164. #[cfg(target_arch = "x86_64")]
  165. fn verify_pmtmr_rate() -> bool {
  166. return true;
  167. }
  168. const ACPI_PM_MONOTONIC_CHECKS: u32 = 10;
  169. const ACPI_PM_READ_CHECKS: u32 = 10000;
  170. /// # 解析fadt
  171. fn find_acpi_pm_clock() -> Result<(), SystemError> {
  172. let fadt = acpi_manager()
  173. .tables()
  174. .unwrap()
  175. .find_table::<Fadt>()
  176. .expect("failed to find FADT table");
  177. let pm_timer_block = fadt.pm_timer_block().map_err(|_| SystemError::ENODEV)?;
  178. let pm_timer_block = pm_timer_block.ok_or(SystemError::ENODEV)?;
  179. let pmtmr_addr = pm_timer_block.address;
  180. unsafe {
  181. PMTMR_IO_PORT.store(pmtmr_addr as u32, Ordering::SeqCst);
  182. }
  183. kinfo!("apic_pmtmr I/O port: {}", unsafe {
  184. PMTMR_IO_PORT.load(Ordering::SeqCst)
  185. });
  186. return Ok(());
  187. }
  188. /// # 初始化ACPI PM Timer作为系统时钟源
  189. // #[unified_init(INITCALL_FS)]
  190. #[inline(never)]
  191. #[allow(dead_code)]
  192. pub fn init_acpi_pm_clocksource() -> Result<(), SystemError> {
  193. let acpi_pm = Acpipm::new();
  194. unsafe {
  195. CLOCKSOURCE_ACPI_PM = Some(acpi_pm);
  196. }
  197. // 解析fadt
  198. find_acpi_pm_clock()?;
  199. // 检查pmtmr_io_port是否被设置
  200. if unsafe { PMTMR_IO_PORT.load(Ordering::SeqCst) } == 0 {
  201. return Err(SystemError::ENODEV);
  202. }
  203. // 验证ACPI PM Timer作为时钟源的稳定性和一致性
  204. for j in 0..ACPI_PM_MONOTONIC_CHECKS {
  205. let mut cnt = 100 * j;
  206. while cnt > 0 {
  207. cnt -= 1;
  208. }
  209. let value1 = clocksource_acpi_pm().read().data();
  210. let mut i = 0;
  211. for _ in 0..ACPI_PM_READ_CHECKS {
  212. let value2 = clocksource_acpi_pm().read().data();
  213. if value2 == value1 {
  214. i += 1;
  215. continue;
  216. }
  217. if value2 > value1 {
  218. break;
  219. }
  220. if (value2 < value1) && (value2 < 0xfff) {
  221. break;
  222. }
  223. kinfo!("PM Timer had inconsistens results: {} {}", value1, value2);
  224. unsafe {
  225. PMTMR_IO_PORT.store(0, Ordering::SeqCst);
  226. }
  227. return Err(SystemError::EINVAL);
  228. }
  229. if i == ACPI_PM_READ_CHECKS {
  230. kinfo!("PM Timer failed consistency check: {}", value1);
  231. unsafe {
  232. PMTMR_IO_PORT.store(0, Ordering::SeqCst);
  233. }
  234. return Err(SystemError::EINVAL);
  235. }
  236. }
  237. // 检查ACPI PM Timer的频率是否正确
  238. if !verify_pmtmr_rate() {
  239. unsafe {
  240. PMTMR_IO_PORT.store(0, Ordering::SeqCst);
  241. }
  242. }
  243. // 检查TSC时钟源的监视器是否被禁用,如果被禁用则将时钟源的标志设置为CLOCK_SOURCE_MUST_VERIFY
  244. // 没有实现clocksource_selecet_watchdog函数,所以这里设置为false
  245. let tsc_clocksource_watchdog_disabled = false;
  246. if tsc_clocksource_watchdog_disabled {
  247. clocksource_acpi_pm().0.lock_irqsave().data.flags |=
  248. ClocksourceFlags::CLOCK_SOURCE_MUST_VERIFY;
  249. }
  250. // 注册ACPI PM Timer
  251. let acpi_pmtmr = clocksource_acpi_pm() as Arc<dyn Clocksource>;
  252. match acpi_pmtmr.register(100, PMTMR_TICKS_PER_SEC as u32) {
  253. Ok(_) => {
  254. kinfo!("ACPI PM Timer registered as clocksource sccessfully");
  255. return Ok(());
  256. }
  257. Err(_) => {
  258. kinfo!("ACPI PM Timer init registered failed");
  259. return Err(SystemError::ENOSYS);
  260. }
  261. };
  262. }