88
99//! Architecture-specific code.
1010
11- use core:: arch:: asm;
11+ use core:: arch:: { asm, naked_asm } ;
1212
1313/// Data Synchronization Barrier.
1414pub fn dsb ( ) {
@@ -35,6 +35,7 @@ pub fn isb() {
3535}
3636
3737/// Invalidate all instruction caches.
38+ #[ allow( dead_code) ]
3839pub fn ic_iallu ( ) {
3940 // SAFETY: `ic iallu` is always safe.
4041 unsafe {
@@ -43,6 +44,7 @@ pub fn ic_iallu() {
4344}
4445
4546/// Invalidate all TLB entries for EL2.
47+ #[ allow( dead_code) ]
4648pub fn tlbi_alle2is ( ) {
4749 // SAFETY: `tlbi alle2is` is always safe.
4850 unsafe {
@@ -153,7 +155,33 @@ sys_reg!(elr_el2);
153155sys_reg ! ( sp_el1) ;
154156sys_reg ! ( mpidr_el1) ;
155157
156- pub ( super ) fn disable_mmu_and_caches ( ) {
158+ /// Disable MMU and caches.
159+ ///
160+ /// # Safety
161+ ///
162+ /// It is not sound to execute arbitrary Rust code after disabling the data cache, so this
163+ /// should only ever be called from assembly.
164+ /// This disables MMU, so the caller must ensure that the code will be executable at the
165+ /// same address.
166+ #[ unsafe( naked) ]
167+ pub unsafe extern "C" fn disable_mmu_and_caches ( ) {
168+ naked_asm ! (
169+ "mov x28, x30" ,
170+ "bl {invalidate_caches}" ,
171+ "mov x30, x28" ,
172+ "msr sctlr_el2, x0" ,
173+ "dsb sy" ,
174+ "isb" ,
175+ "ic iallu" ,
176+ "tlbi alle2is" ,
177+ "dsb sy" ,
178+ "isb" ,
179+ "ret" ,
180+ invalidate_caches = sym invalidate_caches,
181+ ) ;
182+ }
183+
184+ unsafe extern "C" fn invalidate_caches ( ) -> u64 {
157185 invalidate_dcache ( ) ;
158186
159187 // Disable MMU and caches
@@ -165,21 +193,8 @@ pub(super) fn disable_mmu_and_caches() {
165193 sctlr &= !sctlr_el2:: M ; // MMU Enable
166194 sctlr &= !sctlr_el2:: C ; // Data Cache Enable
167195 sctlr &= !sctlr_el2:: I ; // Instruction Cache Enable
168- // SAFETY: We assume we have an identity mapped pagetables for the currently running
169- // code, so disabling MMU is safe.
170- unsafe {
171- sctlr_el2:: write ( sctlr) ;
172- }
173- dsb ( ) ;
174- isb ( ) ;
175-
176- // Invalidate I-cache
177- ic_iallu ( ) ;
178- tlbi_alle2is ( ) ;
179196
180- // Final synchronization
181- dsb ( ) ;
182- isb ( ) ;
197+ sctlr
183198}
184199
185200/// Invalidate D-cache by set/way to the point of coherency.
0 commit comments