Skip to content

Commit aab5e6c

Browse files
authored
Merge branch 'main' into add-mmu-to-v7a-examples
2 parents 35237d6 + 4ea0407 commit aab5e6c

42 files changed

Lines changed: 763 additions & 329 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

aarch32-cpu/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ version = "0.2.0"
2626

2727
[dependencies]
2828
arbitrary-int = "2"
29-
bitbybit = "1.4"
29+
bitbybit = "2"
3030
num_enum = { version = "0.7", default-features = false }
3131
critical-section = {version = "1.2.0", features = ["restore-state-u8"], optional = true}
3232
thiserror = { version = "2", default-features = false }

aarch32-cpu/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ minor version release (e.g. from `0.3.0` to `0.3.1`, because this is still a
4141
* Copyright (c) Ferrous Systems
4242
* Copyright (c) The Rust Embedded Devices Working Group developers
4343

44-
Licensed under either [MIT](./LICENSE-MIT) or [Apache-2.0](./LICENSE-APACHE) at
44+
Licensed under either [MIT](../LICENSE-MIT) or [Apache-2.0](../LICENSE-APACHE) at
4545
your option.
4646

4747
## Contribution

aarch32-cpu/src/lib.rs

Lines changed: 192 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,201 @@ pub mod generic_timer;
3737
#[cfg(any(test, doc, arm_architecture = "v8-r"))]
3838
pub mod pmsav8;
3939

40-
/// Generate an SVC call with the given argument.
40+
/// Generate an SVC call with no parameters.
4141
///
42-
/// Safe to call even in Supervisor (SupervisorCall) mode, as long as your Svc handler
43-
/// saves and restores SPSR_svc correctly.
42+
/// Puts the first argument in the instruction. Gives you back
43+
/// the value left in `r0` by the handler.
44+
///
45+
/// ```rust,ignore
46+
/// let value = svc!(0xFF);
47+
/// ```
4448
#[macro_export]
4549
macro_rules! svc {
46-
($r0:expr) => {
50+
($num:expr) => { {
51+
let retval: u32;
52+
unsafe {
53+
core::arch::asm!("svc {arg}", arg = const $num, lateout("r0") retval);
54+
}
55+
retval
56+
} }
57+
}
58+
59+
/// Generate an SVC call with 1 parameters
60+
///
61+
/// Puts the first argument in the instruction, and the parameter in r0. Gives you back
62+
/// the value left in `r0` by the handler.
63+
///
64+
/// ```rust,ignore
65+
/// const SYSCALL_FOO: u32 = 0x100;
66+
/// let result = svc1!(0x00, SYSCALL_FOO);
67+
/// ```
68+
#[macro_export]
69+
macro_rules! svc1 {
70+
($num:expr, $arg0:expr) => { {
71+
let retval: u32;
72+
let arg0: u32 = $arg0;
73+
unsafe {
74+
core::arch::asm!(
75+
// Do the SVCall
76+
"svc {arg}",
77+
arg = const $num,
78+
inout("r0") arg0 => retval);
79+
}
80+
retval
81+
} }
82+
}
83+
84+
/// Generate an SVC call with 2 parameters
85+
///
86+
/// Puts the first argument in the instruction, and the parameters in r0-r1. Gives you back
87+
/// the value left in `r0` by the handler.
88+
///
89+
/// ```rust,ignore
90+
/// const SYSCALL_FOO: u32 = 0x100;
91+
/// let result = svc2!(0x00, SYSCALL_FOO, 1);
92+
/// ```
93+
#[macro_export]
94+
macro_rules! svc2 {
95+
($num:expr, $arg0:expr, $arg1:expr) => { {
96+
let retval: u32;
97+
let arg0: u32 = $arg0;
98+
let arg1: u32 = $arg1;
99+
unsafe {
100+
core::arch::asm!(
101+
// Do the SVCall
102+
"svc {arg}",
103+
arg = const $num,
104+
inout("r0") arg0 => retval,
105+
in("r1") arg1);
106+
}
107+
retval
108+
} }
109+
}
110+
111+
/// Generate an SVC call with 3 parameters
112+
///
113+
/// Puts the first argument in the instruction, and the parameters in r0-r2. Gives you back
114+
/// the value left in `r0` by the handler.
115+
///
116+
/// ```rust,ignore
117+
/// const SYSCALL_FOO: u32 = 0x100;
118+
/// let result = svc3!(0x00, SYSCALL_FOO, 1, 2);
119+
/// ```
120+
#[macro_export]
121+
macro_rules! svc3 {
122+
($num:expr, $arg0:expr, $arg1:expr, $arg2:expr) => { {
123+
let retval: u32;
124+
let arg0: u32 = $arg0;
125+
let arg1: u32 = $arg1;
126+
let arg2: u32 = $arg2;
127+
unsafe {
128+
core::arch::asm!(
129+
// Do the SVCall
130+
"svc {arg}",
131+
arg = const $num,
132+
inout("r0") arg0 => retval,
133+
in("r1") arg1,
134+
in("r2") arg2);
135+
}
136+
retval
137+
} }
138+
}
139+
140+
/// Generate an SVC call with 4 parameters
141+
///
142+
/// Puts the first argument in the instruction, and the parameters in r0-r3. Gives you back
143+
/// the value left in `r0` by the handler.
144+
///
145+
/// ```rust,ignore
146+
/// const SYSCALL_FOO: u32 = 0x100;
147+
/// let result = svc4!(0x00, SYSCALL_FOO, 1, 2, 3);
148+
/// ```
149+
#[macro_export]
150+
macro_rules! svc4 {
151+
($num:expr, $arg0:expr, $arg1:expr, $arg2:expr, $arg3:expr) => { {
152+
let retval: u32;
153+
let arg0: u32 = $arg0;
154+
let arg1: u32 = $arg1;
155+
let arg2: u32 = $arg2;
156+
let arg3: u32 = $arg3;
157+
unsafe {
158+
core::arch::asm!(
159+
// Do the SVCall
160+
"svc {arg}",
161+
arg = const $num,
162+
inout("r0") arg0 => retval,
163+
in("r1") arg1,
164+
in("r2") arg2,
165+
in("r3") arg3);
166+
}
167+
retval
168+
} }
169+
}
170+
171+
/// Generate an SVC call with 5 parameters
172+
///
173+
/// Puts the first argument in the instruction, and the parameters in r0-r4. Gives you back
174+
/// the value left in `r0` by the handler.
175+
///
176+
/// ```rust,ignore
177+
/// const SYSCALL_FOO: u32 = 0x100;
178+
/// let result = svc5!(0x00, SYSCALL_FOO, 1, 2, 3, 4);
179+
/// ```
180+
#[macro_export]
181+
macro_rules! svc5 {
182+
($num:expr, $arg0:expr, $arg1:expr, $arg2:expr, $arg3:expr, $arg4:expr) => { {
183+
let retval: u32;
184+
let arg0: u32 = $arg0;
185+
let arg1: u32 = $arg1;
186+
let arg2: u32 = $arg2;
187+
let arg3: u32 = $arg3;
188+
let arg4: u32 = $arg4;
189+
unsafe {
190+
core::arch::asm!(
191+
// Do the SVCall
192+
"svc {arg}",
193+
arg = const $num,
194+
inout("r0") arg0 => retval,
195+
in("r1") arg1,
196+
in("r2") arg2,
197+
in("r3") arg3,
198+
in("r4") arg4);
199+
}
200+
retval
201+
} }
202+
}
203+
204+
/// Generate an SVC call with 6 parameters
205+
///
206+
/// Puts the first argument in the instruction, and the parameters in r0-r5. Gives you back
207+
/// the value left in `r0` by the handler.
208+
///
209+
/// ```rust,ignore
210+
/// const SYSCALL_FOO: u32 = 0x100;
211+
/// let result = svc6!(0x00, SYSCALL_FOO, 1, 2, 3, 4, 5);
212+
/// ```
213+
#[macro_export]
214+
macro_rules! svc6 {
215+
($num:expr, $arg0:expr, $arg1:expr, $arg2:expr, $arg3:expr, $arg4:expr, $arg5:expr) => { {
216+
let retval: u32;
217+
let arg0: u32 = $arg0;
218+
let arg1: u32 = $arg1;
219+
let arg2: u32 = $arg2;
220+
let arg3: u32 = $arg3;
221+
let arg4: u32 = $arg4;
222+
let arg5: u32 = $arg5;
47223
unsafe {
48-
core::arch::asm!("svc {arg}", arg = const $r0, out("lr") _);
224+
core::arch::asm!(
225+
// Do the SVCall
226+
"svc {arg}",
227+
arg = const $num,
228+
inout("r0") arg0 => retval,
229+
in("r1") arg1,
230+
in("r2") arg2,
231+
in("r3") arg3,
232+
in("r4") arg4,
233+
in("r5") arg5);
49234
}
50-
}
235+
retval
236+
} }
51237
}

aarch32-rt-macros/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ minor version release (e.g. from `0.3.0` to `0.3.1`, because this is still a
1818
* Copyright (c) Ferrous Systems
1919
* Copyright (c) The Rust Embedded Devices Working Group developers
2020

21-
Licensed under either [MIT](./LICENSE-MIT) or [Apache-2.0](./LICENSE-APACHE) at
21+
Licensed under either [MIT](../LICENSE-MIT) or [Apache-2.0](../LICENSE-APACHE) at
2222
your option.
2323

2424
## Contribution

aarch32-rt-macros/src/lib.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,8 @@ fn handle_vector(args: TokenStream, input: TokenStream, kind: VectorKind) -> Tok
301301
VectorKind::Interrupt => Exception::Irq,
302302
};
303303

304-
let block = f.block;
304+
let func_name = f.sig.ident.clone();
305+
let block = f.block.clone();
305306
let (ref cfgs, ref attrs) = extract_cfgs(f.attrs.clone());
306307

307308
let handler = match exception {
@@ -387,16 +388,18 @@ fn handle_vector(args: TokenStream, input: TokenStream, kind: VectorKind) -> Tok
387388
)
388389
}
389390
}
390-
// extern "C" fn _svc_handler(addr: usize);
391+
// extern "C" fn _svc_handler(arg: u32, args: &Frame) -> u32
391392
Exception::SupervisorCall => {
392393
let tramp_ident = Ident::new("__aarch32_rt_svc_handler", Span::call_site());
393394
quote!(
394395
#(#cfgs)*
395396
#(#attrs)*
396397
#[doc(hidden)]
397398
#[export_name = "_svc_handler"]
398-
pub unsafe extern "C" fn #tramp_ident(arg: u32) {
399-
#block
399+
pub unsafe extern "C" fn #tramp_ident(arg: u32, frame: &aarch32_rt::Frame) -> u32 {
400+
#f
401+
402+
#func_name(arg, frame)
400403
}
401404
)
402405
}

