gpu: nvgpu: Fix Bad bit shift Coverity issues

Fixed following Coverity Defects:
ioctl_as.c : Bad bit shift operation
mc_tu104.c : Bad bit shift operation
vm.c : Bad bit shift operation
vm_remap.c : Bad bit shift operation

A new linux header file for ilog2 is created.
The files which used the old ilog2 function
have been changed to use the new nvgpu_ilog2
function.

CID 9847922
CID 9869507
CID 9859508
CID 10112314
CID 10127813
CID 10127899
CID 10128004

Signed-off-by: Jinesh Parakh <jparakh@nvidia.com>
Change-Id: Ia201eea7cc426c3d6581e1e5ae3b882dbab3b490
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvgpu/+/2700994
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Jinesh Parakh
2022-04-21 19:42:23 +05:30
committed by mobile promotions
parent 167e7b0256
commit 622fe70dab
16 changed files with 153 additions and 37 deletions

View File

@@ -261,6 +261,7 @@ headers:
include/nvgpu/linux/soc_fuse.h,
include/nvgpu/linux/thread.h,
include/nvgpu/linux/log.h,
include/nvgpu/linux/log2.h,
include/nvgpu/linux/utils.h,
include/nvgpu/linux/vm.h,
include/nvgpu/linux/vm_remap.h ]

View File

