You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
118 lines
3.6 KiB
C++
118 lines
3.6 KiB
C++
/*! \file
|
|
* \brief Access to internals of a CPU \ref Core
|
|
*/
|
|
|
|
/*! \defgroup sync CPU Synchronization
|
|
*
|
|
* The synchronization module houses functions useful for orchestrating multiple
|
|
* processors and their activities. Synchronisation, in this case, means
|
|
* handling the resource contention between multiple participants, running on
|
|
* either the same or different cores.
|
|
*/
|
|
|
|
#pragma once
|
|
#include "../types.h"
|
|
#include "core_cr.h"
|
|
#include "core_interrupt.h"
|
|
#include "core_msr.h"
|
|
|
|
/*! \brief Implements an abstraction for CPU internals.
|
|
*
|
|
* These internals include functions to \ref Core::Interrupt "allow or deny
|
|
* interrupts", access \ref Core::CR "control registers".
|
|
*/
|
|
namespace Core {
|
|
|
|
/*! \brief Maximum number of supported CPUs
|
|
*/
|
|
constexpr unsigned MAX = 8;
|
|
|
|
/*! \brief Get the ID of the current CPU core
|
|
* using \ref LAPIC::getID() with an internal lookup table.
|
|
*
|
|
* \return ID of current Core (a number between 0 and \ref Core::MAX)
|
|
*/
|
|
unsigned getID();
|
|
|
|
/*! \brief Initialize this CPU core
|
|
*
|
|
* Mark this core as *online* and setup the cores \ref LAPIC by assigning it a
|
|
* unique \ref APIC::getLogicalAPICID() "logical APIC ID"
|
|
*
|
|
* \note Should only be called from \ref kernel_init() during startup.
|
|
*/
|
|
void init();
|
|
|
|
/*! \brief Deinitialize this CPU core
|
|
*
|
|
* Mark this Core as *offline*
|
|
*
|
|
* \note Should only be called from \ref kernel_init() after returning from
|
|
* `main()` or `main_ap()`.
|
|
*/
|
|
void exit();
|
|
|
|
/*! \brief Get number of available CPU cores
|
|
*
|
|
* \return total number of cores
|
|
*/
|
|
unsigned count();
|
|
|
|
/*! \brief Get number of successfully started (and currently active) CPU cores
|
|
*
|
|
* \return total number of online cores
|
|
*/
|
|
unsigned countOnline();
|
|
|
|
/*! \brief Check if CPU core is currently active
|
|
* \param core_id ID of the CPU core
|
|
* \return `true` if successfully started and is currently active
|
|
*/
|
|
bool isOnline(uint8_t core_id);
|
|
|
|
/*! \brief Gives the core a hint that it is executing a spinloop and should
|
|
* sleep "shortly"
|
|
*
|
|
* Improves the over-all performance when executing a spinloop by waiting a
|
|
* short moment reduce the load on the memory.
|
|
*
|
|
* \see [ISDMv2, Chapter 4. PAUSE - Spin Loop
|
|
* Hint](intel_manual_vol2.pdf#page=887)
|
|
*/
|
|
inline void pause() { asm volatile("pause\n\t" : : : "memory"); }
|
|
|
|
/*! \brief Halt the CPU core until the next interrupt.
|
|
*
|
|
* Halts the current CPU core such that it will wake up on the next interrupt.
|
|
* Internally, this function first enables the interrupts via `sti` and then
|
|
* halts the core using `hlt`. Halted cores can only be woken by interrupts. The
|
|
* effect of `sti` is delayed by one instruction, making the sequence `sti hlt`
|
|
* atomic (if interrupts were disabled previously).
|
|
*
|
|
* \see [ISDMv2, Chapter 4. STI - Set Interrupt
|
|
* Flag](intel_manual_vol2.pdf#page=1297)
|
|
* \see [ISDMv2, Chapter 3. HLT - Halt](intel_manual_vol2.pdf#page=539)
|
|
*/
|
|
inline void idle() { asm volatile("sti\n\t hlt\n\t" : : : "memory"); }
|
|
|
|
/*! \brief Permanently halts the core.
|
|
*
|
|
* Permanently halts the current CPU core. Internally, this function first
|
|
* disables the interrupts via `cli` and then halts the CPU core using `hlt`. As
|
|
* halted CPU cores can only be woken by interrupts, it is guaranteed that this
|
|
* core will be halted until the next reboot. The execution of die never
|
|
* returns. On multicore systems, only the executing CPU core will be halted
|
|
* permanently, other cores will continue execution.
|
|
*
|
|
* \see [ISDMv2, Chapter 3. CLI - Clear Interrupt
|
|
* Flag](intel_manual_vol2.pdf#page=245)
|
|
* \see [ISDMv2, Chapter 3. HLT - Halt](intel_manual_vol2.pdf#page=539)
|
|
*/
|
|
[[noreturn]] inline void die() {
|
|
while (true) {
|
|
asm volatile("cli\n\t hlt\n\t" : : : "memory");
|
|
}
|
|
}
|
|
|
|
} // namespace Core
|