--- /dev/null
+From stable-owner@vger.kernel.org Mon Apr 17 19:21:21 2023
+From: Waiman Long <longman@redhat.com>
+Date: Mon, 17 Apr 2023 13:19:58 -0400
+Subject: cgroup/cpuset: Add cpuset_can_fork() and cpuset_cancel_fork() methods
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, stable@vger.kernel.org
+Cc: "Tejun Heo" <tj@kernel.org>, "Michal Koutný" <mkoutny@suse.com>, "Giuseppe Scrivano" <gscrivan@redhat.com>, "Waiman Long" <longman@redhat.com>
+Message-ID: <20230417171958.3389333-4-longman@redhat.com>
+
+From: Waiman Long <longman@redhat.com>
+
+commit eee87853794187f6adbe19533ed79c8b44b36a91 upstream.
+
+In the case of CLONE_INTO_CGROUP, not all cpusets are ready to accept
+new tasks. It is too late to check that in cpuset_fork(). So we need
+to add the cpuset_can_fork() and cpuset_cancel_fork() methods to
+pre-check it before we can allow attachment to a different cpuset.
+
+We also need to set the attach_in_progress flag to alert other code
+that a new task is going to be added to the cpuset.
+
+Fixes: ef2c41cf38a7 ("clone3: allow spawning processes into cgroups")
+Suggested-by: Michal Koutný <mkoutny@suse.com>
+Signed-off-by: Waiman Long <longman@redhat.com>
+Cc: stable@vger.kernel.org # v5.7+
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/cgroup/cpuset.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++---
+ 1 file changed, 83 insertions(+), 5 deletions(-)
+
+--- a/kernel/cgroup/cpuset.c
++++ b/kernel/cgroup/cpuset.c
+@@ -2151,6 +2151,18 @@ static int fmeter_getrate(struct fmeter
+
+ static struct cpuset *cpuset_attach_old_cs;
+
++/*
++ * Check to see if a cpuset can accept a new task
++ * For v1, cpus_allowed and mems_allowed can't be empty.
++ */
++static int cpuset_can_attach_check(struct cpuset *cs)
++{
++ if (!is_in_v2_mode() &&
++ (cpumask_empty(cs->cpus_allowed) || nodes_empty(cs->mems_allowed)))
++ return -ENOSPC;
++ return 0;
++}
++
+ /* Called by cgroups to determine if a cpuset is usable; cpuset_rwsem held */
+ static int cpuset_can_attach(struct cgroup_taskset *tset)
+ {
+@@ -2165,10 +2177,8 @@ static int cpuset_can_attach(struct cgro
+
+ percpu_down_write(&cpuset_rwsem);
+
+- /* allow moving tasks into an empty cpuset if on default hierarchy */
+- ret = -ENOSPC;
+- if (!is_in_v2_mode() &&
+- (cpumask_empty(cs->cpus_allowed) || nodes_empty(cs->mems_allowed)))
++ ret = cpuset_can_attach_check(cs);
++ if (ret)
+ goto out_unlock;
+
+ cgroup_taskset_for_each(task, css, tset) {
+@@ -2185,7 +2195,6 @@ static int cpuset_can_attach(struct cgro
+ * changes which zero cpus/mems_allowed.
+ */
+ cs->attach_in_progress++;
+- ret = 0;
+ out_unlock:
+ percpu_up_write(&cpuset_rwsem);
+ return ret;
+@@ -2913,6 +2922,68 @@ static void cpuset_bind(struct cgroup_su
+ }
+
+ /*
++ * In case the child is cloned into a cpuset different from its parent,
++ * additional checks are done to see if the move is allowed.
++ */
++static int cpuset_can_fork(struct task_struct *task, struct css_set *cset)
++{
++ struct cpuset *cs = css_cs(cset->subsys[cpuset_cgrp_id]);
++ bool same_cs;
++ int ret;
++
++ rcu_read_lock();
++ same_cs = (cs == task_cs(current));
++ rcu_read_unlock();
++
++ if (same_cs)
++ return 0;
++
++ lockdep_assert_held(&cgroup_mutex);
++ percpu_down_write(&cpuset_rwsem);
++
++ /* Check to see if task is allowed in the cpuset */
++ ret = cpuset_can_attach_check(cs);
++ if (ret)
++ goto out_unlock;
++
++ ret = task_can_attach(task, cs->effective_cpus);
++ if (ret)
++ goto out_unlock;
++
++ ret = security_task_setscheduler(task);
++ if (ret)
++ goto out_unlock;
++
++ /*
++ * Mark attach is in progress. This makes validate_change() fail
++ * changes which zero cpus/mems_allowed.
++ */
++ cs->attach_in_progress++;
++out_unlock:
++ percpu_up_write(&cpuset_rwsem);
++ return ret;
++}
++
++static void cpuset_cancel_fork(struct task_struct *task, struct css_set *cset)
++{
++ struct cpuset *cs = css_cs(cset->subsys[cpuset_cgrp_id]);
++ bool same_cs;
++
++ rcu_read_lock();
++ same_cs = (cs == task_cs(current));
++ rcu_read_unlock();
++
++ if (same_cs)
++ return;
++
++ percpu_down_write(&cpuset_rwsem);
++ cs->attach_in_progress--;
++ if (!cs->attach_in_progress)
++ wake_up(&cpuset_attach_wq);
++ percpu_up_write(&cpuset_rwsem);
++}
++
++/*
+ * Make sure the new task conform to the current state of its parent,
+ * which could have been changed by cpuset just after it inherits the
+ * state from the parent and before it sits on the cgroup's task list.
+@@ -2946,6 +3017,11 @@ static void cpuset_fork(struct task_stru
+ else
+ guarantee_online_cpus(cs, cpus_attach);
+ cpuset_attach_task(cs, task);
++
++ cs->attach_in_progress--;
++ if (!cs->attach_in_progress)
++ wake_up(&cpuset_attach_wq);
++
+ percpu_up_write(&cpuset_rwsem);
+ }
+
+@@ -2959,6 +3035,8 @@ struct cgroup_subsys cpuset_cgrp_subsys
+ .attach = cpuset_attach,
+ .post_attach = cpuset_post_attach,
+ .bind = cpuset_bind,
++ .can_fork = cpuset_can_fork,
++ .cancel_fork = cpuset_cancel_fork,
+ .fork = cpuset_fork,
+ .legacy_cftypes = legacy_files,
+ .dfl_cftypes = dfl_files,
--- /dev/null
+From stable-owner@vger.kernel.org Mon Apr 17 19:21:31 2023
+From: Waiman Long <longman@redhat.com>
+Date: Mon, 17 Apr 2023 13:19:55 -0400
+Subject: cgroup/cpuset: Change references of cpuset_mutex to cpuset_rwsem
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, stable@vger.kernel.org
+Cc: "Tejun Heo" <tj@kernel.org>, "Michal Koutný" <mkoutny@suse.com>, "Giuseppe Scrivano" <gscrivan@redhat.com>, "Waiman Long" <longman@redhat.com>
+Message-ID: <20230417171958.3389333-1-longman@redhat.com>
+
+From: Waiman Long <longman@redhat.com>
+
+Commit b94f9ac79a7395c2d6171cc753cc27942df0be73 upstream.
+
+Since commit 1243dc518c9d ("cgroup/cpuset: Convert cpuset_mutex to
+percpu_rwsem"), cpuset_mutex has been replaced by cpuset_rwsem which is
+a percpu rwsem. However, the comments in kernel/cgroup/cpuset.c still
+reference cpuset_mutex which are now incorrect.
+
+Change all the references of cpuset_mutex to cpuset_rwsem.
+
+Fixes: 1243dc518c9d ("cgroup/cpuset: Convert cpuset_mutex to percpu_rwsem")
+Signed-off-by: Waiman Long <longman@redhat.com>
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/cgroup/cpuset.c | 56 +++++++++++++++++++++++++------------------------
+ 1 file changed, 29 insertions(+), 27 deletions(-)
+
+--- a/kernel/cgroup/cpuset.c
++++ b/kernel/cgroup/cpuset.c
+@@ -299,17 +299,19 @@ static struct cpuset top_cpuset = {
+ if (is_cpuset_online(((des_cs) = css_cs((pos_css)))))
+
+ /*
+- * There are two global locks guarding cpuset structures - cpuset_mutex and
++ * There are two global locks guarding cpuset structures - cpuset_rwsem and
+ * callback_lock. We also require taking task_lock() when dereferencing a
+ * task's cpuset pointer. See "The task_lock() exception", at the end of this
+- * comment.
++ * comment. The cpuset code uses only cpuset_rwsem write lock. Other
++ * kernel subsystems can use cpuset_read_lock()/cpuset_read_unlock() to
++ * prevent change to cpuset structures.
+ *
+ * A task must hold both locks to modify cpusets. If a task holds
+- * cpuset_mutex, then it blocks others wanting that mutex, ensuring that it
++ * cpuset_rwsem, it blocks others wanting that rwsem, ensuring that it
+ * is the only task able to also acquire callback_lock and be able to
+ * modify cpusets. It can perform various checks on the cpuset structure
+ * first, knowing nothing will change. It can also allocate memory while
+- * just holding cpuset_mutex. While it is performing these checks, various
++ * just holding cpuset_rwsem. While it is performing these checks, various
+ * callback routines can briefly acquire callback_lock to query cpusets.
+ * Once it is ready to make the changes, it takes callback_lock, blocking
+ * everyone else.
+@@ -380,7 +382,7 @@ static inline bool is_in_v2_mode(void)
+ * One way or another, we guarantee to return some non-empty subset
+ * of cpu_online_mask.
+ *
+- * Call with callback_lock or cpuset_mutex held.
++ * Call with callback_lock or cpuset_rwsem held.
+ */
+ static void guarantee_online_cpus(struct cpuset *cs, struct cpumask *pmask)
+ {
+@@ -410,7 +412,7 @@ static void guarantee_online_cpus(struct
+ * One way or another, we guarantee to return some non-empty subset
+ * of node_states[N_MEMORY].
+ *
+- * Call with callback_lock or cpuset_mutex held.
++ * Call with callback_lock or cpuset_rwsem held.
+ */
+ static void guarantee_online_mems(struct cpuset *cs, nodemask_t *pmask)
+ {
+@@ -422,7 +424,7 @@ static void guarantee_online_mems(struct
+ /*
+ * update task's spread flag if cpuset's page/slab spread flag is set
+ *
+- * Call with callback_lock or cpuset_mutex held.
++ * Call with callback_lock or cpuset_rwsem held.
+ */
+ static void cpuset_update_task_spread_flag(struct cpuset *cs,
+ struct task_struct *tsk)
+@@ -443,7 +445,7 @@ static void cpuset_update_task_spread_fl
+ *
+ * One cpuset is a subset of another if all its allowed CPUs and
+ * Memory Nodes are a subset of the other, and its exclusive flags
+- * are only set if the other's are set. Call holding cpuset_mutex.
++ * are only set if the other's are set. Call holding cpuset_rwsem.
+ */
+
+ static int is_cpuset_subset(const struct cpuset *p, const struct cpuset *q)
+@@ -552,7 +554,7 @@ static inline void free_cpuset(struct cp
+ * If we replaced the flag and mask values of the current cpuset
+ * (cur) with those values in the trial cpuset (trial), would
+ * our various subset and exclusive rules still be valid? Presumes
+- * cpuset_mutex held.
++ * cpuset_rwsem held.
+ *
+ * 'cur' is the address of an actual, in-use cpuset. Operations
+ * such as list traversal that depend on the actual address of the
+@@ -675,7 +677,7 @@ static void update_domain_attr_tree(stru
+ rcu_read_unlock();
+ }
+
+-/* Must be called with cpuset_mutex held. */
++/* Must be called with cpuset_rwsem held. */
+ static inline int nr_cpusets(void)
+ {
+ /* jump label reference count + the top-level cpuset */
+@@ -701,7 +703,7 @@ static inline int nr_cpusets(void)
+ * domains when operating in the severe memory shortage situations
+ * that could cause allocation failures below.
+ *
+- * Must be called with cpuset_mutex held.
++ * Must be called with cpuset_rwsem held.
+ *
+ * The three key local variables below are:
+ * cp - cpuset pointer, used (together with pos_css) to perform a
+@@ -980,7 +982,7 @@ partition_and_rebuild_sched_domains(int
+ * 'cpus' is removed, then call this routine to rebuild the
+ * scheduler's dynamic sched domains.
+ *
+- * Call with cpuset_mutex held. Takes get_online_cpus().
++ * Call with cpuset_rwsem held. Takes get_online_cpus().
+ */
+ static void rebuild_sched_domains_locked(void)
+ {
+@@ -1053,7 +1055,7 @@ void rebuild_sched_domains(void)
+ * @cs: the cpuset in which each task's cpus_allowed mask needs to be changed
+ *
+ * Iterate through each task of @cs updating its cpus_allowed to the
+- * effective cpuset's. As this function is called with cpuset_mutex held,
++ * effective cpuset's. As this function is called with cpuset_rwsem held,
+ * cpuset membership stays stable.
+ */
+ static void update_tasks_cpumask(struct cpuset *cs)
+@@ -1328,7 +1330,7 @@ static int update_parent_subparts_cpumas
+ *
+ * On legacy hierachy, effective_cpus will be the same with cpu_allowed.
+ *
+- * Called with cpuset_mutex held
++ * Called with cpuset_rwsem held
+ */
+ static void update_cpumasks_hier(struct cpuset *cs, struct tmpmasks *tmp)
+ {
+@@ -1688,12 +1690,12 @@ static void *cpuset_being_rebound;
+ * @cs: the cpuset in which each task's mems_allowed mask needs to be changed
+ *
+ * Iterate through each task of @cs updating its mems_allowed to the
+- * effective cpuset's. As this function is called with cpuset_mutex held,
++ * effective cpuset's. As this function is called with cpuset_rwsem held,
+ * cpuset membership stays stable.
+ */
+ static void update_tasks_nodemask(struct cpuset *cs)
+ {
+- static nodemask_t newmems; /* protected by cpuset_mutex */
++ static nodemask_t newmems; /* protected by cpuset_rwsem */
+ struct css_task_iter it;
+ struct task_struct *task;
+
+@@ -1706,7 +1708,7 @@ static void update_tasks_nodemask(struct
+ * take while holding tasklist_lock. Forks can happen - the
+ * mpol_dup() cpuset_being_rebound check will catch such forks,
+ * and rebind their vma mempolicies too. Because we still hold
+- * the global cpuset_mutex, we know that no other rebind effort
++ * the global cpuset_rwsem, we know that no other rebind effort
+ * will be contending for the global variable cpuset_being_rebound.
+ * It's ok if we rebind the same mm twice; mpol_rebind_mm()
+ * is idempotent. Also migrate pages in each mm to new nodes.
+@@ -1752,7 +1754,7 @@ static void update_tasks_nodemask(struct
+ *
+ * On legacy hiearchy, effective_mems will be the same with mems_allowed.
+ *
+- * Called with cpuset_mutex held
++ * Called with cpuset_rwsem held
+ */
+ static void update_nodemasks_hier(struct cpuset *cs, nodemask_t *new_mems)
+ {
+@@ -1805,7 +1807,7 @@ static void update_nodemasks_hier(struct
+ * mempolicies and if the cpuset is marked 'memory_migrate',
+ * migrate the tasks pages to the new memory.
+ *
+- * Call with cpuset_mutex held. May take callback_lock during call.
++ * Call with cpuset_rwsem held. May take callback_lock during call.
+ * Will take tasklist_lock, scan tasklist for tasks in cpuset cs,
+ * lock each such tasks mm->mmap_lock, scan its vma's and rebind
+ * their mempolicies to the cpusets new mems_allowed.
+@@ -1895,7 +1897,7 @@ static int update_relax_domain_level(str
+ * @cs: the cpuset in which each task's spread flags needs to be changed
+ *
+ * Iterate through each task of @cs updating its spread flags. As this
+- * function is called with cpuset_mutex held, cpuset membership stays
++ * function is called with cpuset_rwsem held, cpuset membership stays
+ * stable.
+ */
+ static void update_tasks_flags(struct cpuset *cs)
+@@ -1915,7 +1917,7 @@ static void update_tasks_flags(struct cp
+ * cs: the cpuset to update
+ * turning_on: whether the flag is being set or cleared
+ *
+- * Call with cpuset_mutex held.
++ * Call with cpuset_rwsem held.
+ */
+
+ static int update_flag(cpuset_flagbits_t bit, struct cpuset *cs,
+@@ -1964,7 +1966,7 @@ out:
+ * cs: the cpuset to update
+ * new_prs: new partition root state
+ *
+- * Call with cpuset_mutex held.
++ * Call with cpuset_rwsem held.
+ */
+ static int update_prstate(struct cpuset *cs, int new_prs)
+ {
+@@ -2145,7 +2147,7 @@ static int fmeter_getrate(struct fmeter
+
+ static struct cpuset *cpuset_attach_old_cs;
+
+-/* Called by cgroups to determine if a cpuset is usable; cpuset_mutex held */
++/* Called by cgroups to determine if a cpuset is usable; cpuset_rwsem held */
+ static int cpuset_can_attach(struct cgroup_taskset *tset)
+ {
+ struct cgroup_subsys_state *css;
+@@ -2201,7 +2203,7 @@ static void cpuset_cancel_attach(struct
+ }
+
+ /*
+- * Protected by cpuset_mutex. cpus_attach is used only by cpuset_attach()
++ * Protected by cpuset_rwsem. cpus_attach is used only by cpuset_attach()
+ * but we can't allocate it dynamically there. Define it global and
+ * allocate from cpuset_init().
+ */
+@@ -2209,7 +2211,7 @@ static cpumask_var_t cpus_attach;
+
+ static void cpuset_attach(struct cgroup_taskset *tset)
+ {
+- /* static buf protected by cpuset_mutex */
++ /* static buf protected by cpuset_rwsem */
+ static nodemask_t cpuset_attach_nodemask_to;
+ struct task_struct *task;
+ struct task_struct *leader;
+@@ -2402,7 +2404,7 @@ static ssize_t cpuset_write_resmask(stru
+ * operation like this one can lead to a deadlock through kernfs
+ * active_ref protection. Let's break the protection. Losing the
+ * protection is okay as we check whether @cs is online after
+- * grabbing cpuset_mutex anyway. This only happens on the legacy
++ * grabbing cpuset_rwsem anyway. This only happens on the legacy
+ * hierarchies.
+ */
+ css_get(&cs->css);
+@@ -3641,7 +3643,7 @@ void __cpuset_memory_pressure_bump(void)
+ * - Used for /proc/<pid>/cpuset.
+ * - No need to task_lock(tsk) on this tsk->cpuset reference, as it
+ * doesn't really matter if tsk->cpuset changes after we read it,
+- * and we take cpuset_mutex, keeping cpuset_attach() from changing it
++ * and we take cpuset_rwsem, keeping cpuset_attach() from changing it
+ * anyway.
+ */
+ int proc_cpuset_show(struct seq_file *m, struct pid_namespace *ns,
--- /dev/null
+From stable-owner@vger.kernel.org Mon Apr 17 19:21:27 2023
+From: Waiman Long <longman@redhat.com>
+Date: Mon, 17 Apr 2023 13:19:57 -0400
+Subject: cgroup/cpuset: Make cpuset_fork() handle CLONE_INTO_CGROUP properly
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, stable@vger.kernel.org
+Cc: "Tejun Heo" <tj@kernel.org>, "Michal Koutný" <mkoutny@suse.com>, "Giuseppe Scrivano" <gscrivan@redhat.com>, "Waiman Long" <longman@redhat.com>
+Message-ID: <20230417171958.3389333-3-longman@redhat.com>
+
+From: Waiman Long <longman@redhat.com>
+
+commit 42a11bf5c5436e91b040aeb04063be1710bb9f9c upstream.
+
+By default, the clone(2) syscall spawn a child process into the same
+cgroup as its parent. With the use of the CLONE_INTO_CGROUP flag
+introduced by commit ef2c41cf38a7 ("clone3: allow spawning processes
+into cgroups"), the child will be spawned into a different cgroup which
+is somewhat similar to writing the child's tid into "cgroup.threads".
+
+The current cpuset_fork() method does not properly handle the
+CLONE_INTO_CGROUP case where the cpuset of the child may be different
+from that of its parent. Update the cpuset_fork() method to treat the
+CLONE_INTO_CGROUP case similar to cpuset_attach().
+
+Since the newly cloned task has not been running yet, its actual
+memory usage isn't known. So it is not necessary to make change to mm
+in cpuset_fork().
+
+Fixes: ef2c41cf38a7 ("clone3: allow spawning processes into cgroups")
+Reported-by: Giuseppe Scrivano <gscrivan@redhat.com>
+Signed-off-by: Waiman Long <longman@redhat.com>
+Cc: stable@vger.kernel.org # v5.7+
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/cgroup/cpuset.c | 60 +++++++++++++++++++++++++++++++++++--------------
+ 1 file changed, 44 insertions(+), 16 deletions(-)
+
+--- a/kernel/cgroup/cpuset.c
++++ b/kernel/cgroup/cpuset.c
+@@ -2207,16 +2207,29 @@ static void cpuset_cancel_attach(struct
+ }
+
+ /*
+- * Protected by cpuset_rwsem. cpus_attach is used only by cpuset_attach()
++ * Protected by cpuset_rwsem. cpus_attach is used only by cpuset_attach_task()
+ * but we can't allocate it dynamically there. Define it global and
+ * allocate from cpuset_init().
+ */
+ static cpumask_var_t cpus_attach;
++static nodemask_t cpuset_attach_nodemask_to;
++
++static void cpuset_attach_task(struct cpuset *cs, struct task_struct *task)
++{
++ percpu_rwsem_assert_held(&cpuset_rwsem);
++
++ /*
++ * can_attach beforehand should guarantee that this doesn't
++ * fail. TODO: have a better way to handle failure here
++ */
++ WARN_ON_ONCE(set_cpus_allowed_ptr(task, cpus_attach));
++
++ cpuset_change_task_nodemask(task, &cpuset_attach_nodemask_to);
++ cpuset_update_task_spread_flags(cs, task);
++}
+
+ static void cpuset_attach(struct cgroup_taskset *tset)
+ {
+- /* static buf protected by cpuset_rwsem */
+- static nodemask_t cpuset_attach_nodemask_to;
+ struct task_struct *task;
+ struct task_struct *leader;
+ struct cgroup_subsys_state *css;
+@@ -2237,16 +2250,8 @@ static void cpuset_attach(struct cgroup_
+
+ guarantee_online_mems(cs, &cpuset_attach_nodemask_to);
+
+- cgroup_taskset_for_each(task, css, tset) {
+- /*
+- * can_attach beforehand should guarantee that this doesn't
+- * fail. TODO: have a better way to handle failure here
+- */
+- WARN_ON_ONCE(set_cpus_allowed_ptr(task, cpus_attach));
+-
+- cpuset_change_task_nodemask(task, &cpuset_attach_nodemask_to);
+- cpuset_update_task_spread_flags(cs, task);
+- }
++ cgroup_taskset_for_each(task, css, tset)
++ cpuset_attach_task(cs, task);
+
+ /*
+ * Change mm for all threadgroup leaders. This is expensive and may
+@@ -2914,11 +2919,34 @@ static void cpuset_bind(struct cgroup_su
+ */
+ static void cpuset_fork(struct task_struct *task)
+ {
+- if (task_css_is_root(task, cpuset_cgrp_id))
++ struct cpuset *cs;
++ bool same_cs;
++
++ rcu_read_lock();
++ cs = task_cs(task);
++ same_cs = (cs == task_cs(current));
++ rcu_read_unlock();
++
++ if (same_cs) {
++ if (cs == &top_cpuset)
++ return;
++
++ set_cpus_allowed_ptr(task, current->cpus_ptr);
++ task->mems_allowed = current->mems_allowed;
+ return;
++ }
++
++ /* CLONE_INTO_CGROUP */
++ percpu_down_write(&cpuset_rwsem);
++ guarantee_online_mems(cs, &cpuset_attach_nodemask_to);
+
+- set_cpus_allowed_ptr(task, current->cpus_ptr);
+- task->mems_allowed = current->mems_allowed;
++ /* prepare for attach */
++ if (cs == &top_cpuset)
++ cpumask_copy(cpus_attach, cpu_possible_mask);
++ else
++ guarantee_online_cpus(cs, cpus_attach);
++ cpuset_attach_task(cs, task);
++ percpu_up_write(&cpuset_rwsem);
+ }
+
+ struct cgroup_subsys cpuset_cgrp_subsys = {
--- /dev/null
+From stable-owner@vger.kernel.org Mon Apr 17 19:21:24 2023
+From: Waiman Long <longman@redhat.com>
+Date: Mon, 17 Apr 2023 13:19:56 -0400
+Subject: cgroup/cpuset: Skip spread flags update on v2
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, stable@vger.kernel.org
+Cc: "Tejun Heo" <tj@kernel.org>, "Michal Koutný" <mkoutny@suse.com>, "Giuseppe Scrivano" <gscrivan@redhat.com>, "Waiman Long" <longman@redhat.com>
+Message-ID: <20230417171958.3389333-2-longman@redhat.com>
+
+From: Waiman Long <longman@redhat.com>
+
+commit 18f9a4d47527772515ad6cbdac796422566e6440 upstream.
+
+Cpuset v2 has no spread flags to set. So we can skip spread
+flags update if cpuset v2 is being used. Also change the name to
+cpuset_update_task_spread_flags() to indicate that there are multiple
+spread flags.
+
+Signed-off-by: Waiman Long <longman@redhat.com>
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/cgroup/cpuset.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+--- a/kernel/cgroup/cpuset.c
++++ b/kernel/cgroup/cpuset.c
+@@ -424,11 +424,15 @@ static void guarantee_online_mems(struct
+ /*
+ * update task's spread flag if cpuset's page/slab spread flag is set
+ *
+- * Call with callback_lock or cpuset_rwsem held.
++ * Call with callback_lock or cpuset_rwsem held. The check can be skipped
++ * if on default hierarchy.
+ */
+-static void cpuset_update_task_spread_flag(struct cpuset *cs,
++static void cpuset_update_task_spread_flags(struct cpuset *cs,
+ struct task_struct *tsk)
+ {
++ if (cgroup_subsys_on_dfl(cpuset_cgrp_subsys))
++ return;
++
+ if (is_spread_page(cs))
+ task_set_spread_page(tsk);
+ else
+@@ -1907,7 +1911,7 @@ static void update_tasks_flags(struct cp
+
+ css_task_iter_start(&cs->css, 0, &it);
+ while ((task = css_task_iter_next(&it)))
+- cpuset_update_task_spread_flag(cs, task);
++ cpuset_update_task_spread_flags(cs, task);
+ css_task_iter_end(&it);
+ }
+
+@@ -2241,7 +2245,7 @@ static void cpuset_attach(struct cgroup_
+ WARN_ON_ONCE(set_cpus_allowed_ptr(task, cpus_attach));
+
+ cpuset_change_task_nodemask(task, &cpuset_attach_nodemask_to);
+- cpuset_update_task_spread_flag(cs, task);
++ cpuset_update_task_spread_flags(cs, task);
+ }
+
+ /*
--- /dev/null
+From bf84937e882009075f57fd213836256fc65d96bc Mon Sep 17 00:00:00 2001
+From: Steve Clevenger <scclevenger@os.amperecomputing.com>
+Date: Mon, 27 Feb 2023 16:54:32 -0700
+Subject: coresight-etm4: Fix for() loop drvdata->nr_addr_cmp range bug
+
+From: Steve Clevenger <scclevenger@os.amperecomputing.com>
+
+commit bf84937e882009075f57fd213836256fc65d96bc upstream.
+
+In etm4_enable_hw, fix for() loop range to represent address comparator pairs.
+
+Fixes: 2e1cdfe184b5 ("coresight-etm4x: Adding CoreSight ETM4x driver")
+Cc: stable@vger.kernel.org
+Signed-off-by: Steve Clevenger <scclevenger@os.amperecomputing.com>
+Reviewed-by: James Clark <james.clark@arm.com>
+Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
+Link: https://lore.kernel.org/r/4a4ee61ce8ef402615a4528b21a051de3444fb7b.1677540079.git.scclevenger@os.amperecomputing.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hwtracing/coresight/coresight-etm4x-core.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
++++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
+@@ -179,7 +179,7 @@ static int etm4_enable_hw(struct etmv4_d
+ writel_relaxed(config->ss_pe_cmp[i],
+ drvdata->base + TRCSSPCICRn(i));
+ }
+- for (i = 0; i < drvdata->nr_addr_cmp; i++) {
++ for (i = 0; i < drvdata->nr_addr_cmp * 2; i++) {
+ writeq_relaxed(config->addr_val[i],
+ drvdata->base + TRCACVRn(i));
+ writeq_relaxed(config->addr_acc[i],
--- /dev/null
+From stable-owner@vger.kernel.org Wed Mar 29 02:08:43 2023
+From: Nathan Chancellor <nathan@kernel.org>
+Date: Tue, 28 Mar 2023 17:08:31 -0700
+Subject: kbuild: check CONFIG_AS_IS_LLVM instead of LLVM_IAS
+To: gregkh@linuxfoundation.org, sashal@kernel.org
+Cc: conor@kernel.org, stable@vger.kernel.org, llvm@lists.linux.dev, Masahiro Yamada <masahiroy@kernel.org>, Nick Desaulniers <ndesaulniers@google.com>, Nathan Chancellor <nathan@kernel.org>
+Message-ID: <20230328-riscv-zifencei-zicsr-5-10-v1-3-bccb3e16dc46@kernel.org>
+
+From: Masahiro Yamada <masahiroy@kernel.org>
+
+commit 52cc02b910284d6bddba46cce402044ab775f314 upstream.
+
+LLVM_IAS is the user interface to set the -(no-)integrated-as flag,
+and it should be used only for that purpose.
+
+LLVM_IAS is checked in some places to determine the assembler type,
+but it is not precise.
+
+For example,
+
+ $ make CC=gcc LLVM_IAS=1
+
+... will use the GNU assembler (i.e. binutils) since LLVM_IAS=1 is
+effective only when $(CC) is clang.
+
+Of course, 'CC=gcc LLVM_IAS=1' is an odd combination, but the build
+system can be more robust against such insane input.
+
+Commit ba64beb17493a ("kbuild: check the minimum assembler version in
+Kconfig") introduced CONFIG_AS_IS_GNU/LLVM, which is more precise
+because Kconfig checks the version string from the assembler in use.
+
+Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
+Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
+Reviewed-by: Nathan Chancellor <nathan@kernel.org>
+[nathan: Backport to 5.10]
+Signed-off-by: Nathan Chancellor <nathan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ Makefile | 2 +-
+ arch/riscv/Makefile | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/Makefile
++++ b/Makefile
+@@ -851,7 +851,7 @@ else
+ DEBUG_CFLAGS += -g
+ endif
+
+-ifeq ($(LLVM_IAS),1)
++ifdef CONFIG_AS_IS_LLVM
+ KBUILD_AFLAGS += -g
+ else
+ KBUILD_AFLAGS += -Wa,-gdwarf-2
+--- a/arch/riscv/Makefile
++++ b/arch/riscv/Makefile
+@@ -40,7 +40,7 @@ ifeq ($(CONFIG_LD_IS_LLD),y)
+ ifeq ($(shell test $(CONFIG_LLD_VERSION) -lt 150000; echo $$?),0)
+ KBUILD_CFLAGS += -mno-relax
+ KBUILD_AFLAGS += -mno-relax
+-ifneq ($(LLVM_IAS),1)
++ifndef CONFIG_AS_IS_LLVM
+ KBUILD_CFLAGS += -Wa,-mno-relax
+ KBUILD_AFLAGS += -Wa,-mno-relax
+ endif
--- /dev/null
+From stable-owner@vger.kernel.org Wed Mar 29 02:08:38 2023
+From: Nathan Chancellor <nathan@kernel.org>
+Date: Tue, 28 Mar 2023 17:08:29 -0700
+Subject: kbuild: check the minimum assembler version in Kconfig
+To: gregkh@linuxfoundation.org, sashal@kernel.org
+Cc: conor@kernel.org, stable@vger.kernel.org, llvm@lists.linux.dev, Masahiro Yamada <masahiroy@kernel.org>, Nathan Chancellor <nathan@kernel.org>
+Message-ID: <20230328-riscv-zifencei-zicsr-5-10-v1-1-bccb3e16dc46@kernel.org>
+
+From: Masahiro Yamada <masahiroy@kernel.org>
+
+commit ba64beb17493a4bfec563100c86a462a15926f24 upstream.
+
+Documentation/process/changes.rst defines the minimum assembler version
+(binutils version), but we have never checked it in the build time.
+
+Kbuild never invokes 'as' directly because all assembly files in the
+kernel tree are *.S, hence must be preprocessed. I do not expect
+raw assembly source files (*.s) would be added to the kernel tree.
+
+Therefore, we always use $(CC) as the assembler driver, and commit
+aa824e0c962b ("kbuild: remove AS variable") removed 'AS'. However,
+we are still interested in the version of the assembler acting behind.
+
+As usual, the --version option prints the version string.
+
+ $ as --version | head -n 1
+ GNU assembler (GNU Binutils for Ubuntu) 2.35.1
+
+But, we do not have $(AS). So, we can add the -Wa prefix so that
+$(CC) passes --version down to the backing assembler.
+
+ $ gcc -Wa,--version | head -n 1
+ gcc: fatal error: no input files
+ compilation terminated.
+
+OK, we need to input something to satisfy gcc.
+
+ $ gcc -Wa,--version -c -x assembler /dev/null -o /dev/null | head -n 1
+ GNU assembler (GNU Binutils for Ubuntu) 2.35.1
+
+The combination of Clang and GNU assembler works in the same way:
+
+ $ clang -no-integrated-as -Wa,--version -c -x assembler /dev/null -o /dev/null | head -n 1
+ GNU assembler (GNU Binutils for Ubuntu) 2.35.1
+
+Clang with the integrated assembler fails like this:
+
+ $ clang -integrated-as -Wa,--version -c -x assembler /dev/null -o /dev/null | head -n 1
+ clang: error: unsupported argument '--version' to option 'Wa,'
+
+For the last case, checking the error message is fragile. If the
+proposal for -Wa,--version support [1] is accepted, this may not be
+even an error in the future.
+
+One easy way is to check if -integrated-as is present in the passed
+arguments. We did not pass -integrated-as to CLANG_FLAGS before, but
+we can make it explicit.
+
+Nathan pointed out -integrated-as is the default for all of the
+architectures/targets that the kernel cares about, but it goes
+along with "explicit is better than implicit" policy. [2]
+
+With all this in my mind, I implemented scripts/as-version.sh to
+check the assembler version in Kconfig time.
+
+ $ scripts/as-version.sh gcc
+ GNU 23501
+ $ scripts/as-version.sh clang -no-integrated-as
+ GNU 23501
+ $ scripts/as-version.sh clang -integrated-as
+ LLVM 0
+
+[1]: https://github.com/ClangBuiltLinux/linux/issues/1320
+[2]: https://lore.kernel.org/linux-kbuild/20210307044253.v3h47ucq6ng25iay@archlinux-ax161/
+
+Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
+Reviewed-by: Nathan Chancellor <nathan@kernel.org>
+[nathan: Backport to 5.10. Drop minimum version checking, as it is not
+ required in 5.10]
+Signed-off-by: Nathan Chancellor <nathan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ Makefile | 4 ++
+ init/Kconfig | 12 ++++++++
+ scripts/Kconfig.include | 6 ++++
+ scripts/as-version.sh | 69 ++++++++++++++++++++++++++++++++++++++++++++++++
+ scripts/dummy-tools/gcc | 6 ++++
+ 5 files changed, 96 insertions(+), 1 deletion(-)
+
+diff --git a/Makefile b/Makefile
+index 71caf5938361..44d9aff4f66a 100644
+--- a/Makefile
++++ b/Makefile
+@@ -580,7 +580,9 @@ endif
+ ifneq ($(GCC_TOOLCHAIN),)
+ CLANG_FLAGS += --gcc-toolchain=$(GCC_TOOLCHAIN)
+ endif
+-ifneq ($(LLVM_IAS),1)
++ifeq ($(LLVM_IAS),1)
++CLANG_FLAGS += -integrated-as
++else
+ CLANG_FLAGS += -no-integrated-as
+ endif
+ CLANG_FLAGS += -Werror=unknown-warning-option
+diff --git a/init/Kconfig b/init/Kconfig
+index eba883d6d9ed..9807c66b24bb 100644
+--- a/init/Kconfig
++++ b/init/Kconfig
+@@ -47,6 +47,18 @@ config CLANG_VERSION
+ int
+ default $(shell,$(srctree)/scripts/clang-version.sh $(CC))
+
++config AS_IS_GNU
++ def_bool $(success,test "$(as-name)" = GNU)
++
++config AS_IS_LLVM
++ def_bool $(success,test "$(as-name)" = LLVM)
++
++config AS_VERSION
++ int
++ # Use clang version if this is the integrated assembler
++ default CLANG_VERSION if AS_IS_LLVM
++ default $(as-version)
++
+ config LLD_VERSION
+ int
+ default $(shell,$(srctree)/scripts/lld-version.sh $(LD))
+diff --git a/scripts/Kconfig.include b/scripts/Kconfig.include
+index a5fe72c504ff..6d37cb780452 100644
+--- a/scripts/Kconfig.include
++++ b/scripts/Kconfig.include
+@@ -42,6 +42,12 @@ $(error-if,$(failure,command -v $(LD)),linker '$(LD)' not found)
+ # Fail if the linker is gold as it's not capable of linking the kernel proper
+ $(error-if,$(success, $(LD) -v | grep -q gold), gold linker '$(LD)' not supported)
+
++# Get the assembler name, version, and error out if it is not supported.
++as-info := $(shell,$(srctree)/scripts/as-version.sh $(CC) $(CLANG_FLAGS))
++$(error-if,$(success,test -z "$(as-info)"),Sorry$(comma) this assembler is not supported.)
++as-name := $(shell,set -- $(as-info) && echo $1)
++as-version := $(shell,set -- $(as-info) && echo $2)
++
+ # machine bit flags
+ # $(m32-flag): -m32 if the compiler supports it, or an empty string otherwise.
+ # $(m64-flag): -m64 if the compiler supports it, or an empty string otherwise.
+diff --git a/scripts/as-version.sh b/scripts/as-version.sh
+new file mode 100755
+index 000000000000..851dcb8a0e68
+--- /dev/null
++++ b/scripts/as-version.sh
+@@ -0,0 +1,69 @@
++#!/bin/sh
++# SPDX-License-Identifier: GPL-2.0-only
++#
++# Print the assembler name and its version in a 5 or 6-digit form.
++# Also, perform the minimum version check.
++# (If it is the integrated assembler, return 0 as the version, and
++# skip the version check.)
++
++set -e
++
++# Convert the version string x.y.z to a canonical 5 or 6-digit form.
++get_canonical_version()
++{
++ IFS=.
++ set -- $1
++
++ # If the 2nd or 3rd field is missing, fill it with a zero.
++ #
++ # The 4th field, if present, is ignored.
++ # This occurs in development snapshots as in 2.35.1.20201116
++ echo $((10000 * $1 + 100 * ${2:-0} + ${3:-0}))
++}
++
++# Clang fails to handle -Wa,--version unless -no-integrated-as is given.
++# We check -(f)integrated-as, expecting it is explicitly passed in for the
++# integrated assembler case.
++check_integrated_as()
++{
++ while [ $# -gt 0 ]; do
++ if [ "$1" = -integrated-as -o "$1" = -fintegrated-as ]; then
++ # For the intergrated assembler, we do not check the
++ # version here. It is the same as the clang version, and
++ # it has been already checked by scripts/cc-version.sh.
++ echo LLVM 0
++ exit 0
++ fi
++ shift
++ done
++}
++
++check_integrated_as "$@"
++
++orig_args="$@"
++
++# Get the first line of the --version output.
++IFS='
++'
++set -- $(LC_ALL=C "$@" -Wa,--version -c -x assembler /dev/null -o /dev/null 2>/dev/null)
++
++# Split the line on spaces.
++IFS=' '
++set -- $1
++
++if [ "$1" = GNU -a "$2" = assembler ]; then
++ shift $(($# - 1))
++ version=$1
++ name=GNU
++else
++ echo "$orig_args: unknown assembler invoked" >&2
++ exit 1
++fi
++
++# Some distributions append a package release number, as in 2.34-4.fc32
++# Trim the hyphen and any characters that follow.
++version=${version%-*}
++
++cversion=$(get_canonical_version $version)
++
++echo $name $cversion
+diff --git a/scripts/dummy-tools/gcc b/scripts/dummy-tools/gcc
+index 346757a87dbc..485427f40dba 100755
+--- a/scripts/dummy-tools/gcc
++++ b/scripts/dummy-tools/gcc
+@@ -67,6 +67,12 @@ if arg_contain -E "$@"; then
+ fi
+ fi
+
++# To set CONFIG_AS_IS_GNU
++if arg_contain -Wa,--version "$@"; then
++ echo "GNU assembler (scripts/dummy-tools) 2.50"
++ exit 0
++fi
++
+ if arg_contain -S "$@"; then
+ # For scripts/gcc-x86-*-has-stack-protector.sh
+ if arg_contain -fstack-protector "$@"; then
+
+--
+2.40.0
+
--- /dev/null
+From stable-owner@vger.kernel.org Wed Mar 29 02:08:38 2023
+From: Nathan Chancellor <nathan@kernel.org>
+Date: Tue, 28 Mar 2023 17:08:30 -0700
+Subject: kbuild: Switch to 'f' variants of integrated assembler flag
+To: gregkh@linuxfoundation.org, sashal@kernel.org
+Cc: conor@kernel.org, stable@vger.kernel.org, llvm@lists.linux.dev, Nick Desaulniers <ndesaulniers@google.com>, Nathan Chancellor <nathan@kernel.org>, Masahiro Yamada <masahiroy@kernel.org>
+Message-ID: <20230328-riscv-zifencei-zicsr-5-10-v1-2-bccb3e16dc46@kernel.org>
+
+From: Nathan Chancellor <nathan@kernel.org>
+
+commit 2185a7e4b0ade86c2c57fc63d4a7535c40254bd0 upstream.
+
+It has been brought up a few times in various code reviews that clang
+3.5 introduced -f{,no-}integrated-as as the preferred way to enable and
+disable the integrated assembler, mentioning that -{no-,}integrated-as
+are now considered legacy flags.
+
+Switch the kernel over to using those variants in case there is ever a
+time where clang decides to remove the non-'f' variants of the flag.
+
+Also, fix a typo in a comment ("intergrated" -> "integrated").
+
+Link: https://releases.llvm.org/3.5.0/tools/clang/docs/ReleaseNotes.html#new-compiler-flags
+Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
+Signed-off-by: Nathan Chancellor <nathan@kernel.org>
+Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
+[nathan: Backport to 5.10]
+Signed-off-by: Nathan Chancellor <nathan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ Makefile | 4 ++--
+ scripts/as-version.sh | 8 ++++----
+ 2 files changed, 6 insertions(+), 6 deletions(-)
+
+--- a/Makefile
++++ b/Makefile
+@@ -581,9 +581,9 @@ ifneq ($(GCC_TOOLCHAIN),)
+ CLANG_FLAGS += --gcc-toolchain=$(GCC_TOOLCHAIN)
+ endif
+ ifeq ($(LLVM_IAS),1)
+-CLANG_FLAGS += -integrated-as
++CLANG_FLAGS += -fintegrated-as
+ else
+-CLANG_FLAGS += -no-integrated-as
++CLANG_FLAGS += -fno-integrated-as
+ endif
+ CLANG_FLAGS += -Werror=unknown-warning-option
+ KBUILD_CFLAGS += $(CLANG_FLAGS)
+--- a/scripts/as-version.sh
++++ b/scripts/as-version.sh
+@@ -21,14 +21,14 @@ get_canonical_version()
+ echo $((10000 * $1 + 100 * ${2:-0} + ${3:-0}))
+ }
+
+-# Clang fails to handle -Wa,--version unless -no-integrated-as is given.
+-# We check -(f)integrated-as, expecting it is explicitly passed in for the
++# Clang fails to handle -Wa,--version unless -fno-integrated-as is given.
++# We check -fintegrated-as, expecting it is explicitly passed in for the
+ # integrated assembler case.
+ check_integrated_as()
+ {
+ while [ $# -gt 0 ]; do
+- if [ "$1" = -integrated-as -o "$1" = -fintegrated-as ]; then
+- # For the intergrated assembler, we do not check the
++ if [ "$1" = -fintegrated-as ]; then
++ # For the integrated assembler, we do not check the
+ # version here. It is the same as the clang version, and
+ # it has been already checked by scripts/cc-version.sh.
+ echo LLVM 0
--- /dev/null
+From stable-owner@vger.kernel.org Wed Mar 29 02:08:41 2023
+From: Nathan Chancellor <nathan@kernel.org>
+Date: Tue, 28 Mar 2023 17:08:32 -0700
+Subject: riscv: Handle zicsr/zifencei issues between clang and binutils
+To: gregkh@linuxfoundation.org, sashal@kernel.org
+Cc: conor@kernel.org, stable@vger.kernel.org, llvm@lists.linux.dev, Conor Dooley <conor.dooley@microchip.com>, Nathan Chancellor <nathan@kernel.org>, Palmer Dabbelt <palmer@rivosinc.com>
+Message-ID: <20230328-riscv-zifencei-zicsr-5-10-v1-4-bccb3e16dc46@kernel.org>
+
+From: Nathan Chancellor <nathan@kernel.org>
+
+commit e89c2e815e76471cb507bd95728bf26da7976430 upstream.
+
+There are two related issues that appear in certain combinations with
+clang and GNU binutils.
+
+The first occurs when a version of clang that supports zicsr or zifencei
+via '-march=' [1] (i.e, >= 17.x) is used in combination with a version
+of GNU binutils that do not recognize zicsr and zifencei in the
+'-march=' value (i.e., < 2.36):
+
+ riscv64-linux-gnu-ld: -march=rv64i2p0_m2p0_a2p0_c2p0_zicsr2p0_zifencei2p0: Invalid or unknown z ISA extension: 'zifencei'
+ riscv64-linux-gnu-ld: failed to merge target specific data of file fs/efivarfs/file.o
+ riscv64-linux-gnu-ld: -march=rv64i2p0_m2p0_a2p0_c2p0_zicsr2p0_zifencei2p0: Invalid or unknown z ISA extension: 'zifencei'
+ riscv64-linux-gnu-ld: failed to merge target specific data of file fs/efivarfs/super.o
+
+The second occurs when a version of clang that does not support zicsr or
+zifencei via '-march=' (i.e., <= 16.x) is used in combination with a
+version of GNU as that defaults to a newer ISA base spec, which requires
+specifying zicsr and zifencei in the '-march=' value explicitly (i.e, >=
+2.38):
+
+ ../arch/riscv/kernel/kexec_relocate.S: Assembler messages:
+ ../arch/riscv/kernel/kexec_relocate.S:147: Error: unrecognized opcode `fence.i', extension `zifencei' required
+ clang-12: error: assembler command failed with exit code 1 (use -v to see invocation)
+
+This is the same issue addressed by commit 6df2a016c0c8 ("riscv: fix
+build with binutils 2.38") (see [2] for additional information) but
+older versions of clang miss out on it because the cc-option check
+fails:
+
+ clang-12: error: invalid arch name 'rv64imac_zicsr_zifencei', unsupported standard user-level extension 'zicsr'
+ clang-12: error: invalid arch name 'rv64imac_zicsr_zifencei', unsupported standard user-level extension 'zicsr'
+
+To resolve the first issue, only attempt to add zicsr and zifencei to
+the march string when using the GNU assembler 2.38 or newer, which is
+when the default ISA spec was updated, requiring these extensions to be
+specified explicitly. LLVM implements an older version of the base
+specification for all currently released versions, so these instructions
+are available as part of the 'i' extension. If LLVM's implementation is
+updated in the future, a CONFIG_AS_IS_LLVM condition can be added to
+CONFIG_TOOLCHAIN_NEEDS_EXPLICIT_ZICSR_ZIFENCEI.
+
+To resolve the second issue, use version 2.2 of the base ISA spec when
+using an older version of clang that does not support zicsr or zifencei
+via '-march=', as that is the spec version most compatible with the one
+clang/LLVM implements and avoids the need to specify zicsr and zifencei
+explicitly due to still being a part of 'i'.
+
+[1]: https://github.com/llvm/llvm-project/commit/22e199e6afb1263c943c0c0d4498694e15bf8a16
+[2]: https://lore.kernel.org/ZAxT7T9Xy1Fo3d5W@aurel32.net/
+
+Cc: stable@vger.kernel.org
+Link: https://github.com/ClangBuiltLinux/linux/issues/1808
+Co-developed-by: Conor Dooley <conor.dooley@microchip.com>
+Signed-off-by: Conor Dooley <conor.dooley@microchip.com>
+Signed-off-by: Nathan Chancellor <nathan@kernel.org>
+Acked-by: Conor Dooley <conor.dooley@microchip.com>
+Link: https://lore.kernel.org/r/20230313-riscv-zicsr-zifencei-fiasco-v1-1-dd1b7840a551@kernel.org
+Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
+Signed-off-by: Nathan Chancellor <nathan@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/riscv/Kconfig | 22 ++++++++++++++++++++++
+ arch/riscv/Makefile | 10 ++++++----
+ 2 files changed, 28 insertions(+), 4 deletions(-)
+
+--- a/arch/riscv/Kconfig
++++ b/arch/riscv/Kconfig
+@@ -331,6 +331,28 @@ config RISCV_BASE_PMU
+
+ endmenu
+
++config TOOLCHAIN_NEEDS_EXPLICIT_ZICSR_ZIFENCEI
++ def_bool y
++ # https://sourceware.org/git/?p=binutils-gdb.git;a=commit;h=aed44286efa8ae8717a77d94b51ac3614e2ca6dc
++ depends on AS_IS_GNU && AS_VERSION >= 23800
++ help
++ Newer binutils versions default to ISA spec version 20191213 which
++ moves some instructions from the I extension to the Zicsr and Zifencei
++ extensions.
++
++config TOOLCHAIN_NEEDS_OLD_ISA_SPEC
++ def_bool y
++ depends on TOOLCHAIN_NEEDS_EXPLICIT_ZICSR_ZIFENCEI
++ # https://github.com/llvm/llvm-project/commit/22e199e6afb1263c943c0c0d4498694e15bf8a16
++ depends on CC_IS_CLANG && CLANG_VERSION < 170000
++ help
++ Certain versions of clang do not support zicsr and zifencei via -march
++ but newer versions of binutils require it for the reasons noted in the
++ help text of CONFIG_TOOLCHAIN_NEEDS_EXPLICIT_ZICSR_ZIFENCEI. This
++ option causes an older ISA spec compatible with these older versions
++ of clang to be passed to GAS, which has the same result as passing zicsr
++ and zifencei to -march.
++
+ config FPU
+ bool "FPU support"
+ default y
+--- a/arch/riscv/Makefile
++++ b/arch/riscv/Makefile
+@@ -53,10 +53,12 @@ riscv-march-$(CONFIG_ARCH_RV64I) := rv64
+ riscv-march-$(CONFIG_FPU) := $(riscv-march-y)fd
+ riscv-march-$(CONFIG_RISCV_ISA_C) := $(riscv-march-y)c
+
+-# Newer binutils versions default to ISA spec version 20191213 which moves some
+-# instructions from the I extension to the Zicsr and Zifencei extensions.
+-toolchain-need-zicsr-zifencei := $(call cc-option-yn, -march=$(riscv-march-y)_zicsr_zifencei)
+-riscv-march-$(toolchain-need-zicsr-zifencei) := $(riscv-march-y)_zicsr_zifencei
++ifdef CONFIG_TOOLCHAIN_NEEDS_OLD_ISA_SPEC
++KBUILD_CFLAGS += -Wa,-misa-spec=2.2
++KBUILD_AFLAGS += -Wa,-misa-spec=2.2
++else
++riscv-march-$(CONFIG_TOOLCHAIN_NEEDS_EXPLICIT_ZICSR_ZIFENCEI) := $(riscv-march-y)_zicsr_zifencei
++endif
+
+ KBUILD_CFLAGS += -march=$(subst fd,,$(riscv-march-y))
+ KBUILD_AFLAGS += -march=$(riscv-march-y)
sched-fair-fix-imbalance-overflow.patch
x86-rtc-remove-__init-for-runtime-functions.patch
i2c-ocores-generate-stop-condition-after-timeout-in-.patch
+cgroup-cpuset-change-references-of-cpuset_mutex-to-cpuset_rwsem.patch
+cgroup-cpuset-skip-spread-flags-update-on-v2.patch
+cgroup-cpuset-make-cpuset_fork-handle-clone_into_cgroup-properly.patch
+cgroup-cpuset-add-cpuset_can_fork-and-cpuset_cancel_fork-methods.patch
+watchdog-sbsa_wdog-make-sure-the-timeout-programming-is-within-the-limits.patch
+coresight-etm4-fix-for-loop-drvdata-nr_addr_cmp-range-bug.patch
+kbuild-check-the-minimum-assembler-version-in-kconfig.patch
+kbuild-switch-to-f-variants-of-integrated-assembler-flag.patch
+kbuild-check-config_as_is_llvm-instead-of-llvm_ias.patch
+riscv-handle-zicsr-zifencei-issues-between-clang-and-binutils.patch
--- /dev/null
+From 000987a38b53c172f435142a4026dd71378ca464 Mon Sep 17 00:00:00 2001
+From: George Cherian <george.cherian@marvell.com>
+Date: Thu, 9 Feb 2023 02:11:17 +0000
+Subject: watchdog: sbsa_wdog: Make sure the timeout programming is within the limits
+
+From: George Cherian <george.cherian@marvell.com>
+
+commit 000987a38b53c172f435142a4026dd71378ca464 upstream.
+
+Make sure to honour the max_hw_heartbeat_ms while programming the timeout
+value to WOR. Clamp the timeout passed to sbsa_gwdt_set_timeout() to
+make sure the programmed value is within the permissible range.
+
+Fixes: abd3ac7902fb ("watchdog: sbsa: Support architecture version 1")
+
+Signed-off-by: George Cherian <george.cherian@marvell.com>
+Reviewed-by: Guenter Roeck <linux@roeck-us.net>
+Link: https://lore.kernel.org/r/20230209021117.1512097-1-george.cherian@marvell.com
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Wim Van Sebroeck <wim@linux-watchdog.org>
+Signed-off-by: Tyler Hicks (Microsoft) <code@tyhicks.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/watchdog/sbsa_gwdt.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/watchdog/sbsa_gwdt.c
++++ b/drivers/watchdog/sbsa_gwdt.c
+@@ -121,6 +121,7 @@ static int sbsa_gwdt_set_timeout(struct
+ struct sbsa_gwdt *gwdt = watchdog_get_drvdata(wdd);
+
+ wdd->timeout = timeout;
++ timeout = clamp_t(unsigned int, timeout, 1, wdd->max_hw_heartbeat_ms / 1000);
+
+ if (action)
+ writel(gwdt->clk * timeout,