22
33use core:: arch:: { asm, global_asm} ;
44
5- use aarch64_cpu:: registers:: { SCTLR_EL1 , Writeable } ;
5+ use aarch64_cpu:: asm:: { barrier, wfe} ;
6+ use aarch64_cpu:: registers:: {
7+ CPACR_EL1 , ID_AA64MMFR0_EL1 , MAIR_EL1 , MDSCR_EL1 , ReadWriteable , Readable , SCTLR_EL1 , TCR_EL1 ,
8+ TPIDR_EL0 , TPIDR_EL1 , Writeable ,
9+ } ;
610use log:: info;
711
812const BOOT_CORE_ID : u64 = 0 ; // ID of CPU for booting on SMP systems - this might be board specific in the future
913
10- /*
11- * Memory types available.
12- */
13- #[ allow( non_upper_case_globals) ]
14- const MT_DEVICE_nGnRnE : u64 = 0 ;
15- #[ allow( non_upper_case_globals) ]
16- const MT_DEVICE_nGnRE : u64 = 1 ;
17- const MT_DEVICE_GRE : u64 = 2 ;
18- const MT_NORMAL_NC : u64 = 3 ;
19- const MT_NORMAL : u64 = 4 ;
20-
21- #[ inline( always) ]
22- const fn mair ( attr : u64 , mt : u64 ) -> u64 {
23- attr << ( mt * 8 )
24- }
25-
26- /*
27- * TCR flags
28- */
29- const TCR_IRGN_WBWA : u64 = ( ( 1 ) << 8 ) | ( ( 1 ) << 24 ) ;
30- const TCR_ORGN_WBWA : u64 = ( ( 1 ) << 10 ) | ( ( 1 ) << 26 ) ;
31- const TCR_SHARED : u64 = ( ( 3 ) << 12 ) | ( ( 3 ) << 28 ) ;
32- const TCR_TBI0 : u64 = 1 << 37 ;
33- const TCR_TBI1 : u64 = 1 << 38 ;
34- const TCR_ASID16 : u64 = 1 << 36 ;
35- const TCR_TG1_16K : u64 = 1 << 30 ;
36- const TCR_TG1_4K : u64 = 0 << 30 ;
37- const TCR_FLAGS : u64 = TCR_IRGN_WBWA | TCR_ORGN_WBWA | TCR_SHARED ;
38-
3914/// Number of virtual address bits for 4KB page
4015const VA_BITS : u64 = 48 ;
4116
42- #[ inline( always) ]
43- const fn tcr_size ( x : u64 ) -> u64 {
44- ( ( 64 - x) << 16 ) | ( 64 - x)
45- }
46-
4717global_asm ! (
4818 include_str!( "entry.s" ) ,
4919 start_rust = sym start_rust,
@@ -59,14 +29,14 @@ unsafe fn pre_init() -> ! {
5929 info ! ( "Enter startup code" ) ;
6030
6131 /* disable interrupts */
32+ /* FIXME: Migrate to aarch64_cpu's DAIFSet definition once released */
6233 unsafe {
6334 asm ! ( "msr daifset, 0b111" , options( nostack) ) ;
6435 }
6536
6637 /* reset thread id registers */
67- unsafe {
68- asm ! ( "msr tpidr_el0, xzr" , "msr tpidr_el1, xzr" , options( nostack) ) ;
69- }
38+ TPIDR_EL0 . set ( 0 ) ;
39+ TPIDR_EL1 . set ( 0 ) ;
7040
7141 /*
7242 * Disable the MMU. We may have entered the kernel with it on and
@@ -75,87 +45,72 @@ unsafe fn pre_init() -> ! {
7545 * but in this case the code to find where we are running from
7646 * would have also failed.
7747 */
78- unsafe {
79- asm ! ( "dsb sy" ,
80- "mrs x2, sctlr_el1" ,
81- "bic x2, x2, 0x1" ,
82- "msr sctlr_el1, x2" ,
83- "isb" ,
84- out( "x2" ) _,
85- options( nostack) ,
86- ) ;
87- }
48+ barrier:: dsb ( barrier:: SY ) ;
49+ SCTLR_EL1 . modify ( SCTLR_EL1 :: M :: Disable ) ;
50+ barrier:: isb ( barrier:: SY ) ;
8851
8952 unsafe {
90- asm ! ( "ic iallu" , "tlbi vmalle1is" , "dsb ish" , options( nostack) ) ;
53+ asm ! ( "ic iallu" , "tlbi vmalle1is" , options( nostack) ) ;
9154 }
55+ barrier:: dsb ( barrier:: ISH ) ;
9256
9357 /*
9458 * Setup memory attribute type tables
95- *
96- * Memory regioin attributes for LPAE:
97- *
98- * n = AttrIndx[2:0]
99- * n MAIR
100- * DEVICE_nGnRnE 000 00000000 (0x00)
101- * DEVICE_nGnRE 001 00000100 (0x04)
102- * DEVICE_GRE 010 00001100 (0x0c)
103- * NORMAL_NC 011 01000100 (0x44)
104- * NORMAL 100 11111111 (0xff)
10559 */
106- let mair_el1 = mair ( 0x00 , MT_DEVICE_nGnRnE )
107- | mair ( 0x04 , MT_DEVICE_nGnRE )
108- | mair ( 0x0c , MT_DEVICE_GRE )
109- | mair ( 0x44 , MT_NORMAL_NC )
110- | mair ( 0xff , MT_NORMAL ) ;
111- unsafe {
112- asm ! ( "msr mair_el1, {}" ,
113- in( reg) mair_el1,
114- options( nostack) ,
115- ) ;
116- }
60+ MAIR_EL1 . write (
61+ MAIR_EL1 :: Attr0_Device :: nonGathering_nonReordering_noEarlyWriteAck
62+ + MAIR_EL1 :: Attr1_Device :: nonGathering_nonReordering_EarlyWriteAck
63+ + MAIR_EL1 :: Attr2_Device :: Gathering_Reordering_EarlyWriteAck
64+ + MAIR_EL1 :: Attr3_Normal_Inner :: NonCacheable
65+ + MAIR_EL1 :: Attr3_Normal_Outer :: NonCacheable
66+ + MAIR_EL1 :: Attr4_Normal_Inner :: WriteBack_NonTransient_ReadWriteAlloc
67+ + MAIR_EL1 :: Attr4_Normal_Outer :: WriteBack_NonTransient_ReadWriteAlloc ,
68+ ) ;
11769
11870 /*
11971 * Setup translation control register (TCR)
12072 */
12173
12274 // determine physical address size
123- unsafe {
124- asm ! ( "mrs x0, id_aa64mmfr0_el1" ,
125- "and x0, x0, 0xF" ,
126- "lsl x0, x0, 32" ,
127- "orr x0, x0, {tcr_bits}" ,
128- "mrs x1, id_aa64mmfr0_el1" ,
129- "bfi x0, x1, #32, #3" ,
130- "msr tcr_el1, x0" ,
131- tcr_bits = in( reg) tcr_size( VA_BITS ) | TCR_TG1_4K | TCR_FLAGS ,
132- out( "x0" ) _,
133- out( "x1" ) _,
134- ) ;
135- }
75+ let pa_range = ID_AA64MMFR0_EL1
76+ . read_as_enum :: < ID_AA64MMFR0_EL1 :: PARange :: Value > ( ID_AA64MMFR0_EL1 :: PARange ) ;
77+ let ips = match pa_range {
78+ Some ( ID_AA64MMFR0_EL1 :: PARange :: Value :: Bits_32 ) => TCR_EL1 :: IPS :: Bits_32 ,
79+ Some ( ID_AA64MMFR0_EL1 :: PARange :: Value :: Bits_36 ) => TCR_EL1 :: IPS :: Bits_36 ,
80+ Some ( ID_AA64MMFR0_EL1 :: PARange :: Value :: Bits_40 ) => TCR_EL1 :: IPS :: Bits_40 ,
81+ Some ( ID_AA64MMFR0_EL1 :: PARange :: Value :: Bits_42 ) => TCR_EL1 :: IPS :: Bits_42 ,
82+ Some ( ID_AA64MMFR0_EL1 :: PARange :: Value :: Bits_44 ) => TCR_EL1 :: IPS :: Bits_44 ,
83+ Some ( ID_AA64MMFR0_EL1 :: PARange :: Value :: Bits_48 ) => TCR_EL1 :: IPS :: Bits_48 ,
84+ Some ( ID_AA64MMFR0_EL1 :: PARange :: Value :: Bits_52 ) => TCR_EL1 :: IPS :: Bits_52 ,
85+ // The spec technically also has 56 bits as an option and marks all other
86+ // cases as reserved
87+ None => panic ! ( "Unknown physical address range" ) ,
88+ } ;
89+
90+ TCR_EL1 . write (
91+ ips + TCR_EL1 :: T1SZ . val ( 64 - VA_BITS )
92+ + TCR_EL1 :: T0SZ . val ( 64 - VA_BITS )
93+ + TCR_EL1 :: TG1 :: KiB_4
94+ + TCR_EL1 :: IRGN0 :: WriteBack_ReadAlloc_WriteAlloc_Cacheable
95+ + TCR_EL1 :: IRGN1 :: WriteBack_ReadAlloc_WriteAlloc_Cacheable
96+ + TCR_EL1 :: ORGN0 :: WriteBack_ReadAlloc_WriteAlloc_Cacheable
97+ + TCR_EL1 :: ORGN1 :: WriteBack_ReadAlloc_WriteAlloc_Cacheable
98+ + TCR_EL1 :: SH0 :: Inner
99+ + TCR_EL1 :: SH1 :: Inner ,
100+ ) ;
136101
137102 /*
138103 * Enable FP/ASIMD in Architectural Feature Access Control Register,
139104 */
140- let bit_mask: u64 = 3 << 20 ;
141- unsafe {
142- asm ! ( "msr cpacr_el1, {mask}" ,
143- mask = in( reg) bit_mask,
144- options( nostack) ,
145- ) ;
146- }
105+ CPACR_EL1 . write ( CPACR_EL1 :: FPEN :: TrapNothing ) ;
147106
148107 /*
149108 * Reset debug control register
150109 */
151- unsafe {
152- asm ! ( "msr mdscr_el1, xzr" , options( nostack) ) ;
153- }
110+ MDSCR_EL1 . set ( 0 ) ;
154111
155112 /* Memory barrier */
156- unsafe {
157- asm ! ( "dsb sy" , options( nostack) ) ;
158- }
113+ barrier:: dsb ( barrier:: SY ) ;
159114
160115 /*
161116 * Prepare system control register (SCTRL)
@@ -195,10 +150,8 @@ unsafe fn pre_init() -> ! {
195150 }
196151}
197152
198- pub unsafe fn wait_forever ( ) -> ! {
153+ pub fn wait_forever ( ) -> ! {
199154 loop {
200- unsafe {
201- asm ! ( "wfe" ) ;
202- }
155+ wfe ( ) ;
203156 }
204157}
0 commit comments