Re: [PATCH v2 00/14] Introducing TIF_NOTIFY_IPI flag
On 2024-06-19 at 00:03:30 +0530, K Prateek Nayak wrote: > Hello Chenyu, > > On 6/18/2024 1:19 PM, Chen Yu wrote: > > [..snip..] > > > > > > > > > > > > > Vincent [5] pointed out a case where the idle load kick will fail > > > > > > > to > > > > > > > run on an idle CPU since the IPI handler launching the ILB will > > > > > > > check > > > > > > > for need_resched(). In such cases, the idle CPU relies on > > > > > > > newidle_balance() to pull tasks towards itself. > > > > > > > > > > > > Is this the need_resched() in _nohz_idle_balance() ? Should we > > > > > > change > > > > > > this to 'need_resched() && (rq->nr_running || rq->ttwu_pending)' or > > > > > > something long those lines? > > > > > > > > > > It's not only this but also in do_idle() as well which exits the loop > > > > > to look for tasks to schedule > > > > > > > > > > > > > > > > > I mean, it's fairly trivial to figure out if there really is going > > > > > > to be > > > > > > work there. > > > > > > > > > > > > > Using an alternate flag instead of NEED_RESCHED to indicate a > > > > > > > pending > > > > > > > IPI was suggested as the correct approach to solve this problem > > > > > > > on the > > > > > > > same thread. > > > > > > > > > > > > So adding per-arch changes for this seems like something we > > > > > > shouldn't > > > > > > unless there really is no other sane options. > > > > > > > > > > > > That is, I really think we should start with something like the > > > > > > below > > > > > > and then fix any fallout from that. > > > > > > > > > > The main problem is that need_resched becomes somewhat meaningless > > > > > because it doesn't only mean "I need to resched a task" and we have > > > > > to add more tests around even for those not using polling > > > > > > > > > > > > > > > > > diff --git a/kernel/sched/core.c b/kernel/sched/core.c > > > > > > index 0935f9d4bb7b..cfa45338ae97 100644 > > > > > > --- a/kernel/sched/core.c > > > > > > +++ b/kernel/sched/core.c > > > > > > @@ -5799,7 +5800,7 @@ static inline struct task_struct * > > > > > >__pick_next_task(struct rq *rq, struct task_struct *prev, struct > > > > > > rq_flags *rf) > > > > > >{ > > > > > > const struct sched_class *class; > > > > > > - struct task_struct *p; > > > > > > + struct task_struct *p = NULL; > > > > > > > > > > > > /* > > > > > >* Optimization: we know that if all tasks are in the > > > > > > fair class we can > > > > > > @@ -5810,9 +5811,11 @@ __pick_next_task(struct rq *rq, struct > > > > > > task_struct *prev, struct rq_flags *rf) > > > > > > if (likely(!sched_class_above(prev->sched_class, > > > > > > &fair_sched_class) && > > > > > > rq->nr_running == rq->cfs.h_nr_running)) { > > > > > > > > > > > > - p = pick_next_task_fair(rq, prev, rf); > > > > > > - if (unlikely(p == RETRY_TASK)) > > > > > > - goto restart; > > > > > > + if (rq->nr_running) { > > > > > > > > > > How do you make the diff between a spurious need_resched() because of > > > > > polling and a cpu becoming idle ? isn't rq->nr_running null in both > > > > > cases ? > > > > > In the later case, we need to call sched_balance_newidle() but not in > > > > > the former > > > > > > > > > > > > > Not sure if I understand correctly, if the goal of > > > > smp_call_function_single() is to > > > > kick the idle CPU and do not force it to launch the > > > > schedule()->sched_balance_newidle(), > > > > can we set the _TIF_POLLING_NRFLAG rather than _TIF_NEED_RESCHED in > > > > set_nr_if_polling()? > > > > I think writing any value to the monitor address would wakeup the idle > > > > CPU. And _TIF_POLLING_NRFLAG > > > > will be cleared once that idle CPU exit the idle loop, so we don't > > > > introduce arch-wide flag. > > > Although this might work for MWAIT, there is no way for the generic idle > > > path to know if there is a pending interrupt within a TIF_POLLING_NRFLAG > > > section. do_idle() sets TIF_POLLING_NRFLAG and relies on a bunch of > > > need_resched() checks along the way to bail early until finally doing a > > > current_clr_polling_and_test() before handing off to the cpuidle driver > > > in call_cpuidle(). I believe this section will necessarily need the sender > > > to indicate a pending interrupt via TIF_NEED_RESCHED flag to enable the > > > early bail out before going into the cpuidle driver since this case cannot > > > be considered the same as a break from MWAIT. > > > > > > > I see, this is a good point. So you mean with only TIF_POLLING_NRFLAG there > > is > > possibility that the 'ipi kick CPU out of idle' is lost after the CPU enters > > do_idle() and before finally entering the idle state. While setting > > _TIF_NEED_RESCHED > > could help the do_idle() loop to detect pending request easier. > > Yup, that is correct. > > > BTW, before the > > commit b2a02fc43a1f ("smp: Optimize send_call
Re: [PATCH] tools/perf: Handle perftool-testsuite_probe testcases fail when kernel debuginfo is not present
On 18/06/2024 11:44, James Clark wrote: > > > On 17/06/2024 17:47, Athira Rajeev wrote: >> >> >>> On 17 Jun 2024, at 8:30 PM, James Clark wrote: >>> >>> >>> >>> On 17/06/2024 13:21, Athira Rajeev wrote: Running "perftool-testsuite_probe" fails as below: ./perf test -v "perftool-testsuite_probe" 83: perftool-testsuite_probe : FAILED There are three fails: 1. Regexp not found: "\s*probe:inode_permission(?:_\d+)?\s+\(on inode_permission(?:[:\+][0-9A-Fa-f]+)?@.+\)" -- [ FAIL ] -- perf_probe :: test_adding_kernel :: listing added probe :: perf probe -l (output regexp parsing) >>> >>> On a machine where NO_DEBUGINFO gets set, this one skips for me. But on >>> a machine where there _is_ debug info this test still fails. >>> >>> But in both cases the probe looks like it was added successfully. So I'm >>> wondering if this one does need to be skipped, or it's just always >>> failing? Do you have this test passing anywhere where there is debug info? >>> >>> The list command looks like it successfully lists the probe for me in >>> both cases, it just doesn't have an address on the end: >>> >>> perf list 'probe:*' >>> >>> probe:inode_permission (on inode_permission) >>> >>> Does the missing address mean anything or is it just not handled >>> properly by the test? >>> >>> Ironically the machine that _does_ pass the debug info test also prints >>> this, but it looks like it still adds and lists the probe correctly: >>> >>> perf probe -l probe:* >>> >>> Failed to find debug information for address 0x80008047ac30 >>>probe:inode_permission (on inode_permission) >> >> Hi James, >> >> Thanks for checking this patch. >> >> In environment where kernel is compiled with debuginfo: >> >> 1) Add probe point >> >> # ./perf probe --add inode_permission >> Added new event: >> probe:inode_permission (on inode_permission) >> >> You can now use it in all perf tools, such as: >> >> perf record -e probe:inode_permission -aR sleep 1 >> >> >> 2) Check using perf probe -l >> >> # ./perf probe -l >> probe:inode_permission (on inode_permission:2@fs/namei.c) >> >> With debuginfo, the result has additional info. >> The test looks for matching pattern >> "\s*probe:inode_permission(?:_\d+)?\s+\(on >> inode_permission(?:[:\+][0-9A-Fa-f]+)?@.+\)” in result >> where it is expecting "inode_permission:2@fs/namei.c” . The “@fs/namei.c” >> info needs debuginfo here. >> > > Hi Athira, > > Maybe there is a real bug and this patch is ok to go in and we should leave > it as failing. Probe -L shows there is debug info available for > inode_permission: > >$ ./perf probe -L inode_permission > > > 0 int inode_permission(struct mnt_idmap *idmap, > struct inode *inode, int mask) > ... more source code ... > > But probe -l has an error which could be related to the following > line not showing the filename details: > > $ ./perf probe -l > > Failed to find debug information for address 0x80008047ac30 > probe:inode_permission (on inode_permission) > > I'm running a clang kernel and sometimes I see issues with debug > info or toolchain stuff, that could be the reason. > >> The function I am using in patch to check for debuginfo >> (skip_if_no_debuginfo) is from "tests/shell/lib/probe_vfs_getname.sh" >> >> skip_if_no_debuginfo() { >> add_probe_vfs_getname -v 2>&1 | grep -E -q "^(Failed to find the >> path for the kernel|Debuginfo-analysis is not supported)|(file has no debug >> information)" && return 2 >> return 1 >> } >> >> So the debuginfo test passes in your case since the log has "Failed to find >> debug information” which is not present in above grep string. >> > > It passes because there is debug info for getname_flags() which is what the > debug info check looks for. After some greps and seds it ultimately does this > which succeeds: > > $ perf probe "vfs_getname=getname_flags:72 pathname=result->name:string" > > Added new event: > probe:vfs_getname(on getname_flags:72 with > pathname=result->name:string) > > "Failed to find debug information for address" is only ever printed > with "perf probe -l" when there are probes added. The stderr > of that command is never piped into any grep anyway, which is why I > see it on the test output. > > So "probe -L" is working but "probe -l" isn't. Ultimately it looks like a real > issue and we should leave the failure in. > To avoid confusion, by leave it in I mean this debuginfo patch is ok and the failure I'm seeing is caused by something else. Reviewed-by: James Clark >> James, >> >> Only “perf probe -l” subtest fails with debuginfo enabled or other two >> subtests as well? Can you also share result on how other two subtests >> behaves ? >> >> 1. Fail 2 : >>perf probe -nf --max-probes=512 -a 'vfs_* $params’ >> >> >> 2. Fail 3 : >> perf probe 'vfs_read >> somenonexistingrandomstuffwhichisalsoprettylongorevenlonge
[PATCH 07/10] soc: fsl: cpm1: qmc: Introduce functions to get a channel from a phandle list
qmc_chan_get_byphandle() and the resource managed version retrieve a channel from a simple phandle. Extend the API and introduce qmc_chan_get_byphandles_index() and the resource managed version in order to retrieve a channel from a phandle list using the provided index to identify the phandle in the list. Also update qmc_chan_get_byphandle() and the resource managed version to use qmc_chan_get_byphandles_index() and so avoid code duplication. Signed-off-by: Herve Codina --- drivers/soc/fsl/qe/qmc.c | 19 +++ include/soc/fsl/qe/qmc.h | 25 ++--- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c index f498db9abe35..e23d60018400 100644 --- a/drivers/soc/fsl/qe/qmc.c +++ b/drivers/soc/fsl/qe/qmc.c @@ -1777,13 +1777,15 @@ static struct qmc_chan *qmc_chan_get_from_qmc(struct device_node *qmc_np, unsign return qmc_chan; } -struct qmc_chan *qmc_chan_get_byphandle(struct device_node *np, const char *phandle_name) +struct qmc_chan *qmc_chan_get_byphandles_index(struct device_node *np, + const char *phandles_name, + int index) { struct of_phandle_args out_args; struct qmc_chan *qmc_chan; int ret; - ret = of_parse_phandle_with_fixed_args(np, phandle_name, 1, 0, + ret = of_parse_phandle_with_fixed_args(np, phandles_name, 1, index, &out_args); if (ret < 0) return ERR_PTR(ret); @@ -1797,7 +1799,7 @@ struct qmc_chan *qmc_chan_get_byphandle(struct device_node *np, const char *phan of_node_put(out_args.np); return qmc_chan; } -EXPORT_SYMBOL(qmc_chan_get_byphandle); +EXPORT_SYMBOL(qmc_chan_get_byphandles_index); struct qmc_chan *qmc_chan_get_bychild(struct device_node *np) { @@ -1827,9 +1829,10 @@ static void devm_qmc_chan_release(struct device *dev, void *res) qmc_chan_put(*qmc_chan); } -struct qmc_chan *devm_qmc_chan_get_byphandle(struct device *dev, -struct device_node *np, -const char *phandle_name) +struct qmc_chan *devm_qmc_chan_get_byphandles_index(struct device *dev, + struct device_node *np, + const char *phandles_name, + int index) { struct qmc_chan *qmc_chan; struct qmc_chan **dr; @@ -1838,7 +1841,7 @@ struct qmc_chan *devm_qmc_chan_get_byphandle(struct device *dev, if (!dr) return ERR_PTR(-ENOMEM); - qmc_chan = qmc_chan_get_byphandle(np, phandle_name); + qmc_chan = qmc_chan_get_byphandles_index(np, phandles_name, index); if (!IS_ERR(qmc_chan)) { *dr = qmc_chan; devres_add(dev, dr); @@ -1848,7 +1851,7 @@ struct qmc_chan *devm_qmc_chan_get_byphandle(struct device *dev, return qmc_chan; } -EXPORT_SYMBOL(devm_qmc_chan_get_byphandle); +EXPORT_SYMBOL(devm_qmc_chan_get_byphandles_index); struct qmc_chan *devm_qmc_chan_get_bychild(struct device *dev, struct device_node *np) diff --git a/include/soc/fsl/qe/qmc.h b/include/soc/fsl/qe/qmc.h index 2a333fc1ea81..0fa7205145ce 100644 --- a/include/soc/fsl/qe/qmc.h +++ b/include/soc/fsl/qe/qmc.h @@ -16,11 +16,30 @@ struct device_node; struct device; struct qmc_chan; -struct qmc_chan *qmc_chan_get_byphandle(struct device_node *np, const char *phandle_name); +struct qmc_chan *qmc_chan_get_byphandles_index(struct device_node *np, + const char *phandles_name, + int index); +struct qmc_chan *devm_qmc_chan_get_byphandles_index(struct device *dev, + struct device_node *np, + const char *phandles_name, + int index); + +static inline struct qmc_chan *qmc_chan_get_byphandle(struct device_node *np, + const char *phandle_name) +{ + return qmc_chan_get_byphandles_index(np, phandle_name, 0); +} + +static inline struct qmc_chan *devm_qmc_chan_get_byphandle(struct device *dev, + struct device_node *np, + const char *phandle_name) +{ + return devm_qmc_chan_get_byphandles_index(dev, np, phandle_name, 0); +} + struct qmc_chan *qmc_chan_get_bychild(struct device_node *np); void qmc_chan_put(struct qmc_chan *chan); -struct qmc_chan *devm_qmc_chan_get_byphandle(struct device *dev, struct device_node *np, -
[PATCH 06/10] ASoC: fsl: fsl_qmc_audio: Introduce qmc_dai_constraints_interleaved()
Constraints are set by qmc_dai_startup(). These constraints are specific to the interleaved mode. With the future introduction of support for non-interleaved mode, a new set of constraints will be set. To make the code clear and keep qmc_dai_startup() simple, extract the current interleaved mode constraints settings to a specific function. Signed-off-by: Herve Codina --- sound/soc/fsl/fsl_qmc_audio.c | 37 +-- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/sound/soc/fsl/fsl_qmc_audio.c b/sound/soc/fsl/fsl_qmc_audio.c index 36145f1ddbf1..f70c6c8eec4a 100644 --- a/sound/soc/fsl/fsl_qmc_audio.c +++ b/sound/soc/fsl/fsl_qmc_audio.c @@ -436,24 +436,14 @@ static int qmc_dai_hw_rule_capture_format_by_channels(struct snd_pcm_hw_params * return qmc_dai_hw_rule_format_by_channels(qmc_dai, params, qmc_dai->nb_rx_ts); } -static int qmc_dai_startup(struct snd_pcm_substream *substream, - struct snd_soc_dai *dai) +static int qmc_dai_constraints_interleaved(struct snd_pcm_substream *substream, + struct qmc_dai *qmc_dai) { - struct qmc_dai_prtd *prtd = substream->runtime->private_data; snd_pcm_hw_rule_func_t hw_rule_channels_by_format; snd_pcm_hw_rule_func_t hw_rule_format_by_channels; - struct qmc_dai *qmc_dai; unsigned int frame_bits; int ret; - qmc_dai = qmc_dai_get_data(dai); - if (!qmc_dai) { - dev_err(dai->dev, "Invalid dai\n"); - return -EINVAL; - } - - prtd->qmc_dai = qmc_dai; - if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { hw_rule_channels_by_format = qmc_dai_hw_rule_capture_channels_by_format; hw_rule_format_by_channels = qmc_dai_hw_rule_capture_format_by_channels; @@ -468,7 +458,7 @@ static int qmc_dai_startup(struct snd_pcm_substream *substream, hw_rule_channels_by_format, qmc_dai, SNDRV_PCM_HW_PARAM_FORMAT, -1); if (ret) { - dev_err(dai->dev, "Failed to add channels rule (%d)\n", ret); + dev_err(qmc_dai->dev, "Failed to add channels rule (%d)\n", ret); return ret; } @@ -476,7 +466,7 @@ static int qmc_dai_startup(struct snd_pcm_substream *substream, hw_rule_format_by_channels, qmc_dai, SNDRV_PCM_HW_PARAM_CHANNELS, -1); if (ret) { - dev_err(dai->dev, "Failed to add format rule (%d)\n", ret); + dev_err(qmc_dai->dev, "Failed to add format rule (%d)\n", ret); return ret; } @@ -484,13 +474,30 @@ static int qmc_dai_startup(struct snd_pcm_substream *substream, SNDRV_PCM_HW_PARAM_FRAME_BITS, frame_bits); if (ret < 0) { - dev_err(dai->dev, "Failed to add frame_bits constraint (%d)\n", ret); + dev_err(qmc_dai->dev, "Failed to add frame_bits constraint (%d)\n", ret); return ret; } return 0; } +static int qmc_dai_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct qmc_dai_prtd *prtd = substream->runtime->private_data; + struct qmc_dai *qmc_dai; + + qmc_dai = qmc_dai_get_data(dai); + if (!qmc_dai) { + dev_err(dai->dev, "Invalid dai\n"); + return -EINVAL; + } + + prtd->qmc_dai = qmc_dai; + + return qmc_dai_constraints_interleaved(substream, qmc_dai); +} + static int qmc_dai_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) -- 2.45.0
[PATCH 08/10] soc: fsl: cpm1: qmc: Introduce qmc_chan_count_phandles()
No function in the QMC API is available to get the number of phandles present in a phandle list. Fill this lack introducing qmc_chan_count_phandles(). Signed-off-by: Herve Codina --- drivers/soc/fsl/qe/qmc.c | 13 + include/soc/fsl/qe/qmc.h | 2 ++ 2 files changed, 15 insertions(+) diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c index e23d60018400..76bb496305a0 100644 --- a/drivers/soc/fsl/qe/qmc.c +++ b/drivers/soc/fsl/qe/qmc.c @@ -1777,6 +1777,19 @@ static struct qmc_chan *qmc_chan_get_from_qmc(struct device_node *qmc_np, unsign return qmc_chan; } +int qmc_chan_count_phandles(struct device_node *np, const char *phandles_name) +{ + int count; + + /* phandles are fixed args phandles with one arg */ + count = of_count_phandle_with_args(np, phandles_name, NULL); + if (count < 0) + return count; + + return count / 2; +} +EXPORT_SYMBOL(qmc_chan_count_phandles); + struct qmc_chan *qmc_chan_get_byphandles_index(struct device_node *np, const char *phandles_name, int index) diff --git a/include/soc/fsl/qe/qmc.h b/include/soc/fsl/qe/qmc.h index 0fa7205145ce..294e42ea8d4c 100644 --- a/include/soc/fsl/qe/qmc.h +++ b/include/soc/fsl/qe/qmc.h @@ -16,6 +16,8 @@ struct device_node; struct device; struct qmc_chan; +int qmc_chan_count_phandles(struct device_node *np, const char *phandles_name); + struct qmc_chan *qmc_chan_get_byphandles_index(struct device_node *np, const char *phandles_name, int index); -- 2.45.0
[PATCH 02/10] ASoC: fsl: fsl_qmc_audio: Fix issues detected by checkpatch
./scripts/checkpatch.pl --strict --codespell detected several issues when running on the fsl_qmc_audio.c file: - CHECK: spaces preferred around that '*' (ctx:VxV) - CHECK: Alignment should match open parenthesis - CHECK: Comparison to NULL could be written "!prtd" - CHECK: spaces preferred around that '/' (ctx:VxV) - CHECK: Lines should not end with a '(' - CHECK: Please don't use multiple blank lines Some of them are present several times. Fix all of these issues without any functional changes. Signed-off-by: Herve Codina --- sound/soc/fsl/fsl_qmc_audio.c | 65 +-- 1 file changed, 31 insertions(+), 34 deletions(-) diff --git a/sound/soc/fsl/fsl_qmc_audio.c b/sound/soc/fsl/fsl_qmc_audio.c index dd90ef16fa97..917a32389f3d 100644 --- a/sound/soc/fsl/fsl_qmc_audio.c +++ b/sound/soc/fsl/fsl_qmc_audio.c @@ -54,7 +54,7 @@ static int qmc_audio_pcm_construct(struct snd_soc_component *component, return ret; snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, card->dev, - 64*1024, 64*1024); + 64 * 1024, 64 * 1024); return 0; } @@ -89,8 +89,8 @@ static void qmc_audio_pcm_write_complete(void *context) prtd->period_ptr_submitted = prtd->dma_buffer_start; ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan, - prtd->period_ptr_submitted, prtd->period_size, - qmc_audio_pcm_write_complete, prtd); + prtd->period_ptr_submitted, prtd->period_size, + qmc_audio_pcm_write_complete, prtd); if (ret) { dev_err(prtd->qmc_dai->dev, "write_submit failed %d\n", ret); @@ -118,8 +118,8 @@ static void qmc_audio_pcm_read_complete(void *context, size_t length, unsigned i prtd->period_ptr_submitted = prtd->dma_buffer_start; ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan, - prtd->period_ptr_submitted, prtd->period_size, - qmc_audio_pcm_read_complete, prtd); + prtd->period_ptr_submitted, prtd->period_size, + qmc_audio_pcm_read_complete, prtd); if (ret) { dev_err(prtd->qmc_dai->dev, "read_submit failed %d\n", ret); @@ -144,8 +144,8 @@ static int qmc_audio_pcm_trigger(struct snd_soc_component *component, if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { /* Submit first chunk ... */ ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan, - prtd->period_ptr_submitted, prtd->period_size, - qmc_audio_pcm_write_complete, prtd); + prtd->period_ptr_submitted, prtd->period_size, + qmc_audio_pcm_write_complete, prtd); if (ret) { dev_err(component->dev, "write_submit failed %d\n", ret); @@ -159,8 +159,8 @@ static int qmc_audio_pcm_trigger(struct snd_soc_component *component, /* ... and send it */ ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan, - prtd->period_ptr_submitted, prtd->period_size, - qmc_audio_pcm_write_complete, prtd); + prtd->period_ptr_submitted, prtd->period_size, + qmc_audio_pcm_write_complete, prtd); if (ret) { dev_err(component->dev, "write_submit failed %d\n", ret); @@ -169,8 +169,8 @@ static int qmc_audio_pcm_trigger(struct snd_soc_component *component, } else { /* Submit first chunk ... */ ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan, - prtd->period_ptr_submitted, prtd->period_size, - qmc_audio_pcm_read_complete, prtd); + prtd->period_ptr_submitted, prtd->period_size, + qmc_audio_pcm_read_complete, prtd); if (ret) { dev_err(component->dev, "read_submit failed %d\n", ret); @@ -184,8 +184,8 @@ static int qmc_audio_pcm_trigger(struct snd_soc_component *component, /* ... and send it */ ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan, - prtd->period_ptr_submitted, prtd->period_size, -
[PATCH 00/10] Add support for non-interleaved mode in qmc_audio
The qmc_audio driver supports only audio in interleaved mode. Non-interleaved mode can be easily supported using several QMC channel per DAI. In that case, data related to ch0 are sent to (received from) the first QMC channel, data related to ch1 use the next QMC channel and so on up to the last channel. In terms of constraints and settings, the interleaved and non-interleaved modes are slightly different. In interleaved mode: - The sample size should fit in the number of time-slots available for the QMC channel. - The number of audio channels should fit in the number of time-slots (taking into account the sample size) available for the QMC channel. In non-interleaved mode: - The number of audio channels is the number of available QMC channels. - Each QMC channel should have the same number of time-slots. - The sample size equals the number of time-slots of one QMC channel. This series add support for the non-interleaved mode in the qmc_audio driver and is composed of the following parts: - Patches 1 and 2: Fix some issues in the qmc_audio - Patches 3 to 6: Prepare qmc_audio for the non-interleaved mode - Patches 7 and 8: Extend the QMC driver API - Patches 9 and 10: The support for non-interleaved mode itself Best regards, Hervé Herve Codina (10): ASoC: fsl: fsl_qmc_audio: Check devm_kasprintf() returned value ASoC: fsl: fsl_qmc_audio: Fix issues detected by checkpatch ASoC: fsl: fsl_qmc_audio: Split channel buffer and PCM pointer handling ASoC: fsl: fsl_qmc_audio: Identify the QMC channel involved in completion routines ASoC: fsl: fsl_qmc_audio: Introduce qmc_audio_pcm_{read,write}_submit() ASoC: fsl: fsl_qmc_audio: Introduce qmc_dai_constraints_interleaved() soc: fsl: cpm1: qmc: Introduce functions to get a channel from a phandle list soc: fsl: cpm1: qmc: Introduce qmc_chan_count_phandles() dt-bindings: sound: fsl,qmc-audio: Add support for multiple QMC channels per DAI ASoC: fsl: fsl_qmc_audio: Add support for non-interleaved mode. .../bindings/sound/fsl,qmc-audio.yaml | 41 +- drivers/soc/fsl/qe/qmc.c | 32 +- include/soc/fsl/qe/qmc.h | 27 +- sound/soc/fsl/fsl_qmc_audio.c | 590 +- 4 files changed, 505 insertions(+), 185 deletions(-) -- 2.45.0
[PATCH 10/10] ASoC: fsl: fsl_qmc_audio: Add support for non-interleaved mode.
The current fsl_qmc_audio works in interleaved mode. The audio samples are interleaved and all data are sent to (received from) one QMC channel. Using several QMC channels, non interleaved mode can be easily supported. In that case, data related to ch0 are sent to (received from) the first QMC channel, data related to ch1 use the next QMC channel and so on up to the last channel. In terms of constraints and settings, the two modes are slightly different: - Interleaved mode: - The sample size should fit in the number of time-slots available for the QMC channel. - The number of audio channels should fit in the number of time-slots (taking into account the sample size) available for the QMC channel. - Non-interleaved mode: - The number of audio channels is the number of available QMC channels. - Each QMC channel should have the same number of time-slots. - The sample size equals the number of time-slots of one QMC channel. Add support for the non-interleaved mode allowing multiple QMC channel per DAI. The DAI switches in non-interleaved mode when more that one QMC channel is available. Signed-off-by: Herve Codina --- sound/soc/fsl/fsl_qmc_audio.c | 371 +++--- 1 file changed, 296 insertions(+), 75 deletions(-) diff --git a/sound/soc/fsl/fsl_qmc_audio.c b/sound/soc/fsl/fsl_qmc_audio.c index f70c6c8eec4a..1560731c8372 100644 --- a/sound/soc/fsl/fsl_qmc_audio.c +++ b/sound/soc/fsl/fsl_qmc_audio.c @@ -29,7 +29,11 @@ struct qmc_dai { struct device *dev; unsigned int nb_tx_ts; unsigned int nb_rx_ts; - struct qmc_dai_chan chan; + + unsigned int nb_chans_avail; + unsigned int nb_chans_used_tx; + unsigned int nb_chans_used_rx; + struct qmc_dai_chan *chans; }; struct qmc_audio { @@ -50,7 +54,10 @@ struct qmc_dai_prtd { dma_addr_t ch_dma_addr_current; dma_addr_t ch_dma_addr_end; size_t ch_dma_size; + size_t ch_dma_offset; + unsigned int channels; + DECLARE_BITMAP(chans_pending, 64); struct snd_pcm_substream *substream; }; @@ -69,6 +76,17 @@ static int qmc_audio_pcm_construct(struct snd_soc_component *component, return 0; } +static bool qmc_audio_access_is_interleaved(snd_pcm_access_t access) +{ + switch (access) { + case SNDRV_PCM_ACCESS_MMAP_INTERLEAVED: + case SNDRV_PCM_ACCESS_RW_INTERLEAVED: + return true; + default: + return false; + } +}; + static int qmc_audio_pcm_hw_params(struct snd_soc_component *component, struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) @@ -76,6 +94,14 @@ static int qmc_audio_pcm_hw_params(struct snd_soc_component *component, struct snd_pcm_runtime *runtime = substream->runtime; struct qmc_dai_prtd *prtd = substream->runtime->private_data; + /* +* In interleaved mode, the driver uses one QMC channel for all audio +* channels whereas in non-interleaved mode, it uses one QMC channel per +* audio channel. +*/ + prtd->channels = qmc_audio_access_is_interleaved(params_access(params)) ? + 1 : params_channels(params); + prtd->substream = substream; prtd->buffer_ended = 0; @@ -83,9 +109,10 @@ static int qmc_audio_pcm_hw_params(struct snd_soc_component *component, prtd->period_size = params_period_size(params); prtd->ch_dma_addr_start = runtime->dma_addr; - prtd->ch_dma_addr_end = runtime->dma_addr + params_buffer_bytes(params); + prtd->ch_dma_offset = params_buffer_bytes(params) / prtd->channels; + prtd->ch_dma_addr_end = runtime->dma_addr + prtd->ch_dma_offset; prtd->ch_dma_addr_current = prtd->ch_dma_addr_start; - prtd->ch_dma_size = params_period_bytes(params); + prtd->ch_dma_size = params_period_bytes(params) / prtd->channels; return 0; } @@ -94,16 +121,23 @@ static void qmc_audio_pcm_write_complete(void *context); static int qmc_audio_pcm_write_submit(struct qmc_dai_prtd *prtd) { + unsigned int i; int ret; - ret = qmc_chan_write_submit(prtd->qmc_dai->chan.qmc_chan, - prtd->ch_dma_addr_current, prtd->ch_dma_size, - qmc_audio_pcm_write_complete, - &prtd->qmc_dai->chan); - if (ret) { - dev_err(prtd->qmc_dai->dev, "write_submit failed %d\n", - ret); - return ret; + for (i = 0; i < prtd->channels; i++) { + bitmap_set(prtd->chans_pending, i, 1); + + ret = qmc_chan_write_submit(prtd->qmc_dai->chans[i].qmc_chan, + prtd->ch_dma_addr_current + i * prtd->ch_dma_offset, + prtd->
[PATCH 01/10] ASoC: fsl: fsl_qmc_audio: Check devm_kasprintf() returned value
devm_kasprintf() can return a NULL pointer on failure but this returned value is not checked. Fix this lack and check the returned value. Fixes: 075c7125b11c ("ASoC: fsl: Add support for QMC audio") Cc: sta...@vger.kernel.org Signed-off-by: Herve Codina --- sound/soc/fsl/fsl_qmc_audio.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/fsl/fsl_qmc_audio.c b/sound/soc/fsl/fsl_qmc_audio.c index bfaaa451735b..dd90ef16fa97 100644 --- a/sound/soc/fsl/fsl_qmc_audio.c +++ b/sound/soc/fsl/fsl_qmc_audio.c @@ -604,6 +604,8 @@ static int qmc_audio_dai_parse(struct qmc_audio *qmc_audio, struct device_node * qmc_dai->name = devm_kasprintf(qmc_audio->dev, GFP_KERNEL, "%s.%d", np->parent->name, qmc_dai->id); + if (!qmc_dai->name) + return -ENOMEM; qmc_dai->qmc_chan = devm_qmc_chan_get_byphandle(qmc_audio->dev, np, "fsl,qmc-chan"); -- 2.45.0
[PATCH 04/10] ASoC: fsl: fsl_qmc_audio: Identify the QMC channel involved in completion routines
The current QMC audio driver uses only one QMC channel per DAI. The context used by QMC channel transfer (read and write) completion routines does not contains any QMC channel and the only one available per DAI is used to schedule the next transfer. This works pretty well with only one QMC channel per DAI. The future support for non-inlerleave mode will use several QMC channel per DAI. In that case, QMC channel transfer completion routines need to identify the QMC channel related to the completion. In order to fill this lack, even if identifying the current QMC channel among several QMC channels is not needed for the current code, add one indirection level and introduce the qmc_dai_chan data structrure. This structure contains the QMC channel involved in the completion and refererences to the runtime context (capture and playback) used by the DAI. Signed-off-by: Herve Codina --- sound/soc/fsl/fsl_qmc_audio.c | 72 +++ 1 file changed, 47 insertions(+), 25 deletions(-) diff --git a/sound/soc/fsl/fsl_qmc_audio.c b/sound/soc/fsl/fsl_qmc_audio.c index e8281e548746..b07770257bad 100644 --- a/sound/soc/fsl/fsl_qmc_audio.c +++ b/sound/soc/fsl/fsl_qmc_audio.c @@ -17,13 +17,19 @@ #include #include +struct qmc_dai_chan { + struct qmc_dai_prtd *prtd_tx; + struct qmc_dai_prtd *prtd_rx; + struct qmc_chan *qmc_chan; +}; + struct qmc_dai { char *name; int id; struct device *dev; - struct qmc_chan *qmc_chan; unsigned int nb_tx_ts; unsigned int nb_rx_ts; + struct qmc_dai_chan chan; }; struct qmc_audio { @@ -86,9 +92,12 @@ static int qmc_audio_pcm_hw_params(struct snd_soc_component *component, static void qmc_audio_pcm_write_complete(void *context) { - struct qmc_dai_prtd *prtd = context; + struct qmc_dai_chan *chan = context; + struct qmc_dai_prtd *prtd; int ret; + prtd = chan->prtd_tx; + prtd->buffer_ended += prtd->period_size; if (prtd->buffer_ended >= prtd->buffer_size) prtd->buffer_ended = 0; @@ -97,9 +106,10 @@ static void qmc_audio_pcm_write_complete(void *context) if (prtd->ch_dma_addr_current >= prtd->ch_dma_addr_end) prtd->ch_dma_addr_current = prtd->ch_dma_addr_start; - ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan, + ret = qmc_chan_write_submit(prtd->qmc_dai->chan.qmc_chan, prtd->ch_dma_addr_current, prtd->ch_dma_size, - qmc_audio_pcm_write_complete, prtd); + qmc_audio_pcm_write_complete, + &prtd->qmc_dai->chan); if (ret) { dev_err(prtd->qmc_dai->dev, "write_submit failed %d\n", ret); @@ -110,9 +120,12 @@ static void qmc_audio_pcm_write_complete(void *context) static void qmc_audio_pcm_read_complete(void *context, size_t length, unsigned int flags) { - struct qmc_dai_prtd *prtd = context; + struct qmc_dai_chan *chan = context; + struct qmc_dai_prtd *prtd; int ret; + prtd = chan->prtd_rx; + if (length != prtd->ch_dma_size) { dev_err(prtd->qmc_dai->dev, "read complete length = %zu, exp %zu\n", length, prtd->ch_dma_size); @@ -126,9 +139,10 @@ static void qmc_audio_pcm_read_complete(void *context, size_t length, unsigned i if (prtd->ch_dma_addr_current >= prtd->ch_dma_addr_end) prtd->ch_dma_addr_current = prtd->ch_dma_addr_start; - ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan, + ret = qmc_chan_read_submit(prtd->qmc_dai->chan.qmc_chan, prtd->ch_dma_addr_current, prtd->ch_dma_size, - qmc_audio_pcm_read_complete, prtd); + qmc_audio_pcm_read_complete, + &prtd->qmc_dai->chan); if (ret) { dev_err(prtd->qmc_dai->dev, "read_submit failed %d\n", ret); @@ -151,10 +165,13 @@ static int qmc_audio_pcm_trigger(struct snd_soc_component *component, switch (cmd) { case SNDRV_PCM_TRIGGER_START: if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + prtd->qmc_dai->chan.prtd_tx = prtd; + /* Submit first chunk ... */ - ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan, + ret = qmc_chan_write_submit(prtd->qmc_dai->chan.qmc_chan, prtd->ch_dma_addr_current, prtd->ch_dma_size, - qmc_audio_pcm_write_complete, prtd); + qmc_audio_pcm_write_complete, + &prtd->qmc_dai->chan);
[PATCH 09/10] dt-bindings: sound: fsl,qmc-audio: Add support for multiple QMC channels per DAI
The QMC audio uses one QMC channel per DAI and uses this QMC channel to transmit interleaved audio channel samples. In order to work in non-interleave mode, a QMC audio DAI needs to use multiple QMC channels. In that case, the DAI maps each QMC channel to exactly one audio channel. Allow QMC audio DAIs with multiple QMC channels attached. Signed-off-by: Herve Codina --- .../bindings/sound/fsl,qmc-audio.yaml | 41 --- 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/fsl,qmc-audio.yaml b/Documentation/devicetree/bindings/sound/fsl,qmc-audio.yaml index b522ed7dcc51..a23e49198c37 100644 --- a/Documentation/devicetree/bindings/sound/fsl,qmc-audio.yaml +++ b/Documentation/devicetree/bindings/sound/fsl,qmc-audio.yaml @@ -12,7 +12,9 @@ maintainers: description: | The QMC audio is an ASoC component which uses QMC (QUICC Multichannel Controller) channels to transfer the audio data. - It provides as many DAI as the number of QMC channel used. + It provides several DAIs. For each DAI, the DAI is working in interleaved mode + if only one QMC channel is used by the DAI or it is working in non-interleaved + mode if several QMC channels are used by the DAI. allOf: - $ref: dai-common.yaml# @@ -45,12 +47,19 @@ patternProperties: fsl,qmc-chan: $ref: /schemas/types.yaml#/definitions/phandle-array items: - - items: - - description: phandle to QMC node - - description: Channel number + items: +- description: phandle to QMC node +- description: Channel number +minItems: 1 description: - Should be a phandle/number pair. The phandle to QMC node and the QMC - channel to use for this DAI. + Should be a phandle/number pair list. The list of phandle to QMC node + and the QMC channel pair to use for this DAI. + If only one phandle/number pair is provided, this DAI works in + interleaved mode, i.e. audio channels for this DAI are interleaved in + the QMC channel. If more than one pair is provided, this DAI works + in non-interleave mode. In that case the first audio channel uses the + the first QMC channel, the second audio channel uses the second QMC + channel, etc... required: - reg @@ -79,6 +88,11 @@ examples: reg = <17>; fsl,qmc-chan = <&qmc 17>; }; +dai@18 { +reg = <18>; +/* Non-interleaved mode */ +fsl,qmc-chan = <&qmc 18>, <&qmc 19>; +}; }; sound { @@ -115,4 +129,19 @@ examples: dai-tdm-slot-rx-mask = <0 0 1 0 1 0 1 0 1>; }; }; +simple-audio-card,dai-link@2 { +reg = <2>; +format = "dsp_b"; +cpu { +sound-dai = <&audio_controller 18>; +}; +codec { +sound-dai = <&codec3>; +dai-tdm-slot-num = <2>; +dai-tdm-slot-width = <8>; +/* TS 9, 10 */ +dai-tdm-slot-tx-mask = <0 0 0 0 0 0 0 0 0 1 1>; +dai-tdm-slot-rx-mask = <0 0 0 0 0 0 0 0 0 1 1>; +}; +}; }; -- 2.45.0
[PATCH 05/10] ASoC: fsl: fsl_qmc_audio: Introduce qmc_audio_pcm_{read,write}_submit()
Submitting data to QMC channels is done in several places: transfer completions and DAI start. The operation done is simple and consist in one function call. With the future introduction of support for non-interleaved mode, submitting data will be more complex. To avoid copy/paste of code in several places, introduce qmc_audio_pcm_{read,write}_submit() whose goal is to handle this data submission. Signed-off-by: Herve Codina --- sound/soc/fsl/fsl_qmc_audio.c | 93 +-- 1 file changed, 45 insertions(+), 48 deletions(-) diff --git a/sound/soc/fsl/fsl_qmc_audio.c b/sound/soc/fsl/fsl_qmc_audio.c index b07770257bad..36145f1ddbf1 100644 --- a/sound/soc/fsl/fsl_qmc_audio.c +++ b/sound/soc/fsl/fsl_qmc_audio.c @@ -90,11 +90,29 @@ static int qmc_audio_pcm_hw_params(struct snd_soc_component *component, return 0; } +static void qmc_audio_pcm_write_complete(void *context); + +static int qmc_audio_pcm_write_submit(struct qmc_dai_prtd *prtd) +{ + int ret; + + ret = qmc_chan_write_submit(prtd->qmc_dai->chan.qmc_chan, + prtd->ch_dma_addr_current, prtd->ch_dma_size, + qmc_audio_pcm_write_complete, + &prtd->qmc_dai->chan); + if (ret) { + dev_err(prtd->qmc_dai->dev, "write_submit failed %d\n", + ret); + return ret; + } + + return 0; +} + static void qmc_audio_pcm_write_complete(void *context) { struct qmc_dai_chan *chan = context; struct qmc_dai_prtd *prtd; - int ret; prtd = chan->prtd_tx; @@ -106,23 +124,33 @@ static void qmc_audio_pcm_write_complete(void *context) if (prtd->ch_dma_addr_current >= prtd->ch_dma_addr_end) prtd->ch_dma_addr_current = prtd->ch_dma_addr_start; - ret = qmc_chan_write_submit(prtd->qmc_dai->chan.qmc_chan, - prtd->ch_dma_addr_current, prtd->ch_dma_size, - qmc_audio_pcm_write_complete, - &prtd->qmc_dai->chan); + qmc_audio_pcm_write_submit(prtd); + + snd_pcm_period_elapsed(prtd->substream); +} + +static void qmc_audio_pcm_read_complete(void *context, size_t length, unsigned int flags); + +static int qmc_audio_pcm_read_submit(struct qmc_dai_prtd *prtd) +{ + int ret; + + ret = qmc_chan_read_submit(prtd->qmc_dai->chan.qmc_chan, + prtd->ch_dma_addr_current, prtd->ch_dma_size, + qmc_audio_pcm_read_complete, + &prtd->qmc_dai->chan); if (ret) { - dev_err(prtd->qmc_dai->dev, "write_submit failed %d\n", + dev_err(prtd->qmc_dai->dev, "read_submit failed %d\n", ret); } - snd_pcm_period_elapsed(prtd->substream); + return 0; } static void qmc_audio_pcm_read_complete(void *context, size_t length, unsigned int flags) { struct qmc_dai_chan *chan = context; struct qmc_dai_prtd *prtd; - int ret; prtd = chan->prtd_rx; @@ -139,14 +167,7 @@ static void qmc_audio_pcm_read_complete(void *context, size_t length, unsigned i if (prtd->ch_dma_addr_current >= prtd->ch_dma_addr_end) prtd->ch_dma_addr_current = prtd->ch_dma_addr_start; - ret = qmc_chan_read_submit(prtd->qmc_dai->chan.qmc_chan, - prtd->ch_dma_addr_current, prtd->ch_dma_size, - qmc_audio_pcm_read_complete, - &prtd->qmc_dai->chan); - if (ret) { - dev_err(prtd->qmc_dai->dev, "read_submit failed %d\n", - ret); - } + qmc_audio_pcm_read_submit(prtd); snd_pcm_period_elapsed(prtd->substream); } @@ -168,15 +189,9 @@ static int qmc_audio_pcm_trigger(struct snd_soc_component *component, prtd->qmc_dai->chan.prtd_tx = prtd; /* Submit first chunk ... */ - ret = qmc_chan_write_submit(prtd->qmc_dai->chan.qmc_chan, - prtd->ch_dma_addr_current, prtd->ch_dma_size, - qmc_audio_pcm_write_complete, - &prtd->qmc_dai->chan); - if (ret) { - dev_err(component->dev, "write_submit failed %d\n", - ret); + ret = qmc_audio_pcm_write_submit(prtd); + if (ret) return ret; - } /* ... prepare next one ... */ prtd->ch_dma_addr_current += prtd->ch_dma_size; @@ -184,28 +199,16 @@ static int qmc_audio_pcm_trigger(struct
[PATCH 03/10] ASoC: fsl: fsl_qmc_audio: Split channel buffer and PCM pointer handling
The driver mixes some internal values for channel DMA buffer handling and PCM pointer handling. In the currently supported interleaved mode, this mix does not lead to any issues but in order to prepare the support for the non-interleaved mode, having them clearly separated will ease the support and avoid additional computation to convert values used in channel DMA buffer management in values usable for PCM pointer. Use a specific set of variable for PCM pointer handling and an other set for channel DMA buffer. Signed-off-by: Herve Codina --- sound/soc/fsl/fsl_qmc_audio.c | 84 +++ 1 file changed, 46 insertions(+), 38 deletions(-) diff --git a/sound/soc/fsl/fsl_qmc_audio.c b/sound/soc/fsl/fsl_qmc_audio.c index 917a32389f3d..e8281e548746 100644 --- a/sound/soc/fsl/fsl_qmc_audio.c +++ b/sound/soc/fsl/fsl_qmc_audio.c @@ -35,11 +35,16 @@ struct qmc_audio { struct qmc_dai_prtd { struct qmc_dai *qmc_dai; - dma_addr_t dma_buffer_start; - dma_addr_t period_ptr_submitted; - dma_addr_t period_ptr_ended; - dma_addr_t dma_buffer_end; - size_t period_size; + + snd_pcm_uframes_t buffer_ended; + snd_pcm_uframes_t buffer_size; + snd_pcm_uframes_t period_size; + + dma_addr_t ch_dma_addr_start; + dma_addr_t ch_dma_addr_current; + dma_addr_t ch_dma_addr_end; + size_t ch_dma_size; + struct snd_pcm_substream *substream; }; @@ -65,13 +70,17 @@ static int qmc_audio_pcm_hw_params(struct snd_soc_component *component, struct snd_pcm_runtime *runtime = substream->runtime; struct qmc_dai_prtd *prtd = substream->runtime->private_data; - prtd->dma_buffer_start = runtime->dma_addr; - prtd->dma_buffer_end = runtime->dma_addr + params_buffer_bytes(params); - prtd->period_size = params_period_bytes(params); - prtd->period_ptr_submitted = prtd->dma_buffer_start; - prtd->period_ptr_ended = prtd->dma_buffer_start; prtd->substream = substream; + prtd->buffer_ended = 0; + prtd->buffer_size = params_buffer_size(params); + prtd->period_size = params_period_size(params); + + prtd->ch_dma_addr_start = runtime->dma_addr; + prtd->ch_dma_addr_end = runtime->dma_addr + params_buffer_bytes(params); + prtd->ch_dma_addr_current = prtd->ch_dma_addr_start; + prtd->ch_dma_size = params_period_bytes(params); + return 0; } @@ -80,16 +89,16 @@ static void qmc_audio_pcm_write_complete(void *context) struct qmc_dai_prtd *prtd = context; int ret; - prtd->period_ptr_ended += prtd->period_size; - if (prtd->period_ptr_ended >= prtd->dma_buffer_end) - prtd->period_ptr_ended = prtd->dma_buffer_start; + prtd->buffer_ended += prtd->period_size; + if (prtd->buffer_ended >= prtd->buffer_size) + prtd->buffer_ended = 0; - prtd->period_ptr_submitted += prtd->period_size; - if (prtd->period_ptr_submitted >= prtd->dma_buffer_end) - prtd->period_ptr_submitted = prtd->dma_buffer_start; + prtd->ch_dma_addr_current += prtd->ch_dma_size; + if (prtd->ch_dma_addr_current >= prtd->ch_dma_addr_end) + prtd->ch_dma_addr_current = prtd->ch_dma_addr_start; ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chan, - prtd->period_ptr_submitted, prtd->period_size, + prtd->ch_dma_addr_current, prtd->ch_dma_size, qmc_audio_pcm_write_complete, prtd); if (ret) { dev_err(prtd->qmc_dai->dev, "write_submit failed %d\n", @@ -104,21 +113,21 @@ static void qmc_audio_pcm_read_complete(void *context, size_t length, unsigned i struct qmc_dai_prtd *prtd = context; int ret; - if (length != prtd->period_size) { + if (length != prtd->ch_dma_size) { dev_err(prtd->qmc_dai->dev, "read complete length = %zu, exp %zu\n", - length, prtd->period_size); + length, prtd->ch_dma_size); } - prtd->period_ptr_ended += prtd->period_size; - if (prtd->period_ptr_ended >= prtd->dma_buffer_end) - prtd->period_ptr_ended = prtd->dma_buffer_start; + prtd->buffer_ended += prtd->period_size; + if (prtd->buffer_ended >= prtd->buffer_size) + prtd->buffer_ended = 0; - prtd->period_ptr_submitted += prtd->period_size; - if (prtd->period_ptr_submitted >= prtd->dma_buffer_end) - prtd->period_ptr_submitted = prtd->dma_buffer_start; + prtd->ch_dma_addr_current += prtd->ch_dma_size; + if (prtd->ch_dma_addr_current >= prtd->ch_dma_addr_end) + prtd->ch_dma_addr_current = prtd->ch_dma_addr_start; ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chan, - prtd->period_ptr_submitted, prtd->period_size, +
Re: [PATCH] KVM: PPC: Book3S HV: Prevent UAF in kvm_spapr_tce_attach_iommu_group()
On Fri, 14 Jun 2024 22:29:10 +1000, Michael Ellerman wrote: > Al reported a possible use-after-free (UAF) in > kvm_spapr_tce_attach_iommu_group(). > > It looks up `stt` from tablefd, but then continues to use it after doing > fdput() on the returned fd. After the fdput() the tablefd is free to be > closed by another thread. The close calls kvm_spapr_tce_release() and > then release_spapr_tce_table() (via call_rcu()) which frees `stt`. > > [...] Applied to powerpc/fixes. [1/1] KVM: PPC: Book3S HV: Prevent UAF in kvm_spapr_tce_attach_iommu_group() https://git.kernel.org/powerpc/c/a986fa57fd81a1430e00b3c6cf8a325d6f894a63 cheers
Re: [PATCH] powerpc/crypto: Add generated P8 asm to .gitignore
On Mon, 03 Jun 2024 08:01:03 -0500, Nathan Lynch wrote: > Looks like drivers/crypto/vmx/.gitignore should have been merged into > arch/powerpc/crypto/.gitignore as part of commit > 109303336a0c ("crypto: vmx - Move to arch/powerpc/crypto") so that all > generated asm files are ignored. > > Applied to powerpc/fixes. [1/1] powerpc/crypto: Add generated P8 asm to .gitignore https://git.kernel.org/powerpc/c/2b85b7fb1376481f7d4c2cf92e5da942f06b2547 cheers
Re: (subset) [PATCH 0/6] defconfig: drop RT_GROUP_SCHED=y
On Thu, 30 May 2024 19:19:48 +0800, Celeste Liu wrote: > For cgroup v1, if turned on, and there's any cgroup in the "cpu" hierarchy it > needs an RT budget assigned, otherwise the processes in it will not be able to > get RT at all. The problem with RT group scheduling is that it requires the > budget assigned but there's no way we could assign a default budget, since the > values to assign are both upper and lower time limits, are absolute, and need > to > be sum up to < 1 for each individal cgroup. That means we cannot really come > up > with values that would work by default in the general case.[1] > > [...] Patch 4 applied to powerpc/next. [4/6] powerpc: defconfig: drop RT_GROUP_SCHED=y from ppc6xx_defconfig https://git.kernel.org/powerpc/c/2bac6caee94e25f59ee47e2d365d7e07465089ba cheers
Re: [PATCH v2] arch/powerpc: Remove unused cede related functions
On Tue, 14 May 2024 18:54:55 +0530, Gautam Menghani wrote: > Remove extended_cede_processor() and its helpers as > extended_cede_processor() has no callers since > commit 48f6e7f6d948("powerpc/pseries: remove cede offline state for CPUs") > > Applied to powerpc/next. [1/1] arch/powerpc: Remove unused cede related functions https://git.kernel.org/powerpc/c/214f33fcf656bf1be3f9f03d58fda067cdf7eecc cheers
Re: [PATCH] powerpc/pseries/iommu: Split Dynamic DMA Window to be used in Hybrid mode
On Mon, 13 May 2024 20:46:08 -0500, Gaurav Batra wrote: > Dynamic DMA Window (DDW) supports TCEs that are backed by 2MB page size. > In most configurations, DDW is big enough to pre-map all of LPAR memory > for IO. Pre-mapping of memory for DMA results in improvements in IO > performance. > > Persistent memory, vPMEM, can be assigned to an LPAR as well. vPMEM is not > contiguous with LPAR memory and usually is assigned at high memory > addresses. This makes is not possible to pre-map both vPMEM and LPAR > memory in the same DDW. > > [...] Applied to powerpc/next. [1/1] powerpc/pseries/iommu: Split Dynamic DMA Window to be used in Hybrid mode https://git.kernel.org/powerpc/c/ff5163bb7000a0254ffdd7b50cb6df43add94f33 cheers
Re: [PATCH v6] powerpc/pseries/vas: Use usleep_range() to support HCALL delay
On Mon, 15 Jan 2024 21:59:10 -0800, Haren Myneni wrote: > VAS allocate, modify and deallocate HCALLs returns > H_LONG_BUSY_ORDER_1_MSEC or H_LONG_BUSY_ORDER_10_MSEC for busy > delay and expects OS to reissue HCALL after that delay. But using > msleep() will often sleep at least 20 msecs even though the > hypervisor suggests OS reissue these HCALLs after 1 or 10msecs. > > The open and close VAS window functions hold mutex and then issue > these HCALLs. So these operations can take longer than the > necessary when multiple threads issue open or close window APIs > simultaneously, especially might affect the performance in the > case of repeat open/close APIs for each compression request. > > [...] Applied to powerpc/next. [1/1] powerpc/pseries/vas: Use usleep_range() to support HCALL delay https://git.kernel.org/powerpc/c/43ac9f5cd457bb01930f87448ddaaae455f8a8cf cheers
Re: [PATCH] powerpc/mm/drmem: Silence drmem_init() early return
On Mon, 03 Jun 2024 14:31:32 -0500, Nathan Lynch wrote: > It's not an error or noteworthy condition if the > "ibm,dynamic-reconfiguration-memory" node isn't present. > > Drop the needless message. > > Applied to powerpc/next. [1/1] powerpc/mm/drmem: Silence drmem_init() early return https://git.kernel.org/powerpc/c/11e6e6d8bf8f908468bac0447727e3f3923c8512 cheers
Re: [PATCH v2 0/1] powerpc/numa: Make cpu/memory less numa-node online
On Fri, 17 May 2024 19:55:21 +0530, Nilay Shroff wrote: > On NUMA aware system, we make a numa-node online only if that node is > attached to cpu/memory. However it's possible that we have some PCI/IO > device affinitized to a numa-node which is not currently online. In such > case we set the numa-node id of the corresponding PCI device to -1 > (NUMA_NO_NODE). Not assigning the correct numa-node id to PCI device may > impact the performance of such device. For instance, we have a multi > controller NVMe disk where each controller of the disk is attached to > different PHB (PCI host bridge). Each of these PHBs has numa-node id > assigned during PCI enumeration. During PCI enumeration if we find that > the numa-node is not online then we set the numa-node id of the PHB to -1. > If we create shared namespace and attach to multi controller NVMe disk > then that namespace could be accessed through each controller and as each > controller is connected to different PHBs, it's possible to access the > same namespace using multiple PCI channel. While sending IO to a shared > namespace, NVMe driver would calculate the optimal IO path using numa-node > distance. However if the numa-node id is not correctly assigned to NVMe > PCIe controller then it's possible that driver would calculate incorrect > NUMA distance and hence select the non-optimal path for sending IO. If > this happens then we could potentially observe the degraded IO performance. > > [...] Applied to powerpc/next. [1/1] powerpc/numa: Online a node if PHB is attached. https://git.kernel.org/powerpc/c/11981816e3614156a1fe14a1e8e77094ea46c7d5 cheers
[PATCHv5 0/9] ASoC: fsl-asoc-card: add S/PDIF controller
Hello, This is the v5 of the series of patches aiming to make the machine driver `fsl-asoc-card` compatible with S/PDIF controllers on imx boards. The main goal is to allow the use of S/PDIF controllers with ASRC modules. The `imx-spdif` machine driver already has specific support for S/PDIF controllers but doesn't support using an ASRC with it. However, the `fsl-asoc-card` machine driver has the necessary code to create a sound card which can use an ASRC module. It is then possible to extend the support for S/PDIF audio cards by merging the `imx-spdif` driver into `fsl-asoc-card`. The first patch fixes a NULL pointer dereference in `fsl-asoc-card` which occurs when the function "fsl_asoc_card_audmux_init()" prints error logs. The next three patches adapt the `fsl-asoc-card` driver to support multiple codec use cases. The driver can get 2 codec phandles from the device tree, and codec-related variables are doubled. `for_each_codecs` macros are also used when possible to ease adding other multi-codec use cases in the future. This makes possible to use the two S/PDIF dummy codec drivers `spdif_receiver` and `spdif_transmitter` instead of `snd-soc-dummy`, which was used in `imx-spdif`. The fifth patch merges the S/PDIF support from `imx-spdif` to `fsl-asoc-card`. `fsl-asoc-card` offers the same functionalities as `imx-spdif` did, but this merge also extends the S/PDIF support with the possibility of using an ASRC. Compatible "fsl,imx-audio-spdif" is kept, but some DT properties have to be updated in device trees to match those of `fsl-asoc-card`: * "spdif-controller" is now "audio-cpu" in `fsl-asoc-card`. * "spdif-in" and "spdif-out" are now replaced by the "audio-codec" property of `fsl-asoc-card`. S/PDIF specific dummy codecs should be used with `fsl-asoc-card`, and therefore declared in device trees. The last four patches update the device tree bindings of `fsl-asoc-card`, remove the now obsolete binding of `imx-spdif`, and update all device trees using the `fsl,imx-audio-spdif` compatible. This series of patches was successfully built for arm64 and x86 on top of the latest??"for-next" branch of the ASoC git tree on the 19th of June 2024. These modifications have also been tested on an i.MX8MN evaluation board with a linux kernel RT v6.1.26-rt8. If you have any questions or remarks about these commits, don't hesitate to reply to this message. Best regards, Elinor Montmasson Changelog: v4 -> v5: * Focus the contribution to bringing S/PDIF / ASRC support. * Instead of creating a new compatible for the S/PDIF `fsl-asoc-card` support, merge the driver `imx-spdif` into `fsl-asoc-card`, and keep the compatible. It preserves the base S/PDIF audio card support but also extends it with the possibility to use an ASRC. It also reduces code and driver duplication. * Following driver merge, adapt device trees using "fsl,imx-audio-spdif" compatible. * Use more `for_each_codecs` macros in `fsl-asoc-card` when adding multi-codec support. * Remove patches about new device-tree bindings that were not relevant for an S/PDIF specific support. * Improve DT schema changes. * Move `priv->pdev` assignment earlier in "fsl_asoc_card_probe()" to fix a NULL pointer dereference in "fsl_asoc_card_audmux_init()". * v4 patch series at : https://lore.kernel.org/all/20240515135411.34-1-elinor.montmas...@savoirfairelinux.com/ v3 -> v4: * Use the standard TDM bidings, as defined in "tdm-slot.txt", for the new optional DT bindings setting the TDM slots number and width. * Use the clock DT bindings to optionally specify the CPU DAI system clock frequency, instead of a dedicated new binding. * Rename the new DT binding "cpu-sysclk-dir-out" to "cpu-system-clock-direction-out" to better follow the style of the simple-card driver. * Merge TX an RX bindings for CPU DAI system-clock, to better follow the style of the simple-card driver, and also as there was no use case in fsl-asoc-card where TX and RX settings had to be different. * Add the documentation for the new bindings in the new DT schema bindings documentation. Also add an example with the generic codec. * v3 patch series at : https://lore.kernel.org/alsa-devel/20231218124058.2047167-1-elinor.montmas...@savoirfairelinux.com/ v2 -> v3: * When the bitmaster or framemaster are retrieved from the device tree, the driver will now compare them with the two codecs possibly given in device tree, and not just the first codec. * Improve driver modifications to use multiple codecs for better integration of future multi-codec use cases: * Use `for_each_codec` macros when possible. * `fsl_asoc_card_priv` struct now has 2 `codec_priv` as the driver can currently retrieve 2 codec phandles from the device tree. * Fix subject of patch 10/10 to follow the style of the subsystem * v2 patch series at: https://lore.kernel.org/alsa-devel/20231027144734.3654829-1-elinor.montmas...@savoirfairelinux.com/ v1 -> v2: * Replace use of the dummy cod
[PATCHv5 1/9] ASoC: fsl-asoc-card: set priv->pdev before using it
priv->pdev pointer was set after being used in fsl_asoc_card_audmux_init(). Move this assignment at the start of the probe function, so sub-functions can correctly use pdev through priv. fsl_asoc_card_audmux_init() dereferences priv->pdev to get access to the dev struct, used with dev_err macros. As priv is zero-initialised, there would be a NULL pointer dereference. Note that if priv->dev is dereferenced before assignment but never used, for example if there is no error to be printed, the driver won't crash probably due to compiler optimisations. Fixes: 708b4351f08c ("ASoC: fsl: Add Freescale Generic ASoC Sound Card with ASRC support") Signed-off-by: Elinor Montmasson --- sound/soc/fsl/fsl-asoc-card.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index 5ddc0c2fe53f..eb67689dcd6e 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -559,6 +559,8 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; + priv->pdev = pdev; + cpu_np = of_parse_phandle(np, "audio-cpu", 0); /* Give a chance to old DT binding */ if (!cpu_np) @@ -787,7 +789,6 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) } /* Initialize sound card */ - priv->pdev = pdev; priv->card.dev = &pdev->dev; priv->card.owner = THIS_MODULE; ret = snd_soc_of_parse_card_name(&priv->card, "model"); -- 2.34.1
[PATCHv5 2/9] ASoC: fsl-asoc-card: add support for dai links with multiple codecs
Add support for dai links using multiple codecs for multi-codec use cases. Co-developed-by: Philip-Dylan Gleonec Signed-off-by: Philip-Dylan Gleonec Signed-off-by: Elinor Montmasson --- sound/soc/fsl/fsl-asoc-card.c | 19 +++ 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index eb67689dcd6e..e8003fbc8092 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -542,6 +542,7 @@ static int fsl_asoc_card_late_probe(struct snd_soc_card *card) static int fsl_asoc_card_probe(struct platform_device *pdev) { struct device_node *cpu_np, *codec_np, *asrc_np; + struct snd_soc_dai_link_component *codec_comp; struct device_node *np = pdev->dev.of_node; struct platform_device *asrc_pdev = NULL; struct device_node *bitclkprovider = NULL; @@ -552,6 +553,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) const char *codec_dai_name; const char *codec_dev_name; u32 asrc_fmt = 0; + int codec_idx; u32 width; int ret; @@ -816,10 +818,10 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) /* Normal DAI Link */ priv->dai_link[0].cpus->of_node = cpu_np; - priv->dai_link[0].codecs->dai_name = codec_dai_name; + priv->dai_link[0].codecs[0].dai_name = codec_dai_name; if (!fsl_asoc_card_is_ac97(priv)) - priv->dai_link[0].codecs->of_node = codec_np; + priv->dai_link[0].codecs[0].of_node = codec_np; else { u32 idx; @@ -830,11 +832,11 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) goto asrc_fail; } - priv->dai_link[0].codecs->name = + priv->dai_link[0].codecs[0].name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "ac97-codec.%u", (unsigned int)idx); - if (!priv->dai_link[0].codecs->name) { + if (!priv->dai_link[0].codecs[0].name) { ret = -ENOMEM; goto asrc_fail; } @@ -848,10 +850,11 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) /* DPCM DAI Links only if ASRC exists */ priv->dai_link[1].cpus->of_node = asrc_np; priv->dai_link[1].platforms->of_node = asrc_np; - priv->dai_link[2].codecs->dai_name = codec_dai_name; - priv->dai_link[2].codecs->of_node = codec_np; - priv->dai_link[2].codecs->name = - priv->dai_link[0].codecs->name; + for_each_link_codecs((&(priv->dai_link[2])), codec_idx, codec_comp) { + codec_comp->dai_name = priv->dai_link[0].codecs[codec_idx].dai_name; + codec_comp->of_node = priv->dai_link[0].codecs[codec_idx].of_node; + codec_comp->name = priv->dai_link[0].codecs[codec_idx].name; + } priv->dai_link[2].cpus->of_node = cpu_np; priv->dai_link[2].dai_fmt = priv->dai_fmt; priv->card.num_links = 3; -- 2.34.1
[PATCHv5 3/9] ASoC: fsl-asoc-card: add second dai link component for codecs
Add a second dai link component for codecs that will be used for use cases with 2 codecs. It is needed for future integration of the SPDIF support, which will use spdif_receiver and spdif_transmitter drivers. To prevent deferring in use cases using only one codec, also set by default the number of codecs to 1 for the relevant dai links. Co-developed-by: Philip-Dylan Gleonec Signed-off-by: Philip-Dylan Gleonec Signed-off-by: Elinor Montmasson --- sound/soc/fsl/fsl-asoc-card.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index e8003fbc8092..805e2030bde4 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -296,7 +296,7 @@ static int be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, SND_SOC_DAILINK_DEFS(hifi, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_EMPTY()), + DAILINK_COMP_ARRAY(COMP_EMPTY(), COMP_EMPTY()), DAILINK_COMP_ARRAY(COMP_EMPTY())); SND_SOC_DAILINK_DEFS(hifi_fe, @@ -306,7 +306,7 @@ SND_SOC_DAILINK_DEFS(hifi_fe, SND_SOC_DAILINK_DEFS(hifi_be, DAILINK_COMP_ARRAY(COMP_EMPTY()), - DAILINK_COMP_ARRAY(COMP_EMPTY())); + DAILINK_COMP_ARRAY(COMP_EMPTY(), COMP_EMPTY())); static const struct snd_soc_dai_link fsl_asoc_card_dai[] = { /* Default ASoC DAI Link*/ @@ -622,6 +622,8 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) memcpy(priv->dai_link, fsl_asoc_card_dai, sizeof(struct snd_soc_dai_link) * ARRAY_SIZE(priv->dai_link)); + priv->dai_link[0].num_codecs = 1; + priv->dai_link[2].num_codecs = 1; priv->card.dapm_routes = audio_map; priv->card.num_dapm_routes = ARRAY_SIZE(audio_map); -- 2.34.1
[PATCHv5 4/9] ASoC: fsl-asoc-card: add compatibility to use 2 codecs in dai-links
Adapt the driver to work with configurations using two codecs or more. Modify fsl_asoc_card_probe() to handle use cases where 2 codecs are given in the device tree. This will be needed to add support for the SPDIF. Use cases using one codec will ignore any given codecs other than the first. Co-developed-by: Philip-Dylan Gleonec Signed-off-by: Philip-Dylan Gleonec Signed-off-by: Elinor Montmasson --- sound/soc/fsl/fsl-asoc-card.c | 279 -- 1 file changed, 161 insertions(+), 118 deletions(-) diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index 805e2030bde4..87329731e02d 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -99,7 +99,7 @@ struct fsl_asoc_card_priv { struct simple_util_jack hp_jack; struct simple_util_jack mic_jack; struct platform_device *pdev; - struct codec_priv codec_priv; + struct codec_priv codec_priv[2]; struct cpu_priv cpu_priv; struct snd_soc_card card; u8 streams; @@ -172,10 +172,12 @@ static int fsl_asoc_card_hw_params(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; - struct codec_priv *codec_priv = &priv->codec_priv; + struct codec_priv *codec_priv; + struct snd_soc_dai *codec_dai; struct cpu_priv *cpu_priv = &priv->cpu_priv; struct device *dev = rtd->card->dev; unsigned int pll_out; + int codec_idx; int ret; priv->sample_rate = params_rate(params); @@ -208,28 +210,32 @@ static int fsl_asoc_card_hw_params(struct snd_pcm_substream *substream, } /* Specific configuration for PLL */ - if (codec_priv->pll_id >= 0 && codec_priv->fll_id >= 0) { - if (priv->sample_format == SNDRV_PCM_FORMAT_S24_LE) - pll_out = priv->sample_rate * 384; - else - pll_out = priv->sample_rate * 256; + for_each_rtd_codec_dais(rtd, codec_idx, codec_dai) { + codec_priv = &priv->codec_priv[codec_idx]; - ret = snd_soc_dai_set_pll(snd_soc_rtd_to_codec(rtd, 0), - codec_priv->pll_id, - codec_priv->mclk_id, - codec_priv->mclk_freq, pll_out); - if (ret) { - dev_err(dev, "failed to start FLL: %d\n", ret); - goto fail; - } + if (codec_priv->pll_id >= 0 && codec_priv->fll_id >= 0) { + if (priv->sample_format == SNDRV_PCM_FORMAT_S24_LE) + pll_out = priv->sample_rate * 384; + else + pll_out = priv->sample_rate * 256; - ret = snd_soc_dai_set_sysclk(snd_soc_rtd_to_codec(rtd, 0), -codec_priv->fll_id, -pll_out, SND_SOC_CLOCK_IN); + ret = snd_soc_dai_set_pll(codec_dai, + codec_priv->pll_id, + codec_priv->mclk_id, + codec_priv->mclk_freq, pll_out); + if (ret) { + dev_err(dev, "failed to start FLL: %d\n", ret); + goto fail; + } - if (ret && ret != -ENOTSUPP) { - dev_err(dev, "failed to set SYSCLK: %d\n", ret); - goto fail; + ret = snd_soc_dai_set_sysclk(codec_dai, + codec_priv->fll_id, + pll_out, SND_SOC_CLOCK_IN); + + if (ret && ret != -ENOTSUPP) { + dev_err(dev, "failed to set SYSCLK: %d\n", ret); + goto fail; + } } } @@ -244,28 +250,34 @@ static int fsl_asoc_card_hw_free(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card); - struct codec_priv *codec_priv = &priv->codec_priv; + struct codec_priv *codec_priv; + struct snd_soc_dai *codec_dai; struct device *dev = rtd->card->dev; + int codec_idx; int ret; priv->streams &= ~BIT(substream->stream); - if (!priv->streams && codec_priv->pll_id >= 0 && codec_priv->fll_id >= 0) { - /* Force freq to be free_freq to avoid error message in codec */ -
[PATCHv5 5/9] ASoC: fsl-asoc-card: merge spdif support from imx-spdif.c
The imx-spdif machine driver creates audio card to directly use an S/PDIF device. However, it doesn't support interacting with an ASRC. fsl-asoc-card already has the support to create audio card which can use the ASRC. Merge the S/PDIF support from imx-spdif into fsl-asoc-card to extend the support of S/PDIF audio card with the use of ASRC devices. It also substitutes the use of the dummy codec in imx-spdif with the existing spdif_transmitter and spdif_receiver codec drivers. Signed-off-by: Elinor Montmasson --- arch/arm/configs/imx_v6_v7_defconfig | 1 - arch/arm64/configs/defconfig | 1 - sound/soc/fsl/Kconfig| 10 +-- sound/soc/fsl/Makefile | 2 - sound/soc/fsl/fsl-asoc-card.c| 58 +++ sound/soc/fsl/imx-spdif.c| 103 --- 6 files changed, 59 insertions(+), 116 deletions(-) delete mode 100644 sound/soc/fsl/imx-spdif.c diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig index cf2480dce285..ac5ae621b2af 100644 --- a/arch/arm/configs/imx_v6_v7_defconfig +++ b/arch/arm/configs/imx_v6_v7_defconfig @@ -311,7 +311,6 @@ CONFIG_SND_IMX_SOC=y CONFIG_SND_SOC_EUKREA_TLV320=y CONFIG_SND_SOC_IMX_ES8328=y CONFIG_SND_SOC_IMX_SGTL5000=y -CONFIG_SND_SOC_IMX_SPDIF=y CONFIG_SND_SOC_FSL_ASOC_CARD=y CONFIG_SND_SOC_AC97_CODEC=y CONFIG_SND_SOC_CS42XX8_I2C=y diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 57a9abe78ee4..a6c9688fee0e 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -940,7 +940,6 @@ CONFIG_SND_SOC_FSL_MICFIL=m CONFIG_SND_SOC_FSL_EASRC=m CONFIG_SND_IMX_SOC=m CONFIG_SND_SOC_IMX_SGTL5000=m -CONFIG_SND_SOC_IMX_SPDIF=m CONFIG_SND_SOC_FSL_ASOC_CARD=m CONFIG_SND_SOC_IMX_AUDMIX=m CONFIG_SND_SOC_MT8183=m diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 9a371d4496c2..e3b2bfb016c8 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -296,15 +296,6 @@ config SND_SOC_IMX_SGTL5000 SND_SOC_FSL_ASOC_CARD and SND_SOC_SGTL5000 to use the newer driver. -config SND_SOC_IMX_SPDIF - tristate "SoC Audio support for i.MX boards with S/PDIF" - select SND_SOC_IMX_PCM_DMA - select SND_SOC_FSL_SPDIF - help - SoC Audio support for i.MX boards with S/PDIF - Say Y if you want to add support for SoC audio on an i.MX board with - a S/DPDIF. - config SND_SOC_FSL_ASOC_CARD tristate "Generic ASoC Sound Card with ASRC support" depends on OF && I2C @@ -316,6 +307,7 @@ config SND_SOC_FSL_ASOC_CARD select SND_SOC_FSL_ESAI select SND_SOC_FSL_SAI select SND_SOC_FSL_SSI + select SND_SOC_FSL_SPDIF select SND_SOC_TLV320AIC31XX select SND_SOC_WM8994 select MFD_WM8994 diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index 2fe78eed3a48..1ae181b24a88 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile @@ -65,7 +65,6 @@ obj-$(CONFIG_SND_SOC_IMX_PCM_RPMSG) += imx-pcm-rpmsg.o snd-soc-eukrea-tlv320-y := eukrea-tlv320.o snd-soc-imx-es8328-y := imx-es8328.o snd-soc-imx-sgtl5000-y := imx-sgtl5000.o -snd-soc-imx-spdif-y := imx-spdif.o snd-soc-imx-audmix-y := imx-audmix.o snd-soc-imx-hdmi-y := imx-hdmi.o snd-soc-imx-rpmsg-y := imx-rpmsg.o @@ -74,7 +73,6 @@ snd-soc-imx-card-y := imx-card.o obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o obj-$(CONFIG_SND_SOC_IMX_ES8328) += snd-soc-imx-es8328.o obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o -obj-$(CONFIG_SND_SOC_IMX_SPDIF) += snd-soc-imx-spdif.o obj-$(CONFIG_SND_SOC_IMX_AUDMIX) += snd-soc-imx-audmix.o obj-$(CONFIG_SND_SOC_IMX_HDMI) += snd-soc-imx-hdmi.o obj-$(CONFIG_SND_SOC_IMX_RPMSG) += snd-soc-imx-rpmsg.o diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index 87329731e02d..c0e600525680 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -477,6 +477,59 @@ static int fsl_asoc_card_audmux_init(struct device_node *np, return 0; } +static int fsl_asoc_card_spdif_init(struct device_node *codec_np[], + struct device_node *cpu_np, + const char *codec_dai_name[], + struct fsl_asoc_card_priv *priv) +{ + struct device *dev = &priv->pdev->dev; + + if (!of_node_name_eq(cpu_np, "spdif")) { + dev_err(dev, "CPU phandle invalid, should be an SPDIF device\n"); + return -EINVAL; + } + + priv->dai_link[0].playback_only = true; + priv->dai_link[0].capture_only = true; + + for (int i = 0; i < 2; i++) { + if (!codec_np[i]) + break; + + if (of_device_is_compatible(codec_np[i], "linux,spdif-dit")) { + priv->dai_link[0].capture_only = false; + codec_dai_name[i] = "dit-hifi"; +
[PATCHv5 6/9] ASoC: dt-bindings: fsl-asoc-card: add compatible string for spdif
The S/PDIF audio card support was merged from imx-spdif into the fsl-asoc-card driver, making it possible to use an S/PDIF with an ASRC. Add the new compatible and update properties. Signed-off-by: Elinor Montmasson --- .../bindings/sound/fsl-asoc-card.yaml | 30 --- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/fsl-asoc-card.yaml b/Documentation/devicetree/bindings/sound/fsl-asoc-card.yaml index 9922664d5ccc..f2e28b32808e 100644 --- a/Documentation/devicetree/bindings/sound/fsl-asoc-card.yaml +++ b/Documentation/devicetree/bindings/sound/fsl-asoc-card.yaml @@ -33,6 +33,7 @@ properties: - items: - enum: - fsl,imx-sgtl5000 + - fsl,imx-sabreauto-spdif - fsl,imx25-pdk-sgtl5000 - fsl,imx53-cpuvo-sgtl5000 - fsl,imx51-babbage-sgtl5000 @@ -54,6 +55,7 @@ properties: - fsl,imx6q-ventana-sgtl5000 - fsl,imx6sl-evk-wm8962 - fsl,imx6sx-sdb-mqs + - fsl,imx6sx-sdb-spdif - fsl,imx6sx-sdb-wm8962 - fsl,imx7d-evk-wm8960 - karo,tx53-audio-sgtl5000 @@ -65,6 +67,7 @@ properties: - fsl,imx-audio-sgtl5000 - fsl,imx-audio-wm8960 - fsl,imx-audio-wm8962 + - fsl,imx-audio-spdif - items: - enum: - fsl,imx-audio-ac97 @@ -81,6 +84,7 @@ properties: - fsl,imx-audio-wm8960 - fsl,imx-audio-wm8962 - fsl,imx-audio-wm8958 + - fsl,imx-audio-spdif model: $ref: /schemas/types.yaml#/definitions/string @@ -93,8 +97,15 @@ properties: need to add ASRC support via DPCM. audio-codec: -$ref: /schemas/types.yaml#/definitions/phandle -description: The phandle of an audio codec +$ref: /schemas/types.yaml#/definitions/phandle-array +description: | + The phandle of an audio codec. + With "fsl,imx-audio-spdif", either SPDIF audio codec spdif_transmitter, + spdif_receiver or both. +minItems: 1 +maxItems: 2 +items: + maxItems: 1 audio-cpu: $ref: /schemas/types.yaml#/definitions/phandle @@ -150,8 +161,10 @@ properties: description: dai-link uses bit clock inversion. mclk-id: -$ref: /schemas/types.yaml#/definitions/uint32 -description: main clock id, specific for each card configuration. +$ref: /schemas/types.yaml#/definitions/uint32-array +description: Main clock id for each codec, specific for each card configuration. +minItems: 1 +maxItems: 2 mux-int-port: $ref: /schemas/types.yaml#/definitions/uint32 @@ -195,3 +208,12 @@ examples: "AIN2L", "Line In Jack", "AIN2R", "Line In Jack"; }; + + - | +sound-spdif-asrc { + compatible = "fsl,imx-audio-spdif"; + model = "spdif-asrc-audio"; + audio-cpu = <&spdif>; + audio-asrc = <&easrc>; + audio-codec = <&spdifdit>, <&spdifdir>; +}; -- 2.34.1
[PATCHv5 7/9] ASoC: dt-bindings: imx-audio-spdif: remove binding
imx-audio-spdif was merged into the fsl-asoc-card driver, and therefore removed. Signed-off-by: Elinor Montmasson --- .../bindings/sound/fsl,imx-audio-spdif.yaml | 66 --- 1 file changed, 66 deletions(-) delete mode 100644 Documentation/devicetree/bindings/sound/fsl,imx-audio-spdif.yaml diff --git a/Documentation/devicetree/bindings/sound/fsl,imx-audio-spdif.yaml b/Documentation/devicetree/bindings/sound/fsl,imx-audio-spdif.yaml deleted file mode 100644 index 5fc543d02ecb.. --- a/Documentation/devicetree/bindings/sound/fsl,imx-audio-spdif.yaml +++ /dev/null @@ -1,66 +0,0 @@ -# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -%YAML 1.2 -$id: http://devicetree.org/schemas/sound/fsl,imx-audio-spdif.yaml# -$schema: http://devicetree.org/meta-schemas/core.yaml# - -title: Freescale i.MX audio complex with S/PDIF transceiver - -maintainers: - - Shengjiu Wang - -properties: - compatible: -oneOf: - - items: - - enum: - - fsl,imx-sabreauto-spdif - - fsl,imx6sx-sdb-spdif - - const: fsl,imx-audio-spdif - - enum: - - fsl,imx-audio-spdif - - model: -$ref: /schemas/types.yaml#/definitions/string -description: User specified audio sound card name - - spdif-controller: -$ref: /schemas/types.yaml#/definitions/phandle -description: The phandle of the i.MX S/PDIF controller - - spdif-out: -type: boolean -description: - If present, the transmitting function of S/PDIF will be enabled, - indicating there's a physical S/PDIF out connector or jack on the - board or it's connecting to some other IP block, such as an HDMI - encoder or display-controller. - - spdif-in: -type: boolean -description: - If present, the receiving function of S/PDIF will be enabled, - indicating there is a physical S/PDIF in connector/jack on the board. - -required: - - compatible - - model - - spdif-controller - -anyOf: - - required: - - spdif-in - - required: - - spdif-out - -additionalProperties: false - -examples: - - | -sound-spdif { -compatible = "fsl,imx-audio-spdif"; -model = "imx-spdif"; -spdif-controller = <&spdif>; -spdif-out; -spdif-in; -}; -- 2.34.1
[PATCHv5 8/9] arm64: dts: imx8m: update spdif sound card node properties
Following merge of imx-spdif driver into fsl-asoc-card: * update properties to match those used by fsl-asoc-card. * S/PDIF in/out dummy codecs must now be declared explicitly, add and use them. These modifications were tested only on an imx8mn-evk board. Signed-off-by: Elinor Montmasson --- arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi | 15 +--- arch/arm64/boot/dts/freescale/imx8mn-evk.dtsi | 15 +--- arch/arm64/boot/dts/freescale/imx8mq-evk.dts | 24 +++ 3 files changed, 43 insertions(+), 11 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi b/arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi index 90d1901df2b1..348855a41852 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mm-evk.dtsi @@ -180,12 +180,21 @@ cpu { }; }; + spdif_out: spdif-out { + #sound-dai-cells = <0>; + compatible = "linux,spdif-dit"; + }; + + spdif_in: spdif-in { + #sound-dai-cells = <0>; + compatible = "linux,spdif-dir"; + }; + sound-spdif { compatible = "fsl,imx-audio-spdif"; model = "imx-spdif"; - spdif-controller = <&spdif1>; - spdif-out; - spdif-in; + audio-cpu = <&spdif1>; + audio-codec = <&spdif_out>, <&spdif_in>; }; }; diff --git a/arch/arm64/boot/dts/freescale/imx8mn-evk.dtsi b/arch/arm64/boot/dts/freescale/imx8mn-evk.dtsi index 9e0259ddf4bc..6a47e09703a7 100644 --- a/arch/arm64/boot/dts/freescale/imx8mn-evk.dtsi +++ b/arch/arm64/boot/dts/freescale/imx8mn-evk.dtsi @@ -124,12 +124,21 @@ sound-wm8524 { "Line Out Jack", "LINEVOUTR"; }; + spdif_out: spdif-out { + #sound-dai-cells = <0>; + compatible = "linux,spdif-dit"; + }; + + spdif_in: spdif-in { + #sound-dai-cells = <0>; + compatible = "linux,spdif-dir"; + }; + sound-spdif { compatible = "fsl,imx-audio-spdif"; model = "imx-spdif"; - spdif-controller = <&spdif1>; - spdif-out; - spdif-in; + audio-cpu = <&spdif1>; + audio-codec = <&spdif_out>, <&spdif_in>; }; sound-micfil { diff --git a/arch/arm64/boot/dts/freescale/imx8mq-evk.dts b/arch/arm64/boot/dts/freescale/imx8mq-evk.dts index 7507548cdb16..b953865f0b46 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq-evk.dts +++ b/arch/arm64/boot/dts/freescale/imx8mq-evk.dts @@ -125,19 +125,33 @@ link_codec: simple-audio-card,codec { }; }; + spdif_out: spdif-out { + #sound-dai-cells = <0>; + compatible = "linux,spdif-dit"; + }; + + spdif_in: spdif-in { + #sound-dai-cells = <0>; + compatible = "linux,spdif-dir"; + }; + sound-spdif { compatible = "fsl,imx-audio-spdif"; model = "imx-spdif"; - spdif-controller = <&spdif1>; - spdif-out; - spdif-in; + audio-cpu = <&spdif1>; + audio-codec = <&spdif_out>, <&spdif_in>; + }; + + hdmi_arc_in: hdmi-arc-in { + #sound-dai-cells = <0>; + compatible = "linux,spdif-dir"; }; sound-hdmi-arc { compatible = "fsl,imx-audio-spdif"; model = "imx-hdmi-arc"; - spdif-controller = <&spdif2>; - spdif-in; + audio-cpu = <&spdif2>; + audio-codec = <&hdmi_arc_in>; }; }; -- 2.34.1
[PATCHv5 9/9] ARM: dts: imx6: update spdif sound card node properties
Following merge of imx-spdif driver into fsl-asoc-card: * update properties to match those used by fsl-asoc-card. * S/PDIF in/out dummy codecs must now be declared explicitly, add and use them. These modifications were tested only on an imx8mn-evk board. Signed-off-by: Elinor Montmasson --- arch/arm/boot/dts/nxp/imx/imx6q-cm-fx6.dts| 15 --- arch/arm/boot/dts/nxp/imx/imx6q-prti6q.dts| 15 --- arch/arm/boot/dts/nxp/imx/imx6q-tbs2910.dts | 9 +++-- arch/arm/boot/dts/nxp/imx/imx6qdl-apalis.dtsi | 15 --- arch/arm/boot/dts/nxp/imx/imx6qdl-apf6dev.dtsi| 9 +++-- arch/arm/boot/dts/nxp/imx/imx6qdl-colibri.dtsi| 15 --- arch/arm/boot/dts/nxp/imx/imx6qdl-cubox-i.dtsi| 9 +++-- .../boot/dts/nxp/imx/imx6qdl-hummingboard.dtsi| 9 +++-- arch/arm/boot/dts/nxp/imx/imx6qdl-sabreauto.dtsi | 9 +++-- arch/arm/boot/dts/nxp/imx/imx6qdl-wandboard.dtsi | 9 +++-- arch/arm/boot/dts/nxp/imx/imx6sx-sabreauto.dts| 9 +++-- arch/arm/boot/dts/nxp/imx/imx6sx-sdb.dtsi | 9 +++-- 12 files changed, 104 insertions(+), 28 deletions(-) diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-cm-fx6.dts b/arch/arm/boot/dts/nxp/imx/imx6q-cm-fx6.dts index 95b49fc83f7b..5c664c0f2169 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6q-cm-fx6.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6q-cm-fx6.dts @@ -127,12 +127,21 @@ simple-audio-card,codec { }; }; + spdif_out: spdif-out { + #sound-dai-cells = <0>; + compatible = "linux,spdif-dit"; + }; + + spdif_in: spdif-in { + #sound-dai-cells = <0>; + compatible = "linux,spdif-dir"; + }; + sound-spdif { compatible = "fsl,imx-audio-spdif"; model = "imx-spdif"; - spdif-controller = <&spdif>; - spdif-out; - spdif-in; + audio-cpu = <&spdif>; + audio-codec = <&spdif_out>, <&spdif_in>; }; }; diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-prti6q.dts b/arch/arm/boot/dts/nxp/imx/imx6q-prti6q.dts index a7d5693c5ab7..8491d656ef17 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6q-prti6q.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6q-prti6q.dts @@ -111,12 +111,21 @@ simple-audio-card,codec { }; }; + spdif_out: spdif-out { + #sound-dai-cells = <0>; + compatible = "linux,spdif-dit"; + }; + + spdif_in: spdif-in { + #sound-dai-cells = <0>; + compatible = "linux,spdif-dir"; + }; + sound-spdif { compatible = "fsl,imx-audio-spdif"; model = "imx-spdif"; - spdif-controller = <&spdif>; - spdif-in; - spdif-out; + audio-cpu = <&spdif>; + audio-codec = <&spdif_out>, <&spdif_in>; }; }; diff --git a/arch/arm/boot/dts/nxp/imx/imx6q-tbs2910.dts b/arch/arm/boot/dts/nxp/imx/imx6q-tbs2910.dts index 7c298d9aa21e..ea9a98887c7b 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6q-tbs2910.dts +++ b/arch/arm/boot/dts/nxp/imx/imx6q-tbs2910.dts @@ -90,11 +90,16 @@ sound-sgtl5000 { ssi-controller = <&ssi1>; }; + spdif_out: spdif-out { + #sound-dai-cells = <0>; + compatible = "linux,spdif-dit"; + }; + sound-spdif { compatible = "fsl,imx-audio-spdif"; model = "On-board SPDIF"; - spdif-controller = <&spdif>; - spdif-out; + audio-cpu = <&spdif>; + audio-codec = <&spdif_out>; }; }; diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-apalis.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-apalis.dtsi index ea40623d12e5..6f4546c59d38 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-apalis.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-apalis.dtsi @@ -197,11 +197,20 @@ sound { ssi-controller = <&ssi1>; }; + spdif_out: spdif-out { + #sound-dai-cells = <0>; + compatible = "linux,spdif-dit"; + }; + + spdif_in: spdif-in { + #sound-dai-cells = <0>; + compatible = "linux,spdif-dir"; + }; + sound_spdif: sound-spdif { compatible = "fsl,imx-audio-spdif"; - spdif-controller = <&spdif>; - spdif-in; - spdif-out; + audio-cpu = <&spdif>; + audio-codec = <&spdif_out>, <&spdif_in>; model = "imx-spdif"; status = "disabled"; }; diff --git a/arch/arm/boot/dts/nxp/imx/imx6qdl-apf6dev.dtsi b/arch/arm/boot/dts/nxp/imx/imx6qdl-apf6dev.dtsi index 3a46ade3b6bd..6aa6b152c3ae 100644 --- a/arch/arm/boot/dts/nxp/imx/imx6qdl-apf6dev.dtsi +++ b/arch/arm/boot/dts/nxp/imx/imx6qdl-apf6dev.dtsi @@ -121,11 +121,16 @@ sound { mux-
Re: [PATCH v2 0/2] powerpc: kexec fixes
On Fri, 10 May 2024 15:52:33 +0530, Sourabh Jain wrote: > Patch series fixes two kexec issues. > > 01/02: Update extra size calculation for kexec FDT to avoid kexec load > failure due to FDT_ERR_NOSPACE while including CPU nodes added post > boot and reserved memory ranges. > > 02/02: Fix update_cpus_node/core_64.c function to include missing device > nodes under /cpus node with device_type != "cpu". > > [...] Applied to powerpc/next. [1/2] powerpc/kexec_file: fix extra size calculation for kexec FDT https://git.kernel.org/powerpc/c/0d3ff067331ef84e7e7f49537d768881042ed5ba [2/2] powerpc/kexec_file: fix cpus node update to FDT https://git.kernel.org/powerpc/c/932bed41217059638c78a75411b7893b121d2162 cheers
Re: [PATCH v2 0/2] Fix doorbell emulation for v2 API on PPC
On Wed, 05 Jun 2024 17:09:08 +0530, Gautam Menghani wrote: > Doorbell emulation for KVM on PAPR guests is broken as support for DPDES > was not added in initial patch series [1]. > Add DPDES support and doorbell handling support for V2 API. > > [1] lore.kernel.org/linuxppc-dev/20230914030600.16993-1-jniet...@gmail.com > > Changes in v2: > 1. Split DPDES support into its own patch > > [...] Applied to powerpc/topic/ppc-kvm. [1/2] arch/powerpc/kvm: Add DPDES support in helper library for Guest state buffer https://git.kernel.org/powerpc/c/55dfb8bed6fe8bda390cc71cca878d11a9407099 [2/2] arch/powerpc/kvm: Fix doorbell emulation for v2 API https://git.kernel.org/powerpc/c/54ec2bd9e0173b75daf84675d07c56584f96564b cheers
Re: [PATCH v9] arch/powerpc/kvm: Add support for reading VPA counters for pseries guests
On Mon, 20 May 2024 23:27:40 +0530, Gautam Menghani wrote: > PAPR hypervisor has introduced three new counters in the VPA area of > LPAR CPUs for KVM L2 guest (see [1] for terminology) observability - 2 > for context switches from host to guest and vice versa, and 1 counter > for getting the total time spent inside the KVM guest. Add a tracepoint > that enables reading the counters for use by ftrace/perf. Note that this > tracepoint is only available for nestedv2 API (i.e, KVM on PowerVM). > > [...] Applied to powerpc/topic/ppc-kvm. [1/1] arch/powerpc/kvm: Add support for reading VPA counters for pseries guests https://git.kernel.org/powerpc/c/e1f288d2f9c69bb8965db9fb99a19b58231a00dd cheers
Re: [PATCH v2 0/8] KVM: PPC: Book3S HV: Nested guest migration fixes
On Wed, 05 Jun 2024 13:06:00 +, Shivaprasad G Bhat wrote: > The series fixes the issues exposed by the kvm-unit-tests[1] > sprs-migration test. > > The SDAR, MMCR3 were seen to have some typo/refactoring bugs. > The first two patches fix them. > > The remaining patches take care of save-restoring the guest > state elements for DEXCR, HASHKEYR and HASHPKEYR SPRs with PHYP > during entry-exit. The KVM_PPC_REG too for them are missing which > are added for use by the QEMU. > > [...] Applied to powerpc/topic/ppc-kvm. [1/8] KVM: PPC: Book3S HV: Fix the set_one_reg for MMCR3 https://git.kernel.org/powerpc/c/f9ca6a10be20479d526f27316cc32cfd1785ed39 [2/8] KVM: PPC: Book3S HV: Fix the get_one_reg of SDAR https://git.kernel.org/powerpc/c/009f6f42c67e9de737d6d3d199f92b21a8cb9622 [3/8] KVM: PPC: Book3S HV: Add one-reg interface for DEXCR register https://git.kernel.org/powerpc/c/1a1e6865f516696adcf6e94f286c7a0f84d78df3 [4/8] KVM: PPC: Book3S HV nestedv2: Keep nested guest DEXCR in sync https://git.kernel.org/powerpc/c/2d6be3ca3276ab30fb14f285d400461a718d45e7 [5/8] KVM: PPC: Book3S HV: Add one-reg interface for HASHKEYR register https://git.kernel.org/powerpc/c/e9eb790b25577a15d3f450ed585c59048e4e6c44 [6/8] KVM: PPC: Book3S HV nestedv2: Keep nested guest HASHKEYR in sync https://git.kernel.org/powerpc/c/1e97c1eb785fe2dc863c2bd570030d6fcf4b5e5b [7/8] KVM: PPC: Book3S HV: Add one-reg interface for HASHPKEYR register https://git.kernel.org/powerpc/c/9a0d2f4995ddde3022c54e43f9ece4f71f76f6e8 [8/8] KVM: PPC: Book3S HV nestedv2: Keep nested guest HASHPKEYR in sync https://git.kernel.org/powerpc/c/0b65365f3fa95c2c5e2094739151a05cabb3c48a cheers
Re: [PATCH] tools/perf: Handle perftool-testsuite_probe testcases fail when kernel debuginfo is not present
> On 20 Jun 2024, at 2:03 PM, James Clark wrote: > > > > On 18/06/2024 11:44, James Clark wrote: >> >> >> On 17/06/2024 17:47, Athira Rajeev wrote: >>> >>> On 17 Jun 2024, at 8:30 PM, James Clark wrote: On 17/06/2024 13:21, Athira Rajeev wrote: > Running "perftool-testsuite_probe" fails as below: > > ./perf test -v "perftool-testsuite_probe" > 83: perftool-testsuite_probe : FAILED > > There are three fails: > > 1. Regexp not found: "\s*probe:inode_permission(?:_\d+)?\s+\(on > inode_permission(?:[:\+][0-9A-Fa-f]+)?@.+\)" > -- [ FAIL ] -- perf_probe :: test_adding_kernel :: listing added probe > :: perf probe -l (output regexp parsing) > On a machine where NO_DEBUGINFO gets set, this one skips for me. But on a machine where there _is_ debug info this test still fails. But in both cases the probe looks like it was added successfully. So I'm wondering if this one does need to be skipped, or it's just always failing? Do you have this test passing anywhere where there is debug info? The list command looks like it successfully lists the probe for me in both cases, it just doesn't have an address on the end: perf list 'probe:*' probe:inode_permission (on inode_permission) Does the missing address mean anything or is it just not handled properly by the test? Ironically the machine that _does_ pass the debug info test also prints this, but it looks like it still adds and lists the probe correctly: perf probe -l probe:* Failed to find debug information for address 0x80008047ac30 probe:inode_permission (on inode_permission) >>> >>> Hi James, >>> >>> Thanks for checking this patch. >>> >>> In environment where kernel is compiled with debuginfo: >>> >>> 1) Add probe point >>> >>> # ./perf probe --add inode_permission >>> Added new event: >>> probe:inode_permission (on inode_permission) >>> >>> You can now use it in all perf tools, such as: >>> >>> perf record -e probe:inode_permission -aR sleep 1 >>> >>> >>> 2) Check using perf probe -l >>> >>> # ./perf probe -l >>> probe:inode_permission (on inode_permission:2@fs/namei.c) >>> >>> With debuginfo, the result has additional info. >>> The test looks for matching pattern >>> "\s*probe:inode_permission(?:_\d+)?\s+\(on >>> inode_permission(?:[:\+][0-9A-Fa-f]+)?@.+\)” in result >>> where it is expecting "inode_permission:2@fs/namei.c” . The “@fs/namei.c” >>> info needs debuginfo here. >>> >> >> Hi Athira, >> >> Maybe there is a real bug and this patch is ok to go in and we should leave >> it as failing. Probe -L shows there is debug info available for >> inode_permission: >> >> $ ./perf probe -L inode_permission >> >> >> 0 int inode_permission(struct mnt_idmap *idmap, >> struct inode *inode, int mask) >> ... more source code ... >> >> But probe -l has an error which could be related to the following >> line not showing the filename details: >> >> $ ./perf probe -l >> >> Failed to find debug information for address 0x80008047ac30 >>probe:inode_permission (on inode_permission) >> >> I'm running a clang kernel and sometimes I see issues with debug >> info or toolchain stuff, that could be the reason. >> >>> The function I am using in patch to check for debuginfo >>> (skip_if_no_debuginfo) is from "tests/shell/lib/probe_vfs_getname.sh" >>> >>> skip_if_no_debuginfo() { >>>add_probe_vfs_getname -v 2>&1 | grep -E -q "^(Failed to find the >>> path for the kernel|Debuginfo-analysis is not supported)|(file has no debug >>> information)" && return 2 >>>return 1 >>> } >>> >>> So the debuginfo test passes in your case since the log has "Failed to find >>> debug information” which is not present in above grep string. >>> >> >> It passes because there is debug info for getname_flags() which is what the >> debug info check looks for. After some greps and seds it ultimately does this >> which succeeds: >> >> $ perf probe "vfs_getname=getname_flags:72 pathname=result->name:string" >> >> Added new event: >>probe:vfs_getname(on getname_flags:72 with >> pathname=result->name:string) >> >> "Failed to find debug information for address" is only ever printed >> with "perf probe -l" when there are probes added. The stderr >> of that command is never piped into any grep anyway, which is why I >> see it on the test output. >> >> So "probe -L" is working but "probe -l" isn't. Ultimately it looks like a >> real >> issue and we should leave the failure in. >> > > To avoid confusion, by leave it in I mean this debuginfo patch is ok and > the failure I'm seeing is caused by something else. > > Reviewed-by: James Clark Thanks James for the Reviewed-by, Athira > >>> James, >>> >>> Only “perf probe -l” subtest fails with debuginfo enabled or other two >>> su
Re: [V4 00/16] Add data type profiling support for powerpc
> On 14 Jun 2024, at 10:56 PM, Athira Rajeev > wrote: > > The patchset from Namhyung added support for data type profiling > in perf tool. This enabled support to associate PMU samples to data > types they refer using DWARF debug information. With the upstream > perf, currently it possible to run perf report or perf annotate to > view the data type information on x86. > > Initial patchset posted here had changes need to enable data type > profiling support for powerpc. > > https://lore.kernel.org/all/6e09dc28-4a2e-49d8-a2b5-ffb3396a9...@csgroup.eu/T/ > > Main change were: > 1. powerpc instruction nmemonic table to associate load/store > instructions with move_ops which is use to identify if instruction > is a memory access one. > 2. To get register number and access offset from the given > instruction, code uses fields from "struct arch" -> objump. > Added entry for powerpc here. > 3. A get_arch_regnum to return register number from the > register name string. > > But the apporach used in the initial patchset used parsing of > disassembled code which the current perf tool implementation does. > > Example: lwz r10,0(r9) > > This line "lwz r10,0(r9)" is parsed to extract instruction name, > registers names and offset. Also to find whether there is a memory > reference in the operands, "memory_ref_char" field of objdump is used. > For x86, "(" is used as memory_ref_char to tackle instructions of the > form "mov (%rax), %rcx". > > In case of powerpc, not all instructions using "(" are the only memory > instructions. Example, above instruction can also be of extended form (X > form) "lwzx r10,0,r19". Inorder to easy identify the instruction category > and extract the source/target registers, second patchset added support to use > raw instruction. With raw instruction, macros are added to extract opcode > and register fields. > Link to second patchset: > https://lore.kernel.org/all/20240506121906.76639-1-atraj...@linux.vnet.ibm.com/ > > Example representation using --show-raw-insn in objdump gives result: > > 38 01 81 e8 ld r4,312(r1) > > Here "38 01 81 e8" is the raw instruction representation. In powerpc, > this translates to instruction form: "ld RT,DS(RA)" and binary code > as: > _ > | 58 | RT | RA | DS | | > - > 06 1116 30 31 > > Second patchset used "objdump" again to read the raw instruction. > But since there is no need to disassemble and binary code can be read > directly from the DSO, third patchset (ie this patchset) uses below > apporach. The apporach preferred in powerpc to parse sample for data > type profiling in V3 patchset is: > - Read directly from DSO using dso__data_read_offset > - If that fails for any case, fallback to using libcapstone > - If libcapstone is not supported, approach will use objdump > > Patchset adds support to pick the opcode and reg fields from this > raw/binary instruction code. This approach came in from review comment > by Segher Boessenkool and Christophe for the initial patchset. > > Apart from that, instruction tracking is enabled for powerpc and > support function is added to find variables defined as registers > Example, in powerpc, below two registers are > defined to represent variable: > 1. r13: represents local_paca > register struct paca_struct *local_paca asm("r13"); > > 2. r1: represents stack_pointer > register void *__stack_pointer asm("r1"); > > These are handled in this patchset. > > - Patch 1 is to rearrange register state type structures to header file > so that it can referred from other arch specific files > - Patch 2 is to make instruction tracking as a callback to"struct arch" > so that it can be implemented by other archs easily and defined in arch > specific files > - Patch 3 adds support to capture and parse raw instruction in powerpc > using dso__data_read_offset utility > - Patch 4 adds logic to support using objdump when doing default "perf > report" or "perf annotate" since it that needs disassembled instruction. > - Patch 5 adds disasm_line__parse to parse raw instruction for powerpc > - Patch 6 update parameters for reg extract functions to use raw > instruction on powerpc > - Patch 7 add support to identify memory instructions of opcode 31 in > powerpc > - Patch 8 adds more instructions to support instruction tracking in powerpc > - Patch 9 and 10 handles instruction tracking for powerpc. > - Patch 11, 12 and 13 add support to use libcapstone in powerpc > - Patch 14 and patch 15 handles support to find global register variables > - Patch 16 handles insn-stat option for perf annotate > > Note: > - There are remaining unknowns (25%) as seen in annotate Instruction stats > below. > - This patchset is not tested on powerpc32. In next step of enhancements > along with handling remaining unknowns, plan to cover powerpc32 changes > based on how testing goes. > > With the current patchset: > > ./
[PATCH 00/15] linux system call fixes
From: Arnd Bergmann I'm working on cleanup series for Linux system call handling, trying to unify some of the architecture specific code there among other things. In the process, I came across a number of bugs that are ABI relevant, so I'm trying to merge these first. I found all of these by inspection, not by running the code, so any extra review would help. I assume some of the issues were already caught by existing LTP tests, while for others we could add a test. Again, I did not check what is already there. The sync_file_range and fadvise64_64 changes on sh, csky and hexagon are likely to also require changes in the libc implementation. Once the patches are reviewed, I plan to merge my changes as bugfixes through the asm-generic tree, but architecture maintainers can also pick them up directly to speed up the bugfix. Arnd Cc: linux-a...@vger.kernel.org Cc: linux-ker...@vger.kernel.org Cc: Thomas Bogendoerfer Cc: linux-m...@vger.kernel.org Cc: Helge Deller Cc: linux-par...@vger.kernel.org Cc: "David S. Miller" Cc: Andreas Larsson Cc: sparcli...@vger.kernel.org Cc: Michael Ellerman Cc: Nicholas Piggin Cc: Christophe Leroy Cc: Naveen N. Rao Cc: linuxppc-dev@lists.ozlabs.org Cc: Brian Cain Cc: linux-hexa...@vger.kernel.org Cc: Guo Ren Cc: linux-c...@vger.kernel.org Cc: Heiko Carstens Cc: linux-s...@vger.kernel.org Cc: Rich Felker Cc: John Paul Adrian Glaubitz Cc: linux...@vger.kernel.org Cc: "H. Peter Anvin" Cc: Alexander Viro Cc: Christian Brauner Cc: linux-fsde...@vger.kernel.org Cc: libc-al...@sourceware.org Cc: m...@lists.openwall.com Cc: l...@lists.linux.it Arnd Bergmann (15): ftruncate: pass a signed offset syscalls: fix compat_sys_io_pgetevents_time64 usage mips: fix compat_sys_lseek syscall sparc: fix old compat_sys_select() sparc: fix compat recv/recvfrom syscalls parisc: use correct compat recv/recvfrom syscalls parisc: use generic sys_fanotify_mark implementation powerpc: restore some missing spu syscalls sh: rework sync_file_range ABI csky, hexagon: fix broken sys_sync_file_range hexagon: fix fadvise64_64 calling conventions s390: remove native mmap2() syscall syscalls: mmap(): use unsigned offset type consistently asm-generic: unistd: fix time32 compat syscall handling linux/syscalls.h: add missing __user annotations arch/arm64/include/asm/unistd32.h | 2 +- arch/csky/include/uapi/asm/unistd.h | 1 + arch/csky/kernel/syscall.c| 2 +- arch/hexagon/include/asm/syscalls.h | 6 + arch/hexagon/include/uapi/asm/unistd.h| 1 + arch/hexagon/kernel/syscalltab.c | 7 + arch/loongarch/kernel/syscall.c | 2 +- arch/microblaze/kernel/sys_microblaze.c | 2 +- arch/mips/kernel/syscalls/syscall_n32.tbl | 2 +- arch/mips/kernel/syscalls/syscall_o32.tbl | 4 +- arch/parisc/Kconfig | 1 + arch/parisc/kernel/sys_parisc32.c | 9 - arch/parisc/kernel/syscalls/syscall.tbl | 6 +- arch/powerpc/kernel/syscalls/syscall.tbl | 6 +- arch/riscv/kernel/sys_riscv.c | 4 +- arch/s390/kernel/syscall.c| 27 --- arch/s390/kernel/syscalls/syscall.tbl | 2 +- arch/sh/kernel/sys_sh32.c | 11 ++ arch/sh/kernel/syscalls/syscall.tbl | 3 +- arch/sparc/kernel/sys32.S | 221 -- arch/sparc/kernel/syscalls/syscall.tbl| 8 +- arch/x86/entry/syscalls/syscall_32.tbl| 2 +- fs/open.c | 4 +- include/asm-generic/syscalls.h| 2 +- include/linux/compat.h| 2 +- include/linux/syscalls.h | 20 +- include/uapi/asm-generic/unistd.h | 146 +- 27 files changed, 160 insertions(+), 343 deletions(-) create mode 100644 arch/hexagon/include/asm/syscalls.h -- 2.39.2
[PATCH 01/15] ftruncate: pass a signed offset
From: Arnd Bergmann The old ftruncate() syscall, using the 32-bit off_t misses a sign extension when called in compat mode on 64-bit architectures. As a result, passing a negative length accidentally succeeds in truncating to file size between 2GiB and 4GiB. Changing the type of the compat syscall to the signed compat_off_t changes the behavior so it instead returns -EINVAL. The native entry point, the truncate() syscall and the corresponding loff_t based variants are all correct already and do not suffer from this mistake. Fixes: 3f6d078d4acc ("fix compat truncate/ftruncate") Cc: sta...@vger.kernel.org Signed-off-by: Arnd Bergmann --- fs/open.c| 4 ++-- include/linux/compat.h | 2 +- include/linux/syscalls.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/open.c b/fs/open.c index 89cafb572061..50e45bc7c4d8 100644 --- a/fs/open.c +++ b/fs/open.c @@ -202,13 +202,13 @@ long do_sys_ftruncate(unsigned int fd, loff_t length, int small) return error; } -SYSCALL_DEFINE2(ftruncate, unsigned int, fd, unsigned long, length) +SYSCALL_DEFINE2(ftruncate, unsigned int, fd, off_t, length) { return do_sys_ftruncate(fd, length, 1); } #ifdef CONFIG_COMPAT -COMPAT_SYSCALL_DEFINE2(ftruncate, unsigned int, fd, compat_ulong_t, length) +COMPAT_SYSCALL_DEFINE2(ftruncate, unsigned int, fd, compat_off_t, length) { return do_sys_ftruncate(fd, length, 1); } diff --git a/include/linux/compat.h b/include/linux/compat.h index 233f61ec8afc..56cebaff0c91 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -608,7 +608,7 @@ asmlinkage long compat_sys_fstatfs(unsigned int fd, asmlinkage long compat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct compat_statfs64 __user *buf); asmlinkage long compat_sys_truncate(const char __user *, compat_off_t); -asmlinkage long compat_sys_ftruncate(unsigned int, compat_ulong_t); +asmlinkage long compat_sys_ftruncate(unsigned int, compat_off_t); /* No generic prototype for truncate64, ftruncate64, fallocate */ asmlinkage long compat_sys_openat(int dfd, const char __user *filename, int flags, umode_t mode); diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 9104952d323d..ba9337709878 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -418,7 +418,7 @@ asmlinkage long sys_listmount(const struct mnt_id_req __user *req, u64 __user *mnt_ids, size_t nr_mnt_ids, unsigned int flags); asmlinkage long sys_truncate(const char __user *path, long length); -asmlinkage long sys_ftruncate(unsigned int fd, unsigned long length); +asmlinkage long sys_ftruncate(unsigned int fd, off_t length); #if BITS_PER_LONG == 32 asmlinkage long sys_truncate64(const char __user *path, loff_t length); asmlinkage long sys_ftruncate64(unsigned int fd, loff_t length); -- 2.39.2
[PATCH 02/15] syscalls: fix compat_sys_io_pgetevents_time64 usage
From: Arnd Bergmann Using sys_io_pgetevents() as the entry point for compat mode tasks works almost correctly, but misses the sign extension for the min_nr and nr arguments. This was addressed on parisc by switching to compat_sys_io_pgetevents_time64() in commit 6431e92fc827 ("parisc: io_pgetevents_time64() needs compat syscall in 32-bit compat mode"), as well as by using more sophisticated system call wrappers on x86 and s390. However, arm64, mips, powerpc, sparc and riscv still have the same bug. Changes all of them over to use compat_sys_io_pgetevents_time64() like parisc already does. This was clearly the intention when the function was originally added, but it got hooked up incorrectly in the tables. Cc: sta...@vger.kernel.org Fixes: 48166e6ea47d ("y2038: add 64-bit time_t syscalls to all 32-bit architectures") Signed-off-by: Arnd Bergmann --- arch/arm64/include/asm/unistd32.h | 2 +- arch/mips/kernel/syscalls/syscall_n32.tbl | 2 +- arch/mips/kernel/syscalls/syscall_o32.tbl | 2 +- arch/powerpc/kernel/syscalls/syscall.tbl | 2 +- arch/s390/kernel/syscalls/syscall.tbl | 2 +- arch/sparc/kernel/syscalls/syscall.tbl| 2 +- arch/x86/entry/syscalls/syscall_32.tbl| 2 +- include/uapi/asm-generic/unistd.h | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h index 266b96acc014..1386e8e751f2 100644 --- a/arch/arm64/include/asm/unistd32.h +++ b/arch/arm64/include/asm/unistd32.h @@ -840,7 +840,7 @@ __SYSCALL(__NR_pselect6_time64, compat_sys_pselect6_time64) #define __NR_ppoll_time64 414 __SYSCALL(__NR_ppoll_time64, compat_sys_ppoll_time64) #define __NR_io_pgetevents_time64 416 -__SYSCALL(__NR_io_pgetevents_time64, sys_io_pgetevents) +__SYSCALL(__NR_io_pgetevents_time64, compat_sys_io_pgetevents_time64) #define __NR_recvmmsg_time64 417 __SYSCALL(__NR_recvmmsg_time64, compat_sys_recvmmsg_time64) #define __NR_mq_timedsend_time64 418 diff --git a/arch/mips/kernel/syscalls/syscall_n32.tbl b/arch/mips/kernel/syscalls/syscall_n32.tbl index cc869f5d5693..953f5b7dc723 100644 --- a/arch/mips/kernel/syscalls/syscall_n32.tbl +++ b/arch/mips/kernel/syscalls/syscall_n32.tbl @@ -354,7 +354,7 @@ 412n32 utimensat_time64sys_utimensat 413n32 pselect6_time64 compat_sys_pselect6_time64 414n32 ppoll_time64compat_sys_ppoll_time64 -416n32 io_pgetevents_time64sys_io_pgetevents +416n32 io_pgetevents_time64compat_sys_io_pgetevents_time64 417n32 recvmmsg_time64 compat_sys_recvmmsg_time64 418n32 mq_timedsend_time64 sys_mq_timedsend 419n32 mq_timedreceive_time64 sys_mq_timedreceive diff --git a/arch/mips/kernel/syscalls/syscall_o32.tbl b/arch/mips/kernel/syscalls/syscall_o32.tbl index 008ebe60263e..85751c9b9cdb 100644 --- a/arch/mips/kernel/syscalls/syscall_o32.tbl +++ b/arch/mips/kernel/syscalls/syscall_o32.tbl @@ -403,7 +403,7 @@ 412o32 utimensat_time64sys_utimensat sys_utimensat 413o32 pselect6_time64 sys_pselect6 compat_sys_pselect6_time64 414o32 ppoll_time64sys_ppoll compat_sys_ppoll_time64 -416o32 io_pgetevents_time64sys_io_pgetevents sys_io_pgetevents +416o32 io_pgetevents_time64sys_io_pgetevents compat_sys_io_pgetevents_time64 417o32 recvmmsg_time64 sys_recvmmsg compat_sys_recvmmsg_time64 418o32 mq_timedsend_time64 sys_mq_timedsend sys_mq_timedsend 419o32 mq_timedreceive_time64 sys_mq_timedreceive sys_mq_timedreceive diff --git a/arch/powerpc/kernel/syscalls/syscall.tbl b/arch/powerpc/kernel/syscalls/syscall.tbl index 3656f1ca7a21..c6b0546b284d 100644 --- a/arch/powerpc/kernel/syscalls/syscall.tbl +++ b/arch/powerpc/kernel/syscalls/syscall.tbl @@ -502,7 +502,7 @@ 41232 utimensat_time64sys_utimensat sys_utimensat 41332 pselect6_time64 sys_pselect6 compat_sys_pselect6_time64 41432 ppoll_time64sys_ppoll compat_sys_ppoll_time64 -41632 io_pgetevents_time64sys_io_pgetevents sys_io_pgetevents +41632 io_pgetevents_time64sys_io_pgetevents compat_sys_io_pgetevents_time64 41732 recvmmsg_time64 sys_recvmmsg compat_sys_recvmmsg_time64 41832 mq_timedsend_time64 sys_mq_timedsend sys_mq_timedsend 41932 mq_timedreceive_time64 sys_mq_timedreceive sys_mq_timedreceive diff --git a/arch/s390/kernel
[PATCH 03/15] mips: fix compat_sys_lseek syscall
From: Arnd Bergmann This is almost compatible, but passing a negative offset should result in a EINVAL error, but on mips o32 compat mode would seek to a large 32-bit byte offset. Use compat_sys_lseek() to correctly sign-extend the argument. Signed-off-by: Arnd Bergmann --- arch/mips/kernel/syscalls/syscall_o32.tbl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/kernel/syscalls/syscall_o32.tbl b/arch/mips/kernel/syscalls/syscall_o32.tbl index 85751c9b9cdb..2439a2491cff 100644 --- a/arch/mips/kernel/syscalls/syscall_o32.tbl +++ b/arch/mips/kernel/syscalls/syscall_o32.tbl @@ -27,7 +27,7 @@ 17 o32 break sys_ni_syscall # 18 was sys_stat 18 o32 unused18sys_ni_syscall -19 o32 lseek sys_lseek +19 o32 lseek sys_lseek compat_sys_lseek 20 o32 getpid sys_getpid 21 o32 mount sys_mount 22 o32 umount sys_oldumount -- 2.39.2
[PATCH 04/15] sparc: fix old compat_sys_select()
From: Arnd Bergmann sparc has two identical select syscalls at numbers 93 and 230, respectively. During the conversion to the modern syscall.tbl format, the older one of the two broke in compat mode, and now refers to the native 64-bit syscall. Restore the correct behavior. This has very little effect, as glibc has been using the newer number anyway. Fixes: 6ff645dd683a ("sparc: add system call table generation support") Signed-off-by: Arnd Bergmann --- arch/sparc/kernel/syscalls/syscall.tbl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/sparc/kernel/syscalls/syscall.tbl b/arch/sparc/kernel/syscalls/syscall.tbl index b354139b40be..5e55f73f9880 100644 --- a/arch/sparc/kernel/syscalls/syscall.tbl +++ b/arch/sparc/kernel/syscalls/syscall.tbl @@ -117,7 +117,7 @@ 90 common dup2sys_dup2 91 32 setfsuid32 sys_setfsuid 92 common fcntl sys_fcntl compat_sys_fcntl -93 common select sys_select +93 common select sys_select compat_sys_select 94 32 setfsgid32 sys_setfsgid 95 common fsync sys_fsync 96 common setpriority sys_setpriority -- 2.39.2
[PATCH 05/15] sparc: fix compat recv/recvfrom syscalls
From: Arnd Bergmann sparc has the wrong compat version of recv() and recvfrom() for both the direct syscalls and socketcall(). The direct syscalls just need to use the compat version. For socketcall, the same thing could be done, but it seems better to completely remove the custom assembler code for it and just use the same implementation that everyone else has. Fixes: 1dacc76d0014 ("net/compat/wext: send different messages to compat tasks") Signed-off-by: Arnd Bergmann --- arch/sparc/kernel/sys32.S | 221 - arch/sparc/kernel/syscalls/syscall.tbl | 4 +- 2 files changed, 2 insertions(+), 223 deletions(-) diff --git a/arch/sparc/kernel/sys32.S b/arch/sparc/kernel/sys32.S index a45f0f31fe51..a3d308f2043e 100644 --- a/arch/sparc/kernel/sys32.S +++ b/arch/sparc/kernel/sys32.S @@ -18,224 +18,3 @@ sys32_mmap2: sethi %hi(sys_mmap), %g1 jmpl%g1 + %lo(sys_mmap), %g0 sllx %o5, 12, %o5 - - .align 32 - .globl sys32_socketcall -sys32_socketcall: /* %o0=call, %o1=args */ - cmp %o0, 1 - bl,pn %xcc, do_einval -cmp%o0, 18 - bg,pn %xcc, do_einval -sub%o0, 1, %o0 - sllx%o0, 5, %o0 - sethi %hi(__socketcall_table_begin), %g2 - or %g2, %lo(__socketcall_table_begin), %g2 - jmpl%g2 + %o0, %g0 -nop -do_einval: - retl -mov-EINVAL, %o0 - - .align 32 -__socketcall_table_begin: - - /* Each entry is exactly 32 bytes. */ -do_sys_socket: /* sys_socket(int, int, int) */ -1: ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(sys_socket), %g1 -2: ldswa [%o1 + 0x8] %asi, %o2 - jmpl%g1 + %lo(sys_socket), %g0 -3: ldswa [%o1 + 0x4] %asi, %o1 - nop - nop - nop -do_sys_bind: /* sys_bind(int fd, struct sockaddr *, int) */ -4: ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(sys_bind), %g1 -5: ldswa [%o1 + 0x8] %asi, %o2 - jmpl%g1 + %lo(sys_bind), %g0 -6: lduwa [%o1 + 0x4] %asi, %o1 - nop - nop - nop -do_sys_connect: /* sys_connect(int, struct sockaddr *, int) */ -7: ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(sys_connect), %g1 -8: ldswa [%o1 + 0x8] %asi, %o2 - jmpl%g1 + %lo(sys_connect), %g0 -9: lduwa [%o1 + 0x4] %asi, %o1 - nop - nop - nop -do_sys_listen: /* sys_listen(int, int) */ -10:ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(sys_listen), %g1 - jmpl%g1 + %lo(sys_listen), %g0 -11: ldswa [%o1 + 0x4] %asi, %o1 - nop - nop - nop - nop -do_sys_accept: /* sys_accept(int, struct sockaddr *, int *) */ -12:ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(sys_accept), %g1 -13:lduwa [%o1 + 0x8] %asi, %o2 - jmpl%g1 + %lo(sys_accept), %g0 -14: lduwa [%o1 + 0x4] %asi, %o1 - nop - nop - nop -do_sys_getsockname: /* sys_getsockname(int, struct sockaddr *, int *) */ -15:ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(sys_getsockname), %g1 -16:lduwa [%o1 + 0x8] %asi, %o2 - jmpl%g1 + %lo(sys_getsockname), %g0 -17: lduwa [%o1 + 0x4] %asi, %o1 - nop - nop - nop -do_sys_getpeername: /* sys_getpeername(int, struct sockaddr *, int *) */ -18:ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(sys_getpeername), %g1 -19:lduwa [%o1 + 0x8] %asi, %o2 - jmpl%g1 + %lo(sys_getpeername), %g0 -20: lduwa [%o1 + 0x4] %asi, %o1 - nop - nop - nop -do_sys_socketpair: /* sys_socketpair(int, int, int, int *) */ -21:ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(sys_socketpair), %g1 -22:ldswa [%o1 + 0x8] %asi, %o2 -23:lduwa [%o1 + 0xc] %asi, %o3 - jmpl%g1 + %lo(sys_socketpair), %g0 -24: ldswa [%o1 + 0x4] %asi, %o1 - nop - nop -do_sys_send: /* sys_send(int, void *, size_t, unsigned int) */ -25:ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(sys_send), %g1 -26:lduwa [%o1 + 0x8] %asi, %o2 -27:lduwa [%o1 + 0xc] %asi, %o3 - jmpl%g1 + %lo(sys_send), %g0 -28: lduwa [%o1 + 0x4] %asi, %o1 - nop - nop -do_sys_recv: /* sys_recv(int, void *, size_t, unsigned int) */ -29:ldswa [%o1 + 0x0] %asi, %o0 - sethi %hi(sys_recv), %g1 -30:lduwa [%o1 + 0x8] %asi, %o2 -31:lduwa [%o1 + 0xc] %asi, %o3 - jmpl%g1 + %lo(sys_recv), %g
[PATCH 06/15] parisc: use correct compat recv/recvfrom syscalls
From: Arnd Bergmann Johannes missed parisc back when he introduced the compat version of these syscalls, so receiving cmsg messages that require a compat conversion is still broken. Use the correct calls like the other architectures do. Fixes: 1dacc76d0014 ("net/compat/wext: send different messages to compat tasks") Signed-off-by: Arnd Bergmann --- arch/parisc/kernel/syscalls/syscall.tbl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/parisc/kernel/syscalls/syscall.tbl b/arch/parisc/kernel/syscalls/syscall.tbl index b13c21373974..39e67fab7515 100644 --- a/arch/parisc/kernel/syscalls/syscall.tbl +++ b/arch/parisc/kernel/syscalls/syscall.tbl @@ -108,7 +108,7 @@ 95 common fchown sys_fchown 96 common getpriority sys_getpriority 97 common setpriority sys_setpriority -98 common recvsys_recv +98 common recvsys_recv compat_sys_recv 99 common statfs sys_statfs compat_sys_statfs 100common fstatfs sys_fstatfs compat_sys_fstatfs 101common stat64 sys_stat64 @@ -135,7 +135,7 @@ 120common clone sys_clone_wrapper 121common setdomainname sys_setdomainname 122common sendfilesys_sendfile compat_sys_sendfile -123common recvfromsys_recvfrom +123common recvfromsys_recvfrom compat_sys_recvfrom 12432 adjtimexsys_adjtimex_time32 12464 adjtimexsys_adjtimex 125common mprotectsys_mprotect -- 2.39.2
[PATCH 07/15] parisc: use generic sys_fanotify_mark implementation
From: Arnd Bergmann The sys_fanotify_mark() syscall on parisc uses the reverse word order for the two halves of the 64-bit argument compared to all syscalls on all 32-bit architectures. As far as I can tell, the problem is that the function arguments on parisc are sorted backwards (26, 25, 24, 23, ...) compared to everyone else, so the calling conventions of using an even/odd register pair in native word order result in the lower word coming first in function arguments, matching the expected behavior on little-endian architectures. The system call conventions however ended up matching what the other 32-bit architectures do. A glibc cleanup in 2020 changed the userspace behavior in a way that handles all architectures consistently, but this inadvertently broke parisc32 by changing to the same method as everyone else. The change made it into glibc-2.35 and subsequently into debian 12 (bookworm), which is the latest stable release. This means we need to choose between reverting the glibc change or changing the kernel to match it again, but either hange will leave some systems broken. Pick the option that is more likely to help current and future users and change the kernel to match current glibc. This also means the behavior is now consistent across architectures, but it breaks running new kernels with old glibc builds before 2.35. Link: https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=d150181d73d9 Link: https://git.kernel.org/pub/scm/linux/kernel/git/history/history.git/commit/arch/parisc/kernel/sys_parisc.c?h=57b1dfbd5b4a39d Cc: Adhemerval Zanella Signed-off-by: Arnd Bergmann --- I found this through code inspection, please double-check to make sure I got the bug and the fix right. The alternative is to fix this by reverting glibc back to the unusual behavior. --- arch/parisc/Kconfig | 1 + arch/parisc/kernel/sys_parisc32.c | 9 - arch/parisc/kernel/syscalls/syscall.tbl | 2 +- 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index daafeb20f993..dc9b902de8ea 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -16,6 +16,7 @@ config PARISC select ARCH_HAS_UBSAN select ARCH_HAS_PTE_SPECIAL select ARCH_NO_SG_CHAIN + select ARCH_SPLIT_ARG64 if !64BIT select ARCH_SUPPORTS_HUGETLBFS if PA20 select ARCH_SUPPORTS_MEMORY_FAILURE select ARCH_STACKWALK diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c index 2a12a547b447..826c8e51b585 100644 --- a/arch/parisc/kernel/sys_parisc32.c +++ b/arch/parisc/kernel/sys_parisc32.c @@ -23,12 +23,3 @@ asmlinkage long sys32_unimplemented(int r26, int r25, int r24, int r23, current->comm, current->pid, r20); return -ENOSYS; } - -asmlinkage long sys32_fanotify_mark(compat_int_t fanotify_fd, compat_uint_t flags, - compat_uint_t mask0, compat_uint_t mask1, compat_int_t dfd, - const char __user * pathname) -{ - return sys_fanotify_mark(fanotify_fd, flags, - ((__u64)mask1 << 32) | mask0, -dfd, pathname); -} diff --git a/arch/parisc/kernel/syscalls/syscall.tbl b/arch/parisc/kernel/syscalls/syscall.tbl index 39e67fab7515..66dc406b12e4 100644 --- a/arch/parisc/kernel/syscalls/syscall.tbl +++ b/arch/parisc/kernel/syscalls/syscall.tbl @@ -364,7 +364,7 @@ 320common accept4 sys_accept4 321common prlimit64 sys_prlimit64 322common fanotify_init sys_fanotify_init -323common fanotify_mark sys_fanotify_mark sys32_fanotify_mark +323common fanotify_mark sys_fanotify_mark compat_sys_fanotify_mark 32432 clock_adjtime sys_clock_adjtime32 32464 clock_adjtime sys_clock_adjtime 325common name_to_handle_at sys_name_to_handle_at -- 2.39.2
[PATCH 08/15] powerpc: restore some missing spu syscalls
From: Arnd Bergmann A couple of system calls were inadventently removed from the table during a bugfix for 32-bit powerpc entry. Restore the original behavior. Fixes: e23750623835 ("powerpc/32: fix syscall wrappers with 64-bit arguments of unaligned register-pairs") Signed-off-by: Arnd Bergmann --- arch/powerpc/kernel/syscalls/syscall.tbl | 4 1 file changed, 4 insertions(+) diff --git a/arch/powerpc/kernel/syscalls/syscall.tbl b/arch/powerpc/kernel/syscalls/syscall.tbl index c6b0546b284d..ebae8415dfbb 100644 --- a/arch/powerpc/kernel/syscalls/syscall.tbl +++ b/arch/powerpc/kernel/syscalls/syscall.tbl @@ -230,8 +230,10 @@ 178nospu rt_sigsuspend sys_rt_sigsuspend compat_sys_rt_sigsuspend 17932 pread64 sys_ppc_pread64 compat_sys_ppc_pread64 17964 pread64 sys_pread64 +179spu pread64 sys_pread64 18032 pwrite64sys_ppc_pwrite64 compat_sys_ppc_pwrite64 18064 pwrite64sys_pwrite64 +180spu pwrite64sys_pwrite64 181common chown sys_chown 182common getcwd sys_getcwd 183common capget sys_capget @@ -246,6 +248,7 @@ 190common ugetrlimit sys_getrlimit compat_sys_getrlimit 19132 readahead sys_ppc_readahead compat_sys_ppc_readahead 19164 readahead sys_readahead +191spu readahead sys_readahead 19232 mmap2 sys_mmap2 compat_sys_mmap2 19332 truncate64 sys_ppc_truncate64 compat_sys_ppc_truncate64 19432 ftruncate64 sys_ppc_ftruncate64 compat_sys_ppc_ftruncate64 @@ -293,6 +296,7 @@ 232nospu set_tid_address sys_set_tid_address 23332 fadvise64 sys_ppc32_fadvise64 compat_sys_ppc32_fadvise64 23364 fadvise64 sys_fadvise64 +233spu fadvise64 sys_fadvise64 234nospu exit_group sys_exit_group 235nospu lookup_dcookie sys_ni_syscall 236common epoll_createsys_epoll_create -- 2.39.2
[PATCH 09/15] sh: rework sync_file_range ABI
From: Arnd Bergmann The unusual function calling conventions on superh ended up causing sync_file_range to have the wrong argument order, with the 'flags' argument getting sorted before 'nbytes' by the compiler. In userspace, I found that musl, glibc, uclibc and strace all expect the normal calling conventions with 'nbytes' last, so changing the kernel to match them should make all of those work. In order to be able to also fix libc implementations to work with existing kernels, they need to be able to tell which ABI is used. An easy way to do this is to add yet another system call using the sync_file_range2 ABI that works the same on all architectures. Old user binaries can now work on new kernels, and new binaries can try the new sync_file_range2() to work with new kernels or fall back to the old sync_file_range() version if that doesn't exist. Cc: sta...@vger.kernel.org Fixes: 75c92acdd5b1 ("sh: Wire up new syscalls.") Signed-off-by: Arnd Bergmann --- arch/sh/kernel/sys_sh32.c | 11 +++ arch/sh/kernel/syscalls/syscall.tbl | 3 ++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/arch/sh/kernel/sys_sh32.c b/arch/sh/kernel/sys_sh32.c index 9dca568509a5..d5a4f7c697d8 100644 --- a/arch/sh/kernel/sys_sh32.c +++ b/arch/sh/kernel/sys_sh32.c @@ -59,3 +59,14 @@ asmlinkage int sys_fadvise64_64_wrapper(int fd, u32 offset0, u32 offset1, (u64)len0 << 32 | len1, advice); #endif } + +/* + * swap the arguments the way that libc wants it instead of + * moving flags ahead of the 64-bit nbytes argument + */ +SYSCALL_DEFINE6(sh_sync_file_range6, int, fd, SC_ARG64(offset), +SC_ARG64(nbytes), unsigned int, flags) +{ +return ksys_sync_file_range(fd, SC_VAL64(loff_t, offset), +SC_VAL64(loff_t, nbytes), flags); +} diff --git a/arch/sh/kernel/syscalls/syscall.tbl b/arch/sh/kernel/syscalls/syscall.tbl index bbf83a2db986..c55fd7696d40 100644 --- a/arch/sh/kernel/syscalls/syscall.tbl +++ b/arch/sh/kernel/syscalls/syscall.tbl @@ -321,7 +321,7 @@ 311common set_robust_list sys_set_robust_list 312common get_robust_list sys_get_robust_list 313common splice sys_splice -314common sync_file_range sys_sync_file_range +314common sync_file_range sys_sh_sync_file_range6 315common tee sys_tee 316common vmsplicesys_vmsplice 317common move_pages sys_move_pages @@ -395,6 +395,7 @@ 385common pkey_alloc sys_pkey_alloc 386common pkey_free sys_pkey_free 387common rseqsys_rseq +388common sync_file_range2sys_sync_file_range2 # room for arch specific syscalls 393common semget sys_semget 394common semctl sys_semctl -- 2.39.2
[PATCH 10/15] csky, hexagon: fix broken sys_sync_file_range
From: Arnd Bergmann Both of these architectures require u64 function arguments to be passed in even/odd pairs of registers or stack slots, which in case of sync_file_range would result in a seven-argument system call that is not currently possible. The system call is therefore incompatible with all existing binaries. While it would be possible to implement support for seven arguments like on mips, it seems better to use a six-argument version, either with the normal argument order but misaligned as on most architectures or with the reordered sync_file_range2() calling conventions as on arm and powerpc. Cc: sta...@vger.kernel.org Signed-off-by: Arnd Bergmann --- arch/csky/include/uapi/asm/unistd.h| 1 + arch/hexagon/include/uapi/asm/unistd.h | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/csky/include/uapi/asm/unistd.h b/arch/csky/include/uapi/asm/unistd.h index 7ff6a2466af1..e0594b6370a6 100644 --- a/arch/csky/include/uapi/asm/unistd.h +++ b/arch/csky/include/uapi/asm/unistd.h @@ -6,6 +6,7 @@ #define __ARCH_WANT_SYS_CLONE3 #define __ARCH_WANT_SET_GET_RLIMIT #define __ARCH_WANT_TIME32_SYSCALLS +#define __ARCH_WANT_SYNC_FILE_RANGE2 #include #define __NR_set_thread_area (__NR_arch_specific_syscall + 0) diff --git a/arch/hexagon/include/uapi/asm/unistd.h b/arch/hexagon/include/uapi/asm/unistd.h index 432c4db1b623..21ae22306b5d 100644 --- a/arch/hexagon/include/uapi/asm/unistd.h +++ b/arch/hexagon/include/uapi/asm/unistd.h @@ -36,5 +36,6 @@ #define __ARCH_WANT_SYS_VFORK #define __ARCH_WANT_SYS_FORK #define __ARCH_WANT_TIME32_SYSCALLS +#define __ARCH_WANT_SYNC_FILE_RANGE2 #include -- 2.39.2
[PATCH 11/15] hexagon: fix fadvise64_64 calling conventions
From: Arnd Bergmann fadvise64_64() has two 64-bit arguments at the wrong alignment for hexagon, which turns them into a 7-argument syscall that is not supported by Linux. The downstream musl port for hexagon actually asks for a 6-argument version the same way we do it on arm, csky, powerpc, so make the kernel do it the same way to avoid having to change both. Link: https://github.com/quic/musl/blob/hexagon/arch/hexagon/syscall_arch.h#L78 Cc: sta...@vger.kernel.org Signed-off-by: Arnd Bergmann --- arch/hexagon/include/asm/syscalls.h | 6 ++ arch/hexagon/kernel/syscalltab.c| 7 +++ 2 files changed, 13 insertions(+) create mode 100644 arch/hexagon/include/asm/syscalls.h diff --git a/arch/hexagon/include/asm/syscalls.h b/arch/hexagon/include/asm/syscalls.h new file mode 100644 index ..40f2d08bec92 --- /dev/null +++ b/arch/hexagon/include/asm/syscalls.h @@ -0,0 +1,6 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#include + +asmlinkage long sys_hexagon_fadvise64_64(int fd, int advice, + u32 a2, u32 a3, u32 a4, u32 a5); diff --git a/arch/hexagon/kernel/syscalltab.c b/arch/hexagon/kernel/syscalltab.c index 0fadd582cfc7..5d98bdc494ec 100644 --- a/arch/hexagon/kernel/syscalltab.c +++ b/arch/hexagon/kernel/syscalltab.c @@ -14,6 +14,13 @@ #undef __SYSCALL #define __SYSCALL(nr, call) [nr] = (call), +SYSCALL_DEFINE6(hexagon_fadvise64_64, int, fd, int, advice, + SC_ARG64(offset), SC_ARG64(len)) +{ + return ksys_fadvise64_64(fd, SC_VAL64(loff_t, offset), SC_VAL64(loff_t, len), advice); +} +#define sys_fadvise64_64 sys_hexagon_fadvise64_64 + void *sys_call_table[__NR_syscalls] = { #include }; -- 2.39.2
[PATCH 12/15] s390: remove native mmap2() syscall
From: Arnd Bergmann The mmap2() syscall has never been used on 64-bit s390x and should have been removed as part of 5a79859ae0f3 ("s390: remove 31 bit support"). Remove it now. Signed-off-by: Arnd Bergmann --- arch/s390/kernel/syscall.c | 27 --- 1 file changed, 27 deletions(-) diff --git a/arch/s390/kernel/syscall.c b/arch/s390/kernel/syscall.c index dc2355c623d6..50cbcbbaa03d 100644 --- a/arch/s390/kernel/syscall.c +++ b/arch/s390/kernel/syscall.c @@ -38,33 +38,6 @@ #include "entry.h" -/* - * Perform the mmap() system call. Linux for S/390 isn't able to handle more - * than 5 system call parameters, so this system call uses a memory block - * for parameter passing. - */ - -struct s390_mmap_arg_struct { - unsigned long addr; - unsigned long len; - unsigned long prot; - unsigned long flags; - unsigned long fd; - unsigned long offset; -}; - -SYSCALL_DEFINE1(mmap2, struct s390_mmap_arg_struct __user *, arg) -{ - struct s390_mmap_arg_struct a; - int error = -EFAULT; - - if (copy_from_user(&a, arg, sizeof(a))) - goto out; - error = ksys_mmap_pgoff(a.addr, a.len, a.prot, a.flags, a.fd, a.offset); -out: - return error; -} - #ifdef CONFIG_SYSVIPC /* * sys_ipc() is the de-multiplexer for the SysV IPC calls. -- 2.39.2
[PATCH 13/15] syscalls: mmap(): use unsigned offset type consistently
From: Arnd Bergmann Most architectures that implement the old-style mmap() with byte offset use 'unsigned long' as the type for that offset, but microblaze and riscv have the off_t type that is shared with userspace, matching the prototype in include/asm-generic/syscalls.h. Make this consistent by using an unsigned argument everywhere. This changes the behavior slightly, as the argument is shifted to a page number, and an user input with the top bit set would result in a negative page offset rather than a large one as we use elsewhere. For riscv, the 32-bit sys_mmap2() definition actually used a custom type that is different from the global declaration, but this was missed due to an incorrect type check. Signed-off-by: Arnd Bergmann --- arch/csky/kernel/syscall.c | 2 +- arch/loongarch/kernel/syscall.c | 2 +- arch/microblaze/kernel/sys_microblaze.c | 2 +- arch/riscv/kernel/sys_riscv.c | 4 ++-- include/asm-generic/syscalls.h | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/csky/kernel/syscall.c b/arch/csky/kernel/syscall.c index 3d30e58a45d2..4540a271ee39 100644 --- a/arch/csky/kernel/syscall.c +++ b/arch/csky/kernel/syscall.c @@ -20,7 +20,7 @@ SYSCALL_DEFINE6(mmap2, unsigned long, prot, unsigned long, flags, unsigned long, fd, - off_t, offset) + unsigned long, offset) { if (unlikely(offset & (~PAGE_MASK >> 12))) return -EINVAL; diff --git a/arch/loongarch/kernel/syscall.c b/arch/loongarch/kernel/syscall.c index b4c5acd7aa3b..8801611143ab 100644 --- a/arch/loongarch/kernel/syscall.c +++ b/arch/loongarch/kernel/syscall.c @@ -22,7 +22,7 @@ #define __SYSCALL(nr, call)[nr] = (call), SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len, unsigned long, - prot, unsigned long, flags, unsigned long, fd, off_t, offset) + prot, unsigned long, flags, unsigned long, fd, unsigned long, offset) { if (offset & ~PAGE_MASK) return -EINVAL; diff --git a/arch/microblaze/kernel/sys_microblaze.c b/arch/microblaze/kernel/sys_microblaze.c index ed9f34da1a2a..0850b099f300 100644 --- a/arch/microblaze/kernel/sys_microblaze.c +++ b/arch/microblaze/kernel/sys_microblaze.c @@ -35,7 +35,7 @@ SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len, unsigned long, prot, unsigned long, flags, unsigned long, fd, - off_t, pgoff) + unsigned long, pgoff) { if (pgoff & ~PAGE_MASK) return -EINVAL; diff --git a/arch/riscv/kernel/sys_riscv.c b/arch/riscv/kernel/sys_riscv.c index 64155323cc92..d77afe05578f 100644 --- a/arch/riscv/kernel/sys_riscv.c +++ b/arch/riscv/kernel/sys_riscv.c @@ -23,7 +23,7 @@ static long riscv_sys_mmap(unsigned long addr, unsigned long len, #ifdef CONFIG_64BIT SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len, unsigned long, prot, unsigned long, flags, - unsigned long, fd, off_t, offset) + unsigned long, fd, unsigned long, offset) { return riscv_sys_mmap(addr, len, prot, flags, fd, offset, 0); } @@ -32,7 +32,7 @@ SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len, #if defined(CONFIG_32BIT) || defined(CONFIG_COMPAT) SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len, unsigned long, prot, unsigned long, flags, - unsigned long, fd, off_t, offset) + unsigned long, fd, unsigned long, offset) { /* * Note that the shift for mmap2 is constant (12), diff --git a/include/asm-generic/syscalls.h b/include/asm-generic/syscalls.h index 933ca6581aba..fabcefe8a80a 100644 --- a/include/asm-generic/syscalls.h +++ b/include/asm-generic/syscalls.h @@ -19,7 +19,7 @@ asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, #ifndef sys_mmap asmlinkage long sys_mmap(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, - unsigned long fd, off_t pgoff); + unsigned long fd, unsigned long off); #endif #ifndef sys_rt_sigreturn -- 2.39.2
[PATCH 14/15] asm-generic: unistd: fix time32 compat syscall handling
From: Arnd Bergmann arch/riscv/ appears to have accidentally enabled the compat time32 syscalls in 64-bit kernels even though the native 32-bit ABI does not expose those. Address this by adding another level of indirection, checking for both the target ABI (32 or 64) and the __ARCH_WANT_TIME32_SYSCALLS macro. The macro arguments are meant to follow the syscall.tbl format, the idea here is that by the end of the series, all other syscalls are changed to the same format to make it possible to move all architectures over to generating the system call table consistently. Only this patch needs to be backported though. Cc: sta...@vger.kernel.org # v5.19+ Fixes: 7eb6369d7acf ("RISC-V: Add support for rv32 userspace via COMPAT") Signed-off-by: Arnd Bergmann --- include/uapi/asm-generic/unistd.h | 146 +++--- 1 file changed, 94 insertions(+), 52 deletions(-) diff --git a/include/uapi/asm-generic/unistd.h b/include/uapi/asm-generic/unistd.h index 3fdaa573d661..e47c966557d0 100644 --- a/include/uapi/asm-generic/unistd.h +++ b/include/uapi/asm-generic/unistd.h @@ -16,10 +16,32 @@ #define __SYSCALL(x, y) #endif +#ifndef __SC +#define __SC(_cond, _nr, _sys) __SYSCALL_ ## _cond (_nr, _sys) +#endif + +#ifndef __SCC +#ifdef __SYSCALL_COMPAT +#define __SCC(_cond, _nr, _sys, _comp) __SC(_cond, _nr, _comp) +#else +#define __SCC(_cond, _nr, _sys, _comp) __SC(_cond, _nr, _sys) +#endif +#endif + #if __BITS_PER_LONG == 32 || defined(__SYSCALL_COMPAT) #define __SC_3264(_nr, _32, _64) __SYSCALL(_nr, _32) +#define __SYSCALL_32(_nr, _sys)__SYSCALL(__NR_ ## _nr, _sys) +#define __SYSCALL_64(_nr, _sys) #else #define __SC_3264(_nr, _32, _64) __SYSCALL(_nr, _64) +#define __SYSCALL_32(_nr, _sys) +#define __SYSCALL_64(_nr, _sys)__SYSCALL(__NR_ ## _nr, _sys) +#endif + +#if defined(__ARCH_WANT_TIME32_SYSCALLS) +#define __SYSCALL_time32(_nr, _sys)__SYSCALL_32(__NR_ ## _nr, _sys) +#else +#define __SYSCALL_time32(_nr, _sys) #endif #ifdef __SYSCALL_COMPAT @@ -41,7 +63,8 @@ __SYSCALL(__NR_io_cancel, sys_io_cancel) #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 #define __NR_io_getevents 4 -__SC_3264(__NR_io_getevents, sys_io_getevents_time32, sys_io_getevents) +__SC(time32, io_getevents, sys_io_getevents_time32) +__SC(64, io_getevents, sys_io_getevents) #endif #define __NR_setxattr 5 @@ -190,9 +213,11 @@ __SYSCALL(__NR3264_sendfile, sys_sendfile64) #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 #define __NR_pselect6 72 -__SC_COMP_3264(__NR_pselect6, sys_pselect6_time32, sys_pselect6, compat_sys_pselect6_time32) +__SCC(time32, pselect6, sys_pselect6_time32, compat_sys_pselect6_time32) +__SC(64, pselect6, sys_pselect6) #define __NR_ppoll 73 -__SC_COMP_3264(__NR_ppoll, sys_ppoll_time32, sys_ppoll, compat_sys_ppoll_time32) +__SCC(time32, ppoll, sys_ppoll_time32, compat_sys_ppoll_time32) +__SC(64, ppoll, sys_ppoll) #endif #define __NR_signalfd4 74 @@ -235,16 +260,17 @@ __SYSCALL(__NR_timerfd_create, sys_timerfd_create) #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 #define __NR_timerfd_settime 86 -__SC_3264(__NR_timerfd_settime, sys_timerfd_settime32, \ - sys_timerfd_settime) +__SC(time32, timerfd_settime, sys_timerfd_settime32) +__SC(64, timerfd_settime, sys_timerfd_settime) #define __NR_timerfd_gettime 87 -__SC_3264(__NR_timerfd_gettime, sys_timerfd_gettime32, \ - sys_timerfd_gettime) +__SC(time32, timerfd_gettime, sys_timerfd_gettime32) +__SC(64, timerfd_gettime, sys_timerfd_gettime) #endif #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 #define __NR_utimensat 88 -__SC_3264(__NR_utimensat, sys_utimensat_time32, sys_utimensat) +__SC(time32, utimensat, sys_utimensat_time32) +__SC(64, utimensat, sys_utimensat) #endif #define __NR_acct 89 @@ -268,7 +294,8 @@ __SYSCALL(__NR_unshare, sys_unshare) #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 #define __NR_futex 98 -__SC_3264(__NR_futex, sys_futex_time32, sys_futex) +__SC(time32, futex, sys_futex_time32) +__SC(64, futex, sys_futex) #endif #define __NR_set_robust_list 99 @@ -280,7 +307,8 @@ __SC_COMP(__NR_get_robust_list, sys_get_robust_list, \ #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 #define __NR_nanosleep 101 -__SC_3264(__NR_nanosleep, sys_nanosleep_time32, sys_nanosleep) +__SC(time32, nanosleep, sys_nanosleep_time32) +__SC(64, nanosleep, sys_nanosleep) #endif #define __NR_getitimer 102 @@ -298,7 +326,8 @@ __SC_COMP(__NR_timer_create, sys_timer_create, compat_sys_timer_create) #if defined(__ARCH_WANT_TIME32_SYSCALLS) || __BITS_PER_LONG != 32 #define __NR_timer_gettime 108 -__SC_3264(__NR_timer_gettime, sys_timer_gettime32, sys_timer_gettime) +__SC(time32, timer_gettime, sys_timer_gettime32) +__SC(64, timer_gettime, sys_timer_gettime) #endif #define __NR_timer_getoverrun 109 @@ -306,7 +335,8 @@ __SYSCALL(__NR_timer_getoverrun, sys_timer_g
[PATCH 15/15] linux/syscalls.h: add missing __user annotations
From: Arnd Bergmann A couple of declarations in linux/syscalls.h are missing __user annotations on their pointers, which can lead to warnings from sparse because these don't match the implementation that have the correct address space annotations. Signed-off-by: Arnd Bergmann --- include/linux/syscalls.h | 18 +- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index ba9337709878..63424af87bba 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -322,13 +322,13 @@ asmlinkage long sys_io_pgetevents(aio_context_t ctx_id, long nr, struct io_event __user *events, struct __kernel_timespec __user *timeout, - const struct __aio_sigset *sig); + const struct __aio_sigset __user *sig); asmlinkage long sys_io_pgetevents_time32(aio_context_t ctx_id, long min_nr, long nr, struct io_event __user *events, struct old_timespec32 __user *timeout, - const struct __aio_sigset *sig); + const struct __aio_sigset __user *sig); asmlinkage long sys_io_uring_setup(u32 entries, struct io_uring_params __user *p); asmlinkage long sys_io_uring_enter(unsigned int fd, u32 to_submit, @@ -441,7 +441,7 @@ asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group); asmlinkage long sys_openat(int dfd, const char __user *filename, int flags, umode_t mode); asmlinkage long sys_openat2(int dfd, const char __user *filename, - struct open_how *how, size_t size); + struct open_how __user *how, size_t size); asmlinkage long sys_close(unsigned int fd); asmlinkage long sys_close_range(unsigned int fd, unsigned int max_fd, unsigned int flags); @@ -555,7 +555,7 @@ asmlinkage long sys_get_robust_list(int pid, asmlinkage long sys_set_robust_list(struct robust_list_head __user *head, size_t len); -asmlinkage long sys_futex_waitv(struct futex_waitv *waiters, +asmlinkage long sys_futex_waitv(struct futex_waitv __user *waiters, unsigned int nr_futexes, unsigned int flags, struct __kernel_timespec __user *timeout, clockid_t clockid); @@ -907,7 +907,7 @@ asmlinkage long sys_seccomp(unsigned int op, unsigned int flags, asmlinkage long sys_getrandom(char __user *buf, size_t count, unsigned int flags); asmlinkage long sys_memfd_create(const char __user *uname_ptr, unsigned int flags); -asmlinkage long sys_bpf(int cmd, union bpf_attr *attr, unsigned int size); +asmlinkage long sys_bpf(int cmd, union bpf_attr __user *attr, unsigned int size); asmlinkage long sys_execveat(int dfd, const char __user *filename, const char __user *const __user *argv, const char __user *const __user *envp, int flags); @@ -960,11 +960,11 @@ asmlinkage long sys_cachestat(unsigned int fd, struct cachestat_range __user *cstat_range, struct cachestat __user *cstat, unsigned int flags); asmlinkage long sys_map_shadow_stack(unsigned long addr, unsigned long size, unsigned int flags); -asmlinkage long sys_lsm_get_self_attr(unsigned int attr, struct lsm_ctx *ctx, - u32 *size, u32 flags); -asmlinkage long sys_lsm_set_self_attr(unsigned int attr, struct lsm_ctx *ctx, +asmlinkage long sys_lsm_get_self_attr(unsigned int attr, struct lsm_ctx __user *ctx, + u32 __user *size, u32 flags); +asmlinkage long sys_lsm_set_self_attr(unsigned int attr, struct lsm_ctx __user *ctx, u32 size, u32 flags); -asmlinkage long sys_lsm_list_modules(u64 *ids, u32 *size, u32 flags); +asmlinkage long sys_lsm_list_modules(u64 __user *ids, u32 __user *size, u32 flags); /* * Architecture-specific system calls -- 2.39.2
Re: [PATCH] powerpc/pseries: Whitelist dtl slub object for copying to userspace
Hi Kees Thank you for your review. On 17/06/24 23:29, Kees Cook wrote: > On Fri, Jun 14, 2024 at 11:08:44PM +0530, Anjali K wrote: >> Reading the dispatch trace log from /sys/kernel/debug/powerpc/dtl/cpu-* >> results in a BUG() when the config CONFIG_HARDENED_USERCOPY is enabled as >> shown below. >> >> kernel BUG at mm/usercopy.c:102! >> Oops: Exception in kernel mode, sig: 5 [#1] >> LE PAGE_SIZE=64K MMU=Radix SMP NR_CPUS=2048 NUMA pSeries >> Modules linked in: xfs libcrc32c dm_service_time sd_mod t10_pi sg ibmvfc >> scsi_transport_fc ibmveth pseries_wdt dm_multipath dm_mirror >> dm_region_hash dm_log dm_mod fuse >> CPU: 27 PID: 1815 Comm: python3 Not tainted 6.10.0-rc3 #85 >> Hardware name: IBM,9040-MRX POWER10 (raw) 0x800200 0xf06 >> of:IBM,FW1060.00 (NM1060_042) hv:phyp pSeries >> NIP: c05d23d4 LR: c05d23d0 CTR: 006ee6f8 >> REGS: c00120c078c0 TRAP: 0700 Not tainted (6.10.0-rc3) >> MSR: 80029033 CR: 2828220f XER: >> 000e >> CFAR: c01fdc80 IRQMASK: 0 >> [ ... GPRs omitted ... ] >> NIP [c05d23d4] usercopy_abort+0x78/0xb0 >> LR [c05d23d0] usercopy_abort+0x74/0xb0 >> Call Trace: >> usercopy_abort+0x74/0xb0 (unreliable) >> __check_heap_object+0xf8/0x120 >> check_heap_object+0x218/0x240 >> __check_object_size+0x84/0x1a4 >> dtl_file_read+0x17c/0x2c4 >> full_proxy_read+0x8c/0x110 >> vfs_read+0xdc/0x3a0 >> ksys_read+0x84/0x144 >> system_call_exception+0x124/0x330 >> system_call_vectored_common+0x15c/0x2ec >> --- interrupt: 3000 at 0x7fff81f3ab34 >> >> Commit 6d07d1cd300f ("usercopy: Restrict non-usercopy caches to size 0") >> requires that only whitelisted areas in slab/slub objects can be copied to >> userspace when usercopy hardening is enabled using CONFIG_HARDENED_USERCOPY. >> Dtl contains hypervisor dispatch events which are expected to be read by >> privileged users. Hence mark this safe for user access. >> Specify useroffset=0 and usersize=DISPATCH_LOG_BYTES to whitelist the >> entire object. >> >> Co-developed-by: Vishal Chourasia >> Signed-off-by: Vishal Chourasia >> Signed-off-by: Anjali K >> --- >> arch/powerpc/platforms/pseries/setup.c | 4 ++-- >> 1 file changed, 2 insertions(+), 2 deletions(-) >> >> diff --git a/arch/powerpc/platforms/pseries/setup.c >> b/arch/powerpc/platforms/pseries/setup.c >> index 284a6fa04b0c..cba40d9d1284 100644 >> --- a/arch/powerpc/platforms/pseries/setup.c >> +++ b/arch/powerpc/platforms/pseries/setup.c >> @@ -343,8 +343,8 @@ static int alloc_dispatch_log_kmem_cache(void) >> { >> void (*ctor)(void *) = get_dtl_cache_ctor(); >> >> -dtl_cache = kmem_cache_create("dtl", DISPATCH_LOG_BYTES, >> -DISPATCH_LOG_BYTES, 0, ctor); >> +dtl_cache = kmem_cache_create_usercopy("dtl", DISPATCH_LOG_BYTES, >> +DISPATCH_LOG_BYTES, 0, 0, >> DISPATCH_LOG_BYTES, ctor); >> if (!dtl_cache) { >> pr_warn("Failed to create dispatch trace log buffer cache\n"); >> pr_warn("Stolen time statistics will be unreliable\n"); > Are you sure you want to universally expose this memory region? It > sounds like it's only exposed via a debug interface. Maybe it'd be > better to use a bounce buffer in the debug interface instead > > diff --git a/arch/powerpc/platforms/pseries/dtl.c > b/arch/powerpc/platforms/pseries/dtl.c > index 3f1cdccebc9c..3adcff5cc4b2 100644 > --- a/arch/powerpc/platforms/pseries/dtl.c > +++ b/arch/powerpc/platforms/pseries/dtl.c > @@ -257,6 +257,22 @@ static int dtl_file_release(struct inode *inode, struct > file *filp) > return 0; > } > > +static inline int bounce_copy(char __user *buf, void *src, size_t size) > +{ > + u8 *bounce; > + int rc; > + > + bounce = kmalloc(size, GFP_KERNEL); > + if (!bounce) > + return -ENOMEM; > + > + memcpy(bounce, src, size); > + rc = copy_to_user(buf, bounce, size); > + > + kfree(bounce); > + return rc; > +} > + > static ssize_t dtl_file_read(struct file *filp, char __user *buf, size_t len, > loff_t *pos) > { > @@ -300,7 +316,7 @@ static ssize_t dtl_file_read(struct file *filp, char > __user *buf, size_t len, > if (i + n_req > dtl->buf_entries) { > read_size = dtl->buf_entries - i; > > - rc = copy_to_user(buf, &dtl->buf[i], > + rc = bounce_copy(buf, &dtl->buf[i], > read_size * sizeof(struct dtl_entry)); > if (rc) > return -EFAULT; > @@ -312,7 +328,7 @@ static ssize_t dtl_file_read(struct file *filp, char > __user *buf, size_t len, > } > > /* .. and now the head */ > - rc = copy_to_user(buf, &dtl->buf[i], n_req * sizeof(struct dtl_entry)); > + rc = bounce_copy(buf, &dtl->buf[i], n_req * sizeof(struct dtl_entry)); >
[PATCH 1/3] powerpc/pseries: Macros and wrapper functions for H_HTM call
Define macros and wrapper functions to handle H_HTM (Hardware Trace Macro) hypervisor call. H_HTM is new HCALL added to export data from Hardware Trace Macro (HTM) function. Signed-off-by: Madhavan Srinivasan --- arch/powerpc/include/asm/hvcall.h | 34 +++ arch/powerpc/include/asm/plpar_wrappers.h | 21 ++ 2 files changed, 55 insertions(+) diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h index 7a8495660c2f..7ad13685c127 100644 --- a/arch/powerpc/include/asm/hvcall.h +++ b/arch/powerpc/include/asm/hvcall.h @@ -348,6 +348,7 @@ #define H_SCM_FLUSH0x44C #define H_GET_ENERGY_SCALE_INFO0x450 #define H_PKS_SIGNED_UPDATE0x454 +#define H_HTM 0x458 #define H_WATCHDOG 0x45C #define H_GUEST_GET_CAPABILITIES 0x460 #define H_GUEST_SET_CAPABILITIES 0x464 @@ -497,6 +498,39 @@ #define H_GUEST_CAP_POWER10(1UL<<(63-2)) #define H_GUEST_CAP_BITMAP2(1UL<<(63-63)) +/* + * Defines for H_HTM - Macros for hardware trace macro (HTM) function. + */ +#define H_HTM_FLAGS_HARDWARE_TARGET(1ul << 63) +#define H_HTM_FLAGS_LOGICAL_TARGET (1ul << 62) +#define H_HTM_FLAGS_PROCID_TARGET (1ul << 61) +#define H_HTM_FLAGS_NOWRAP (1ul << 60) + +#define H_HTM_OP_SHIFT (63-15) +#define H_HTM_OP(x)((unsigned long)(x)< diff --git a/arch/powerpc/include/asm/plpar_wrappers.h b/arch/powerpc/include/asm/plpar_wrappers.h index b3ee44a40c2f..24d5647096e0 100644 --- a/arch/powerpc/include/asm/plpar_wrappers.h +++ b/arch/powerpc/include/asm/plpar_wrappers.h @@ -93,6 +93,27 @@ static inline long register_dtl(unsigned long cpu, unsigned long vpa) return vpa_call(H_VPA_REG_DTL, cpu, vpa); } +static inline long htm_call(unsigned long flags, unsigned long target, + unsigned long operation, unsigned long param1, + unsigned long param2, unsigned long param3) +{ + return plpar_hcall_norets(H_HTM, flags, target, operation, + param1, param2, param3); +} + +static inline long htm_get_dump_hardware(unsigned long nodeindex, + unsigned long nodalchipindex, unsigned long coreindexonchip, + unsigned long type, unsigned long addr, unsigned long size, + unsigned long offset) +{ + return htm_call(H_HTM_FLAGS_HARDWARE_TARGET, + H_HTM_TARGET_NODE_INDEX(nodeindex) | + H_HTM_TARGET_NODAL_CHIP_INDEX(nodalchipindex) | + H_HTM_TARGET_CORE_INDEX_ON_CHIP(coreindexonchip), + H_HTM_OP(H_HTM_OP_DUMP_DATA) | H_HTM_TYPE(type), + addr, size, offset); +} + extern void vpa_init(int cpu); static inline long plpar_pte_enter(unsigned long flags, -- 2.45.2
[PATCH 2/3] powerpc/pseries: Export hardware trace macro dump via debugfs
This patch adds debugfs interface to export Hardware Trace Macro (HTM) function data in a LPAR. New hypervisor call "H_HTM" has been defined to setup, configure, control and dump the HTM data. This patch supports only dumping of HTM data in a LPAR. New debugfs folder called "htmdump" has been added under /sys/kernel/debug/arch path which contains files need to pass required parameters for the H_HTM dump function. New Kconfig option called "CONFIG_HTMDUMP" has been in platform/pseries for the same. With patch series applied and booted, list of files in debugfs path # pwd /sys/kernel/debug/powerpc/htmdump # ls coreindexonchip htmtype nodalchipindex nodeindex trace Signed-off-by: Madhavan Srinivasan --- arch/powerpc/platforms/pseries/Kconfig | 8 ++ arch/powerpc/platforms/pseries/Makefile | 1 + arch/powerpc/platforms/pseries/htmdump.c | 130 +++ 3 files changed, 139 insertions(+) create mode 100644 arch/powerpc/platforms/pseries/htmdump.c diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig index afc0f6a61337..46c0ea605e33 100644 --- a/arch/powerpc/platforms/pseries/Kconfig +++ b/arch/powerpc/platforms/pseries/Kconfig @@ -128,6 +128,14 @@ config CMM will be reused for other LPARs. The interface allows firmware to balance memory across many LPARs. +config HTMDUMP + tristate "PHYP HTM data dumper" + default y + help + Select this option, if you want to enable the kernel debugfs + interface to dump the Hardware Trace Macro (HTM) function data + in the LPAR. + config HV_PERF_CTRS bool "Hypervisor supplied PMU events (24x7 & GPCI)" default y diff --git a/arch/powerpc/platforms/pseries/Makefile b/arch/powerpc/platforms/pseries/Makefile index 7bf506f6b8c8..3f3e3492e436 100644 --- a/arch/powerpc/platforms/pseries/Makefile +++ b/arch/powerpc/platforms/pseries/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o obj-$(CONFIG_HVCS) += hvcserver.o obj-$(CONFIG_HCALL_STATS) += hvCall_inst.o obj-$(CONFIG_CMM) += cmm.o +obj-$(CONFIG_HTMDUMP) += htmdump.o obj-$(CONFIG_IO_EVENT_IRQ) += io_event_irq.o obj-$(CONFIG_LPARCFG) += lparcfg.o obj-$(CONFIG_IBMVIO) += vio.o diff --git a/arch/powerpc/platforms/pseries/htmdump.c b/arch/powerpc/platforms/pseries/htmdump.c new file mode 100644 index ..540cdb7e069c --- /dev/null +++ b/arch/powerpc/platforms/pseries/htmdump.c @@ -0,0 +1,130 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (C) IBM Corporation, 2024 + */ + +#define pr_fmt(fmt) "htmdump: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* This enables us to keep track of the memory removed from each node. */ +struct htmdump_entry { + void *buf; + struct dentry *dir; + char name[16]; +}; + +static u32 nodeindex = 0; +static u32 nodalchipindex = 0; +static u32 coreindexonchip = 0; +static u32 htmtype = 0; + +#define BUFFER_SIZE PAGE_SIZE + +static ssize_t htmdump_read(struct file *filp, char __user *ubuf, +size_t count, loff_t *ppos) +{ + struct htmdump_entry *ent = filp->private_data; + unsigned long page, read_size, available; + loff_t offset; + long rc; + + page = ALIGN_DOWN(*ppos, BUFFER_SIZE); + offset = (*ppos) % BUFFER_SIZE; + + rc = htm_get_dump_hardware(nodeindex, nodalchipindex, coreindexonchip, + htmtype, virt_to_phys(ent->buf), BUFFER_SIZE, page); + + switch(rc) { + case H_SUCCESS: + case H_PARTIAL: + break; + case H_NOT_AVAILABLE: + return 0; + case H_BUSY: + case H_LONG_BUSY_ORDER_1_MSEC: + case H_LONG_BUSY_ORDER_10_MSEC: + case H_LONG_BUSY_ORDER_100_MSEC: + case H_LONG_BUSY_ORDER_1_SEC: + case H_LONG_BUSY_ORDER_10_SEC: + case H_LONG_BUSY_ORDER_100_SEC: + case H_PARAMETER: + case H_P2: + case H_P3: + case H_P4: + case H_P5: + case H_P6: + case H_STATE: + case H_AUTHORITY: + return -EINVAL; + } + + available = BUFFER_SIZE - offset; + read_size = min(count, available); + *ppos += read_size; + return simple_read_from_buffer(ubuf, count, &offset, ent->buf, available); +} + +static const struct file_operations htmdump_fops = { + .llseek = default_llseek, + .read = htmdump_read, + .open = simple_open, +}; + +static struct dentry *htmdump_debugfs_dir; + +static int htmdump_init_debugfs(void) +{ + struct htmdump_entry *ent; + + ent = kcalloc(1, sizeof(struct htmdump_entry), GFP_KERNEL); + if (!ent) { + pr_err("Failed to allocate ent\n"); + return -EINVAL; + } + + e
[PATCH 3/3] powerpc: Document details on H_HTM hcall
Add documentation to 'papr_hcalls.rst' describing the input, output and return values of the H_HTM hcall as per the internal specification. Signed-off-by: Madhavan Srinivasan --- Documentation/arch/powerpc/papr_hcalls.rst | 11 +++ 1 file changed, 11 insertions(+) diff --git a/Documentation/arch/powerpc/papr_hcalls.rst b/Documentation/arch/powerpc/papr_hcalls.rst index 80d2c0aadab5..805e1cb9bab9 100644 --- a/Documentation/arch/powerpc/papr_hcalls.rst +++ b/Documentation/arch/powerpc/papr_hcalls.rst @@ -289,6 +289,17 @@ to be issued multiple times in order to be completely serviced. The subsequent hcalls to the hypervisor until the hcall is completely serviced at which point H_SUCCESS or other error is returned by the hypervisor. +**H_HTM** + +| Input: flags, target, operation (op), op-param1, op-param2, op-param3 +| Out: *dumphtmbufferdata* +| Return Value: *H_Success,H_Busy,H_LongBusyOrder,H_Partial,H_Parameter, +H_P2,H_P3,H_P4,H_P5,H_P6,H_State,H_Not_Available,H_Authority* + +H_HTM supports setup, configuration, control and dumping of Hardware Trace +Macro (HTM) function and its data. HTM buffer stores tracing data for functions +like core instruction, core LLAT and nest. + References == .. [1] "Power Architecture Platform Reference" -- 2.45.2
[Patch v4 00/10] Add audio support for LPC32XX CPUs
This pach set is to bring back audio to machines with a LPC32XX CPU. The legacy LPC32XX SoC used to have audio spport in linux 2.6.27. The support was dropped due to lack of interest from mainaeners. Piotr Wojtaszczyk (10): dt-bindings: dma: pl08x: Add dma-cells description dt-bindings: dma: Add lpc32xx DMA mux binding ASoC: dt-bindings: lpc32xx: Add lpc32xx i2s DT binding ARM: dts: lpc32xx: Add missing dma and i2s properties clk: lpc32xx: initialize regmap using parent syscon dmaengine: Add dma router for pl08x in LPC32XX SoC ARM: lpc32xx: Remove pl08x platform data in favor for device tree mtd: rawnand: lpx32xx: Request DMA channels using DT entries ASoC: fsl: Add i2s and pcm drivers for LPC32xx CPUs i2x: pnx: Use threaded irq to fix warning from del_timer_sync() .../devicetree/bindings/dma/arm-pl08x.yaml| 7 + .../bindings/dma/nxp,lpc3220-dmamux.yaml | 56 +++ .../bindings/sound/nxp,lpc3220-i2s.yaml | 73 MAINTAINERS | 21 + arch/arm/boot/dts/nxp/lpc/lpc32xx.dtsi| 53 ++- arch/arm/mach-lpc32xx/phy3250.c | 54 --- drivers/clk/Kconfig | 1 + drivers/clk/nxp/clk-lpc32xx.c | 10 +- drivers/dma/Kconfig | 9 + drivers/dma/Makefile | 1 + drivers/dma/lpc32xx-dmamux.c | 195 + drivers/i2c/busses/i2c-pnx.c | 4 +- drivers/mtd/nand/raw/lpc32xx_mlc.c| 10 +- drivers/mtd/nand/raw/lpc32xx_slc.c| 10 +- sound/soc/fsl/Kconfig | 7 + sound/soc/fsl/Makefile| 2 + sound/soc/fsl/lpc3xxx-i2s.c | 376 ++ sound/soc/fsl/lpc3xxx-i2s.h | 79 sound/soc/fsl/lpc3xxx-pcm.c | 73 19 files changed, 954 insertions(+), 87 deletions(-) create mode 100644 Documentation/devicetree/bindings/dma/nxp,lpc3220-dmamux.yaml create mode 100644 Documentation/devicetree/bindings/sound/nxp,lpc3220-i2s.yaml create mode 100644 drivers/dma/lpc32xx-dmamux.c create mode 100644 sound/soc/fsl/lpc3xxx-i2s.c create mode 100644 sound/soc/fsl/lpc3xxx-i2s.h create mode 100644 sound/soc/fsl/lpc3xxx-pcm.c -- 2.25.1
[PATCH v4 18/40] powerpc: optimize arch code by using atomic find_bit() API
Use find_and_{set,clear}_bit() where appropriate and simplify the logic. Signed-off-by: Yury Norov --- arch/powerpc/mm/book3s32/mmu_context.c | 11 +++--- arch/powerpc/platforms/pasemi/dma_lib.c| 46 ++ arch/powerpc/platforms/powernv/pci-sriov.c | 13 ++ 3 files changed, 20 insertions(+), 50 deletions(-) diff --git a/arch/powerpc/mm/book3s32/mmu_context.c b/arch/powerpc/mm/book3s32/mmu_context.c index 1922f9a6b058..ece7b55b6cdb 100644 --- a/arch/powerpc/mm/book3s32/mmu_context.c +++ b/arch/powerpc/mm/book3s32/mmu_context.c @@ -17,6 +17,7 @@ *Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds */ +#include #include #include #include @@ -50,13 +51,11 @@ static unsigned long context_map[LAST_CONTEXT / BITS_PER_LONG + 1]; unsigned long __init_new_context(void) { - unsigned long ctx = next_mmu_context; + unsigned long ctx; - while (test_and_set_bit(ctx, context_map)) { - ctx = find_next_zero_bit(context_map, LAST_CONTEXT+1, ctx); - if (ctx > LAST_CONTEXT) - ctx = 0; - } + ctx = find_and_set_next_bit(context_map, LAST_CONTEXT + 1, next_mmu_context); + if (ctx > LAST_CONTEXT) + ctx = 0; next_mmu_context = (ctx + 1) & LAST_CONTEXT; return ctx; diff --git a/arch/powerpc/platforms/pasemi/dma_lib.c b/arch/powerpc/platforms/pasemi/dma_lib.c index 1be1f18f6f09..db008902e5f3 100644 --- a/arch/powerpc/platforms/pasemi/dma_lib.c +++ b/arch/powerpc/platforms/pasemi/dma_lib.c @@ -5,6 +5,7 @@ * Common functions for DMA access on PA Semi PWRficient */ +#include #include #include #include @@ -118,14 +119,9 @@ static int pasemi_alloc_tx_chan(enum pasemi_dmachan_type type) limit = MAX_TXCH; break; } -retry: - bit = find_next_bit(txch_free, MAX_TXCH, start); - if (bit >= limit) - return -ENOSPC; - if (!test_and_clear_bit(bit, txch_free)) - goto retry; - - return bit; + + bit = find_and_clear_next_bit(txch_free, MAX_TXCH, start); + return bit < limit ? bit : -ENOSPC; } static void pasemi_free_tx_chan(int chan) @@ -136,15 +132,9 @@ static void pasemi_free_tx_chan(int chan) static int pasemi_alloc_rx_chan(void) { - int bit; -retry: - bit = find_first_bit(rxch_free, MAX_RXCH); - if (bit >= MAX_TXCH) - return -ENOSPC; - if (!test_and_clear_bit(bit, rxch_free)) - goto retry; - - return bit; + int bit = find_and_clear_bit(rxch_free, MAX_RXCH); + + return bit < MAX_TXCH ? bit : -ENOSPC; } static void pasemi_free_rx_chan(int chan) @@ -374,16 +364,9 @@ EXPORT_SYMBOL(pasemi_dma_free_buf); */ int pasemi_dma_alloc_flag(void) { - int bit; + int bit = find_and_clear_bit(flags_free, MAX_FLAGS); -retry: - bit = find_first_bit(flags_free, MAX_FLAGS); - if (bit >= MAX_FLAGS) - return -ENOSPC; - if (!test_and_clear_bit(bit, flags_free)) - goto retry; - - return bit; + return bit < MAX_FLAGS ? bit : -ENOSPC; } EXPORT_SYMBOL(pasemi_dma_alloc_flag); @@ -439,16 +422,9 @@ EXPORT_SYMBOL(pasemi_dma_clear_flag); */ int pasemi_dma_alloc_fun(void) { - int bit; - -retry: - bit = find_first_bit(fun_free, MAX_FLAGS); - if (bit >= MAX_FLAGS) - return -ENOSPC; - if (!test_and_clear_bit(bit, fun_free)) - goto retry; + int bit = find_and_clear_bit(fun_free, MAX_FLAGS); - return bit; + return bit < MAX_FLAGS ? bit : -ENOSPC; } EXPORT_SYMBOL(pasemi_dma_alloc_fun); diff --git a/arch/powerpc/platforms/powernv/pci-sriov.c b/arch/powerpc/platforms/powernv/pci-sriov.c index cc7b1dd54ac6..e33e57c559f7 100644 --- a/arch/powerpc/platforms/powernv/pci-sriov.c +++ b/arch/powerpc/platforms/powernv/pci-sriov.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -397,18 +398,12 @@ static int64_t pnv_ioda_map_m64_single(struct pnv_phb *phb, static int pnv_pci_alloc_m64_bar(struct pnv_phb *phb, struct pnv_iov_data *iov) { - int win; + int win = find_and_set_bit(&phb->ioda.m64_bar_alloc, phb->ioda.m64_bar_idx + 1); - do { - win = find_next_zero_bit(&phb->ioda.m64_bar_alloc, - phb->ioda.m64_bar_idx + 1, 0); - - if (win >= phb->ioda.m64_bar_idx + 1) - return -1; - } while (test_and_set_bit(win, &phb->ioda.m64_bar_alloc)); + if (win >= phb->ioda.m64_bar_idx + 1) + return -1; set_bit(win, iov->used_m64_bar_mask); - return win; } -- 2.43.0
[Patch v4 01/10] dt-bindings: dma: pl08x: Add dma-cells description
Recover dma-cells description from the legacy DT binding. Signed-off-by: Piotr Wojtaszczyk --- Changes for v4: - This patch is new in v4 Documentation/devicetree/bindings/dma/arm-pl08x.yaml | 7 +++ 1 file changed, 7 insertions(+) diff --git a/Documentation/devicetree/bindings/dma/arm-pl08x.yaml b/Documentation/devicetree/bindings/dma/arm-pl08x.yaml index ab25ae63d2c3..191215d36c85 100644 --- a/Documentation/devicetree/bindings/dma/arm-pl08x.yaml +++ b/Documentation/devicetree/bindings/dma/arm-pl08x.yaml @@ -52,6 +52,13 @@ properties: clock-names: maxItems: 1 + "#dma-cells": +const: 2 +description: | + First cell should contain the DMA request, + second cell should contain either 1 or 2 depending on + which AHB master that is used. + lli-bus-interface-ahb1: type: boolean description: if AHB master 1 is eligible for fetching LLIs -- 2.25.1
[Patch v4 02/10] dt-bindings: dma: Add lpc32xx DMA mux binding
LPC32XX SoCs use pl080 dma controller which have few request signals multiplexed between peripherals. This binding describes how devices can use the multiplexed request signals. Signed-off-by: Piotr Wojtaszczyk --- Changes for v4: - This patch is new in v4 .../bindings/dma/nxp,lpc3220-dmamux.yaml | 56 +++ MAINTAINERS | 9 +++ 2 files changed, 65 insertions(+) create mode 100644 Documentation/devicetree/bindings/dma/nxp,lpc3220-dmamux.yaml diff --git a/Documentation/devicetree/bindings/dma/nxp,lpc3220-dmamux.yaml b/Documentation/devicetree/bindings/dma/nxp,lpc3220-dmamux.yaml new file mode 100644 index ..a5384b6c67fc --- /dev/null +++ b/Documentation/devicetree/bindings/dma/nxp,lpc3220-dmamux.yaml @@ -0,0 +1,56 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/dma/nxp,lpc3220-dmamux.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: DMA multiplexer for LPC32XX SoC (DMA request router) + +maintainers: + - J.M.B. Downing + - Piotr Wojtaszczyk + +allOf: + - $ref: dma-router.yaml# + +properties: + "#dma-cells": +const: 3 +description: | + First two cells same as for device pointed in dma-masters. + Third cell represents mux value for the request. + + compatible: +const: nxp,lpc3220-dmamux + + dma-masters: +description: phandle to a dma node compatible with arm,pl080 + + reg: +maxItems: 1 + +required: + - compatible + - reg + - dma-masters + +additionalProperties: false + +examples: + - | +syscon@40004000 { + compatible = "nxp,lpc3220-creg", "syscon", "simple-mfd"; + reg = <0x40004000 0x114>; + ranges = <0 0x40004000 0x114>; + #address-cells = <1>; + #size-cells = <1>; + + dma-router@7c { +compatible = "nxp,lpc3220-dmamux"; +reg = <0x7c 0x8>; +#dma-cells = <3>; +dma-masters = <&dma>; + }; +}; + +... diff --git a/MAINTAINERS b/MAINTAINERS index aacccb376c28..f7adf9f66dfa 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2396,6 +2396,15 @@ F: drivers/usb/host/ohci-nxp.c F: drivers/watchdog/pnx4008_wdt.c N: lpc32xx +ARM/LPC32XX DMAMUX SUPPORT +M: J.M.B. Downing +M: Piotr Wojtaszczyk +R: Vladimir Zapolskiy +L: linux-arm-ker...@lists.infradead.org (moderated for non-subscribers) +S: Maintained +F: Documentation/devicetree/bindings/dma/nxp,lpc3220-dmamux.yaml +N: lpc32xx + ARM/Marvell Dove/MV78xx0/Orion SOC support M: Andrew Lunn M: Sebastian Hesselbarth -- 2.25.1
[Patch v4 03/10] ASoC: dt-bindings: lpc32xx: Add lpc32xx i2s DT binding
Add nxp,lpc3220-i2s DT binding documentation. Signed-off-by: Piotr Wojtaszczyk --- Changes for v4: - Custom dma-vc-names property with standard dmas and dma-names - Added to MAINTAINERS Changes for v3: - Added '$ref: dai-common.yaml#' and '#sound-dai-cells' - Dropped all clock-names, references - Dropped status property from the example - Added interrupts property - 'make dt_binding_check' pass Changes for v2: - Added maintainers field - Dropped clock-names - Dropped unused unneded interrupts field .../bindings/sound/nxp,lpc3220-i2s.yaml | 73 +++ MAINTAINERS | 10 +++ 2 files changed, 83 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/nxp,lpc3220-i2s.yaml diff --git a/Documentation/devicetree/bindings/sound/nxp,lpc3220-i2s.yaml b/Documentation/devicetree/bindings/sound/nxp,lpc3220-i2s.yaml new file mode 100644 index ..40a0877a8aba --- /dev/null +++ b/Documentation/devicetree/bindings/sound/nxp,lpc3220-i2s.yaml @@ -0,0 +1,73 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/nxp,lpc3220-i2s.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NXP LPC32XX I2S Controller + +description: + The I2S controller in LPC32XX SoCs, ASoC DAI. + +maintainers: + - J.M.B. Downing + - Piotr Wojtaszczyk + +allOf: + - $ref: dai-common.yaml# + +properties: + compatible: +enum: + - nxp,lpc3220-i2s + + reg: +maxItems: 1 + + interrupts: +maxItems: 1 + + clocks: +items: + - description: input clock of the peripheral. + + dmas: +items: + - description: RX DMA Channel + - description: TX DMA Channel + + dma-names: +items: + - const: rx + - const: tx + + "#sound-dai-cells": +const: 0 + +required: + - compatible + - reg + - interrupts + - clocks + - dmas + - dma-names + - '#sound-dai-cells' + +additionalProperties: false + +examples: + - | +#include +#include + +i2s@20094000 { + compatible = "nxp,lpc3220-i2s"; + reg = <0x20094000 0x1000>; + interrupts = <22 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk LPC32XX_CLK_I2S0>; + dmas = <&dma 0 1>, <&dma 13 1>; + dma-names = "rx", "tx"; + #sound-dai-cells = <0>; +}; + +... diff --git a/MAINTAINERS b/MAINTAINERS index f7adf9f66dfa..fadf1baafd89 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8918,6 +8918,16 @@ S: Maintained F: sound/soc/fsl/fsl* F: sound/soc/fsl/imx* +FREESCALE SOC LPC32XX SOUND DRIVERS +M: J.M.B. Downing +M: Piotr Wojtaszczyk +R: Vladimir Zapolskiy +L: alsa-de...@alsa-project.org (moderated for non-subscribers) +L: linuxppc-dev@lists.ozlabs.org +S: Maintained +F: Documentation/devicetree/bindings/sound/nxp,lpc3220-i2s.yaml +N: lpc32xx + FREESCALE SOC SOUND QMC DRIVER M: Herve Codina L: alsa-de...@alsa-project.org (moderated for non-subscribers) -- 2.25.1
[PATCH v4 37/40] KVM: PPC: Book3s HV: drop locking around kvmppc_uvmem_bitmap
The driver operates on individual bits of the kvmppc_uvmem_bitmap. Now that we have an atomic search API for bitmaps, we can rely on it and drop locking around the bitmap entirely. Signed-off-by: Yury Norov --- arch/powerpc/kvm/book3s_hv_uvmem.c | 33 ++ 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/arch/powerpc/kvm/book3s_hv_uvmem.c b/arch/powerpc/kvm/book3s_hv_uvmem.c index 92f33115144b..93d09137cb23 100644 --- a/arch/powerpc/kvm/book3s_hv_uvmem.c +++ b/arch/powerpc/kvm/book3s_hv_uvmem.c @@ -86,6 +86,7 @@ * page-sizes, we need to break this assumption. */ +#include #include #include #include @@ -99,7 +100,6 @@ static struct dev_pagemap kvmppc_uvmem_pgmap; static unsigned long *kvmppc_uvmem_bitmap; -static DEFINE_SPINLOCK(kvmppc_uvmem_bitmap_lock); /* * States of a GFN @@ -697,23 +697,20 @@ static struct page *kvmppc_uvmem_get_page(unsigned long gpa, struct kvm *kvm) struct page *dpage = NULL; unsigned long bit, uvmem_pfn; struct kvmppc_uvmem_page_pvt *pvt; - unsigned long pfn_last, pfn_first; + unsigned long num_pfns, pfn_first; pfn_first = kvmppc_uvmem_pgmap.range.start >> PAGE_SHIFT; - pfn_last = pfn_first + - (range_len(&kvmppc_uvmem_pgmap.range) >> PAGE_SHIFT); + num_pfns = range_len(&kvmppc_uvmem_pgmap.range) >> PAGE_SHIFT; - spin_lock(&kvmppc_uvmem_bitmap_lock); - bit = find_first_zero_bit(kvmppc_uvmem_bitmap, - pfn_last - pfn_first); - if (bit >= (pfn_last - pfn_first)) - goto out; - bitmap_set(kvmppc_uvmem_bitmap, bit, 1); - spin_unlock(&kvmppc_uvmem_bitmap_lock); + bit = find_and_set_bit(kvmppc_uvmem_bitmap, num_pfns); + if (bit >= num_pfns) + return NULL; pvt = kzalloc(sizeof(*pvt), GFP_KERNEL); - if (!pvt) - goto out_clear; + if (!pvt) { + clear_bit(bit, kvmppc_uvmem_bitmap); + return NULL; + } uvmem_pfn = bit + pfn_first; kvmppc_gfn_secure_uvmem_pfn(gpa >> PAGE_SHIFT, uvmem_pfn, kvm); @@ -725,12 +722,6 @@ static struct page *kvmppc_uvmem_get_page(unsigned long gpa, struct kvm *kvm) dpage->zone_device_data = pvt; zone_device_page_init(dpage); return dpage; -out_clear: - spin_lock(&kvmppc_uvmem_bitmap_lock); - bitmap_clear(kvmppc_uvmem_bitmap, bit, 1); -out: - spin_unlock(&kvmppc_uvmem_bitmap_lock); - return NULL; } /* @@ -1021,9 +1012,7 @@ static void kvmppc_uvmem_page_free(struct page *page) (kvmppc_uvmem_pgmap.range.start >> PAGE_SHIFT); struct kvmppc_uvmem_page_pvt *pvt; - spin_lock(&kvmppc_uvmem_bitmap_lock); - bitmap_clear(kvmppc_uvmem_bitmap, pfn, 1); - spin_unlock(&kvmppc_uvmem_bitmap_lock); + clear_bit(pfn, kvmppc_uvmem_bitmap); pvt = page->zone_device_data; page->zone_device_data = NULL; -- 2.43.0
[PATCH v4 40/40] powerpc/xive: drop locking around IRQ map
The code operates on individual bits of the bitmap, and leveraging atomic find ops we can drop locking scheme around the map. Signed-off-by: Yury Norov --- arch/powerpc/sysdev/xive/spapr.c | 34 ++-- 1 file changed, 6 insertions(+), 28 deletions(-) diff --git a/arch/powerpc/sysdev/xive/spapr.c b/arch/powerpc/sysdev/xive/spapr.c index e45419264391..2b3b8ad75b42 100644 --- a/arch/powerpc/sysdev/xive/spapr.c +++ b/arch/powerpc/sysdev/xive/spapr.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -41,7 +42,6 @@ struct xive_irq_bitmap { unsigned long *bitmap; unsigned intbase; unsigned intcount; - spinlock_t lock; struct list_headlist; }; @@ -55,7 +55,6 @@ static int __init xive_irq_bitmap_add(int base, int count) if (!xibm) return -ENOMEM; - spin_lock_init(&xibm->lock); xibm->base = base; xibm->count = count; xibm->bitmap = bitmap_zalloc(xibm->count, GFP_KERNEL); @@ -81,47 +80,26 @@ static void xive_irq_bitmap_remove_all(void) } } -static int __xive_irq_bitmap_alloc(struct xive_irq_bitmap *xibm) -{ - int irq; - - irq = find_first_zero_bit(xibm->bitmap, xibm->count); - if (irq != xibm->count) { - set_bit(irq, xibm->bitmap); - irq += xibm->base; - } else { - irq = -ENOMEM; - } - - return irq; -} - static int xive_irq_bitmap_alloc(void) { struct xive_irq_bitmap *xibm; - unsigned long flags; - int irq = -ENOENT; list_for_each_entry(xibm, &xive_irq_bitmaps, list) { - spin_lock_irqsave(&xibm->lock, flags); - irq = __xive_irq_bitmap_alloc(xibm); - spin_unlock_irqrestore(&xibm->lock, flags); - if (irq >= 0) - break; + int irq = find_and_set_bit(xibm->bitmap, xibm->count); + + if (irq < xibm->count) + return irq + xibm->base; } - return irq; + return -ENOENT; } static void xive_irq_bitmap_free(int irq) { - unsigned long flags; struct xive_irq_bitmap *xibm; list_for_each_entry(xibm, &xive_irq_bitmaps, list) { if ((irq >= xibm->base) && (irq < xibm->base + xibm->count)) { - spin_lock_irqsave(&xibm->lock, flags); clear_bit(irq - xibm->base, xibm->bitmap); - spin_unlock_irqrestore(&xibm->lock, flags); break; } } -- 2.43.0
[Patch v4 04/10] ARM: dts: lpc32xx: Add missing dma and i2s properties
Adds properties declared in the new DT bindings: - nxp,lpc3220-i2s.yaml - nxp,lpc3220-dmamux.yaml for dma router/mux and I2S interface. Signed-off-by: Piotr Wojtaszczyk --- Changes for v4: - This patch is renamed from "ARM: dts: lpc32xx: Add missing properties for the i2s interfaces" to describe dma changes as well - Added dmas and dma-names properties in to all node which have dma request signals - Add bus properties to pl08x dma node since they are removed from platform data in phy3250.c - Put clock-controller@0 and dma-router@7c under the same syscon, simple-mfd device Changes for v3: - Split previous commit for separate subsystems - Add properties to match dt binding arch/arm/boot/dts/nxp/lpc/lpc32xx.dtsi | 53 +++--- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/arch/arm/boot/dts/nxp/lpc/lpc32xx.dtsi b/arch/arm/boot/dts/nxp/lpc/lpc32xx.dtsi index 974410918f35..c58dc127e59f 100644 --- a/arch/arm/boot/dts/nxp/lpc/lpc32xx.dtsi +++ b/arch/arm/boot/dts/nxp/lpc/lpc32xx.dtsi @@ -67,6 +67,8 @@ slc: flash@2002 { reg = <0x2002 0x1000>; clocks = <&clk LPC32XX_CLK_SLC>; status = "disabled"; + dmas = <&dma 1 1>; + dma-names = "rx-tx"; }; mlc: flash@200a8000 { @@ -75,6 +77,8 @@ mlc: flash@200a8000 { interrupts = <11 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clk LPC32XX_CLK_MLC>; status = "disabled"; + dmas = <&dma 12 1>; + dma-names = "rx-tx"; }; dma: dma@3100 { @@ -83,6 +87,13 @@ dma: dma@3100 { interrupts = <28 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clk LPC32XX_CLK_DMA>; clock-names = "apb_pclk"; + #dma-cells = <2>; + dma-channels = <8>; + dma-requests = <16>; + lli-bus-interface-ahb1; + mem-bus-interface-ahb1; + memcpy-burst-size = <256>; + memcpy-bus-width = <32>; }; usb { @@ -182,6 +193,8 @@ ssp0: spi@20084000 { clock-names = "apb_pclk"; #address-cells = <1>; #size-cells = <0>; + dmas = <&dmamux 14 1 1>, <&dmamux 15 1 1>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -191,6 +204,8 @@ spi1: spi@20088000 { clocks = <&clk LPC32XX_CLK_SPI1>; #address-cells = <1>; #size-cells = <0>; + dmas = <&dmamux 11 1 0>; + dma-names = "rx-tx"; status = "disabled"; }; @@ -206,6 +221,8 @@ ssp1: spi@2008c000 { clock-names = "apb_pclk"; #address-cells = <1>; #size-cells = <0>; + dmas = <&dmamux 3 1 1>, <&dmamux 11 1 1>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -215,12 +232,19 @@ spi2: spi@2009 { clocks = <&clk LPC32XX_CLK_SPI2>; #address-cells = <1>; #size-cells = <0>; + dmas = <&dmamux 3 1 0>; + dma-names = "rx-tx"; status = "disabled"; }; i2s0: i2s@20094000 { compatible = "nxp,lpc3220-i2s"; reg = <0x20094000 0x1000>; + interrupts = <22 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&clk LPC32XX_CLK_I2S0>; + dmas = <&dma 0 1>, <&dma 13 1>; + dma-names = "rx", "tx"; + #sound-dai-cells = <0>; status = "disabled"; }; @@ -231,12 +255,19 @@ sd: sd@20098000 { <13 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clk LPC32XX_CLK_SD>; clock-names = "apb_pclk"; + dmas = <&dma 4 1>; + dma-names = "rx"; status = "disabled"; }; i2s1: i2s@2009c000 {
[Patch v4 05/10] clk: lpc32xx: initialize regmap using parent syscon
This allows to share the regmap with other simple-mfd devices like nxp,lpc32xx-dmamux Signed-off-by: Piotr Wojtaszczyk --- Changes for v4: - This patch is new in v4 drivers/clk/Kconfig | 1 + drivers/clk/nxp/clk-lpc32xx.c | 10 ++ 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 3e9099504fad..85ef57d5cccf 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -346,6 +346,7 @@ config COMMON_CLK_LOONGSON2 config COMMON_CLK_NXP def_bool COMMON_CLK && (ARCH_LPC18XX || ARCH_LPC32XX) select REGMAP_MMIO if ARCH_LPC32XX + select MFD_SYSCON if ARCH_LPC32XX select MFD_SYSCON if ARCH_LPC18XX help Support for clock providers on NXP platforms. diff --git a/drivers/clk/nxp/clk-lpc32xx.c b/drivers/clk/nxp/clk-lpc32xx.c index d0f870eff0d6..2a183a9ded93 100644 --- a/drivers/clk/nxp/clk-lpc32xx.c +++ b/drivers/clk/nxp/clk-lpc32xx.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -1511,17 +1512,10 @@ static void __init lpc32xx_clk_init(struct device_node *np) return; } - base = of_iomap(np, 0); - if (!base) { - pr_err("failed to map system control block registers\n"); - return; - } - - clk_regmap = regmap_init_mmio(NULL, base, &lpc32xx_scb_regmap_config); + clk_regmap = syscon_node_to_regmap(np->parent); if (IS_ERR(clk_regmap)) { pr_err("failed to regmap system control block: %ld\n", PTR_ERR(clk_regmap)); - iounmap(base); return; } -- 2.25.1
[Patch v4 06/10] dmaengine: Add dma router for pl08x in LPC32XX SoC
LPC32XX connects few of its peripherals to pl08x DMA thru a multiplexer, this driver allows to route a signal request line thru the multiplexer for given peripheral. Signed-off-by: Piotr Wojtaszczyk --- Changes for v4: - This patch is new in v4 MAINTAINERS | 1 + drivers/dma/Kconfig | 9 ++ drivers/dma/Makefile | 1 + drivers/dma/lpc32xx-dmamux.c | 195 +++ 4 files changed, 206 insertions(+) create mode 100644 drivers/dma/lpc32xx-dmamux.c diff --git a/MAINTAINERS b/MAINTAINERS index fadf1baafd89..5ffe988ee282 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2403,6 +2403,7 @@ R:Vladimir Zapolskiy L: linux-arm-ker...@lists.infradead.org (moderated for non-subscribers) S: Maintained F: Documentation/devicetree/bindings/dma/nxp,lpc3220-dmamux.yaml +F: drivers/dma/lpc32xx-dmamux.c N: lpc32xx ARM/Marvell Dove/MV78xx0/Orion SOC support diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 002a5ec80620..aeace3d7e066 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -378,6 +378,15 @@ config LPC18XX_DMAMUX Enable support for DMA on NXP LPC18xx/43xx platforms with PL080 and multiplexed DMA request lines. +config LPC32XX_DMAMUX + bool "NXP LPC32xx DMA MUX for PL080" + depends on ARCH_LPC32XX || COMPILE_TEST + depends on OF && AMBA_PL08X + select MFD_SYSCON + help + Support for PL080 multiplexed DMA request lines on + LPC32XX platrofm. + config LS2X_APB_DMA tristate "Loongson LS2X APB DMA support" depends on LOONGARCH || COMPILE_TEST diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile index 802ca916f05f..6f1350b62e7f 100644 --- a/drivers/dma/Makefile +++ b/drivers/dma/Makefile @@ -50,6 +50,7 @@ obj-$(CONFIG_INTEL_IOATDMA) += ioat/ obj-y += idxd/ obj-$(CONFIG_K3_DMA) += k3dma.o obj-$(CONFIG_LPC18XX_DMAMUX) += lpc18xx-dmamux.o +obj-$(CONFIG_LPC32XX_DMAMUX) += lpc32xx-dmamux.o obj-$(CONFIG_LS2X_APB_DMA) += ls2x-apb-dma.o obj-$(CONFIG_MILBEAUT_HDMAC) += milbeaut-hdmac.o obj-$(CONFIG_MILBEAUT_XDMAC) += milbeaut-xdmac.o diff --git a/drivers/dma/lpc32xx-dmamux.c b/drivers/dma/lpc32xx-dmamux.c new file mode 100644 index ..4e6ce6026164 --- /dev/null +++ b/drivers/dma/lpc32xx-dmamux.c @@ -0,0 +1,195 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// Copyright 2024 Timesys Corporation +// +// Based on TI DMA Crossbar driver by: +// Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com +// Author: Peter Ujfalusi + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LPC32XX_SSP_CLK_CTRL 0x78 +#define LPC32XX_I2S_CLK_CTRL 0x7c + +struct lpc32xx_dmamux { + int signal; + char *name_sel0; + char *name_sel1; + int muxval; + int muxreg; + int bit; + bool busy; +}; + +/* From LPC32x0 User manual "3.2.1 DMA request signals" */ +static struct lpc32xx_dmamux lpc32xx_muxes[] = { + { + .signal = 3, + .name_sel0 = "spi2-rx-tx", + .name_sel1 = "ssp1-rx", + .muxreg = LPC32XX_SSP_CLK_CTRL, + .bit = 5, + }, + { + .signal = 10, + .name_sel0 = "uart7-rx", + .name_sel1 = "i2s1-dma1", + .muxreg = LPC32XX_I2S_CLK_CTRL, + .bit = 4, + }, + { + .signal = 11, + .name_sel0 = "spi1-rx-tx", + .name_sel1 = "ssp1-tx", + .muxreg = LPC32XX_SSP_CLK_CTRL, + .bit = 4, + }, + { + .signal = 14, + .name_sel0 = "none", + .name_sel1 = "ssp0-rx", + .muxreg = LPC32XX_SSP_CLK_CTRL, + .bit = 3, + }, + { + .signal = 15, + .name_sel0 = "none", + .name_sel1 = "ssp0-tx", + .muxreg = LPC32XX_SSP_CLK_CTRL, + .bit = 2, + }, +}; + +struct lpc32xx_dmamux_data { + struct dma_router dmarouter; + struct regmap *reg; + spinlock_t lock; /* protects busy status flag */ +}; + +static void lpc32xx_dmamux_release(struct device *dev, void *route_data) +{ + struct lpc32xx_dmamux_data *dmamux = dev_get_drvdata(dev); + struct lpc32xx_dmamux *mux = route_data; + unsigned long flags; + + dev_dbg(dev, "releasing dma request signal %d routed to %s\n", + mux->signal, mux->muxval ? mux->name_sel1 : mux->name_sel1); + + guard(spinlock)(&dmamux->lock); + + mux->busy = false; +} + +static void *lpc32xx_dmamux_reserve(struct of_phandle_args *dma_spec, + struct of_dma *ofdma) +{ + struct platform_device *pdev = of_find_device_by_node(ofdma->of_node); + struct device *dev = &pdev->dev; + struct lpc32xx_dmamux_data *dmamux = platform_
[Patch v4 07/10] ARM: lpc32xx: Remove pl08x platform data in favor for device tree
With the driver for nxp,lpc3220-dmamux we can remove the pl08x platform data and let pl08x driver to create peripheral channels from the DT properties. Signed-off-by: Piotr Wojtaszczyk --- Changes for v4: - This patch is new in v4 arch/arm/mach-lpc32xx/phy3250.c | 54 - 1 file changed, 54 deletions(-) diff --git a/arch/arm/mach-lpc32xx/phy3250.c b/arch/arm/mach-lpc32xx/phy3250.c index 66701bf43248..0c7797a0e44e 100644 --- a/arch/arm/mach-lpc32xx/phy3250.c +++ b/arch/arm/mach-lpc32xx/phy3250.c @@ -16,64 +16,10 @@ #include #include "common.h" -static struct pl08x_channel_data pl08x_slave_channels[] = { - { - .bus_id = "nand-slc", - .min_signal = 1, /* SLC NAND Flash */ - .max_signal = 1, - .periph_buses = PL08X_AHB1, - }, - { - .bus_id = "nand-mlc", - .min_signal = 12, /* MLC NAND Flash */ - .max_signal = 12, - .periph_buses = PL08X_AHB1, - }, -}; - -static int pl08x_get_signal(const struct pl08x_channel_data *cd) -{ - return cd->min_signal; -} - -static void pl08x_put_signal(const struct pl08x_channel_data *cd, int ch) -{ -} - -static struct pl08x_platform_data pl08x_pd = { - /* Some reasonable memcpy defaults */ - .memcpy_burst_size = PL08X_BURST_SZ_256, - .memcpy_bus_width = PL08X_BUS_WIDTH_32_BITS, - .slave_channels = &pl08x_slave_channels[0], - .num_slave_channels = ARRAY_SIZE(pl08x_slave_channels), - .get_xfer_signal = pl08x_get_signal, - .put_xfer_signal = pl08x_put_signal, - .lli_buses = PL08X_AHB1, - .mem_buses = PL08X_AHB1, -}; - -static struct lpc32xx_slc_platform_data lpc32xx_slc_data = { - .dma_filter = pl08x_filter_id, -}; - -static struct lpc32xx_mlc_platform_data lpc32xx_mlc_data = { - .dma_filter = pl08x_filter_id, -}; - -static const struct of_dev_auxdata lpc32xx_auxdata_lookup[] __initconst = { - OF_DEV_AUXDATA("arm,pl080", 0x3100, "pl08xdmac", &pl08x_pd), - OF_DEV_AUXDATA("nxp,lpc3220-slc", 0x2002, "2002.flash", - &lpc32xx_slc_data), - OF_DEV_AUXDATA("nxp,lpc3220-mlc", 0x200a8000, "200a8000.flash", - &lpc32xx_mlc_data), - { } -}; - static void __init lpc3250_machine_init(void) { lpc32xx_serial_init(); - of_platform_default_populate(NULL, lpc32xx_auxdata_lookup, NULL); } static const char *const lpc32xx_dt_compat[] __initconst = { -- 2.25.1
[Patch v4 08/10] mtd: rawnand: lpx32xx: Request DMA channels using DT entries
Move away from pl08x platform data towards device tree. Signed-off-by: Piotr Wojtaszczyk --- Changes for v4: - This patch is new in v4 drivers/mtd/nand/raw/lpc32xx_mlc.c | 10 +- drivers/mtd/nand/raw/lpc32xx_slc.c | 10 +- 2 files changed, 2 insertions(+), 18 deletions(-) diff --git a/drivers/mtd/nand/raw/lpc32xx_mlc.c b/drivers/mtd/nand/raw/lpc32xx_mlc.c index 677fcb03f9be..e504e3c5af11 100644 --- a/drivers/mtd/nand/raw/lpc32xx_mlc.c +++ b/drivers/mtd/nand/raw/lpc32xx_mlc.c @@ -574,15 +574,7 @@ static int lpc32xx_dma_setup(struct lpc32xx_nand_host *host) struct mtd_info *mtd = nand_to_mtd(&host->nand_chip); dma_cap_mask_t mask; - if (!host->pdata || !host->pdata->dma_filter) { - dev_err(mtd->dev.parent, "no DMA platform data\n"); - return -ENOENT; - } - - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - host->dma_chan = dma_request_channel(mask, host->pdata->dma_filter, -"nand-mlc"); + host->dma_chan = dma_request_chan(mtd->dev.parent, "rx-tx"); if (!host->dma_chan) { dev_err(mtd->dev.parent, "Failed to request DMA channel\n"); return -EBUSY; diff --git a/drivers/mtd/nand/raw/lpc32xx_slc.c b/drivers/mtd/nand/raw/lpc32xx_slc.c index 1c5fa855b9f2..f83a31411bde 100644 --- a/drivers/mtd/nand/raw/lpc32xx_slc.c +++ b/drivers/mtd/nand/raw/lpc32xx_slc.c @@ -721,15 +721,7 @@ static int lpc32xx_nand_dma_setup(struct lpc32xx_nand_host *host) struct mtd_info *mtd = nand_to_mtd(&host->nand_chip); dma_cap_mask_t mask; - if (!host->pdata || !host->pdata->dma_filter) { - dev_err(mtd->dev.parent, "no DMA platform data\n"); - return -ENOENT; - } - - dma_cap_zero(mask); - dma_cap_set(DMA_SLAVE, mask); - host->dma_chan = dma_request_channel(mask, host->pdata->dma_filter, -"nand-slc"); + host->dma_chan = dma_request_chan(mtd->dev.parent, "rx-tx"); if (!host->dma_chan) { dev_err(mtd->dev.parent, "Failed to request DMA channel\n"); return -EBUSY; -- 2.25.1
[Patch v4 09/10] ASoC: fsl: Add i2s and pcm drivers for LPC32xx CPUs
This driver was ported from an old version in linux 2.6.27 and adjusted for the new ASoC framework and DMA API. Signed-off-by: Piotr Wojtaszczyk --- Changes for v4: - Add to MAINTAINERS - Use guard(mutex)(&i2s_info_p->lock) when possible - Request dma chennels using DT entries in devm_snd_dmaengine_pcm_register Changes for v3: - Split previous commit for separate subsystems - Add support and as a maintainer for the driver - Replaced `SND_SOC` config dependency with COMPILE_TEST - Moved `snd-soc-fsl-lpc3xxx-y` in Makefile up in the list to maintain alfabedical order - Changed comment to c++ format - replaced custom absd32() with standard abs() function - Added clock provider check in lpc3xxx_i2s_set_dai_fmt() - Removed empty lpc32xx_i2s_remove() function - Reworked i2s regs definitions to include LPC3XXX prefix - Replaced custom _BIT, _SBD with standard BIT and FIELD_PREP macros Changes for v2: - Coding Style cleanup - Use dev_err_probe() for error handling in probe function - Removed unneded err_clk_disable label - Removed empty function - Droped of_match_ptr in lpc32xx_i2s_match DT match table - ASoC struct adjustmes for the latest 6.10-rc3 kernel MAINTAINERS | 1 + sound/soc/fsl/Kconfig | 7 + sound/soc/fsl/Makefile | 2 + sound/soc/fsl/lpc3xxx-i2s.c | 376 sound/soc/fsl/lpc3xxx-i2s.h | 79 sound/soc/fsl/lpc3xxx-pcm.c | 73 +++ 6 files changed, 538 insertions(+) create mode 100644 sound/soc/fsl/lpc3xxx-i2s.c create mode 100644 sound/soc/fsl/lpc3xxx-i2s.h create mode 100644 sound/soc/fsl/lpc3xxx-pcm.c diff --git a/MAINTAINERS b/MAINTAINERS index 5ffe988ee282..2705f48c967d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8927,6 +8927,7 @@ L:alsa-de...@alsa-project.org (moderated for non-subscribers) L: linuxppc-dev@lists.ozlabs.org S: Maintained F: Documentation/devicetree/bindings/sound/nxp,lpc3220-i2s.yaml +F: sound/soc/fsl/lpc3xxx-* N: lpc32xx FREESCALE SOC SOUND QMC DRIVER diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 270726c134b3..72f2d4d15696 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -130,6 +130,13 @@ config SND_SOC_FSL_RPMSG This option is only useful for out-of-tree drivers since in-tree drivers select it automatically. +config SND_SOC_FSL_LPC3XXX + tristate "SoC Audio for NXP LPC32XX CPUs" + depends on ARCH_LPC32XX || COMPILE_TEST + select SND_SOC_GENERIC_DMAENGINE_PCM + help + Say Y or M if you want to add support for the LPC3XXX I2S interface. + config SND_SOC_IMX_PCM_DMA tristate select SND_SOC_GENERIC_DMAENGINE_PCM diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index 2fe78eed3a48..2a61e2f96438 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_SND_SOC_P1022_RDK) += snd-soc-p1022-rdk.o snd-soc-fsl-audmix-y := fsl_audmix.o snd-soc-fsl-asoc-card-y := fsl-asoc-card.o snd-soc-fsl-asrc-y := fsl_asrc.o fsl_asrc_dma.o +snd-soc-fsl-lpc3xxx-y := lpc3xxx-pcm.o lpc3xxx-i2s.o snd-soc-fsl-sai-y := fsl_sai.o snd-soc-fsl-ssi-y := fsl_ssi.o snd-soc-fsl-ssi-$(CONFIG_DEBUG_FS) += fsl_ssi_dbg.o @@ -29,6 +30,7 @@ snd-soc-fsl-qmc-audio-y := fsl_qmc_audio.o obj-$(CONFIG_SND_SOC_FSL_AUDMIX) += snd-soc-fsl-audmix.o obj-$(CONFIG_SND_SOC_FSL_ASOC_CARD) += snd-soc-fsl-asoc-card.o obj-$(CONFIG_SND_SOC_FSL_ASRC) += snd-soc-fsl-asrc.o +obj-$(CONFIG_SND_SOC_FSL_LPC3XXX) += snd-soc-fsl-lpc3xxx.o obj-$(CONFIG_SND_SOC_FSL_SAI) += snd-soc-fsl-sai.o obj-$(CONFIG_SND_SOC_FSL_SSI) += snd-soc-fsl-ssi.o obj-$(CONFIG_SND_SOC_FSL_SPDIF) += snd-soc-fsl-spdif.o diff --git a/sound/soc/fsl/lpc3xxx-i2s.c b/sound/soc/fsl/lpc3xxx-i2s.c new file mode 100644 index ..7fdba451c643 --- /dev/null +++ b/sound/soc/fsl/lpc3xxx-i2s.c @@ -0,0 +1,376 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +// +// Author: Kevin Wells +// +// Copyright (C) 2008 NXP Semiconductors +// Copyright 2023 Timesys Corporation + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "lpc3xxx-i2s.h" + +#define I2S_PLAYBACK_FLAG 0x1 +#define I2S_CAPTURE_FLAG 0x2 + +#define LPC3XXX_I2S_RATES ( \ + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \ + SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \ + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000) + +#define LPC3XXX_I2S_FORMATS ( \ + SNDRV_PCM_FMTBIT_S8 | \ + SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S32_LE) + +static void __lpc3xxx_find_clkdiv(u32 *clkx, u32 *clky, int freq, int xbytes, u32 clkrate) +{ + u32 i2srate; + u32 idxx, idyy; + u32 savedbitclkrate, diff, trate, baseclk; + + /* Adjust rate for sample size (bits) and 2 channels and offset for +* divider in clock output +*/ + i2srate = (freq / 100) * 2 * (8 * xbytes
[Patch v4 10/10] i2x: pnx: Use threaded irq to fix warning from del_timer_sync()
When del_timer_sync() is called in an interrupt context it throws a warning because of potential deadlock. Threaded irq handler fixes the potential problem. Signed-off-by: Piotr Wojtaszczyk --- drivers/i2c/busses/i2c-pnx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c index a12525b3186b..b2ab6fb168bf 100644 --- a/drivers/i2c/busses/i2c-pnx.c +++ b/drivers/i2c/busses/i2c-pnx.c @@ -718,8 +718,8 @@ static int i2c_pnx_probe(struct platform_device *pdev) ret = alg_data->irq; goto out_clock; } - ret = devm_request_irq(&pdev->dev, alg_data->irq, i2c_pnx_interrupt, - 0, pdev->name, alg_data); + ret = devm_request_threaded_irq(&pdev->dev, alg_data->irq, NULL, i2c_pnx_interrupt, + IRQF_ONESHOT, pdev->name, alg_data); if (ret) goto out_clock; -- 2.25.1
[RFC PATCH v3 00/11] powerpc: Add support for ftrace direct and BPF trampolines
This is v3 of the patches posted here: http://lkml.kernel.org/r/cover.1718008093.git.nav...@kernel.org Since v2, I have addressed review comments from Steven and Masahiro along with a few fixes. Patches 7-11 are new in this series and add support for ftrace direct and bpf trampolines. This series depends on the patch series from Benjamin Gray adding support for patch_ulong(): http://lkml.kernel.org/r/20240515024445.236364-1-bg...@linux.ibm.com - Naveen Naveen N Rao (11): powerpc/kprobes: Use ftrace to determine if a probe is at function entry powerpc/ftrace: Unify 32-bit and 64-bit ftrace entry code powerpc/module_64: Convert #ifdef to IS_ENABLED() powerpc/ftrace: Remove pointer to struct module from dyn_arch_ftrace kbuild: Add generic hook for architectures to use before the final vmlinux link powerpc64/ftrace: Move ftrace sequence out of line powerpc/ftrace: Add support for DYNAMIC_FTRACE_WITH_CALL_OPS powerpc/ftrace: Add support for DYNAMIC_FTRACE_WITH_DIRECT_CALLS samples/ftrace: Add support for ftrace direct samples on powerpc powerpc64/bpf: Fold bpf_jit_emit_func_call_hlp() into bpf_jit_emit_func_call_rel() powerpc64/bpf: Add support for bpf trampolines arch/Kconfig| 3 + arch/powerpc/Kconfig| 9 + arch/powerpc/Makefile | 8 + arch/powerpc/include/asm/ftrace.h | 29 +- arch/powerpc/include/asm/module.h | 5 + arch/powerpc/include/asm/ppc-opcode.h | 14 + arch/powerpc/kernel/asm-offsets.c | 11 + arch/powerpc/kernel/kprobes.c | 18 +- arch/powerpc/kernel/module_64.c | 67 +- arch/powerpc/kernel/trace/ftrace.c | 269 +++- arch/powerpc/kernel/trace/ftrace_64_pg.c| 73 +- arch/powerpc/kernel/trace/ftrace_entry.S| 210 -- arch/powerpc/kernel/vmlinux.lds.S | 3 +- arch/powerpc/net/bpf_jit.h | 11 + arch/powerpc/net/bpf_jit_comp.c | 702 +++- arch/powerpc/net/bpf_jit_comp32.c | 7 +- arch/powerpc/net/bpf_jit_comp64.c | 68 +- arch/powerpc/tools/Makefile | 10 + arch/powerpc/tools/gen-ftrace-pfe-stubs.sh | 49 ++ samples/ftrace/ftrace-direct-modify.c | 85 ++- samples/ftrace/ftrace-direct-multi-modify.c | 101 ++- samples/ftrace/ftrace-direct-multi.c| 79 ++- samples/ftrace/ftrace-direct-too.c | 83 ++- samples/ftrace/ftrace-direct.c | 69 +- scripts/Makefile.vmlinux| 8 + scripts/link-vmlinux.sh | 11 +- 26 files changed, 1813 insertions(+), 189 deletions(-) create mode 100644 arch/powerpc/tools/Makefile create mode 100755 arch/powerpc/tools/gen-ftrace-pfe-stubs.sh base-commit: e2b06d707dd067509cdc9ceba783c06fa6a551c2 prerequisite-patch-id: a1d50e589288239d5a8b1c1f354cd4737057c9d3 prerequisite-patch-id: da4142d56880861bd0ad7ad7087c9e2670a2ee54 prerequisite-patch-id: 609d292e054b2396b603890522a940fa0bdfb6d8 prerequisite-patch-id: 6f7213fb77b1260defbf43be0e47bff9c80054cc prerequisite-patch-id: ad3b71bf071ae4ba1bee5b087e61a2055772a74f -- 2.45.2
[RFC PATCH v3 02/11] powerpc/ftrace: Unify 32-bit and 64-bit ftrace entry code
On 32-bit powerpc, gcc generates a three instruction sequence for function profiling: mflrr0 stw r0, 4(r1) bl _mcount On kernel boot, the call to _mcount() is nop-ed out, to be patched back in when ftrace is actually enabled. The 'stw' instruction therefore is not necessary unless ftrace is enabled. Nop it out during ftrace init. When ftrace is enabled, we want the 'stw' so that stack unwinding works properly. Perform the same within the ftrace handler, similar to 64-bit powerpc. For 64-bit powerpc, early versions of gcc used to emit a three instruction sequence for function profiling (with -mprofile-kernel) with a 'std' instruction to mimic the 'stw' above. Address that scenario also by nop-ing out the 'std' instruction during ftrace init. Signed-off-by: Naveen N Rao --- arch/powerpc/kernel/trace/ftrace.c | 6 -- arch/powerpc/kernel/trace/ftrace_entry.S | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/arch/powerpc/kernel/trace/ftrace.c b/arch/powerpc/kernel/trace/ftrace.c index d8d6b4fd9a14..463bd7531dc8 100644 --- a/arch/powerpc/kernel/trace/ftrace.c +++ b/arch/powerpc/kernel/trace/ftrace.c @@ -241,13 +241,15 @@ int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec) /* Expected sequence: 'mflr r0', 'stw r0,4(r1)', 'bl _mcount' */ ret = ftrace_validate_inst(ip - 8, ppc_inst(PPC_RAW_MFLR(_R0))); if (!ret) - ret = ftrace_validate_inst(ip - 4, ppc_inst(PPC_RAW_STW(_R0, _R1, 4))); + ret = ftrace_modify_code(ip - 4, ppc_inst(PPC_RAW_STW(_R0, _R1, 4)), +ppc_inst(PPC_RAW_NOP())); } else if (IS_ENABLED(CONFIG_MPROFILE_KERNEL)) { /* Expected sequence: 'mflr r0', ['std r0,16(r1)'], 'bl _mcount' */ ret = ftrace_read_inst(ip - 4, &old); if (!ret && !ppc_inst_equal(old, ppc_inst(PPC_RAW_MFLR(_R0 { ret = ftrace_validate_inst(ip - 8, ppc_inst(PPC_RAW_MFLR(_R0))); - ret |= ftrace_validate_inst(ip - 4, ppc_inst(PPC_RAW_STD(_R0, _R1, 16))); + ret |= ftrace_modify_code(ip - 4, ppc_inst(PPC_RAW_STD(_R0, _R1, 16)), + ppc_inst(PPC_RAW_NOP())); } } else { return -EINVAL; diff --git a/arch/powerpc/kernel/trace/ftrace_entry.S b/arch/powerpc/kernel/trace/ftrace_entry.S index 76dbe9fd2c0f..244a1c7bb1e8 100644 --- a/arch/powerpc/kernel/trace/ftrace_entry.S +++ b/arch/powerpc/kernel/trace/ftrace_entry.S @@ -33,6 +33,8 @@ * and then arrange for the ftrace function to be called. */ .macro ftrace_regs_entry allregs + /* Save the original return address in A's stack frame */ + PPC_STL r0, LRSAVE(r1) /* Create a minimal stack frame for representing B */ PPC_STLUr1, -STACK_FRAME_MIN_SIZE(r1) @@ -44,8 +46,6 @@ SAVE_GPRS(3, 10, r1) #ifdef CONFIG_PPC64 - /* Save the original return address in A's stack frame */ - std r0, LRSAVE+SWITCH_FRAME_SIZE+STACK_FRAME_MIN_SIZE(r1) /* Ok to continue? */ lbz r3, PACA_FTRACE_ENABLED(r13) cmpdi r3, 0 -- 2.45.2
[RFC PATCH v3 03/11] powerpc/module_64: Convert #ifdef to IS_ENABLED()
Minor refactor for converting #ifdef to IS_ENABLED(). Signed-off-by: Naveen N Rao --- arch/powerpc/kernel/module_64.c | 11 +-- 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c index e9bab599d0c2..c202be11683b 100644 --- a/arch/powerpc/kernel/module_64.c +++ b/arch/powerpc/kernel/module_64.c @@ -241,14 +241,13 @@ static unsigned long get_stubs_size(const Elf64_Ehdr *hdr, } } -#ifdef CONFIG_DYNAMIC_FTRACE /* make the trampoline to the ftrace_caller */ - relocs++; -#ifdef CONFIG_DYNAMIC_FTRACE_WITH_REGS + if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE)) + relocs++; + /* an additional one for ftrace_regs_caller */ - relocs++; -#endif -#endif + if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_REGS)) + relocs++; pr_debug("Looks like a total of %lu stubs, max\n", relocs); return relocs * sizeof(struct ppc64_stub_entry); -- 2.45.2
[RFC PATCH v3 04/11] powerpc/ftrace: Remove pointer to struct module from dyn_arch_ftrace
Pointer to struct module is only relevant for ftrace records belonging to kernel modules. Having this field in dyn_arch_ftrace wastes memory for all ftrace records belonging to the kernel. Remove the same in favour of looking up the module from the ftrace record address, similar to other architectures. Signed-off-by: Naveen N Rao --- arch/powerpc/include/asm/ftrace.h| 1 - arch/powerpc/kernel/trace/ftrace.c | 54 +++--- arch/powerpc/kernel/trace/ftrace_64_pg.c | 73 +++- 3 files changed, 65 insertions(+), 63 deletions(-) diff --git a/arch/powerpc/include/asm/ftrace.h b/arch/powerpc/include/asm/ftrace.h index 107fc5a48456..201f9d15430a 100644 --- a/arch/powerpc/include/asm/ftrace.h +++ b/arch/powerpc/include/asm/ftrace.h @@ -26,7 +26,6 @@ unsigned long prepare_ftrace_return(unsigned long parent, unsigned long ip, struct module; struct dyn_ftrace; struct dyn_arch_ftrace { - struct module *mod; }; #ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS diff --git a/arch/powerpc/kernel/trace/ftrace.c b/arch/powerpc/kernel/trace/ftrace.c index 463bd7531dc8..2cff37b5fd2c 100644 --- a/arch/powerpc/kernel/trace/ftrace.c +++ b/arch/powerpc/kernel/trace/ftrace.c @@ -106,28 +106,48 @@ static unsigned long find_ftrace_tramp(unsigned long ip) return 0; } +#ifdef CONFIG_MODULES +static unsigned long ftrace_lookup_module_stub(unsigned long ip, unsigned long addr) +{ + struct module *mod = NULL; + + /* +* NOTE: __module_text_address() must be called with preemption +* disabled, but we can rely on ftrace_lock to ensure that 'mod' +* retains its validity throughout the remainder of this code. +*/ + preempt_disable(); + mod = __module_text_address(ip); + preempt_enable(); + + if (!mod) + pr_err("No module loaded at addr=%lx\n", ip); + + return (addr == (unsigned long)ftrace_caller ? mod->arch.tramp : mod->arch.tramp_regs); +} +#else +static unsigned long ftrace_lookup_module_stub(unsigned long ip, unsigned long addr) +{ + return 0; +} +#endif + static int ftrace_get_call_inst(struct dyn_ftrace *rec, unsigned long addr, ppc_inst_t *call_inst) { unsigned long ip = rec->ip; unsigned long stub; - if (is_offset_in_branch_range(addr - ip)) { + if (is_offset_in_branch_range(addr - ip)) /* Within range */ stub = addr; -#ifdef CONFIG_MODULES - } else if (rec->arch.mod) { - /* Module code would be going to one of the module stubs */ - stub = (addr == (unsigned long)ftrace_caller ? rec->arch.mod->arch.tramp : - rec->arch.mod->arch.tramp_regs); -#endif - } else if (core_kernel_text(ip)) { + else if (core_kernel_text(ip)) /* We would be branching to one of our ftrace stubs */ stub = find_ftrace_tramp(ip); - if (!stub) { - pr_err("0x%lx: No ftrace stubs reachable\n", ip); - return -EINVAL; - } - } else { + else + stub = ftrace_lookup_module_stub(ip, addr); + + if (!stub) { + pr_err("0x%lx: No ftrace stubs reachable\n", ip); return -EINVAL; } @@ -258,14 +278,6 @@ int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec) if (ret) return ret; - if (!core_kernel_text(ip)) { - if (!mod) { - pr_err("0x%lx: No module provided for non-kernel address\n", ip); - return -EFAULT; - } - rec->arch.mod = mod; - } - /* Nop-out the ftrace location */ new = ppc_inst(PPC_RAW_NOP()); addr = MCOUNT_ADDR; diff --git a/arch/powerpc/kernel/trace/ftrace_64_pg.c b/arch/powerpc/kernel/trace/ftrace_64_pg.c index 12fab1803bcf..a563b9ffcc2b 100644 --- a/arch/powerpc/kernel/trace/ftrace_64_pg.c +++ b/arch/powerpc/kernel/trace/ftrace_64_pg.c @@ -116,6 +116,24 @@ static unsigned long find_bl_target(unsigned long ip, ppc_inst_t op) } #ifdef CONFIG_MODULES +static struct module *ftrace_lookup_module(struct dyn_ftrace *rec) +{ + struct module *mod; + /* +* NOTE: __module_text_address() must be called with preemption +* disabled, but we can rely on ftrace_lock to ensure that 'mod' +* retains its validity throughout the remainder of this code. +*/ + preempt_disable(); + mod = __module_text_address(rec->ip); + preempt_enable(); + + if (!mod) + pr_err("No module loaded at addr=%lx\n", rec->ip); + + return mod; +} + static int __ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, unsigned long addr) @@ -124,6 +142,12 @@ __ftrace_make_nop(struct module *mod, unsigned long ip = rec->ip; ppc_ins
[RFC PATCH v3 05/11] kbuild: Add generic hook for architectures to use before the final vmlinux link
On powerpc, we would like to be able to make a pass on vmlinux.o and generate a new object file to be linked into vmlinux. Add a generic pass in Makefile.vmlinux that architectures can use for this purpose. Architectures need to select CONFIG_ARCH_WANTS_PRE_LINK_VMLINUX and must provide arch//tools/Makefile with .arch.vmlinux.o target, which will be invoked prior to the final vmlinux link step. Signed-off-by: Naveen N Rao --- arch/Kconfig | 3 +++ scripts/Makefile.vmlinux | 8 scripts/link-vmlinux.sh | 11 --- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/arch/Kconfig b/arch/Kconfig index 975dd22a2dbd..649f0903e7ef 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -1643,4 +1643,7 @@ config CC_HAS_SANE_FUNCTION_ALIGNMENT config ARCH_NEED_CMPXCHG_1_EMU bool +config ARCH_WANTS_PRE_LINK_VMLINUX + def_bool n + endmenu diff --git a/scripts/Makefile.vmlinux b/scripts/Makefile.vmlinux index 49946cb96844..6410e0be7f52 100644 --- a/scripts/Makefile.vmlinux +++ b/scripts/Makefile.vmlinux @@ -22,6 +22,14 @@ targets += .vmlinux.export.o vmlinux: .vmlinux.export.o endif +ifdef CONFIG_ARCH_WANTS_PRE_LINK_VMLINUX +targets += .arch.vmlinux.o +.arch.vmlinux.o: vmlinux.o FORCE + $(Q)$(MAKE) $(build)=arch/$(SRCARCH)/tools .arch.vmlinux.o + +vmlinux: .arch.vmlinux.o +endif + ARCH_POSTLINK := $(wildcard $(srctree)/arch/$(SRCARCH)/Makefile.postlink) # Final link of vmlinux with optional arch pass after final link diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index 518c70b8db50..aafaed1412ea 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -122,7 +122,7 @@ gen_btf() return 1 fi - vmlinux_link ${1} + vmlinux_link ${1} ${arch_vmlinux_o} info "BTF" ${2} LLVM_OBJCOPY="${OBJCOPY}" ${PAHOLE} -J ${PAHOLE_FLAGS} ${1} @@ -178,7 +178,7 @@ kallsyms_step() kallsymso=${kallsyms_vmlinux}.o kallsyms_S=${kallsyms_vmlinux}.S - vmlinux_link ${kallsyms_vmlinux} "${kallsymso_prev}" ${btf_vmlinux_bin_o} + vmlinux_link ${kallsyms_vmlinux} "${kallsymso_prev}" ${btf_vmlinux_bin_o} ${arch_vmlinux_o} mksysmap ${kallsyms_vmlinux} ${kallsyms_vmlinux}.syms kallsyms ${kallsyms_vmlinux}.syms ${kallsyms_S} @@ -223,6 +223,11 @@ fi ${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init init/version-timestamp.o +arch_vmlinux_o="" +if is_enabled CONFIG_ARCH_WANTS_PRE_LINK_VMLINUX; then + arch_vmlinux_o=.arch.vmlinux.o +fi + btf_vmlinux_bin_o="" if is_enabled CONFIG_DEBUG_INFO_BTF; then btf_vmlinux_bin_o=.btf.vmlinux.bin.o @@ -273,7 +278,7 @@ if is_enabled CONFIG_KALLSYMS; then fi fi -vmlinux_link vmlinux "${kallsymso}" ${btf_vmlinux_bin_o} +vmlinux_link vmlinux "${kallsymso}" ${btf_vmlinux_bin_o} ${arch_vmlinux_o} # fill in BTF IDs if is_enabled CONFIG_DEBUG_INFO_BTF && is_enabled CONFIG_BPF; then -- 2.45.2
[RFC PATCH v3 06/11] powerpc64/ftrace: Move ftrace sequence out of line
Function profile sequence on powerpc includes two instructions at the beginning of each function: mflrr0 bl ftrace_caller The call to ftrace_caller() gets nop'ed out during kernel boot and is patched in when ftrace is enabled. Given the sequence, we cannot return from ftrace_caller with 'blr' as we need to keep LR and r0 intact. This results in link stack imbalance when ftrace is enabled. To address that, we would like to use a three instruction sequence: mflrr0 bl ftrace_caller mtlrr0 Further more, to support DYNAMIC_FTRACE_WITH_CALL_OPS, we need to reserve two instruction slots before the function. This results in a total of five instruction slots to be reserved for ftrace use on each function that is traced. Move the function profile sequence out-of-line to minimize its impact. To do this, we reserve a single nop at function entry using -fpatchable-function-entry=1 and add a pass on vmlinux.o to determine the total number of functions that can be traced. This is then used to generate a .S file reserving the appropriate amount of space for use as ftrace stubs, which is built and linked into vmlinux. On bootup, the stub space is split into separate stubs per function and populated with the proper instruction sequence. A pointer to the associated stub is maintained in dyn_arch_ftrace. For modules, space for ftrace stubs is reserved from the generic module stub space. This is restricted to and enabled by default only on 64-bit powerpc. Signed-off-by: Naveen N Rao --- arch/powerpc/Kconfig | 5 + arch/powerpc/Makefile | 4 + arch/powerpc/include/asm/ftrace.h | 10 ++ arch/powerpc/include/asm/module.h | 5 + arch/powerpc/kernel/asm-offsets.c | 4 + arch/powerpc/kernel/module_64.c| 58 +++- arch/powerpc/kernel/trace/ftrace.c | 147 +++-- arch/powerpc/kernel/trace/ftrace_entry.S | 99 ++ arch/powerpc/kernel/vmlinux.lds.S | 3 +- arch/powerpc/tools/Makefile| 10 ++ arch/powerpc/tools/gen-ftrace-pfe-stubs.sh | 48 +++ 11 files changed, 355 insertions(+), 38 deletions(-) create mode 100644 arch/powerpc/tools/Makefile create mode 100755 arch/powerpc/tools/gen-ftrace-pfe-stubs.sh diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index c88c6d46a5bc..dd7efca2275a 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -568,6 +568,11 @@ config ARCH_USING_PATCHABLE_FUNCTION_ENTRY def_bool $(success,$(srctree)/arch/powerpc/tools/gcc-check-fpatchable-function-entry.sh $(CC) -mlittle-endian) if PPC64 && CPU_LITTLE_ENDIAN def_bool $(success,$(srctree)/arch/powerpc/tools/gcc-check-fpatchable-function-entry.sh $(CC) -mbig-endian) if PPC64 && CPU_BIG_ENDIAN +config FTRACE_PFE_OUT_OF_LINE + def_bool PPC64 && ARCH_USING_PATCHABLE_FUNCTION_ENTRY + depends on PPC64 + select ARCH_WANTS_PRE_LINK_VMLINUX + config HOTPLUG_CPU bool "Support for enabling/disabling CPUs" depends on SMP && (PPC_PSERIES || \ diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index a8479c881cac..bb920d48ec6e 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -155,7 +155,11 @@ CC_FLAGS_NO_FPU:= $(call cc-option,-msoft-float) ifdef CONFIG_FUNCTION_TRACER ifdef CONFIG_ARCH_USING_PATCHABLE_FUNCTION_ENTRY KBUILD_CPPFLAGS+= -DCC_USING_PATCHABLE_FUNCTION_ENTRY +ifdef CONFIG_FTRACE_PFE_OUT_OF_LINE +CC_FLAGS_FTRACE := -fpatchable-function-entry=1 +else CC_FLAGS_FTRACE := -fpatchable-function-entry=2 +endif else CC_FLAGS_FTRACE := -pg ifdef CONFIG_MPROFILE_KERNEL diff --git a/arch/powerpc/include/asm/ftrace.h b/arch/powerpc/include/asm/ftrace.h index 201f9d15430a..9da1da0f87b4 100644 --- a/arch/powerpc/include/asm/ftrace.h +++ b/arch/powerpc/include/asm/ftrace.h @@ -26,6 +26,9 @@ unsigned long prepare_ftrace_return(unsigned long parent, unsigned long ip, struct module; struct dyn_ftrace; struct dyn_arch_ftrace { +#ifdef CONFIG_FTRACE_PFE_OUT_OF_LINE + unsigned long pfe_stub; +#endif }; #ifdef CONFIG_DYNAMIC_FTRACE_WITH_ARGS @@ -132,6 +135,13 @@ static inline u8 this_cpu_get_ftrace_enabled(void) { return 1; } #ifdef CONFIG_FUNCTION_TRACER extern unsigned int ftrace_tramp_text[], ftrace_tramp_init[]; +#ifdef CONFIG_FTRACE_PFE_OUT_OF_LINE +struct ftrace_pfe_stub { + u32 insn[4]; +}; +extern struct ftrace_pfe_stub ftrace_pfe_stub_text[], ftrace_pfe_stub_inittext[]; +extern unsigned long ftrace_pfe_stub_text_count, ftrace_pfe_stub_inittext_count; +#endif void ftrace_free_init_tramp(void); unsigned long ftrace_call_adjust(unsigned long addr); #else diff --git a/arch/powerpc/include/asm/module.h b/arch/powerpc/include/asm/module.h index 300c777cc307..28dbd1ec5593 100644 --- a/arch/powerpc/include/asm/module.h +++ b/arch/powerpc/include/asm/module.h @@ -47,6 +47,11 @@ struct mod_ar
[RFC PATCH v3 07/11] powerpc/ftrace: Add support for DYNAMIC_FTRACE_WITH_CALL_OPS
Implement support for DYNAMIC_FTRACE_WITH_CALL_OPS similar to the arm64 implementation. This works by patching-in a pointer to an associated ftrace_ops structure before each traceable function. If multiple ftrace_ops are associated with a call site, then a special ftrace_list_ops is used to enable iterating over all the registered ftrace_ops. If no ftrace_ops are associated with a call site, then a special ftrace_nop_ops structure is used to render the ftrace call as a no-op. ftrace trampoline can then read the associated ftrace_ops for a call site by loading from an offset from the LR, and branch directly to the associated function. The primary advantage with this approach is that we don't have to iterate over all the registered ftrace_ops for call sites that have a single ftrace_ops registered. This is the equivalent of implementing support for dynamic ftrace trampolines, which set up a special ftrace trampoline for each registered ftrace_ops and have individual call sites branch into those directly. A secondary advantage is that this gives us a way to add support for direct ftrace callers without having to resort to using stubs. The address of the direct call trampoline can be loaded from the ftrace_ops structure. To support this, we reserve a nop before each function on 32-bit powerpc. For 64-bit powerpc, two nops are reserved before each out-of-line stub. During ftrace activation, we update this location with the associated ftrace_ops pointer. Then, on ftrace entry, we load from this location and call into ftrace_ops->func(). For 64-bit powerpc, we ensure that the out-of-line stub area is doubleword aligned so that ftrace_ops address can be updated atomically. Signed-off-by: Naveen N Rao --- arch/powerpc/Kconfig | 1 + arch/powerpc/Makefile | 4 ++ arch/powerpc/include/asm/ftrace.h | 5 +- arch/powerpc/kernel/asm-offsets.c | 4 ++ arch/powerpc/kernel/trace/ftrace.c | 59 +- arch/powerpc/kernel/trace/ftrace_entry.S | 34 ++--- arch/powerpc/tools/gen-ftrace-pfe-stubs.sh | 5 +- 7 files changed, 101 insertions(+), 11 deletions(-) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index dd7efca2275a..fde64ad19de5 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -235,6 +235,7 @@ config PPC select HAVE_DEBUG_STACKOVERFLOW select HAVE_DYNAMIC_FTRACE select HAVE_DYNAMIC_FTRACE_WITH_ARGSif ARCH_USING_PATCHABLE_FUNCTION_ENTRY || MPROFILE_KERNEL || PPC32 + select HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS if FTRACE_PFE_OUT_OF_LINE || (PPC32 && ARCH_USING_PATCHABLE_FUNCTION_ENTRY) select HAVE_DYNAMIC_FTRACE_WITH_REGSif ARCH_USING_PATCHABLE_FUNCTION_ENTRY || MPROFILE_KERNEL || PPC32 select HAVE_EBPF_JIT select HAVE_EFFICIENT_UNALIGNED_ACCESS diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index bb920d48ec6e..c3e577dea137 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -158,8 +158,12 @@ KBUILD_CPPFLAGS+= -DCC_USING_PATCHABLE_FUNCTION_ENTRY ifdef CONFIG_FTRACE_PFE_OUT_OF_LINE CC_FLAGS_FTRACE := -fpatchable-function-entry=1 else +ifdef CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS # PPC32 only +CC_FLAGS_FTRACE := -fpatchable-function-entry=3,1 +else CC_FLAGS_FTRACE := -fpatchable-function-entry=2 endif +endif else CC_FLAGS_FTRACE := -pg ifdef CONFIG_MPROFILE_KERNEL diff --git a/arch/powerpc/include/asm/ftrace.h b/arch/powerpc/include/asm/ftrace.h index 9da1da0f87b4..938cecf72eb1 100644 --- a/arch/powerpc/include/asm/ftrace.h +++ b/arch/powerpc/include/asm/ftrace.h @@ -137,8 +137,11 @@ static inline u8 this_cpu_get_ftrace_enabled(void) { return 1; } extern unsigned int ftrace_tramp_text[], ftrace_tramp_init[]; #ifdef CONFIG_FTRACE_PFE_OUT_OF_LINE struct ftrace_pfe_stub { +#ifdef CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS + struct ftrace_ops *ftrace_op; +#endif u32 insn[4]; -}; +} __aligned(sizeof(unsigned long)); extern struct ftrace_pfe_stub ftrace_pfe_stub_text[], ftrace_pfe_stub_inittext[]; extern unsigned long ftrace_pfe_stub_text_count, ftrace_pfe_stub_inittext_count; #endif diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 5f1a411d714c..a11ea5f4d86a 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -678,5 +678,9 @@ int main(void) DEFINE(FTRACE_PFE_STUB_SIZE, sizeof(struct ftrace_pfe_stub)); #endif +#ifdef CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS + OFFSET(FTRACE_OPS_FUNC, ftrace_ops, func); +#endif + return 0; } diff --git a/arch/powerpc/kernel/trace/ftrace.c b/arch/powerpc/kernel/trace/ftrace.c index 9f3c10307331..028548312c23 100644 --- a/arch/powerpc/kernel/trace/ftrace.c +++ b/arch/powerpc/kernel/trace/ftrace.c @@ -38,8 +38,11 @@ unsigned long ftrace_call_adjust(unsigned long addr) return 0; if (IS_ENABLED(CONFIG_ARCH_USING_PATCHABLE_FUNCTION_ENT
[RFC PATCH v3 08/11] powerpc/ftrace: Add support for DYNAMIC_FTRACE_WITH_DIRECT_CALLS
Add support for DYNAMIC_FTRACE_WITH_DIRECT_CALLS similar to the arm64 implementation. ftrace direct calls allow custom trampolines to be called into directly from function ftrace call sites, bypassing the ftrace trampoline completely. This functionality is currently utilized by BPF trampolines to hook into kernel function entries. Since we have limited relative branch range, we support ftrace direct calls through support for DYNAMIC_FTRACE_WITH_CALL_OPS. In this approach, ftrace trampoline is not entirely bypassed. Rather, it is re-purposed into a stub that reads direct_call field from the associated ftrace_ops structure and branches into that, if it is not NULL. For this, it is sufficient if we can ensure that the ftrace trampoline is reachable from all traceable functions. When multiple ftrace_ops are associated with a call site, we utilize a call back to set pt_regs->orig_gpr3 that can then be tested on the return path from the ftrace trampoline to branch into the direct caller. Signed-off-by: Naveen N Rao --- arch/powerpc/Kconfig | 1 + arch/powerpc/include/asm/ftrace.h| 15 arch/powerpc/kernel/asm-offsets.c| 3 + arch/powerpc/kernel/trace/ftrace.c | 9 +++ arch/powerpc/kernel/trace/ftrace_entry.S | 99 ++-- 5 files changed, 105 insertions(+), 22 deletions(-) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index fde64ad19de5..96ae653bdcde 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -236,6 +236,7 @@ config PPC select HAVE_DYNAMIC_FTRACE select HAVE_DYNAMIC_FTRACE_WITH_ARGSif ARCH_USING_PATCHABLE_FUNCTION_ENTRY || MPROFILE_KERNEL || PPC32 select HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS if FTRACE_PFE_OUT_OF_LINE || (PPC32 && ARCH_USING_PATCHABLE_FUNCTION_ENTRY) + select HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS if HAVE_DYNAMIC_FTRACE_WITH_CALL_OPS select HAVE_DYNAMIC_FTRACE_WITH_REGSif ARCH_USING_PATCHABLE_FUNCTION_ENTRY || MPROFILE_KERNEL || PPC32 select HAVE_EBPF_JIT select HAVE_EFFICIENT_UNALIGNED_ACCESS diff --git a/arch/powerpc/include/asm/ftrace.h b/arch/powerpc/include/asm/ftrace.h index 938cecf72eb1..fc0f25b10e86 100644 --- a/arch/powerpc/include/asm/ftrace.h +++ b/arch/powerpc/include/asm/ftrace.h @@ -147,6 +147,21 @@ extern unsigned long ftrace_pfe_stub_text_count, ftrace_pfe_stub_inittext_count; #endif void ftrace_free_init_tramp(void); unsigned long ftrace_call_adjust(unsigned long addr); + +#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS +/* + * When an ftrace registered caller is tracing a function that is also set by a + * register_ftrace_direct() call, it needs to be differentiated in the + * ftrace_caller trampoline so that the direct call can be invoked after the + * other ftrace ops. To do this, place the direct caller in the orig_gpr3 field + * of pt_regs. This tells ftrace_caller that there's a direct caller. + */ +static inline void arch_ftrace_set_direct_caller(struct ftrace_regs *fregs, unsigned long addr) +{ + struct pt_regs *regs = &fregs->regs; + regs->orig_gpr3 = addr; +} +#endif /* CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS */ #else static inline void ftrace_free_init_tramp(void) { } static inline unsigned long ftrace_call_adjust(unsigned long addr) { return addr; } diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index a11ea5f4d86a..0b955dddeb28 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -680,6 +680,9 @@ int main(void) #ifdef CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS OFFSET(FTRACE_OPS_FUNC, ftrace_ops, func); +#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS + OFFSET(FTRACE_OPS_DIRECT_CALL, ftrace_ops, direct_call); +#endif #endif return 0; diff --git a/arch/powerpc/kernel/trace/ftrace.c b/arch/powerpc/kernel/trace/ftrace.c index 028548312c23..799612ee270f 100644 --- a/arch/powerpc/kernel/trace/ftrace.c +++ b/arch/powerpc/kernel/trace/ftrace.c @@ -153,6 +153,15 @@ static int ftrace_get_call_inst(struct dyn_ftrace *rec, unsigned long addr, ppc_ if (IS_ENABLED(CONFIG_FTRACE_PFE_OUT_OF_LINE)) ip = ftrace_get_pfe_stub(rec) + MCOUNT_INSN_SIZE; /* second instruction in stub */ + if (!is_offset_in_branch_range(addr - ip) && addr != FTRACE_ADDR && addr != FTRACE_REGS_ADDR) { + /* This can only happen with ftrace direct */ + if (!IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS)) { + pr_err("0x%lx (0x%lx): Unexpected target address 0x%lx\n", ip, rec->ip, addr); + return -EINVAL; + } + addr = FTRACE_ADDR; + } + if (is_offset_in_branch_range(addr - ip)) /* Within range */ stub = addr; diff --git a/arch/powerpc/kernel/trace/ftrace_entry.S b/arch/powerpc/kernel/trace/ftrace_entry.S index a76aedd970a6..d5a63e60aafa 100644 --- a/arc
[RFC PATCH v3 01/11] powerpc/kprobes: Use ftrace to determine if a probe is at function entry
Rather than hard-coding the offset into a function to be used to determine if a kprobe is at function entry, use ftrace_location() to determine the ftrace location within the function and categorize all instructions till that offset to be function entry. For functions that cannot be traced, we fall back to using a fixed offset of 8 (two instructions) to categorize a probe as being at function entry for 64-bit elfv2, unless we are using pcrel. Acked-by: Masami Hiramatsu (Google) Signed-off-by: Naveen N Rao --- arch/powerpc/kernel/kprobes.c | 18 -- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index 14c5ddec3056..ca204f4f21c1 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c @@ -105,24 +105,22 @@ kprobe_opcode_t *kprobe_lookup_name(const char *name, unsigned int offset) return addr; } -static bool arch_kprobe_on_func_entry(unsigned long offset) +static bool arch_kprobe_on_func_entry(unsigned long addr, unsigned long offset) { -#ifdef CONFIG_PPC64_ELF_ABI_V2 -#ifdef CONFIG_KPROBES_ON_FTRACE - return offset <= 16; -#else - return offset <= 8; -#endif -#else + unsigned long ip = ftrace_location(addr); + + if (ip) + return offset <= (ip - addr); + if (IS_ENABLED(CONFIG_PPC64_ELF_ABI_V2) && !IS_ENABLED(CONFIG_PPC_KERNEL_PCREL)) + return offset <= 8; return !offset; -#endif } /* XXX try and fold the magic of kprobe_lookup_name() in this */ kprobe_opcode_t *arch_adjust_kprobe_addr(unsigned long addr, unsigned long offset, bool *on_func_entry) { - *on_func_entry = arch_kprobe_on_func_entry(offset); + *on_func_entry = arch_kprobe_on_func_entry(addr, offset); return (kprobe_opcode_t *)(addr + offset); } -- 2.45.2
[RFC PATCH v3 09/11] samples/ftrace: Add support for ftrace direct samples on powerpc
Add powerpc 32-bit and 64-bit samples for ftrace direct. This serves to show the sample instruction sequence to be used by ftrace direct calls to adhere to the ftrace ABI. On 64-bit powerpc, TOC setup requires some additional work. Signed-off-by: Naveen N Rao --- arch/powerpc/Kconfig| 2 + samples/ftrace/ftrace-direct-modify.c | 85 +++- samples/ftrace/ftrace-direct-multi-modify.c | 101 +++- samples/ftrace/ftrace-direct-multi.c| 79 ++- samples/ftrace/ftrace-direct-too.c | 83 +++- samples/ftrace/ftrace-direct.c | 69 - 6 files changed, 414 insertions(+), 5 deletions(-) diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 96ae653bdcde..cf5780d6f7bf 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -275,6 +275,8 @@ config PPC select HAVE_REGS_AND_STACK_ACCESS_API select HAVE_RELIABLE_STACKTRACE select HAVE_RSEQ + select HAVE_SAMPLE_FTRACE_DIRECTif HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS + select HAVE_SAMPLE_FTRACE_DIRECT_MULTI if HAVE_DYNAMIC_FTRACE_WITH_DIRECT_CALLS select HAVE_SETUP_PER_CPU_AREA if PPC64 select HAVE_SOFTIRQ_ON_OWN_STACK select HAVE_STACKPROTECTOR if PPC32 && $(cc-option,-mstack-protector-guard=tls -mstack-protector-guard-reg=r2) diff --git a/samples/ftrace/ftrace-direct-modify.c b/samples/ftrace/ftrace-direct-modify.c index 81220390851a..fa8996e251c8 100644 --- a/samples/ftrace/ftrace-direct-modify.c +++ b/samples/ftrace/ftrace-direct-modify.c @@ -2,7 +2,7 @@ #include #include #include -#ifndef CONFIG_ARM64 +#if !defined(CONFIG_ARM64) && !defined(CONFIG_PPC32) #include #endif @@ -199,6 +199,89 @@ asm ( #endif /* CONFIG_LOONGARCH */ +#ifdef CONFIG_PPC +#include + +#ifdef CONFIG_PPC64 +#define STACK_FRAME_SIZE 48 +#else +#define STACK_FRAME_SIZE 24 +#endif + +#if defined(CONFIG_PPC64_ELF_ABI_V2) && !defined(CONFIG_PPC_KERNEL_PCREL) +#define PPC64_TOC_SAVE_AND_UPDATE \ +" std 2, 24(1)\n" \ +" bcl 20, 31, 1f\n" \ +" 1: mflr12\n" \ +" ld 2, (99f - 1b)(12)\n" +#define PPC64_TOC_RESTORE \ +" ld 2, 24(1)\n" +#define PPC64_TOC \ +" 99:.quad .TOC.@tocbase\n" +#else +#define PPC64_TOC_SAVE_AND_UPDATE "" +#define PPC64_TOC_RESTORE "" +#define PPC64_TOC "" +#endif + +#ifdef CONFIG_FTRACE_PFE_OUT_OF_LINE +#define PPC_FTRACE_RESTORE_LR \ + PPC_LL" 0, "__stringify(PPC_LR_STKOFF)"(1)\n" \ +" mtlr0\n" +#define PPC_FTRACE_RET \ +" blr\n" +#else +#define PPC_FTRACE_RESTORE_LR \ + PPC_LL" 0, "__stringify(PPC_LR_STKOFF)"(1)\n" \ +" mtctr 0\n" +#define PPC_FTRACE_RET \ +" mtlr0\n"\ +" bctr\n" +#endif + +asm ( +" .pushsection.text, \"ax\", @progbits\n" +" .type my_tramp1, @function\n" +" .globl my_tramp1\n" +" my_tramp1:\n" + PPC_STL"0, "__stringify(PPC_LR_STKOFF)"(1)\n" + PPC_STLU" 1, -"__stringify(STACK_FRAME_MIN_SIZE)"(1)\n" +" mflr0\n" + PPC_STL"0, "__stringify(PPC_LR_STKOFF)"(1)\n" + PPC_STLU" 1, -"__stringify(STACK_FRAME_SIZE)"(1)\n" + PPC64_TOC_SAVE_AND_UPDATE +" bl my_direct_func1\n" + PPC64_TOC_RESTORE +" addi1, 1, "__stringify(STACK_FRAME_SIZE)"\n" + PPC_FTRACE_RESTORE_LR +" addi1, 1, "__stringify(STACK_FRAME_MIN_SIZE)"\n" + PPC_LL" 0, "__stringify(PPC_LR_STKOFF)"(1)\n" + PPC_FTRACE_RET +" .size my_tramp1, .-my_tramp1\n" + +" .type my_tramp2, @function\n" +" .globl my_tramp2\n" +" my_tramp2:\n" + PPC_STL"0, "__stringify(PPC_LR_STKOFF)"(1)\n" + PPC_STLU" 1, -"__stringify(STACK_FRAME_MIN_SIZE)"(1)\n" +" mflr0\n" + PPC_STL"0, "__stringify(PPC_LR_STKOFF)"(1)\n" + PPC_STLU" 1, -"__stringify(STACK_FRAME_SIZE)"(1)\n" + PPC64_TOC_SAVE_AND_UPDATE +" bl my_direct_func2\n" + PPC64_TOC_RESTORE +" addi1, 1, "__stringify(STACK_FRAME_SIZE)"\n" + PPC_FTRACE_RESTORE_LR +" addi1, 1, "__stringify(STACK_FRAME_MIN_SIZE)"\n" + PPC_LL" 0, "__stringify(PPC_LR_STKOFF)"(1)\n" + PPC_FTRACE_RET + PPC64_TOC +" .size my_tramp2, .-my_tramp2\n" +" .popsection\n" +); + +#endif /* CONFIG_PPC */ + static struct ftrace_ops direct; static unsigned long my_tramp = (unsig
Re: [PATCH] powerpc/pseries: Whitelist dtl slub object for copying to userspace
On Thu, Jun 20, 2024 at 10:58:49PM +0530, Anjali K wrote: > However given that: > (i) The dtl buffer is read-only. The dtl trace is a set of metrics which > are collected to be read by privileged users. > (ii) Users usually reads all the dtl entries, not a subset. > > (iii) Read overflows are unlikely to expose anything useful to attackers > > since we are whitelisting the complete slub object and there are no > contiguous memory locations which need to be hidden. > Can we go ahead with the whitelisting using kmem_cache_create_usercopy() > approach? > Or are there other reasons to prefer the bounce buffer approach? Yeah, based on this and what mpe said, I have no objection to just allowing it in kmem_cache_create_usercopy(). I was mainly just curious what the threat model was. :) Reviewed-by: Kees Cook -- Kees Cook
[RFC PATCH v3 10/11] powerpc64/bpf: Fold bpf_jit_emit_func_call_hlp() into bpf_jit_emit_func_call_rel()
Commit 61688a82e047 ("powerpc/bpf: enable kfunc call") enhanced bpf_jit_emit_func_call_hlp() to handle calls out to module region, where bpf progs are generated. The only difference now between bpf_jit_emit_func_call_hlp() and bpf_jit_emit_func_call_rel() is in handling of the initial pass where target function address is not known. Fold that logic into bpf_jit_emit_func_call_hlp() and rename it to bpf_jit_emit_func_call_rel() to simplify bpf function call JIT code. We don't actually need to load/restore TOC across a call out to a different kernel helper or to a different bpf program since they all work with the kernel TOC. We only need to do it if we have to call out to a module function. So, guard TOC load/restore with appropriate conditions. Signed-off-by: Naveen N Rao --- arch/powerpc/net/bpf_jit_comp64.c | 61 +-- 1 file changed, 17 insertions(+), 44 deletions(-) diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c index 7703dcf48be8..288ff32d676f 100644 --- a/arch/powerpc/net/bpf_jit_comp64.c +++ b/arch/powerpc/net/bpf_jit_comp64.c @@ -202,14 +202,22 @@ void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx) EMIT(PPC_RAW_BLR()); } -static int -bpf_jit_emit_func_call_hlp(u32 *image, u32 *fimage, struct codegen_context *ctx, u64 func) +int bpf_jit_emit_func_call_rel(u32 *image, u32 *fimage, struct codegen_context *ctx, u64 func) { unsigned long func_addr = func ? ppc_function_entry((void *)func) : 0; long reladdr; - if (WARN_ON_ONCE(!kernel_text_address(func_addr))) - return -EINVAL; + /* bpf to bpf call, func is not known in the initial pass. Emit 5 nops as a placeholder */ + if (!func) { + for (int i = 0; i < 5; i++) + EMIT(PPC_RAW_NOP()); + /* elfv1 needs an additional instruction to load addr from descriptor */ + if (IS_ENABLED(CONFIG_PPC64_ELF_ABI_V1)) + EMIT(PPC_RAW_NOP()); + EMIT(PPC_RAW_MTCTR(_R12)); + EMIT(PPC_RAW_BCTRL()); + return 0; + } #ifdef CONFIG_PPC_KERNEL_PCREL reladdr = func_addr - local_paca->kernelbase; @@ -266,7 +274,8 @@ bpf_jit_emit_func_call_hlp(u32 *image, u32 *fimage, struct codegen_context *ctx, * We can clobber r2 since we get called through a * function pointer (so caller will save/restore r2). */ - EMIT(PPC_RAW_LD(_R2, bpf_to_ppc(TMP_REG_2), 8)); + if (is_module_text_address(func_addr)) + EMIT(PPC_RAW_LD(_R2, bpf_to_ppc(TMP_REG_2), 8)); } else { PPC_LI64(_R12, func); EMIT(PPC_RAW_MTCTR(_R12)); @@ -276,46 +285,14 @@ bpf_jit_emit_func_call_hlp(u32 *image, u32 *fimage, struct codegen_context *ctx, * Load r2 with kernel TOC as kernel TOC is used if function address falls * within core kernel text. */ - EMIT(PPC_RAW_LD(_R2, _R13, offsetof(struct paca_struct, kernel_toc))); + if (is_module_text_address(func_addr)) + EMIT(PPC_RAW_LD(_R2, _R13, offsetof(struct paca_struct, kernel_toc))); } #endif return 0; } -int bpf_jit_emit_func_call_rel(u32 *image, u32 *fimage, struct codegen_context *ctx, u64 func) -{ - unsigned int i, ctx_idx = ctx->idx; - - if (WARN_ON_ONCE(func && is_module_text_address(func))) - return -EINVAL; - - /* skip past descriptor if elf v1 */ - func += FUNCTION_DESCR_SIZE; - - /* Load function address into r12 */ - PPC_LI64(_R12, func); - - /* For bpf-to-bpf function calls, the callee's address is unknown -* until the last extra pass. As seen above, we use PPC_LI64() to -* load the callee's address, but this may optimize the number of -* instructions required based on the nature of the address. -* -* Since we don't want the number of instructions emitted to increase, -* we pad the optimized PPC_LI64() call with NOPs to guarantee that -* we always have a five-instruction sequence, which is the maximum -* that PPC_LI64() can emit. -*/ - if (!image) - for (i = ctx->idx - ctx_idx; i < 5; i++) - EMIT(PPC_RAW_NOP()); - - EMIT(PPC_RAW_MTCTR(_R12)); - EMIT(PPC_RAW_BCTRL()); - - return 0; -} - static int bpf_jit_emit_tail_call(u32 *image, struct codegen_context *ctx, u32 out) { /* @@ -1047,11 +1024,7 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct code if (ret < 0) return ret; - if (func_addr_fixed) - ret = bpf_jit_emi
[RFC PATCH v3 11/11] powerpc64/bpf: Add support for bpf trampolines
Add support for bpf_arch_text_poke() and arch_prepare_bpf_trampoline() for 64-bit powerpc. BPF prog JIT is extended to mimic 64-bit powerpc approach for ftrace having a single nop at function entry, followed by the function profiling sequence out-of-line and a separate long branch stub for calls to trampolines that are out of range. A dummy_tramp is provided to simplify synchronization similar to arm64. BPF Trampolines adhere to the existing ftrace ABI utilizing a two-instruction profiling sequence, as well as the newer ABI utilizing a three-instruction profiling sequence enabling return with a 'blr'. The trampoline code itself closely follows x86 implementation. While the code is generic, BPF trampolines are only enabled on 64-bit powerpc. 32-bit powerpc will need testing and some updates. Signed-off-by: Naveen N Rao --- arch/powerpc/include/asm/ppc-opcode.h | 14 + arch/powerpc/net/bpf_jit.h| 11 + arch/powerpc/net/bpf_jit_comp.c | 702 +- arch/powerpc/net/bpf_jit_comp32.c | 7 +- arch/powerpc/net/bpf_jit_comp64.c | 7 +- 5 files changed, 738 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/include/asm/ppc-opcode.h b/arch/powerpc/include/asm/ppc-opcode.h index 076ae60b4a55..9eaa2c5d9b73 100644 --- a/arch/powerpc/include/asm/ppc-opcode.h +++ b/arch/powerpc/include/asm/ppc-opcode.h @@ -585,12 +585,26 @@ #define PPC_RAW_MTSPR(spr, d) (0x7c0003a6 | ___PPC_RS(d) | __PPC_SPR(spr)) #define PPC_RAW_EIEIO()(0x7c0006ac) +/* bcl 20,31,$+4 */ +#define PPC_RAW_BCL() (0x429f0005) #define PPC_RAW_BRANCH(offset) (0x4800 | PPC_LI(offset)) #define PPC_RAW_BL(offset) (0x4801 | PPC_LI(offset)) #define PPC_RAW_TW(t0, a, b) (0x7c08 | ___PPC_RS(t0) | ___PPC_RA(a) | ___PPC_RB(b)) #define PPC_RAW_TRAP() PPC_RAW_TW(31, 0, 0) #define PPC_RAW_SETB(t, bfa) (0x7c000100 | ___PPC_RT(t) | ___PPC_RA((bfa) << 2)) +#ifdef CONFIG_PPC32 +#define PPC_RAW_STLPPC_RAW_STW +#define PPC_RAW_STLU PPC_RAW_STWU +#define PPC_RAW_LL PPC_RAW_LWZ +#define PPC_RAW_CMPLI PPC_RAW_CMPWI +#else +#define PPC_RAW_STLPPC_RAW_STD +#define PPC_RAW_STLU PPC_RAW_STDU +#define PPC_RAW_LL PPC_RAW_LD +#define PPC_RAW_CMPLI PPC_RAW_CMPDI +#endif + /* Deal with instructions that older assemblers aren't aware of */ #definePPC_BCCTR_FLUSH stringify_in_c(.long PPC_INST_BCCTR_FLUSH) #definePPC_CP_ABORTstringify_in_c(.long PPC_RAW_CP_ABORT) diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h index cdea5dccaefe..58cdfbfbef94 100644 --- a/arch/powerpc/net/bpf_jit.h +++ b/arch/powerpc/net/bpf_jit.h @@ -21,6 +21,9 @@ #define CTX_NIA(ctx) ((unsigned long)ctx->idx * 4) +#define SZLsizeof(unsigned long) +#define BPF_INSN_SAFETY64 + #define PLANT_INSTR(d, idx, instr) \ do { if (d) { (d)[idx] = instr; } idx++; } while (0) #define EMIT(instr)PLANT_INSTR(image, ctx->idx, instr) @@ -81,6 +84,13 @@ EMIT(PPC_RAW_ORI(d, d, (uintptr_t)(i) & \ 0x)); \ } } while (0) +#define PPC_LI_ADDRPPC_LI64 +#define PPC64_LOAD_PACA()\ + EMIT(PPC_RAW_LD(_R2, _R13, offsetof(struct paca_struct, kernel_toc))) +#else +#define PPC_LI64 BUILD_BUG +#define PPC_LI_ADDRPPC_LI32 +#define PPC64_LOAD_PACA() BUILD_BUG() #endif /* @@ -165,6 +175,7 @@ int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct code u32 *addrs, int pass, bool extra_pass); void bpf_jit_build_prologue(u32 *image, struct codegen_context *ctx); void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx); +void bpf_jit_build_fentry_stubs(u32 *image, struct codegen_context *ctx); void bpf_jit_realloc_regs(struct codegen_context *ctx); int bpf_jit_emit_exit_insn(u32 *image, struct codegen_context *ctx, int tmp_reg, long exit_addr); diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c index 984655419da5..54df51ce54c8 100644 --- a/arch/powerpc/net/bpf_jit_comp.c +++ b/arch/powerpc/net/bpf_jit_comp.c @@ -22,11 +22,81 @@ #include "bpf_jit.h" +/* These offsets are from bpf prog end and stay the same across progs */ +static int bpf_jit_ool_stub, bpf_jit_long_branch_stub; + static void bpf_jit_fill_ill_insns(void *area, unsigned int size) { memset32(area, BREAKPOINT_INSTRUCTION, size / 4); } +void dummy_tramp(void); + +asm ( +" .pushsection .text, \"ax\", @progbits ;" +" .global dummy_tramp ;" +" .type dummy_tramp, @function;" +"dummy_tramp:
Re: [Patch v4 02/10] dt-bindings: dma: Add lpc32xx DMA mux binding
On Thu, 20 Jun 2024 19:56:33 +0200, Piotr Wojtaszczyk wrote: > LPC32XX SoCs use pl080 dma controller which have few request signals > multiplexed between peripherals. This binding describes how devices can > use the multiplexed request signals. > > Signed-off-by: Piotr Wojtaszczyk > --- > Changes for v4: > - This patch is new in v4 > > .../bindings/dma/nxp,lpc3220-dmamux.yaml | 56 +++ > MAINTAINERS | 9 +++ > 2 files changed, 65 insertions(+) > create mode 100644 > Documentation/devicetree/bindings/dma/nxp,lpc3220-dmamux.yaml > My bot found errors running 'make dt_binding_check' on your patch: yamllint warnings/errors: dtschema/dtc warnings/errors: Documentation/devicetree/bindings/dma/nxp,lpc3220-dmamux.example.dtb: /example-0/syscon@40004000: failed to match any schema with compatible: ['nxp,lpc3220-creg', 'syscon', 'simple-mfd'] doc reference errors (make refcheckdocs): See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/20240620175657.358273-3-piotr.wojtaszc...@timesys.com The base for the series is generally the latest rc1. A different dependency should be noted in *this* patch. If you already ran 'make dt_binding_check' and didn't see the above error(s), then make sure 'yamllint' is installed and dt-schema is up to date: pip3 install dtschema --upgrade Please check and re-submit after running the above command yourself. Note that DT_SCHEMA_FILES can be set to your schema file to speed up checking your schema. However, it must be unset to test all examples with your schema.
Re: [PATCH 07/15] parisc: use generic sys_fanotify_mark implementation
On 6/20/24 18:23, Arnd Bergmann wrote: From: Arnd Bergmann The sys_fanotify_mark() syscall on parisc uses the reverse word order for the two halves of the 64-bit argument compared to all syscalls on all 32-bit architectures. As far as I can tell, the problem is that the function arguments on parisc are sorted backwards (26, 25, 24, 23, ...) compared to everyone else, r26 is arg0, r25 is arg1, and so on. I'm not sure I would call this "sorted backwards". I think the reason is simply that hppa is the only 32-bit big-endian arch left... so the calling conventions of using an even/odd register pair in native word order result in the lower word coming first in function arguments, matching the expected behavior on little-endian architectures. The system call conventions however ended up matching what the other 32-bit architectures do. A glibc cleanup in 2020 changed the userspace behavior in a way that handles all architectures consistently, but this inadvertently broke parisc32 by changing to the same method as everyone else. I appreciate such cleanups to make arches consistent. But it's bad if breakages aren't noticed or reported then... The change made it into glibc-2.35 and subsequently into debian 12 (bookworm), which is the latest stable release. This means we need to choose between reverting the glibc change or changing the kernel to match it again, but either hange will leave some systems broken. Pick the option that is more likely to help current and future users and change the kernel to match current glibc. Agreed (assuming we have really a problem on parisc). This also means the behavior is now consistent across architectures, but it breaks running new kernels with old glibc builds before 2.35. Link: https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=d150181d73d9 Link: https://git.kernel.org/pub/scm/linux/kernel/git/history/history.git/commit/arch/parisc/kernel/sys_parisc.c?h=57b1dfbd5b4a39d Cc: Adhemerval Zanella Signed-off-by: Arnd Bergmann --- I found this through code inspection, please double-check to make sure I got the bug and the fix right. The patch looks good at first sight. I'll pick it up in my parisc git tree and will do some testing the next few days and then push forward for 6.11 when it opens Thank you!! Helge The alternative is to fix this by reverting glibc back to the unusual behavior. --- arch/parisc/Kconfig | 1 + arch/parisc/kernel/sys_parisc32.c | 9 - arch/parisc/kernel/syscalls/syscall.tbl | 2 +- 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index daafeb20f993..dc9b902de8ea 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -16,6 +16,7 @@ config PARISC select ARCH_HAS_UBSAN select ARCH_HAS_PTE_SPECIAL select ARCH_NO_SG_CHAIN + select ARCH_SPLIT_ARG64 if !64BIT select ARCH_SUPPORTS_HUGETLBFS if PA20 select ARCH_SUPPORTS_MEMORY_FAILURE select ARCH_STACKWALK diff --git a/arch/parisc/kernel/sys_parisc32.c b/arch/parisc/kernel/sys_parisc32.c index 2a12a547b447..826c8e51b585 100644 --- a/arch/parisc/kernel/sys_parisc32.c +++ b/arch/parisc/kernel/sys_parisc32.c @@ -23,12 +23,3 @@ asmlinkage long sys32_unimplemented(int r26, int r25, int r24, int r23, current->comm, current->pid, r20); return -ENOSYS; } - -asmlinkage long sys32_fanotify_mark(compat_int_t fanotify_fd, compat_uint_t flags, - compat_uint_t mask0, compat_uint_t mask1, compat_int_t dfd, - const char __user * pathname) -{ - return sys_fanotify_mark(fanotify_fd, flags, - ((__u64)mask1 << 32) | mask0, -dfd, pathname); -} diff --git a/arch/parisc/kernel/syscalls/syscall.tbl b/arch/parisc/kernel/syscalls/syscall.tbl index 39e67fab7515..66dc406b12e4 100644 --- a/arch/parisc/kernel/syscalls/syscall.tbl +++ b/arch/parisc/kernel/syscalls/syscall.tbl @@ -364,7 +364,7 @@ 320 common accept4 sys_accept4 321 common prlimit64 sys_prlimit64 322 common fanotify_init sys_fanotify_init -323common fanotify_mark sys_fanotify_mark sys32_fanotify_mark +323common fanotify_mark sys_fanotify_mark compat_sys_fanotify_mark 324 32 clock_adjtime sys_clock_adjtime32 324 64 clock_adjtime sys_clock_adjtime 325 common name_to_handle_at sys_name_to_handle_at
Re: [Patch v4 10/10] i2x: pnx: Use threaded irq to fix warning from del_timer_sync()
Hi Piotr, On Thu, Jun 20, 2024 at 07:56:41PM GMT, Piotr Wojtaszczyk wrote: > When del_timer_sync() is called in an interrupt context it throws a warning > because of potential deadlock. Threaded irq handler fixes the potential > problem. > > Signed-off-by: Piotr Wojtaszczyk did you run into a lockdep splat? Anything against using del_timer(), instead? Have you tried? Thanks, Andi
Re: (subset) [PATCHv5 0/9] ASoC: fsl-asoc-card: add S/PDIF controller
On Thu, 20 Jun 2024 15:25:02 +0200, Elinor Montmasson wrote: > This is the v5 of the series of patches aiming to make the machine > driver `fsl-asoc-card` compatible with S/PDIF controllers on imx boards. > The main goal is to allow the use of S/PDIF controllers with ASRC > modules. > > The `imx-spdif` machine driver already has specific support for S/PDIF > controllers but doesn't support using an ASRC with it. However, the > `fsl-asoc-card` machine driver has the necessary code to create a sound > card which can use an ASRC module. > It is then possible to extend the support for S/PDIF audio cards by > merging the `imx-spdif` driver into `fsl-asoc-card`. > > [...] Applied to https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-next Thanks! [1/9] ASoC: fsl-asoc-card: set priv->pdev before using it commit: 90f3feb24172185f1832636264943e8b5e289245 All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted. You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed. If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced. Please add any relevant lists and maintainers to the CCs when replying to this mail. Thanks, Mark
[powerpc:merge] BUILD SUCCESS e2b06d707dd067509cdc9ceba783c06fa6a551c2
tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git merge branch HEAD: e2b06d707dd067509cdc9ceba783c06fa6a551c2 Automatic merge of 'next' into merge (2024-06-17 15:38) elapsed time: 5231m configs tested: 121 configs skipped: 2 The following configs have been built successfully. More configs may be tested in the coming days. tested configs: alpha allnoconfig gcc-13.2.0 alpha defconfig gcc-13.2.0 arc allnoconfig gcc-13.2.0 arc defconfig gcc-13.2.0 arc randconfig-001-20240618 gcc-13.2.0 arc randconfig-002-20240618 gcc-13.2.0 arm allnoconfig clang-19 arm defconfig clang-14 arm randconfig-001-20240618 gcc-13.2.0 arm randconfig-002-20240618 gcc-13.2.0 arm randconfig-003-20240618 clang-19 arm randconfig-004-20240618 gcc-13.2.0 arm64 allnoconfig gcc-13.2.0 arm64 defconfig gcc-13.2.0 arm64 randconfig-001-20240618 clang-17 arm64 randconfig-002-20240618 clang-19 arm64 randconfig-003-20240618 clang-16 arm64 randconfig-004-20240618 clang-19 csky allnoconfig gcc-13.2.0 cskydefconfig gcc-13.2.0 csky randconfig-001-20240618 gcc-13.2.0 csky randconfig-002-20240618 gcc-13.2.0 hexagon allnoconfig clang-19 hexagon defconfig clang-19 hexagon randconfig-001-20240618 clang-19 hexagon randconfig-002-20240618 clang-19 i386 buildonly-randconfig-001-20240618 gcc-13 i386 buildonly-randconfig-002-20240618 gcc-12 i386 buildonly-randconfig-003-20240618 gcc-8 i386 buildonly-randconfig-004-20240618 gcc-10 i386 buildonly-randconfig-005-20240618 gcc-10 i386 buildonly-randconfig-006-20240618 gcc-10 i386 randconfig-001-20240618 clang-18 i386 randconfig-002-20240618 gcc-13 i386 randconfig-003-20240618 gcc-13 i386 randconfig-004-20240618 clang-18 i386 randconfig-005-20240618 clang-18 i386 randconfig-006-20240618 clang-18 i386 randconfig-011-20240618 gcc-13 i386 randconfig-012-20240618 gcc-11 i386 randconfig-013-20240618 gcc-7 i386 randconfig-014-20240618 gcc-11 i386 randconfig-015-20240618 clang-18 i386 randconfig-016-20240618 clang-18 loongarch allnoconfig gcc-13.2.0 loongarch defconfig gcc-13.2.0 loongarch randconfig-001-20240618 gcc-13.2.0 loongarch randconfig-002-20240618 gcc-13.2.0 m68k allnoconfig gcc-13.2.0 m68kdefconfig gcc-13.2.0 microblazeallnoconfig gcc-13.2.0 microblaze defconfig gcc-13.2.0 mips allnoconfig gcc-13.2.0 nios2 allnoconfig gcc-13.2.0 nios2 defconfig gcc-13.2.0 nios2 randconfig-001-20240618 gcc-13.2.0 nios2 randconfig-002-20240618 gcc-13.2.0 openrisc allnoconfig gcc-13.2.0 openriscdefconfig gcc-13.2.0 pariscallnoconfig gcc-13.2.0 parisc defconfig gcc-13.2.0 pariscrandconfig-001-20240618 gcc-13.2.0 pariscrandconfig-002-20240618 gcc-13.2.0 parisc64defconfig gcc-13.2.0 powerpc allnoconfig gcc-13.2.0 powerpc randconfig-001-20240618 gcc-13.2.0 powerpc randconfig-002-20240618 clang-19 powerpc randconfig-003-20240618 clang-19 powerpc64 randconfig-001-20240618 clang-19 powerpc64 randconfig-002-20240618 clang-17 powerpc64 randconfig-003-20240618 clang-19 riscv allnoconfig gcc-13.2.0 riscv defconfig clang-19 riscv randconfig-001-20240618 gcc-13.2.0 riscv randconfig-002-20240618 clang-14 s390 allnoconfig clang-19 s390defconfig clang-19 s390 randconfig-001-20240618 clang-15 s390 randconfig-002-20240618 gcc-13.2.0 shallnoconfig gcc-13.2.0 s
[PATCH 12/15] net: ibmvnic: Convert tasklet API to new bottom half workqueue mechanism
Migrate tasklet APIs to the new bottom half workqueue mechanism. It replaces all occurrences of tasklet usage with the appropriate workqueue APIs throughout the ibmvnic driver. This transition ensures compatibility with the latest design and enhances performance. Signed-off-by: Allen Pais --- drivers/net/ethernet/ibm/ibmvnic.c | 24 drivers/net/ethernet/ibm/ibmvnic.h | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 5e9a93bdb518..2e817a560c3a 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -2725,7 +2725,7 @@ static const char *reset_reason_to_string(enum ibmvnic_reset_reason reason) /* * Initialize the init_done completion and return code values. We * can get a transport event just after registering the CRQ and the - * tasklet will use this to communicate the transport event. To ensure + * bh work will use this to communicate the transport event. To ensure * we don't miss the notification/error, initialize these _before_ * regisering the CRQ. */ @@ -4429,7 +4429,7 @@ static void send_request_cap(struct ibmvnic_adapter *adapter, int retry) int cap_reqs; /* We send out 6 or 7 REQUEST_CAPABILITY CRQs below (depending on -* the PROMISC flag). Initialize this count upfront. When the tasklet +* the PROMISC flag). Initialize this count upfront. When the bh work * receives a response to all of these, it will send the next protocol * message (QUERY_IP_OFFLOAD). */ @@ -4965,7 +4965,7 @@ static void send_query_cap(struct ibmvnic_adapter *adapter) int cap_reqs; /* We send out 25 QUERY_CAPABILITY CRQs below. Initialize this count -* upfront. When the tasklet receives a response to all of these, it +* upfront. When the bh work receives a response to all of these, it * can send out the next protocol messaage (REQUEST_CAPABILITY). */ cap_reqs = 25; @@ -5477,7 +5477,7 @@ static int handle_login_rsp(union ibmvnic_crq *login_rsp_crq, int i; /* CHECK: Test/set of login_pending does not need to be atomic -* because only ibmvnic_tasklet tests/clears this. +* because only ibmvnic_bh_work tests/clears this. */ if (!adapter->login_pending) { netdev_warn(netdev, "Ignoring unexpected login response\n"); @@ -6063,13 +6063,13 @@ static irqreturn_t ibmvnic_interrupt(int irq, void *instance) { struct ibmvnic_adapter *adapter = instance; - tasklet_schedule(&adapter->tasklet); + queue_work(system_bh_wq, &adapter->bh_work); return IRQ_HANDLED; } -static void ibmvnic_tasklet(struct tasklet_struct *t) +static void ibmvnic_bh_work(struct work_struct *work) { - struct ibmvnic_adapter *adapter = from_tasklet(adapter, t, tasklet); + struct ibmvnic_adapter *adapter = from_work(adapter, work, bh_work); struct ibmvnic_crq_queue *queue = &adapter->crq; union ibmvnic_crq *crq; unsigned long flags; @@ -6150,7 +6150,7 @@ static void release_crq_queue(struct ibmvnic_adapter *adapter) netdev_dbg(adapter->netdev, "Releasing CRQ\n"); free_irq(vdev->irq, adapter); - tasklet_kill(&adapter->tasklet); + cancel_work_sync(&adapter->bh_work); do { rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address); } while (rc == H_BUSY || H_IS_LONG_BUSY(rc)); @@ -6201,7 +6201,7 @@ static int init_crq_queue(struct ibmvnic_adapter *adapter) retrc = 0; - tasklet_setup(&adapter->tasklet, (void *)ibmvnic_tasklet); + INIT_WORK(&adapter->bh_work, (void *)ibmvnic_bh_work); netdev_dbg(adapter->netdev, "registering irq 0x%x\n", vdev->irq); snprintf(crq->name, sizeof(crq->name), "ibmvnic-%x", @@ -6223,12 +6223,12 @@ static int init_crq_queue(struct ibmvnic_adapter *adapter) spin_lock_init(&crq->lock); /* process any CRQs that were queued before we enabled interrupts */ - tasklet_schedule(&adapter->tasklet); + queue_work(system_bh_wq, &adapter->bh_work); return retrc; req_irq_failed: - tasklet_kill(&adapter->tasklet); + cancel_work_sync(&adapter->bh_work); do { rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address); } while (rc == H_BUSY || H_IS_LONG_BUSY(rc)); @@ -6621,7 +6621,7 @@ static int ibmvnic_resume(struct device *dev) if (adapter->state != VNIC_OPEN) return 0; - tasklet_schedule(&adapter->tasklet); + queue_work(system_bh_wq, &adapter->bh_work); return 0; } diff --git a/drivers/net/ethernet/ibm/ibmvnic.h b/drivers/net/ethernet/ibm/ibmvnic.h index 94ac36b1408b..b65b210a8059 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.h +++ b/drivers/net/ethernet/ibm/ibmvnic.h @@ -1036,7 +1036,7 @@ struct ibmvni
Re: [PATCH 07/15] parisc: use generic sys_fanotify_mark implementation
Le 20/06/2024 à 23:21, Helge Deller a écrit : > [Vous ne recevez pas souvent de courriers de del...@gmx.de. Découvrez > pourquoi ceci est important à > https://aka.ms/LearnAboutSenderIdentification ] > > On 6/20/24 18:23, Arnd Bergmann wrote: >> From: Arnd Bergmann >> >> The sys_fanotify_mark() syscall on parisc uses the reverse word order >> for the two halves of the 64-bit argument compared to all syscalls on >> all 32-bit architectures. As far as I can tell, the problem is that >> the function arguments on parisc are sorted backwards (26, 25, 24, 23, >> ...) compared to everyone else, > > r26 is arg0, r25 is arg1, and so on. > I'm not sure I would call this "sorted backwards". > I think the reason is simply that hppa is the only 32-bit big-endian > arch left... powerpc/32 is big-endian: r3 is arg0, r4 is arg1, ... r10 is arg7. In case of a 64bits arg, r3 is the high part and r4 is the low part. Christophe > >> so the calling conventions of using an >> even/odd register pair in native word order result in the lower word >> coming first in function arguments, matching the expected behavior >> on little-endian architectures. The system call conventions however >> ended up matching what the other 32-bit architectures do. >> >> A glibc cleanup in 2020 changed the userspace behavior in a way that >> handles all architectures consistently, but this inadvertently broke >> parisc32 by changing to the same method as everyone else. > > I appreciate such cleanups to make arches consistent. > But it's bad if breakages aren't noticed or reported then... > >> The change made it into glibc-2.35 and subsequently into debian 12 >> (bookworm), which is the latest stable release. This means we >> need to choose between reverting the glibc change or changing the >> kernel to match it again, but either hange will leave some systems >> broken. >> >> Pick the option that is more likely to help current and future >> users and change the kernel to match current glibc. > > Agreed (assuming we have really a problem on parisc). > >> This also >> means the behavior is now consistent across architectures, but >> it breaks running new kernels with old glibc builds before 2.35. >> >> Link: >> https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=d150181d73d9 >> Link: >> https://git.kernel.org/pub/scm/linux/kernel/git/history/history.git/commit/arch/parisc/kernel/sys_parisc.c?h=57b1dfbd5b4a39d >> Cc: Adhemerval Zanella >> Signed-off-by: Arnd Bergmann >> --- >> I found this through code inspection, please double-check to make >> sure I got the bug and the fix right. > > The patch looks good at first sight. > I'll pick it up in my parisc git tree and will do some testing the > next few days and then push forward for 6.11 when it opens > > Thank you!! > > Helge > >> The alternative is to fix this by reverting glibc back to the >> unusual behavior. >> --- >> arch/parisc/Kconfig | 1 + >> arch/parisc/kernel/sys_parisc32.c | 9 - >> arch/parisc/kernel/syscalls/syscall.tbl | 2 +- >> 3 files changed, 2 insertions(+), 10 deletions(-) >> >> diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig >> index daafeb20f993..dc9b902de8ea 100644 >> --- a/arch/parisc/Kconfig >> +++ b/arch/parisc/Kconfig >> @@ -16,6 +16,7 @@ config PARISC >> select ARCH_HAS_UBSAN >> select ARCH_HAS_PTE_SPECIAL >> select ARCH_NO_SG_CHAIN >> + select ARCH_SPLIT_ARG64 if !64BIT >> select ARCH_SUPPORTS_HUGETLBFS if PA20 >> select ARCH_SUPPORTS_MEMORY_FAILURE >> select ARCH_STACKWALK >> diff --git a/arch/parisc/kernel/sys_parisc32.c >> b/arch/parisc/kernel/sys_parisc32.c >> index 2a12a547b447..826c8e51b585 100644 >> --- a/arch/parisc/kernel/sys_parisc32.c >> +++ b/arch/parisc/kernel/sys_parisc32.c >> @@ -23,12 +23,3 @@ asmlinkage long sys32_unimplemented(int r26, int >> r25, int r24, int r23, >> current->comm, current->pid, r20); >> return -ENOSYS; >> } >> - >> -asmlinkage long sys32_fanotify_mark(compat_int_t fanotify_fd, >> compat_uint_t flags, >> - compat_uint_t mask0, compat_uint_t mask1, compat_int_t dfd, >> - const char __user * pathname) >> -{ >> - return sys_fanotify_mark(fanotify_fd, flags, >> - ((__u64)mask1 << 32) | mask0, >> - dfd, pathname); >> -} >> diff --git a/arch/parisc/kernel/syscalls/syscall.tbl >> b/arch/parisc/kernel/syscalls/syscall.tbl >> index 39e67fab7515..66dc406b12e4 100644 >> --- a/arch/parisc/kernel/syscalls/syscall.tbl >> +++ b/arch/parisc/kernel/syscalls/syscall.tbl >> @@ -364,7 +364,7 @@ >> 320 common accept4 sys_accept4 >> 321 common prlimit64 sys_prlimit64 >> 322 common fanotify_init sys_fanotify_init >> -323 common fanotify_mark sys_fanotify_mark >> sys32_fanotify_mark >> +323 common fanotify_mark sys_fanotify_mark >> compat_sys_fanotify_mark >> 324 32 clock_adjtime sys_clock_adjtime32 >>
Re: [Patch v4 04/10] ARM: dts: lpc32xx: Add missing dma and i2s properties
> Adds properties declared in the new DT bindings: Add?How do you think about to replace such an abbreviation? https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process/submitting-patches.rst?h=v6.10-rc4#n94 Regards, Markus
Re: [Patch v4 05/10] clk: lpc32xx: initialize regmap using parent syscon
> This allows to share the regmap with other simple-mfd devices like > nxp,lpc32xx-dmamux Please choose an imperative wording for an improved change description. https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process/submitting-patches.rst?h=v6.10-rc4#n94 Regards, Markus
Re: [Patch v4 06/10] dmaengine: Add dma router for pl08x in LPC32XX SoC
… > this driver allows to route a signal request line thru the multiplexer for > given peripheral. Would you like to choose an imperative wording for an improved change description? https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process/submitting-patches.rst?h=v6.10-rc4#n94 Regards, Markus
Re: [Patch v4 07/10] ARM: lpc32xx: Remove pl08x platform data in favor for device tree
> With the driver for nxp,lpc3220-dmamux we can remove the pl08x platform > data and let pl08x driver to create peripheral channels from the DT > properties. Do you see opportunities to improve such a change description? https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/process/submitting-patches.rst?h=v6.10-rc4#n94 Regards, Markus
[PATCH v1 1/2] powerpc/mmiotrace: Add MMIO Tracing tool for PowerPC
mmiotrace is a useful tool to trace MMIO accesses. Nowadays, it only supported on x86 and x86_64 platforms. Here is a support for powerpc. The manual is located at Documentation/trace/mmiotrace.rst which means I have not changed user API. People will be easy to use it. Almost all files are copied from x86/mm, there are only some differences from hardware and architectures software. LINK: https://lore.kernel.org/lkml/20080127195536.50809...@daedalus.pq.iki.fi/ Signed-off-by: Jialong Yang --- arch/powerpc/Kconfig.debug | 3 + arch/powerpc/mm/Makefile | 1 + arch/powerpc/mm/kmmio.c | 649 +++ arch/powerpc/mm/mmio-mod.c | 414 arch/powerpc/mm/mmiotrace_arch.c | 149 +++ arch/powerpc/mm/mmiotrace_arch.h | 25 ++ arch/powerpc/mm/pf_in.c | 185 + arch/powerpc/mm/pf_in.h | 33 ++ 8 files changed, 1459 insertions(+) create mode 100644 arch/powerpc/mm/kmmio.c create mode 100644 arch/powerpc/mm/mmio-mod.c create mode 100644 arch/powerpc/mm/mmiotrace_arch.c create mode 100644 arch/powerpc/mm/mmiotrace_arch.h create mode 100644 arch/powerpc/mm/pf_in.c create mode 100644 arch/powerpc/mm/pf_in.h diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug index 8c80b154e814..8a69188aa75a 100644 --- a/arch/powerpc/Kconfig.debug +++ b/arch/powerpc/Kconfig.debug @@ -1,5 +1,8 @@ # SPDX-License-Identifier: GPL-2.0 +config HAVE_MMIOTRACE_SUPPORT + def_bool y + config PPC_DISABLE_WERROR bool "Don't build arch/powerpc code with -Werror" help diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile index 0fe2f085c05a..cb92049f1239 100644 --- a/arch/powerpc/mm/Makefile +++ b/arch/powerpc/mm/Makefile @@ -17,3 +17,4 @@ obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-noncoherent.o obj-$(CONFIG_PPC_COPRO_BASE) += copro_fault.o obj-$(CONFIG_PTDUMP_CORE) += ptdump/ obj-$(CONFIG_KASAN)+= kasan/ +obj-$(CONFIG_MMIOTRACE) += kmmio.o mmio-mod.o pf_in.o mmiotrace_arch.o diff --git a/arch/powerpc/mm/kmmio.c b/arch/powerpc/mm/kmmio.c new file mode 100644 index ..f4374e721b37 --- /dev/null +++ b/arch/powerpc/mm/kmmio.c @@ -0,0 +1,649 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Support for MMIO probes. + * Derived from arch/x86/mm/kmmio.c: + * Copyright (C) 2024 Jialong Yang (jialong.y...@shingroup.cn) + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mmiotrace_arch.h" + +typedef unsigned long pteval_t; +typedef unsigned long pmdval_t; + +#define KMMIO_PAGE_HASH_BITS 4 +#define KMMIO_PAGE_TABLE_SIZE (1 << KMMIO_PAGE_HASH_BITS) + +struct kmmio_fault_page { + struct list_head list; + struct kmmio_fault_page *release_next; + unsigned long addr; /* the requested address */ + pteval_t old_presence; /* page presence prior to arming */ + bool armed; + + /* +* Number of times this page has been registered as a part +* of a probe. If zero, page is disarmed and this may be freed. +* Used only by writers (RCU) and post_kmmio_handler(). +* Protected by kmmio_lock, when linked into kmmio_page_table. +*/ + int count; + + bool scheduled_for_release; +}; + +struct kmmio_delayed_release { + struct rcu_head rcu; + struct kmmio_fault_page *release_list; +}; + +struct kmmio_context { + struct kmmio_fault_page *fpage; + struct kmmio_probe *probe; + unsigned long saved_flags; + unsigned long saved_softe; + unsigned long addr; + int active; +}; + +/* + * The kmmio_lock is taken in int3 context, which is treated as NMI context. + * This causes lockdep to complain about it bein in both NMI and normal + * context. Hide it from lockdep, as it should not have any other locks + * taken under it, and this is only enabled for debugging mmio anyway. + */ +static arch_spinlock_t kmmio_lock = __ARCH_SPIN_LOCK_UNLOCKED; + +/* Protected by kmmio_lock */ +unsigned int kmmio_count; + +/* Read-protected by RCU, write-protected by kmmio_lock. */ +static struct list_head kmmio_page_table[KMMIO_PAGE_TABLE_SIZE]; +static LIST_HEAD(kmmio_probes); + +static struct list_head *kmmio_page_list(unsigned long addr) +{ + unsigned int l; + pte_t *pte = lookup_address(addr, &l); + + if (!pte) + return NULL; + addr &= page_level_mask(l); + + return &kmmio_page_table[hash_long(addr, KMMIO_PAGE_HASH_BITS)]; +} + +/* Accessed per-cpu */ +static DEFINE_PER_CPU(struct kmmio_context, kmmio_ctx); + +/* + * this is basically a dynamic stabbing problem: + * Could use the existing prio tree code or + * Possible better implementations: + * The Interval Skip List: A Data Structure for Finding All Intervals That + * Over
[PATCH v1 2/2] powerpc/mmiotrace: bind ioremap and page fault to active mmiotrace
Hacking the code in ioremap entry and page fault handler entry to integrate mmiotrace. Signed-off-by: Jialong Yang --- arch/powerpc/mm/fault.c | 17 + arch/powerpc/mm/ioremap_64.c | 11 +-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index 215690452495..b03cba73de92 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -50,6 +51,19 @@ * do_page_fault error handling helpers */ +/* + * Returns 0 if mmiotrace is disabled, or if the fault is not + * handled by mmiotrace: + */ +static nokprobe_inline int +kmmio_fault(struct pt_regs *regs, unsigned long addr) +{ + if (unlikely(is_kmmio_active())) + if (kmmio_handler(regs, addr) == 1) + return -1; + return 0; +} + static int __bad_area_nosemaphore(struct pt_regs *regs, unsigned long address, int si_code) { @@ -422,6 +436,9 @@ static int ___do_page_fault(struct pt_regs *regs, unsigned long address, vm_fault_t fault, major = 0; bool kprobe_fault = kprobe_page_fault(regs, 11); + if (unlikely(kmmio_fault(regs, address))) + return 0; + if (unlikely(debugger_fault_handler(regs) || kprobe_fault)) return 0; diff --git a/arch/powerpc/mm/ioremap_64.c b/arch/powerpc/mm/ioremap_64.c index d24e5f166723..f5f717bf35df 100644 --- a/arch/powerpc/mm/ioremap_64.c +++ b/arch/powerpc/mm/ioremap_64.c @@ -3,12 +3,15 @@ #include #include #include +#include void __iomem *__ioremap_caller(phys_addr_t addr, unsigned long size, pgprot_t prot, void *caller) { phys_addr_t paligned, offset; void __iomem *ret; + phys_addr_t unaligned_phys_addr = addr; + const unsigned long unaligned_size = size; int err; /* We don't support the 4K PFN hack with ioremap */ @@ -28,8 +31,11 @@ void __iomem *__ioremap_caller(phys_addr_t addr, unsigned long size, if (size == 0 || paligned == 0) return NULL; - if (slab_is_available()) - return generic_ioremap_prot(addr, size, prot); + if (slab_is_available()) { + ret = generic_ioremap_prot(addr, size, prot); + mmiotrace_ioremap(unaligned_phys_addr, unaligned_size, ret); + return ret; + } pr_warn("ioremap() called early from %pS. Use early_ioremap() instead\n", caller); @@ -52,6 +58,7 @@ void iounmap(volatile void __iomem *token) if (!slab_is_available()) return; + mmiotrace_iounmap(token); generic_iounmap(PCI_FIX_ADDR(token)); } EXPORT_SYMBOL(iounmap); -- 2.34.1
RE: [PATCH 00/26] KVM: vfio: Hide KVM internals from others
> -Original Message- > From: Sean Christopherson > Sent: Saturday, September 16, 2023 1:31 AM > To: Catalin Marinas ; Will Deacon > ; Marc Zyngier ; Oliver Upton > ; Huacai Chen ; Michael > Ellerman ; Anup Patel ; Paul > Walmsley ; Palmer Dabbelt > ; Albert Ou ; Heiko > Carstens ; Vasily Gorbik ; > Alexander Gordeev ; Christian Borntraeger > ; Janosch Frank ; > Claudio Imbrenda ; Thomas Gleixner > ; Ingo Molnar ; Borislav Petkov > ; Dave Hansen ; > x...@kernel.org; Peter Zijlstra ; Arnaldo Carvalho de > Melo ; Sean Christopherson ; > Paolo Bonzini ; Tony Krowiak > ; Halil Pasic ; Jason Herne > ; Harald Freudenberger ; > Alex Williamson ; Andy Lutomirski > > Cc: linux-arm-ker...@lists.infradead.org; kvm...@lists.linux.dev; linux- > m...@vger.kernel.org; k...@vger.kernel.org; linuxppc-dev@lists.ozlabs.org; > kvm-ri...@lists.infradead.org; linux-ri...@lists.infradead.org; linux- > s...@vger.kernel.org; linux-ker...@vger.kernel.org; linux-perf- > us...@vger.kernel.org; Anish Ghulati ; Venkatesh > Srinivas ; Andrew Thornton > > Subject: [PATCH 00/26] KVM: vfio: Hide KVM internals from others > > This is a borderline RFC series to hide KVM's internals from the rest of > the kernel, where "internals" means data structures, enums, #defines, > APIs, etc. that are intended to be KVM-only, but are exposed everywhere > due to kvm_host.h (and other headers) living in the global include paths. > > The motiviation for hiding KVM's internals is to allow *safely* loading a > "new" KVM module without having to reboot the host. Where "new" doesn't > have to be strictly newer, just a different incarnation of KVM. Hiding > KVM's internals means those assets can change across KVM instances > without > breaking things, e.g. would allow modifying the layout of struct kvm_vcpu > to introduce new fields related to a new feature or mitigation for hardware > bugs. > > The end goal for all of this is to allow loading and running multiple > instances of KVM (the module) simultaneously on a single host, e.g. to > deploy fixes, mitigations, and/or new features without having to drain > all VMs from the host. > > For now, the immediate goal is to get KVM to a state where KVM x86 doesn't > expose anything to the broader world that isn't intended for external > consumption, e.g. the page write-tracking APIs used by KVM-GT. > > I say this is borderline RFC because I don't think I've "formally" proposed > the idea of hiding KVM internals before now. I decided not to tag this RFC > because the changes ended up being not _that_ invasive, and everything > before the last six patches is worthwhile even if hiding internals is > ultimately rejected (IMO). > > This would ideally be ~5 separate series, and I certainly have no objection > if that's how we want to get this stuff merged. E.g. (1) VFIO cleanups, > (2) drop HAVE_KVM, (3) clean up makefiles, (4) x86 perf cleanup, and > (5) final push for hiding state. The HAVE_KVM and virt/kvm include stuff > isn't strictly necessary, but I included them here because they're > relatively minor (in the grand scheme). Hi Sean, Just thought of checking with you on this series. Do you have plans to revive this series? The reason I am asking is, on ARM64/KVM side we do have a requirement to share the KVM VMID with SMMUV3. Please see the RFC I sent out earlier this year[1]. The series basically provides a way for KVM to pin a VMID and also associates an iommufd ctx with a struct kvm * to retrieve that VMID. As mentioned above, some of the patches in this series(especially 1-4 & 6) that does the VFIO cleanups and dropping CONFIG_KVM_VFIO looks very straightforward and useful. I am thinking of including those when I re-spin my RFC series, if that’s ok. Please let me know your thoughts. Thanks, Shameer [1]. https://lore.kernel.org/linux-iommu/20240209115824.GA2922446@myrica/
[PATCH v4 00/40] lib/find: add atomic find_bit() primitives
--- This v4 moves new API to separate headers, as adding stuff to find.h concerns people, particularly Linus. It also adds few more conversions alongside other cosmetic changes. See full changelog below. --- Add helpers around test_and_{set,clear}_bit() to allow searching for clear or set bits and flipping them atomically. Using atomic search primitives allows to implement lockless bitmap handling where only individual bits are touched by concurrent processes, and where people now have to protect their bitmaps to search for a free or set bit due to the lack of atomic searching routines. The typical lock-protected bit allocation may look like this: unsigned long alloc_bit() { unsigned long bit; spin_lock(bitmap_lock); bit = find_first_zero_bit(bitmap, nbits); if (bit < nbits) __set_bit(bit, bitmap); spin_unlock(bitmap_lock); return bit; } void free_bit(unsigned long bit) { spin_lock(bitmap_lock); __clear_bit(bit, bitmap); spin_unlock(bitmap_lock); } Now with atomic find_and_set_bit(), the above can be implemented lockless, directly by using it and atomic clear_bit(). Patches 36-40 do this in few places in the kernel where the transition is clear. There is likely more candidates for refactoring. The other important case is when people opencode atomic search or atomic traverse on the maps with the patterns looking like: for (idx = 0; idx < nbits; idx++) if (test_and_clear_bit(idx, bitmap)) do_something(idx); Or like this: do { bit = find_first_bit(bitmap, nbits); if (bit >= nbits) return nbits; } while (!test_and_clear_bit(bit, bitmap)); return bit; In both cases, the opencoded loop may be converted to a single function or iterator call. Correspondingly: for_each_test_and_clear_bit(idx, bitmap, nbits) do_something(idx); Or: return find_and_clear_bit(bitmap, nbits); Obviously, the less routine code people have to write themself, the less probability to make a mistake. The patch #33 fixes one such mistake. The new API is not only a handy helpers - it also resolves a non-trivial issue of using non-atomic find_bit() together with atomic test_and_{set,clear)_bit(). The trick is that find_bit() implies that the bitmap is a regular non-volatile piece of memory, and compiler is allowed to use such optimization techniques like re-fetching memory instead of caching it. For example, find_first_bit() is implemented like: for (idx = 0; idx * BITS_PER_LONG < sz; idx++) { val = addr[idx]; if (val) { sz = min(idx * BITS_PER_LONG + __ffs(val), sz); break; } } On register-memory architectures, like x86, compiler may decide to access memory twice - first time to compare against 0, and second time to fetch its value to pass it to __ffs(). When running find_first_bit() on volatile memory, the memory may get changed in-between, and for instance, it may lead to passing 0 to __ffs(), which is an undefined behaviour. This is a potentially dangerous call. find_and_clear_bit() as a wrapper around test_and_clear_bit() naturally treats underlying bitmap as a volatile memory and prevents compiler from such optimizations. Now that KCSAN is catching exactly this type of situations and warns on undercover memory modifications. We can use it to reveal improper usage of find_bit(), and convert it to atomic find_and_*_bit() as appropriate. In some cases concurrent operations with plain find_bit() are acceptable. For example: - two threads running find_*_bit(): safe wrt ffs(0) and returns correct value, because underlying bitmap is unchanged; - find_next_bit() in parallel with set or clear_bit(), when modifying a bit prior to the start bit to search: safe and correct; - find_first_bit() in parallel with set_bit(): safe, but may return wrong bit number; - find_first_zero_bit() in parallel with clear_bit(): same as above. In last 2 cases find_bit() may not return a correct bit number, but it may be OK if caller requires any (not exactly the first) set or clear bit, correspondingly. In such cases, KCSAN may be safely silenced with data_race(). But in most cases where KCSAN detects concurrency we should carefully review the code and likely protect critical sections or switch to atomic find_and_bit(), as appropriate. This patch adds the following atomic primitives: find_and_set_bit(addr, nbits); find_and_set_next_bit(addr, nbits, start); ... Here find_and_{set,clear} part refers to the corresponding test_and_{set,clear}_bit function. Suffixes like _wrap or _lock derive their semantics from corresponding find() or
[PATCH v4 02/40] lib/find: add test for atomic find_bit() ops
Add basic functionality test for new API. Signed-off-by: Yury Norov --- lib/test_bitmap.c | 62 +++ 1 file changed, 62 insertions(+) diff --git a/lib/test_bitmap.c b/lib/test_bitmap.c index 65a75d58ed9e..405f79dd2266 100644 --- a/lib/test_bitmap.c +++ b/lib/test_bitmap.c @@ -6,6 +6,7 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include +#include #include #include #include @@ -221,6 +222,65 @@ static void __init test_zero_clear(void) expect_eq_pbl("", bmap, 1024); } +static void __init test_find_and_bit(void) +{ + unsigned long w, w_part, bit, cnt = 0; + DECLARE_BITMAP(bmap, EXP1_IN_BITS); + + /* +* Test find_and_clear{_next}_bit() and corresponding +* iterators +*/ + bitmap_copy(bmap, exp1, EXP1_IN_BITS); + w = bitmap_weight(bmap, EXP1_IN_BITS); + + for_each_test_and_clear_bit(bit, bmap, EXP1_IN_BITS) + cnt++; + + expect_eq_uint(w, cnt); + expect_eq_uint(0, bitmap_weight(bmap, EXP1_IN_BITS)); + + bitmap_copy(bmap, exp1, EXP1_IN_BITS); + w = bitmap_weight(bmap, EXP1_IN_BITS); + w_part = bitmap_weight(bmap, EXP1_IN_BITS / 3); + + cnt = 0; + bit = EXP1_IN_BITS / 3; + for_each_test_and_clear_bit_from(bit, bmap, EXP1_IN_BITS) + cnt++; + + expect_eq_uint(bitmap_weight(bmap, EXP1_IN_BITS), bitmap_weight(bmap, EXP1_IN_BITS / 3)); + expect_eq_uint(w_part, bitmap_weight(bmap, EXP1_IN_BITS)); + expect_eq_uint(w - w_part, cnt); + + /* +* Test find_and_set{_next}_bit() and corresponding +* iterators +*/ + bitmap_copy(bmap, exp1, EXP1_IN_BITS); + w = bitmap_weight(bmap, EXP1_IN_BITS); + cnt = 0; + + for_each_test_and_set_bit(bit, bmap, EXP1_IN_BITS) + cnt++; + + expect_eq_uint(EXP1_IN_BITS - w, cnt); + expect_eq_uint(EXP1_IN_BITS, bitmap_weight(bmap, EXP1_IN_BITS)); + + bitmap_copy(bmap, exp1, EXP1_IN_BITS); + w = bitmap_weight(bmap, EXP1_IN_BITS); + w_part = bitmap_weight(bmap, EXP1_IN_BITS / 3); + cnt = 0; + + bit = EXP1_IN_BITS / 3; + for_each_test_and_set_bit_from(bit, bmap, EXP1_IN_BITS) + cnt++; + + expect_eq_uint(EXP1_IN_BITS - bitmap_weight(bmap, EXP1_IN_BITS), + EXP1_IN_BITS / 3 - bitmap_weight(bmap, EXP1_IN_BITS / 3)); + expect_eq_uint(EXP1_IN_BITS * 2 / 3 - (w - w_part), cnt); +} + static void __init test_find_nth_bit(void) { unsigned long b, bit, cnt = 0; @@ -1482,6 +1542,8 @@ static void __init selftest(void) test_for_each_clear_bitrange_from(); test_for_each_set_clump8(); test_for_each_set_bit_wrap(); + + test_find_and_bit(); } KSTM_MODULE_LOADERS(test_bitmap); -- 2.43.0