From patchwork Tue Jan 24 16:09:45 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Carrillo, Erik G" X-Patchwork-Id: 122487 X-Patchwork-Delegate: jerinj@marvell.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id A4F0E4247D; Tue, 24 Jan 2023 17:10:49 +0100 (CET) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 5A0AE40150; Tue, 24 Jan 2023 17:10:49 +0100 (CET) Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by mails.dpdk.org (Postfix) with ESMTP id 7E298400EF; Tue, 24 Jan 2023 17:10:47 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1674576648; x=1706112648; h=from:to:cc:subject:date:message-id:mime-version: content-transfer-encoding; bh=5blOGHqs7hKwgS4PFLYU1vkX9A9CIQdfOoJeAH9WEFI=; b=ijRVua86t4YjWNTLWyxUE35L2u2HJPCwTLOQX4IzMJqbtO8+2MPQXIYk gCli2Dn9zSQHAZxF/UJwLC5TTqzVAKMRgubp2ccEOC4Uig43XSzSefgGx GW3QeGiSTpqHR97D0Rh3y/MGJpVYLrdv/by2xUaaitq8ifBcwpKFRrtwh So+QrbETz2FmD1x9CAJQ9eaKajJ+r0EQmSchsks99V6jyapfHTEEHmthW vopRC81368lELP5LYTwiEM0fKmnMjAawrTjiXQkbTeqZ8FWpt6YxdNU07 rqgcCJnKt/LlzQklVgPDD3Czga1BBXaGHk07MvNQI44kNJYDMgPOiebGW g==; X-IronPort-AV: E=McAfee;i="6500,9779,10600"; a="325006849" X-IronPort-AV: E=Sophos;i="5.97,242,1669104000"; d="scan'208";a="325006849" Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 24 Jan 2023 08:09:52 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10600"; a="664128939" X-IronPort-AV: E=Sophos;i="5.97,242,1669104000"; d="scan'208";a="664128939" Received: from txandevlnx321.an.intel.com ([10.123.117.43]) by fmsmga007.fm.intel.com with ESMTP; 24 Jan 2023 08:09:52 -0800 From: Erik Gabriel Carrillo To: jerinj@marvell.com Cc: dev@dpdk.org, stable@dpdk.org Subject: [PATCH] eventdev/timer: fix overflow issue Date: Tue, 24 Jan 2023 10:09:45 -0600 Message-Id: <20230124160945.3003303-1-erik.g.carrillo@intel.com> X-Mailer: git-send-email 2.23.0 MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org The software timer adapter converts event timer timeout ticks to a number of CPU cycles at which an rte_timer should expire. The computation uses integer operations that can result in overflow. Use floating point operations instead to perform the computation, and convert the final result back to an integer type when returning. Also move the logic that checks the timeout range into the function that performs the above computation. Fixes: 6750b21bd6af ("eventdev: add default software timer adapter") Cc: stable@dpdk.org Signed-off-by: Erik Gabriel Carrillo --- lib/eventdev/rte_event_timer_adapter.c | 72 +++++++++++++------------- 1 file changed, 35 insertions(+), 37 deletions(-) diff --git a/lib/eventdev/rte_event_timer_adapter.c b/lib/eventdev/rte_event_timer_adapter.c index d357f7403a..dbfb91ec1c 100644 --- a/lib/eventdev/rte_event_timer_adapter.c +++ b/lib/eventdev/rte_event_timer_adapter.c @@ -719,13 +719,29 @@ swtim_callback(struct rte_timer *tim) } } -static __rte_always_inline uint64_t +static __rte_always_inline int get_timeout_cycles(struct rte_event_timer *evtim, - const struct rte_event_timer_adapter *adapter) + const struct rte_event_timer_adapter *adapter, + uint64_t *timeout_cycles) { struct swtim *sw = swtim_pmd_priv(adapter); - uint64_t timeout_ns = evtim->timeout_ticks * sw->timer_tick_ns; - return timeout_ns * rte_get_timer_hz() / NSECPERSEC; + uint64_t timeout_nsecs; + double cycles_per_nsec; + + cycles_per_nsec = (double)rte_get_timer_hz() / NSECPERSEC; + + timeout_nsecs = evtim->timeout_ticks * sw->timer_tick_ns; + if (timeout_nsecs > sw->max_tmo_ns || + timeout_nsecs > UINT64_MAX / cycles_per_nsec) + return -1; + if (timeout_nsecs < sw->timer_tick_ns) + return -2; + + if (timeout_cycles) + *timeout_cycles = (uint64_t)ceil(timeout_nsecs * + cycles_per_nsec); + + return 0; } /* This function returns true if one or more (adapter) ticks have occurred since @@ -759,23 +775,6 @@ swtim_did_tick(struct swtim *sw) return false; } -/* Check that event timer timeout value is in range */ -static __rte_always_inline int -check_timeout(struct rte_event_timer *evtim, - const struct rte_event_timer_adapter *adapter) -{ - uint64_t tmo_nsec; - struct swtim *sw = swtim_pmd_priv(adapter); - - tmo_nsec = evtim->timeout_ticks * sw->timer_tick_ns; - if (tmo_nsec > sw->max_tmo_ns) - return -1; - if (tmo_nsec < sw->timer_tick_ns) - return -2; - - return 0; -} - /* Check that event timer event queue sched type matches destination event queue * sched type */ @@ -1195,21 +1194,6 @@ __swtim_arm_burst(const struct rte_event_timer_adapter *adapter, break; } - ret = check_timeout(evtims[i], adapter); - if (unlikely(ret == -1)) { - __atomic_store_n(&evtims[i]->state, - RTE_EVENT_TIMER_ERROR_TOOLATE, - __ATOMIC_RELAXED); - rte_errno = EINVAL; - break; - } else if (unlikely(ret == -2)) { - __atomic_store_n(&evtims[i]->state, - RTE_EVENT_TIMER_ERROR_TOOEARLY, - __ATOMIC_RELAXED); - rte_errno = EINVAL; - break; - } - if (unlikely(check_destination_event_queue(evtims[i], adapter) < 0)) { __atomic_store_n(&evtims[i]->state, @@ -1225,7 +1209,21 @@ __swtim_arm_burst(const struct rte_event_timer_adapter *adapter, evtims[i]->impl_opaque[0] = (uintptr_t)tim; evtims[i]->impl_opaque[1] = (uintptr_t)adapter; - cycles = get_timeout_cycles(evtims[i], adapter); + ret = get_timeout_cycles(evtims[i], adapter, &cycles); + if (unlikely(ret == -1)) { + __atomic_store_n(&evtims[i]->state, + RTE_EVENT_TIMER_ERROR_TOOLATE, + __ATOMIC_RELAXED); + rte_errno = EINVAL; + break; + } else if (unlikely(ret == -2)) { + __atomic_store_n(&evtims[i]->state, + RTE_EVENT_TIMER_ERROR_TOOEARLY, + __ATOMIC_RELAXED); + rte_errno = EINVAL; + break; + } + ret = rte_timer_alt_reset(sw->timer_data_id, tim, cycles, type, lcore_id, NULL, evtims[i]); if (ret < 0) {