From cfaad9cd6dda13c43e0c428cd95e6d82ccbaffb4 Mon Sep 17 00:00:00 2001 From: Janardhan Reddy Date: Mon, 19 Aug 2024 11:00:14 +0000 Subject: [PATCH] nvscic2c-pcie: Add Buffer limts per endpoint Address security ARR: DOS60-REQ-7169 in streaming mode. Add per endpoint streaming mode buffer limits. Bug 4883175 JIRA NVIPC-2453 Change-Id: I31edb2bacf4a8af560e7e6da7d378da874d105bd Signed-off-by: Janardhan Reddy Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3196300 Tested-by: mobile promotions Reviewed-by: mobile promotions --- drivers/misc/nvscic2c-pcie/dt.c | 41 +++++- drivers/misc/nvscic2c-pcie/endpoint.c | 6 +- drivers/misc/nvscic2c-pcie/module.h | 2 + .../misc/nvscic2c-pcie/stream-extensions.c | 17 ++- .../misc/nvscic2c-pcie/stream-extensions.h | 7 +- drivers/misc/nvscic2c-pcie/vmap.c | 121 +++++++++++++++++- drivers/misc/nvscic2c-pcie/vmap.h | 8 +- 7 files changed, 188 insertions(+), 14 deletions(-) diff --git a/drivers/misc/nvscic2c-pcie/dt.c b/drivers/misc/nvscic2c-pcie/dt.c index ce77d99a..d8e83521 100644 --- a/drivers/misc/nvscic2c-pcie/dt.c +++ b/drivers/misc/nvscic2c-pcie/dt.c @@ -1,5 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-only -// Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +/* + * SPDX-FileCopyrightText: Copyright (c) 2022-2024, NVIDIA CORPORATION & AFFILIATES. + * All rights reserved. + */ #define pr_fmt(fmt) "nvscic2c-pcie: dt: " fmt @@ -59,8 +62,8 @@ dt_print(struct driver_param_t *drv_param) prop = &drv_param->endpoint_props[i]; pr_debug("\t\t(%s)::\n", prop->name); - pr_debug("\t\t\tnframes = (%02u) frame_size=(%08u)", - prop->nframes, prop->frame_sz); + pr_debug("\t\t\tnframes = (%02u) frame_size=(%08u) buff limit=(%lld)", + prop->nframes, prop->frame_sz, prop->aperture_limit); } pr_debug("dt parsing ends\n"); } @@ -114,6 +117,31 @@ tokenize_u8(char **input, const char *delim, return ret; } +/* + * helper function to tokenize the string with caller provided + * delimiter and provide the sting->u64 value. + * + * @param input is an in,out parameter. + * + */ +static int +tokenize_u64(char **input, const char *delim, + u32 base, u64 *value) +{ + int ret = 0; + char *token = NULL; + + /* skipping args check - internal api.*/ + + token = tokenize(input, delim); + if (!token) + ret = -ENODATA; + else + ret = kstrtou64(token, base, value); + + return ret; +} + /* * helper function to tokenize the string with caller provided * delimiter and provide the sting->u32 value. @@ -550,6 +578,13 @@ parse_endpoint_db(struct driver_param_t *drv_param) break; } + /* parse streaming mode per endpoint PCIe aperture mapping limit */ + ret = tokenize_u64(&inp, ",", base, &ep_prop->aperture_limit); + if (ret) { + pr_err("Error parsing token aperture_limit\n"); + break; + } + /* validate some basic properties of endpoint.*/ ret = validate_endpoint_prop(ep_prop); if (ret) { diff --git a/drivers/misc/nvscic2c-pcie/endpoint.c b/drivers/misc/nvscic2c-pcie/endpoint.c index 6f7d764b..25524c48 100644 --- a/drivers/misc/nvscic2c-pcie/endpoint.c +++ b/drivers/misc/nvscic2c-pcie/endpoint.c @@ -1,5 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-only -// Copyright (c) 2022-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +/* + * SPDX-FileCopyrightText: Copyright (c) 2022-2024, NVIDIA CORPORATION & AFFILIATES. + * All rights reserved. + */ #define pr_fmt(fmt) "nvscic2c-pcie: endpoint: " fmt @@ -1113,6 +1116,7 @@ endpoints_setup(struct driver_ctx_t *drv_ctx, void **endpoints_h) stream_ext_params->ep_id = ep_prop->id; stream_ext_params->ep_name = endpoint->name; stream_ext_params->drv_mode = drv_ctx->drv_mode; + stream_ext_params->aperture_limit = ep_prop->aperture_limit; /* create nvscic2c-pcie endpoint device.*/ ret = create_endpoint_device(eps_ctx, endpoint); diff --git a/drivers/misc/nvscic2c-pcie/module.h b/drivers/misc/nvscic2c-pcie/module.h index 05e217a9..a7bebd3d 100644 --- a/drivers/misc/nvscic2c-pcie/module.h +++ b/drivers/misc/nvscic2c-pcie/module.h @@ -74,6 +74,8 @@ struct driver_param_t { /* Frames and per frame size.*/ u8 nframes; u32 frame_sz; + /* Streaming mode per endpoint PCIe aperture mapping limit */ + uint64_t aperture_limit; } endpoint_props[MAX_ENDPOINTS]; }; diff --git a/drivers/misc/nvscic2c-pcie/stream-extensions.c b/drivers/misc/nvscic2c-pcie/stream-extensions.c index 2b2ce3de..c263f258 100644 --- a/drivers/misc/nvscic2c-pcie/stream-extensions.c +++ b/drivers/misc/nvscic2c-pcie/stream-extensions.c @@ -180,6 +180,10 @@ struct stream_ext_ctx_t { u32 ep_id; char ep_name[NAME_MAX]; + /* Streaming mode per endpoint PCIe aperture mapping limit */ + uint64_t aperture_limit; + /* Streaming mode per endpoint PCIe aperture mapping usage */ + uint64_t aperture_inuse; struct node_info_t local_node; struct node_info_t peer_node; @@ -640,6 +644,11 @@ ioctl_set_max_copy_requests(struct stream_ext_ctx_t *ctx, struct copy_request *cr = NULL; struct list_head *curr = NULL, *next = NULL; + if (ctx->aperture_limit == 0) { + pr_err("Err: Streaming is not supported in this Endpoint: %s\n", ctx->ep_name); + return -EINVAL; + } + if (WARN_ON(!args->max_copy_requests || !args->max_flush_ranges || !args->max_post_fences)) @@ -762,6 +771,8 @@ stream_extension_init(struct stream_ext_params *params, void **stream_ext_h) ctx->vmap_h = params->vmap_h; ctx->pci_client_h = params->pci_client_h; ctx->comm_channel_h = params->comm_channel_h; + ctx->aperture_limit = params->aperture_limit; + ctx->aperture_inuse = 0UL; strscpy(ctx->ep_name, params->ep_name, NAME_MAX); memcpy(&ctx->local_node, params->local_node, sizeof(ctx->local_node)); memcpy(&ctx->peer_node, params->peer_node, sizeof(ctx->peer_node)); @@ -895,7 +906,11 @@ allocate_handle(struct stream_ext_ctx_t *ctx, enum nvscic2c_pcie_obj_type type, pr_err("Incorrect NVSCIC2C_IOCTL_MAP params\n"); return -EINVAL; } - ret = vmap_obj_map(ctx->vmap_h, &vmap_params, &vmap_attrib); + ret = vmap_obj_map(ctx->vmap_h, + &vmap_params, + &vmap_attrib, + ctx->aperture_limit, + &ctx->aperture_inuse); if (ret) { if (ret == -EAGAIN) pr_info("Failed to map obj of type: (%d)\n", type); diff --git a/drivers/misc/nvscic2c-pcie/stream-extensions.h b/drivers/misc/nvscic2c-pcie/stream-extensions.h index cc3ef675..f12c2d06 100644 --- a/drivers/misc/nvscic2c-pcie/stream-extensions.h +++ b/drivers/misc/nvscic2c-pcie/stream-extensions.h @@ -1,5 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -/* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ +/* + * SPDX-FileCopyrightText: Copyright (c) 2022-2024, NVIDIA CORPORATION & AFFILIATES. + * All rights reserved. + */ /* * Internal to gos-nvscic2c module. This file is not supposed to be included @@ -21,6 +24,8 @@ struct stream_ext_params { struct node_info_t *peer_node; u32 ep_id; char *ep_name; + /* Streaming mode per endpoint PCIe aperture mapping limit */ + uint64_t aperture_limit; struct platform_device *host1x_pdev; enum drv_mode_t drv_mode; void *pci_client_h; diff --git a/drivers/misc/nvscic2c-pcie/vmap.c b/drivers/misc/nvscic2c-pcie/vmap.c index 420f913e..09e33845 100644 --- a/drivers/misc/nvscic2c-pcie/vmap.c +++ b/drivers/misc/nvscic2c-pcie/vmap.c @@ -1,5 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-only -// Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +/* + * SPDX-FileCopyrightText: Copyright (c) 2022-2024, NVIDIA CORPORATION & AFFILIATES. + * All rights reserved. + */ #define pr_fmt(fmt) "nvscic2c-pcie: vmap: " fmt @@ -42,13 +45,76 @@ match_dmabuf(int id, void *entry, void *data) return 0; } +static int dev_map_limit_check(uint64_t aperture_limit, uint64_t aperture_inuse, size_t map_size) +{ + int ret = 0; + + if ((aperture_inuse + map_size) > aperture_limit) { + ret = -ENOMEM; + pr_err("per endpoint mapping limit exceeded, aperture_inuse: %lld, map_size: %zu\n", + aperture_inuse, map_size); + return ret; + } + + return ret; +} + +static void +dma_mem_get_size_exit(struct memobj_pin_t *pin) +{ + if (!(IS_ERR_OR_NULL(pin->sgt))) { + dma_buf_unmap_attachment(pin->attach, pin->sgt, pin->dir); + pin->sgt = NULL; + } + + if (!(IS_ERR_OR_NULL(pin->attach))) { + dma_buf_detach(pin->dmabuf, pin->attach); + pin->attach = NULL; + } +} + +static int dma_mem_get_size(struct vmap_ctx_t *vmap_ctx, struct memobj_pin_t *pin, size_t *map_size) +{ + int ret = 0; + u32 sg_index = 0; + struct scatterlist *sg = NULL; + + /* + * pin to dummy device (which has smmu disabled) to get scatter-list + * of phys addr. + */ + pin->attach = dma_buf_attach(pin->dmabuf, &vmap_ctx->dummy_pdev->dev); + if (IS_ERR_OR_NULL(pin->attach)) { + ret = PTR_ERR(pin->attach); + pr_err("client_mngd dma_buf_attach failed\n"); + goto fn_exit; + } + pin->sgt = dma_buf_map_attachment(pin->attach, pin->dir); + if (IS_ERR_OR_NULL(pin->sgt)) { + ret = PTR_ERR(pin->sgt); + pr_err("client_mngd dma_buf_attachment failed\n"); + goto fn_exit; + } + + *map_size = 0; + for_each_sg(pin->sgt->sgl, sg, pin->sgt->nents, sg_index) + *map_size += sg->length; + +fn_exit: + dma_mem_get_size_exit(pin); + return ret; +} + static int memobj_map(struct vmap_ctx_t *vmap_ctx, struct vmap_memobj_map_params *params, - struct vmap_obj_attributes *attrib) + struct vmap_obj_attributes *attrib, + uint64_t aperture_limit, + uint64_t *const aperture_inuse) { int ret = 0; s32 id_exist = 0; + size_t map_size = 0; struct memobj_map_ref *map = NULL; struct dma_buf *dmabuf = NULL; @@ -105,6 +171,23 @@ memobj_map(struct vmap_ctx_t *vmap_ctx, goto err; } + if ((map->pin.mngd == VMAP_MNGD_CLIENT) && (aperture_inuse != NULL)) { + ret = dma_mem_get_size(vmap_ctx, &map->pin, &map_size); + if (ret != 0) { + pr_err("Failed in dma buf mem get size\n"); + idr_remove(&vmap_ctx->mem_idr, map->obj_id); + kfree(map); + goto err; + } + ret = dev_map_limit_check(aperture_limit, *aperture_inuse, map_size); + if (ret != 0) { + pr_err("Failed in aperture limit check\n"); + idr_remove(&vmap_ctx->mem_idr, map->obj_id); + kfree(map); + goto err; + } + } + /* populates map->pin.attrib within.*/ ret = memobj_pin(vmap_ctx, &map->pin); if (ret) { @@ -113,6 +196,8 @@ memobj_map(struct vmap_ctx_t *vmap_ctx, kfree(map); goto err; } + if ((map->pin.mngd == VMAP_MNGD_CLIENT) && (aperture_inuse != NULL)) + *aperture_inuse += map->pin.attrib.size; } attrib->type = VMAP_OBJ_TYPE_MEM; @@ -200,7 +285,9 @@ match_syncpt_id(int id, void *entry, void *data) static int syncobj_map(struct vmap_ctx_t *vmap_ctx, struct vmap_syncobj_map_params *params, - struct vmap_obj_attributes *attrib) + struct vmap_obj_attributes *attrib, + uint64_t aperture_limit, + uint64_t *const aperture_inuse) { int ret = 0; s32 id_exist = 0; @@ -239,6 +326,16 @@ syncobj_map(struct vmap_ctx_t *vmap_ctx, goto err; } + if ((params->mngd == VMAP_MNGD_CLIENT) && (aperture_inuse != NULL)) { + ret = dev_map_limit_check(aperture_limit, *aperture_inuse, SP_MAP_SIZE); + if (ret != 0) { + pr_err("Failed in aperture limit check\n"); + idr_remove(&vmap_ctx->sync_idr, map->obj_id); + kfree(map); + goto err; + } + } + /* local syncobjs do not need to be pinned to pcie iova.*/ map->pin.fd = params->fd; map->pin.syncpt_id = syncpt_id; @@ -253,6 +350,9 @@ syncobj_map(struct vmap_ctx_t *vmap_ctx, kfree(map); goto err; } + if ((params->mngd == VMAP_MNGD_CLIENT) && (aperture_inuse != NULL)) + *aperture_inuse += map->pin.attrib.size; + attrib->type = VMAP_OBJ_TYPE_SYNC; attrib->id = map->obj_id; attrib->iova = map->pin.attrib.iova; @@ -461,7 +561,8 @@ importobj_getref(struct vmap_ctx_t *vmap_ctx, s32 obj_id) int vmap_obj_map(void *vmap_h, struct vmap_obj_map_params *params, - struct vmap_obj_attributes *attrib) + struct vmap_obj_attributes *attrib, uint64_t aperture_limit, + uint64_t *const aperture_inuse) { int ret = 0; struct vmap_ctx_t *vmap_ctx = (struct vmap_ctx_t *)vmap_h; @@ -471,10 +572,18 @@ vmap_obj_map(void *vmap_h, struct vmap_obj_map_params *params, switch (params->type) { case VMAP_OBJ_TYPE_MEM: - ret = memobj_map(vmap_ctx, ¶ms->u.memobj, attrib); + ret = memobj_map(vmap_ctx, + ¶ms->u.memobj, + attrib, + aperture_limit, + aperture_inuse); break; case VMAP_OBJ_TYPE_SYNC: - ret = syncobj_map(vmap_ctx, ¶ms->u.syncobj, attrib); + ret = syncobj_map(vmap_ctx, + ¶ms->u.syncobj, + attrib, + aperture_limit, + aperture_inuse); break; case VMAP_OBJ_TYPE_IMPORT: ret = importobj_map(vmap_ctx, ¶ms->u.importobj, attrib); diff --git a/drivers/misc/nvscic2c-pcie/vmap.h b/drivers/misc/nvscic2c-pcie/vmap.h index db4e3e56..77809416 100644 --- a/drivers/misc/nvscic2c-pcie/vmap.h +++ b/drivers/misc/nvscic2c-pcie/vmap.h @@ -1,5 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -/* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */ +/* + * SPDX-FileCopyrightText: Copyright (c) 2022-2024, NVIDIA CORPORATION & AFFILIATES. + * All rights reserved. + */ #ifndef __VMAP_H__ #define __VMAP_H__ @@ -232,7 +235,8 @@ vmap_deinit(void **vmap_h); /* Map objects to pcie device.*/ int vmap_obj_map(void *vmap_h, struct vmap_obj_map_params *params, - struct vmap_obj_attributes *attrib); + struct vmap_obj_attributes *attrib, uint64_t aperture_limit, + uint64_t *const aperture_inuse); /* Unmap objects from pcie device.*/ int