]> git.lizzy.rs Git - rust.git/commitdiff
Add a new ABI to support cmse_nonsecure_call
authorHugues de Valon <hugues.devalon@arm.com>
Sun, 24 Jan 2021 17:15:05 +0000 (17:15 +0000)
committerHugues de Valon <hugues.devalon@arm.com>
Tue, 2 Feb 2021 13:04:31 +0000 (13:04 +0000)
This commit adds a new ABI to be selected via `extern
"C-cmse-nonsecure-call"` on function pointers in order for the compiler to
apply the corresponding cmse_nonsecure_call callsite attribute.
For Armv8-M targets supporting TrustZone-M, this will perform a
non-secure function call by saving, clearing and calling a non-secure
function pointer using the BLXNS instruction.

See the page on the unstable book for details.

Signed-off-by: Hugues de Valon <hugues.devalon@arm.com>
44 files changed:
compiler/rustc_ast_passes/src/feature_gate.rs
compiler/rustc_codegen_cranelift/src/abi/mod.rs
compiler/rustc_codegen_llvm/src/abi.rs
compiler/rustc_codegen_llvm/src/llvm/ffi.rs
compiler/rustc_codegen_llvm/src/llvm/mod.rs
compiler/rustc_error_codes/src/error_codes.rs
compiler/rustc_error_codes/src/error_codes/E0781.md [new file with mode: 0644]
compiler/rustc_feature/src/active.rs
compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
compiler/rustc_middle/src/ty/layout.rs
compiler/rustc_span/src/symbol.rs
compiler/rustc_target/src/abi/call/mod.rs
compiler/rustc_target/src/spec/abi.rs
compiler/rustc_typeck/src/check/check.rs
src/doc/unstable-book/src/language-features/abi-c-cmse-nonsecure-call.md [new file with mode: 0644]
src/test/ui/cmse-nonsecure-entry/gate_test.rs [deleted file]
src/test/ui/cmse-nonsecure-entry/gate_test.stderr [deleted file]
src/test/ui/cmse-nonsecure-entry/params-on-registers.rs [deleted file]
src/test/ui/cmse-nonsecure-entry/params-on-stack.rs [deleted file]
src/test/ui/cmse-nonsecure-entry/params-on-stack.stderr [deleted file]
src/test/ui/cmse-nonsecure-entry/trustzone-only.rs [deleted file]
src/test/ui/cmse-nonsecure-entry/trustzone-only.stderr [deleted file]
src/test/ui/cmse-nonsecure-entry/wrong-abi.rs [deleted file]
src/test/ui/cmse-nonsecure-entry/wrong-abi.stderr [deleted file]
src/test/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.rs [new file with mode: 0644]
src/test/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.stderr [new file with mode: 0644]
src/test/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-registers.rs [new file with mode: 0644]
src/test/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.rs [new file with mode: 0644]
src/test/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.stderr [new file with mode: 0644]
src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.rs [new file with mode: 0644]
src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.stderr [new file with mode: 0644]
src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.rs [new file with mode: 0644]
src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.stderr [new file with mode: 0644]
src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.rs [new file with mode: 0644]
src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.stderr [new file with mode: 0644]
src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-registers.rs [new file with mode: 0644]
src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs [new file with mode: 0644]
src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.stderr [new file with mode: 0644]
src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.rs [new file with mode: 0644]
src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.stderr [new file with mode: 0644]
src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs [new file with mode: 0644]
src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr [new file with mode: 0644]
src/test/ui/codemap_tests/unicode.stderr
src/test/ui/parser/issue-8537.stderr

index 7bd805f91c8575ee0f629cedddfde4a8ac928100..62d0721c35fb1edd9f94ab33cbda8ac1d57c8185 100644 (file)
@@ -156,6 +156,14 @@ fn check_abi(&self, abi: ast::StrLit) {
                     "efiapi ABI is experimental and subject to change"
                 );
             }
+            "C-cmse-nonsecure-call" => {
+                gate_feature_post!(
+                    &self,
+                    abi_c_cmse_nonsecure_call,
+                    span,
+                    "C-cmse-nonsecure-call ABI is experimental and subject to change"
+                );
+            }
             abi => self
                 .sess
                 .parse_sess