aarch32-rt/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ minor version release (e.g. from `0.3.0` to `0.3.1`, because this is still a
3434
* Copyright (c) Ferrous Systems
3535
* Copyright (c) The Rust Embedded Devices Working Group developers
3636

37-
Licensed under either [MIT](./LICENSE-MIT) or [Apache-2.0](./LICENSE-APACHE) at
37+
Licensed under either [MIT](../LICENSE-MIT) or [Apache-2.0](../LICENSE-APACHE) at
3838
your option.
3939

4040
## Contribution

aarch32-rt/src/arch_v4/abort.rs

Lines changed: 45 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -14,30 +14,37 @@ core::arch::global_asm!(
1414
.global _asm_default_data_abort_handler
1515
.type _asm_default_data_abort_handler, %function
1616
_asm_default_data_abort_handler:
17-
// Subtract 8 from the stored LR, see p.1214 of the ARMv7-A architecture manual.
18-
subs lr, lr, #8
19-
// state save from compiled code
20-
stmfd sp!, {{ r0 }}
21-
mrs r0, spsr
22-
stmfd sp!, {{ r0 }}
17+
sub lr, lr, #8 // Subtract 8 from LR, see p.1214 of the ARMv7-A architecture manual.
18+
push {{ r12 }} // Save preserved register R12 - can now use it
19+
mrs r12, spsr // grab SPSR
20+
push {{ r12 }} // save SPSR value
21+
mov r12, sp // align SP down to eight byte boundary using R12
22+
and r12, r12, 7 //
23+
sub sp, r12 // SP now aligned - only push 64-bit values from here
24+
push {{ r0-r4, r12 }} // push alignment amount, and preserved registers - can now use R0-R3 (R4 is just padding)
2325
"#,
24-
crate::save_context!(),
26+
crate::save_fpu_context!(),
2527
r#"
26-
// Pass the faulting instruction address to the handler.
27-
mov r0, lr
28-
// call C handler
29-
bl _data_abort_handler
30-
// if we get back here, assume they returned a new LR in r0
31-
mov lr, r0
28+
mov r0, lr // Pass the faulting instruction address to the handler.
29+
bl _data_abort_handler // call C handler
30+
mov lr, r0 // if we get back here, assume they returned a new LR in r0
3231
"#,
33-
crate::restore_context!(),
32+
crate::restore_fpu_context!(),
3433
r#"
35-
// Return from the asm handler
36-
ldmia sp!, {{ r0 }}
37-
msr spsr, r0
38-
ldmia sp!, {{ r0 }}
39-
movs pc, lr
34+
pop {{ r0-r4, r12 }} // restore preserved registers, dummy value, and alignment amount
35+
add sp, r12 // restore SP alignment using R12
36+
pop {{ r12 }} // restore SPSR using R12
37+
msr spsr, r12 //
38+
pop {{ r12 }} // restore R12
39+
movs pc, lr // return from exception
4040
.size _asm_default_data_abort_handler, . - _asm_default_data_abort_handler
41+
"#
42+
);
43+
44+
core::arch::global_asm!(
45+
r#"
46+
// Work around https://github.com/rust-lang/rust/issues/127269
47+
.fpu vfp2
4148
4249
4350
// Called from the vector table when we have a prefetch abort.
@@ -48,29 +55,29 @@ core::arch::global_asm!(
4855
.global _asm_default_prefetch_abort_handler
4956
.type _asm_default_prefetch_abort_handler, %function
5057
_asm_default_prefetch_abort_handler:
51-
// Subtract 4 from the stored LR, see p.1212 of the ARMv7-A architecture manual.
52-
subs lr, lr, #4
53-
// state save from compiled code
54-
stmfd sp!, {{ r0 }}
55-
mrs r0, spsr
56-
stmfd sp!, {{ r0 }}
58+
sub lr, lr, #4 // Subtract 4 from LR, see p.1212 of the ARMv7-A architecture manual.
59+
push {{ r12 }} // Save preserved register R12 - can now use it
60+
mrs r12, spsr // grab SPSR
61+
push {{ r12 }} // save SPSR value
62+
mov r12, sp // align SP down to eight byte boundary using R12
63+
and r12, r12, 7 //
64+
sub sp, r12 // SP now aligned - only push 64-bit values from here
65+
push {{ r0-r4, r12 }} // push alignment amount, and preserved registers - can now use R0-R3 (R4 is just padding)
5766
"#,
58-
crate::save_context!(),
67+
crate::save_fpu_context!(),
5968
r#"
60-
// Pass the faulting instruction address to the handler.
61-
mov r0, lr
62-
// call C handler
63-
bl _prefetch_abort_handler
64-
// if we get back here, assume they returned a new LR in r0
65-
mov lr, r0
69+
mov r0, lr // Pass the faulting instruction address to the handler.
70+
bl _prefetch_abort_handler // call C handler
71+
mov lr, r0 // if we get back here, assume they returned a new LR in r0
6672
"#,
67-
crate::restore_context!(),
73+
crate::restore_fpu_context!(),
6874
r#"
69-
// Return from the asm handler
70-
ldmia sp!, {{ r0 }}
71-
msr spsr, r0
72-
ldmia sp!, {{ r0 }}
73-
movs pc, lr
75+
pop {{ r0-r4, r12 }} // restore preserved registers, dummy value, and alignment amount
76+
add sp, r12 // restore SP alignment using R12
77+
pop {{ r12 }} // restore SPSR using R12
78+
msr spsr, r12 //
79+
pop {{ r12 }} // restore R12
80+
movs pc, lr // return from exception
7481
.size _asm_default_prefetch_abort_handler, . - _asm_default_prefetch_abort_handler
7582
"#,
7683
);

0 commit comments

Comments
 (0)