mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: "Christian König" <christian.koenig@amd.com>
To: Peter Zijlstra <peterz@infradead.org>
Cc: Mikhail Gavrilov <mikhail.v.gavrilov@gmail.com>,
	kernel test robot <lkp@intel.com>,
	jpoimboe@kernel.org, llvm@lists.linux.dev,
	oe-kbuild-all@lists.linux.dev,
	Alex Deucher <alexander.deucher@amd.com>,
	Linux List Kernel Mailing <linux-kernel@vger.kernel.org>
Subject: Re: [linux-next:master 14191/14955] vmlinux.o: error: objtool: amdgpu_vm_handle_fault+0x186: sibling call from callable instruction with modified stack frame
Date: Wed, 24 Jun 2026 13:04:36 +0200	[thread overview]
Message-ID: <0ff5f3f7-c2d3-4b56-95ad-400626d8abb9@amd.com> (raw)
In-Reply-To: <20260624105658.GB48970@noisy.programming.kicks-ass.net>

On 6/24/26 12:56, Peter Zijlstra wrote:
> On Wed, Jun 24, 2026 at 11:48:09AM +0200, Christian König wrote:
> 
>>> So, if my heat-addled brain isn't completely gone, then this all boils
>>> down to something like:
>>>
>>>   drm_exec_init(&exec);
>>> label:
>>>   for (;drm_exec_cleanup(&exec);) {
>>>      ...
>>>      if (unlikely(drm_exec_is_contended(&exec)))
>>>        goto label;
>>>      ...
>>>   }
>>>   ...
>>>   drm_exec_fini(&exec);
>>>
>>> Except, you've laundered that label through a computed goto to allow
>>> multiple such constructs in a single function -- because can't have
>>> multiple identical labels etc.
>>
>> Just FYI: That's actually not the reason for this, the label name is unique now.
> 
> Yeah, I know, but I thought that the only way to transfer the name to
> the drm_exec_retry() sites was to create that computed-goto alias.

Yes, that was also a problem.

> 
>> The computed goto is used to limit the scope you can use the retry
>> macros because we initially had problems with people using that
>> outside of the loop.
> 
> Ah, also a very good reason.
> 
>> Exactly that, yes. The nested loops are unfortunately a very common use case here.
> 
> Yep, saw that.
> 
>>> That is, I think this drm_exec_until_all_locked() thing has some
>>> fundamental problems the moment clang fails to optimize it away.
>>> Correctness really depends on the compiler not actually ever doing a
>>> computed goto.
>>
>> Mhm, that's not good at all but I also of hand don't see a way to
>> avoid the computed goto.
> 
> Best I can come up with is something like this. Not exactly nice, but
> should be fairly trivial to do.

Yeah, definitely not nice. The macro was created exactly because people messed this approach up more than once.

I could live with some other hack/workaround, but clearly not with changing all users.

Maybe we can goto the fixed named label but have an extra variable to check that we are in the right scope or something like that.

Regards,
Christian.