index 6a025f2e88ae3f8b4c022663739fca48bcc9323b..b2647e6c8d3849409ca0e74b9ee4974b218d098c 100644 (file)
@@ -28,6 +28,7 @@ fn clif_sig_from_fn_abi<'tcx>(
         Conv::X86_64SysV => CallConv::SystemV,
         Conv::X86_64Win64 => CallConv::WindowsFastcall,
         Conv::ArmAapcs
+        | Conv::CCmseNonSecureCall
         | Conv::Msp430Intr
         | Conv::PtxKernel
         | Conv::X86Fastcall
index 915dd3d9eda1586ecef67545eb8514b309e790cb..a69241e456f165acefaee6a1832ce5986bfc873c 100644 (file)
@@ -389,7 +389,7 @@ fn ptr_to_llvm_type(&self, cx: &CodegenCx<'ll, 'tcx>) -> &'ll Type {
 
     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 @@ fn apply_attrs_callsite(&self, bx: &mut Builder<'a, 'll, 'tcx>, callsite: &'ll V
         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).
+            unsafe {
+                llvm::AddCallSiteAttrString(
+                    callsite,
+                    llvm::AttributePlace::Function,
+                    rustc_data_structures::const_cstr!("cmse_nonsecure_call"),
+                );
+            }
+        }
     }
 }
 
index d9f42efebab474e9a13d78cda974218e13852ef8..e82198f8f0c06adeade76fcdc8890ac1d563fc2a 100644 (file)
@@ -1100,6 +1100,7 @@ pub fn LLVMAppendBasicBlockInContext(
     // Operations on call sites
     pub fn LLVMSetInstructionCallConv(Instr: &Value, CC: c_uint);
     pub fn LLVMRustAddCallSiteAttribute(Instr: &Value, index: c_uint, attr: Attribute);
+    pub fn LLVMRustAddCallSiteAttrString(Instr: &Value, index: c_uint, Name: *const c_char);
     pub fn LLVMRustAddAlignmentCallSiteAttr(Instr: &Value, index: c_uint, bytes: u32);
     pub fn LLVMRustAddDereferenceableCallSiteAttr(Instr: &Value, index: c_uint, bytes: u64);
     pub fn LLVMRustAddDereferenceableOrNullCallSiteAttr(Instr: &Value, index: c_uint, bytes: u64);
index fc40065a9664ea1c84e8917dea7da1fcfab1ca33..bb9c6d47373babf23fc20ca22477da4f3f0390b7 100644 (file)
@@ -43,6 +43,10 @@ pub fn AddFunctionAttrString(llfn: &'a Value, idx: AttributePlace, attr: &CStr)
     }
 }
 
