sifive_core/
asm.rs

1//! Assembly instructions
2//!
3//! # Absence of PAUSE instruction
4//!
5//! SiFive cores may have PAUSE instruction implemented, which is also defined in RISC-V extension
6//! Zihintpause. This extension is adapted to [`core::hint::spin_loop()`] function in Rust core crate,
7//! and thus not implemented separately in platform specific assembly instruction module.
8//!
9//! On hardware implementation of SiFive platform, PAUSE instruction causes a stall of
10//! up to 32 cycles or until a cache eviction occurs, whichever comes first.
11//!
12//! [`core::hint::spin_loop()`]: https://doc.rust-lang.org/stable/core/hint/fn.spin_loop.html
13use core::arch::asm;
14
15/// CEASE, core halt instruction
16///
17/// This function will never return and will immediately cease the current hart.
18///
19/// # Unsafety
20///
21/// Calling this function is unsafe, because the resource this function uses
22/// is not freed (i.e. `fn drop` in Drop trait is not called) after current hart ceased.
23/// Caller must ensure that all resources are freed before invoking CEASE instruction.
24///
25/// # Privilege mode permissions
26///
27/// This is a privileged instruction and it's only available in M-mode.
28///
29/// # Example
30///
31/// ```no_run
32/// #[panic_handler]
33/// fn machine_panic(info: &PanicInfo) -> ! {
34///     print_stack_trace_and_information(info);
35///     unsafe { sifive_core::asm::cease() }
36/// }
37/// ```
38///
39/// # Hardware implmenetaion
40///
41/// After retiring CEASE, hart will not retire another instruction until reset.
42///
43/// Instigates power-down sequence, which will eventually raise the `cease_from_tile_N` signal
44/// to the outside of the Core Complex, indicating that it is safe to power down.
45///
46/// CEASE has no effect on System Bus Access.
47///
48/// Debug `haltreq` will not work after a CEASE instruction has retired.
49#[inline]
50pub unsafe fn cease() -> ! {
51    // opcode: 0x30500073
52    asm!(".insn i 0x73, 0, x0, x0, 0x305", options(noreturn))
53}
54
55/// CFLUSH.D.L1 x0, L1 data cache full-cache flush instruction
56///
57/// This instruction writes back and invalidates all lines in the L1 data cache.
58///
59/// # Privilege mode permissions
60///
61/// Only available in M-mode.
62///
63/// # Platform support
64///
65/// CFLUSH.D.L1 full-cache flush instruction is supported by all SiFive® Performance™ cores,
66/// all SiFive® Intelligence™ cores, and SiFive® Essential™ U7, U5, S7 and E7 cores.
67///
68// supported by U74, U74-MC, U54, U54-MC, S76, S76-MC, E76 and E76-MC
69// *not* supported by S54, S51, S21, E34, E31, E24, E21 and E20 cores
70//
71/// If this instruction is not supported by current platform, an illegal-instruction exception is raised.
72///
73/// # Hardware implmenetaion
74///
75/// Implemented as state machine in L1 data cache, for cores with data caches.
76#[inline]
77pub fn cflush_d_l1_all() {
78    // opcode: 0xFC000073
79    unsafe { asm!(".insn i 0x73, 0, x0, x0, -0x40") }
80}
81
82/// CFLUSH.D.L1 rs1, L1 data cache flush virtual address instruction
83///
84/// This instruction writes back and invalidates the L1 data cache line containing
85/// the virtual address in integer register rs1.
86///
87/// # Privilege mode permissions
88///
89/// Only available in M-mode.
90///
91/// # Exceptions
92///
93/// If the effective privilege mode does not have write permissions to the address in rs1, then
94/// a store access or store page-fault exception is raised.
95///
96/// If the address in rs1 is in an uncacheable region with write permissions, the instruction has
97/// no effect but raises no exceptions.
98///
99/// Note that if the PMP scheme write-protects only part of a cache line, then using a value for
100/// rs1 in the write-protected region will cause an exception, whereas using a value for rs1 in
101/// the write-permitted region will write back the entire cache line.
102///
103/// # Platform support
104///
105/// CFLUSH.D.L1 with rs1 ≠ x0 is supported by SiFive® Performance™ P550, P550-MC,
106/// SiFive® Essential™ S76, S76-MC, E76 and E76-MC cores.
107///
108// CFLUSH.D.L1 with rs1 ≠ x0 is *not* supported on SiFive® Performance™ P270, P270-MC,
109// SiFive® Intelligence™ X280, X280-MC,
110// SiFive® Essential™ U74, U74-MC, U54, U54-MC, S54, S51, S21, E34, E31, E24, E21 and E20 cores.
111//
112/// If this instruction is not supported by current platform, an illegal-instruction exception is raised.
113///
114/// # Hardware implmenetaion
115///
116/// Implemented as state machine in L1 data cache, for cores with data caches.
117#[inline]
118pub fn cflush_d_l1_va(va: usize) {
119    // opcode: 0xFC000073 + (rs1 << 15)
120    unsafe { asm!(".insn i 0x73, 0, x0, {}, -0x40", in(reg) va) }
121}
122
123/// CDISCARD.D.L1 x0, L1 data cache full-cache invalidate instruction
124///
125/// This instruction invalidates, but does not write back, all lines in the L1 data cache.
126/// Dirty data within the cache is lost.
127///
128/// # Privilege mode permissions
129///
130/// Only available in M-mode.
131///
132/// # Platform support
133///
134/// CDISCARD.D.L1 full-cache invalidate instruction is supported by all SiFive® Performance™ cores,
135/// all SiFive® Intelligence™ cores, and SiFive® Essential™ U7, U5, S7 and E7 cores.
136///
137// supported by U74, U74-MC, U54, U54-MC, S76, S76-MC, E76 and E76-MC
138// *not* supported by S54, S51, S21, E34, E31, E24, E21 and E20 cores
139//
140/// If this instruction is not supported by current platform, an illegal-instruction exception is raised.
141///
142/// # Hardware implmenetaion
143///
144/// Implemented as state machine in L1 data cache, for cores with data caches.
145#[inline]
146pub fn cdiscard_d_l1_all() {
147    // opcode: 0xFC200073
148    unsafe { asm!(".insn i 0x73, 0, x0, x0, -0x3E") }
149}
150
151/// CDISCARD.D.L1 rs1, L1 data cache invalidate virtual address instruction
152///
153/// This instruction invalidates, but does not write back, the L1 data cache line containing
154/// the virtual address in integer parameter `va`.
155/// Dirty data within the cache line is lost.
156///
157/// # Privilege mode permissions
158///
159/// Only available in M-mode.
160///
161/// # Exceptions
162///
163/// If the effective privilege mode does not have write permissions to the address in rs1, then
164/// a store access or store page-fault exception is raised.
165///
166/// If the address in rs1 is in an uncacheable region with write permissions, the instruction has
167/// no effect but raises no exceptions.
168///
169/// Note that if the PMP scheme write-protects only part of a cache line, then using a value for
170/// rs1 in the write-protected region will cause an exception, whereas using a value for rs1 in
171/// the write-permitted region will invalidate and discard the entire cache line.
172///
173/// # Platform support
174///
175/// CDISCARD.D.L1 virtual address cache invalidate instruction is supported by all SiFive® Performance™ cores,
176/// all SiFive® Intelligence™ cores, and SiFive® Essential™ U7, U5, S7 and E7 cores.
177///
178/// If this instruction is not supported by current platform, an illegal-instruction exception is raised.
179///
180/// # Hardware implmenetaion
181///
182/// Implemented as state machine in L1 data cache, for cores with data caches.
183#[inline]
184pub fn cdiscard_d_l1_va(va: usize) {
185    // opcode: 0xFC200073 + (rs1 << 15)
186    unsafe { asm!(".insn i 0x73, 0, x0, {}, -0x3E", in(reg) va) }
187}
188
189/// MNRET, non-maskable interrupt return instruction
190///
191/// This M-mode only instruction uses the values in `mnepc` and `mnstatus` to return
192/// to the program counter and privileged mode of the interrupted context, respectively.
193/// This instruction also sets the internal `rnmie` state bits.
194#[inline]
195pub unsafe fn mnret() -> ! {
196    // opcode: 0x70200073
197    asm!(".insn i 0x73, 0, x0, x0, 0x702", options(noreturn))
198}