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
//! Operations for cache maintenance.
//!
//! Since the agent that performs data access is separate from the agent that performs instruction
//! fetches, operations that change instructions must sync one's cache to the other. There are three
//! relevant caches that must be in sync for updates to instructions to become visible:
//!
//! - The data cache (d-cache), in which the changes are initially made.
//! - The instruction cache (i-cache), used by the instruction fetch pipeline.
//! - The branch prediction subsystem (the term "cache" is used loosely here, but this also has to
//! be synced).
//!
//! Therefore, for an instruction update to take effect in a uniprocessor setting, the following
//! operations must be made:
//!
//! 1. The instruction must be written to the data cache. (e.g. via [`core::ptr::write_volatile`])
//! 2. The changes in the data cache must synced far enough that the i-cache sees it when it queries
//! main memory. (via [`cache::clean_dcache_to_unification`])
//! 3. The instruction cache must read any changes from main memory. (via
//! [`cache::invalidate_icache`])
//! 4. Any branch predictions for the instruction must be cleared, since they're now invalid. (this
//! is handled by the previous function).
use asm;
/// Ensure the visibility of an instruction update for a uniprocessor.
/// Syncs the given portion of data cache with main memory such that any changes made to this
/// cache are visible to other caches when they access main memory.
///
/// The cache is cleaned to the Point of Unification: other subsystems of the processor (such
/// as other caches and translation table walks) are guaranteed to see the changes, but the
/// changes aren't guaranteed to be visible to external agents that can access the memory.
/// Invalidates the CPU instruction cache, so that any changes from main memory are synced into
/// the i-cache.
///
/// Branch predictors are also invalidated.