diff --git a/sys/arm64/arm64/locore.S b/sys/arm64/arm64/locore.S --- a/sys/arm64/arm64/locore.S +++ b/sys/arm64/arm64/locore.S @@ -940,20 +940,17 @@ bfi x2, x3, #(TCR_ASID_SHIFT), #(TCR_ASID_WIDTH) /* - * Check if the HW supports access flag and dirty state updates, - * and set TCR_EL1.HA and TCR_EL1.HD accordingly. + * Check if the HW supports access flag updates, and set + * TCR_EL1.HA accordingly. The TCR_EL1.HD flag to enable + * HW management of dirty state is set in C code as it may + * need to be disabled because of CPU errata. */ mrs x3, id_aa64mmfr1_el1 and x3, x3, #(ID_AA64MMFR1_HAFDBS_MASK) - cmp x3, #1 - b.ne 1f - orr x2, x2, #(TCR_HA) - b 2f + cbz x3, 1f + orr x2, x2, #(TCR_HA) 1: - cmp x3, #2 - b.ne 2f - orr x2, x2, #(TCR_HA | TCR_HD) -2: + msr tcr_el1, x2 /* diff --git a/sys/arm64/arm64/mp_machdep.c b/sys/arm64/arm64/mp_machdep.c --- a/sys/arm64/arm64/mp_machdep.c +++ b/sys/arm64/arm64/mp_machdep.c @@ -219,6 +219,7 @@ pcpup = cpuid_to_pcpu[cpu]; pcpup->pc_midr = get_midr(); identify_cpu(cpu); + pmap_cpu_init(); /* Ensure the stores in identify_cpu have completed */ atomic_thread_fence_acq_rel(); diff --git a/sys/arm64/arm64/pmap.c b/sys/arm64/arm64/pmap.c --- a/sys/arm64/arm64/pmap.c +++ b/sys/arm64/arm64/pmap.c @@ -1309,6 +1309,8 @@ vm_paddr_t start_pa, pa; uint64_t tcr; + pmap_cpu_init(); + tcr = READ_SPECIALREG(tcr_el1); /* Verify that the ASID is set through TTBR0. */ @@ -1623,6 +1625,25 @@ } } +void +pmap_cpu_init(void) +{ + uint64_t id_aa64mmfr1, tcr; + + /* Enable HAFDBS if supported */ + id_aa64mmfr1 = READ_SPECIALREG(id_aa64mmfr1_el1); + if (ID_AA64MMFR1_HAFDBS_VAL(id_aa64mmfr1) >=ID_AA64MMFR1_HAFDBS_AF_DBS){ + tcr = READ_SPECIALREG(tcr_el1) | TCR_HD; + WRITE_SPECIALREG(tcr_el1, tcr); + isb(); + /* Flush the local TLB for the TCR_HD flag change */ + dsb(nshst); + __asm __volatile("tlbi vmalle1"); + dsb(nsh); + isb(); + } +} + /* * Initialize the pmap module. * diff --git a/sys/arm64/include/pmap.h b/sys/arm64/include/pmap.h --- a/sys/arm64/include/pmap.h +++ b/sys/arm64/include/pmap.h @@ -140,6 +140,7 @@ void pmap_activate_vm(pmap_t); void pmap_bootstrap(vm_size_t); +void pmap_cpu_init(void); int pmap_change_attr(vm_offset_t va, vm_size_t size, int mode); int pmap_change_prot(vm_offset_t va, vm_size_t size, vm_prot_t prot); void pmap_kenter(vm_offset_t sva, vm_size_t size, vm_paddr_t pa, int mode);