@@ -96,7 +96,7 @@ static u32 nvgpu_balloc_page_size_to_pte_size(struct nvgpu_buddy_allocator *a,
*/
static void balloc_compute_max_order(struct nvgpu_buddy_allocator *a)
{
u64 true_max_order = ilog2(a->blks);
u64 true_max_order = nvgpu_ilog2(a->blks);
if (true_max_order > GPU_BALLOC_MAX_ORDER) {
alloc_dbg(balloc_owner(a),
@@ -113,15 +113,25 @@ static void balloc_compute_max_order(struct nvgpu_buddy_allocator *a)
* Since we can only allocate in chucks of a->blk_size we need to trim off
* any excess data that is not aligned to a->blk_size.
*/
static void balloc_allocator_align(struct nvgpu_buddy_allocator *a)
static int balloc_allocator_align(struct nvgpu_buddy_allocator *a)
{
int err = 0;
u64 blks;
a->start = NVGPU_ALIGN(a->base, a->blk_size);
WARN_ON(a->start != a->base);
nvgpu_assert(a->blk_size > 0ULL);
a->end = nvgpu_safe_add_u64(a->base, a->length) &
~(a->blk_size - 1U);
a->count = nvgpu_safe_sub_u64(a->end, a->start);
a->blks = a->count >> a->blk_shift;
blks = a->count >> a->blk_shift;
if (blks == 0ULL) {
err = -EINVAL;
goto fail;
}
a->blks = blks;
fail:
return err;
}
/*
@@ -228,7 +238,7 @@ static u64 balloc_max_order_in(struct nvgpu_buddy_allocator *a,
u64 size = nvgpu_safe_sub_u64(end, start) >> a->blk_shift;
if (size > 0U) {
return min_t(u64, ilog2(size), a->max_order);
return min_t(u64, nvgpu_ilog2(size), a->max_order);
} else {
return GPU_BALLOC_MAX_ORDER;
}
@@ -1506,7 +1516,10 @@ int nvgpu_buddy_allocator_init(struct gk20a *g, struct nvgpu_allocator *na,
goto fail;
}
balloc_allocator_align(a);
err = balloc_allocator_align(a);
if (err != 0) {
goto fail;
}
balloc_compute_max_order(a);
a->buddy_cache = nvgpu_kmem_cache_create(g, sizeof(struct nvgpu_buddy));

View File

@@ -438,12 +438,17 @@ static struct nvgpu_page_alloc *nvgpu_alloc_slab(
struct page_alloc_slab *slab;
struct nvgpu_page_alloc *alloc = NULL;
struct nvgpu_mem_sgl *sgl = NULL;
u64 aligned_page;
/*
* Align the length to a page and then divide by the page size (4k for
* this code). ilog2() of that then gets us the correct slab to use.
* this code). nvgpu_ilog2() of that then gets us the correct slab to use.
*/
slab_nr = ilog2(PAGE_ALIGN(len) >> 12);
aligned_page = PAGE_ALIGN(len) >> 12;
if (aligned_page == 0) {
goto fail;
}
slab_nr = nvgpu_ilog2(aligned_page);
slab = &a->slabs[slab_nr];
alloc = nvgpu_kmem_cache_alloc(a->alloc_cache);
@@ -1012,17 +1017,24 @@ static const struct nvgpu_allocator_ops page_ops = {
* slabs. For 64k page_size that works on like:
*
* 1024*64 / 1024*4 = 16
* ilog2(16) = 4
* nvgpu_ilog2(16) = 4
*
* That gives buckets of 1, 2, 4, and 8 pages (i.e 4k, 8k, 16k, 32k).
*/
static int nvgpu_page_alloc_init_slabs(struct nvgpu_page_allocator *a)
{
/* Use temp var for MISRA 10.8 */
unsigned long tmp_nr_slabs = ilog2(a->page_size >> 12);
u32 nr_slabs = nvgpu_safe_cast_u64_to_u32(tmp_nr_slabs);
unsigned long aligned_page_size = a->page_size >> 12;
unsigned long tmp_nr_slabs;
u32 nr_slabs;
u32 i;
if (aligned_page_size == 0UL) {
return -EINVAL;
}
tmp_nr_slabs = nvgpu_ilog2(aligned_page_size);
nr_slabs = nvgpu_safe_cast_u64_to_u32(tmp_nr_slabs);
/*
* As slab_size is 32-bits wide, maximum possible slab_size
* is 2^32 i.e. 4Gb

View File

@@ -52,8 +52,12 @@ nvgpu_pd_mem_entry_from_tree_entry(struct nvgpu_rbtree_node *node)
static u32 nvgpu_pd_cache_nr(u32 bytes)
{
unsigned long tmp = ilog2((unsigned long)bytes >>
((unsigned long)NVGPU_PD_CACHE_MIN_SHIFT - 1UL));
unsigned long bytes_shift = (unsigned long)bytes >>
((unsigned long)NVGPU_PD_CACHE_MIN_SHIFT - 1UL);
unsigned long tmp;
nvgpu_assert(bytes_shift > 0UL);
tmp = nvgpu_ilog2(bytes_shift);
nvgpu_assert(tmp <= U32_MAX);
return (u32)tmp;

View File

@@ -1272,11 +1272,16 @@ static int nvgpu_vm_do_map(struct vm_gk20a *vm,
* Figure out the kind and ctag offset for the GMMU page tables
*/
if (binfo_ptr->compr_kind != NVGPU_KIND_INVALID && ctag_offset != 0U) {
u64 compression_page_size = g->ops.fb.compression_page_size(g);
nvgpu_assert(compression_page_size > 0ULL);
/*
* Adjust the ctag_offset as per the buffer map offset
*/
ctag_offset += (u32)(phys_offset >>
ilog2(g->ops.fb.compression_page_size(g)));
nvgpu_ilog2(compression_page_size));
nvgpu_assert((binfo_ptr->compr_kind >= 0) &&
(binfo_ptr->compr_kind <= (s16)U8_MAX));
pte_kind = (u8)binfo_ptr->compr_kind;

View File

@@ -27,6 +27,7 @@
#include <nvgpu/comptags.h>
#include <nvgpu/string.h>
#include <nvgpu/power_features/pg.h>
#include<nvgpu/log2.h>
/*
* Return a pointer to the os-specific structure for the specified physical
@@ -357,6 +358,7 @@ static u64 nvgpu_vm_remap_get_ctag_offset(struct vm_gk20a *vm,
u64 page_size = nvgpu_vm_remap_page_size(op);
u64 phys_offset = nvgpu_safe_mult_u64(op->mem_offset_in_pages,
page_size);
u64 compression_page_size;
gk20a_get_comptags(os_buf, &comptags);
@@ -366,9 +368,13 @@ static u64 nvgpu_vm_remap_get_ctag_offset(struct vm_gk20a *vm,
if (op->compr_kind != NVGPU_KIND_INVALID) {
*kind = op->compr_kind;
compression_page_size = g->ops.fb.compression_page_size(g);
nvgpu_assert(compression_page_size > 0ULL);
if (ctag != 0) {
ctag_offset = ctag + (phys_offset >>
ilog2(g->ops.fb.compression_page_size(g)));
nvgpu_ilog2(compression_page_size));
} else {
ctag_offset = 0;
}
@@ -727,6 +733,7 @@ int nvgpu_vm_remap_vpool_create(struct vm_gk20a *vm,
struct gk20a *g = gk20a_from_vm(vm);
struct nvgpu_vm_remap_vpool *vp;
u64 start_page_nr = 0;
u32 gmmu_page_size;
if ((num_pages == 0ULL) ||
((vm_area->flags & NVGPU_VM_AREA_ALLOC_SPARSE) == 0U)) {
@@ -737,9 +744,11 @@ int nvgpu_vm_remap_vpool_create(struct vm_gk20a *vm,
if (vp == NULL) {
return -ENOMEM;
}
gmmu_page_size = vm->gmmu_page_sizes[vm_area->pgsz_idx];
nvgpu_assert(gmmu_page_size > 0U);
start_page_nr = vm_area->addr >>
ilog2(vm->gmmu_page_sizes[vm_area->pgsz_idx]);
nvgpu_ilog2(gmmu_page_size);
vp->base_offset_in_pages = start_page_nr;
vp->num_pages = num_pages;

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020-2021, NVIDIA CORPORATION. All rights reserved.
* Copyright (c) 2020-2022, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -217,7 +217,7 @@ void ga10b_channel_read_state(struct gk20a *g, struct nvgpu_channel *ch,
* Status is true if the corresponding bit is set.
* Go through each set bit and copy status string to status string list.
*/
for_each_set_bit(bit, &status_str_bits, ilog2(U32_MAX)) {
for_each_set_bit(bit, &status_str_bits, nvgpu_ilog2(U32_MAX)) {
chram_status_list[status_str_count] =
chram_status_str[BIT32(bit)];
status_str_count = nvgpu_safe_add_u32(status_str_count, 1UL);

View File

@@ -379,7 +379,7 @@ u32 gm20b_pbdma_get_gp_base_hi(u64 gpfifo_base, u32 gpfifo_entry)
{
return (pbdma_gp_base_hi_offset_f(u64_hi32(gpfifo_base)) |
pbdma_gp_base_hi_limit2_f(
nvgpu_safe_cast_u64_to_u32(ilog2(gpfifo_entry))));
nvgpu_safe_cast_u64_to_u32(nvgpu_ilog2(gpfifo_entry))));
}
u32 gm20b_pbdma_get_fc_subdevice(void)

View File

@@ -155,6 +155,14 @@ static void intr_tu104_nonstall_enable(struct gk20a *g)
*/
nonstall_intr_base = nvgpu_readl(g,
ctrl_legacy_engine_nonstall_intr_base_vectorid_r());
/*
* FIXME: ctrl_legacy_engine_nonstall_intr_base_vectorid_r() has a range of 0-4095,
* but bit shifting is currently using u64 variables (after typecast).
*/
if (nonstall_intr_base > 63U) {
nvgpu_err(g, "Invalid nostall_intr_base, %u", nonstall_intr_base);
return;
}
for (i = 0; i < g->fifo.num_engines; i++) {
const struct nvgpu_device *dev = g->fifo.active_engines[i];
@@ -325,10 +333,18 @@ u32 intr_tu104_isr_nonstall(struct gk20a *g)
func_priv_cpu_intr_leaf_r(
NV_CPU_INTR_SUBTREE_TO_LEAF_REG1(
NV_CPU_INTR_TOP_NONSTALL_SUBTREE)));
/*
* FIXME: ctrl_legacy_engine_nonstall_intr_base_vectorid_r() has a range of 0-4095,
* but bit shifting is currently using u64 variables (after typecast).
*/
nonstall_intr_base = nvgpu_readl(g,
ctrl_legacy_engine_nonstall_intr_base_vectorid_r());
if (nonstall_intr_base > 63U) {
nvgpu_err(g, "Invalid nostall_intr_base, %u", nonstall_intr_base);
return ops;
}
for (i = 0U; i < g->fifo.num_engines; i++) {
const struct nvgpu_device *dev = g->fifo.active_engines[i];

View File

@@ -125,12 +125,9 @@ static void update_pte(struct vm_gk20a *vm,
u64 compression_page_size;
compression_page_size = g->ops.fb.compression_page_size(g);
nvgpu_assert(compression_page_size > 0ULL);
if (compression_page_size == 0ULL) {
nvgpu_err(g, "compression_page_size is 0");
} else {
ctag_shift = (u32)ilog2(compression_page_size);
}
ctag_shift = (u32)nvgpu_ilog2(compression_page_size);
#endif
pte_w[0] = pte_valid | addr;
@@ -192,12 +189,9 @@ static void update_gmmu_pte_locked(struct vm_gk20a *vm,
u32 ctag_shift = 0;
compression_page_size = g->ops.fb.compression_page_size(g);
nvgpu_assert(compression_page_size > 0ULL);
if (compression_page_size == 0ULL) {
nvgpu_err(g, "compression_page_size is 0");
} else {
ctag_shift = (u32)ilog2(compression_page_size);
}
ctag_shift = (u32)nvgpu_ilog2(compression_page_size);
#endif
if (phys_addr != 0ULL) {

View File

@@ -0,0 +1,46 @@
/* SPDX-License-Identifier: MIT
* Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#ifndef __LOG2_LINUX_H__
#define __LOG2_LINUX_H__
#include <linux/log2.h>
/**
* @brief Integer logarithm for base 2.
*
* Calculates the log to the base 2 of input value \a x and returns the
* integer value of the same.
* Macro performs validation of the parameter.
*
* @param x [in] The number to get the log for.
*
* @return Integer value of log to the base 2 of input \a x.
*/
#define nvgpu_ilog2(x) ({ \
unsigned long result; \
nvgpu_assert(x > 0ULL); \
result = nvgpu_safe_cast_s32_to_u64(ilog2(x)); \
result; \
})
#endif

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2019, NVIDIA CORPORATION. All rights reserved.
* Copyright (c) 2017-2022, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -23,7 +23,7 @@
#define NVGPU_LOG2_H
#ifdef __KERNEL__
#include <linux/log2.h>
#include <nvgpu/linux/log2.h>
#else
#include <nvgpu/posix/log2.h>
#endif

View File

@@ -36,7 +36,7 @@
*
* @return Integer value of log to the base 2 of input \a x.
*/
#define ilog2(x) ({ \
#define nvgpu_ilog2(x) ({ \
unsigned long fls_val = nvgpu_fls(x); \
\
nvgpu_assert(fls_val > 0ULL); \

View File

@@ -258,10 +258,20 @@ static int gk20a_as_ioctl_get_va_regions(
(void) memset(&region, 0, sizeof(struct nvgpu_as_va_region));
region.page_size = vm->gmmu_page_sizes[i];
/*
* The gmmu_page_sizes values are assigned in nvgpu_vm_init_attribute function.
* The only value that can possibly be zero is vm->gmmu_page_sizes[1] when big_pages
* are not enabled.
* The upper bound on page_sizes already handles this issue. When big_pages are not enabled
* write_entries will be 1 and hence vm->gmmu_page_sizes[1] will never be accessed.
* Hence, an assert would suffice instead of an if check.
*/
nvgpu_assert(region.page_size > 0U);
region.offset = nvgpu_alloc_base(vma);
/* No __aeabi_uldivmod() on some platforms... */
region.pages = (nvgpu_alloc_end(vma) -
nvgpu_alloc_base(vma)) >> ilog2(region.page_size);
nvgpu_alloc_base(vma)) >> nvgpu_ilog2(region.page_size);
if (copy_to_user(user_region_ptr + i, &region, sizeof(region)))
return -EFAULT;

View File

@@ -20,6 +20,7 @@
#include <uapi/linux/nvgpu.h>
#include <nvgpu/log.h>
#include<nvgpu/log2.h>
#include <nvgpu/lock.h>
#include <nvgpu/rbtree.h>
#include <nvgpu/vm_area.h>
@@ -468,6 +469,7 @@ int nvgpu_vm_mapping_modify(struct vm_gk20a *vm,
u32 page_size;
u64 ctag_offset;
s16 kind = NV_KIND_INVALID;
u64 compression_page_size;
nvgpu_mutex_acquire(&vm->update_gmmu_lock);
@@ -528,8 +530,12 @@ int nvgpu_vm_mapping_modify(struct vm_gk20a *vm,
}
ctag_offset = mapped_buffer->ctag_offset;
compression_page_size = g->ops.fb.compression_page_size(g);
nvgpu_assert(compression_page_size > 0ULL);
ctag_offset += (u32)(buffer_offset >>
ilog2(g->ops.fb.compression_page_size(g)));
nvgpu_ilog2(compression_page_size));
if (g->ops.mm.gmmu.map(vm,
map_address + buffer_offset,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
* Copyright (c) 2020-2022, NVIDIA CORPORATION. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@@ -37,7 +37,7 @@ int test_ilog2(struct unit_module *m,
for (i = 0; i < BITS_PER_LONG; i++) {
test = 1UL << i;
ret = ilog2(test);
ret = nvgpu_ilog2(test);
if (ret != i) {
unit_return_fail(m,
"ilog2 failure %ld\n", test);
@@ -47,7 +47,7 @@ int test_ilog2(struct unit_module *m,
for (i = 1; i < (BITS_PER_LONG - 1); i++) {
test = 1UL << i;
test += 1;
ret = ilog2(test);
ret = nvgpu_ilog2(test);
if (ret != i) {
unit_return_fail(m,
"ilog2 failure %ld\n", test);