[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-Id: <BE0991D9-65E7-43CA-A4B4-D3547D96291A@lca.pw>
Date: Mon, 22 Jul 2019 23:08:41 -0400
From: Qian Cai <cai@....pw>
To: James Y Knight <jyknight@...gle.com>
Cc: David Miller <davem@...emloft.net>,
Bill Wendling <morbo@...gle.com>,
Nick Desaulniers <ndesaulniers@...gle.com>,
sathya.perla@...adcom.com, ajit.khaparde@...adcom.com,
sriharsha.basavapatna@...adcom.com, somnath.kotur@...adcom.com,
Arnd Bergmann <arnd@...db.de>,
David Howells <dhowells@...hat.com>,
"H. Peter Anvin" <hpa@...or.com>, netdev@...r.kernel.org,
linux-arch@...r.kernel.org,
Linux Kernel Mailing List <linux-kernel@...r.kernel.org>,
natechancellor@...il.com, Jakub Jelinek <jakub@...hat.com>
Subject: Re: [PATCH] be2net: fix adapter->big_page_size miscaculation
The original issue,
https://lore.kernel.org/netdev/1562959401-19815-1-git-send-email-cai@lca.pw/
The debugging so far seems point to that the compilers get confused by the
module sections. During module_param(), it stores “__param_rx_frag_size"
as a “struct kernel_param” into the __param section. Later, load_module()
obtains all “kernel_param” from the __param section and compare against the
user-input module parameters from the command-line. If there is a match, it
calls params[i].ops->set(¶ms[I]) to replace the value. If compilers can’t
see that params[i].ops->set(¶ms[I]) could potentially change the value
of rx_frag_size, it will wrongly optimize it as a constant.
For example (it is not
compilable yet as I have not able to extract variable from the __param section
like find_module_sections()),
#include <stdio.h>
#include <string.h>
#define __module_param_call(name, ops, arg) \
static struct kernel_param __param_##name \
__attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) = { \
#name, ops, { arg } }
struct kernel_param {
const char *name;
const struct kernel_param_ops *ops;
union {
int *arg;
};
};
struct kernel_param_ops {
int (*set)(const struct kernel_param *kp);
};
#define STANDARD_PARAM_DEF(name) \
int param_set_##name(const struct kernel_param *kp) \
{ \
*kp->arg = 2; \
} \
const struct kernel_param_ops param_ops_##name = { \
.set = param_set_##name, \
};
STANDARD_PARAM_DEF(ushort);
static int rx = 1;
__module_param_call(rx_frag_siz, ¶m_ops_ushort, &rx_frag_size);
int main(int argc, char *argv[])
{
const struct kernel_param *params = <<< Get all kernel_param from the __param section >>>;
int i;
if (__builtin_constant_p(rx_frag_size))
printf("rx_frag_size is a const.\n");
for (i = 0; i < num_param; i++) {
if (!strcmp(params[I].name, argv[1])) {
params[i].ops->set(¶ms[i]);
break;
}
}
printf("rx_frag_size = %d\n", rx_frag_size);
return 0;
}
Powered by blists - more mailing lists