From 5eec36f20a0780f79383c93f2eac5cd758eda9b1 Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Thu, 25 May 2023 09:07:49 +0100 Subject: [PATCH 1/4] [main] Add __chkfeat hint intrinsic --- main/acle.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/main/acle.md b/main/acle.md index 6589011c..b34a7a67 100644 --- a/main/acle.md +++ b/main/acle.md @@ -3279,6 +3279,19 @@ inclusive. See implementation documentation for the effect (if any) of this instruction and the meaning of the argument. This is available only when compiling for AArch32. +``` c + uint64_t __chkfeat(uint64_t); +``` + +Checks for hardware features at runtime using the CHKFEAT hint instruction. +`__chkfeat` returns a bitmask where a bit is set if the same bit in the +input argument is set and the corresponding feature is enabled. (Note: for +usability reasons the return value differs from how the CHKFEAT instruction +sets X16.) It can be used with predefined macros: + +| **Macro name** | **Value** | **Meaning** | +| ``_CHKFEAT_GCS`` | 1 | Guarded Control Stack (GCS) protection is enabled. | + ## Swap `__swp` is available for all targets. This intrinsic expands to a From 38006aabf84bda47ab621b1d11a6b0b493dee7a9 Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Thu, 25 May 2023 09:47:25 +0100 Subject: [PATCH 2/4] [main] Add Guarded Control Stack feature test macros --- main/acle.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/main/acle.md b/main/acle.md index b34a7a67..0b33a57f 100644 --- a/main/acle.md +++ b/main/acle.md @@ -1713,6 +1713,15 @@ mechanisms such as function attributes. Pointer Authentication extension (FEAT_PAuth_LR) are available on the target. It is undefined otherwise. +### Guarded Control Stack + +`__ARM_FEATURE_GCS_DEFAULT` is defined to `1` if the code generation is +compatible with enabling the Guarded Control Stack (GCS) extension based +protection. It is undefined otherwise. + +`__ARM_FEATURE_GCS` is defined to `1` if the Guarded Control Stack (GCS) +extension is available on the target. It is undefined otherwise. + ### Large System Extensions `__ARM_FEATURE_ATOMICS` is defined if the Large System Extensions introduced in @@ -2507,6 +2516,8 @@ be found in [[BA]](#BA). | [`__ARM_FEATURE_FP8DOT4`](#modal-8-bit-floating-point-extensions) | Modal 8-bit floating-point extensions | 1 | | [`__ARM_FEATURE_FP8FMA`](#modal-8-bit-floating-point-extensions) | Modal 8-bit floating-point extensions | 1 | | [`__ARM_FEATURE_FRINT`](#availability-of-armv8.5-a-floating-point-rounding-intrinsics) | Floating-point rounding extension (Arm v8.5-A) | 1 | +| [`__ARM_FEATURE_GCS`](#guarded-control-stack) | Guarded Control Stack | 1 | +| [`__ARM_FEATURE_GCS_DEFAULT`](#guarded-control-stack) | Guarded Control Stack protection can be enabled | 1 | | [`__ARM_FEATURE_IDIV`](#hardware-integer-divide) | Hardware Integer Divide | 1 | | [`__ARM_FEATURE_JCVT`](#javascript-floating-point-conversion) | Javascript conversion (ARMv8.3-A) | 1 | | [`__ARM_FEATURE_LDREX`](#ldrexstrex) *(Deprecated)* | Load/store exclusive instructions | 0x0F | From 78c6ef8cfe265375c0094fbbace47714a79c67bb Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Thu, 25 May 2023 11:10:48 +0100 Subject: [PATCH 3/4] [main] Add Guarded Control Stack intrinsics Co-authored-by: Yury Khrustalev --- main/acle.md | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/main/acle.md b/main/acle.md index 0b33a57f..7f878f75 100644 --- a/main/acle.md +++ b/main/acle.md @@ -4844,6 +4844,60 @@ two pointers, ignoring the tags. The return value is the sign-extended result of the computation. The tag bits in the input pointers are ignored for this operation. +# Guarded Control Stack intrinsics + +## Introduction + +This section describes the intrinsics for the instructions of the +Guarded Control Stack (GCS) extension. The GCS instructions are present +in the AArch64 execution state only. + +When GCS protection is enabled then function calls also save the return +address to a separate stack, the GCS, that is checked against the actual +return address when the function returns. At runtime GCS protection can +be disabled and then calls and returns do not access the GCS. The GCS +grows down and a GCS pointer points to the last entry of the GCS. +Each thread has a separate GCS and GCS pointer. + +To use the intrinsics, `arm_acle.h` needs to be included. + +These intrinsics are available when GCS instructions are supported. +The `__chkfeat` intrinsics with `_CHKFEAT_GCS` can be used to check +if GCS protection is enabled at runtime. GCS protection is only +enabled at runtime if the code is GCS compatible and the GCS +instructions are supported. + +## Intrinsics + + +``` c + void *__gcspr(void); +``` + +Returns the GCS pointer of the current thread. The GCS pointer is represented +with the `void *` type. While normal stores do not work on GCS memory, this +pointer may be writable via the `GCSSS` operation or the `GCSSTR` instruction +when enabled. + +``` c + uint64_t __gcspopm(void); +``` + +Reads and returns the last entry on the GCS of the current thread and +updates the GCS pointer to point to the previous entry. If GCS +protection is disabled then it has no side effect and returns `0`. + +An entry on the GCS is represented with the `uint64_t` because it has fixed +size and can be a token rather than a pointer. + +``` c + void *__gcsss(void *); +``` + +Switches the GCS of the current thread, where the argument is the new +GCS pointer, and returns the old GCS pointer. If GCS protection is +disabled then it has no side effect and returns `NULL`. + # State management The specification for SME is in From df9b82b07c72dbf18070aa5630c50b6ad5f48700 Mon Sep 17 00:00:00 2001 From: Szabolcs Nagy Date: Thu, 25 May 2023 16:38:37 +0100 Subject: [PATCH 4/4] Add GCS design document Co-authored-by: Yury Khrustalev --- main/design_documents/gcs.md | 67 ++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 main/design_documents/gcs.md diff --git a/main/design_documents/gcs.md b/main/design_documents/gcs.md new file mode 100644 index 00000000..02c41453 --- /dev/null +++ b/main/design_documents/gcs.md @@ -0,0 +1,67 @@ +# Design Document for GCS + +## Feature test + +GCS support has three levels: + +* (1) Code generation is GCS compatible. (Compile time decision.) + +* (2) HW supports GCS instructions. (Might be known at compile time, + but this is a runtime feature.) + +* (3) GCS is enabled at runtime. (Only known at runtime.) + +Where (3) implies (1) and (2). In principle a user may decide to +enable GCS even if (1) was false at compile time, but this is +a user error. The runtime system is responsible for enabling GCS +when (1) and (2) holds and GCS protection was requested for the +program. + +(1) and (2) need feature test macros since they can be known at +compile time. + +(3) can be detected using `__chkfeat(_CHKFEAT_GCS)` which is +available without GCS support. + +## Intrinsics + +Alternative designs for the support levels at which the intrinsics +are well defined: + +* (A) require (3), + +* (B) require (1) and (2) but not (3), + +* (C) require (2) only. + +Simplest is (A), but it does not allow asynchronously disabling GCS, +for that at least (B) is needed since the intrinsics must do something +reasonable if GCS is disabled. Asynchronous disable is e.g. needed to +allow disabling GCS at dlopen time in a multi-threaded process when +the loaded module is not GCS compatible. + +(C) is similar to (B) but allows using the intrinsics even if GCS is +guaranteed to be disabled. The intrinsics are expected to be used +behind runtime check for (3) since they don't do anything useful +otherwise and thus (1) and (2) are true when the intrinsics are used +either way. With (B) it is possible to only expose the intrinsics +at compile time if (1) is true which can be feature tested. With (C) +there is no obvious feature test for the presence of the intrinsics. + +Since intrinsics are available unconditionally and runtime checks +can be used to detect feature availability, it makes sense to go +with (C), have separate semantics defined for the enabled and disabled +case and let user code deal with the runtime checks. + +The type of the intrinsics is based on the `void *` GCS pointer +type and `uint64_t` GCS entry type. The GCS pointer could be +`uint64_t *`, but void is more general in that it allows +different access to the GCS (e.g. accessing entries as pointers or +bytes). A GCS entry is usually a code pointer, but the architecture +requires it to be 8 bytes (even with ILP32) and it may be a special +token that requires bit operations to detect, so fixed width +unsigned int type is the most appropriate. + +The `const` qualifier could be used for the GCS pointer because +normal stores cannot modify the GCS memory but specific instructions +still can do it.