be enabled. However, KVM guest also require VHE mode and hence
          CONFIG_ARM64_VHE=y option to use this feature.
 
+         If the feature is present on the boot CPU but not on a late CPU, then
+         the late CPU will be parked. Also, if the boot CPU does not have
+         address auth and the late CPU has then the late CPU will still boot
+         but with the feature disabled. On such a system, this option should
+         not be selected.
+
 endmenu
 
 menu "ARMv8.5 architectural features"
 
 #define ARM64_CPUCAP_STRICT_BOOT_CPU_FEATURE           \
        (ARM64_CPUCAP_SCOPE_BOOT_CPU | ARM64_CPUCAP_PANIC_ON_CONFLICT)
 
+/*
+ * CPU feature used early in the boot based on the boot CPU. It is safe for a
+ * late CPU to have this feature even though the boot CPU hasn't enabled it,
+ * although the feature will not be used by Linux in this case. If the boot CPU
+ * has enabled this feature already, then every late CPU must have it.
+ */
+#define ARM64_CPUCAP_BOOT_CPU_FEATURE                  \
+       (ARM64_CPUCAP_SCOPE_BOOT_CPU | ARM64_CPUCAP_PERMITTED_FOR_LATE_CPU)
+
 struct arm64_cpu_capabilities {
        const char *desc;
        u16 capability;
 
 #endif /* CONFIG_ARM64_RAS_EXTN */
 
 #ifdef CONFIG_ARM64_PTR_AUTH
-static void cpu_enable_address_auth(struct arm64_cpu_capabilities const *cap)
-{
-       sysreg_clear_set(sctlr_el1, 0, SCTLR_ELx_ENIA | SCTLR_ELx_ENIB |
-                                      SCTLR_ELx_ENDA | SCTLR_ELx_ENDB);
-}
-
 static bool has_address_auth(const struct arm64_cpu_capabilities *entry,
                             int __unused)
 {
        {
                .desc = "Address authentication (architected algorithm)",
                .capability = ARM64_HAS_ADDRESS_AUTH_ARCH,
-               .type = ARM64_CPUCAP_SYSTEM_FEATURE,
+               .type = ARM64_CPUCAP_BOOT_CPU_FEATURE,
                .sys_reg = SYS_ID_AA64ISAR1_EL1,
                .sign = FTR_UNSIGNED,
                .field_pos = ID_AA64ISAR1_APA_SHIFT,
        {
                .desc = "Address authentication (IMP DEF algorithm)",
                .capability = ARM64_HAS_ADDRESS_AUTH_IMP_DEF,
-               .type = ARM64_CPUCAP_SYSTEM_FEATURE,
+               .type = ARM64_CPUCAP_BOOT_CPU_FEATURE,
                .sys_reg = SYS_ID_AA64ISAR1_EL1,
                .sign = FTR_UNSIGNED,
                .field_pos = ID_AA64ISAR1_API_SHIFT,
        },
        {
                .capability = ARM64_HAS_ADDRESS_AUTH,
-               .type = ARM64_CPUCAP_SYSTEM_FEATURE,
+               .type = ARM64_CPUCAP_BOOT_CPU_FEATURE,
                .matches = has_address_auth,
-               .cpu_enable = cpu_enable_address_auth,
        },
        {
                .desc = "Generic authentication (architected algorithm)",
 
 #include <asm/pgtable-hwdef.h>
 #include <asm/cpufeature.h>
 #include <asm/alternative.h>
+#include <asm/smp.h>
 
 #ifdef CONFIG_ARM64_64K_PAGES
 #define TCR_TG_FLAGS   TCR_TG0_64K | TCR_TG1_64K
 1:
 #endif /* CONFIG_ARM64_HW_AFDBM */
        msr     tcr_el1, x10
+       mov     x1, x0
        /*
         * Prepare SCTLR
         */
        mov_q   x0, SCTLR_EL1_SET
+
+#ifdef CONFIG_ARM64_PTR_AUTH
+       /* No ptrauth setup for run time cpus */
+       cmp     x1, #ARM64_CPU_RUNTIME
+       b.eq    3f
+
+       /* Check if the CPU supports ptrauth */
+       mrs     x2, id_aa64isar1_el1
+       ubfx    x2, x2, #ID_AA64ISAR1_APA_SHIFT, #8
+       cbz     x2, 3f
+
+       msr_s   SYS_APIAKEYLO_EL1, xzr
+       msr_s   SYS_APIAKEYHI_EL1, xzr
+
+       /* Just enable ptrauth for primary cpu */
+       cmp     x1, #ARM64_CPU_BOOT_PRIMARY
+       b.eq    2f
+
+       /* if !system_supports_address_auth() then skip enable */
+alternative_if_not ARM64_HAS_ADDRESS_AUTH
+       b       3f
+alternative_else_nop_endif
+
+2:     /* Enable ptrauth instructions */
+       ldr     x2, =SCTLR_ELx_ENIA | SCTLR_ELx_ENIB | \
+                    SCTLR_ELx_ENDA | SCTLR_ELx_ENDB
+       orr     x0, x0, x2
+3:
+#endif
        ret                                     // return to head.S
 SYM_FUNC_END(__cpu_setup)