Commit 1d6d3992 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'kthread-for-6.14-rc1' of...

Merge tag 'kthread-for-6.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/frederic/linux-dynticks

Pull kthread updates from Frederic Weisbecker:
 "Kthreads affinity follow either of 4 existing different patterns:

   1) Per-CPU kthreads must stay affine to a single CPU and never
      execute relevant code on any other CPU. This is currently handled
      by smpboot code which takes care of CPU-hotplug operations.
      Affinity here is a correctness constraint.

   2) Some kthreads _have_ to be affine to a specific set of CPUs and
      can't run anywhere else. The affinity is set through
      kthread_bind_mask() and the subsystem takes care by itself to
      handle CPU-hotplug operations. Affinity here is assumed to be a
      correctness constraint.

   3) Per-node kthreads _prefer_ to be affine to a specific NUMA node.
      This is not a correctness constraint but merely a preference in
      terms of memory locality. kswapd and kcompactd both fall into this
      category. The affinity is set manually like for any other task and
      CPU-hotplug is supposed to be handled by the relevant subsystem so
      that the task is properly reaffined whenever a given CPU from the
      node comes up. Also care should be taken so that the node affinity
      doesn't cross isolated (nohz_full) cpumask boundaries.

   4) Similar to the previous point except kthreads have a _preferred_
      affinity different than a node. Both RCU boost kthreads and RCU
      exp kworkers fall into this category as they refer to "RCU nodes"
      from a distinctly distributed tree.

  Currently the preferred affinity patterns (3 and 4) have at least 4
  identified users, with more or less success when it comes to handle
  CPU-hotplug operations and CPU isolation. Each of which do it in its
  own ad-hoc way.

  This is an infrastructure proposal to handle this with the following
  API changes:

   - kthread_create_on_node() automatically affines the created kthread
     to its target node unless it has been set as per-cpu or bound with
     kthread_bind[_mask]() before the first wake-up.

   - kthread_affine_preferred() is a new function that can be called
     right after kthread_create_on_node() to specify a preferred
     affinity different than the specified node.

  When the preferred affinity can't be applied because the possible
  targets are offline or isolated (nohz_full), the kthread is affine to
  the housekeeping CPUs (which means to all online CPUs most of the time
  or only the non-nohz_full CPUs when nohz_full= is set).

  kswapd, kcompactd, RCU boost kthreads and RCU exp kworkers have been
  converted, along with a few old drivers.

  Summary of the changes:

   - Consolidate a bunch of ad-hoc implementations of
     kthread_run_on_cpu()

   - Introduce task_cpu_fallback_mask() that defines the default last
     resort affinity of a task to become nohz_full aware

   - Add some correctness check to ensure kthread_bind() is always
     called before the first kthread wake up.

   - Default affine kthread to its preferred node.

   - Convert kswapd / kcompactd and remove their halfway working ad-hoc
     affinity implementation

   - Implement kthreads preferred affinity

   - Unify kthread worker and kthread API's style

   - Convert RCU kthreads to the new API and remove the ad-hoc affinity
     implementation"

* tag 'kthread-for-6.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/frederic/linux-dynticks:
  kthread: modify kernel-doc function name to match code
  rcu: Use kthread preferred affinity for RCU exp kworkers
  treewide: Introduce kthread_run_worker[_on_cpu]()
  kthread: Unify kthread_create_on_cpu() and kthread_create_worker_on_cpu() automatic format
  rcu: Use kthread preferred affinity for RCU boost
  kthread: Implement preferred affinity
  mm: Create/affine kswapd to its preferred node
  mm: Create/affine kcompactd to its preferred node
  kthread: Default affine kthread to its preferred NUMA node
  kthread: Make sure kthread hasn't started while binding it
  sched,arm64: Handle CPU isolation on last resort fallback rq selection
  arm64: Exclude nohz_full CPUs from 32bits el0 support
  lib: test_objpool: Use kthread_run_on_cpu()
  kallsyms: Use kthread_run_on_cpu()
  soc/qman: test: Use kthread_run_on_cpu()
  arm/bL_switcher: Use kthread_run_on_cpu()
