mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-05-28 05:34:11 -04:00
exo2: rename exosphere2 -> exosphere
This commit is contained in:
parent
282f8f6612
commit
42f1a3bf60
136 changed files with 15 additions and 15 deletions
212
exosphere/program/source/secmon_start_warm.s
Normal file
212
exosphere/program/source/secmon_start_warm.s
Normal file
|
@ -0,0 +1,212 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* For some reason GAS doesn't know about it, even with .cpu cortex-a57 */
|
||||
#define cpuactlr_el1 s3_1_c15_c2_0
|
||||
#define cpuectlr_el1 s3_1_c15_c2_1
|
||||
|
||||
.macro RESET_CORE
|
||||
mov x0, #(1 << 63)
|
||||
msr cpuactlr_el1, x0 /* disable regional clock gating */
|
||||
isb
|
||||
mov x0, #3
|
||||
msr rmr_el3, x0
|
||||
isb
|
||||
dsb sy
|
||||
/* Nintendo forgot to copy-paste the branch instruction below. */
|
||||
1:
|
||||
wfi
|
||||
b 1b
|
||||
.endm
|
||||
|
||||
.macro ERRATUM_INVALIDATE_BTB_AT_BOOT
|
||||
/* Nintendo copy-pasted https://github.com/ARM-software/arm-trusted-firmware/blob/master/plat/nvidia/tegra/common/aarch64/tegra_helpers.S#L312 */
|
||||
/*
|
||||
* Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
/* The following comments are mine. */
|
||||
|
||||
/*
|
||||
Enable invalidates of branch target buffer, then flush
|
||||
the entire instruction cache at the local level, and
|
||||
with the reg change, the branch target buffer, then disable
|
||||
invalidates of the branch target buffer again.
|
||||
*/
|
||||
mrs x0, cpuactlr_el1
|
||||
orr x0, x0, #1
|
||||
msr cpuactlr_el1, x0
|
||||
|
||||
dsb sy
|
||||
isb
|
||||
ic iallu
|
||||
dsb sy
|
||||
isb
|
||||
|
||||
mrs x0, cpuactlr_el1
|
||||
bic x0, x0, #1
|
||||
msr cpuactlr_el1, x0
|
||||
|
||||
.rept 7
|
||||
nop /* wait long enough for the write to cpuactlr_el1 to have completed */
|
||||
.endr
|
||||
|
||||
/* if the OS lock is set, disable it and request a warm reset */
|
||||
mrs x0, oslsr_el1
|
||||
ands x0, x0, #2
|
||||
b.eq 2f
|
||||
mov x0, xzr
|
||||
msr oslar_el1, x0
|
||||
|
||||
RESET_CORE
|
||||
|
||||
.rept 65
|
||||
nop /* guard against speculative excecution */
|
||||
.endr
|
||||
|
||||
2:
|
||||
/* set the OS lock */
|
||||
mov x0, #1
|
||||
msr oslar_el1, x0
|
||||
.endm
|
||||
|
||||
.section .warmboot.text.start, "ax", %progbits
|
||||
.align 4
|
||||
.global _start_warm
|
||||
_start_warm:
|
||||
/* mask all interrupts */
|
||||
msr daifset, #0xF
|
||||
|
||||
/* Fixup hardware erratum */
|
||||
ERRATUM_INVALIDATE_BTB_AT_BOOT
|
||||
|
||||
/* Acquire exclusive access to the common warmboot stack. */
|
||||
bl _ZN3ams6secmon26AcquireCommonWarmbootStackEv
|
||||
|
||||
/* Set the stack pointer to the common warmboot stack address. */
|
||||
msr spsel, #1
|
||||
ldr x20, =0x7C0107C0
|
||||
mov sp, x20
|
||||
|
||||
/* Perform warmboot setup. */
|
||||
bl _ZN3ams6secmon59SetupSocDmaControllersCpuMemoryControllersEnableMmuWarmbootEv
|
||||
|
||||
/* Jump to the newly-mapped virtual address. */
|
||||
b _ZN3ams6secmon20StartWarmbootVirtualEv
|
||||
|
||||
|
||||
/* void ams::secmon::AcquireCommonWarmbootStack() { */
|
||||
/* NOTE: This implements critical section enter via https://en.wikipedia.org/wiki/Lamport%27s_bakery_algorithm */
|
||||
/* This algorithm is used because the MMU is not awake yet, so exclusive load/store instructions are not usable. */
|
||||
/* NOTE: Nintendo attempted to implement this algorithm themselves, but did not really understand how it works. */
|
||||
/* They use the same ticket number for all cores; this can lead to starvation and other problems. */
|
||||
.section .warmboot.text._ZN3ams6secmon26AcquireCommonWarmbootStackEv, "ax", %progbits
|
||||
.align 4
|
||||
.global _ZN3ams6secmon26AcquireCommonWarmbootStackEv
|
||||
_ZN3ams6secmon26AcquireCommonWarmbootStackEv:
|
||||
/* BakeryLock *lock = std::addressof(secmon::CommonWarmBootStackLock); */
|
||||
ldr x0, =_ZN3ams6secmon23CommonWarmbootStackLockE
|
||||
|
||||
/* const u32 id = GetCurrentCoreId(); */
|
||||
mrs x8, mpidr_el1
|
||||
and x8, x8, #3
|
||||
|
||||
/* lock->customers[id].is_entering = true; */
|
||||
ldrb w2, [x0, x8]
|
||||
orr w2, w2, #~0x7F
|
||||
strb w2, [x0, x8]
|
||||
|
||||
/* const u8 ticket_0 = lock->customers[0].ticket_number; */
|
||||
ldrb w4, [x0, #0]
|
||||
and w4, w4, #0x7F
|
||||
|
||||
/* const u8 ticket_1 = lock->customers[1].ticket_number; */
|
||||
ldrb w5, [x0, #1]
|
||||
and w5, w5, #0x7F
|
||||
|
||||
/* const u8 ticket_2 = lock->customers[2].ticket_number; */
|
||||
ldrb w6, [x0, #2]
|
||||
and w6, w6, #0x7F
|
||||
|
||||
/* const u8 ticket_3 = lock->customers[3].ticket_number; */
|
||||
ldrb w7, [x0, #3]
|
||||
and w7, w7, #0x7F
|
||||
|
||||
/* u8 biggest_ticket = std::max(std::max(ticket_0, ticket_1), std::max(ticket_2, ticket_3)) */
|
||||
cmp w4, w5
|
||||
csel w2, w4, w5, hi
|
||||
cmp w6, w7
|
||||
csel w3, w6, w7, hi
|
||||
cmp w2, w3
|
||||
csel w2, w2, w3, hi
|
||||
|
||||
/* NOTE: The biggest a ticket can ever be is 4, so the general increment is safe and 7-bit increment is not needed. */
|
||||
/* lock->customers[id] = { .is_entering = false, .ticket_number = ++biggest_ticket }; */
|
||||
add w2, w2, #1
|
||||
strb w2, [x0, x8]
|
||||
|
||||
/* Ensure instructions aren't reordered around this point. */
|
||||
/* hw::DataSynchronizationBarrier(); */
|
||||
dsb sy
|
||||
|
||||
/* hw::SendEvent(); */
|
||||
sev
|
||||
|
||||
/* for (unsigned int i = 0; i < 4; ++i) { */
|
||||
mov w3, #0
|
||||
1:
|
||||
/* hw::SendEventLocal(); */
|
||||
sevl
|
||||
|
||||
/* do { */
|
||||
2:
|
||||
/* hw::WaitForEvent(); */
|
||||
wfe
|
||||
/* while (lock->customers[i].is_entering); */
|
||||
ldrb w4, [x0, x3]
|
||||
tbnz w4, #7, 2b
|
||||
|
||||
/* u8 their_ticket; */
|
||||
|
||||
/* hw::SendEventLocal(); */
|
||||
sevl
|
||||
|
||||
/* do { */
|
||||
2:
|
||||
/* hw::WaitForEvent(); */
|
||||
wfe
|
||||
/* their_ticket = lock->customers[i].ticket_number; */
|
||||
ldrb w4, [x0, x3]
|
||||
ands w4, w4, #0x7F
|
||||
/* if (their_ticket == 0) { break; } */
|
||||
b.eq 3f
|
||||
/* while ((their_ticket > my_ticket) || (their_ticket == my_ticket && id > i)); */
|
||||
cmp w2, w4
|
||||
b.hi 2b
|
||||
ccmp w8, w3, #0, eq
|
||||
b.hi 2b
|
||||
|
||||
/* } */
|
||||
3:
|
||||
add w3, w3, #1
|
||||
cmp w3, #4
|
||||
b.ne 1b
|
||||
|
||||
/* hw::DataMemoryBarrier(); */
|
||||
dmb sy
|
||||
|
||||
ret
|
Loading…
Add table
Add a link
Reference in a new issue