On Fri, Aug 04, 2023 at 01:26:08PM +0200, Peter J. Philipp wrote: > On Tue, Aug 01, 2023 at 01:43:36PM +0200, p...@delphinusdns.org wrote: > > >Synopsis: non-terminated strings buffer in riscv64/cpu.c > > >Category: kernel > > >Environment: > > System : OpenBSD 7.3 > > Details : OpenBSD 7.3-current (GENERIC.MP) #376: Thu Jul 13 > > 03:59:40 MDT 2023 > > > > dera...@riscv64.openbsd.org:/usr/src/sys/arch/riscv64/compile/GENERIC.MP > > > > Architecture: OpenBSD.riscv64 > > Machine : riscv64 > > >Description: > > The cpu detect output is not NUL terminated, this causes *puke* to be > > displayed on serial terminals. > > >How-To-Repeat: > > Using Qemu for riscv64 arch. > > > > from a eeprom -p | grep isa output: > > > > riscv,isa: > > 'rv64imafdch_zicsr_zifencei_zihintpause_zba_zbb_zbc_zbs_sstc' > > riscv,isa: > > 'rv64imafdch_zicsr_zifencei_zihintpause_zba_zbb_zbc_zbs_sstc' > > > > I counted this as 60 bytes long. > > >Fix: > > > > There is two approaches. One is to explicitly NUL terminate the 32 byte > > buffer or make it bigger. I give an untested patch of the latter.
riscv,isa is going away: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=aeb71e42caae2031ec849a858080d81462cacca9 I see no point in trying to parse it. > > > > Index: cpu.c > > =================================================================== > > RCS file: /cvs/src/sys/arch/riscv64/riscv64/cpu.c,v > > retrieving revision 1.14 > > diff -u -p -u -r1.14 cpu.c > > --- cpu.c 15 Jun 2023 22:18:08 -0000 1.14 > > +++ cpu.c 1 Aug 2023 11:35:28 -0000 > > @@ -87,7 +87,7 @@ int cpu_errata_sifive_cip_1200; > > void > > cpu_identify(struct cpu_info *ci) > > { > > - char isa[32]; > > + char isa[64]; > > uint64_t marchid, mimpid; > > uint32_t mvendorid; > > const char *vendor_name = NULL; > > > > > > [tying in tech@] > > This wasn't effective I just saw. On another QEMU host the cpu ISA string is > larger than 80 characters. So I've made another patch. > > With this patch it looks like so: > > oceans$ dmesg|grep cpu > cpu0 at mainbus0: vendor 0 arch 0 imp 0 rv64imafdch Zicbom Zicboz Zicsr > Zifencei Zihintpause Zawrs Zfa Zca Zcd Zba Zbb Zbc Zbs Sstc Svadu > intc0 at cpu0 > cpu1 at mainbus0: vendor 0 arch 0 imp 0 rv64imafdch Zicbom Zicboz Zicsr > Zifencei Zihintpause Zawrs Zfa Zca Zcd Zba Zbb Zbc Zbs Sstc Svadu > oceans# grep zicboz /root/eeprom-p.out > > riscv,isa: > 'rv64imafdch_zicbom_zicboz_zicsr_zifencei_zihintpause_zawrs_zfa_zca_zcd_zba_zbb_zbc_zbs_sstc_svadu' > riscv,isa: > 'rv64imafdch_zicbom_zicboz_zicsr_zifencei_zihintpause_zawrs_zfa_zca_zcd_zba_zbb_zbc_zbs_sstc_svadu' > > This is in convention with the cpu.c found in qemu: > > https://gitlab.com/qemu-project/qemu/-/blob/master/target/riscv/cpu.c > > lines 64 through 84 is the description of it. > > While I have no OpenBSD/riscv64 on true hardware it works on QEMU, and I > googled for a dmesg online and the Hifive Unmatched should work as well. > > patch follows: > > Index: cpu.c > =================================================================== > RCS file: /cvs/src/sys/arch/riscv64/riscv64/cpu.c,v > retrieving revision 1.14 > diff -u -p -u -r1.14 cpu.c > --- cpu.c 15 Jun 2023 22:18:08 -0000 1.14 > +++ cpu.c 4 Aug 2023 11:15:16 -0000 > @@ -84,15 +84,19 @@ struct cfdriver cpu_cd = { > > int cpu_errata_sifive_cip_1200; > > + > void > cpu_identify(struct cpu_info *ci) > { > - char isa[32]; > + char isa[255]; > + char szx_ext[255]; /* S, Z and X extension buffer */ > + char *extensions = "imafdqlcbkjtpvh"; > uint64_t marchid, mimpid; > uint32_t mvendorid; > const char *vendor_name = NULL; > const char *arch_name = NULL; > struct arch *archlist = cpu_arch_none; > + char *p, *pe, *end; > int i, len; > > mvendorid = sbi_get_mvendorid(); > @@ -126,8 +130,70 @@ cpu_identify(struct cpu_info *ci) > > len = OF_getprop(ci->ci_node, "riscv,isa", isa, sizeof(isa)); > if (len != -1) { > + /* terminate it, it could be non-terminated */ > + isa[sizeof(isa) - 1] = '\0'; > + > + /* PARSE the IMAFDQ... extensions */ > + pe = extensions; > + if ((p = strchr(isa, 'i')) != NULL || > + (p = strchr(isa, 'I')) != NULL) { > + for (; *pe != '\0'; pe++) { > + if (((*p)|0x20) == *pe) { > + if (p[1]) { > + p++; > + i++; > + } else > + break; > + } > + /* > + * we've hit an underscore what follows > + * may be an S or Z extension > + */ > + if (*p == '_') > + break; > + } > + > + szx_ext[0] = '\0'; > + if (*p == '_') { > + *p++ = '\0'; > + for (; *p ;) { > + end = strchr(p, '_'); > + if (end != NULL) > + *end++ = '\0'; > + > + switch (*p) { > + case 'Z': > + case 'z': > + strlcat(szx_ext, "Z", > sizeof(szx_ext)); > + break; > + case 'S': > + case 's': > + strlcat(szx_ext, "S", > sizeof(szx_ext)); > + break; > + case 'X': > + case 'x': > + default: > + strlcat(szx_ext, "?", > sizeof(szx_ext)); > + break; > + } > + p++; > + i++; > + strlcat(szx_ext, p, sizeof(szx_ext)); > + if (end) { > + strlcat(szx_ext, " ", > sizeof(szx_ext)); > + p = end; > + } else > + break; > + } > + } else > + *p = '\0'; > + } > + > printf(" %s", isa); > strlcpy(cpu_model, isa, sizeof(cpu_model)); > + > + printf(" %s", szx_ext); > + > } > printf("\n"); > > > Best Regards, > -peter > >