From: Sam Ravnborg <sam@ravnborg.org>
To: Dawei Li <dawei.li@shingroup.cn>
Cc: davem@davemloft.net, andreas@gaisler.com,
sparclinux@vger.kernel.org, linux-kernel@vger.kernel.org,
yury.norov@gmail.com
Subject: Re: [PATCH 0/5] Remove onstack cpumask var usage
Date: Fri, 19 Apr 2024 22:33:29 +0200 [thread overview]
Message-ID: <20240419203329.GA590733@ravnborg.org> (raw)
In-Reply-To: <A60F94A9589C8589+ZiI4yj073cgmt5Qq@centos8>
Hi Dawei,
> About this case, it's kinda tricky for:
> - dr_cpu_data() returns void, so alloc_cpumask_var() is no go.
>
> - No idea of the calling context of dr_cpu_data(). IIUC,
> dr_cpu_data()
> ->dr_cpu_configure()
> ->kzalloc(resp_len, GFP_KERNEL)
> So I guess it's in process context?
> If consumption above is OK, a simple but _ugly_ solution could be:
>
> diff --git a/arch/sparc/kernel/ds.c b/arch/sparc/kernel/ds.c
> index ffdc15588ac2..c9e4ebdccf49 100644
> --- a/arch/sparc/kernel/ds.c
> +++ b/arch/sparc/kernel/ds.c
> @@ -634,7 +634,8 @@ static void dr_cpu_data(struct ds_info *dp, struct ds_cap_state *cp, void *buf,
> struct dr_cpu_tag *tag = (struct dr_cpu_tag *) (data + 1);
> u32 *cpu_list = (u32 *) (tag + 1);
> u64 req_num = tag->req_num;
> - cpumask_t mask;
> + static DEFINE_MUTEX(mask_lock);
> + static cpumask_t mask;
> unsigned int i;
> int err;
>
> @@ -651,6 +652,8 @@ static void dr_cpu_data(struct ds_info *dp, struct ds_cap_state *cp, void *buf,
>
> purge_dups(cpu_list, tag->num_records);
>
> + mutex_lock(&mask_lock);
> +
> cpumask_clear(&mask);
> for (i = 0; i < tag->num_records; i++) {
> if (cpu_list[i] == CPU_SENTINEL)
> @@ -665,6 +668,8 @@ static void dr_cpu_data(struct ds_info *dp, struct ds_cap_state *cp, void *buf,
> else
> err = dr_cpu_unconfigure(dp, cp, req_num, &mask);
>
> + mutex_unlock(&mask_lock);
> +
> if (err)
> dr_cpu_send_error(dp, cp, data);
> }
>
> How does it sound to you?
This introduces too much complexity to solve a potential stack issue.
If an improvement is required, then we need a simpler solution.
>
> > kernel/leon_kernel.c: cpumask_t mask;
>
> It's in irqchip::irq_set_affinity(), which is in atomic context(raw spinlock(s) held),
> so dynamic allocation is not a good idea.
>
> My proposal(*untested*) is somewhat complicated for it introduces a new helper.
>
> diff --git a/arch/sparc/kernel/leon_kernel.c b/arch/sparc/kernel/leon_kernel.c
> index 4c61da491fee..6eced7acb8bc 100644
> --- a/arch/sparc/kernel/leon_kernel.c
> +++ b/arch/sparc/kernel/leon_kernel.c
> @@ -104,15 +104,25 @@ unsigned long leon_get_irqmask(unsigned int irq)
> }
>
> #ifdef CONFIG_SMP
> +
> +static bool cpumask_include(const struct cpumask *srcp1, const struct cpumask *srcp2)
> +{
> + unsigned int cpu;
> +
> + for_each_cpu(cpu, srcp2) {
> + if (!cpumask_test_cpu(cpu, srcp1))
> + return false;
> + }
> +
> + return true;
> +}
> +
> static int irq_choose_cpu(const struct cpumask *affinity)
> {
> - cpumask_t mask;
> + unsigned int cpu = cpumask_first_and(affinity, cpu_online_mask);
>
> - cpumask_and(&mask, cpu_online_mask, affinity);
> - if (cpumask_equal(&mask, cpu_online_mask) || cpumask_empty(&mask))
> - return boot_cpu_id;
> - else
> - return cpumask_first(&mask);
> + return cpumask_include(affinity, cpu_online_mask) || cpu >= nr_cpu_ids ?
> + boot_cpu_id : cpu;
> }
I think something like the following should do the trick.
if (cpumask_equal(affinity, cpu_online_mask))
return boot_cpu_id;
cpuid = cpumask_first_and(affinity, cpu_online_mask);
if (cpuid < nr_cpu_ids)
return cpuid;
else
return boot_cpu_id;
If the passed affinity equals the online cpu's, then use the boot cpu.
Else, use the first online cpu in the affinity mask.
If none found use the boot cpu.
> #else
> #define irq_choose_cpu(affinity) boot_cpu_id
>
> Is it OK?
>
> [cc Yury for bitmap API]
>
> > kernel/leon_smp.c:static void leon_cross_call(void *func, cpumask_t mask, unsigned long arg1,
> > kernel/sun4d_smp.c:static void sun4d_cross_call(void *func, cpumask_t mask, unsigned long arg1,
Looks simple, just pass a pointer and not by value.
>
> Actually I am awared of existence of (at least some of) them, but so far I
> have not found a _proper_ way of dealing with them(especially for case of
> ds.c).
>
> Please lemme dig into it.
Looks forward to next iteration.
Sam
next prev parent reply other threads:[~2024-04-19 20:34 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-04-18 10:49 [PATCH 0/5] Remove onstack cpumask var usage Dawei Li
2024-04-18 10:49 ` [PATCH 1/5] sparc/srmmu: Remove on-stack cpumask var Dawei Li
2024-04-18 10:49 ` [PATCH 2/5] sparc/irq: " Dawei Li
2024-04-19 0:19 ` kernel test robot
2024-04-18 10:49 ` [PATCH 3/5] sparc/of: " Dawei Li
2024-04-18 10:49 ` [PATCH 4/5] sparc/pci_msi: " Dawei Li
2024-04-18 10:49 ` [PATCH 5/5] sparc: " Dawei Li
2024-04-19 5:13 ` [PATCH 0/5] Remove onstack cpumask var usage Sam Ravnborg
2024-04-19 9:26 ` Dawei Li
2024-04-19 20:33 ` Sam Ravnborg [this message]
2024-04-19 22:13 ` Yury Norov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20240419203329.GA590733@ravnborg.org \
--to=sam@ravnborg.org \
--cc=andreas@gaisler.com \
--cc=davem@davemloft.net \
--cc=dawei.li@shingroup.cn \
--cc=linux-kernel@vger.kernel.org \
--cc=sparclinux@vger.kernel.org \
--cc=yury.norov@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.