}
                }
  
-               /*
-                * For all possible cpus, we have already validated in
-                * the boot process that they at least contain "rv" and
-                * whichever of "32"/"64" this kernel supports, and so this
-                * section can be skipped.
-                */
-               isa += 4;
- 
-               while (*isa) {
-                       const char *ext = isa++;
-                       const char *ext_end = isa;
-                       bool ext_long = false, ext_err = false;
- 
-                       switch (*ext) {
-                       case 's':
-                               /*
-                                * Workaround for invalid single-letter 's' & 'u'(QEMU).
-                                * No need to set the bit in riscv_isa as 's' & 'u' are
-                                * not valid ISA extensions. It works until multi-letter
-                                * extension starting with "Su" appears.
-                                */
-                               if (ext[-1] != '_' && ext[1] == 'u') {
-                                       ++isa;
-                                       ext_err = true;
-                                       break;
-                               }
-                               fallthrough;
-                       case 'S':
-                       case 'x':
-                       case 'X':
-                       case 'z':
-                       case 'Z':
-                               /*
-                                * Before attempting to parse the extension itself, we find its end.
-                                * As multi-letter extensions must be split from other multi-letter
-                                * extensions with an "_", the end of a multi-letter extension will
-                                * either be the null character or the "_" at the start of the next
-                                * multi-letter extension.
-                                *
-                                * Next, as the extensions version is currently ignored, we
-                                * eliminate that portion. This is done by parsing backwards from
-                                * the end of the extension, removing any numbers. This may be a
-                                * major or minor number however, so the process is repeated if a
-                                * minor number was found.
-                                *
-                                * ext_end is intended to represent the first character *after* the
-                                * name portion of an extension, but will be decremented to the last
-                                * character itself while eliminating the extensions version number.
-                                * A simple re-increment solves this problem.
-                                */
-                               ext_long = true;
-                               for (; *isa && *isa != '_'; ++isa)
-                                       if (unlikely(!isalnum(*isa)))
-                                               ext_err = true;
- 
-                               ext_end = isa;
-                               if (unlikely(ext_err))
-                                       break;
- 
-                               if (!isdigit(ext_end[-1]))
-                                       break;
- 
-                               while (isdigit(*--ext_end))
-                                       ;
- 
-                               if (tolower(ext_end[0]) != 'p' || !isdigit(ext_end[-1])) {
-                                       ++ext_end;
-                                       break;
-                               }
- 
-                               while (isdigit(*--ext_end))
-                                       ;
- 
-                               ++ext_end;
-                               break;
-                       default:
-                               /*
-                                * Things are a little easier for single-letter extensions, as they
-                                * are parsed forwards.
-                                *
-                                * After checking that our starting position is valid, we need to
-                                * ensure that, when isa was incremented at the start of the loop,
-                                * that it arrived at the start of the next extension.
-                                *
-                                * If we are already on a non-digit, there is nothing to do. Either
-                                * we have a multi-letter extension's _, or the start of an
-                                * extension.
-                                *
-                                * Otherwise we have found the current extension's major version
-                                * number. Parse past it, and a subsequent p/minor version number
-                                * if present. The `p` extension must not appear immediately after
-                                * a number, so there is no fear of missing it.
-                                *
-                                */
-                               if (unlikely(!isalpha(*ext))) {
-                                       ext_err = true;
-                                       break;
-                               }
- 
-                               if (!isdigit(*isa))
-                                       break;
- 
-                               while (isdigit(*++isa))
-                                       ;
- 
-                               if (tolower(*isa) != 'p')
-                                       break;
- 
-                               if (!isdigit(*++isa)) {
-                                       --isa;
-                                       break;
-                               }
- 
-                               while (isdigit(*++isa))
-                                       ;
- 
-                               break;
-                       }
- 
-                       /*
-                        * The parser expects that at the start of an iteration isa points to the
-                        * first character of the next extension. As we stop parsing an extension
-                        * on meeting a non-alphanumeric character, an extra increment is needed
-                        * where the succeeding extension is a multi-letter prefixed with an "_".
-                        */
-                       if (*isa == '_')
-                               ++isa;
- 
- #define SET_ISA_EXT_MAP(name, bit)                                                    \
-                       do {                                                            \
-                               if ((ext_end - ext == sizeof(name) - 1) &&              \
-                                    !strncasecmp(ext, name, sizeof(name) - 1) &&       \
-                                    riscv_isa_extension_check(bit))                    \
-                                       set_bit(bit, isainfo->isa);                     \
-                       } while (false)                                                 \
- 
-                       if (unlikely(ext_err))
-                               continue;
-                       if (!ext_long) {
-                               int nr = tolower(*ext) - 'a';
- 
-                               if (riscv_isa_extension_check(nr)) {
-                                       this_hwcap |= isa2hwcap[nr];
-                                       set_bit(nr, isainfo->isa);
-                               }
-                       } else {
-                               /* sorted alphabetically */
-                               SET_ISA_EXT_MAP("smaia", RISCV_ISA_EXT_SMAIA);
-                               SET_ISA_EXT_MAP("ssaia", RISCV_ISA_EXT_SSAIA);
-                               SET_ISA_EXT_MAP("sscofpmf", RISCV_ISA_EXT_SSCOFPMF);
-                               SET_ISA_EXT_MAP("sstc", RISCV_ISA_EXT_SSTC);
-                               SET_ISA_EXT_MAP("svinval", RISCV_ISA_EXT_SVINVAL);
-                               SET_ISA_EXT_MAP("svnapot", RISCV_ISA_EXT_SVNAPOT);
-                               SET_ISA_EXT_MAP("svpbmt", RISCV_ISA_EXT_SVPBMT);
-                               SET_ISA_EXT_MAP("zba", RISCV_ISA_EXT_ZBA);
-                               SET_ISA_EXT_MAP("zbb", RISCV_ISA_EXT_ZBB);
-                               SET_ISA_EXT_MAP("zbs", RISCV_ISA_EXT_ZBS);
-                               SET_ISA_EXT_MAP("zicbom", RISCV_ISA_EXT_ZICBOM);
-                               SET_ISA_EXT_MAP("zicboz", RISCV_ISA_EXT_ZICBOZ);
-                               SET_ISA_EXT_MAP("zihintpause", RISCV_ISA_EXT_ZIHINTPAUSE);
-                       }
- #undef SET_ISA_EXT_MAP
-               }
+               riscv_parse_isa_string(&this_hwcap, isainfo, isa2hwcap, isa);
  
 -              /*
 -               * Linux requires the following extensions, so we may as well
 -               * always set them.
 -               */
 -              set_bit(RISCV_ISA_EXT_ZICSR, isainfo->isa);
 -              set_bit(RISCV_ISA_EXT_ZIFENCEI, isainfo->isa);
 -
                /*
                 * These ones were as they were part of the base ISA when the
                 * port & dt-bindings were upstreamed, and so can be set