-
Notifications
You must be signed in to change notification settings - Fork 38
Expand file tree
/
Copy pathdaifset.rs
More file actions
100 lines (89 loc) · 3.65 KB
/
daifset.rs
File metadata and controls
100 lines (89 loc) · 3.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// SPDX-License-Identifier: Apache-2.0 OR MIT
//
// Copyright (c) 2026 by the author(s)
//
// Author(s):
// - Niu Zhihong <zhihong@nzhnb.com>
//! Interrupt Mask Bits [set]
//!
//! Allows atomically setting (masking) individual DAIF interrupt mask bits
//! without affecting other bits, using the `MSR DAIFSet, #<imm>` instruction.
//!
//! This avoids the read-modify-write hazard of using `MSR DAIF, <Xt>` directly.
use tock_registers::{interfaces::Writeable, register_bitfields};
register_bitfields! {u64,
pub DAIFSet [
/// Process state D mask. The possible values of this bit are:
///
/// 0 No effect on the D mask.
///
/// 1 Watchpoint, Breakpoint, and Software Step exceptions targeted at
/// the current Exception level are masked.
D OFFSET(3) NUMBITS(1) [
NoEffect = 0,
Mask = 1
],
/// SError interrupt mask bit. The possible values of this bit are:
///
/// 0 No effect on the A mask.
/// 1 Exception masked.
A OFFSET(2) NUMBITS(1) [
NoEffect = 0,
Mask = 1
],
/// IRQ mask bit. The possible values of this bit are:
///
/// 0 No effect on the I mask.
/// 1 Exception masked.
I OFFSET(1) NUMBITS(1) [
NoEffect = 0,
Mask = 1
],
/// FIQ mask bit. The possible values of this bit are:
///
/// 0 No effect on the F mask.
/// 1 Exception masked.
F OFFSET(0) NUMBITS(1) [
NoEffect = 0,
Mask = 1
]
]
}
pub struct Reg;
impl Writeable for Reg {
type T = u64;
type R = DAIFSet::Register;
#[cfg(target_arch = "aarch64")]
#[inline]
fn set(&self, value: u64) {
// MSR DAIFSet takes a 4-bit immediate operand, so we must match on all
// possible values and emit the corresponding instruction with a constant
// immediate.
let imm = value & 0xF;
match imm {
0b0000 => {}
0b0001 => unsafe { core::arch::asm!("msr daifset, #0x1", options(nomem, nostack)) },
0b0010 => unsafe { core::arch::asm!("msr daifset, #0x2", options(nomem, nostack)) },
0b0011 => unsafe { core::arch::asm!("msr daifset, #0x3", options(nomem, nostack)) },
0b0100 => unsafe { core::arch::asm!("msr daifset, #0x4", options(nomem, nostack)) },
0b0101 => unsafe { core::arch::asm!("msr daifset, #0x5", options(nomem, nostack)) },
0b0110 => unsafe { core::arch::asm!("msr daifset, #0x6", options(nomem, nostack)) },
0b0111 => unsafe { core::arch::asm!("msr daifset, #0x7", options(nomem, nostack)) },
0b1000 => unsafe { core::arch::asm!("msr daifset, #0x8", options(nomem, nostack)) },
0b1001 => unsafe { core::arch::asm!("msr daifset, #0x9", options(nomem, nostack)) },
0b1010 => unsafe { core::arch::asm!("msr daifset, #0xa", options(nomem, nostack)) },
0b1011 => unsafe { core::arch::asm!("msr daifset, #0xb", options(nomem, nostack)) },
0b1100 => unsafe { core::arch::asm!("msr daifset, #0xc", options(nomem, nostack)) },
0b1101 => unsafe { core::arch::asm!("msr daifset, #0xd", options(nomem, nostack)) },
0b1110 => unsafe { core::arch::asm!("msr daifset, #0xe", options(nomem, nostack)) },
0b1111 => unsafe { core::arch::asm!("msr daifset, #0xf", options(nomem, nostack)) },
_ => unreachable!(),
}
}
#[cfg(not(target_arch = "aarch64"))]
fn set(&self, _value: u64) {
unimplemented!()
}
}
#[allow(non_upper_case_globals)]
pub const DAIFSet: Reg = Reg {};