-
Notifications
You must be signed in to change notification settings - Fork 13k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add a new ABI to support cmse_nonsecure_call #81346
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -389,7 +389,7 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { | |
|
||
fn llvm_cconv(&self) -> llvm::CallConv { | ||
match self.conv { | ||
Conv::C | Conv::Rust => llvm::CCallConv, | ||
Conv::C | Conv::Rust | Conv::CCmseNonSecureCall => llvm::CCallConv, | ||
Conv::AmdGpuKernel => llvm::AmdGpuKernel, | ||
Conv::AvrInterrupt => llvm::AvrInterrupt, | ||
Conv::AvrNonBlockingInterrupt => llvm::AvrNonBlockingInterrupt, | ||
|
@@ -546,6 +546,18 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> { | |
if cconv != llvm::CCallConv { | ||
llvm::SetInstructionCallConv(callsite, cconv); | ||
} | ||
|
||
if self.conv == Conv::CCmseNonSecureCall { | ||
// This will probably get ignored on all targets but those supporting the TrustZone-M | ||
// extension (thumbv8m targets). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should reject the ABI when using a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. True! Initially I was looking how to check the target from this file but I am not sure how to get the target information from there. It looks like it would be possible to do it in the change file There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If I do, can I maybe re-use and modify the same error code used for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah that should be fine There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah I see, sorry I mixed up the two things and thought we were talking about the target check. Cool I can move the Just wondering how I would do it 😅 In the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah ok, got it. I noticed that So one easy way would be to add a check for Maybe it's a bit risky if There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, seems fine if there are tests There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok done, there should be:
|
||
unsafe { | ||
llvm::AddCallSiteAttrString( | ||
callsite, | ||
llvm::AttributePlace::Function, | ||
rustc_data_structures::const_cstr!("cmse_nonsecure_call"), | ||
); | ||
} | ||
} | ||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
The `C-cmse-nonsecure-call` ABI can only be used with function pointers. | ||
|
||
Erroneous code example: | ||
|
||
```compile_fail,E0781 | ||
#![feature(abi_c_cmse_nonsecure_call)] | ||
|
||
pub extern "C-cmse-nonsecure-call" fn test() {} | ||
``` | ||
|
||
The `C-cmse-nonsecure-call` ABI should be used by casting function pointers to | ||
specific addresses. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -551,6 +551,7 @@ pub enum Conv { | |
|
||
// Target-specific calling conventions. | ||
ArmAapcs, | ||
CCmseNonSecureCall, | ||
|
||
Msp430Intr, | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
# `abi_c_cmse_nonsecure_call` | ||
|
||
The tracking issue for this feature is: [#81391] | ||
|
||
[#81391]: https://github.com/rust-lang/rust/issues/81391 | ||
|
||
------------------------ | ||
|
||
The [TrustZone-M | ||
feature](https://developer.arm.com/documentation/100690/latest/) is available | ||
for targets with the Armv8-M architecture profile (`thumbv8m` in their target | ||
name). | ||
LLVM, the Rust compiler and the linker are providing | ||
[support](https://developer.arm.com/documentation/ecm0359818/latest/) for the | ||
TrustZone-M feature. | ||
|
||
One of the things provided, with this unstable feature, is the | ||
`C-cmse-nonsecure-call` function ABI. This ABI is used on function pointers to | ||
non-secure code to mark a non-secure function call (see [section | ||
5.5](https://developer.arm.com/documentation/ecm0359818/latest/) for details). | ||
|
||
With this ABI, the compiler will do the following to perform the call: | ||
* save registers needed after the call to Secure memory | ||
* clear all registers that might contain confidential information | ||
* clear the Least Significant Bit of the function address | ||
* branches using the BLXNS instruction | ||
|
||
To avoid using the non-secure stack, the compiler will constrain the number and | ||
type of parameters/return value. | ||
|
||
The `extern "C-cmse-nonsecure-call"` ABI is otherwise equivalent to the | ||
`extern "C"` ABI. | ||
|
||
<!-- NOTE(ignore) this example is specific to thumbv8m targets --> | ||
|
||
``` rust,ignore | ||
#![no_std] | ||
#![feature(abi_c_cmse_nonsecure_call)] | ||
|
||
#[no_mangle] | ||
pub fn call_nonsecure_function(addr: usize) -> u32 { | ||
let non_secure_function = | ||
unsafe { core::mem::transmute::<usize, extern "C-cmse-nonsecure-call" fn() -> u32>(addr) }; | ||
non_secure_function() | ||
} | ||
``` | ||
|
||
``` text | ||
$ rustc --emit asm --crate-type lib --target thumbv8m.main-none-eabi function.rs | ||
|
||
call_nonsecure_function: | ||
.fnstart | ||
.save {r7, lr} | ||
push {r7, lr} | ||
.setfp r7, sp | ||
mov r7, sp | ||
.pad #16 | ||
sub sp, #16 | ||
str r0, [sp, #12] | ||
ldr r0, [sp, #12] | ||
str r0, [sp, #8] | ||
b .LBB0_1 | ||
.LBB0_1: | ||
ldr r0, [sp, #8] | ||
push.w {r4, r5, r6, r7, r8, r9, r10, r11} | ||
bic r0, r0, #1 | ||
mov r1, r0 | ||
mov r2, r0 | ||
mov r3, r0 | ||
mov r4, r0 | ||
mov r5, r0 | ||
mov r6, r0 | ||
mov r7, r0 | ||
mov r8, r0 | ||
mov r9, r0 | ||
mov r10, r0 | ||
mov r11, r0 | ||
mov r12, r0 | ||
msr apsr_nzcvq, r0 | ||
blxns r0 | ||
pop.w {r4, r5, r6, r7, r8, r9, r10, r11} | ||
str r0, [sp, #4] | ||
b .LBB0_2 | ||
.LBB0_2: | ||
ldr r0, [sp, #4] | ||
add sp, #16 | ||
pop {r7, pc} | ||
``` |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
// gate-test-abi_c_cmse_nonsecure_call | ||
fn main() { | ||
let non_secure_function = unsafe { | ||
core::mem::transmute::<usize, extern "C-cmse-nonsecure-call" fn(i32, i32, i32, i32) -> i32>( | ||
//~^ ERROR [E0658] | ||
0x10000004, | ||
) | ||
}; | ||
let mut toto = 5; | ||
toto += non_secure_function(toto, 2, 3, 5); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
error[E0658]: C-cmse-nonsecure-call ABI is experimental and subject to change | ||
--> $DIR/gate_test.rs:4:46 | ||
| | ||
LL | core::mem::transmute::<usize, extern "C-cmse-nonsecure-call" fn(i32, i32, i32, i32) -> i32>( | ||
| ^^^^^^^^^^^^^^^^^^^^^^^ | ||
| | ||
= note: see issue #81391 <https://github.com/rust-lang/rust/issues/81391> for more information | ||
= help: add `#![feature(abi_c_cmse_nonsecure_call)]` to the crate attributes to enable | ||
|
||
error: aborting due to previous error | ||
|
||
For more information about this error, try `rustc --explain E0658`. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
// build-pass | ||
// compile-flags: --target thumbv8m.main-none-eabi --crate-type lib | ||
// only-thumbv8m.main-none-eabi | ||
#![feature(abi_c_cmse_nonsecure_call)] | ||
#![no_std] | ||
|
||
#[no_mangle] | ||
pub fn test(a: u32, b: u32, c: u32, d: u32) -> u32 { | ||
let non_secure_function = unsafe { | ||
core::mem::transmute::<usize, extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32) -> u32>( | ||
0x10000004, | ||
) | ||
}; | ||
non_secure_function(a, b, c, d) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// compile-flags: --target thumbv8m.main-none-eabi --crate-type lib | ||
// only-thumbv8m.main-none-eabi | ||
#![feature(abi_c_cmse_nonsecure_call)] | ||
#![no_std] | ||
|
||
#[no_mangle] | ||
pub fn test(a: u32, b: u32, c: u32, d: u32, e: u32) -> u32 { | ||
let non_secure_function = unsafe { | ||
core::mem::transmute::< | ||
usize, | ||
extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32, u32) -> u32> | ||
( | ||
0x10000004, | ||
) | ||
}; | ||
non_secure_function(a, b, c, d, e) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
error: <unknown>:0:0: in function test i32 (i32, i32, i32, i32, i32): call to non-secure function would require passing arguments on stack | ||
|
||
|
||
error: aborting due to previous error | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
// compile-flags: --target thumbv8m.main-none-eabi --crate-type lib | ||
// only-thumbv8m.main-none-eabi | ||
#![feature(abi_c_cmse_nonsecure_call)] | ||
#![no_std] | ||
|
||
pub extern "C-cmse-nonsecure-call" fn test() {} //~ ERROR [E0781] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
error[E0781]: the `"cmse-nonsecure-call"` ABI is only allowed on function pointers. | ||
--> $DIR/wrong-abi-location-1.rs:6:1 | ||
| | ||
LL | pub extern "C-cmse-nonsecure-call" fn test() {} //~ ERROR [E0781] | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
error: aborting due to previous error | ||
|
||
For more information about this error, try `rustc --explain E0781`. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
// compile-flags: --target thumbv8m.main-none-eabi --crate-type lib | ||
// only-thumbv8m.main-none-eabi | ||
#![feature(abi_c_cmse_nonsecure_call)] | ||
#![no_std] | ||
|
||
extern "C-cmse-nonsecure-call" { //~ ERROR [E0781] | ||
fn test(); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
error[E0781]: the `"C-cmse-nonsecure-call"` ABI is only allowed on function pointers. | ||
--> $DIR/wrong-abi-location-2.rs:6:1 | ||
| | ||
LL | / extern "C-cmse-nonsecure-call" { | ||
LL | | fn test(); //~ ERROR [E0781] | ||
LL | | } | ||
| |_^ | ||
|
||
error: aborting due to previous error | ||
|
||
For more information about this error, try `rustc --explain E0781`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rebased and added this to fix the error