mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-05-31 23:08:22 -04:00
kern: implement SvcSleepSystem
This commit is contained in:
parent
418de7b0dc
commit
9231646f33
22 changed files with 1242 additions and 49 deletions
|
@ -163,14 +163,18 @@ namespace ams::kern::arch::arm64 {
|
|||
HandleUserException(context, esr, far, afsr0, afsr1, data);
|
||||
}
|
||||
} else {
|
||||
MESOSPHERE_LOG("Unhandled Exception in Supervisor Mode\n");
|
||||
MESOSPHERE_LOG("Current Process = %s\n", GetCurrentProcess().GetName());
|
||||
const s32 core_id = GetCurrentCoreId();
|
||||
|
||||
MESOSPHERE_LOG("%d: Unhandled Exception in Supervisor Mode\n", core_id);
|
||||
if (GetCurrentProcessPointer() != nullptr) {
|
||||
MESOSPHERE_LOG("%d: Current Process = %s\n", core_id, GetCurrentProcess().GetName());
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < 31; i++) {
|
||||
MESOSPHERE_LOG("X[%02zu] = %016lx\n", i, context->x[i]);
|
||||
MESOSPHERE_LOG("%d: X[%02zu] = %016lx\n", core_id, i, context->x[i]);
|
||||
}
|
||||
MESOSPHERE_LOG("PC = %016lx\n", context->pc);
|
||||
MESOSPHERE_LOG("SP = %016lx\n", context->sp);
|
||||
MESOSPHERE_LOG("%d: PC = %016lx\n", core_id, context->pc);
|
||||
MESOSPHERE_LOG("%d: SP = %016lx\n", core_id, context->sp);
|
||||
|
||||
MESOSPHERE_PANIC("Unhandled Exception in Supervisor Mode\n");
|
||||
}
|
||||
|
|
|
@ -84,4 +84,114 @@ namespace ams::kern::arch::arm64 {
|
|||
this->gicc = nullptr;
|
||||
}
|
||||
|
||||
void KInterruptController::SaveCoreLocal(LocalState *state) const {
|
||||
/* Save isenabler. */
|
||||
for (size_t i = 0; i < util::size(state->isenabler); ++i) {
|
||||
constexpr size_t Offset = 0;
|
||||
state->isenabler[i] = this->gicd->isenabler[i + Offset];
|
||||
this->gicd->isenabler[i + Offset] = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
/* Save ipriorityr. */
|
||||
for (size_t i = 0; i < util::size(state->ipriorityr); ++i) {
|
||||
constexpr size_t Offset = 0;
|
||||
state->ipriorityr[i] = this->gicd->ipriorityr.words[i + Offset];
|
||||
this->gicd->ipriorityr.words[i + Offset] = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
/* Save itargetsr. */
|
||||
for (size_t i = 0; i < util::size(state->itargetsr); ++i) {
|
||||
constexpr size_t Offset = 0;
|
||||
state->itargetsr[i] = this->gicd->itargetsr.words[i + Offset];
|
||||
}
|
||||
|
||||
/* Save icfgr. */
|
||||
for (size_t i = 0; i < util::size(state->icfgr); ++i) {
|
||||
constexpr size_t Offset = 0;
|
||||
state->icfgr[i] = this->gicd->icfgr[i + Offset];
|
||||
}
|
||||
}
|
||||
|
||||
void KInterruptController::SaveGlobal(GlobalState *state) const {
|
||||
/* Save isenabler. */
|
||||
for (size_t i = 0; i < util::size(state->isenabler); ++i) {
|
||||
constexpr size_t Offset = util::size(LocalState{}.isenabler);
|
||||
state->isenabler[i] = this->gicd->isenabler[i + Offset];
|
||||
this->gicd->isenabler[i + Offset] = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
/* Save ipriorityr. */
|
||||
for (size_t i = 0; i < util::size(state->ipriorityr); ++i) {
|
||||
constexpr size_t Offset = util::size(LocalState{}.ipriorityr);
|
||||
state->ipriorityr[i] = this->gicd->ipriorityr.words[i + Offset];
|
||||
this->gicd->ipriorityr.words[i + Offset] = 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
/* Save itargetsr. */
|
||||
for (size_t i = 0; i < util::size(state->itargetsr); ++i) {
|
||||
constexpr size_t Offset = util::size(LocalState{}.itargetsr);
|
||||
state->itargetsr[i] = this->gicd->itargetsr.words[i + Offset];
|
||||
}
|
||||
|
||||
/* Save icfgr. */
|
||||
for (size_t i = 0; i < util::size(state->icfgr); ++i) {
|
||||
constexpr size_t Offset = util::size(LocalState{}.icfgr);
|
||||
state->icfgr[i] = this->gicd->icfgr[i + Offset];
|
||||
}
|
||||
}
|
||||
|
||||
void KInterruptController::RestoreCoreLocal(const LocalState *state) const {
|
||||
/* Restore ipriorityr. */
|
||||
for (size_t i = 0; i < util::size(state->ipriorityr); ++i) {
|
||||
constexpr size_t Offset = 0;
|
||||
this->gicd->ipriorityr.words[i + Offset] = state->ipriorityr[i];
|
||||
}
|
||||
|
||||
/* Restore itargetsr. */
|
||||
for (size_t i = 0; i < util::size(state->itargetsr); ++i) {
|
||||
constexpr size_t Offset = 0;
|
||||
this->gicd->itargetsr.words[i + Offset] = state->itargetsr[i];
|
||||
}
|
||||
|
||||
/* Restore icfgr. */
|
||||
for (size_t i = 0; i < util::size(state->icfgr); ++i) {
|
||||
constexpr size_t Offset = 0;
|
||||
this->gicd->icfgr[i + Offset] = state->icfgr[i];
|
||||
}
|
||||
|
||||
/* Restore isenabler. */
|
||||
for (size_t i = 0; i < util::size(state->isenabler); ++i) {
|
||||
constexpr size_t Offset = 0;
|
||||
this->gicd->icenabler[i + Offset] = 0xFFFFFFFF;
|
||||
this->gicd->isenabler[i + Offset] = state->isenabler[i];
|
||||
}
|
||||
}
|
||||
|
||||
void KInterruptController::RestoreGlobal(const GlobalState *state) const {
|
||||
/* Restore ipriorityr. */
|
||||
for (size_t i = 0; i < util::size(state->ipriorityr); ++i) {
|
||||
constexpr size_t Offset = util::size(LocalState{}.ipriorityr);
|
||||
this->gicd->ipriorityr.words[i + Offset] = state->ipriorityr[i];
|
||||
}
|
||||
|
||||
/* Restore itargetsr. */
|
||||
for (size_t i = 0; i < util::size(state->itargetsr); ++i) {
|
||||
constexpr size_t Offset = util::size(LocalState{}.itargetsr);
|
||||
this->gicd->itargetsr.words[i + Offset] = state->itargetsr[i];
|
||||
}
|
||||
|
||||
/* Restore icfgr. */
|
||||
for (size_t i = 0; i < util::size(state->icfgr); ++i) {
|
||||
constexpr size_t Offset = util::size(LocalState{}.icfgr);
|
||||
this->gicd->icfgr[i + Offset] = state->icfgr[i];
|
||||
}
|
||||
|
||||
/* Restore isenabler. */
|
||||
for (size_t i = 0; i < util::size(state->isenabler); ++i) {
|
||||
constexpr size_t Offset = util::size(LocalState{}.isenabler);
|
||||
this->gicd->icenabler[i + Offset] = 0xFFFFFFFF;
|
||||
this->gicd->isenabler[i + Offset] = state->isenabler[i];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -31,6 +31,81 @@ namespace ams::kern::arch::arm64 {
|
|||
this->interrupt_controller.Finalize(core_id);
|
||||
}
|
||||
|
||||
void KInterruptManager::Save(s32 core_id) {
|
||||
/* Ensure all cores get to this point before continuing. */
|
||||
cpu::SynchronizeAllCores();
|
||||
|
||||
/* If on core 0, save the global interrupts. */
|
||||
if (core_id == 0) {
|
||||
MESOSPHERE_ABORT_UNLESS(!s_global_state_saved);
|
||||
this->interrupt_controller.SaveGlobal(std::addressof(s_global_state));
|
||||
s_global_state_saved = true;
|
||||
}
|
||||
|
||||
/* Ensure all cores get to this point before continuing. */
|
||||
cpu::SynchronizeAllCores();
|
||||
|
||||
/* Save all local interrupts. */
|
||||
MESOSPHERE_ABORT_UNLESS(!this->local_state_saved);
|
||||
this->interrupt_controller.SaveCoreLocal(std::addressof(this->local_state));
|
||||
this->local_state_saved = true;
|
||||
|
||||
/* Ensure all cores get to this point before continuing. */
|
||||
cpu::SynchronizeAllCores();
|
||||
|
||||
/* Finalize all cores other than core 0. */
|
||||
if (core_id != 0) {
|
||||
this->Finalize(core_id);
|
||||
}
|
||||
|
||||
/* Ensure all cores get to this point before continuing. */
|
||||
cpu::SynchronizeAllCores();
|
||||
|
||||
/* Finalize core 0. */
|
||||
if (core_id == 0) {
|
||||
this->Finalize(core_id);
|
||||
}
|
||||
}
|
||||
|
||||
void KInterruptManager::Restore(s32 core_id) {
|
||||
/* Ensure all cores get to this point before continuing. */
|
||||
cpu::SynchronizeAllCores();
|
||||
|
||||
/* Initialize core 0. */
|
||||
if (core_id == 0) {
|
||||
this->Initialize(core_id);
|
||||
}
|
||||
|
||||
/* Ensure all cores get to this point before continuing. */
|
||||
cpu::SynchronizeAllCores();
|
||||
|
||||
/* Initialize all cores other than core 0. */
|
||||
if (core_id != 0) {
|
||||
this->Initialize(core_id);
|
||||
}
|
||||
|
||||
/* Ensure all cores get to this point before continuing. */
|
||||
cpu::SynchronizeAllCores();
|
||||
|
||||
/* Restore all local interrupts. */
|
||||
MESOSPHERE_ASSERT(this->local_state_saved);
|
||||
this->interrupt_controller.RestoreCoreLocal(std::addressof(this->local_state));
|
||||
this->local_state_saved = false;
|
||||
|
||||
/* Ensure all cores get to this point before continuing. */
|
||||
cpu::SynchronizeAllCores();
|
||||
|
||||
/* If on core 0, restore the global interrupts. */
|
||||
if (core_id == 0) {
|
||||
MESOSPHERE_ASSERT(s_global_state_saved);
|
||||
this->interrupt_controller.RestoreGlobal(std::addressof(s_global_state));
|
||||
s_global_state_saved = false;
|
||||
}
|
||||
|
||||
/* Ensure all cores get to this point before continuing. */
|
||||
cpu::SynchronizeAllCores();
|
||||
}
|
||||
|
||||
bool KInterruptManager::OnHandleInterrupt() {
|
||||
/* Get the interrupt id. */
|
||||
const u32 raw_irq = this->interrupt_controller.GetIrq();
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace ams::kern::arch::arm64 {
|
|||
|
||||
void KSupervisorPageTable::Initialize(s32 core_id) {
|
||||
/* Get the identity mapping ttbr0. */
|
||||
this->ttbr0[core_id] = cpu::GetTtbr0El1();
|
||||
this->ttbr0_identity[core_id] = cpu::GetTtbr0El1();
|
||||
|
||||
/* Set sctlr_el1 */
|
||||
cpu::SystemControlRegisterAccessor().SetWxn(true).Store();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue