Message ID | 20241203212854.5565-1-paul@os.amperecomputing.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | [v2] firmware: smccc: Support optional Arm SMC SOC_ID name | expand |
Hi Paul, kernel test robot noticed the following build warnings: [auto build test WARNING on soc/for-next] [also build test WARNING on linus/master v6.13-rc1 next-20241203] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Paul-Benoit/firmware-smccc-Support-optional-Arm-SMC-SOC_ID-name/20241204-124243 base: https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git for-next patch link: https://lore.kernel.org/r/20241203212854.5565-1-paul%40os.amperecomputing.com patch subject: [PATCH v2] firmware: smccc: Support optional Arm SMC SOC_ID name config: arm-sp7021_defconfig (https://download.01.org/0day-ci/archive/20241204/202412041926.d2p2hcQe-lkp@intel.com/config) compiler: arm-linux-gnueabi-gcc (GCC) 14.2.0 reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241204/202412041926.d2p2hcQe-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202412041926.d2p2hcQe-lkp@intel.com/ All warnings (new ones prefixed by >>): drivers/firmware/smccc/soc_id.c: In function 'str_fragment_from_reg': >> drivers/firmware/smccc/soc_id.c:109:23: warning: right shift count >= width of type [-Wshift-count-overflow] 109 | dst[4] = (reg >> 32) & 0xff; | ^~ drivers/firmware/smccc/soc_id.c:110:23: warning: right shift count >= width of type [-Wshift-count-overflow] 110 | dst[5] = (reg >> 40) & 0xff; | ^~ drivers/firmware/smccc/soc_id.c:111:23: warning: right shift count >= width of type [-Wshift-count-overflow] 111 | dst[6] = (reg >> 48) & 0xff; | ^~ drivers/firmware/smccc/soc_id.c:112:23: warning: right shift count >= width of type [-Wshift-count-overflow] 112 | dst[7] = (reg >> 56) & 0xff; | ^~ drivers/firmware/smccc/soc_id.c: At top level: >> drivers/firmware/smccc/soc_id.c:37:29: warning: 'smccc_soc_id_name' defined but not used [-Wunused-variable] 37 | static char __ro_after_init smccc_soc_id_name[136] = ""; | ^~~~~~~~~~~~~~~~~ vim +109 drivers/firmware/smccc/soc_id.c 36 > 37 static char __ro_after_init smccc_soc_id_name[136] = ""; 38 39 static int __init smccc_soc_init(void) 40 { 41 int soc_id_rev, soc_id_version; 42 static char soc_id_str[20], soc_id_rev_str[12]; 43 static char soc_id_jep106_id_str[12]; 44 45 if (arm_smccc_get_version() < ARM_SMCCC_VERSION_1_2) 46 return 0; 47 48 soc_id_version = arm_smccc_get_soc_id_version(); 49 if (soc_id_version == SMCCC_RET_NOT_SUPPORTED) { 50 pr_info("ARCH_SOC_ID not implemented, skipping ....\n"); 51 return 0; 52 } 53 54 if (soc_id_version < 0) { 55 pr_err("Invalid SoC Version: %x\n", soc_id_version); 56 return -EINVAL; 57 } 58 59 soc_id_rev = arm_smccc_get_soc_id_revision(); 60 if (soc_id_rev < 0) { 61 pr_err("Invalid SoC Revision: %x\n", soc_id_rev); 62 return -EINVAL; 63 } 64 65 soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); 66 if (!soc_dev_attr) 67 return -ENOMEM; 68 69 sprintf(soc_id_rev_str, "0x%08x", soc_id_rev); 70 sprintf(soc_id_jep106_id_str, "jep106:%02x%02x", 71 JEP106_BANK_CONT_CODE(soc_id_version), 72 JEP106_ID_CODE(soc_id_version)); 73 sprintf(soc_id_str, "%s:%04x", soc_id_jep106_id_str, 74 IMP_DEF_SOC_ID(soc_id_version)); 75 76 soc_dev_attr->soc_id = soc_id_str; 77 soc_dev_attr->revision = soc_id_rev_str; 78 soc_dev_attr->family = soc_id_jep106_id_str; 79 soc_dev_attr->machine = smccc_soc_name_init(); 80 81 soc_dev = soc_device_register(soc_dev_attr); 82 if (IS_ERR(soc_dev)) { 83 kfree(soc_dev_attr); 84 return PTR_ERR(soc_dev); 85 } 86 87 pr_info("ID = %s Revision = %s\n", soc_dev_attr->soc_id, 88 soc_dev_attr->revision); 89 90 return 0; 91 } 92 module_init(smccc_soc_init); 93 94 static void __exit smccc_soc_exit(void) 95 { 96 if (soc_dev) 97 soc_device_unregister(soc_dev); 98 kfree(soc_dev_attr); 99 } 100 module_exit(smccc_soc_exit); 101 102 103 static inline void str_fragment_from_reg(char *dst, unsigned long reg) 104 { 105 dst[0] = (reg >> 0) & 0xff; 106 dst[1] = (reg >> 8) & 0xff; 107 dst[2] = (reg >> 16) & 0xff; 108 dst[3] = (reg >> 24) & 0xff; > 109 dst[4] = (reg >> 32) & 0xff; 110 dst[5] = (reg >> 40) & 0xff; 111 dst[6] = (reg >> 48) & 0xff; 112 dst[7] = (reg >> 56) & 0xff; 113 } 114
Hi Paul, kernel test robot noticed the following build warnings: [auto build test WARNING on soc/for-next] [also build test WARNING on linus/master v6.13-rc1 next-20241203] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Paul-Benoit/firmware-smccc-Support-optional-Arm-SMC-SOC_ID-name/20241204-124243 base: https://git.kernel.org/pub/scm/linux/kernel/git/soc/soc.git for-next patch link: https://lore.kernel.org/r/20241203212854.5565-1-paul%40os.amperecomputing.com patch subject: [PATCH v2] firmware: smccc: Support optional Arm SMC SOC_ID name config: arm-qcom_defconfig (https://download.01.org/0day-ci/archive/20241204/202412042020.U9EEV8mE-lkp@intel.com/config) compiler: clang version 20.0.0git (https://github.com/llvm/llvm-project 592c0fe55f6d9a811028b5f3507be91458ab2713) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241204/202412042020.U9EEV8mE-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202412042020.U9EEV8mE-lkp@intel.com/ All warnings (new ones prefixed by >>): >> drivers/firmware/smccc/soc_id.c:109:16: warning: shift count >= width of type [-Wshift-count-overflow] 109 | dst[4] = (reg >> 32) & 0xff; | ^ ~~ drivers/firmware/smccc/soc_id.c:110:16: warning: shift count >= width of type [-Wshift-count-overflow] 110 | dst[5] = (reg >> 40) & 0xff; | ^ ~~ drivers/firmware/smccc/soc_id.c:111:16: warning: shift count >= width of type [-Wshift-count-overflow] 111 | dst[6] = (reg >> 48) & 0xff; | ^ ~~ drivers/firmware/smccc/soc_id.c:112:16: warning: shift count >= width of type [-Wshift-count-overflow] 112 | dst[7] = (reg >> 56) & 0xff; | ^ ~~ >> drivers/firmware/smccc/soc_id.c:37:29: warning: unused variable 'smccc_soc_id_name' [-Wunused-variable] 37 | static char __ro_after_init smccc_soc_id_name[136] = ""; | ^~~~~~~~~~~~~~~~~ drivers/firmware/smccc/soc_id.c:103:20: warning: unused function 'str_fragment_from_reg' [-Wunused-function] 103 | static inline void str_fragment_from_reg(char *dst, unsigned long reg) | ^~~~~~~~~~~~~~~~~~~~~ 6 warnings generated. vim +109 drivers/firmware/smccc/soc_id.c 36 > 37 static char __ro_after_init smccc_soc_id_name[136] = ""; 38 39 static int __init smccc_soc_init(void) 40 { 41 int soc_id_rev, soc_id_version; 42 static char soc_id_str[20], soc_id_rev_str[12]; 43 static char soc_id_jep106_id_str[12]; 44 45 if (arm_smccc_get_version() < ARM_SMCCC_VERSION_1_2) 46 return 0; 47 48 soc_id_version = arm_smccc_get_soc_id_version(); 49 if (soc_id_version == SMCCC_RET_NOT_SUPPORTED) { 50 pr_info("ARCH_SOC_ID not implemented, skipping ....\n"); 51 return 0; 52 } 53 54 if (soc_id_version < 0) { 55 pr_err("Invalid SoC Version: %x\n", soc_id_version); 56 return -EINVAL; 57 } 58 59 soc_id_rev = arm_smccc_get_soc_id_revision(); 60 if (soc_id_rev < 0) { 61 pr_err("Invalid SoC Revision: %x\n", soc_id_rev); 62 return -EINVAL; 63 } 64 65 soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); 66 if (!soc_dev_attr) 67 return -ENOMEM; 68 69 sprintf(soc_id_rev_str, "0x%08x", soc_id_rev); 70 sprintf(soc_id_jep106_id_str, "jep106:%02x%02x", 71 JEP106_BANK_CONT_CODE(soc_id_version), 72 JEP106_ID_CODE(soc_id_version)); 73 sprintf(soc_id_str, "%s:%04x", soc_id_jep106_id_str, 74 IMP_DEF_SOC_ID(soc_id_version)); 75 76 soc_dev_attr->soc_id = soc_id_str; 77 soc_dev_attr->revision = soc_id_rev_str; 78 soc_dev_attr->family = soc_id_jep106_id_str; 79 soc_dev_attr->machine = smccc_soc_name_init(); 80 81 soc_dev = soc_device_register(soc_dev_attr); 82 if (IS_ERR(soc_dev)) { 83 kfree(soc_dev_attr); 84 return PTR_ERR(soc_dev); 85 } 86 87 pr_info("ID = %s Revision = %s\n", soc_dev_attr->soc_id, 88 soc_dev_attr->revision); 89 90 return 0; 91 } 92 module_init(smccc_soc_init); 93 94 static void __exit smccc_soc_exit(void) 95 { 96 if (soc_dev) 97 soc_device_unregister(soc_dev); 98 kfree(soc_dev_attr); 99 } 100 module_exit(smccc_soc_exit); 101 102 103 static inline void str_fragment_from_reg(char *dst, unsigned long reg) 104 { 105 dst[0] = (reg >> 0) & 0xff; 106 dst[1] = (reg >> 8) & 0xff; 107 dst[2] = (reg >> 16) & 0xff; 108 dst[3] = (reg >> 24) & 0xff; > 109 dst[4] = (reg >> 32) & 0xff; > 110 dst[5] = (reg >> 40) & 0xff; 111 dst[6] = (reg >> 48) & 0xff; 112 dst[7] = (reg >> 56) & 0xff; 113 } 114
diff --git a/drivers/firmware/smccc/soc_id.c b/drivers/firmware/smccc/soc_id.c index 1990263fbba0..b72d100bdf31 100644 --- a/drivers/firmware/smccc/soc_id.c +++ b/drivers/firmware/smccc/soc_id.c @@ -32,6 +32,10 @@ static struct soc_device *soc_dev; static struct soc_device_attribute *soc_dev_attr; +static char __init *smccc_soc_name_init(void); + +static char __ro_after_init smccc_soc_id_name[136] = ""; + static int __init smccc_soc_init(void) { int soc_id_rev, soc_id_version; @@ -72,6 +76,7 @@ static int __init smccc_soc_init(void) soc_dev_attr->soc_id = soc_id_str; soc_dev_attr->revision = soc_id_rev_str; soc_dev_attr->family = soc_id_jep106_id_str; + soc_dev_attr->machine = smccc_soc_name_init(); soc_dev = soc_device_register(soc_dev_attr); if (IS_ERR(soc_dev)) { @@ -93,3 +98,73 @@ static void __exit smccc_soc_exit(void) kfree(soc_dev_attr); } module_exit(smccc_soc_exit); + + +static inline void str_fragment_from_reg(char *dst, unsigned long reg) +{ + dst[0] = (reg >> 0) & 0xff; + dst[1] = (reg >> 8) & 0xff; + dst[2] = (reg >> 16) & 0xff; + dst[3] = (reg >> 24) & 0xff; + dst[4] = (reg >> 32) & 0xff; + dst[5] = (reg >> 40) & 0xff; + dst[6] = (reg >> 48) & 0xff; + dst[7] = (reg >> 56) & 0xff; +} + +static char __init *smccc_soc_name_init(void) +{ +#ifdef CONFIG_ARM64 + struct arm_smccc_1_2_regs args; + struct arm_smccc_1_2_regs res; + size_t len; + + /* + * Issue Number 1.6 of the Arm SMC Calling Convention + * specification introduces an optional "name" string + * to the ARM_SMCCC_ARCH_SOC_ID function. Fetch it if + * available. + */ + args.a0 = ARM_SMCCC_ARCH_SOC_ID; + args.a1 = 2; /* SOC_ID name */ + arm_smccc_1_2_invoke(&args, &res); + if ((u32)res.a0 == 0) { + const unsigned int regsize = sizeof(res.a1); + + /* + * Copy res.a1..res.a17 to the smccc_soc_id_name string + * 8 bytes at a time. As per Issue 1.6 of the Arm SMC + * Calling Convention, the string will be NUL terminated + * and padded, from the end of the string to the end of the + * 136 byte buffer, with NULs. + */ + str_fragment_from_reg(smccc_soc_id_name + 0*regsize, res.a1); + str_fragment_from_reg(smccc_soc_id_name + 1*regsize, res.a2); + str_fragment_from_reg(smccc_soc_id_name + 2*regsize, res.a3); + str_fragment_from_reg(smccc_soc_id_name + 3*regsize, res.a4); + str_fragment_from_reg(smccc_soc_id_name + 4*regsize, res.a5); + str_fragment_from_reg(smccc_soc_id_name + 5*regsize, res.a6); + str_fragment_from_reg(smccc_soc_id_name + 6*regsize, res.a7); + str_fragment_from_reg(smccc_soc_id_name + 7*regsize, res.a8); + str_fragment_from_reg(smccc_soc_id_name + 8*regsize, res.a9); + str_fragment_from_reg(smccc_soc_id_name + 9*regsize, res.a10); + str_fragment_from_reg(smccc_soc_id_name + 10*regsize, res.a11); + str_fragment_from_reg(smccc_soc_id_name + 11*regsize, res.a12); + str_fragment_from_reg(smccc_soc_id_name + 12*regsize, res.a13); + str_fragment_from_reg(smccc_soc_id_name + 13*regsize, res.a14); + str_fragment_from_reg(smccc_soc_id_name + 14*regsize, res.a15); + str_fragment_from_reg(smccc_soc_id_name + 15*regsize, res.a16); + str_fragment_from_reg(smccc_soc_id_name + 16*regsize, res.a17); + + len = strnlen(smccc_soc_id_name, sizeof(smccc_soc_id_name)); + if (len) { + if (len == sizeof(smccc_soc_id_name)) + pr_warn(FW_BUG "Ignoring improperly formatted Name\n"); + else + return smccc_soc_id_name; + } + } +#endif + + return NULL; +} diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h index 67f6fdf2e7cd..9d444e5862fe 100644 --- a/include/linux/arm-smccc.h +++ b/include/linux/arm-smccc.h @@ -607,6 +607,12 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1, ___res->a0 = SMCCC_RET_NOT_SUPPORTED; \ } while (0) +#define __fail_smccc_1_2(___res) \ + do { \ + if (___res) \ + ___res->a0 = SMCCC_RET_NOT_SUPPORTED; \ + } while (0) + /* * arm_smccc_1_1_invoke() - make an SMCCC v1.1 compliant call * @@ -639,5 +645,36 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1, method; \ }) +/* + * arm_smccc_1_2_invoke() - make an SMCCC v1.2 compliant call + * + * @args: SMC args are in the a0..a17 fields of the arm_smcc_1_2_regs structure + * @res: result values from registers 0 to 17 + * + * This macro will make either an HVC call or an SMC call depending on the + * current SMCCC conduit. If no valid conduit is available then -1 + * (SMCCC_RET_NOT_SUPPORTED) is returned in @res.a0 (if supplied). + * + * The return value also provides the conduit that was used. + */ +#define arm_smccc_1_2_invoke(args, res) ({ \ + struct arm_smccc_1_2_regs *__args = args; \ + struct arm_smccc_1_2_regs *__res = res; \ + int method = arm_smccc_1_1_get_conduit(); \ + switch (method) { \ + case SMCCC_CONDUIT_HVC: \ + arm_smccc_1_2_hvc(__args, __res); \ + break; \ + case SMCCC_CONDUIT_SMC: \ + arm_smccc_1_2_smc(__args, __res); \ + break; \ + default: \ + __fail_smccc_1_2(__res); \ + method = SMCCC_CONDUIT_NONE; \ + break; \ + } \ + method; \ + }) + #endif /*__ASSEMBLY__*/ #endif /*__LINUX_ARM_SMCCC_H*/
Issue Number 1.6 of the Arm SMC Calling Convention introduces an optional SOC_ID name string. If available, point the 'machine' field of the SoC Device Attributes at this string so that it will appear under /sys/bus/soc/devices/soc0/machine. On Arm SMC compliant SoCs, this will allow things like 'lscpu' to eventually get a SoC provider model name from there rather than each tool/utility needing to get a possibly inconsistent, obsolete, or incorrect model/machine name from its own hardcoded model/machine name table. Signed-off-by: Paul Benoit <paul@os.amperecomputing.com> Cc: Mark Rutland <mark.rutland@arm.com> Cc: Lorenzo Pieralisi <lpieralisi@kernel.org> Cc: Sudeep Holla <sudeep.holla@arm.com> Cc: linux-arm-kernel@lists.infradead.org --- v1->v2: Address code review identified issues. drivers/firmware/smccc/soc_id.c | 75 +++++++++++++++++++++++++++++++++ include/linux/arm-smccc.h | 37 ++++++++++++++++ 2 files changed, 112 insertions(+)