2
2
//
3
3
// Copyright (c) 2018-2020 Andre Richter <andre.o.richter@gmail.com>
4
4
5
- //! AArch64 .
5
+ //! Architectural processor code .
6
6
7
- mod exception;
8
- mod mmu;
9
- pub mod sync;
10
- mod time;
11
-
12
- use crate :: { bsp, interface} ;
7
+ use crate :: { bsp, cpu} ;
13
8
use cortex_a:: { asm, regs:: * } ;
14
9
10
+ //--------------------------------------------------------------------------------------------------
11
+ // Boot Code
12
+ //--------------------------------------------------------------------------------------------------
13
+
15
14
/// The entry of the `kernel` binary.
16
15
///
17
16
/// The function must be named `_start`, because the linker is looking for this exact name.
18
17
///
19
18
/// # Safety
20
19
///
21
20
/// - Linker script must ensure to place this function at `0x80_000`.
21
+ #[ naked]
22
22
#[ no_mangle]
23
23
pub unsafe extern "C" fn _start ( ) -> ! {
24
- const CORE_MASK : u64 = 0x3 ;
25
-
26
24
// Expect the boot core to start in EL2.
27
- if ( bsp:: BOOT_CORE_ID == MPIDR_EL1 . get ( ) & CORE_MASK )
25
+ if ( bsp:: cpu :: BOOT_CORE_ID == cpu :: smp :: core_id ( ) )
28
26
&& ( CurrentEL . get ( ) == CurrentEL :: EL :: EL2 . value )
29
27
{
30
28
el2_to_el1_transition ( )
@@ -39,9 +37,12 @@ pub unsafe extern "C" fn _start() -> ! {
39
37
/// # Safety
40
38
///
41
39
/// - The HW state of EL1 must be prepared in a sound way.
42
- /// - Exception return from EL2 must must continue execution in EL1 with ´runtime_init::init()`.
40
+ /// - Exception return from EL2 must must continue execution in EL1 with
41
+ /// `runtime_init::runtime_init()`.
43
42
#[ inline( always) ]
44
43
unsafe fn el2_to_el1_transition ( ) -> ! {
44
+ use crate :: runtime_init;
45
+
45
46
// Enable timer counter registers for EL1.
46
47
CNTHCTL_EL2 . write ( CNTHCTL_EL2 :: EL1PCEN :: SET + CNTHCTL_EL2 :: EL1PCTEN :: SET ) ;
47
48
@@ -53,7 +54,7 @@ unsafe fn el2_to_el1_transition() -> ! {
53
54
54
55
// Set up a simulated exception return.
55
56
//
56
- // First, fake a saved program status, where all interrupts were masked and SP_EL1 was used as a
57
+ // First, fake a saved program status where all interrupts were masked and SP_EL1 was used as a
57
58
// stack pointer.
58
59
SPSR_EL2 . write (
59
60
SPSR_EL2 :: D :: Masked
@@ -63,99 +64,38 @@ unsafe fn el2_to_el1_transition() -> ! {
63
64
+ SPSR_EL2 :: M :: EL1h ,
64
65
) ;
65
66
66
- // Second, let the link register point to init ().
67
- ELR_EL2 . set ( crate :: runtime_init:: runtime_init as * const ( ) as u64 ) ;
67
+ // Second, let the link register point to runtime_init ().
68
+ ELR_EL2 . set ( runtime_init:: runtime_init as * const ( ) as u64 ) ;
68
69
69
70
// Set up SP_EL1 (stack pointer), which will be used by EL1 once we "return" to it.
70
- SP_EL1 . set ( bsp:: BOOT_CORE_STACK_START ) ;
71
+ SP_EL1 . set ( bsp:: cpu :: BOOT_CORE_STACK_START ) ;
71
72
72
- // Use `eret` to "return" to EL1. This will result in execution of `reset()` in EL1.
73
+ // Use `eret` to "return" to EL1. This results in execution of runtime_init() in EL1.
73
74
asm:: eret ( )
74
75
}
75
76
76
77
//--------------------------------------------------------------------------------------------------
77
- // Global instances
78
- //--------------------------------------------------------------------------------------------------
79
-
80
- static TIMER : time:: Timer = time:: Timer ;
81
- static MMU : mmu:: MMU = mmu:: MMU ;
82
-
83
- //--------------------------------------------------------------------------------------------------
84
- // Implementation of the kernel's architecture abstraction code
78
+ // Public Code
85
79
//--------------------------------------------------------------------------------------------------
86
80
87
81
pub use asm:: nop;
88
82
89
83
/// Spin for `n` cycles.
84
+ #[ inline( always) ]
90
85
pub fn spin_for_cycles ( n : usize ) {
91
86
for _ in 0 ..n {
92
87
asm:: nop ( ) ;
93
88
}
94
89
}
95
90
96
- /// Return a reference to a `interface::time::TimeKeeper` implementation.
97
- pub fn timer ( ) -> & ' static impl interface:: time:: Timer {
98
- & TIMER
99
- }
100
-
101
- /// Pause execution on the calling CPU core.
91
+ /// Pause execution on the core.
102
92
#[ inline( always) ]
103
93
pub fn wait_forever ( ) -> ! {
104
94
loop {
105
95
asm:: wfe ( )
106
96
}
107
97
}
108
98
109
- /// Enable exception handling.
110
- ///
111
- /// # Safety
112
- ///
113
- /// - Changes the HW state of the processing element.
114
- pub unsafe fn enable_exception_handling ( ) {
115
- exception:: set_vbar_el1 ( ) ;
116
- }
117
-
118
- /// Return a reference to an `interface::mm::MMU` implementation.
119
- pub fn mmu ( ) -> & ' static impl interface:: mm:: MMU {
120
- & MMU
121
- }
122
-
123
- /// Information about the HW state.
124
- pub mod state {
125
- use crate :: arch:: PrivilegeLevel ;
126
- use cortex_a:: regs:: * ;
127
-
128
- /// The processing element's current privilege level.
129
- pub fn current_privilege_level ( ) -> ( PrivilegeLevel , & ' static str ) {
130
- let el = CurrentEL . read_as_enum ( CurrentEL :: EL ) ;
131
- match el {
132
- Some ( CurrentEL :: EL :: Value :: EL2 ) => ( PrivilegeLevel :: Hypervisor , "EL2" ) ,
133
- Some ( CurrentEL :: EL :: Value :: EL1 ) => ( PrivilegeLevel :: Kernel , "EL1" ) ,
134
- Some ( CurrentEL :: EL :: Value :: EL0 ) => ( PrivilegeLevel :: User , "EL0" ) ,
135
- _ => ( PrivilegeLevel :: Unknown , "Unknown" ) ,
136
- }
137
- }
138
-
139
- /// Print the AArch64 exceptions status.
140
- #[ rustfmt:: skip]
141
- pub fn print_exception_state ( ) {
142
- use super :: {
143
- exception,
144
- exception:: { Debug , SError , FIQ , IRQ } ,
145
- } ;
146
- use crate :: info;
147
-
148
- let to_mask_str = |x| -> _ {
149
- if x { "Masked" } else { "Unmasked" }
150
- } ;
151
-
152
- info ! ( " Debug: {}" , to_mask_str( exception:: is_masked:: <Debug >( ) ) ) ;
153
- info ! ( " SError: {}" , to_mask_str( exception:: is_masked:: <SError >( ) ) ) ;
154
- info ! ( " IRQ: {}" , to_mask_str( exception:: is_masked:: <IRQ >( ) ) ) ;
155
- info ! ( " FIQ: {}" , to_mask_str( exception:: is_masked:: <FIQ >( ) ) ) ;
156
- }
157
- }
158
-
159
99
//--------------------------------------------------------------------------------------------------
160
100
// Testing
161
101
//--------------------------------------------------------------------------------------------------
0 commit comments