This commit is contained in:
Niklas Gollenstede
2025-10-31 22:37:36 +01:00
commit 174fe17e89
197 changed files with 79558 additions and 0 deletions

114
kernel/interrupt/guard.cc Normal file
View File

@@ -0,0 +1,114 @@
/*! \file
* \brief Guard implementation
*/
#include "guard.h"
#include "../arch/cache.h"
#include "../arch/core.h"
#include "../debug/assert.h" // IWYU pragma: keep
#include "../debug/output.h"
#include "../object/bbuffer.h"
#include "epilogues.h"
//! \brief The protected data for the epilogue level
static Vault global_vault;
//! \brief State of the epilogue level (per core)
struct State {
//! \brief lists of pending epilogues
BBuffer<Epilogue, 32> epilogue_queue;
//! \brief indicates whether the epilogue level is entered
bool epi_flag = false;
} __attribute__((aligned(CACHE_LINE_SIZE)));
constinit State state = {};
static inline State &get_state() { return state; }
Vault::Vault() {}
Guarded::~Guarded() { Guard::leave(); }
Guarded Guard::enter() {
assert(!get_state().epi_flag);
// Mark entry of epilogue level on this core
get_state().epi_flag = true;
return Guarded(global_vault);
}
void Guard::leave() {
// Make sure that we've performed an enter before.
assert(get_state().epi_flag);
Vault &vault = global_vault;
bool status;
while (true) {
status = Core::Interrupt::disable();
// Get item from epilogue queue (if any)
Epilogue iter;
if (!get_state().epilogue_queue.consume(iter)) {
break;
}
// Interrupts shall be restored before processing the epilogue
Core::Interrupt::restore(status);
// Process epilogue
iter(vault);
}
// leave the epilogue level this core
get_state().epi_flag = false;
// Restore previous interrupt state
Core::Interrupt::restore(status);
}
void Guard::relay(Epilogue handler) {
if (get_state().epi_flag) {
// Enqueue epilogue
bool success = get_state().epilogue_queue.produce(handler);
if (!success) DBG << "Dropped epilogue!" << endl;
} else {
// Mark entry of epilogue level on this core
get_state().epi_flag = true;
// Enable interrupts (interrupt_handler should already have sent the ACK
// IRQ via LAPIC)
Core::Interrupt::enable();
// We are, at this point, in the prologue level (E1), so this is
// allowed:
Vault &vault = global_vault;
// Process epilogue
handler(vault);
// Make sure pending epilogues are executed
while (true) {
// Disable Interrupts while accessing the epilogue queue
Core::Interrupt::disable();
Epilogue iter;
if (!get_state().epilogue_queue.consume(iter)) {
break;
}
// Interrupts shall be enabled before processing the epilogue
Core::Interrupt::enable();
// Process epilogue
iter(vault);
}
Core::Interrupt::disable();
// leave the epilogue level this core
get_state().epi_flag = false;
}
}
const Vault &Guard::unsafeConstAccess() { return global_vault; }