HPET.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. /*
  2. * Copyright (c) 2020, Liav A. <liavalb@hotmail.co.il>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/StringView.h>
  7. #include <Kernel/ACPI/Parser.h>
  8. #include <Kernel/Debug.h>
  9. #include <Kernel/Interrupts/InterruptManagement.h>
  10. #include <Kernel/Memory/MemoryManager.h>
  11. #include <Kernel/Memory/TypedMapping.h>
  12. #include <Kernel/Sections.h>
  13. #include <Kernel/Time/HPET.h>
  14. #include <Kernel/Time/HPETComparator.h>
  15. #include <Kernel/Time/TimeManagement.h>
  16. namespace Kernel {
  17. #define ABSOLUTE_MAXIMUM_COUNTER_TICK_PERIOD 0x05F5E100
  18. #define NANOSECOND_PERIOD_TO_HERTZ(x) 1000000000 / x
  19. #define HERTZ_TO_MEGAHERTZ(x) (x / 1000000)
  20. namespace HPETFlags {
  21. enum class Attributes {
  22. Counter64BitCapable = 1 << 13,
  23. LegacyReplacementRouteCapable = 1 << 15
  24. };
  25. enum class Configuration {
  26. Enable = 1 << 0,
  27. LegacyReplacementRoute = 1 << 1
  28. };
  29. enum class TimerConfiguration : u32 {
  30. LevelTriggered = 1 << 1,
  31. InterruptEnable = 1 << 2,
  32. GeneratePeriodicInterrupt = 1 << 3,
  33. PeriodicInterruptCapable = 1 << 4,
  34. Timer64BitsCapable = 1 << 5,
  35. ValueSet = 1 << 6,
  36. Force32BitMode = 1 << 8,
  37. FSBInterruptEnable = 1 << 14,
  38. FSBInterruptDelivery = 1 << 15
  39. };
  40. };
  41. struct [[gnu::packed]] HPETRegister {
  42. volatile u32 low;
  43. volatile u32 high;
  44. };
  45. struct [[gnu::packed]] TimerStructure {
  46. volatile u32 capabilities;
  47. volatile u32 interrupt_routing;
  48. HPETRegister comparator_value;
  49. volatile u64 fsb_interrupt_route;
  50. u64 reserved;
  51. };
  52. struct [[gnu::packed]] HPETCapabilityRegister {
  53. // Note: We must do a 32 bit access to offsets 0x0, or 0x4 only, according to HPET spec.
  54. volatile u32 attributes;
  55. volatile u32 main_counter_tick_period;
  56. u64 reserved;
  57. };
  58. struct [[gnu::packed]] HPETRegistersBlock {
  59. HPETCapabilityRegister capabilities;
  60. HPETRegister configuration;
  61. u64 reserved1;
  62. HPETRegister interrupt_status;
  63. u8 reserved2[0xF0 - 0x28];
  64. HPETRegister main_counter_value;
  65. u64 reserved3;
  66. TimerStructure timers[32];
  67. };
  68. static_assert(__builtin_offsetof(HPETRegistersBlock, main_counter_value) == 0xf0);
  69. static_assert(__builtin_offsetof(HPETRegistersBlock, timers[0]) == 0x100);
  70. static_assert(__builtin_offsetof(HPETRegistersBlock, timers[1]) == 0x120);
  71. // Note: The HPET specification says it reserves the range of byte 0x160 to
  72. // 0x400 for comparators 3-31, but for implementing all 32 comparators the HPET
  73. // MMIO space has to be 1280 bytes and not 1024 bytes.
  74. static_assert(sizeof(HPETRegistersBlock) == 0x500);
  75. static u64 read_register_safe64(const HPETRegister& reg)
  76. {
  77. // As per 2.4.7 this reads the 64 bit value in a consistent manner
  78. // using only 32 bit reads
  79. u32 low, high = reg.high;
  80. for (;;) {
  81. low = reg.low;
  82. u32 new_high = reg.high;
  83. if (new_high == high)
  84. break;
  85. high = new_high;
  86. }
  87. return ((u64)high << 32) | (u64)low;
  88. }
  89. static HPET* s_hpet;
  90. static bool hpet_initialized { false };
  91. bool HPET::initialized()
  92. {
  93. return hpet_initialized;
  94. }
  95. HPET& HPET::the()
  96. {
  97. VERIFY(HPET::initialized());
  98. VERIFY(s_hpet != nullptr);
  99. return *s_hpet;
  100. }
  101. UNMAP_AFTER_INIT bool HPET::test_and_initialize()
  102. {
  103. VERIFY(!HPET::initialized());
  104. hpet_initialized = true;
  105. auto hpet = ACPI::Parser::the()->find_table("HPET");
  106. if (hpet.is_null())
  107. return false;
  108. dmesgln("HPET @ {}", hpet);
  109. auto sdt = Memory::map_typed<ACPI::Structures::HPET>(hpet);
  110. // Note: HPET is only usable from System Memory
  111. VERIFY(sdt->event_timer_block.address_space == (u8)ACPI::GenericAddressStructure::AddressSpace::SystemMemory);
  112. if (TimeManagement::is_hpet_periodic_mode_allowed()) {
  113. if (!check_for_exisiting_periodic_timers()) {
  114. dbgln("HPET: No periodic capable timers");
  115. return false;
  116. }
  117. }
  118. new HPET(PhysicalAddress(hpet));
  119. return true;
  120. }
  121. UNMAP_AFTER_INIT bool HPET::check_for_exisiting_periodic_timers()
  122. {
  123. auto hpet = ACPI::Parser::the()->find_table("HPET");
  124. if (hpet.is_null())
  125. return false;
  126. auto sdt = Memory::map_typed<ACPI::Structures::HPET>(hpet);
  127. VERIFY(sdt->event_timer_block.address_space == 0);
  128. auto registers = Memory::map_typed<HPETRegistersBlock>(PhysicalAddress(sdt->event_timer_block.address));
  129. size_t timers_count = ((registers->capabilities.attributes >> 8) & 0x1f) + 1;
  130. for (size_t index = 0; index < timers_count; index++) {
  131. if (registers->timers[index].capabilities & (u32)HPETFlags::TimerConfiguration::PeriodicInterruptCapable)
  132. return true;
  133. }
  134. return false;
  135. }
  136. void HPET::global_disable()
  137. {
  138. auto& regs = registers();
  139. regs.configuration.low = regs.configuration.low & ~(u32)HPETFlags::Configuration::Enable;
  140. }
  141. void HPET::global_enable()
  142. {
  143. auto& regs = registers();
  144. regs.configuration.low = regs.configuration.low | (u32)HPETFlags::Configuration::Enable;
  145. }
  146. void HPET::update_periodic_comparator_value()
  147. {
  148. // According to 2.3.9.2.2 the only safe way to change the periodic timer frequency
  149. // is to disable all periodic timers, reset the main counter and each timer's comparator value.
  150. // This introduces time drift, so it should be avoided unless absolutely necessary.
  151. global_disable();
  152. auto& regs = registers();
  153. u64 previous_main_value = (u64)regs.main_counter_value.low | ((u64)regs.main_counter_value.high << 32);
  154. m_main_counter_drift += previous_main_value - m_main_counter_last_read;
  155. m_main_counter_last_read = 0;
  156. regs.main_counter_value.low = 0;
  157. if (m_main_counter_64bits)
  158. regs.main_counter_value.high = 0;
  159. for (auto& comparator : m_comparators) {
  160. auto& timer = regs.timers[comparator.comparator_number()];
  161. if (!comparator.is_enabled())
  162. continue;
  163. if (comparator.is_periodic()) {
  164. // Note that this means we're restarting all periodic timers. There is no
  165. // way to resume periodic timers properly because we reset the main counter
  166. // and we can only write the period into the comparator value...
  167. timer.capabilities = timer.capabilities | (u32)HPETFlags::TimerConfiguration::ValueSet;
  168. u64 value = ns_to_raw_counter_ticks(1000000000ull / comparator.ticks_per_second());
  169. dbgln_if(HPET_DEBUG, "HPET: Update periodic comparator {} comparator value to {} main value was: {}",
  170. comparator.comparator_number(),
  171. value,
  172. previous_main_value);
  173. timer.comparator_value.low = (u32)value;
  174. if (comparator.is_64bit_capable()) {
  175. timer.capabilities = timer.capabilities | (u32)HPETFlags::TimerConfiguration::ValueSet;
  176. timer.comparator_value.high = (u32)(value >> 32);
  177. }
  178. } else {
  179. // Set the new target comparator value to the delta to the remaining ticks
  180. u64 current_value = (u64)timer.comparator_value.low | ((u64)timer.comparator_value.high << 32);
  181. u64 value = current_value - previous_main_value;
  182. dbgln_if(HPET_DEBUG, "HPET: Update non-periodic comparator {} comparator value from {} to {} main value was: {}",
  183. comparator.comparator_number(),
  184. current_value,
  185. value,
  186. previous_main_value);
  187. timer.comparator_value.low = (u32)value;
  188. if (comparator.is_64bit_capable())
  189. timer.comparator_value.high = (u32)(value >> 32);
  190. }
  191. }
  192. global_enable();
  193. }
  194. void HPET::update_non_periodic_comparator_value(const HPETComparator& comparator)
  195. {
  196. VERIFY_INTERRUPTS_DISABLED();
  197. VERIFY(!comparator.is_periodic());
  198. VERIFY(comparator.comparator_number() <= m_comparators.size());
  199. auto& regs = registers();
  200. auto& timer = regs.timers[comparator.comparator_number()];
  201. u64 value = frequency() / comparator.ticks_per_second();
  202. // NOTE: If the main counter passes this new value before we finish writing it, we will never receive an interrupt!
  203. u64 new_counter_value = read_main_counter() + value;
  204. timer.comparator_value.high = (u32)(new_counter_value >> 32);
  205. timer.comparator_value.low = (u32)new_counter_value;
  206. }
  207. u64 HPET::update_time(u64& seconds_since_boot, u32& ticks_this_second, bool query_only)
  208. {
  209. // Should only be called by the time keeper interrupt handler!
  210. u64 current_value = read_main_counter();
  211. u64 delta_ticks = m_main_counter_drift;
  212. if (current_value >= m_main_counter_last_read) {
  213. delta_ticks += current_value - m_main_counter_last_read;
  214. } else {
  215. // the counter wrapped around
  216. delta_ticks += m_main_counter_last_read - current_value;
  217. if (!m_main_counter_64bits)
  218. m_32bit_main_counter_wraps++;
  219. }
  220. u64 ticks_since_last_second = (u64)ticks_this_second + delta_ticks;
  221. auto ticks_per_second = frequency();
  222. if (ticks_since_last_second >= ticks_per_second) {
  223. seconds_since_boot += ticks_since_last_second / ticks_per_second;
  224. ticks_this_second = ticks_since_last_second % ticks_per_second;
  225. } else {
  226. ticks_this_second = ticks_since_last_second;
  227. }
  228. if (!query_only) {
  229. m_main_counter_drift = 0;
  230. m_main_counter_last_read = current_value;
  231. }
  232. // Return the time passed (in ns) since last time update_time was called
  233. return (delta_ticks * 1000000000ull) / ticks_per_second;
  234. }
  235. u64 HPET::read_main_counter_unsafe() const
  236. {
  237. auto& main_counter = registers().main_counter_value;
  238. if (m_main_counter_64bits)
  239. return ((u64)main_counter.high << 32) | (u64)main_counter.low;
  240. return ((u64)m_32bit_main_counter_wraps << 32) | (u64)main_counter.low;
  241. }
  242. u64 HPET::read_main_counter() const
  243. {
  244. if (m_main_counter_64bits)
  245. return read_register_safe64(registers().main_counter_value);
  246. auto& main_counter = registers().main_counter_value;
  247. u32 wraps = m_32bit_main_counter_wraps;
  248. u32 last_read_value = m_main_counter_last_read & 0xffffffff;
  249. u32 current_value = main_counter.low;
  250. if (current_value < last_read_value)
  251. wraps++;
  252. return ((u64)wraps << 32) | (u64)current_value;
  253. }
  254. void HPET::enable_periodic_interrupt(const HPETComparator& comparator)
  255. {
  256. dbgln_if(HPET_DEBUG, "HPET: Set comparator {} to be periodic.", comparator.comparator_number());
  257. disable(comparator);
  258. VERIFY(comparator.comparator_number() <= m_comparators.size());
  259. auto& timer = registers().timers[comparator.comparator_number()];
  260. auto capabilities = timer.capabilities;
  261. VERIFY(capabilities & (u32)HPETFlags::TimerConfiguration::PeriodicInterruptCapable);
  262. timer.capabilities = capabilities | (u32)HPETFlags::TimerConfiguration::GeneratePeriodicInterrupt;
  263. if (comparator.is_enabled())
  264. enable(comparator);
  265. }
  266. void HPET::disable_periodic_interrupt(const HPETComparator& comparator)
  267. {
  268. dbgln_if(HPET_DEBUG, "HPET: Disable periodic interrupt in comparator {}", comparator.comparator_number());
  269. disable(comparator);
  270. VERIFY(comparator.comparator_number() <= m_comparators.size());
  271. auto& timer = registers().timers[comparator.comparator_number()];
  272. auto capabilities = timer.capabilities;
  273. VERIFY(capabilities & (u32)HPETFlags::TimerConfiguration::PeriodicInterruptCapable);
  274. timer.capabilities = capabilities & ~(u32)HPETFlags::TimerConfiguration::GeneratePeriodicInterrupt;
  275. if (comparator.is_enabled())
  276. enable(comparator);
  277. }
  278. void HPET::disable(const HPETComparator& comparator)
  279. {
  280. dbgln_if(HPET_DEBUG, "HPET: Disable comparator {}", comparator.comparator_number());
  281. VERIFY(comparator.comparator_number() <= m_comparators.size());
  282. auto& timer = registers().timers[comparator.comparator_number()];
  283. timer.capabilities = timer.capabilities & ~(u32)HPETFlags::TimerConfiguration::InterruptEnable;
  284. }
  285. void HPET::enable(const HPETComparator& comparator)
  286. {
  287. dbgln_if(HPET_DEBUG, "HPET: Enable comparator {}", comparator.comparator_number());
  288. VERIFY(comparator.comparator_number() <= m_comparators.size());
  289. auto& timer = registers().timers[comparator.comparator_number()];
  290. timer.capabilities = timer.capabilities | (u32)HPETFlags::TimerConfiguration::InterruptEnable;
  291. }
  292. Vector<unsigned> HPET::capable_interrupt_numbers(const HPETComparator& comparator)
  293. {
  294. VERIFY(comparator.comparator_number() <= m_comparators.size());
  295. Vector<unsigned> capable_interrupts;
  296. auto& comparator_registers = registers().timers[comparator.comparator_number()];
  297. u32 interrupt_bitfield = comparator_registers.interrupt_routing;
  298. for (size_t index = 0; index < 32; index++) {
  299. if (interrupt_bitfield & 1)
  300. capable_interrupts.append(index);
  301. interrupt_bitfield >>= 1;
  302. }
  303. return capable_interrupts;
  304. }
  305. Vector<unsigned> HPET::capable_interrupt_numbers(u8 comparator_number)
  306. {
  307. VERIFY(comparator_number <= m_comparators.size());
  308. Vector<unsigned> capable_interrupts;
  309. auto& comparator_registers = registers().timers[comparator_number];
  310. u32 interrupt_bitfield = comparator_registers.interrupt_routing;
  311. for (size_t index = 0; index < 32; index++) {
  312. if (interrupt_bitfield & 1)
  313. capable_interrupts.append(index);
  314. interrupt_bitfield >>= 1;
  315. }
  316. return capable_interrupts;
  317. }
  318. void HPET::set_comparator_irq_vector(u8 comparator_number, u8 irq_vector)
  319. {
  320. VERIFY(comparator_number <= m_comparators.size());
  321. auto& comparator_registers = registers().timers[comparator_number];
  322. comparator_registers.capabilities = comparator_registers.capabilities | (irq_vector << 9);
  323. }
  324. bool HPET::is_periodic_capable(u8 comparator_number) const
  325. {
  326. VERIFY(comparator_number <= m_comparators.size());
  327. auto& comparator_registers = registers().timers[comparator_number];
  328. return comparator_registers.capabilities & (u32)HPETFlags::TimerConfiguration::PeriodicInterruptCapable;
  329. }
  330. bool HPET::is_64bit_capable(u8 comparator_number) const
  331. {
  332. VERIFY(comparator_number <= m_comparators.size());
  333. auto& comparator_registers = registers().timers[comparator_number];
  334. return comparator_registers.capabilities & (u32)HPETFlags::TimerConfiguration::Timer64BitsCapable;
  335. }
  336. void HPET::set_comparators_to_optimal_interrupt_state(size_t)
  337. {
  338. // FIXME: Implement this method for allowing to use HPET timers 2-31...
  339. VERIFY_NOT_REACHED();
  340. }
  341. PhysicalAddress HPET::find_acpi_hpet_registers_block()
  342. {
  343. auto sdt = Memory::map_typed<const volatile ACPI::Structures::HPET>(m_physical_acpi_hpet_table);
  344. VERIFY(sdt->event_timer_block.address_space == (u8)ACPI::GenericAddressStructure::AddressSpace::SystemMemory);
  345. return PhysicalAddress(sdt->event_timer_block.address);
  346. }
  347. const HPETRegistersBlock& HPET::registers() const
  348. {
  349. return *(const HPETRegistersBlock*)m_hpet_mmio_region->vaddr().offset(m_physical_acpi_hpet_registers.offset_in_page()).as_ptr();
  350. }
  351. HPETRegistersBlock& HPET::registers()
  352. {
  353. return *(HPETRegistersBlock*)m_hpet_mmio_region->vaddr().offset(m_physical_acpi_hpet_registers.offset_in_page()).as_ptr();
  354. }
  355. u64 HPET::raw_counter_ticks_to_ns(u64 raw_ticks) const
  356. {
  357. // ABSOLUTE_MAXIMUM_COUNTER_TICK_PERIOD == 100 nanoseconds
  358. return (raw_ticks * (u64)registers().capabilities.main_counter_tick_period * 100ull) / ABSOLUTE_MAXIMUM_COUNTER_TICK_PERIOD;
  359. }
  360. u64 HPET::ns_to_raw_counter_ticks(u64 ns) const
  361. {
  362. return (ns * 1000000ull) / (u64)registers().capabilities.main_counter_tick_period;
  363. }
  364. UNMAP_AFTER_INIT HPET::HPET(PhysicalAddress acpi_hpet)
  365. : m_physical_acpi_hpet_table(acpi_hpet)
  366. , m_physical_acpi_hpet_registers(find_acpi_hpet_registers_block())
  367. , m_hpet_mmio_region(MM.allocate_kernel_region(m_physical_acpi_hpet_registers.page_base(), PAGE_SIZE, "HPET MMIO", Memory::Region::Access::ReadWrite))
  368. {
  369. s_hpet = this; // Make available as soon as possible so that IRQs can use it
  370. auto sdt = Memory::map_typed<const volatile ACPI::Structures::HPET>(m_physical_acpi_hpet_table);
  371. m_vendor_id = sdt->pci_vendor_id;
  372. m_minimum_tick = sdt->mininum_clock_tick;
  373. dmesgln("HPET: Minimum clock tick - {}", m_minimum_tick);
  374. auto& regs = registers();
  375. // Note: We must do a 32 bit access to offsets 0x0, or 0x4 only.
  376. size_t timers_count = ((regs.capabilities.attributes >> 8) & 0x1f) + 1;
  377. m_main_counter_64bits = (regs.capabilities.attributes & (u32)HPETFlags::Attributes::Counter64BitCapable) != 0;
  378. dmesgln("HPET: Timers count - {}", timers_count);
  379. dmesgln("HPET: Main counter size: {}", (m_main_counter_64bits ? "64-bit" : "32-bit"));
  380. for (size_t i = 0; i < timers_count; i++) {
  381. bool capable_64_bit = regs.timers[i].capabilities & (u32)HPETFlags::TimerConfiguration::Timer64BitsCapable;
  382. dmesgln("HPET: Timer[{}] comparator size: {}, mode: {}", i,
  383. (capable_64_bit ? "64-bit" : "32-bit"),
  384. ((!capable_64_bit || (regs.timers[i].capabilities & (u32)HPETFlags::TimerConfiguration::Force32BitMode)) ? "32-bit" : "64-bit"));
  385. }
  386. VERIFY(timers_count >= 2);
  387. global_disable();
  388. m_frequency = NANOSECOND_PERIOD_TO_HERTZ(raw_counter_ticks_to_ns(1));
  389. dmesgln("HPET: frequency {} Hz ({} MHz) resolution: {} ns", m_frequency, HERTZ_TO_MEGAHERTZ(m_frequency), raw_counter_ticks_to_ns(1));
  390. VERIFY(regs.capabilities.main_counter_tick_period <= ABSOLUTE_MAXIMUM_COUNTER_TICK_PERIOD);
  391. // Reset the counter, just in case... (needs to match m_main_counter_last_read)
  392. regs.main_counter_value.high = 0;
  393. regs.main_counter_value.low = 0;
  394. if (regs.capabilities.attributes & (u32)HPETFlags::Attributes::LegacyReplacementRouteCapable)
  395. regs.configuration.low = regs.configuration.low | (u32)HPETFlags::Configuration::LegacyReplacementRoute;
  396. m_comparators.append(HPETComparator::create(0, 0, is_periodic_capable(0), is_64bit_capable(0)));
  397. m_comparators.append(HPETComparator::create(1, 8, is_periodic_capable(1), is_64bit_capable(1)));
  398. global_enable();
  399. }
  400. }