return 1;
 }
 
+/*
+ * Guest usage of a ptrauth instruction (which the guest EL1 did not turn into
+ * a NOP).
+ */
+static int kvm_handle_ptrauth(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+       /*
+        * We don't currently support ptrauth in a guest, and we mask the ID
+        * registers to prevent well-behaved guests from trying to make use of
+        * it.
+        *
+        * Inject an UNDEF, as if the feature really isn't present.
+        */
+       kvm_inject_undefined(vcpu);
+       return 1;
+}
+
 static exit_handle_fn arm_exit_handlers[] = {
        [0 ... ESR_ELx_EC_MAX]  = kvm_handle_unknown_ec,
        [ESR_ELx_EC_WFx]        = kvm_handle_wfx,
        [ESR_ELx_EC_BKPT32]     = kvm_handle_guest_debug,
        [ESR_ELx_EC_BRK64]      = kvm_handle_guest_debug,
        [ESR_ELx_EC_FP_ASIMD]   = handle_no_fpsimd,
+       [ESR_ELx_EC_PAC]        = kvm_handle_ptrauth,
 };
 
 static exit_handle_fn kvm_get_exit_handler(struct kvm_vcpu *vcpu)
 
                        kvm_debug("SVE unsupported for guests, suppressing\n");
 
                val &= ~(0xfUL << ID_AA64PFR0_SVE_SHIFT);
+       } else if (id == SYS_ID_AA64ISAR1_EL1) {
+               const u64 ptrauth_mask = (0xfUL << ID_AA64ISAR1_APA_SHIFT) |
+                                        (0xfUL << ID_AA64ISAR1_API_SHIFT) |
+                                        (0xfUL << ID_AA64ISAR1_GPA_SHIFT) |
+                                        (0xfUL << ID_AA64ISAR1_GPI_SHIFT);
+               if (val & ptrauth_mask)
+                       kvm_debug("ptrauth unsupported for guests, suppressing\n");
+               val &= ~ptrauth_mask;
        } else if (id == SYS_ID_AA64MMFR1_EL1) {
                if (val & (0xfUL << ID_AA64MMFR1_LOR_SHIFT))
                        kvm_debug("LORegions unsupported for guests, suppressing\n");