+pub fn AddCallSiteAttrString(callsite: &Value, idx: AttributePlace, attr: &CStr) {
+    unsafe { LLVMRustAddCallSiteAttrString(callsite, idx.as_uint(), attr.as_ptr()) }
+}
+
 #[derive(Copy, Clone)]
 pub enum AttributePlace {
     ReturnValue,
index c669f7fed272a298762341b6db2ef50db48bec97..4cf674afcfadad6b5c504d7c9f3f6e9b5a399f68 100644 (file)
 E0778: include_str!("./error_codes/E0778.md"),
 E0779: include_str!("./error_codes/E0779.md"),
 E0780: include_str!("./error_codes/E0780.md"),
+E0781: include_str!("./error_codes/E0781.md"),
 ;
 //  E0006, // merged with E0005
 //  E0008, // cannot bind by-move into a pattern guard
diff --git a/compiler/rustc_error_codes/src/error_codes/E0781.md b/compiler/rustc_error_codes/src/error_codes/E0781.md
new file mode 100644 (file)
index 0000000..7641acf
--- /dev/null
@@ -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.
index e12b533b110d22fc4124852c52fd2d5848f49e27..818f6c70de01eef911166e9d9cea437711cc36b3 100644 (file)
@@ -628,6 +628,9 @@ pub fn set(&self, features: &mut Features, span: Span) {
 
     /// Allows using `pointer` and `reference` in intra-doc links
     (active, intra_doc_pointers, "1.51.0", Some(80896), None),
+
+    /// Allows `extern "C-cmse-nonsecure-call" fn()`.
+    (active, abi_c_cmse_nonsecure_call, "1.51.0", Some(81391), None),
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates
     // -------------------------------------------------------------------------
index 1d89fc80496602c3a11d6eba3433ae5d7a5ac862..4118e9307456391dd4939002f4f93d55c32bd9a6 100644 (file)
@@ -216,6 +216,14 @@ extern "C" void LLVMRustAddCallSiteAttribute(LLVMValueRef Instr, unsigned Index,
   Call->addAttribute(Index, Attr);
 }
 
+extern "C" void LLVMRustAddCallSiteAttrString(LLVMValueRef Instr, unsigned Index,
+                                              const char *Name) {
+  CallBase *Call = unwrap<CallBase>(Instr);
+  Attribute Attr = Attribute::get(Call->getContext(), Name);
+  Call->addAttribute(Index, Attr);
+}
+
+
 extern "C" void LLVMRustAddAlignmentCallSiteAttr(LLVMValueRef Instr,
                                                  unsigned Index,
                                                  uint32_t Bytes) {
index adee88ac1c95fdc88d2327666189a76b2589ab3e..596e4f67174455db5c0501087ae3aec248a51ca1 100644 (file)
@@ -2650,6 +2650,7 @@ fn new_internal(
             Win64 => Conv::X86_64Win64,
             SysV64 => Conv::X86_64SysV,
             Aapcs => Conv::ArmAapcs,
+            CCmseNonSecureCall => Conv::CCmseNonSecureCall,
             PtxKernel => Conv::PtxKernel,
             Msp430Interrupt => Conv::Msp430Intr,
             X86Interrupt => Conv::X86Intr,
index f2f975c0cf9e5c475dbbea6f468b49509197fee0..9b6a41b206734637f3517ea00886f1d24f7ef105 100644 (file)
         abi,
         abi_amdgpu_kernel,
         abi_avr_interrupt,
+        abi_c_cmse_nonsecure_call,
         abi_efiapi,
         abi_msp430_interrupt,
         abi_ptx,
index ce8e56b194980ee1f238558d70d314903fb89d7c..825c13f733c78d903532a8b942a74f62a88abd5f 100644 (file)
@@ -551,6 +551,7 @@ pub enum Conv {
 
     // Target-specific calling conventions.
     ArmAapcs,
+    CCmseNonSecureCall,
 
     Msp430Intr,
 
index 1e45739ca22b4a76f61c33be87661d35d4f19f5e..65e8a4e8db2ad2514472b8ca0d3e5d2471b2b943 100644 (file)
@@ -36,6 +36,7 @@ pub enum Abi {
     EfiApi,
     AvrInterrupt,
     AvrNonBlockingInterrupt,
+    CCmseNonSecureCall,
 
     // Multiplatform / generic ABIs
     System,
@@ -81,6 +82,7 @@ pub struct AbiData {
         name: "avr-non-blocking-interrupt",
         generic: false,
     },
+    AbiData { abi: Abi::CCmseNonSecureCall, name: "C-cmse-nonsecure-call", generic: false },
     // Cross-platform ABIs
     AbiData { abi: Abi::System, name: "system", generic: true },
     AbiData { abi: Abi::RustIntrinsic, name: "rust-intrinsic", generic: true },
index 47361092a5c50a83dbe48008f73a375b5a9129b0..0935dd86240b6e6d7d528552c0e2b3c7655f66f7 100644 (file)
@@ -42,6 +42,17 @@ pub(super) fn check_abi(tcx: TyCtxt<'_>, span: Span, abi: Abi) {
         )
         .emit()
     }
+
+    // This ABI is only allowed on function pointers
+    if abi == Abi::CCmseNonSecureCall {
+        struct_span_err!(
+            tcx.sess,
+            span,
+            E0781,
+            "the `\"C-cmse-nonsecure-call\"` ABI is only allowed on function pointers."
+        )
+        .emit()
+    }
 }
 
 /// Helper used for fns and closures. Does the grungy work of checking a function
diff --git a/src/doc/unstable-book/src/language-features/abi-c-cmse-nonsecure-call.md b/src/doc/unstable-book/src/language-features/abi-c-cmse-nonsecure-call.md
new file mode 100644 (file)
index 0000000..79a177c
--- /dev/null
@@ -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}
+```
diff --git a/src/test/ui/cmse-nonsecure-entry/gate_test.rs b/src/test/ui/cmse-nonsecure-entry/gate_test.rs
deleted file mode 100644 (file)
index 02d5f20..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// gate-test-cmse_nonsecure_entry
-
-#[no_mangle]
-#[cmse_nonsecure_entry]
-//~^ ERROR [E0775]
-//~| ERROR [E0658]
-pub extern "C" fn entry_function(input: u32) -> u32 {
-    input + 6
-}
-
-fn main() {}
diff --git a/src/test/ui/cmse-nonsecure-entry/gate_test.stderr b/src/test/ui/cmse-nonsecure-entry/gate_test.stderr
deleted file mode 100644 (file)
index 75a29b3..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0658]: the `#[cmse_nonsecure_entry]` attribute is an experimental feature
-  --> $DIR/gate_test.rs:4:1
-   |
-LL | #[cmse_nonsecure_entry]
-   | ^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #75835 <https://github.com/rust-lang/rust/issues/75835> for more information
-   = help: add `#![feature(cmse_nonsecure_entry)]` to the crate attributes to enable
-
-error[E0775]: `#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension
-  --> $DIR/gate_test.rs:4:1
-   |
-LL | #[cmse_nonsecure_entry]
-   | ^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0658, E0775.
-For more information about an error, try `rustc --explain E0658`.
diff --git a/src/test/ui/cmse-nonsecure-entry/params-on-registers.rs b/src/test/ui/cmse-nonsecure-entry/params-on-registers.rs
deleted file mode 100644 (file)
index a723eb7..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// build-pass
-// compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
-// only-thumbv8m.main-none-eabi
-#![feature(cmse_nonsecure_entry)]
-#![no_std]
-
-#[no_mangle]
-#[cmse_nonsecure_entry]
-pub extern "C" fn entry_function(a: u32, b: u32, c: u32, d: u32) -> u32 {
-    a + b + c + d
-}
diff --git a/src/test/ui/cmse-nonsecure-entry/params-on-stack.rs b/src/test/ui/cmse-nonsecure-entry/params-on-stack.rs
deleted file mode 100644 (file)
index 553d3a8..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
-// only-thumbv8m.main-none-eabi
-#![feature(cmse_nonsecure_entry)]
-#![no_std]
-
-#[no_mangle]
-#[cmse_nonsecure_entry]
-pub extern "C" fn entry_function(a: u32, b: u32, c: u32, d: u32, e: u32) -> u32 { //~ ERROR
-    a + b + c + d + e
-}
diff --git a/src/test/ui/cmse-nonsecure-entry/params-on-stack.stderr b/src/test/ui/cmse-nonsecure-entry/params-on-stack.stderr
deleted file mode 100644 (file)
index d9956ac..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-error: <unknown>:0:0: in function entry_function i32 (i32, i32, i32, i32, i32): secure entry function requires arguments on stack
-
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/cmse-nonsecure-entry/trustzone-only.rs b/src/test/ui/cmse-nonsecure-entry/trustzone-only.rs
deleted file mode 100644 (file)
index 3783e27..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// ignore-thumbv8m.main-none-eabi
-#![feature(cmse_nonsecure_entry)]
-
-#[no_mangle]
-#[cmse_nonsecure_entry] //~ ERROR [E0775]
-pub extern "C" fn entry_function(input: u32) -> u32 {
-    input + 6
-}
-
-fn main() {}
diff --git a/src/test/ui/cmse-nonsecure-entry/trustzone-only.stderr b/src/test/ui/cmse-nonsecure-entry/trustzone-only.stderr
deleted file mode 100644 (file)
index 7e8862f..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0775]: `#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension
-  --> $DIR/trustzone-only.rs:5:1
-   |
-LL | #[cmse_nonsecure_entry]
-   | ^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0775`.
diff --git a/src/test/ui/cmse-nonsecure-entry/wrong-abi.rs b/src/test/ui/cmse-nonsecure-entry/wrong-abi.rs
deleted file mode 100644 (file)
index 611c864..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
-// only-thumbv8m.main-none-eabi
-#![feature(cmse_nonsecure_entry)]
-#![no_std]
-
-#[no_mangle]
-#[cmse_nonsecure_entry]
-pub fn entry_function(a: u32, b: u32, c: u32, d: u32) -> u32 { //~ ERROR [E0776]
-    a + b + c + d
-}
diff --git a/src/test/ui/cmse-nonsecure-entry/wrong-abi.stderr b/src/test/ui/cmse-nonsecure-entry/wrong-abi.stderr
deleted file mode 100644 (file)
index d6967a1..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0776]: `#[cmse_nonsecure_entry]` functions require C ABI
-  --> $DIR/wrong-abi.rs:7:1
-   |
-LL | #[cmse_nonsecure_entry]
-   | ^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0776`.
diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.rs b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.rs
new file mode 100644 (file)
index 0000000..e05dbf3
--- /dev/null
@@ -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);
+}
diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.stderr b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.stderr
new file mode 100644 (file)
index 0000000..ed8e168
--- /dev/null
@@ -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`.
diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-registers.rs b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-registers.rs
new file mode 100644 (file)
index 0000000..b09ea06
--- /dev/null
@@ -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)
+}
diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.rs b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.rs
new file mode 100644 (file)
index 0000000..cfdce4f
--- /dev/null
@@ -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)
+}
diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.stderr b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.stderr
new file mode 100644 (file)
index 0000000..c906418
--- /dev/null
@@ -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
+
diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.rs b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.rs
new file mode 100644 (file)
index 0000000..1711730
--- /dev/null
@@ -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]
diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.stderr b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.stderr
new file mode 100644 (file)
index 0000000..78490bf
--- /dev/null
@@ -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`.
diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.rs b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.rs
new file mode 100644 (file)
index 0000000..78f553d
--- /dev/null
@@ -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();
+}
diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.stderr b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.stderr
new file mode 100644 (file)
index 0000000..5c148e2
--- /dev/null
@@ -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`.
diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.rs b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.rs
new file mode 100644 (file)
index 0000000..02d5f20
--- /dev/null
@@ -0,0 +1,11 @@
+// gate-test-cmse_nonsecure_entry
+
+#[no_mangle]
+#[cmse_nonsecure_entry]
+//~^ ERROR [E0775]
+//~| ERROR [E0658]
+pub extern "C" fn entry_function(input: u32) -> u32 {
+    input + 6
+}
+
+fn main() {}
diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.stderr b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.stderr
new file mode 100644 (file)
index 0000000..75a29b3
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0658]: the `#[cmse_nonsecure_entry]` attribute is an experimental feature
+  --> $DIR/gate_test.rs:4:1
+   |
+LL | #[cmse_nonsecure_entry]
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #75835 <https://github.com/rust-lang/rust/issues/75835> for more information
+   = help: add `#![feature(cmse_nonsecure_entry)]` to the crate attributes to enable
+
+error[E0775]: `#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension
+  --> $DIR/gate_test.rs:4:1
+   |
+LL | #[cmse_nonsecure_entry]
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0658, E0775.
+For more information about an error, try `rustc --explain E0658`.
diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-registers.rs b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-registers.rs
new file mode 100644 (file)
index 0000000..a723eb7
--- /dev/null
@@ -0,0 +1,11 @@
+// build-pass
+// compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
+// only-thumbv8m.main-none-eabi
+#![feature(cmse_nonsecure_entry)]
+#![no_std]
+
+#[no_mangle]
+#[cmse_nonsecure_entry]
+pub extern "C" fn entry_function(a: u32, b: u32, c: u32, d: u32) -> u32 {
+    a + b + c + d
+}
diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs
new file mode 100644 (file)
index 0000000..553d3a8
--- /dev/null
@@ -0,0 +1,10 @@
+// compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
+// only-thumbv8m.main-none-eabi
+#![feature(cmse_nonsecure_entry)]
+#![no_std]
+
+#[no_mangle]
+#[cmse_nonsecure_entry]
+pub extern "C" fn entry_function(a: u32, b: u32, c: u32, d: u32, e: u32) -> u32 { //~ ERROR
+    a + b + c + d + e
+}
diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.stderr b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.stderr
new file mode 100644 (file)
index 0000000..d9956ac
--- /dev/null
@@ -0,0 +1,5 @@
+error: <unknown>:0:0: in function entry_function i32 (i32, i32, i32, i32, i32): secure entry function requires arguments on stack
+
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.rs b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.rs
new file mode 100644 (file)
index 0000000..3783e27
--- /dev/null
@@ -0,0 +1,10 @@
+// ignore-thumbv8m.main-none-eabi
+#![feature(cmse_nonsecure_entry)]
+
+#[no_mangle]
+#[cmse_nonsecure_entry] //~ ERROR [E0775]
+pub extern "C" fn entry_function(input: u32) -> u32 {
+    input + 6
+}
+
+fn main() {}
diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.stderr b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.stderr
new file mode 100644 (file)
index 0000000..7e8862f
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0775]: `#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension
+  --> $DIR/trustzone-only.rs:5:1
+   |
+LL | #[cmse_nonsecure_entry]
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0775`.
diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs
new file mode 100644 (file)
index 0000000..611c864
--- /dev/null
@@ -0,0 +1,10 @@
+// compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
+// only-thumbv8m.main-none-eabi
+#![feature(cmse_nonsecure_entry)]
+#![no_std]
+
+#[no_mangle]
+#[cmse_nonsecure_entry]
+pub fn entry_function(a: u32, b: u32, c: u32, d: u32) -> u32 { //~ ERROR [E0776]
+    a + b + c + d
+}
diff --git a/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr
new file mode 100644 (file)
index 0000000..d6967a1
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0776]: `#[cmse_nonsecure_entry]` functions require C ABI
+  --> $DIR/wrong-abi.rs:7:1
+   |
+LL | #[cmse_nonsecure_entry]
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0776`.
index 8b85adb58453f1ef303d2dc52d9b8a391fb3d3c1..61c3f4f1c9847d15ae5339757a50469f51a854af 100644 (file)
@@ -4,7 +4,7 @@ error[E0703]: invalid ABI: found `路濫狼á́́`
 LL | extern "路濫狼á́́" fn foo() {}
    |        ^^^^^^^^^ invalid ABI
    |
-   = help: valid ABIs: Rust, C, cdecl, stdcall, fastcall, vectorcall, thiscall, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, avr-interrupt, avr-non-blocking-interrupt, system, rust-intrinsic, rust-call, platform-intrinsic, unadjusted
+   = help: valid ABIs: Rust, C, cdecl, stdcall, fastcall, vectorcall, thiscall, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, avr-interrupt, avr-non-blocking-interrupt, C-cmse-nonsecure-call, system, rust-intrinsic, rust-call, platform-intrinsic, unadjusted
 
 error: aborting due to previous error
 
index e33adb239d78d52e89bd15201680fca3ce7d5d5f..3f63c080210981307ed0c1cce3a93223156028c4 100644 (file)
@@ -4,7 +4,7 @@ error[E0703]: invalid ABI: found `invalid-ab_isize`
 LL |   "invalid-ab_isize"
    |   ^^^^^^^^^^^^^^^^^^ invalid ABI
    |
-   = help: valid ABIs: Rust, C, cdecl, stdcall, fastcall, vectorcall, thiscall, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, avr-interrupt, avr-non-blocking-interrupt, system, rust-intrinsic, rust-call, platform-intrinsic, unadjusted
+   = help: valid ABIs: Rust, C, cdecl, stdcall, fastcall, vectorcall, thiscall, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, avr-interrupt, avr-non-blocking-interrupt, C-cmse-nonsecure-call, system, rust-intrinsic, rust-call, platform-intrinsic, unadjusted
 
 error: aborting due to previous error