| /* |
| * Copyright (c) 2020 Intel Corporation |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| #ifndef ZEPHYR_INCLUDE_SYS_KOBJECT_H |
| #define ZEPHYR_INCLUDE_SYS_KOBJECT_H |
| |
| #include <stdint.h> |
| #include <stddef.h> |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| struct k_thread; |
| struct k_mutex; |
| struct z_futex_data; |
| |
| /** |
| * @brief Kernel Object Types |
| * |
| * This enumeration needs to be kept in sync with the lists of kernel objects |
| * and subsystems in scripts/gen_kobject_list.py, as well as the otype_to_str() |
| * function in kernel/userspace.c |
| */ |
| enum k_objects { |
| K_OBJ_ANY, |
| |
| /** @cond |
| * Doxygen should ignore this build-time generated include file |
| * when generating API documentation. Enumeration values are |
| * generated during build by gen_kobject_list.py. It includes |
| * basic kernel objects (e.g. pipes and mutexes) and driver types. |
| */ |
| #include <kobj-types-enum.h> |
| /** @endcond |
| */ |
| |
| K_OBJ_LAST |
| }; |
| /** |
| * @defgroup usermode_apis User Mode APIs |
| * @ingroup kernel_apis |
| * @{ |
| */ |
| |
| #ifdef CONFIG_USERSPACE |
| #ifdef CONFIG_GEN_PRIV_STACKS |
| /* Metadata struct for K_OBJ_THREAD_STACK_ELEMENT */ |
| struct z_stack_data { |
| /* Size of the entire stack object, including reserved areas */ |
| size_t size; |
| |
| /* Stack buffer for privilege mode elevations */ |
| uint8_t *priv; |
| }; |
| #endif /* CONFIG_GEN_PRIV_STACKS */ |
| |
| /* Object extra data. Only some objects use this, determined by object type */ |
| union z_object_data { |
| /* Backing mutex for K_OBJ_SYS_MUTEX */ |
| struct k_mutex *mutex; |
| |
| /* Numerical thread ID for K_OBJ_THREAD */ |
| unsigned int thread_id; |
| |
| #ifdef CONFIG_GEN_PRIV_STACKS |
| /* Metadata for K_OBJ_THREAD_STACK_ELEMENT */ |
| const struct z_stack_data *stack_data; |
| #else |
| /* Stack buffer size for K_OBJ_THREAD_STACK_ELEMENT */ |
| size_t stack_size; |
| #endif /* CONFIG_GEN_PRIV_STACKS */ |
| |
| /* Futex wait queue and spinlock for K_OBJ_FUTEX */ |
| struct z_futex_data *futex_data; |
| |
| /* All other objects */ |
| int unused; |
| }; |
| |
| /* Table generated by gperf, these objects are retrieved via |
| * z_object_find() */ |
| struct z_object { |
| void *name; |
| uint8_t perms[CONFIG_MAX_THREAD_BYTES]; |
| uint8_t type; |
| uint8_t flags; |
| union z_object_data data; |
| } __packed __aligned(4); |
| |
| struct z_object_assignment { |
| struct k_thread *thread; |
| void * const *objects; |
| }; |
| |
| /** |
| * @brief Grant a static thread access to a list of kernel objects |
| * |
| * For threads declared with K_THREAD_DEFINE(), grant the thread access to |
| * a set of kernel objects. These objects do not need to be in an initialized |
| * state. The permissions will be granted when the threads are initialized |
| * in the early boot sequence. |
| * |
| * All arguments beyond the first must be pointers to kernel objects. |
| * |
| * @param name_ Name of the thread, as passed to K_THREAD_DEFINE() |
| */ |
| #define K_THREAD_ACCESS_GRANT(name_, ...) \ |
| static void * const _CONCAT(_object_list_, name_)[] = \ |
| { __VA_ARGS__, NULL }; \ |
| static const STRUCT_SECTION_ITERABLE(z_object_assignment, \ |
| _CONCAT(_object_access_, name_)) = \ |
| { (&_k_thread_obj_ ## name_), \ |
| (_CONCAT(_object_list_, name_)) } |
| |
| /** Object initialized */ |
| #define K_OBJ_FLAG_INITIALIZED BIT(0) |
| /** Object is Public */ |
| #define K_OBJ_FLAG_PUBLIC BIT(1) |
| /** Object allocated */ |
| #define K_OBJ_FLAG_ALLOC BIT(2) |
| /** Driver Object */ |
| #define K_OBJ_FLAG_DRIVER BIT(3) |
| |
| /** |
| * Lookup a kernel object and init its metadata if it exists |
| * |
| * Calling this on an object will make it usable from userspace. |
| * Intended to be called as the last statement in kernel object init |
| * functions. |
| * |
| * @param obj Address of the kernel object |
| */ |
| void z_object_init(const void *obj); |
| |
| /** |
| * Grant a thread access to a kernel object |
| * |
| * The thread will be granted access to the object if the caller is from |
| * supervisor mode, or the caller is from user mode AND has permissions |
| * on both the object and the thread whose access is being granted. |
| * |
| * @param object Address of kernel object |
| * @param thread Thread to grant access to the object |
| */ |
| __syscall void k_object_access_grant(const void *object, |
| struct k_thread *thread); |
| |
| /** |
| * Revoke a thread's access to a kernel object |
| * |
| * The thread will lose access to the object if the caller is from |
| * supervisor mode, or the caller is from user mode AND has permissions |
| * on both the object and the thread whose access is being revoked. |
| * |
| * @param object Address of kernel object |
| * @param thread Thread to remove access to the object |
| */ |
| void k_object_access_revoke(const void *object, struct k_thread *thread); |
| |
| /** |
| * @brief Release an object |
| * |
| * Allows user threads to drop their own permission on an object |
| * Their permissions are automatically cleared when a thread terminates. |
| * |
| * @param object The object to be released |
| * |
| */ |
| __syscall void k_object_release(const void *object); |
| |
| /** |
| * Grant all present and future threads access to an object |
| * |
| * If the caller is from supervisor mode, or the caller is from user mode and |
| * have sufficient permissions on the object, then that object will have |
| * permissions granted to it for *all* current and future threads running in |
| * the system, effectively becoming a public kernel object. |
| * |
| * Use of this API should be avoided on systems that are running untrusted code |
| * as it is possible for such code to derive the addresses of kernel objects |
| * and perform unwanted operations on them. |
| * |
| * It is not possible to revoke permissions on public objects; once public, |
| * any thread may use it. |
| * |
| * @param object Address of kernel object |
| */ |
| void k_object_access_all_grant(const void *object); |
| |
| #else |
| /* LCOV_EXCL_START */ |
| #define K_THREAD_ACCESS_GRANT(thread, ...) |
| |
| /** |
| * @internal |
| */ |
| static inline void z_object_init(const void *obj) |
| { |
| ARG_UNUSED(obj); |
| } |
| |
| /** |
| * @internal |
| */ |
| static inline void z_impl_k_object_access_grant(const void *object, |
| struct k_thread *thread) |
| { |
| ARG_UNUSED(object); |
| ARG_UNUSED(thread); |
| } |
| |
| /** |
| * @internal |
| */ |
| static inline void k_object_access_revoke(const void *object, |
| struct k_thread *thread) |
| { |
| ARG_UNUSED(object); |
| ARG_UNUSED(thread); |
| } |
| |
| /** |
| * @internal |
| */ |
| static inline void z_impl_k_object_release(const void *object) |
| { |
| ARG_UNUSED(object); |
| } |
| |
| static inline void k_object_access_all_grant(const void *object) |
| { |
| ARG_UNUSED(object); |
| } |
| /* LCOV_EXCL_STOP */ |
| #endif /* !CONFIG_USERSPACE */ |
| |
| #ifdef CONFIG_DYNAMIC_OBJECTS |
| /** |
| * Allocate a kernel object of a designated type |
| * |
| * This will instantiate at runtime a kernel object of the specified type, |
| * returning a pointer to it. The object will be returned in an uninitialized |
| * state, with the calling thread being granted permission on it. The memory |
| * for the object will be allocated out of the calling thread's resource pool. |
| * |
| * Currently, allocation of thread stacks is not supported. |
| * |
| * @param otype Requested kernel object type |
| * @return A pointer to the allocated kernel object, or NULL if memory wasn't |
| * available |
| */ |
| __syscall void *k_object_alloc(enum k_objects otype); |
| |
| /** |
| * Allocate memory and install as a generic kernel object |
| * |
| * This is a low-level function to allocate some memory, and register that |
| * allocated memory in the kernel object lookup tables with type K_OBJ_ANY. |
| * Initialization state and thread permissions will be cleared. The |
| * returned z_object's data value will be uninitialized. |
| * |
| * Most users will want to use k_object_alloc() instead. |
| * |
| * Memory allocated will be drawn from the calling thread's reasource pool |
| * and may be freed later by passing the actual object pointer (found |
| * in the returned z_object's 'name' member) to k_object_free(). |
| * |
| * @param align Required memory alignment for the allocated object |
| * @param size Size of the allocated object |
| * @return NULL on insufficient memory |
| * @return A pointer to the associated z_object that is installed in the |
| * kernel object tables |
| */ |
| struct z_object *z_dynamic_object_aligned_create(size_t align, size_t size); |
| |
| /** |
| * Allocate memory and install as a generic kernel object |
| * |
| * This is a low-level function to allocate some memory, and register that |
| * allocated memory in the kernel object lookup tables with type K_OBJ_ANY. |
| * Initialization state and thread permissions will be cleared. The |
| * returned z_object's data value will be uninitialized. |
| * |
| * Most users will want to use k_object_alloc() instead. |
| * |
| * Memory allocated will be drawn from the calling thread's reasource pool |
| * and may be freed later by passing the actual object pointer (found |
| * in the returned z_object's 'name' member) to k_object_free(). |
| * |
| * @param size Size of the allocated object |
| * @return NULL on insufficient memory |
| * @return A pointer to the associated z_object that is installed in the |
| * kernel object tables |
| */ |
| static inline struct z_object *z_dynamic_object_create(size_t size) |
| { |
| return z_dynamic_object_aligned_create(0, size); |
| } |
| |
| /** |
| * Free a kernel object previously allocated with k_object_alloc() |
| * |
| * This will return memory for a kernel object back to resource pool it was |
| * allocated from. Care must be exercised that the object will not be used |
| * during or after when this call is made. |
| * |
| * @param obj Pointer to the kernel object memory address. |
| */ |
| void k_object_free(void *obj); |
| #else |
| |
| /* LCOV_EXCL_START */ |
| static inline void *z_impl_k_object_alloc(enum k_objects otype) |
| { |
| ARG_UNUSED(otype); |
| |
| return NULL; |
| } |
| |
| static inline struct z_object *z_dynamic_object_aligned_create(size_t align, |
| size_t size) |
| { |
| ARG_UNUSED(align); |
| ARG_UNUSED(size); |
| |
| return NULL; |
| } |
| |
| static inline struct z_object *z_dynamic_object_create(size_t size) |
| { |
| ARG_UNUSED(size); |
| |
| return NULL; |
| } |
| |
| /** |
| * @brief Free an object |
| * |
| * @param obj |
| */ |
| static inline void k_object_free(void *obj) |
| { |
| ARG_UNUSED(obj); |
| } |
| /* LCOV_EXCL_STOP */ |
| #endif /* CONFIG_DYNAMIC_OBJECTS */ |
| |
| /** @} */ |
| |
| #include <syscalls/kobject.h> |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif |