APIC.h 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. /*
  2. * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #pragma once
  7. #include <AK/Types.h>
  8. #include <Kernel/Memory/MemoryManager.h>
  9. #include <Kernel/Time/HardwareTimer.h>
  10. namespace Kernel {
  11. class APICTimer;
  12. struct LocalAPIC {
  13. u32 apic_id;
  14. };
  15. class APIC {
  16. public:
  17. static APIC& the();
  18. static void initialize();
  19. static bool initialized();
  20. bool init_bsp();
  21. void eoi();
  22. void boot_aps();
  23. void enable(u32 cpu);
  24. void init_finished(u32 cpu);
  25. void broadcast_ipi();
  26. void send_ipi(u32 cpu);
  27. static u8 spurious_interrupt_vector();
  28. Thread* get_idle_thread(u32 cpu) const;
  29. u32 enabled_processor_count() const { return m_processor_enabled_cnt; }
  30. APICTimer* initialize_timers(HardwareTimerBase&);
  31. APICTimer* get_timer() const { return m_apic_timer; }
  32. enum class TimerMode {
  33. OneShot,
  34. Periodic,
  35. TSCDeadline
  36. };
  37. void setup_local_timer(u32, TimerMode, bool);
  38. u32 get_timer_current_count();
  39. u32 get_timer_divisor();
  40. private:
  41. struct ICRReg {
  42. enum DeliveryMode {
  43. Fixed = 0x0,
  44. LowPriority = 0x1,
  45. SMI = 0x2,
  46. NMI = 0x4,
  47. INIT = 0x5,
  48. StartUp = 0x6,
  49. };
  50. enum DestinationMode {
  51. Physical = 0x0,
  52. Logical = 0x1,
  53. };
  54. enum Level {
  55. DeAssert = 0x0,
  56. Assert = 0x1
  57. };
  58. enum class TriggerMode {
  59. Edge = 0x0,
  60. Level = 0x1,
  61. };
  62. enum DestinationShorthand {
  63. NoShorthand = 0x0,
  64. Self = 0x1,
  65. AllIncludingSelf = 0x2,
  66. AllExcludingSelf = 0x3,
  67. };
  68. u8 vector { 0 };
  69. u32 destination { 0 };
  70. DeliveryMode delivery_mode { DeliveryMode::Fixed };
  71. DestinationMode destination_mode { DestinationMode::Physical };
  72. Level level { Level::DeAssert };
  73. TriggerMode trigger_mode { TriggerMode::Edge };
  74. DestinationShorthand destination_short { DestinationShorthand::NoShorthand };
  75. u32 x_low() const { return (u32)vector | (delivery_mode << 8) | (destination_mode << 11) | (level << 14) | (static_cast<u32>(trigger_mode) << 15) | (destination_short << 18); }
  76. u32 x_high() const { return destination << 24; }
  77. u64 x2_value() const { return ((u64)destination << 32) | x_low(); }
  78. };
  79. OwnPtr<Memory::Region> m_apic_base;
  80. Vector<OwnPtr<Processor>> m_ap_processor_info;
  81. Vector<Thread*> m_ap_idle_threads;
  82. Atomic<u8> m_apic_ap_count { 0 };
  83. Atomic<u8> m_apic_ap_continue { 0 };
  84. u32 m_processor_cnt { 0 };
  85. u32 m_processor_enabled_cnt { 0 };
  86. APICTimer* m_apic_timer { nullptr };
  87. bool m_is_x2 { false };
  88. static PhysicalAddress get_base();
  89. void set_base(const PhysicalAddress& base);
  90. void write_register(u32 offset, u32 value);
  91. u32 read_register(u32 offset);
  92. void set_lvt(u32 offset, u8 interrupt);
  93. void set_siv(u32 offset, u8 interrupt);
  94. void wait_for_pending_icr();
  95. void write_icr(const ICRReg& icr);
  96. void do_boot_aps();
  97. };
  98. }