blob: d7b63b35efddfd1f774d295b0838be4fa7407576 [file] [log] [blame]
Alice Wang81399f52023-05-26 14:23:43 +00001// Copyright 2023, The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Wrappers of assembly calls.
16
17/// Reads a value from a system register.
18#[macro_export]
19macro_rules! read_sysreg {
20 ($sysreg:literal) => {{
21 let mut r: usize;
22 // Safe because it reads a system register and does not affect Rust.
23 #[allow(unused_unsafe)] // In case the macro is used within an unsafe block.
24 unsafe {
25 core::arch::asm!(
26 concat!("mrs {}, ", $sysreg),
27 out(reg) r,
28 options(nomem, nostack, preserves_flags),
29 )
30 }
31 r
32 }};
33}
34
35/// Writes a value to a system register.
36///
37/// # Safety
38///
39/// Callers must ensure that side effects of updating the system register are properly handled.
40#[macro_export]
41macro_rules! write_sysreg {
42 ($sysreg:literal, $val:expr) => {{
43 let value: usize = $val;
44 core::arch::asm!(
45 concat!("msr ", $sysreg, ", {}"),
46 in(reg) value,
47 options(nomem, nostack, preserves_flags),
48 )
49 }};
50}
51
52/// Executes an instruction synchronization barrier.
53#[macro_export]
54macro_rules! isb {
55 () => {{
56 // Safe because this is just a memory barrier and does not affect Rust.
57 #[allow(unused_unsafe)] // In case the macro is used within an unsafe block.
58 unsafe {
59 core::arch::asm!("isb", options(nomem, nostack, preserves_flags));
60 }
61 }};
62}
63
64/// Executes a data synchronization barrier.
65#[macro_export]
66macro_rules! dsb {
67 ($option:literal) => {{
68 // Safe because this is just a memory barrier and does not affect Rust.
69 #[allow(unused_unsafe)] // In case the macro is used within an unsafe block.
70 unsafe {
71 core::arch::asm!(concat!("dsb ", $option), options(nomem, nostack, preserves_flags));
72 }
73 }};
74}
75
76/// Invalidates cached leaf PTE entries by virtual address.
77#[macro_export]
78macro_rules! tlbi {
79 ($option:literal, $asid:expr, $addr:expr) => {{
80 let asid: usize = $asid;
81 let addr: usize = $addr;
82 // Safe because it invalidates TLB and doesn't affect Rust. When the address matches a
83 // block entry larger than the page size, all translations for the block are invalidated.
84 #[allow(unused_unsafe)] // In case the macro is used within an unsafe block.
85 unsafe {
86 core::arch::asm!(
87 concat!("tlbi ", $option, ", {x}"),
88 x = in(reg) (asid << 48) | (addr >> 12),
89 options(nomem, nostack, preserves_flags)
90 );
91 }
92 }};
93}