From patchwork Tue Mar 8 14:14:15 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marco Elver X-Patchwork-Id: 12773868 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 52C3AC433F5 for ; Tue, 8 Mar 2022 14:14:27 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id D39ED8D0007; Tue, 8 Mar 2022 09:14:26 -0500 (EST) Received: by kanga.kvack.org (Postfix, from userid 40) id CE8A78D0001; Tue, 8 Mar 2022 09:14:26 -0500 (EST) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id BD7E18D0007; Tue, 8 Mar 2022 09:14:26 -0500 (EST) X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0160.hostedemail.com [216.40.44.160]) by kanga.kvack.org (Postfix) with ESMTP id AF2AA8D0001 for ; Tue, 8 Mar 2022 09:14:26 -0500 (EST) Received: from smtpin18.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay03.hostedemail.com (Postfix) with ESMTP id 4DF06824C420 for ; Tue, 8 Mar 2022 14:14:26 +0000 (UTC) X-FDA: 79221414132.18.4D941D2 Received: from mail-ed1-f74.google.com (mail-ed1-f74.google.com [209.85.208.74]) by imf03.hostedemail.com (Postfix) with ESMTP id C9C252000B for ; Tue, 8 Mar 2022 14:14:25 +0000 (UTC) Received: by mail-ed1-f74.google.com with SMTP id l8-20020a056402028800b0041636072ef0so4619382edv.13 for ; Tue, 08 Mar 2022 06:14:25 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=date:message-id:mime-version:subject:from:to:cc; bh=gyMGBvpuWMfS9cnvL/h1tsboqRL4o8fwiR0D5Pa1mrE=; b=q2POkYW1YeKnITLGDcWKnutHfsCisYKRva4yrqAUA+rihvnBLs8fN9iUwLD++uU+WG uR7+nswf5DGs8L5xUPfntSbabDhdn+SQuGMOXv/0kQw7/a42EwJj8jBZBax0jzPLPMZp cbaVbRm8FDJoysaKSeoeyykLy56NTg+e1e30m579EiYOzRNJ+FmBPv330zenq/cMbyJj 01CePPnVvJxO9Zh4O/uhs3Tb71UBgWfnq7DBBnpGl12E6EWbz1+0XUSy3Ae2YHmoGG0p Xt29qvMTCAOb5IgFKSlK/pOhtDF67QEaNUxxuIW4GOXVeNVygX+r7sd196TjMXEfWvGR sTYQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:message-id:mime-version:subject:from:to:cc; bh=gyMGBvpuWMfS9cnvL/h1tsboqRL4o8fwiR0D5Pa1mrE=; b=7L/aUHNPH7xYiiPjE42SqSTCXP88R6oSAehNUQRZ1Fz1MMxb8K9o+D0UF88vgUos20 su8SwcZ5xiiDki2N4txZLamLv1Wj5F1ipKbOViFwFMiQeY7C7d2uOJq8SD6Hzxz5ug6e MnAIq/iz98ZQSnTYXQfW2ySVlNotCqLAOPwDkLxdd6ElFUGVvlO58IBZWRirwwIkM1Zd AGwq1TSnFzzdGRPAc+Mr8rIFmXdqgsTKhMz0jD9Wm8MPBjILU9Vm/TE2EX1hylgp6f8P ASsBzkRINyDWLIGAZlFppxmCv9wQ6a9NPZEVlp55W2XWo6+9daE6jaCVmpfGLVfiqzrv xa7A== X-Gm-Message-State: AOAM530CikZT4ksq+wP7nlgk+GWvQGOmXRRJw/ZDrRd/r4C2ZtuGE3FX hbr1J3Wgq69xdTfiAUDKjzsumvuSoA== X-Google-Smtp-Source: ABdhPJyjGKAOe5D5WM5m7t1nu4yQN2fo/haxq+9mLVG9lQsaIlWMlvX9X9himb4U5X+Cj5kjj0kAu1iKuQ== X-Received: from elver.muc.corp.google.com ([2a00:79e0:15:13:edd7:29ac:9b6f:1abd]) (user=elver job=sendgmr) by 2002:a17:907:7244:b0:6d9:c722:577a with SMTP id ds4-20020a170907724400b006d9c722577amr13651190ejc.0.1646748864121; Tue, 08 Mar 2022 06:14:24 -0800 (PST) Date: Tue, 8 Mar 2022 15:14:15 +0100 Message-Id: <20220308141415.3168078-1-elver@google.com> Mime-Version: 1.0 X-Mailer: git-send-email 2.35.1.616.g0bdcbb4464-goog Subject: [PATCH v2] kfence: allow use of a deferrable timer From: Marco Elver To: elver@google.com, Andrew Morton Cc: Alexander Potapenko , Dmitry Vyukov , kasan-dev@googlegroups.com, linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mm@kvack.org X-Rspamd-Server: rspam06 X-Rspamd-Queue-Id: C9C252000B X-Stat-Signature: 9bi6yttmoeumjxoxi3gmksmc5tfbnnt1 Authentication-Results: imf03.hostedemail.com; dkim=pass header.d=google.com header.s=20210112 header.b=q2POkYW1; spf=pass (imf03.hostedemail.com: domain of 3wGQnYgUKCD8fmwfshpphmf.dpnmjovy-nnlwbdl.psh@flex--elver.bounces.google.com designates 209.85.208.74 as permitted sender) smtp.mailfrom=3wGQnYgUKCD8fmwfshpphmf.dpnmjovy-nnlwbdl.psh@flex--elver.bounces.google.com; dmarc=pass (policy=reject) header.from=google.com X-Rspam-User: X-HE-Tag: 1646748865-462023 X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: Allow the use of a deferrable timer, which does not force CPU wake-ups when the system is idle. A consequence is that the sample interval becomes very unpredictable, to the point that it is not guaranteed that the KFENCE KUnit test still passes. Nevertheless, on power-constrained systems this may be preferable, so let's give the user the option should they accept the above trade-off. Signed-off-by: Marco Elver Reviewed-by: Alexander Potapenko --- v2: * Add more documentation. * Remove 'if EXPERT' from Kconfig option since it's configurable via kernel boot param anyway. --- Documentation/dev-tools/kfence.rst | 12 ++++++++++++ lib/Kconfig.kfence | 12 ++++++++++++ mm/kfence/core.c | 15 +++++++++++++-- 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/Documentation/dev-tools/kfence.rst b/Documentation/dev-tools/kfence.rst index ac6b89d1a8c3..936f6aaa75c8 100644 --- a/Documentation/dev-tools/kfence.rst +++ b/Documentation/dev-tools/kfence.rst @@ -41,6 +41,18 @@ guarded by KFENCE. The default is configurable via the Kconfig option ``CONFIG_KFENCE_SAMPLE_INTERVAL``. Setting ``kfence.sample_interval=0`` disables KFENCE. +The sample interval controls a timer that sets up KFENCE allocations. By +default, to keep the real sample interval predictable, the normal timer also +causes CPU wake-ups when the system is completely idle. This may be undesirable +on power-constrained systems. The boot parameter ``kfence.deferrable=1`` +instead switches to a "deferrable" timer which does not force CPU wake-ups on +idle systems, at the risk of unpredictable sample intervals. The default is +configurable via the Kconfig option ``CONFIG_KFENCE_DEFERRABLE``. + +.. warning:: + The KUnit test suite is very likely to fail when using a deferrable timer + since it currently causes very unpredictable sample intervals. + The KFENCE memory pool is of fixed size, and if the pool is exhausted, no further KFENCE allocations occur. With ``CONFIG_KFENCE_NUM_OBJECTS`` (default 255), the number of available guarded objects can be controlled. Each object diff --git a/lib/Kconfig.kfence b/lib/Kconfig.kfence index 912f252a41fc..459dda9ef619 100644 --- a/lib/Kconfig.kfence +++ b/lib/Kconfig.kfence @@ -45,6 +45,18 @@ config KFENCE_NUM_OBJECTS pages are required; with one containing the object and two adjacent ones used as guard pages. +config KFENCE_DEFERRABLE + bool "Use a deferrable timer to trigger allocations" + help + Use a deferrable timer to trigger allocations. This avoids forcing + CPU wake-ups if the system is idle, at the risk of a less predictable + sample interval. + + Warning: The KUnit test suite fails with this option enabled - due to + the unpredictability of the sample interval! + + Say N if you are unsure. + config KFENCE_STATIC_KEYS bool "Use static keys to set up allocations" if EXPERT depends on JUMP_LABEL diff --git a/mm/kfence/core.c b/mm/kfence/core.c index f126b53b9b85..2f9fdfde1941 100644 --- a/mm/kfence/core.c +++ b/mm/kfence/core.c @@ -95,6 +95,10 @@ module_param_cb(sample_interval, &sample_interval_param_ops, &kfence_sample_inte static unsigned long kfence_skip_covered_thresh __read_mostly = 75; module_param_named(skip_covered_thresh, kfence_skip_covered_thresh, ulong, 0644); +/* If true, use a deferrable timer. */ +static bool kfence_deferrable __read_mostly = IS_ENABLED(CONFIG_KFENCE_DEFERRABLE); +module_param_named(deferrable, kfence_deferrable, bool, 0444); + /* The pool of pages used for guard pages and objects. */ char *__kfence_pool __read_mostly; EXPORT_SYMBOL(__kfence_pool); /* Export for test modules. */ @@ -740,6 +744,8 @@ late_initcall(kfence_debugfs_init); /* === Allocation Gate Timer ================================================ */ +static struct delayed_work kfence_timer; + #ifdef CONFIG_KFENCE_STATIC_KEYS /* Wait queue to wake up allocation-gate timer task. */ static DECLARE_WAIT_QUEUE_HEAD(allocation_wait); @@ -762,7 +768,6 @@ static DEFINE_IRQ_WORK(wake_up_kfence_timer_work, wake_up_kfence_timer); * avoids IPIs, at the cost of not immediately capturing allocations if the * instructions remain cached. */ -static struct delayed_work kfence_timer; static void toggle_allocation_gate(struct work_struct *work) { if (!READ_ONCE(kfence_enabled)) @@ -790,7 +795,6 @@ static void toggle_allocation_gate(struct work_struct *work) queue_delayed_work(system_unbound_wq, &kfence_timer, msecs_to_jiffies(kfence_sample_interval)); } -static DECLARE_DELAYED_WORK(kfence_timer, toggle_allocation_gate); /* === Public interface ===================================================== */ @@ -809,8 +813,15 @@ static void kfence_init_enable(void) { if (!IS_ENABLED(CONFIG_KFENCE_STATIC_KEYS)) static_branch_enable(&kfence_allocation_key); + + if (kfence_deferrable) + INIT_DEFERRABLE_WORK(&kfence_timer, toggle_allocation_gate); + else + INIT_DELAYED_WORK(&kfence_timer, toggle_allocation_gate); + WRITE_ONCE(kfence_enabled, true); queue_delayed_work(system_unbound_wq, &kfence_timer, 0); + pr_info("initialized - using %lu bytes for %d objects at 0x%p-0x%p\n", KFENCE_POOL_SIZE, CONFIG_KFENCE_NUM_OBJECTS, (void *)__kfence_pool, (void *)(__kfence_pool + KFENCE_POOL_SIZE));