543 lines
15 KiB
C

/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
/*
*
* (C) COPYRIGHT 2024 ARM Limited. All rights reserved.
*
* This program is free software and is provided to you under the terms of the
* GNU General Public License version 2 as published by the Free Software
* Foundation, and any use by you of this program is subject to the terms
* of such GNU license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you can access it online at
* http://www.gnu.org/licenses/gpl-2.0.html.
*
*/
#ifndef _KBASE_IOCTL_HELPERS_H_
#define _KBASE_IOCTL_HELPERS_H_
#include <uapi/gpu/arm/bifrost/mali_kbase_ioctl.h>
/* Macro for IOCTLs that don't have IOCTL struct */
#define KBASE_HANDLE_IOCTL(cmd, function, arg) \
do { \
int ret; \
BUILD_BUG_ON(_IOC_DIR(cmd) != _IOC_NONE); \
dev_dbg(arg->kbdev->dev, "Enter ioctl %s\n", #function); \
ret = function(arg); \
dev_dbg(arg->kbdev->dev, "Return %d from ioctl %s\n", ret, #function); \
return ret; \
} while (0)
/* Macro for IOCTLs that have input IOCTL struct */
#define KBASE_HANDLE_IOCTL_IN(cmd, function, type, arg) \
do { \
type param; \
int ret, err; \
dev_dbg(arg->kbdev->dev, "Enter ioctl %s\n", #function); \
BUILD_BUG_ON(_IOC_DIR(cmd) != _IOC_WRITE); \
BUILD_BUG_ON(sizeof(param) != _IOC_SIZE(cmd)); \
err = copy_from_user(&param, uarg, sizeof(param)); \
if (unlikely(err)) \
return -EFAULT; \
err = check_padding_##cmd(&param); \
if (unlikely(err)) \
return -EINVAL; \
ret = function(arg, &param); \
dev_dbg(arg->kbdev->dev, "Return %d from ioctl %s\n", ret, #function); \
return ret; \
} while (0)
/* Macro for IOCTLs that have output IOCTL struct */
#define KBASE_HANDLE_IOCTL_OUT(cmd, function, type, arg) \
do { \
type param; \
int ret, err; \
dev_dbg(arg->kbdev->dev, "Enter ioctl %s\n", #function); \
BUILD_BUG_ON(_IOC_DIR(cmd) != _IOC_READ); \
BUILD_BUG_ON(sizeof(param) != _IOC_SIZE(cmd)); \
memset(&param, 0, sizeof(param)); \
ret = function(arg, &param); \
err = copy_to_user(uarg, &param, sizeof(param)); \
if (unlikely(err)) \
return -EFAULT; \
dev_dbg(arg->kbdev->dev, "Return %d from ioctl %s\n", ret, #function); \
return ret; \
} while (0)
/* Macro for IOCTLs that have input and output IOCTL struct */
#define KBASE_HANDLE_IOCTL_INOUT(cmd, function, type, arg) \
do { \
type param; \
int ret, err; \
dev_dbg(arg->kbdev->dev, "Enter ioctl %s\n", #function); \
BUILD_BUG_ON(_IOC_DIR(cmd) != (_IOC_WRITE | _IOC_READ)); \
BUILD_BUG_ON(sizeof(param) != _IOC_SIZE(cmd)); \
err = copy_from_user(&param, uarg, sizeof(param)); \
if (unlikely(err)) \
return -EFAULT; \
err = check_padding_##cmd(&param); \
if (unlikely(err)) \
return -EINVAL; \
ret = function(arg, &param); \
err = copy_to_user(uarg, &param, sizeof(param)); \
if (unlikely(err)) \
return -EFAULT; \
dev_dbg(arg->kbdev->dev, "Return %d from ioctl %s\n", ret, #function); \
return ret; \
} while (0)
/* Inline functions to check padding bytes in the input IOCTL struct.
* Return 0 if all padding bytes are zero, non-zero otherwise.
*/
static inline int check_padding_KBASE_IOCTL_VERSION_CHECK(struct kbase_ioctl_version_check *p)
{
return 0;
}
static inline int
check_padding_KBASE_IOCTL_VERSION_CHECK_RESERVED(struct kbase_ioctl_version_check *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_SET_FLAGS(struct kbase_ioctl_set_flags *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_GET_GPUPROPS(struct kbase_ioctl_get_gpuprops *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_MEM_ALLOC(union kbase_ioctl_mem_alloc *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_MEM_QUERY(union kbase_ioctl_mem_query *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_MEM_FREE(struct kbase_ioctl_mem_free *p)
{
return 0;
}
static inline int
check_padding_KBASE_IOCTL_HWCNT_READER_SETUP(struct kbase_ioctl_hwcnt_reader_setup *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_HWCNT_SET(struct kbase_ioctl_hwcnt_values *p)
{
return p->padding;
}
static inline int check_padding_KBASE_IOCTL_GET_DDK_VERSION(struct kbase_ioctl_get_ddk_version *p)
{
return p->padding;
}
static inline int check_padding_KBASE_IOCTL_MEM_JIT_INIT(struct kbase_ioctl_mem_jit_init *p)
{
size_t i;
for (i = 0; i < ARRAY_SIZE(p->padding); i++) {
if (p->padding[i])
return -1;
}
return 0;
}
static inline int check_padding_KBASE_IOCTL_MEM_SYNC(struct kbase_ioctl_mem_sync *p)
{
size_t i;
/*
* Checking p->padding is deferred till the support window for backward-compatibility ends.
* GPUCORE-42000 will add the checking.
*
* To avoid the situation with old version of base which might not set padding bytes as 0,
* padding bytes are set as zero here on behalf on user space.
*/
for (i = 0; i < ARRAY_SIZE(p->padding); i++)
p->padding[i] = 0;
return 0;
}
static inline int
check_padding_KBASE_IOCTL_MEM_FIND_CPU_OFFSET(union kbase_ioctl_mem_find_cpu_offset *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_TLSTREAM_ACQUIRE(struct kbase_ioctl_tlstream_acquire *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_MEM_COMMIT(struct kbase_ioctl_mem_commit *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_MEM_ALIAS(union kbase_ioctl_mem_alias *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_MEM_IMPORT(union kbase_ioctl_mem_import *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_MEM_FLAGS_CHANGE(struct kbase_ioctl_mem_flags_change *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_STREAM_CREATE(struct kbase_ioctl_stream_create *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_FENCE_VALIDATE(struct kbase_ioctl_fence_validate *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_MEM_PROFILE_ADD(struct kbase_ioctl_mem_profile_add *p)
{
return p->padding;
}
static inline int
check_padding_KBASE_IOCTL_STICKY_RESOURCE_MAP(struct kbase_ioctl_sticky_resource_map *p)
{
return 0;
}
static inline int
check_padding_KBASE_IOCTL_STICKY_RESOURCE_UNMAP(struct kbase_ioctl_sticky_resource_unmap *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_MEM_FIND_GPU_START_AND_OFFSET(
union kbase_ioctl_mem_find_gpu_start_and_offset *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_CINSTR_GWT_DUMP(union kbase_ioctl_cinstr_gwt_dump *p)
{
/*
* Checking p->padding is deferred till the support window for backward-compatibility ends.
* GPUCORE-42000 will add the checking.
*
* To avoid the situation with old version of base which might not set padding bytes as 0,
* padding bytes are set as zero here on behalf on user space.
*/
p->in.padding = 0;
return 0;
}
static inline int check_padding_KBASE_IOCTL_MEM_EXEC_INIT(struct kbase_ioctl_mem_exec_init *p)
{
return 0;
}
static inline int
check_padding_KBASE_IOCTL_GET_CPU_GPU_TIMEINFO(union kbase_ioctl_get_cpu_gpu_timeinfo *p)
{
size_t i;
for (i = 0; i < ARRAY_SIZE(p->in.paddings); i++) {
if (p->in.paddings[i])
return -1;
}
return 0;
}
static inline int
check_padding_KBASE_IOCTL_CONTEXT_PRIORITY_CHECK(struct kbase_ioctl_context_priority_check *p)
{
return 0;
}
static inline int
check_padding_KBASE_IOCTL_SET_LIMITED_CORE_COUNT(struct kbase_ioctl_set_limited_core_count *p)
{
return 0;
}
static inline int
check_padding_KBASE_IOCTL_KINSTR_PRFCNT_ENUM_INFO(struct kbase_ioctl_kinstr_prfcnt_enum_info *p)
{
return 0;
}
static inline int
check_padding_KBASE_IOCTL_KINSTR_PRFCNT_SETUP(union kbase_ioctl_kinstr_prfcnt_setup *p)
{
return 0;
}
#if MALI_UNIT_TEST
#endif /* MALI_UNIT_TEST */
#if MALI_USE_CSF
static inline int
check_padding_KBASE_IOCTL_CS_QUEUE_REGISTER(struct kbase_ioctl_cs_queue_register *p)
{
size_t i;
for (i = 0; i < ARRAY_SIZE(p->padding); i++) {
if (p->padding[i])
return -1;
}
return 0;
}
static inline int check_padding_KBASE_IOCTL_CS_QUEUE_KICK(struct kbase_ioctl_cs_queue_kick *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_CS_QUEUE_BIND(union kbase_ioctl_cs_queue_bind *p)
{
size_t i;
/*
* Checking p->padding is deferred till the support window for backward-compatibility ends.
* GPUCORE-42000 will add the checking.
*
* To avoid the situation with old version of base which might not set padding bytes as 0,
* padding bytes are set as zero here on behalf on user space.
*/
for (i = 0; i < ARRAY_SIZE(p->in.padding); i++)
p->in.padding[i] = 0;
return 0;
}
static inline int
check_padding_KBASE_IOCTL_CS_QUEUE_REGISTER_EX(struct kbase_ioctl_cs_queue_register_ex *p)
{
size_t i;
for (i = 0; i < ARRAY_SIZE(p->padding); i++) {
if (p->padding[i])
return -1;
}
for (i = 0; i < ARRAY_SIZE(p->ex_padding); i++) {
if (p->ex_padding[i])
return -1;
}
return 0;
}
static inline int
check_padding_KBASE_IOCTL_CS_QUEUE_TERMINATE(struct kbase_ioctl_cs_queue_terminate *p)
{
return 0;
}
static inline int
check_padding_KBASE_IOCTL_CS_QUEUE_GROUP_CREATE_1_6(union kbase_ioctl_cs_queue_group_create_1_6 *p)
{
size_t i;
for (i = 0; i < ARRAY_SIZE(p->in.padding); i++) {
if (p->in.padding[i])
return -1;
}
return 0;
}
static inline int check_padding_KBASE_IOCTL_CS_QUEUE_GROUP_CREATE_1_18(
union kbase_ioctl_cs_queue_group_create_1_18 *p)
{
size_t i;
for (i = 0; i < ARRAY_SIZE(p->in.padding); i++) {
if (p->in.padding[i])
return -1;
}
return 0;
}
static inline int
check_padding_KBASE_IOCTL_CS_QUEUE_GROUP_CREATE(union kbase_ioctl_cs_queue_group_create *p)
{
size_t i;
for (i = 0; i < ARRAY_SIZE(p->in.padding); i++) {
if (p->in.padding[i])
return -1;
}
return 0;
}
static inline int
check_padding_KBASE_IOCTL_CS_QUEUE_GROUP_TERMINATE(struct kbase_ioctl_cs_queue_group_term *p)
{
size_t i;
for (i = 0; i < ARRAY_SIZE(p->padding); i++) {
if (p->padding[i])
return -1;
}
return 0;
}
static inline int
check_padding_KBASE_IOCTL_KCPU_QUEUE_DELETE(struct kbase_ioctl_kcpu_queue_delete *p)
{
size_t i;
/*
* Checking p->padding is deferred till the support window for backward-compatibility ends.
* GPUCORE-42000 will add the checking.
*
* To avoid the situation with old version of base which might not set padding bytes as 0,
* padding bytes are set as zero here on behalf on user space.
*/
for (i = 0; i < ARRAY_SIZE(p->padding); i++)
p->padding[i] = 0;
return 0;
}
static inline int
check_padding_KBASE_IOCTL_KCPU_QUEUE_ENQUEUE(struct kbase_ioctl_kcpu_queue_enqueue *p)
{
size_t i;
/*
* Checking p->padding is deferred till the support window for backward-compatibility ends.
* GPUCORE-42000 will add the checking.
*
* To avoid the situation with old version of base which might not set padding bytes as 0,
* padding bytes are set as zero here on behalf on user space.
*/
for (i = 0; i < ARRAY_SIZE(p->padding); i++)
p->padding[i] = 0;
return 0;
}
static inline int
check_padding_KBASE_IOCTL_CS_TILER_HEAP_INIT(union kbase_ioctl_cs_tiler_heap_init *p)
{
return p->in.padding;
}
static inline int
check_padding_KBASE_IOCTL_CS_TILER_HEAP_INIT_1_13(union kbase_ioctl_cs_tiler_heap_init_1_13 *p)
{
return p->in.padding;
}
static inline int
check_padding_KBASE_IOCTL_CS_TILER_HEAP_TERM(struct kbase_ioctl_cs_tiler_heap_term *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_CS_GET_GLB_IFACE(union kbase_ioctl_cs_get_glb_iface *p)
{
return 0;
}
static inline int
check_padding_KBASE_IOCTL_CS_CPU_QUEUE_DUMP(struct kbase_ioctl_cs_cpu_queue_info *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_MEM_ALLOC_EX(union kbase_ioctl_mem_alloc_ex *p)
{
size_t i;
for (i = 0; i < ARRAY_SIZE(p->in.extra); i++) {
if (p->in.extra[i])
return -1;
}
return 0;
}
static inline int check_padding_KBASE_IOCTL_READ_USER_PAGE(union kbase_ioctl_read_user_page *p)
{
return p->in.padding;
}
static inline int
check_padding_KBASE_IOCTL_QUEUE_GROUP_CLEAR_FAULTS(struct kbase_ioctl_queue_group_clear_faults *p)
{
size_t i;
/*
* Checking p->padding is deferred till the support window for backward-compatibility ends.
* GPUCORE-42000 will add the checking.
*
* To avoid the situation with old version of base which might not set padding bytes as 0,
* padding bytes are set as zero here on behalf on user space.
*/
for (i = 0; i < ARRAY_SIZE(p->padding); i++)
p->padding[i] = 0;
return 0;
}
#else /* MALI_USE_CSF */
static inline int check_padding_KBASE_IOCTL_JOB_SUBMIT(struct kbase_ioctl_job_submit *p)
{
return 0;
}
static inline int
check_padding_KBASE_IOCTL_SOFT_EVENT_UPDATE(struct kbase_ioctl_soft_event_update *p)
{
return 0;
}
static inline int check_padding_KBASE_IOCTL_KINSTR_JM_FD(union kbase_kinstr_jm_fd *p)
{
size_t i;
for (i = 0; i < ARRAY_SIZE(p->in.padding); i++) {
if (p->in.padding[i])
return -1;
}
return 0;
}
#endif /* !MALI_USE_CSF */
#endif /* _KBASE_IOCTL_HELPERS_H_ */