APIC.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  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 setup_ap_boot_environment();
  23. void boot_aps();
  24. void enable(u32 cpu);
  25. void init_finished(u32 cpu);
  26. void broadcast_ipi();
  27. void send_ipi(u32 cpu);
  28. static u8 spurious_interrupt_vector();
  29. Thread* get_idle_thread(u32 cpu) const;
  30. u32 enabled_processor_count() const { return m_processor_enabled_cnt; }
  31. APICTimer* initialize_timers(HardwareTimerBase&);
  32. APICTimer* get_timer() const { return m_apic_timer; }
  33. enum class TimerMode {
  34. OneShot,
  35. Periodic,
  36. TSCDeadline
  37. };
  38. void setup_local_timer(u32, TimerMode, bool);
  39. u32 get_timer_current_count();
  40. u32 get_timer_divisor();
  41. private:
  42. struct ICRReg {
  43. enum DeliveryMode {
  44. Fixed = 0x0,
  45. LowPriority = 0x1,
  46. SMI = 0x2,
  47. NMI = 0x4,
  48. INIT = 0x5,
  49. StartUp = 0x6,
  50. };
  51. enum DestinationMode {
  52. Physical = 0x0,
  53. Logical = 0x1,
  54. };
  55. enum Level {
  56. DeAssert = 0x0,
  57. Assert = 0x1
  58. };
  59. enum class TriggerMode {
  60. Edge = 0x0,
  61. Level = 0x1,
  62. };
  63. enum DestinationShorthand {
  64. NoShorthand = 0x0,
  65. Self = 0x1,
  66. AllIncludingSelf = 0x2,
  67. AllExcludingSelf = 0x3,
  68. };
  69. u8 vector { 0 };
  70. u32 destination { 0 };
  71. DeliveryMode delivery_mode { DeliveryMode::Fixed };
  72. DestinationMode destination_mode { DestinationMode::Physical };
  73. Level level { Level::DeAssert };
  74. TriggerMode trigger_mode { TriggerMode::Edge };
  75. DestinationShorthand destination_short { DestinationShorthand::NoShorthand };
  76. u32 x_low() const { return (u32)vector | (delivery_mode << 8) | (destination_mode << 11) | (level << 14) | (static_cast<u32>(trigger_mode) << 15) | (destination_short << 18); }
  77. u32 x_high() const { return destination << 24; }
  78. u64 x2_value() const { return ((u64)destination << 32) | x_low(); }
  79. };
  80. OwnPtr<Memory::Region> m_apic_base;
  81. Vector<OwnPtr<Processor>> m_ap_processor_info;
  82. Vector<OwnPtr<Memory::Region>> m_ap_temporary_boot_stacks;
  83. Vector<Thread*> m_ap_idle_threads;
  84. OwnPtr<Memory::Region> m_ap_boot_environment;
  85. Atomic<u8> m_apic_ap_count { 0 };
  86. Atomic<u8> m_apic_ap_continue { 0 };
  87. u32 m_processor_cnt { 0 };
  88. u32 m_processor_enabled_cnt { 0 };
  89. APICTimer* m_apic_timer { nullptr };
  90. bool m_is_x2 { false };
  91. static PhysicalAddress get_base();
  92. void set_base(const PhysicalAddress& base);
  93. void write_register(u32 offset, u32 value);
  94. u32 read_register(u32 offset);
  95. void set_lvt(u32 offset, u8 interrupt);
  96. void set_siv(u32 offset, u8 interrupt);
  97. void wait_for_pending_icr();
  98. void write_icr(const ICRReg& icr);
  99. void do_boot_aps();
  100. };
  101. }