mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-05-23 03:06:52 -04:00
kern: audit (and fix) our hardware maintenance instructions to match official kernel
This commit is contained in:
parent
fb59d0ad43
commit
e81a1ce5a8
16 changed files with 104 additions and 203 deletions
|
@ -61,139 +61,3 @@ _ZN3ams4kern4arch5arm643cpu23SynchronizeAllCoresImplEPii:
|
|||
5:
|
||||
stlr wzr, [x0]
|
||||
ret
|
||||
|
||||
|
||||
/* ams::kern::arch::arm64::cpu::ClearPageToZero(void *) */
|
||||
.section .text._ZN3ams4kern4arch5arm643cpu19ClearPageToZeroImplEPv, "ax", %progbits
|
||||
.global _ZN3ams4kern4arch5arm643cpu19ClearPageToZeroImplEPv
|
||||
.type _ZN3ams4kern4arch5arm643cpu19ClearPageToZeroImplEPv, %function
|
||||
_ZN3ams4kern4arch5arm643cpu19ClearPageToZeroImplEPv:
|
||||
/* Efficiently clear the page using dc zva. */
|
||||
dc zva, x0
|
||||
add x8, x0, #0x040
|
||||
dc zva, x8
|
||||
add x8, x0, #0x080
|
||||
dc zva, x8
|
||||
add x8, x0, #0x0c0
|
||||
dc zva, x8
|
||||
add x8, x0, #0x100
|
||||
dc zva, x8
|
||||
add x8, x0, #0x140
|
||||
dc zva, x8
|
||||
add x8, x0, #0x180
|
||||
dc zva, x8
|
||||
add x8, x0, #0x1c0
|
||||
dc zva, x8
|
||||
add x8, x0, #0x200
|
||||
dc zva, x8
|
||||
add x8, x0, #0x240
|
||||
dc zva, x8
|
||||
add x8, x0, #0x280
|
||||
dc zva, x8
|
||||
add x8, x0, #0x2c0
|
||||
dc zva, x8
|
||||
add x8, x0, #0x300
|
||||
dc zva, x8
|
||||
add x8, x0, #0x340
|
||||
dc zva, x8
|
||||
add x8, x0, #0x380
|
||||
dc zva, x8
|
||||
add x8, x0, #0x3c0
|
||||
dc zva, x8
|
||||
add x8, x0, #0x400
|
||||
dc zva, x8
|
||||
add x8, x0, #0x440
|
||||
dc zva, x8
|
||||
add x8, x0, #0x480
|
||||
dc zva, x8
|
||||
add x8, x0, #0x4c0
|
||||
dc zva, x8
|
||||
add x8, x0, #0x500
|
||||
dc zva, x8
|
||||
add x8, x0, #0x540
|
||||
dc zva, x8
|
||||
add x8, x0, #0x580
|
||||
dc zva, x8
|
||||
add x8, x0, #0x5c0
|
||||
dc zva, x8
|
||||
add x8, x0, #0x600
|
||||
dc zva, x8
|
||||
add x8, x0, #0x640
|
||||
dc zva, x8
|
||||
add x8, x0, #0x680
|
||||
dc zva, x8
|
||||
add x8, x0, #0x6c0
|
||||
dc zva, x8
|
||||
add x8, x0, #0x700
|
||||
dc zva, x8
|
||||
add x8, x0, #0x740
|
||||
dc zva, x8
|
||||
add x8, x0, #0x780
|
||||
dc zva, x8
|
||||
add x8, x0, #0x7c0
|
||||
dc zva, x8
|
||||
add x8, x0, #0x800
|
||||
dc zva, x8
|
||||
add x8, x0, #0x840
|
||||
dc zva, x8
|
||||
add x8, x0, #0x880
|
||||
dc zva, x8
|
||||
add x8, x0, #0x8c0
|
||||
dc zva, x8
|
||||
add x8, x0, #0x900
|
||||
dc zva, x8
|
||||
add x8, x0, #0x940
|
||||
dc zva, x8
|
||||
add x8, x0, #0x980
|
||||
dc zva, x8
|
||||
add x8, x0, #0x9c0
|
||||
dc zva, x8
|
||||
add x8, x0, #0xa00
|
||||
dc zva, x8
|
||||
add x8, x0, #0xa40
|
||||
dc zva, x8
|
||||
add x8, x0, #0xa80
|
||||
dc zva, x8
|
||||
add x8, x0, #0xac0
|
||||
dc zva, x8
|
||||
add x8, x0, #0xb00
|
||||
dc zva, x8
|
||||
add x8, x0, #0xb40
|
||||
dc zva, x8
|
||||
add x8, x0, #0xb80
|
||||
dc zva, x8
|
||||
add x8, x0, #0xbc0
|
||||
dc zva, x8
|
||||
add x8, x0, #0xc00
|
||||
dc zva, x8
|
||||
add x8, x0, #0xc40
|
||||
dc zva, x8
|
||||
add x8, x0, #0xc80
|
||||
dc zva, x8
|
||||
add x8, x0, #0xcc0
|
||||
dc zva, x8
|
||||
add x8, x0, #0xd00
|
||||
dc zva, x8
|
||||
add x8, x0, #0xd40
|
||||
dc zva, x8
|
||||
add x8, x0, #0xd80
|
||||
dc zva, x8
|
||||
add x8, x0, #0xdc0
|
||||
dc zva, x8
|
||||
add x8, x0, #0xe00
|
||||
dc zva, x8
|
||||
add x8, x0, #0xe40
|
||||
dc zva, x8
|
||||
add x8, x0, #0xe80
|
||||
dc zva, x8
|
||||
add x8, x0, #0xec0
|
||||
dc zva, x8
|
||||
add x8, x0, #0xf00
|
||||
dc zva, x8
|
||||
add x8, x0, #0xf40
|
||||
dc zva, x8
|
||||
add x8, x0, #0xf80
|
||||
dc zva, x8
|
||||
add x8, x0, #0xfc0
|
||||
dc zva, x8
|
||||
ret
|
|
@ -225,7 +225,7 @@ namespace ams::kern::arch::arm64 {
|
|||
if (AMS_UNLIKELY(GetCurrentThread().IsSingleStep())) {
|
||||
GetCurrentThread().ClearSingleStep();
|
||||
cpu::MonitorDebugSystemControlRegisterAccessor().SetSoftwareStep(false).Store();
|
||||
cpu::EnsureInstructionConsistency();
|
||||
cpu::InstructionMemoryBarrier();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -169,10 +169,10 @@ namespace ams::kern::arch::arm64 {
|
|||
m_manager = std::addressof(Kernel::GetSystemPageTableManager());
|
||||
|
||||
/* Allocate a page for ttbr. */
|
||||
/* NOTE: It is a postcondition of page table manager allocation that the page is all-zero. */
|
||||
const u64 asid_tag = (static_cast<u64>(m_asid) << 48ul);
|
||||
const KVirtualAddress page = m_manager->Allocate();
|
||||
MESOSPHERE_ASSERT(page != Null<KVirtualAddress>);
|
||||
cpu::ClearPageToZero(GetVoidPointer(page));
|
||||
m_ttbr = GetInteger(KPageTableBase::GetLinearMappedPhysicalAddress(page)) | asid_tag;
|
||||
|
||||
/* Initialize the base page table. */
|
||||
|
@ -1058,7 +1058,7 @@ namespace ams::kern::arch::arm64 {
|
|||
auto sw_reserved_bits = PageTableEntry::EncodeSoftwareReservedBits(head_entry->IsHeadMergeDisabled(), head_entry->IsHeadAndBodyMergeDisabled(), tail_entry->IsTailMergeDisabled());
|
||||
|
||||
/* Merge! */
|
||||
PteDataSynchronizationBarrier();
|
||||
/* NOTE: As of 13.1.0, Nintendo does not do: PteDataSynchronizationBarrier(); */
|
||||
*l1_entry = L1PageTableEntry(PageTableEntry::BlockTag{}, phys_addr, PageTableEntry(entry_template), sw_reserved_bits, false);
|
||||
|
||||
/* Note that we updated. */
|
||||
|
|
|
@ -656,9 +656,8 @@ namespace ams::kern::board::nintendo::nx {
|
|||
MESOSPHERE_ASSERT(IsValidPhysicalAddress(table_phys_addr));
|
||||
Kernel::GetSystemPageTableManager().Open(table_virt_addr, 1);
|
||||
|
||||
/* Clear the page and save it. */
|
||||
/* Save the page. Note that it is a pre-condition that the page is cleared, when allocated from the system page table manager. */
|
||||
/* NOTE: Nintendo does not check the result of StoreDataCache. */
|
||||
cpu::ClearPageToZero(GetVoidPointer(table_virt_addr));
|
||||
cpu::StoreDataCache(GetVoidPointer(table_virt_addr), PageDirectorySize);
|
||||
g_reserved_table_phys_addr = table_phys_addr;
|
||||
|
||||
|
|
|
@ -341,7 +341,9 @@ namespace ams::kern::board::nintendo::nx {
|
|||
|
||||
/* Restore pmu registers. */
|
||||
cpu::SetPmUserEnrEl0(0);
|
||||
cpu::PerformanceMonitorsControlRegisterAccessor().SetEventCounterReset(true).SetCycleCounterReset(true).Store();
|
||||
cpu::PerformanceMonitorsControlRegisterAccessor(0).SetEventCounterReset(true).SetCycleCounterReset(true).Store();
|
||||
cpu::EnsureInstructionConsistency();
|
||||
|
||||
cpu::SetPmOvsClrEl0(static_cast<u64>(static_cast<u32>(~u32())));
|
||||
cpu::SetPmIntEnClrEl1(static_cast<u64>(static_cast<u32>(~u32())));
|
||||
cpu::SetPmCntEnClrEl0(static_cast<u64>(static_cast<u32>(~u32())));
|
||||
|
|
|
@ -79,13 +79,6 @@ namespace ams::kern {
|
|||
RescheduleCurrentCore();
|
||||
}
|
||||
|
||||
void KScheduler::RescheduleOtherCores(u64 cores_needing_scheduling) {
|
||||
if (const u64 core_mask = cores_needing_scheduling & ~(1ul << m_core_id); core_mask != 0) {
|
||||
cpu::DataSynchronizationBarrier();
|
||||
Kernel::GetInterruptManager().SendInterProcessorInterrupt(KInterruptName_Scheduler, core_mask);
|
||||
}
|
||||
}
|
||||
|
||||
u64 KScheduler::UpdateHighestPriorityThread(KThread *highest_thread) {
|
||||
if (KThread *prev_highest_thread = m_state.highest_priority_thread; AMS_LIKELY(prev_highest_thread != highest_thread)) {
|
||||
if (AMS_LIKELY(prev_highest_thread != nullptr)) {
|
||||
|
@ -254,9 +247,24 @@ namespace ams::kern {
|
|||
|
||||
MESOSPHERE_KTRACE_THREAD_SWITCH(next_thread);
|
||||
|
||||
#if defined(MESOSPHERE_ENABLE_HARDWARE_SINGLE_STEP)
|
||||
/* Ensure the single-step bit in mdscr reflects the correct single-step state for the new thread. */
|
||||
cpu::MonitorDebugSystemControlRegisterAccessor().SetSoftwareStep(next_thread->IsSingleStep()).Store();
|
||||
#endif
|
||||
|
||||
/* Switch the current process, if we're switching processes. */
|
||||
if (KProcess *next_process = next_thread->GetOwnerProcess(); next_process != cur_process) {
|
||||
KProcess::Switch(cur_process, next_process);
|
||||
} else {
|
||||
/* The single-step bit set up above requires an instruction synchronization barrier, to ensure */
|
||||
/* the state change takes before we actually perform a return which might break-to-step. */
|
||||
/* KProcess::Switch performs an isb incidentally, and so when we're changing process we */
|
||||
/* can piggy-back off of that isb to avoid unnecessarily emptying the pipeline twice. */
|
||||
/* However, this means that when we're switching to thread in a different process, */
|
||||
/* we must ensure that we still isb. In practice, gcc will deduplicate into a single isb. */
|
||||
#if defined(MESOSPHERE_ENABLE_HARDWARE_SINGLE_STEP)
|
||||
cpu::InstructionMemoryBarrier();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Set the new thread. */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue