Index | Thread | Search

From:
Kurt Miller <kurt@intricatesoftware.com>
Subject:
devel/jdk: aarch64 cpu info and hardware capablities
To:
ports@openbsd.org
Date:
Wed, 17 Dec 2025 14:58:29 +0000

Download raw body.

Thread
New version. On aarch64 the jdk wants hardware capablities and cpu
info so it can adjust its behavior to conform to the hardware ablities. 

This diff uses elf_aux_info(3) for hardware capablities and if
HWCAP_CPUID is set will use READ_SPECIALREG(midr_el1) to obtain
the cpu info. If HWCAP_CPUID is not set it will fallback to parsing
sysctl hw.model output to lookup the cpu info.

This has been tested on Apple Mac Mini (M2 Pro, 2023) which supports
HWCAP_CPUID and Pine64 RockPro64 v2.1 which does not support
HWCAP_CPUID. It also corrects some deadlocks I was seeing on the
Mac Mini in the tier1 tests.

okay?

Index: 1.8/Makefile
===================================================================
RCS file: /cvs/ports/devel/jdk/1.8/Makefile,v
diff -u -p -u -r1.100 Makefile
--- 1.8/Makefile	3 Nov 2025 13:37:17 -0000	1.100
+++ 1.8/Makefile	16 Dec 2025 19:33:50 -0000
@@ -12,6 +12,7 @@ V=		${BASE_VER}.${UPDATE_VER}.${BUILD_VE
 PKGNAME=	jdk-${V}
 PKGSTEM=	jdk-${BASE_VER}
 EPOCH=		0
+REVISION=	0
 
 DIST_SUBDIR=	jdk
 DISTNAME=	jdk8u${UPDATE_VER}-${BUILD_VER}.${BSD_PORT_REL}
Index: 1.8/patches/patch-hotspot_src_os_cpu_bsd_aarch64_vm_vm_version_bsd_aarch64_cpp
===================================================================
RCS file: 1.8/patches/patch-hotspot_src_os_cpu_bsd_aarch64_vm_vm_version_bsd_aarch64_cpp
diff -N 1.8/patches/patch-hotspot_src_os_cpu_bsd_aarch64_vm_vm_version_bsd_aarch64_cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 1.8/patches/patch-hotspot_src_os_cpu_bsd_aarch64_vm_vm_version_bsd_aarch64_cpp	16 Dec 2025 19:33:50 -0000
@@ -0,0 +1,493 @@
+Get hardware capablilites using elf_aux_info(3).
+Detect CPU, model, variant and revision using READ_SPECIALREG
+when HWCAP_CPUID is set, otherwise parse sysctl hw.model to
+get needed info.
+
+Index: hotspot/src/os_cpu/bsd_aarch64/vm/vm_version_bsd_aarch64.cpp
+--- hotspot/src/os_cpu/bsd_aarch64/vm/vm_version_bsd_aarch64.cpp.orig
++++ hotspot/src/os_cpu/bsd_aarch64/vm/vm_version_bsd_aarch64.cpp
+@@ -27,91 +27,84 @@
+ #include "vm_version_aarch64.hpp"
+ 
+ #include <machine/armreg.h>
+-#if defined (__FreeBSD__)
+-#include <machine/elf.h>
++#if defined (__FreeBSD__) || defined (__OpenBSD__)
++#include <sys/auxv.h>
+ #endif
+ 
+-#ifndef HWCAP_ASIMD
+-#define HWCAP_ASIMD (1<<1)
+-#endif
++#define	CPU_IMPL(midr)	(((midr) >> 24) & 0xff)
++#define	CPU_PART(midr)	(((midr) >> 4) & 0xfff)
++#define	CPU_VAR(midr)	(((midr) >> 20) & 0xf)
++#define	CPU_REV(midr)	(((midr) >> 0) & 0xf)
+ 
+-#ifndef HWCAP_AES
+-#define HWCAP_AES   (1<<3)
+-#endif
++#ifdef __OpenBSD__
++// For older processors on OpenBSD READ_SPECIALREG is not supported.
++// These constants and tables allow for looking up the cpu and model.
+ 
+-#ifndef HWCAP_PMULL
+-#define HWCAP_PMULL (1<<4)
+-#endif
++#include <sys/types.h>
++#include <sys/sysctl.h>
++#include <string.h>
++#include <stdio.h>
+ 
+-#ifndef HWCAP_SHA1
+-#define HWCAP_SHA1  (1<<5)
+-#endif
+-
+-#ifndef HWCAP_SHA2
+-#define HWCAP_SHA2  (1<<6)
+-#endif
+-
+-#ifndef HWCAP_CRC32
+-#define HWCAP_CRC32 (1<<7)
+-#endif
+-
+-#ifndef HWCAP_ATOMICS
+-#define HWCAP_ATOMICS (1<<8)
+-#endif
+-
+-#ifndef ID_AA64PFR0_AdvSIMD_SHIFT
+-#define ID_AA64PFR0_AdvSIMD_SHIFT 20
+-#endif
+-
+-#ifndef ID_AA64PFR0_AdvSIMD
+-#define ID_AA64PFR0_AdvSIMD(x) ((x) & (UL(0xf) << ID_AA64PFR0_AdvSIMD_SHIFT))
+-#endif
+-
+-#ifndef ID_AA64PFR0_AdvSIMD_IMPL
+-#define ID_AA64PFR0_AdvSIMD_IMPL (UL(0x0) << ID_AA64PFR0_AdvSIMD_SHIFT)
+-#endif
+-
+-#ifndef ID_AA64PFR0_AdvSIMD_HP
+-#define ID_AA64PFR0_AdvSIMD_HP (UL(0x1) << ID_AA64PFR0_AdvSIMD_SHIFT)
+-#endif
+-
+-#ifndef ID_AA64ISAR0_AES_VAL
+-#define ID_AA64ISAR0_AES_VAL ID_AA64ISAR0_AES
+-#endif
+-
+-#ifndef ID_AA64ISAR0_SHA1_VAL
+-#define ID_AA64ISAR0_SHA1_VAL ID_AA64ISAR0_SHA1
+-#endif
+-
+-#ifndef ID_AA64ISAR0_SHA2_VAL
+-#define ID_AA64ISAR0_SHA2_VAL ID_AA64ISAR0_SHA2
+-#endif
+-
+-#ifndef ID_AA64ISAR0_CRC32_VAL
+-#define ID_AA64ISAR0_CRC32_VAL ID_AA64ISAR0_CRC32
+-#endif
+-
+ #define	CPU_IMPL_ARM		0x41
+ #define	CPU_IMPL_BROADCOM	0x42
+ #define	CPU_IMPL_CAVIUM		0x43
+ #define	CPU_IMPL_DEC		0x44
++#define	CPU_IMPL_FUJITSU	0x46
++#define	CPU_IMPL_HISILICON	0x48
+ #define	CPU_IMPL_INFINEON	0x49
+ #define	CPU_IMPL_FREESCALE	0x4D
+ #define	CPU_IMPL_NVIDIA		0x4E
+ #define	CPU_IMPL_APM		0x50
+ #define	CPU_IMPL_QUALCOMM	0x51
+ #define	CPU_IMPL_MARVELL	0x56
++#define	CPU_IMPL_APPLE		0x61
+ #define	CPU_IMPL_INTEL		0x69
++#define	CPU_IMPL_AMPERE		0xC0
++#define	CPU_IMPL_MICROSOFT	0x6D
+ 
+ /* ARM Part numbers */
+ #define	CPU_PART_FOUNDATION	0xD00
+-#define	CPU_PART_CORTEX_A35	0xD04
++#define	CPU_PART_CORTEX_A34	0xD02
+ #define	CPU_PART_CORTEX_A53	0xD03
++#define	CPU_PART_CORTEX_A35	0xD04
+ #define	CPU_PART_CORTEX_A55	0xD05
++#define	CPU_PART_CORTEX_A65	0xD06
+ #define	CPU_PART_CORTEX_A57	0xD07
+ #define	CPU_PART_CORTEX_A72	0xD08
+ #define	CPU_PART_CORTEX_A73	0xD09
+ #define	CPU_PART_CORTEX_A75	0xD0A
++#define	CPU_PART_CORTEX_A76	0xD0B
++#define	CPU_PART_NEOVERSE_N1	0xD0C
++#define	CPU_PART_CORTEX_A77	0xD0D
++#define	CPU_PART_CORTEX_A76AE	0xD0E
++#define	CPU_PART_AEM_V8		0xD0F
++#define	CPU_PART_NEOVERSE_V1	0xD40
++#define	CPU_PART_CORTEX_A78	0xD41
++#define	CPU_PART_CORTEX_A78AE	0xD42
++#define	CPU_PART_CORTEX_A65AE	0xD43
++#define	CPU_PART_CORTEX_X1	0xD44
++#define	CPU_PART_CORTEX_A510	0xD46
++#define	CPU_PART_CORTEX_A710	0xD47
++#define	CPU_PART_CORTEX_X2	0xD48
++#define	CPU_PART_NEOVERSE_N2	0xD49
++#define	CPU_PART_NEOVERSE_E1	0xD4A
++#define	CPU_PART_CORTEX_A78C	0xD4B
++#define	CPU_PART_CORTEX_X1C	0xD4C
++#define	CPU_PART_CORTEX_A715	0xD4D
++#define	CPU_PART_CORTEX_X3	0xD4E
++#define	CPU_PART_NEOVERSE_V2	0xD4F
++#define	CPU_PART_CORTEX_A520	0xD80
++#define	CPU_PART_CORTEX_A720	0xD81
++#define	CPU_PART_CORTEX_X4	0xD82
++#define	CPU_PART_NEOVERSE_V3AE	0xD83
++#define	CPU_PART_NEOVERSE_V3	0xD84
++#define	CPU_PART_CORTEX_X925	0xD85
++#define	CPU_PART_CORTEX_A725	0xD87
++#define	CPU_PART_C1_NANO	0xD8A
++#define	CPU_PART_C1_PRO		0xD8B
++#define	CPU_PART_C1_ULTRA	0xD8C
++#define	CPU_PART_NEOVERSE_N3	0xD8E
++#define	CPU_PART_C1_PREMIUM	0xD90
+ 
+ /* Cavium Part numbers */
+ #define	CPU_PART_THUNDERX	0x0A1
+@@ -124,21 +117,35 @@
+ 
+ #define	CPU_REV_THUNDERX2_0	0x00
+ 
+-#define	CPU_IMPL(midr)	(((midr) >> 24) & 0xff)
+-#define	CPU_PART(midr)	(((midr) >> 4) & 0xfff)
+-#define	CPU_VAR(midr)	(((midr) >> 20) & 0xf)
+-#define	CPU_REV(midr)	(((midr) >> 0) & 0xf)
+-#define UL(x)   UINT64_C(x)
++/* APM (now Ampere) Part number */
++#define CPU_PART_EMAG8180	0x000
+ 
+-struct cpu_desc {
+-	u_int		cpu_impl;
+-	u_int		cpu_part_num;
+-	u_int		cpu_variant;
+-	u_int		cpu_revision;
+-	const char	*cpu_impl_name;
+-	const char	*cpu_part_name;
+-};
++/* Ampere Part numbers */
++#define	CPU_PART_AMPERE1	0xAC3
++#define	CPU_PART_AMPERE1A	0xAC4
+ 
++/* Microsoft Part numbers */
++#define	CPU_PART_AZURE_COBALT_100	0xD49
++
++/* Qualcomm */
++#define CPU_PART_ORYON          0x001
++#define	CPU_PART_KRYO400_GOLD	0x804
++#define	CPU_PART_KRYO400_SILVER	0x805
++
++/* Apple part numbers */
++#define CPU_PART_M1_ICESTORM      0x022
++#define CPU_PART_M1_FIRESTORM     0x023
++#define CPU_PART_M1_ICESTORM_PRO  0x024
++#define CPU_PART_M1_FIRESTORM_PRO 0x025
++#define CPU_PART_M1_ICESTORM_MAX  0x028
++#define CPU_PART_M1_FIRESTORM_MAX 0x029
++#define CPU_PART_M2_BLIZZARD      0x032
++#define CPU_PART_M2_AVALANCHE     0x033
++#define CPU_PART_M2_BLIZZARD_PRO  0x034
++#define CPU_PART_M2_AVALANCHE_PRO 0x035
++#define CPU_PART_M2_BLIZZARD_MAX  0x038
++#define CPU_PART_M2_AVALANCHE_MAX 0x039
++
+ struct cpu_parts {
+ 	u_int		part_id;
+ 	const char	*part_name;
+@@ -159,130 +166,218 @@ struct cpu_implementers {
+ /*
+  * Per-implementer table of (PartNum, CPU Name) pairs.
+  */
+-/* ARM Ltd. */
++/* ARM Ltd. From FreeBSD but using OpenBSD strings */
+ static const struct cpu_parts cpu_parts_arm[] = {
++	{ CPU_PART_AEM_V8, "AEMv8" },
+ 	{ CPU_PART_FOUNDATION, "Foundation-Model" },
++	{ CPU_PART_CORTEX_A34, "Cortex-A34" },
+ 	{ CPU_PART_CORTEX_A35, "Cortex-A35" },
+ 	{ CPU_PART_CORTEX_A53, "Cortex-A53" },
+ 	{ CPU_PART_CORTEX_A55, "Cortex-A55" },
+ 	{ CPU_PART_CORTEX_A57, "Cortex-A57" },
++	{ CPU_PART_CORTEX_A65, "Cortex-A65" },
++	{ CPU_PART_CORTEX_A65AE, "Cortex-A65AE" },
+ 	{ CPU_PART_CORTEX_A72, "Cortex-A72" },
+ 	{ CPU_PART_CORTEX_A73, "Cortex-A73" },
+ 	{ CPU_PART_CORTEX_A75, "Cortex-A75" },
++	{ CPU_PART_CORTEX_A76, "Cortex-A76" },
++	{ CPU_PART_CORTEX_A76AE, "Cortex-A76AE" },
++	{ CPU_PART_CORTEX_A77, "Cortex-A77" },
++	{ CPU_PART_CORTEX_A78, "Cortex-A78" },
++	{ CPU_PART_CORTEX_A78AE, "Cortex-A78AE" },
++	{ CPU_PART_CORTEX_A78C, "Cortex-A78C" },
++	{ CPU_PART_CORTEX_A510, "Cortex-A510" },
++	{ CPU_PART_CORTEX_A520, "Cortex-A520" },
++	{ CPU_PART_CORTEX_A710, "Cortex-A710" },
++	{ CPU_PART_CORTEX_A715, "Cortex-A715" },
++	{ CPU_PART_CORTEX_A720, "Cortex-A720" },
++	{ CPU_PART_CORTEX_A725, "Cortex-A725" },
++	{ CPU_PART_CORTEX_X925, "Cortex-A925" },
++	{ CPU_PART_CORTEX_X1C, "Cortex-X1C" },
++	{ CPU_PART_CORTEX_X1, "Cortex-X1" },
++	{ CPU_PART_CORTEX_X2, "Cortex-X2" },
++	{ CPU_PART_CORTEX_X3, "Cortex-X3" },
++	{ CPU_PART_CORTEX_X4, "Cortex-X4" },
++	{ CPU_PART_C1_NANO, "C1-Nano" },
++	{ CPU_PART_C1_PRO, "C1-Pro" },
++	{ CPU_PART_C1_PREMIUM, "C1-Premium" },
++	{ CPU_PART_C1_ULTRA, "C1-Ultra" },
++	{ CPU_PART_NEOVERSE_E1, "Neoverse E1" },
++	{ CPU_PART_NEOVERSE_N1, "Neoverse N1" },
++	{ CPU_PART_NEOVERSE_N2, "Neoverse N2" },
++	{ CPU_PART_NEOVERSE_N3, "Neoverse N3" },
++	{ CPU_PART_NEOVERSE_V1, "Neoverse V1" },
++	{ CPU_PART_NEOVERSE_V2, "Neoverse V2" },
++	{ CPU_PART_NEOVERSE_V3, "Neoverse V3" },
++	{ CPU_PART_NEOVERSE_V3AE, "Neoverse V3AE" },
+ 	CPU_PART_NONE,
+ };
+-/* Cavium */
++
++/* Cavium  From FreeBSD but using OpenBSD strings */
+ static const struct cpu_parts cpu_parts_cavium[] = {
+-	{ CPU_PART_THUNDERX, "ThunderX" },
+-	{ CPU_PART_THUNDERX2, "ThunderX2" },
++	{ CPU_PART_THUNDERX, "ThunderX T88" },
++	{ CPU_PART_THUNDERX_81XX, "ThunderX T81" },
++	{ CPU_PART_THUNDERX_83XX, "ThunderX T83" },
++	{ CPU_PART_THUNDERX2, "ThunderX2 T99" },
+ 	CPU_PART_NONE,
+ };
+ 
++/* APM (now Ampere), From FreeBSD but using OpenBSD strings */
++static const struct cpu_parts cpu_parts_apm[] = {
++	{ CPU_PART_EMAG8180, "X-Gene" },
++	CPU_PART_NONE,
++};
++
++/* Ampere From FreeBSD, but using OpenBSD strings */
++static const struct cpu_parts cpu_parts_ampere[] = {
++	{ CPU_PART_AMPERE1A, "AmpereOne AC04" },
++	{ CPU_PART_AMPERE1, "AmpereOne" },
++	CPU_PART_NONE,
++};
++
++/* Microsoft */
++static const struct cpu_parts cpu_parts_microsoft[] = {
++	{ CPU_PART_AZURE_COBALT_100, "Azure Cobalt 100" },
++	CPU_PART_NONE,
++};
++
++/* Qualcomm From FreeBSD & OpenBSD. */
++static const struct cpu_parts cpu_parts_qcom[] = {
++	{ CPU_PART_KRYO400_GOLD, "Kryo 400 Gold" },
++	{ CPU_PART_KRYO400_SILVER, "Kryo 400 Silver" },
++	{ CPU_PART_ORYON, "Oryon" },
++	CPU_PART_NONE,
++};
++
++/* Apple. From FreeBSD but using OpenBSD strings */
++static const struct cpu_parts cpu_parts_apple[] = {
++	{ CPU_PART_M1_ICESTORM, "Icestorm" },
++	{ CPU_PART_M1_FIRESTORM, "Firestorm" },
++	{ CPU_PART_M1_ICESTORM_PRO, "Icestorm Pro" },
++	{ CPU_PART_M1_FIRESTORM_PRO, "Firestorm Pro" },
++	{ CPU_PART_M1_ICESTORM_MAX, "Icestorm Max" },
++	{ CPU_PART_M1_FIRESTORM_MAX, "Firestorm Max" },
++	{ CPU_PART_M2_BLIZZARD, "Blizzard" },
++	{ CPU_PART_M2_AVALANCHE, "Avalanche" },
++	{ CPU_PART_M2_BLIZZARD_PRO, "Blizzard Pro" },
++	{ CPU_PART_M2_AVALANCHE_PRO, "Avalanche Pro" },
++	{ CPU_PART_M2_BLIZZARD_MAX, "Blizzard Max" },
++	{ CPU_PART_M2_AVALANCHE_MAX, "Avalanche Max" },
++	CPU_PART_NONE,
++};
++
+ /* Unknown */
+ static const struct cpu_parts cpu_parts_none[] = {
+ 	CPU_PART_NONE,
+ };
+ 
+ /*
+- * Implementers table.
++ * Implementers table. From FreeBSD, but using OpenBSD strings
+  */
+ const struct cpu_implementers cpu_implementers[] = {
++	{ CPU_IMPL_AMPERE,	"Ampere",	cpu_parts_ampere },
++	{ CPU_IMPL_APPLE,	"Apple",	cpu_parts_apple },
++	{ CPU_IMPL_APM,		"Applied Micro",cpu_parts_apm },
+ 	{ CPU_IMPL_ARM,		"ARM",		cpu_parts_arm },
+ 	{ CPU_IMPL_BROADCOM,	"Broadcom",	cpu_parts_none },
+ 	{ CPU_IMPL_CAVIUM,	"Cavium",	cpu_parts_cavium },
+ 	{ CPU_IMPL_DEC,		"DEC",		cpu_parts_none },
+-	{ CPU_IMPL_INFINEON,	"IFX",		cpu_parts_none },
+ 	{ CPU_IMPL_FREESCALE,	"Freescale",	cpu_parts_none },
+-	{ CPU_IMPL_NVIDIA,	"NVIDIA",	cpu_parts_none },
+-	{ CPU_IMPL_APM,		"APM",		cpu_parts_none },
+-	{ CPU_IMPL_QUALCOMM,	"Qualcomm",	cpu_parts_none },
+-	{ CPU_IMPL_MARVELL,	"Marvell",	cpu_parts_none },
++	{ CPU_IMPL_FUJITSU,	"Fujitsu",	cpu_parts_none },
++	{ CPU_IMPL_HISILICON,	"HiSilicon",	cpu_parts_none },
++	{ CPU_IMPL_INFINEON,	"IFX",		cpu_parts_none },
+ 	{ CPU_IMPL_INTEL,	"Intel",	cpu_parts_none },
++	{ CPU_IMPL_MARVELL,	"Marvell",	cpu_parts_none },
++	{ CPU_IMPL_MICROSOFT,	"Microsoft",	cpu_parts_microsoft },
++	{ CPU_IMPL_NVIDIA,	"NVIDIA",	cpu_parts_none },
++	{ CPU_IMPL_QUALCOMM,	"Qualcomm",	cpu_parts_qcom },
+ 	CPU_IMPLEMENTER_NONE,
+ };
+ 
+-#ifdef __OpenBSD__
+-// READ_SPECIALREG is not available from userland on OpenBSD.
+-// Hardcode these values to the "lowest common denominator"
+-unsigned long VM_Version::os_get_processor_features() {
+-  _cpu = CPU_IMPL_ARM;
+-  _model = CPU_PART_CORTEX_A53;
+-  _variant = 0;
+-  _revision = 0;
+-  return HWCAP_ASIMD;
+-}
+-#else
+-unsigned long VM_Version::os_get_processor_features() {
+-  struct cpu_desc cpu_desc[1];
+-  struct cpu_desc user_cpu_desc;
+-  unsigned long auxv = 0;
+-  uint64_t id_aa64isar0, id_aa64pfr0;
+-
+-  uint32_t midr;
+-  uint32_t impl_id;
+-  uint32_t part_id;
+-  uint32_t cpu = 0;
++static void
++lookup_cpu(int &_cpu, int &_model, int &_variant, int &_revision) {
++  int mib[] = { CTL_HW, HW_MODEL };
++  char descr[BUFSIZ];
++  char *part_name, *rv_str;
++  size_t descr_len = sizeof(descr);
++  size_t impl_name_len;
++  const struct cpu_parts *cpu_partsp = nullptr;
+   size_t i;
+-  const struct cpu_parts *cpu_partsp = NULL;
+ 
+-  midr = READ_SPECIALREG(midr_el1);
++  if (sysctl(mib, nitems(mib), &descr, &descr_len, NULL, 0) == -1)
++    return;
+ 
+-  impl_id = CPU_IMPL(midr);
+   for (i = 0; i < nitems(cpu_implementers); i++) {
+-    if (impl_id == cpu_implementers[i].impl_id ||
+-      cpu_implementers[i].impl_id == 0) {
+-      cpu_desc[cpu].cpu_impl = impl_id;
+-      cpu_desc[cpu].cpu_impl_name = cpu_implementers[i].impl_name;
++    impl_name_len = strlen(cpu_implementers[i].impl_name);
++    if (cpu_implementers[i].impl_id == 0 ||
++      strncmp(descr, cpu_implementers[i].impl_name, impl_name_len) == 0) {
++      _cpu = cpu_implementers[i].impl_id;
+       cpu_partsp = cpu_implementers[i].cpu_parts;
+       break;
+     }
+   }
+ 
+-  part_id = CPU_PART(midr);
+-  for (i = 0; &cpu_partsp[i] != NULL; i++) {
+-    if (part_id == cpu_partsp[i].part_id || cpu_partsp[i].part_id == 0) {
+-      cpu_desc[cpu].cpu_part_num = part_id;
+-      cpu_desc[cpu].cpu_part_name = cpu_partsp[i].part_name;
+-      break;
+-    }
+-  }
++  if (_cpu == 0)
++    return;
+ 
+-  cpu_desc[cpu].cpu_revision = CPU_REV(midr);
+-  cpu_desc[cpu].cpu_variant = CPU_VAR(midr);
++  // +1 to skip space +1 more because descr_len includes NUL
++  if (impl_name_len + 2 > descr_len)
++    return;
+ 
+-  _cpu = cpu_desc[cpu].cpu_impl;
+-  _variant = cpu_desc[cpu].cpu_variant;
+-  _model = cpu_desc[cpu].cpu_part_num;
+-  _revision = cpu_desc[cpu].cpu_revision;
++  part_name = &descr[impl_name_len+1];
+ 
+-  id_aa64isar0 = READ_SPECIALREG(id_aa64isar0_el1);
+-  id_aa64pfr0 = READ_SPECIALREG(id_aa64pfr0_el1);
++  rv_str = strrchr(part_name, ' ');
++  if (rv_str == nullptr)
++    return;
+ 
+-  if (ID_AA64ISAR0_AES_VAL(id_aa64isar0) == ID_AA64ISAR0_AES_BASE) {
+-    auxv = auxv | HWCAP_AES;
+-  }
++  // null term part_name and skip over it
++  *(rv_str++) = '\0';
+ 
+-  if (ID_AA64ISAR0_AES_VAL(id_aa64isar0) == ID_AA64ISAR0_AES_PMULL) {
+-    auxv = auxv | HWCAP_PMULL;
++  for (i = 0; &cpu_partsp[i] != nullptr; i++) {
++    if (cpu_partsp[i].part_id == 0 ||
++      strcmp(part_name, cpu_partsp[i].part_name) == 0) {
++      _model = cpu_partsp[i].part_id;
++      break;
++    }
+   }
+ 
+-  if (ID_AA64ISAR0_SHA1_VAL(id_aa64isar0) == ID_AA64ISAR0_SHA1_BASE) {
+-    auxv = auxv | HWCAP_SHA1;
+-  }
++  sscanf(rv_str, "r%up%u", &_variant, &_revision);
++}
++#endif // __OpenBSD__
+ 
+-  if (ID_AA64ISAR0_SHA2_VAL(id_aa64isar0) == ID_AA64ISAR0_SHA2_BASE) {
+-    auxv = auxv | HWCAP_SHA2;
+-  }
++unsigned long VM_Version::os_get_processor_features() {
++  unsigned long auxv = 0;
+ 
+-  if (ID_AA64ISAR0_CRC32_VAL(id_aa64isar0) == ID_AA64ISAR0_CRC32_BASE) {
+-    auxv = auxv | HWCAP_CRC32;
+-  }
++#if defined(__FreeBSD__) || defined(__OpenBSD__)
++  /*
++   * Step 1: setup _features using elf_aux_info(3). Keep in sync with Linux.
++   */
++  elf_aux_info(AT_HWCAP, &auxv, sizeof(auxv));
+ 
+-  if (ID_AA64PFR0_AdvSIMD(id_aa64pfr0) == ID_AA64PFR0_AdvSIMD_IMPL || \
+-      ID_AA64PFR0_AdvSIMD(id_aa64pfr0) == ID_AA64PFR0_AdvSIMD_HP ) {
+-    auxv = auxv | HWCAP_ASIMD;
++  /*
++   * Step 2: setup _cpu, _model, _variant and _revision using READ_SPECIALREG on
++   * midr_el1 if allowed. On OpenBSD fallback to sysctl hw.model and lookup from
++   * tables.
++   */
++#ifdef __FreeBSD__
++  uint32_t midr = READ_SPECIALREG(midr_el1);
++  _cpu = CPU_IMPL(midr);
++  _model = CPU_PART(midr);
++  _variant = CPU_VAR(midr);
++  _revision = CPU_REV(midr);
++#else
++  /* On OpenBSD READ_SPECIALREG is only available if HWCAP_CPUID is set */
++  if (auxv & HWCAP_CPUID) {
++    uint32_t midr = READ_SPECIALREG(midr_el1);
++    _cpu = CPU_IMPL(midr);
++    _model = CPU_PART(midr);
++    _variant = CPU_VAR(midr);
++    _revision = CPU_REV(midr);
++  } else {
++    lookup_cpu(_cpu, _model, _variant, _revision);
+   }
++#endif // __FreeBSD__
++#endif // __FreeBSD__ || __OpenBSD__
+ 
+   return auxv;
+ }
+-#endif
Index: 11/Makefile
===================================================================
RCS file: /cvs/ports/devel/jdk/11/Makefile,v
diff -u -p -u -r1.67 Makefile
--- 11/Makefile	5 Dec 2025 22:00:14 -0000	1.67
+++ 11/Makefile	16 Dec 2025 19:33:50 -0000
@@ -12,7 +12,7 @@ PACKAGE_VER=	${BASE_VER}.${PATCH_VER}.${
 PKGNAME=	jdk-${PACKAGE_VER}
 PKGSTEM=	jdk-11
 EPOCH=		0
-REVISION=	0
+REVISION=	1
 
 DIST_SUBDIR=	jdk
 DISTNAME=	jdk-${VERSION_STR}
Index: 11/patches/patch-src_hotspot_os_cpu_bsd_aarch64_vm_version_bsd_aarch64_cpp
===================================================================
RCS file: 11/patches/patch-src_hotspot_os_cpu_bsd_aarch64_vm_version_bsd_aarch64_cpp
diff -N 11/patches/patch-src_hotspot_os_cpu_bsd_aarch64_vm_version_bsd_aarch64_cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 11/patches/patch-src_hotspot_os_cpu_bsd_aarch64_vm_version_bsd_aarch64_cpp	16 Dec 2025 19:33:50 -0000
@@ -0,0 +1,533 @@
+Get hardware capablilites using elf_aux_info(3).
+Detect CPU, model, variant and revision using READ_SPECIALREG
+when HWCAP_CPUID is set, otherwise parse sysctl hw.model to
+get needed info.
+
+Index: src/hotspot/os_cpu/bsd_aarch64/vm_version_bsd_aarch64.cpp
+--- src/hotspot/os_cpu/bsd_aarch64/vm_version_bsd_aarch64.cpp.orig
++++ src/hotspot/os_cpu/bsd_aarch64/vm_version_bsd_aarch64.cpp
+@@ -90,93 +90,85 @@ bool VM_Version::is_cpu_emulated() {
+ #else // __APPLE__
+ 
+ #include "vm_version_aarch64.hpp"
+-
+ #include <machine/armreg.h>
+-#if defined (__FreeBSD__)
+-#include <machine/elf.h>
++#if defined (__FreeBSD__) || defined (__OpenBSD__)
++#include <sys/auxv.h>
+ #endif
+ 
+-#ifndef HWCAP_ASIMD
+-#define HWCAP_ASIMD (1<<1)
+-#endif
++#define	CPU_IMPL(midr)	(((midr) >> 24) & 0xff)
++#define	CPU_PART(midr)	(((midr) >> 4) & 0xfff)
++#define	CPU_VAR(midr)	(((midr) >> 20) & 0xf)
++#define	CPU_REV(midr)	(((midr) >> 0) & 0xf)
+ 
+-#ifndef HWCAP_AES
+-#define HWCAP_AES   (1<<3)
+-#endif
++#ifdef __OpenBSD__
++// For older processors on OpenBSD READ_SPECIALREG is not supported.
++// These constants and tables allow for looking up the cpu and model.
+ 
+-#ifndef HWCAP_PMULL
+-#define HWCAP_PMULL (1<<4)
+-#endif
++#include <sys/types.h>
++#include <sys/sysctl.h>
++#include <string.h>
++#include <stdio.h>
+ 
+-#ifndef HWCAP_SHA1
+-#define HWCAP_SHA1  (1<<5)
+-#endif
+-
+-#ifndef HWCAP_SHA2
+-#define HWCAP_SHA2  (1<<6)
+-#endif
+-
+-#ifndef HWCAP_CRC32
+-#define HWCAP_CRC32 (1<<7)
+-#endif
+-
+-#ifndef HWCAP_ATOMICS
+-#define HWCAP_ATOMICS (1<<8)
+-#endif
+-
+-#ifndef ID_AA64PFR0_AdvSIMD_SHIFT
+-#define ID_AA64PFR0_AdvSIMD_SHIFT 20
+-#endif
+-
+-#ifndef ID_AA64PFR0_AdvSIMD
+-#define ID_AA64PFR0_AdvSIMD(x) ((x) & (UL(0xf) << ID_AA64PFR0_AdvSIMD_SHIFT))
+-#endif
+-
+-#ifndef ID_AA64PFR0_AdvSIMD_IMPL
+-#define ID_AA64PFR0_AdvSIMD_IMPL (UL(0x0) << ID_AA64PFR0_AdvSIMD_SHIFT)
+-#endif
+-
+-#ifndef ID_AA64PFR0_AdvSIMD_HP
+-#define ID_AA64PFR0_AdvSIMD_HP (UL(0x1) << ID_AA64PFR0_AdvSIMD_SHIFT)
+-#endif
+-
+-#ifndef ID_AA64ISAR0_AES_VAL
+-#define ID_AA64ISAR0_AES_VAL ID_AA64ISAR0_AES
+-#endif
+-
+-#ifndef ID_AA64ISAR0_SHA1_VAL
+-#define ID_AA64ISAR0_SHA1_VAL ID_AA64ISAR0_SHA1
+-#endif
+-
+-#ifndef ID_AA64ISAR0_SHA2_VAL
+-#define ID_AA64ISAR0_SHA2_VAL ID_AA64ISAR0_SHA2
+-#endif
+-
+-#ifndef ID_AA64ISAR0_CRC32_VAL
+-#define ID_AA64ISAR0_CRC32_VAL ID_AA64ISAR0_CRC32
+-#endif
+-
+ #define	CPU_IMPL_ARM		0x41
+ #define	CPU_IMPL_BROADCOM	0x42
+ #define	CPU_IMPL_CAVIUM		0x43
+ #define	CPU_IMPL_DEC		0x44
++#define	CPU_IMPL_FUJITSU	0x46
++#define	CPU_IMPL_HISILICON	0x48
+ #define	CPU_IMPL_INFINEON	0x49
+ #define	CPU_IMPL_FREESCALE	0x4D
+ #define	CPU_IMPL_NVIDIA		0x4E
+ #define	CPU_IMPL_APM		0x50
+ #define	CPU_IMPL_QUALCOMM	0x51
+ #define	CPU_IMPL_MARVELL	0x56
++#define	CPU_IMPL_APPLE		0x61
+ #define	CPU_IMPL_INTEL		0x69
++#define	CPU_IMPL_AMPERE		0xC0
++#define	CPU_IMPL_MICROSOFT	0x6D
+ 
+ /* ARM Part numbers */
+ #define	CPU_PART_FOUNDATION	0xD00
+-#define	CPU_PART_CORTEX_A35	0xD04
++#define	CPU_PART_CORTEX_A34	0xD02
+ #define	CPU_PART_CORTEX_A53	0xD03
++#define	CPU_PART_CORTEX_A35	0xD04
+ #define	CPU_PART_CORTEX_A55	0xD05
++#define	CPU_PART_CORTEX_A65	0xD06
+ #define	CPU_PART_CORTEX_A57	0xD07
+ #define	CPU_PART_CORTEX_A72	0xD08
+ #define	CPU_PART_CORTEX_A73	0xD09
+ #define	CPU_PART_CORTEX_A75	0xD0A
++#define	CPU_PART_CORTEX_A76	0xD0B
++#define	CPU_PART_NEOVERSE_N1	0xD0C
++#define	CPU_PART_CORTEX_A77	0xD0D
++#define	CPU_PART_CORTEX_A76AE	0xD0E
++#define	CPU_PART_AEM_V8		0xD0F
++#define	CPU_PART_NEOVERSE_V1	0xD40
++#define	CPU_PART_CORTEX_A78	0xD41
++#define	CPU_PART_CORTEX_A78AE	0xD42
++#define	CPU_PART_CORTEX_A65AE	0xD43
++#define	CPU_PART_CORTEX_X1	0xD44
++#define	CPU_PART_CORTEX_A510	0xD46
++#define	CPU_PART_CORTEX_A710	0xD47
++#define	CPU_PART_CORTEX_X2	0xD48
++#define	CPU_PART_NEOVERSE_N2	0xD49
++#define	CPU_PART_NEOVERSE_E1	0xD4A
++#define	CPU_PART_CORTEX_A78C	0xD4B
++#define	CPU_PART_CORTEX_X1C	0xD4C
++#define	CPU_PART_CORTEX_A715	0xD4D
++#define	CPU_PART_CORTEX_X3	0xD4E
++#define	CPU_PART_NEOVERSE_V2	0xD4F
++#define	CPU_PART_CORTEX_A520	0xD80
++#define	CPU_PART_CORTEX_A720	0xD81
++#define	CPU_PART_CORTEX_X4	0xD82
++#define	CPU_PART_NEOVERSE_V3AE	0xD83
++#define	CPU_PART_NEOVERSE_V3	0xD84
++#define	CPU_PART_CORTEX_X925	0xD85
++#define	CPU_PART_CORTEX_A725	0xD87
++#define	CPU_PART_C1_NANO	0xD8A
++#define	CPU_PART_C1_PRO		0xD8B
++#define	CPU_PART_C1_ULTRA	0xD8C
++#define	CPU_PART_NEOVERSE_N3	0xD8E
++#define	CPU_PART_C1_PREMIUM	0xD90
+ 
+ /* Cavium Part numbers */
+ #define	CPU_PART_THUNDERX	0x0A1
+@@ -189,21 +181,35 @@ bool VM_Version::is_cpu_emulated() {
+ 
+ #define	CPU_REV_THUNDERX2_0	0x00
+ 
+-#define	CPU_IMPL(midr)	(((midr) >> 24) & 0xff)
+-#define	CPU_PART(midr)	(((midr) >> 4) & 0xfff)
+-#define	CPU_VAR(midr)	(((midr) >> 20) & 0xf)
+-#define	CPU_REV(midr)	(((midr) >> 0) & 0xf)
+-#define UL(x)   UINT64_C(x)
++/* APM (now Ampere) Part number */
++#define CPU_PART_EMAG8180	0x000
+ 
+-struct cpu_desc {
+-	u_int		cpu_impl;
+-	u_int		cpu_part_num;
+-	u_int		cpu_variant;
+-	u_int		cpu_revision;
+-	const char	*cpu_impl_name;
+-	const char	*cpu_part_name;
+-};
++/* Ampere Part numbers */
++#define	CPU_PART_AMPERE1	0xAC3
++#define	CPU_PART_AMPERE1A	0xAC4
+ 
++/* Microsoft Part numbers */
++#define	CPU_PART_AZURE_COBALT_100	0xD49
++
++/* Qualcomm */
++#define CPU_PART_ORYON          0x001
++#define	CPU_PART_KRYO400_GOLD	0x804
++#define	CPU_PART_KRYO400_SILVER	0x805
++
++/* Apple part numbers */
++#define CPU_PART_M1_ICESTORM      0x022
++#define CPU_PART_M1_FIRESTORM     0x023
++#define CPU_PART_M1_ICESTORM_PRO  0x024
++#define CPU_PART_M1_FIRESTORM_PRO 0x025
++#define CPU_PART_M1_ICESTORM_MAX  0x028
++#define CPU_PART_M1_FIRESTORM_MAX 0x029
++#define CPU_PART_M2_BLIZZARD      0x032
++#define CPU_PART_M2_AVALANCHE     0x033
++#define CPU_PART_M2_BLIZZARD_PRO  0x034
++#define CPU_PART_M2_AVALANCHE_PRO 0x035
++#define CPU_PART_M2_BLIZZARD_MAX  0x038
++#define CPU_PART_M2_AVALANCHE_MAX 0x039
++
+ struct cpu_parts {
+ 	u_int		part_id;
+ 	const char	*part_name;
+@@ -224,136 +230,203 @@ struct cpu_implementers {
+ /*
+  * Per-implementer table of (PartNum, CPU Name) pairs.
+  */
+-/* ARM Ltd. */
++/* ARM Ltd. From FreeBSD but using OpenBSD strings */
+ static const struct cpu_parts cpu_parts_arm[] = {
++	{ CPU_PART_AEM_V8, "AEMv8" },
+ 	{ CPU_PART_FOUNDATION, "Foundation-Model" },
++	{ CPU_PART_CORTEX_A34, "Cortex-A34" },
+ 	{ CPU_PART_CORTEX_A35, "Cortex-A35" },
+ 	{ CPU_PART_CORTEX_A53, "Cortex-A53" },
+ 	{ CPU_PART_CORTEX_A55, "Cortex-A55" },
+ 	{ CPU_PART_CORTEX_A57, "Cortex-A57" },
++	{ CPU_PART_CORTEX_A65, "Cortex-A65" },
++	{ CPU_PART_CORTEX_A65AE, "Cortex-A65AE" },
+ 	{ CPU_PART_CORTEX_A72, "Cortex-A72" },
+ 	{ CPU_PART_CORTEX_A73, "Cortex-A73" },
+ 	{ CPU_PART_CORTEX_A75, "Cortex-A75" },
++	{ CPU_PART_CORTEX_A76, "Cortex-A76" },
++	{ CPU_PART_CORTEX_A76AE, "Cortex-A76AE" },
++	{ CPU_PART_CORTEX_A77, "Cortex-A77" },
++	{ CPU_PART_CORTEX_A78, "Cortex-A78" },
++	{ CPU_PART_CORTEX_A78AE, "Cortex-A78AE" },
++	{ CPU_PART_CORTEX_A78C, "Cortex-A78C" },
++	{ CPU_PART_CORTEX_A510, "Cortex-A510" },
++	{ CPU_PART_CORTEX_A520, "Cortex-A520" },
++	{ CPU_PART_CORTEX_A710, "Cortex-A710" },
++	{ CPU_PART_CORTEX_A715, "Cortex-A715" },
++	{ CPU_PART_CORTEX_A720, "Cortex-A720" },
++	{ CPU_PART_CORTEX_A725, "Cortex-A725" },
++	{ CPU_PART_CORTEX_X925, "Cortex-A925" },
++	{ CPU_PART_CORTEX_X1C, "Cortex-X1C" },
++	{ CPU_PART_CORTEX_X1, "Cortex-X1" },
++	{ CPU_PART_CORTEX_X2, "Cortex-X2" },
++	{ CPU_PART_CORTEX_X3, "Cortex-X3" },
++	{ CPU_PART_CORTEX_X4, "Cortex-X4" },
++	{ CPU_PART_C1_NANO, "C1-Nano" },
++	{ CPU_PART_C1_PRO, "C1-Pro" },
++	{ CPU_PART_C1_PREMIUM, "C1-Premium" },
++	{ CPU_PART_C1_ULTRA, "C1-Ultra" },
++	{ CPU_PART_NEOVERSE_E1, "Neoverse E1" },
++	{ CPU_PART_NEOVERSE_N1, "Neoverse N1" },
++	{ CPU_PART_NEOVERSE_N2, "Neoverse N2" },
++	{ CPU_PART_NEOVERSE_N3, "Neoverse N3" },
++	{ CPU_PART_NEOVERSE_V1, "Neoverse V1" },
++	{ CPU_PART_NEOVERSE_V2, "Neoverse V2" },
++	{ CPU_PART_NEOVERSE_V3, "Neoverse V3" },
++	{ CPU_PART_NEOVERSE_V3AE, "Neoverse V3AE" },
+ 	CPU_PART_NONE,
+ };
+-/* Cavium */
++
++/* Cavium  From FreeBSD but using OpenBSD strings */
+ static const struct cpu_parts cpu_parts_cavium[] = {
+-	{ CPU_PART_THUNDERX, "ThunderX" },
+-	{ CPU_PART_THUNDERX2, "ThunderX2" },
++	{ CPU_PART_THUNDERX, "ThunderX T88" },
++	{ CPU_PART_THUNDERX_81XX, "ThunderX T81" },
++	{ CPU_PART_THUNDERX_83XX, "ThunderX T83" },
++	{ CPU_PART_THUNDERX2, "ThunderX2 T99" },
+ 	CPU_PART_NONE,
+ };
+ 
++/* APM (now Ampere), From FreeBSD but using OpenBSD strings */
++static const struct cpu_parts cpu_parts_apm[] = {
++	{ CPU_PART_EMAG8180, "X-Gene" },
++	CPU_PART_NONE,
++};
++
++/* Ampere From FreeBSD, but using OpenBSD strings */
++static const struct cpu_parts cpu_parts_ampere[] = {
++	{ CPU_PART_AMPERE1A, "AmpereOne AC04" },
++	{ CPU_PART_AMPERE1, "AmpereOne" },
++	CPU_PART_NONE,
++};
++
++/* Microsoft */
++static const struct cpu_parts cpu_parts_microsoft[] = {
++	{ CPU_PART_AZURE_COBALT_100, "Azure Cobalt 100" },
++	CPU_PART_NONE,
++};
++
++/* Qualcomm From FreeBSD & OpenBSD. */
++static const struct cpu_parts cpu_parts_qcom[] = {
++	{ CPU_PART_KRYO400_GOLD, "Kryo 400 Gold" },
++	{ CPU_PART_KRYO400_SILVER, "Kryo 400 Silver" },
++	{ CPU_PART_ORYON, "Oryon" },
++	CPU_PART_NONE,
++};
++
++/* Apple. From FreeBSD but using OpenBSD strings */
++static const struct cpu_parts cpu_parts_apple[] = {
++	{ CPU_PART_M1_ICESTORM, "Icestorm" },
++	{ CPU_PART_M1_FIRESTORM, "Firestorm" },
++	{ CPU_PART_M1_ICESTORM_PRO, "Icestorm Pro" },
++	{ CPU_PART_M1_FIRESTORM_PRO, "Firestorm Pro" },
++	{ CPU_PART_M1_ICESTORM_MAX, "Icestorm Max" },
++	{ CPU_PART_M1_FIRESTORM_MAX, "Firestorm Max" },
++	{ CPU_PART_M2_BLIZZARD, "Blizzard" },
++	{ CPU_PART_M2_AVALANCHE, "Avalanche" },
++	{ CPU_PART_M2_BLIZZARD_PRO, "Blizzard Pro" },
++	{ CPU_PART_M2_AVALANCHE_PRO, "Avalanche Pro" },
++	{ CPU_PART_M2_BLIZZARD_MAX, "Blizzard Max" },
++	{ CPU_PART_M2_AVALANCHE_MAX, "Avalanche Max" },
++	CPU_PART_NONE,
++};
++
+ /* Unknown */
+ static const struct cpu_parts cpu_parts_none[] = {
+ 	CPU_PART_NONE,
+ };
+ 
+ /*
+- * Implementers table.
++ * Implementers table. From FreeBSD, but using OpenBSD strings
+  */
+ const struct cpu_implementers cpu_implementers[] = {
++	{ CPU_IMPL_AMPERE,	"Ampere",	cpu_parts_ampere },
++	{ CPU_IMPL_APPLE,	"Apple",	cpu_parts_apple },
++	{ CPU_IMPL_APM,		"Applied Micro",cpu_parts_apm },
+ 	{ CPU_IMPL_ARM,		"ARM",		cpu_parts_arm },
+ 	{ CPU_IMPL_BROADCOM,	"Broadcom",	cpu_parts_none },
+ 	{ CPU_IMPL_CAVIUM,	"Cavium",	cpu_parts_cavium },
+ 	{ CPU_IMPL_DEC,		"DEC",		cpu_parts_none },
+-	{ CPU_IMPL_INFINEON,	"IFX",		cpu_parts_none },
+ 	{ CPU_IMPL_FREESCALE,	"Freescale",	cpu_parts_none },
+-	{ CPU_IMPL_NVIDIA,	"NVIDIA",	cpu_parts_none },
+-	{ CPU_IMPL_APM,		"APM",		cpu_parts_none },
+-	{ CPU_IMPL_QUALCOMM,	"Qualcomm",	cpu_parts_none },
+-	{ CPU_IMPL_MARVELL,	"Marvell",	cpu_parts_none },
++	{ CPU_IMPL_FUJITSU,	"Fujitsu",	cpu_parts_none },
++	{ CPU_IMPL_HISILICON,	"HiSilicon",	cpu_parts_none },
++	{ CPU_IMPL_INFINEON,	"IFX",		cpu_parts_none },
+ 	{ CPU_IMPL_INTEL,	"Intel",	cpu_parts_none },
++	{ CPU_IMPL_MARVELL,	"Marvell",	cpu_parts_none },
++	{ CPU_IMPL_MICROSOFT,	"Microsoft",	cpu_parts_microsoft },
++	{ CPU_IMPL_NVIDIA,	"NVIDIA",	cpu_parts_none },
++	{ CPU_IMPL_QUALCOMM,	"Qualcomm",	cpu_parts_qcom },
+ 	CPU_IMPLEMENTER_NONE,
+ };
+ 
+-#ifdef __FreeBSD__
+-static unsigned long os_get_processor_features() {
+-  unsigned long auxv = 0;
+-  uint64_t id_aa64isar0, id_aa64pfr0;
++static void
++lookup_cpu(int &_cpu, int &_model, int &_variant, int &_revision) {
++  int mib[] = { CTL_HW, HW_MODEL };
++  char descr[BUFSIZ];
++  char *part_name, *rv_str;
++  size_t descr_len = sizeof(descr);
++  size_t impl_name_len;
++  const struct cpu_parts *cpu_partsp = nullptr;
++  size_t i;
+ 
+-  id_aa64isar0 = READ_SPECIALREG(id_aa64isar0_el1);
+-  id_aa64pfr0 = READ_SPECIALREG(id_aa64pfr0_el1);
++  if (sysctl(mib, nitems(mib), &descr, &descr_len, NULL, 0) == -1)
++    return;
+ 
+-  if (ID_AA64ISAR0_AES_VAL(id_aa64isar0) == ID_AA64ISAR0_AES_BASE) {
+-    auxv = auxv | HWCAP_AES;
++  for (i = 0; i < nitems(cpu_implementers); i++) {
++    impl_name_len = strlen(cpu_implementers[i].impl_name);
++    if (cpu_implementers[i].impl_id == 0 ||
++      strncmp(descr, cpu_implementers[i].impl_name, impl_name_len) == 0) {
++      _cpu = cpu_implementers[i].impl_id;
++      cpu_partsp = cpu_implementers[i].cpu_parts;
++      break;
++    }
+   }
+ 
+-  if (ID_AA64ISAR0_AES_VAL(id_aa64isar0) == ID_AA64ISAR0_AES_PMULL) {
+-    auxv = auxv | HWCAP_PMULL;
+-  }
++  if (_cpu == 0)
++    return;
+ 
+-  if (ID_AA64ISAR0_SHA1_VAL(id_aa64isar0) == ID_AA64ISAR0_SHA1_BASE) {
+-    auxv = auxv | HWCAP_SHA1;
+-  }
++  // +1 to skip space +1 more because descr_len includes NUL
++  if (impl_name_len + 2 > descr_len)
++    return;
+ 
+-  if (ID_AA64ISAR0_SHA2_VAL(id_aa64isar0) == ID_AA64ISAR0_SHA2_BASE) {
+-    auxv = auxv | HWCAP_SHA2;
+-  }
++  part_name = &descr[impl_name_len+1];
+ 
+-  if (ID_AA64ISAR0_CRC32_VAL(id_aa64isar0) == ID_AA64ISAR0_CRC32_BASE) {
+-    auxv = auxv | HWCAP_CRC32;
+-  }
++  rv_str = strrchr(part_name, ' ');
++  if (rv_str == nullptr)
++    return;
+ 
+-  if (ID_AA64PFR0_AdvSIMD(id_aa64pfr0) == ID_AA64PFR0_AdvSIMD_IMPL || \
+-      ID_AA64PFR0_AdvSIMD(id_aa64pfr0) == ID_AA64PFR0_AdvSIMD_HP ) {
+-    auxv = auxv | HWCAP_ASIMD;
+-  }
++  // null term part_name and skip over it
++  *(rv_str++) = '\0';
+ 
+-  return auxv;
+-}
+-#endif
+-
+-void VM_Version::get_os_cpu_info() {
+-#if defined(__OpenBSD__) || defined(__NetBSD__)
+-  // READ_SPECIALREG is not available from userland on OpenBSD.
+-  // Hardcode these values to the "lowest common denominator"
+-  _cpu = CPU_IMPL_ARM;
+-  _model = CPU_PART_CORTEX_A53;
+-  _variant = 0;
+-  _revision = 0;
+-  _features = HWCAP_ASIMD;
+-#elif defined(__FreeBSD__)
+-  struct cpu_desc cpu_desc[1];
+-  struct cpu_desc user_cpu_desc;
+-
+-  uint32_t midr;
+-  uint32_t impl_id;
+-  uint32_t part_id;
+-  uint32_t cpu = 0;
+-  size_t i;
+-  const struct cpu_parts *cpu_partsp = NULL;
+-
+-  midr = READ_SPECIALREG(midr_el1);
+-
+-  impl_id = CPU_IMPL(midr);
+-  for (i = 0; i < nitems(cpu_implementers); i++) {
+-    if (impl_id == cpu_implementers[i].impl_id ||
+-      cpu_implementers[i].impl_id == 0) {
+-      cpu_desc[cpu].cpu_impl = impl_id;
+-      cpu_desc[cpu].cpu_impl_name = cpu_implementers[i].impl_name;
+-      cpu_partsp = cpu_implementers[i].cpu_parts;
++  for (i = 0; &cpu_partsp[i] != nullptr; i++) {
++    if (cpu_partsp[i].part_id == 0 ||
++      strcmp(part_name, cpu_partsp[i].part_name) == 0) {
++      _model = cpu_partsp[i].part_id;
+       break;
+     }
+   }
+-  part_id = CPU_PART(midr);
+-  for (i = 0; &cpu_partsp[i] != NULL; i++) {
+-    if (part_id == cpu_partsp[i].part_id || cpu_partsp[i].part_id == 0) {
+-      cpu_desc[cpu].cpu_part_num = part_id;
+-      cpu_desc[cpu].cpu_part_name = cpu_partsp[i].part_name;
+-      break;
+-    }
+-  }
+ 
+-  cpu_desc[cpu].cpu_revision = CPU_REV(midr);
+-  cpu_desc[cpu].cpu_variant = CPU_VAR(midr);
++  sscanf(rv_str, "r%up%u", &_variant, &_revision);
++}
++#endif // __OpenBSD__
+ 
+-  _cpu = cpu_desc[cpu].cpu_impl;
+-  _variant = cpu_desc[cpu].cpu_variant;
+-  _model = cpu_desc[cpu].cpu_part_num;
+-  _revision = cpu_desc[cpu].cpu_revision;
++void VM_Version::get_os_cpu_info() {
++#if defined(__FreeBSD__) || defined(__OpenBSD__)
+ 
+-  uint64_t auxv = os_get_processor_features();
++  /*
++   * Step 1: setup _features using elf_aux_info(3). Keep in sync with Linux.
++   */
++  unsigned long auxv = 0;
++  elf_aux_info(AT_HWCAP, &auxv, sizeof(auxv));
+ 
++  STATIC_ASSERT(CPU_FP      == HWCAP_FP);
++  STATIC_ASSERT(CPU_ASIMD   == HWCAP_ASIMD);
++  STATIC_ASSERT(CPU_EVTSTRM == HWCAP_EVTSTRM);
++  STATIC_ASSERT(CPU_AES     == HWCAP_AES);
++  STATIC_ASSERT(CPU_PMULL   == HWCAP_PMULL);
++  STATIC_ASSERT(CPU_SHA1    == HWCAP_SHA1);
++  STATIC_ASSERT(CPU_SHA2    == HWCAP_SHA2);
++  STATIC_ASSERT(CPU_CRC32   == HWCAP_CRC32);
++  STATIC_ASSERT(CPU_LSE     == HWCAP_ATOMICS);
+   _features = auxv & (
+       HWCAP_FP      |
+       HWCAP_ASIMD   |
+@@ -363,13 +436,36 @@ void VM_Version::get_os_cpu_info() {
+       HWCAP_SHA1    |
+       HWCAP_SHA2    |
+       HWCAP_CRC32   |
+-      HWCAP_ATOMICS |
+-      HWCAP_DCPOP   |
+-      HWCAP_SHA3    |
+-      HWCAP_SHA512  |
+-      HWCAP_SVE);
+-#endif
++      HWCAP_ATOMICS);
+ 
++  /*
++   * Step 2: setup _cpu, _model, _variant and _revision using READ_SPECIALREG on
++   * midr_el1 if allowed. On OpenBSD fallback to sysctl hw.model and lookup from
++   * tables.
++   */
++#ifdef __FreeBSD__
++  uint32_t midr = READ_SPECIALREG(midr_el1);
++  _cpu = CPU_IMPL(midr);
++  _model = CPU_PART(midr);
++  _variant = CPU_VAR(midr);
++  _revision = CPU_REV(midr);
++#else
++  /* On OpenBSD READ_SPECIALREG is only available if HWCAP_CPUID is set */
++  if (auxv & HWCAP_CPUID) {
++    uint32_t midr = READ_SPECIALREG(midr_el1);
++    _cpu = CPU_IMPL(midr);
++    _model = CPU_PART(midr);
++    _variant = CPU_VAR(midr);
++    _revision = CPU_REV(midr);
++  } else {
++    lookup_cpu(_cpu, _model, _variant, _revision);
++  }
++#endif // __FreeBSD__
++#endif // __FreeBSD__ || __OpenBSD__
++
++  /*
++   * Step 3: Get cache line sizes and _zva_length using same approach as Linux.
++   */
+   uint64_t ctr_el0;
+   uint64_t dczid_el0;
+   __asm__ (
Index: 17/Makefile
===================================================================
RCS file: /cvs/ports/devel/jdk/17/Makefile,v
diff -u -p -u -r1.36 Makefile
--- 17/Makefile	3 Nov 2025 13:44:13 -0000	1.36
+++ 17/Makefile	16 Dec 2025 19:33:50 -0000
@@ -12,6 +12,7 @@ PACKAGE_VER=	${BASE_VER}.${PATCH_VER}.${
 PKGNAME=	jdk-${PACKAGE_VER}
 PKGSTEM=	jdk-17
 EPOCH=		0
+REVISION=	0
 
 DIST_SUBDIR=	jdk
 DISTNAME=	jdk-${VERSION_STR}
Index: 17/patches/patch-src_hotspot_os_cpu_bsd_aarch64_vm_version_bsd_aarch64_cpp
===================================================================
RCS file: 17/patches/patch-src_hotspot_os_cpu_bsd_aarch64_vm_version_bsd_aarch64_cpp
diff -N 17/patches/patch-src_hotspot_os_cpu_bsd_aarch64_vm_version_bsd_aarch64_cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 17/patches/patch-src_hotspot_os_cpu_bsd_aarch64_vm_version_bsd_aarch64_cpp	16 Dec 2025 19:33:50 -0000
@@ -0,0 +1,533 @@
+Get hardware capablilites using elf_aux_info(3).
+Detect CPU, model, variant and revision using READ_SPECIALREG
+when HWCAP_CPUID is set, otherwise parse sysctl hw.model to
+get needed info.
+
+Index: src/hotspot/os_cpu/bsd_aarch64/vm_version_bsd_aarch64.cpp
+--- src/hotspot/os_cpu/bsd_aarch64/vm_version_bsd_aarch64.cpp.orig
++++ src/hotspot/os_cpu/bsd_aarch64/vm_version_bsd_aarch64.cpp
+@@ -104,91 +104,84 @@ bool VM_Version::is_cpu_emulated() {
+ #else // __APPLE__
+ 
+ #include <machine/armreg.h>
+-#if defined (__FreeBSD__)
+-#include <machine/elf.h>
++#if defined (__FreeBSD__) || defined (__OpenBSD__)
++#include <sys/auxv.h>
+ #endif
+ 
+-#ifndef HWCAP_ASIMD
+-#define HWCAP_ASIMD (1<<1)
+-#endif
++#define	CPU_IMPL(midr)	(((midr) >> 24) & 0xff)
++#define	CPU_PART(midr)	(((midr) >> 4) & 0xfff)
++#define	CPU_VAR(midr)	(((midr) >> 20) & 0xf)
++#define	CPU_REV(midr)	(((midr) >> 0) & 0xf)
+ 
+-#ifndef HWCAP_AES
+-#define HWCAP_AES   (1<<3)
+-#endif
++#ifdef __OpenBSD__
++// For older processors on OpenBSD READ_SPECIALREG is not supported.
++// These constants and tables allow for looking up the cpu and model.
+ 
+-#ifndef HWCAP_PMULL
+-#define HWCAP_PMULL (1<<4)
+-#endif
++#include <sys/types.h>
++#include <sys/sysctl.h>
++#include <string.h>
++#include <stdio.h>
+ 
+-#ifndef HWCAP_SHA1
+-#define HWCAP_SHA1  (1<<5)
+-#endif
+-
+-#ifndef HWCAP_SHA2
+-#define HWCAP_SHA2  (1<<6)
+-#endif
+-
+-#ifndef HWCAP_CRC32
+-#define HWCAP_CRC32 (1<<7)
+-#endif
+-
+-#ifndef HWCAP_ATOMICS
+-#define HWCAP_ATOMICS (1<<8)
+-#endif
+-
+-#ifndef ID_AA64PFR0_AdvSIMD_SHIFT
+-#define ID_AA64PFR0_AdvSIMD_SHIFT 20
+-#endif
+-
+-#ifndef ID_AA64PFR0_AdvSIMD
+-#define ID_AA64PFR0_AdvSIMD(x) ((x) & (UL(0xf) << ID_AA64PFR0_AdvSIMD_SHIFT))
+-#endif
+-
+-#ifndef ID_AA64PFR0_AdvSIMD_IMPL
+-#define ID_AA64PFR0_AdvSIMD_IMPL (UL(0x0) << ID_AA64PFR0_AdvSIMD_SHIFT)
+-#endif
+-
+-#ifndef ID_AA64PFR0_AdvSIMD_HP
+-#define ID_AA64PFR0_AdvSIMD_HP (UL(0x1) << ID_AA64PFR0_AdvSIMD_SHIFT)
+-#endif
+-
+-#ifndef ID_AA64ISAR0_AES_VAL
+-#define ID_AA64ISAR0_AES_VAL ID_AA64ISAR0_AES
+-#endif
+-
+-#ifndef ID_AA64ISAR0_SHA1_VAL
+-#define ID_AA64ISAR0_SHA1_VAL ID_AA64ISAR0_SHA1
+-#endif
+-
+-#ifndef ID_AA64ISAR0_SHA2_VAL
+-#define ID_AA64ISAR0_SHA2_VAL ID_AA64ISAR0_SHA2
+-#endif
+-
+-#ifndef ID_AA64ISAR0_CRC32_VAL
+-#define ID_AA64ISAR0_CRC32_VAL ID_AA64ISAR0_CRC32
+-#endif
+-
+ #define	CPU_IMPL_ARM		0x41
+ #define	CPU_IMPL_BROADCOM	0x42
+ #define	CPU_IMPL_CAVIUM		0x43
+ #define	CPU_IMPL_DEC		0x44
++#define	CPU_IMPL_FUJITSU	0x46
++#define	CPU_IMPL_HISILICON	0x48
+ #define	CPU_IMPL_INFINEON	0x49
+ #define	CPU_IMPL_FREESCALE	0x4D
+ #define	CPU_IMPL_NVIDIA		0x4E
+ #define	CPU_IMPL_APM		0x50
+ #define	CPU_IMPL_QUALCOMM	0x51
+ #define	CPU_IMPL_MARVELL	0x56
++#define	CPU_IMPL_APPLE		0x61
+ #define	CPU_IMPL_INTEL		0x69
++#define	CPU_IMPL_AMPERE		0xC0
++#define	CPU_IMPL_MICROSOFT	0x6D
+ 
+ /* ARM Part numbers */
+ #define	CPU_PART_FOUNDATION	0xD00
+-#define	CPU_PART_CORTEX_A35	0xD04
++#define	CPU_PART_CORTEX_A34	0xD02
+ #define	CPU_PART_CORTEX_A53	0xD03
++#define	CPU_PART_CORTEX_A35	0xD04
+ #define	CPU_PART_CORTEX_A55	0xD05
++#define	CPU_PART_CORTEX_A65	0xD06
+ #define	CPU_PART_CORTEX_A57	0xD07
+ #define	CPU_PART_CORTEX_A72	0xD08
+ #define	CPU_PART_CORTEX_A73	0xD09
+ #define	CPU_PART_CORTEX_A75	0xD0A
++#define	CPU_PART_CORTEX_A76	0xD0B
++#define	CPU_PART_NEOVERSE_N1	0xD0C
++#define	CPU_PART_CORTEX_A77	0xD0D
++#define	CPU_PART_CORTEX_A76AE	0xD0E
++#define	CPU_PART_AEM_V8		0xD0F
++#define	CPU_PART_NEOVERSE_V1	0xD40
++#define	CPU_PART_CORTEX_A78	0xD41
++#define	CPU_PART_CORTEX_A78AE	0xD42
++#define	CPU_PART_CORTEX_A65AE	0xD43
++#define	CPU_PART_CORTEX_X1	0xD44
++#define	CPU_PART_CORTEX_A510	0xD46
++#define	CPU_PART_CORTEX_A710	0xD47
++#define	CPU_PART_CORTEX_X2	0xD48
++#define	CPU_PART_NEOVERSE_N2	0xD49
++#define	CPU_PART_NEOVERSE_E1	0xD4A
++#define	CPU_PART_CORTEX_A78C	0xD4B
++#define	CPU_PART_CORTEX_X1C	0xD4C
++#define	CPU_PART_CORTEX_A715	0xD4D
++#define	CPU_PART_CORTEX_X3	0xD4E
++#define	CPU_PART_NEOVERSE_V2	0xD4F
++#define	CPU_PART_CORTEX_A520	0xD80
++#define	CPU_PART_CORTEX_A720	0xD81
++#define	CPU_PART_CORTEX_X4	0xD82
++#define	CPU_PART_NEOVERSE_V3AE	0xD83
++#define	CPU_PART_NEOVERSE_V3	0xD84
++#define	CPU_PART_CORTEX_X925	0xD85
++#define	CPU_PART_CORTEX_A725	0xD87
++#define	CPU_PART_C1_NANO	0xD8A
++#define	CPU_PART_C1_PRO		0xD8B
++#define	CPU_PART_C1_ULTRA	0xD8C
++#define	CPU_PART_NEOVERSE_N3	0xD8E
++#define	CPU_PART_C1_PREMIUM	0xD90
+ 
+ /* Cavium Part numbers */
+ #define	CPU_PART_THUNDERX	0x0A1
+@@ -201,21 +194,35 @@ bool VM_Version::is_cpu_emulated() {
+ 
+ #define	CPU_REV_THUNDERX2_0	0x00
+ 
+-#define	CPU_IMPL(midr)	(((midr) >> 24) & 0xff)
+-#define	CPU_PART(midr)	(((midr) >> 4) & 0xfff)
+-#define	CPU_VAR(midr)	(((midr) >> 20) & 0xf)
+-#define	CPU_REV(midr)	(((midr) >> 0) & 0xf)
+-#define UL(x)   UINT64_C(x)
++/* APM (now Ampere) Part number */
++#define CPU_PART_EMAG8180	0x000
+ 
+-struct cpu_desc {
+-	u_int		cpu_impl;
+-	u_int		cpu_part_num;
+-	u_int		cpu_variant;
+-	u_int		cpu_revision;
+-	const char	*cpu_impl_name;
+-	const char	*cpu_part_name;
+-};
++/* Ampere Part numbers */
++#define	CPU_PART_AMPERE1	0xAC3
++#define	CPU_PART_AMPERE1A	0xAC4
+ 
++/* Microsoft Part numbers */
++#define	CPU_PART_AZURE_COBALT_100	0xD49
++
++/* Qualcomm */
++#define CPU_PART_ORYON          0x001
++#define	CPU_PART_KRYO400_GOLD	0x804
++#define	CPU_PART_KRYO400_SILVER	0x805
++
++/* Apple part numbers */
++#define CPU_PART_M1_ICESTORM      0x022
++#define CPU_PART_M1_FIRESTORM     0x023
++#define CPU_PART_M1_ICESTORM_PRO  0x024
++#define CPU_PART_M1_FIRESTORM_PRO 0x025
++#define CPU_PART_M1_ICESTORM_MAX  0x028
++#define CPU_PART_M1_FIRESTORM_MAX 0x029
++#define CPU_PART_M2_BLIZZARD      0x032
++#define CPU_PART_M2_AVALANCHE     0x033
++#define CPU_PART_M2_BLIZZARD_PRO  0x034
++#define CPU_PART_M2_AVALANCHE_PRO 0x035
++#define CPU_PART_M2_BLIZZARD_MAX  0x038
++#define CPU_PART_M2_AVALANCHE_MAX 0x039
++
+ struct cpu_parts {
+ 	u_int		part_id;
+ 	const char	*part_name;
+@@ -236,136 +243,209 @@ struct cpu_implementers {
+ /*
+  * Per-implementer table of (PartNum, CPU Name) pairs.
+  */
+-/* ARM Ltd. */
++/* ARM Ltd. From FreeBSD but using OpenBSD strings */
+ static const struct cpu_parts cpu_parts_arm[] = {
++	{ CPU_PART_AEM_V8, "AEMv8" },
+ 	{ CPU_PART_FOUNDATION, "Foundation-Model" },
++	{ CPU_PART_CORTEX_A34, "Cortex-A34" },
+ 	{ CPU_PART_CORTEX_A35, "Cortex-A35" },
+ 	{ CPU_PART_CORTEX_A53, "Cortex-A53" },
+ 	{ CPU_PART_CORTEX_A55, "Cortex-A55" },
+ 	{ CPU_PART_CORTEX_A57, "Cortex-A57" },
++	{ CPU_PART_CORTEX_A65, "Cortex-A65" },
++	{ CPU_PART_CORTEX_A65AE, "Cortex-A65AE" },
+ 	{ CPU_PART_CORTEX_A72, "Cortex-A72" },
+ 	{ CPU_PART_CORTEX_A73, "Cortex-A73" },
+ 	{ CPU_PART_CORTEX_A75, "Cortex-A75" },
++	{ CPU_PART_CORTEX_A76, "Cortex-A76" },
++	{ CPU_PART_CORTEX_A76AE, "Cortex-A76AE" },
++	{ CPU_PART_CORTEX_A77, "Cortex-A77" },
++	{ CPU_PART_CORTEX_A78, "Cortex-A78" },
++	{ CPU_PART_CORTEX_A78AE, "Cortex-A78AE" },
++	{ CPU_PART_CORTEX_A78C, "Cortex-A78C" },
++	{ CPU_PART_CORTEX_A510, "Cortex-A510" },
++	{ CPU_PART_CORTEX_A520, "Cortex-A520" },
++	{ CPU_PART_CORTEX_A710, "Cortex-A710" },
++	{ CPU_PART_CORTEX_A715, "Cortex-A715" },
++	{ CPU_PART_CORTEX_A720, "Cortex-A720" },
++	{ CPU_PART_CORTEX_A725, "Cortex-A725" },
++	{ CPU_PART_CORTEX_X925, "Cortex-A925" },
++	{ CPU_PART_CORTEX_X1C, "Cortex-X1C" },
++	{ CPU_PART_CORTEX_X1, "Cortex-X1" },
++	{ CPU_PART_CORTEX_X2, "Cortex-X2" },
++	{ CPU_PART_CORTEX_X3, "Cortex-X3" },
++	{ CPU_PART_CORTEX_X4, "Cortex-X4" },
++	{ CPU_PART_C1_NANO, "C1-Nano" },
++	{ CPU_PART_C1_PRO, "C1-Pro" },
++	{ CPU_PART_C1_PREMIUM, "C1-Premium" },
++	{ CPU_PART_C1_ULTRA, "C1-Ultra" },
++	{ CPU_PART_NEOVERSE_E1, "Neoverse E1" },
++	{ CPU_PART_NEOVERSE_N1, "Neoverse N1" },
++	{ CPU_PART_NEOVERSE_N2, "Neoverse N2" },
++	{ CPU_PART_NEOVERSE_N3, "Neoverse N3" },
++	{ CPU_PART_NEOVERSE_V1, "Neoverse V1" },
++	{ CPU_PART_NEOVERSE_V2, "Neoverse V2" },
++	{ CPU_PART_NEOVERSE_V3, "Neoverse V3" },
++	{ CPU_PART_NEOVERSE_V3AE, "Neoverse V3AE" },
+ 	CPU_PART_NONE,
+ };
+-/* Cavium */
++
++/* Cavium  From FreeBSD but using OpenBSD strings */
+ static const struct cpu_parts cpu_parts_cavium[] = {
+-	{ CPU_PART_THUNDERX, "ThunderX" },
+-	{ CPU_PART_THUNDERX2, "ThunderX2" },
++	{ CPU_PART_THUNDERX, "ThunderX T88" },
++	{ CPU_PART_THUNDERX_81XX, "ThunderX T81" },
++	{ CPU_PART_THUNDERX_83XX, "ThunderX T83" },
++	{ CPU_PART_THUNDERX2, "ThunderX2 T99" },
+ 	CPU_PART_NONE,
+ };
+ 
++/* APM (now Ampere), From FreeBSD but using OpenBSD strings */
++static const struct cpu_parts cpu_parts_apm[] = {
++	{ CPU_PART_EMAG8180, "X-Gene" },
++	CPU_PART_NONE,
++};
++
++/* Ampere From FreeBSD, but using OpenBSD strings */
++static const struct cpu_parts cpu_parts_ampere[] = {
++	{ CPU_PART_AMPERE1A, "AmpereOne AC04" },
++	{ CPU_PART_AMPERE1, "AmpereOne" },
++	CPU_PART_NONE,
++};
++
++/* Microsoft */
++static const struct cpu_parts cpu_parts_microsoft[] = {
++	{ CPU_PART_AZURE_COBALT_100, "Azure Cobalt 100" },
++	CPU_PART_NONE,
++};
++
++/* Qualcomm From FreeBSD & OpenBSD. */
++static const struct cpu_parts cpu_parts_qcom[] = {
++	{ CPU_PART_KRYO400_GOLD, "Kryo 400 Gold" },
++	{ CPU_PART_KRYO400_SILVER, "Kryo 400 Silver" },
++	{ CPU_PART_ORYON, "Oryon" },
++	CPU_PART_NONE,
++};
++
++/* Apple. From FreeBSD but using OpenBSD strings */
++static const struct cpu_parts cpu_parts_apple[] = {
++	{ CPU_PART_M1_ICESTORM, "Icestorm" },
++	{ CPU_PART_M1_FIRESTORM, "Firestorm" },
++	{ CPU_PART_M1_ICESTORM_PRO, "Icestorm Pro" },
++	{ CPU_PART_M1_FIRESTORM_PRO, "Firestorm Pro" },
++	{ CPU_PART_M1_ICESTORM_MAX, "Icestorm Max" },
++	{ CPU_PART_M1_FIRESTORM_MAX, "Firestorm Max" },
++	{ CPU_PART_M2_BLIZZARD, "Blizzard" },
++	{ CPU_PART_M2_AVALANCHE, "Avalanche" },
++	{ CPU_PART_M2_BLIZZARD_PRO, "Blizzard Pro" },
++	{ CPU_PART_M2_AVALANCHE_PRO, "Avalanche Pro" },
++	{ CPU_PART_M2_BLIZZARD_MAX, "Blizzard Max" },
++	{ CPU_PART_M2_AVALANCHE_MAX, "Avalanche Max" },
++	CPU_PART_NONE,
++};
++
+ /* Unknown */
+ static const struct cpu_parts cpu_parts_none[] = {
+ 	CPU_PART_NONE,
+ };
+ 
+ /*
+- * Implementers table.
++ * Implementers table. From FreeBSD, but using OpenBSD strings
+  */
+ const struct cpu_implementers cpu_implementers[] = {
++	{ CPU_IMPL_AMPERE,	"Ampere",	cpu_parts_ampere },
++	{ CPU_IMPL_APPLE,	"Apple",	cpu_parts_apple },
++	{ CPU_IMPL_APM,		"Applied Micro",cpu_parts_apm },
+ 	{ CPU_IMPL_ARM,		"ARM",		cpu_parts_arm },
+ 	{ CPU_IMPL_BROADCOM,	"Broadcom",	cpu_parts_none },
+ 	{ CPU_IMPL_CAVIUM,	"Cavium",	cpu_parts_cavium },
+ 	{ CPU_IMPL_DEC,		"DEC",		cpu_parts_none },
+-	{ CPU_IMPL_INFINEON,	"IFX",		cpu_parts_none },
+ 	{ CPU_IMPL_FREESCALE,	"Freescale",	cpu_parts_none },
+-	{ CPU_IMPL_NVIDIA,	"NVIDIA",	cpu_parts_none },
+-	{ CPU_IMPL_APM,		"APM",		cpu_parts_none },
+-	{ CPU_IMPL_QUALCOMM,	"Qualcomm",	cpu_parts_none },
+-	{ CPU_IMPL_MARVELL,	"Marvell",	cpu_parts_none },
++	{ CPU_IMPL_FUJITSU,	"Fujitsu",	cpu_parts_none },
++	{ CPU_IMPL_HISILICON,	"HiSilicon",	cpu_parts_none },
++	{ CPU_IMPL_INFINEON,	"IFX",		cpu_parts_none },
+ 	{ CPU_IMPL_INTEL,	"Intel",	cpu_parts_none },
++	{ CPU_IMPL_MARVELL,	"Marvell",	cpu_parts_none },
++	{ CPU_IMPL_MICROSOFT,	"Microsoft",	cpu_parts_microsoft },
++	{ CPU_IMPL_NVIDIA,	"NVIDIA",	cpu_parts_none },
++	{ CPU_IMPL_QUALCOMM,	"Qualcomm",	cpu_parts_qcom },
+ 	CPU_IMPLEMENTER_NONE,
+ };
+ 
+-#ifdef __FreeBSD__
+-static unsigned long os_get_processor_features() {
+-  unsigned long auxv = 0;
+-  uint64_t id_aa64isar0, id_aa64pfr0;
++static void
++lookup_cpu(int &_cpu, int &_model, int &_variant, int &_revision) {
++  int mib[] = { CTL_HW, HW_MODEL };
++  char descr[BUFSIZ];
++  char *part_name, *rv_str;
++  size_t descr_len = sizeof(descr);
++  size_t impl_name_len;
++  const struct cpu_parts *cpu_partsp = nullptr;
++  size_t i;
+ 
+-  id_aa64isar0 = READ_SPECIALREG(id_aa64isar0_el1);
+-  id_aa64pfr0 = READ_SPECIALREG(id_aa64pfr0_el1);
++  if (sysctl(mib, nitems(mib), &descr, &descr_len, NULL, 0) == -1)
++    return;
+ 
+-  if (ID_AA64ISAR0_AES_VAL(id_aa64isar0) == ID_AA64ISAR0_AES_BASE) {
+-    auxv = auxv | HWCAP_AES;
++  for (i = 0; i < nitems(cpu_implementers); i++) {
++    impl_name_len = strlen(cpu_implementers[i].impl_name);
++    if (cpu_implementers[i].impl_id == 0 ||
++      strncmp(descr, cpu_implementers[i].impl_name, impl_name_len) == 0) {
++      _cpu = cpu_implementers[i].impl_id;
++      cpu_partsp = cpu_implementers[i].cpu_parts;
++      break;
++    }
+   }
+ 
+-  if (ID_AA64ISAR0_AES_VAL(id_aa64isar0) == ID_AA64ISAR0_AES_PMULL) {
+-    auxv = auxv | HWCAP_PMULL;
+-  }
++  if (_cpu == 0)
++    return;
+ 
+-  if (ID_AA64ISAR0_SHA1_VAL(id_aa64isar0) == ID_AA64ISAR0_SHA1_BASE) {
+-    auxv = auxv | HWCAP_SHA1;
+-  }
++  // +1 to skip space +1 more because descr_len includes NUL
++  if (impl_name_len + 2 > descr_len)
++    return;
+ 
+-  if (ID_AA64ISAR0_SHA2_VAL(id_aa64isar0) == ID_AA64ISAR0_SHA2_BASE) {
+-    auxv = auxv | HWCAP_SHA2;
+-  }
++  part_name = &descr[impl_name_len+1];
+ 
+-  if (ID_AA64ISAR0_CRC32_VAL(id_aa64isar0) == ID_AA64ISAR0_CRC32_BASE) {
+-    auxv = auxv | HWCAP_CRC32;
+-  }
++  rv_str = strrchr(part_name, ' ');
++  if (rv_str == nullptr)
++    return;
+ 
+-  if (ID_AA64PFR0_AdvSIMD(id_aa64pfr0) == ID_AA64PFR0_AdvSIMD_IMPL || \
+-      ID_AA64PFR0_AdvSIMD(id_aa64pfr0) == ID_AA64PFR0_AdvSIMD_HP ) {
+-    auxv = auxv | HWCAP_ASIMD;
+-  }
++  // null term part_name and skip over it
++  *(rv_str++) = '\0';
+ 
+-  return auxv;
+-}
+-#endif
+-
+-void VM_Version::get_os_cpu_info() {
+-#ifdef __OpenBSD__
+-  // READ_SPECIALREG is not available from userland on OpenBSD.
+-  // Hardcode these values to the "lowest common denominator"
+-  _cpu = CPU_IMPL_ARM;
+-  _model = CPU_PART_CORTEX_A53;
+-  _variant = 0;
+-  _revision = 0;
+-  _features = HWCAP_ASIMD;
+-#elif defined(__FreeBSD__)
+-  struct cpu_desc cpu_desc[1];
+-  struct cpu_desc user_cpu_desc;
+-
+-  uint32_t midr;
+-  uint32_t impl_id;
+-  uint32_t part_id;
+-  uint32_t cpu = 0;
+-  size_t i;
+-  const struct cpu_parts *cpu_partsp = NULL;
+-
+-  midr = READ_SPECIALREG(midr_el1);
+-
+-  impl_id = CPU_IMPL(midr);
+-  for (i = 0; i < nitems(cpu_implementers); i++) {
+-    if (impl_id == cpu_implementers[i].impl_id ||
+-      cpu_implementers[i].impl_id == 0) {
+-      cpu_desc[cpu].cpu_impl = impl_id;
+-      cpu_desc[cpu].cpu_impl_name = cpu_implementers[i].impl_name;
+-      cpu_partsp = cpu_implementers[i].cpu_parts;
++  for (i = 0; &cpu_partsp[i] != nullptr; i++) {
++    if (cpu_partsp[i].part_id == 0 ||
++      strcmp(part_name, cpu_partsp[i].part_name) == 0) {
++      _model = cpu_partsp[i].part_id;
+       break;
+     }
+   }
+-  part_id = CPU_PART(midr);
+-  for (i = 0; &cpu_partsp[i] != NULL; i++) {
+-    if (part_id == cpu_partsp[i].part_id || cpu_partsp[i].part_id == 0) {
+-      cpu_desc[cpu].cpu_part_num = part_id;
+-      cpu_desc[cpu].cpu_part_name = cpu_partsp[i].part_name;
+-      break;
+-    }
+-  }
+ 
+-  cpu_desc[cpu].cpu_revision = CPU_REV(midr);
+-  cpu_desc[cpu].cpu_variant = CPU_VAR(midr);
++  sscanf(rv_str, "r%up%u", &_variant, &_revision);
++}
++#endif // __OpenBSD__
+ 
+-  _cpu = cpu_desc[cpu].cpu_impl;
+-  _variant = cpu_desc[cpu].cpu_variant;
+-  _model = cpu_desc[cpu].cpu_part_num;
+-  _revision = cpu_desc[cpu].cpu_revision;
++void VM_Version::get_os_cpu_info() {
++#if defined(__FreeBSD__) || defined(__OpenBSD__)
+ 
+-  uint64_t auxv = os_get_processor_features();
++  /*
++   * Step 1: setup _features using elf_aux_info(3). Keep in sync with Linux.
++   */
++  unsigned long auxv = 0;
++  unsigned long auxv2 = 0;
++  elf_aux_info(AT_HWCAP, &auxv, sizeof(auxv));
++  elf_aux_info(AT_HWCAP2, &auxv2, sizeof(auxv2));
+ 
++  static_assert(CPU_FP      == HWCAP_FP,      "Flag CPU_FP must follow Linux HWCAP");
++  static_assert(CPU_ASIMD   == HWCAP_ASIMD,   "Flag CPU_ASIMD must follow Linux HWCAP");
++  static_assert(CPU_EVTSTRM == HWCAP_EVTSTRM, "Flag CPU_EVTSTRM must follow Linux HWCAP");
++  static_assert(CPU_AES     == HWCAP_AES,     "Flag CPU_AES must follow Linux HWCAP");
++  static_assert(CPU_PMULL   == HWCAP_PMULL,   "Flag CPU_PMULL must follow Linux HWCAP");
++  static_assert(CPU_SHA1    == HWCAP_SHA1,    "Flag CPU_SHA1 must follow Linux HWCAP");
++  static_assert(CPU_SHA2    == HWCAP_SHA2,    "Flag CPU_SHA2 must follow Linux HWCAP");
++  static_assert(CPU_CRC32   == HWCAP_CRC32,   "Flag CPU_CRC32 must follow Linux HWCAP");
++  static_assert(CPU_LSE     == HWCAP_ATOMICS, "Flag CPU_LSE must follow Linux HWCAP");
++  static_assert(CPU_DCPOP   == HWCAP_DCPOP,   "Flag CPU_DCPOP must follow Linux HWCAP");
++  static_assert(CPU_SHA3    == HWCAP_SHA3,    "Flag CPU_SHA3 must follow Linux HWCAP");
++  static_assert(CPU_SHA512  == HWCAP_SHA512,  "Flag CPU_SHA512 must follow Linux HWCAP");
++  static_assert(CPU_SVE     == HWCAP_SVE,     "Flag CPU_SVE must follow Linux HWCAP");
+   _features = auxv & (
+       HWCAP_FP      |
+       HWCAP_ASIMD   |
+@@ -380,8 +460,37 @@ void VM_Version::get_os_cpu_info() {
+       HWCAP_SHA3    |
+       HWCAP_SHA512  |
+       HWCAP_SVE);
+-#endif
+ 
++  if (auxv2 & HWCAP2_SVE2) _features |= CPU_SVE2;
++
++  /*
++   * Step 2: setup _cpu, _model, _variant and _revision using READ_SPECIALREG on
++   * midr_el1 if allowed. On OpenBSD fallback to sysctl hw.model and lookup from
++   * tables.
++   */
++#ifdef __FreeBSD__
++  uint32_t midr = READ_SPECIALREG(midr_el1);
++  _cpu = CPU_IMPL(midr);
++  _model = CPU_PART(midr);
++  _variant = CPU_VAR(midr);
++  _revision = CPU_REV(midr);
++#else
++  /* On OpenBSD READ_SPECIALREG is only available if HWCAP_CPUID is set */
++  if (auxv & HWCAP_CPUID) {
++    uint32_t midr = READ_SPECIALREG(midr_el1);
++    _cpu = CPU_IMPL(midr);
++    _model = CPU_PART(midr);
++    _variant = CPU_VAR(midr);
++    _revision = CPU_REV(midr);
++  } else {
++    lookup_cpu(_cpu, _model, _variant, _revision);
++  }
++#endif // __FreeBSD__
++#endif // __FreeBSD__ || __OpenBSD__
++
++  /*
++   * Step 3: Get cache line sizes and _zva_length using same approach as Linux.
++   */
+   uint64_t ctr_el0;
+   uint64_t dczid_el0;
+   __asm__ (
Index: 21/Makefile
===================================================================
RCS file: /cvs/ports/devel/jdk/21/Makefile,v
diff -u -p -u -r1.10 Makefile
--- 21/Makefile	3 Nov 2025 15:43:43 -0000	1.10
+++ 21/Makefile	16 Dec 2025 19:33:50 -0000
@@ -12,6 +12,7 @@ PACKAGE_VER=	${BASE_VER}.${PATCH_VER}.${
 PKGNAME=	jdk-${PACKAGE_VER}
 PKGSTEM=	jdk-21
 EPOCH=		0
+REVISION=	0
 
 DIST_SUBDIR=	jdk
 DISTNAME=	jdk-${VERSION_STR}
Index: 21/patches/patch-make_common_NativeCompilation_gmk
===================================================================
RCS file: /cvs/ports/devel/jdk/21/patches/patch-make_common_NativeCompilation_gmk,v
diff -u -p -u -r1.1.1.1 patch-make_common_NativeCompilation_gmk
--- 21/patches/patch-make_common_NativeCompilation_gmk	11 Dec 2023 14:36:21 -0000	1.1.1.1
+++ 21/patches/patch-make_common_NativeCompilation_gmk	16 Dec 2025 19:33:50 -0000
@@ -5,7 +5,7 @@ get the debug package without bloating t
 Index: make/common/NativeCompilation.gmk
 --- make/common/NativeCompilation.gmk.orig
 +++ make/common/NativeCompilation.gmk
-@@ -1066,9 +1066,8 @@ define SetupNativeCompilationBody
+@@ -1080,9 +1080,8 @@ define SetupNativeCompilationBody
            # so we can run it after strip is called, since strip can sometimes mangle the
            # embedded debuglink, which we want to avoid.
            $1_CREATE_DEBUGINFO_CMDS := \
Index: 21/patches/patch-src_hotspot_os_cpu_bsd_aarch64_vm_version_bsd_aarch64_cpp
===================================================================
RCS file: 21/patches/patch-src_hotspot_os_cpu_bsd_aarch64_vm_version_bsd_aarch64_cpp
diff -N 21/patches/patch-src_hotspot_os_cpu_bsd_aarch64_vm_version_bsd_aarch64_cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 21/patches/patch-src_hotspot_os_cpu_bsd_aarch64_vm_version_bsd_aarch64_cpp	16 Dec 2025 19:33:50 -0000
@@ -0,0 +1,537 @@
+Get hardware capablilites using elf_aux_info(3).
+Detect CPU, model, variant and revision using READ_SPECIALREG
+when HWCAP_CPUID is set, otherwise parse sysctl hw.model to
+get needed info.
+
+Index: src/hotspot/os_cpu/bsd_aarch64/vm_version_bsd_aarch64.cpp
+--- src/hotspot/os_cpu/bsd_aarch64/vm_version_bsd_aarch64.cpp.orig
++++ src/hotspot/os_cpu/bsd_aarch64/vm_version_bsd_aarch64.cpp
+@@ -135,91 +135,84 @@ bool VM_Version::is_cpu_emulated() {
+ #else // __APPLE__
+ 
+ #include <machine/armreg.h>
+-#if defined (__FreeBSD__)
+-#include <machine/elf.h>
++#if defined (__FreeBSD__) || defined (__OpenBSD__)
++#include <sys/auxv.h>
+ #endif
+ 
+-#ifndef HWCAP_ASIMD
+-#define HWCAP_ASIMD (1<<1)
+-#endif
++#define	CPU_IMPL(midr)	(((midr) >> 24) & 0xff)
++#define	CPU_PART(midr)	(((midr) >> 4) & 0xfff)
++#define	CPU_VAR(midr)	(((midr) >> 20) & 0xf)
++#define	CPU_REV(midr)	(((midr) >> 0) & 0xf)
+ 
+-#ifndef HWCAP_AES
+-#define HWCAP_AES   (1<<3)
+-#endif
++#ifdef __OpenBSD__
++// For older processors on OpenBSD READ_SPECIALREG is not supported.
++// These constants and tables allow for looking up the cpu and model.
+ 
+-#ifndef HWCAP_PMULL
+-#define HWCAP_PMULL (1<<4)
+-#endif
++#include <sys/types.h>
++#include <sys/sysctl.h>
++#include <string.h>
++#include <stdio.h>
+ 
+-#ifndef HWCAP_SHA1
+-#define HWCAP_SHA1  (1<<5)
+-#endif
+-
+-#ifndef HWCAP_SHA2
+-#define HWCAP_SHA2  (1<<6)
+-#endif
+-
+-#ifndef HWCAP_CRC32
+-#define HWCAP_CRC32 (1<<7)
+-#endif
+-
+-#ifndef HWCAP_ATOMICS
+-#define HWCAP_ATOMICS (1<<8)
+-#endif
+-
+-#ifndef ID_AA64PFR0_AdvSIMD_SHIFT
+-#define ID_AA64PFR0_AdvSIMD_SHIFT 20
+-#endif
+-
+-#ifndef ID_AA64PFR0_AdvSIMD
+-#define ID_AA64PFR0_AdvSIMD(x) ((x) & (UL(0xf) << ID_AA64PFR0_AdvSIMD_SHIFT))
+-#endif
+-
+-#ifndef ID_AA64PFR0_AdvSIMD_IMPL
+-#define ID_AA64PFR0_AdvSIMD_IMPL (UL(0x0) << ID_AA64PFR0_AdvSIMD_SHIFT)
+-#endif
+-
+-#ifndef ID_AA64PFR0_AdvSIMD_HP
+-#define ID_AA64PFR0_AdvSIMD_HP (UL(0x1) << ID_AA64PFR0_AdvSIMD_SHIFT)
+-#endif
+-
+-#ifndef ID_AA64ISAR0_AES_VAL
+-#define ID_AA64ISAR0_AES_VAL ID_AA64ISAR0_AES
+-#endif
+-
+-#ifndef ID_AA64ISAR0_SHA1_VAL
+-#define ID_AA64ISAR0_SHA1_VAL ID_AA64ISAR0_SHA1
+-#endif
+-
+-#ifndef ID_AA64ISAR0_SHA2_VAL
+-#define ID_AA64ISAR0_SHA2_VAL ID_AA64ISAR0_SHA2
+-#endif
+-
+-#ifndef ID_AA64ISAR0_CRC32_VAL
+-#define ID_AA64ISAR0_CRC32_VAL ID_AA64ISAR0_CRC32
+-#endif
+-
+ #define	CPU_IMPL_ARM		0x41
+ #define	CPU_IMPL_BROADCOM	0x42
+ #define	CPU_IMPL_CAVIUM		0x43
+ #define	CPU_IMPL_DEC		0x44
++#define	CPU_IMPL_FUJITSU	0x46
++#define	CPU_IMPL_HISILICON	0x48
+ #define	CPU_IMPL_INFINEON	0x49
+ #define	CPU_IMPL_FREESCALE	0x4D
+ #define	CPU_IMPL_NVIDIA		0x4E
+ #define	CPU_IMPL_APM		0x50
+ #define	CPU_IMPL_QUALCOMM	0x51
+ #define	CPU_IMPL_MARVELL	0x56
++#define	CPU_IMPL_APPLE		0x61
+ #define	CPU_IMPL_INTEL		0x69
++#define	CPU_IMPL_AMPERE		0xC0
++#define	CPU_IMPL_MICROSOFT	0x6D
+ 
+ /* ARM Part numbers */
+ #define	CPU_PART_FOUNDATION	0xD00
+-#define	CPU_PART_CORTEX_A35	0xD04
++#define	CPU_PART_CORTEX_A34	0xD02
+ #define	CPU_PART_CORTEX_A53	0xD03
++#define	CPU_PART_CORTEX_A35	0xD04
+ #define	CPU_PART_CORTEX_A55	0xD05
++#define	CPU_PART_CORTEX_A65	0xD06
+ #define	CPU_PART_CORTEX_A57	0xD07
+ #define	CPU_PART_CORTEX_A72	0xD08
+ #define	CPU_PART_CORTEX_A73	0xD09
+ #define	CPU_PART_CORTEX_A75	0xD0A
++#define	CPU_PART_CORTEX_A76	0xD0B
++#define	CPU_PART_NEOVERSE_N1	0xD0C
++#define	CPU_PART_CORTEX_A77	0xD0D
++#define	CPU_PART_CORTEX_A76AE	0xD0E
++#define	CPU_PART_AEM_V8		0xD0F
++#define	CPU_PART_NEOVERSE_V1	0xD40
++#define	CPU_PART_CORTEX_A78	0xD41
++#define	CPU_PART_CORTEX_A78AE	0xD42
++#define	CPU_PART_CORTEX_A65AE	0xD43
++#define	CPU_PART_CORTEX_X1	0xD44
++#define	CPU_PART_CORTEX_A510	0xD46
++#define	CPU_PART_CORTEX_A710	0xD47
++#define	CPU_PART_CORTEX_X2	0xD48
++#define	CPU_PART_NEOVERSE_N2	0xD49
++#define	CPU_PART_NEOVERSE_E1	0xD4A
++#define	CPU_PART_CORTEX_A78C	0xD4B
++#define	CPU_PART_CORTEX_X1C	0xD4C
++#define	CPU_PART_CORTEX_A715	0xD4D
++#define	CPU_PART_CORTEX_X3	0xD4E
++#define	CPU_PART_NEOVERSE_V2	0xD4F
++#define	CPU_PART_CORTEX_A520	0xD80
++#define	CPU_PART_CORTEX_A720	0xD81
++#define	CPU_PART_CORTEX_X4	0xD82
++#define	CPU_PART_NEOVERSE_V3AE	0xD83
++#define	CPU_PART_NEOVERSE_V3	0xD84
++#define	CPU_PART_CORTEX_X925	0xD85
++#define	CPU_PART_CORTEX_A725	0xD87
++#define	CPU_PART_C1_NANO	0xD8A
++#define	CPU_PART_C1_PRO		0xD8B
++#define	CPU_PART_C1_ULTRA	0xD8C
++#define	CPU_PART_NEOVERSE_N3	0xD8E
++#define	CPU_PART_C1_PREMIUM	0xD90
+ 
+ /* Cavium Part numbers */
+ #define	CPU_PART_THUNDERX	0x0A1
+@@ -232,21 +225,35 @@ bool VM_Version::is_cpu_emulated() {
+ 
+ #define	CPU_REV_THUNDERX2_0	0x00
+ 
+-#define	CPU_IMPL(midr)	(((midr) >> 24) & 0xff)
+-#define	CPU_PART(midr)	(((midr) >> 4) & 0xfff)
+-#define	CPU_VAR(midr)	(((midr) >> 20) & 0xf)
+-#define	CPU_REV(midr)	(((midr) >> 0) & 0xf)
+-#define UL(x)   UINT64_C(x)
++/* APM (now Ampere) Part number */
++#define CPU_PART_EMAG8180	0x000
+ 
+-struct cpu_desc {
+-	u_int		cpu_impl;
+-	u_int		cpu_part_num;
+-	u_int		cpu_variant;
+-	u_int		cpu_revision;
+-	const char	*cpu_impl_name;
+-	const char	*cpu_part_name;
+-};
++/* Ampere Part numbers */
++#define	CPU_PART_AMPERE1	0xAC3
++#define	CPU_PART_AMPERE1A	0xAC4
+ 
++/* Microsoft Part numbers */
++#define	CPU_PART_AZURE_COBALT_100	0xD49
++
++/* Qualcomm */
++#define CPU_PART_ORYON          0x001
++#define	CPU_PART_KRYO400_GOLD	0x804
++#define	CPU_PART_KRYO400_SILVER	0x805
++
++/* Apple part numbers */
++#define CPU_PART_M1_ICESTORM      0x022
++#define CPU_PART_M1_FIRESTORM     0x023
++#define CPU_PART_M1_ICESTORM_PRO  0x024
++#define CPU_PART_M1_FIRESTORM_PRO 0x025
++#define CPU_PART_M1_ICESTORM_MAX  0x028
++#define CPU_PART_M1_FIRESTORM_MAX 0x029
++#define CPU_PART_M2_BLIZZARD      0x032
++#define CPU_PART_M2_AVALANCHE     0x033
++#define CPU_PART_M2_BLIZZARD_PRO  0x034
++#define CPU_PART_M2_AVALANCHE_PRO 0x035
++#define CPU_PART_M2_BLIZZARD_MAX  0x038
++#define CPU_PART_M2_AVALANCHE_MAX 0x039
++
+ struct cpu_parts {
+ 	u_int		part_id;
+ 	const char	*part_name;
+@@ -267,136 +274,210 @@ struct cpu_implementers {
+ /*
+  * Per-implementer table of (PartNum, CPU Name) pairs.
+  */
+-/* ARM Ltd. */
++/* ARM Ltd. From FreeBSD but using OpenBSD strings */
+ static const struct cpu_parts cpu_parts_arm[] = {
++	{ CPU_PART_AEM_V8, "AEMv8" },
+ 	{ CPU_PART_FOUNDATION, "Foundation-Model" },
++	{ CPU_PART_CORTEX_A34, "Cortex-A34" },
+ 	{ CPU_PART_CORTEX_A35, "Cortex-A35" },
+ 	{ CPU_PART_CORTEX_A53, "Cortex-A53" },
+ 	{ CPU_PART_CORTEX_A55, "Cortex-A55" },
+ 	{ CPU_PART_CORTEX_A57, "Cortex-A57" },
++	{ CPU_PART_CORTEX_A65, "Cortex-A65" },
++	{ CPU_PART_CORTEX_A65AE, "Cortex-A65AE" },
+ 	{ CPU_PART_CORTEX_A72, "Cortex-A72" },
+ 	{ CPU_PART_CORTEX_A73, "Cortex-A73" },
+ 	{ CPU_PART_CORTEX_A75, "Cortex-A75" },
++	{ CPU_PART_CORTEX_A76, "Cortex-A76" },
++	{ CPU_PART_CORTEX_A76AE, "Cortex-A76AE" },
++	{ CPU_PART_CORTEX_A77, "Cortex-A77" },
++	{ CPU_PART_CORTEX_A78, "Cortex-A78" },
++	{ CPU_PART_CORTEX_A78AE, "Cortex-A78AE" },
++	{ CPU_PART_CORTEX_A78C, "Cortex-A78C" },
++	{ CPU_PART_CORTEX_A510, "Cortex-A510" },
++	{ CPU_PART_CORTEX_A520, "Cortex-A520" },
++	{ CPU_PART_CORTEX_A710, "Cortex-A710" },
++	{ CPU_PART_CORTEX_A715, "Cortex-A715" },
++	{ CPU_PART_CORTEX_A720, "Cortex-A720" },
++	{ CPU_PART_CORTEX_A725, "Cortex-A725" },
++	{ CPU_PART_CORTEX_X925, "Cortex-A925" },
++	{ CPU_PART_CORTEX_X1C, "Cortex-X1C" },
++	{ CPU_PART_CORTEX_X1, "Cortex-X1" },
++	{ CPU_PART_CORTEX_X2, "Cortex-X2" },
++	{ CPU_PART_CORTEX_X3, "Cortex-X3" },
++	{ CPU_PART_CORTEX_X4, "Cortex-X4" },
++	{ CPU_PART_C1_NANO, "C1-Nano" },
++	{ CPU_PART_C1_PRO, "C1-Pro" },
++	{ CPU_PART_C1_PREMIUM, "C1-Premium" },
++	{ CPU_PART_C1_ULTRA, "C1-Ultra" },
++	{ CPU_PART_NEOVERSE_E1, "Neoverse E1" },
++	{ CPU_PART_NEOVERSE_N1, "Neoverse N1" },
++	{ CPU_PART_NEOVERSE_N2, "Neoverse N2" },
++	{ CPU_PART_NEOVERSE_N3, "Neoverse N3" },
++	{ CPU_PART_NEOVERSE_V1, "Neoverse V1" },
++	{ CPU_PART_NEOVERSE_V2, "Neoverse V2" },
++	{ CPU_PART_NEOVERSE_V3, "Neoverse V3" },
++	{ CPU_PART_NEOVERSE_V3AE, "Neoverse V3AE" },
+ 	CPU_PART_NONE,
+ };
+-/* Cavium */
++
++/* Cavium  From FreeBSD but using OpenBSD strings */
+ static const struct cpu_parts cpu_parts_cavium[] = {
+-	{ CPU_PART_THUNDERX, "ThunderX" },
+-	{ CPU_PART_THUNDERX2, "ThunderX2" },
++	{ CPU_PART_THUNDERX, "ThunderX T88" },
++	{ CPU_PART_THUNDERX_81XX, "ThunderX T81" },
++	{ CPU_PART_THUNDERX_83XX, "ThunderX T83" },
++	{ CPU_PART_THUNDERX2, "ThunderX2 T99" },
+ 	CPU_PART_NONE,
+ };
+ 
++/* APM (now Ampere), From FreeBSD but using OpenBSD strings */
++static const struct cpu_parts cpu_parts_apm[] = {
++	{ CPU_PART_EMAG8180, "X-Gene" },
++	CPU_PART_NONE,
++};
++
++/* Ampere From FreeBSD, but using OpenBSD strings */
++static const struct cpu_parts cpu_parts_ampere[] = {
++	{ CPU_PART_AMPERE1A, "AmpereOne AC04" },
++	{ CPU_PART_AMPERE1, "AmpereOne" },
++	CPU_PART_NONE,
++};
++
++/* Microsoft */
++static const struct cpu_parts cpu_parts_microsoft[] = {
++	{ CPU_PART_AZURE_COBALT_100, "Azure Cobalt 100" },
++	CPU_PART_NONE,
++};
++
++/* Qualcomm From FreeBSD & OpenBSD. */
++static const struct cpu_parts cpu_parts_qcom[] = {
++	{ CPU_PART_KRYO400_GOLD, "Kryo 400 Gold" },
++	{ CPU_PART_KRYO400_SILVER, "Kryo 400 Silver" },
++	{ CPU_PART_ORYON, "Oryon" },
++	CPU_PART_NONE,
++};
++
++/* Apple. From FreeBSD but using OpenBSD strings */
++static const struct cpu_parts cpu_parts_apple[] = {
++	{ CPU_PART_M1_ICESTORM, "Icestorm" },
++	{ CPU_PART_M1_FIRESTORM, "Firestorm" },
++	{ CPU_PART_M1_ICESTORM_PRO, "Icestorm Pro" },
++	{ CPU_PART_M1_FIRESTORM_PRO, "Firestorm Pro" },
++	{ CPU_PART_M1_ICESTORM_MAX, "Icestorm Max" },
++	{ CPU_PART_M1_FIRESTORM_MAX, "Firestorm Max" },
++	{ CPU_PART_M2_BLIZZARD, "Blizzard" },
++	{ CPU_PART_M2_AVALANCHE, "Avalanche" },
++	{ CPU_PART_M2_BLIZZARD_PRO, "Blizzard Pro" },
++	{ CPU_PART_M2_AVALANCHE_PRO, "Avalanche Pro" },
++	{ CPU_PART_M2_BLIZZARD_MAX, "Blizzard Max" },
++	{ CPU_PART_M2_AVALANCHE_MAX, "Avalanche Max" },
++	CPU_PART_NONE,
++};
++
+ /* Unknown */
+ static const struct cpu_parts cpu_parts_none[] = {
+ 	CPU_PART_NONE,
+ };
+ 
+ /*
+- * Implementers table.
++ * Implementers table. From FreeBSD, but using OpenBSD strings
+  */
+ const struct cpu_implementers cpu_implementers[] = {
++	{ CPU_IMPL_AMPERE,	"Ampere",	cpu_parts_ampere },
++	{ CPU_IMPL_APPLE,	"Apple",	cpu_parts_apple },
++	{ CPU_IMPL_APM,		"Applied Micro",cpu_parts_apm },
+ 	{ CPU_IMPL_ARM,		"ARM",		cpu_parts_arm },
+ 	{ CPU_IMPL_BROADCOM,	"Broadcom",	cpu_parts_none },
+ 	{ CPU_IMPL_CAVIUM,	"Cavium",	cpu_parts_cavium },
+ 	{ CPU_IMPL_DEC,		"DEC",		cpu_parts_none },
+-	{ CPU_IMPL_INFINEON,	"IFX",		cpu_parts_none },
+ 	{ CPU_IMPL_FREESCALE,	"Freescale",	cpu_parts_none },
+-	{ CPU_IMPL_NVIDIA,	"NVIDIA",	cpu_parts_none },
+-	{ CPU_IMPL_APM,		"APM",		cpu_parts_none },
+-	{ CPU_IMPL_QUALCOMM,	"Qualcomm",	cpu_parts_none },
+-	{ CPU_IMPL_MARVELL,	"Marvell",	cpu_parts_none },
++	{ CPU_IMPL_FUJITSU,	"Fujitsu",	cpu_parts_none },
++	{ CPU_IMPL_HISILICON,	"HiSilicon",	cpu_parts_none },
++	{ CPU_IMPL_INFINEON,	"IFX",		cpu_parts_none },
+ 	{ CPU_IMPL_INTEL,	"Intel",	cpu_parts_none },
++	{ CPU_IMPL_MARVELL,	"Marvell",	cpu_parts_none },
++	{ CPU_IMPL_MICROSOFT,	"Microsoft",	cpu_parts_microsoft },
++	{ CPU_IMPL_NVIDIA,	"NVIDIA",	cpu_parts_none },
++	{ CPU_IMPL_QUALCOMM,	"Qualcomm",	cpu_parts_qcom },
+ 	CPU_IMPLEMENTER_NONE,
+ };
+ 
+-#ifdef __FreeBSD__
+-static unsigned long os_get_processor_features() {
+-  unsigned long auxv = 0;
+-  uint64_t id_aa64isar0, id_aa64pfr0;
++static void
++lookup_cpu(int &_cpu, int &_model, int &_variant, int &_revision) {
++  int mib[] = { CTL_HW, HW_MODEL };
++  char descr[BUFSIZ];
++  char *part_name, *rv_str;
++  size_t descr_len = sizeof(descr);
++  size_t impl_name_len;
++  const struct cpu_parts *cpu_partsp = nullptr;
++  size_t i;
+ 
+-  id_aa64isar0 = READ_SPECIALREG(id_aa64isar0_el1);
+-  id_aa64pfr0 = READ_SPECIALREG(id_aa64pfr0_el1);
++  if (sysctl(mib, nitems(mib), &descr, &descr_len, NULL, 0) == -1)
++    return;
+ 
+-  if (ID_AA64ISAR0_AES_VAL(id_aa64isar0) == ID_AA64ISAR0_AES_BASE) {
+-    auxv = auxv | HWCAP_AES;
++  for (i = 0; i < nitems(cpu_implementers); i++) {
++    impl_name_len = strlen(cpu_implementers[i].impl_name);
++    if (cpu_implementers[i].impl_id == 0 ||
++      strncmp(descr, cpu_implementers[i].impl_name, impl_name_len) == 0) {
++      _cpu = cpu_implementers[i].impl_id;
++      cpu_partsp = cpu_implementers[i].cpu_parts;
++      break;
++    }
+   }
+ 
+-  if (ID_AA64ISAR0_AES_VAL(id_aa64isar0) == ID_AA64ISAR0_AES_PMULL) {
+-    auxv = auxv | HWCAP_PMULL;
+-  }
++  if (_cpu == 0)
++    return;
+ 
+-  if (ID_AA64ISAR0_SHA1_VAL(id_aa64isar0) == ID_AA64ISAR0_SHA1_BASE) {
+-    auxv = auxv | HWCAP_SHA1;
+-  }
++  // +1 to skip space +1 more because descr_len includes NUL
++  if (impl_name_len + 2 > descr_len)
++    return;
+ 
+-  if (ID_AA64ISAR0_SHA2_VAL(id_aa64isar0) == ID_AA64ISAR0_SHA2_BASE) {
+-    auxv = auxv | HWCAP_SHA2;
+-  }
++  part_name = &descr[impl_name_len+1];
+ 
+-  if (ID_AA64ISAR0_CRC32_VAL(id_aa64isar0) == ID_AA64ISAR0_CRC32_BASE) {
+-    auxv = auxv | HWCAP_CRC32;
+-  }
++  rv_str = strrchr(part_name, ' ');
++  if (rv_str == nullptr)
++    return;
+ 
+-  if (ID_AA64PFR0_AdvSIMD(id_aa64pfr0) == ID_AA64PFR0_AdvSIMD_IMPL || \
+-      ID_AA64PFR0_AdvSIMD(id_aa64pfr0) == ID_AA64PFR0_AdvSIMD_HP ) {
+-    auxv = auxv | HWCAP_ASIMD;
+-  }
++  // null term part_name and skip over it
++  *(rv_str++) = '\0';
+ 
+-  return auxv;
+-}
+-#endif
+-
+-void VM_Version::get_os_cpu_info() {
+-#ifdef __OpenBSD__
+-  // READ_SPECIALREG is not available from userland on OpenBSD.
+-  // Hardcode these values to the "lowest common denominator"
+-  _cpu = CPU_IMPL_ARM;
+-  _model = CPU_PART_CORTEX_A53;
+-  _variant = 0;
+-  _revision = 0;
+-  _features = HWCAP_ASIMD;
+-#elif defined(__FreeBSD__)
+-  struct cpu_desc cpu_desc[1];
+-  struct cpu_desc user_cpu_desc;
+-
+-  uint32_t midr;
+-  uint32_t impl_id;
+-  uint32_t part_id;
+-  uint32_t cpu = 0;
+-  size_t i;
+-  const struct cpu_parts *cpu_partsp = nullptr;
+-
+-  midr = READ_SPECIALREG(midr_el1);
+-
+-  impl_id = CPU_IMPL(midr);
+-  for (i = 0; i < nitems(cpu_implementers); i++) {
+-    if (impl_id == cpu_implementers[i].impl_id ||
+-      cpu_implementers[i].impl_id == 0) {
+-      cpu_desc[cpu].cpu_impl = impl_id;
+-      cpu_desc[cpu].cpu_impl_name = cpu_implementers[i].impl_name;
+-      cpu_partsp = cpu_implementers[i].cpu_parts;
+-      break;
+-    }
+-  }
+-  part_id = CPU_PART(midr);
+   for (i = 0; &cpu_partsp[i] != nullptr; i++) {
+-    if (part_id == cpu_partsp[i].part_id || cpu_partsp[i].part_id == 0) {
+-      cpu_desc[cpu].cpu_part_num = part_id;
+-      cpu_desc[cpu].cpu_part_name = cpu_partsp[i].part_name;
++    if (cpu_partsp[i].part_id == 0 ||
++      strcmp(part_name, cpu_partsp[i].part_name) == 0) {
++      _model = cpu_partsp[i].part_id;
+       break;
+     }
+   }
+ 
+-  cpu_desc[cpu].cpu_revision = CPU_REV(midr);
+-  cpu_desc[cpu].cpu_variant = CPU_VAR(midr);
++  sscanf(rv_str, "r%up%u", &_variant, &_revision);
++}
++#endif // __OpenBSD__
+ 
+-  _cpu = cpu_desc[cpu].cpu_impl;
+-  _variant = cpu_desc[cpu].cpu_variant;
+-  _model = cpu_desc[cpu].cpu_part_num;
+-  _revision = cpu_desc[cpu].cpu_revision;
++void VM_Version::get_os_cpu_info() {
++#if defined(__FreeBSD__) || defined(__OpenBSD__)
+ 
+-  uint64_t auxv = os_get_processor_features();
++  /*
++   * Step 1: setup _features using elf_aux_info(3). Keep in sync with Linux.
++   */
++  unsigned long auxv = 0;
++  unsigned long auxv2 = 0;
++  elf_aux_info(AT_HWCAP, &auxv, sizeof(auxv));
++  elf_aux_info(AT_HWCAP2, &auxv2, sizeof(auxv2));
+ 
++  static_assert(CPU_FP      == HWCAP_FP,      "Flag CPU_FP must follow HWCAP");
++  static_assert(CPU_ASIMD   == HWCAP_ASIMD,   "Flag CPU_ASIMD must follow HWCAP");
++  static_assert(CPU_EVTSTRM == HWCAP_EVTSTRM, "Flag CPU_EVTSTRM must follow HWCAP");
++  static_assert(CPU_AES     == HWCAP_AES,     "Flag CPU_AES must follow HWCAP");
++  static_assert(CPU_PMULL   == HWCAP_PMULL,   "Flag CPU_PMULL must follow HWCAP");
++  static_assert(CPU_SHA1    == HWCAP_SHA1,    "Flag CPU_SHA1 must follow HWCAP");
++  static_assert(CPU_SHA2    == HWCAP_SHA2,    "Flag CPU_SHA2 must follow HWCAP");
++  static_assert(CPU_CRC32   == HWCAP_CRC32,   "Flag CPU_CRC32 must follow HWCAP");
++  static_assert(CPU_LSE     == HWCAP_ATOMICS, "Flag CPU_LSE must follow HWCAP");
++  static_assert(CPU_DCPOP   == HWCAP_DCPOP,   "Flag CPU_DCPOP must follow HWCAP");
++  static_assert(CPU_SHA3    == HWCAP_SHA3,    "Flag CPU_SHA3 must follow HWCAP");
++  static_assert(CPU_SHA512  == HWCAP_SHA512,  "Flag CPU_SHA512 must follow HWCAP");
++  static_assert(CPU_SVE     == HWCAP_SVE,     "Flag CPU_SVE must follow HWCAP");
++  static_assert(CPU_PACA    == HWCAP_PACA,    "Flag CPU_PACA must follow HWCAP");
+   _features = auxv & (
+       HWCAP_FP      |
+       HWCAP_ASIMD   |
+@@ -410,9 +491,40 @@ void VM_Version::get_os_cpu_info() {
+       HWCAP_DCPOP   |
+       HWCAP_SHA3    |
+       HWCAP_SHA512  |
+-      HWCAP_SVE);
+-#endif
++      HWCAP_SVE     |
++      HWCAP_PACA);
+ 
++  if (auxv2 & HWCAP2_SVE2) _features |= CPU_SVE2;
++  if (auxv2 & HWCAP2_SVEBITPERM) _features |= CPU_SVEBITPERM;
++
++  /*
++   * Step 2: setup _cpu, _model, _variant and _revision using READ_SPECIALREG on
++   * midr_el1 if allowed. On OpenBSD fallback to sysctl hw.model and lookup from
++   * tables.
++   */
++#ifdef __FreeBSD__
++  uint32_t midr = READ_SPECIALREG(midr_el1);
++  _cpu = CPU_IMPL(midr);
++  _model = CPU_PART(midr);
++  _variant = CPU_VAR(midr);
++  _revision = CPU_REV(midr);
++#else
++  /* On OpenBSD READ_SPECIALREG is only available if HWCAP_CPUID is set */
++  if (auxv & HWCAP_CPUID) {
++    uint32_t midr = READ_SPECIALREG(midr_el1);
++    _cpu = CPU_IMPL(midr);
++    _model = CPU_PART(midr);
++    _variant = CPU_VAR(midr);
++    _revision = CPU_REV(midr);
++  } else {
++    lookup_cpu(_cpu, _model, _variant, _revision);
++  }
++#endif // __FreeBSD__
++#endif // __FreeBSD__ || __OpenBSD__
++
++  /*
++   * Step 3: Get cache line sizes and _zva_length using same approach as Linux.
++   */
+   uint64_t ctr_el0;
+   uint64_t dczid_el0;
+   __asm__ (
Index: 25/Makefile
===================================================================
RCS file: /cvs/ports/devel/jdk/25/Makefile,v
diff -u -p -u -r1.3 Makefile
--- 25/Makefile	13 Nov 2025 22:48:44 -0000	1.3
+++ 25/Makefile	16 Dec 2025 19:33:50 -0000
@@ -12,6 +12,7 @@ PACKAGE_VER=	${BASE_VER}.${BUILD_VER}.${
 PKGNAME=	jdk-${PACKAGE_VER}
 PKGSTEM=	jdk-25
 EPOCH=		0
+REVISION=	0
 
 DIST_SUBDIR=	jdk
 DISTNAME=	jdk-${VERSION_STR}
Index: 25/patches/patch-src_hotspot_os_cpu_bsd_aarch64_vm_version_bsd_aarch64_cpp
===================================================================
RCS file: 25/patches/patch-src_hotspot_os_cpu_bsd_aarch64_vm_version_bsd_aarch64_cpp
diff -N 25/patches/patch-src_hotspot_os_cpu_bsd_aarch64_vm_version_bsd_aarch64_cpp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 25/patches/patch-src_hotspot_os_cpu_bsd_aarch64_vm_version_bsd_aarch64_cpp	16 Dec 2025 19:33:50 -0000
@@ -0,0 +1,541 @@
+Get hardware capablilites using elf_aux_info(3).
+Detect CPU, model, variant and revision using READ_SPECIALREG
+when HWCAP_CPUID is set, otherwise parse sysctl hw.model to
+get needed info.
+
+Index: src/hotspot/os_cpu/bsd_aarch64/vm_version_bsd_aarch64.cpp
+--- src/hotspot/os_cpu/bsd_aarch64/vm_version_bsd_aarch64.cpp.orig
++++ src/hotspot/os_cpu/bsd_aarch64/vm_version_bsd_aarch64.cpp
+@@ -135,91 +135,84 @@ bool VM_Version::is_cpu_emulated() {
+ #else // __APPLE__
+ 
+ #include <machine/armreg.h>
+-#if defined (__FreeBSD__)
+-#include <machine/elf.h>
++#if defined (__FreeBSD__) || defined (__OpenBSD__)
++#include <sys/auxv.h>
+ #endif
+ 
+-#ifndef HWCAP_ASIMD
+-#define HWCAP_ASIMD (1<<1)
+-#endif
++#define	CPU_IMPL(midr)	(((midr) >> 24) & 0xff)
++#define	CPU_PART(midr)	(((midr) >> 4) & 0xfff)
++#define	CPU_VAR(midr)	(((midr) >> 20) & 0xf)
++#define	CPU_REV(midr)	(((midr) >> 0) & 0xf)
+ 
+-#ifndef HWCAP_AES
+-#define HWCAP_AES   (1<<3)
+-#endif
++#ifdef __OpenBSD__
++// For older processors on OpenBSD READ_SPECIALREG is not supported.
++// These constants and tables allow for looking up the cpu and model.
+ 
+-#ifndef HWCAP_PMULL
+-#define HWCAP_PMULL (1<<4)
+-#endif
++#include <sys/types.h>
++#include <sys/sysctl.h>
++#include <string.h>
++#include <stdio.h>
+ 
+-#ifndef HWCAP_SHA1
+-#define HWCAP_SHA1  (1<<5)
+-#endif
+-
+-#ifndef HWCAP_SHA2
+-#define HWCAP_SHA2  (1<<6)
+-#endif
+-
+-#ifndef HWCAP_CRC32
+-#define HWCAP_CRC32 (1<<7)
+-#endif
+-
+-#ifndef HWCAP_ATOMICS
+-#define HWCAP_ATOMICS (1<<8)
+-#endif
+-
+-#ifndef ID_AA64PFR0_AdvSIMD_SHIFT
+-#define ID_AA64PFR0_AdvSIMD_SHIFT 20
+-#endif
+-
+-#ifndef ID_AA64PFR0_AdvSIMD
+-#define ID_AA64PFR0_AdvSIMD(x) ((x) & (UL(0xf) << ID_AA64PFR0_AdvSIMD_SHIFT))
+-#endif
+-
+-#ifndef ID_AA64PFR0_AdvSIMD_IMPL
+-#define ID_AA64PFR0_AdvSIMD_IMPL (UL(0x0) << ID_AA64PFR0_AdvSIMD_SHIFT)
+-#endif
+-
+-#ifndef ID_AA64PFR0_AdvSIMD_HP
+-#define ID_AA64PFR0_AdvSIMD_HP (UL(0x1) << ID_AA64PFR0_AdvSIMD_SHIFT)
+-#endif
+-
+-#ifndef ID_AA64ISAR0_AES_VAL
+-#define ID_AA64ISAR0_AES_VAL ID_AA64ISAR0_AES
+-#endif
+-
+-#ifndef ID_AA64ISAR0_SHA1_VAL
+-#define ID_AA64ISAR0_SHA1_VAL ID_AA64ISAR0_SHA1
+-#endif
+-
+-#ifndef ID_AA64ISAR0_SHA2_VAL
+-#define ID_AA64ISAR0_SHA2_VAL ID_AA64ISAR0_SHA2
+-#endif
+-
+-#ifndef ID_AA64ISAR0_CRC32_VAL
+-#define ID_AA64ISAR0_CRC32_VAL ID_AA64ISAR0_CRC32
+-#endif
+-
+ #define	CPU_IMPL_ARM		0x41
+ #define	CPU_IMPL_BROADCOM	0x42
+ #define	CPU_IMPL_CAVIUM		0x43
+ #define	CPU_IMPL_DEC		0x44
++#define	CPU_IMPL_FUJITSU	0x46
++#define	CPU_IMPL_HISILICON	0x48
+ #define	CPU_IMPL_INFINEON	0x49
+ #define	CPU_IMPL_FREESCALE	0x4D
+ #define	CPU_IMPL_NVIDIA		0x4E
+ #define	CPU_IMPL_APM		0x50
+ #define	CPU_IMPL_QUALCOMM	0x51
+ #define	CPU_IMPL_MARVELL	0x56
++#define	CPU_IMPL_APPLE		0x61
+ #define	CPU_IMPL_INTEL		0x69
++#define	CPU_IMPL_AMPERE		0xC0
++#define	CPU_IMPL_MICROSOFT	0x6D
+ 
+ /* ARM Part numbers */
+ #define	CPU_PART_FOUNDATION	0xD00
+-#define	CPU_PART_CORTEX_A35	0xD04
++#define	CPU_PART_CORTEX_A34	0xD02
+ #define	CPU_PART_CORTEX_A53	0xD03
++#define	CPU_PART_CORTEX_A35	0xD04
+ #define	CPU_PART_CORTEX_A55	0xD05
++#define	CPU_PART_CORTEX_A65	0xD06
+ #define	CPU_PART_CORTEX_A57	0xD07
+ #define	CPU_PART_CORTEX_A72	0xD08
+ #define	CPU_PART_CORTEX_A73	0xD09
+ #define	CPU_PART_CORTEX_A75	0xD0A
++#define	CPU_PART_CORTEX_A76	0xD0B
++#define	CPU_PART_NEOVERSE_N1	0xD0C
++#define	CPU_PART_CORTEX_A77	0xD0D
++#define	CPU_PART_CORTEX_A76AE	0xD0E
++#define	CPU_PART_AEM_V8		0xD0F
++#define	CPU_PART_NEOVERSE_V1	0xD40
++#define	CPU_PART_CORTEX_A78	0xD41
++#define	CPU_PART_CORTEX_A78AE	0xD42
++#define	CPU_PART_CORTEX_A65AE	0xD43
++#define	CPU_PART_CORTEX_X1	0xD44
++#define	CPU_PART_CORTEX_A510	0xD46
++#define	CPU_PART_CORTEX_A710	0xD47
++#define	CPU_PART_CORTEX_X2	0xD48
++#define	CPU_PART_NEOVERSE_N2	0xD49
++#define	CPU_PART_NEOVERSE_E1	0xD4A
++#define	CPU_PART_CORTEX_A78C	0xD4B
++#define	CPU_PART_CORTEX_X1C	0xD4C
++#define	CPU_PART_CORTEX_A715	0xD4D
++#define	CPU_PART_CORTEX_X3	0xD4E
++#define	CPU_PART_NEOVERSE_V2	0xD4F
++#define	CPU_PART_CORTEX_A520	0xD80
++#define	CPU_PART_CORTEX_A720	0xD81
++#define	CPU_PART_CORTEX_X4	0xD82
++#define	CPU_PART_NEOVERSE_V3AE	0xD83
++#define	CPU_PART_NEOVERSE_V3	0xD84
++#define	CPU_PART_CORTEX_X925	0xD85
++#define	CPU_PART_CORTEX_A725	0xD87
++#define	CPU_PART_C1_NANO	0xD8A
++#define	CPU_PART_C1_PRO		0xD8B
++#define	CPU_PART_C1_ULTRA	0xD8C
++#define	CPU_PART_NEOVERSE_N3	0xD8E
++#define	CPU_PART_C1_PREMIUM	0xD90
+ 
+ /* Cavium Part numbers */
+ #define	CPU_PART_THUNDERX	0x0A1
+@@ -232,21 +225,35 @@ bool VM_Version::is_cpu_emulated() {
+ 
+ #define	CPU_REV_THUNDERX2_0	0x00
+ 
+-#define	CPU_IMPL(midr)	(((midr) >> 24) & 0xff)
+-#define	CPU_PART(midr)	(((midr) >> 4) & 0xfff)
+-#define	CPU_VAR(midr)	(((midr) >> 20) & 0xf)
+-#define	CPU_REV(midr)	(((midr) >> 0) & 0xf)
+-#define UL(x)   UINT64_C(x)
++/* APM (now Ampere) Part number */
++#define CPU_PART_EMAG8180	0x000
+ 
+-struct cpu_desc {
+-	u_int		cpu_impl;
+-	u_int		cpu_part_num;
+-	u_int		cpu_variant;
+-	u_int		cpu_revision;
+-	const char	*cpu_impl_name;
+-	const char	*cpu_part_name;
+-};
++/* Ampere Part numbers */
++#define	CPU_PART_AMPERE1	0xAC3
++#define	CPU_PART_AMPERE1A	0xAC4
+ 
++/* Microsoft Part numbers */
++#define	CPU_PART_AZURE_COBALT_100	0xD49
++
++/* Qualcomm */
++#define CPU_PART_ORYON          0x001
++#define	CPU_PART_KRYO400_GOLD	0x804
++#define	CPU_PART_KRYO400_SILVER	0x805
++
++/* Apple part numbers */
++#define CPU_PART_M1_ICESTORM      0x022
++#define CPU_PART_M1_FIRESTORM     0x023
++#define CPU_PART_M1_ICESTORM_PRO  0x024
++#define CPU_PART_M1_FIRESTORM_PRO 0x025
++#define CPU_PART_M1_ICESTORM_MAX  0x028
++#define CPU_PART_M1_FIRESTORM_MAX 0x029
++#define CPU_PART_M2_BLIZZARD      0x032
++#define CPU_PART_M2_AVALANCHE     0x033
++#define CPU_PART_M2_BLIZZARD_PRO  0x034
++#define CPU_PART_M2_AVALANCHE_PRO 0x035
++#define CPU_PART_M2_BLIZZARD_MAX  0x038
++#define CPU_PART_M2_AVALANCHE_MAX 0x039
++
+ struct cpu_parts {
+ 	u_int		part_id;
+ 	const char	*part_name;
+@@ -267,136 +274,212 @@ struct cpu_implementers {
+ /*
+  * Per-implementer table of (PartNum, CPU Name) pairs.
+  */
+-/* ARM Ltd. */
++/* ARM Ltd. From FreeBSD but using OpenBSD strings */
+ static const struct cpu_parts cpu_parts_arm[] = {
++	{ CPU_PART_AEM_V8, "AEMv8" },
+ 	{ CPU_PART_FOUNDATION, "Foundation-Model" },
++	{ CPU_PART_CORTEX_A34, "Cortex-A34" },
+ 	{ CPU_PART_CORTEX_A35, "Cortex-A35" },
+ 	{ CPU_PART_CORTEX_A53, "Cortex-A53" },
+ 	{ CPU_PART_CORTEX_A55, "Cortex-A55" },
+ 	{ CPU_PART_CORTEX_A57, "Cortex-A57" },
++	{ CPU_PART_CORTEX_A65, "Cortex-A65" },
++	{ CPU_PART_CORTEX_A65AE, "Cortex-A65AE" },
+ 	{ CPU_PART_CORTEX_A72, "Cortex-A72" },
+ 	{ CPU_PART_CORTEX_A73, "Cortex-A73" },
+ 	{ CPU_PART_CORTEX_A75, "Cortex-A75" },
++	{ CPU_PART_CORTEX_A76, "Cortex-A76" },
++	{ CPU_PART_CORTEX_A76AE, "Cortex-A76AE" },
++	{ CPU_PART_CORTEX_A77, "Cortex-A77" },
++	{ CPU_PART_CORTEX_A78, "Cortex-A78" },
++	{ CPU_PART_CORTEX_A78AE, "Cortex-A78AE" },
++	{ CPU_PART_CORTEX_A78C, "Cortex-A78C" },
++	{ CPU_PART_CORTEX_A510, "Cortex-A510" },
++	{ CPU_PART_CORTEX_A520, "Cortex-A520" },
++	{ CPU_PART_CORTEX_A710, "Cortex-A710" },
++	{ CPU_PART_CORTEX_A715, "Cortex-A715" },
++	{ CPU_PART_CORTEX_A720, "Cortex-A720" },
++	{ CPU_PART_CORTEX_A725, "Cortex-A725" },
++	{ CPU_PART_CORTEX_X925, "Cortex-A925" },
++	{ CPU_PART_CORTEX_X1C, "Cortex-X1C" },
++	{ CPU_PART_CORTEX_X1, "Cortex-X1" },
++	{ CPU_PART_CORTEX_X2, "Cortex-X2" },
++	{ CPU_PART_CORTEX_X3, "Cortex-X3" },
++	{ CPU_PART_CORTEX_X4, "Cortex-X4" },
++	{ CPU_PART_C1_NANO, "C1-Nano" },
++	{ CPU_PART_C1_PRO, "C1-Pro" },
++	{ CPU_PART_C1_PREMIUM, "C1-Premium" },
++	{ CPU_PART_C1_ULTRA, "C1-Ultra" },
++	{ CPU_PART_NEOVERSE_E1, "Neoverse E1" },
++	{ CPU_PART_NEOVERSE_N1, "Neoverse N1" },
++	{ CPU_PART_NEOVERSE_N2, "Neoverse N2" },
++	{ CPU_PART_NEOVERSE_N3, "Neoverse N3" },
++	{ CPU_PART_NEOVERSE_V1, "Neoverse V1" },
++	{ CPU_PART_NEOVERSE_V2, "Neoverse V2" },
++	{ CPU_PART_NEOVERSE_V3, "Neoverse V3" },
++	{ CPU_PART_NEOVERSE_V3AE, "Neoverse V3AE" },
+ 	CPU_PART_NONE,
+ };
+-/* Cavium */
++
++/* Cavium  From FreeBSD but using OpenBSD strings */
+ static const struct cpu_parts cpu_parts_cavium[] = {
+-	{ CPU_PART_THUNDERX, "ThunderX" },
+-	{ CPU_PART_THUNDERX2, "ThunderX2" },
++	{ CPU_PART_THUNDERX, "ThunderX T88" },
++	{ CPU_PART_THUNDERX_81XX, "ThunderX T81" },
++	{ CPU_PART_THUNDERX_83XX, "ThunderX T83" },
++	{ CPU_PART_THUNDERX2, "ThunderX2 T99" },
+ 	CPU_PART_NONE,
+ };
+ 
++/* APM (now Ampere), From FreeBSD but using OpenBSD strings */
++static const struct cpu_parts cpu_parts_apm[] = {
++	{ CPU_PART_EMAG8180, "X-Gene" },
++	CPU_PART_NONE,
++};
++
++/* Ampere From FreeBSD, but using OpenBSD strings */
++static const struct cpu_parts cpu_parts_ampere[] = {
++	{ CPU_PART_AMPERE1A, "AmpereOne AC04" },
++	{ CPU_PART_AMPERE1, "AmpereOne" },
++	CPU_PART_NONE,
++};
++
++/* Microsoft */
++static const struct cpu_parts cpu_parts_microsoft[] = {
++	{ CPU_PART_AZURE_COBALT_100, "Azure Cobalt 100" },
++	CPU_PART_NONE,
++};
++
++/* Qualcomm From FreeBSD & OpenBSD. */
++static const struct cpu_parts cpu_parts_qcom[] = {
++	{ CPU_PART_KRYO400_GOLD, "Kryo 400 Gold" },
++	{ CPU_PART_KRYO400_SILVER, "Kryo 400 Silver" },
++	{ CPU_PART_ORYON, "Oryon" },
++	CPU_PART_NONE,
++};
++
++/* Apple. From FreeBSD but using OpenBSD strings */
++static const struct cpu_parts cpu_parts_apple[] = {
++	{ CPU_PART_M1_ICESTORM, "Icestorm" },
++	{ CPU_PART_M1_FIRESTORM, "Firestorm" },
++	{ CPU_PART_M1_ICESTORM_PRO, "Icestorm Pro" },
++	{ CPU_PART_M1_FIRESTORM_PRO, "Firestorm Pro" },
++	{ CPU_PART_M1_ICESTORM_MAX, "Icestorm Max" },
++	{ CPU_PART_M1_FIRESTORM_MAX, "Firestorm Max" },
++	{ CPU_PART_M2_BLIZZARD, "Blizzard" },
++	{ CPU_PART_M2_AVALANCHE, "Avalanche" },
++	{ CPU_PART_M2_BLIZZARD_PRO, "Blizzard Pro" },
++	{ CPU_PART_M2_AVALANCHE_PRO, "Avalanche Pro" },
++	{ CPU_PART_M2_BLIZZARD_MAX, "Blizzard Max" },
++	{ CPU_PART_M2_AVALANCHE_MAX, "Avalanche Max" },
++	CPU_PART_NONE,
++};
++
+ /* Unknown */
+ static const struct cpu_parts cpu_parts_none[] = {
+ 	CPU_PART_NONE,
+ };
+ 
+ /*
+- * Implementers table.
++ * Implementers table. From FreeBSD, but using OpenBSD strings
+  */
+ const struct cpu_implementers cpu_implementers[] = {
++	{ CPU_IMPL_AMPERE,	"Ampere",	cpu_parts_ampere },
++	{ CPU_IMPL_APPLE,	"Apple",	cpu_parts_apple },
++	{ CPU_IMPL_APM,		"Applied Micro",cpu_parts_apm },
+ 	{ CPU_IMPL_ARM,		"ARM",		cpu_parts_arm },
+ 	{ CPU_IMPL_BROADCOM,	"Broadcom",	cpu_parts_none },
+ 	{ CPU_IMPL_CAVIUM,	"Cavium",	cpu_parts_cavium },
+ 	{ CPU_IMPL_DEC,		"DEC",		cpu_parts_none },
+-	{ CPU_IMPL_INFINEON,	"IFX",		cpu_parts_none },
+ 	{ CPU_IMPL_FREESCALE,	"Freescale",	cpu_parts_none },
+-	{ CPU_IMPL_NVIDIA,	"NVIDIA",	cpu_parts_none },
+-	{ CPU_IMPL_APM,		"APM",		cpu_parts_none },
+-	{ CPU_IMPL_QUALCOMM,	"Qualcomm",	cpu_parts_none },
+-	{ CPU_IMPL_MARVELL,	"Marvell",	cpu_parts_none },
++	{ CPU_IMPL_FUJITSU,	"Fujitsu",	cpu_parts_none },
++	{ CPU_IMPL_HISILICON,	"HiSilicon",	cpu_parts_none },
++	{ CPU_IMPL_INFINEON,	"IFX",		cpu_parts_none },
+ 	{ CPU_IMPL_INTEL,	"Intel",	cpu_parts_none },
++	{ CPU_IMPL_MARVELL,	"Marvell",	cpu_parts_none },
++	{ CPU_IMPL_MICROSOFT,	"Microsoft",	cpu_parts_microsoft },
++	{ CPU_IMPL_NVIDIA,	"NVIDIA",	cpu_parts_none },
++	{ CPU_IMPL_QUALCOMM,	"Qualcomm",	cpu_parts_qcom },
+ 	CPU_IMPLEMENTER_NONE,
+ };
+ 
+-#ifdef __FreeBSD__
+-static unsigned long os_get_processor_features() {
+-  unsigned long auxv = 0;
+-  uint64_t id_aa64isar0, id_aa64pfr0;
++static void
++lookup_cpu(int &_cpu, int &_model, int &_variant, int &_revision) {
++  int mib[] = { CTL_HW, HW_MODEL };
++  char descr[BUFSIZ];
++  char *part_name, *rv_str;
++  size_t descr_len = sizeof(descr);
++  size_t impl_name_len;
++  const struct cpu_parts *cpu_partsp = nullptr;
++  size_t i;
+ 
+-  id_aa64isar0 = READ_SPECIALREG(id_aa64isar0_el1);
+-  id_aa64pfr0 = READ_SPECIALREG(id_aa64pfr0_el1);
++  if (sysctl(mib, nitems(mib), &descr, &descr_len, NULL, 0) == -1)
++    return;
+ 
+-  if (ID_AA64ISAR0_AES_VAL(id_aa64isar0) == ID_AA64ISAR0_AES_BASE) {
+-    auxv = auxv | HWCAP_AES;
++  for (i = 0; i < nitems(cpu_implementers); i++) {
++    impl_name_len = strlen(cpu_implementers[i].impl_name);
++    if (cpu_implementers[i].impl_id == 0 ||
++      strncmp(descr, cpu_implementers[i].impl_name, impl_name_len) == 0) {
++      _cpu = cpu_implementers[i].impl_id;
++      cpu_partsp = cpu_implementers[i].cpu_parts;
++      break;
++    }
+   }
+ 
+-  if (ID_AA64ISAR0_AES_VAL(id_aa64isar0) == ID_AA64ISAR0_AES_PMULL) {
+-    auxv = auxv | HWCAP_PMULL;
+-  }
++  if (_cpu == 0)
++    return;
+ 
+-  if (ID_AA64ISAR0_SHA1_VAL(id_aa64isar0) == ID_AA64ISAR0_SHA1_BASE) {
+-    auxv = auxv | HWCAP_SHA1;
+-  }
++  // +1 to skip space +1 more because descr_len includes NUL
++  if (impl_name_len + 2 > descr_len)
++    return;
+ 
+-  if (ID_AA64ISAR0_SHA2_VAL(id_aa64isar0) == ID_AA64ISAR0_SHA2_BASE) {
+-    auxv = auxv | HWCAP_SHA2;
+-  }
++  part_name = &descr[impl_name_len+1];
+ 
+-  if (ID_AA64ISAR0_CRC32_VAL(id_aa64isar0) == ID_AA64ISAR0_CRC32_BASE) {
+-    auxv = auxv | HWCAP_CRC32;
+-  }
++  rv_str = strrchr(part_name, ' ');
++  if (rv_str == nullptr)
++    return;
+ 
+-  if (ID_AA64PFR0_AdvSIMD(id_aa64pfr0) == ID_AA64PFR0_AdvSIMD_IMPL || \
+-      ID_AA64PFR0_AdvSIMD(id_aa64pfr0) == ID_AA64PFR0_AdvSIMD_HP ) {
+-    auxv = auxv | HWCAP_ASIMD;
+-  }
++  // null term part_name and skip over it
++  *(rv_str++) = '\0';
+ 
+-  return auxv;
+-}
+-#endif
+-
+-void VM_Version::get_os_cpu_info() {
+-#ifdef __OpenBSD__
+-  // READ_SPECIALREG is not available from userland on OpenBSD.
+-  // Hardcode these values to the "lowest common denominator"
+-  _cpu = CPU_IMPL_ARM;
+-  _model = CPU_PART_CORTEX_A53;
+-  _variant = 0;
+-  _revision = 0;
+-  _features = HWCAP_ASIMD;
+-#elif defined(__FreeBSD__)
+-  struct cpu_desc cpu_desc[1];
+-  struct cpu_desc user_cpu_desc;
+-
+-  uint32_t midr;
+-  uint32_t impl_id;
+-  uint32_t part_id;
+-  uint32_t cpu = 0;
+-  size_t i;
+-  const struct cpu_parts *cpu_partsp = nullptr;
+-
+-  midr = READ_SPECIALREG(midr_el1);
+-
+-  impl_id = CPU_IMPL(midr);
+-  for (i = 0; i < nitems(cpu_implementers); i++) {
+-    if (impl_id == cpu_implementers[i].impl_id ||
+-      cpu_implementers[i].impl_id == 0) {
+-      cpu_desc[cpu].cpu_impl = impl_id;
+-      cpu_desc[cpu].cpu_impl_name = cpu_implementers[i].impl_name;
+-      cpu_partsp = cpu_implementers[i].cpu_parts;
+-      break;
+-    }
+-  }
+-  part_id = CPU_PART(midr);
+   for (i = 0; &cpu_partsp[i] != nullptr; i++) {
+-    if (part_id == cpu_partsp[i].part_id || cpu_partsp[i].part_id == 0) {
+-      cpu_desc[cpu].cpu_part_num = part_id;
+-      cpu_desc[cpu].cpu_part_name = cpu_partsp[i].part_name;
++    if (cpu_partsp[i].part_id == 0 ||
++      strcmp(part_name, cpu_partsp[i].part_name) == 0) {
++      _model = cpu_partsp[i].part_id;
+       break;
+     }
+   }
+ 
+-  cpu_desc[cpu].cpu_revision = CPU_REV(midr);
+-  cpu_desc[cpu].cpu_variant = CPU_VAR(midr);
++  sscanf(rv_str, "r%up%u", &_variant, &_revision);
++}
++#endif // __OpenBSD__
+ 
+-  _cpu = cpu_desc[cpu].cpu_impl;
+-  _variant = cpu_desc[cpu].cpu_variant;
+-  _model = cpu_desc[cpu].cpu_part_num;
+-  _revision = cpu_desc[cpu].cpu_revision;
++void VM_Version::get_os_cpu_info() {
++#if defined(__FreeBSD__) || defined(__OpenBSD__)
+ 
+-  uint64_t auxv = os_get_processor_features();
++  /*
++   * Step 1: setup _features using elf_aux_info(3). Keep in sync with Linux.
++   */
++  unsigned long auxv = 0;
++  unsigned long auxv2 = 0;
++  elf_aux_info(AT_HWCAP, &auxv, sizeof(auxv));
++  elf_aux_info(AT_HWCAP2, &auxv2, sizeof(auxv2));
+ 
++  static_assert(CPU_FP      == HWCAP_FP,      "Flag CPU_FP must follow HWCAP");
++  static_assert(CPU_ASIMD   == HWCAP_ASIMD,   "Flag CPU_ASIMD must follow HWCAP");
++  static_assert(CPU_EVTSTRM == HWCAP_EVTSTRM, "Flag CPU_EVTSTRM must follow HWCAP");
++  static_assert(CPU_AES     == HWCAP_AES,     "Flag CPU_AES must follow HWCAP");
++  static_assert(CPU_PMULL   == HWCAP_PMULL,   "Flag CPU_PMULL must follow HWCAP");
++  static_assert(CPU_SHA1    == HWCAP_SHA1,    "Flag CPU_SHA1 must follow HWCAP");
++  static_assert(CPU_SHA2    == HWCAP_SHA2,    "Flag CPU_SHA2 must follow HWCAP");
++  static_assert(CPU_CRC32   == HWCAP_CRC32,   "Flag CPU_CRC32 must follow HWCAP");
++  static_assert(CPU_LSE     == HWCAP_ATOMICS, "Flag CPU_LSE must follow HWCAP");
++  static_assert(CPU_DCPOP   == HWCAP_DCPOP,   "Flag CPU_DCPOP must follow HWCAP");
++  static_assert(CPU_SHA3    == HWCAP_SHA3,    "Flag CPU_SHA3 must follow HWCAP");
++  static_assert(CPU_SHA512  == HWCAP_SHA512,  "Flag CPU_SHA512 must follow HWCAP");
++  static_assert(CPU_SVE     == HWCAP_SVE,     "Flag CPU_SVE must follow HWCAP");
++  static_assert(CPU_PACA    == HWCAP_PACA,    "Flag CPU_PACA must follow HWCAP");
++  static_assert(CPU_FPHP    == HWCAP_FPHP,    "Flag CPU_FPHP must follow HWCAP");
++  static_assert(CPU_ASIMDHP == HWCAP_ASIMDHP, "Flag CPU_ASIMDHP must follow HWCAP");
+   _features = auxv & (
+       HWCAP_FP      |
+       HWCAP_ASIMD   |
+@@ -410,9 +493,42 @@ void VM_Version::get_os_cpu_info() {
+       HWCAP_DCPOP   |
+       HWCAP_SHA3    |
+       HWCAP_SHA512  |
+-      HWCAP_SVE);
+-#endif
++      HWCAP_SVE     |
++      HWCAP_PACA    |
++      HWCAP_FPHP    |
++      HWCAP_ASIMDHP);
+ 
++  if (auxv2 & HWCAP2_SVE2) _features |= CPU_SVE2;
++  if (auxv2 & HWCAP2_SVEBITPERM) _features |= CPU_SVEBITPERM;
++
++  /*
++   * Step 2: setup _cpu, _model, _variant and _revision using READ_SPECIALREG on
++   * midr_el1 if allowed. On OpenBSD fallback to sysctl hw.model and lookup from
++   * tables.
++   */
++#ifdef __FreeBSD__
++  uint32_t midr = READ_SPECIALREG(midr_el1);
++  _cpu = CPU_IMPL(midr);
++  _model = CPU_PART(midr);
++  _variant = CPU_VAR(midr);
++  _revision = CPU_REV(midr);
++#else
++  /* On OpenBSD READ_SPECIALREG is only available if HWCAP_CPUID is set */
++  if (auxv & HWCAP_CPUID) {
++    uint32_t midr = READ_SPECIALREG(midr_el1);
++    _cpu = CPU_IMPL(midr);
++    _model = CPU_PART(midr);
++    _variant = CPU_VAR(midr);
++    _revision = CPU_REV(midr);
++  } else {
++    lookup_cpu(_cpu, _model, _variant, _revision);
++  }
++#endif // __FreeBSD__
++#endif // __FreeBSD__ || __OpenBSD__
++
++  /*
++   * Step 3: Get cache line sizes and _zva_length using same approach as Linux.
++   */
+   uint64_t ctr_el0;
+   uint64_t dczid_el0;
+   __asm__ (