zircon/kernel/arch/arm64/feature.cc
// call on every cpu to save features
call on every cpu to save features
call on every cpu to save features
void arm64_feature_init() {
  cpu_num_t cpu = arch_curr_cpu_num();
  if (cpu == 0) {
    uint64_t dczid = __arm_rsr64("dczid_el0");
    uint32_t arm64_zva_shift = 0;
    if (BIT(dczid, 4) == 0) {
      arm64_zva_shift = (uint32_t)(__arm_rsr64("dczid_el0") & 0xf) + 2;
    }
    ASSERT(arm64_zva_shift != 0);  
    arm64_zva_size = (1u << arm64_zva_shift);
    uint64_t ctr = __arm_rsr64("ctr_el0");
    uint32_t arm64_dcache_shift = (uint32_t)BITS_SHIFT(ctr, 19, 16) + 2;
    arm64_dcache_size = (1u << arm64_dcache_shift);
    uint32_t arm64_icache_shift = (uint32_t)BITS(ctr, 3, 0) + 2;
    arm64_icache_size = (1u << arm64_icache_shift);
    arm64_isa_features |= ZX_HAS_CPU_FEATURES;
    uint64_t isar0 = __arm_rsr64("id_aa64isar0_el1");
    if (BITS_SHIFT(isar0, 7, 4) >= 1) {
      arm64_isa_features |= ZX_ARM64_FEATURE_ISA_AES;
    }
    if (BITS_SHIFT(isar0, 7, 4) >= 2) {
      arm64_isa_features |= ZX_ARM64_FEATURE_ISA_PMULL;
    }
    if (BITS_SHIFT(isar0, 11, 8) >= 1) {
      arm64_isa_features |= ZX_ARM64_FEATURE_ISA_SHA1;
    }
    if (BITS_SHIFT(isar0, 15, 12) >= 1) {
      arm64_isa_features |= ZX_ARM64_FEATURE_ISA_SHA2;
    }
    if (BITS_SHIFT(isar0, 19, 16) >= 1) {
      arm64_isa_features |= ZX_ARM64_FEATURE_ISA_CRC32;
    }
    if (BITS_SHIFT(isar0, 23, 20) >= 1) {
      arm64_isa_features |= ZX_ARM64_FEATURE_ISA_ATOMICS;
    }
    if (BITS_SHIFT(isar0, 31, 28) >= 1) {
      arm64_isa_features |= ZX_ARM64_FEATURE_ISA_RDM;
    }
    if (BITS_SHIFT(isar0, 35, 32) >= 1) {
      arm64_isa_features |= ZX_ARM64_FEATURE_ISA_SHA3;
    }
    if (BITS_SHIFT(isar0, 39, 36) >= 1) {
      arm64_isa_features |= ZX_ARM64_FEATURE_ISA_SM3;
    }
    if (BITS_SHIFT(isar0, 43, 40) >= 1) {
      arm64_isa_features |= ZX_ARM64_FEATURE_ISA_SM4;
    }
    if (BITS_SHIFT(isar0, 47, 44) >= 1) {
      arm64_isa_features |= ZX_ARM64_FEATURE_ISA_DP;
    }
    if (BITS_SHIFT(isar0, 51, 48) >= 1) {
      arm64_isa_features |= ZX_ARM64_FEATURE_ISA_FHM;
    }
    if (BITS_SHIFT(isar0, 55, 52) >= 1) {
      arm64_isa_features |= ZX_ARM64_FEATURE_ISA_TS;
    }
    if (BITS_SHIFT(isar0, 63, 60) >= 1) {
      arm64_isa_features |= ZX_ARM64_FEATURE_ISA_RNDR;
    }
    uint64_t isar1 = __arm_rsr64("id_aa64isar1_el1");
    if (BITS_SHIFT(isar1, 3, 0) >= 1) {
      arm64_isa_features |= ZX_ARM64_FEATURE_ISA_DPB;
    }
    uint64_t pfr0 = __arm_rsr64("id_aa64pfr0_el1");
    if (BITS_SHIFT(pfr0, 19, 16) < 0b1111) {
      arm64_isa_features |= ZX_ARM64_FEATURE_ISA_FP;
    }
    if (BITS_SHIFT(pfr0, 23, 20) < 0b1111) {
      arm64_isa_features |= ZX_ARM64_FEATURE_ISA_ASIMD;
    }
  }
  arm64_get_cache_info(&(cache_info[cpu]));
  uint64_t mmfr0 = __arm_rsr64("id_aa64mmfr0_el1");
  ASSERT((mmfr0 & ARM64_MMFR0_ASIDBITS_MASK) == ARM64_MMFR0_ASIDBITS_16);
}
void arm64_feature_init ( ) { cpu_num_t cpu = arch_curr_cpu_num ( ) ; if ( cpu == 0 ) { uint64_t dczid = __arm_rsr64 ( " " ) ; uint32_t arm64_zva_shift = 0 ; if ( BIT ( dczid , 4 ) == 0 ) { arm64_zva_shift = ( uint32_t ) ( __arm_rsr64 ( " " ) & 0xf ) + 2 ; } ASSERT ( arm64_zva_shift != 0 ) ; arm64_zva_size = ( 1u << arm64_zva_shift ) ; uint64_t ctr = __arm_rsr64 ( " " ) ; uint32_t arm64_dcache_shift = ( uint32_t ) BITS_SHIFT ( ctr , 19 , 16 ) + 2 ; arm64_dcache_size = ( 1u << arm64_dcache_shift ) ; uint32_t arm64_icache_shift = ( uint32_t ) BITS ( ctr , 3 , 0 ) + 2 ; arm64_icache_size = ( 1u << arm64_icache_shift ) ; arm64_isa_features |= ZX_HAS_CPU_FEATURES ; uint64_t isar0 = __arm_rsr64 ( " " ) ; if ( BITS_SHIFT ( isar0 , 7 , 4 ) >= 1 ) { arm64_isa_features |= ZX_ARM64_FEATURE_ISA_AES ; } if ( BITS_SHIFT ( isar0 , 7 , 4 ) >= 2 ) { arm64_isa_features |= ZX_ARM64_FEATURE_ISA_PMULL ; } if ( BITS_SHIFT ( isar0 , 11 , 8 ) >= 1 ) { arm64_isa_features |= ZX_ARM64_FEATURE_ISA_SHA1 ; } if ( BITS_SHIFT ( isar0 , 15 , 12 ) >= 1 ) { arm64_isa_features |= ZX_ARM64_FEATURE_ISA_SHA2 ; } if ( BITS_SHIFT ( isar0 , 19 , 16 ) >= 1 ) { arm64_isa_features |= ZX_ARM64_FEATURE_ISA_CRC32 ; } if ( BITS_SHIFT ( isar0 , 23 , 20 ) >= 1 ) { arm64_isa_features |= ZX_ARM64_FEATURE_ISA_ATOMICS ; } if ( BITS_SHIFT ( isar0 , 31 , 28 ) >= 1 ) { arm64_isa_features |= ZX_ARM64_FEATURE_ISA_RDM ; } if ( BITS_SHIFT ( isar0 , 35 , 32 ) >= 1 ) { arm64_isa_features |= ZX_ARM64_FEATURE_ISA_SHA3 ; } if ( BITS_SHIFT ( isar0 , 39 , 36 ) >= 1 ) { arm64_isa_features |= ZX_ARM64_FEATURE_ISA_SM3 ; } if ( BITS_SHIFT ( isar0 , 43 , 40 ) >= 1 ) { arm64_isa_features |= ZX_ARM64_FEATURE_ISA_SM4 ; } if ( BITS_SHIFT ( isar0 , 47 , 44 ) >= 1 ) { arm64_isa_features |= ZX_ARM64_FEATURE_ISA_DP ; } if ( BITS_SHIFT ( isar0 , 51 , 48 ) >= 1 ) { arm64_isa_features |= ZX_ARM64_FEATURE_ISA_FHM ; } if ( BITS_SHIFT ( isar0 , 55 , 52 ) >= 1 ) { arm64_isa_features |= ZX_ARM64_FEATURE_ISA_TS ; } if ( BITS_SHIFT ( isar0 , 63 , 60 ) >= 1 ) { arm64_isa_features |= ZX_ARM64_FEATURE_ISA_RNDR ; } uint64_t isar1 = __arm_rsr64 ( " " ) ; if ( BITS_SHIFT ( isar1 , 3 , 0 ) >= 1 ) { arm64_isa_features |= ZX_ARM64_FEATURE_ISA_DPB ; } uint64_t pfr0 = __arm_rsr64 ( " " ) ; if ( BITS_SHIFT ( pfr0 , 19 , 16 ) < 0b1111 ) { arm64_isa_features |= ZX_ARM64_FEATURE_ISA_FP ; } if ( BITS_SHIFT ( pfr0 , 23 , 20 ) < 0b1111 ) { arm64_isa_features |= ZX_ARM64_FEATURE_ISA_ASIMD ; } } arm64_get_cache_info ( & ( cache_info [ cpu ] ) ) ; uint64_t mmfr0 = __arm_rsr64 ( " " ) ; ASSERT ( ( mmfr0 & ARM64_MMFR0_ASIDBITS_MASK ) == ARM64_MMFR0_ASIDBITS_16 ) ; }
call on every cpu to save features
call on every cpu to save features
// set up some global constants based on the boot cpu // read the block size of DC ZVA // for now, fail if DC ZVA is unavailable // read the dcache and icache line size // parse the ISA feature bits // read the cache info for each cpu // check to make sure implementation supports 16 bit asids