From 2ed5a70bca0bcad048171f6784bddf85a6adba54 Mon Sep 17 00:00:00 2001 From: Sui Jingfeng <15330273260@189.cn> Date: Fri, 12 Nov 2021 00:06:50 +0800 Subject: [PATCH] mips: Implement the run-time MIPS MSA discovery function correctly The old implementation of png_have_msa() caused a bus error, if a word in /proc/cpuinfo was longer than 10 characters. In the original implementation, `word[10]` was too short, and `word[i++] = ch` caused a stack smash if the characters between spaces were more than 10. And also, fclose(f) should be called before leaving. For example on loongson ls3a4000 cpu platform: $ cat /proc/cpuinfo system type : Generic Loongson64 System machine : loongson,loongson64g-4core-ls7a processor : 0 cpu model : ICT Loongson-3 V0.1 FPU V0.1 BogoMIPS : 3594.02 wait instruction : yes microsecond timers : yes tlb_entries : 2112 extra interrupt vector : no hardware watchpoint : no isa : mips1 mips2 mips3 mips4 mips5 mips32r1 mips32r2 mips64r1 mips64r2 ASEs implemented : vz msa loongson-mmi loongson-cam loongson-ext loongson-ext2 shadow register sets : 1 kscratch registers : 6 package : 0 core : 0 VCED exceptions : not available VCEI exceptions : not available processor : 1 cpu model : ICT Loongson-3 V0.1 FPU V0.1 BogoMIPS : 3611.26 wait instruction : yes microsecond timers : yes tlb_entries : 2112 extra interrupt vector : no hardware watchpoint : no isa : mips1 mips2 mips3 mips4 mips5 mips32r1 mips32r2 mips64r1 mips64r2 ASEs implemented : vz msa loongson-mmi loongson-cam loongson-ext loongson-ext2 shadow register sets : 1 kscratch registers : 6 package : 0 core : 1 VCED exceptions : not available VCEI exceptions : not available Co-authored-by: Cosmin Truta Signed-off-by: Sui Jingfeng <15330273260@189.cn> Signed-off-by: Cosmin Truta --- contrib/mips-msa/linux.c | 60 ++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 36 deletions(-) diff --git a/contrib/mips-msa/linux.c b/contrib/mips-msa/linux.c index 3bac6111b..cae8ca50f 100644 --- a/contrib/mips-msa/linux.c +++ b/contrib/mips-msa/linux.c @@ -1,67 +1,55 @@ /* contrib/mips-msa/linux.c * - * Copyright (c) 2020 Cosmin Truta + * Copyright (c) 2020-2023 Cosmin Truta * Copyright (c) 2016 Glenn Randers-Pehrson * Written by Mandar Sahastrabuddhe, 2016. + * Updated by Sui Jingfeng, 2021. * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer * and license in png.h * - * SEE contrib/mips-msa/README before reporting bugs + * On Linux, png_have_msa is implemented by reading the pseudo-file + * "/proc/self/auxv". + * + * See contrib/mips-msa/README before reporting bugs. * * STATUS: SUPPORTED * BUG REPORTS: png-mng-implement@sourceforge.net - * - * png_have_msa implemented for Linux by reading the widely available - * pseudo-file /proc/cpuinfo. - * - * This code is strict ANSI-C and is probably moderately portable; it does - * however use and it assumes that /proc/cpuinfo is never localized. */ -#include -#include +#include +#include #include +#include static int png_have_msa(png_structp png_ptr) { - FILE *f = fopen("/proc/cpuinfo", "rb"); + Elf64_auxv_t aux; + int fd; + int has_msa = 0; - char *string = "msa"; - char word[10]; - - if (f != NULL) + fd = open("/proc/self/auxv", O_RDONLY); + if (fd >= 0) { - while(!feof(f)) + while (read(fd, &aux, sizeof(Elf64_auxv_t)) == sizeof(Elf64_auxv_t)) { - int ch = fgetc(f); - static int i = 0; - - while(!(ch <= 32)) + if (aux.a_type == AT_HWCAP) { - word[i++] = ch; - ch = fgetc(f); + uint64_t hwcap = aux.a_un.a_val; + + has_msa = (hwcap >> 1) & 1; + break; } - - int val = strcmp(string, word); - - if (val == 0) { - fclose(f); - return 1; - } - - i = 0; - memset(word, 0, 10); } - - fclose(f); + close(fd); } #ifdef PNG_WARNINGS_SUPPORTED else - png_warning(png_ptr, "/proc/cpuinfo open failed"); + png_warning(png_ptr, "/proc/self/auxv open failed"); #endif - return 0; + + return has_msa; }