parents 96c84703 d8b4bf4e
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -153,3 +153,11 @@ asymmetric system, a broken guest at EL1 could still attempt to execute
mode will return to host userspace with an ``exit_reason`` of
``KVM_EXIT_FAIL_ENTRY`` and will remain non-runnable until successfully
re-initialised by a subsequent ``KVM_ARM_VCPU_INIT`` operation.

NOHZ FULL
---------

To avoid perturbing an adaptive-ticks CPU (specified using
``nohz_full=``) when a 32-bit task is forcefully migrated, these CPUs
are treated as 64-bit-only when support for asymmetric 32-bit systems
is enabled.
+4 −6
Original line number Diff line number Diff line
@@ -307,13 +307,11 @@ static struct task_struct *bL_switcher_thread_create(int cpu, void *arg)
{
	struct task_struct *task;

	task = kthread_create_on_node(bL_switcher_thread, arg,
				      cpu_to_node(cpu), "kswitcher_%d", cpu);
	if (!IS_ERR(task)) {
		kthread_bind(task, cpu);
		wake_up_process(task);
	} else
	task = kthread_run_on_cpu(bL_switcher_thread, arg,
				  cpu, "kswitcher_%d");
	if (IS_ERR(task))
		pr_err("%s failed for CPU %d\n", __func__, cpu);

	return task;
}

+1 −0
Original line number Diff line number Diff line
@@ -671,6 +671,7 @@ static inline bool supports_clearbhb(int scope)
}

const struct cpumask *system_32bit_el0_cpumask(void);
const struct cpumask *fallback_32bit_el0_cpumask(void);
DECLARE_STATIC_KEY_FALSE(arm64_mismatched_32bit_el0);

static inline bool system_supports_32bit_el0(void)
+11 −3
Original line number Diff line number Diff line
@@ -271,18 +271,26 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next,
}

static inline const struct cpumask *
task_cpu_possible_mask(struct task_struct *p)
__task_cpu_possible_mask(struct task_struct *p, const struct cpumask *mask)
{
	if (!static_branch_unlikely(&arm64_mismatched_32bit_el0))
		return cpu_possible_mask;
		return mask;

	if (!is_compat_thread(task_thread_info(p)))
		return cpu_possible_mask;
		return mask;

	return system_32bit_el0_cpumask();
}

static inline const struct cpumask *
task_cpu_possible_mask(struct task_struct *p)
{
	return __task_cpu_possible_mask(p, cpu_possible_mask);
}
#define task_cpu_possible_mask	task_cpu_possible_mask

const struct cpumask *task_cpu_fallback_mask(struct task_struct *p);

void verify_cpu_asid_bits(void);
void post_ttbr_update_workaround(void);

+14 −1
Original line number Diff line number Diff line
@@ -75,6 +75,7 @@
#include <linux/cpu.h>
#include <linux/kasan.h>
#include <linux/percpu.h>
#include <linux/sched/isolation.h>

#include <asm/cpu.h>
#include <asm/cpufeature.h>
@@ -1644,6 +1645,11 @@ const struct cpumask *system_32bit_el0_cpumask(void)
	return cpu_possible_mask;
}

const struct cpumask *task_cpu_fallback_mask(struct task_struct *p)
{
	return __task_cpu_possible_mask(p, housekeeping_cpumask(HK_TYPE_TICK));
}

static int __init parse_32bit_el0_param(char *str)
{
	allow_mismatched_32bit_el0 = true;
@@ -3773,7 +3779,14 @@ static int enable_mismatched_32bit_el0(unsigned int cpu)
	static int lucky_winner = -1;

	struct cpuinfo_arm64 *info = &per_cpu(cpu_data, cpu);
	bool cpu_32bit = id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0);
	bool cpu_32bit = false;

	if (id_aa64pfr0_32bit_el0(info->reg_id_aa64pfr0)) {
		if (!housekeeping_cpu(cpu, HK_TYPE_TICK))
			pr_info("Treating adaptive-ticks CPU %u as 64-bit only\n", cpu);
		else
			cpu_32bit = true;
	}

	if (cpu_32bit) {
		cpumask_set_cpu(cpu, cpu_32bit_el0_mask);
Loading