[PATCH] coresight: Add mode check when enable/disable csdev source
hejunhao
hejunhao3 at huawei.com
Tue Sep 26 04:43:45 PDT 2023
Hi, Suzuki
On 2023/9/22 17:20, Suzuki K Poulose wrote:
> On 21/09/2023 16:36, James Clark wrote:
>>
>>
>> On 21/09/2023 14:29, Junhao He wrote:
>>> The commmit [1] replace "source_ops(csdev)::enable()" with
>>> coresight_enable_source(). After this patch, when enable ETM through
>>> perf mode, the csdev::enable will be set to true. Then if we to disable
>>> the ETM by sysfs mode at the time, the resource will be released
>>> incorrectly, kernel will report the following call trace.
>>>
>>> perf record -e cs_etm/@ultra_smb0/ -C 2 sleep 30 &
>>> echo 1 > /sys/bus/coresight/devices/ultra_smb0/enable_sink
>>> echo 1 > /sys/bus/coresight/devices/etm0/enable_source
>>> echo 0 > /sys/bus/coresight/devices/etm0/enable_source
>>> Unable to handle kernel NULL pointer dereference at virtual
>>> address 00000000000001d0
>>> Internal error: Oops: 0000000096000004 [#1] PREEMPT SMP
>>> ...
>>> Call trace:
>>> etm4_disable+0x54/0x150 [coresight_etm4x]
>>> coresight_disable_source+0x6c/0x98 [coresight]
>>> coresight_disable+0x74/0x1c0 [coresight]
>>> enable_source_store+0x88/0xa0 [coresight]
>>> dev_attr_store+0x20/0x40
>>> sysfs_kf_write+0x4c/0x68
>>> kernfs_fop_write_iter+0x120/0x1b8
>>> vfs_write+0x2dc/0x3b0
>>> ksys_write+0x70/0x108
>>> __arm64_sys_write+0x24/0x38
>>> invoke_syscall+0x50/0x128
>>> el0_svc_common.constprop.0+0x104/0x130
>>> do_el0_svc+0x40/0xb8
>>> el0_svc+0x2c/0xb8
>>> el0t_64_sync_handler+0xc0/0xc8
>>> el0t_64_sync+0x1a4/0x1a8
>>> Code: d53cd042 91002000 b9402a81 b8626800 (f940ead5)
>>> ---[ end trace 0000000000000000 ]---
>>>
>>> The csdev::enable specify the device is currently part of an active
>>> path, when enabling source via perf mode, csdev::enable also should
>>> be set to true. We can add mode check in etm4_disable() to fix that,
>>> if it's done, the sysfs cannot report busy when sysfs to enable ETM
>>> that has been enabled by perf.
>>>
>>> Struct coresight_device add member of mode to check device busy in
>>> coresight_(enable/disable)_source function to fixes handle kernel
>>> NULL pointer, and sysfs report busy if perf session is already using
>>> the ETM.
>>> By the way, inperhaps another cleanup patch may be upload to remove
>>> the etmv4_drvdata::mode tmc_drvdata::mode or others.
>>>
>>
>> Hi Junhao,
>>
>> I definitely think we should do the cleanup at the same time as this
>> change. Otherwise we risk leaving in the other modes which are
>> duplicates of this and could easily cause confusion.
>>
>> Although I saw there are a couple of modes that are not enum cs_mode,
>> but a different kind of mode. And it's not always obvious because enum
>> cs_mode is sometimes stored as an int...
>>
>>> Test:
>>> perf record -e cs_etm/@ultra_smb0/ -C 2 sleep 30 &
>>> cat /sys/bus/coresight/devices/etm2/enable_source
>>> 1
>>> echo 1 > /sys/bus/coresight/devices/etm2/enable_source
>>> -bash: echo: write error: Device or resource busy
>>> echo 0 > /sys/bus/coresight/devices/etm2/enable_source
>>> coresight etm2: Someone is already using the tracer
>>> cat /sys/bus/coresight/devices/etm2/enable_source
>>> 1
>>>
>>
>> I tested the fix and it works, although I have a few comments below on
>> whether we should do something else instead.
>>
>>> [1] "coresight: Enable and disable helper devices adjacent to the
>>> path"> Fixes: 6148652807ba ("coresight: Enable and disable helper
>>> devices
>> adjacent to the path")
>>
>> What was the original behavior before that change? Maybe it didn't have
>> exactly the same error but was it still possible to enable and disable a
>> sink after starting a Perf session? Seems like on the disable the same
>> thing would have happened or something else bad?
>
> Before that, the perf was using the source_ops->enable/disable directly.
> And thus the csdev->enable was not set, forcing the sysfs mode to try
> enabling it via the source_ops->enable, which would reject the request.
>
> But with the switch to using enable_source, the sysfs mode request
> bails out early assuming that the "csdev->enable == true" set by the
> perf mode, to indicate the sysfs mode and goes ahead.
>
> Ideally, we should rely on the backend driver to do the check ?
As i said above. We can add mode check in etm4_disable() to fix that.
But I didn't do this because I wanted sysfs to report a busy log. If the
logs are unimportant, we do not need to add csdev->mode and can
check the mode in etm4_disable().
>
> Does the following patch fix problems for you ?
>
I tested on my platform and the problem still exists.
If the ETM has been used by the perf session, coresight_disable_source()
still
responds to the disable csdev by sysfs.
# perf record -e /cs_etm/@ultra_smb0/ -C 22 -- sleep 30 &
[2] 11157
# echo 1 > /sys/bus/coresight/devices/etm22/enable_source
# echo 0 > /sys/bus/coresight/devices/etm22/enable_source
[ 5308.708990] Unable to handle kernel NULL pointer dereference at
virtual address 00000000000001d0
[ 5308.834767] CPU: 2 PID: 11058 Comm: bash Kdump: loaded Tainted:
G O 6.5.0-rc4+ #1
[ 5308.843894] Hardware name: Huawei TaiShan 200 (Model
2280)/BC82AMDD, BIOS 2280-V2 CS V5.B221.01 12/09/2021
[ 5308.854030] pstate: 60400009 (nZCv daif +PAN -UAO -TCO -DIT -SSBS
BTYPE=--)
[ 5308.861227] pc : etm4_disable+0x54/0x150 [coresight_etm4x]
[ 5308.866956] lr : coresight_disable_source+0x5c/0xb8 [coresight]
Best regards,
Junhao.
>
>
>
> diff --git a/drivers/hwtracing/coresight/coresight-core.c
> b/drivers/hwtracing/coresight/coresight-core.c
> index 9fabe00a40d6..10e3609d8290 100644
> --- a/drivers/hwtracing/coresight/coresight-core.c
> +++ b/drivers/hwtracing/coresight/coresight-core.c
> @@ -381,15 +381,12 @@ int coresight_enable_source(struct
> coresight_device *csdev, enum cs_mode mode,
> {
> int ret;
>
> - if (!csdev->enable) {
> - if (source_ops(csdev)->enable) {
> - ret = source_ops(csdev)->enable(csdev, data, mode);
> - if (ret)
> - return ret;
> - }
> + if (source_ops(csdev)->enable) {
> + ret = source_ops(csdev)->enable(csdev, data, mode);
> + if (ret)
> + return ret;
> csdev->enable = true;
> }
> -
> atomic_inc(&csdev->refcnt);
>
> return 0;
> @@ -453,7 +450,7 @@ static void coresight_disable_helpers(struct
> coresight_device *csdev)
> */
> bool coresight_disable_source(struct coresight_device *csdev, void
> *data)
> {
> - if (atomic_dec_return(&csdev->refcnt) == 0) {
> + if (csdev->enable && atomic_dec_return(&csdev->refcnt) == 0) {
> if (source_ops(csdev)->disable)
> source_ops(csdev)->disable(csdev, data);
> coresight_disable_helpers(csdev);
> @@ -1202,7 +1199,7 @@ void coresight_disable(struct coresight_device
> *csdev)
> if (ret)
> goto out;
>
> - if (!csdev->enable || !coresight_disable_source(csdev, NULL))
> + if (!coresight_disable_source(csdev, NULL))
> goto out;
>
> switch (csdev->subtype.source_subtype) {
>
>
>
>
> Suzuki
>
>
> _______________________________________________
> CoreSight mailing list -- coresight at lists.linaro.org
> To unsubscribe send an email to coresight-leave at lists.linaro.org
>
> .
>
More information about the linux-arm-kernel
mailing list