| // Copyright Microsoft and CHERIoT Contributors. | 
 | // SPDX-License-Identifier: MIT | 
 |  | 
 | #pragma once | 
 | /** | 
 |  * C++ helpers for operating on capabilities. | 
 |  */ | 
 | #include <cheri.h> | 
 | #include <cstddef> | 
 | #include <cstdint> | 
 | #include <initializer_list> | 
 | #include <magic_enum/magic_enum.hpp> | 
 |  | 
 | namespace CHERI | 
 | { | 
 | 	/** | 
 | 	 * The complete set of architectural permissions. | 
 | 	 */ | 
 | 	enum class Permission : uint32_t | 
 | 	{ | 
 | 		/** | 
 | 		 * Capability refers to global memory (this capability may be stored | 
 | 		 * anywhere). | 
 | 		 */ | 
 | 		Global = CheriPermissionGlobal, | 
 | 		/** | 
 | 		 * Global capabilities can be loaded through this capability.  Without | 
 | 		 *  this permission, any capability loaded via this capability will | 
 | 		 *  have `Global` and `LoadGlobal` removed. | 
 | 		 */ | 
 | 		LoadGlobal = CheriPermissionLoadGlobal, | 
 | 		/** | 
 | 		 * Capability may be used to store.  Any store via a capability without | 
 | 		 * this permission will trap. | 
 | 		 */ | 
 | 		Store = CheriPermissionStore, | 
 | 		/** | 
 | 		 * Capabilities with store permission may be loaded through this | 
 | 		 * capability.  Without this, any loaded capability will have | 
 | 		 * `LoadMutable` and `Store` removed. | 
 | 		 */ | 
 | 		LoadMutable = CheriPermissionLoadMutable, | 
 | 		/** | 
 | 		 * This capability may be used to store capabilities that do not have | 
 | 		 * `Global` permission. | 
 | 		 */ | 
 | 		StoreLocal = CheriPermissionStoreLocal, | 
 | 		/** | 
 | 		 * This capability can be used to load. | 
 | 		 */ | 
 | 		Load = CheriPermissionLoad, | 
 | 		/** | 
 | 		 * Any load and store permissions on this capability convey the right to | 
 | 		 * load or store capabilities in addition to data. | 
 | 		 */ | 
 | 		LoadStoreCapability = CheriPermissionLoadStoreCapability, | 
 | 		/** | 
 | 		 * If installed as the program counter capability, running code may | 
 | 		 * access privileged system registers. | 
 | 		 */ | 
 | 		AccessSystemRegisters = CheriPermissionAccessSystemRegisters, | 
 | 		/** | 
 | 		 * This capability may be used as a jump target and used to execute | 
 | 		 * instructions. | 
 | 		 */ | 
 | 		Execute = CheriPermissionExecute, | 
 | 		/** | 
 | 		 * This capability may be used to unseal other capabilities.  The | 
 | 		 * 'address' range is in the sealing type namespace and not in the | 
 | 		 * memory namespace. | 
 | 		 */ | 
 | 		Unseal = CheriPermissionUnseal, | 
 | 		/** | 
 | 		 * This capability may be used to seal other capabilities.  The | 
 | 		 * 'address' range is in the sealing type namespace and not in the | 
 | 		 * memory namespace. | 
 | 		 */ | 
 | 		Seal = CheriPermissionSeal, | 
 | 		/** | 
 | 		 * Software defined permission bit, no architectural meaning. | 
 | 		 */ | 
 | 		User0 = CheriPermissionUser0 | 
 | 	}; | 
 |  | 
 | 	/** | 
 | 	 * Class encapsulating a set of permissions. | 
 | 	 */ | 
 | 	class PermissionSet | 
 | 	{ | 
 | 		/** | 
 | 		 * Helper that returns the bit associated with a given permission. | 
 | 		 */ | 
 | 		static constexpr uint32_t permission_bit(Permission p) | 
 | 		{ | 
 | 			return 1 << static_cast<uint32_t>(p); | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Helper for building permissions, adds a permission to the raw | 
 | 		 * bitfield. | 
 | 		 */ | 
 | 		__always_inline constexpr void add_permission(Permission p) | 
 | 		{ | 
 | 			rawPermissions |= permission_bit(p); | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Private constructor for creating a permission set from a raw bitmask. | 
 | 		 * This should never be used accidentally and so is hidden behind a | 
 | 		 * factory method with an explicit name.  Callers should use | 
 | 		 * `PermissionSet::from_raw`. | 
 | 		 */ | 
 | 		constexpr PermissionSet(uint32_t rawPermissions) | 
 | 		  : rawPermissions(rawPermissions) | 
 | 		{ | 
 | 		} | 
 |  | 
 | 		public: | 
 | 		/** | 
 | 		 * Computes (at compile time) a bitmask containing the set of valid | 
 | 		 * permission bits. | 
 | 		 * | 
 | 		 * FIXME would ideally make this private and expose a public static | 
 | 		 * constexpr field but this seems to trigger a compiler bug when trying | 
 | 		 * to initialise said field using this function. | 
 | 		 */ | 
 | 		static constexpr uint32_t valid_permissions_mask() | 
 | 		{ | 
 | 			uint32_t mask = 0; | 
 | 			for (auto permission : magic_enum::enum_values<Permission>()) | 
 | 			{ | 
 | 				mask |= 1 << static_cast<uint32_t>(permission); | 
 | 			} | 
 | 			return mask; | 
 | 		} | 
 |  | 
 | 		private: | 
 | 		/** | 
 | 		 * Permissions iterator.  Stores the permissions and iterates over them | 
 | 		 * one bit at a time. | 
 | 		 */ | 
 | 		class Iterator | 
 | 		{ | 
 | 			/// `PermissionSet` may construct this. | 
 | 			friend class PermissionSet; | 
 | 			/// The raw permissions bitmap. | 
 | 			uint32_t permissions; | 
 | 			/// Constructor, take a raw permissions bitmap. | 
 | 			constexpr Iterator(uint32_t rawPermissions) | 
 | 			  : permissions(rawPermissions) | 
 | 			{ | 
 | 			} | 
 |  | 
 | 			public: | 
 | 			/** | 
 | 			 * Dereference, returns the lowest-numbered permission. | 
 | 			 */ | 
 | 			constexpr Permission operator*() | 
 | 			{ | 
 | 				return Permission(__builtin_ffs(permissions) - 1); | 
 | 			} | 
 |  | 
 | 			/** | 
 | 			 * Preincrement, drops the lowest-numbered permission. | 
 | 			 */ | 
 | 			constexpr Iterator &operator++() | 
 | 			{ | 
 | 				permissions &= ~(1 << (__builtin_ffs(permissions) - 1)); | 
 | 				return *this; | 
 | 			} | 
 |  | 
 | 			/** | 
 | 			 * Returns true if the other iterator has a different set of | 
 | 			 * permissions. | 
 | 			 */ | 
 | 			constexpr bool operator!=(const Iterator Other) | 
 | 			{ | 
 | 				return permissions != Other.permissions; | 
 | 			} | 
 | 		}; | 
 |  | 
 | 		public: | 
 | 		/** | 
 | 		 * The raw bitmap of permissions.  This is public so that this class | 
 | 		 * meets the requirements of a structural type and can therefore be | 
 | 		 * used as a template parameter.  This field should never be directly | 
 | 		 * modified. | 
 | 		 */ | 
 | 		uint32_t rawPermissions = 0; | 
 |  | 
 | 		/** | 
 | 		 * Constructs a permission set from a raw permission mask. | 
 | 		 */ | 
 | 		static constexpr PermissionSet from_raw(uint32_t raw) | 
 | 		{ | 
 | 			raw &= valid_permissions_mask(); | 
 | 			return {raw}; | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Constructs a permission set from a single permission. | 
 | 		 */ | 
 | 		constexpr PermissionSet(Permission p) | 
 | 		{ | 
 | 			add_permission(p); | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Construct a permission set from a list of permissions. | 
 | 		 */ | 
 | 		__always_inline constexpr PermissionSet( | 
 | 		  std::initializer_list<Permission> permissions) | 
 | 		{ | 
 | 			for (auto p : permissions) | 
 | 			{ | 
 | 				add_permission(p); | 
 | 			} | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Copy constructor. | 
 | 		 */ | 
 | 		constexpr PermissionSet(const PermissionSet &other) | 
 |  | 
 | 		  = default; | 
 |  | 
 | 		/** | 
 | 		 * Returns a permission set representing all permissions. | 
 | 		 */ | 
 | 		constexpr static PermissionSet omnipotent() | 
 | 		{ | 
 | 			return PermissionSet{valid_permissions_mask()}; | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * And-permissions operation, creates a new permission set containing | 
 | 		 * only permissions present in both this set and the argument. | 
 | 		 */ | 
 | 		constexpr PermissionSet operator&(PermissionSet p) | 
 | 		{ | 
 | 			return PermissionSet{rawPermissions & p.rawPermissions}; | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * And-permissions operation, removes all permissions that are not | 
 | 		 * present in both permission sets. | 
 | 		 */ | 
 | 		constexpr PermissionSet &operator&=(PermissionSet p) | 
 | 		{ | 
 | 			rawPermissions &= p.rawPermissions; | 
 | 			return *this; | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Constructs a new permission set without the specified permission. | 
 | 		 */ | 
 | 		[[nodiscard]] constexpr PermissionSet without(Permission p) const | 
 | 		{ | 
 | 			return {rawPermissions & ~permission_bit(p)}; | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Constructs a new permission set without the specified permissions. | 
 | 		 */ | 
 | 		template<std::same_as<Permission>... Permissions> | 
 | 		[[nodiscard]] constexpr PermissionSet without(Permission p, | 
 | 		                                              Permissions... ps) const | 
 | 		{ | 
 | 			return this->without(p).without(ps...); | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Returns true if, and only if, this permission set can be derived | 
 | 		 * from the argument set. | 
 | 		 */ | 
 | 		[[nodiscard]] constexpr bool can_derive_from(PermissionSet other) const | 
 | 		{ | 
 | 			return (rawPermissions & other.rawPermissions) == rawPermissions; | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Returns true if this permission set contains the specified | 
 | 		 * permission. | 
 | 		 */ | 
 | 		[[nodiscard]] constexpr bool contains(Permission permission) const | 
 | 		{ | 
 | 			return (permission_bit(permission) & rawPermissions) == | 
 | 			       permission_bit(permission); | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Returns true if this permission set contains the specified | 
 | 		 * permissions. | 
 | 		 */ | 
 | 		template<std::same_as<Permission>... Permissions> | 
 | 		[[nodiscard]] constexpr bool contains(Permission p, | 
 | 		                                      Permissions... ps) const | 
 | 		{ | 
 | 			return this->contains(p) && this->contains(ps...); | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Returns the raw permission mask as an integer containing a bitfield | 
 | 		 * of permissions. | 
 | 		 */ | 
 | 		[[nodiscard]] constexpr uint32_t as_raw() const | 
 | 		{ | 
 | 			return rawPermissions; | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Returns an iterator over the permissions starting at the | 
 | 		 * lowest-numbered permission. | 
 | 		 */ | 
 | 		[[nodiscard]] constexpr Iterator begin() const | 
 | 		{ | 
 | 			return {rawPermissions}; | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Returns an end iterator. | 
 | 		 */ | 
 | 		[[nodiscard]] constexpr Iterator end() const | 
 | 		{ | 
 | 			// Each increment of an iterator will drop one permission and so an | 
 | 			// iterator will compare equal to {0} once all permissions have | 
 | 			// been dropped. | 
 | 			return {0}; | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Three-way comparison.  Treats a superset as greater-than, identical | 
 | 		 * permissions as equivalent, and sets that don't have a superset | 
 | 		 * releationship as unordered. | 
 | 		 */ | 
 | 		constexpr auto operator<=>(const PermissionSet Other) const | 
 | 		{ | 
 | 			if (rawPermissions == Other.rawPermissions) | 
 | 			{ | 
 | 				return std::partial_ordering::equivalent; | 
 | 			} | 
 | 			if (can_derive_from(Other)) | 
 | 			{ | 
 | 				return std::partial_ordering::less; | 
 | 			} | 
 | 			if (Other.can_derive_from(*this)) | 
 | 			{ | 
 | 				return std::partial_ordering::greater; | 
 | 			} | 
 | 			return std::partial_ordering::unordered; | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Equality operator, wraps the three-way compare operator. | 
 | 		 */ | 
 | 		constexpr bool operator==(PermissionSet other) const | 
 | 		{ | 
 | 			// Clang-tidy spuriously suggests that this 0 should be nullptr. | 
 | 			return (*this <=> other) == 0; // NOLINT(modernize-use-nullptr) | 
 | 		} | 
 | 	}; | 
 |  | 
 | 	/** | 
 | 	 * Rounds `len` up to a CHERI representable length for the current | 
 | 	 * architecture. | 
 | 	 */ | 
 | 	__always_inline inline size_t representable_length(size_t length) | 
 | 	{ | 
 | 		return __builtin_cheri_round_representable_length(length); | 
 | 	} | 
 |  | 
 | 	/** | 
 | 	 * Returns the alignment mask required for a given length. | 
 | 	 */ | 
 | 	__always_inline inline size_t representable_alignment_mask(size_t length) | 
 | 	{ | 
 | 		return __builtin_cheri_representable_alignment_mask(length); | 
 | 	} | 
 |  | 
 | 	/// Can the range [base, base + size) be precisely covered by a capability? | 
 | 	inline bool is_precise_range(ptraddr_t base, size_t size) | 
 | 	{ | 
 | 		return (base & ~representable_alignment_mask(size)) == 0 && | 
 | 		       representable_length(size) == size; | 
 | 	} | 
 |  | 
 | 	/** | 
 | 	 * Helper class for accessing capability properties on pointers. | 
 | 	 */ | 
 | 	template<typename T> | 
 | 	class Capability | 
 | 	{ | 
 | 		protected: | 
 | 		/// The capability that this class wraps. | 
 | 		T *ptr; | 
 |  | 
 | 		private: | 
 | 		/** | 
 | 		 * Constructs a PermissionSet with the permissions of the given pointer. | 
 | 		 */ | 
 | 		static PermissionSet permission_set_from_pointer(const void *p) | 
 | 		{ | 
 | 			auto perms = __builtin_cheri_perms_get(p); | 
 | 			auto mask  = PermissionSet::valid_permissions_mask(); | 
 | 			/* FIXME teach the compiler that the builtin always returns a value | 
 | 			 * that is a subset of the mask, otherwise it unnecessarily | 
 | 			 * constructs and applies the mask in from_raw */ | 
 | 			__builtin_assume((perms & ~mask) == 0); | 
 | 			return PermissionSet::from_raw(perms); | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Base class for the proxies that accessors in this class return. | 
 | 		 */ | 
 | 		class PropertyProxyBase | 
 | 		{ | 
 | 			protected: | 
 | 			/** | 
 | 			 * The capability that this proxy refers to. | 
 | 			 */ | 
 | 			Capability ∩ | 
 |  | 
 | 			/** | 
 | 			 * Replaces the underlying capability | 
 | 			 */ | 
 | 			template<typename U> | 
 | 			void set(U *newPtr) | 
 | 			{ | 
 | 				cap.ptr = static_cast<T *>(newPtr); | 
 | 			} | 
 |  | 
 | 			/** | 
 | 			 * Returns the capability's pointer. | 
 | 			 */ | 
 | 			[[nodiscard]] T *ptr() const | 
 | 			{ | 
 | 				return cap.ptr; | 
 | 			} | 
 |  | 
 | 			public: | 
 | 			/// Constructor, takes the capability whose property this class is | 
 | 			/// proxying. | 
 | 			PropertyProxyBase(Capability &c) : cap(c) {} | 
 | 		}; | 
 |  | 
 | 		/** | 
 | 		 * Proxy for accessing a capability's address. | 
 | 		 */ | 
 | 		struct AddressProxy : public PropertyProxyBase | 
 | 		{ | 
 | 			/// Inherit the constructor from the base class. | 
 | 			using PropertyProxyBase::PropertyProxyBase; | 
 | 			/// Inherit the pointer accesors | 
 | 			/// @{ | 
 | 			using PropertyProxyBase::ptr; | 
 | 			using PropertyProxyBase::set; | 
 | 			/// @} | 
 |  | 
 | 			/** | 
 | 			 * Implicit casts can convert this to an address. | 
 | 			 */ | 
 | 			operator ptraddr_t() const | 
 | 			{ | 
 | 				return __builtin_cheri_address_get(ptr()); | 
 | 			} | 
 |  | 
 | 			/** | 
 | 			 * Set the address in the underlying capability. | 
 | 			 */ | 
 | 			AddressProxy &operator=(ptraddr_t addr) | 
 | 			{ | 
 | 				set(__builtin_cheri_address_set(ptr(), addr)); | 
 | 				return *this; | 
 | 			} | 
 |  | 
 | 			/** | 
 | 			 * Set the address in the underlying capability given another | 
 | 			 * address proxy. | 
 | 			 */ | 
 | 			AddressProxy &operator=(AddressProxy addr) | 
 | 			{ | 
 | 				set(__builtin_cheri_address_set(ptr(), addr)); | 
 | 				return *this; | 
 | 			} | 
 |  | 
 | 			/** | 
 | 			 * Add a displacement to the capability's address. | 
 | 			 */ | 
 | 			AddressProxy &operator+=(ptrdiff_t displacement) | 
 | 			{ | 
 | 				set(__builtin_cheri_offset_increment(ptr(), displacement)); | 
 | 				return *this; | 
 | 			} | 
 |  | 
 | 			/** | 
 | 			 * Subtract a displacement from the capability's address. | 
 | 			 */ | 
 | 			AddressProxy &operator-=(ptrdiff_t displacement) | 
 | 			{ | 
 | 				set(__builtin_cheri_offset_increment(ptr(), -displacement)); | 
 | 				return *this; | 
 | 			} | 
 | 		}; | 
 |  | 
 | 		/** | 
 | 		 * Proxy for accessing an object's bounds. | 
 | 		 */ | 
 | 		struct BoundsProxy : public PropertyProxyBase | 
 | 		{ | 
 | 			/// Inherit the constructor from the base class. | 
 | 			using PropertyProxyBase::PropertyProxyBase; | 
 | 			/// Inherit the pointer accesors | 
 | 			/// @{ | 
 | 			using PropertyProxyBase::ptr; | 
 | 			using PropertyProxyBase::set; | 
 | 			/// @} | 
 |  | 
 | 			/** | 
 | 			 * Return the object's bounds (displacement from the address to the | 
 | 			 * end). | 
 | 			 */ | 
 | 			operator ptrdiff_t() const | 
 | 			{ | 
 | 				return __builtin_cheri_length_get(ptr()) - | 
 | 				       (__builtin_cheri_address_get(ptr()) - | 
 | 				        __builtin_cheri_base_get(ptr())); | 
 | 			} | 
 |  | 
 | 			/** | 
 | 			 * Set the capability's bounds, giving an invalid capability if this | 
 | 			 * cannot be represented exactly. | 
 | 			 */ | 
 | 			BoundsProxy &operator=(size_t bounds) | 
 | 			{ | 
 | 				set(__builtin_cheri_bounds_set_exact(ptr(), bounds)); | 
 | 				return *this; | 
 | 			} | 
 |  | 
 | 			/** | 
 | 			 * Set the bounds, adding some padding (up to the bounds of the | 
 | 			 * original capability) if necessary for alignment. | 
 | 			 */ | 
 | 			BoundsProxy &set_inexact(size_t bounds) | 
 | 			{ | 
 | 				set(__builtin_cheri_bounds_set(ptr(), bounds)); | 
 | 				return *this; | 
 | 			} | 
 |  | 
 | 			private: | 
 | 			BoundsProxy &set_inexact_at_most_slow(size_t bounds) | 
 | 			{ | 
 | 				ptraddr_t newBaseAddress = this->cap.address(); | 
 |  | 
 | 				// The number of bits in CHERIoT's capability encoding's | 
 | 				// mantissa.  This is part of the capability encoding and | 
 | 				// so, ideally, wouldn't be hard coded here. | 
 | 				static constexpr size_t MantissaBits = 9; | 
 |  | 
 | 				// The maximum possible representable length given the new | 
 | 				// base is a full mantissa width of 1s followed by 0s with | 
 | 				// its least significant 1 aligned to the least significant | 
 | 				// 1 in the base address. | 
 | 				size_t maximumLength = ((1 << MantissaBits) - 1) | 
 | 				                       << __builtin_ctz(newBaseAddress); | 
 |  | 
 | 				// Ensure that the requested length is representable by | 
 | 				// making sure that it fits within a mantissa width, | 
 | 				// rounding down by dropping any lower bits.  This might be | 
 | 				// excessive by up to one bit position, because the | 
 | 				// representable alignment mask is designed to work with the | 
 | 				// rounding-up inexact bounds setting instruction.  As a result, | 
 | 				// we might not return the largest possible representable | 
 | 				// length, but we won't return a wildly too small one, either. | 
 | 				size_t alignedLength = | 
 | 				  bounds & representable_alignment_mask(bounds); | 
 |  | 
 | 				// Select the smaller of those two lengths. | 
 | 				bounds = std::min<size_t>(alignedLength, maximumLength); | 
 | 				*this  = bounds; | 
 | 				return *this; | 
 | 			} | 
 |  | 
 | 			public: | 
 | 			/** | 
 | 			 * Set the bounds to `length` if `length` is representable with the | 
 | 			 * current alignment of `buffer`. If not, then select a smaller | 
 | 			 * `length` that is representable.  Unlike set_inexact(), the | 
 | 			 * resulting base will always be the current address; that is, there | 
 | 			 * will be no padding below the current address. | 
 | 			 * | 
 | 			 * The caller must call .length() on the resulting capability to | 
 | 			 * determine the imposed bounds. | 
 | 			 * | 
 | 			 * See is_precise_range(). | 
 | 			 */ | 
 | 			__always_inline BoundsProxy &set_inexact_at_most(size_t bounds) | 
 | 			{ | 
 | 				// Just try to set the requested bounds, first.  If that works, | 
 | 				// there's no need for bit-twiddling at all. | 
 | 				Capability p = ptr(); | 
 | 				p.bounds()   = bounds; | 
 | 				if (p.is_valid()) | 
 | 				{ | 
 | 					set(static_cast<T *>(p)); | 
 | 					return *this; | 
 | 				} | 
 |  | 
 | 				return set_inexact_at_most_slow(bounds); | 
 | 			} | 
 | 		}; | 
 |  | 
 | 		/** | 
 | 		 * Proxy for accessing a capability's permissions | 
 | 		 */ | 
 | 		struct PermissionsProxy : public PropertyProxyBase | 
 | 		{ | 
 | 			/// Inherit the constructor from the base class. | 
 | 			using PropertyProxyBase::PropertyProxyBase; | 
 | 			/// Inherit the pointer accesors | 
 | 			/// @{ | 
 | 			using PropertyProxyBase::ptr; | 
 | 			using PropertyProxyBase::set; | 
 | 			/// @} | 
 |  | 
 | 			/** | 
 | 			 * Implicitly convert to a permission set. | 
 | 			 */ | 
 | 			operator PermissionSet() const | 
 | 			{ | 
 | 				return permission_set_from_pointer(ptr()); | 
 | 			} | 
 |  | 
 | 			/** | 
 | 			 * And-permissions operation, removes all permissions that are not | 
 | 			 * present in both permission sets from the capability. | 
 | 			 */ | 
 | 			PermissionsProxy &operator&=(PermissionSet permissions) | 
 | 			{ | 
 | 				set(__builtin_cheri_perms_and(ptr(), permissions.as_raw())); | 
 | 				return *this; | 
 | 			} | 
 |  | 
 | 			/** | 
 | 			 * Returns a permission set containing only the permissions held by | 
 | 			 * the capability and the argument. | 
 | 			 */ | 
 | 			constexpr PermissionSet operator&(PermissionSet p) | 
 | 			{ | 
 | 				return static_cast<PermissionSet>(*this) & p; | 
 | 			} | 
 |  | 
 | 			/** | 
 | 			 * Constructs a new permission set without the specified | 
 | 			 * permissions. | 
 | 			 */ | 
 | 			template<std::same_as<Permission>... Permissions> | 
 | 			constexpr PermissionSet without(Permissions... ps) const | 
 | 			{ | 
 | 				return static_cast<PermissionSet>(*this).without(ps...); | 
 | 			} | 
 |  | 
 | 			/** | 
 | 			 * Returns true if, and only if, this permission set can be derived | 
 | 			 * from the argument set. | 
 | 			 */ | 
 | 			[[nodiscard]] constexpr bool | 
 | 			can_derive_from(PermissionSet other) const | 
 | 			{ | 
 | 				return static_cast<PermissionSet>(*this).can_derive_from(other); | 
 | 			} | 
 |  | 
 | 			/** | 
 | 			 * Returns true if this permission set contains the specified | 
 | 			 * permissions. | 
 | 			 */ | 
 | 			template<std::same_as<Permission>... Permissions> | 
 | 			constexpr bool contains(Permissions... permissions) const | 
 | 			{ | 
 | 				return static_cast<PermissionSet>(*this).contains( | 
 | 				  permissions...); | 
 | 			} | 
 |  | 
 | 			/** | 
 | 			 * Returns the raw permission mask as an integer containing a | 
 | 			 * bitfield of permissions. | 
 | 			 */ | 
 | 			[[nodiscard]] constexpr uint32_t as_raw() const | 
 | 			{ | 
 | 				return static_cast<PermissionSet>(*this).as_raw(); | 
 | 			} | 
 |  | 
 | 			/** | 
 | 			 * Returns an iterator over the permissions starting at the | 
 | 			 * lowest-numbered permission. | 
 | 			 */ | 
 | 			auto begin() | 
 | 			{ | 
 | 				return static_cast<PermissionSet>(*this).begin(); | 
 | 			} | 
 |  | 
 | 			/** | 
 | 			 * Returns an end iterator. | 
 | 			 */ | 
 | 			auto end() | 
 | 			{ | 
 | 				return static_cast<PermissionSet>(*this).end(); | 
 | 			} | 
 |  | 
 | 			/** | 
 | 			 * Comparison operator. | 
 | 			 */ | 
 | 			constexpr std::partial_ordering | 
 | 			operator<=>(const PermissionSet Other) const | 
 | 			{ | 
 | 				return static_cast<PermissionSet>(*this) <=> Other; | 
 | 			} | 
 |  | 
 | 			/** | 
 | 			 * Equality operator, wraps the three-way compare operator. | 
 | 			 */ | 
 | 			constexpr bool operator==(const PermissionSet Other) const | 
 | 			{ | 
 | 				return (*this <=> Other) == 0; | 
 | 			} | 
 | 		}; | 
 |  | 
 | 		/// The property proxy base is allowed to directly access the pointer | 
 | 		/// that this class wraps. | 
 | 		friend class PropertyProxyBase; | 
 |  | 
 | 		public: | 
 | 		/// Constructor from a null pointer. | 
 | 		constexpr Capability(std::nullptr_t) : ptr(nullptr) {} | 
 | 		/// Default constructor, initialises with a null pointer. | 
 | 		constexpr Capability() : ptr(nullptr) {} | 
 | 		/// Constructor, takes an existing pointer to wrap | 
 | 		constexpr Capability(T *p) : ptr(p) {} | 
 | 		/// Copy constructor, aliases the object that is pointed to by `ptr`. | 
 | 		constexpr Capability(const Capability &other) : ptr(other.ptr) {} | 
 | 		/// Move constructor. | 
 | 		constexpr Capability(Capability &&other) : ptr(other.ptr) | 
 | 		{ | 
 | 			other.ptr = nullptr; | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Replace the pointer that this capability wraps with another. | 
 | 		 */ | 
 | 		Capability &operator=(const Capability &other) | 
 | 		{ | 
 | 			ptr = other.ptr; | 
 | 			return *this; | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Transfer the pointer that this capability wraps from . | 
 | 		 */ | 
 | 		Capability &operator=(Capability &&other) | 
 | 		{ | 
 | 			ptr       = other.ptr; | 
 | 			other.ptr = nullptr; | 
 | 			return *this; | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Access the address of the capability. | 
 | 		 */ | 
 | 		AddressProxy address() [[clang::lifetimebound]] | 
 | 		{ | 
 | 			return {*this}; | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Return the address as an integer from a `const` capability. | 
 | 		 */ | 
 | 		[[nodiscard]] ptraddr_t address() const | 
 | 		{ | 
 | 			return __builtin_cheri_address_get(ptr); | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Access (read, set) the capability's bounds. | 
 | 		 */ | 
 | 		BoundsProxy bounds() [[clang::lifetimebound]] | 
 | 		{ | 
 | 			return {*this}; | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Return the bounds as an integer. | 
 | 		 */ | 
 | 		[[nodiscard]] ptrdiff_t bounds() const | 
 | 		{ | 
 | 			return __builtin_cheri_length_get(ptr) - | 
 | 			       (__builtin_cheri_address_get(ptr()) - | 
 | 			        __builtin_cheri_base_get(ptr())); | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Access the permissions of this capability. | 
 | 		 */ | 
 | 		PermissionsProxy permissions() [[clang::lifetimebound]] | 
 | 		{ | 
 | 			return {*this}; | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Get a copy of the permissions from a `const` capability. | 
 | 		 */ | 
 | 		[[nodiscard]] PermissionSet permissions() const | 
 | 		{ | 
 | 			return permission_set_from_pointer(ptr); | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Pointer subtraction. | 
 | 		 */ | 
 | 		Capability operator-(ptrdiff_t diff) | 
 | 		{ | 
 | 			return {ptr - diff}; | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Pointer subtraction. | 
 | 		 */ | 
 | 		Capability &operator-=(ptrdiff_t diff) | 
 | 		{ | 
 | 			ptr -= diff; | 
 | 			return *this; | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Pointer addition. | 
 | 		 */ | 
 | 		Capability operator+(ptrdiff_t diff) | 
 | 		{ | 
 | 			return {ptr + diff}; | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Pointer addition. | 
 | 		 */ | 
 | 		Capability &operator+=(ptrdiff_t diff) | 
 | 		{ | 
 | 			ptr += diff; | 
 | 			return *this; | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Returns the tag bit indicating whether this is a valid capability. | 
 | 		 */ | 
 | 		[[nodiscard]] bool is_valid() const | 
 | 		{ | 
 | 			// The clang static analyser doesn't yet know that null is untagged | 
 | 			// and so warns of possible null dereferences after this method | 
 | 			// returns true.  Explicitly assume that a tagged thing is non-null | 
 | 			// to fix this. | 
 | 			if (__builtin_cheri_tag_get(ptr)) | 
 | 			{ | 
 | 				__builtin_assume(ptr != nullptr); | 
 | 				return true; | 
 | 			} | 
 | 			return false; | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Return whether this is a sealed capability. | 
 | 		 */ | 
 | 		[[nodiscard]] bool is_sealed() const | 
 | 		{ | 
 | 			return __builtin_cheri_type_get(ptr) != 0; | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Returns the type of this capability, 0 if this is not a sealed | 
 | 		 * capability. | 
 | 		 */ | 
 | 		[[nodiscard]] uint32_t type() const | 
 | 		{ | 
 | 			return __builtin_cheri_type_get(ptr); | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Returns the base address of this capability. | 
 | 		 */ | 
 | 		[[nodiscard]] ptraddr_t base() const | 
 | 		{ | 
 | 			return __builtin_cheri_base_get(ptr); | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Returns the length of this capability. | 
 | 		 */ | 
 | 		[[nodiscard]] size_t length() const | 
 | 		{ | 
 | 			return __builtin_cheri_length_get(ptr); | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Returns the address of the top of this capability. | 
 | 		 */ | 
 | 		[[nodiscard]] ptraddr_t top() const | 
 | 		{ | 
 | 			return base() + length(); | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Capability comparison.  Defines ordered comparison for capabilities | 
 | 		 * with the same bounds and permissions.  All other capabilities are | 
 | 		 * either equivalent (identical bit pattern, including the tag bit) or | 
 | 		 * unordered. | 
 | 		 */ | 
 | 		constexpr std::partial_ordering operator<=>(T *other) const | 
 | 		{ | 
 | 			return (*this <=> Capability<T>{other}) == 0; | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Comparison against null pointer. | 
 | 		 * | 
 | 		 * Returns equivalent if this is a canonical null pointer, returns | 
 | 		 * unordered for any other (tagged or untagged) value.  Callers may | 
 | 		 * often want `is_valid` instead of this. | 
 | 		 */ | 
 | 		constexpr std::partial_ordering operator<=>(std::nullptr_t) const | 
 | 		{ | 
 | 			if (__builtin_cheri_equal_exact(ptr, nullptr)) | 
 | 			{ | 
 | 				return std::partial_ordering::equivalent; | 
 | 			} | 
 | 			return std::partial_ordering::unordered; | 
 | 		} | 
 |  | 
 | 		constexpr bool operator==(const Capability Other) const | 
 | 		{ | 
 | 			return __builtin_cheri_equal_exact(ptr, Other.ptr); | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Capability comparison.  Defines ordered comparison for capabilities | 
 | 		 * with the same bounds and permissions.  All other capabilities are | 
 | 		 * either equivalent (identical bit pattern, including the tag bit) or | 
 | 		 * unordered. | 
 | 		 * | 
 | 		 * Callers may want to compare addresses, rather than capabilities, if | 
 | 		 * they want a defined comparison that is stable between two objects. | 
 | 		 */ | 
 | 		constexpr std::partial_ordering | 
 | 		operator<=>(const Capability Other) const | 
 | 		{ | 
 | 			if (__builtin_cheri_equal_exact(ptr, Other.ptr)) | 
 | 			{ | 
 | 				return std::partial_ordering::equivalent; | 
 | 			} | 
 | 			// If neither capability is sealed, check if everything except the | 
 | 			// address is the same and define ordered comparison on pointers to | 
 | 			// the same object. | 
 | 			if (!(is_sealed() || Other.is_sealed()) && | 
 | 			    __builtin_cheri_equal_exact(__builtin_address_set( | 
 | 			      ptr, __builtin_address_get(Other), Other))) | 
 | 			{ | 
 | 				return static_cast<ptraddr_t>(ptr) <=> | 
 | 				       static_cast<ptraddr_t>(Other); | 
 | 			} | 
 | 			// Comparison of pointers to different objects is ub, you probably | 
 | 			// want address comparison: | 
 | 			return std::partial_ordering::unordered; | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Equality operator, wraps the three-way compare operator. | 
 | 		 */ | 
 | 		constexpr bool operator==(std::nullptr_t) const | 
 | 		{ | 
 | 			return (*this <=> nullptr) == 0; | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Implicit cast to the raw pointer type. | 
 | 		 */ | 
 | 		template<typename U = T> | 
 | 		requires(!std::same_as<U, void>) operator U *() | 
 | 		{ | 
 | 			return ptr; | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Implicit cast to a raw pointer type. | 
 | 		 */ | 
 | 		operator void *() | 
 | 		{ | 
 | 			return ptr; | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Access fields of the target as if this were a raw pointer. | 
 | 		 */ | 
 | 		T *operator->() | 
 | 		{ | 
 | 			return ptr; | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Explicitly get the raw pointer. | 
 | 		 */ | 
 | 		T *get() | 
 | 		{ | 
 | 			return ptr; | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Dereference operator. | 
 | 		 */ | 
 | 		template<typename U = T> | 
 | 		requires(!std::same_as<U, void>) U &operator*() | 
 | 		{ | 
 | 			return *ptr; | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Cast this capability to some other type. | 
 | 		 */ | 
 | 		template<typename U> | 
 | 		Capability<U> cast() | 
 | 		{ | 
 | 			return {static_cast<U *>(ptr)}; | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Returns true if the tags of `this` and `other` match and if `this` | 
 | 		 * conveys no rights that are not present in `other`.  Returns false in | 
 | 		 * all other cases. | 
 | 		 */ | 
 | 		template<typename U> | 
 | 		bool is_subset_of(Capability<U> other) | 
 | 		{ | 
 | 			return __builtin_cheri_subset_test(other.ptr, ptr); | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Seal this capability with the given key. | 
 | 		 */ | 
 | 		Capability<T> &seal(void *key) | 
 | 		{ | 
 | 			ptr = static_cast<T *>(__builtin_cheri_seal(ptr, key)); | 
 | 			return *this; | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Unseal this capability with the given key. | 
 | 		 */ | 
 | 		Capability<T> &unseal(void *key) | 
 | 		{ | 
 | #ifdef FLUTE | 
 | 			// Flute still throws exceptions on invalid use.  As a temporary | 
 | 			// work-around, add a quick check that this thing has the sealing | 
 | 			// type and don't unseal if it hasn't.  This isn't a complete test, | 
 | 			// it's just sufficient to get the tests passing on Flute. | 
 | 			if (type() != __builtin_cheri_address_get(key)) | 
 | 			{ | 
 | 				ptr = nullptr; | 
 | 			} | 
 | 			else | 
 | #endif | 
 | 			{ | 
 | 				ptr = static_cast<T *>(__builtin_cheri_unseal(ptr, key)); | 
 | 			} | 
 | 			return *this; | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Subscript operator. | 
 | 		 */ | 
 | 		template<typename U = T> | 
 | 		requires(!std::same_as<U, void>) U &operator[](size_t index) | 
 | 		{ | 
 | 			return ptr[index]; | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Returns true if the capability is `align`-byte aligned, false | 
 | 		 * otherwise. | 
 | 		 */ | 
 | 		bool is_aligned(size_t align) | 
 | 		{ | 
 | 			return __builtin_is_aligned(ptr, align); | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Aligns the capability down to the nearest `align`-byte boundary. | 
 | 		 */ | 
 | 		Capability &align_down(size_t align) | 
 | 		{ | 
 | 			ptr = __builtin_align_down(ptr, align); | 
 | 			return *this; | 
 | 		} | 
 |  | 
 | 		/** | 
 | 		 * Aligns the capability up to the nearest `align`-byte boundary. | 
 | 		 */ | 
 | 		Capability &align_up(size_t align) | 
 | 		{ | 
 | 			ptr = __builtin_align_up(ptr, align); | 
 | 			return *this; | 
 | 		} | 
 | 	}; | 
 |  | 
 | 	/** | 
 | 	 * Concept that matches pointers. | 
 | 	 */ | 
 | 	template<typename T> | 
 | 	concept IsPointer = std::is_pointer_v<T>; | 
 |  | 
 | 	/** | 
 | 	 * Concept that matches smart pointers, i.e., classes which implements | 
 | 	 * a `get` method returning a pointer, and supports `operator=` with | 
 | 	 * the return value of `get`. This will match `Capability`, standard | 
 | 	 * library smart pointers, etc. | 
 | 	 */ | 
 | 	template<typename T> | 
 | 	concept IsSmartPointerLike = requires(T b) | 
 | 	{ | 
 | 		{ | 
 | 			b.get() | 
 | 			} -> IsPointer; | 
 | 	} | 
 | 	&&requires(T b) | 
 | 	{ | 
 | 		b = b.get(); | 
 | 	}; | 
 |  | 
 | 	/** | 
 | 	 * Checks that `ptr` is valid, unsealed, has at least `Permissions`, | 
 | 	 * and has at least `Space` bytes after the current offset. | 
 | 	 * | 
 | 	 * `ptr` can be a pointer, or a smart pointer, i.e., any class that | 
 | 	 * supports a `get` method returning a pointer, and `operator=`. This | 
 | 	 * includes `Capability` and standard library smart pointers. | 
 | 	 * | 
 | 	 * If the permissions do not include Global, then this will also check | 
 | 	 * that the capability does not point to the current thread's stack. | 
 | 	 * This behaviour can be disabled (for example, for use in a shared | 
 | 	 * library) by passing `false` for `CheckStack`. | 
 | 	 * | 
 | 	 * If `EnforceStrictPermissions` is set to `true`, this will also set | 
 | 	 * the permissions of passed capability reference to `Permissions`, and | 
 | 	 * its bounds to `space`. This is useful for detecting cases where | 
 | 	 * compartments ask for less permissions than they actually require. | 
 | 	 * | 
 | 	 * This function is provided as a wrapper for the `::check_pointer` C | 
 | 	 * API. It is always inlined. For each call site, it materialises the | 
 | 	 * constants needed before performing an indirect call to | 
 | 	 * `::check_pointer`. | 
 | 	 */ | 
 | 	template<PermissionSet Permissions = PermissionSet{Permission::Load}, | 
 | 	         bool          CheckStack  = true, | 
 | 	         bool          EnforceStrictPermissions = false> | 
 | 	__always_inline inline bool check_pointer( | 
 | 	  auto  &ptr, | 
 | 	  size_t space = sizeof( | 
 | 	    std::remove_pointer< | 
 | 	      decltype(ptr)>)) requires(std:: | 
 | 	                                  is_pointer_v< | 
 | 	                                    std::remove_cvref_t<decltype(ptr)>> || | 
 | 	                                IsSmartPointerLike< | 
 | 	                                  std::remove_cvref_t<decltype(ptr)>>) | 
 | 	{ | 
 | 		// We can skip a stack check if we've asked for Global because the | 
 | 		// stack does not have this permission. | 
 | 		constexpr bool StackCheckNeeded = | 
 | 		  CheckStack && !Permissions.contains(Permission::Global); | 
 | 		constexpr bool IsRawPointer = | 
 | 		  std::is_pointer_v<std::remove_cvref_t<decltype(ptr)>>; | 
 |  | 
 | 		bool isValid; | 
 | 		if constexpr (IsRawPointer) | 
 | 		{ | 
 | 			// If passed `ptr` as a raw capability (e.g., `void*`), | 
 | 			// pass it as-is to ::check_pointer. | 
 | 			isValid = ::check_pointer( | 
 | 			  ptr, space, Permissions.as_raw(), StackCheckNeeded); | 
 | 		} | 
 | 		else | 
 | 		{ | 
 | 			// Otherwise, call `get` on `ptr` to retrieve a raw | 
 | 			// capability. | 
 | 			isValid = ::check_pointer( | 
 | 			  ptr.get(), space, Permissions.as_raw(), StackCheckNeeded); | 
 | 		} | 
 | 		// If passed `EnforceStrictPermissions`, set the permissions | 
 | 		// of `ptr` to `Permissions`, and its bounds to `space` | 
 | 		if constexpr (EnforceStrictPermissions) | 
 | 		{ | 
 | 			if (isValid) | 
 | 			{ | 
 | 				if constexpr (IsRawPointer) | 
 | 				{ | 
 | 					Capability cap{ptr}; | 
 | 					cap.permissions() &= Permissions; | 
 | 					cap.bounds() = space; | 
 | 					ptr          = cap.get(); | 
 | 				} | 
 | 				else | 
 | 				{ | 
 | 					Capability cap{ptr.get()}; | 
 | 					cap.permissions() &= Permissions; | 
 | 					cap.bounds() = space; | 
 | 					ptr          = cap.get(); | 
 | 				} | 
 | 			} | 
 | 		} | 
 | 		return isValid; | 
 | 	} | 
 |  | 
 | 	/** | 
 | 	 * Invokes the passed callable object with interrupts disabled. | 
 | 	 */ | 
 | 	template<typename T> | 
 | 	[[cheri::interrupt_state(disabled)]] auto with_interrupts_disabled(T &&fn) | 
 | 	{ | 
 | 		return fn(); | 
 | 	} | 
 |  | 
 | 	/** | 
 | 	 * The codes used in the cause field of the mtval CSR when the processor | 
 | 	 * takes a CHERI exception. | 
 | 	 */ | 
 | 	enum class CauseCode | 
 | 	{ | 
 | 		/** | 
 | 		 * No exception. This value is passed to the error handler after a | 
 | 		 * forced unwind in a called compartment. | 
 | 		 */ | 
 | 		None = CheriCauseCodeNone, | 
 | 		/** | 
 | 		 * Attempted to use a capability outside its bounds. | 
 | 		 */ | 
 | 		BoundsViolation = CheriCauseCodeBoundsViolation, | 
 | 		/** | 
 | 		 * Attempted to use an untagged capability to authorize something. | 
 | 		 */ | 
 | 		TagViolation = CheriCauseCodeTagViolation, | 
 | 		/** | 
 | 		 * Attempted to use a sealed capability to authorize something. | 
 | 		 */ | 
 | 		SealViolation = CheriCauseCodeSealViolation, | 
 | 		/** | 
 | 		 * Attempted to jump to a capability without `Permission::Execute`. | 
 | 		 */ | 
 | 		PermitExecuteViolation = CheriCauseCodePermitExecuteViolation, | 
 | 		/** | 
 | 		 * Attempted to load via a capability without `Permission::Load`. | 
 | 		 */ | 
 | 		PermitLoadViolation = CheriCauseCodePermitLoadViolation, | 
 | 		/** | 
 | 		 * Attempted to store via a capability without `Permission::Store`. | 
 | 		 */ | 
 | 		PermitStoreViolation = CheriCauseCodePermitStoreViolation, | 
 | 		/** | 
 | 		 * Attempted to store a tagged capability via a capability without | 
 | 		 * `Permission::LoadStoreCapability`. | 
 | 		 */ | 
 | 		PermitStoreCapabilityViolation = | 
 | 		  CheriCauseCodePermitStoreCapabilityViolation, | 
 | 		/** | 
 | 		 * Attempted to store a tagged capability without `Permission::Global` | 
 | 		 * via capability without `Permission::StoreLocal`. | 
 | 		 */ | 
 | 		PermitStoreLocalCapabilityViolation = | 
 | 		  CheriCauseCodePermitStoreLocalCapabilityViolation, | 
 | 		/** | 
 | 		 * Attempted to access a restricted CSR or SCR with PCC without | 
 | 		 * `Permission::AccessSystemRegisters`. | 
 | 		 */ | 
 | 		PermitAccessSystemRegistersViolation = | 
 | 		  CheriCauseCodePermitAccessSystemRegistersViolation, | 
 | 		/** | 
 | 		 * Used to represent a value that has no valid meaning in hardware. | 
 | 		 */ | 
 | 		Invalid = CheriCauseCodeInvalid, | 
 | 	}; | 
 |  | 
 | 	/** | 
 | 	 * Register numbers as reported in cap idx field of  `mtval` CSR when | 
 | 	 * a CHERI exception is taken. Values less than 32 refer to general | 
 | 	 * purpose registers and others to SCRs (of these, only PCC can actually | 
 | 	 * cause an exception). | 
 | 	 */ | 
 | 	enum class RegisterNumber | 
 | 	{ | 
 | 		/** | 
 | 		 * The zero register, which always contains the `NULL` capability. | 
 | 		 */ | 
 | 		CZR = CheriRegisterNumberCzr, | 
 | 		/** | 
 | 		 * `$c1` / `$cra` used by the ABI as the return address. | 
 | 		 * Not preserved across calls. | 
 | 		 */ | 
 | 		CRA = CheriRegisterNumberCra, | 
 | 		/** | 
 | 		 * `$c2` / `$csp` used by the ABI as the stack pointer. | 
 | 		 * Preserved across calls. | 
 | 		 */ | 
 | 		CSP = CheriRegisterNumberCsp, | 
 | 		/** | 
 | 		 * `$c3` / `$cgp` used by the ABI as the global pointer. | 
 | 		 * Not allocatable by the compiler, set by the switcher on compartment | 
 | 		 * entry. | 
 | 		 */ | 
 | 		CGP = CheriRegisterNumberCgp, | 
 | 		/** | 
 | 		 * `$c4` / `$ctp` used by the ABI as the thread pointer. | 
 | 		 * Currently unused by the compiler. | 
 | 		 * Not preserved across compartment calls. | 
 | 		 */ | 
 | 		CTP = CheriRegisterNumberCtp, | 
 | 		/** | 
 | 		 * `$c5` / `$ct0` used by the ABI as temporary register. | 
 | 		 * Not preserved across calls. | 
 | 		 */ | 
 | 		CT0 = CheriRegisterNumberCT0, | 
 | 		/** | 
 | 		 * `$c6` / `$ct1` used by the ABI as temporary register. | 
 | 		 * Not preserved across calls. | 
 | 		 */ | 
 | 		CT1 = CheriRegisterNumberCT1, | 
 | 		/** | 
 | 		 * `$c7` / `$ct2` used by the ABI as temporary register. | 
 | 		 * Not preserved across calls. | 
 | 		 */ | 
 | 		CT2 = CheriRegisterNumberCT2, | 
 | 		/** | 
 | 		 * `$c8` / `$cs0` used by the ABI as a callee-saved register. | 
 | 		 * Preserved across calls. | 
 | 		 */ | 
 | 		CS0 = CheriRegisterNumberCS0, | 
 | 		/** | 
 | 		 * `$c9` / `$cs1` used by the ABI as a callee-saved register. | 
 | 		 * Preserved across calls. | 
 | 		 */ | 
 | 		CS1 = CheriRegisterNumberCS1, | 
 | 		/** | 
 | 		 * `$c10` / `$ca0` used by the ABI as an argument register. | 
 | 		 * Not preserved across calls. | 
 | 		 */ | 
 | 		CA0 = CheriRegisterNumberCA0, | 
 | 		/** | 
 | 		 * `$c11` / `$ca1` used by the ABI as an argument register. | 
 | 		 * Not preserved across calls. | 
 | 		 */ | 
 | 		CA1 = CheriRegisterNumberCA1, | 
 | 		/** | 
 | 		 * `$c12` / `$ca2` used by the ABI as an argument register. | 
 | 		 * Not preserved across calls. | 
 | 		 */ | 
 | 		CA2 = CheriRegisterNumberCA2, | 
 | 		/** | 
 | 		 * `$c13` / `$ca3` used by the ABI as an argument register. | 
 | 		 * Not preserved across calls. | 
 | 		 */ | 
 | 		CA3 = CheriRegisterNumberCA3, | 
 | 		/** | 
 | 		 * `$c14` / `$ca4` used by the ABI as an argument register. | 
 | 		 * Not preserved across calls. | 
 | 		 */ | 
 | 		CA4 = CheriRegisterNumberCA4, | 
 | 		/** | 
 | 		 * `$c15` / `$ca5` used by the ABI as an argument register. | 
 | 		 * Not preserved across calls. | 
 | 		 */ | 
 | 		CA5 = CheriRegisterNumberCA5, | 
 | 		/** | 
 | 		 * The Program Counter Capability. | 
 | 		 * | 
 | 		 * Special capability register used to authorize instruction fetch. The | 
 | 		 * address is that of the faulting instruction. Also used for accessing | 
 | 		 * read-only globals. | 
 | 		 */ | 
 | 		PCC = CheriRegisterNumberPcc, | 
 | 		/** | 
 | 		 * Machine-mode Trap Code Capability. | 
 | 		 * | 
 | 		 * Special capability register that | 
 | 		 * is installed in PCC when the CPU takes a trap. The address has the | 
 | 		 * same semantics as the RISC-V `mtvec` CSR. Only accessible when PCC | 
 | 		 * has the AccessSystemRegisters permission. | 
 | 		 */ | 
 | 		MTCC = CheriRegisterNumberMtcc, | 
 | 		/** | 
 | 		 * Machine-mode Tusted Data Capability. | 
 | 		 * | 
 | 		 * Special capability register that contains the memory root capability | 
 | 		 * on boot. Only accessible when PCC has the AccessSystemRegisters | 
 | 		 * permission.  Use by the RTOS to store a capability to the trusted | 
 | 		 * stack. | 
 | 		 */ | 
 | 		MTDC = CheriRegisterNumberMtdc, | 
 | 		/** | 
 | 		 * Machine-mode Scratch Capability. Special capabiltiy register that | 
 | 		 * contains the sealing root capability on boot. Only accessible when | 
 | 		 * PCC has the AccessSystemRegisters permission. | 
 | 		 */ | 
 | 		MScratchC = CheriRegisterNumberMScratchC, | 
 | 		/** | 
 | 		 * Machine-mode Exception Program Counter Capability. Special capability | 
 | 		 * register that contains the PCC of the faulting instruction on trap. | 
 | 		 * The address has the same semantics as the RISC-V `mepc` CSR. Only | 
 | 		 * accessible when PCC has the AccessSystemRegisters permission. | 
 | 		 */ | 
 | 		MEPCC = CheriRegisterNumberMepcc, | 
 | 		/** | 
 | 		 * Indicates a value that is not used by the hardware to refer to a | 
 | 		 * register. | 
 | 		 */ | 
 | 		Invalid = CheriRegisterNumberInvalid, | 
 | 	}; | 
 |  | 
 | 	/** | 
 | 	 * Decompose the value reported in the `mtval` CSR on CHERI exception | 
 | 	 * into a pair of `CauseCode` and `RegisterNumber`. | 
 | 	 * | 
 | 	 * Will return `CauseCode::Invalid` if the code field is not one | 
 | 	 * of the defined causes and `RegisterNumber::Invalid` if the register | 
 | 	 * number is not a valid register number. Other bits of mtval are ignored. | 
 | 	 */ | 
 | 	inline std::pair<CauseCode, RegisterNumber> | 
 | 	extract_cheri_mtval(uint32_t mtval) | 
 | 	{ | 
 | 		auto causeCode = magic_enum::enum_cast<CauseCode>(mtval & 0x1f) | 
 | 		                   .value_or(CauseCode::Invalid); | 
 | 		auto registerNumber = | 
 | 		  magic_enum::enum_cast<RegisterNumber>((mtval >> 5) & 0x3f) | 
 | 		    .value_or(RegisterNumber::Invalid); | 
 | 		return {causeCode, registerNumber}; | 
 | 	} | 
 | } // namespace CHERI |