> 
> ---
> diff --git a/drivers/gpu/drm/tests/drm_exec_test.c b/drivers/gpu/drm/tests/drm_exec_test.c
> index 2fc47f3b463b..7d69c06b2dd3 100644
> --- a/drivers/gpu/drm/tests/drm_exec_test.c
> +++ b/drivers/gpu/drm/tests/drm_exec_test.c
> @@ -60,6 +60,7 @@ static void test_lock(struct kunit *test)
>  
>  	drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0);
>  	drm_exec_until_all_locked(&exec) {
> +drm_exec_label:
>  		ret = drm_exec_lock_obj(&exec, &gobj);
>  		drm_exec_retry_on_contention(&exec);
>  		KUNIT_EXPECT_EQ(test, ret, 0);
> @@ -80,6 +81,7 @@ static void test_lock_unlock(struct kunit *test)
>  
>  	drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0);
>  	drm_exec_until_all_locked(&exec) {
> +drm_exec_label:
>  		ret = drm_exec_lock_obj(&exec, &gobj);
>  		drm_exec_retry_on_contention(&exec);
>  		KUNIT_EXPECT_EQ(test, ret, 0);
> @@ -107,6 +109,7 @@ static void test_duplicates(struct kunit *test)
>  
>  	drm_exec_init(&exec, DRM_EXEC_IGNORE_DUPLICATES, 0);
>  	drm_exec_until_all_locked(&exec) {
> +drm_exec_label:
>  		ret = drm_exec_lock_obj(&exec, &gobj);
>  		drm_exec_retry_on_contention(&exec);
>  		KUNIT_EXPECT_EQ(test, ret, 0);
> @@ -134,6 +137,7 @@ static void test_prepare(struct kunit *test)
>  
>  	drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0);
>  	drm_exec_until_all_locked(&exec) {
> +drm_exec_label:
>  		ret = drm_exec_prepare_obj(&exec, &gobj, 1);
>  		drm_exec_retry_on_contention(&exec);
>  		KUNIT_EXPECT_EQ(test, ret, 0);
> @@ -166,9 +170,10 @@ static void test_prepare_array(struct kunit *test)
>  	drm_gem_private_object_init(priv->drm, gobj2, PAGE_SIZE);
>  
>  	drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0);
> -	drm_exec_until_all_locked(&exec)
> -		ret = drm_exec_prepare_array(&exec, array, ARRAY_SIZE(array),
> -					     1);
> +	drm_exec_until_all_locked(&exec) {
> +drm_exec_label:
> +		ret = drm_exec_prepare_array(&exec, array, ARRAY_SIZE(array), 1);
> +	}
>  	KUNIT_EXPECT_EQ(test, ret, 0);
>  	drm_exec_fini(&exec);
>  
> @@ -181,15 +186,15 @@ static void test_multiple_loops(struct kunit *test)
>  	struct drm_exec exec;
>  
>  	drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0);
> -	drm_exec_until_all_locked(&exec)
> -	{
> +	drm_exec_until_all_locked(&exec) {
> +drm_exec_label:
>  		break;
>  	}
>  	drm_exec_fini(&exec);
>  
>  	drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0);
> -	drm_exec_until_all_locked(&exec)
> -	{
> +	drm_exec_until_all_locked(&exec) {
> +drm_exec_label:
>  		break;
>  	}
>  	drm_exec_fini(&exec);
> diff --git a/include/drm/drm_exec.h b/include/drm/drm_exec.h
> index 8725ba92ff91..f2bfa6aa7b7b 100644
> --- a/include/drm/drm_exec.h
> +++ b/include/drm/drm_exec.h
> @@ -101,17 +101,6 @@ drm_exec_obj(struct drm_exec *exec, unsigned long index)
>  #define drm_exec_for_each_locked_object_reverse(exec, obj)		\
>  	__drm_exec_for_each_locked_object_reverse(exec, obj, __UNIQUE_ID(drm_exec))
>  
> -/*
> - * Helper to drm_exec_until_all_locked(). Don't use directly.
> - *
> - * Since labels can't be defined local to the loop's body we use a jump pointer
> - * to make sure that the retry is only used from within the loop's body.
> - */
> -#define __drm_exec_until_all_locked(exec, _label)			 \
> -_label:									 \
> -	for (void *const __maybe_unused __drm_exec_retry_ptr = &&_label; \
> -	     drm_exec_cleanup(exec);)
> -
>  /**
>   * drm_exec_until_all_locked - loop until all GEM objects are locked
>   * @exec: drm_exec object
> @@ -121,7 +110,18 @@ _label:									 \
>   * guaranteed that no GEM object is locked.
>   */
>  #define drm_exec_until_all_locked(exec)					\
> -	__drm_exec_until_all_locked(exec, __UNIQUE_ID(drm_exec))
> +	while (drm_exec_cleanup(exec))
> +
> +#define drm_exec_label							\
> +	__label__ __drm_exec_retry;					\
> +	__label__ __drm_foo;						\
> +	if (0) {							\
> +	__drm_exec_retry: __maybe_unused;				\
> +		continue;						\
> +		goto __drm_foo;						\
> +	}								\
> +	__drm_foo
> +
>  
>  /**
>   * drm_exec_retry_on_contention - restart the loop to grap all locks
> @@ -133,7 +133,7 @@ _label:									 \
>  #define drm_exec_retry_on_contention(exec)			\
>  	do {							\
>  		if (unlikely(drm_exec_is_contended(exec)))	\
> -			goto *__drm_exec_retry_ptr;		\
> +			goto __drm_exec_retry;			\
>  	} while (0)
>  
>  /**
> @@ -158,7 +158,7 @@ static inline bool drm_exec_is_contended(struct drm_exec *exec)
>  #define drm_exec_retry(_exec)					\
>  	do {							\
>  		WARN_ON((_exec)->contended != DRM_EXEC_DUMMY);	\
> -		goto *__drm_exec_retry_ptr;			\
> +		goto __drm_exec_retry;				\
>  	} while (0)
>  
>  /**


  reply	other threads:[~2026-06-24 11:04 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <202606232356.gwHMAJAW-lkp@intel.com>
2026-06-23 20:57 ` Mikhail Gavrilov
2026-06-24  9:28   ` Peter Zijlstra
2026-06-24  9:48     ` Christian König
2026-06-24 10:56       ` Peter Zijlstra
2026-06-24 11:04         ` Christian König [this message]
2026-06-24 11:16           ` Peter Zijlstra
2026-06-24 11:21             ` Peter Zijlstra
2026-06-24 12:36     ` Mikhail Gavrilov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=0ff5f3f7-c2d3-4b56-95ad-400626d8abb9@amd.com \
    --to=christian.koenig@amd.com \
    --cc=alexander.deucher@amd.com \
    --cc=jpoimboe@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lkp@intel.com \
    --cc=llvm@lists.linux.dev \
    --cc=mikhail.v.gavrilov@gmail.com \
    --cc=oe-kbuild-all@lists.linux.dev \
    --cc=peterz@infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®