about summary refs log tree commit diff
diff options
context:
space:
mode:
authorHugues de Valon <hugues.devalon@arm.com>2021-01-24 17:15:05 +0000
committerHugues de Valon <hugues.devalon@arm.com>2021-02-02 13:04:31 +0000
commitce9818f2b7beaed0039f42605e2f547e9e461430 (patch)
treeb6b6b3e156b4d3d38e12124ce5129b00d19fb9c8
parentd60b29d1ae8147538b8d542f7ffcc03b48e2cbda (diff)
downloadrust-ce9818f2b7beaed0039f42605e2f547e9e461430.tar.gz
rust-ce9818f2b7beaed0039f42605e2f547e9e461430.zip
Add a new ABI to support cmse_nonsecure_call
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>
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs8
-rw-r--r--compiler/rustc_codegen_cranelift/src/abi/mod.rs1
-rw-r--r--compiler/rustc_codegen_llvm/src/abi.rs14
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs1
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/mod.rs4
-rw-r--r--compiler/rustc_error_codes/src/error_codes.rs1
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0781.md12
-rw-r--r--compiler/rustc_feature/src/active.rs3
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp8
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs1
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_target/src/abi/call/mod.rs1
-rw-r--r--compiler/rustc_target/src/spec/abi.rs2
-rw-r--r--compiler/rustc_typeck/src/check/check.rs11
-rw-r--r--src/doc/unstable-book/src/language-features/abi-c-cmse-nonsecure-call.md88
-rw-r--r--src/test/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.rs11
-rw-r--r--src/test/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.stderr12
-rw-r--r--src/test/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-registers.rs15
-rw-r--r--src/test/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.rs17
-rw-r--r--src/test/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.stderr5
-rw-r--r--src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.rs6
-rw-r--r--src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.stderr9
-rw-r--r--src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.rs8
-rw-r--r--src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.stderr11
-rw-r--r--src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.rs (renamed from src/test/ui/cmse-nonsecure-entry/gate_test.rs)0
-rw-r--r--src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.stderr (renamed from src/test/ui/cmse-nonsecure-entry/gate_test.stderr)0
-rw-r--r--src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-registers.rs (renamed from src/test/ui/cmse-nonsecure-entry/params-on-registers.rs)0
-rw-r--r--src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs (renamed from src/test/ui/cmse-nonsecure-entry/params-on-stack.rs)0
-rw-r--r--src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.stderr (renamed from src/test/ui/cmse-nonsecure-entry/params-on-stack.stderr)0
-rw-r--r--src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.rs (renamed from src/test/ui/cmse-nonsecure-entry/trustzone-only.rs)0
-rw-r--r--src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.stderr (renamed from src/test/ui/cmse-nonsecure-entry/trustzone-only.stderr)0
-rw-r--r--src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs (renamed from src/test/ui/cmse-nonsecure-entry/wrong-abi.rs)0
-rw-r--r--src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr (renamed from src/test/ui/cmse-nonsecure-entry/wrong-abi.stderr)0
-rw-r--r--src/test/ui/codemap_tests/unicode.stderr2
-rw-r--r--src/test/ui/parser/issue-8537.stderr2
35 files changed, 251 insertions, 3 deletions
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 7bd805f91c8..62d0721c35f 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -156,6 +156,14 @@ impl<'a> PostExpansionVisitor<'a> {
                     "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
diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
index 6a025f2e88a..b2647e6c8d3 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
@@ -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
diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs
index 915dd3d9eda..a69241e456f 100644
--- a/compiler/rustc_codegen_llvm/src/abi.rs
+++ b/compiler/rustc_codegen_llvm/src/abi.rs
@@ -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).
+            unsafe {
+                llvm::AddCallSiteAttrString(
+                    callsite,
+                    llvm::AttributePlace::Function,
+                    rustc_data_structures::const_cstr!("cmse_nonsecure_call"),
+                );
+            }
+        }
     }
 }
 
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index d9f42efebab..e82198f8f0c 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -1100,6 +1100,7 @@ extern "C" {
     // 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);
diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs
index fc40065a966..bb9c6d47373 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs
@@ -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,
diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs
index c669f7fed27..4cf674afcfa 100644
--- a/compiler/rustc_error_codes/src/error_codes.rs
+++ b/compiler/rustc_error_codes/src/error_codes.rs
@@ -465,6 +465,7 @@ E0777: include_str!("./error_codes/E0777.md"),
 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
index 00000000000..7641acfb524
--- /dev/null
+++ b/compiler/rustc_error_codes/src/error_codes/E0781.md
@@ -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.
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index e12b533b110..818f6c70de0 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -628,6 +628,9 @@ declare_features! (
 
     /// 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
     // -------------------------------------------------------------------------
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index 1d89fc80496..4118e930745 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -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) {
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index adee88ac1c9..596e4f67174 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -2650,6 +2650,7 @@ where
             Win64 => Conv::X86_64Win64,
             SysV64 => Conv::X86_64SysV,
             Aapcs => Conv::ArmAapcs,
+            CCmseNonSecureCall => Conv::CCmseNonSecureCall,
             PtxKernel => Conv::PtxKernel,
             Msp430Interrupt => Conv::Msp430Intr,
             X86Interrupt => Conv::X86Intr,
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index f2f975c0cf9..9b6a41b2067 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -218,6 +218,7 @@ symbols! {
         abi,
         abi_amdgpu_kernel,
         abi_avr_interrupt,
+        abi_c_cmse_nonsecure_call,
         abi_efiapi,
         abi_msp430_interrupt,
         abi_ptx,
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs
index ce8e56b1949..825c13f733c 100644
--- a/compiler/rustc_target/src/abi/call/mod.rs
+++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -551,6 +551,7 @@ pub enum Conv {
 
     // Target-specific calling conventions.
     ArmAapcs,
+    CCmseNonSecureCall,
 
     Msp430Intr,
 
diff --git a/compiler/rustc_target/src/spec/abi.rs b/compiler/rustc_target/src/spec/abi.rs
index 1e45739ca22..65e8a4e8db2 100644
--- a/compiler/rustc_target/src/spec/abi.rs
+++ b/compiler/rustc_target/src/spec/abi.rs
@@ -36,6 +36,7 @@ pub enum Abi {
     EfiApi,
     AvrInterrupt,
     AvrNonBlockingInterrupt,
+    CCmseNonSecureCall,
 
     // Multiplatform / generic ABIs
     System,
@@ -81,6 +82,7 @@ const AbiDatas: &[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 },
diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs
index 47361092a5c..0935dd86240 100644
--- a/compiler/rustc_typeck/src/check/check.rs
+++ b/compiler/rustc_typeck/src/check/check.rs
@@ -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
index 00000000000..79a177cb28b
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/abi-c-cmse-nonsecure-call.md
@@ -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/cmse-nonsecure-call/gate_test.rs b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.rs
new file mode 100644
index 00000000000..e05dbf3bbc4
--- /dev/null
+++ b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.rs
@@ -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
index 00000000000..ed8e16899a1
--- /dev/null
+++ b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.stderr
@@ -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
index 00000000000..b09ea06c8f3
--- /dev/null
+++ b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-registers.rs
@@ -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
index 00000000000..cfdce4f4e92
--- /dev/null
+++ b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.rs
@@ -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
index 00000000000..c9064184075
--- /dev/null
+++ b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/params-on-stack.stderr
@@ -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
index 00000000000..17117301fef
--- /dev/null
+++ b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.rs
@@ -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
index 00000000000..78490bf8f68
--- /dev/null
+++ b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-1.stderr
@@ -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
index 00000000000..78f553d747c
--- /dev/null
+++ b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.rs
@@ -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
index 00000000000..5c148e2cd6f
--- /dev/null
+++ b/src/test/ui/cmse-nonsecure/cmse-nonsecure-call/wrong-abi-location-2.stderr
@@ -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-entry/gate_test.rs b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.rs
index 02d5f20febc..02d5f20febc 100644
--- a/src/test/ui/cmse-nonsecure-entry/gate_test.rs
+++ b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.rs
diff --git a/src/test/ui/cmse-nonsecure-entry/gate_test.stderr b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.stderr
index 75a29b317df..75a29b317df 100644
--- a/src/test/ui/cmse-nonsecure-entry/gate_test.stderr
+++ b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.stderr
diff --git a/src/test/ui/cmse-nonsecure-entry/params-on-registers.rs b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-registers.rs
index a723eb73473..a723eb73473 100644
--- a/src/test/ui/cmse-nonsecure-entry/params-on-registers.rs
+++ b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-registers.rs
diff --git a/src/test/ui/cmse-nonsecure-entry/params-on-stack.rs b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs
index 553d3a8cb0b..553d3a8cb0b 100644
--- a/src/test/ui/cmse-nonsecure-entry/params-on-stack.rs
+++ b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs
diff --git a/src/test/ui/cmse-nonsecure-entry/params-on-stack.stderr b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.stderr
index d9956acbe75..d9956acbe75 100644
--- a/src/test/ui/cmse-nonsecure-entry/params-on-stack.stderr
+++ b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.stderr
diff --git a/src/test/ui/cmse-nonsecure-entry/trustzone-only.rs b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.rs
index 3783e279402..3783e279402 100644
--- a/src/test/ui/cmse-nonsecure-entry/trustzone-only.rs
+++ b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.rs
diff --git a/src/test/ui/cmse-nonsecure-entry/trustzone-only.stderr b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.stderr
index 7e8862f9ab7..7e8862f9ab7 100644
--- a/src/test/ui/cmse-nonsecure-entry/trustzone-only.stderr
+++ b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.stderr
diff --git a/src/test/ui/cmse-nonsecure-entry/wrong-abi.rs b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs
index 611c8643dcb..611c8643dcb 100644
--- a/src/test/ui/cmse-nonsecure-entry/wrong-abi.rs
+++ b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs
diff --git a/src/test/ui/cmse-nonsecure-entry/wrong-abi.stderr b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr
index d6967a11e6b..d6967a11e6b 100644
--- a/src/test/ui/cmse-nonsecure-entry/wrong-abi.stderr
+++ b/src/test/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr
diff --git a/src/test/ui/codemap_tests/unicode.stderr b/src/test/ui/codemap_tests/unicode.stderr
index 8b85adb5845..61c3f4f1c98 100644
--- a/src/test/ui/codemap_tests/unicode.stderr
+++ b/src/test/ui/codemap_tests/unicode.stderr
@@ -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
 
diff --git a/src/test/ui/parser/issue-8537.stderr b/src/test/ui/parser/issue-8537.stderr
index e33adb239d7..3f63c080210 100644
--- a/src/test/ui/parser/issue-8537.stderr
+++ b/src/test/ui/parser/issue-8537.stderr
@@ -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