2023-09-13 21:49:23

by Josh Poimboeuf

[permalink] [raw]
Subject: Re: linux-next: Tree for Sep 13 (objtool)

On Wed, Sep 13, 2023 at 01:34:11PM -0700, Randy Dunlap wrote:
>
>
> On 9/12/23 22:04, Stephen Rothwell wrote:
> > Hi all,
> >
> > Changes since 20230912:
> >
> > The bpf-next tree (I think) gained a boot time warning due to a semantic
> > interaction with changes in the bpf tree.
> >
> > The drm-misc tree gained a conflict against Linus' tree.
> >
> > Non-merge commits (relative to Linus' tree): 4427
> > 1907 files changed, 354449 insertions(+), 27039 deletions(-)
> >
> > ----------------------------------------------------------------------------
>
> on x86_64:
>
> drivers/media/common/siano/smscoreapi.o: warning: objtool: .text.unlikely: unexpected end of section
>
> Full randconfig file is attached.

Objtool is correct:

Disassembly of section .text.unlikely:

0000000000000000 <smscore_set_device_mode.cold>:
0: 48 83 05 00 00 00 00 01 addq $0x1,0x0(%rip) # 8 <__UNIQUE_ID___addressable_smscore_unregister_client433> 3: R_X86_64_PC32 .bss+0xa03

It's not really a functional bug, it's just gcov somehow keeping GCC
from finishing an optimization.

In smscore_load_firmware_from_file(), which gets inlined by
smscore_set_device_mode(), GCC is smart enough to know that

'coredev->device_flags & SMS_DEVICE_FAMILY2'

is always true, so it half-optimizes out the ':' condition:

rc = (coredev->device_flags & SMS_DEVICE_FAMILY2) ?
smscore_load_firmware_family2(coredev, fw_buf, fw_buf_size)
: loadfirmware_handler(coredev->context, fw_buf,
fw_buf_size);

Though it actually still keeps the branch. It goes to
smscore_set_device_mode.cold so it can set the GCOV "branch taken" bit
for the !SMS_DEVICE_FAMILY2 case. But then it just falls off the edge
off .text.unlikely.

Peter, any opinions how to handle this?

We could just make smscore_load_firmware_from_file() noinline.

Or we could hard-code the fact that smscore_load_firmware_from_file() is
only called in the SMS_DEVICE_FAMILY2 case, like:

diff --git a/drivers/media/common/siano/smscoreapi.c b/drivers/media/common/siano/smscoreapi.c
index 7d4bc2733f2b..58d951903e93 100644
--- a/drivers/media/common/siano/smscoreapi.c
+++ b/drivers/media/common/siano/smscoreapi.c
@@ -1127,19 +1127,19 @@ static char *smscore_get_fw_filename(struct smscore_device_t *coredev,
* @param coredev pointer to a coredev object returned by
* smscore_register_device
* @param filename null-terminated string specifies firmware file name
- * @param loadfirmware_handler device handler that loads firmware
*
* return: 0 on success, <0 on error.
*/
static int smscore_load_firmware_from_file(struct smscore_device_t *coredev,
- int mode,
- loadfirmware_t loadfirmware_handler)
+ int mode)
{
int rc = -ENOENT;
u8 *fw_buf;
u32 fw_buf_size;
const struct firmware *fw;

+ BUG_ON(coredev->device_flags != SMS_DEVICE_FAMILY2);
+
char *fw_filename = smscore_get_fw_filename(coredev, mode);
if (!fw_filename) {
pr_err("mode %d not supported on this device\n", mode);
@@ -1147,10 +1147,6 @@ static int smscore_load_firmware_from_file(struct smscore_device_t *coredev,
}
pr_debug("Firmware name: %s\n", fw_filename);

- if (!loadfirmware_handler &&
- !(coredev->device_flags & SMS_DEVICE_FAMILY2))
- return -EINVAL;
-
rc = request_firmware(&fw, fw_filename, coredev->device);
if (rc < 0) {
pr_err("failed to open firmware file '%s'\n", fw_filename);
@@ -1166,10 +1162,7 @@ static int smscore_load_firmware_from_file(struct smscore_device_t *coredev,
memcpy(fw_buf, fw->data, fw->size);
fw_buf_size = fw->size;

- rc = (coredev->device_flags & SMS_DEVICE_FAMILY2) ?
- smscore_load_firmware_family2(coredev, fw_buf, fw_buf_size)
- : loadfirmware_handler(coredev->context, fw_buf,
- fw_buf_size);
+ rc = smscore_load_firmware_family2(coredev, fw_buf, fw_buf_size);
}

kfree(fw_buf);
@@ -1353,8 +1346,7 @@ int smscore_set_device_mode(struct smscore_device_t *coredev, int mode)
}

if (!(coredev->modes_supported & (1 << mode))) {
- rc = smscore_load_firmware_from_file(coredev,
- mode, NULL);
+ rc = smscore_load_firmware_from_file(coredev, mode);
if (rc >= 0)
pr_debug("firmware download success\n");
} else {


2023-09-14 13:51:23

by Peter Zijlstra

[permalink] [raw]
Subject: Re: linux-next: Tree for Sep 13 (objtool)


On Wed, Sep 13, 2023 at 11:47:53PM +0200, Josh Poimboeuf wrote:
> On Wed, Sep 13, 2023 at 01:34:11PM -0700, Randy Dunlap wrote:
> >
> >
> > On 9/12/23 22:04, Stephen Rothwell wrote:
> > > Hi all,
> > >
> > > Changes since 20230912:
> > >
> > > The bpf-next tree (I think) gained a boot time warning due to a semantic
> > > interaction with changes in the bpf tree.
> > >
> > > The drm-misc tree gained a conflict against Linus' tree.
> > >
> > > Non-merge commits (relative to Linus' tree): 4427
> > > 1907 files changed, 354449 insertions(+), 27039 deletions(-)
> > >
> > > ----------------------------------------------------------------------------
> >
> > on x86_64:
> >
> > drivers/media/common/siano/smscoreapi.o: warning: objtool: .text.unlikely: unexpected end of section
> >
> > Full randconfig file is attached.
>
> Objtool is correct:
>
> Disassembly of section .text.unlikely:
>
> 0000000000000000 <smscore_set_device_mode.cold>:
> 0: 48 83 05 00 00 00 00 01 addq $0x1,0x0(%rip) # 8 <__UNIQUE_ID___addressable_smscore_unregister_client433> 3: R_X86_64_PC32 .bss+0xa03
>
> It's not really a functional bug, it's just gcov somehow keeping GCC
> from finishing an optimization.
>
> In smscore_load_firmware_from_file(), which gets inlined by
> smscore_set_device_mode(), GCC is smart enough to know that
>
> 'coredev->device_flags & SMS_DEVICE_FAMILY2'
>
> is always true, so it half-optimizes out the ':' condition:
>
> rc = (coredev->device_flags & SMS_DEVICE_FAMILY2) ?
> smscore_load_firmware_family2(coredev, fw_buf, fw_buf_size)
> : loadfirmware_handler(coredev->context, fw_buf,
> fw_buf_size);
>
> Though it actually still keeps the branch. It goes to
> smscore_set_device_mode.cold so it can set the GCOV "branch taken" bit
> for the !SMS_DEVICE_FAMILY2 case. But then it just falls off the edge
> off .text.unlikely.
>
> Peter, any opinions how to handle this?

Ask the GCC people to not do this? :-)

> We could just make smscore_load_firmware_from_file() noinline.
>
> Or we could hard-code the fact that smscore_load_firmware_from_file() is
> only called in the SMS_DEVICE_FAMILY2 case, like:

Yeah, this seems simplest. The code in question doesn't seem overly
complicated and we can simply avoid confusing GCC.

> diff --git a/drivers/media/common/siano/smscoreapi.c b/drivers/media/common/siano/smscoreapi.c
> index 7d4bc2733f2b..58d951903e93 100644
> --- a/drivers/media/common/siano/smscoreapi.c
> +++ b/drivers/media/common/siano/smscoreapi.c
> @@ -1127,19 +1127,19 @@ static char *smscore_get_fw_filename(struct smscore_device_t *coredev,
> * @param coredev pointer to a coredev object returned by
> * smscore_register_device
> * @param filename null-terminated string specifies firmware file name
> - * @param loadfirmware_handler device handler that loads firmware
> *
> * return: 0 on success, <0 on error.
> */
> static int smscore_load_firmware_from_file(struct smscore_device_t *coredev,
> - int mode,
> - loadfirmware_t loadfirmware_handler)
> + int mode)
> {
> int rc = -ENOENT;
> u8 *fw_buf;
> u32 fw_buf_size;
> const struct firmware *fw;
>
> + BUG_ON(coredev->device_flags != SMS_DEVICE_FAMILY2);
> +
> char *fw_filename = smscore_get_fw_filename(coredev, mode);
> if (!fw_filename) {
> pr_err("mode %d not supported on this device\n", mode);
> @@ -1147,10 +1147,6 @@ static int smscore_load_firmware_from_file(struct smscore_device_t *coredev,
> }
> pr_debug("Firmware name: %s\n", fw_filename);
>
> - if (!loadfirmware_handler &&
> - !(coredev->device_flags & SMS_DEVICE_FAMILY2))
> - return -EINVAL;
> -
> rc = request_firmware(&fw, fw_filename, coredev->device);
> if (rc < 0) {
> pr_err("failed to open firmware file '%s'\n", fw_filename);
> @@ -1166,10 +1162,7 @@ static int smscore_load_firmware_from_file(struct smscore_device_t *coredev,
> memcpy(fw_buf, fw->data, fw->size);
> fw_buf_size = fw->size;
>
> - rc = (coredev->device_flags & SMS_DEVICE_FAMILY2) ?
> - smscore_load_firmware_family2(coredev, fw_buf, fw_buf_size)
> - : loadfirmware_handler(coredev->context, fw_buf,
> - fw_buf_size);
> + rc = smscore_load_firmware_family2(coredev, fw_buf, fw_buf_size);
> }
>
> kfree(fw_buf);
> @@ -1353,8 +1346,7 @@ int smscore_set_device_mode(struct smscore_device_t *coredev, int mode)
> }
>
> if (!(coredev->modes_supported & (1 << mode))) {
> - rc = smscore_load_firmware_from_file(coredev,
> - mode, NULL);
> + rc = smscore_load_firmware_from_file(coredev, mode);
> if (rc >= 0)
> pr_debug("firmware download success\n");
> } else {

2023-09-14 13:57:11

by Josh Poimboeuf

[permalink] [raw]
Subject: Re: linux-next: Tree for Sep 13 (objtool)

On Thu, Sep 14, 2023 at 09:23:27AM +0200, Peter Zijlstra wrote:
> > We could just make smscore_load_firmware_from_file() noinline.
> >
> > Or we could hard-code the fact that smscore_load_firmware_from_file() is
> > only called in the SMS_DEVICE_FAMILY2 case, like:
>
> Yeah, this seems simplest. The code in question doesn't seem overly
> complicated and we can simply avoid confusing GCC.

I'm on my way out the door for vacation, if anybody wants to slap a
description on the patch and send it along, feel free :-)

--
Josh